Обработка больших изображений в Delphi для сохранения в формате .jpeg - PullRequest
3 голосов
/ 28 октября 2009

В Delphi 7 у меня есть библиотека, которая использует компонент TCanvas для вывода некоторой информации. Полученное изображение составляет около 4800 * 6000 пикселей, и я хотел бы распечатать его и сохранить как .jpeg.

Чтобы добиться этого, я создал TBitmap и передал его Canvas в качестве параметра библиотеке, а затем назначил растровое изображение jpeg. Очевидно, это занимает слишком много памяти, потому что я получаю исключение при попытке установить ширину и высоту растрового изображения, говоря: «Недостаточно памяти для обработки этой команды».

// output to printer
Printer.BeginDoc();
doPrint(Printer.Canvas);
Printer.EndDoc();

// output in bmp.Canvas
bmp := TBitmap.Create;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; // <- BAM! Exception!
doPrint(bmp.Canvas);

// save as jpeg
jpg := TJPEGImage.Create;
jpg.Assign(bmp);
jpg.SaveToFile('...');

// free
bmp.Free();
jpg.Free();

Что я делаю не так? Могу ли я сохранить Printer.Canvas непосредственно как .jpeg файл?

Редактировать: Обновлена ​​аппроксимация размера изображения с 2000 * 2000 до 4800 *6000* 1010 *

Ответы [ 10 ]

3 голосов
/ 29 октября 2009

вы должны иметь возможность обрабатывать большие растровые изображения, используя TBitmap32 из Graphic32 (http://www.graphics32.org/wiki/)

2 голосов
/ 29 октября 2009

Вы должны установить для пикселя формат пикселя bmp, прежде чем задавать размер bmp, как предлагает Бен Зиглер. В этом вся разница.

1 голос
/ 25 сентября 2012

Эта ошибка возникает, если вы устанавливаете размер растрового изображения больше, чем размер вашего рабочего стола. Чтобы избежать этой ошибки, вы можете создать независимое от устройства растровое изображение следующим образом:

bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; 

Нужно ли вам это решение, зависит от возможностей вашей видеокарты. Мы часто сталкивались с этой ошибкой в ​​терминальных серверных ситуациях, когда на одну сессию выделялось мало видеопамяти. Используя это решение, вы заставляете Delphi использовать обычную оперативную память для своего растрового изображения вместо памяти на видеокарте.

0 голосов
/ 25 сентября 2012

Чтобы использовать меньше памяти, вы всегда можете попробовать создать меньшие растровые изображения. Допустим, вы делите высоту принтера на 10 или устанавливаете максимальную высоту на 1000. Просто предложение, не уверенное, применимо ли это в вашем случае. В результате получается более одного изображения на странице.

0 голосов
/ 10 июля 2011

Это не формат JPEG: спецификация допускает растровые изображения размером до 32767x32767 пикселей.

Проблема заключается в огромном потреблении памяти большими растровыми изображениями, и ограничениями TCanvas, которые в конечном итоге могут бытьпрослеживается до платформы Windows.

Моя библиотека NativeJpg декодирует обработку JPEG отдельно от визуализации, и вы можете, например, сохранить такой JPEG, используя «полосу за полосой», с более управляемыми плитками растрового изображения в результате.

NativeJpg с открытым исходным кодом, и вы можете скачать эту библиотеку здесь: http://www.simdesign.nl/forum/viewforum.php?f=16

Посмотрите на демонстрацию tile, чтобы узнать, как создавать и сохранять огромные искусственные изображения JPEG.

С уважениемНильс

0 голосов
/ 30 октября 2009

Не уверен, сработает ли это или поможет. Но мы создали функцию, которая будет сохранять компонент в формате JPEG:

    function SaveComponentToJPeg(mControl: TWinControl): TJpegImage;
    var
      bmp: TPicture;
      jpg : TJpegImage;
      dc: HDC;
      wnd: HWND;
      Params: array[0..255] of Char;

    begin
      bmp:=TPicture.Create;
      jpg := TJpegImage.create;
      try
        bmp.Bitmap.Width  := mControl.Width  - 05;  // Deduct for border.
        bmp.Bitmap.Height := mControl.Height -05;  // Deduct for border.
        wnd               := mControl.Handle;  //ctiveWindow;
        dc                := GetDc(wnd);
        BitBlt(bmp.Bitmap.Canvas.Handle,0,0,bmp.Width,bmp.Height,dc,0,0,SrcCopy);
        ReleaseDc(wnd, dc);
        jpg.assign(bmp.bitmap);
        result := jpg
      finally
        bmp.Free;
      end;
    end;
0 голосов
/ 30 октября 2009

Попробуйте установить PixelFormat в pf32bit или pf24bit (как, например, в Ben Ziegler), в большинстве случаев этот PixelFormat добивается цели (как я помню, это было в основном на XP). Вы можете найти больше информации здесь .

0 голосов
/ 29 октября 2009

Как сказала Мги: Это зависит от вашей системы см. компьютерная лаборатория EFG на больших растровых изображениях

0 голосов
/ 29 октября 2009

Я попробовал следующий код на моей машине (Windows XP, Delphi 2006) и не получил никаких исключений. Какую ОС вы используете?

  procedure TForm3.Button3Click(Sender: TObject);
  var
     bmp : TBitmap;
  begin
     bmp := TBitmap.Create;
     bmp.PixelFormat := pf32bit;
     bmp.Width := 6000;
     bmp.Height := 4800;
     bmp.Free;
  end;
0 голосов
/ 28 октября 2009

Delphi TBitmap имеет проблемы с обработкой таких больших растровых изображений. И нет, вы не можете сохранить TCanvas напрямую в файл .jpg.

...