2012-06-06 17 views
5

O, como alternativa, ¿existe una mejor biblioteca para manejar la compresión?¿Puedo cambiar el algoritmo de compresión utilizado por el ImageWriter de Java al crear un archivo JPEG?

Déjeme prefacio con lo que ya entiendo: (1) JPEG es con pérdida: no se verá igual que el archivo de entrada. (2) Puedo ajustar la configuración de calidad de compresión a algo entre 0.0 y 1.0, como he hecho en el siguiente código.

Estoy tomando una Imagen Buffered y convirtiéndola a JPEG y estoy notando que el método .write() de Java ImageWriter produce resultados por debajo de las imágenes JPEG (en comparación con Photoshop "Guardar para Web", como ejemplo).

Mi código es un poco como esto ahora:

// img is a BufferedImage, here 
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); 
ImageWriteParam iwp = writer.getDefaultWriteParam(); 
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
iwp.setCompressionQuality(.75f); 

IIOImage image = new IIOImage(img, null, null); 
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); 
writer.setOutput(ImageIO.createImageOutputStream(byteArrayOut)); 
writer.write(null, image, iwp); 
writer.dispose(); 

Jugando con el ajuste de calidad de compresión produce resultados de calidad diferentes, pero incluso en el ajuste "1.0", que no se ven tan bien como lo que puede obtener con otras herramientas al crear un JPEG.

Como soy un nuevo usuario y no puedo publicar imágenes todavía ... here's a webpage that demos the differences. Espero poder conseguirlos aquí de forma permanente en algún momento para futuros usuarios que puedan tener una pregunta similar.

Obviamente, esta imagen particular no es la mejor opción para la compresión JPEG (la PNG es mucho más pequeña y sin pérdidas), pero permite que los artefactos de compresión se vean más fácilmente. Las imágenes reales serán principalmente de naturaleza fotográfica. Por lo menos, esto es más para cuestionar el algoritmo y la calidad de la compresión JPEG de Java frente a otros que producen imágenes que se ven más cercanas al original con menos bytes.

+0

Acabo de obtener el enlace de muestra terminado, para cualquier persona que haya visto esto de inmediato. – timehat

+0

Ideal sería incorporar una mejor compresión JPEG en Java estándar; tomar una implementación de sala limpia de código abierto (GNU/Linux libjpeg?/especialmente GNU Classpath) y portarlo a Java. Quizás con algún apoyo de un JUG, podría ser factible. –

Respuesta

5

".write de Java ImageWriter() método produce resultados por debajo del par de imágenes JPEG (en comparación con Photoshop "Guardar para Web", como ejemplo)."

Hay más de una razón por la que esto sucede y es injusto comparar la calidad de imagen producida por la imagen de Java con un software de imagen profesional como photoshop.

De todos modos, veamos cuál es la causa más probable de los artefactos en su imagen: generalmente, para que un software guarde imágenes como JPEG, le permitirá especificar un parámetro como compresión o calidad, uno es el inverso de el otro. Este parámetro se usa para escalar las tablas de cuantificación utilizadas en el proceso de cuantificación, que es el factor que más contribuye a la pérdida de JPEG. Diferentes codificadores pueden usar diferentes tablas de cuantificación que parcialmente representan la diferencia de calidad de imagen.

Pero podría haber otros factores que afectan la compresión y la calidad de imagen entre los que se encuentra el submuestreo de crominancia (o reducción de muestreo) que ocurre realmente antes del proceso de cuantificación. El submuestreo de croma es el proceso mediante el cual se toma una muestra de la información de color de la imagen a una resolución inferior a la original. Para una mejor explicación, lea this artículo.

Calvin Hass proporciona una excelente herramienta de amortiguación JPEG llamada JPEGSnoop que se puede descargar desde http://www.impulseadventure.com. El uso de esta herramienta la imagen ps75.jpg que ya ha proporcionado en adelante, me encontré con el siguiente resultado que pertenece a submuestreo de croma:

Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) 
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x01 (Chrom: Cb) 
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x01 (Chrom: Cr) 

lo que significa que no hay submuestreo realizado sobre los componentes de color. Por otro lado, la parte de submuestreo de 100.jpg y 75.jpg son los mismos:

Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) 
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) 
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) 

que significa subsamping se ha hecho en ambas direcciones horizontal y vertical para componentes de color tomando el promedio de dos píxeles consecutivos.

El efecto del submuestreo de croma en la calidad de la imagen será más notable cuando las imágenes originales estén compuestas por tiras y/o cuadrados como en su caso y ya habrá notado que los artefactos son más fáciles de ver aquí.

Por lo tanto, IMO, para este caso especial, el problema es más del submuestreado de crominancia que del ajuste del factor de calidad. Tal vez no he profundizado lo suficiente, pero no pude encontrar una manera de establecer los factores de muestreo para la imagen o el ImageWriter detrás de ella (que es muy probablemente com.sun.imageio.plugins.jpeg.JPEGImageWriter) aunque parece posible establecer cuantificación y tablas de Huffman para ser utilizado por ImageWriter.

Por lo tanto, es poco probable que pueda cambiar el algoritmo de compresión utilizado por el ImageWriter de Java a menos que escriba su propio complemento ImageWriter para imageio o como uno independiente. Pero ambos no son triviales dada la complejidad del algoritmo de compresión JEPG. Hay una implementación Java JpegEncoder relativamente fácil de seguir escrita por James R. Weeks que por defecto no hace submuestreo de croma. Solía ​​ser gratis, pero puedes encontrar las versiones originales buscando en la web.

Otra cosa interesante es: a partir de la salida de JPEGSnoop, el factor de calidad real para la imagen 75% JPEG guardada por photoshop se muestra realmente como alrededor del 92%. Y el siguiente texto citado de la página web de Calvin Hass contestará a la pregunta de por qué photoshop utilizando submuestreo en su caso:

Como acotación al margen, tenga en cuenta que Photoshop CS2 usa diferentes niveles de submuestreo cromático en función de los ajustes de Calidad Guardar JPEG:

Photoshop Save As Quality 0-6 - 2x2 Chroma Subsampling 
Photoshop Save As Quality 7-12 - 1x1 No Chroma Subsampling 
Photoshop Save For Web Quality 0-50 - 2x2 Chroma Subsampling 
Photoshop Save For Web Quality 51-100 - 1x1 No Chroma Subsampling 

Echa un vistazo a this Biblioteca de imágenes Java que también puede escribir imágenes JPEG.

+0

Gracias por la explicación detallada. Tiene sentido que el submuestreo de croma sea aún más importante que la configuración de calidad en esta instancia. Sabía que comparar el sistema integrado con Photoshop no era exactamente justo, pero pensé que sería un buen estándar para comparar. Gracias de nuevo por los indicadores. – timehat

Cuestiones relacionadas