Question

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 souhaite redimensionner 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 prendrai en considération les critères suivants pour prendre ma décision (dans cet ordre):

  • Gratuit / Open Source (essentiel)
  • Facile à mettre en œuvre
  • Qualité des résultats
  • Performances
  • Taille de l'exécutable
Était-ce utile?

La solution

Consultez le image Java I / O API pour lire / écrire l'image. Ensuite, utilisez AffineTransform pour redimensionner.

voici un exemple complet utilisant java.awt.Image.

Autres conseils

Je recommanderais vivement de jeter un coup d'oeil sur imgscalr .

Il est commercialisé sous une licence Apache 2, hébergée sur GitHub , déjà déployé dans une poignée d'applications Web. Très simple, mais API documentée de manière cinglante , a un code qui fonctionne pour vous, de manière transparente, à environ 2 bugs d’image majeurs dans le JDK que vous ne remarquerez jamais que si vous commencez soudainement à obtenir du "noir". les images après une opération à grande échelle ou des résultats épouvantables, vous donnent les meilleurs résultats possibles disponibles en Java, sont disponibles via Maven ainsi que sous forme de ZIP et constituent simplement une seule classe.

L'utilisation de base ressemble à ceci:

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

Il s’agit de l’appel le plus simple pour lequel la bibliothèque devinera au mieux la qualité, honorera les proportions de l’image et adaptera le résultat dans un cadre de sélection de 320x320. REMARQUE: le cadre de sélection ne représente que le W / H maximal utilisé, puisque les proportions de votre image sont respectées, l’image résultante conservera tout de même cette impression, par exemple en 320x200.

Si vous souhaitez remplacer le mode automatique et le forcer pour obtenir le résultat le plus esthétique et même appliquer un filtre anti-alias très doux au résultat afin qu'il soit encore meilleur (particulièrement adapté aux vignettes), cet appel ressembler à:

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 très simples aux plus spécialisés. Vous pouvez même transmettre vos propres images BufferedImageOps à appliquer à l'image (et la bibliothèque corrige automatiquement le bogue BufferedImageOp JDK de 6 ans pour vous!)

La bibliothèque réussit mieux à redimensionner des images en Java. Par exemple, conservez toujours l'image dans l'un des types d'images RVB ou ARVB les mieux pris en charge lorsque vous la manipulez. Sous la couverture, le pipeline de traitement d'image Java2D retombe sur un pipeline logiciel inférieur si le type d'image utilisé pour les opérations sur l'image est mal pris en charge.

Si tout cela vous a fait mal à la tête, c’est en quelque sorte ... c’est pourquoi j’ai écrit la bibliothèque et l’approvisionner en source ouverte, afin que les gens puissent redimensionner leurs images et passer à autre chose sans avoir à s’inquiéter. .

L’espoir que cela aide.

Examinez également la bibliothèque java-image-scaling . Il a créé des images de meilleure qualité que ImageIO.

Je sais que la question est très ancienne, mais j’ai eu ma propre solution à l’aide de 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é.

Le meilleur outil pour l'édition d'images est ImageMagick . Il est en open source.

Il existe deux interfaces pour le langage Java:

JMagick qui utilise l'interface JNI avec ImageMagick

et

im4java , qu'est-ce qu'une interface de ligne de commande pour ImageMagick

J'ai essayé imgscalr en comparaison avec 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);

Quelques essais effectués par mes yeux pendant 5 minutes ont eu l’impression que la deuxième chose (Java 1.6 pur) donne de meilleurs résultats.

Cela s'est avéré 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();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top