Как записать огромный JPEG, который превышает физическую RAM с помощью Delphi?

Вот проблема. У меня есть большой набор мозаик JPEG на 512x512 пикселей как регулярные jpg файлы.

Я записал часть программного обеспечения, которое делает набор вещей и действительно должно сшить все те файлы в единственный огромный JPEG в конце.

В первую очередь, я НЕ хочу использовать ImageMagick, чтобы сделать это, но выполнить его в моем программном обеспечении!

В Delphi не возможно скопировать файл JPG на другой холст JPG, таким образом, TBitmap должен быть создан сначала, затем мозаики копируются на холст TBitmap, и затем TBitmap преобразовывается в изображение JPEG и сохраняется в файл.

Проблема возникает, когда получающиеся размеры файла являются слишком большими (как 20 000 x 20 000 пикселей). Когда я называю TBitmap. SetSize я естественно получаю ошибку (из памяти или чего-то вроде этого).

Я сделал некоторые тесты с помощью Photoshop на той же самой машине и смог создать комплекс (не пробел) 30 файлов 000 x 30 000 и сохранить его к JPEG.

Таким образом, вопрос, как я мог выполнить то же самое? Fing некоторый способ сшить все те JPEGS путем записи результата непосредственно в диск или использовать некоторый другой прием?...

Даже при том, что 20k x 20k пиксели кажется достаточно большим, это значение действительно только относится к моей машине (поршень на 4 ГБ), таким образом, меньшая сумма поршня еще больше ограничила бы программным обеспечением!

Спасибо

Редактирование: разъясниться:

То, что я хотел бы, должно найти способ сшить те маленькие изображения JPG и записать большое, не сохраняя большое изображение в RAM. По-видимому, растровое потоковое чтение-запись возможно непосредственно на диске (не уверенный), но это привело бы к ОЧЕНЬ большому файлу. Так, если бы формат JPG не позволяет делать, это, любой другой сжатый формат как TIFF или PNG сделали бы. Я также хотел бы избежать слишком большого повторного сжатия для не потери (уже сжатый) начальное качество JPG.

Следовательно идеальное решение было бы способом непосредственно считать маленькие файлы и запись в большую так или иначе. Размеры мозаик 256x256 или 512x512 в случае, если это помогло бы для некоторого выравнивания на материале сжатия JPEG.

11
задан Alexander 27 June 2010 в 13:29
поделиться

8 ответов

Всем спасибо!

Фактически, ответ и возможное решение - действовать так же, как Photoshop, то есть записывать поток растровых изображений из плиток в большой файл BMP на диске (например, файл размером 20 000 x 30 000 будет 2,4 Гб) и затем используйте библиотеку NativeJpg, чтобы преобразовать это большое растровое изображение в jpg, передав полоску данных растрового изображения по полосе, каждая из которых имеет высоту 8 пикселей.

Также можно было бы сшить одну линию плиток (высотой 512 пикселей), а затем передать ее в библиотеку NativeJpg 8 на 8, а затем перейти к следующей строке плиток!

Пример кода от Эрика Тернера:

procedure GetBitmapTile(BM: TBitmap; Y, X: Integer);
var JpegImage: TJpegImage;
begin
  JpegImage := NIL; // Replace with tile lookup //
  BM.PixelFormat := pf32bit;
  BM.Width := JpegImage.Width;
  BM.Height := JpegImage.Height;
  BM.Canvas.Draw(0, 0, JpegImage);
end;

procedure WriteBitmapFile(TileCountY, TileCountX: Integer; BM_Stm: TStream);
var
  BM: TBitmap;
  TileY: Integer;
  TileX: Integer;
  PixelY: Integer;
begin
  BM := TBitmap.Create;
  for TileY := 0 to TileCountY-1 do
    for TileX := 0 to TileCountX-1 do
    begin
      GetBitmapTile(BM, TileY, TileX);
      for PixelY := 0 to 511 do
        BM_Stm.Write(BM.ScanLine[PixelY]^, 512 * SizeOf(TRGBQuad));
    end;
    BM.Free;
end;

Библиотека NativeJpg: http://www.simdesign.nl/nativejpg.html

8
ответ дан 3 December 2019 в 08:54
поделиться

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

Вы также можете посмотреть, как это делает кто-то другой. Я отмечаю, что группа разработчиков PixeLook имеет свою библиотеку PixeLook , которая является компонентами Delphi 6 для создания приложений для обработки изображений и данных.

Они утверждают, что большие изображения и матрицы данных легко обрабатываются и на их странице снимков экрана они показывают отображение изображения 5200 x 5200 (26 МБ), и они говорят, что их тесты также проводились с размер изображения до 220 МБ.

