Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# GDI
I’m having a problem using StretchBlt to copy an image from a PictureBox to a Bitmap for use in creating an AVI file.
The AVI file is an unimportant aspect I believe - I can just display the Bitmap on another PictureBox and see the problem.
 
The problem is that occasionally (not often) a single image is flipped (mirrored across the X axis).
I’m not sure if this is a known problem with StretchBlt I haven’t yet found mention of or if I am doing something wrong.
It is NOT due to the intended functionality with StretchBlt of "If the signs of source and destination height or width are different then it creates a mirror image".
 
UPDATE: I changed things to force the source/destination to be the same size, and am using BitBlt with the same behavior.
 
I’ve included some code (c#), hopefully all of the important parts.
 
Stepping through the code I can see this happen for a single image that has exactly the same information being passed to StretchBlt (other than the hdc to copy to) as the previous image and the next image (and next, next) all of which are fine.
It doesn't happen often, and I dont see any reason when it does. Or a way to detect it happened (so I can flip it back).
I have a work around that doesn't use StretchBlt, but it is much slower and really degrades performance.
 
Another possibly useful bit: this flipped image is rare in normal usage (less than 1 in 100 frames). But when run in the IDE, stepping through image by image, it happens very regularly (maybe 1 in 10).
 
Any ideas what could be causing this or what I could be doing wrong? Or other FAST methods to copy the Bitmap including re-sizing.
NOTE: The bitmaps do vary in size (can't use BitBlt), but not by a lot.
 
Thank you!
Kate
 
// --- Import statement
[DllImport("GDI32.DLL", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool StretchBlt( 
IntPtr hdcDest, int nXDest, int nYDest, int nDestWidth, int nDestHeight,
IntPtr hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, Int32 dwRop );
 
// --- A small class for creating/storing Bitmap and Graphics objects, which get reused
public class CAviImageInfo
  {
    private Bitmap    mAviBitmap = null;
    private Graphics  mAviGraphics = null;
 
    public CAviImageInfo(int width, int height )
    {
      mAviBitmap = new Bitmap(width, height);
      mAviGraphics = Graphics.FromImage(mAviBitmap);
    }
    ~CAviImageInfo()
    {
      mAviGraphics.Dispose();
      mAviGraphics = null;
    }
    public Bitmap AviBitmap
    { get { return mAviBitmap; } }
    public Graphics AviGraphics
    { get { return mAviGraphics;  } }
}
 
// --- Two PictureBoxs placed on form at design time (one is just to watch for these mirrored images):
PictureBox mMainPictureBox; // --- Displays the images to be copied
PictureBox DebugPictureBox;
 
//  --- The following done one time:
Graphics  mMainPictureBoxGraphics = mMainPictureBox.CreateGraphics();
IntPtr    mMainPictureBoxHdc      = mMainPictureBoxGraphics.GetHdc();
 
// --- Method that does the copying.  Called each time image on panel is updated.
Public void UpdateAviRecording()
{
  // --- Gets unused Bitmap and Graphics objects (these are reused)
  CAviImageInfo aviImageInfo = GetUnusedAviImageInfo();
 
  IntPtr destinationHdc = aviImageInfo.AviGraphics.GetHdc();
 
  StretchBlt(
    destinationHdc, 
    0, 0, aviImageInfo.AviBitmap.Width, aviImageInfo.AviBitmap.Height,
    mMainPictureBoxHdc, 
    0, 0, mMainPictureBox.Width, mMainPictureBox.Height, SRCCOPY);
		
  // --- Show the copied Bitmap on the debug PictureBox 
  // --- (normally would pass it to be written to avi file)
  DebugPictureBox.Image = aviImageInfo.AviBitmap;
  DebugPictureBox.Refresh();
 
  aviImageInfo.AviGraphics.ReleaseHdc(destinationHdc);		
}
Posted 3-Jun-12 6:53am
KateToo211
Edited 4-Jun-12 14:03pm
v8
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

See the comments for the StretchBlt()[^] function. If the signs of source and destination height or width are different then it creates a mirror image. This may be something to do with the type of your source images.
  Permalink  
Comments
KateToo at 3-Jun-12 13:22pm
   
I had read that, yes, but it is not the cause.
Those values are never negative, and the exact same values for those, from one image to the next, can result in one of the images having been flipped.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Please try this:
 
During the copying image (my mean is when using "StretchBlt"), please compare the size of the DESTINATION rectangle and the source RECTANGLE (source image size). It is safe to do this procedure for all frames.
 
If the sizes (rectangles) are different from each other, do resampling the source image and let the dest and source image frames be the same in terms of sizes.
 
The abve process prevents occuring differences in the "nHeightSrc and nHeightDest parameters in StretchBlt " randomly.
 

Regards.
  Permalink  
v2
Comments
KateToo at 4-Jun-12 15:08pm
   
I do check the sizes and if they are the same use BitBlt.
What would you suggest for the resampling? Isn't that basically what I'm using StretchBlt for? My work around is actually to use Graphics.DrawImage so I dont need StretchBlt ... but this is too slow.
 
Please let me know if there is some other way to do the resample that is quick that I'm missing.
Thanks!
muhtarqong at 4-Jun-12 15:41pm
   
First, please always check the DEST and SOURCE rectangles. If they are equal, skip resampling. If accasionally or randomly, they are not equal, do resampling only for that frame. Thus, we can skip many exta-resampling jobs and only do small amount of resampling if any exists.
 
If the Graphics.DrawImage is slow. You may use pixel-wise operations for resampling. In general, pixel-wise operations is quite fast. Please try it.

You may try also this. It has resampling command in Generic imaging dll. It is fast.
http://www.artuxsoft.com/
KateToo at 4-Jun-12 16:10pm
   
I do check the DEST and SOURCE and do not resample if the same.
 
Can you point me to what functions you mean for the pixel-wise resampling operations?
 
I'll take a look at artuxsoft, thanks.
muhtarqong at 4-Jun-12 16:33pm
   
My mean is do not use Graphics.DrawImage(....), but use pixel-wise operations for the resampling procedure (e.g., Use LockBits and BitmapData directly access pixel values and do resumple). I think this is fast and safe. Because in some case you can not get graphics from some image formats.
KateToo at 4-Jun-12 18:04pm
   
Still not following you. I can access the pixels directly, yes - but how do I map from one size to another?
Are there re-sampling functions I'm missing?
All I'm aware are of the StretchBlt and Graphics.DrawImage. Generally StretchBlt works great except for this occasional mirrored image.
Muhtar Qong at 4-Jun-12 23:28pm
   
You are not missing any functions. You may create your own function when you are resampling by using pixel-wise operations. However, there are many kinds of "mapping" (resampling algorithms). Among them, Nearest Neighbor, bi-linear Interpolation and Cubic Convolutions are frequently used. You can get some information from here: http://artuxsoft.com/help/resample-an-image.aspx
KateToo at 6-Jun-12 13:24pm
   
I'm not ready to go that route. This should be simple, just resizing an image to write it to an AVI file. There must be something I'm doing wrong.
Thanks for trying to help.

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

  Print Answers RSS
0 DamithSL 320
1 OriginalGriff 235
2 Afzaal Ahmad Zeeshan 154
3 Sergey Alexandrovich Kryukov 147
4 BillWoodruff 135
0 OriginalGriff 7,510
1 DamithSL 5,494
2 Sergey Alexandrovich Kryukov 4,954
3 Maciej Los 4,936
4 Kornfeld Eliyahu Peter 4,514


Advertise | Privacy | Mobile
Web01 | 2.8.141223.1 | Last Updated 4 Jun 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100