2016-08-23 99 views
0

我有一個圖片框內的面板爲了放大和平移。我創建了通過鼠標單擊選擇4個點並在PictureBox上繪製矩形的可能性。一旦矩形結束了我的圖片,我將矩形的座標傳遞給「cropRectangle」方法。此方法裁剪矩形並用裁剪的圖像替換舊圖像。 這個作品非常好如何放大面板內圖片框的繪製矩形?

OriginalImage是實際圖像的圖片框位圖)

private void cropRectangle(Rectangle rect){ 
    double left = (rect.X) * originalImage.Width/pictureBox.Width, 
    top = (rect.Y) * originalImage.Width/pictureBox.Height, 
    right = (rect.Width) * originalImage.Width/pictureBox.Width, 
    bottom = (rect.Height) * originalImage.Height/pictureBox.Height; 
    rect = new Rectangle (Convert.ToInt32(left), Convert.ToInt32(top), Convert.ToInt32(right), Convert.ToInt32(bottom)); 

    Bitmap bitmap = orignalImage.Clone(rect, originalImage.PixelFormat); 
    pictureBox.Image = (Image)bitmap; 

    centerPictureBox(); 

    // fit image into pictureBox with respect to the ratio 
    float ratio = orignalImage.Width/orignalImage.Height; 
    pictureBox.Width = panel.Width; 
    pictureBox.Height = Convert.ToInt32(pictureBox.Width * ratio); 
    centerPictureBox(); 
} 

什麼我想現在要做的是放大所選擇的區域,而不是對裁剪。圖框的矩形必須與面板匹配。

如何通過面板僅顯示圖片框的選定區域(矩形)而不裁剪圖像?

回答

0

我已經找到了完美的解決方案,以我的問題:

private void zoomInsideRectangle(Rectangle rect){ 
    float zoomFactor = ((float)panel.Width/rect.Width) - 1; 

    pictureBox.Width = pictureBox.Width + convertToIntPerfect(pictureBox.Width * zoomFactor); 
    pictureBox.Height = pictureBox.Height + convertToIntPerfect(pictureBox.Height * zoomFactor); 

    rect.X = rect.X + convertToIntPerfect(rect.X * zoomFactor); 
    rect.Y = rect.Y + convertToIntPerfect(rect.Y * zoomFactor); 

    pictureBox.Left = convertToIntPerfect(-rect.X); 
    pictureBox.Top = convertToIntPerfect(-rect.Y); 
} 

因爲我知道面板的長度在那裏我可以看到圖片框。我把面板和我想要放大的矩形的寬度的比率。這個比例是我的縮放比例。

我將picturebox的大小乘以我計算的比例。

我將左邊和上邊的圖片框用我的矩形座標固定。但在這之前,我必須將我的矩形的座標與zoomratio相乘,因爲我改變了picturebox的大小。

由於圖像的原始比率將被損壞,我沒有實現Y變換。

1

您應該堅持使用Graphics對象修改現有的Bitmap,而不是更改PictureBox的大小。當所需的功能在其他地方已經可用時,您不希望被綁定到UI控件。

下面是粗糙的步驟來實現的是:

  1. 創建一個臨時Bitmap對象將存儲在縮放的圖像。 Bitmap tBitmap = new Bitmap(zoomX, zoomY, PixelFormat.Format24bppRgb);
  2. 當你想放大時,計算縮放因子和像你已經做過的東西(我沒有檢查代碼是否正確,但我假設它是這樣)。
  3. 從臨時位圖創建一個新的圖形對象。 Graphics graphics = Graphics.FromImage(tBitmap);
  4. 設置InterpolationMode,以便圖像以高質量縮放。 graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  5. 使用DrawImage方法(使用PictureBox中的原始圖像)繪製縮放圖像。 graphics.DrawImage(pictureBox.Image, new Rectangle(0, 0, pictureBox.Width, pictureBox.Height), new Rectangle(/*The crop rectangle you draw already*/), GraphicsUnit.Pixel);
  6. 將新繪製的位圖設置爲圖片框中的圖像。 pictureBox.Image = tBitmap;
  7. 請記住處置我們用於繪製的圖形對象。 graphics.Dispose();
  8. 您可能需要刷新PictureBox才能強制重畫自己。 pictureBox.Refresh();

