How can I make this image zoom faster?
I have a trackbar that zooms in or zooms out an image as I move it but it doesn't zoom smoothly, with a split second lag for zo开发者_开发技巧om of 200% or more.
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;
}
I found a user control someone made http://www.codeproject.com/KB/graphics/YLScsImagePanel.aspx that zooms very smoothly. There is no lag at all.
private void trackBar1_Scroll(object sender, EventArgs e)
{
imagePanel1.Zoom = trackBar1.Value * 0.02f;
}
This is from the custom control 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);
}
}
Is it because I'm creating a new bitmap each time that it lags? How can I make it zoom smoothly like this one?
as @CodingBarfield mentioned, it is not a good idea to compute the scaled image in the trackBar1_ValueChanged()
method. The reason is that you if you zoom too fast, you would still compute the rescaled image in every intermediate step (even those steps, that would be never displayed). So change the method to look like this:
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
panel1.Invalidate();
}
And put the scaling itself to the OnPaint()
method to look something like this:
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)
{
...
}
}
The scaling in OnPaint()
method is not a 100% clean solution, because it can still a bit hold your GUI thread back. Better option would be to use a background thread, but I think this should be enough and it can save you some coding time.
Also you can obtain some additional performance gain by scaling just the part of the image you need. This technique will save you square of the zoom, so the large the zoom is the more computations are saved.
Another option is to choose some less computationally expensive interpolation mode. Or you can even compute some low quality approximation, display it, and then compute some better quality image using background thread.
Or maybe you can throw all this code away and just a bit modify the CodePlex example to fit your needs :).
Hope this helps.
精彩评论