Board index » delphi » How to get to TImage Canvas drawing bitmap

How to get to TImage Canvas drawing bitmap

I have a bitmap to draw that is higher resolution than a TBitmap allows(
runs out of resources once > about 1500x1500).  So I created a TImage,
loaded a WMF in, set the aspect ratio of the TImage properly and used
the Stretch property to get it to draw on the TImage..

Then, I have a number of objects that I need to draw on top of the
TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
that, it looks fine on the screen.

Now I want to print it (scaled to the printer resolution).  I repeat the
process mentioned above and now I need to have the TImage draw itself to
the printer.

The problem is, that the TImage.Picture.Graphic doesn't include any of
the information that was drawn on the TImage.Canvas.  How do I get the
TImage to draw all of itself to the printer (both the Graphic and the
stuff that was drawn to the TImage.Canvas)?

  mtiede.vcf
< 1K Download
 

Re:How to get to TImage Canvas drawing bitmap


Further testing with a smaller app looks like this ought to work.

Perhaps I have a bug somewhere...

  mtiede.vcf
< 1K Download

Re:How to get to TImage Canvas drawing bitmap


Mark,

You need to use Canvas->CopyRect to get the desired part of the image from
the form. Something like this.

 TRect SrcRect,DesRect;;
Graphics::TBitmap *PrintImage, *FormImage;

        SrcRect = Rect(y,.x, Width, Height);
        DesRect = Rect(0, 0, Width, Height);

        PrintImage = new Graphics::TBitmap();
        FormImage = FormToPrint->GetFormImage();

        PrintImage->Height = DesRect.Bottom;
        PrintImage->Width = DesRect.Right;
        PrintImage->PixelFormat = pf24bit;
        PrintImage->Canvas->CopyRect(DesRect, FormImage->Canvas, SrcRect);

The PrintImage->Canvas now contains the image to be printed.

Hope this helps

John Clark

Quote
"Mark L. Tiede" wrote:
> I have a bitmap to draw that is higher resolution than a TBitmap allows(
> runs out of resources once > about 1500x1500).  So I created a TImage,
> loaded a WMF in, set the aspect ratio of the TImage properly and used
> the Stretch property to get it to draw on the TImage..

> Then, I have a number of objects that I need to draw on top of the
> TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> that, it looks fine on the screen.

> Now I want to print it (scaled to the printer resolution).  I repeat the
> process mentioned above and now I need to have the TImage draw itself to
> the printer.

> The problem is, that the TImage.Picture.Graphic doesn't include any of
> the information that was drawn on the TImage.Canvas.  How do I get the
> TImage to draw all of itself to the printer (both the Graphic and the
> stuff that was drawn to the TImage.Canvas)?

Re:How to get to TImage Canvas drawing bitmap


Hi,

"Mark L. Tiede" schrieb:

Quote

> I have a bitmap to draw that is higher resolution than a TBitmap allows(
> runs out of resources once > about 1500x1500).  So I created a TImage,
> loaded a WMF in, set the aspect ratio of the TImage properly and used
> the Stretch property to get it to draw on the TImage..

That is, TImage.Picture.Graphic is TMetafile at this point...

Quote
> Then, I have a number of objects that I need to draw on top of the
> TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> that, it looks fine on the screen.

I cannot see how this possibly should work.  TImage.Canvas is a wrapper
for TImage.Picture.Bitmap.Canvas; it's invalid whenever the Picture
property holds some graphic type different from TBitmap.  I'd expect an
EInvalidOperation exception here.

A piece of code could help making things clearer.

Greetings, Robert
--
Robert Ro?mair
http://home.t-online.de/home/Robert.Rossmair/
Programming environment: Delphi 5.01 Professional, WinNT 4.0 SP6

Re:How to get to TImage Canvas drawing bitmap


Robert,

Quote
> "Mark L. Tiede" schrieb:

> > I have a bitmap to draw that is higher resolution than a TBitmap allows(
> > runs out of resources once > about 1500x1500).  So I created a TImage,
> > loaded a WMF in, set the aspect ratio of the TImage properly and used
> > the Stretch property to get it to draw on the TImage..

