Solved

problem printing a TImage

Posted on 2001-06-14
6
270 Views
Last Modified: 2010-04-06
hello,

i've been trying to send a TImage to my printer, but all i get is a blance piece of paper.

i tried printer.canvas.draw(0,0,image1.picture.graphic), but it doesnt work

printer.canvas := image1.canvas doesnt work eiter, because TCanvas is in this case a read-only value.

does anyone know the solution?
thanks in advance
0
Comment
Question by:brutebass
  • 3
  • 2
6 Comments
 
LVL 4

Accepted Solution

by:
Colin_Dawson earned 50 total points
Comment Utility
ah ha, This old chestnut again.  You're trying to send a Device Dependent Bitmap to the printer.  You need to convert the bitmap to a Device Independant Bitmap before you print it.

Check out the Borland website for an example of how to do this.  (I got a procedure from there a couple of years ago, but can't remember where I've put it.)

Colin Dawson
0
 

Author Comment

by:brutebass
Comment Utility
ah few years ago..well borland.com has changed over the years, i've looked everywhere, but i can't find it.

isnt there another site with some free components?
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
Could you try something simple like:

Printer.Canvas.StretchDraw(RECT(0, 0, Printer.PageWidth, Printer.PageHeight), image1.Picture.Bitmap);

Maybe try creating a TBitmap and copy the TImage into it (and then print the TBitmap)

You've probably already tried it but what the hell, that's my two cents of useless rubbish

The Neil =:)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:brutebass
Comment Utility
Printer.Orientation := polandscape;{PoPortrait;}

  with form5.Image1.Picture.Bitmap do
  begin
       { Call GetDIBSizes to get the Info header and image size }
       GetDIBSizes(Handle, InfoSize, ImageSize);
       { Allocate memory for the info header }
       GetMem(info, infosize);
    //Info := MemAlloc(InfoSize);
    try
      { Allocate memory for the Image }
        GetMem(Image, imagesize);
     // Image := MemAlloc(ImageSize);
      try
        { Retrieve the bitmap bits in device-independent format, the
          palette and the Info header }
        GetDIB(Handle, Palette, Info^, Image^);
        with Info^.bmiHeader do begin
        { Call StretchDIBits to print the bitmap }
          Printer.BeginDoc;
          try
          begin
            StretchDIBits(Printer.Canvas.Handle, 0, 0,
             Printer.PageHeight{Width},
              Printer.PageHeight, 0, 0, biWidth, biHeight, Image, Info^,
              DIB_RGB_COLORS, SRCCOPY);
          end;
          finally
            Printer.EndDoc;
          end;
        end;
      finally
        FreeMem(Image, ImageSize); // Free the memory allocated
      end;
    finally
      FreeMem(Info, InfoSize);
  end;
      Printer.Orientation := PoPortrait;
  end;

0
 

Author Comment

by:brutebass
Comment Utility
thanks for helping me on the right way... DBB -> DIB :)
with your help i found some stuff i didnt know about Device Independent Bitmaps. i found some sourcecode on google.com and it works. I submitted the code to the thread on EE.

thanks,

brutebass
0
 
LVL 4

Expert Comment

by:Colin_Dawson
Comment Utility
Glad I could point you in the right direction.  I would have put the code snippet straight in here, but I could not remember where I'd put it.   I've got a really easy method for doing this conversion, wrapped up as a single function call!  Here's the source.

You should find that is is REALLY simple to use. And it also means that you don't have to worry about the conversion.

Thanks for the points.



procedure BltTBitmapAsDib(DestDc : hdc;   {Handle of where to blt}
                          x : word;       {Bit at x}
                          y : word;       {Blt at y}
                          Width : word;   {Width to stretch}
                          Height : word;  {Height to stretch}
                          bm : TBitmap);  {the TBitmap to Blt}
var
  OriginalWidth :LongInt;               {width of BM}
  dc : hdc;                             {screen dc}
  IsPaletteDevice : bool;               {if the device uses palettes}
  IsDestPaletteDevice : bool;           {if the device uses palettes}
  BitmapInfoSize : integer;             {sizeof the bitmapinfoheader}
  lpBitmapInfo : PBitmapInfo;           {the bitmap info header}
  hBm : hBitmap;                        {handle to the bitmap}
  hPal : hPalette;                      {handle to the palette}
  OldPal : hPalette;                    {temp palette}
  hBits : THandle;                      {handle to the DIB bits}
  pBits : pointer;                      {pointer to the DIB bits}
  lPPalEntriesArray : PPalEntriesArray; {palette entry array}
  NumPalEntries : integer;              {number of palette entries}
  i : integer;                          {looping variable}
