diff --git a/build/fr/iutfbleau/sae/mhuffman/FrequencyTable.class b/build/fr/iutfbleau/sae/mhuffman/FrequencyTable.class index 980e373..3800669 100644 Binary files a/build/fr/iutfbleau/sae/mhuffman/FrequencyTable.class and b/build/fr/iutfbleau/sae/mhuffman/FrequencyTable.class differ diff --git a/build/fr/iutfbleau/sae/mhuffman/HuffmanNode.class b/build/fr/iutfbleau/sae/mhuffman/HuffmanNode.class index 460a579..753c3ac 100644 Binary files a/build/fr/iutfbleau/sae/mhuffman/HuffmanNode.class and b/build/fr/iutfbleau/sae/mhuffman/HuffmanNode.class differ diff --git a/build/fr/iutfbleau/sae/mpif/PIFWriter.class b/build/fr/iutfbleau/sae/mpif/PIFWriter.class index 1647dc7..78b8424 100644 Binary files a/build/fr/iutfbleau/sae/mpif/PIFWriter.class and b/build/fr/iutfbleau/sae/mpif/PIFWriter.class differ diff --git a/build/fr/iutfbleau/sae/util/BitOutputStream.class b/build/fr/iutfbleau/sae/util/BitOutputStream.class index ab684aa..dd9b936 100644 Binary files a/build/fr/iutfbleau/sae/util/BitOutputStream.class and b/build/fr/iutfbleau/sae/util/BitOutputStream.class differ diff --git a/src/fr/iutfbleau/sae/mhuffman/FrequencyTable.java b/src/fr/iutfbleau/sae/mhuffman/FrequencyTable.java index e290162..9768aa2 100644 --- a/src/fr/iutfbleau/sae/mhuffman/FrequencyTable.java +++ b/src/fr/iutfbleau/sae/mhuffman/FrequencyTable.java @@ -1,4 +1,5 @@ package fr.iutfbleau.sae.mhuffman; +import fr.iutfbleau.sae.mimage.Pixel; import fr.iutfbleau.sae.mimage.RGBImage; /** @@ -26,7 +27,7 @@ import fr.iutfbleau.sae.mimage.RGBImage; *
* * @author Algassimou Pellel Diallo - * @version 1.0 + * @version 1.1 * @since 2025-12-13 */ public class FrequencyTable { @@ -62,22 +63,28 @@ public class FrequencyTable { * * * @param img l'image RGB à analyser + * @throws IllegalArgumentException si l'image est null */ public void computeFromImage(RGBImage img) { - /*Nb: une composante de couleur est un entier entre 0 et 255 qui représente la part de rouge,vert ou bleu - dans la couleur d'un pixel. - */ - /* pour chaque composante de couleur de chaque pixel, on incrémente la fréquence correspondante, - c'est-à-dire on compte le nombre de fois que la composante apparaît dans l'image. - ex: si un pixel P a une composante rouge de 150, on incrémente freqR[150] de 1. - puis on fait de même pour les composantes verte et bleue. - on répète ce processus pour tous les pixels de l'image. - */ - for (int ligne = 0; ligne < img.getWidth(); ligne++) { - for (int colonne = 0; colonne < img.getHeight(); colonne++) { - this.freqR[img.getPixel(ligne, colonne).getR()]++; // Incrémente la fréquence de la composante rouge - this.freqG[img.getPixel(ligne, colonne).getG()]++; // Incrémente la fréquence de la composante verte - this.freqB[img.getPixel(ligne, colonne).getB()]++; // Incrémente la fréquence de la composante bleue + if (img == null) { + throw new IllegalArgumentException("L'image ne peut pas être null"); + } + + /* Pour chaque composante de couleur de chaque pixel, on incrémente la fréquence correspondante, + * c'est-à-dire on compte le nombre de fois que la composante apparaît dans l'image. + * Ex: si un pixel P a une composante rouge de 150, on incrémente freqR[150] de 1. + * Puis on fait de même pour les composantes verte et bleue. + * On répète ce processus pour tous les pixels de l'image. + */ + for (int x = 0; x < img.getWidth(); x++) { + for (int y = 0; y < img.getHeight(); y++) { + // On récupère le pixel une seule fois pour optimiser + Pixel pixel = img.getPixel(x, y); + + // Puis on incrémente les trois fréquences + this.freqR[pixel.getR()]++; + this.freqG[pixel.getG()]++; + this.freqB[pixel.getB()]++; } } } @@ -93,7 +100,6 @@ public class FrequencyTable { /** * Retourne le tableau des fréquences de la composante verte. - * * @return un tableau de 256 entiers représentant les fréquences du vert */ public int[] getGreen() { @@ -108,8 +114,4 @@ public class FrequencyTable { public int[] getBlue() { return this.freqB; } -} - - - - +} \ No newline at end of file diff --git a/src/fr/iutfbleau/sae/mhuffman/HuffmanNode.java b/src/fr/iutfbleau/sae/mhuffman/HuffmanNode.java index 8c46124..e3dcefb 100644 --- a/src/fr/iutfbleau/sae/mhuffman/HuffmanNode.java +++ b/src/fr/iutfbleau/sae/mhuffman/HuffmanNode.java @@ -21,10 +21,14 @@ package fr.iutfbleau.sae.mhuffman; */ public class HuffmanNode { - /** Valeur de la composante (cette valeur est appelée symbole, voir l'histoire de huffman, tres interressant) représentée par ce nœud (si feuille). c'est la part de la composante (rouge, verte ou bleue) dans la couleur d'un pixel. */ + /** + * Valeur de la composante (symbole) représentée par ce nœud (uniquement pour les feuilles). + * Représente la part de la composante (rouge, verte ou bleue) dans la couleur d'un pixel. + * Pour les nœuds internes, cette valeur vaut -1. + */ private int value; - /** Fréquence du symbole (somme des fréquences des enfants). */ + /** Fréquence du symbole (somme des fréquences des enfants pour les nœuds internes). */ private int frequence; /** Fils gauche du nœud (null si feuille). */ @@ -40,10 +44,18 @@ public class HuffmanNode { * issue de la table de fréquences. * * - * @param value la valeur (symbole) représentée par ce nœud + * @param value la valeur (symbole) représentée par ce nœud (entre 0 et 255) * @param frequence la fréquence d'apparition de la valeur + * @throws IllegalArgumentException si la valeur n'est pas entre 0 et 255 + * ou si la fréquence est négative */ public HuffmanNode(int value, int frequence) { + if (value < 0 || value > 255) { + throw new IllegalArgumentException("La valeur doit être entre 0 et 255"); + } + if (frequence < 0) { + throw new IllegalArgumentException("La fréquence ne peut pas être négative"); + } this.value = value; this.frequence = frequence; this.left = null; @@ -59,8 +71,13 @@ public class HuffmanNode { * * @param left le fils gauche * @param right le fils droit + * @throws IllegalArgumentException si l'un des fils est null */ public HuffmanNode(HuffmanNode left, HuffmanNode right) { + if (left == null || right == null) { + throw new IllegalArgumentException("Les fils ne peuvent pas être null"); + } + this.value = -1; // Valeur sentinelle pour les nœuds internes this.left = left; this.right = right; this.frequence = left.frequence + right.frequence; @@ -87,7 +104,7 @@ public class HuffmanNode { /** * Retourne le fils gauche du nœud. * - * @return le fils gauche + * @return le fils gauche, ou null si le nœud est une feuille */ public HuffmanNode getLeft() { return this.left; @@ -96,7 +113,7 @@ public class HuffmanNode { /** * Retourne le fils droit du nœud. * - * @return le fils droit + * @return le fils droit, ou null si le nœud est une feuille */ public HuffmanNode getRight() { return this.right; @@ -108,12 +125,29 @@ public class HuffmanNode { * Cette méthode n'a de sens que si le nœud est une feuille. * * - * @return la valeur du symbole + * @return la valeur du symbole (entre 0 et 255) + * @throws IllegalStateException si le nœud n'est pas une feuille */ public int getValue() { - if (!this.isLeaf()) { - throw new IllegalStateException("La valeur n'est définie que pour les feuilles."); - } + if (!this.isLeaf()) { + throw new IllegalStateException("La valeur n'est définie que pour les feuilles."); + } return this.value; } -} + + /** + * Retourne une représentation textuelle du nœud. + *+ * Utile pour le débogage et l'affichage de l'arbre. + *
+ * + * @return une chaîne décrivant le nœud + */ + @Override + public String toString() { + if (this.isLeaf()) { + return "Feuille(valeur=" + this.value + ", freq=" + this.frequence + ")"; + } + return "Noeud(freq=" + this.frequence + ")"; + } +} \ No newline at end of file diff --git a/src/fr/iutfbleau/sae/mhuffman/HuffmanTree.java b/src/fr/iutfbleau/sae/mhuffman/HuffmanTree.java index d87c0b3..2d3482f 100644 --- a/src/fr/iutfbleau/sae/mhuffman/HuffmanTree.java +++ b/src/fr/iutfbleau/sae/mhuffman/HuffmanTree.java @@ -167,36 +167,6 @@ public class HuffmanTree { generateCodesRec(node.getLeft(), prefiixe + "0"); // On va a droite en ajoutant "1" au code generateCodesRec(node.getRight(), prefiixe + "1"); - - - // this.codes = new HashMap<>(); - // this.chaineCarac = new String(); - - // if(root.isLeaf()){ - // codes.put(root.getValue(),Integer.parseInt(chaineCarac)); - // return codes; - // } - - // HuffmanNode temp = root; - - // if (root.getLeft() != null) { - // root = root.getLeft(); - // chaineCarac = chaineCarac + "0"; - // generateCodes(); - // // on retire le dernier bit lorsqu'on remonte car sinon les codes seront faussés - // chaineCarac = chaineCarac.substring(0, chaineCarac.length() - 1); - // } - - // if (temp.getRight() != null) { - // root = temp.getRight(); - // chaineCarac = chaineCarac + "1"; - // generateCodes(); - // chaineCarac = chaineCarac.substring(0, chaineCarac.length() - 1); - // } - - - // root = temp; - // return codes; } /** diff --git a/src/fr/iutfbleau/sae/mpif/PIFReader.java b/src/fr/iutfbleau/sae/mpif/PIFReader.java index 80b3c2e..1bfbeab 100644 --- a/src/fr/iutfbleau/sae/mpif/PIFReader.java +++ b/src/fr/iutfbleau/sae/mpif/PIFReader.java @@ -1,13 +1,11 @@ package fr.iutfbleau.sae.mpif; - +import fr.iutfbleau.sae.mimage.RGBImage; import fr.iutfbleau.sae.util.BitInputStream; -import fr.iutfbleau.sae.util.BitOutputStream; +import java.io.BufferedInputStream; import java.io.FileInputStream; import java.util.Map; -import fr.iutfbleau.sae.mimage.RGBImage; - public class PIFReader { @@ -19,8 +17,11 @@ public class PIFReader { public RGBImage read(String filepath) throws Exception { + + // j'Utilise d'un BufferedInputStream pour une meilleure performance FileInputStream fis = new FileInputStream(filepath); - BitInputStream lecteur = new BitInputStream(fis); + BufferedInputStream bis = new BufferedInputStream(fis); + BitInputStream lecteur = new BitInputStream(bis); // je lis l'entête et les tables canoniques this.readHeader(lecteur); @@ -42,7 +43,7 @@ public class PIFReader { } public void readHeader(BitInputStream in) { - // TODO: Implement header reading + } public void readCanonicalTables(BitInputStream in) { diff --git a/src/fr/iutfbleau/sae/mpif/PIFWriter.java b/src/fr/iutfbleau/sae/mpif/PIFWriter.java index a941a18..199ac17 100644 --- a/src/fr/iutfbleau/sae/mpif/PIFWriter.java +++ b/src/fr/iutfbleau/sae/mpif/PIFWriter.java @@ -1,6 +1,7 @@ package fr.iutfbleau.sae.mpif; import fr.iutfbleau.sae.mimage.RGBImage; +import fr.iutfbleau.sae.mimage.Pixel; import fr.iutfbleau.sae.util.BitOutputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; @@ -16,9 +17,9 @@ public class PIFWriter { throws Exception { // Création du flux de sortie binaire - FileOutputStream fos =new FileOutputStream(filepath); - BufferedOutputStream bos =new BufferedOutputStream(fos); - BitOutputStream ecriveur =new BitOutputStream(bos); + FileOutputStream fos = new FileOutputStream(filepath); + BufferedOutputStream bos = new BufferedOutputStream(fos); + BitOutputStream ecriveur = new BitOutputStream(bos); // Écriture de l'en-tête writeHeader(ecriveur, image.getWidth(), image.getHeight()); @@ -31,96 +32,109 @@ public class PIFWriter { ecriveur.fermerFlux(); - System.err.println("SYSTEME"); + System.out.println("Fichier PIF écrit avec succès"); } // Ecriture de l'en-tête du fichier PIF (largeur et hauteur) - public void writeHeader(BitOutputStream out,int width, int height){ + public void writeHeader(BitOutputStream out, int width, int height) { try { - out.writeBits(width >> 8 & 0xFF, 8); // octet de poids fort - out.writeBits(width & 0xFF, 8); // octet de poids faible - - out.writeBits(height >> 8 & 0xFF, 8); // octet de poids fort - out.writeBits(height & 0xFF, 8); // octet de poids faible + out.writeBits(width, 16); // ✅ Simplifié : 16 bits d'un coup + out.writeBits(height, 16); // ✅ Simplifié : 16 bits d'un coup } catch (Exception e) { - System.err.println("Erreur lors de l’écriture de l’en-tête du fichier PIF"); + System.err.println("Erreur lors de l'écriture de l'en-tête du fichier PIF"); } - } public void writeTables(BitOutputStream out, Map