Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win


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

Posted on 2004-09-01
Medium Priority
Last Modified: 2010-05-02
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.

Question by:Burbble
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
LVL 46

Expert Comment

ID: 11959871
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.

Author Comment

ID: 11959962
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 :)

LVL 46

Accepted Solution

aikimark earned 2000 total points
ID: 11960249
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?
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 11960480
>> * 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).



Author Comment

ID: 11960493
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 :/

LVL 46

Expert Comment

ID: 11962266
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.

Author Comment

ID: 11963726
>> 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...)


Author Comment

ID: 11963962
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" ;-)

LVL 46

Expert Comment

ID: 11966129
or, as a temporary measure, programmatically start a hidden IE window

Author Comment

ID: 11967060
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 :)


Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question