奇怪的问题。也许有人可以提供一些见识。

  • 场景1 。我在内存中有一个TBitmap,当进行复杂的计算来计算每个像素的颜色时,会写入该TBitmap。通常每隔一段时间(通常是在填充位图的每条水平线之后),将TBitmap绘制到窗体上的图像上(image1.Canvas.Draw(0,0,TBitmap)。在大多数情况下,此工作正常,但我注意到如果每个位图行有很多缓慢的复杂计算(例如,要花费超过30秒或一分钟的时间来计算),则主窗体会出现暂时的“闪烁”,从而以某种方式擦除位图,因此image.draw调用只会绘制最新的计算线和前y行在位图中被遮盖了,我在计算之前通过锁定位图来解决此问题。
  • 方案2. 这是主要的麻烦。我写的是TMemoryStream而不是位图。同样的交易。进行计算以计算每个像素值,然后在此过程中使用memstream.Write(bytevalue,1)将每个像素值写入TMemoryStream。在所有计算的最后,我使用memstream.SaveToFile('whatever.bmp')将流保存到位图,然后使用memstream.Free释放流。如果计算很快,那么无论大小如何,流都将节省(我正在使用10000x10000尺寸进行测试)。

  • 我什至可以告诉您生成的文件将被破坏,因为主应用程序窗口/窗体确实像被重新粉刷一样略有闪烁。当发生这种情况时,就好像位图和TMemoryStream的每个句柄都被杀死/刷新,因此现有数据已损坏。

    有任何想法吗?这真糟透了。尤其是当每个单个图像需要花费一个小时才能创建时,才发现它在完成时发现后台发生了某些事情并损坏了位图或TMemoryStream。

    有什么方法可以像使用位图一样锁定TMemoryStream句柄吗?这可能会有所帮助。或通过一些声明来告诉Delphi:“即使应用程序花费的时间太长,也不要弄乱我的对象”

    还是有人知道Delphi内部的后端原因导致这种情况发生。

    TMemoryStream是在执行所有计算的过程中创建的,因此是一个本地对象。对于位图问题,位图是过程之外的全局变量,它发生了,所以我认为这不是原因。

    在Windows 7下也是如此,但是我注意到Vista下的原始位图问题。

    更新1:

    很抱歉没有使用注释,但是文字大小有限制。

    回复雷米(及其他阅读此书的人)...

    单线程。对于内存流,如果计算速度很快,则在5000x5000分辨率下可以正常工作,但如果校准速度较慢,则无法工作。

    作为基本框架,代码遵循以下原则:
    SetupMemorystream;
    for y:=0 to height do
       for x:=0 to width do
          DoCalcs;
          SetByteValue;
       end;
    end;
    SaveStream;
    

    如果DoCalcs相对较快,那么一切都会按计划进行。如果速度很慢,那么我会损坏TMemoryStream并将流保存到的结果位图也损坏了。

    这与使用内存中的TBitmap相同,直到我发现可以锁定位图,这会阻止Delphi和/或Windows“在需要时”为其重新分配新的句柄,这会破坏位图中的数据。

    这太巧合了,以至于不能认为TMemoryStream及其句柄不会发生相同的问题。

    更新2:

    可能还有一点有用的信息。

    当TMemoryStream保存确定时,结果文件(对于5000x5000位图)的大小为75,000,054字节。

    当保存的流损坏时,它似乎是一个随机值(从句柄损坏到保存流为止的大小)。示例大小分别为22 MB和9 MB。

    当我查看生成的文件是一个十六进制编辑器时,它表明文件的开头与 header 块是正确的,但是尾端以某种方式被截断了。

    真奇怪无论如何,我绝对可以确定在SaveToFile调用之后并释放它之前刷新TMemoryStream吗?

    最佳答案

  • 在将每个字节写入内存流之前,请将“容量”设置为比特流的近似大小,以便它不会经常调整内存大小。这将加快
  • 的速度
  • 我认为您必须为循环
  • 从“高度”和“宽度”中减去1

    干杯

    10-08 01:29