Pregunta

Tengo una aplicación web escrita en Java (Spring, Hibernate / JPA, Struts2) donde los usuarios pueden cargar imágenes y almacenarlas en el sistema de archivos. Me gustaría escalar esas imágenes para que tengan un tamaño consistente para mostrar en el sitio. ¿Qué bibliotecas o funciones incorporadas ofrecerán los mejores resultados? Consideraré los siguientes criterios al tomar mi decisión (en este orden):

  • Código libre / abierto (esencial)
  • Fácil de implementar
  • Calidad de los resultados
  • Rendimiento
  • Tamaño del ejecutable
¿Fue útil?

Solución

Eche un vistazo a la Imagen de Java I / O API para leer / escribir la imagen. Luego use AffineTransform para cambiar el tamaño.

También, he aquí un ejemplo completo usando java.awt.Image.

Otros consejos

Realmente recomendaría echar un vistazo a imgscalr .

Se publica bajo una licencia de Apache 2, alojada en GitHub , implementada en un puñado de aplicaciones web, ya tiene un muy simple, pero API documentada de forma pediátrica , tiene un código que funciona alrededor de 2 errores de imagen principales en el JDK para usted de forma transparente que solo notará si de repente comienza a aparecer " negro " imágenes después de una operación de escala o resultados de aspecto horrible, le ofrece los mejores resultados de aspecto disponibles en Java, está disponible a través de Maven, así como un ZIP y es solo una clase.

El uso básico se ve así:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);

Esta es la llamada más simple donde la biblioteca hará una mejor estimación de la calidad, respetará las proporciones de su imagen y ajustará el resultado dentro de un cuadro delimitador de 320x320. NOTA: el cuadro delimitador es solo la W / H máxima utilizada, ya que se respetan las proporciones de su imagen, la imagen resultante aún respetaría eso, digamos 320x200.

Si desea anular el modo automático y forzarlo a darle el mejor resultado e incluso aplicar un filtro anti-alias muy suave al resultado para que se vea aún mejor (especialmente bueno para las miniaturas), esa llamada sería parece que:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

Todos estos son solo ejemplos, la API es amplia y cubre todo, desde casos de uso súper simples hasta muy especializados. Incluso puede pasar su propio BufferedImageOps para que se aplique a la imagen (¡y la biblioteca corrige automáticamente el error JDK BufferedImageOp de 6 años por usted!)

Hay mucho más para escalar imágenes en Java con éxito que la biblioteca hace por usted, por ejemplo, mantener siempre la imagen en uno de los tipos de imágenes RGB o ARGB mejor compatibles mientras se opera en ella. Debajo de las cubiertas, la tubería de procesamiento de imágenes Java2D vuelve a una tubería de software inferior si el tipo de imagen utilizado para cualquier operación de imagen es poco compatible.

Si todo eso sonaba como un gran dolor de cabeza, es como ... es por eso que escribí la biblioteca y la encontré abierta, para que la gente pudiera cambiar el tamaño de sus imágenes y seguir con sus vidas sin tener que preocuparse por eso .

Espero que eso ayude.

Consulte también la java-image-scaling . Creó imágenes de mejor calidad que ImageIO.

Sé que esta es una pregunta muy antigua, pero obtuve mi propia solución para esto utilizando la API estándar de Java

import java.awt.*;
import java.awt.event.*;
import javax.imageio.*
import java.awt.image.*;

BufferedImage im, bi, bi2;
Graphics2D gfx;
int imWidth, imHeight, dstWidth, dstHeight;
int DESIRED_WIDTH = 500, DESIRED_HEIGHT = 500;

im = ImageIO.read(new File(filePath));
imWidth = im.getWidth(null);
imHeight = im.getHeight(null);

dstWidth = DESIRED_WIDTH;
dstHeight = (dstWidth * imHeight) / imWidth;

bi = new BufferedImage(dstWidth, dstHeight, im.getType());

gfx = bi.createGraphics();
gfx.drawImage(im, 0, 0, dstWidth, dstHeight, 0, 0, imWidth, imHeight, null);

bi2 = new BufferedImage(DESIRED_WIDTH, DESIRED_HEIGHT, im.getType());
gfx = bi2.createGraphics();

gfx.drawImage(bi, 0, 0, DESIRED_WIDTH, DESIRED_HEIGHT, null);

ImageIO.write(bi2, "jpg", new File(filePath));

Estoy seguro de que se puede mejorar y adaptar.

La mejor herramienta para editar imágenes es ImageMagick y es de código abierto.

Hay dos interfaces para el lenguaje Java:

JMagick que usa la interfaz JNI para ImageMagick

y

im4java es una interfaz de línea de comandos para ImageMagick

Intenté imgscalr en comparación con Java 1.6 estándar y no puedo decir que sea mejor.

Lo que he intentado es

BufferedImage bufferedScaled = Scalr.resize(sourceImage, Method.QUALITY, 8000, height);

y

  Image scaled = sourceImage.getScaledInstance(-1, height, Image.SCALE_SMOOTH);
  BufferedImage bufferedScaled = new BufferedImage(scaled.getWidth(null),  scaled.getHeight(null), BufferedImage.TYPE_INT_RGB);
  bufferedScaled.getGraphics().drawImage(scaled, 0, 0, null);

algunas pruebas de 5 minutos por mi ojo dieron la impresión de que la segunda cosa (Java 1.6 puro) produce mejores resultados.

Encontré que esto es más rápido:

public static BufferedImage getScaledInstance(final BufferedImage img, final int targetWidth, final int targetHeight,
                                              final Object hint) {
    final int type = BufferedImage.TYPE_INT_RGB;
    int drawHeight = targetHeight;
    int drawWidth = targetWidth;
    final int imageWidth = img.getWidth();
    final int imageHeight = img.getHeight();
    if ((imageWidth <= targetWidth) && (imageHeight <= targetHeight)) {
        logger.info("Image " + imageWidth + "/" + imageHeight + " within desired scale");
        return img;
    }
    final double sar = ((double) imageWidth) / ((double) imageHeight);
    if (sar != 0) {
        final double tar = ((double) targetWidth) / ((double) targetHeight);
        if ((Math.abs(tar - sar) > .001) && (tar != 0)) {
            final boolean isSoureWider = sar > (targetWidth / targetHeight);
            if (isSoureWider) {
                drawHeight = (int) (targetWidth / sar);
            }
            else {
                drawWidth = (int) (targetHeight * sar);
            }
        }
    }
    logger.info("Scaling image from " + imageWidth + "/" + imageHeight + " to " + drawWidth + "/" + drawHeight);
    final BufferedImage result = new BufferedImage(drawWidth, drawHeight, type);
    try {
        final Graphics2D g2 = result.createGraphics();
        try {
            if (hint != null) {
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            }
            g2.drawImage(img, 0, 0, drawWidth, drawHeight, null);
        }
        finally {
            g2.dispose();
        }
        return result;
    }
    finally {
        result.flush();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top