web-dev-qa-db-fra.com

Comment créer une image miniature à partir d'un JPEG en Java?

Quelqu'un peut-il aider avec du code pour créer une vignette pour un JPEG en Java.

Je suis nouveau dans ce domaine, donc une explication étape par étape serait appréciée.

37
mmmmr
Image img = ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, BufferedImage.SCALE_SMOOTH);

Cela créera une miniature de 100 x 100 pixels en tant qu'objet Image. Si vous voulez l'écrire sur le disque, convertissez simplement le code en ceci:

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, Image.SCALE_SMOOTH),0,0,null);
ImageIO.write(img, "jpg", new File("test_thumb.jpg"));

De plus, si vous êtes préoccupé par les problèmes de vitesse (la méthode décrite ci-dessus est plutôt lente si vous souhaitez mettre à l'échelle de nombreuses images), utilisez ces méthodes et la déclaration suivante:

private BufferedImage scale(BufferedImage source,double ratio) {
  int w = (int) (source.getWidth() * ratio);
  int h = (int) (source.getHeight() * ratio);
  BufferedImage bi = getCompatibleImage(w, h);
  Graphics2D g2d = bi.createGraphics();
  double xScale = (double) w / source.getWidth();
  double yScale = (double) h / source.getHeight();
  AffineTransform at = AffineTransform.getScaleInstance(xScale,yScale);
  g2d.drawRenderedImage(source, at);
  g2d.dispose();
  return bi;
}

private BufferedImage getCompatibleImage(int w, int h) {
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice Gd = ge.getDefaultScreenDevice();
  GraphicsConfiguration gc = Gd.getDefaultConfiguration();
  BufferedImage image = gc.createCompatibleImage(w, h);
  return image;
}

Et puis appelez:

BufferedImage scaled = scale(img,0.5);

où 0,5 est le rapport d'échelle et img est une image tamponnée contenant l'image de taille normale.

69
Savvas Dalkitsis

Comme vous l'avez peut-être découvert, "facile" et "bon résultat" sont deux choses très différentes. J'ai encapsulé ces deux exigences dans une très simple bibliothèque de mise à l'échelle d'image Java (licence Apache 2) qui fait tout ce qu'il faut pour vous.

Un exemple de code pour créer une miniature ressemble à ceci:

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

Vos proportions d'image sont respectées, la bibliothèque fait une meilleure estimation de la méthode à utiliser en fonction de la quantité de changement dans l'image due à la mise à l'échelle (PLUS RAPIDE, ÉQUILIBRÉE ou QUALITÉ) et les meilleurs types d'images Java2D pris en charge sont toujours utilisés pour le faire la mise à l'échelle pour éviter le problème de résultats "noirs" ou d'une sortie vraiment terrible (par exemple des images GIF trop tramées).

De plus, si vous souhaitez le forcer à afficher la miniature la plus belle possible en Java, l'appel d'API ressemblerait à ceci:

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

Non seulement la bibliothèque utilisera la mise à l'échelle incrémentielle recommandée par Java2D pour vous donner le meilleur résultat, mais elle appliquera également un effet d'anticrénelage facultatif à la vignette (ConvolveOp avec un noyau très affiné) pour adoucir légèrement le les transitions entre les valeurs de pixels rendent donc la vignette plus uniforme et non nette ou coquelicot comme vous l'avez vu en passant d'images très grandes à très petites.

Vous pouvez lire tous les commentaires de la bibliothèque (le code lui-même est largement documenté) pour voir tous les différents bogues JDK qui sont contournés ou les optimisations qui sont faites pour améliorer les performances ou l'utilisation de la mémoire. J'ai passé BEAUCOUP de temps à régler cette implémentation et j'ai reçu beaucoup de bons commentaires de gens qui l'ont déployée dans des applications Web et d'autres projets Java Java.

31
Riyad Kalla

C'est un moyen simple de créer une vignette 100 X 100 sans étirement ni biais dans l'image.

private  void saveScaledImage(String filePath,String outputFile){
    try {

        BufferedImage sourceImage = ImageIO.read(new File(filePath));
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();

        if(width>height){
            float extraSize=    height-100;
            float percentHight = (extraSize/height)*100;
            float percentWidth = width - ((width/100)*percentHight);
            BufferedImage img = new BufferedImage((int)percentWidth, 100, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance((int)percentWidth, 100, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage((int)((percentWidth-100)/2), 0, 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));    
        }else{
            float extraSize=    width-100;
            float percentWidth = (extraSize/width)*100;
            float  percentHight = height - ((height/100)*percentWidth);
            BufferedImage img = new BufferedImage(100, (int)percentHight, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance(100,(int)percentHight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage(0, (int)((percentHight-100)/2), 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
12
Ali Imran

La bibliothèque JMagick (et l'implémentation de ImageMagick en Java) aura ce dont vous avez besoin.

4
mfloryan

le Java ci-dessus (avec les méthodes scale/getCompatibleImage) a très bien fonctionné pour moi, mais lorsque j'ai déployé sur un serveur, il a cessé de fonctionner, car le serveur n'avait pas d'affichage associé - quiconque sinon, ce problème peut le résoudre en utilisant: BufferedImage bi = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);

au lieu de BufferedImage bi = getCompatibleImage (w, h);

et suppression de la méthode getCompatibleImage

(note plus tard - il s'avère que cela fonctionne très bien pour la plupart des images, mais j'ai reçu un tas de services marketing de mon entreprise qui sont des images jpeg de profondeur de couleur 32 bits, et la bibliothèque lève une exception de format d'image non prise en charge pour tous ceux-ci :( - - imagemagick/jmagick commencent à paraître plus attrayants)

3
Kem Mason

Je sais que c'est un assez vieux post. Je cherchais une solution pour générer la miniature alors finissez par utiliser ce

Thumbnails.of(originalImage).scale(0.25).asBufferedImage();

si vous utilisez pour mobile suggérerait de mettre l'échelle à 0,45

Thumbnails.of(originalImage).scale(0.45).asBufferedImage();

https://github.com/coobird/thumbnailator

C'est certainement beaucoup plus rapide en utilisant Graphics2D car nous avons testé les deux options.

2
Athar

J'ai utilisé Thumbnailator! Cela a résolu mon problème avec deux lignes de code.

https://github.com/coobird/thumbnailator

2
martins.tuga

Un moyen simple de créer une vignette sans étirement ni bibliothèque. Fonctionne également avec la transparence dans les pngs.

public File createThumbnail(String imageUrl, String targetPath) {
    final int imageSize = 100;
    File thumbnail = new File(targetPath);

    try {
        thumbnail.getParentFile().mkdirs();
        thumbnail.createNewFile();
        BufferedImage sourceImage = ImageIO.read(new File(imageUrl));
        float width = sourceImage.getWidth();
        float height = sourceImage.getHeight();

        BufferedImage img2;
        if (width > height) {
            float scaledWidth = (width / height) * (float) imageSize;
            float scaledHeight = imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledWidth - scaledHeight) / 2f);
            img2 = img.getSubimage(offset, 0, imageSize, imageSize);
        }
        else if (width < height) {
            float scaledWidth = imageSize;
            float scaledHeight = (height / width) * (float) imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledHeight - scaledWidth) / 2f);
            img2 = img.getSubimage(0, offset, imageSize, imageSize);
        }
        else {
            img2 = new BufferedImage(imageSize, imageSize, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance(imageSize, imageSize, Image.SCALE_SMOOTH);
            img2.createGraphics().drawImage(scaledImage, 0, 0, null);
        }
        ImageIO.write(img2, "png", thumbnail);
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return thumbnail;
}
1
Johannes J

Il existe de nombreux frameworks de traitement d'image disponibles que vous pouvez faire en quelques lignes seulement. L'exemple ci-dessous génère les vignettes dans différentes résolutions (avec une largeur comme référence) en utilisant Marvin Framework . Les trois miniatures ont été générées en 92 ms .

entrée:

enter image description here

sortie:

enter image description here

enter image description here

enter image description here

import static marvin.MarvinPluginCollection.*;

MarvinImage image = MarvinImageIO.loadImage("./res/input.jpg");
MarvinImage scaledImage = new MarvinImage(1,1);

scale(image, scaledImage, 250);
MarvinImageIO.saveImage(scaledImage, "./res/output_x250.jpg");

scale(image, scaledImage, 150);
MarvinImageIO.saveImage(scaledImage, "./res/output_x150.jpg");

scale(image, scaledImage, 50);
MarvinImageIO.saveImage(scaledImage, "./res/output_x50.jpg");

J'ai créé une application appelée fotovault (sourceforge.net) qui peut télécharger des images et créer des vignettes en Java en utilisant imagej apis.

Veuillez lire mon blog ci-dessous

http://www.gingercart.com/Home/Java-snippets/create-image-thumbnail-in-Java-using-imagej-api

1
Mouli

J'ai parcouru un blog selon lequel vous avez les options suivantes -

  1. Pour les fichiers RVB simples, utilisez ImageScalr. La classe ImageIO est utilisée pour lire des fichiers et ImageScalr pour créer des miniatures
  2. Pour prendre en charge RGB + CYMK, utilisez ImageIO et l'API JAI (Java Advanced Imaging) pour lire les fichiers et ImageScalr pour créer une miniature.
  3. Dans le cas où vous ne savez pas quels formats de fichier, mode de couleur vous allez traiter, l'option la plus sûre est d'utiliser ImageMagick.

Voici lien qui donne une réponse complète avec des extraits de code.

1
Gagan

J'ai utilisé la classe writtena avec des méthodes statiques il y a des années en utilisant JAI. Java Advanced Imaging API est l'API la plus fiable dans Java pour traiter les images. Son interpolation vectorielle est la chose la plus proche de Photoshop dans Java monde. En voici un:

public static ByteArrayOutputStream resize(InputStream inputStream , int IMG_WIDTH,
        int IMG_HEIGHT) throws Exception {
    BufferedImage originalImage = ImageIO.read(inputStream);
    int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
            : originalImage.getType();
    BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
            type);
    {
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
        g.dispose();
        g.setComposite(AlphaComposite.Src);

        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    }
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(resizedImage, "png", bos);
    return bos;

} 
1
mike oganyan