AVI ファイルの作成に使用するために、PictureBox から Bitmap に画像をコピーするために StretchBlt (または BitBlt) を使用する際に問題が発生しています。AVI ファイルは重要ではないと私は信じています。ビットマップを別の PictureBox に表示して、問題を確認することができます。
問題は、ときどき (頻繁ではありませんが) 1 つの画像が反転することです (Y 軸ではなく X 軸でミラーリングされます)。これが StretchBlt の既知の問題であるかどうか、まだ言及されていないのか、何か間違っているのかはわかりません。
これは、「ソースと宛先の高さまたは幅の符号が異なる場合、鏡像を作成する」という StretchBlt の意図された機能によるものではないことに注意してください。
更新: ソース/宛先を強制的に同じサイズにするように変更し、同じ動作で BitBlt を使用しています。
いくつかのコード (c#) を含めましたが、重要な部分がすべて含まれていることを願っています。
コードをステップ実行すると、前の画像と次の画像 (および次、次) とまったく同じ情報が StretchBlt (コピー先の hdc 以外) に渡される単一の画像で発生することがわかります。大丈夫。頻繁に発生するわけではなく、発生する理由はわかりません。または、それが発生したことを検出する方法 (そのため、元に戻すことができます)。StretchBlt を使用しない回避策がありますが、はるかに遅くなり、パフォーマンスが大幅に低下します。
もう 1 つの役立つ可能性のあるビット: この反転した画像は、通常の使用ではまれです (100 フレームに 1 未満)。しかし、IDE で実行し、画像ごとにステップ実行すると、非常に定期的に発生します (10 分の 1 程度)。
これを引き起こしている可能性のあるもの、または私が間違っている可能性のあるアイデアはありますか? または、サイズ変更を含むビットマップをコピーする他の 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);
}