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.
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.
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.
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();
}
}
La bibliothèque JMagick (et l'implémentation de ImageMagick en Java) aura ce dont vous avez besoin.
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)
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.
J'ai utilisé Thumbnailator! Cela a résolu mon problème avec deux lignes de code.
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;
}
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:
sortie:
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
J'ai parcouru un blog selon lequel vous avez les options suivantes -
Voici lien qui donne une réponse complète avec des extraits de code.
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;
}