Ошибка при попытке прочитать регион из очень большого файла изображения в java

Мне нужно прочитать очень большой файл изображения (56000 пикселей X 49000 пикселей). Мне нужно читать его небольшими прямоугольными кусками, поэтому я пытаюсь следовать этому примеру: Считать область из очень большого файла изображения на Java

Однако я получаю эту ошибку: java.lang.IllegalArgumentException: width * height> Integer.MAX_VALUE!

Мой фрагмент кода ниже (взят более или менее точно из ссылки выше):

ImageInputStream stream = null;
    try {
        stream = ImageIO.createImageInputStream(new File(this.inFile)); // File or input stream
    } catch (Exception ex) {
        Logger.getLogger(CreateTrainingSetFromImage.class.getName()).log(Level.SEVERE, null, ex);
    }
    Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);

    ImageReader r = readers.next();
    System.out.println("Using reader: " + r);
    r.setInput(stream);
    try {
        System.out.println("Height = " + r.getHeight(0));
        System.out.println("Width = " + r.getWidth(0));
    } catch (IOException ex) {
        Logger.getLogger(CreateTrainingSetFromImage.class.getName()).log(Level.SEVERE, null, ex);
    }

ImageReadParam param = r.getDefaultReadParam();
Rectangle sourceRegion = new Rectangle(0, 0, 200, 200);
param.setSourceRegion(sourceRegion); // Set region

        BufferedImage image = null;
        try {
            image = r.read(0, param); // Will read only the region specified
            System.out.println("Read file " + this.inFile);
            System.out.println("Width = " + image.getWidth());
            System.out.println("Height = " + image.getHeight());
        } catch (Exception ex) {
            Logger.getLogger(CreateTrainingSetFromImage.class.getName()).log(Level.SEVERE, null, ex);
        }

Насколько я понимаю, указание Rectangle sourceRegion для параметра приведет к тому, что ImageReader будет читать только этот небольшой фрагмент изображения, поэтому я не понимаю, что вызывает ошибку. Любая помощь приветствуется. Если это поможет, я использую плагины TwelveMonkeys ImageIO.

Вот результат:

Using reader: com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader@5437dd04
Height = 49429
Width = 56281
Apr 23, 2017 11:57:17 AM createtrainingsetfromimage.CreateTrainingSetFromImage    test
SEVERE: null
java.lang.IllegalArgumentException: width*height > Integer.MAX_VALUE!
at javax.imageio.ImageReader.getDestination(ImageReader.java:2840)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1066)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)
at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:382)
at createtrainingsetfromimage.CreateTrainingSetFromImage.test(CreateTrainingSetFromImage.java:102)
at createtrainingsetfromimage.CreateTrainingSetFromImage.createTrainingSet(CreateTrainingSetFromImage.java:168)
at createtrainingsetfromimage.CreateTrainingSetFromImage.main(CreateTrainingSetFromImage.java:46)

person Samarth    schedule 23.04.2017    source источник
comment
где возникает исключение?   -  person Albert    schedule 23.04.2017
comment
Я не уверен, что является источником ошибки, но предполагаю, что вам нужно использовать double.   -  person c0der    schedule 23.04.2017
comment
Предоставьте, пожалуйста, трассировку стека и укажите, в какой строке происходит ошибка. Я собираюсь предположить, что ImageIO.createImageInputStream выполняет расчет с шириной и высотой, превышающей максимальный целочисленный размер.   -  person Christopher Schneider    schedule 23.04.2017
comment
Ошибка возникает при image = r.read (0, param); Я отредактировал сообщение, чтобы включить вывод.   -  person Samarth    schedule 23.04.2017
comment
@Samarth Можете ли вы разместить ссылку на такое огромное изображение в тестовых целях?   -  person Harald K    schedule 24.04.2017
comment
@haraldK Вот ссылка на jpeg, который я использую в тестовых целях: filedropper.com/floydclass   -  person Samarth    schedule 24.04.2017
comment
@haraldK Хм ... Я просто попробовал еще раз (и в Firefox, и в Chrome) и смог его скачать. Позвольте мне попробовать найти другой файловый хостинг, чтобы поделиться им.   -  person Samarth    schedule 24.04.2017
comment
@Samarth Неважно, наверное, просто проблема с рабочей сетью. Теперь отлично работает из другого места.   -  person Harald K    schedule 24.04.2017


Ответы (1)


Существует известная ошибка / ограничение в методе getDestination базового класса ImageReader (суперкласс JPEGImageReader и всех других реализаций считывателя ImageIO), который вычисляет ширину * высоту входного изображения, а не регион, который вы на самом деле пытаетесь прочитать ... Это мешает вам читать даже небольшие части таких изображений.

Код выглядит так, а параметры width и height - это размеры ввода:

if ((long) width * height > Integer.MAX_VALUE) {
    throw new IllegalArgumentException("width*height > Integer.MAX_VALUE!");
}

В большинстве моих (библиотеки TwelveMonkeys ImageIO) ImageReaders я обхожу это ограничение, используя другую реализацию метода getDestination. Но для JPEGImageReader я делегирую фактическое декодирование com.sun....JPEGImageReader, который использует исходный метод и вызывает это исключение.

Можно было бы обойти проблему, используя метод readRaster вместо read (поскольку он не использует метод getDestination), но это требует дополнительной работы, и у меня еще не было возможности проверить это.

person Harald K    schedule 24.04.2017
comment
Я использую jpeg для тестирования (я разместил ссылку в ответ на ваши комментарии выше). Мне действительно нужно использовать его с файлами TIFF. Когда я попробовал тот же код с tiff, я получил следующую ошибку: Exception in thread "main" java.util.NoSuchElementException в строке ImageReader r = readers.next();. Перед этим я проверяю, зарегистрирован ли TwelveMonkeys TIFFImageReader как читатель tiff, так что проблема не в этом. Означает ли это, что мое изображение в формате TIFF каким-то образом не соответствует требованиям? - person Samarth; 24.04.2017
comment
Если вы на 100% уверены, что TIFFImageReader зарегистрирован, это означает, что ваш файл не является файлом TIFF (логика обнаружения довольно проста, проверяются только первые 4 байта). Может, это BigTIFF? - person Harald K; 24.04.2017
comment
Я думаю, что это могло быть сгенерировано из arcGIS, так что это может быть geotiff. - person Samarth; 24.04.2017
comment
Вот ссылка на tiff-файл, если вы хотите попробовать: filedropper.com/floydclass_1 - person Samarth; 25.04.2017
comment
@Samarth Как я и думал, это файл BigTIFF. TwelveMonkeys TIFFImageReader в настоящее время не поддерживает BigTIFF. Хотя, возможно, в будущем. :-) - person Harald K; 25.04.2017
comment
Спасибо за вашу помощь с этим. Сам бы я в этом не разобрался. - person Samarth; 25.04.2017
comment
@Samarth FYI: я планирую добавить поддержку BigTIFF в следующей версии библиотека. - person Harald K; 27.04.2017