Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PrntScr from Delphi vs MS Paint (which bypasses some thing) 2

Status
Not open for further replies.

ronkq

Programmer
Jul 10, 2010
13
US
.have a piece of Delphi (6,7,2010) code which does a screen capture to the Windows Clipboard, and prints a single sheet of the screen (1024x768) on any printer.
Problem: takes too long to get started printing vs MS Paint, which prints immediately.
How to achieve same thing in Delphi/PascaL.
Examination of the print queue - if using Delphi/ Windows normal print entry point; then the print queue fills with 50+ MB of data; if using MS Paint then the print queue fills with about 0.6MB. The Delphi program delivers about 0.7MB of data, but Windows blows it up to 50+MB depending on the printer. Applies to Win XP... Win 7.
What gives?.. What does MS Paint bypass, so that we can bypass that too?
Hope somebody can help.
Thank you for all efforts,
 
oops, "thank you, did so.." is not applicable here . this question was originally posted in the Pascal forum. Where the feedback was to post this question in the Borland Delphi Forum.

Now the question is here and begs for an answer/tip.
thanks,
ronkq.
 
please show us the code you use to print the screenshot.

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Yes, the feedback was given there because Pascal is different than Delphi and the fact that more eyes would see your question here than there.

Anyhow, to get to your question. As I read it, you are wondering why your Delphi program is sending 50+ MB data to the print queue while MS Paint is sending 0.6 MB?

Seeing your code will ultimately help answer this, but I'll make some observations. In my initial look at the question, I notice that the printer will require uncompressed bit data, which means you will end up with a lot of data. A 1024x768 24 bpp bitmap I have here is 6.5MB.

I also notice that my printer's effective resolution per 8 1/2 x 11 page is 6411x4800. This means the amount of data will grow even larger if I'm scaling the image to match the page.

But I can also observe in how MS Paint works that it is *probably* scaling the image to the capabilities of the printer before it sends the data to it. Which means if I take that bitmap I mentioned above, I'm sending too much data if my printer only supports 16 bpp, and the printer driver has to convert it to have meaning to the device. This will also take time. Dots per inch (DPI) will also be a factor, I'm sure.

Anyhow, my guess is that MS Paint is manipulating the image to match the capabilities of the printer, and you will need to learn how to do that as well to match what you are seeing in MS Paint.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Thank you for multiple replies.
My code sends only non-zero (screen) bytes to the printer.
I understand that the Win-printing system may have to (or is geared) to send/specify all bytes to print on the paper; and that therefore 50 MB is warranted. MS Paint would be slaved to that too, but it isn't. What trick does it do to avoid this? It is curious that MS Paint needs to be manually scaled to about 90% for it to be able to put a 1024x768 screen shot on a 8.5x11 inch sheet of paper...
My coed uses the TPrinter object..
procedure TRMH7.PrntScrn1Click(Sender: TObject);

var w : integer;
print_size: integer;

procedure fill_printer_map;
var py, y : integer;
procedure one_scan; var i, ii, x, p, px: integer;
begin
px := (printer.pagewidth-(w*RMH7.ClientWidth))div 2;
x := 0;
repeat
p:= Imag1.Image1.canvas.Pixels[x,y];
if p <> bak_color then begin
printer.Canvas.Pixels[px,py] := p;
for i := 0 to 4 do
for ii := 0 to w-1 do begin
printer.Canvas.Pixels[px+i,py+ii] := p;
inc(print_size,1) end end;
px := px+w; x := x+1;
until x >= RMH7.ClientWidth;
py := py+w
end;{ one_scan}

begin{fill_printer_map}
print_size := 0;
py := (printer.pageheight-(w*RMH7.ClientHeight))div 4;
py := py*3;
for y := 0 to RMH7.ClientHeight-w do begin
one_scan;
if y mod 100 = 0 then Caption := Caption+'.' end; {for y }
end;{fill_printer_map}

