首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我怎样才能让这张图片放大得更快?

我怎样才能让这张图片放大得更快?
EN

Stack Overflow用户
提问于 2011-08-01 10:38:25
回答 1查看 1.7K关注 0票数 2

我有一个跟踪条,当我移动图像时,它可以放大或缩小图像,但它不能平滑地缩放,缩放200%或更多时会有瞬间延迟。

代码语言:javascript
复制
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,它的缩放非常流畅。

代码语言:javascript
复制
private void trackBar1_Scroll(object sender, EventArgs e)
{
    imagePanel1.Zoom = trackBar1.Value * 0.02f;
}

代码语言:javascript
复制
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);
    }

}

是不是因为我每次都会创建一个新的位图,所以它会滞后?我怎么才能让它像这样平滑地缩放呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-12-01 02:14:32

正如@CodingBarfield提到的,在trackBar1_ValueChanged()方法中计算缩放图像不是一个好主意。原因是,如果你放大得太快,你仍然会在每个中间步骤计算重新缩放的图像(即使是那些永远不会显示的步骤)。因此,将方法更改为如下所示:

代码语言:javascript
复制
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
    panel1.Invalidate();
}

并将缩放本身放到OnPaint()方法中,如下所示:

代码语言:javascript
复制
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)
    {
        ...
    }
}

scaling in OnPaint()方法并不是一个100%干净的解决方案,因为它仍然会阻碍你的GUI线程。更好的选择是使用后台线程,但我认为这应该足够了,它可以节省一些编码时间。

此外,您还可以通过仅缩放所需的图像部分来获得一些额外的性能提升。此技术将节省缩放的平方,因此缩放越大,节省的计算量就越多。

另一种选择是选择一些计算成本较低的插值模式。或者你甚至可以计算一些低质量的近似值,显示它,然后使用背景线程计算一些质量更好的图像。

或者,您可以丢弃所有这些代码,只需稍微修改一下CodePlex example以满足您的需求:)。

希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6893778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档