[英]How zoom into a drawn rectangle of picturebox which is inside a panel?
我在面板內有一個PictureBox ,以便縮放和平移。 我創建了通過單擊鼠標來選擇4點並在PictureBox上繪制矩形的可能性。 一旦矩形在我的圖片上,我就將矩形的坐標傳遞給方法“ cropRectangle”。 此方法裁剪矩形並用裁剪后的圖像替換舊圖像。 這很好用 :
( OriginalImage是pictureBox中實際圖像的位圖 )
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();
}
我現在想要做的是縮放所選區域而不是對其進行裁剪。 圖片框的矩形必須與面板匹配。
如何通過面板僅顯示圖片框的選定區域(矩形),而不裁剪圖像?
您應該堅持使用Graphics
對象修改現有的Bitmap
,而不要更改PictureBox的大小。 當所需的功能在其他地方已經可用時,您不希望被綁定到UI控件。
以下是實現該目標的粗略步驟:
Bitmap
對象,該對象將存儲縮放的圖像。 Bitmap tBitmap = new Bitmap(zoomX, zoomY, PixelFormat.Format24bppRgb);
Graphics graphics = Graphics.FromImage(tBitmap);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.DrawImage(pictureBox.Image, new Rectangle(0, 0, pictureBox.Width, pictureBox.Height), new Rectangle(/*The crop rectangle you draw already*/), GraphicsUnit.Pixel);
pictureBox.Image = tBitmap;
graphics.Dispose();
pictureBox.Refresh();
這些是要遵循的基本步驟。 我沒有時間深入研究現有代碼,因此您可能需要更改一些其他內容才能使其正常工作。
這也是一篇MSDN文章,涵蓋了相同的內容: 在GDI +中裁剪和縮放圖像
您可能對此控件(ZoomPicBox)感興趣,該控件可用於縮放和平移圖片框。
該代碼的全部功勞是鮑勃·鮑威爾(Bob Powell),它是從他的網站上獲取的(現在看來該網站已經關閉,並且已經存在了很長時間)。
我在以下鏈接中從archive.org復制了代碼:
https://web.archive.org/web/20080313161349/http://www.bobpowell.net/zoompicbox.htm
該鏈接具有其他信息,值得一讀。 該代碼在VB.Net中也可用。
我不知道鮑勃·鮑威爾(Bob Powell)的網站為什么倒塌,但是它是Windows Graphics信息的絕佳站點。
我覺得這段代碼值得重復。 可以將該控件拖到窗體上。
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;
}
}
}
我找到了解決問題的好方法:
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);
}
由於我知道可以看到圖片框的面板的長度。 我將要放大的面板比例和矩形的寬度。此比例就是我的縮放比例。
我將圖片框的大小乘以我計算出的比率。
我將圖片框固定在矩形的左側和頂部。 但是在此之前,由於更改了圖片框的大小,因此必須將矩形的坐標乘以縮放比例。
由於圖像的原始比例會被損壞,因此我沒有實施Y轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.