Если вам действительно нужна обработка больших изображений прямо в приложении, этот пакет может вам подойти за 50 долларов. Если он близок, но не совсем правильно (я не знаю, присоединится ли он к jpeg), вы можете подумать о покупке исходного кода за 299 долларов, посмотреть, что он делает, и расширить его.

Заявление об ограничении ответственности: я не имею отношения к этой компании.

0
ответ дан 3 December 2019 в 08:54
поделиться

Максимальный размер изображений в Delphi (по крайней мере, в предыдущих версиях) больше зависел от графических драйверов Windows, чем от объема системной памяти

Некоторые эксперименты над этим: Компьютерная лаборатория EFG

1
ответ дан 3 December 2019 в 08:54
поделиться

Вам может потребоваться реализовать собственный класс, чтобы справиться с этим.

В видеопамяти изображение (или экранный буфер) представляет собой линейный массив. Горизонтальные строки сохраняются последовательно, и каждый пиксель соответствует смещению массива в (y * width + x) -1.

Таким образом, в изображении 320x200 пиксель 5,2 будет иметь индекс массива 5 * 320 + 2-1, или 1601. Еще в те дни, когда еще не было аппаратного ускорения, вы бы malloc () использовали буфер размером экрана и математически выполнять такие операции, как рисование текстур, форм, световых эффектов и т. д., затем BLT буфер в видеопамять.

В вашем случае вы можете использовать встроенные классы растровых изображений и изображений для работы с меньшими изображениями, которые помещаются в памяти, а затем копировать их пиксельные данные в большой массив или серию массивов (я забываю, позволяет ли виртуальная память Вам создать буферы> размера физической RAM).Затем, используя библиотеку JPEG, которая работает непосредственно с этим массивом (которая не зависит от размера ОЗУ, установленного на машине), вы сможете передать массив в библиотеку и сохранить ее содержимое на диск. Сжатие LZW довольно просто, и я ожидаю, что в них будет много материала о том, как вручную реализовать сжатие JPEG в Интернете.

Одно предостережение: если вы используете 32-битную ОС, ваше адресное пространство должно быть ограничено до 4 ГБ. Единственный способ, который я могу придумать, чтобы обойти это, - это создать буферы меньшего размера (скажем, по одной строке за раз), бросить заполнение данных той частью данных пикселей, которой соответствует строка в изображения, которые нужно сшить, сохраните и зацикливайте, пока не покроете всю область изображения.

Надеюсь, это ясно. Удачи!

1
ответ дан 3 December 2019 в 08:54
поделиться

Это довольно сложная область, и, как уже сказал @Peter, люди из Photoshop занимаются этим с 1990 года. Вы, вероятно, не сможете работать со встроенными в ваш язык программирования библиотеками декодирования JPG, поскольку они, скорее всего, будут загружать (и распаковывать) все изображение в оперативную память.

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

1
ответ дан 3 December 2019 в 08:54
поделиться

Для такой тяжелой работы я прибегаю к http://www.graphicsmagick.org/

Здесь также есть набор модулей Паскаля http : //graphics32.org/ , но они довольно математичны и сложны (и поэтому я не заставил их работать), но также созданы для тяжелой работы.

1
ответ дан 3 December 2019 в 08:54
поделиться

Photoshop, как и многие другие мультимедийные программы, долгое время сталкивался с проблемой работы с файлами, размер которых превышал размер основной памяти. Для больших фотографий одна из техник - мозаика, позволяющая обработать только часть изображения.

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

Я не программист на Delphi, но меня беспокоит то, что, когда у вас заканчивается память для создания образа, не произойдет ли то же самое, когда вы попытаетесь использовать этот образ?

1
ответ дан 3 December 2019 в 08:54
поделиться

Как насчет частичного решения с использованием внешнего ПО/внутреннего вызова? У IJG (Independent JPEG Group) есть отличный инструмент командной строки jpegtran, который я использовал в своем вьювере для вращения без потерь. Нет проблем с использованием CreateProcess, WaitForsingleObject внутри вашего собственного кода, чтобы сделать его похожим на ваш собственный код. Вы даже можете упаковать исполняемые файлы в свой ресурс и извлечь его временно

У них также есть утилита jpegjoin (найдите ее по адресу http://jpegclub.org/jpegtran/), которую можно использовать таким же образом. UPDATE: эта утилита предназначена для объединения без потерь, поэтому требует гораздо меньше памяти/диска

0
ответ дан 3 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: