1

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);      
}
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 に答える