Resample d'image anti aliasé => interpolation BICUBIC [Résolu] - Java - Programmation
Marsh Posté le 03-03-2005 à 15:44:38
les preuves :
affine transform java de base :
interpolation biliéaire JAI:
interpolation bicubique JAI :
interpolation bicubique2 JAI :
photoshop :
edit : c'est surtout sur la bretelle qu'on le voit.
c'est pas que je suis chiant, mais je fais ça pour un graphiste qui s'est plaint de ce défaut
Marsh Posté le 03-03-2005 à 15:52:37
J'aurais mis :
AffineTransformOp rop=new AffineTransformOp(tr, RenderingHints.VALUE_INTERPOLATION_BICUBIC); |
Je pense que c'est suffisant
Marsh Posté le 03-03-2005 à 16:14:06
tu voulais dire :
AffineTransformOp rop=new AffineTransformOp(tr, new RenderingHints(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC));
?
Ça reste pixélisé... en fait, ces méthodes d'interpolation elles marchent très bien quand il s'agit d'agrandir mais là...
Moi j'y connais pas énorme en traitement d'image, y'apa une histoire d'AntiAliasing ?
Marsh Posté le 03-03-2005 à 16:14:43
Non, je dis bien
AffineTransformOp rop=new AffineTransformOp(tr, RenderingHints.VALUE_INTERPOLATION_BICUBIC); |
Pas besoin de construire un objet RenderingHints
Marsh Posté le 03-03-2005 à 17:23:02
Eclipse m'a soufflé que le constructeur AffineTransformOp(AffineTransform, Object) n'était pas défini.
Marsh Posté le 03-03-2005 à 18:31:29
Bon, j'ai fait des comparaisons et voilà, j'ai quasiment au pixel près la même image que quand je rescale en NEAREST_NEIGHBOR dans photoshop.
Donc, j'en conclus que le rescale se fait effectivement en NEAREST_NEIGHBOR là c'est vraiment flagrant.
Sinon, j'ai essayé en mettant un blur avant le rescale c'est déjà moins pire mais ça ne fonctionne que si on connait déjà en gros la taille de l'image à redimentionner.
Est-ce que je devrais essayer d'appliquer un algo moi même ? (un truc tout fait j'y connais rien)
Ça me parraît suspect que jamais personne n'ait eu à redimentionner une image en petit et en net en java.
Marsh Posté le 03-03-2005 à 18:35:25
Non, normalement on peut y arriver. C'est étrange qu'en mode Bicubic ça ne fonctionne pas
Marsh Posté le 03-03-2005 à 18:48:44
bah je pense aussi.. mais là c'est même pas comme si ça ouvait venir de l'enregistrement JPEG parce que même avant compression affiché dans un JPanel c'est pareil, y'a des escaliers.
Et ce juste avec un :
Code :
|
Marsh Posté le 03-03-2005 à 18:50:25
Et puis c'est pas pour dire mais JAI c'est un de ces bordel
Marsh Posté le 03-03-2005 à 23:38:12
JAI c'est pas "déprecié" depuis qu'il y a a peu pres la meme chose dans le jdk1.4?
et sinon pour la visibilité des defauts, moi c'est les yeux et la bouche qui me choquent
et sinon le sujet m'interesse aussi... j'avais fait un jour un sujet similaire, mais pour le texte
edit: on y avait pas trouvé de bonne réponse pour l'anti alias, mais bon voilà: http://forum.hardware.fr/forum2.ph [...] 155&cat=10
Marsh Posté le 04-03-2005 à 01:03:56
bah.. JAI en fait ça me ferait plaisir que ce soit déprécié, c'est vraiment un bordel infâme.
sinon, cette tronche pour tes String antialiasées ça t'irait pas ?
c'est le truc d'emploi du temps sur lequel je bosse et avec un simple RenderingHints.VALUE_ANTIALIAS_ON ça me fait un truc assez propre je trouve
mais ce qui me tue c'est que les 3 modes d'interpolation en java c'est NEAREST, BILINEAR et BICUBIC et que.... dans photoshop c'est exactement les mêmes.
enfin, ce qui me tue c'est justement que le BICUBIC de java corresponde au NEAREST de photoshop, tandis que le NEAREST de java ne correspond à peu près à rien.
c'est pas possible, c'est forcément les mêmes algos.. je comprends pas.
Marsh Posté le 04-03-2005 à 09:12:43
raytaller a écrit : bah.. JAI en fait ça me ferait plaisir que ce soit déprécié, c'est vraiment un bordel infâme. |
De ce que tu nous montre là, j'ai l'impression que c'est pas du "bicubique filtré" comme dirait Monsieur GDIPlus. C'est à dire qu'il ne fait le bicubique que sur les pixels immédiatement voisins du pixel source. Et si ton image est grande, ça ignore complètement une grosse partie des pixels alentour..
Si tu le peux, essaye de faire du bicubique par increments (c'est à dire faire un resize en 100x100, puis 80x80, pui 60x60, etc.). D'ailleurs, même sous Photoshop, c'est recommandé (ça s'appelle le pyramidal bicubic je crois).
Marsh Posté le 04-03-2005 à 09:58:14
ah, tiens c'est une bonne idée ça
ouais, je vais essayer ça, les réductions de 1/2 ça se passe bien, je vais utiliser ça comme pas.
sinon, j'en avais eu une d'idée, j'ai testé sous photoshop et ça a l'air pas mal : mettre un blur avant de redimentionner
en fait, si l'image est réduite par plus que 3, je pensais faire une convolution 3*3, réduite par 4, une convolution 4*4 etc...
même si j'ai pas fait ça précisément, sous photoshop, faire un blur puis un rescale en NEAREST c'est déjà mile fois mieux que ce que j'ai avec java.
mais là je vais tenter de le faire par étapes en effet.
sinon, on m'a conseillé imageMagik mais le wrapper pour java a pas de vraie doc, et j'ai vu nulle part qu'on choisissait la méthode de resample...
Marsh Posté le 04-03-2005 à 10:37:51
Si tu fais une convolution 3*3, il faut réduire par 2. En partant du principe que tu utilises ce noyau là:
1 2 1 |
(C'est basé sur le triangle de pascal, qui permet d'avoir une bonne approximation des facteurs à appliquer pour calculer un gaussian blur)
D'un point de vue théorique, le blur de Photoshop passe bien, parce qu'il ne garde que les basses fréquences, ce qui est précisemment ce qui te manque dans ton resize. Par contre, le blur est gaussien et non pas uniforme: il utilise une courbe en forme de "cloche" pour calculer les facteurs.
Rien ne t'empêche de le faire toi-même, et en plus, ça t'apprendra beaucoup. Tu as juste besoin de savoir 2 choses:
Code :
|
Marsh Posté le 04-03-2005 à 10:46:14
Lam's a écrit : Si tu fais une convolution 3*3, il faut réduire par 2. En partant du principe que tu utilises ce noyau là:
|
ah ouais, j'aurais juré que le gauss ça se faisait en fonciton de la distance géométrique de chaque pixel (donc un truc qui dépend des x et des y)
mais là, j'ai appliqué ce que tu me conseillais, et ça marche je dirais à peu près parfaitement... en plus c'est simple comme idée mais j'y avais même pas pensé, vraiment là ça me soulage
je te remercie avec force
Marsh Posté le 04-03-2005 à 10:51:17
raytaller a écrit : ah ouais, j'aurais juré que le gauss ça se faisait en fonciton de la distance géométrique de chaque pixel (donc un truc qui dépend des x et des y) |
Bah oui, mais comme je t'ai dit, il est séparable, donc d'abord tu l'appliques en longueur (donc ça dépend effectivement de la distance horizontale), puis en largeur (donc ça dépend de la distance verticale).
Ceci dit, là où j'utilise i², tu peux utiliser "exp( -(i²+j²)/d²)" si tu souhaites calculer le noyau complet.
Marsh Posté le 04-03-2005 à 10:52:40
Et sinon, en passant par un objet Graphics2D et la méthode drawImage qui peut faire du rescaling, et en plus qui peut filtrer la chose ?
Marsh Posté le 04-03-2005 à 11:58:02
raytaller >> ben si en fait c'est pas mal ton résultat. me rappelle même plus sur quoi je m'étais basé pour me dire que ça vallait la peine de creuser !? j'avais du faire des tests, mais ché plus où
Marsh Posté le 04-03-2005 à 12:25:57
the real moins moins a écrit : raytaller >> ben si en fait c'est pas mal ton résultat. me rappelle même plus sur quoi je m'étais basé pour me dire que ça vallait la peine de creuser !? j'avais du faire des tests, mais ché plus où |
Si ça t'intéresse, j'avais posté ça sur un autre topic, elles ressemblent à rien ces méthodes (et puis c'est vrai que le français bof bof mais là c'était de circonstance) mais elles dessinent une String dans un rectangle, en gardant le ratio de la Font et en centrant si y'a besoin.
Mine de rien, j'm'en sers pas mal :
http://forum.hardware.fr/forum2.ph [...] 16#t996923
Lam's > bah oui, chuis con, la distance au carré c'est rien d'autre qu'une addition
FlorentG > bah en fait, quelle que soit la méthode utilisée, un rescale direct fait moche. En fait, il faut faire comme Lam's a dit et là c'est nickel
Marsh Posté le 04-03-2005 à 12:26:48
C'est marrant, parce que moi j'avais déjà fait des rescale, et ils n'étaient pas moche. Et sans passer par un bordel monstre
Marsh Posté le 04-03-2005 à 12:31:08
bah figure toi que je m'en étais même pas rendu compte, en fait, c'est en comparant avec le rescale de photoshop que c'est flagrant.
et puis tant que le facteur d'échelle est supérieur à 1/2 ça se voit pas, mais comme l'a dit Lam's c'est sûrement que le BICUBIC de java ne s'occupe que des pixels proches et dans le cas d'un facteur d'échelle minus (là c'était le cas, j'avais en moyenne du 1/10) plein de pixels sont ignorés.
en fait là pour avoir vraiment un beau rendu, je l'ai fait par étapes de 0.875 mais même avec 0.75 c'est déjà bien
Marsh Posté le 03-03-2005 à 15:23:03
Bon, ça fait 3 heures que j'essaye de redimentionner une image sans que ça devienne crade quand je la réduise.
J'avais commencé avec AffineTransformOp, puis pas satisfait je me suis dit qu'avec JAI ce serait mieux, et non rien n'y fait quand j'agrandis ça va c'est assez beau, mais quand je réduis, j'ai l'impression que l'anti aliasing marche pas.
Voilà le code sans JAI :
// dans le doute j'ai tout mis à fond
renderHints=new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
renderHints.put(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
renderHints.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
//.....
AffineTransform tr=new AffineTransform();
tr.scale((double)finalw/(double)w,(double)finalh/(double)h);
AffineTransformOp rop=new AffineTransformOp(tr,renderHints);
return rop.filter(pre, ret);
et en fait quand je le fais avec JAI le rendu est quasiment pareil
ParameterBlockJAI pb = new ParameterBlockJAI("scale" );
pb.addSource(loadedImage);
pb.setParameter("xScale",(float)zoomFactor);
pb.setParameter("yScale",(float)zoomFactor);
pb.setParameter("xTrans",0f);
pb.setParameter("yTrans",0f);
pb.setParameter("interpolation",new InterpolationBicubic2(8));
PlanarImage newImage= JAI.create("scale", pb, renderHints); // le même renderHints qu'avant
donc là je sais pas... si quelqu'un a déjà fait ça...
Message édité par raytaller le 04-03-2005 à 12:32:50