объединить несколько изображений JPEG с низким или постоянным объемом памяти - PullRequest
3 голосов
/ 20 марта 2012

У меня есть несколько изображений, и каждое изображение имеет разрешение около 2560x10000, я хочу объединить все эти изображения в одно изображение. Я не могу использовать метод BufferedImage в качестве конечного изображения, и изображение, к которому я должен присоединиться, будет в памяти одновременно, вызывая OutOfMemory. Поэтому я попробовал следующий подход:

public static void joinJpegFiles(File infile, File outfile, float compQuality,int i) {
    try {
        RenderedImage renderedImage = ImageIO.read(infile);
        ImageWriter Iwriter = null;

        Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
        if (iter.hasNext()) {
            Iwriter = (ImageWriter)iter.next();
        }

        ImageOutputStream IOStream = ImageIO.createImageOutputStream(outfile);
        Iwriter.setOutput(IOStream);
        IOStream.seek( IOStream.length());
        JPEGImageWriteParam JIWP=new JPEGImageWriteParam(Locale.getDefault());
        JIWP.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
        JIWP.setCompressionQuality(compQuality);
        Iwriter.write(null, new IIOImage(renderedImage,null,null), JIWP);               
        IOStream.flush();
        IOStream.close();
        Iwriter.dispose();
    } catch (IOException e) {
        System.out.println("write error: " + e.getMessage());
    }
}

Этот метод вызывается для каждого изображения, к которому я хочу присоединиться.
Проблема этого подхода заключается в том, что размер конечного изображения увеличивается и равен сумме размеров всех изображений, к которым я присоединился, но при открытии окончательного изображения видно только первое изображение. Я до сих пор не могу понять, что я делаю неправильно, и я также не смог найти пример кода для присоединения к jpegs, кроме подходов BufferedImage и ImageIO.write. Я прочитал в группе новостей, что она работает для формата TIFF, но мне нужно, чтобы она работала для форматов JPEG / PNG.

1 Ответ

1 голос
/ 23 июня 2013

Полагаю, вы уже решили эту проблему или как-то обошли ее, но .. Если кому-то еще понадобится решить аналогичную проблему:

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

Несколько изображений в одном файле:

Ваш код добавляет несколько отдельных файлов JPEG в один файл.Формат JPEG (JFIF) не поддерживает это, и большинство программ, вероятно, увидят ваш файл как первый JPEG с множеством ненужных байтов, добавленных к нему в конце.PNG не позволяет хранить несколько изображений в одном файле AFAIK.Такой формат, как TIFF, позволяет использовать несколько изображений (даже позволяет сохранять их в виде потоков JPEG), поэтому, вероятно, и был вызван формат TIFF.

Однако в стандарте JPEG есть концепция, называемая Сокращенные потоки., это очень похоже на то, как JPEG обычно хранится в пирамидальном формате TIFF.ImageIO JPEGImageWriter поддерживает эту функцию:

"Сокращенные потоки записываются с использованием методов последовательности ImageWriter. Метаданные потока используются для записи изображения только для таблиц в начале потока, итаблицы настраиваются для использования с использованием ImageWriter.prepareWriteSequence. Если метаданные потока не передаются в ImageWriter.prepareWriteSequence, то не записывается изображение только для таблиц. Если метаданные потока, не содержащие таблиц, не передаются в ImageWriter.prepareWriteSequence, то таблицызаписывается только изображение, содержащее стандартные таблицы без визуальных потерь. "

Я не уверен, как другие программы будут интерпретировать файлы такого типа, и согласно документам libjpeg он, вероятно, выигралдаже не работают:

"Хотя сокращенные потоки данных могут быть полезны в закрытой среде, их использование настоятельно не рекомендуется в любой ситуации, когда может потребоваться обмен данными с другими приложениями. Caveat designer."

Так .. Может или можетне подходит для вашего случая использования.

Составьте несколько изображений в одно большое изображение:

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

Он использует буферизированные в памяти байтовые буферы и могут быть мучительно медленными, если у вас недостаточно памяти для хранения данных в ОЗУ.Кроме того, результирующее BufferedImage всегда будет иметь значение TYPE_CUSTOM, поэтому оно будет пропускать большинство потенциально аппаратного или собственного ускорения, которое вы обычно получаете, и некоторые операции могут не работать на нем.Однако, по крайней мере, вы не ограничены ни размером кучи, ни физической памятью.

...