> That is, TImage.Picture.Graphic is TMetafile at this point...

Bingo!  You are correct and that is an important point.

Quote
> > Then, I have a number of objects that I need to draw on top of the
> > TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> > that, it looks fine on the screen.

> I cannot see how this possibly should work.  TImage.Canvas is a wrapper
> for TImage.Picture.Bitmap.Canvas; it's invalid whenever the Picture
> property holds some graphic type different from TBitmap.  I'd expect an
> EInvalidOperation exception here.

You are absolutely correct.  Later I realized that what I said I was doing is
not what I was doing :-)

It looked fine on the screen because all the OBJECTS were there and showed
themselves.  I intended to then have them Draw to the Image canvas, but as you
pointed out (and I found out the hard way :-), that would be illegal since it
is a Metafile.

Quote
> A piece of code could help making things clearer.

Not so easy since a lot of objects and code are involved.  I tried to distill
my problem in the description I posted earlier because it was not easy to make
a simple code snippet from what I have.

Is there a way to have a Panel Print itself?  Or get it to draw itself to a
Canvas or something?  I have all my objects contained in a TPanel for clipping
reasons.  If I could print the Panel, that would help.

Thanks.

  mtiede.vcf
< 1K Download

Re:How to get to TImage Canvas drawing bitmap


"Mark L. Tiede" <mti...@mjwcorp.com> wrote in message news:393CF8CD.893BC345@mjwcorp.com...

Quote
> Is there a way to have a Panel Print itself?  Or get it to draw itself to a
> Canvas or something?  I have all my objects contained in a TPanel for clipping
> reasons.  If I could print the Panel, that would help.

Normally I'd point you to my "Printing" page and tell you to check out a link
there, but Deja has messed up most of its older links, so I'll just repost this:

================================================================

From: "Earl F. Glynn" <EarlGl...@att.net>
Subject: Re: Printing a panel
Date: 03 Jun 1999 00:00:00 GMT
Message-ID: <7j6seo$lsn5@forums.borland.com>
References: <7j6gur$lei18@forums.borland.com>
X-Priority: 3
X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300
Organization: Another Netscape Collabra Server User
X-MSMail-Priority: Normal
Newsgroups: borland.public.delphi.graphics

Quote
Bill Talbert <btalb...@marathonoil.com> wrote in message

news:7j6gur$lei18@forums.borland.com...

Quote
> Ok, I got you this far, hang in there.  This is a tough one, at least for
> me.

> I want to print out the contents I have placed on a panel.  I have placed
> several images and assorted graphic controls on the panel.  Now I want to
> print it out.  My problem is the panel does not have a canvas property.
> Some how I should be able to manipulate the "graphics" on the panel.  What I
> thought might work is to do a screen capture of the panel area, but I am not
> sure what the function calls are.

> Does anybody have any ideas.  I want to be able to scale the image and print
> it to a specific part of the page

The Form has a canvas.  You can create a new bitmap the same size as your panel
and then use CopyRect to copy the Panel and its content from the Form to this
in-memory bitmap.  Then you can print the in-memory bitmap.  Here's an example:

procedure TFormPrintWindows.ButtonPrintPanelClick(Sender: TObject);
  var
    Bitmap       :  TBitmap;
    FromLeft     :  INTEGER;
    FromTop      :  INTEGER;
    PrintedWidth :  INTEGER;
    PrintedHeight:  INTEGER;
begin
  Printer.BeginDoc;
  TRY
    Bitmap := TBitmap.Create;
    TRY
      Bitmap.Width  := Panel1.Width;
      Bitmap.Height := Panel1.Height;
      Bitmap.PixelFormat := pf24bit;  // avoid palettes

      // Copy the Panel area from the Form into a separate Bitmap
      Bitmap.Canvas.CopyRect(Rect(0,0, Bitmap.Width,Bitmap.Height),
                             FormPrintWindows.Canvas,
                             Rect(Panel1.Left, Panel1.Top,
                                  Panel1.Left + Panel1.Width-1,
                                  Panel1.Top  + Panel1.Height-1) );

      // Assumes 10% left, right and top margin
      // Assumes bitmap aspect ratio > ~0.75 for portrait mode
      PrintedWidth  := MulDiv(Printer.PageWidth, 80,100);  // 80%
      PrintedHeight := MulDiv(PrintedWidth, Bitmap.Height, Bitmap.Width);
      FromLeft      := MulDiv(Printer.PageWidth, 10,100);  // 10%
      FromTop       := MulDiv(Printer.PageHeight,10,100);  // 10%

      PrintBitmap(Printer.Canvas,
        Rect(FromLeft, FromTop,
             FromLeft + PrintedWidth,
             FromTop  + PrintedHeight),
        Bitmap);
    FINALLY
      Bitmap.Free
    END;
  FINALLY
    Printer.EndDoc
  END

end;

--
efg

Earl F. Glynn     E-mail:  EarlGl...@att.net
Overland Park, KS  USA

efg's Computer Lab:  http://www.efg2.com/Lab

Re:How to get to TImage Canvas drawing bitmap


Earl,

Quote

> The Form has a canvas.  You can create a new bitmap the same size as your panel
> and then use CopyRect to copy the Panel and its content from the Form to this
> in-memory bitmap.  Then you can print the in-memory bitmap.  Here's an example:

Sorry, my original problem stated that the image could be TOO BIG for a tbitmap.  So I can't
create a bitmap to copy to the printer.

What I am doing is putting all my objects into a TPanel that contains a TImage.  The TImage is
a "map" onto which objects are placed.  The TPanel and TImage objects are made to have a width
and height in pixels the same size as the area I want to draw on the printer.  This area could
be too big for a TBitmap (around 1500x1500 on Win95 and around 3000x3000 on WinNT (by trial and
error) as I recall ).  If the bitmap is too big, when I try to set the dimensions of the
tbitmap, I get an "out of resources" type message.

I thought I had it{*word*180}ed because when the image was loaded from a WMF and I did a PaintTo from
the TPanel to the printer, my objects came out properly including being clipped to the panel.
Unfortunately, I then tried loading a PCX (using ImageLib to convert from PCX to DIB) and then
the image printed fine, but the other objects on the panel were not printed.  Go figure...

Any other suggestions?

  mtiede.vcf
< 1K Download

Re:How to get to TImage Canvas drawing bitmap


"Mark L. Tiede" <mti...@mjwcorp.com> wrote in message news:393D170E.973D08F9@mjwcorp.com...

Quote
> What I am doing is putting all my objects into a TPanel that contains a TImage.  The TImage is
> a "map" onto which objects are placed.  The TPanel and TImage objects are made to have a width
> and height in pixels the same size as the area I want to draw on the printer.  This area could
> be too big for a TBitmap (around 1500x1500 on Win95 and around 3000x3000 on WinNT (by trial and
> error) as I recall ).  If the bitmap is too big, when I try to set the dimensions of the
> tbitmap, I get an "out of resources" type message.
> I thought I had it{*word*180}ed because when the image was loaded from a WMF and I did a PaintTo from
> the TPanel to the printer, my objects came out properly including being clipped to the panel.
> Unfortunately, I then tried loading a PCX (using ImageLib to convert from PCX to DIB) and then
> the image printed fine, but the other objects on the panel were not printed.  Go figure...

