Qualité de l'image Redimensionner (Java)

voix
14

J'ai une application open-source qui télécharge des photos sur Facebook. Pour économiser la bande passante, les photos sont automatiquement redimensionnées avant le téléchargement (Facebook impose une limite de taille maximale). Quelques personnes se sont plaints de la qualité photo, et en fait , vous pouvez voir la différence (voir cette question pour quelques images de démonstration).

Donc, ma question est, quelle est la « meilleure » de mise à l'échelle vers le bas des images (par exemple des photos) en Java sans perte de qualité, ou au moins, avec un minimum de perte de qualité / artefacts?

Vous pouvez voir le code actuel je ici (redimensionne code via cette page ).

Créé 26/10/2009 à 15:28
source utilisateur
Dans d'autres langues...                            


7 réponses

voix
16

Phil, je ne sais pas quelle solution vous finalement allé avec, mais les images d'échelle en Java peut sembler très bon si vous:

  • Évitez les types BufferedImage qui ne sont pas bien pris en charge par le JDK.
  • Utilisez l'échelle incrémentale
  • Tenez-vous à bicubique lors de l'utilisation progressive mise à l'échelle

Je l'ai fait une part équitable des tests avec ces méthodes et la mise à l'échelle supplémentaire ainsi coller à des types d'image bien pris en charge est la clé - je vois Alexander a dit qu'il n'a toujours pas eu bonne chance avec ce qui est une vraie corvée.

J'ai sorti la bibliothèque imgscalr (Apache 2) il y a environ 6 mois pour aborder la question de « Je veux beau copies à l' échelle de cette image, faites - le maintenant! » après avoir lu quelque chose comme 10 questions comme celle - ci sur le SO.

usage standard ressemble à:

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

Le 2ème argument est la largeur et la hauteur de délimitation imgscalr utilisera à l' échelle de l'image - en gardant ses proportions correctes , même si vous avez passé dans les dimensions non valides - il y a beaucoup de méthodes plus détaillées , mais qui est l'utilisation la plus simple.

Le cas d'utilisation que vous voulez, par exemple, si Facebook limité images à 800x600 pixels, devrait ressembler à ceci:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 800, 600);

Cela assurera les séjours d'image dans le type d'image mieux pris en charge et mis à l'échelle avec la méthode la plus haute qualité que Java peut rassembler.

Dans mes propres tests à haute résolution, je ne l'ai pas remarqué des écarts béants avec des images mises à l'échelle en utilisant cette bibliothèque / ces méthodes, sauf lorsque l'image se mettre dans un type d'image mal pris en charge par le chargeur ImageIO - par exemple, cela se produit beaucoup avec GIFs . Si vous les laissez comme ça et ne les obtenez pas de ces types mal pris en charge, il finit par regarder vraiment tramées et terrible.

La raison en est que l'équipe Java2D a en fait un matériel différent pipelines accélérés pour tous les différents types de BufferedImages que le JDK processus - un sous-ensemble de ces types d'images qui sont tombent tous moins fréquents retour à l'utilisation du même pipeline de rendu logiciel sous la couvre Java2D, donnant des images à la recherche pauvres et parfois totalement incorrectes. Ce fut une telle PIA pour expliquer et essayer de comprendre que je viens d'écrire cette logique directement dans la bibliothèque.

Les deux meilleurs types pris en charge sont BufferedImage.TYPE_INT_RGB et _ARGB si vous êtes curieux.

Créé 05/07/2011 à 17:03
source utilisateur

voix
12

Je l' ai essayé tout - y compris les trucs ici , et tout ce que je peux dire que vous êtes mieux d'utiliser ImageMagick avec ce que l' interface, les bibliothèques d'imagerie Javas sont tout simplement pas à la hauteur quand il vient à ce sujet . Vous devez prendre en charge de nombreux formats et algorithmes pour obtenir ce droit.

Créé 26/10/2009 à 15:54
source utilisateur

voix
5

Les deux bibliothèques open source les plus populaires spécialisés dans redimensionnement de l'image en Java sont actuellement:

Additonal il y a la façon dont JDK Java de Graphics2D( voir cette question sur la façon de le faire ) qui est notoire pour créer de mauvais résultats en particulier avec downscaling . Il y a aussi une interface Java pour ImageMagick qui sera omise ici parce qu'il nécessite un outil externe.

Qualité visuelle

Voici une comparaison des résultats de redimensionnement / downscaling un 580x852.png à 145x213. Comme référence Photoshop CS5 Redimensionnement « Enregistrer pour le Web » est utilisé. Remarque: les résultats sont 1: 1 ce que les bibliothèques créées viennent d'être copiés ensemble. Le zoom n'utilise pas de filtrage, juste un simple algorithme du plus proche voisin. Ici vous pouvez trouver l'image originale.

Comparaison

  1. Thumbnailator 0.4.8 avec les paramètres par défaut, aucun ajustement de la dimension
  2. Photoshop CS5 avec l'algorithme bicubique
  3. imgscalr 4.2 avec le réglage ULTRA_QUALITY, aucun ajustement de la dimension
  4. Graphics2D (Java 8) avec des notes VALUE_INTERPOLATION_BICUBIC rendu, VALUE_RENDER_QUALITY, VALUE_ANTIALIAS_ON

