Reputation: 7233
In Delphi 7, I have a library that uses the TCanvas component to output some information. The resulting image is about 4800*6000 pixels and I would like to print it and save it as .jpeg
.
To achieve this, I created a TBitmap and gave its Canvas as parameter to the library and then I assigned the bitmap to the jpeg. Apparently, this is taking too much memory, because I am getting an exception when trying to set the bitmap's width and height, saying "Not enough storage is available to process this command."
// 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();
What am I doing wrong? Could I save Printer.Canvas directly as a .jpeg
file?
Edit: Updated image size approximation from 2000*2000 to 4800*6000
Upvotes: 3
Views: 6216
Reputation: 75
This error occurs if you set the size of the bitmap to something larger than te size of you desktop. To avoid this error you can create a Device Independent bitmap in the following way:
bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight;
Whether you need this solution depends on the capabilities of your video card. We had this error a lot in terminal server situations where not much video RAM was allocated to one session. Using this solution you force Delphi to use normal RAM for your bitmap instead of memory on your video card.
Upvotes: 1
Reputation: 932
To consume less memory, you can always try create smaller bitmaps. lets say you divide the printer height by 10, or set a max height to 1000. Just a suggestion, not sure if it is applicable in your case. It does result more than one image per page.
Upvotes: 0
Reputation: 1
It's not the JPEG format: the spec allows bitmaps as large as 32767x32767 pixels.
The problem is the huge mem consumption of big bitmaps, and the TCanvas limits that ultimately can be traced down to the Windows platform.
My NativeJpg library decodes the JPEG processing separate from visualisation, and you can e.g. save such a JPEG using "strip by strip", with more manageable bitmap tiles as a result.
NativeJpg is open-source and you can download this lib here: http://www.simdesign.nl/forum/viewforum.php?f=16
Look at the tiledemo to see how to create and save huge artificial JPEG images.
Kind regards, Nils
Upvotes: 0
Reputation: 6364
Not sure if this will work or help. But we created a function which will save a component to a 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;
Upvotes: -1
Reputation: 1285
Try to set PixelFormat to pf32bit or pf24bit (as in example by Ben Ziegler), in most cases this PixelFormat does the trick (as I remember, it was mainly on XP). You can find more info here.
Upvotes: 0
Reputation: 46
You should set the pixelformat for the bmp to something before sizing up the bmp, as Ben Ziegler suggests. This makes all the difference.
Upvotes: 2
Reputation: 487
As mghie said: It depends a lot on your system see EFGs computer lab on large bitmaps
Upvotes: 0
Reputation: 2960
you should be able to process large bitmaps using TBitmap32 from Graphic32 (http://www.graphics32.org/wiki/)
Upvotes: 3
Reputation: 431
I tried the following code on my machine (Windows XP, Delphi 2006), and did not receive any exceptions. What OS are you using?
procedure TForm3.Button3Click(Sender: TObject);
var
bmp : TBitmap;
begin
bmp := TBitmap.Create;
bmp.PixelFormat := pf32bit;
bmp.Width := 6000;
bmp.Height := 4800;
bmp.Free;
end;
Upvotes: 0
Reputation: 598309
Delphi's TBitmap class has problems handling such large bitmaps. And no, you cannot save a TCanvas directly to a .jpg file.
Upvotes: 0