Worst... StretchBlt... Ever...

Okay, how is this for a weird problem?

I have a program that uses StretchBlt to paint an image from one Picture Box into another, smaller one. The user can check whether to squeeze the larger image to fit the smaller area, or to crop the image.

Example "Squeeze" code:
StretchBlt Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, SRCCOPY

Example "Cropped" code:
StretchBlt Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, Picture2.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, SRCCOPY

Well, it's not weird yet, is it? Until I run the program (either compiled or in the IDE). Then the crazy stuff happens...

(Times in milliseconds are averages gathered using the GetTickCount API)

Okay, let's say my program is the only program that I have open. Here are the times it takes to draw the image:

Squeezed: 50ms
Cropped: <1ms

Now, let's open Internet explorer.

Squeezed: 50ms
Cropped: <1ms

Let's navigate to a site that has an embedded Flash movie on the page.

Squeezed: 2ms
Cropped: <1ms

All I can say is: ???

Seriously, what is going on? Am I going crazy, or does this just not make any sense? Using the .PaintPicture method of the Picture Box, the same thing happens.

Is there an alternative to the StretchBlt API that is reliably fast? It's really, really annoying how inconsistant it is...


Edit: I should mention that the program is quickly and repeatedly StretchBlt'ing different images to the Picture Box, which is why the speed matters.

Who is Participating?
aikimarkConnect With a Mentor Commented:
Here are three performance-related ideas:
1. allocate and use long integer variables in place of the picturebox (non-image) properties.
lng1Width = Picture1.ScaleWidth
lng1Height = Picture1.ScaleHeight
lng2Width = Picture2.ScaleWidth
lng2Height = Picture2.ScaleHeight
'within your Do or For loop
StretchBlt Picture1.hdc, 0, 0, lng1Width , lng1Height , Picture2.hdc, 0, 0, lng2Width , lng2Height , SRCCOPY

Note: you also might replace the .hdc property references with long integer variables.

2. look at your pictureboxs' autoredraw property

3. consider a memory-only data structure for your images during the stretching process or hide the picturebox that is being used for the stretching operation.

* Are you also calling SetStretchBltMode?
* Have you explored alternatives, such as PaintPicture?
It is understandable to experience the time differences you see.  Think about what 'work' is required to stretch a picture (either enlarging or shrinking) versus simply transferring a partial picture image (directly).

If performance is a real big problem, you might try the following when doing a stretching operation:
* allocate a data structure to contain all 'frames' of the picture series
* transfer the stretched images without displaying any during this transfer process
* display the stretched images directly, using the clipped call

You might also experiment with an image control when doing a stretched display.
BurbbleAuthor Commented:
Why are both operations lightning fast when an Internet Explorer window with a webpage containing a Flash movie is open, but the "Squeeze" operation is 25x slower without it? (That was sort of my primary question ;-)

I can't really load all the images into memory; there could be hundreds, or even thousands, and I know it would just be a disaster, I can feel it... lol

>> You might also experiment with an image control when doing a stretched display.

Image control was the original design, but flickering looks very unprofessional.

So, I mean, my computer is obviously capable of resizing an image in less than 3 milliseconds using StretchBlt, it just "chooses" not to ("I choose not to run!") unless a Flash component is loaded? That just seems to totally not make sense.

Thanks for the quick response, however :)

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

BurbbleAuthor Commented:
>> * Are you also calling SetStretchBltMode?

Not sure what that is? Should I be? (or how should I be?)

>> * Have you explored alternatives, such as PaintPicture?

Yep, PaintPicture does the same thing, but slower (about 20ms difference between PaintPicture and StretchBlt if I remember correctly).

I changed all of the .ScaleWidth, .ScaleHeight, etc etc properties to be set into Longs in memory, there is a slight increase in speed with the StretchBlt calls.

Autoredraw is set to true (it has to be).

The Picture Box that I am StretchBlt'ing the image from is hidden (.Visible = False).


BurbbleAuthor Commented:
The "Squeezing" StretchBlt is still lightning fast with Internet Explorer open, and excessively sluggish without IE (but the "Cropping" one is faster *without* IE).

Weird :/

I've experienced something similar in one of my commercial applications.  If I positioned a control so that it slightly overlayed the picturebox, the redrawing was noticably faster (much faster).  I never figured out why.

The SetStretchBltMode function sets the bitmap stretching mode in the specified device context. (API definition)

When you compress a picture, StretchBlt has to merge many rows of pixels into fewer rows. The SetStretchBltMode function sets one of three modes for dealing with the extra lines. You can combine the extra lines with the remaining lines, using either an AND operation or an OR operation, or you can simply delete the extra lines. Using the SetStretchBltMode function on the destination surface has no effect on how PaintPicture compresses images, however. Visual Basic chooses a default mode (apparently the delete mode), and that’s that.

So you might explore the performance differences between the default stretching logic and the alternatives.  Perhaps the presence of IE or flash has changed this setting behind the scenes.

You might start reading pages at
and moving forward with the navigator buttons on these pages.

I still think you might benefit from using a memory only picture object to accomplish your stretching.
BurbbleAuthor Commented:
>> I still think you might benefit from using a memory only picture object to accomplish your stretching.

How do you mean?

I am experimenting with SetStretchBltMode... I checked the Picture Boxes using GetStretchBltMode, and they all returned "1" (STRETCH_ANDSCANS) right now, without my intervention. I'm going to play around with it and I'll let you know what happens (and I have to close this Internet Explorer window, so...)

BurbbleAuthor Commented:
Well, setting them all to mode "3" helped the speed a little. The "Squeezed" time without Internet Explorer is now around 45ms (as opposed to 50 before). It still doesn't compare to the <2ms time when Internet Explorer is loaded.

If I didn't specify a certain BltMode, it always defaulted to "1", regardless of what else was loaded.

I don't know what else could be causing it to do that. I guess I will wind up adding a warning somewhere in the documentation, "The images will render faster when Crop Mode is selected..."

Or, "Open Internet Explorer and navigate to a webpage in order to decrease render times" ;-)

or, as a temporary measure, programmatically start a hidden IE window
BurbbleAuthor Commented:
Nah, it's too risky to do that. I will just make a note in the documentation.

Thanks for your help, at least I got it a little faster from your suggestions :)

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.