Подвыборка изображения при чтении с использованием JAI

StackOverflow https://stackoverflow.com/questions/1657978

  •  11-09-2019
  •  | 
  •  

Вопрос

Приложение, которое у меня есть, читает довольно большие изображения (в формате JPEG), но ему нужно работать только с изображениями меньшего размера, поэтому я субдискретизирую их с помощью чего-то вроде

ImageReadParam param = reader.getDefaultReadParam();
param.setSourceSubsampling(4, 4, 0, 0);
img = reader.read(0);

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

try {
Class<?> c = ImageUtil.class.getClassLoader().loadClass("javax.media.jai.JAI");

if (c != null) { 
    URL url = new URL("file://" + file.getAbsolutePath());
    Method m = c.getMethod("create", String.class, Object.class);
    Object pi = m.invoke(null, "url", url);
    img = (BufferedImage) pi.getClass().getMethod("getAsBufferedImage").invoke(pi);
}
} catch (Throwable tt) {
// ...
}

Однако некоторые изображения действительно большие, и время от времени у меня возникают исключения из памяти. Могу ли я в любом случае заставить JAI выполнять субдискретизацию изображения, когда оно читается так, как я читаю изображения с помощью ImageReader?

Это было полезно?

Решение

Я предполагаю, что исключение нехватки памяти выдается, когда вы пытаетесь выполнить преобразование в BufferedImage?

Если это так, то, возможно, стоит рассмотреть возможность использования RenderedOp, возвращаемого методом создания JAI, и вместо этого использовать параметрBlock и дальнейшее создание JAI для создания масштабированного изображения?

ParameterBlock paramBlock = new ParameterBlock();
paramBlock.addSource(((RenderedOp) pi).createInstance()); // Updated this
paramBlock.add(0.5f); // x Scale (Change these two Scale values!)
paramBlock.add(0.5f); // y Scale
paramBlock.add(0.0f); // x Translate
paramBlock.add(0.0f); // y Translate
paramBlock.add(new InterpolationBilinear()); // I think this Interpolation should work...)
RenderedOp resized = JAI.create("scale", paramBlock, null);

Боюсь, приведенный выше код в стандартной комплектации полностью непроверен, но с него стоит начать!

Получив измененный размер RenderedOp, вы сможете безопасно преобразовать его в BufferedImage, если понадобится.

Другие советы

RenderedOp rop = JAI.create("fileload", file.getAbsolutePath());

ParameterBlock pb = new ParameterBlock();
pb.addSource(rop);
pb.add(0.5f);
pb.add(0.5f);
rop = JAI.create("scale", pb);

// For better looking results, but slower:
// rop = JAI.create("SubsampleAverage", pb);

BufferedImage bufImg = rop.getAsBufferedImage();   
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top