我怎样才能使这张照片变焦快一点?
本文关键字:变焦 一点 照片 张照片 | 更新日期: 2023-09-27 18:04:10
我有一个跟踪条,它可以在我移动图像时放大或缩小图像,但它不能平滑地缩放,缩放200%或更大时会有一瞬间的延迟。
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
zoom = trackBar1.Value;
zoomValue = (float)(zoom / 10.0f);
newBitmap = new Bitmap((int)(currWidth * zoomValue), (int)(currHeight * zoomValue));
g = Graphics.FromImage(newBitmap);
Matrix mx = new Matrix();
mx.Scale(zoomValue, zoomValue);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.Transform = mx;
g.DrawImage(currImage, new Rectangle(0, 0, currWidth, currHeight));
g.Dispose();
mx.Dispose();
panel1.BackgroundImage = newBitmap;
}
我发现一个用户控制某人http://www.codeproject.com/KB/graphics/YLScsImagePanel.aspx缩放非常顺利。完全没有延迟
private void trackBar1_Scroll(object sender, EventArgs e)
{
imagePanel1.Zoom = trackBar1.Value * 0.02f;
}
来自自定义控件ImagePanel.cs
public float Zoom
{
get { return zoom; }
set
{
if (value < 0.001f) value = 0.001f;
zoom = value;
displayScrollbar();
setScrollbarValues();
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//draw image
if(image!=null)
{
Rectangle srcRect,distRect;
Point pt=new Point((int)(hScrollBar1.Value/zoom),(int)(vScrollBar1.Value/zoom));
if (canvasSize.Width * zoom < viewRectWidth && canvasSize.Height * zoom < viewRectHeight)
srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height); // view all image
else srcRect = new Rectangle(pt, new Size((int)(viewRectWidth / zoom), (int)(viewRectHeight / zoom))); // view a portion of image
distRect=new Rectangle((int)(-srcRect.Width/2),-srcRect.Height/2,srcRect.Width,srcRect.Height); // the center of apparent image is on origin
Matrix mx=new Matrix(); // create an identity matrix
mx.Scale(zoom,zoom); // zoom image
mx.Translate(viewRectWidth/2.0f,viewRectHeight/2.0f, MatrixOrder.Append); // move image to view window center
Graphics g=e.Graphics;
g.InterpolationMode=interMode;
g.Transform=mx;
g.DrawImage(image,distRect,srcRect, GraphicsUnit.Pixel);
}
}
是因为我每次创建一个新的位图,它滞后吗?我怎样才能使它像这样平滑地变焦?
正如@CodingBarfield所提到的,在trackBar1_ValueChanged()
方法中计算缩放后的图像并不是一个好主意。原因是,如果您缩放太快,您仍然需要在每个中间步骤中计算重新缩放的图像(即使是那些步骤,也永远不会显示)。所以把这个方法改成这样:
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
panel1.Invalidate();
}
将缩放本身设置为OnPaint()
方法,看起来像这样:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
zoom = trackBar1.Value;
if (lastZoom != zoom)
{
// the zoom has changed, clear the cache
lastZoom = zoom;
imageCache = null;
}
if (imageCache == null && image != null)
{
// compute scaled image
imageCache = scaleImage(image, zoom);
}
//draw image
if(image!=null)
{
...
}
}
OnPaint()
方法中的缩放不是100%干净的解决方案,因为它仍然可以稍微保留您的GUI线程。更好的选择是使用后台线程,但我认为这应该足够了,它可以节省你一些编码时间。
还可以通过只缩放所需的映像部分来获得一些额外的性能增益。这种技术将节省你的平方缩放,所以变焦越大,节省的计算就越多。
另一个选择是选择一些计算成本较低的插值模式。或者你甚至可以计算一些低质量的近似值,显示它,然后使用后台线程计算一些质量更好的图像。
或者你可以把所有这些代码都扔掉,只修改一下CodePlex的例子来满足你的需要:)。