Je laisse au lecteur de choisir le meilleur résultat que cela est subjectif. En général, tous ont un bon rendement , sauf Graphics2D. Thumbnailator génère des images plus nettes très similaires à la sortie Photoshop, tandis que la production de imgscalr est beaucoup plus douce. Pour les icônes / texte , etc. vous voulez une sortie plus nette, des images que vous pouvez sortie plus douce.

Le temps de calcul

Voici référence non-scientifique en utilisant cet outil et 114 images avec la dimension d'environ 96x96jusqu'à la 2560x1440traiter comme des images 425% créant: 100%, 150%, 200%, 300% et 400% des versions mises à l' échelle de celui - ci (donc 114 * 5 échelle opérations). Tous les libs utilisent les mêmes paramètres que dans la comparaison de la qualité (donc la meilleure qualité possible). Les temps d ' échelle seulement pas le processus. Fait sur un i5-2520M avec 8 Go Ram et 5 pistes.

  • Thumbnailator : 7003.0ms | 6581.3ms | 6019.1ms | 6375.3ms | 8700.3ms
  • imgscalr : 25218.5ms | 25786.6ms | 25095.7ms | 25790.4ms | 29296.3ms
  • Graphics2D : 7387.6ms | 7177.0ms | 7048.2ms | 7132.3ms | 7510.3ms

Voici le code utilisé dans cette référence.

Il est intéressant de Thumbnailator est aussi le plus rapide avec un temps moyen de 6,9 sec suivi par Java2D avec 7,2 sec laissant imgscalr derrière avec un pauvre 26,2 sec . Ceci est probablement pas juste puisque imgscalr est réglé sur ce ULTRA_QUALITYqui semble être extrêmement coûteux; avec les sa QUALITYmise en moyenne à un 11.1 sec plus compétitif.

Créé 29/03/2016 à 21:05
source utilisateur

voix
5

Pour redimensionner l'image avec une utilisation personnalisée de qualité thumbnailator.jar.

Exemple de code http://code.google.com/p/thumbnailator/wiki/Examples

Créé 27/01/2012 à 07:11
source utilisateur

voix
2

Qu'est-ce qui rend soupçon utilisez-vous? Habituellement rééchantillonnage bicubique sera le meilleur. Dans les photos que vous liez ils sont très dentelée, ce qui me fait penser que vous utilisez le plus proche voisin comme indice.

Dans la PictureScaler classe que vous un lien, dans la paintComponentméthode, il utilise six moyens différents de redimensionner l'image. Avez - vous essayé tous les six pour voir ce qui donne le meilleur résultat?

Créé 26/10/2009 à 15:39
source utilisateur

voix
0

Je voulais plus haute qualité redimensionne avec un rapport d'aspect préservé. J'ai essayé quelques petites choses et lire plusieurs entrées. Perdu deux jours et à la fin je suis le meilleur résultat avec la méthode Java simple (aussi essayé ImageMagick et bibliothèques-échelle java-image):

public static boolean resizeUsingJavaAlgo(String source, File dest, int width, int height) throws IOException {
  BufferedImage sourceImage = ImageIO.read(new FileInputStream(source));
  double ratio = (double) sourceImage.getWidth()/sourceImage.getHeight();
  if (width < 1) {
    width = (int) (height * ratio + 0.4);
  } else if (height < 1) {
    height = (int) (width /ratio + 0.4);
  }

  Image scaled = sourceImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
  BufferedImage bufferedScaled = new BufferedImage(scaled.getWidth(null), scaled.getHeight(null), BufferedImage.TYPE_INT_RGB);
  Graphics2D g2d = bufferedScaled.createGraphics();
  g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
  g2d.drawImage(scaled, 0, 0, width, height, null);
  dest.createNewFile();
  writeJpeg(bufferedScaled, dest.getCanonicalPath(), 1.0f);
  return true;
}


/**
* Write a JPEG file setting the compression quality.
*
* @param image a BufferedImage to be saved
* @param destFile destination file (absolute or relative path)
* @param quality a float between 0 and 1, where 1 means uncompressed.
* @throws IOException in case of problems writing the file
*/
private static void writeJpeg(BufferedImage image, String destFile, float quality)
      throws IOException {
  ImageWriter writer = null;
  FileImageOutputStream output = null;
  try {
    writer = ImageIO.getImageWritersByFormatName("jpeg").next();
    ImageWriteParam param = writer.getDefaultWriteParam();
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(quality);
    output = new FileImageOutputStream(new File(destFile));
    writer.setOutput(output);
    IIOImage iioImage = new IIOImage(image, null, null);
    writer.write(null, iioImage, param);
  } catch (IOException ex) {
    throw ex;
  } finally {
    if (writer != null) {
      writer.dispose();
    }
    if (output != null) {
      output.close();
    }
  }
}
Créé 31/05/2013 à 15:16
source utilisateur

voix
0

Après quelques expériences frustrantes que je trouve ce qui suit l' évaluation Redimensionner et employé l'approche multi-passe dans mon projet.

Pour ce faire , que je copiais la méthode dans ma classe de générateur miniature, changé mon image lu approche getScaledInstance () pour utiliser ImageIO (que l' on retourne un BufferedImage) et je suis maintenant très heureux !

Je comparais le résultat avec un redimensionnement fait dans Photoshop CS3 et le résultat est sensiblement la même.

Créé 01/12/2009 à 12:25
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more