Deux fonctions rotation en Java.

Résolu/Fermé
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 - Modifié par Étienne9 le 8/03/2012 à 20:37
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 - 18 mars 2012 à 12:35
Bonjour,

Voilà, j'ai deux fonctions de rotation en Java et sur les deux ça ne va pas.
La première s'occupe de tous les angles sauf 90 180 et 270.
Et la deuxième ne s'occupe que des angles 90 180 et 270.

Si quelqu'un pouvez m'aider. Merci beaucoup !

public static void rotation(int angle)
{
// Fonction chargée de la rotation d'une image pour tout angle sauf les multiples de 90°.
int l=0,h=0,i=0,j=0,pix=0,phd=0,pbd=0;
// l et h pour la largueur et la hauteur de l'image de départ.
// i et j pour deux boucles pour imbriquées.
// phd signifie pixel en haut à droite, pbd signifie pixel en bas à droite car ils vont servir à trouver la nouvelle taille de l'image.
BufferedImage im=null,imro=null;
// On déclare deux images, celle de départ im et celle d'arrivée imro. Au départ elles sont toutes les deux noires.
try {
im = ImageIO.read(new File("./image.bmp"));
}
catch (Exception e) {}
// On charge l'image qui s'appelle im.
l = im.getWidth();
// Récupération de la largueur de l'image de départ.
h = im.getHeight();
// Récupération de la hauteur de l'image de départ.
phd = (int) ((double)((Math.abs((l-1)*Math.cos(angle*Math.PI/180)))));
// Calcul des coordonnées du point phd.
// Formule (avec angle en radian) : x' = x*cos(angle) - y*sin(angle) or y de phd = 0
pbd = (int) ((double)((Math.abs((l-1)*Math.sin(angle*Math.PI/180) + (h-1)*Math.cos(angle*Math.PI/180)))));
// Calcul des coordonnées du point pbd.
// Formule (avec angle en radian) : y' = x*sin(angle) + y*cos(angle)
imro = new BufferedImage(phd+1,pbd+1,BufferedImage.TYPE_INT_RGB);
// On crée l'image imro qui sera la nouvelle.
for (j=0;j<h;j++) {
for (i=0;i<l;i++) {
// On parcourt l'image d'origine avec les deux boucles imbriquées.
pix = im.getRGB(i,j);
// On récupère le pixel aux coordonnées i,j.
imro.setRGB(Math.abs((int) (i*Math.cos(angle*Math.PI/180)-j*Math.sin(angle*Math.PI/180))),Math.abs((int) (i*Math.sin(angle*Math.PI/180) + j*Math.cos(angle*Math.PI/180))),pix);
// Grâce à la formule précédemment énoncé, on calcule les coordonnées du pixel récupéré et on l'implante dans la nouvelle image.
}
}
try {
ImageIO.write(imro,"png",new File("rotation.png"));
}
catch (Exception e) {};
// On sauvegarde l'image.
}
public static void rotation90(int nb, BufferedImage im)
{
// Petite fonction "récursive" chargée de faire pivoter une image d'un angle uniquement de 90, 180 ou 270.
// Elle prend en paramètres un chiffre soit 1, 2 ou 3 et une image. (1 pour 90°, 2 pour 180° et 3 pour 270°)
int l=0,h=0,i=0,j=0,pix=0;
// l et h largueur et hauteur de l'ancienne image.
BufferedImage imro;
// Déclaration de la nouvelle image.
l = im.getWidth();
// Récupération de la largueur de l'image de départ.
h = im.getHeight();
// Récupération de la hauteur de l'image de départ.
imro = new BufferedImage(h,l,BufferedImage.TYPE_INT_RGB);
// On crée l'image imro qui sera la nouvelle.
// Sachant que l'angle est soit 90, 180 ou 270, il faut au moins la faire tourner une fois.
for (j=0;j<h;j++) {
for (i=0;i<l;i++) {
//On parcout l'image d'origine.
pix = im.getRGB(i,j);
//Récupération du pixel aux coordonnées i,j
imro.setRGB(h-j-1,l-i-1,pix);
//On dépose le pixel d'origine au bon endroit sur la nouvelle image sachant que :
// h-j-1 correspond à j dans le sens inverse (i décroissant).
// l-i-1 correspond à i dans le sens inverse (j décroissant).
}
}
if (nb == 1) {
// Si on la fait tourner une fois alors.
try {
ImageIO.write(imro,"png",new File("rotation.png"));
}
catch (Exception e) {};
// On sauvegarde tout de suite car c'est déjà fait.
// Si jamais c'était deux fois ou trois fois, on remonte dans la récursivité.
}
else {
if(nb == 2) {
// Sinon si on doit la faire pivoter d'un angle de 180°
rotation90(1,imro);
// Alors comme on a déjà fait une fois, on ne va relancer qu'une fois de plus une rotation de 90°
}
else {
// Sinon, c'est nécessairement une rotation de 3 fois 90° donc 270 car dans le programme principal il n'envoit que 1, 2 ou 3 à la fonction.
rotation90(2,imro);
// Donc on doit relancer la fonction encore deux fois.
}
}
}

