Comment redimensionner un BufferedImage
À la suite de la javadoc, j'ai essayé de mettre à l'échelle un BufferedImage
sans succès voici mon code:
BufferedImage image = MatrixToImageWriter.getBufferedImage(encoded);
Graphics2D grph = image.createGraphics();
grph.scale(2.0, 2.0);
grph.dispose();
Je ne comprends pas pourquoi il ne fonctionne pas, toute aide?
- Un excellent tutoriel: glyphic.com/transform/applet/1intro.html
- De cette écriture, la réponse la plus populaire est la mauvaise réponse. Il l'échelle de l'image, mais il renvoie une image de la même taille, avec 3/4 de l'image manquante. C'est la réponse donnée par trashgod. C'est proche, mais il a un petit bug.
- Merci, @MiguelMunoz. Comme nous l'avons plus de commentaires que je peux changer la réponse.
Vous devez vous connecter pour publier un commentaire.
AffineTransformOp
offre la possibilité de choisir le type d'interpolation.Le fragment ci dessous illustre rééchantillonnage, pas recadrage; ce réponse adresses de la question; quelques exemples sont examinés ici.
after
, lorsque vous avez un énoncé comme:after = ...
?ColorModel
vous voulez enfilter()
. Elle retourne une référence, donc il n'y a pas de mémoire supplémentaire.after
est de la même taille, et il est juste en haut à gauche trimestre de l'original. La solution est de multiplier w et h de l'échelle lors de la création deafter
.Malheureusement, les performances de getScaledInstance() est très pauvre si ne pose pas de problème.
L'approche alternative consiste à créer un nouveau BufferedImage et et dessiner une version modifiée de l'original sur la nouvelle.
newWidth,newHeight indiquer la nouvelle BufferedImage taille et doivent être correctement calculée.
En cas de facteur de mise à l'échelle:
MODIFIER: Trouve de l'article illustrant le problème de performance: Les Dangers de l'Image.getScaledInstance()
RenderingHints.KEY_INTERPOLATION
Comme @Bozho dit, vous voudrez probablement utiliser
getScaledInstance
.De comprendre comment
grph.scale(2.0, 2.0)
fonctionne cependant, vous pourriez avoir un coup d'oeil à ce code:Donné duc.png:
il produit duke_double_size.png:
grph.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation);
oùinterpolation
estRenderingHints.VALUE_INTERPOLATION_...
par exempleVALUE_INTERPOLATION_BICUBIC
?À l'aide de imgscalr – Java Échelle de l'Image de la Bibliothèque:
C'est assez rapide pour moi.
Si vous n'avez pas l'esprit à l'aide d'une bibliothèque externe, Thumbnailator pouvez effectuer la mise à l'échelle de
BufferedImage
s.Thumbnailator prendra en charge la Java 2D de traitement (comme l'utilisation de
Graphics2D
des le rendu des conseils) de sorte qu'une simple API fluent appel peut être utilisé pour redimensionner les images:Bien que Thumbnailator, comme son nom l'indique, est orientée vers le rétrécissement des images, il va faire un travail décent agrandissement d'images, en utilisant la méthode d'interpolation bilinéaire dans son défaut resizer mise en œuvre.
Disclaimer: je suis le responsable de la Thumbnailator bibliothèque.
scale(..)
fonctionne un peu différemment. Vous pouvez utiliserbufferedImage.getScaledInstance(..)
À l'échelle d'une image, vous devez créer une nouvelle image et dessiner. Une façon est d'utiliser l'
filter()
méthode d'unAffineTransferOp
, comme l'a suggéré ici. Cela vous permet de choisir la technique d'interpolation.Une autre façon est de simplement dessiner l'image d'origine dans la nouvelle image, à l'aide d'un détartrage à faire la mise à l'échelle. Cette méthode est très similaire, mais il explique également comment vous pouvez dessiner ce que vous voulez dans l'image finale. (Je l'ai mis dans une ligne vide où les deux méthodes diffèrent.)
Addendum: Résultats
Pour illustrer les différences, j'ai comparé les résultats des cinq méthodes ci-dessous. Voici ce que les résultats ressemblent, mis à l'échelle à la fois en haut et en bas, le long avec des données de performance. (Le rendement varie de l'un à l'autre, afin de prendre ces seuls chiffres bruts des lignes directrices.) L'image du haut est l'original. Je échelle double de la taille et de la moitié de la taille.
Comme vous pouvez le voir,
AffineTransformOp.filter()
, utilisé dansscaleBilinear()
, est plus rapide que la norme de méthode de dessin deGraphics2D.drawImage()
dansscale2()
. Aussi l'interpolation Bicubique est le plus lent, mais donne de meilleurs résultats lors de l'expansion de l'image. (Pour la performance, il ne doit être comparé avecscaleBilinear()
etscaleNearest().
) Bilinéaire semble être meilleur pour réduire l'image, même si c'est une question difficile. Et NearestNeighbor est le plus rapide, avec les pires résultats. Bilinéaire semble être le meilleur compromis entre vitesse et qualité. LeImage.getScaledInstance()
, appelé dans lequestionable()
méthode, fait très mal, et a renvoyé le même de faible qualité en tant que NearestNeighbor. (Les chiffres de la Performance sont uniquement donnés à l'expansion de l'image.)