piffffff
@@ -120,8 +120,8 @@ Objectif : Lecture du fichier `.pif` + visualisateur opérationnel
|
|||||||
|
|
||||||
| US | Assigné | Statut | | Description |
|
| US | Assigné | Statut | | Description |
|
||||||
|----------|---------|--------|-----|-------------|
|
|----------|---------|--------|-----|-------------|
|
||||||
| US-D7 | AD | TODO | 🟥 | Reconstruire les codes canoniques depuis fichier |
|
| US-D7 | AD | DONE | 🟩 | Reconstruire les codes canoniques depuis fichier |
|
||||||
| US-D8 | AD | TODO | 🟥 | Décoder pixels (implémenter PIFReader) |
|
| US-D8 | AD | DONE | 🟩 | Décoder pixels (implémenter PIFReader) |
|
||||||
| US-U1 | YB | TODO | 🟥 | Ouvrir `.pif` via argument ou JFileChooser |
|
| US-U1 | YB | TODO | 🟥 | Ouvrir `.pif` via argument ou JFileChooser |
|
||||||
| US-U2 | AA | TODO | 🟥 | Afficher l’image dans une fenêtre |
|
| US-U2 | AA | TODO | 🟥 | Afficher l’image dans une fenêtre |
|
||||||
| US-U3 | AA | TODO | 🟥 | Centrer l’image si elle est petite |
|
| US-U3 | AA | TODO | 🟥 | Centrer l’image si elle est petite |
|
||||||
@@ -130,19 +130,22 @@ Objectif : Lecture du fichier `.pif` + visualisateur opérationnel
|
|||||||
|
|
||||||
## Fichiers à créer – Sprint 3
|
## Fichiers à créer – Sprint 3
|
||||||
|
|
||||||
## Fichiers à créer – Sprint 2
|
|
||||||
|
|
||||||
### `src/mpif/`
|
### `src/mpif/`
|
||||||
| Nom du fichier | Rôle | US |
|
| Nom du fichier | Rôle | US |
|
||||||
|----------------|-------|----|
|
|----------------|-------|----|
|
||||||
| `PIFWriter.java` | Écriture du fichier `.pif` | US-C5, US-U6 |
|
| `PIFReader.java` | Lecture et décodage du `.pif` | US-D7, US-D8 |
|
||||||
|
|
||||||
### `src/vconverter/` (complément)
|
### `src/vviewer/`
|
||||||
| Nom du fichier | Rôle | US |
|
| Nom du fichier | Rôle | US |
|
||||||
|----------------|-------|----|
|
|----------------|-------|----|
|
||||||
| `SavePanel.java` *(optionnel)* | Interface de sauvegarde `.pif` | US-U6 |
|
| `ViewerWindow.java` | Fenêtre visualisation | US-U2 |
|
||||||
|
| `ImagePanel.java` | Affichage + déplacement image | US-U2, US-U3, US-U4 |
|
||||||
|
|
||||||
|
### `src/`
|
||||||
|
| Nom du fichier | Rôle | US |
|
||||||
|
|----------------|-------|----|
|
||||||
|
| `ViewerController.java` | Contrôle du visualisateur | US-U1..U4 |
|
||||||
|
| `Viewer.java` | Programme principal du visualisateur | US-U1 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
@startuml
|
|
||||||
skinparam packageStyle rectangle
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' MODEL (bleu)
|
|
||||||
' ============================
|
|
||||||
package mimage {
|
|
||||||
class Pixel #aliceblue
|
|
||||||
class RGBImage #aliceblue
|
|
||||||
}
|
|
||||||
|
|
||||||
RGBImage *-- Pixel
|
|
||||||
|
|
||||||
package mhuffman {
|
|
||||||
class FrequencyTable #aliceblue
|
|
||||||
class HuffmanNode #aliceblue
|
|
||||||
class HuffmanTree #aliceblue
|
|
||||||
class CanonicalCode #aliceblue
|
|
||||||
}
|
|
||||||
|
|
||||||
HuffmanTree *-- HuffmanNode
|
|
||||||
FrequencyTable ..> RGBImage
|
|
||||||
CanonicalCode ..> HuffmanTree
|
|
||||||
|
|
||||||
package util {
|
|
||||||
class BitInputStream #aliceblue
|
|
||||||
class BitOutputStream #aliceblue
|
|
||||||
class ByteUtils #aliceblue
|
|
||||||
class FileUtils #aliceblue
|
|
||||||
}
|
|
||||||
|
|
||||||
package mpif {
|
|
||||||
class PIFWriter #aliceblue
|
|
||||||
}
|
|
||||||
|
|
||||||
PIFWriter ..> RGBImage
|
|
||||||
PIFWriter ..> CanonicalCode
|
|
||||||
PIFWriter ..> BitOutputStream
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' VIEW (vert)
|
|
||||||
' ============================
|
|
||||||
package vconverter {
|
|
||||||
class ConverterWindow #palegreen
|
|
||||||
class PreviewPanel #palegreen
|
|
||||||
class FrequencyTablePanel #palegreen
|
|
||||||
class CodeTablePanel #palegreen
|
|
||||||
}
|
|
||||||
|
|
||||||
ConverterWindow *-- PreviewPanel
|
|
||||||
ConverterWindow *-- FrequencyTablePanel
|
|
||||||
ConverterWindow *-- CodeTablePanel
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' CONTROLLER (orange)
|
|
||||||
' ============================
|
|
||||||
class ConverterController #ffddaa
|
|
||||||
|
|
||||||
ConverterController ..> RGBImage
|
|
||||||
ConverterController ..> FrequencyTable
|
|
||||||
ConverterController ..> HuffmanTree
|
|
||||||
ConverterController ..> CanonicalCode
|
|
||||||
ConverterController ..> PIFWriter
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
|
Before Width: | Height: | Size: 50 KiB |
@@ -1,206 +0,0 @@
|
|||||||
@startuml
|
|
||||||
skinparam packageStyle rectangle
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' PACKAGE mimage (MODEL - BLEU)
|
|
||||||
' ============================
|
|
||||||
package mimage {
|
|
||||||
|
|
||||||
class Pixel #aliceblue {
|
|
||||||
- r : int
|
|
||||||
- g : int
|
|
||||||
- b : int
|
|
||||||
+ Pixel(r, g, b)
|
|
||||||
+ getR()
|
|
||||||
+ getG()
|
|
||||||
+ getB()
|
|
||||||
+ setR(r)
|
|
||||||
+ setG(g)
|
|
||||||
+ setB(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
class RGBImage #aliceblue {
|
|
||||||
- width : int
|
|
||||||
- height : int
|
|
||||||
- pixels : Pixel[*]
|
|
||||||
+ RGBImage(width, height)
|
|
||||||
+ getWidth()
|
|
||||||
+ getHeight()
|
|
||||||
+ getPixel(x, y)
|
|
||||||
+ setPixel(x, y, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
RGBImage *-- Pixel : contient
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' PACKAGE mhuffman (MODEL - BLEU)
|
|
||||||
' ============================
|
|
||||||
package mhuffman {
|
|
||||||
|
|
||||||
class FrequencyTable #aliceblue {
|
|
||||||
- freqR : int[*]
|
|
||||||
- freqG : int[*]
|
|
||||||
- freqB : int[*]
|
|
||||||
+ computeFromImage(img)
|
|
||||||
+ getRed()
|
|
||||||
+ getGreen()
|
|
||||||
+ getBlue()
|
|
||||||
}
|
|
||||||
|
|
||||||
class HuffmanNode #aliceblue {
|
|
||||||
- value : int
|
|
||||||
- frequency : int
|
|
||||||
- left : HuffmanNode
|
|
||||||
- right : HuffmanNode
|
|
||||||
+ setLeft(HuffmanNode lef): void
|
|
||||||
+ setRight(HuffmanNode rig): void
|
|
||||||
+ isLead(HuffmanNode f): boolean
|
|
||||||
+ getFrequence(): int
|
|
||||||
}
|
|
||||||
|
|
||||||
class HuffmanTree #aliceblue {
|
|
||||||
- root : HuffmanNode
|
|
||||||
+ generateCodes()
|
|
||||||
}
|
|
||||||
|
|
||||||
class CanonicalCode #aliceblue {
|
|
||||||
- codeLengths : Map
|
|
||||||
- canonicalCodes : Map
|
|
||||||
+ getCode(value)
|
|
||||||
+ getLength(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
FrequencyTable ..> RGBImage : analyse
|
|
||||||
HuffmanTree *-- HuffmanNode
|
|
||||||
CanonicalCode ..> HuffmanTree : dérive
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' PACKAGE util (MODEL - BLEU)
|
|
||||||
' ============================
|
|
||||||
package util {
|
|
||||||
|
|
||||||
class BitInputStream #aliceblue {
|
|
||||||
- fluxEntree
|
|
||||||
- octetCourant : int
|
|
||||||
- positionBit : int
|
|
||||||
- finDeFlux : boolean
|
|
||||||
|
|
||||||
+ BitInputStream(fluxEntree)
|
|
||||||
+ readBit() : int
|
|
||||||
+ readBits(nombreBits) : int
|
|
||||||
+ closeFlux()
|
|
||||||
}
|
|
||||||
|
|
||||||
class BitOutputStream #aliceblue {
|
|
||||||
- fluxSortie
|
|
||||||
- octetEnConstruction : int
|
|
||||||
- positionBit : int
|
|
||||||
- fluxFerme : boolean
|
|
||||||
|
|
||||||
+ BitOutputStream(fluxSortie)
|
|
||||||
+ writeBit(bit)
|
|
||||||
+ writeBits(valeur, nombreBits)
|
|
||||||
+ flush()
|
|
||||||
+ fermerFlux()
|
|
||||||
}
|
|
||||||
|
|
||||||
class ByteUtils #aliceblue {
|
|
||||||
<<utilitaire>>
|
|
||||||
+ toInt(high, low) : int
|
|
||||||
+ toBytes(value) : byte[]
|
|
||||||
}
|
|
||||||
|
|
||||||
class FileUtils #aliceblue {
|
|
||||||
<<utilitaire>>
|
|
||||||
+ isPIFFile(f) : boolean
|
|
||||||
+ readBinaryFile(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' PACKAGE mpif (MODEL - BLEU) — Sprint 2
|
|
||||||
' ============================
|
|
||||||
package mpif {
|
|
||||||
|
|
||||||
class PIFWriter #aliceblue {
|
|
||||||
+ writeHeader(out, width, height)
|
|
||||||
+ writeTables(out, red, green, blue)
|
|
||||||
+ encodePixels(out, img, red, green, blue)
|
|
||||||
+ writeToFile(path, img, red, green, blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
' (optionnel) PIFImage si tu souhaite la représenter
|
|
||||||
class PIFImage #aliceblue {
|
|
||||||
- width : int
|
|
||||||
- height : int
|
|
||||||
- lenR : int[*]
|
|
||||||
- lenG : int[*]
|
|
||||||
- lenB : int[*]
|
|
||||||
- pixelData
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
PIFWriter ..> RGBImage
|
|
||||||
PIFWriter ..> CanonicalCode
|
|
||||||
PIFWriter ..> BitOutputStream
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' PACKAGE vconverter (VIEW - VERT)
|
|
||||||
' ============================
|
|
||||||
package vconverter {
|
|
||||||
|
|
||||||
class ConverterWindow #palegreen {
|
|
||||||
+ setImagePreview(img)
|
|
||||||
+ setFrequencyTable()
|
|
||||||
+ setHuffmanTable()
|
|
||||||
+ setCanonicalTable()
|
|
||||||
}
|
|
||||||
|
|
||||||
class PreviewPanel #palegreen {
|
|
||||||
- image
|
|
||||||
+ setImage(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
class FrequencyTablePanel #palegreen {
|
|
||||||
+ updateFrequencies()
|
|
||||||
}
|
|
||||||
|
|
||||||
class CodeTablePanel #palegreen {
|
|
||||||
+ updateCodes()
|
|
||||||
}
|
|
||||||
|
|
||||||
ConverterWindow *-- PreviewPanel
|
|
||||||
ConverterWindow *-- FrequencyTablePanel
|
|
||||||
ConverterWindow *-- CodeTablePanel
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
' ============================
|
|
||||||
' CONTROLLER (ORANGE)
|
|
||||||
' ============================
|
|
||||||
class ConverterController #ffddaa {
|
|
||||||
+ loadImage(path)
|
|
||||||
+ computeFrequencies()
|
|
||||||
+ computeHuffman()
|
|
||||||
+ computeCanonical()
|
|
||||||
+ saveAsPIF(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
ConverterController ..> RGBImage
|
|
||||||
ConverterController ..> FrequencyTable
|
|
||||||
ConverterController ..> HuffmanTree
|
|
||||||
ConverterController ..> CanonicalCode
|
|
||||||
ConverterController ..> PIFWriter : écrit le .pif
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
|
Before Width: | Height: | Size: 174 KiB |
@@ -2,6 +2,7 @@
|
|||||||
JAVAC = javac
|
JAVAC = javac
|
||||||
JAVA = java
|
JAVA = java
|
||||||
JAVADOC = javadoc
|
JAVADOC = javadoc
|
||||||
|
ARGS =
|
||||||
|
|
||||||
# Dossiers
|
# Dossiers
|
||||||
SRC = src
|
SRC = src
|
||||||
@@ -124,12 +125,14 @@ $(BIN)/$(PKG_PATH)/mpif/PIFWriter.class: $(BIN) \
|
|||||||
$(JAVAC) -cp $(BIN) -d $(BIN) $(SRC)/$(PKG_PATH)/mpif/PIFWriter.java
|
$(JAVAC) -cp $(BIN) -d $(BIN) $(SRC)/$(PKG_PATH)/mpif/PIFWriter.java
|
||||||
|
|
||||||
|
|
||||||
# GROSSE compilation du listener + ConvertController + ConvertWindow car il y a une dependance cirulaire
|
# GROSSE compilation du listener + ConvertController + ConvertWindow + PIFSaverTask car il y a une dependance cirulaire
|
||||||
$(BIN)/$(PKG_PATH)/ConverterController.class \
|
$(BIN)/$(PKG_PATH)/ConverterController.class \
|
||||||
$(BIN)/$(PKG_PATH)/ExportButtonListener.class \
|
$(BIN)/$(PKG_PATH)/ExportButtonListener.class \
|
||||||
|
$(BIN)/$(PKG_PATH)/PIFSaveTask.class \
|
||||||
$(BIN)/$(PKG_PATH)/vconverter/ConverterWindow.class: \
|
$(BIN)/$(PKG_PATH)/vconverter/ConverterWindow.class: \
|
||||||
$(SRC)/$(PKG_PATH)/ConverterController.java \
|
$(SRC)/$(PKG_PATH)/ConverterController.java \
|
||||||
$(SRC)/$(PKG_PATH)/ExportButtonListener.java \
|
$(SRC)/$(PKG_PATH)/ExportButtonListener.java \
|
||||||
|
$(SRC)/$(PKG_PATH)/PIFSaveTask.java \
|
||||||
$(SRC)/$(PKG_PATH)/vconverter/ConverterWindow.java \
|
$(SRC)/$(PKG_PATH)/vconverter/ConverterWindow.java \
|
||||||
$(BIN)/$(PKG_PATH)/mimage/Pixel.class \
|
$(BIN)/$(PKG_PATH)/mimage/Pixel.class \
|
||||||
$(BIN)/$(PKG_PATH)/mimage/RGBImage.class \
|
$(BIN)/$(PKG_PATH)/mimage/RGBImage.class \
|
||||||
@@ -143,12 +146,13 @@ $(BIN)/$(PKG_PATH)/mpif/PIFWriter.class | $(BIN)
|
|||||||
@$(JAVAC) -cp $(BIN) -d $(BIN) \
|
@$(JAVAC) -cp $(BIN) -d $(BIN) \
|
||||||
$(SRC)/$(PKG_PATH)/ConverterController.java \
|
$(SRC)/$(PKG_PATH)/ConverterController.java \
|
||||||
$(SRC)/$(PKG_PATH)/ExportButtonListener.java \
|
$(SRC)/$(PKG_PATH)/ExportButtonListener.java \
|
||||||
|
$(SRC)/$(PKG_PATH)/PIFSaveTask.java \
|
||||||
$(SRC)/$(PKG_PATH)/vconverter/ConverterWindow.java
|
$(SRC)/$(PKG_PATH)/vconverter/ConverterWindow.java
|
||||||
|
|
||||||
|
|
||||||
# Exécution
|
# Exécution
|
||||||
run-conv: all
|
run-conv: all
|
||||||
$(JAVA) -cp $(BIN) $(MAIN_CONVERTER)
|
$(JAVA) -cp $(BIN) $(MAIN_CONVERTER) $(ARGS)
|
||||||
|
|
||||||
run-view: all
|
run-view: all
|
||||||
$(JAVA) -cp $(BIN) $(MAIN_VIEWER)
|
$(JAVA) -cp $(BIN) $(MAIN_VIEWER)
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public class ConverterController {
|
|||||||
this.fen = fen;
|
this.fen = fen;
|
||||||
this.outputPath = out;
|
this.outputPath = out;
|
||||||
this.inputPath = in;
|
this.inputPath = in;
|
||||||
|
|
||||||
|
System.out.println(this.inputPath+" ==> "+this.outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -166,7 +168,9 @@ public class ConverterController {
|
|||||||
chooser.setDialogTitle("Enregistrer le fichier .pif");
|
chooser.setDialogTitle("Enregistrer le fichier .pif");
|
||||||
|
|
||||||
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||||
saveAsPIF(chooser.getSelectedFile().getAbsolutePath());
|
//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());
|
System.out.println("Fichier sauvegardé : " + chooser.getSelectedFile().getAbsolutePath());
|
||||||
JOptionPane.showMessageDialog(null, "Fichier sauvegardé avec succès : " + chooser.getSelectedFile().getName());
|
JOptionPane.showMessageDialog(null, "Fichier sauvegardé avec succès : " + chooser.getSelectedFile().getName());
|
||||||
}
|
}
|
||||||
@@ -175,7 +179,6 @@ public class ConverterController {
|
|||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
System.out.println("Erreur lors de la sauvegarde : " + ex.getMessage());
|
System.out.println("Erreur lors de la sauvegarde : " + ex.getMessage());
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +196,7 @@ public class ConverterController {
|
|||||||
this.loadImage(choosser.getSelectedFile());
|
this.loadImage(choosser.getSelectedFile());
|
||||||
}else {
|
}else {
|
||||||
System.err.println("Aucune image choisie. Arrêt du programme.");
|
System.err.println("Aucune image choisie. Arrêt du programme.");
|
||||||
|
System.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package fr.iutfbleau.sae;
|
package fr.iutfbleau.sae;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
public class ExportButtonListener implements ActionListener {
|
public class ExportButtonListener implements ActionListener {
|
||||||
private ConverterController controller;
|
private PIFSaveTask saveTask;
|
||||||
|
|
||||||
public ExportButtonListener(ConverterController controller){
|
public ExportButtonListener(ConverterController controller){
|
||||||
this.controller = controller;
|
this.saveTask = new PIFSaveTask(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e){
|
public void actionPerformed(ActionEvent e){
|
||||||
controller.saveViaBtn();
|
SwingUtilities.invokeLater(saveTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package fr.iutfbleau.sae;
|
||||||
|
public class PIFSaveTask implements Runnable{
|
||||||
|
private ConverterController controller;
|
||||||
|
|
||||||
|
public PIFSaveTask(ConverterController c) {
|
||||||
|
this.controller = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
controller.saveViaBtn();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package fr.iutfbleau.sae.mpif;
|
||||||
|
|
||||||
|
import fr.iutfbleau.sae.util.BitInputStream;
|
||||||
|
import fr.iutfbleau.sae.util.BitOutputStream;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fr.iutfbleau.sae.mimage.RGBImage;
|
||||||
|
|
||||||
|
|
||||||
|
public class PIFReader {
|
||||||
|
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
private int[] lenR;
|
||||||
|
private int[] lenG;
|
||||||
|
private int[] lenB;
|
||||||
|
|
||||||
|
public RGBImage read(String filepath)
|
||||||
|
throws Exception {
|
||||||
|
FileInputStream fis = new FileInputStream(filepath);
|
||||||
|
BitInputStream lecteur = new BitInputStream(fis);
|
||||||
|
|
||||||
|
// je lis l'entê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
|
||||||
|
Map<String, Integer> canonR = rebuildCanonical(lenR);
|
||||||
|
Map<String, Integer> canonG = rebuildCanonical(lenG);
|
||||||
|
Map<String, Integer> canonB = rebuildCanonical(lenB);
|
||||||
|
|
||||||
|
DecodeNode trieR = buildDecodageTree(canonR);
|
||||||
|
DecodeNode trieG = buildDecodageTree(canonG);
|
||||||
|
DecodeNode trieB = buildDecodageTree(canonB);
|
||||||
|
|
||||||
|
RGBImage img = decodePixels(lecteur, trieR, trieG, trieB);
|
||||||
|
|
||||||
|
lecteur.closeFlux();
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readHeader(BitInputStream in) {
|
||||||
|
// TODO: Implement header reading
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readCanonicalTables(BitInputStream in) {
|
||||||
|
// TODO: Implement canonical table reading
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,Integer> rebuildCanonical(int[] lengths) {
|
||||||
|
// TODO: Implement canonical table reconstruction
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,11 +2,38 @@ package fr.iutfbleau.sae.mpif;
|
|||||||
|
|
||||||
import fr.iutfbleau.sae.mimage.RGBImage;
|
import fr.iutfbleau.sae.mimage.RGBImage;
|
||||||
import fr.iutfbleau.sae.util.BitOutputStream;
|
import fr.iutfbleau.sae.util.BitOutputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class PIFWriter {
|
public class PIFWriter {
|
||||||
|
|
||||||
|
public void writeTOFile(String filepath, RGBImage image,
|
||||||
|
Map<Integer,String> canonR,
|
||||||
|
Map<Integer,String> canonG,
|
||||||
|
Map<Integer,String> canonB)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
// Création du flux de sortie binaire
|
||||||
|
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());
|
||||||
|
|
||||||
|
// Écriture des tables de longueurs des codes canoniques
|
||||||
|
writeTables(ecriveur, canonR, canonG, canonB);
|
||||||
|
|
||||||
|
// Ecriture des pixels
|
||||||
|
encodePixels(ecriveur, image, canonR, canonG, canonB);
|
||||||
|
|
||||||
|
ecriveur.fermerFlux();
|
||||||
|
|
||||||
|
System.err.println("SYSTEME");
|
||||||
|
}
|
||||||
|
|
||||||
// Ecriture de l'en-tête du fichier PIF (largeur et hauteur)
|
// 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 {
|
try {
|
||||||
@@ -26,7 +53,7 @@ public class PIFWriter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Écriture des longueurs des codes canoniques pour chaque composante
|
// Écriture des longueurs des codes canoniques pour chaque composante
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
int len;
|
int len;
|
||||||
if (canonR.containsKey(i)) { // petite securité (au cas où)
|
if (canonR.containsKey(i)) { // petite securité (au cas où)
|
||||||
len = canonR.get(i).length();
|
len = canonR.get(i).length();
|
||||||
@@ -36,7 +63,7 @@ public class PIFWriter {
|
|||||||
out.writeBits(len, 8);
|
out.writeBits(len, 8);
|
||||||
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
int len;
|
int len;
|
||||||
if (canonG.containsKey(i)) {
|
if (canonG.containsKey(i)) {
|
||||||
len = canonG.get(i).length();
|
len = canonG.get(i).length();
|
||||||
@@ -45,7 +72,7 @@ public class PIFWriter {
|
|||||||
}
|
}
|
||||||
out.writeBits(len, 8);
|
out.writeBits(len, 8);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
int len;
|
int len;
|
||||||
if (canonB.containsKey(i)) {
|
if (canonB.containsKey(i)) {
|
||||||
len = canonB.get(i).length();
|
len = canonB.get(i).length();
|
||||||
@@ -54,7 +81,7 @@ public class PIFWriter {
|
|||||||
}
|
}
|
||||||
out.writeBits(len, 8);
|
out.writeBits(len, 8);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Erreur lors de l’écriture des tables de fréquences dans le fichier PIF");
|
System.err.println("Erreur lors de l’écriture des tables de fréquences dans le fichier PIF");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,14 +95,13 @@ public class PIFWriter {
|
|||||||
out.writeBit(0);
|
out.writeBit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Erreur lors de l’écriture des bits dans le fichier PIF");
|
System.err.println("Erreur lors de l’écriture des bits dans le fichier PIF");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Méthode pour encoder les pixels de l'image en utilisant les codes canoniques
|
// Méthode pour encoder les pixels de l'image en utilisant les codes canoniques
|
||||||
public void encodePixels(BitOutputStream out, RGBImage image, Map<Integer, String> canonRED, Map<Integer, String> canonGREEN, Map<Integer, String> canonBLUE){
|
public void encodePixels(BitOutputStream out, RGBImage image, Map<Integer, String> canonRED, Map<Integer, String> canonGREEN, Map<Integer, String> canonBLUE){
|
||||||
try {
|
|
||||||
int width = image.getWidth();
|
int width = image.getWidth();
|
||||||
int height = image.getHeight();
|
int height = image.getHeight();
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
@@ -92,33 +118,9 @@ public class PIFWriter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("Erreur lors de l’encodage des pixels dans le fichier PIF");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTOFile(String filepath, RGBImage image,
|
|
||||||
Map<Integer,String> canonR,
|
|
||||||
Map<Integer,String> canonG,
|
|
||||||
Map<Integer,String> canonB)
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
// Création du flux de sortie binaire
|
|
||||||
FileOutputStream fos =new FileOutputStream(filepath);
|
|
||||||
BitOutputStream ecriveur =new BitOutputStream(fos);
|
|
||||||
|
|
||||||
// Écriture de l'en-tête
|
|
||||||
writeHeader(ecriveur, image.getWidth(), image.getHeight());
|
|
||||||
|
|
||||||
// Écriture des tables de longueurs des codes canoniques
|
|
||||||
writeTables(ecriveur, canonR, canonG, canonB);
|
|
||||||
|
|
||||||
// Ecriture des pixels
|
|
||||||
encodePixels(ecriveur, image, canonR, canonG, canonB);
|
|
||||||
|
|
||||||
ecriveur.fermerFlux();
|
|
||||||
|
|
||||||
System.err.println("SYSTEME");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
package fr.iutfbleau.sae.util;
|
package fr.iutfbleau.sae.util;
|
||||||
import fr.iutfbleau.sae.util.BitOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
@@ -99,9 +98,14 @@ public class BitOutputStream {
|
|||||||
if (fluxFerme) {
|
if (fluxFerme) {
|
||||||
throw new IOException("Le flux de sortie est fermé");
|
throw new IOException("Le flux de sortie est fermé");
|
||||||
}
|
}
|
||||||
while (this.positionBit >= 0) {
|
|
||||||
writeBit(0);
|
// Si l'octet nes pas vide on le complete avec des 0
|
||||||
|
if(this.positionBit < 7){
|
||||||
|
this.fluxSortie.write(this.octetEnConstruction);
|
||||||
|
this.octetEnConstruction = 0;
|
||||||
|
this.positionBit = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fluxSortie.flush(); // Force l'écriture dans le flux sous-jacent dans le but de vider le buffer
|
this.fluxSortie.flush(); // Force l'écriture dans le flux sous-jacent dans le but de vider le buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import java.io.InputStream;
|
|||||||
* @version 1.0
|
* @version 1.0
|
||||||
* @since 2025-12-13
|
* @since 2025-12-13
|
||||||
*/
|
*/
|
||||||
public class BitinputStream {
|
public class BitInputStream {
|
||||||
|
|
||||||
/** Flux d'entrée sous-jacent */
|
/** Flux d'entrée sous-jacent */
|
||||||
private final InputStream fluxEntree;
|
private final InputStream fluxEntree;
|
||||||
@@ -41,7 +41,7 @@ public class BitinputStream {
|
|||||||
* @param fluxEntree flux d'entrée à décorer
|
* @param fluxEntree flux d'entrée à décorer
|
||||||
* @throws IllegalArgumentException si le flux est nul
|
* @throws IllegalArgumentException si le flux est nul
|
||||||
*/
|
*/
|
||||||
public BitinputStream(InputStream fluxEntree) {
|
public BitInputStream(InputStream fluxEntree) {
|
||||||
if (fluxEntree == null) {
|
if (fluxEntree == null) {
|
||||||
throw new IllegalArgumentException("Le flux d'entrée ne peut pas être nul");
|
throw new IllegalArgumentException("Le flux d'entrée ne peut pas être nul");
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 4.5 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
@@ -24,8 +24,7 @@ Learning log – Problème de blocage de la fenêtre après la sauvegarde:
|
|||||||
Ce sont des opérations potentiellement longues et qui se déroulaient sur le thread principal,
|
Ce sont des opérations potentiellement longues et qui se déroulaient sur le thread principal,
|
||||||
avant même que l’EDT ne prenne le relais pour gérer l’interface.
|
avant même que l’EDT ne prenne le relais pour gérer l’interface.
|
||||||
|
|
||||||
Cela avait deux conséquences. D'abord, la fenêtre pouvait parfois être affichée trop tard ou de manière irrégulière.
|
Cela avait pour conséquences que Swing se retrouvait dans un état instable, puisque certaines opérations graphiques avaient été réalisées
|
||||||
Ensuite, après l’export, Swing se retrouvait dans un état instable, puisque certaines opérations graphiques avaient été réalisées
|
|
||||||
hors du thread dédié.
|
hors du thread dédié.
|
||||||
C’est exactement ce qui provoquait le gel de l’interface : une fois le fichier enregistré, la fenêtre ne répondait plus car
|
C’est exactement ce qui provoquait le gel de l’interface : une fois le fichier enregistré, la fenêtre ne répondait plus car
|
||||||
l’EDT était bloqué ou interrompu, empêchant toute interaction, y compris la fermeture de la fenêtre.
|
l’EDT était bloqué ou interrompu, empêchant toute interaction, y compris la fermeture de la fenêtre.
|
||||||
@@ -43,3 +42,9 @@ Learning log – Problème de blocage de la fenêtre après la sauvegarde:
|
|||||||
Grâce à cette analyse, j’ai mieux compris la manière dont Swing gère les threads et j’ai pu corriger la structure de mon programme
|
Grâce à cette analyse, j’ai mieux compris la manière dont Swing gère les threads et j’ai pu corriger la structure de mon programme
|
||||||
afin qu’il reste totalement réactif, même après l’export. Cette expérience m’a rappelé l’importance de maîtriser les principes fondamentaux
|
afin qu’il reste totalement réactif, même après l’export. Cette expérience m’a rappelé l’importance de maîtriser les principes fondamentaux
|
||||||
des bibliothèques graphiques et leurs contraintes en matière de multithreading.
|
des bibliothèques graphiques et leurs contraintes en matière de multithreading.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
le proble aussi avec mon flush infini
|
||||||
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 3.8 MiB |