DSPACK コンポーネント ライブラリで記述された Delphi6 DirectShow フィルタ (プッシュ ソース ビデオ フィルタ) があります。FillBuffer() 呼び出しで、変更されたビットマップを宛先メディア サンプルに出力する前に、ビットマップを変更するいくつかの単純なコードで、本当に厄介な問題が発生しています。コードを以下に示します。
ご覧のとおり、Byte ポインターを使用して 24 ビット ビットマップの RGB 値をトラバースする 2 つの単純なループです。このコードは、DirectShow 以外のテスト アプリケーションでは問題なく動作しました。ただし、私の DirectShow フィルターでは、使用されている値に関係なく、レンダリングされたビットマップに変化が見られません。単純にすべてのバイトを 0 に設定したテスト行も確認できます。画像はまだ変更されていません。ファントムまたは破損したビットマップ オブジェクトがないことを確認するために、ビットマップに簡単な文を出力する行を追加しました。文は、レンダリングされたビットマップに表示されます。
さらにややこしいのは、このコードを実行すると、タスク マネージャーから報告されるように、毎秒数千のソフトページ フォールトが発生することです。このコードを無効にすると、ソフトページ フォールトがなくなります。コードがこれを行う原因は何ですか? ループをトレースしたところ、各行の後に Byte 値が変化することが実際に確認されましたが、画像は影響を受けません。
最後に、Scanline を使用せずにピクセル アクセスを行う高速な方法を誰かが知っている場合は、教えてください。TBitmap.Scanline をトレースすると、FreeImage が呼び出されます。可能であれば、メモリ割り当てを最小限に抑えたいと思います。GR32.TBitmap32 を使用できません。Synopse の高速 jpeg デコーダーを使用しており、TBitmap32 オブジェクトでは機能しないためです。
UPDATE : 問題は、ScanLine プロパティにアクセスする前に、ビットマップのPixelFormatプロパティを pf24Bit に設定していなかったことです。詳細については、このスレッドを参照してください:ピクセル変更コードはメイン アプリですばやく実行されますが、Delphi 6 DirectShow フィルターでは他の問題で非常に遅くなります
procedure brightnessTurboBoost(var clip: TBitmap; rangeExpansionPowerOf2: integer; shiftValue: Byte);
var
p0: PByte;
x,y: Integer;
begin
if (rangeExpansionPowerOf2 = 0) and (shiftValue = 0) then
exit; // These parameter settings will not change the pixel values.
for y := 0 to clip.Height-1 do
begin
p0 := clip.scanline[y];
// Can't just do the whole buffer as a big block of bytes since the
// individual scan lines may be padded for CPU alignment.
for x := 0 to (clip.Width - 1) * 3 do
begin
if rangeExpansionPowerOf2 >= 1 then
p0^ := IntToByte((p0^ shl rangeExpansionPowerOf2) + shiftValue)
else
p0^ := IntToByte(p0^ + shiftValue);
// Test wiping the image (didn't work, still see image).
// p0^ := 0;
Inc(p0);
end;
end;
clip.Canvas.TextOut(10, 10, 'HELLO THERE IS THERE ANYONE THERE?');
end;