sae fini les gars
This commit is contained in:
@@ -3,7 +3,7 @@ import fr.iutfbleau.sae.mhuffman.*;
|
||||
import fr.iutfbleau.sae.mpif.PIFWriter;
|
||||
import fr.iutfbleau.sae.mpif.Pixel;
|
||||
import fr.iutfbleau.sae.mpif.RGBImage;
|
||||
import fr.iutfbleau.sae.util.GestionErreur;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -12,77 +12,105 @@ import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
|
||||
/**
|
||||
* Contrôleur pour la conversion d'images.
|
||||
* <p>
|
||||
* Cette classe gère le chargement des fichiers image et les opérations
|
||||
* de conversion associées. tel que
|
||||
* </p>
|
||||
*
|
||||
* Controleur pour la conversion d'images au format PIF.
|
||||
* Gere le chargement des images, le calcul des frequences,
|
||||
* la generation des codes de Huffman et la sauvegarde au format PIF.
|
||||
*/
|
||||
public class ConverterController {
|
||||
// Image convertie en RGBImage
|
||||
|
||||
/** Image convertie en RGBImage */
|
||||
private RGBImage image;
|
||||
|
||||
// Table de fréquences pour chaque composante
|
||||
/** Table de frequences pour chaque composante */
|
||||
private FrequencyTable frequencyTable;
|
||||
|
||||
// Arbres de Huffman pour chaque composante
|
||||
/** Codes de Huffman pour la composante rouge */
|
||||
private Map<Integer, String> abrHuffmanR;
|
||||
|
||||
/** Codes de Huffman pour la composante verte */
|
||||
private Map<Integer, String> abrHuffmanG;
|
||||
|
||||
/** Codes de Huffman pour la composante bleue */
|
||||
private Map<Integer, String> abrHuffmanB;
|
||||
|
||||
// Codes canoniques pour chaque composante
|
||||
/** Codes canoniques pour la composante rouge */
|
||||
private Map<Integer, String> canonRED;
|
||||
|
||||
/** Codes canoniques pour la composante verte */
|
||||
private Map<Integer, String> canonGREEN;
|
||||
|
||||
/** Codes canoniques pour la composante bleue */
|
||||
private Map<Integer, String> canonBLUE;
|
||||
|
||||
// La fenêtre du convertisseur
|
||||
/** La fenetre du convertisseur */
|
||||
private ConverterWindow fen;
|
||||
|
||||
/** Chemin du fichier de sortie */
|
||||
String outputPath;
|
||||
|
||||
/** Chemin du fichier d'entree */
|
||||
String inputPath;
|
||||
|
||||
/**
|
||||
* Construit un nouveau controleur de conversion.
|
||||
*
|
||||
* @param fen la fenetre de l'interface graphique
|
||||
* @param in le chemin du fichier d'entree (peut etre null)
|
||||
* @param out le chemin du fichier de sortie (peut etre null)
|
||||
*/
|
||||
public ConverterController(ConverterWindow fen, String in, String out) {
|
||||
this.fen = fen;
|
||||
this.outputPath = out;
|
||||
this.inputPath = in;
|
||||
}
|
||||
|
||||
|
||||
// charger une image depuis un fichier avec bufferedImage et la convertir en RGBImage
|
||||
/**
|
||||
* Charge une image depuis un fichier et la convertit en RGBImage.
|
||||
* Extrait les composantes RGB de chaque pixel et met a jour l'interface.
|
||||
*
|
||||
* @param file le fichier image a charger
|
||||
*/
|
||||
public void loadImage(File file) {
|
||||
try{
|
||||
try {
|
||||
// Lire l'image avec BufferedImage
|
||||
BufferedImage buffimage = ImageIO.read(file);
|
||||
BufferedImage buffimage = ImageIO.read(file);
|
||||
if (buffimage == null) {
|
||||
throw new IllegalArgumentException("Le fichier spécifié n'est pas une image valide.");
|
||||
throw new IllegalArgumentException("Le fichier specifie n'est pas une image valide.");
|
||||
}
|
||||
|
||||
int w = buffimage.getWidth();
|
||||
int h = buffimage.getHeight();
|
||||
|
||||
// Créer une RGBImage de la même taille
|
||||
// Creer une RGBImage de la meme taille
|
||||
this.image = new RGBImage(w, h);
|
||||
// remplir la RGBImage avec les pixels de BufferedImage
|
||||
|
||||
// Remplir la RGBImage avec les pixels de BufferedImage
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int rgb = buffimage.getRGB(x, y); // obtenir la valeur RGB du pixel
|
||||
int rgb = buffimage.getRGB(x, y);
|
||||
|
||||
// Extraire les composantes R, G, B
|
||||
int r = (rgb >> 16) & 0xFF;
|
||||
int g = (rgb >> 8) & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
// Créer un pixel et l'ajouter à la RGBImage
|
||||
|
||||
// Creer un pixel et l'ajouter a la RGBImage
|
||||
this.image.setPixel(x, y, new Pixel(r, g, b));
|
||||
}
|
||||
}
|
||||
// Mettre à jour le GUI
|
||||
|
||||
// Mettre a jour le GUI
|
||||
this.fen.setImagePreview(buffimage);
|
||||
|
||||
} catch (IOException e) {
|
||||
GestionErreur.afficherErreur("Erreur lors du chargement : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calcule les frequences d'apparition de chaque valeur RGB dans l'image.
|
||||
* Met a jour l'interface avec les tables de frequences calculees.
|
||||
*/
|
||||
public void computeFrequencies() {
|
||||
this.frequencyTable = new FrequencyTable();
|
||||
if (this.image == null) {
|
||||
@@ -90,42 +118,59 @@ public class ConverterController {
|
||||
}
|
||||
this.frequencyTable.computeFromImage(this.image);
|
||||
|
||||
// Mettre à jour le GUI avec les fréquences
|
||||
// Mettre a jour le GUI avec les frequences
|
||||
int[] freqR = this.frequencyTable.getRed();
|
||||
int[] freqG = this.frequencyTable.getGreen();
|
||||
int[] freqB = this.frequencyTable.getBlue();
|
||||
this.fen.setFrequencyTable(freqR, freqG, freqB);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Genere les arbres de Huffman pour chaque composante RGB.
|
||||
* Cree les codes binaires optimaux bases sur les frequences calculees.
|
||||
* Met a jour l'interface avec les codes de Huffman generes.
|
||||
*/
|
||||
public void computeHuffman() {
|
||||
// Génération des arbres de Huffman pour chaque composante et stockage des codes
|
||||
// Generation des arbres de Huffman pour chaque composante
|
||||
HuffmanTree arbreR = new HuffmanTree(this.frequencyTable.getRed());
|
||||
this.abrHuffmanR = arbreR.generateCodes();
|
||||
|
||||
HuffmanTree arbreG = new HuffmanTree(this.frequencyTable.getGreen());
|
||||
this.abrHuffmanG = arbreG.generateCodes();
|
||||
|
||||
HuffmanTree arbreB = new HuffmanTree(this.frequencyTable.getBlue());
|
||||
this.abrHuffmanB = arbreB.generateCodes();
|
||||
|
||||
// Mettre à jour le GUI avec les codes de Huffman
|
||||
// Mettre a jour le GUI avec les codes de Huffman
|
||||
this.fen.setHuffmanTable(this.abrHuffmanR, this.abrHuffmanG, this.abrHuffmanB);
|
||||
}
|
||||
|
||||
public void computeCanonical(){
|
||||
/**
|
||||
* Genere les codes canoniques a partir des codes de Huffman.
|
||||
* Les codes canoniques sont une forme normalisee des codes de Huffman
|
||||
* qui facilite le stockage et le decodage.
|
||||
* Met a jour l'interface avec les codes canoniques generes.
|
||||
*/
|
||||
public void computeCanonical() {
|
||||
CanonicalCode codeCanoniques = new CanonicalCode();
|
||||
this.canonRED = codeCanoniques.generateCodes(this.abrHuffmanR);
|
||||
this.canonGREEN = codeCanoniques.generateCodes(this.abrHuffmanG);
|
||||
this.canonBLUE = codeCanoniques.generateCodes(this.abrHuffmanB);
|
||||
|
||||
// Mettre à jour le GUI avec les codes canoniques
|
||||
// Mettre a jour le GUI avec les codes canoniques
|
||||
this.fen.setCanonicalTable(this.canonRED, this.canonGREEN, this.canonBLUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sauvegarde l'image au format PIF.
|
||||
* Verifie que l'image et les codes canoniques sont disponibles avant
|
||||
* d'effectuer la sauvegarde.
|
||||
*
|
||||
* @param pathfile le chemin du fichier de sortie
|
||||
*/
|
||||
public void saveAsPIF(String pathfile) {
|
||||
// je vérifie que l'image et les codes canoniques sont disponibles
|
||||
if(this.image == null || this.canonRED == null){
|
||||
// Verifier que l'image et les codes canoniques sont disponibles
|
||||
if (this.image == null || this.canonRED == null) {
|
||||
GestionErreur.afficherErreur("Impossible de sauvegarder : image ou codes canoniques manquants.");
|
||||
return;
|
||||
}
|
||||
@@ -134,42 +179,47 @@ public class ConverterController {
|
||||
PIFWriter ecriveur = new PIFWriter();
|
||||
ecriveur.writeTOFile(pathfile, this.image, this.canonRED, this.canonGREEN, this.canonBLUE);
|
||||
} catch (Exception e) {
|
||||
GestionErreur.afficherErreur("Erreur lors de l’écriture du fichier .pif : ");
|
||||
GestionErreur.afficherErreur("Erreur lors de l'ecriture du fichier .pif : ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gere la sauvegarde via le bouton de l'interface.
|
||||
* Si un chemin de sortie est defini, sauvegarde directement.
|
||||
* Sinon, ouvre un selecteur de fichier pour que l'utilisateur choisisse
|
||||
* l'emplacement de sauvegarde.
|
||||
* La sauvegarde est effectuee dans un thread separe pour ne pas bloquer
|
||||
* l'interface graphique.
|
||||
*/
|
||||
public void saveViaBtn() {
|
||||
try {
|
||||
if (outputPath != null) {
|
||||
saveAsPIF(outputPath);
|
||||
GestionErreur.afficherInfo("Fichier sauvegardé avec succès. Chemin : " + outputPath);
|
||||
return;
|
||||
}
|
||||
if (outputPath != null) {
|
||||
saveAsPIF(outputPath);
|
||||
GestionErreur.afficherInfo("Fichier sauvegarde avec succes. Chemin : " + outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sinon JFileChooser
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setDialogTitle("Enregistrer le fichier .pif");
|
||||
// Sinon JFileChooser
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setDialogTitle("Enregistrer le fichier .pif");
|
||||
|
||||
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
//saveAsPIF(chooser.getSelectedFile().getAbsolutePath());
|
||||
// On lance la sauvegarde lourde dans un thread séparé
|
||||
new Thread(() -> {
|
||||
try {
|
||||
saveAsPIF(chooser.getSelectedFile().getAbsolutePath());
|
||||
GestionErreur.afficherInfo("Fichier sauvegardé avec succès : " + chooser.getSelectedFile().getName());
|
||||
} catch (Exception e) {
|
||||
GestionErreur.afficherErreur("Erreur lors de la sauvegarde : " + e.getMessage());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
GestionErreur.afficherErreur("Erreur lors de la sauvegarde : ");
|
||||
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
File fichierSelectionne = chooser.getSelectedFile();
|
||||
ThreadSauvegardePIF thread = new ThreadSauvegardePIF(this, fichierSelectionne);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void convessionProcess(){
|
||||
// chragement
|
||||
/**
|
||||
* Lance le processus complet de conversion d'une image au format PIF.
|
||||
* Etapes :
|
||||
* 1. Chargement de l'image (depuis un fichier ou via selecteur)
|
||||
* 2. Calcul des frequences
|
||||
* 3. Generation des codes de Huffman
|
||||
* 4. Generation des codes canoniques
|
||||
* 5. Sauvegarde (automatique ou via bouton selon les parametres)
|
||||
*/
|
||||
public void conversionProcess() {
|
||||
// Chargement
|
||||
if (this.inputPath != null) {
|
||||
// Chargement direct depuis les arguments
|
||||
File file = new File(inputPath);
|
||||
@@ -179,38 +229,40 @@ public class ConverterController {
|
||||
return;
|
||||
}
|
||||
this.loadImage(file);
|
||||
}else{
|
||||
} else {
|
||||
// Sinon JFileChooser pour choisir l'image
|
||||
JFileChooser choosser =new JFileChooser();
|
||||
choosser.setDialogTitle("Choisissez une image");
|
||||
if (choosser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
this.loadImage(choosser.getSelectedFile());
|
||||
}else {
|
||||
GestionErreur.afficherErreur("Aucune image choisie. Arrêt du programme.");
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setDialogTitle("Choisissez une image");
|
||||
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
this.loadImage(chooser.getSelectedFile());
|
||||
} else {
|
||||
GestionErreur.afficherErreur("Aucune image choisie. Arret du programme.");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// je place la logique de conversion dans lordre
|
||||
// Placer la logique de conversion dans l'ordre
|
||||
computeFrequencies();
|
||||
computeHuffman();
|
||||
computeCanonical();
|
||||
|
||||
// Sauvegarder: un second argument est donné sauvegarde automatique
|
||||
// Sauvegarder : si un second argument est donne, sauvegarde automatique
|
||||
if (this.outputPath != null) {
|
||||
this.saveAsPIF(this.outputPath);
|
||||
GestionErreur.afficherInfo("Fichier sauvegardé automatiquement : " + this.outputPath);
|
||||
}else{
|
||||
// pas de deuxième argument j'ajoute un boutton pour choisir avec un jfilechoser
|
||||
GestionErreur.afficherInfo("Fichier sauvegarde automatiquement : " + this.outputPath);
|
||||
} else {
|
||||
// Pas de deuxieme argument : ajouter un bouton pour choisir avec un JFileChooser
|
||||
fen.addSaveButton(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public RGBImage getImage(){
|
||||
/**
|
||||
* Retourne l'image actuellement chargee.
|
||||
*
|
||||
* @return l'image RGB chargee, ou null si aucune image n'est chargee
|
||||
*/
|
||||
public RGBImage getImage() {
|
||||
return this.image;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user