Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi &引用;“存储空间不足”;使用位图时出错_Delphi - Fatal编程技术网

Delphi &引用;“存储空间不足”;使用位图时出错

Delphi &引用;“存储空间不足”;使用位图时出错,delphi,Delphi,当我尝试设置BMP.Height或BMP.Width时,当我尝试使用BMP文件时,我得到一个“OutofResources-没有足够的存储空间”。i在这些指令之后,堆栈跟踪立即为(按此顺序): ntdll.dll.RtlLeaveCriticalSection、kernel32.dll.FileTimeToDosDateTime、GDI32.dll.GdiReleaseDC、GDI32.dll.PatBlt、kernel32.dll.ReadFile或类似文件: |7E429130|user32

当我尝试设置BMP.Height或BMP.Width时,当我尝试使用BMP文件时,我得到一个“OutofResources-没有足够的存储空间”。i在这些指令之后,堆栈跟踪立即为(按此顺序): 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秒后发生过一次。我的程序在循环中循环,我只处理一次图像!因此,这与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”调用

有帖子指出了通过编辑Windows注册表项可能的解决方案。然而,邮报说它只适用于赢得XP。而我的错误也出现在Win7上


我看到许多类似的帖子(其中一些与将文件保存到磁盘有密切关系),但直到没有人回来报告他修复了错误


更新:

根据您的要求,这是出现错误的代码:

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;
过程TMyBitmap.SetLargeSize(iWidth,iHeight:Integer);
常数ctbytesperpoixel=3;
开始
{保护大/空图像}
如果iWidth<1,则iWidth:=1
如果iWidth>32768,则iWidth:=32768;
如果iHeight<1,则iHeight:=1,否则
如果iHeight>32768,则iHeight:=32768;
{设置图像类型}
如果iWidth*iHeight*ctBytesPerPixel>9000000{~9MB}
然后HandleType:=bmDIB{优点和缺点:-无硬件加速,+支持更大的图像}
else HandleType:=bmDDB;
{总大小大于1GB?}
如果(iWidth*iHeight*ctbytesperpoixel)>1*GB,则
开始
宽度:=8000;{设置较小的大小}
高度:=8000;{并引发错误}
引发异常。创建('图像太大');
结束;
{设置大小}

宽度:=宽度 根据我的实验,最大位图大小取决于:

  • 操作系统版本(例如XP似乎允许比七个更小的位图资源)
  • 操作系统版本(64位操作系统允许比32位操作系统更大的资源分配)
  • 当前安装的RAM(和免费的)
  • 已分配的位图数(因为它们是共享资源)
因此,当您开始处理大数据(比屏幕上的位图分辨率更高)时,您无法确定位图分配是否成功

以下是一些潜在的解决方案(我已经使用了其中的一些):

  • 不要分配位图资源,而是分配一个普通内存块,然后使用直接Win32 BitBlt API绘制它-但您必须编写一些专用的进程函数(或使用一些第三方库),在32位操作系统上,IMHO VirtualAlloc API(FastMM4为大内存块调用的API)无法分配超过1 GB的连续内存
  • 以前版本的增强:要么使用64位进程来处理巨大的RAM块(欢迎使用XE2编译器),要么使用文件作为临时存储,然后内存映射其内容以进行处理(这是PhotoShop或其他处理巨大内存的方式)-如果您有足够的RAM,则不需要使用临时文件(磁盘上不会写入任何数据)
  • 将大图片平铺成小图片-JPEG库只能渲染图片的一部分,并且可以轻松地放入位图资源中
  • 在所有情况下,防止任何重复的位图资源(因为所有位图资源都是共享的):例如,如果您正在读取位图,请将其内容复制到临时内存块或文件中,释放其资源,然后分配目标位图
  • 关于性能,先做对,然后再做快——不要过早地在实现中包含“技巧”(您的客户可能会接受等待几秒钟,但不会接受全局失败)

没有完美的解决方案(我的首选是使用较小的图片,因为它具有易于多线程处理的优点,因此使用新的CPU可能会加快很多速度),请注意,资源分配可能在您全新的64位Windows 7 PC上工作,但在您客户的32位XP计算机上失败。

请显示源代码…听起来更像是资源泄漏(即句柄泄漏)而不是内存问题…位图有多大?位图可以有任何大小。通常它们应该是普通数码相机图片(4-16 MPixel)。更新:这家伙说他有一个解决方案,将格式设置为PF24位:将图像合并,不要不断创建/销毁。