這些是遵循的基本步驟。我沒有時間仔細閱讀現有代碼,因此您可能需要更改一些其他內容才能使其工作。

這裏也是一個MSDN文章,涵蓋同樣的東西:Cropping and Scaling Images in GDI+

+0

我無法管理它的工作。 – dll

+1

@dll我記得在Codeproject.com上看到了這種功能的不少實例。你可以搜索「picturebox zoom windows forms」這樣的東西。 – hankide

+0

謝謝,但我只是找到了我的問題的解決方案。 – dll

1

您可能對此控件(ZoomPicBox)感興趣,該控件允許縮放和平移圖片框。

此代碼的所有功勞是鮑勃鮑威爾,它是從他的網站(這似乎是現在下來,已經很長一段時間了)。

我複製從archive.org碼在此鏈接:

https://web.archive.org/web/20080313161349/http://www.bobpowell.net/zoompicbox.htm

該鏈接有更多的信息,值得一讀。該代碼也可以在VB.Net中使用。

我不知道爲什麼鮑勃鮑威爾的網站已關閉,但它是Windows圖形信息的絕佳網站。

我覺得這段代碼值得重複。這個控件可以拖到表單上。

namespace bobpowell.net 
{ 
    /// <summary> 
    /// ZoomPicBox does what it says on the wrapper. 
    /// </summary> 
    /// <remarks> 
    /// PictureBox doesn't lend itself well to overriding. Why not start with something basic and do the job properly? 
    /// </remarks> 
    public class ZoomPicBox : ScrollableControl 
    { 

    Image _image; 
    [ 
    Category("Appearance"), 
    Description("The image to be displayed") 
    ] 
    public Image Image 
    { 
     get{return _image;} 
     set 
     { 
     _image=value; 
     UpdateScaleFactor(); 
     Invalidate(); 
     } 
    } 

    float _zoom=1.0f; 
    [ 
    Category("Appearance"), 
    Description("The zoom factor. Less than 1 to reduce. More than 1 to magnify.") 
    ] 
    public float Zoom 
    { 
     get{return _zoom;} 
     set 
     { 
     if(value<0 || value<0.00001) 
      value=0.00001f; 
     _zoom=value; 
     UpdateScaleFactor(); 
     Invalidate(); 
     } 
    } 

    /// <summary> 
    /// Calculates the effective size of the image 
    ///after zooming and updates the AutoScrollSize accordingly 
    /// </summary> 
    private void UpdateScaleFactor() 
    { 
     if(_image==null) 
     this.AutoScrollMinSize=this.Size; 
     else 
     { 
     this.AutoScrollMinSize=new Size(
      (int)(this._image.Width*_zoom+0.5f), 
      (int)(this._image.Height*_zoom+0.5f) 
     ); 
     } 
    } 

    InterpolationMode _interpolationMode=InterpolationMode.High; 
    [ 
    Category("Appearance"), 
    Description("The interpolation mode used to smooth the drawing") 
    ] 
    public InterpolationMode InterpolationMode 
    { 
     get{return _interpolationMode;} 
     set{_interpolationMode=value;} 
    } 


    protected override void OnPaintBackground(PaintEventArgs pevent) 
    { 
     // do nothing. 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     //if no image, don't bother 
     if(_image==null) 
     { 
     base.OnPaintBackground(e); 
     return; 
     } 
     //Set up a zoom matrix 
     Matrix mx=new Matrix(_zoom,0,0,_zoom,0,0); 
     //now translate the matrix into position for the scrollbars 
     mx.Translate(this.AutoScrollPosition.X/_zoom, this.AutoScrollPosition.Y/_zoom); 
     //use the transform 
     e.Graphics.Transform=mx; 
     //and the desired interpolation mode 
     e.Graphics.InterpolationMode=_interpolationMode; 
     //Draw the image ignoring the images resolution settings. 
     e.Graphics.DrawImage(_image,new Rectangle(0,0,this._image.Width,this._image.Height),0,0,_image.Width, _image.Height,GraphicsUnit.Pixel); 
     base.OnPaint (e); 
    } 


    public ZoomPicBox() 
    { 
     //Double buffer the control 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint | 
     ControlStyles.UserPaint | 
     ControlStyles.ResizeRedraw | 
     ControlStyles.UserPaint | 
     ControlStyles.DoubleBuffer, true); 

     this.AutoScroll=true; 
    } 
    } 
}