如何解决渲染/绘制图像时的性能问题(图像的矩形移动非常缓慢) [英] How to solve performance problem in rendering/Drawing of image (rectangle movement is very slow on image)

查看:113
本文介绍了如何解决渲染/绘制图像时的性能问题(图像的矩形移动非常缓慢)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,其中正在加载图像并在图像上绘制一个小矩形.将移动另一个矩形以选择特定区域,并在其他图片框中缩放该区域.
我的问题是,当我移动矩形时,移动速度非常慢.这可能是由于不必要的绘图或渲染图像所致.下面是绘制图像和矩形的示例代码:

I have an application in which I am loading an image and drawing a small rectangle on the image. Further rectangle is moved to select speific area and zoom that area in other picture box.
My problem is when I move the rectangle the movement is very slow. It may be due to unnecessary drawing or rendering the image. Below is the sample code to draw image and rectangle:

//OnPaint event to draw the image
protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    Graphics g = e.Graphics;
    g.InterpolationMode = interMode;

    //draw image
    if (image != null)
    {
        Rectangle srcRect;
        Point pt = new Point((int)(hScrollBar1.Value / zoom),
            (int)(vScrollBar1.Value / zoom));
        if (canvasSize.Width * zoom < viewRectWidth &&
            canvasSize.Height * zoom < viewRectHeight)
        {
            // view all image
            srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height);
        }
        else
        {
            // view a portion of image
            srcRect = new Rectangle(pt, new Size((int)(viewRectWidth / zoom),
                (int)(viewRectHeight / zoom)));
        }
        g.DrawImage(image, srcRect, srcRect, GraphicsUnit.Pixel);
    }
}

//Code to draw rectangle (class: Selection)
public Selection Selection
{
    get { return selection; }
    set { selection = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    if (selection != null)
        selection.Draw(e.Graphics);
}

public void Draw(Graphics g)
{
    Pen p = new Pen(lineColor, lineWidth);
    g.DrawRectangle(p, new Rectangle(location, size));
    p.Dispose();
}
//Events of Mouse
private void YLScsPanel1_MouseDown(object sender, MouseEventArgs e)
{
    Point pt = new Point(e.X, e.Y);
    pt = YLScsPanel1.ConvertControlPointToCanvas(pt);
    if (selection.isHitting(pt) && e.Button == MouseButtons.Left && srcBmp != null)
    {
        isHit = true;
        YLScsPanel1.Cursor = Cursors.Hand;
    }
}
private void YLScsPanel1_MouseMove(object sender, MouseEventArgs e)
{
    if (isHit)
    {
        YLScsPanel1.Cursor = Cursors.Hand;
        Point pt = new Point(e.X, e.Y);
        pt = YLScsPanel1.ConvertControlPointToCanvas(pt);
        newLocation.X = Math.Max(0, Math.Min(pt.X, srcBmp.Width - newSize.Width));
        newLocation.Y = Math.Max(0, Math.Min(pt.Y, srcBmp.Height - newSize.Height));
        selection.Location = newLocation;
        YLScsPanel1.Selection = selection;
    }
}
private void YLScsPanel1_MouseUp(object sender, MouseEventArgs e)
{
    if (isHit)
    {
        isHit = false;
        YLScsPanel1.Cursor = Cursors.Default;
        showPanel2();
    }
}


欢迎任何建议.
预先感谢.


Any suggestion is welcome.
Thanks in advance.

推荐答案

不要在没有参数的情况下使用Invalidate,在参数中使用Invalidate:矩形或区域.这些区域支持点集算术:您可以对它们进行AND和OR(以及做集合论的其他运算).

想象一下,将矩形移动到图像顶部,然后按X和Y小步.移动矩形时,只打开两个窄带.在一个区域中使用OR(或移动显示的任何内容)将这两个波段合并在一起,然后将此区域传递到Invalidate.

这样,您将只重新渲染最基本的内容.

我的其他建议是使用WPF.您根本不需要渲染,只需在画布上放置并移动对象即可. WPF已完成所有渲染和优化.

现在,我对您的代码感到困惑.您显示两种方法OnPaint.它甚至不应该编译.如果来自不同的类,则应正确显示代码.您假设要绘制图像,并在其顶部绘制移动的矩形.此矩形的坐标是可变的.动作是:修改坐标(此处不渲染),它们在控件上调用Invalidate,您在其中重写OnPaint.

注意:您并未回答有关代码的所有问题,包括大小.

我之所以问是因为另一个令人费解的方面是:我渲染了更复杂的图形,其中通过缩放/平移和大量计算来实时渲染图形,并且渲染的图形可能是屏幕的很多倍.即使这样的设置,即使初始渲染花费了相当多的时间,我的性能仍然可以接受.我不明白为什么这是您的代码的问题.然后再回答我过去的问题.您是否使用缩放和平移?我看不到.图片大小是多少?也许您还有其他未显示的代码?您的代码显示的是什么类?您的变焦功能是什么?您不显示缩放代码.如果这是位图图像,则不能缩放.
您可能有一些数据源,可以将其转换为某处的位图,而这花费的时间最多.我请您解释一下原始数据是什么.请解释一下.

—SA
Don''t use Invalidate without parameters, use Invalidate with parameters: rectangle or region. The regions support point-set arithmetic: you can AND and OR them (and do other operations of set theory).

Imagine you move your rectangle on top of the image by a small step by X and Y. When you move it, you open only two narrow bands. Combine these two bands together using OR (or whatever you expose by the move) in one region, and pass this region to Invalidate.

In this way, you will re-render only what''s minimally needed.

My other recommendation is using WPF. You don''t do rendering at all, you just place and move your objects on canvas. All rendering and optimization is already done by WPF.

Now, I am puzzled with your code. You show two methods OnPaint. It should not even compile. If this is from different classes, you should show you code properly. You''re suppose to draw your image, and on top of it draw your moving rectangle. The coordinates of this rectangle are variable. The movement is: modify coordinates (no rendering here), them call Invalidate on the control where you override OnPaint.

Note: you did not answer all my questions about your code, including the size.

I''m asking because another puzzling aspect is this: I rendered way more complex graphics, where the graphics is rendered on the fly with zooming/panning and a lot of calculations and the rendered graphics could be many times more the the screen. Even is such settings I got acceptable performance even though initial rendering took noticeable time. I don''t understand why this is the issue with your code. Then again, answer my past questions. Do you use zoom and/or pan? I cannot see it. What''s the size if the image? Maybe, you have some other code you don''t show? What is the class you show with your code? What your zoom does? You don''t show zoom code. If this is a bitmap image, it cannot be zoom.
You probably have some source of data that you convert to bitmap somewhere, and that takes the most time. I asked you to explain what is the original data. Please explain it.

—SA


这篇关于如何解决渲染/绘制图像时的性能问题(图像的矩形移动非常缓慢)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