.jpegとして保存するためにDelphiで大きな画像を処理する
-
08-07-2019 - |
質問
Delphi 7には、TCanvasコンポーネントを使用して情報を出力するライブラリがあります。結果の画像は約4800 * 6000ピクセルです。印刷して .jpeg
として保存したいです。
これを実現するために、TBitmapを作成し、Canvasをパラメーターとしてライブラリに渡し、ビットマップをjpegに割り当てました。ビットマップの幅と高さを設定しようとすると例外が発生し、「このコマンドを処理するのに十分なストレージがありません」と言っているため、これはメモリを大量に消費しているようです。
// output to printer
Printer.BeginDoc();
doPrint(Printer.Canvas);
Printer.EndDoc();
// output in bmp.Canvas
bmp := TBitmap.Create;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; // <- BAM! Exception!
doPrint(bmp.Canvas);
// save as jpeg
jpg := TJPEGImage.Create;
jpg.Assign(bmp);
jpg.SaveToFile('...');
// free
bmp.Free();
jpg.Free();
間違っているのは何ですか? Printer.Canvasを .jpeg
ファイルとして直接保存できますか?
編集:画像サイズの近似値を2000 * 2000から4800 * 6000に更新しました
解決
Graphic32のTBitmap32を使用して大きなビットマップを処理できるはずです( http://www.graphics32.org / wiki / )
他のヒント
bmpのサイズを設定する前に、Ben Zieglerが提案するように、bmpのピクセル形式を何かに設定する必要があります。これがすべての違いになります。
ビットマップのサイズをデスクトップのサイズよりも大きい値に設定すると、このエラーが発生します。このエラーを回避するには、次の方法でデバイスに依存しないビットマップを作成できます。
bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight;
このソリューションが必要かどうかは、ビデオカードの機能に依存します。 1つのセッションに割り当てられたビデオRAMがあまり多くないターミナルサーバーの状況で、このエラーが頻繁に発生しました。このソリューションを使用すると、ビデオカードのメモリではなくビットマップに通常のRAMを使用するようにDelphiに強制します。
DelphiのTBitmapクラスには、このような大きなビットマップの処理に問題があります。いいえ、TCanvasを.jpgファイルに直接保存することはできません。
自分のマシン(Windows XP、Delphi 2006)で次のコードを試しましたが、例外は発生しませんでした。どのOSを使用していますか
procedure TForm3.Button3Click(Sender: TObject);
var
bmp : TBitmap;
begin
bmp := TBitmap.Create;
bmp.PixelFormat := pf32bit;
bmp.Width := 6000;
bmp.Height := 4800;
bmp.Free;
end;
mghieが言ったように: システムに大きく依存します 大きなビットマップのEFGコンピューターラボ
をご覧ください。PixelFormatをpf32bitまたはpf24bit(Ben Zieglerの例のように)に設定してみてください。ほとんどの場合、このPixelFormatはトリックを実行します(覚えているように、それは主にXPでした)。 詳細については、こちらをご覧ください。
JPEG形式ではありません。32767x32767ピクセルのビットマップが仕様で許可されています。
問題は、大きなビットマップの大量のメモリ消費と、最終的にWindowsプラットフォームにまで遡ることができるTCanvasの制限です。
NativeJpgライブラリは、視覚化とは別にJPEG処理をデコードします。 「ストリップごとのストリップ」を使用してこのようなJPEGを保存し、結果としてより管理しやすいビットマップタイルを作成します。
NativeJpgはオープンソースであり、このlibはここからダウンロードできます。 http://www.simdesign.nl/forum/viewforum.php?f=16
タイルデモを見て、巨大な人工JPEG画像を作成および保存する方法を確認してください。
敬具、ニルス
より少ないメモリを消費するために、常により小さいビットマップを作成してみてください。プリンターの高さを10で除算するか、最大高さを1000に設定するとします。提案にすぎず、実際に適用できるかどうかはわかりません。ページごとに複数の画像が作成されます。
これが機能するか、助けになるかはわかりません。しかし、コンポーネントをjpegに保存する関数を作成しました:
function SaveComponentToJPeg(mControl: TWinControl): TJpegImage;
var
bmp: TPicture;
jpg : TJpegImage;
dc: HDC;
wnd: HWND;
Params: array[0..255] of Char;
begin
bmp:=TPicture.Create;
jpg := TJpegImage.create;
try
bmp.Bitmap.Width := mControl.Width - 05; // Deduct for border.
bmp.Bitmap.Height := mControl.Height -05; // Deduct for border.
wnd := mControl.Handle; //ctiveWindow;
dc := GetDc(wnd);
BitBlt(bmp.Bitmap.Canvas.Handle,0,0,bmp.Width,bmp.Height,dc,0,0,SrcCopy);
ReleaseDc(wnd, dc);
jpg.assign(bmp.bitmap);
result := jpg
finally
bmp.Free;
end;
end;