procedure CopyToClipboard;
var MyRect :TRect;
begin
Imag1.Image1.ClientHeight := RMH7.ClientHeight;
Imag1.Image1.ClientWidth := RMH7.ClientWidth;
MyRect := Rect(0,0,RMH7.ClientWidth,RMH7.ClientHeight);
Imag1.Image1.Canvas.CopyRect(MyRect,RMH7.Canvas,MyRect);
Clipboard.Open;
Clipboard.Assign(Imag1.Image1.Picture.Bitmap);
MyRect := Rect(0,0,Imag1.Image1.ClientWidth,Imag1.Image1.ClientHeight);
Imag1.Canvas.CopyRect(MyRect,Imag1.Image1.Canvas,MyRect);
Clipboard.close end {CopyToClipboard};


begin {PrntScrn1Click}
printer.Printers.Text;
printer.Orientation := poLandscape;
w := printer.pagewidth;
w := w div RMH7.ClientWidth;
w:= Int_lesser_of(w,printer.pageheight div RMH7.ClientHeight);
RMH7.AutoRefresh.Enabled := false;
{ RMH7.Stat_AutoCycle.Caption := 'AutoCycle: OFF';
} MyMtrx^.old_caption := Caption;
RMH7.AutoRefresh.enabled := false;
{ if RMH7.AutoRefresh.enabled = true then
Stat_AutoCycle.Caption
:= 'AutoCycle: '+inttostr(AutoRefresh.Interval div 1000)
else Stat_AutoCycle.Caption := 'AutoCycle: OFF';
} Caption := 'Print Screen: Printing '
+inttostr(ClientHeight*ClientWidth)+' symbols. Please wait..';
CopyToClipboard;
printer.Title := copy(MyASCIIfile,length(MyASCIIfile)-10,10);
if PrintDialog1.Execute then begin
printer.BeginDoc;
fill_printer_map;
printer.EndDoc;
Info_Msg('RMH7 finished sending Screen Print to '
+#13+#10+'Windows AND your Printer has accepted complete control.'
+#13+#10+'The size of the Screen Data delivered was: '+inttostr(print_size div 1000)+'KB'
+#13+#10+'RMH7 is now ready to do more charting.');
end;
RMH7.Caption := MyMtrx^.old_caption;
end;{PrntScrn1Click}

BTW: found PrintWiz. In demo mode it works fast like MS Paint; and it is written in Delphi. However only the .EXE file is available; and author and his website have been neglected/abandoned since 2006....

Mani tnx,
RonQ
 
sorry... about slight oops on my part: the program sends only non-background colored screen bytes to the printer... figuring the white spaces on the paper would not need changing/printing.....
RonQ
BTW: program fragment is supplied in"confidential mode" to the forum .. and "normal" legalease applies :)
 
My experience(s) show that the print job preamble between MS Paint and Delphi's Printer Object "must be" different. I gather that Windows and the printer both decypher the print job preamble.... So I could see needing knowledge of details about the "print job preamble"; and consequently access to Delphi's TPrinter object to manage the preamble generated by Delphi. All my Delphi versions appear to have the same limitations. For testing I have purchased a copy of Delphi 2010 and it behaves the same way... me sad....since the code only requires Delphi 6....
RonQ
 
Okay, my research indicates that MS Paint is likely compressing the data it sends to the printer. In that sense, it's probably not going to be a big deal for you that your program is not, unless you're working with a networked printer and response time is important.

Now, how it does this is something I'm not finding (or understanding in relation of what to do with it), but this page gives the best clue towards it.


It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
the main reason the speed is an issue (local or networked) is that customer feedback on printing, is "unsatisfactory performance". That it would be faster to copy the clipboard to MS Paint and print (prints in 20seconds), than to invoke the printing from within the program( prints in 10 minutes local or networked); albeit it is acknowledged that this would be more tedious.
The MS link mentioned above only states that raster compression exists, but not -what it takes to do it.
The Unidriver obviously does not "know about" the simple compression of only specifying the pixels which are "non background color"; and Delphi/Unidriver builds the whole canvas for all pixels on the sheet of paper in the Queue, before sending it to the printer. Seems to me that Windows/MS in this case does not isolate the client program from the printer printing job... the program needs to know whether a raster graph or a vector graph device is connected and therefore send different data(types) to the output device. MS says that Unidriver selects its own compression mode(s), if not otherwise directed, but that obviously does not work for/in the Delphi TPrinter Object...
Thanks for dialog(s),
RonQ
 