A voir également:

12 réponses

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
8 mars 2012 à 20:56
Pour la rotation à 90° 180° et 270° j'ai envie de dire trop facile !
Il suffit de bien gérer les indices et c'est bon, par contre appeler 2 ou 3 fois une rotation à 90° pour faire 180° et 270° c'est vraiment très moche !

Pour la rotation quelconque, si tu fais un positionnement de points avec des sinus et des cosinus tu risques de te retrouver avec des pixels vides !
Il faudrait peut-être d'abord augmenter la taille de l'image (pour grossir les pixels), et remplir les trous avec les voisins, avant de rétablir la proportion originale de l'image.
Remarque : il est surement possible de faire toutes ces opérations en une seule étape mais il faut bien calculer les valeurs (c'est plus compliqué que juste cos et sin)
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 8/03/2012 à 22:36
Pour la rotation de 90, 180, et 270, juste avec les indices on peut faire cela ???
Mon int nb me servirait quand même pour définir les indices c'est ça ?

Pour la rotation quelconque, je grossis l'image mais est-ce que ça suffit si je la grossis deux fois ? Ensuite je fais la rotation, et je remplis les trous c'est cela ?

Dernière question, comment fais-t-on s'il vous plaît en Java pour mettre un pixel en transparent.

Merci beaucoup d'avance.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
8 mars 2012 à 23:17
Quand je dis juste les indices, je veux dire comme tu as commencé à le faire avec cette ligne :
imro.setRGB(h-j-1,l-i-1,pix);
Je n'ai pas regardé si elle était bonne, mais l'idée est là en tout cas, et il suffit de faire pareil pour 180° et 270°

Pour la rotation quelconque, l'intérêt d'augmenter la taille est de pouvoir utiliser des "fractions de pixels" pour faire la rotation, en effet tes sinus et cosinus ne seront pas entiers donc avec les arrondis ça peut mettre deux pixels au même endroit ou aucun à un endroit et donc former un "trou".
Plus tu augmentes la taille plus la fraction de pixels sera importante, et la rotation n'en sera que plus esthétiquement appréciable, mais il ne faut pas trop multiplier pour autant car augmenter par N la taille multiplie le nombre de pixels par N² (qui est donc gourmand en mémoire et temps de calcul), d'autant que tout façon le but est ensuite de rediviser ce que tu auras multiplié, et tu vas donc devoir mélanger plusieurs pixels en un seul (en faisant la moyenne, ou alors avec une majorité) ce qui d'ailleurs peut te permettre de combler les trous en les ignorants lors de la division...
Donc le choix de la multiplication est un dilemme, à mon avis il faut tester pour quelques valeurs et voir ce qui est le mieux... mais l'idéal est de rajouter un paramètre à la méthode pour laisser l'utilisateur choisir.

Pour mettre un pixel en transparent tu doit utiliser la composante alpha des Color, ce qui doit se faire par exemple en manipulant le WritableRaster que tu obtiens avec getAlphaRaster()
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 9/03/2012 à 12:04
Pour la rotation quelconque, un fois l'image multipliée, je n'ai pas compris comment vous faites... Vous utilisez ensuite Cosinus et Sinus ? Mais l'image est multipliée alors pas compris...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
9 mars 2012 à 12:23
Tu utilises les cosinus et les sinus sur l'image multipliée, mais le fait que l'image soit multipliée va te permettre d'avoir un traitement plus doux car la partie entière de ton cosinus va tomber sur une fraction de pixel ce qui n'était pas possible sur l'image d'origine.

Exemple:
Sans multiplication ta rotation (cosinus et sinus) te dit de placer un pixel en x=12.53 y=17.35
Or x et y sont des entiers tu vas donc les placer en 12 et 17, mais la conversion en entier va t'induire un décalage et faire que ta rotation sera moche.
En multipliant par deux (avec les même valeurs) tu devras placer ton pixel en x=25.06 y=34.70
En passant à l'entier ça va te donner 25 et 34, c'est donc plus précis car en anticipant sur le division derrière, c'est comme si tu avais placé ton x en 12.5 ce qui n'était pas possible en conservant la taille de départ. En multipliant par 3, ça va te donner x=37 et y=52 correspondant à 12.33 et 17.33 etc...

La multiplication permet donc de compenser les erreurs de calculs induits par le passage des valeurs réelles à entières du résultats des fonctions trigonométriques et qui vont t'amener à placer plusieurs fois des pixels d'origines différentes sur le même pixel d'arrivée. Augmenter le nombre de pixels va diminuer le nombre de conflits (pour l'image redivisée derrière), ta rotation sera plus fluide.
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 9/03/2012 à 13:13
Donc si j'ai bien compris :
- J'agrandis l'image par n fois.
- Je crée une nouvelle image de la même taille que mon image agrandie.
- J'utilise le cosinus et le sinus en multipliant les coordonnées x et y par n pour remplir la nouvelle image.
- Cette image qui a subit une rotation, je crée une nouvelle image qui sera de taille l'image qui a été pivoté divisé par n pour réduire l'image de la rotation agrandie.
- Je parcours l'image et je fais la moyenne des n pixels et je place cette moyenne sur la dernière image.

C'est ça ?

Mais comment connaître la dimension de l'image retournée ?

À quoi ça sert de faire la moyenne sachant que par exemple, si l'image est multipliée par deux il y aura deux fois le premier pixel au début ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
9 mars 2012 à 13:30
"Je crée une nouvelle image de la même taille que mon image agrandie."
Non, il faut que la nouvelle image soit de la taille de l'image agrandie et pivoté.
Par exemple si tu as un carré de taille 10x10, pivoté de 45° ça devient une image 14x14.
Le calcul se fait avec les cosinus et les sinus également, il suffit de connaitre la position des coins de l'image après le pivotement pour définir les bords de la nouvelle image?

"À quoi ça sert de faire la moyenne sachant que par exemple, si l'image est multipliée par deux il y aura deux fois le premier pixel au début"
En fait si tu multiplie par 2, tu auras 4 fois le même pixel, mais une fois pivoté ils ne seront pas nécessairement placé au même endroit car avec les arrondis ils pourraient se chevaucher. D'où l'intérêt d'avoir augmenté l'image, parce que du coup si on en a 4, on a plus de chance d'en garder 1 ou 2. Et du coup ce n'est pas forcément la moyenne qu'il faut faire mais peut-être plutôt gardé le pixel le plus nombreux dans la zone à diminuer.

"Je parcours l'image et je fais la moyenne des n pixels et je place cette moyenne sur la dernière image."
Cette étape ne sert à rien, ou alors, elle doit être incluse dans l'étape "réduire l'image de la rotation"

Et tu as oublié une étape : il faut remplir les trous obtenus à cause des erreurs d'arrondis après avoir fait les cosinus et sinus, et avant de diminuer l'image.
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 9/03/2012 à 14:49
Et bien, ça ne va pas être du gâteau tout ça...

Lors de l'agrandissement, je voulais savoir comment procéder. On copie le même pixel autant de fois que le nombre de fois qu'on a agrandi l'image ??

Exemple : si on a multiplié l'image par deux, il y aura quatre fois chaque même pixel ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
9 mars 2012 à 15:54
Je peux me servir de l'interpolation linéaire pour l'agrandissement ?
Car cela m'embête d'avoir deux fonctions agrandissements...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
9 mars 2012 à 15:59
Le truc c'est qu'ici ne tu ne te sers pas de l'agrandissement pour faire de l'agrandissement, mais pour augmenter le nombre de pixels à la même valeur et ainsi compenser le fait qu'avec les arrondis tu risques d'en perdre en cours de route.
Si tu fais une interpolation linéaire ça n'aura plus de sens parce que les pixels que tu vas faire pivoter ne seront plus ceux de l'image d'origine mais un mélange de plusieurs voisins de l'image agrandie alors qu'en pivotant ces voisins ne seront surement plus les même...
Ici l'interpolation linéaire va te donner de mauvais résultats, en plus c'est beaucoup de calculs pour pas grand chose car copier-coller des pixels en carrés c'est beaucoup plus simple que faire une interpolation.
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
9 mars 2012 à 17:26
J'ai fait la fonction agrandissement pour la rotation mais il y a un soucis.
Vous pouvez regarder s'il vous plaît ?


public static void agrandissementpix(int nb)
{
int i=0,j=0,k=0,m=0,l=0,h=0,pix=0;
BufferedImage im=null,imagpix=null;
try {
im=ImageIO.read(new File("./image.bmp"));
}
catch(Exception e){}
if(nb <= 1) {
System.out.println("L'agrandissement doit etre au moins de 2");
}
else {
l=im.getWidth();
h=im.getHeight();
imagpix= new BufferedImage(l*nb,h*nb,BufferedImage.TYPE_INT_RGB);
for(j=0;j<h;j++){
for(i=0;i<l;i++){
pix=im.getRGB(i,j);
imagpix.setRGB(i*nb,j*nb,pix);
for(k=0;k<=nb;k++) {
for(m=0;m<=nb;m++) {
imagpix.setRGB(i+m,j+k,pix);
}
}
}
}
try {
ImageIO.write(imagpix,"png",new File("redimensionnement.png"));
}
catch (Exception e){};
}
}
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
Modifié par KX le 9/03/2012 à 18:57
Déjà quand on fait une méthode, on met en paramètre tout ce qu'il faut, en l'occurrence, les noms de fichiers n'ont rien à faire en dur dans le code !

De plus si tu fais des try catch avec rien dedans il vaut mieux être sûr de ton coup, or ici sur des IOException, il serait judicieux de mettre au minimum un println(e), sauf que de toute façon, s'il y a une erreur tu ne peux plus continuer donc autant ne pas récupérer l'exception !

Ton test sur la valeur de nb, il vaut mieux le faire avant de lire le fichier, car sinon tu l'auras lu pour rien...

