2012-02-02 117 views
2

在通过Delphi TCanvas打印JPEG图像时遇到了一些麻烦。 任何时候,JPEG将以黑色 正方形打印出来的时间为30-50%,而不是按照它应该的那样。尝试更改许多设置以查看 是否存在打印失败的特定条件,但在写入时什么都没有发挥作用且条件仍然存在 - 我无法确定打印输出可能有何时黑色JPEG或打印正确时。Delphi - 将JPEG加载并打印输出为黑色方块?

这是我用来将JPEG打印到画布上的代码。

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} 

不幸的代码是写的人谁不再工作在我的公司,我只是试图解决现有的问题。

+2

请花时间正确格式化您的代码。不要使用制表符;从四个空格字符开始缩进,并根据缩进需要添加额外的空格。(您可以通过在输入问题时立即在输入问题的位置进行实时预览,以便您可以查看格式的使用方式。)发布信息时进行格式化,不仅可以节省其他人的时间,要做到这一点,还要使其更具可读性,以便您更快地获得答案。 :) – 2012-02-02 02:37:06

+0

这是一个多线程应用程序?另外,这是否始终是相同的jpg文件失败?我问这是因为我有一个类似的问题是过去的,因为VCL不是线程安全的。 – Steve 2012-02-02 06:57:57

+0

谢谢你肯为粗心大意抱歉。您好史蒂夫 - 没有它的只是单线程,并发生在不同的JPEG文件,但不是全部。 – jmc 2012-02-02 07:21:16

回答

3

很难用你发布的代码片段来判断。你应该发布一些自足的工作代码(可编译和可运行)。
实例没有本地var声明,没有Begindoc/EndDoc。

现在,加入当地的声明之后,有一个未初始化变量iTopiLeft一堆编译器警告。如果这些东西留下随机垃圾,那可能是因为你没有画出你认为你在做的事。

你也假设你总是有一个pf24bit格式,根本没有保证。由于您没有指定相同的JPG是否可以随机打印确定或失败,或者如果使用不同的JPG格式,您遇到了问题,因此不能排除格式转换问题。

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

然后让我们看看PrintBitmap过程中有什么...您是否试图直接在打印机画布上绘图?

更新:
PrintBitmap代码似乎只是它不检查任何返回代码合法:

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

的问题可能来自打印机/驱动程序。
你用另一台打印机或其他驱动程序尝试过吗?
此外,请确保您的打印机已准备就绪...

+0

+1有一个模糊的问题,答案是不可避免的推测。这里有很多好的建议。 – 2012-02-02 22:25:37

+0

非常感谢您的出色建议。我已经采取了在打印之前保存和查看位图图像的建议,并且它始终是正确的,并且不会在文件中显示为黑色方块。对于问题的不明确性抱歉,问题发生在某种程度上随机出现,同一张JPEG在任何给定时间都可以打印成功或失败。不幸的是,代码写得很差,并且与应用程序的其他区域紧密耦合,因此自给自足的代码很难在这里实现。 我已经添加了上面的PrintBitmap过程。 – jmc 2012-02-03 00:41:45

+0

@jmc,看我的更新。之后,我恐怕我的想法... – 2012-02-03 01:16:19