petit push sprint 3 fini
This commit is contained in:
+109
-109
@@ -1,110 +1,110 @@
|
||||
package fr.iutfbleau.sae.vconverter;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Panneau d'affichage des codes Huffman et canoniques.
|
||||
* Affiche les codes pour chaque composante de couleur (rouge, vert, bleu).
|
||||
* @author Algassimou
|
||||
*/
|
||||
public class CodeTablePanel extends JPanel {
|
||||
|
||||
// Zones de texte pour les codes Huffman
|
||||
private JTextArea textHuffRouge, textHuffVert, textHuffBleu;
|
||||
|
||||
// Zones de texte pour les codes canoniques
|
||||
private JTextArea textCanonRouge, textCanonVert, textCanonBleu;
|
||||
|
||||
/**
|
||||
* Constructeur qui initialise l'interface utilisateur.
|
||||
*/
|
||||
public CodeTablePanel() {
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
// Titre pour les codes Huffman
|
||||
JLabel titreHuff = new JLabel("Codes Huffman");
|
||||
titreHuff.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
add(titreHuff);
|
||||
add(Box.createVerticalStrut(10));
|
||||
|
||||
// Création des zones de texte pour les codes Huffman
|
||||
textHuffRouge = creerZoneTexte("Rouge");
|
||||
textHuffVert = creerZoneTexte("Vert");
|
||||
textHuffBleu = creerZoneTexte("Bleu");
|
||||
|
||||
// Séparateur
|
||||
add(Box.createVerticalStrut(20));
|
||||
|
||||
// Titre pour les codes canoniques
|
||||
JLabel titreCanon = new JLabel("Codes Canoniques");
|
||||
titreCanon.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
add(titreCanon);
|
||||
add(Box.createVerticalStrut(10));
|
||||
|
||||
// Création des zones de texte pour les codes canoniques
|
||||
textCanonRouge = creerZoneTexte("Rouge (Canonique)");
|
||||
textCanonVert = creerZoneTexte("Vert (Canonique)");
|
||||
textCanonBleu = creerZoneTexte("Bleu (Canonique)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une zone de texte avec une étiquette.
|
||||
* @param titre Le titre à afficher au-dessus de la zone de texte
|
||||
* @return La zone de texte configurée
|
||||
*/
|
||||
private JTextArea creerZoneTexte(String titre) {
|
||||
add(new JLabel(titre + ":"));
|
||||
JTextArea zone = new JTextArea(8, 30);
|
||||
zone.setEditable(false);
|
||||
zone.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
JScrollPane scroll = new JScrollPane(zone);
|
||||
scroll.setPreferredSize(new Dimension(300, 120));
|
||||
add(scroll);
|
||||
add(Box.createVerticalStrut(10));
|
||||
return zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l'affichage des codes Huffman.
|
||||
* @param rouge Les codes pour la composante rouge
|
||||
* @param vert Les codes pour la composante verte
|
||||
* @param bleu Les codes pour la composante bleue
|
||||
*/
|
||||
public void updateCodes(Map<Integer, String> rouge,
|
||||
Map<Integer, String> vert,
|
||||
Map<Integer, String> bleu) {
|
||||
mettreAJourZoneTexte(textHuffRouge, rouge);
|
||||
mettreAJourZoneTexte(textHuffVert, vert);
|
||||
mettreAJourZoneTexte(textHuffBleu, bleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l'affichage des codes canoniques.
|
||||
* @param rouge Les codes pour la composante rouge
|
||||
* @param vert Les codes pour la composante verte
|
||||
* @param bleu Les codes pour la composante bleue
|
||||
*/
|
||||
public void updateCanonicalCodes(Map<Integer, String> rouge,
|
||||
Map<Integer, String> vert,
|
||||
Map<Integer, String> bleu) {
|
||||
mettreAJourZoneTexte(textCanonRouge, rouge);
|
||||
mettreAJourZoneTexte(textCanonVert, vert);
|
||||
mettreAJourZoneTexte(textCanonBleu, bleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le contenu d'une zone de texte avec les codes fournis.
|
||||
* @param zone La zone de texte à mettre à jour
|
||||
* @param codes Les codes à afficher
|
||||
*/
|
||||
private void mettreAJourZoneTexte(JTextArea zone, Map<Integer, String> codes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<Integer, String> entry : codes.entrySet()) {
|
||||
sb.append(String.format("%3d : %s%n", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
zone.setText(sb.toString());
|
||||
}
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Panneau d'affichage des codes Huffman et canoniques.
|
||||
* Affiche les codes pour chaque composante de couleur (rouge, vert, bleu).
|
||||
* @author Algassimou
|
||||
*/
|
||||
public class CodeTablePanel extends JPanel {
|
||||
|
||||
// Zones de texte pour les codes Huffman
|
||||
private JTextArea textHuffRouge, textHuffVert, textHuffBleu;
|
||||
|
||||
// Zones de texte pour les codes canoniques
|
||||
private JTextArea textCanonRouge, textCanonVert, textCanonBleu;
|
||||
|
||||
/**
|
||||
* Constructeur qui initialise l'interface utilisateur.
|
||||
*/
|
||||
public CodeTablePanel() {
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
// Titre pour les codes Huffman
|
||||
JLabel titreHuff = new JLabel("Codes Huffman");
|
||||
titreHuff.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
add(titreHuff);
|
||||
add(Box.createVerticalStrut(10));
|
||||
|
||||
// Création des zones de texte pour les codes Huffman
|
||||
textHuffRouge = creerZoneTexte("Rouge");
|
||||
textHuffVert = creerZoneTexte("Vert");
|
||||
textHuffBleu = creerZoneTexte("Bleu");
|
||||
|
||||
// Séparateur
|
||||
add(Box.createVerticalStrut(20));
|
||||
|
||||
// Titre pour les codes canoniques
|
||||
JLabel titreCanon = new JLabel("Codes Canoniques");
|
||||
titreCanon.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
add(titreCanon);
|
||||
add(Box.createVerticalStrut(10));
|
||||
|
||||
// Création des zones de texte pour les codes canoniques
|
||||
textCanonRouge = creerZoneTexte("Rouge (Canonique)");
|
||||
textCanonVert = creerZoneTexte("Vert (Canonique)");
|
||||
textCanonBleu = creerZoneTexte("Bleu (Canonique)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une zone de texte avec une étiquette.
|
||||
* @param titre Le titre à afficher au-dessus de la zone de texte
|
||||
* @return La zone de texte configurée
|
||||
*/
|
||||
private JTextArea creerZoneTexte(String titre) {
|
||||
add(new JLabel(titre + ":"));
|
||||
JTextArea zone = new JTextArea(8, 30);
|
||||
zone.setEditable(false);
|
||||
zone.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
JScrollPane scroll = new JScrollPane(zone);
|
||||
scroll.setPreferredSize(new Dimension(300, 120));
|
||||
add(scroll);
|
||||
add(Box.createVerticalStrut(10));
|
||||
return zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l'affichage des codes Huffman.
|
||||
* @param rouge Les codes pour la composante rouge
|
||||
* @param vert Les codes pour la composante verte
|
||||
* @param bleu Les codes pour la composante bleue
|
||||
*/
|
||||
public void updateCodes(Map<Integer, String> rouge,
|
||||
Map<Integer, String> vert,
|
||||
Map<Integer, String> bleu) {
|
||||
mettreAJourZoneTexte(textHuffRouge, rouge);
|
||||
mettreAJourZoneTexte(textHuffVert, vert);
|
||||
mettreAJourZoneTexte(textHuffBleu, bleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l'affichage des codes canoniques.
|
||||
* @param rouge Les codes pour la composante rouge
|
||||
* @param vert Les codes pour la composante verte
|
||||
* @param bleu Les codes pour la composante bleue
|
||||
*/
|
||||
public void updateCanonicalCodes(Map<Integer, String> rouge,
|
||||
Map<Integer, String> vert,
|
||||
Map<Integer, String> bleu) {
|
||||
mettreAJourZoneTexte(textCanonRouge, rouge);
|
||||
mettreAJourZoneTexte(textCanonVert, vert);
|
||||
mettreAJourZoneTexte(textCanonBleu, bleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le contenu d'une zone de texte avec les codes fournis.
|
||||
* @param zone La zone de texte à mettre à jour
|
||||
* @param codes Les codes à afficher
|
||||
*/
|
||||
private void mettreAJourZoneTexte(JTextArea zone, Map<Integer, String> codes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<Integer, String> entry : codes.entrySet()) {
|
||||
sb.append(String.format("%3d : %s%n", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
zone.setText(sb.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
package fr.iutfbleau.sae;
|
||||
import fr.iutfbleau.sae.mhuffman.*;
|
||||
import fr.iutfbleau.sae.mimage.*;
|
||||
import fr.iutfbleau.sae.mpif.PIFWriter;
|
||||
import fr.iutfbleau.sae.vconverter.ConverterWindow;
|
||||
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;
|
||||
import java.util.Map;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
/**
|
||||
* Contrôleur pour la conversion d'images.
|
||||
@@ -45,8 +46,6 @@ public class ConverterController {
|
||||
this.fen = fen;
|
||||
this.outputPath = out;
|
||||
this.inputPath = in;
|
||||
|
||||
System.out.println(this.inputPath+" ==> "+this.outputPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,24 +75,19 @@ public class ConverterController {
|
||||
this.image.setPixel(x, y, new Pixel(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour le GUI
|
||||
this.fen.setImagePreview(buffimage);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
GestionErreur.afficherErreur("Erreur lors du chargement : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void computeFrequencies() {
|
||||
|
||||
if (this.image == null) {
|
||||
System.err.println("Aucune image chargée pour le calcul des fréquences.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.frequencyTable = new FrequencyTable();
|
||||
if (this.image == null) {
|
||||
System.out.println("Gros pepin");
|
||||
}
|
||||
this.frequencyTable.computeFromImage(this.image);
|
||||
|
||||
// Mettre à jour le GUI avec les fréquences
|
||||
@@ -105,12 +99,6 @@ public class ConverterController {
|
||||
|
||||
|
||||
public void computeHuffman() {
|
||||
|
||||
if (this.frequencyTable == null) {
|
||||
System.err.println("Les fréquences ne sont pas encore calculées.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Génération des arbres de Huffman pour chaque composante et stockage des codes
|
||||
HuffmanTree arbreR = new HuffmanTree(this.frequencyTable.getRed());
|
||||
this.abrHuffmanR = arbreR.generateCodes();
|
||||
@@ -123,12 +111,7 @@ public class ConverterController {
|
||||
this.fen.setHuffmanTable(this.abrHuffmanR, this.abrHuffmanG, this.abrHuffmanB);
|
||||
}
|
||||
|
||||
public void computeCanonical() {
|
||||
if (this.abrHuffmanR == null || this.abrHuffmanG == null || this.abrHuffmanB == null) {
|
||||
System.err.println("Les codes de Huffman doivent être générés d'abord.");
|
||||
return;
|
||||
}
|
||||
|
||||
public void computeCanonical(){
|
||||
CanonicalCode codeCanoniques = new CanonicalCode();
|
||||
this.canonRED = codeCanoniques.generateCodes(this.abrHuffmanR);
|
||||
this.canonGREEN = codeCanoniques.generateCodes(this.abrHuffmanG);
|
||||
@@ -139,10 +122,11 @@ public class ConverterController {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void saveAsPIF(String pathfile) {
|
||||
// je Vérifie que l'image et les codes canoniques sont disponibles
|
||||
if(this.image == null || this.canonRED == null){
|
||||
System.err.println("Impossible d'ecrire le fichier PIF : données manquantes.");
|
||||
// je vérifie 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;
|
||||
}
|
||||
|
||||
@@ -150,16 +134,15 @@ public class ConverterController {
|
||||
PIFWriter ecriveur = new PIFWriter();
|
||||
ecriveur.writeTOFile(pathfile, this.image, this.canonRED, this.canonGREEN, this.canonBLUE);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Erreur lors de l’écriture du fichier .pif : " + pathfile);
|
||||
GestionErreur.afficherErreur("Erreur lors de l’écriture du fichier .pif : ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void saveViaBtn() {
|
||||
try {
|
||||
if (outputPath != null) {
|
||||
saveAsPIF(outputPath);
|
||||
System.out.println("Sauvegarde dans : " + outputPath);
|
||||
GestionErreur.afficherInfo("Fichier sauvegardé avec succès. Chemin : " + outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,23 +153,31 @@ public class ConverterController {
|
||||
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
//saveAsPIF(chooser.getSelectedFile().getAbsolutePath());
|
||||
// On lance la sauvegarde lourde dans un thread séparé
|
||||
new Thread(() -> saveAsPIF(chooser.getSelectedFile().getAbsolutePath())).start();
|
||||
System.out.println("Fichier sauvegardé : " + chooser.getSelectedFile().getAbsolutePath());
|
||||
JOptionPane.showMessageDialog(null, "Fichier sauvegardé avec succès : " + chooser.getSelectedFile().getName());
|
||||
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();
|
||||
}
|
||||
|
||||
System.out.println("Via BTN Sauvegarde terminée.");
|
||||
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Erreur lors de la sauvegarde : " + ex.getMessage());
|
||||
} catch (Exception e) {
|
||||
GestionErreur.afficherErreur("Erreur lors de la sauvegarde : ");
|
||||
}
|
||||
}
|
||||
|
||||
public void StartconvessionProcess(){
|
||||
public void convessionProcess(){
|
||||
// chragement
|
||||
if (this.inputPath != null) {
|
||||
// Chargement direct depuis les arguments
|
||||
File file = new File(inputPath);
|
||||
if (!file.exists()) {
|
||||
GestionErreur.afficherErreur("Le fichier n'existe pas : " + inputPath);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
this.loadImage(file);
|
||||
}else{
|
||||
// Sinon JFileChooser pour choisir l'image
|
||||
@@ -195,7 +186,7 @@ public class ConverterController {
|
||||
if (choosser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
this.loadImage(choosser.getSelectedFile());
|
||||
}else {
|
||||
System.err.println("Aucune image choisie. Arrêt du programme.");
|
||||
GestionErreur.afficherErreur("Aucune image choisie. Arrêt du programme.");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
@@ -209,7 +200,7 @@ public class ConverterController {
|
||||
// Sauvegarder: un second argument est donné sauvegarde automatique
|
||||
if (this.outputPath != null) {
|
||||
this.saveAsPIF(this.outputPath);
|
||||
System.out.println("Fichier sauvegardé automatiquement : " + this.outputPath);
|
||||
GestionErreur.afficherInfo("Fichier sauvegardé automatiquement : " + this.outputPath);
|
||||
}else{
|
||||
// pas de deuxième argument j'ajoute un boutton pour choisir avec un jfilechoser
|
||||
fen.addSaveButton(this);
|
||||
|
||||
+159
-161
@@ -1,161 +1,159 @@
|
||||
package fr.iutfbleau.sae.vconverter;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
import fr.iutfbleau.sae.ConverterController;
|
||||
import fr.iutfbleau.sae.ExportButtonListener;
|
||||
|
||||
/**
|
||||
* Fenêtre principale du convertisseur.
|
||||
*
|
||||
* <p>
|
||||
* Cette classe correspond à la vue principale de l’application.
|
||||
* Elle centralise l’affichage des informations liées à la conversion
|
||||
* d’une image (aperçu, fréquences, codes).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Elle sert de point d’entrée unique pour la partie graphique
|
||||
* </p>
|
||||
*/
|
||||
public class ConverterWindow extends JFrame {
|
||||
|
||||
private ImagePreviewPanel imagePreviewPanel;
|
||||
private FrequencyTablePanel frequencyTablePanel;
|
||||
private CodeTablePanel codeTablePanel;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Crée la fenêtre principale du convertisseur.
|
||||
*
|
||||
* <p>
|
||||
* Le constructeur initialise la fenêtre et met en place
|
||||
* les différents panneaux graphiques utilisés pour l’affichage.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public ConverterWindow() {
|
||||
// Configuration de la fenetre
|
||||
this.setTitle("Convertisseur PIF - Visualisation des données");
|
||||
this.setSize(900, 600);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setLocationRelativeTo(null); // Centre la fenêtre
|
||||
this.setResizable(true); // on autorise le
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
|
||||
|
||||
// Initialisation des panels
|
||||
this.imagePreviewPanel = new ImagePreviewPanel();
|
||||
this.frequencyTablePanel = new FrequencyTablePanel();
|
||||
this.codeTablePanel = new CodeTablePanel();
|
||||
|
||||
// Je gere le panel principal
|
||||
JPanel contentPanel = new JPanel();
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
|
||||
//contentPanel.setBackground(new Color(255, 0, 0)); // rouge vif pour demo
|
||||
contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
|
||||
// Titre
|
||||
JLabel header = new JLabel(" Convertisseur PIF – Visualisation des données ");
|
||||
header.setFont(new Font("SansSerif", Font.BOLD, 18));
|
||||
header.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
contentPanel.add(header);
|
||||
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5))); // espace
|
||||
|
||||
// Ajout du panel d'aperçu
|
||||
contentPanel.add(imagePreviewPanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// Ajout du panel des fréquences
|
||||
contentPanel.add(frequencyTablePanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// Ajout panel des codes
|
||||
contentPanel.add(codeTablePanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// la section du scrollpane
|
||||
JScrollPane scrollPane = new JScrollPane(contentPanel);
|
||||
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.getVerticalScrollBar().setUnitIncrement(16); // scroll plus adouci fluide
|
||||
|
||||
this.add(scrollPane, BorderLayout.CENTER);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Met à jour l’image affichée dans la zone d’aperçu.
|
||||
*
|
||||
* <p>
|
||||
* Cette méthode est appelée lorsque l’image à convertir
|
||||
* a été chargée. La fenêtre ne modifie pas l’image :
|
||||
* elle la transmet simplement au panneau d’aperçu.
|
||||
* </p>
|
||||
*
|
||||
* @param img image à afficher
|
||||
*/
|
||||
public void setImagePreview(BufferedImage img) {
|
||||
imagePreviewPanel.setImage(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des tables de fréquences.
|
||||
*/
|
||||
public void setFrequencyTable(int[] freqR,int[] freqG,int[] freqB) {
|
||||
frequencyTablePanel.updateFrequencies(freqR,freqG,freqB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des codes Huffman.
|
||||
*
|
||||
* <p>
|
||||
* Elle permet uniquement d’afficher les codes
|
||||
* qui ont été produits par la partie traitement.
|
||||
* </p>
|
||||
*/
|
||||
public void setHuffmanTable(Map<Integer, String> codesRouge,
|
||||
Map<Integer, String> codesVert,
|
||||
Map<Integer, String> codesBleu) {
|
||||
codeTablePanel.updateCodes(codesRouge, codesVert, codesBleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des codes canoniques.
|
||||
*
|
||||
* <p>
|
||||
* Les codes canoniques sont transmis au panneau
|
||||
* chargé de leur affichage.
|
||||
* </p>
|
||||
*/
|
||||
public void setCanonicalTable(Map<Integer, String> codesRouge,
|
||||
Map<Integer, String> codesVert,
|
||||
Map<Integer, String> codesBleu) {
|
||||
codeTablePanel.updateCanonicalCodes(codesRouge, codesVert, codesBleu);
|
||||
}
|
||||
|
||||
public void addSaveButton(ConverterController controller) {
|
||||
JButton saveBtn = new JButton("Exporter en .pif");
|
||||
ExportButtonListener ecouteur =new ExportButtonListener(controller);
|
||||
saveBtn.addActionListener(ecouteur);
|
||||
|
||||
// panneau du bas
|
||||
JPanel bottomPanel = new JPanel();
|
||||
bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
|
||||
bottomPanel.add(saveBtn);
|
||||
|
||||
// ajoute au bas de la fenêtre
|
||||
this.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
// rafraîchir l'affichage
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package fr.iutfbleau.sae;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Fenêtre principale du convertisseur.
|
||||
*
|
||||
* <p>
|
||||
* Cette classe correspond à la vue principale de l’application.
|
||||
* Elle centralise l’affichage des informations liées à la conversion
|
||||
* d’une image (aperçu, fréquences, codes).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Elle sert de point d’entrée unique pour la partie graphique
|
||||
* </p>
|
||||
*/
|
||||
public class ConverterWindow extends JFrame {
|
||||
|
||||
private ImagePreviewPanel imagePreviewPanel;
|
||||
private FrequencyTablePanel frequencyTablePanel;
|
||||
private CodeTablePanel codeTablePanel;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Crée la fenêtre principale du convertisseur.
|
||||
*
|
||||
* <p>
|
||||
* Le constructeur initialise la fenêtre et met en place
|
||||
* les différents panneaux graphiques utilisés pour l’affichage.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public ConverterWindow() {
|
||||
// Configuration de la fenetre
|
||||
this.setTitle("Convertisseur PIF - Visualisation des données");
|
||||
this.setSize(900, 600);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setLocationRelativeTo(null); // Centre la fenêtre
|
||||
this.setResizable(true); // on autorise le
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
|
||||
|
||||
// Initialisation des panels
|
||||
this.imagePreviewPanel = new ImagePreviewPanel();
|
||||
this.frequencyTablePanel = new FrequencyTablePanel();
|
||||
this.codeTablePanel = new CodeTablePanel();
|
||||
|
||||
// Je gere le panel principal
|
||||
JPanel contentPanel = new JPanel();
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
|
||||
//contentPanel.setBackground(new Color(255, 0, 0)); // rouge vif pour demo
|
||||
contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
|
||||
// Titre
|
||||
JLabel header = new JLabel(" Convertisseur PIF – Visualisation des données ");
|
||||
header.setFont(new Font("SansSerif", Font.BOLD, 18));
|
||||
header.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
contentPanel.add(header);
|
||||
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5))); // espace
|
||||
|
||||
// Ajout du panel d'aperçu
|
||||
contentPanel.add(imagePreviewPanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// Ajout du panel des fréquences
|
||||
contentPanel.add(frequencyTablePanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// Ajout panel des codes
|
||||
contentPanel.add(codeTablePanel);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
// la section du scrollpane
|
||||
JScrollPane scrollPane = new JScrollPane(contentPanel);
|
||||
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.getVerticalScrollBar().setUnitIncrement(16); // scroll plus adouci fluide
|
||||
|
||||
this.add(scrollPane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Met à jour l’image affichée dans la zone d’aperçu.
|
||||
*
|
||||
* <p>
|
||||
* Cette méthode est appelée lorsque l’image à convertir
|
||||
* a été chargée. La fenêtre ne modifie pas l’image :
|
||||
* elle la transmet simplement au panneau d’aperçu.
|
||||
* </p>
|
||||
*
|
||||
* @param img image à afficher
|
||||
*/
|
||||
public void setImagePreview(BufferedImage img) {
|
||||
imagePreviewPanel.setImage(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des tables de fréquences.
|
||||
*/
|
||||
public void setFrequencyTable(int[] freqR,int[] freqG,int[] freqB) {
|
||||
frequencyTablePanel.updateFrequencies(freqR,freqG,freqB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des codes Huffman.
|
||||
*
|
||||
* <p>
|
||||
* Elle permet uniquement d’afficher les codes
|
||||
* qui ont été produits par la partie traitement.
|
||||
* </p>
|
||||
*/
|
||||
public void setHuffmanTable(Map<Integer, String> codesRouge,
|
||||
Map<Integer, String> codesVert,
|
||||
Map<Integer, String> codesBleu) {
|
||||
codeTablePanel.updateCodes(codesRouge, codesVert, codesBleu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l’affichage des codes canoniques.
|
||||
*
|
||||
* <p>
|
||||
* Les codes canoniques sont transmis au panneau
|
||||
* chargé de leur affichage.
|
||||
* </p>
|
||||
*/
|
||||
public void setCanonicalTable(Map<Integer, String> codesRouge,
|
||||
Map<Integer, String> codesVert,
|
||||
Map<Integer, String> codesBleu) {
|
||||
codeTablePanel.updateCanonicalCodes(codesRouge, codesVert, codesBleu);
|
||||
|
||||
this.setVisible(true); // je limage visible apre avoir tout ajouter
|
||||
}
|
||||
|
||||
public void addSaveButton(ConverterController controller) {
|
||||
JButton saveBtn = new JButton("Exporter en .pif");
|
||||
ExportButtonListener ecouteur =new ExportButtonListener(controller);
|
||||
saveBtn.addActionListener(ecouteur);
|
||||
|
||||
// panneau du bas
|
||||
JPanel bottomPanel = new JPanel();
|
||||
bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
|
||||
bottomPanel.add(saveBtn);
|
||||
|
||||
// ajoute au bas de la fenêtre
|
||||
this.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
// rafraîchir l'affichage
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import fr.iutfbleau.sae.vconverter.ConverterWindow;
|
||||
|
||||
public class Convertisseur {
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -20,6 +18,7 @@ public class Convertisseur {
|
||||
// je la passe au controleur
|
||||
ConverterController controller = new ConverterController(window, inpuPath, outputPath);
|
||||
|
||||
controller.StartconvessionProcess();
|
||||
// je demare le programe de conversion
|
||||
controller.convessionProcess();
|
||||
}
|
||||
}
|
||||
+70
-70
@@ -1,70 +1,70 @@
|
||||
package fr.iutfbleau.sae.vconverter;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
public class FrequencyTablePanel extends JPanel {
|
||||
// 3 Zone de texte pour la fréquence du rouge , du vert et du bleu
|
||||
private JTextArea freqRouge , freqVert , freqBleu;
|
||||
|
||||
public FrequencyTablePanel() {
|
||||
setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
// Premiere étiquette pour les fréquences en géneral
|
||||
JLabel etiquette1 = new JLabel("Frequence");
|
||||
etiquette1.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
super.add(etiquette1);
|
||||
super.add(Box.createVerticalStrut(10));
|
||||
|
||||
|
||||
// Puis création de zone de texte pour le rouge , le vert et le bleu
|
||||
this.freqRouge = creationZoneText("Rouge");
|
||||
this.freqVert = creationZoneText("Vert");
|
||||
this.freqBleu = creationZoneText("Bleu");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private JTextArea creationZoneText(String t) {
|
||||
super.add(new JLabel(t + ":"));
|
||||
GridLayout gestionnaire_mise_en_page = new GridLayout(5,5,10,10);
|
||||
JTextArea zone = new JTextArea(8, 30);
|
||||
zone.setLayout(gestionnaire_mise_en_page);
|
||||
zone.setEditable(false);
|
||||
zone.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
JScrollPane scroll = new JScrollPane(zone);
|
||||
scroll.setPreferredSize(new Dimension(300, 120));
|
||||
add(scroll);
|
||||
add(Box.createVerticalStrut(10));
|
||||
return zone;
|
||||
}
|
||||
|
||||
|
||||
public void updateFrequencies(int[] freqR,int[] freqG,int[] freqB) {
|
||||
mettreAJour(freqRouge,freqR);
|
||||
mettreAJour(freqVert,freqG);
|
||||
mettreAJour(freqBleu,freqB);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void mettreAJour(JTextArea zone,int[] frequence){
|
||||
StringBuilder string = new StringBuilder();
|
||||
|
||||
for(int i = 0 ; i < frequence.length ; i++){
|
||||
string.append(String.format("%3d : %s%n", i, frequence[i]));
|
||||
|
||||
if(i%10 == 0 && i!=0){
|
||||
string.append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
zone.setText(string.toString());
|
||||
}
|
||||
}
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
public class FrequencyTablePanel extends JPanel {
|
||||
// 3 Zone de texte pour la fréquence du rouge , du vert et du bleu
|
||||
private JTextArea freqRouge , freqVert , freqBleu;
|
||||
|
||||
public FrequencyTablePanel() {
|
||||
setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
// Premiere étiquette pour les fréquences en géneral
|
||||
JLabel etiquette1 = new JLabel("Frequence");
|
||||
etiquette1.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||
super.add(etiquette1);
|
||||
super.add(Box.createVerticalStrut(10));
|
||||
|
||||
|
||||
// Puis création de zone de texte pour le rouge , le vert et le bleu
|
||||
this.freqRouge = creationZoneText("Rouge");
|
||||
this.freqVert = creationZoneText("Vert");
|
||||
this.freqBleu = creationZoneText("Bleu");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private JTextArea creationZoneText(String t) {
|
||||
super.add(new JLabel(t + ":"));
|
||||
GridLayout gestionnaire_mise_en_page = new GridLayout(5,5,10,10);
|
||||
JTextArea zone = new JTextArea(8, 30);
|
||||
zone.setLayout(gestionnaire_mise_en_page);
|
||||
zone.setEditable(false);
|
||||
zone.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
JScrollPane scroll = new JScrollPane(zone);
|
||||
scroll.setPreferredSize(new Dimension(300, 120));
|
||||
add(scroll);
|
||||
add(Box.createVerticalStrut(10));
|
||||
return zone;
|
||||
}
|
||||
|
||||
|
||||
public void updateFrequencies(int[] freqR,int[] freqG,int[] freqB) {
|
||||
mettreAJour(freqRouge,freqR);
|
||||
mettreAJour(freqVert,freqG);
|
||||
mettreAJour(freqBleu,freqB);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void mettreAJour(JTextArea zone,int[] frequence){
|
||||
StringBuilder string = new StringBuilder();
|
||||
|
||||
for(int i = 0 ; i < frequence.length ; i++){
|
||||
string.append(String.format("%3d : %s%n", i, frequence[i]));
|
||||
|
||||
if(i%10 == 0 && i!=0){
|
||||
string.append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
zone.setText(string.toString());
|
||||
}
|
||||
}
|
||||
+75
-75
@@ -1,76 +1,76 @@
|
||||
package fr.iutfbleau.sae.vconverter;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.*;
|
||||
/**
|
||||
* Le panneau d’aperçu de l’image.
|
||||
*
|
||||
* <p>
|
||||
* Ce panneau affiche un aperçu de l’image en cours de conversion.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
|
||||
public class ImagePreviewPanel extends JPanel {
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
// je donne une taille préférée au panel
|
||||
public ImagePreviewPanel() {
|
||||
this.setPreferredSize(new Dimension(600, 800));
|
||||
this.setMinimumSize(new Dimension(600, 800));
|
||||
}
|
||||
|
||||
|
||||
public void setImage(BufferedImage img) {
|
||||
this.image = img;
|
||||
repaint();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics pinceau) {
|
||||
// Appel de la méthode parente pour effacer l'arrière-plan
|
||||
super.paintComponent(pinceau);
|
||||
|
||||
if (image == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recuperer les dimensions du panel pour centrer l'image
|
||||
int panelWidth = this.getWidth();
|
||||
int panelHeight = this.getHeight();
|
||||
|
||||
// Recuperer les dimensions de l'image
|
||||
int imgWidth = image.getWidth();
|
||||
int imgHeight = image.getHeight();
|
||||
|
||||
// Je calcule le facteur du reduction (si l'image est trop grande) en gros le dezoom
|
||||
double scale = Math.min(
|
||||
(double) panelWidth / imgWidth,
|
||||
(double) panelHeight / imgHeight
|
||||
);
|
||||
|
||||
// Si l'image est plus petite que le panel, on ne la redimensionne pas donc scale = 1
|
||||
if (scale > 1.0) {
|
||||
scale = 1.0;
|
||||
}
|
||||
|
||||
// je recalcule les dimensions de l'image à dessiner
|
||||
int drawWidth = (int) (imgWidth * scale);
|
||||
int drawHeight = (int) (imgHeight * scale);
|
||||
|
||||
// Centrage de l'image dans le panel
|
||||
int x = (panelWidth - drawWidth) / 2;
|
||||
int y = (panelHeight - drawHeight) / 2;
|
||||
|
||||
Graphics2D pinceau2D = (Graphics2D) pinceau;
|
||||
pinceau2D.setRenderingHint(
|
||||
RenderingHints.KEY_INTERPOLATION,
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR
|
||||
);
|
||||
|
||||
pinceau2D.drawImage(image, x, y, drawWidth, drawHeight, this);
|
||||
}
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.JPanel;
|
||||
/**
|
||||
* Le panneau d’aperçu de l’image.
|
||||
*
|
||||
* <p>
|
||||
* Ce panneau affiche un aperçu de l’image en cours de conversion.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
|
||||
public class ImagePreviewPanel extends JPanel {
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
// je donne une taille préférée au panel
|
||||
public ImagePreviewPanel() {
|
||||
this.setPreferredSize(new Dimension(600, 800));
|
||||
this.setMinimumSize(new Dimension(600, 800));
|
||||
}
|
||||
|
||||
|
||||
public void setImage(BufferedImage img) {
|
||||
this.image = img;
|
||||
repaint();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics pinceau) {
|
||||
// Appel de la méthode parente pour effacer l'arrière-plan
|
||||
super.paintComponent(pinceau);
|
||||
|
||||
if (image == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recuperer les dimensions du panel pour centrer l'image
|
||||
int panelWidth = this.getWidth();
|
||||
int panelHeight = this.getHeight();
|
||||
|
||||
// Recuperer les dimensions de l'image
|
||||
int imgWidth = image.getWidth();
|
||||
int imgHeight = image.getHeight();
|
||||
|
||||
// Je calcule le facteur du reduction (si l'image est trop grande) en gros le dezoom
|
||||
double scale = Math.min(
|
||||
(double) panelWidth / imgWidth,
|
||||
(double) panelHeight / imgHeight
|
||||
);
|
||||
|
||||
// Si l'image est plus petite que le panel, on ne la redimensionne pas donc scale = 1
|
||||
if (scale > 1.0) {
|
||||
scale = 1.0;
|
||||
}
|
||||
|
||||
// je recalcule les dimensions de l'image à dessiner
|
||||
int drawWidth = (int) (imgWidth * scale);
|
||||
int drawHeight = (int) (imgHeight * scale);
|
||||
|
||||
// Centrage de l'image dans le panel
|
||||
int x = (panelWidth - drawWidth) / 2;
|
||||
int y = (panelHeight - drawHeight) / 2;
|
||||
|
||||
Graphics2D pinceau2D = (Graphics2D) pinceau;
|
||||
pinceau2D.setRenderingHint(
|
||||
RenderingHints.KEY_INTERPOLATION,
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR
|
||||
);
|
||||
|
||||
pinceau2D.drawImage(image, x, y, drawWidth, drawHeight, this);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,20 @@
|
||||
<<<<<<< HEAD
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
public class Viewer {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("dqkdjqkdjqkdjqkdjqkdj");
|
||||
}
|
||||
}
|
||||
=======
|
||||
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
//teste avec ia
|
||||
private void chargerFichier() {
|
||||
JTextArea zoneTexte = new JTextArea();
|
||||
zoneTexte.setEditable(false);
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(fichierPif))) {
|
||||
String ligne;
|
||||
while ((ligne = br.readLine()) != null) {
|
||||
zoneTexte.append(ligne + "\n");
|
||||
public class Viewer {
|
||||
public static void main(String[] args) {
|
||||
// chemins de l'image
|
||||
String inpuPath = null;
|
||||
if (args.length >= 1) {
|
||||
inpuPath = args[0];
|
||||
}
|
||||
} catch (IOException e) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Erreur lors de l'ouverture du fichier",
|
||||
"Erreur",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
add(new JScrollPane(zoneTexte), BorderLayout.CENTER);
|
||||
setVisible(true);
|
||||
ViewerWindow fen = new ViewerWindow();
|
||||
ViewerControleur controleur = new ViewerControleur(fen,inpuPath);
|
||||
|
||||
|
||||
controleur.loadPIF();
|
||||
|
||||
}
|
||||
}
|
||||
>>>>>>> 40f71dddd52fc07edc1d47d48d56fd65a2a79fe3
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import fr.iutfbleau.sae.mpif.PIFReader;
|
||||
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 javax.swing.JFileChooser;
|
||||
|
||||
public class ViewerControleur {
|
||||
|
||||
private RGBImage image; // L'image à décoder
|
||||
private ViewerWindow window; // La fenêtre du visualiseur
|
||||
private File file;
|
||||
|
||||
public ViewerControleur(ViewerWindow window, String path) {
|
||||
this.window = window;
|
||||
if (path != null) {
|
||||
this.file = new File(path);
|
||||
} else {
|
||||
this.file = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void loadPIF() {
|
||||
File fichierPIF;
|
||||
// Déterminer si on le charge avec jFilechoose ou pas
|
||||
if (this.file != null) {
|
||||
// Fichier fourni en argument
|
||||
fichierPIF = this.file;
|
||||
} else {
|
||||
// Demander à l'utilisateur via JFileChooser
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setDialogTitle("Choisissez un fichier PIF");
|
||||
|
||||
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
fichierPIF = chooser.getSelectedFile();
|
||||
} else {
|
||||
GestionErreur.afficherErreur("Aucun fichier sélectionné. Arrêt du programme.");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// je Vérifi la conformiter du fichier avec isPIFFile
|
||||
if (!PIFReader.isPIFFile(fichierPIF)) {
|
||||
GestionErreur.afficherErreur("Le fichier fourni n'est pas au format PIF (.pif)");
|
||||
return;
|
||||
}
|
||||
|
||||
// je Charge et décoder le fichier PIF
|
||||
try {
|
||||
PIFReader lecteur = new PIFReader();
|
||||
this.image = lecteur.decodePifFile(fichierPIF);
|
||||
|
||||
System.out.println("Image décodée : " + this.image.getWidth() + "x" + this.image.getHeight());
|
||||
|
||||
// je convertit RGBImage en BufferedImage
|
||||
BufferedImage buffImg = convertToBufferedImage(this.image);
|
||||
|
||||
// j'affiche l'image
|
||||
this.window.displayImage(buffImg);
|
||||
|
||||
} catch (Exception e) {
|
||||
GestionErreur.afficherErreur("Erreur lors du chargement du fichier PIF : ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit une RGBImage en BufferedImage.
|
||||
*
|
||||
* @param rgbImage l'image à convertir
|
||||
* @return l'image convertie
|
||||
*/
|
||||
private BufferedImage convertToBufferedImage(RGBImage rgbImage) {
|
||||
int width = rgbImage.getWidth();
|
||||
int height = rgbImage.getHeight();
|
||||
|
||||
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// Copier tous les pixels
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
Pixel pixel = rgbImage.getPixel(x, y);
|
||||
|
||||
// Composer la couleur RGB la couleur est coder sur 32 bit argb chacun a 8 bit
|
||||
int rgb = (pixel.getR() << 16) | (pixel.getG() << 8) | pixel.getB();
|
||||
|
||||
// Définir le pixel dans le BufferedImage
|
||||
buffImg.setRGB(x, y, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
return buffImg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package fr.iutfbleau.sae;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.*;
|
||||
|
||||
public class ViewerWindow extends JFrame implements MouseListener, MouseMotionListener {
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
private int offsetX = 0;
|
||||
private int offsetY = 0;
|
||||
|
||||
private int lastX;
|
||||
private int lastY;
|
||||
|
||||
public ViewerWindow() {
|
||||
super("PIF Viewer");
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setResizable(true);
|
||||
this.addMouseListener(this);
|
||||
this.addMouseMotionListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void displayImage(BufferedImage img) {
|
||||
this.image = img;
|
||||
|
||||
// je prend la taille de l'ecran
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
// je prend una taille de 90% pour etre raisonable
|
||||
int maxW = (int)(screen.width * 0.9);
|
||||
int maxH = (int)(screen.height * 0.9);
|
||||
|
||||
int w = Math.min(img.getWidth(), maxW);
|
||||
int h = Math.min(img.getHeight(), maxH);
|
||||
|
||||
this.setSize(w, h);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
|
||||
super.paint(g);
|
||||
|
||||
if (image == null) return;
|
||||
|
||||
int panelW = getWidth();
|
||||
int panelH = getHeight();
|
||||
|
||||
int imgW = image.getWidth();
|
||||
int imgH = image.getHeight();
|
||||
|
||||
int drawX = offsetX;
|
||||
int drawY = offsetY;
|
||||
|
||||
// centrage automatique si image plus petite
|
||||
if (imgW < panelW) drawX = (panelW - imgW) / 2;
|
||||
if (imgH < panelH) drawY = (panelH - imgH) / 2;
|
||||
|
||||
g.drawImage(image, drawX, drawY, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
lastX = e.getX();
|
||||
lastY = e.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
offsetX += e.getX() - lastX;
|
||||
offsetY += e.getY() - lastY;
|
||||
|
||||
lastX = e.getX();
|
||||
lastY = e.getY();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override public void mouseReleased(MouseEvent e) {}
|
||||
@Override public void mouseClicked(MouseEvent e) {}
|
||||
@Override public void mouseEntered(MouseEvent e) {}
|
||||
@Override public void mouseExited(MouseEvent e) {}
|
||||
@Override public void mouseMoved(MouseEvent e) {}
|
||||
}
|
||||
@@ -16,13 +16,7 @@ public class CanonicalCode{
|
||||
List<Map.Entry<Integer, String>> liste = new ArrayList<>(codesHuffman.entrySet());
|
||||
|
||||
// ici on comparer par longueur de la valeur ou sinon par la clé
|
||||
|
||||
|
||||
|
||||
Collections.sort(liste, new ComparateurCanonique());
|
||||
|
||||
|
||||
|
||||
Map<Integer,String> canonicalCodes = new HashMap<>();
|
||||
int code = 0; // code canonique à attribuer
|
||||
int temp = 0; //garde la longueur du code précedent , pour gérer le décalage
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package fr.iutfbleau.sae.mhuffman;
|
||||
import fr.iutfbleau.sae.mimage.Pixel;
|
||||
import fr.iutfbleau.sae.mimage.RGBImage;
|
||||
import fr.iutfbleau.sae.mpif.Pixel;
|
||||
import fr.iutfbleau.sae.mpif.RGBImage;
|
||||
|
||||
/**
|
||||
* Représente une table de fréquences pour une image RGB.
|
||||
@@ -33,13 +33,13 @@ import fr.iutfbleau.sae.mimage.RGBImage;
|
||||
public class FrequencyTable {
|
||||
|
||||
/** Tableau des fréquences pour la composante rouge (valeurs de 0 à 255). */
|
||||
private int[] freqR;
|
||||
private final int[] freqR;
|
||||
|
||||
/** Tableau des fréquences pour la composante verte (valeurs de 0 à 255). */
|
||||
private int[] freqG;
|
||||
private final int[] freqG;
|
||||
|
||||
/** Tableau des fréquences pour la composante bleue (valeurs de 0 à 255). */
|
||||
private int[] freqB;
|
||||
private final int[] freqB;
|
||||
|
||||
/**
|
||||
* Construit une table de fréquences vide.
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
// test
|
||||
import fr.iutfbleau.sae.util.HuffmanNode;
|
||||
|
||||
/**
|
||||
* Implémente un arbre de Huffman utilisé pour la compression de données.
|
||||
@@ -59,14 +59,7 @@ public class HuffmanTree {
|
||||
*/
|
||||
// j'ai retirer le static car chaque arbre a ses propres codes et j'utilise string plutot que int pour stocker les codes car on construit une chaine de 0 et de 1
|
||||
private Map<Integer, String> codes;
|
||||
|
||||
|
||||
/**
|
||||
* Chaine de caracteres qui va nous permettre de sauvegader le code Huffman
|
||||
* Permet en d'autres termes de construire la chaine de 1 et de 0
|
||||
*/
|
||||
|
||||
private String chaineCarac;
|
||||
|
||||
/**
|
||||
* Construit un arbre de Huffman.
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package fr.iutfbleau.sae.mpif;
|
||||
import fr.iutfbleau.sae.mimage.RGBImage;
|
||||
import fr.iutfbleau.sae.util.BitInputStream;
|
||||
|
||||
import fr.iutfbleau.sae.util.BitInputStream;
|
||||
import fr.iutfbleau.sae.util.DecodeNode;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -15,73 +20,250 @@ public class PIFReader {
|
||||
private int[] lenG;
|
||||
private int[] lenB;
|
||||
|
||||
public RGBImage read(String filepath)
|
||||
throws Exception {
|
||||
|
||||
// j'Utilise d'un BufferedInputStream pour une meilleure performance
|
||||
FileInputStream fis = new FileInputStream(filepath);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
BitInputStream lecteur = new BitInputStream(bis);
|
||||
/**
|
||||
* Lit et décode un fichier PIF.
|
||||
*
|
||||
* @param filepath chemin du fichier PIF
|
||||
* @return l'image RGB décodée
|
||||
* @throws Exception si erreur de lecture
|
||||
*/
|
||||
public RGBImage decodePifFile(File file) throws Exception {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
BufferedInputStream bos = new BufferedInputStream(fis);
|
||||
BitInputStream lecteur = new BitInputStream(bos);
|
||||
|
||||
// je lis l'entête et les tables canoniques
|
||||
// Je lis l'en-tête et les tables canoniques
|
||||
this.readHeader(lecteur);
|
||||
this.readCanonicalTables(lecteur);
|
||||
|
||||
// je reconstructe les tables canoniques car dans le fichier on a juste les longueurs en bits
|
||||
// Je reconstruis les tables canoniques car dans le fichier on a juste les longueurs en bits
|
||||
Map<String, Integer> canonR = rebuildCanonical(lenR);
|
||||
Map<String, Integer> canonG = rebuildCanonical(lenG);
|
||||
Map<String, Integer> canonB = rebuildCanonical(lenB);
|
||||
|
||||
// Je construis les arbres de décodage
|
||||
DecodeNode trieR = buildDecodageTree(canonR);
|
||||
DecodeNode trieG = buildDecodageTree(canonG);
|
||||
DecodeNode trieB = buildDecodageTree(canonB);
|
||||
|
||||
// Je décode les pixels
|
||||
RGBImage img = decodePixels(lecteur, trieR, trieG, trieB);
|
||||
|
||||
lecteur.closeFlux();
|
||||
System.out.println("Fichier PIF lu avec succès : " + width + "x" + height);
|
||||
return img;
|
||||
}
|
||||
|
||||
public void readHeader(BitInputStream in) {
|
||||
|
||||
// La largeur et l'hauteur de l'image occupe chaqun deux octets soit 16 bits :
|
||||
|
||||
/**
|
||||
* Lit l'en-tête du fichier PIF (largeur et hauteur sur 16 bits chacune).
|
||||
* @throws IOException si erreur de lecture
|
||||
*/
|
||||
public void readHeader(BitInputStream in) throws IOException {
|
||||
this.width = in.readBits(16);
|
||||
this.height = in.readBits(16);
|
||||
System.out.println("Dimensions lues : " + this.width + "x" + this.height);
|
||||
}
|
||||
|
||||
public void readCanonicalTables(BitInputStream in) {
|
||||
this.lenR = new int[256];
|
||||
this.lenG = new int[256];
|
||||
this.lenB = new int[256];
|
||||
|
||||
/**
|
||||
* Lit les trois tables de longueurs (R, G, B).
|
||||
* Chaque table contient 256 valeurs sur 5 bits.
|
||||
* @throws IOException si erreur de lecture
|
||||
*/
|
||||
public void readCanonicalTables(BitInputStream in) throws IOException {
|
||||
// Table Rouge
|
||||
this.lenR = new int[256];
|
||||
for (int i = 0; i < 256; i++){
|
||||
lenR[i] = in.readBits(8);
|
||||
this.lenR[i] = in.readBits(8);
|
||||
}
|
||||
for (int j = 0; j < 256; j++){
|
||||
lenG[j] = in.readBits(8);
|
||||
|
||||
// Table Vert
|
||||
this.lenG = new int[256];
|
||||
for (int i = 0; i < 256; i++){
|
||||
this.lenG[i] = in.readBits(8);
|
||||
}
|
||||
|
||||
// Table Bleu
|
||||
this.lenB = new int[256];
|
||||
for (int i = 0; i < 256; i++){
|
||||
this.lenB[i] = in.readBits(8);
|
||||
}
|
||||
|
||||
System.out.println("Tables de longueurs lues");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstruit les codes canoniques à partir des longueurs.
|
||||
*
|
||||
* @param lengths tableau de 256 longueurs
|
||||
* @return Map<code, symbole> pour le décodage
|
||||
*/
|
||||
public Map<String, Integer> rebuildCanonical(int[] lengths) {
|
||||
// je cree une liste de paires (symbole, longueur)
|
||||
List<Map.Entry<Integer, Integer>> entiers = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < lengths.length; i++) {
|
||||
if (lengths[i] > 0) {
|
||||
entiers.add(new java.util.AbstractMap.SimpleEntry<>(i, lengths[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Je trie par longueur croissante, puis par symbole croissant
|
||||
entiers.sort((a, b) -> {
|
||||
int cmp = a.getValue().compareTo(b.getValue());
|
||||
if (cmp != 0) return cmp;
|
||||
return a.getKey().compareTo(b.getKey());
|
||||
});
|
||||
|
||||
// je genere les codes canoniques
|
||||
Map<String, Integer> codes = new HashMap<>();
|
||||
int code = 0;
|
||||
int previousLength = 0;
|
||||
|
||||
for (Map.Entry<Integer, Integer> entry : entiers) {
|
||||
int symbol = entry.getKey();
|
||||
int length = entry.getValue();
|
||||
|
||||
// Decalage pour aligner le code sur la longueur courante
|
||||
code <<= (length - previousLength);
|
||||
|
||||
// je convertit ce code en texte binaire
|
||||
String codeStr = Integer.toBinaryString(code);
|
||||
// On s'assure que la chaîne a la bonne longueur en ajoutant des zéros à gauche si nécessaire
|
||||
while (codeStr.length() < length) {
|
||||
codeStr = "0" + codeStr;
|
||||
}
|
||||
// je restocke le code + symbole en inversant car la map est inverse dans l'encodage
|
||||
codes.put(codeStr, symbol);
|
||||
|
||||
code++;
|
||||
previousLength = length;
|
||||
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construit l'arbre de décodage à partir des codes canoniques.
|
||||
*
|
||||
* @param codes Map<String (code binaire), symbole> les codes canoniques avec les bits comme clés et les symboles comme valeurs
|
||||
* @return la racine de l'arbre de décodage
|
||||
*/
|
||||
public DecodeNode buildDecodageTree(Map<String,Integer> codes) {
|
||||
DecodeNode root = new DecodeNode(); // la racine de larbre
|
||||
|
||||
for (Map.Entry<String, Integer> entry : codes.entrySet()) {
|
||||
String code = entry.getKey(); // 101011101110 par exemple
|
||||
int symbol = entry.getValue(); // 0,1,2,3 etc. par exemple
|
||||
|
||||
DecodeNode current = root;
|
||||
|
||||
// je parcours le code bit à bit
|
||||
for (int i = 0; i < code.length(); i++) {
|
||||
char bit = code.charAt(i);
|
||||
|
||||
if(i == code.length() - 1) {
|
||||
// Dernier bit: je cree une feuille avec la valeur du symbol
|
||||
if(bit == '0') {
|
||||
current.left = new DecodeNode(null, null, symbol);
|
||||
} else {
|
||||
current.right = new DecodeNode(null, null, symbol);
|
||||
}
|
||||
} else {
|
||||
// Si c'est pas le dernier bit : je creer un node interne
|
||||
if(bit == '0') {
|
||||
if(current.left == null) {
|
||||
current.left = new DecodeNode(); // Node interne
|
||||
}
|
||||
current = current.left;
|
||||
} else {
|
||||
if(current.right == null) {
|
||||
current.right = new DecodeNode(); // node intern
|
||||
}
|
||||
current = current.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Décode les pixels à partir des arbres de décodage.
|
||||
*
|
||||
* @param in flux d'entrée binaire
|
||||
* @param red arbre de décodage pour la composante rouge
|
||||
* @param green arbre de décodage pour la composante verte
|
||||
* @param blue arbre de décodage pour la composante bleue
|
||||
* @return l'image reconstruite
|
||||
*/
|
||||
public RGBImage decodePixels(BitInputStream in, DecodeNode red, DecodeNode green, DecodeNode blue) throws IOException{
|
||||
RGBImage image = new RGBImage(width, height);
|
||||
|
||||
for(int y = 0; y < height; y++) {
|
||||
for(int x = 0; x < width; x++) {
|
||||
// je decode chaque composante en parcourant son arbre
|
||||
int r = decodeSymbole(in, red);
|
||||
int g = decodeSymbole(in, green);
|
||||
int b = decodeSymbole(in, blue);
|
||||
|
||||
// je cree et je place le pixel
|
||||
Pixel pixel = new Pixel(r, g, b);
|
||||
image.setPixel(x, y, pixel);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Décode un symbole en parcourant l'arbre bit par bit
|
||||
* @param in le flux d'entrée binaire
|
||||
* @param root la racine de l'arbre de décodage
|
||||
* @return le symbole décodé (valeur entre 0 et 255)
|
||||
* @throws IOException si une erreur d'entrée/sortie se produit
|
||||
*/
|
||||
private int decodeSymbole(BitInputStream in, DecodeNode root) throws IOException {
|
||||
DecodeNode current = root;
|
||||
|
||||
// je parcours l'arbre en suivant les bits du flux jusqu'à atteindre une feuille
|
||||
while (!current.isLeaf()) {
|
||||
int bit = in.readBit();
|
||||
if (bit == 0) {
|
||||
current = current.left;
|
||||
} else {
|
||||
current = current.right;
|
||||
}
|
||||
|
||||
if (current == null) {
|
||||
throw new IOException("code invalide: noeud null rencontre");
|
||||
}
|
||||
}
|
||||
// si on est arrivé à une feuille, on retourne la valeur
|
||||
if (current.value == -1) {
|
||||
throw new IOException("Feuille sans valeur assignée");
|
||||
}
|
||||
return current.value;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isPIFFile(File f) {
|
||||
if (f == null){
|
||||
return false;
|
||||
}
|
||||
if (!f.exists() || !f.isFile()){
|
||||
return false;
|
||||
}
|
||||
|
||||
//je verifi l'extension
|
||||
String name = f.getName().toLowerCase();
|
||||
if (!name.endsWith(".pif")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 256; k++){
|
||||
lenB[k] = in.readBits(8);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,Integer> rebuildCanonical(int[] lengths) {
|
||||
// TODO: Implement canonical table reconstruction
|
||||
return null;
|
||||
return f.length() >= 772; // taille minimal pour un fichier pif longueur largeur et tables de frequance
|
||||
}
|
||||
|
||||
public RGBImage decodePixels(BitInputStream in, DecodeNode red, DecodeNode green, DecodeNode blue) {
|
||||
// TODO: Implement pixel decoding
|
||||
return null;
|
||||
}
|
||||
|
||||
public DecodeNode buildDecodageTree(Map<String,Integer> codes) {
|
||||
// TODO: Implement trie building
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
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;
|
||||
@@ -31,17 +29,15 @@ public class PIFWriter {
|
||||
encodePixels(ecriveur, image, canonR, canonG, canonB);
|
||||
|
||||
ecriveur.fermerFlux();
|
||||
|
||||
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) {
|
||||
try {
|
||||
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");
|
||||
out.writeBits(width, 16);
|
||||
out.writeBits(height, 16);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Erreur lors de l'écriture de l'en-tête du fichier PIF: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,31 +78,6 @@ public class PIFWriter {
|
||||
} catch (IOException e) {
|
||||
System.err.println("Erreur lors de l'écriture des tables de fréquences dans le fichier PIF");
|
||||
}
|
||||
|
||||
|
||||
// Debug pour compter les symboles utilisés et calculer les longueurs moyennes
|
||||
int totalBitsR = 0, totalBitsG = 0, totalBitsB = 0;
|
||||
int countR = 0, countG = 0, countB = 0;
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (canonR.containsKey(i)) {
|
||||
totalBitsR += canonR.get(i).length();
|
||||
countR++;
|
||||
}
|
||||
if (canonG.containsKey(i)) {
|
||||
totalBitsG += canonG.get(i).length();
|
||||
countG++;
|
||||
}
|
||||
if (canonB.containsKey(i)) {
|
||||
totalBitsB += canonB.get(i).length();
|
||||
countB++;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Longueur moyenne Rouge : " + (totalBitsR / (double)countR));
|
||||
System.out.println("Longueur moyenne Vert : " + (totalBitsG / (double)countG));
|
||||
System.out.println("Longueur moyenne Bleu : " + (totalBitsB / (double)countB));
|
||||
System.out.println("Symboles utilisés - R:" + countR + " G:" + countG + " B:" + countB);
|
||||
}
|
||||
|
||||
// Méthode pour encoder les pixels de l'image en utilisant les codes canoniques
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
package fr.iutfbleau.sae.mimage;
|
||||
|
||||
public class Pixel{
|
||||
private int r;
|
||||
private int g;
|
||||
private int b;
|
||||
|
||||
//à completer
|
||||
public Pixel(int red, int green, int blue){
|
||||
this.r=red;
|
||||
this.g=green;
|
||||
this.b=blue;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public int getG() {
|
||||
return g;
|
||||
}
|
||||
|
||||
public int getR() {
|
||||
return r;
|
||||
}
|
||||
|
||||
public void setR(int r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public void setB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public void setG(int g) {
|
||||
this.g = g;
|
||||
}
|
||||
package fr.iutfbleau.sae.mpif;
|
||||
|
||||
public class Pixel{
|
||||
private int r;
|
||||
private int g;
|
||||
private int b;
|
||||
|
||||
//à completer
|
||||
public Pixel(int red, int green, int blue){
|
||||
this.r=red;
|
||||
this.g=green;
|
||||
this.b=blue;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public int getG() {
|
||||
return g;
|
||||
}
|
||||
|
||||
public int getR() {
|
||||
return r;
|
||||
}
|
||||
|
||||
public void setR(int r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public void setB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public void setG(int g) {
|
||||
this.g = g;
|
||||
}
|
||||
}
|
||||
+30
-29
@@ -1,30 +1,31 @@
|
||||
package fr.iutfbleau.sae.mimage;
|
||||
|
||||
public class RGBImage {
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private Pixel [][] pixels;
|
||||
|
||||
public RGBImage (int lar, int haut){
|
||||
this.width=lar;
|
||||
this.height=haut;
|
||||
this.pixels = new Pixel[this.width][this.height];
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setPixel(int x, int y, Pixel p) {
|
||||
this.pixels[x][y] = p;
|
||||
}
|
||||
|
||||
public Pixel getPixel(int x, int y) {
|
||||
return this.pixels[x][y];
|
||||
}
|
||||
package fr.iutfbleau.sae.mpif;
|
||||
|
||||
public class RGBImage {
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private Pixel [][] pixels;
|
||||
|
||||
public RGBImage (int lar, int haut){
|
||||
this.width=lar;
|
||||
this.height=haut;
|
||||
this.pixels = new Pixel[this.width][this.height];
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setPixel(int x, int y, Pixel p) {
|
||||
this.pixels[x][y] = p;
|
||||
}
|
||||
|
||||
public Pixel getPixel(int x, int y) {
|
||||
return this.pixels[x][y];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
/**
|
||||
* Classe utilitaire regroupant des opérations de conversion entre
|
||||
* entiers et octets.
|
||||
* <p>
|
||||
* Elle est utilisée pour encoder et décoder les champs binaires
|
||||
* du format PIF (largeur, hauteur, tailles, etc.).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Cette classe :
|
||||
* <ul>
|
||||
* <li>ne lit aucun fichier</li>
|
||||
* <li>n'écrit aucun fichier</li>
|
||||
* <li>ne manipule pas les bits individuellement</li>
|
||||
* </ul>
|
||||
* Elle fournit uniquement des conversions octets ↔ entiers.
|
||||
* </p>
|
||||
*/
|
||||
public final class ByteUtils {
|
||||
|
||||
/**
|
||||
* Constructeur privé empêchant l'instanciation.
|
||||
* <p>
|
||||
* Cette classe est purement utilitaire et ne doit pas être instanciée.
|
||||
* </p>
|
||||
*/
|
||||
private ByteUtils() {
|
||||
// j'empêche l'instanciation
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit un entier non négatif en deux octets (ordre big-endian).
|
||||
* <p>
|
||||
* L'octet de poids fort est placé en première position,
|
||||
* suivi de l'octet de poids faible.
|
||||
* </p>
|
||||
*
|
||||
* @param value valeur entière à convertir (0 ≤ value ≤ 65535)
|
||||
* @return tableau de deux octets : [octetFort, octetFaible] M
|
||||
* @throws IllegalArgumentException si la valeur ne tient pas sur 2 octets
|
||||
*/
|
||||
public static byte[] toBytes(int value) {
|
||||
if (value < 0 || value > 0xFFFF) {
|
||||
throw new IllegalArgumentException(
|
||||
"La valeur doit être comprise entre 0 et 65535"
|
||||
);
|
||||
}
|
||||
|
||||
byte[] result = new byte[2];
|
||||
|
||||
/*
|
||||
* Extraction de l'octet de poids fort :
|
||||
* - décalage de 8 bits vers la droite
|
||||
* - masquage pour ne conserver que les 8 bits utiles
|
||||
*/
|
||||
result[0] = (byte) ((value >>> 8) & 0xFF);
|
||||
|
||||
/*
|
||||
* Extraction de l'octet de poids faible :
|
||||
* - aucun décalage nécessaire
|
||||
* - masquage pour conserver les 8 bits de droite
|
||||
*/
|
||||
result[1] = (byte) (value & 0xFF);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstruit un entier à partir de deux octets (ordre big-endian).
|
||||
* <p>
|
||||
* L'octet de poids fort est replacé dans les bits 15 à 8,
|
||||
* puis combiné avec l'octet de poids faible.
|
||||
* </p>
|
||||
*
|
||||
* @param high octet de poids fort
|
||||
* @param low octet de poids faible
|
||||
* @return entier reconstruit à partir des deux octets
|
||||
*/
|
||||
public static int toInt(byte high, byte low) {
|
||||
/*
|
||||
* - masquage pour supprimer le signe des octets Java
|
||||
* - décalage de l'octet fort vers la gauche
|
||||
* - combinaison des deux octets par un OU binaire
|
||||
*/
|
||||
return ((high & 0xFF) << 8) | (low & 0xFF);
|
||||
}
|
||||
}
|
||||
+23
-23
@@ -1,23 +1,23 @@
|
||||
package fr.iutfbleau.sae.mpif;
|
||||
|
||||
public class DecodeNode {
|
||||
public DecodeNode left;
|
||||
public DecodeNode right;
|
||||
public Integer value; // null si pas une feuille
|
||||
|
||||
public DecodeNode() {
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
public DecodeNode(DecodeNode left, DecodeNode right, Integer value) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isLeaf() {
|
||||
return this.left == null && this.right == null;
|
||||
}
|
||||
}
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
public class DecodeNode {
|
||||
public DecodeNode left;
|
||||
public DecodeNode right;
|
||||
public Integer value; // null si pas une feuille
|
||||
|
||||
public DecodeNode() {
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
this.value = -1; // valeur non initialisée
|
||||
}
|
||||
|
||||
public DecodeNode(DecodeNode left, DecodeNode right, Integer value) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isLeaf() {
|
||||
return this.left == null && this.right == null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
public class GestErreur {
|
||||
public static void erreur(String message) {
|
||||
System.err.println("Erreur : " + message);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package fr.iutfbleau.sae.util;
|
||||
import javax.swing.*;
|
||||
|
||||
public class GestionErreur {
|
||||
public static void afficherErreur(String message) {
|
||||
JOptionPane.showMessageDialog(null, message, "Erreur", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public static void afficherInfo(String message) {
|
||||
JOptionPane.showMessageDialog(null, message, "Information", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package fr.iutfbleau.sae.mhuffman;
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
/**
|
||||
* Représente un nœud de l'arbre de Huffman.
|
||||
@@ -1,7 +0,0 @@
|
||||
package fr.iutfbleau.sae.vviewer;
|
||||
|
||||
public class ImagePanel extends JPanel{
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package fr.iutfbleau.sae.vviewer;
|
||||
|
||||
public class ViewerWindow extends JFrame{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user