FastJpeg ライブラリ (jpegdec.pas) を使用して、JPEG フレームを Graphics.TBitmap オブジェクトにデコードしています。デコードは正常に機能し、TBitmap.SaveToFile() メソッドを使用して目視検査用にビットマップをファイルに出力すると、見栄えがよくなります。次に、TBitmap ハンドルを使用して GetObject() を呼び出し、TDibSection オブジェクトを取得します。返された TDibSection オブジェクトは、トップ レベル フィールド (bmWidth、bmHeight など) の正しい値を示しますが、bmBit は NIL であり、SaveToFile() 呼び出しが画像をディスクに正しく書き出すので驚くべきことがわかりました。私が抱えている問題は、TBitmapHeaderInfo フィールド (dsBmih) がすべてゼロであることです。また、問題があれば、dsBitFields、dshSection、および dsOffset フィールドもすべてゼロになります。プライマリ フィールドが埋められ、それ以降のすべてが除外されたかのようです。ここ'
dsBm: (0, 320, 240, 1280, 1, 32, nil)
dsBmih: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
dsBitfields: (0, 0, 0)
dshSection: 0
dsOffset: 0
以下のコードは、基本的に私が何をしているかを示しています。空白の TBitmapHeaderInfo フィールドが返されるのはなぜですか? これが AVI dll の呼び出しに問題を引き起こしているので、これを修正する必要があります。
これがコードスニペットです
var
theBitmap: Graphics.TBitmap;
aryBytes: TDynamicByteArray;
dibs: TDibSection;
begin
aryBytes := nil;
// The following function loads JPEG frame #0 from a collection of JPEG frames.
aryBytes := LoadJpegFrame(0);
// Decode the first JPEG frame so we can pass it to the compressor
// selector call.
theBitmap := JpegDecode(@aryBytes[0], Length(aryBytes));
if GetObject(theBitmap.Handle, sizeof(dibs), @dibs) = 0 then
raise Exception.Create('Get Object failed getting the TDibSection information for the bitmap.');
// ... The TBitmapHeaderInfo field in dibs is empty as described in the post.
end;
更新: TLama のコメントに応えて、以下に示すようにコードを更新しました。それは今動作します。いくつか質問があります:
1) コードを合理化できますか? これは明らかに上記の元のコードよりもはるかに複雑で、実行する手順が多すぎる可能性があります。
2) すべてのメモリを解放し、必要なすべての GDI ハンドルとオブジェクトを解放していますか? 私はメモリリークを望んでいません。
更新されたコードは次のとおりです。
var
hr: HRESULT;
bmi: TBitmapInfo;
pImg: PJpegDecode;
jpegDecodeErr: TJpegDecodeError;
hbm: HBITMAP;
pBits: Pointer;
begin
hr := 0; pImg := nil; hbm := 0; pBits := nil;
try
jpegDecodeErr := JpegDecode(@aryBytes[0], Length(aryBytes), pImg);
if jpegDecodeErr <> JPEG_SUCCESS then
raise Exception.Create('(TfrmMain_moviemaker_.cmdTestClick) The bitmap failed to decode with error code: ' + IntToStr(Ord(jpegDecodeErr)));
if not Assigned(pImg) then
raise Exception.Create('(TfrmMain_moviemaker_.cmdTestClick) The bitmap decoded from the first JPEG frame in the video file is unassigned: ' + fullVideoInFilename);
pImg^.ToBMI(bmi);
theBitmap := pImg.ToBitmap;
// Now create a DIB section.
hbm := CreateDIBSection(theBitmap.Handle, bmi, DIB_RGB_COLORS, pBits, 0, 0);
if hbm = ERROR_INVALID_PARAMETER then
raise Exception.Create('(TfrmMain_moviemaker_.cmdTestClick) One of the parameters passed to CreateDIBSection is invalid.');
if hbm = 0 then
raise Exception.Create('(TfrmMain_moviemaker_.cmdTestClick) The call to CreateDIBSection failed.');
// Select the compressor. This call USED to fail before TLama's
// suggestion. Now it works.
hr := aviMaker.compression(hbm, nil, true, Self.Handle);
if hr <> S_OK then
raise Exception.Create('(TfrmMain_moviemaker_.cmdTestClick) Error during compressor selector call: ' + FormatAviMessage(hr));
finally
if Assigned(pImg) then
begin
pImg^.Free;
pImg := nil;
end;
if Assigned(theBitmap) then
FreeAndNil(theBitmap);
if hbm > 0 then
DeleteObject(hbm);
end; // try (2)
end;