StretchBlt偶尔会在不应该反转图像的时候反转图像

本文关键字:图像 候反转 偶尔 不应该 StretchBlt | 更新日期: 2023-09-27 18:36:18

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

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

更新:我更改了内容以强制源/目标大小相同,并且正在使用具有相同行为的 BitBlt。

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

逐步完成代码,我可以看到单个图像发生了这种情况,该图像与上一个图像和下一个图像(以及下一个,下一个)具有完全相同的信息传递给 StretchBlt(除了要复制到的 hdc)所有这些都很好。它并不经常发生,而且我看不出有任何理由。 或者一种检测它发生的方法(所以我可以把它翻回来)。我有一个不使用 StretchBlt 的解决方法,但它要慢得多并且确实会降低性能。

另一个可能有用的一点是:这种翻转的图像在正常使用中很少见(不到 100 帧中的 1 帧)。 但是,在 IDE 中逐个映像单步执行时,它会发生非常规律(可能是十分之一)。

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

StretchBlt偶尔会在不应该反转图像的时候反转图像

这只是

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

在调用 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);