De plus évite d'utiliser des lettres visuellement ambigües par exemple l (L minuscule) et I (i majuscule) .
Et parlons un peu convention, les boucles sont généralement imbriqués par ordre alphabétique (on met d'abord le for sur i, avant le for sur j, d'autant plus ici, qu'en maths i représente les lignes et j les colonnes, et que tu les as inversé. L'idéal ici étant d'utiliser x et y !

Concernant l'erreur en elle même, tu as fait varier k et m jusqu'à nb inclus alors que commençant à 0, ça en fait un de trop à chaque fois ! Sans oublier qu'après tu fais i+m et j+k, ce qui est évidemment faux vu que tu es censé raisonner en multiples de nb.
PS. J'imagine que k et m sont les deux premières lettres que tu as trouvé sur le clavier, mais l'idéal c'est de faire un nommage intelligent qui a un sens dans le contexte !

Une dernière remarque : vu toutes les manipulations d'image que tu souhaites faire, il serait nettement moins coûteux de faire des méthodes qui prennent en entrée un BufferedImage, et renvoie le BufferedImage résultat. Parce que faire de la lecture et écriture de fichiers images c'est très coûteux !

public static void agrandissementpix(String src, String dst, String formatName, int nb) throws IOException 
{ 
    if (nb<=1) 
    { 
        System.err.println("L'agrandissement doit etre au moins de 2"); 
        return; 
    } 
     
    BufferedImage imgSrc=ImageIO.read(new File(src)); 
    int w=imgSrc.getWidth(); 
    int h=imgSrc.getHeight(); 
     
    BufferedImage imgDst= new BufferedImage(w*nb,h*nb,BufferedImage.TYPE_INT_RGB); 
     
    for(int x=0;x<w;x++) 
    for(int y=0;y<h;y++) 
    { 
        int rgb=imgSrc.getRGB(x,y); 
         
        for(int nx=0; nx<nb; nx++) 
        for(int ny=0; ny<nb; ny++) 
            imgDst.setRGB(x*nb+nx,y*nb+ny,rgb); 
    } 
     
    ImageIO.write(imgDst,formatName,new File(dst)); 
} 

public static void main(String...args) throws IOException 
{ 
    agrandissementpix("./image.bmp","redimenssionement.png","png",2); 
}
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
9 mars 2012 à 19:45
Je vais manger, merci beaucoup. En fait je voudrais cette fonction mais qui renvoie l'image maintenant, pas qui la crée car j'en aurai besoin pour la rotation...
Alors j'essaie de la refaire mais à cause de l'exception, je n'arrive pas à renvoyer du vent.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
9 mars 2012 à 19:53
Je ne vois pas en quoi l'exception pose problème.
Tu remplaces void par BufferedImage, et tu fais un return imgDst.
En plus si tu mets également imgSrc en paramètre de la méthode ça veut dire que tu ne manipules plus aucun fichier, et il est alors impossible d'obtenir une IOException....
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
9 mars 2012 à 20:49
J'ai réussi... Je vais m'occuper demain de la fonction rotation mais j'ai une chance sur cent de la réussir...
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 10:13
Une question, dans les équations quelqu'un m'a dit que si a = - alpha, on a l'équation inverse. On peut faire comme ça ou non ? Est-ce plus simple ? Le rend est-il mieux?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 12:24
Tu parles de quelles équations ? C'est quoi a ?
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 13:05
Voilà exactement ce qu'on m'a dit.

"x' = x cos(a) + y sin(a)
y' = x sin(a) - y cos(a)


si a = -alpha

tu as l'équation partant d'un pixel final vers un pixel original..

Tu parcoures simplement l'image finale et applique l'équation à chaque pixel pour avoir le pixel initial (et donc la valeur) à appliquer.."
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 14:06
Oui mais j'ai pris la valeur absolue, de plus, 90°, 180° et 270° c'est une autre fonction qui s'en occupe car ce sont trois rotations qui sont des exceptions...

Actuellement voilà le résultat d'une rotation de 10°
https://imageshack.com/

Je voulais savoir pourquoi le coin en bas à gauche pose problème...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 14:22
Je sais que 90° 180° et 270° sont faites par une autre méthode, mais d'une part j'ai pris 90° pour pouvoir avoir des cos(a), sin(a) faciles à calculer, d'autre part ta méthode général devrait normalement fonctionner correctement pour ces valeurs là même si une autre méthode existe !

Pour le coin en bas à gauche, c'est ce que je disais, il faut recentrer les résultats car avec les cosinus et les sinus tu obtiens des valeurs négatives !

Remarque :
- Sur ton image on voit bien les pertes de pixels dont je parlais hier (les points noirs un peu partout)
- Je n'ai pas l'impression que tu gères la transparence ici, car tu as du noir par défaut, il faudrait que tu utilises BufferedImage.TYPE_INT_ARGB au lieu de TYPE_INT_RGB
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 14:34
Comment marche TYPE_INT_ARGB s'il vous plaît ?
Modification: j'ai réussi à faire la transparence, merci beaucoup. Reste donc le soucis d'agrandir puis travailler sur l'image et enfin le soucis d'en bas à gauche...

Comment je recentre mon résultat ?

En plus, comment je calcule la distance de ma nouvelle image ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
Modifié par KX le 10/03/2012 à 14:33
le ARGB c'est juste quand tu créés ton buffer :
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Pour recentrer le résultat et calculer la taille de ta nouvelle image en fait ça se fait en même temps, il suffit de calculer les positions des 4 coins de l'image tourné, pour avoir Xmin, Xmax, Ymin, Ymax.
La taille de ton image est donc Xmax-Xmin+1, Ymax-Ymin+1, et pour recentrer il suffit de soustraire Xmin, et Ymin (qui sont négatifs) à chaque position x,y et le tour est joué !
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
10 mars 2012 à 15:02
Merci beaucoup.

Alors, je voudrais récapituler un peu un truc si possible.
Dès que j'ai l'image d'origine, je crée trois nouvelles images.

Une qui sera l'image d'origine agrandie nx sans rotation.
Une qui sera l'image agrandie nx avec rotation.
Et une dernière qui sera l'image finale pivoté.

C'est cela ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 15:07
J'imagine que pour l'instant tu as fait ta méthode de rotation simple, sans agrandir ni rien du tout.
Le problème qui se pose c'est les pixels perdus un peu partout. Il faut trouver une méthode pour combler les trous. Moi je proposais d'augmenter la taille puis de la rediminuer de sorte que les trous soient absorbés lors de la diminution, mais tu peux faire une autre méthode si tu veux, comme par exemple colorer chaque trou en prenant la moyenne des pixels voisins comme couleur.
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
10 mars 2012 à 15:27
C'est quoi le mieux ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 15:34
Si on n'augmente pas la taille c'est plus économe en ressource (espace mémoire et de temps), mais le résultat risque d'être moins joli, surtout sur les bords.
Mais tu peux commencer par la méthode des moyennes, si le résultat te suffit visuellement tant mieux, sinon tu auras juste à augmenter avant et diminuer après pour améliorer le traitement.
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 15:37
Mais question d'agrandissement je ne vois pas comment faire en fait....
Au fait, ymin vaut toujours 0 non ? Car sur l'image d'origine c'est le point qui a pour coordonnées (0,0). ??
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 15:47
Si tu fais une rotation à 180° (ou 179.9999 si tu préfères ^^), le point de coordonnées (w,h) va se retrouver en (-w,-h), on aura donc ymin = -h, ce n'est donc pas toujours 0...

Question agrandissement, on l'a déjà fait hier ici
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
10 mars 2012 à 15:49
En fait, désolé je me suis mal expliqué.
L'agrandissement pas de soucis, mais eu... Une fois agrandie je ne vois pas exactement comment faire en faire.
Vous pouvez me faire des dessins s'il vous plaît que je vois les étapes ?
En parlant de ça, j'ai arrangé ma fonction pour ajouter ymin xmin ymax et xmax et tout mais ça ne fonctionne pas.



public static void rotation(int angle)
{
// Fonction chargée de la rotation d'une image pour tout angle sauf les multiples de 90°.
int l=0,h=0,i=0,j=0,pix=0,xmax=0,ymax=0,xmin=0,ymin=0;
// l et h pour la largueur et la hauteur de l'image de départ.
// i et j pour deux boucles pour imbriquées.
// phd signifie pixel en haut à droite, pbd signifie pixel en bas à droite car ils vont servir à trouver la nouvelle taille de l'image.
BufferedImage im=null,imro=null;
// On déclare deux images, celle de départ im et celle d'arrivée imro. Au départ elles sont toutes les deux noires.
try {
im = ImageIO.read(new File("./image.bmp"));
}
catch (Exception e) {}
// On charge l'image qui s'appelle im.
l = im.getWidth();
// Récupération de la largueur de l'image de départ.
h = im.getHeight();
// Récupération de la hauteur de l'image de départ.
xmax = (int) Math.abs((l-1)*Math.cos(angle*Math.PI/180));
xmin = (int) Math.abs(-(h-1)*Math.sin(angle*Math.PI/180));
// Calcul des coordonnées des points xmax et xmin qui sont les coordonnées des coins en haut à droite et en bas à gauche.
// Formule (avec angle en radian) : x' = x*cos(angle) - y*sin(angle) or y de phd = 0
ymax = (int) ((Math.abs((l-1)*Math.sin(angle*Math.PI/180) + (h-1)*Math.cos(angle*Math.PI/180))));
// Calcul des coordonnées du point ymax.
// Formule (avec angle en radian) : y' = x*sin(angle) + y*cos(angle)
imro = new BufferedImage(xmax-xmin+1,ymax-ymin+1,BufferedImage.TYPE_INT_ARGB);
// On crée l'image imro qui sera la nouvelle.
for (j=0;j<h;j++) {
for (i=0;i<l;i++) {
// On parcourt l'image d'origine avec les deux boucles imbriquées.
pix = im.getRGB(i,j);
// On récupère le pixel aux coordonnées i,j.
imro.setRGB(Math.abs((int) (i*Math.cos(angle*Math.PI/180)-j*Math.sin(angle*Math.PI/180)))-xmin,Math.abs((int) (i*Math.sin(angle*Math.PI/180) + j*Math.cos(angle*Math.PI/180)))-ymin,pix);
// Grâce à la formule précédemment énoncé, on calcule les coordonnées du pixel récupéré et on l'implante dans la nouvelle image.
}
}
try {
ImageIO.write(imro,"png",new File("rotation.png"));
}
catch (Exception e) {};
// On sauvegarde l'image.
}
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 16:07
En fait la méthode de rotation ne changera pas si on agrandit l'image, mais le résultat devrait être visuellement plus doux puisque les pixels morts de l'image agrandie ne sont en fait que des fractions de pixels de l'image d'origine.

Sinon, je ne vois pas pourquoi tu t'embêtes à recalculer à chaque fois tout tes cosinus et sinus en faisant ta conversion degrés/radians, tu n'as qu'à le faire une bonne fois pour toute au début du programme :

double cos = Math.cos(Math.PI*angle/180);
double sin = Math.sin(Math.PI*angle/180);

Après, outre le fait que tu refais un code tout moche et où je te renvoie à mes remarques d'hier, tu calcules (xmin,ymin) en considérant que ça correspond nécessairement aux coordonnées du coin supérieur droit une fois tourné, or ce n'est pas toujours le cas, d'ailleurs en général, les valeurs de xmin et de ymin ne correspondront pas forcément au même coin, de même pour (xmax,ymax)
Dessine les rotations à 0°, 45°, 90°, 135° etc... pour t'en convaincre !
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 17:48
Est-ce bon cela pour l'instant s'il vous plaît ?

abcd[0] = 0;
abcd[1] = (int) (l-1)*cos;
abcd[2] = (int) -(h-1)*sin;
abcd[3] = (int) (l-1)*cos - (h-1)*sin;
abcd[4] = 0;
abcd[5] = (int) (l-1)*sin;
abcd[6] = (int) (h-1)*cos;
abcd[7] = (int) (l-1)*sin + (h-1)*cos;

Sachant que l'ordre dans le tableau est
xA xB xC xD yA yB yC yD xmin xmax ymin ymax
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 17:59
Tes calculs de xA... sont corrects mais ils devraient être en double pas en int, il va falloir que tu repasses en int qu'au dernier moment pour faire un minimum d'erreurs d'arrondis.
Mais je ne vois toujours pas l'intérêt du tableau ! Car il suffit maintenant de faire Math.min ou Math.max sur les valeurs pour trouver xmin et les autres, ton tableau est vraiment inutile !
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
10 mars 2012 à 18:02
Il aurait fallu que je crée 12 variables? ??
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 18:06
Bah oui... où est le problème ?
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 10/03/2012 à 18:08
Ça fait trop, moi les professeurs m'ont toujours dique quand il y avait beaucoup de variables, on faisait un tableau.

Je peux utiliser Math.min et Math.max pour remplir la fin du tableau ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
10 mars 2012 à 18:16
On fait des tableaux lorsqu'on veut traiter toutes les cases de la même manière, or ici on ne peut pas comparer leurs rôles puisque tu mélanges les x et les y, les données et les résultats...
Bref, utiliser un tableau uniquement parce que ça fait beaucoup de variables est absurde ici, il est beaucoup plus logique de mettre la valeur xA dans une variable xA que dans la case abcd[0] !

Et évidement que tu dois utiliser Math.min pour calculer xmin, à moins que tu ne veuilles vraiment continuer dans l'absurdité d'un tableau et faire une boucle for pour 4 valeurs...
0
Étienne9 Messages postés 1022 Date d'inscription mardi 1 mars 2011 Statut Membre Dernière intervention 10 mai 2015 49
Modifié par Étienne9 le 18/03/2012 à 09:31
Trop tard, le projet a été rendu.
Je ne sais pas utiliser les switch....
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
18 mars 2012 à 12:35
Et bien tu as encore du boulot avant de savoir bien coder en Java !

Les switch c'est la base (et pas que en Java ! Regarde ici), sans parler de toutes les erreurs que j'ai pu relever au cours des différentes discussions que l'on a eu sur ce projet, il y a vraiment des trucs que tu dois revoir dans ta manière de programmer. Le mieux serait de comparer mes remarques avec celles que pourrait avoir ton prof sur ton projet (par exemple sur cette histoire de tableau à la place des variables) parce que si tu as rendu ton code en conservant ces erreurs, il est évident qu'il va te sanctionner, mais ce serait l'occasion qu'il te réexplique son cours sur les points que j'ai pu critiquer.
0