2011-10-30 9 views
3

BMP.HeightまたはBMP.Widthを設定しようとすると、BMPファイルを操作しようとすると「EOutofresources - ストレージが不足しています。これらの命令の後にImediatelly、スタックトレースは(この順序で) ntdll.dll.RtlLeaveCriticalSection、kernel32.dll.FileTimeToDosDateTime、GDI32.dll.GdiReleaseDC、GDI32.dll.PatBlt、kernel32.dll.ReadFileまたは次のようになります。ビットマップで作業中に「ストレージが不足しています」というエラーが発生しました

|7E429130|user32.dll   GetParent     
|7C90FF2D|ntdll.dll   RtlGetNtGlobalFlags  
|77F15A00|GDI32.dll   GdiReleaseDC 
|7C83069E|kernel32.dll  FileTimeToDosDateTime 
|7C9010E0|ntdll.dll   RtlLeaveCriticalSection 
|  |my function (where I set BMP.Height or BMP.Width) 

現時点では私はそれがメモリの断片化で何かを持っていることを確認しました - システムは、私の画像を処理するのに十分な空きRAMがあったが、私のイメージを保持するのに十分な大き一切ブロックがなかったので、メモリが断片化されました。しかし、その後私はそれがWindowsの起動後11秒に1回起こっているのを見ました。私のプログラムは、私が一度だけ画像を処理するループを循環しました!したがって、これはRAMの断片化に関連するものではありません。

異なる状況(まだ図面に関連した)、私はこのエラーを得たときは、以下の通りです:

|77F16A7E|GDI32.dll   IntersectClipRect  
|77F16FE5|GDI32.dll   BitBlt    
|7E429011|user32.dll   OffsetRect   
|7E42A97D|user32.dll   CallWindowProcA   
|7E42A993|user32.dll   CallWindowProcA   
|7C9010E0|ntdll.dll   RtlLeaveCriticalSection 
|7E4196C2|user32.dll   DispatchMessageA  
|7E4196B8|user32.dll   DispatchMessageA  
|0058A2E1|UTest.exe   UTest.dpr 
|7C90DCB8|ntdll.dll   ZwSetInformationThread 

私はBMP.Height後のスタックトレースの「RtlLeaveCriticalSection」コールが常にあると思います。

thisというポストが、Windowsレジストリキーを編集して解決策を示しています。しかし、この記事はWin XPだけに当てはまると言います。私のエラーが勝つ7


にも見えますが、私は多くの類似の記事を参照してください(そのうちのいくつかは、近いディスクにファイルを保存するに接続されている)が、誰もが、彼は、エラーを修正したことを報告するために戻って来なかったまで。


更新:

あなたが要求したように、これはエラーが表示されたコードです:

procedure TMyBitmap.SetLargeSize(iWidth, iHeight: Integer); 
CONST ctBytesPerPixel= 3; 
begin 
{ Protect agains huge/empty images } 
if iWidth<  1 then iWidth:=  1 else 
if iWidth> 32768 then iWidth:= 32768; 

if iHeight<  1 then iHeight:=  1 else 
if iHeight> 32768 then iHeight:= 32768; 

{ Set image type } 
if iWidth * iHeight * ctBytesPerPixel > 9000000 {~9MB}      
then HandleType:= bmDIB           { Pros and cons: -no hardware acceleration, +supports larger images } 
else HandleType:= bmDDB;              

{ Total size is higher than 1GB? } 
if (iWidth* iHeight* ctBytesPerPixel) > 1*GB then 
    begin 
    Width := 8000;               { Set a smaller size } 
    Height := 8000;               { And rise an error } 
    RAISE Exception.Create('Image is too large.'); 
    end; 

{ Set size } 
Width := iWidth;       <----------------- HERE 
Height:= iHeight; 
end; 
+1

ソースコードを表示してください...メモリリークよりもリソースリーク(ハンドルリーク)のように聞こえる... – Yahia

+0

ビットマップの大きさはどれくらいですか? –

+0

ビットマップのサイズは任意です。通常は、通常のデジタルカメラの画像(4-16メガピクセル)である必要があります。 – Ampere

答えて

4

私の実験から、最大ビットマップのサイズが依存:

  • OSのバージョン(例えば、XPはSevenよりも小さなビットマップリソースを許可するようです)。
  • OSのエディション(64ビットOSでは32ビットOSよりも大きなリソース割り当てが可能です)。
  • 現在のRAMがインストールされています(無料)。
  • 既に割り当てられているビットマップの数(これらは共有リソースなので)。

巨大なデータ(画面上のビットマップ解像度以上)で作業を開始すると、ビットマップ割り当てが成功するかどうかは分かりません。ここで

いくつかの潜在的な解決策(私はそのうちのいくつかを使用しました)されています

  • は、それを描くために、直接のWin32のBitBlt APIを使用し、ビットマップリソースをない割り当てるが、で動作するように、プレーンメモリブロック - 32ビットOSでは、IMHO VirtualAlloc API(大きなメモリブロック用にFastMM4によって呼び出されたもの)は、より多くを割り当てることができません。 1 GBの連続したメモリ。
  • 巨大なRAMブロック(歓迎XE2コンパイラ)を処理するために64ビットプロセスを使用するか、または一時的なストレージ用にファイルを使用し、その内容をメモリマップして処理します(これはPhotoShopやその他の処理方法です巨大なメモリ) - あなたが十分なRAMを持っている場合、一時ファイルを使用する必要はありません遅い(データはディスクに書き込まれません)。
  • 大きな画像を小さな画像に並べる - JPEGライブラリは画像の一部のみをレンダリングすることができ、ビットマップリソースに簡単に収まるようになります。
  • すべてのビットマップリソースが共有されているので、ビットマップリソースが重複しないようにしてください。たとえば、ビットマップから読み込み、その内容を一時メモリブロックまたはファイルにコピーし、リソースを解放し、宛先ビットマップ。
  • パフォーマンスについては、それを正しいものにしてから速くしてください。実装が早すぎる "トリック"は含めないでください(お客様は数秒待つことができますが、グローバルなエラーは受け付けません)。

完全な解決策はありません(私の好みは、プロセスにとって簡単にマルチスレッド化できるという利点があるため、小さいCPUを使用することです)。リソースの割り当ては、新しい64ビットWindows 7 PCでも動作しますが、お客様の32ビットXPコンピュータでは機能しません。

関連する問題