jeudi 22 avril 2010

version bêta de l'application de traitement des fichiers images

Vous avais-je déjà parlé d’une application java permettant de travailler des images en noir et blanc pour les coloriser ( avec de nombreuses fonctionnalités ).

Elle est quasiment finie, autant en faire un billet.

Copie d’écran

 

 

 

 

 

 

 

 

 

Fonctionnalités

  • recharger une image
  • sauver
  • sauver sous
  • supprimer
  • charger un répertoire
  • quitter l’application
  • réduire le nombre de couleurs
  • zoom in
  • zoom out
  • nettoyer ( effacer les points parasites )
  • rotation +90°
  • rotation -90°
  • fill couleur ( borné par autre couleur )
  • remplacer une couleur
  • prélever une couleur
  • couper
  • définir un rectangle
  • bookmarquer
  • dé-bookmarquer
  • statistiques des couleurs de l’images
  • mesurer les dimensions
  • plein écran
  • dans le navigateur
  • trouver un code couleur

fichiers de ressources ( property file )

  • un fichier pour gérer les paramètres de l’application
  • un fichier pour gérer les éléments du menu
  • un fichier pour chaque fournisseur de couleur à afficher dans une jtable

Et concernant les images traitées ?

  • elles sont stockées dans un BufferedImage
  • plutôt que d’utiliser les fonctions java de transformations affines, les rotations sont traitées directement par permutations dans un repère (x,y)
  • la fonction fill est assez rapide, moins de 3 secondes pour traiter une grande zoe ) borner ( 1 seconde pour substituer tous les points d’une image ( 1000 * 1000 pixels )
  • la fonction ‘sauver sous’ sauve les images au format png ( RVB sans alpha )

Et concernant les couleurs utilisées ?

  • voir les billets précédents
  • chaque ligne est de la forme code_couleur.rgb=0x??????
  • un comparator est utilisé avec les jtable pour gérer les données stockées dans des listes triées. Il faut que ‘h12’ s’affiche avant ‘h101’ etc.
  • les jtable statistiques et (un)bookmark sont mise à jour directement à partir des click de souris sur l’image

Autres informations

  • pas mal de design patterns utilisés, pas mal de découplage des différents composants avec un pattern Observer amélioré
  • pas mal de classes génériques paramétrées utilisées
  • création d’un générateur automatique de remplissage d’un Jmenu et d’un JtoolBar ( voir copie d’écran )
  • la fonction undo a été retirée, le stockage des images étant très volumineux, une petite centaine d’actions ( avec sauvegarde des images ) sature la mémoire sur mon PC. Les 10 dernières actions auraient pu être gérée
  • un splash screen pour afficher les informations durant le chargement de l’application

Fonctionnalités à rajouter ?

  • éclaircir / foncer des couleurs
  • améliorer les contrastes ( il y a des algorithmes sympas ;) )
  • appliquer des filtres
  • en bref, réinventer ce que font photoshop, the Gimp et autres logiciels de traitement d’images
Dans l’intervalle, les fonctions existantes sont bien suffisantes dans la plupart des cas.

mercredi 14 avril 2010

graphviz : générer des graphes en ligne de commande


Description


L'outil en ligne de commande graphviz créé par ATT permet de générer des graphes orientés ou non, circulaires ou non à partir d'un fichier texte de description.
Voici quelques exemples permettant de générer des graphes hautement paramétrables.


Exemple d'un fichier de configuration


Un fichier de configuration simple comprend :
  • le type de graphe i.e. "graph" pour un graphe non-orienté.
  • le nom du projet i.e. "mcd" dans cet exemple.
  • des noeuds "node" définis par une forme "shape" et des objets à créer "voiture" et "marque".
  • chaque noeud est caractérisé par du texte décrit entre des crochets "[label="personne|insee\nnom\nprenom"]".
  • des liens ( non-orientés ici liant deux objets à la fois ( encore que ) comme "voiture -- "fabriquer" [label="1,1"]".
  • un titre, voir "label" et "fontsize" en fin de code.

à supposer que le fichier d'exemple ci-après se nomme mcd.xml,
pour générer une image nommée "mcd.png", il faut lancer en ligne de commande :
dot.exe -Tpng -omcd.png mcd.txt -Gcharset=latin1

graph mcd {
node [shape=box]; voiture; marque;
node [shape=record]; personne;
node [shape=ellipse,style=filled,color=lightgrey]; "posseder"; "fabriquer";

personne [label="personne|insee\nnom\nprenom"];

personne -- "posseder" [label="0,n"];
"posseder" -- voiture [label="1,1"];

voiture -- "fabriquer" [label="1,1"];
"fabriquer" -- marque [label="1,n"];

label = "\n\nMCD by NEATO";
fontsize=16;
}



Quelques fonctions avancées


Voici quelques paramètres et autres types de données permettant d'améliorer la lecture des graphes :
  • "#rankdir=LR ;" permet d'écrire les noeuds de gauche à droite.
  • "subgraph" permet de définir des sous-graphes avec des composants connexes.
  • "\n" dans des labels permet des sauts de ligne.
  • Les noeuds liés peuvent être chaînés linéairement : "sql0 -> sql1 -> sql2 -> sql3 -> sql4 -> sql5 ;".
  • Les noeuds liés peuvent être chaînés par destination : "sql4 -> { sql0 ; sql2 }".
  • définir des compartiments "boîte" dans les labels : "e0 [shape="record",label="e0|{0|0}"] ;".
  • le couplage de graphviz à un dictionnaire de données pour analyser un schéma ( utilisateur "scott" d'Oracle ) permet de visualiser graphiquement les tables. L'outil SchemaSpy génère le même genre de graphe et s'appuie sur graphviz ! ...


digraph wc_sql
{
#rankdir=LR ;
edge [color="tan",fontname="arial"] ;
node [color="white",fontname="arial",fontsize="10",shape="box",style="filled"] ;
bgcolor="white" ;
fontname="arial";
fontsize="10";

subgraph cluster_uml
{
color="whitesmoke"
style="filled" ;
label="SQL" ;

sql0 [label="étape\nSQL",color="orange",shape="ellipse"] ;
sql1 [label="vérifier\ntaille sources"] ;
sql2 [label="dropper le package généré \n(en cas de besoin)"] ;
sql3 [label="builder les packages"] ;
sql4 [label="vérifier\nvalidité",color="darkorange",shape="ellipse"] ;
sql5 [label="étape\njava",color="orange",shape="ellipse"] ;

sql0 -> sql1 -> sql2 -> sql3 -> sql4 -> sql5 ;

sql4 -> { sql0 ; sql2 } [ label="tant que pas OK" ,color="red",fontname="arial",fontsize="10" ] ;
sql1 -> sql0 [ label="tant que pas OK" ,color="red",fontname="arial",fontsize="10" ] ;
}
}


"Diagramme PERT"


digraph PERT {

rankdir="LR" ;

e0 [shape="record",label="e0|{0|0}"] ;
e1 [shape="record",label="e1|{5|5}"] ;
e2 [shape="record",label="e2|{7|17}"] ;
e3 [shape="record",label="e3|{13|13}"] ;
e4 [shape="record",label="e4|{16|17}"] ;
e5 [shape="record",label="e5|{23|24}"] ;
e6 [shape="record",label="e6|{0|3}"] ;
e7 [shape="record",label="e7|{3|6}"] ;
e8 [shape="record",label="e8|{4|7}"] ;
e9 [shape="record",label="e9|{8|13}"] ;
e10 [shape="record",label="e10|{4|15}"] ;
e11 [shape="record",label="e11|{13|13}"] ;
e12 [shape="record",label="e12|{15|15}"] ;
e13 [shape="record",label="e13|{24|24}"] ;

e1 -> e2 [label="j 2"] ;
e2 -> e4 [label="---"] ;
e3 -> e4 [label="k 3"] ;
e4 -> e5 [label="l 7"] ;
e5 -> e13 [label="---"] ;

e0 -> e6 [label="---"] ;
e6 -> e7 [label="a 3"] ;
e7 -> e8 [label="b 1"] ;
e7 -> e9 [label="c 5"] ;
e8 -> e10 [label="e 4"] ;
e8 -> e11 [label="d 6"] ;
e9 -> e11 [label="---"] ;
e10 -> e12 [label="---"] ;

e0 -> e1 [label="h 5"] ;
e1 -> e3 [label="i 8"] ;
e3 -> e11 [label="---"] ;
e11 -> e12 [label="f 2"] ;
e12 -> e13 [label="g 9"] ;

{
rank="same" ;
node [ fillcolor="red"] ;
e0 ; e1 ;
}

label = "\n\nPERT by DOT";
fontsize=16;
}











Autres exemples de graphes










































 

 

 

 

 

 

 

 

 





Programme java permettant de traiter tous les fichiers txt d'un même répertoire


import java.io.File;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;


public class TaiterFichiersDot
{
//-------------------------------------------
String dotPath = "\"C:\\Program Files\\ATT\\Graphviz\\bin\\dot\"" ;
String rep = "C:/_cmd/" ;
String repWin = "C:\\_cmd\\" ;
String format = "png" ;
String winShell = "c:\\WINNT\\system32\\cmd.exe /K " ;
SortedMap<String, String> smFichiers = new TreeMap<String, String>() ;
int nb = 0 ;
int nbOk = 0 ;
int nbKo = 0 ;
//-------------------------------------------
TaiterFichiersDot()
{
}
//-------------------------------------------
void faire()
{
lireRep(rep) ;
for(Entry<String, String> entry : smFichiers.entrySet())
{
{
String fic = entry.getValue() ;
executerCommandLine(fic) ;
}
}
}
//-------------------------------------------
String construireCommande( String _fichier )
{
return dotPath + " -T" + format + " -o" + repWin + "" + _fichier + "." + format + " " + repWin + "" + _fichier + " -Gcharset=latin1" ;
}
//-------------------------------------------
void lireRep( String _rep )
{
String [] s = new File(_rep).list();
int iMax = s.length ;
int i ;
String ff,match,matchLow ;
//
for ( i=0 ; i<iMax ; i++ )
{
ff = s[i].toLowerCase() ;
if ( ff.endsWith(".txt"))
{
match = s[i] ;
matchLow = match.toLowerCase() ;
smFichiers.put(matchLow,match) ;
nb++ ;
}
}
}
//-------------------------------------------
void afficherResume()
{
System.out.println("commandes OK : " + nbOk );
System.out.println("commandes KO : " + nbKo );
}
//-------------------------------------------
void executerCommandLine( String _fichier )
{
String chCmd = winShell + construireCommande(_fichier) ;
try
{
Runtime.getRuntime().exec(chCmd);
System.out.println("OK pour : "+chCmd);
nbOk++ ;
}
catch(Exception ie)
{
System.out.println("erreur : " + chCmd );
nbKo++ ;
}
}
//-------------------------------------------
public static void main(String[] args)
{
TaiterFichiersDot appli = new TaiterFichiersDot() ;
appli.faire() ;
appli.afficherResume() ;
}
//-------------------------------------------
}


Plus d'informations sur


  • Graphviz site ici.
  • Graphviz galleries ici.
  • Graphviz documentation ici.
  • Doxygen site ici.
  • SchemaSpy site ici.