mardi 6 avril 2010

GIMP Immortalizes My Pictures (didactiel 2/5)

Comment parler de libre et d'image sans évoquer GIMP. J'en parlerai d'autant plus dans cet entrée que Scheme, le langage de programmation utilisable dans GIMP, est, comme Haskell, un langage fonctionnel (et pour l'anecdote, c'est en apprenant Scheme que j'ai re-decouvert Python ce qui m'a amené, le moins naturellement du monde, à Haskell!).
Quand on veut manipuler (recadrer, recoloriser, recomposer...) avec GIMP une image comme notre pauvre image créee précédemment avec Octave, le plus simple est de la convertir au format ppm :
saveimage("pourrie.ppm",x,"ppm")
qui a la particularité de générer un fichier binaire (on peut quand même lire le code "P6" en début de fichier confirmant qu'il s'agit bien du format ppm toutefois rien ne garantit de la qualité du fichier produit que, pour ma part, je n'arrive à lire nulle part) .
L'inverse est malheureusement moins direct (ce qui peut se comprendre dans la mesure où Octave n'est pas un outil de traitement d'image a priori) : GIMP n'a pas les moyens de fournir des informations picturales à Octave.
Afin de pouvoir triturer toute sorte d'images (dans la limite de la légalité, bien sûr), le moyen le plus simple auquel j'ai pensé (outre celui de programmer en Scheme mais c'est quand même plutôt pénible) consiste à convertir l'image que l'on a sous la main au format ppm (ppm "P3" cette fois : la version texte de ce format -GIMP nous le propose toujours au moment de l'exportation-) puis, grâce à un petit script, de convertir ce fichier ppm au format img.
Le but de cette entrée est particulièrement de présenter ce script écrit en Haskell et plus généralement de montrer que la syntaxe d'Haskell possède la souplesse et la robustesse permettant d'écrire des codes concis et fiables.
module Main where

import System.IO
import System.Environment (getArgs)

ppm2img inh outh = do
(height, width) <- readHeader inh
hPutStrLn outh "# Created by gimp2octave"
hPutStrLn outh "# name: map"
hPutStrLn outh "# type: matrix"
hPutStrLn outh $ "# rows: " ++ show (height*width)
hPutStrLn outh "# columns: 3"
readWriteLoop inh outh
hPutStrLn outh "# name: img"
hPutStrLn outh "# type: matrix"
hPutStrLn outh $ "# rows: " ++ show height
hPutStrLn outh $ "# columns: " ++ show width
writeLoop outh height width 1 where
readHeader inh = do
inStr <- hGetLine inh -- P3
inStr <- hGetLine inh -- Created by Gimp
inStr <- hGetLine inh -- Height Width
let [hStr,wStr] = words inStr
inStr <- hGetLine inh -- Base
return (read hStr::Int, read wStr::Int)
readWriteLoop inh outh = do
ineof <- hIsEOF inh
if ineof
then return ()
else do
rStr <- hGetLine inh
gStr <- hGetLine inh
bStr <- hGetLine inh
hPutStrLn outh $ " " ++ rStr ++ " " ++ gStr ++ " " ++ bStr
readWriteLoop inh outh
writeLoop outh h w n = do
if n > h
then return ()
else do
let str = foldr (++) "" $ map ((" " ++) . show) [n,n+h..n+(w-1)*h]
hPutStrLn outh str
writeLoop outh h w (n+1)

main = do
args <- getArgs
inh <- openFile (head args) ReadMode
outh <- openFile (head (tail args)) WriteMode
ppm2img inh outh
hClose inh
hClose outh

Aucun commentaire:

Enregistrer un commentaire