2009-10-28 264 views
3

在Delphi 7中,我有一个使用TCanvas组件输出一些信息的库。生成的图像约为4800 * 6000像素,我想将其打印并保存为.jpeg使用Delphi处理大图像,保存为.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

这是什么库,你是否被迫GETMEM或类似的东西?我问这个问题,因为这是一个TBitmap,你会没事的。 RE – Reallyethical 2009-10-28 20:36:44

+0

我没有使用任何特殊的东西,图书馆只是使用Canvas输出一些信息的东西,它也是用Delphi编写的,整个源代码中只有“var s:TStringList”和“ cnv.TextOut(..)“,所以它可以很容易地重新编译,它应该没问题。 – Tom 2009-10-28 20:41:52

回答

0

Delphi的TBitmap类有处理这样大的位图的问题。不,你不能将TCanvas直接保存到.jpg文件。

+0

如果没有人很快提出任何想法/解决方法,我会接受你的答案。 – Tom 2009-10-28 21:23:18

+0

'TBitmap'类本身完全没有问题,它只是Windows API函数的一个包装。取决于Windows版本和图形卡(驱动程序),可能存在问题或不是很简单,但Delphi并没有真正进入它。我可以在我的系统上创建一个10000×10000像素的位图。它只需要一段时间来填充颜色或将其保存到一个文件(380 MB大小)。 – mghie 2009-10-29 08:15:05

+0

答案的一半仍然正确... – Tom 2009-10-30 11:06:28

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; 
+0

带有1GB内存的Windows XP SP1。该应用程序在Windows 7上使用2 GB的RAM没有任何麻烦,但我想确保它在我的系统上运行正常(至少为了调试的缘故) – Tom 2009-10-30 11:07:29

2

应设置像素格式上像Ben Ziegler所建议的那样,在确定bmp之前为bmp提供一些东西。这使所有的差异。

+0

我也会试试这个,反正它是黑白图像。 – Tom 2009-10-30 11:09:25

0

尝试将PixelFormat设置为pf32bit或pf24bit(例如Ben Ziegler),在大多数情况下,这个PixelFormat会执行这个技巧(我记得它主要是在XP上)。 你可以找到更多信息here

-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; 
+0

我已经在做这个。代码发布在问题中。 – Tom 2009-10-31 21:24:49

0

这不是JPEG格式:在规范允许的位图一样大32767x32767像素。

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

我的NativeJpg库解码独立于可视化的JPEG处理,您可以使用“逐条扫描”保存这样的JPEG,从而获得更易于管理的位图切片。

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

看那tiledemo,看看如何创建和保存巨大的人工JPEG图像。如果你的位图的大小设置为东西比你的桌面的TE尺寸

亲切的问候,尼尔斯

1

此错误发生。为了避免这种错误,您可以创建以下面的方式与设备无关的位图:

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

无论你需要这个解决方案取决于你的显卡的能力。在终端服务器情况下,我们遇到了很多错误,其中没有多少视频RAM分配给一个会话。使用这种解决方案,您可以强制Delphi使用普通的RAM作为位图,而不是显卡上的内存。

0

为了消耗更少的内存,您总是可以尝试创建更小的位图。可以说你将打印机高度除以10,或者将最大高度设置为1000.只是一个建议,不确定它是否适用于你的情况。它每页都会产生多个图像。