Solved

Problem drawing images on printer-canvas...

Posted on 1998-08-17
18
249 Views
Last Modified: 2010-04-04
I get an most irritating error when trying to output BMP-images to the printer. The code below:

  Printer.Begindoc;
  for aa := 0 to 4 do begin
    Image1 := TImage.Create(form1);
    Image1.Picture.LoadFromFile(
      format('c:\pics\pic%0.2d.bmp',[aa+1]));
    Printer.Canvas.StretchDraw(Rect(aa*300,10,aa*300+290,300),Image1.Picture.Graphic);
    Image1.Free;
  end;
  Printer.Enddoc;

... should read PIC01..05.BMP into the TImage Image1 and then transfer each picture to a rectangular area on the printer paper. But every time I run it some (or even all) pictures are left out! I put the code above in an OnClick procedure for a button and when I pressed the button, not one print-out looked the same!!
   I use a P75, 24megs of RAM and I've tried it both on my HP Deskjet 890C and my OKI Okipage 4w. Same annoying results on both of them! The BMPs are about 685 kb in size.

PLEASE HELP!!!
0
Comment
Question by:Dippen
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 2
  • +3
18 Comments
 

Author Comment

by:Dippen
ID: 1336212
Edited text of question
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336213
Hey why don't you try this code, and see what happens....

 Printer.Begindoc;
   for aa := 0 to 4 do begin
     Image1 := TImage.Create(self); //the self word not form1
     Image1.Picture.LoadFromFile(
       format('c:\pics\pic%0.2d.bmp',[aa+1]));
     Printer.Canvas.StretchDraw(Rect(aa*300,10,aa*300+290,300),Image1.Picture.Graphic);

     Image1.Free;
   end;
   Printer.Enddoc;

So try this and report what happens...

Regards,
Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336214
It's Viktor again!
If the sample I gave you doesn't help please get the error and tell us what is it...

Regards,
Viktor Ivanov
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Dippen
ID: 1336215
I've tried your suggestion but the problem remained. Then I rewrote the code to include 36 pictures, since I need to be able to display that many pictures (like an negative chart).
It then left out about 10 pictures, until I added the line marked with *****. Then it worked just fine, but why should I have to StretchDraw twice??

  Printer.Begindoc;
  for aa := 0 to 35 do begin
    Image := TImage.Create(Self);
    try
      Image.Picture.LoadFromFile(format('c:\bildregister\bilder\aa\aa%0.2d.bmp',[aa+1]));
    except
      //If a picture is missing, a blank should be printed...
    end;
    DestRect.Left := (aa mod 7) * 300;
    DestRect.Top := (aa div 7) * 300;
    DestRect.Right := (DestRect.Left + 290);
    DestRect.Bottom := (DestRect.Top + 290);
    Printer.Canvas.StretchDraw(DestRect,
      Image.Picture.Graphic);
    Printer.Canvas.StretchDraw(DestRect,
      Image.Picture.Graphic); ***************
    Image.Free;
  end;
  Printer.Enddoc;

Suggestions?

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336216
Here is what I've got. Remember to include the Printers unit in the uses clause...

The lines followed by // ** are essential. The others are to get the scaling correct otherwise you end up with extremely small images. Printer resolutions are higher than your screen resolution.
--------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  ScaleX, ScaleY: Integer;
  R: TRect;
begin
  Printer.BeginDoc;  // **
  with Printer do
  try
    ScaleX := GetDeviceCaps(Handle, logPixelsX) div PixelsPerInch;
    ScaleY := GetDeviceCaps(Handle, logPixelsY) div PixelsPerInch;
    R := Rect(0, 0, Image1.Picture.Width * ScaleX,
      Image1.Picture.Height * ScaleY);
    Canvas.StretchDraw(R, Image1.Picture.Graphic);  // **
  finally
    EndDoc;  // **
  end;
