2010-11-18 48 views
7

Je dois redimensionner une image avec Java JAI. Au moment maintenant, j'utilise le code suivant:Mise à l'échelle des images avec Java JAI

private static RenderedOp scale(RenderedOp image, float scale) { 
    ParameterBlock scaleParams = new ParameterBlock(); 
    scaleParams.addSource(image); 
    scaleParams.add(scale).add(scale).add(0.0f).add(0.0f); 
    scaleParams.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2)); 

    // Quality related hints when scaling the image 
    RenderingHints scalingHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
    scalingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
    scalingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    scalingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
    scalingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
    scalingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
    scalingHints.put(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY)); 

    return JAI.create("scale", scaleParams, scalingHints); 
} 

Malheureusement, cela conduit à des résultats très mauvais, surtout parce que j'ai souvent à l'échelle des images avec un facteur d'échelle inférieure à 0,5 ...

Tous Conseil?

+0

Cette ligne semble scaleParams.add suspect (échelle) .add (échelle) .add (0.0f) .add (0.0f); – whatnick

+0

Quelques exemples de résultats pour illustrer ce que vous entendez par mauvais aidera également à identifier le type d'artefact que vous rencontrez. – whatnick

+0

Une raison de ne pas utiliser AffineTransformOp? Voir aussi http://stackoverflow.com/questions/4216635 – trashgod

Répondre

15

Je suppose que vous essayez de réduire une image plus grande à une taille de vignette ou une différence tout aussi grande de l'image originale à l'échelle? Si tel est le cas, ce sujet a été abordé par Chris Campbell à partir de Java2D en 2007 (je ne m'attends pas à ce que vous le sachiez, car il s'agit d'une question fréquente) car la nouvelle mise à l'échelle Java2D approche (RenderingHints.VALUE_INTERPOLATION_ *) n'a pas fourni un équivalent à l'approche Image.getScaledInstance(SCALE_AREA_AVERAGING or SCALE_SMOOTH) alors obsolète. Il s'avère que les approches SCALE_AREA_AVERAGING ou SCALE_SMOOTH dans l'ancienne approche Java 1.1 Image.getScaledInstance était une opération en plusieurs étapes assez coûteuse qui faisait beaucoup de travail en arrière-plan pour générer cette belle image. Chris a fait remarquer que le nouveau et "correct" moyen, en utilisant Java2D, pour obtenir ce même résultat est un processus incrémental de redimensionner l'image en demi-et plusieurs fois jusqu'à ce que la taille d'image désirée soit atteinte, de préférence en utilisant un échelle de qualité comme RenderHints.VALUE_INTERPOLATION_BICUBIC ou BILINEAR.

Le résultat est presque identique à l'original Image.getScaledInstance approche que les gens veulent.

Je suis allé chercher cette réponse il y a quelques mois en écrivant un service d'hébergement d'images et j'ai été surpris par la complexité de la simple question de "Comment faire une jolie miniature en Java?" devenu. Je crée finalement une petite bibliothèque Java (Apache 2, open sourced) qui implémente 3 approches différentes de la mise à l'échelle de l'image en Java en utilisant les «meilleures pratiques», y compris l'approche incrémentielle suggérée par Chris.

La bibliothèque est appelée imgscalr. Vous pouvez télécharger et utiliser aussi simple que:

BufferedImage thumbnail = Scalr.resize(srcImage, 150); 

Il y a plus d'options pour configurer et utiliser (par exemple, la qualité ou la vitesse de mise à l'échelle), mais hors de la boîte il y a des paramètres par défaut intelligents pour tout pour faire une belle regarder l'image à l'échelle pour vous afin que vous n'ayez pas à vous soucier de plus si vous ne voulez pas. La bibliothèque fait également un effort important pour éliminer et éviter toute allocation d'objet qui n'est pas absolument nécessaire et disposer des instances BufferedImage immédiatement si elle n'est pas nécessaire - il est prévu que le code fasse partie d'une application serveur de longue durée. critique.

J'ai déjà réalisé quelques versions de la bibliothèque, et si vous préférez supprimer les "bonnes choses" et en faire vous-même quelque chose, allez-y. Tout est sur le GitHub et rien de tout cela n'est top secret, juste une tentative pour faciliter la vie des gens.

Espérons que ça aide.

+0

Cette bibliothèque semble très intrigante. J'aime l'écriture/motivation mes premiers exemples ont bien fonctionné. Nous ne l'avons pas encore adopté en attendant une analyse plus approfondie. –

+0

@MichaelEaster Content d'entendre que ça va bien jusqu'à maintenant; Je suis impatient de recevoir des commentaires supplémentaires! –

3

J'ai obtenu de bons résultats avec Thumbnailator. Je ne sais pas ce que JAI.KEY_BORDER_EXTENDER est censé faire, mais je suppose que le reste de la fonctionnalité (antialiasing, dithering, etc) est supporté. Je l'ai utilisé pour générer les vignettes en niveaux de gris des images en noir et blanc assez grand

1

Si vous êtes chanceux et vous avez seulement & noir images blanches, vous pouvez utiliser très rapide et le bon fonctionnement de la qualité: SubsampleBinaryToGray