And in looking at your code (just got the time to), is there any particular reason why you are not using StretchDraw or StretchDIBits to put your image data to the printer? I'd have to profile to be sure, but by the looks of your code what you are doing is slow...

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
StretchDraw / StretchDIBits are new/unfamiliar to me; I'll try looking it up in the Help System for Delphi.
Thanks tip(s). RonQ
 
the Help on StretchDraw does not imply any compression or speed up .. StretchDraw will use the Draw method to stretch the image to fit a specified rectangle... StretchDIBits is not found in Delphi7... Tnx, RonQ
 
the Help on StretchDraw does not imply any compression or speed up ..

But it will probably be much quicker than putting the image to the printer pixel by pixel like you are doing. Besides, this is the preferred and proper method to do the job, and you would do well to do it this way.

StretchDIBits is a Windows API function which does similar to StretchDraw (but a little different).

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
reflecting and sleuthing: seems the print queue fills with the pixel-by-pixel data (50MB) in about 10...20 seconds; and it gets emptied (sent to printer) by Windows in low priority mode (surely a USB port can send data to a printer faster than 50MB per 10 minutes). Looking at CPU performance while printing: CPU is IDLE "all the time" - like in the neighborhood of 80% idle..... in general my / "our" CPU(s) are "never" really busy under Windows. Conjecture: MS Paint "tweaks" the priority of the print job/queue. Sorry that I am right now "out of the office" with no printer attached - for a look and see of this side of the coin... Thanks dialog(s), RonQ
 
Actually my last post is the solution.

That bitmap I referenced above:

With stretchdraw, 269ms to send the print, 6.59MB print size.

Putting pixel by pixel like you are: 3955ms to send to print, 46.1MB print size.

It's the same logical concept as writing/reading disks. You don't send small block chunks to the device because it will be slow.

And as a suggestion, if you ask a question in a forum, please don't doubt the answers you get back in return.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
And as a suggestion, if you ask a question in a forum, please don't doubt the answers you get back in return.
Amen to that!

/Daddy


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
not all forums are alike... I have gotten following response to the same thread question from an other forum:

>>> MS paint is very simple image editing software, it sends very simple data to printer, but your programs is a complicated program, which will processing your image data into this and that, for many purposes.<<<<

what I am I supposed to make out of that?
I am still a newbie to forums and have had to "find/solve" all my other problems/challenges by my self. Thought forums were for discussion(s), did not mean to step on toes and apologise. Just want(ed) to know ramifications. A modern Windows computer really should not have a problem sending 50MB of print....
When you look in Taskmanager and Performance and it says Idle 80% of the time....
Thanks dialog(s) Ronkq
 
A modern Windows computer really should not have a problem sending 50MB of print....
When you look in Taskmanager and Performance and it says Idle 80% of the time....

No offense taken, just was saying that if you ask a question in a forum you should at least consider trying what is returned before you dismiss it.

As far as the quoted text goes, a modern Windows printer really doesn't have a problem sending 50 MB of print, and mine didn't either on the test.

The problem comes in the device and how it handles receiving the data. Your computer will be idle 80% of the time because it's dealing with the device, and in doing that it doesn't need the CPU that much. In my testing, for instance, I locked up the XPS driver in printing pixel by pixel and had to use Task Manager to kill my program and the print driver. And when I ran it to an actual printer, it ran after about 5 minutes and produced garbage print. In short, most print devices aren't designed to deal with data blocks that have small data in them very well.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
me said:
As far as the quoted text goes, a modern Windows printer computer really doesn't have a problem sending 50 MB of print, and mine didn't either on the test.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top