Over the last few years, there have been several threads in newsgroups about how metafiles have
various  problems that cannot be easily dealt with.  The suggestion was usually to do the
drawing yourself and avoid metafiles.  (I don't use them much.)

Have you considered writing a routine that draws on a TCanvas?  Call it once to draw on
the canvas of a TImage (or even a TForm in an OnPaint).  Call it again to draw on the
canvas of a TPrinter.  Write the drawing routine in a device independent way and then
use it to draw on any canvas.  This Lab Report shows an example:
http://www.efg2.com/Lab/OtherProjects/PrinterDemo2.htm
I'm not sure if this will help you since I don't know enough about what you're trying to do.

Another possibility is to contact Joe Hecht and see how he's doing on his project
to create bitmaps of any size.  http://home1.gte.net/joehecht.  Joe mentioned this
project in several other newsgroup posts, but I don't think it's ready quite yet.

--
efg

Earl F. Glynn     E-mail:  EarlGl...@att.net
Overland Park, KS  USA

efg's Computer Lab:  http://www.efg2.com/Lab

Re:How to get to TImage Canvas drawing bitmap


Earl,

Quote
> > I thought I had it{*word*180}ed because when the image was loaded from a WMF and I did a PaintTo from
> > the TPanel to the printer, my objects came out properly including being clipped to the panel.
> > Unfortunately, I then tried loading a PCX (using ImageLib to convert from PCX to DIB) and then
> > the image printed fine, but the other objects on the panel were not printed.  Go figure...

> Over the last few years, there have been several threads in newsgroups about how metafiles have
> various  problems that cannot be easily dealt with.  The suggestion was usually to do the drawing
> yourself and avoid metafiles.  (I don't use them much.)

As you may not have noticed above, the WMF WORKS.  The PCX is the one that somehow now has goofed
things up.

Quote
> Have you considered writing a routine that draws on a TCanvas?  Call it once to draw on
> the canvas of a TImage (or even a TForm in an OnPaint).  Call it again to draw on the
> canvas of a TPrinter.  Write the drawing routine in a device independent way and then
> use it to draw on any canvas.  This Lab Report shows an example:
> http://www.efg2.com/Lab/OtherProjects/PrinterDemo2.htm
> I'm not sure if this will help you since I don't know enough about what you're trying to do.

I AM trying to write the code in a device independent manner and I AM trying to draw on a canvas.  In
fact, I have a form with a panel with an image and I setup a Canvas property in my method to the
proper canvas I want to draw to and then I have objects draw on the canvas for a print preview.  That
works.  My intent was just to change the Canvas property to the printer and execute the same code.  I
have run into problems and have tried numerous little work arounds.

Like that fact that when the TImage has a WMF in it, you CAN'T draw to the TImage.Canvas!

Now I have it to where I just wanted to do a PaintTo from the object that had everything on it and it
doesn't draw certain pieces.
I have now tried to eliminate the background bitmap all together and for the WMF, my objects can draw
to the printer okay and for the PCX they can't.  I don't know why that should make any difference,
particularly since everything shows up fine on my panel.

I will go to the PrinterDemo (though I think I already did look at that a while ago) and see what
there is to see.

Quote

> Another possibility is to contact Joe Hecht and see how he's doing on his project
> to create bitmaps of any size.  http://home1.gte.net/joehecht.  Joe mentioned this
> project in several other newsgroup posts, but I don't think it's ready quite yet.

Of course, my boss wanted this project done last March :-(

This thing has driven my crazy!

  mtiede.vcf
< 1K Download

Re:How to get to TImage Canvas drawing bitmap


--
MGCSoft
"Where graphics meets mathematics"
http://www.mgcsoft.com/
Mark L. Tiede <mti...@mjwcorp.com> wrote in message
news:393BF995.C3D62DFB@mjwcorp.com...

Quote
> I have a bitmap to draw that is higher resolution than a TBitmap allows(
> runs out of resources once > about 1500x1500).  So I created a TImage,
> loaded a WMF in, set the aspect ratio of the TImage properly and used
> the Stretch property to get it to draw on the TImage..

> Then, I have a number of objects that I need to draw on top of the
> TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> that, it looks fine on the screen.

Why not set the TImage.Picture.Metafile to your wmf and then add stuff to
the metafile?

    ie  with TMetafileCanvas.Create(anImage.Picture.Metafile,0) do
        try
           Draw(0,0,anImage.Picture.Metafile);
           {Draw other stuff}
        finally
             free;
          end;

     anImage.Repaint; {might not be neccessary}

I haven't tried this and I only work with emf's but I don't see why it
shouldn't work.

tip 1. Don't use fills on the metafile if you're going to stretch it to the
printer, they won't work on most printers.
tip 2. If you're going to send more than one metafile to the printer (or one
only for that matter) select an appropriate clip region into the printer
canvas (assuming it supports clipping). Otherwise you'll get everything
printed that was drawn to the metafile, regardless of whether you can see it
in whole or in part in the TImage.

Gordon

Re:How to get to TImage Canvas drawing bitmap


Hi Mark,

Quote
> > > Then, I have a number of objects that I need to draw on top of the
> > > TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> > > that, it looks fine on the screen.

> > I cannot see how this possibly should work.  TImage.Canvas is a wrapper
> > for TImage.Picture.Bitmap.Canvas; it's invalid whenever the Picture
> > property holds some graphic type different from TBitmap.  I'd expect an
> > EInvalidOperation exception here.

> You are absolutely correct.  Later I realized that what I said I was doing is
> not what I was doing :-)

> It looked fine on the screen because all the OBJECTS were there and showed
> themselves.  

But how do they show themselves?  There has to be some device context
(resp. its Delphi incarnation, TCanvas) to draw to.  Are your so-called
"OBJECTS" TControl descendants, which either have a canvas of their own
(TWinControl) or use their parent's canvas (TGraphicControl)?

Quote
> I intended to then have them Draw to the Image canvas, but as you
> pointed out (and I found out the hard way :-), that would be illegal since it
> is a Metafile.

I conclude from your later contributions to this thread, that you found
out yourself how to draw on a metafile in the meantime?  And why do you
need to use a PCX?

Sorry for all the questions, but after reading your postings over and
over, I still am not sure what you are doing in detail.

Greetings, Robert
--
Robert Ro?mair
http://home.t-online.de/home/Robert.Rossmair/
Programming environment: Delphi 5.01 Professional, WinNT 4.0 SP6

Re:How to get to TImage Canvas drawing bitmap


Hi Mark,

Maybe this is completely out of subject, but can't you use two TImages one
on top of the other on your TPanel? You could have the "bottom" one use only
to load your PCX, and the "top" one could be transparent and be used to draw
your WMF (or reversely, according to the background needed). If both images
have their Align property to alClient, they should remain the same size even
if you change the size of the TPanel..
When you print, you would just have to draw on the TPrinter canvas the two
images one after and over the other (If I understand well both print
correctly separately).

Thrse

"Mark L. Tiede" <mti...@mjwcorp.com> a crit dans le message news:
393BF995.C3D62...@mjwcorp.com...

Quote
> I have a bitmap to draw that is higher resolution than a TBitmap allows(
> runs out of resources once > about 1500x1500).  So I created a TImage,
> loaded a WMF in, set the aspect ratio of the TImage properly and used
> the Stretch property to get it to draw on the TImage..

> Then, I have a number of objects that I need to draw on top of the
> TImage.  I do that by using the TImage.Canvas.Draw method.  After I do
> that, it looks fine on the screen.

> Now I want to print it (scaled to the printer resolution).  I repeat the
> process mentioned above and now I need to have the TImage draw itself to
> the printer.

> The problem is, that the TImage.Picture.Graphic doesn't include any of
> the information that was drawn on the TImage.Canvas.  How do I get the
> TImage to draw all of itself to the printer (both the Graphic and the
> stuff that was drawn to the TImage.Canvas)?

Re:How to get to TImage Canvas drawing bitmap


The final solution to my problem was to set the TBitmap.HandleType to
bmDIB.  Apparently that type of a bitmap does not have the "device
dependent" limits that a bmDDB has.  I was able to create quite large DIB
images and draw to the DIB canvas without problems.  And importantly, I
could print it.  I used StretchDiBits to print it.

Although it all works now, it is a little slow to print.  I will have to
look into that part of the problem.  It is possible that I can skip the
StretchDiBits step.

  mtiede.vcf
< 1K Download

Other Threads