diff --git a/src/Couleur.java b/src/Couleur.java index c0e1035..56d1d0a 100644 --- a/src/Couleur.java +++ b/src/Couleur.java @@ -1,21 +1,76 @@ + public class Couleur { - private int[] RVB= {0,0,0}; - public Couleur(int R, int V, int B) + int R,G,B; + int N=1; + // N représente de combien de Couleurs est issue celle ci, + //pour pouvoir faire des moyennes sans consommer trop de mémoire + public Couleur(int Red, int Green, int Blue) { - this.RVB[0]=R; - this.RVB[1]=V; - this.RVB[2]=B; + R=Red; + G=Green; + B=Blue; + } + public Couleur(int[] RVB) + { + // deuxième constructeur pour faciliter la vie + R=RVB[0]; + G=RVB[1]; + B=RVB[2]; + } + + public void initN(int n) + { + N=n; } public int getR() { - return this.RVB[0]; + return R; } - public int getV() + public int getG() { - return this.RVB[1]; + return G; } public int getB() { - return this.RVB[2]; + return B; + } + public int getN() + { + return N; + } + public int[] getRVB() + { + int[] a= {R,G,B}; + return a; + } + + public int distance(Couleur C) + { + //calcule la distance au carré entre 2 Couleurs, sur les 3 axes + int A=(R-C.getR())*(R-C.getR()); + A+=(G-C.getG())*(G-C.getG()); + A+=(B-C.getB())*(B-C.getB()); + return A; + } + + public void printcoul() + { + System.out.printf(" %d , %d , %d \n",R, G, B); + } + + public Couleur moyenne(Couleur C) + { + int[] A=new int[3]; + A[0]=(R*N + C.getR()*C.getN())/(N+C.getN()); + A[1]=(G*N + C.getG()*C.getN())/(N+C.getN()); + A[2]=(B*N + C.getB()*C.getN())/(N+C.getN()); + Couleur Retour=new Couleur(A); + Retour.initN(N+C.getN()); + return Retour; + } + public boolean egal(Couleur C) + { + return(R==C.getR() && G==C.getG() && B==C.getB()); } + } diff --git a/src/DisplayedImage.java b/src/DisplayedImage.java index 14a2401..9c2187e 100644 --- a/src/DisplayedImage.java +++ b/src/DisplayedImage.java @@ -30,5 +30,8 @@ public void RefreshImage(BufferedImage newimg){ public void paintComponent(Graphics g){ //g.drawImage(image, 0, 0, this); // draw as much as possible g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this); // draw full image - } + } + public BufferedImage getImage() { + return image; + } } \ No newline at end of file diff --git a/src/ImageViewer.java b/src/ImageViewer.java index 081b6c5..0f89364 100644 --- a/src/ImageViewer.java +++ b/src/ImageViewer.java @@ -3,11 +3,12 @@ import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; +import javax.swing.JTextField; import javax.swing.JButton; +import javax.swing.JFileChooser; import javax.imageio.ImageIO; import javax.swing.BoxLayout; -import java.awt.Image; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -24,11 +25,14 @@ public class ImageViewer extends JFrame /*implements ActionListener*/ private JButton buttonHisto = new JButton("Histogramme"); private JButton buttonQuant = new JButton("Quantification"); - private JButton buttonInverse = new JButton("Inverse"); private JMenuBar menuBar = new JMenuBar(); private JMenu fileMenu = new JMenu("File"); + private JMenuItem itemSave = new JMenuItem("Save"); + + private JMenuItem itemCharge = new JMenuItem("Charger une image"); + private JMenuItem itemClose = new JMenuItem("Close"); @@ -44,6 +48,12 @@ public ImageViewer () { JPanel inverse = new JPanel(); inverse.setLayout(new BoxLayout(inverse, BoxLayout.PAGE_AXIS)); inverse.add(buttonInverse); + + JPanel charger = new JPanel(); + charger.setLayout(new BoxLayout(charger, BoxLayout.PAGE_AXIS)); + charger.add(itemCharge); + // Defines action associated to buttons + itemCharge.addActionListener(new ButtonCharger()); // Defines action associated to buttons buttonAction.addActionListener(new ButtonListener()); @@ -58,8 +68,10 @@ public ImageViewer () { quant.setLayout(new BoxLayout(quant, BoxLayout.PAGE_AXIS)); quant.add(buttonQuant); // Defines action associated to buttons - buttonQuant.addActionListener(new Quant()); - + + // ########## CLASS QUANT ########## + buttonQuant.addActionListener(new Quanti()); +// ############## FIN CLASS QUANT ############# buttonInverse.addActionListener(new ButtonListener(){ public void actionPerformed(ActionEvent arg0) { BufferedImage Invimage; @@ -94,7 +106,6 @@ public void actionPerformed(ActionEvent arg0) { global.setLayout(new BoxLayout(global, BoxLayout.LINE_AXIS)); global.add(input); - global.add(action); global.add(quant); global.add(histo); @@ -111,11 +122,13 @@ public void actionPerformed(ActionEvent arg0) { System.exit(0); } }); - this.fileMenu.add(itemClose); + this.fileMenu.add(itemClose); + this.fileMenu.add(itemCharge); this.menuBar.add(fileMenu); this.setJMenuBar(menuBar); - + itemSave.addActionListener(new ButtonListener2()); + this.fileMenu.add(itemSave); this.setVisible(true); @@ -124,18 +137,102 @@ public void actionPerformed(ActionEvent arg0) { /** * Class listening to a given button */ + class ButtonListener2 implements ActionListener{ + public void actionPerformed(ActionEvent arg0) + { + final JFileChooser fc=new JFileChooser(); + fc.setMultiSelectionEnabled(true); + int returnVal = fc.showSaveDialog(null); + if(returnVal == JFileChooser.APPROVE_OPTION) + { + File saved = fc.getSelectedFile(); + try { + ImageIO.write(ouputImage.getImage(),"png",saved); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + class ButtonCharger implements ActionListener{ + public JTextField status = new JTextField("pas de fichier chargé"); + public JFileChooser choose = new JFileChooser(); + private BufferedImage image = inputImage.getimage(); + + public void actionPerformed(ActionEvent evt){ //ouvrir une boite de dialogue pour choisir un fichier + choose.setApproveButtonText("Charger un fichier"); + choose.showOpenDialog(null); + if (choose.showOpenDialog(null)==JFileChooser.APPROVE_OPTION){ + status.setText(choose.getSelectedFile().getAbsolutePath()); + System.out.println(status.getText()); + + try{ + image = ImageIO.read(new File(status.getText())); + } + catch (IOException e) { + e.printStackTrace(); + } + + + } + inputImage.RefreshImage(image); + ouputImage.RefreshImage(image); + + } + + + } class ButtonListener implements ActionListener{ public void actionPerformed(ActionEvent arg0) { } - - class HistoListener implements ActionListener{ + } + class Quanti implements ActionListener{ public void actionPerformed(ActionEvent arg0) { - System.out.println("Histogramme créé"); + BufferedImage ima = null; + try { + ima = ImageIO.read(new File("img.png")); + } catch (IOException e) { + + e.printStackTrace(); + } + System.out.println("Matrice importée"); + int h; + int w; + w= ima.getWidth(); + h= ima.getHeight(); + int[][][] image = new int[w][h][3]; + System.out.println("L x H :"+w +" "+ h); + //récupération des couleurs, mises dans le tableau image + int i,j,A; + for( j=0 ; j>> 16)&0xFF; + image[i][j][1]=(byte)(A >>> 8)&0xFF; + image[i][j][2]=(byte)(A >>> 0)&0xFF; + } + } + Traitement PAL = new Traitement(image, w,h); + int[][][] image_finale= PAL.returnImage(); + BufferedImage Invimage; + Invimage = ouputImage.getimage(); + + int x,y; + for(x=0;xcoul.getRVB()[P%3]) { if(fils[1]) @@ -43,9 +43,205 @@ public int addpointnode(couleur RVB) } } } - public couleur[] palettenode(couleur[] palette,int p) + public Couleur getcoul() { + return coul; + } + public Couleur[] palnode(Couleur[] pal) + { + int L= pal.length; + if(L==2) + { + pal[0]=filsD.Moy(); + pal[1]=filsG.Moy(); + return pal; + } + else + { + int i; + Couleur[] A=new Couleur[L/2]; + Couleur[] B=new Couleur[L/2]; + if(fils[0]) {A=filsG.palnode(A);} + else { + for(i=0;i getPointFromTree(KdNode point, ArrayList liste){ //donne tous les points en dessous dans l'arbre + if (point != null){ + liste.add(point); + if(point.getFilsG()!=null){ + getPointFromTree(point.getFilsG(),liste); + } + else if(point.getFilsD()!=null){ + getPointFromTree(point.getFilsD(),liste); + } + } + return liste; + } + + public int getDirection(){ + return this.P % 3; //0:R;1:V;2:B + } + + public int removePointNode(KdNode point){ // enleve point et reconstruit arbre, renvoie profondeur + int direction = this.getDirection(); + int new_p = 0; + switch (this.coul.comparaison(direction, point.getcoul())){ + case 1: //fils de gauche + return (this.filsG.removePointNode(point)); + case -1: //fils de droite + return (this.filsD.removePointNode(point)); + + default: //0 + if (this.coul.egal(point.getcoul())){//c'est le point à supprimer + //son fils de droite va prendre sa place, tous les fils de gauche reconstruits + point.replaceNode(point.getFilsD());//il emmene tous ses fils avec + + ArrayList liste = new ArrayList(); + getPointFromTree(point.getFilsG(), liste); + for (int i=0;i (coul.getRVB())[P%3]) + { + if (fils[1]) + { + Couleur CurrentBest = filsD.getNN(A); + if (CurrentBest.distance(A) > coul.distance(A)) + { + CurrentBest=coul; + } + if(CurrentBest.distance(A) > Math.abs((coul.getRVB())[P%3] - (A.getRVB())[P%3]) && fils[0]) + { + Couleur Alter = filsG.getNN(A); + if(CurrentBest.distance(A) > Alter.distance(A)) + { + CurrentBest=Alter; + } + } + return CurrentBest; + } + else + { + return coul; + } + } + else + { + if (fils[0]) + { + Couleur CurrentBest = filsG.getNN(A); + if (CurrentBest.distance(A) > coul.distance(A)) + { + CurrentBest=coul; + } + if(CurrentBest.distance(A) > Math.abs((coul.getRVB())[P%3] - (A.getRVB())[P%3]) && fils[1]) + { + Couleur Alter = filsD.getNN(A); + if(CurrentBest.distance(A) > Alter.distance(A)) + { + CurrentBest=Alter; + } + } + return CurrentBest; + } + else + { + return coul; + } + } } } diff --git a/src/KdTree.java b/src/KdTree.java index c2909c1..7a1102d 100644 --- a/src/KdTree.java +++ b/src/KdTree.java @@ -1,28 +1,62 @@ -public class KdTree { - int P=0; - KdNode Racine; - public KdTree(int[] RVB) - { - couleur coul= new couleur(RVB); - Racine= new KdNode(coul,P); +public class KdTree{ + private int profondeur=0; + + private Couleur CouleurR; + private KdNode Racine; + + public KdTree (int RVB[]){ + this.CouleurR=new Couleur(RVB[0], RVB[1], RVB[2]); + this.Racine= new KdNode(CouleurR,0); } - void addpoint(int []RVB) - { - //ajoute un point à l'arbre, si il est plus profond, on augemente la profondeur max de l'arbre - couleur coul=new couleur(RVB); - int A=Racine.addpointnode(coul); - if (A>P) + public static int getProf(){ + return profondeur; + } + + + + public void addpoint(int RVB[]){ + Couleur C=new Couleur(RVB); + int p= Racine.addpointnode(C); + if(p>profondeur) { - P=A; + profondeur=p; } + + } + + public void removePoint(int RVB[],int XY[]){ + Couleur couleur = new Couleur(RVB); + KdNode point = new KdNode(couleur,0); + int p = this.Racine.removePointNode(point); + + if (p> la méthode addpoint de KdNode devra renvoyer un entier la profondeur du nouveau noeud créé*/ - - /*public int addpoint(Couleur RVB, int[] XY){ - if(RVB.compare(couleur, P%3)){ - if (fils[0]){ - filsG.addpoint(RVB, XY); - } - else{ - filsG= new KdNode(RVB,XY, P+1); - fils[0]=true; return P+1; - } - } - else{ - if (fils[1]){ - filsD.addpoint(RVB, XY); - } - else{ - filsD= new KdNode(RVB,XY,P+1); - fils[1]=true; return P+1; - } - }*/ -} -/*couleurR= couleur de la racine (class Couleur) -Profondeur=profondeur de l’arbre -Racine = Premier noeud de l’arbe (class KdNode)*/ \ No newline at end of file diff --git a/src/Quant.java b/src/Quant.java deleted file mode 100644 index 409c052..0000000 --- a/src/Quant.java +++ /dev/null @@ -1,166 +0,0 @@ -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - - - -import javax.imageio.ImageIO; - -public class Quant implements ActionListener { - public void actionPerformed(ActionEvent arg0) - { - couleur[] palette; - int[][] image_traitee; - //importation de l'image - BufferedImage ima = null; - try { - ima = ImageIO.read(new File("img.png")); - } catch (IOException e) { - - e.printStackTrace(); - } - System.out.println("Matrice importée"); - int h; - int w; - int total=0; - w= ima.getWidth(); - h= ima.getHeight(); - int[][][] image = new int[w][h][3]; - System.out.println("L x H :"+w +" "+ h); - //récupération des couleurs, mises dans le tableau image - int R,V,B,i,j,A; - for( j=0 ; j>> 16)&0xFF; - image[i][j][1]=(byte)(A >>> 8)&0xFF; - image[i][j][2]=(byte)(A >>> 0)&0xFF; - } - } - - //passage d'un tableau w*h à un tableau à une ligne - int[][] line= linear(image,w,h); - //création d'un arbre à partir de line - KdTree Arbre1 = InitFromArray(line); - - } - public void printtab(int[][] tableau, int dim) - { - int i; - for (i=0; i