Pregunta

Necesito cambiar el tamaño de los archivos PNG, JPEG y GIF. ¿Cómo puedo hacer esto usando Java?

¿Fue útil?

Solución

Después de cargar la imagen puedes probar:

BufferedImage createResizedCopy(Image originalImage, 
            int scaledWidth, int scaledHeight, 
            boolean preserveAlpha)
    {
        System.out.println("resizing...");
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
            g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
        g.dispose();
        return scaledBI;
    }

Otros consejos

FWIW Acabo de lanzar (Apache 2, alojado en GitHub) una biblioteca de escala de imagen simple para Java llamada imgscalr (disponible en Central de Maven ).

La biblioteca implementa algunos enfoques diferentes para la ampliación de la imagen (incluido el enfoque incremental de Chris Campbell con algunas mejoras menores) y elegirá el enfoque más óptimo para usted si lo solicita, o le dará el aspecto más rápido o mejor (si pides eso).

El uso es muy simple, solo un montón de métodos estáticos. El caso de uso más simple es:

BufferedImage scaledImage = Scalr.resize(myImage, 200);

Todas las operaciones mantienen las proporciones originales de la imagen, por lo que en este caso le está pidiendo a imgscalr que cambie el tamaño de su imagen dentro de los límites de 200 píxeles de ancho y 200 píxeles de alto y, de forma predeterminada, seleccionará automáticamente el mejor y más rápido enfoque para eso ya que no fue especificado.

Al principio, me doy cuenta de que esto parece ser autopromoción (lo es), pero pasé mi parte del tiempo buscando en Google el mismo tema y seguí presentando diferentes resultados / enfoques / pensamientos / sugerencias y decidí sentarme. y escriba una implementación simple que aborde ese 80-85% de casos de uso en los que tiene una imagen y probablemente desee una miniatura para ella, ya sea lo más rápido posible o lo más atractiva posible (para aquellos que lo han intentado, Notaré que se hace una Graphics.drawImage incluso con interpolación BICUBIC a una imagen lo suficientemente pequeña, todavía parece basura.

Thumbnailator es una biblioteca de redimensionamiento de imágenes de código abierto para Java con una interfaz fluida, distribuida bajo licencia MIT.

Escribí esta biblioteca porque hacer miniaturas de alta calidad en Java puede ser sorprendentemente difícil, y el código resultante podría ser bastante desordenado. Con Thumbnailator, es posible expresar tareas bastante complicadas utilizando una API simple y fluida.

Un ejemplo simple

Para un ejemplo simple, tomar una imagen y cambiar su tamaño a 100 x 100 (conservando la relación de aspecto de la imagen original), y guardarla en un archivo se puede lograr en una sola declaración:

Thumbnails.of("path/to/image")
    .size(100, 100)
    .toFile("path/to/thumbnail");

Un ejemplo avanzado

La realización de tareas complejas de cambio de tamaño se simplifica con la interfaz fluida de Thumbnailator.

Supongamos que queremos hacer lo siguiente:

  1. tomar las imágenes en un directorio y,
  2. cambia su tamaño a 100 x 100, con la relación de aspecto de la imagen original,
  3. guárdelos todos en archivos JPEG con ajustes de calidad de 0.85 ,
  4. donde los nombres de los archivos se toman del original con thumbnail. añadido al principio

Traducido al Thumbnailator, podríamos realizar lo anterior con lo siguiente:

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

Una nota sobre la calidad y la velocidad de la imagen

Esta biblioteca también usa el método de escala bilineal progresiva resaltado en Clusty Rich Clients de Chet Haase y Romain Guy en para generar miniaturas de alta calidad y garantizar un rendimiento de tiempo de ejecución aceptable.

No necesitas una biblioteca para hacer esto. Puedes hacerlo con el propio Java.

Chris Campbell tiene una excelente y detallada reseña de imágenes a escala - vea este artículo .

Chet Haase y Romain Guy también tienen una descripción detallada y muy informativa de la escala de la imagen en su libro, Clientes inmensamente ricos .

Imágenes avanzadas de Java ahora es de código abierto , y proporciona las operaciones que necesita.

Si estás tratando con imágenes grandes o quieres un buen resultado, no es una tarea trivial en Java. Simplemente hacerlo a través de una operación de reescala a través de Graphics2D no creará una miniatura de alta calidad. Puede hacerlo utilizando JAI, pero requiere más trabajo del que podría imaginar para obtener algo que se vea bien y JAI tiene la mala costumbre de soplar su JVM con los errores de OutOfMemory.

Sugiero que uses ImageMagick como un ejecutable externo si puedes salirte con la tuya. Es fácil de usar y hace el trabajo correctamente para que no tenga que hacerlo.

Si tener imagemagick instalado en tu maschine es una opción, recomiendo im4java . Es una capa de abstracción muy delgada en la interfaz de línea de comandos, pero hace su trabajo muy bien.

La API de Java no proporciona una función de escala estándar para las imágenes y reduce la calidad de la imagen.

Debido a esto, intenté usar cvResize desde JavaCV pero parece causar problemas.

Encontré una buena biblioteca para escalar imágenes: simplemente agregue la dependencia para " java-image-scaling " en su pom.xml.

<dependency>
    <groupId>com.mortennobel</groupId>
    <artifactId>java-image-scaling</artifactId>
    <version>0.8.6</version>
</dependency>

En el repositorio de Maven obtendrá la versión reciente para esto.

Ex. En tu programa java

ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);

