¿Cómo puedo cambiar el tamaño de una imagen usando Java?

1. Introducción

En este tutorial, aprenderemos cómo cambiar el tamaño (escalar) de una imagen usando Java. Exploraremos tanto las bibliotecas centrales de Java como las de terceros de código abierto que ofrecen la función de cambio de tamaño de la imagen.

Es importante mencionar que podemos escalar imágenes tanto hacia arriba como hacia abajo. En los ejemplos de código de este tutorial, cambiaremos el tamaño de las imágenes a tamaños más pequeños ya que, en la práctica, ese es el escenario más común.

2. Cambiar el tamaño de una imagen con Core Java

Core Java ofrece las siguientes opciones para cambiar el tamaño de las imágenes:

  • Cambiar el tamaño usando java.awt.Graphics2D
  • Cambiar el tamaño usando Image # getScaledInstance

2.1. java.awt.Graphics2D

Graphics2D es la clase fundamental para renderizar formas, texto e imágenes bidimensionales en la plataforma Java.

Comencemos cambiando el tamaño de una imagen usando Graphics2D :

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = resizedImage.createGraphics(); graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); graphics2D.dispose(); return resizedImage; }

Veamos cómo se ve la imagen antes y después de cambiar el tamaño:

El parámetro BufferedImage.TYPE_INT_RGB indica el modelo de color de la imagen. Una lista completa de valores disponibles está disponible en la documentación oficial de Java BufferedImage .

Graphics2D acepta parámetros adicionales llamados RenderingHints . Usamos RenderingHints para influir en diferentes aspectos del procesamiento de imágenes y, lo más importante, en la calidad de la imagen y el tiempo de procesamiento.

Podemos agregar un RenderingHint usando el método setRenderingHint :

graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

Puede encontrar una lista completa de RenderingHints en este tutorial de Oracle.

2.2. Image.getScaledInstance ()

Este enfoque que usa Image es muy simple y produce imágenes de calidad satisfactoria:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_DEFAULT); BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); outputImage.getGraphics().drawImage(resultingImage, 0, 0, null); return outputImage; }

Veamos qué pasa con una imagen de algo delicioso:

También podemos dirigir el mecanismo de escalado para que utilice uno de los enfoques disponibles proporcionando al método getScaledInstance () una marca que indique el tipo de algoritmo que se utilizará para nuestras necesidades de remuestreo de imágenes:

Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);

Todos los indicadores disponibles se describen en la documentación oficial de Java Image.

3. Imgscalr

Imgscalr usa Graphic2D en segundo plano. Tiene una API simple con algunos métodos diferentes para cambiar el tamaño de la imagen.

Imgscalr nos proporciona el resultado más atractivo, el resultado más rápido o un resultado equilibrado según la opción de escala que elijamos. También están disponibles otras funciones de manipulación de imágenes, como las de recorte y rotación. Demostremos cómo funciona en un ejemplo simple.

Agregaremos la siguiente dependencia de Maven:

 org.imgscalr imgscalr-lib 4.2 

Consulte Maven Central para obtener la última versión.

La forma más sencilla de utilizar Imgscalr es:

BufferedImage simpleResizeImage(BufferedImage originalImage, int targetWidth) throws Exception { return Scalr.resize(originalImage, targetWidth); }

Donde originalImage es la BufferedImage que se cambiará de tamaño y targetWidth es el ancho de una imagen de resultado. Este enfoque mantendrá las proporciones originales de la imagen y utilizará los parámetros predeterminados: Method.AUTOMATIC y Mode.AUTOMATIC .

¿Cómo le va con una foto de fruta deliciosa? Veamos:

La biblioteca también permite múltiples opciones de configuración y maneja la transparencia de la imagen en segundo plano.

