我在使用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);
}
答案 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);