Quelle est la meilleure façon de redimensionner les images en Java?


J'ai une application Web écrite en Java (Spring, Hibernate/JPA, Struts2) où les utilisateurs peuvent télécharger des images et les stocker dans le système de fichiers. Je voudrais mettre à l'échelle ces images afin qu'elles soient d'une taille cohérente pour l'affichage sur le site. Quelles bibliothèques ou fonctions intégrées offriront les meilleurs résultats? Je tiendrai compte des critères suivants pour prendre ma décision (dans cet ordre):

  • Gratuit / Open Source (essentiel)
  • Facile à mettre en Å“uvre
  • Qualité de résultats
  • Performance
  • Taille de l'exécutable
Author: Juha Syrjälä, 2009-05-03

7 answers

Jetez un oeil à l'APIJava Image I/O pour lire/écrire l'image. Ensuite, utilisez AffineTransform pour redimensionner.

Aussi, voici un exemple complet utilisant java.awt.Image.

 4
Author: marcog, 2009-05-03 08:30:40

Je recommanderais vraiment de donner un coup d'oeil à imgscalr.

Il est publié sous une licence Apache 2, hébergé sur GitHub , déjà déployé dans une poignée d'applications web, a une API très simple, mais documentée de manière pédante, a du code qui fonctionne autour de 2 bogues d'image majeurs dans le JDK pour vous de manière transparente que vous ne remarquerez jamais si vous commencez soudainement à obtenir des images "noires" après une opération d'échelle ou des résultats horribles, vous donne le meilleur résultats de recherche possibles disponibles en Java, est disponible via Maven ainsi qu'un ZIP et n'est qu'une seule classe.

L'utilisation de base ressemble à ceci:

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

C'est l'appel le plus simple où la bibliothèque fera une meilleure estimation de la qualité, honorera les proportions de votre image et adaptera le résultat dans une boîte englobante 320x320. NOTEZ que la boîte de délimitation est juste le maximum W / H utilisé, puisque les proportions de votre image sont honorées, l'image résultante honorerait toujours cela, disons 320x200.

Si vous voulez remplacer le mode automatique et le forcer à vous donner le meilleur résultat et même appliquer un filtre anti-alias très doux au résultat afin qu'il soit encore meilleur( particulièrement bon pour les vignettes), cet appel ressemblerait à:

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

Ce ne sont que des exemples, l'API est large et couvre tout, des cas d'utilisation super simples aux cas très spécialisés. Vous pouvez même passer dans votre propre BufferedImageOps à appliquer à l'image (et la bibliothèque corrige automatiquement l'année 6 BufferedImageOp JDK bug pour vous!)

Il y a beaucoup plus à la mise à l'échelle des images en Java avec succès que la bibliothèque fait pour vous, par exemple en gardant toujours l'image dans l'un des types d'image RVB ou ARGB les mieux pris en charge tout en fonctionnant dessus. Sous les couvertures, le pipeline de traitement d'image Java2D revient à un pipeline logiciel inférieur si le type d'image utilisé pour toutes les opérations d'image est mal pris en charge.

Si tout cela ressemblait à beaucoup de maux de tête, c'est en quelque sorte le cas... c'est pourquoi J'ai écrit la bibliothèque et l'ai ouverte, afin que les gens puissent simplement redimensionner leurs images et continuer leur vie sans avoir à s'en soucier.

J'espère que cela aide.

 9
Author: Riyad Kalla, 2011-07-05 16:41:22

Regardez aussi dans la bibliothèquejava-image-scaling . Il a créé des images de meilleure qualité que ImageIO.

 4
Author: Juha Syrjälä, 2010-05-08 09:31:05

Je sais que c'est une très vieille question, mais j'ai obtenu ma propre solution pour cela en utilisant l'API Java standard

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));

Je suis sûr qu'il peut être amélioré et adapté.

 1
Author: Vijay Kumar Kanta, 2017-07-29 10:54:23

Le meilleur outil pour l'édition d'images estImageMagick et il est open source.

Il existe deux interfaces pour le langage Java:

JMagick qui utilise l'interface JNI pour ImageMagick

Et

Im4java qu'est ce qu'une interface de ligne de commande pour ImageMagick

 0
Author: kajo, 2011-04-11 14:18:41

J'ai essayé imgscalr en comparant à Java 1.6 standard et je ne peux pas dire que c'est mieux.

Ce que j'ai essayé, c'est

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

Et

  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);

Certains tests de 5 minutes par mon œil ont eu l'impression que la deuxième chose (Java pur 1.6) produit de meilleurs résultats.

 0
Author: Mladen Adamovic, 2013-04-02 18:08:45

A trouvé cela plus rapide:

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();
    }
}
 -1
Author: eric, 2015-07-18 07:33:40