Los parámetros más importantes son:

  • modo : se utiliza para definir los modos de cambio de tamaño que utilizará el algoritmo. Por ejemplo, podemos definir si nos gustaría mantener las proporciones de la imagen (las opciones son AUTOMATIC, FIT_EXACT, FIT_TO_HEIGHT y FIT_TO_WIDTH )
  • Método : instruye al proceso de cambio de tamaño para que se centre en la velocidad, la calidad o ambas. Los valores posibles son AUTOMATIC, BALANCED, QUALITY, SPEED, ULTRA_QUALITY

También es posible definir propiedades de cambio de tamaño adicionales que nos proporcionarán registro o dirigen a la biblioteca para que haga algunas modificaciones de color en la imagen (hacerla más clara, más oscura, en escala de grises, etc.).

Usemos la parametrización completa del método resize () :

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws Exception { return Scalr.resize(originalImage, Scalr.Method.AUTOMATIC, Scalr.Mode.AUTOMATIC, targetWidth, targetHeight, Scalr.OP_ANTIALIAS); }

Y ahora obtenemos:

Imgscalr funciona con todos los archivos compatibles con Java Image IO: JPG, BMP, JPEG, WBMP, PNG y GIF.

4. Thumbnailator

Thumbnailator es una biblioteca de cambio de tamaño de imágenes de código abierto para Java que utiliza escalado bilineal progresivo. Soporta JPG, BMP, JPEG, WBMP, PNG y GIF.

We'll include it in our project by adding the following Maven dependency to our pom.xml:

 net.coobird thumbnailator 0.4.11 

Available dependency versions can be found on Maven Central.

It has a very simple API and allows us to set output quality in percentage:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Thumbnails.of(originalImage) .size(targetWidth, targetHeight) .outputFormat("JPEG") .outputQuality(1) .toOutputStream(outputStream); byte[] data = outputStream.toByteArray(); ByteArrayInputStream inputStream = new ByteArrayInputStream(data); return ImageIO.read(inputStream); }

Let's see how this smiling photograph looks before and after resizing:

It also has an option for batch processing:

Thumbnails.of(new File("path/to/directory").listFiles()) .size(300, 300) .outputFormat("JPEG") .outputQuality(0.80) .toFiles(Rename.PREFIX_DOT_THUMBNAIL);

As Imgscalr, Thumblinator works with all files supported by Java Image IO – JPG, BMP, JPEG, WBMP, PNG, and GIF.

5. Marvin

Marvin is a handy tool for image manipulation and it offers a lot of useful basic (crop, rotate, skew, flip, scale) and advanced (blur, emboss, texturing) features.

As before, we'll add Maven dependencies needed for Marvin resizing:

 com.github.downgoon marvin 1.5.5 pom   com.github.downgoon MarvinPlugins 1.5.5 

Available Marvin dependency versions can be found on Maven Central, along with the Marvin Plugins versions.

The downside of Marvin is that it doesn't offer an additional scaling configuration. Also, the scale method requires an image and image clone which is a bit cumbersome:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) { MarvinImage image = new MarvinImage(originalImage); Scale scale = new Scale(); scale.load(); scale.setAttribute("newWidth", targetWidth); scale.setAttribute("newHeight", targetHeight); scale.process(image.clone(), image, null, null, false); return image.getBufferedImageNoAlpha(); }

Let's now resize an image of a flower and see how it goes:

6. Best Practice

Image processing is an expensive operation in terms of resources, so picking the highest quality is not necessarily the best option when we don't really need it.

Let's see the performance of all of the approaches. We took one 1920×1920 px image, and scaled it to 200×200 px. The resulting observed times are as follows:

  • java.awt.Graphics2D – 34ms
  • Image.getScaledInstance() – 235ms
  • Imgscalr – 143ms
  • Thumbnailator – 547ms
  • Marvin – 361ms

Además, al definir el ancho y alto de la imagen de destino, debemos prestar atención a la relación de aspecto de la imagen. De esta forma, la imagen conservará sus proporciones originales y no se estirará.

7. Conclusión

Este artículo ilustra algunas formas de cambiar el tamaño de una imagen en Java. También aprendimos cuántos factores diferentes pueden influir en el proceso de cambio de tamaño.

Las muestras de código completas están disponibles en GitHub.