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编写超过物理RAM的巨大JPEG?_Delphi_Bitmap_Jpeg_Tiles_Image Stitching - Fatal编程技术网

如何使用Delphi编写超过物理RAM的巨大JPEG?

如何使用Delphi编写超过物理RAM的巨大JPEG?,delphi,bitmap,jpeg,tiles,image-stitching,Delphi,Bitmap,Jpeg,Tiles,Image Stitching,问题就在这里。我有一大组512x512像素的JPEG图像块作为常规jpg文件 我已经写了一个软件,它可以做很多事情,并且需要在最后将所有这些文件拼接成一个巨大的JPEG 首先,我不想使用ImageMagick来做这件事,而是在我的软件中执行它 在Delphi中,无法将JPG文件复制到另一个JPG画布上,因此必须先创建TBitmap,然后将平铺复制到TBitmap画布上,然后将TBitmap转换为jpeg图片并保存到文件中 当生成的文件尺寸太大(如20000 x 20000像素)时,就会出现问题。

问题就在这里。我有一大组512x512像素的JPEG图像块作为常规jpg文件

我已经写了一个软件,它可以做很多事情,并且需要在最后将所有这些文件拼接成一个巨大的JPEG

首先,我不想使用ImageMagick来做这件事,而是在我的软件中执行它

在Delphi中,无法将JPG文件复制到另一个JPG画布上,因此必须先创建TBitmap,然后将平铺复制到TBitmap画布上,然后将TBitmap转换为jpeg图片并保存到文件中

当生成的文件尺寸太大(如20000 x 20000像素)时,就会出现问题。当我调用TBitmap.SetSize时,自然会出现一个错误(内存不足或类似的情况)

我在同一台机器上使用Photoshop进行了一些测试,能够创建一个复杂的(非空白)30000x30000文件并将其保存到JPEG

所以问题是,我怎样才能做同样的事情?通过将结果直接写入磁盘或使用其他技巧来缝合所有这些JPEG

尽管20k x 20k像素看起来足够大,但这个值只适用于我的机器(4 GB ram),因此更小的ram将对软件造成更大的限制

谢谢

编辑:澄清:

我想要的是找到一种方法来缝合那些小JPG图像,并在不将大图像保存在RAM中的情况下编写大图像。显然,可以直接在磁盘上读取/写入位图流(不确定),但这会导致文件非常大。因此,如果JPG格式不允许这样做,任何其他压缩格式(如TIFF或PNG)都可以。我还想避免过多的重新压缩,以免丢失(已经压缩的)初始JPG质量


因此,完美的解决方案是直接读取小文件,然后以某种方式写入大文件。瓷砖的尺寸为256x256或512x512,以防它有助于JPEG压缩内容的对齐。

Photoshop与许多其他面向媒体的程序一样,必须处理长时间使用大于主内存的文件的问题。对于大型照片,一种技术是仅平铺图像的一部分

实际上,这比简单的剪切和粘贴更复杂(双关语)


我不是Delphi程序员,但让我担心的是,当创建图像的内存不足时,当您尝试使用该图像时,会不会发生同样的情况?

这是一个相当困难的领域,正如@Peter已经说过的,Photoshop的人一直在做这件事。您可能无法使用编程语言的内置JPG解码库,因为它们可能会在RAM中加载(并解压)整个图像


我建议寻找处理这个问题的外部库-我不知道是否有合适的免费库,但可能是这样。

Delphi中图像的最大大小(至少在以前的版本中)更多地取决于windows图形驱动程序,而不是系统内存量

这方面的一些实验:
你的问题也让我想到了电子表格。当然,这里人口稀少。您可以尝试查看一些图像压缩库,这些库可能会给您一些想法

你也可以看看别人是怎么做的。我注意到,PixeLook开发组拥有用于创建图像和数据处理应用程序的Delphi6组件

他们声称,大型图像和数据矩阵易于处理,并且显示5200 x 5200图像(26 MB)的显示,他们还说,他们的测试也在图像大小高达220 MB的情况下进行

如果您真的需要在应用程序中直接进行大型图像处理,这个软件包可能需要50美元。如果它很接近但不完全正确(我不知道它是否会加入JPEG),那么你可以考虑购买源299美元,看看它做什么,并扩展它。


免责声明:我与本公司没有任何联系。

您可能需要实现一个自定义类来处理此问题

在视频存储器中,图像(或屏幕缓冲区)是一个线性阵列。水平行按顺序存储,每个像素对应于(y*width+x)-1处的阵列偏移

因此,在320x200图像中,5,2处的像素将位于阵列索引5*320+2-1或1601处。在硬件加速之前的日子里,你需要一个屏幕大小的缓冲区,然后在数学上执行诸如绘制纹理、形状、灯光效果等操作,然后将缓冲区输出到视频RAM中

在您的例子中,您可以使用内置的位图和图像类处理适合内存的较小图像,然后将它们的像素数据复制到一个大数组或一系列数组中(我忘了虚拟内存是否允许您创建缓冲区>物理RAM的大小)。然后,使用直接在该阵列上工作的JPEG库(与机器上安装的RAM大小无关),您应该能够将该阵列馈送到库中,并让它将内容保存到磁盘。LZW压缩是非常简单的,我希望他们会有很多关于在web上手动实现JPEG压缩的资料

有一个警告:如果你使用的是32位操作系统,你的地址空间应该限制在4GB。我能想到的解决这个问题的唯一方法是创建更小的缓冲区(比如,一次一行),用待粘贴图像中该行对应的部分像素数据填充数据,保存数据,然后循环,直到覆盖整个图像区域

我希望这是清楚的。祝你好运

谢谢大家

事实上,答案和可能的解决方案是像Photoshop那样进行,即将位图流从瓷砖写入一个大的bmp-fi
procedure GetBitmapTile(BM: TBitmap; Y, X: Integer);
var JpegImage: TJpegImage;
begin
  JpegImage := NIL; // Replace with tile lookup //
  BM.PixelFormat := pf32bit;
  BM.Width := JpegImage.Width;
  BM.Height := JpegImage.Height;
  BM.Canvas.Draw(0, 0, JpegImage);
end;

procedure WriteBitmapFile(TileCountY, TileCountX: Integer; BM_Stm: TStream);
var
  BM: TBitmap;
  TileY: Integer;
  TileX: Integer;
  PixelY: Integer;
begin
  BM := TBitmap.Create;
  for TileY := 0 to TileCountY-1 do
    for TileX := 0 to TileCountX-1 do
    begin
      GetBitmapTile(BM, TileY, TileX);
      for PixelY := 0 to 511 do
        BM_Stm.Write(BM.ScanLine[PixelY]^, 512 * SizeOf(TRGBQuad));
    end;
    BM.Free;
end;