begin
  {If range checking is on - lets turn it off for now}
  {we will remember if range checking was on by defining}
  {a define called CKRANGE if range checking is on.}
  {We do this to access array members past the arrays}
  {defined index range without causing a range check}
  {error at runtime. To satisfy the compiler, we must}
  {also access the indexes with a variable. ie: if we}
  {have an array defined as a: array[0..0] of byte,}
  {and an integer i, we can now access a[3] by setting}
  {i := 3; and then accessing a[i] without error}
  {$IFOPT R+}
    {$DEFINE CKRANGE}
    {$R-}
  {$ENDIF}
  OriginalWidth := bm.Width; {Save the original width of the bitmap}
 {Get the screen's dc to use since memory dc's are not reliable}
  dc := GetDc(0);
  IsPaletteDevice := GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE; {Are we a palette device?}
{  dc :=} ReleaseDc(0, dc); {Give back the screen dc}
 {Allocate the BitmapInfo structure}
  if IsPaletteDevice
  then BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255)
  else BitmapInfoSize := sizeof(TBitmapInfo);
  GetMem(lpBitmapInfo, BitmapInfoSize); {Zero out the BitmapInfo structure}
  FillChar(lpBitmapInfo^, BitmapInfoSize, #0);
  {Fill in the BitmapInfo structure}
  lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
  lpBitmapInfo^.bmiHeader.biWidth := OriginalWidth;
  lpBitmapInfo^.bmiHeader.biHeight := bm.Height;
  lpBitmapInfo^.bmiHeader.biPlanes := 1;
  if IsPaletteDevice
  then lpBitmapInfo^.bmiHeader.biBitCount := 8
  else lpBitmapInfo^.bmiHeader.biBitCount := 24;
  lpBitmapInfo^.bmiHeader.biCompression := BI_RGB;
  lpBitmapInfo^.bmiHeader.biSizeImage := ( ( lpBitmapInfo^.bmiHeader.biWidth *
                                          longint( lpBitmapInfo^.bmiHeader.biBitCount ) ) div 8 ) *
                                          lpBitmapInfo^.bmiHeader.biHeight;
  lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0;
  lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0;
  if IsPaletteDevice
  then begin
         lpBitmapInfo^.bmiHeader.biClrUsed := 256;
         lpBitmapInfo^.bmiHeader.biClrImportant := 256;
       end
  else begin
         lpBitmapInfo^.bmiHeader.biClrUsed := 0;
         lpBitmapInfo^.bmiHeader.biClrImportant := 0;
       end;
  {Take ownership of the bitmap handle and palette}
  hBm := bm.ReleaseHandle;
  hPal := bm.ReleasePalette;
 {Get the screen's dc to use since memory dc's are not reliable}
  dc := GetDc( 0 );
  if IsPaletteDevice
  then begin
         {If we are using a palette, it must be}
         {selected into the dc during the conversion}
          OldPal := SelectPalette(dc, hPal, TRUE);
          RealizePalette(dc); {Realize the palette}
        end
  Else OldPal := 0;
  {Tell GetDiBits to fill in the rest of the bitmap info structure}
  GetDiBits( dc, hBm, 0, lpBitmapInfo^.bmiHeader.biHeight, nil, TBitmapInfo(lpBitmapInfo^), DIB_RGB_COLORS );
  {Allocate memory for the Bits}
  hBits := GlobalAlloc( GMEM_MOVEABLE, lpBitmapInfo^.bmiHeader.biSizeImage );
  pBits := GlobalLock( hBits );
  GetDiBits( dc, hBm, 0, lpBitmapInfo^.bmiHeader.biHeight, pBits, TBitmapInfo( lpBitmapInfo^ ), DIB_RGB_COLORS); {Get the bits}
  if IsPaletteDevice then
  begin
    {Lets fix up the color table for buggy video drivers}
    GetMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
    {$IFDEF VER100}
    NumPalEntries := GetPaletteEntries( hPal, 0, 256, lPPalEntriesArray^ );
    {$ELSE}
    NumPalEntries := GetSystemPaletteEntries( dc, 0, 256, lPPalEntriesArray^ );
    {$ENDIF}
    for i := 0 to (NumPalEntries - 1) do
    begin
      lpBitmapInfo^.bmiColors[i].rgbRed := lPPalEntriesArray^[i].peRed;
      lpBitmapInfo^.bmiColors[i].rgbGreen := lPPalEntriesArray^[i].peGreen;
      lpBitmapInfo^.bmiColors[i].rgbBlue := lPPalEntriesArray^[i].peBlue;
    end;
    FreeMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
  end;
  if IsPaletteDevice then
  begin
    SelectPalette(dc, OldPal, TRUE); {Select the old palette back in}
    RealizePalette(dc); {Realize the old palette}
  end;
{  dc := }ReleaseDc(0, dc); {Give back the screen dc}

  IsDestPaletteDevice := GetDeviceCaps(DestDc, RASTERCAPS) and RC_PALETTE = RC_PALETTE; {Is the Dest dc a palette device?}
  if IsPaletteDevice then
  begin
   {If we are using a palette, it must be}
   {selected into the dc during the conversion}
    OldPal := SelectPalette(DestDc, hPal, TRUE);
    RealizePalette(DestDc); {Realize the palette}
  end; {Do the blt}
  StretchDiBits( DestDc, x, y, Width, Height, 0, 0, OriginalWidth, lpBitmapInfo^.bmiHeader.biHeight,
                 pBits, lpBitmapInfo^, DIB_RGB_COLORS, SrcCopy );
  if IsDestPaletteDevice then
  begin
    SelectPalette( DestDc, OldPal, TRUE );     {Select the old palette back in}
    RealizePalette( DestDc );    {Realize the old palette}
  end; {De-Allocate the Dib Bits}
  GlobalUnLock(hBits);  GlobalFree(hBits); {De-Allocate the BitmapInfo}
  FreeMem(lpBitmapInfo, BitmapInfoSize);
  {Set the ownership of the bimap handles back to the bitmap}
  bm.Handle := hBm;
  bm.Palette := hPal;
  {Turn range checking back on if it was on when we started}
  {$IFDEF CKRANGE}
    {$UNDEF CKRANGE}
    {$R+}
  {$ENDIF}
end;
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

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…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now