end;
{Hey, because I haven't included how to do it for 35 images, you need to do your for loop, and assign and load the image from where you want to. If you still can't do it let me know and I'll give you the final code}
-----------------------------------------------
I hope this helps you do your job...

Regards,
Viktor Ivanov
0
 

Author Comment

by:Dippen
ID: 1336217
You've misunderstood my problem, viktor. I'm having no problem positioning the pictures on the canvas, I'm down to less than 0.5 millimeters accuracy and perfect scale ratio.

The question was and is: Why do I have to repeat the Stretchdraw command twice to be sure that all the pictures are included? Why is the single StretchDraw command ignored sometimes, and sometimes not?

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336218
What's wrong with my answer?  I perfectly understood your question, and my example shows you exactly how to do it with only one StretchDraw. Isn't that right?

Anyway, instead of using

  Printer.Canvas.StretchDraw(DestRect,  Image.Picture.Graphic);***************

try using this

 Printer.Canvas.StretchDraw(DestRect,  Image.Picture.Graphic);  //**

and see if it works fine in your way, otherwise why don't you use my way to do it...

Regards,
Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336219
Oh, and if the example above works you won't need to have two Stretches, but only one...

//Viktor Ivanov
0
 

Author Comment

by:Dippen
ID: 1336220
The code I submitted, where I have an aa loop variable from 0 to 35 doesn't work unless I use 2 StretchDraw commands. I want to know why. That's the answer I'm looking for, nothing else. Try my example and see if it works for you. If you do, try it four or five times, and use only one StretchDraw. If it works for you, then maybe it's my printer driver or something else that is the problem and by clarifying that you have helped me. But I have tried it on two different printers, as I stated before, and the same problem occured on both printers.

Your example, besides the scaling, use the exact same technique of putting the image on paper that I do and that method does not work for me. Therefore I haven't tested it, it does not fit into the application I'm developing since I use a different technique of calculating the DestRect.

Please don't answer the question if you have any more suggestions, put it as a comment so I can have some opinions from other experts. If you submit a comment that solves the problem, I will gladly let you repost it as an answer and give you the best grade available!
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1336221
Hi,
What you seem to need to do is to reduce the printer load, since your printers doesn't seem to cope with the images you send them.
Try to use an intermediate TBitmap with a smaller size (1:4-8) and draw your images onto it first and the draw it on the printer canvas. This will reduce the number of pixels transmitted significantly.

  bmIntermediate: TBitmap;

  bmIntermediate := TBitmap.Create;
  bmIntermediate.Width  := bmOriginal.Width div 4; // or whatever
  bmIntermediate.Height := bmOriginal.Height div 4; // or whatever
  bmIntermediate.Canvas.StretchDraw( Rect( 0, 0, bmIntermediate.Width, bmIntermediate.Height ), bmOriginal );
  Printer.Canvas.Draw( 100, 100, bmIntermediate );

Or something like that. Give it a try.

/// John
0
 

Author Comment

by:Dippen
ID: 1336222
I'll check it out. The funny thing is that I tried to add an extra StretchDraw line in the database application I'm developing (the real application...) and then it works just fine; all pictures are shown and in the correct overlapping order.

The problem with your suggestion is that it must reduce picture quality by the same factor, and I'm very eager to get a good looking printout from the application. Earlier I tried to time the StretchDraw so I sent one image every other second, but it didn't help either.
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336223
Well, that's all I could do. Anyway, I'm not sure why it asks for 2nd stretching. It is supose to be working with only one stretch, but i don't know what's going on. maybe some other expert can help :)
All best!

Regards,
Viktor Ivanov
0
 
LVL 3

Expert Comment

by:Matvey
ID: 1336224
I never use StretchDraw. You say it works here, but if I was you, I still wouldn't use it. Try something like:


Var
  Info: PBitmapInfo;
  InfoSize: Integer;
  Image: Pointer;
  ImageSize: DWORD;
  DIBWidth, DIBHeight: Longint;
  bmp: TBitmap;
**********************************************
  GetDIBSizes(bmp.Handle, InfoSize, ImageSize);
  Info := AllocMem(InfoSize);
  Image := AllocMem(ImageSize);
  GetDIB(bmp.Handle, 0, Info^, Image^);
  with Info^.bmiHeader do
  begin
    DIBWidth := biWidth;
    DIBHeight := biHeight;
  end;
  With Printer Do
    StretchDIBits(Canvas.Handle, 0, 0, PageWidth, PageHeight,
                  0, 0, DIBWidth, DIBHeight, Image, Info^,
                  DIB_RGB_COLORS, SRCCOPY);
  FreeMem(Info, InfoSize);
  FreeMem(Image, ImageSize);
0
 
LVL 1

Expert Comment

by:BlackDeath
ID: 1336225
hi, dippen.

what happens if u create timage b4 begindoc and free it after enddoc?

Black Death.
0
 
LVL 1

Expert Comment

by:Odie
ID: 1336226
Dippen,

What version of Delphi is it you're using?
0
 

Author Comment

by:Dippen
ID: 1336227
I'll try your suggestion, Black Death. I'm using v3.0 with Windows 95
0
 

Author Comment

by:Dippen
ID: 1336228
Matvey, if you hear this I would like you to repost your comment as an answer, since I gladely reward you the points. Not only did it solve my problem with the duplicate StretchDraw's, it also solved a problem concerning printing images to a black and white laser printer.
0
 
LVL 3

Accepted Solution

by:
Matvey earned 150 total points
ID: 1336229
Hi Dippen. I'm very glad this way works here too. This code already solved some problems in some questions here earlier. Actually I wrote it based on TForm.Print method. Funny isn't it, Borland came to a dead end with it's own StretchDraw !

Bye!
Matvey
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question