Откройте изображение, используя как можно меньше оперативной памяти - PullRequest
1 голос
/ 07 июля 2011

Я хочу открыть несколько относительно больших файлов (jpg, gif, bmp), используя как можно меньше оперативной памяти. Внутри моей программы мне нужны все открытые файлы, конвертированные в BMP, чтобы я мог их обработать. Однако преобразование из JPG в BMP занимает 27,1 МБ ОЗУ, если я использую классический код преобразования:

function ConvertJPG2BMP(FullFileName: string; BMP: TBitmap);
VAR JPG:  TJpegImage;
begin
 JPG:= TJpegImage.Create;
 TRY
   TRY
     JPG.LoadFromFile(FullFileName);
     BMP.Assign(JPG);
   EXCEPT
   END;
 FINALLY
   FreeAndNil(JPG);
 end;
end;

потому что он использует два изображения (JPEG, который затем передается в растровое изображение).

-

Однако, если я использую TPicture для загрузки файла, я использую только 7,1 МБ ОЗУ. Но в этом случае TPicture.Bitmap пуст, и мне нужен действительный объект TBitmap.

Есть ли способ загрузить изображения с диска, сохраняя при этом небольшой размер mem?

-

(Тестовый файл: 1.JPG, 2,74 МБ, 3264x1840 пикс.)

Ответы [ 2 ]

1 голос
/ 07 июля 2011

Использование памяти происходит не из библиотеки JPEG, а в том виде, в котором вы ее используете.

Если вы конвертируете JPEG в TBitmap, он создаст растровый ресурс, а затем распакует JPEG вбуфер растровой памяти.

Вы можете рисовать прямо из содержимого JPEG на экране.В зависимости от реализации JPEG, он будет использовать (или нет) временный TBitmap.

. Вы не привязаны к устройству JPEG, предоставленному Borland.

Например, вы можете попробовать позвонитьнепосредственно StretchDIBits() Windows API из буфера несжатой памяти, как таковой (этот код извлечен из нашего SSE JPEG декодера ):

procedure TJpegDecode.DrawTo(Canvas: TCanvas; X, Y: integer);
var BMI: TBitmapInfo;
begin
  if @self=nil then
    exit;
  ToBMI(BMI);
  StretchDIBits(Canvas.Handle,X,Y,width,height,0,0,width,height,pRGB,
   BMI,DIB_RGB_COLORS,SrcCopy);
end;

Создание огромного растрового изображения иногда невозможно(по крайней мере, в Windows XP), поскольку он использует общие ресурсы GDI, тогда как использование простой оперативной памяти и StretchDIBits всегда будет работать, даже для огромного контента.Вы можете создать файл с отображенной памятью для обработки двоичного содержимого, но достаточно просто выделить память сразу (и Windows будет использовать жесткий диск, только если не хватает оперативной памяти).На современных ПК у вас должно быть достаточно оперативной памяти даже для больших изображений.(17 МБ это не большое дело, даже для вашего 3264x1840 пикселей).

Затем из этого глобального буфера несжатой памяти, содержащего необработанные пиксельные триплеты, вы можете использовать меньшую битовую карту, соответствующую области изображения, затемработа в регионе, используя StretchDIBits(aBitmap.Handle,....Он будет использовать меньше ресурсов GDI.

Вы также можете полагаться, например, на рисование GDI +, которое будет рисовать его без какого-либо временного растрового изображения.Смотрите, например, OpenSource unit .Из нашего тестирования, это очень быстро и может использоваться без каких-либо TBitmap.Вы также можете запросить только область целого изображения и нарисовать его, используя GDI + на своем растровом холсте: это потребует меньше оперативной памяти.И ваш exe будет немного меньше, чем стандартный JPEG-модуль.И вы сможете отображать и сохранять не только JPEG, но и форматы GIF и TIFF.

Если вы хотите еще больше сократить использование памяти, вам придется напрямую звонитьбиблиотека JPEG, на самом низком уровне.Он может распаковать только область JPEG.Таким образом, вы сможете минимизировать объем используемой оперативной памяти.Вы можете попробовать использовать библиотеку IJL с Delphi, немного старой, но все еще работающей.

1 голос
/ 07 июля 2011

Задняя часть расчета конверта дает 6 мегапикселей.Предполагая, что 32-битный цвет приведет к 24 МБ.

Вы не будете лучше, чем ваш текущий код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...