3

在 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

4

10 回答 10

3

您应该能够使用 Graphic32 ( http://www.graphics32.org/wiki/ )中的 TBitmap32 处理大型位图

于 2009-10-29T02:25:54.367 回答
2

正如 Ben Ziegler 建议的那样,在调整 bmp 大小之前,您应该将 bmp 的像素格式设置为某个值。这一切都不同了。

于 2009-10-29T16:54:16.537 回答
1

如果您将位图的大小设置为大于桌面的大小,则会发生此错误。为避免此错误,您可以通过以下方式创建与设备无关的位图:

bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; 

您是否需要此解决方案取决于您的视频卡的功能。在没有为一个会话分配太多视频 RAM 的终端服务器情况下,我们经常遇到此错误。使用此解决方案,您可以强制 Delphi 为您的位图使用普通 RAM,而不是视频卡上的内存。

于 2012-09-25T10:02:12.717 回答
0

它不是 JPEG 格式:规范允许位图最大为 32767x32767 像素。

问题是大位图的巨大内存消耗,以及最终可以追溯到 Windows 平台的 TCanvas 限制。

我的 NativeJpg 库将 JPEG 处理与可视化分开解码,例如,您可以使用“逐条”保存这样的 JPEG,从而获得更易于管理的位图图块。

NativeJpg 是开源的,你可以在这里下载这个库: http ://www.simdesign.nl/forum/viewforum.php?f=16

查看 tiledemo 以了解如何创建和保存巨大的人造 JPEG 图像。

亲切的问候,尼尔斯

于 2011-07-09T23:59:22.317 回答
0

尝试将 PixelFormat 设置为 pf32bit 或 pf24bit(如 Ben Ziegler 的示例),在大多数情况下,这个 PixelFormat 可以解决问题(我记得,它主要在 XP 上)。你可以在这里找到更多信息。

于 2009-10-29T21:09:49.140 回答
0

正如 mghie 所说:这在很大程度上取决于您的系统,请参阅大型位图上的 EFG 计算机实验室

于 2009-10-29T08:24:21.467 回答
0

要消耗更少的内存,您可以随时尝试创建更小的位图。假设您将打印机高度除以 10,或将最大高度设置为 1000。只是一个建议,不确定它是否适用于您的情况。它确实会导致每页不止一张图像。

于 2012-09-25T10:12:42.567 回答
0

Delphi 的 TBitmap 类在处理如此大的位图时存在问题。不,您不能将 TCanvas 直接保存到 .jpg 文件中。

于 2009-10-28T20:44:05.620 回答
0

我在我的机器(Windows XP,Delphi 2006)上尝试了以下代码,并没有收到任何异常。您使用的是什么操作系统?

  procedure TForm3.Button3Click(Sender: TObject);
  var
     bmp : TBitmap;
  begin
     bmp := TBitmap.Create;
     bmp.PixelFormat := pf32bit;
     bmp.Width := 6000;
     bmp.Height := 4800;
     bmp.Free;
  end;
于 2009-10-28T21:56:07.503 回答
-1

不确定这是否有效或有帮助。但是我们创建了一个将组件保存到 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;
于 2009-10-30T05:39:28.757 回答