title: Delphi - Loading JPEG and printing outputs as a black square?
body: <p>Having some trouble with printing JPEG images via Delphi TCanvas. 
  Anywhere between 30-50% of the time the JPEG will print out as a black
  square rather than as it should. Have tried changing many settings to see
  if there was a particular condition under which it would fail to print but
  as of the time of writing nothing has worked and the condition still exists - I am not able to tell when the printout may have a black JPEG or when it will print correctly.</p>
  
  <p>Here is the code I am using to print the JPEG to the Canvas.</p>
  
  <pre><code>Screen.Cursor := crHourGlass;
  try
    // initialize image
    //&gt;&gt;imgImage := TImage.Create(Self);
    imgImage := TImage.Create(Application);
  
    // load image from file
    imgImage.Picture.LoadFromFile(sFileNameAndPath);
  
    // set width and height to that of loaded image
    ////imgImage.Autosize := true;
    ////Printer.Orientation := poPortrait;
    // Header
    Printer.Canvas.Font.Height := MulDiv(GetDeviceCaps(Printer.Canvas.Handle, LOGPIXELSY), 12, 72);
    Printer.Canvas.Font.Name := 'Courier New';
  
    // Determine height and width of 1 printer-character
    iDeltaW := Printer.Canvas.TextWidth('X');
    iDeltaH := Printer.Canvas.TextHeight('X');
  
    // ------------------------------
    // Method #1 - columns and lines
    // ------------------------------
    // what column to printing from
    iFromLeftMargin := iLeft * iDeltaW;
  
    // what line to print from
    iFromTopOfPage := iTop * iDeltaH;
  
    // ------------------------------
    // Method #2 - pixels
    // ------------------------------
    iPPW := Printer.PageWidth;
    iPPH := Printer.PageHeight;
    iIPW := imgImage.Picture.Width;
  
    ePXW := iPPW / iInvImageWidth;   
    ePXH := iPPH / iInvImageHeight;  
    //~//iFromLeftMargin := Ceil(iLeft * pxW);
    //~//iFromTopOfPage  := Ceil(iTop  * pxH);
    iFromLeftMargin := Ceil(iLeft * ePXW);
    iFromTopOfPage  := Ceil(iTop  * ePXH);
  
    // Set printed bitmap width
    iPrintedImageWidth := MulDiv(iPPW, iIPW, iInvImageWidth);  
    // Set printed bitmap height to maintain aspect ratio
    iPrintedImageHeight := imgImage.Picture.Height * iPrintedImageWidth DIV 
      imgImage.Picture.Width; // maintain aspect ratio of bitmap
  
    Bitmap := TBitmap.Create;
    try
      Bitmap.Width  := imgImage.Picture.Width;
      Bitmap.Height := imgImage.Picture.Height;
      Bitmap.PixelFormat := pf24bit;
      Bitmap.IgnorePalette := False;
      // Convert JPEG (GIF, or whatever) to BMP
      Bitmap.Canvas.Draw(0, 0, imgImage.Picture.Graphic);
  
      // Print Image
      PrintBitmap(Printer.Canvas,
        Rect(iFromLeftMargin, iFromTopOfPage,
             iFromLeftMargin + iPrintedImageWidth,
             iFromTopOfPage  + iPrintedImageHeight),
             Bitmap);
    finally
      // free bitmap memory
      Bitmap.Free;
    end;
    // free image memory
    imgImage.Free;
  finally
    Screen.Cursor := crDefault;
  end;
  </code></pre>
  
  <p>If anyone had any ideas it would be much appreciated!</p>
  
  <p>Regards,
  James</p>
  
  <p>EDIT: code for the PrintBitmap method below. I have taken the advice of saving the bitmap to disk to view it as it is being generated and the it is never saved as a black square even when the printed output is a black square. I hope this indicated the problem is in the PrintBitmap code below.</p>
  
  <pre><code>procedure PrintBitmap(Canvas: TCanvas; DestRect: TRect; Bitmap: TBitmap);
  var
    BitmapHeader: pBitmapInfo;
    BitmapImage: POINTER;
    HeaderSize: DWORD;
    ImageSize: DWORD;
  begin
    GetDIBSizes(Bitmap.Handle, HeaderSize, ImageSize);
    GetMem(BitmapHeader, HeaderSize);
    GetMem(BitmapImage,  ImageSize);
    try
      GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapHeader^, BitmapImage^);
      StretchDIBits(Canvas.Handle,
                DestRect.Left, DestRect.Top,     // Destination Origin
                DestRect.Right  - DestRect.Left, // Destination Width
                DestRect.Bottom - DestRect.Top,  // Destination Height
                0, 0,                            // Source Origin
                Bitmap.Width, Bitmap.Height,     // Source Width &amp; Height
                BitmapImage,
                TBitmapInfo(BitmapHeader^),
                DIB_RGB_COLORS,
                SRCCOPY);
    finally
      FreeMem(BitmapHeader);
      FreeMem(BitmapImage);
    end;
  end; {PrintBitmap}
  </code></pre>
  
  <p>Unfortunately this code was written by someone who no longer works at my company and I am only trying to fix an existing issue.</p>