0

これは、複数のスレッドから単一のビットマップ オブジェクトへのレンダリングからのフォロー アップです。

私が達成しようとしているのは、たとえば 50x50 ピクセルのビットマップを取得し、ビットマップ LockBits 関数またはその他のグラフィックス.DrawImage. DrawImage を使用したくない理由は、他のスレッドに記載されています。

ソース BitmapData から dest BitmapData に Marshal.Copy を使用して何かを取得することができましたが、タイル化された、水平方向に引き伸ばされた画像を作成します。

4

3 に答える 3

1

32bpp [P]ARGB ピクセル形式を使用している場合、これは LockBits/BitmapData を使用して問題なく動作するはずです。コツは、データを一度に 1 行ずつコピーして、正しい場所に配置する必要があることです。次のようなものを使用してこれを行うことができるはずです。

Rectangle srcArea = new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height);
BitmapData srcData = srcBitmap.LockBits(srcArea, ImageLockMode.ReadOnly, destBitmap.PixelFormat);
Rectangle destArea = new Rectangle(25, 25, srcBitmap.Width, srcBitmap.Height);
BitmapData destData = destBitmap.LockBits(destArea, ImageLockMode.WriteOnly, destBitmap.PixelFormat);

IntPtr srcPtr = srcData.Scan0;
IntPtr destPtr = destData.Scan0;
byte[] buffer = new byte[srcData.Stride];
for (int i = 0; i < srcData.Height; ++i)
{
    Marshal.Copy(srcPtr, buffer, 0, buffer.Length);
    Marshal.Copy(buffer, 0, destPtr, buffer.Length);

    srcPtr += srcData.Stride;
    destPtr += destData.Stride;
}

srcBitmap.UnlockBits(srcData);
destBitmap.UnlockBits(destData);

警告として、このコードはそのままでは機能しません。なぜなら、IntPtr をインクリメントするための正しい呪文がわからないからです。私は以前にこれと同じタイプのことをしましたが、C++ で行いました。また、中間バッファーを使用する代わりに、データを直接コピーする方法があるかどうかもわかりません。

追加の警告: LockBits 呼び出し srcBitmap とバッファーのサイズ設定では、srcBitmap が destBitmap に完全に囲まれることを前提としています。そうでない場合 (ビットマップの一部が切り取られる)、領域がロックされ、バッファのサイズを調整する必要があります。

32bpp ピクセル形式 (つまり 24bpp) を使用していない場合は、さらに難しくなります。ソース BitmapData のストライドには、コピーしてはならない量のパディングが含まれている場合があります。ソース行の実際のピクセル データの量を計算し、この量をコピーすることで、これを回避できます。インデックス付きのピクセル形式はさらに手間がかかります。

于 2009-05-19T23:35:22.587 に答える