StretchBlt偶尔会反转图像

时间:2012-06-04 19:00:14

标签: c#

我在使用StretchBlt(或BitBlt)将图像从PictureBox复制到Bitmap以用于创建AVI文件时遇到问题。 我相信AVI文件是一个不重要的方面 - 我可以在另一个PictureBox上显示Bitmap并查看问题。

问题在于偶尔(不经常)翻转单个图像(跨X轴镜像,而不是Y轴镜像)。 我不确定这是StretchBlt的已知问题我还没有提到或者我做错了什么。
请注意,这不是由于StretchBlt的预期功能"如果源和目标高度或宽度的符号不同,则会创建镜像"。

更新:我改变了一些东西来强制源/目标大小相同,并且使用BitBlt具有相同的行为。

我已经包含了一些代码(c#),希望是所有重要的部分。

单步执行代码我可以看到这种情况发生在单个图像上,该图像具有完全相同的信息传递给StretchBlt(除了要复制到的hdc)作为前一个图像和下一个图像(以及下一个,下一个)所有其中很好。 它并不经常发生,我没有看到任何理由。或者是一种检测它的方法(所以我可以将其翻转)。 我有一个不能使用StretchBlt的解决方案,但速度要慢得多,并且确实会降低性能。

另一个可能有用的位:这种翻转图像在正常使用中很少见(100帧中少于1)。但是当在IDE中运行时,逐步逐个图像,它会非常频繁地发生(可能是十分之一)。

任何想法可能导致这个或我可能做错了什么?或者其他FAST方法来复制Bitmap,包括重新调整大小。 注意:位图的大小确实不同(不能使用BitBlt),但不是很多。

谢谢!

凯特

// --- 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);      
}

1 个答案:

答案 0 :(得分:0)

这只是一个建议。我不知道它是否会起作用..

使用StretchBlt调用中图像的Math.Abs​​()设置宽度和高度。 这可能会阻止可能的内存损坏和反转符号(如GSerg所述)。 ..

StretchBlt(
    destinationHdc, 
    0, 0, Math.Abs(aviImageInfo.AviBitmap.Width), 
Math.Abs(aviImageInfo.AviBitmap.Height),
    mMainPictureBoxHdc, 
    0, 0, Math.Abs(mMainPictureBox.Width), 
Math.Abs(mMainPictureBox.Height), SRCCOPY);