Pregunta

Una aplicación que tengo lee en imágenes bastante grandes (archivos JPEG), pero sólo necesita trabajar con imágenes más pequeñas, así que les submuestra con algo como

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

Sin embargo, debido a un error en el lector jpeg que no disponga de algunos de metadatos que tengo caer de nuevo a otros métodos, uno está utilizando JAI para leer la imagen y luego cambiar el tamaño (código está por debajo, no tengo que usar la reflexión como algunos entornos de despliegue no tiene JAI disponibles, sé que podría diseñar en torno a esta mejor, pero eso es lo que es).

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) {
// ...
}

Sin embargo algunas de las imágenes son muy grandes una y otra vez que salga de excepciones de memoria, ¿hay alguna forma de conseguir JAI a submuestra de la imagen cuando se lee de la manera que he leído las imágenes empleando un ImageReader?

¿Fue útil?

Solución

Asumo la excepción de memoria insuficiente se produce cuando se intenta hacer la conversión a un BufferedImage?

Si ese es el caso, entonces tal vez teniendo en cuenta que se pega a la RenderedOp que se devuelve por JAI de crear el método y en su lugar utilizar un ParameterBlock y una JAI más crear para producir la imagen escalada?

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);

El código anterior viene totalmente no probado como estándar Me temo, pero debería empezar!

Una vez que tenga que cambiar el tamaño RenderedOp usted debe ser capaz de convertir de manera segura a un BufferedImage si es necesario.

Otros consejos

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();   
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top