Как объединить несколько многостраничных файлов tif в один файл tif

Я пытаюсь взять несколько многостраничных файлов .tif и объединить их в один многостраничный файл tif.

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

Есть ли небольшое изменение, которое я не вижу, которое заставило бы этот же код захватить каждую страницу из исходных файлов .tif и поместить их все в объединенный .tif?

Чтобы уточнить, исходные файлы хотелось бы:

  • SourceA.tif (3 страницы)
  • SourceB.tif (4 страницы)
  • SourceC.tif (1 страница)

быть объединенным в

  • Combined.tif (8 страниц)

Я также хотел бы иметь возможность указать разрешение и сжатие .tif, но я не уверен, поддерживает ли JAI это, и это не является необходимостью для правильного ответа.

Код из указанного вопроса, измененный мной для загрузки всех файлов .tif в каталоге, приведен ниже для удобства ответа:

public static void main(String[] args) {
        String inputDir = "C:\\tifSources";
        File sourceDirectory = new File(inputDir);
        File file[] = sourceDirectory.listFiles();
        int numImages = file.length;

        BufferedImage image[] = new BufferedImage[numImages];

        try
        {
            for (int i = 0; i < numImages; i++)
            {
                SeekableStream ss = new FileSeekableStream(file[i]);
                ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);
                PlanarImage op = new NullOpImage(decoder.decodeAsRenderedImage(0), null, null, OpImage.OP_IO_BOUND);
                image[i] = op.getAsBufferedImage();
            }

            TIFFEncodeParam params = new TIFFEncodeParam();
            OutputStream out = new FileOutputStream(inputDir + "\\combined.tif"); 
            ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
            List<BufferedImage> imageList = new ArrayList<BufferedImage>();   
            for (int i = 0; i < numImages; i++)
            {
                imageList.add(image[i]); 
            }
            params.setExtraImages(imageList.iterator()); 
            encoder.encode(image[0]); 
            out.close();
        }
        catch (Exception e)
        {
            System.out.println("Exception " + e);
        }
    }

person twilbrand    schedule 12.07.2011    source источник


Ответы (1)


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

Дальнейшие поиски в Интернете привели меня к следующему, а не к следующему:

PlanarImage op = new NullOpImage(decoder.decodeAsRenderedImage(0), null, null, OpImage.OP_IO_BOUND);

Я хотел перебрать каждую страницу текущего документа примерно так:

int numPages = decoder.getNumPages();
for(int j = 0; j < numPages; j++)
{
     PlanarImage op = new NullOpImage(decoder.decodeAsRenderedImage(j), null, null, OpImage.OP_IO_BOUND);
     images.add(op.getAsBufferedImage());
}

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

encoder.encode(images.get(0));

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

params.setExtraImages(imageList.iterator());

который не допускает попадания первой страницы в «ExtraImages» и добавляется с вызовом для кодирования.

Окончательный обновленный код:

public static void main(String[] args) {
        String inputDir = "C:\\tifSources";
        File faxSource = new File(inputDir);
        File file[] = faxSource.listFiles();
        System.out.println("files are " + Arrays.toString(file));
        int numImages = file.length;

        List<BufferedImage> images = new ArrayList<BufferedImage>();

        try
        {
            for (int i = 0; i < numImages; i++)
            {
                SeekableStream ss = new FileSeekableStream(file[i]);
                ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);

                int numPages = decoder.getNumPages();
                for(int j = 0; j < numPages; j++)
                {
                    PlanarImage op = new NullOpImage(decoder.decodeAsRenderedImage(j), null, null, OpImage.OP_IO_BOUND);
                    images.add(op.getAsBufferedImage());
                }
            }

            TIFFEncodeParam params = new TIFFEncodeParam();
            OutputStream out = new FileOutputStream(inputDir + "\\combined.tif"); 
            ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
            List<BufferedImage> imageList = new ArrayList<BufferedImage>();   
            for (int i = 1; i < images.size(); i++)
            {
                imageList.add(images.get(i)); 
            }
            params.setExtraImages(imageList.iterator()); 
            encoder.encode(images.get(0));
            out.close();
        }
        catch (Exception e)
        {
            System.out.println("Exception " + e);
        }
    }
person twilbrand    schedule 12.07.2011
comment
Должен быть способ объединить файлы TIFF без процесса декодирования. - person dragon66; 07.10.2014
comment
Хорошо, после добавления нового метода к существующему TIFFTweaker я смог объединить любое количество многостраничных файлов TIFF в один без фактического декодирования любого из них, и теперь он является частью этой библиотеки Java - github.com/dragon66/icafe/wiki - person dragon66; 17.11.2014
comment
Спасибо, дружище !! - person Dan Ortega; 10.07.2018