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. Graphics.DrawImage - why it's so slow?

Graphics.DrawImage - why it's so slow?

Scheduled Pinned Locked Moved C#
graphicscsharpc++helpquestion
5 Posts 4 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.
  • L Offline
    L Offline
    Libor Tinka
    wrote on last edited by
    #1

    I have some image preview control based on a Panel which remembers current preview image position. Its OnPaint method does nothing except drawing viewed part of the image using this DrawImage override: Graphics.DrawImage(Image, Rectangle, Rectangle, GraphicsUnit) This draws only desired part of an image. The preview control is very small, so the whole painting should be fast, but it isn't. Drawing 50x50 px rectangular part from one image to second - for some unknown reason - depends on the size of the source image :confused: When this method draws little rectangle from 7 Mpx image, it tooks about 200 ms - that's not real-time, when image is moved and the control is repeatedly invalidated. I saw similar preview controls, where the scrolling of image were smooth and doesn't depend on image size. These controls were part of the MFC apps. Then I tried professional .NET component for image previews, which was also slow. I'm confused - why can't this simple task be quick? I spent a life solving this problem, so answer would be appreciated.

    M D 2 Replies Last reply
    0
    • L Libor Tinka

      I have some image preview control based on a Panel which remembers current preview image position. Its OnPaint method does nothing except drawing viewed part of the image using this DrawImage override: Graphics.DrawImage(Image, Rectangle, Rectangle, GraphicsUnit) This draws only desired part of an image. The preview control is very small, so the whole painting should be fast, but it isn't. Drawing 50x50 px rectangular part from one image to second - for some unknown reason - depends on the size of the source image :confused: When this method draws little rectangle from 7 Mpx image, it tooks about 200 ms - that's not real-time, when image is moved and the control is repeatedly invalidated. I saw similar preview controls, where the scrolling of image were smooth and doesn't depend on image size. These controls were part of the MFC apps. Then I tried professional .NET component for image previews, which was also slow. I'm confused - why can't this simple task be quick? I spent a life solving this problem, so answer would be appreciated.

      M Offline
      M Offline
      Marc 0
      wrote on last edited by
      #2

      Here are some possible suggestions i've encountered with similar Stuff: - Is the OnPaint method called very often? (stupid thing i once did number 1 :rolleyes:) - Try using a label instead of a panel. A label is double-buffered (if i remember right) and a panle isn't. Better yet, make your own custom control with the styles DoubleBuffer, AllPaintingInWmPaint and UserPaint on. - Make sure the source rectangle and the destination rectangle are the same width and height, so the GDI doesn't have to schale the screen image. - It can also be a problem as a result of the big image (i think 7 MB is a lot). If it's possible, try drawing a bitmap with a pixel format of Format32bppPArgb, it is said to be the fastest. I hope this helps!


      "..Commit yourself to quality from day one..it's better to do nothing at all than to do something badly.." -- Mark McCormick


      || Fold With Us! || Pensieve || VG.Net ||

      1 Reply Last reply
      0
      • L Libor Tinka

        I have some image preview control based on a Panel which remembers current preview image position. Its OnPaint method does nothing except drawing viewed part of the image using this DrawImage override: Graphics.DrawImage(Image, Rectangle, Rectangle, GraphicsUnit) This draws only desired part of an image. The preview control is very small, so the whole painting should be fast, but it isn't. Drawing 50x50 px rectangular part from one image to second - for some unknown reason - depends on the size of the source image :confused: When this method draws little rectangle from 7 Mpx image, it tooks about 200 ms - that's not real-time, when image is moved and the control is repeatedly invalidated. I saw similar preview controls, where the scrolling of image were smooth and doesn't depend on image size. These controls were part of the MFC apps. Then I tried professional .NET component for image previews, which was also slow. I'm confused - why can't this simple task be quick? I spent a life solving this problem, so answer would be appreciated.

        D Offline
        D Offline
        Dave Kreskowiak
        wrote on last edited by
        #3

        In addition to what Marc said... Instead of redrawing the image from the same 7M pixel image (huge!), have your control draw the thumbnail image to an internal buffer first, the same size as the preview window. Then when your preview has to draw, it can more quickly draw it from the internal buffer version, which should be pretty small. I've had to do this a few times in some custom controls that I wrote. Instead of calculating the same image over and over again in order to redraw a control image that doesn't change much, I monitor the Resize events of my control and redraw the control image to an internal buffer. Then in the Paint event for the control, I draw the control image from the buffer. For example, take a clock face. Most of what you see doesn't change, except for the hand positions. But, to get smoothly turning clock hands, you have to redraw the control about every 30-50 ms at least. Since calculating the positions of the various bits of a clock face can be time consuming, a clock face image should be calculated and drawn once to a cached image. When the control has to redraw itself (every 30ms), it merely has to draw the clock face from the cache, then calculate and draw only the hand positions. When the size of the control changes, you recalculate and redraw the cache image to match the size of the control. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

        L 1 Reply Last reply
        0
        • D Dave Kreskowiak

          In addition to what Marc said... Instead of redrawing the image from the same 7M pixel image (huge!), have your control draw the thumbnail image to an internal buffer first, the same size as the preview window. Then when your preview has to draw, it can more quickly draw it from the internal buffer version, which should be pretty small. I've had to do this a few times in some custom controls that I wrote. Instead of calculating the same image over and over again in order to redraw a control image that doesn't change much, I monitor the Resize events of my control and redraw the control image to an internal buffer. Then in the Paint event for the control, I draw the control image from the buffer. For example, take a clock face. Most of what you see doesn't change, except for the hand positions. But, to get smoothly turning clock hands, you have to redraw the control about every 30-50 ms at least. Since calculating the positions of the various bits of a clock face can be time consuming, a clock face image should be calculated and drawn once to a cached image. When the control has to redraw itself (every 30ms), it merely has to draw the clock face from the cache, then calculate and draw only the hand positions. When the size of the control changes, you recalculate and redraw the cache image to match the size of the control. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

          L Offline
          L Offline
          Libor Tinka
          wrote on last edited by
          #4

          In fact, I'm afraid that using buffer will enhance redrawing when image position doesn't change, but when user will need to shift image viewport by a "hand tool", the redrawing buffer with drawing it on control will take slightly more time than redrawing the control directly. However, the buffer idea is good, because there can be more OnPaint calls, not only on mouse moves... Another idea was to use a three times larger buffer than the control. When user drags mouse over control, the cursor is locked inside the control bounds and OnPaint works just with the buffer. When user releases mouse button, the buffer will update. This can be a little frustrating, when user needs to scroll whole large image (more dragging), but this can be also fast. I'll try these approaches, thank you very much for the new ideas :).

          D 1 Reply Last reply
          0
          • L Libor Tinka

            In fact, I'm afraid that using buffer will enhance redrawing when image position doesn't change, but when user will need to shift image viewport by a "hand tool", the redrawing buffer with drawing it on control will take slightly more time than redrawing the control directly. However, the buffer idea is good, because there can be more OnPaint calls, not only on mouse moves... Another idea was to use a three times larger buffer than the control. When user drags mouse over control, the cursor is locked inside the control bounds and OnPaint works just with the buffer. When user releases mouse button, the buffer will update. This can be a little frustrating, when user needs to scroll whole large image (more dragging), but this can be also fast. I'll try these approaches, thank you very much for the new ideas :).

            D Offline
            D Offline
            Dan Neely
            wrote on last edited by
            #5

            ltinka wrote:

            Another idea was to use a three times larger buffer than the control. When user drags mouse over control, the cursor is locked inside the control bounds and OnPaint works just with the buffer. When user releases mouse button, the buffer will update. This can be a little frustrating, when user needs to scroll whole large image (more dragging), but this can be also fast.

            Instead of tieing the user to a small section of the image per move, if they reach the edge of the bufffer cause an update then. A periodic delay would be much less bothersome for the user than having to repeatedly grab and let go to scroll a large distance.

            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