Delphi - загрузка JPEG и вывод на печать в виде черного квадрата? - PullRequest
2 голосов
/ 02 февраля 2012

Возникли проблемы с печатью изображений JPEG через Delphi TCanvas.Где-нибудь между 30-50% времени JPEG будет распечатываться как черный квадрат, а не как должен.Попытался изменить многие настройки, чтобы увидеть, было ли какое-то конкретное условие, при котором он не смог бы печатать, но на момент написания ничего не работало, и условие все еще существует - я не могу сказать, когда распечатка может иметь черный 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}

К сожалению, этот код был написан кем-то, кто больше не работает в моей компании, и я только пытаюсь исправить существующую проблему.

1 Ответ

3 голосов
/ 03 февраля 2012

Сложно сказать по фрагменту, который вы разместили. Вы должны опубликовать некоторый самодостаточный рабочий код (компилируемый и запускаемый).
Например, нет локального объявления var, нет Begindoc / EndDoc.

Теперь, после добавления локальных объявлений, есть куча предупреждений компилятора для Неинициализированных переменных , таких как iTop или iLeft. Если они остаются со случайным мусором, возможно, вы не рисуете там, где, как вы думаете, вы делаете.

Вы также предполагаете, что у вас всегда есть формат pf24bit, который вообще не гарантируется. Так как вы не указываете, может ли один и тот же JPG печатать ОК или случайно произойти сбой, или если у вас есть проблемы с другими JPG, проблемы преобразования формата не могут быть исключены.

Я бы также предложил установить один из бесплатных доступных визуализаторов отладки изображений, установить точку останова перед PrintBitmap и проверить правильность локального Bitmap перед печатью.

Тогда давайте посмотрим, что происходит в процедуре PrintBitmap ... Вы пытались напрямую нарисовать на холсте принтера?

Обновление:
Код PrintBitmap кажется допустимым, за исключением того, что он не проверяет код возврата:

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

Возможно, проблема связана с принтером / драйвером.
Вы пробовали с другим принтером или с другим драйвером?
Кроме того, убедитесь, что ваш принтер готов ...

...