Puede intentar usar Sistema de procesamiento de imágenes GraphicsMagick con im4java como una interfaz de línea de comandos para Java.

GraphicsMagick ofrece muchas ventajas, pero una para todos:

  • GM se utiliza para procesar miles de millones de archivos en la foto más grande del mundo sitios (por ejemplo, Flickr y Etsy).

Imagen Magick ha sido mencionada. Hay un proyecto de front-end JNI llamado JMagick. No es un proyecto particularmente estable (y se sabe que Image Magick ha cambiado mucho e incluso ha roto la compatibilidad). Dicho esto, hemos tenido una buena experiencia con el uso de JMagick y una versión compatible de Image Magick en un entorno de producción para realizar el escalado a un alto rendimiento y baja tasa de latencia. La velocidad fue sustancialmente mejor que la biblioteca de gráficos Java que probamos anteriormente.

http://www.jmagick.org/index.html

Simplemente use la respuesta de Burkhard pero agregue esta línea después de crear los gráficos:

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

También puede establecer el valor en BICÚBICO, producirá una imagen de mejor calidad pero es una operación más costosa. Hay otras sugerencias de representación que puede establecer, pero he descubierto que la interpolación produce el efecto más notable. Tenga en cuenta que si desea ampliar mucho, lo más probable es que el código Java sea muy lento. Encuentro que las imágenes más grandes comienzan a producir un retraso de alrededor del 300%, incluso con todas las sugerencias de renderizado configuradas para optimizar la velocidad sobre la calidad.

Puede usar Marvin (marco de procesamiento de imágenes Java puro) para este tipo de operación:   http://marvinproject.sourceforge.net

Complemento de escala: http://marvinproject.sourceforge.net/en/plugins/scale.html

Resulta que escribir un escalador performante no es trivial. Lo hice una vez para un proyecto de código abierto: ImageScaler .

En principio, 'java.awt.Image # getScaledInstance (int, int, int)' haría el trabajo también, pero hay un error desagradable en esto: consulte mi enlace para obtener más detalles.

He desarrollado una solución con las clases disponibles gratuitamente (AnimatedGifEncoder, GifDecoder y LWZEncoder) disponibles para manejar la animación GIF.
Puedes descargar el archivo jgifcode y ejecutar la clase GifImageUtil. Enlace: http://www.jgifcode.com

puede utilizar el siguiente producto popular: thumbnailator

Si no quieres importar imgScalr como @Riyad Kalla, la respuesta que he probado también funciona bien. , Puedes hacerlo tomado de respuesta de Peter Walser @Peter Walser sobre otro tema, sin embargo:

 /**
     * utility method to get an icon from the resources of this class
     * @param name the name of the icon
     * @return the icon, or null if the icon wasn't found.
     */
    public Icon getIcon(String name) {
        Icon icon = null;
        URL url = null;
        ImageIcon imgicon = null;
        BufferedImage scaledImage = null;
        try {
            url = getClass().getResource(name);

            icon = new ImageIcon(url);
            if (icon == null) {
                System.out.println("Couldn't find " + url);
            }

            BufferedImage bi = new BufferedImage(
                    icon.getIconWidth(),
                    icon.getIconHeight(),
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = bi.createGraphics();
            // paint the Icon to the BufferedImage.
            icon.paintIcon(null, g, 0,0);
            g.dispose();

            bi = resizeImage(bi,30,30);
            scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
            imgicon = new ImageIcon(scaledImage);

        } catch (Exception e) {
            System.out.println("Couldn't find " + getClass().getName() + "/" + name);
            e.printStackTrace();
        }
        return imgicon;
    }

 public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
        float scaleX = (float) areaWidth / image.getWidth();
        float scaleY = (float) areaHeight / image.getHeight();
        float scale = Math.min(scaleX, scaleY);
        int w = Math.round(image.getWidth() * scale);
        int h = Math.round(image.getHeight() * scale);

        int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        boolean scaleDown = scale < 1;

        if (scaleDown) {
            // multi-pass bilinear div 2
            int currentW = image.getWidth();
            int currentH = image.getHeight();
            BufferedImage resized = image;
            while (currentW > w || currentH > h) {
                currentW = Math.max(w, currentW / 2);
                currentH = Math.max(h, currentH / 2);

                BufferedImage temp = new BufferedImage(currentW, currentH, type);
                Graphics2D g2 = temp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(resized, 0, 0, currentW, currentH, null);
                g2.dispose();
                resized = temp;
            }
            return resized;
        } else {
            Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;

            BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = resized.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(image, 0, 0, w, h, null);
            g2.dispose();
            return resized;
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top