1

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

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

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

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

单步执行代码,我可以看到单个图像发生这种情况,该图像具有与前一个图像和下一个图像(以及下一个,下一个)完全相同的信息传递给 StretchBlt(除了要复制到的 hdc),所有这些都是美好的。它不经常发生,我看不出有什么原因。或者一种检测它发生的方法(所以我可以把它翻转回来)。我有一个不使用 StretchBlt 的解决方法,但它的速度要慢得多,并且确实会降低性能。

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

任何想法可能导致这种情况或我可能做错了什么?或其他快速复制位图的方法,包括调整大小。注意:位图的大小确实不同(不能使用 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);      
}
4

1 回答 1

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);
于 2018-04-06T15:37:21.783 回答