equal java java-2d image-resizing scalr

java - equal - Cómo obtener una miniatura de buena calidad



logic equal struts (5)

Estoy tratando de crear una miniatura de alta calidad de esta imagen, con Java y Scalr 3.2

Este es el código fuente relevante, donde THUMB_WIDTH = 77 y THUMB_HEIGHT = 57

BufferedImage srcImg = ImageIO.read(new File(sourceFile)); BufferedImage dstImg = Scalr.resize(srcImg, Scalr.Method.QUALITY, THUMB_WIDTH, THUMB_HEIGHT); ImageIO.write(dstImg, format, new File(destFile));

Si uso format = "png" , aquí está el resultado:

Si uso format = "jpg" , aquí está el resultado:

Con imagemagick identifique , descubrí que el archivo JPEG se guarda con una calidad de 75 que es totalmente insuficiente para crear una miniatura atractiva. El PNG tampoco me queda bien.

Aquí está la salida de identificación del archivo original y las dos miniaturas:

$ identify 42486_1.jpg 42486_s1.jpg 42486_s1.png 42486_1.jpg JPEG 580x435 580x435+0+0 8-bit DirectClass 50.6KB 0.000u 0:00.000 42486_s1.jpg[1] JPEG 77x58 77x58+0+0 8-bit DirectClass 2.22KB 0.000u 0:00.000 42486_s1.png[2] PNG 77x58 77x58+0+0 8-bit DirectClass 12.2KB 0.000u 0:00.000

Preguntas

  • ¿Cómo mejorar la calidad de la miniatura generada?
  • ¿Cómo guardar un JPEG con una calidad superior? Me gustaría probar con mayor calidad y comparar los resultados. No pude encontrar nada en el JavaDoc para ImageIO.write.
  • ¿Por qué le digo a Scalr que mis dimensiones máximas son 77x57 y que emiten una imagen 77x58? Creo que es para mantener la proporción, pero esos son mi ancho máximo y mi altura máxima. El ancho o la altura puede ser menor pero no más.

ACTUALIZACIÓN : con una búsqueda en la web, encontré un artículo sobre cómo ajustar la calidad de compresión de la imagen JPEG . Escribí mi propio método para guardar un BufferedImage configurando la calidad:

/** * Write a JPEG file setting the compression quality. * * @param image * a BufferedImage to be saved * @param destFile * destination file (absolute or relative path) * @param quality * a float between 0 and 1, where 1 means uncompressed. * @throws IOException * in case of problems writing the file */ private void writeJpeg(BufferedImage image, String destFile, float quality) throws IOException { ImageWriter writer = null; FileImageOutputStream output = null; try { writer = ImageIO.getImageWritersByFormatName("jpeg").next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); output = new FileImageOutputStream(new File(destFile)); writer.setOutput(output); IIOImage iioImage = new IIOImage(image, null, null); writer.write(null, iioImage, param); } catch (IOException ex) { throw ex; } finally { if (writer != null) writer.dispose(); if (output != null) output.close(); } }

Aquí están los resultados. PNG:

Calidad JPEG 75:

Calidad JPEG 90 (los gravatars en stackoverflow se guardan como calidad JPEG 90):

y el tamaño del archivo:

thumb90.jpg JPEG 77x58 77x58+0+0 8-bit DirectClass 6.89KB 0.000u 0:00.000

ACTUALIZACIÓN 2 : prueba para comparar Scalr con java-image-scaling .

private void scaleAndSaveImageWithScalr(String sourceFile, String destFile, int width, int height) throws IOException { BufferedImage sourceImage = ImageIO.read(new File(sourceFile)); BufferedImage destImage = Scalr.resize(sourceImage, Scalr.Method.QUALITY, width, height); writeJpeg(destImage, destFile, JPEG_QUALITY); } private void scaleAndSaveImageWithJImage(String sourceFile, String destFile, int width, int height) throws IOException { BufferedImage sourceImage = ImageIO.read(new File(sourceFile)); ResampleOp resampleOp = new ResampleOp(width, height); resampleOp.setFilter(ResampleFilters.getLanczos3Filter()); resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal); BufferedImage destImage = resampleOp.filter(sourceImage, null); writeJpeg(destImage, destFile, JPEG_QUALITY); }

Calidad JPEG 90 generada con Scalr:

Calidad JPEG 90 generada con java-escala de imagen:

No recibí más comentarios, por lo que mi conclusión personal es que la ampliación de la imagen en java ofrece una calidad superior, y por eso es la biblioteca que elijo.


@Stivlo, lamento no haber respondido a esto, nunca recibí ninguna notificación de SO sobre la pregunta.

java-image-scaleing tiene algunos filtros agradables para ayudarte con el ajuste fino si lo necesitas. Dicho esto, en v4.2 de imgscalr agregué el nuevo ULTRA_QUALITY que podría acercarte a lo que deseas.

Espero que eso ayude, pero me doy cuenta de que esto está siendo respondido casi un año después, desafortunadamente. Lo siento por eso.


Esta no es una respuesta completa a su pregunta, pero:

Respecto a la calidad JPEG:

La calidad de compresión se puede configurar utilizando un ImageWriteParam como se describe aquí . Sugieren utilizar un valor int de 0 | 1, pero creo que en realidad debería especificar un valor flotante entre 0.0 y 1.0.

Con respecto a sus problemas de dimensión de escala:

Desde la página de inicio de Scalr :

NOTA: Si se proporciona un ancho y una altura que violan las proporciones de la imagen (por ejemplo, el intento de cambiar el tamaño de una imagen de 800 × 600 a un cuadrado de 150 × 150), la biblioteca observará primero la orientación de la imagen (paisaje / cuadrado o retrato) y luego seleccione la dimensión primaria (el paisaje o el cuadrado usan el ancho, el retrato usa la altura) para recalcular una dimensión secundaria correcta; ignorando lo que fue pasado por el usuario que violaba las proporciones.

En su caso, la dimensión principal será un ancho de 77 y, por lo tanto, se ignorará su límite de altura de 57.


He ejecutado las mismas pruebas y el escalado de imágenes java definitivamente tiene mejores resultados para miniaturas más pequeñas que 250 px. También es compatible con el filtrado agudo, lo que mejora los resultados.

Conservo ambas bibliotecas ya que la sintaxis de Scalr es a menudo más sencilla, con solo una línea.


Si desea un resultado de alta calidad, use la biblioteca [RapidDecoder] [1]. Es simple como sigue:

importar rapid.decoder.BitmapDecoder; ... Bitmap bitmap = BitmapDecoder.from (getResources (), R.drawable.image) .scale (width, height) .useBuiltInDecoder (true) .decode (); No olvide utilizar el decodificador incorporado si desea reducir la escala en menos del 50% y obtener un resultado de HQ.


Tenga en cuenta que si sus imágenes tienen un canal alfa, ambas bibliotecas son problemáticas. Sólo estoy hablando de reducir imágenes, no he probado agrandarlas.

java-image-scaleing puede crear un borde feo alrededor de los bordes transparentes dependiendo de la imagen, y esto se ve muy mal. No encontré manera de evitar esto.

Scalr solo es problemático al usar los modos de calidad (ultra). Sin embargo, se puede usar fácilmente de una manera que funcione bien: la interpolación bicúbica deja los artefactos en imágenes transparentes, por lo que es posible que desee evitarlo. Sin embargo, como es el valor predeterminado para las imágenes de (ultra) calidad, y scaleImageIncrementally () está protegido por subclases para esto, sin embargo, si desea que la calidad (una fracción superior a 2 se vea muy borrosa con el filtrado bilineal).