Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
4.00/5 (3 votes)
See more:
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.
Posted
Updated 15-Mar-11 2:34am
v3
Comments
JF2015 15-Mar-11 6:33am    
Added code formatting.
Olivier Levrey 15-Mar-11 6:59am    
You have two OnPaint there... and what type is Selection? Is it another control??
SUNILHNBGU 15-Mar-11 8:32am    
Selection is a class where all functionality of drawing rectangle are implemented. first one (public Selection Selection) is constuctor of the class and paint method is to draw rectangle.
Olivier Levrey 15-Mar-11 8:40am    
I edited the question to make the code easier to read.
I understood what Selection is supposed to be, but I don't understand its type. What type does it inherit from? In your code you are using selection.Location = .... Does it mean Selection is a control? A PictureBox or something?
And you say public Selection Selection is contructor... It is not. It is a property. Please explain more clearly.
If you put code from different files in the question, then edit the question and separate the code so we will understand.

1 solution

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
 
Share this answer
 
v4
Comments
Espen Harlinn 15-Mar-11 12:51pm    
Good advice - my 5
Sergey Alexandrovich Kryukov 15-Mar-11 13:26pm    
Still a lot of the unclear in this work...
Thank you, Espen.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900