在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
答案 0 :(得分:3)
您应该能够使用Graphic32中的TBitmap32处理大型位图(http://www.graphics32.org/wiki/)
答案 1 :(得分:2)
正如Ben Ziegler建议的那样,你应该在确定bmp的大小之前将bmp的pixelformat设置为某些东西。这一切都有所不同。
答案 2 :(得分:1)
如果将位图的大小设置为大于桌面的大小,则会发生此错误。要避免此错误,您可以按以下方式创建设备无关位图:
bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight;
是否需要此解决方案取决于视频卡的功能。我们在终端服务器情况下遇到了这个错误,在这种情况下,一个会话没有分配太多的视频RAM。使用此解决方案,您可以强制Delphi为您的位图使用普通RAM而不是视频卡上的内存。
答案 3 :(得分:0)
Delphi的TBitmap类在处理如此大的位图时遇到问题。不,你不能将TCanvas直接保存到.jpg文件。
答案 4 :(得分: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;
答案 5 :(得分:0)
正如mghie所说: 这在很大程度上取决于您的系统 见EFGs computer lab on large bitmaps
答案 6 :(得分:0)
尝试将PixelFormat设置为pf32bit或pf24bit(如Ben Ziegler的例子),在大多数情况下,这个PixelFormat可以解决问题(我记得,它主要是在XP上)。 您可以找到更多信息here。
答案 7 :(得分:0)
这不是JPEG格式:规范允许位图大到32767x32767像素。
问题在于大位图的大量内存消耗,和 TCanvas限制最终可以追溯到Windows平台。
我的NativeJpg库将JPEG处理与可视化分开解码,您可以例如使用“逐条带”保存这样的JPEG,结果是更易于管理的位图图块。
NativeJpg是开源的,你可以在这里下载这个lib: http://www.simdesign.nl/forum/viewforum.php?f=16
查看tiledemo,了解如何创建和保存巨大的人工JPEG图像。
亲切的问候,Nils
答案 8 :(得分:0)
要消耗更少的内存,您始终可以尝试创建更小的位图。假设您将打印机高度除以10,或将最大高度设置为1000.只是一个建议,不确定它是否适用于您的情况。它确实每页产生多个图像。
答案 9 :(得分:-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;