Delphi - 将JPEG和打印输出加载为黑色方块?

时间:2012-02-02 02:24:30

标签: delphi printing jpeg

通过Delphi TCanvas打印JPEG图像时遇到一些麻烦。 在JPEG将打印为黑色的30-50%的任何时间 广场而不是它应该。已尝试更改许多设置以查看 如果有一个特定的条件,它将无法打印,但 截至撰写本文时,没有任何工作,条件仍然存在 - 我无法分辨打印输出何时可能有黑色JPEG或何时打印正确。

以下是我用于将JPEG打印到Canvas的代码。

Screen.Cursor := crHourGlass;
try
  // initialize image
  //>>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;

如果有人有任何想法,我将不胜感激!

此致 詹姆斯

编辑:下面的PrintBitmap方法的代码。我已经采取了将位图保存到磁盘的建议,以便在生成时查看它,即使打印输出为黑色方块,也不会将其保存为黑色方块。我希望这表明问题出现在下面的PrintBitmap代码中。

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 & Height
              BitmapImage,
              TBitmapInfo(BitmapHeader^),
              DIB_RGB_COLORS,
              SRCCOPY);
  finally
    FreeMem(BitmapHeader);
    FreeMem(BitmapImage);
  end;
end; {PrintBitmap}

不幸的是,此代码是由不再在我公司工作的人编写的,我只是想解决现有问题。

1 个答案:

答案 0 :(得分:3)

很难说你发布的代码片段。你应该发布一些自给自足的工作代码(可编辑和可运行) 例如,没有本地var声明,没有Begindoc / EndDoc。

现在,在添加本地声明之后,有一堆编译器警告未初始化变量,如iTopiLeft。如果那些留下随机垃圾,可能是你没有画你认为你做的地方。

您还假设您始终拥有pf24bit格式,但根本无法保证。由于您没有指定相同的JPG是否可以打印正常或随机失败,或者如果它有不同的JPG而您遇到问题,则无法排除格式转换问题。

我还建议您安装一个免费的可用图像调试展示台,在PrintBitmap之前设置一个断点,然后在打印前查看本地Bitmap是否正确。

然后让我们看看PrintBitmap程序中的内容......您是否尝试直接在Printer Canvas上绘图?

更新:
PrintBitmap代码似乎是合法的,除了它不检查任何返回代码:

if not GetDIB(...) then
  raise [...];
if GDI_ERROR = StretchDIBits(...) then
  RaiseLastOSError;

问题可能来自打印机/驱动程序 您是否尝试过其他打印机或其他驱动程序? 另外,请确保您的打印机准备就绪......