Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Memory expensive rubber band selection?

Memory expensive rubber band selection?

Scheduled Pinned Locked Moved C#
graphicsquestionperformance
13 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Chesnokov Yuriy

    What is the reason of memory consumption in the DrawRoi function leading to hundreds of Mb? There is a Frame bitmap and its FrameWithRoi copy to assign to PictureBox. On the mouse move event new ROI coords are estimated and DrawRoi() is called.

    DrawRoi()
    {
    RectangleF roi = Roi;

    RectangleF rect = new RectangleF()
    {
    X = (float)Frame.Width * roi.X,
    Y = (float)Frame.Height * roi.Y,
    Width = (float)Frame.Width * roi.Width,
    Height = (float)Frame.Height * roi.Height
    };

    // draw roi if it is smaller than the whole image
    if (rect.Left > 0 || rect.Right < (float)FrameWithRoi.Width ||
    rect.Top > 0 || rect.Bottom < (float)FrameWithRoi.Height)
    {
    Graphics g = Graphics.FromImage(FrameWithRoi);
    g.DrawImage(Frame, 0, 0);
    using (Bitmap region = new Bitmap(FrameWithRoi.Width, FrameWithRoi.Height, FrameWithRoi.PixelFormat))
    {
    Graphics roi_g = Graphics.FromImage(region);
    roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
    roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
    region.MakeTransparent(Color.Red);
    g.DrawImage(region, 0, 0);
    }
    }

    this.framePictureBox.Image = FrameWithRoi;
    }

    Чесноков

    L Offline
    L Offline
    Luc Pattyn
    wrote on last edited by
    #4

    Graphics objects are expensive, and you should dispose them. Why not use a using statement, just like you did for the region Bitmap? And why would you need two Graphics instances, and a DrawImage()? Couldn't you just use the Bitmap(Image) constructor, and have its Graphics, just the one? :)

    Luc Pattyn [My Articles] Nil Volentibus Arduum

    The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
    Please use <PRE> tags for code snippets, they improve readability.
    CP Vanity has been updated to V2.3

    C 1 Reply Last reply
    0
    • L Luc Pattyn

      Graphics objects are expensive, and you should dispose them. Why not use a using statement, just like you did for the region Bitmap? And why would you need two Graphics instances, and a DrawImage()? Couldn't you just use the Bitmap(Image) constructor, and have its Graphics, just the one? :)

      Luc Pattyn [My Articles] Nil Volentibus Arduum

      The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
      Please use <PRE> tags for code snippets, they improve readability.
      CP Vanity has been updated to V2.3

      C Offline
      C Offline
      Chesnokov Yuriy
      wrote on last edited by
      #5

      I was looking for a way to darken non ROI region in the image. You optimizations would be welcomed. Why the picture box update is very slow if I keep drawing on every mouse move event?

      Чесноков

      L B L P 4 Replies Last reply
      0
      • C Chesnokov Yuriy

        I was looking for a way to darken non ROI region in the image. You optimizations would be welcomed. Why the picture box update is very slow if I keep drawing on every mouse move event?

        Чесноков

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #6

        Mouse-move events are fired continuesly, and the drawing routine looks expensive. You might want to check whether the mouse has moved in the meantime, not redrawing if there's no movement detected.

        Bastard Programmer from Hell :suss:

        1 Reply Last reply
        0
        • C Chesnokov Yuriy

          I was looking for a way to darken non ROI region in the image. You optimizations would be welcomed. Why the picture box update is very slow if I keep drawing on every mouse move event?

          Чесноков

          B Offline
          B Offline
          BobJanova
          wrote on last edited by
          #7

          I recommend overlaying the semitransparent mask over the base image (either in OnPaint on the picture box or by placing another object over the top). Then all you have to redraw is the mask. Creating graphics objects is slow, which is why you should typically do it in OnPaint. In fact, in this case, you should do that, and your mouse move handler should only call Invalidate.

          1 Reply Last reply
          0
          • C Chesnokov Yuriy

            I was looking for a way to darken non ROI region in the image. You optimizations would be welcomed. Why the picture box update is very slow if I keep drawing on every mouse move event?

            Чесноков

            P Offline
            P Offline
            Pete OHanlon
            wrote on last edited by
            #8

            One other thing to bear in mind. The managed version of GDI+ is slow in comparison to the unmanaged version. You pay a price for the simplicity, and that price is speed.

            Forgive your enemies - it messes with their heads

            My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility

            1 Reply Last reply
            0
            • C Chesnokov Yuriy

              I was looking for a way to darken non ROI region in the image. You optimizations would be welcomed. Why the picture box update is very slow if I keep drawing on every mouse move event?

              Чесноков

              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #9

              Chesnokov Yuriy wrote:

              Why the picture box update is very slow if I keep drawing on every mouse move event?

              Because the MouseMove events fire at high frequency (allowing you to track well assuming your handler is fast), possibly 50Hz or higher (which is too high for the human eye to notice), because Graphics objects are expensive, and finally because PictureBoxes are stupid (I wouldn't be surprised if the fact you change the image just causes another mouse move event). You want to run such things continuously? I would experiment with keeping the two Graphics and the Bitmap around as class members, i.e. not create new objects at all, just keep using them over and over. :)

              Luc Pattyn [My Articles] Nil Volentibus Arduum

              The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
              Please use <PRE> tags for code snippets, they improve readability.
              CP Vanity has been updated to V2.3

              C 1 Reply Last reply
              0
              • L Luc Pattyn

                Chesnokov Yuriy wrote:

                Why the picture box update is very slow if I keep drawing on every mouse move event?

                Because the MouseMove events fire at high frequency (allowing you to track well assuming your handler is fast), possibly 50Hz or higher (which is too high for the human eye to notice), because Graphics objects are expensive, and finally because PictureBoxes are stupid (I wouldn't be surprised if the fact you change the image just causes another mouse move event). You want to run such things continuously? I would experiment with keeping the two Graphics and the Bitmap around as class members, i.e. not create new objects at all, just keep using them over and over. :)

                Luc Pattyn [My Articles] Nil Volentibus Arduum

                The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
                Please use <PRE> tags for code snippets, they improve readability.
                CP Vanity has been updated to V2.3

                C Offline
                C Offline
                Chesnokov Yuriy
                wrote on last edited by
                #10

                I need to implement rubber band like ROI selection in the image as in paint editor

                Чесноков

                1 Reply Last reply
                0
                • C Chesnokov Yuriy

                  What is the reason of memory consumption in the DrawRoi function leading to hundreds of Mb? There is a Frame bitmap and its FrameWithRoi copy to assign to PictureBox. On the mouse move event new ROI coords are estimated and DrawRoi() is called.

                  DrawRoi()
                  {
                  RectangleF roi = Roi;

                  RectangleF rect = new RectangleF()
                  {
                  X = (float)Frame.Width * roi.X,
                  Y = (float)Frame.Height * roi.Y,
                  Width = (float)Frame.Width * roi.Width,
                  Height = (float)Frame.Height * roi.Height
                  };

                  // draw roi if it is smaller than the whole image
                  if (rect.Left > 0 || rect.Right < (float)FrameWithRoi.Width ||
                  rect.Top > 0 || rect.Bottom < (float)FrameWithRoi.Height)
                  {
                  Graphics g = Graphics.FromImage(FrameWithRoi);
                  g.DrawImage(Frame, 0, 0);
                  using (Bitmap region = new Bitmap(FrameWithRoi.Width, FrameWithRoi.Height, FrameWithRoi.PixelFormat))
                  {
                  Graphics roi_g = Graphics.FromImage(region);
                  roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
                  roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
                  region.MakeTransparent(Color.Red);
                  g.DrawImage(region, 0, 0);
                  }
                  }

                  this.framePictureBox.Image = FrameWithRoi;
                  }

                  Чесноков

                  _ Offline
                  _ Offline
                  _Erik_
                  wrote on last edited by
                  #11

                  What I understand is that you are trying to darken a rectangle within a image, and that rectangle must be refreshed as long as the mouse is moving. Am I right? If this is what you want to do, the problem is that you are creating too many new Graphics and Bitmap objects in a very short time (and these are expensive objects), and updating the Image property a lot of times as well. The best way to do it is to subscribe to the Paint event of the control and code everything in this event handler, so you will receive a Graphics object as a parameter. In the next example there is only a PictureBox in the Form, called pct:

                  public partial class Form1 : Form
                  {
                  bool drawRect = false;
                  Rectangle r = new Rectangle();
                  Brush br = new SolidBrush(Color.FromArgb(50, Color.Red));

                  public Form1()
                  {
                      InitializeComponent();
                  }
                  
                  private void pct\_Paint(object sender, PaintEventArgs e)
                  {
                      if (drawRect)
                          e.Graphics.FillRectangle(br, r);
                  }
                  
                  private void pct\_MouseDown(object sender, MouseEventArgs e)
                  {
                      drawRect = true;
                      r.X = e.X;
                      r.Y = e.Y;
                  }
                  
                  private void pct\_MouseMove(object sender, MouseEventArgs e)
                  {
                      r.Width = e.X - r.X;
                      r.Height = e.Y - r.Y;
                  
                      Refresh();
                  }
                  
                  private void pct\_MouseUp(object sender, MouseEventArgs e)
                  {
                      drawRect = false;
                      Refresh();
                  }
                  

                  }

                  I've made it quick. You would have to modify it in order to draw the rectangle if the mouse moves to a lower X and/or lower Y coordinate.

                  C 1 Reply Last reply
                  0
                  • _ _Erik_

                    What I understand is that you are trying to darken a rectangle within a image, and that rectangle must be refreshed as long as the mouse is moving. Am I right? If this is what you want to do, the problem is that you are creating too many new Graphics and Bitmap objects in a very short time (and these are expensive objects), and updating the Image property a lot of times as well. The best way to do it is to subscribe to the Paint event of the control and code everything in this event handler, so you will receive a Graphics object as a parameter. In the next example there is only a PictureBox in the Form, called pct:

                    public partial class Form1 : Form
                    {
                    bool drawRect = false;
                    Rectangle r = new Rectangle();
                    Brush br = new SolidBrush(Color.FromArgb(50, Color.Red));

                    public Form1()
                    {
                        InitializeComponent();
                    }
                    
                    private void pct\_Paint(object sender, PaintEventArgs e)
                    {
                        if (drawRect)
                            e.Graphics.FillRectangle(br, r);
                    }
                    
                    private void pct\_MouseDown(object sender, MouseEventArgs e)
                    {
                        drawRect = true;
                        r.X = e.X;
                        r.Y = e.Y;
                    }
                    
                    private void pct\_MouseMove(object sender, MouseEventArgs e)
                    {
                        r.Width = e.X - r.X;
                        r.Height = e.Y - r.Y;
                    
                        Refresh();
                    }
                    
                    private void pct\_MouseUp(object sender, MouseEventArgs e)
                    {
                        drawRect = false;
                        Refresh();
                    }
                    

                    }

                    I've made it quick. You would have to modify it in order to draw the rectangle if the mouse moves to a lower X and/or lower Y coordinate.

                    C Offline
                    C Offline
                    Chesnokov Yuriy
                    wrote on last edited by
                    #12

                    No, I need to darken the area outside rectangle. Consider ROI region. ROI remains clear and the area outside it is darked. I tried preinitialization of graphics and bitmaps and found that the problem part taking much of the time is:

                    ...
                    roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
                    roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
                    region.MakeTransparent(Color.Red);
                    g.DrawImage(region, 0, 0);
                    ...

                    Despite prinitialization it takes about 150ms

                    Чесноков

                    _ 1 Reply Last reply
                    0
                    • C Chesnokov Yuriy

                      No, I need to darken the area outside rectangle. Consider ROI region. ROI remains clear and the area outside it is darked. I tried preinitialization of graphics and bitmaps and found that the problem part taking much of the time is:

                      ...
                      roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
                      roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
                      region.MakeTransparent(Color.Red);
                      g.DrawImage(region, 0, 0);
                      ...

                      Despite prinitialization it takes about 150ms

                      Чесноков

                      _ Offline
                      _ Offline
                      _Erik_
                      wrote on last edited by
                      #13

                      Well, then, draw four rectangles around the area you want to keep clear. Just change the Paint event handler I posted before this way:

                      private void pct_Paint(object sender, PaintEventArgs e)
                      {
                      if (drawRect)
                      {
                      e.Graphics.FillRectangle(br, 0, 0, pct.Width, r.Y);
                      e.Graphics.FillRectangle(br, 0, r.Y, r.X, pct.Height);
                      e.Graphics.FillRectangle(br, r.X, r.Y + r.Height, pct.Width, pct.Height);
                      e.Graphics.FillRectangle(br, r.X + r.Width, r.Y, pct.Width, r.Height);
                      }
                      }

                      This will work pretty well. Do you also want to save the image after you have darkened the area?

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups