Ce post est le résultat d’un travail scolaire. Voir le rapport original. Voir la page actuelle des plugins GIMP.
Rémi Peyronnet – Février 2002
Introduction
Elaboration du plug-in
Utilisation
Code
Conclusion
Références
Introduction
Gimp est un logiciel de traitement d’image issu du monde libre, et de plus en plus employé. OpenSource, il profite de nombreuses contributions, en particulier grâce à de nombreux plugins qu’il est possible de développer.
Cependant, je n’ai pas encore vu à ce jour de plugin permettant la conversion des canaux Rouge Vert Bleu (RGB), dans l’espace de couleur YUV (Luminance, Chrominances rouges et bleues). Il peut être souvent utile de travailler dans un tel mode, et de décomposer l’image en ces trois composantes. Ce plug-in a donc pour but de répondre à ce besoin.
I. Elaboration du plug-in
I. 1. Espaces de couleur
Le problème se pose de savoir comment représenter une couleur sur un ordinateur. Il existe pour cela beaucoup de techniques. La plus utilisée sur les ordinateurs est la représentation RGB, qui décrit une couleur par ses composantes rouges, vertes et bleues. Cette représentation correspond exactement à l’affichage des couleurs sur un écran par projection d’un flux d’électrons plus ou moins intense sur des pastilles rouges, vertes et bleues, qui en se mélangeant nous donne l’impression de couleur.
La représentation YUV est aussi très utilisée, principalement dans tout ce qui est compression d’image. Y représente la luminance de la couleur, et U et V, la chrominance de cette couleur dans le rouge et le bleu. Cette représentation est utile, car l’oeil est plus sensible aux variations de luminances qu’aux variations de chrominance. Séparer ces trois composantes permettra donc de pouvoir dégrader plus les chrominances, tout en conservant mieux la luminance.
I. 2. Formules de conversions
I. 2. a. Du RGB vers le YUV
La principale difficulté, outre l’écriture du plug-in lui-même, a été de trouver les formules adéquates pour la conversion YUV-RGB. En effet, en première approche, nous pouvons prendre pour la luminance simplement la moyenne des trois composantes Rouge, Vert et Bleu. Cependant, cette façon de faire n’est pas très juste, car elle ne tient pas compte de la sensibilité de l’oeil aux couleurs. Comme nous pouvons le constater dans les courbes ci-dessous, l’oeil à l’impression que le vert est beaucoup plus lumineux que le bleu. Il nous faut donc en tenir compte.

Y = 0.299*R + 0.587*G + 0.114*B
. On peut constater que cette formule tient bien compte du fait que l’oeil perçoit le vert comme plus lumineux que le rouge, qui est lui-même plus lumineux que le bleu.
Pour le calcul des chrominances, nous utiliseront les formules : U = -0.169*R - 0.331*G + 0.500*B + 128.0
et V = 0.500*R - 0.419*G - 0.081*B + 128.0
. Comment peut-on comprendre ces formules ? Premièrement, nous pouvons remarquer que ces deux formules sont prévues pour osciller entre 0 et 255 avec comme valeur moyenne 128. Par exemple, une valeur 255 pour Bleu, avec le coefficient 0.5, sera ramené dans les limites. De même pour le rouge et le vert (dans le sens négatif, -(0.169+0.331)=-0.500). Nous sommes ainsi assurés qu’avec des valeurs comprises entre 0 et 255 en entrée, nous aurons bien des valeurs entre 0 et 255 en sortie, ce qui est vital pour notre application. Il est de plus possible d’exprimer U et V en fonction de Y, et de retrouver ainsi le sens premier des chrominances (Y-R), (Y-B).
Récapitulatif :
Y = 0.299*R + 0.587*G + 0.114*B
U = -0.169*R - 0.331*G + 0.500*B + 128.0
V = 0.500*R - 0.419*G - 0.081*B + 128.0
I. 2. b. Du YUV au RGB
Si les formules ci-dessus abondent, il en va autrement dans le sens inverse. J’avais en premier lieu trouvé les formules (associées aux précédentes) :
- R = Y + (1.4075 * (V – 128));
- G = Y – (0.3455 * (U – 128) – (0.7169 * (V – 128));
- B = Y + (1.7790 * (U – 128);
Cependant cet ensemble de formules ne conserve pas du tout correctement les couleurs, comme en témoignent ces deux images, avant et après une conversion RGB vers YUV puis YUV vers RGB :

La distorsion entre les deux est alors intolérable.
Ce que nous cherchons à obtenir en fait, c’est que le produit des transformations RGB vers YUV et YUV vers RGB fasse l’identité. Il suffit donc de chercher à inverser les formules trouvées pour le premier passage. J’ai donc cherché à utiliser MatLab, disponible à l’école. Les résultats obtenus ont été tout à fait décevant, puisque le produit manuel des deux matrices ne donnait pas l’identité… L’utilisation de SciLab, logiciel gratuit, s’est révélée beaucoup plus efficace. Les formules obtenues sont alors :
- r = 1 * y – 0.0009267*(u-128) + 1.4016868*(v-128)
- g = 1 * y – 0.3436954*(u-128) – 0.7141690*(v-128)
- b = 1 * y + 1.7721604*(u-128) + 0.0009902*(v-128)
En raison des arrondis, il faut veiller à arrondir les nombres plus grands que 255 à 255, et négatifs à 0, au risque de voir apparaître des défauts dans l’image, 255.6 étant enregistré à 0 lors de sa conversion à un octet.
Il est tout à fait rassurant de constater après coup que les formules obtenues sont conformes à celles utilisées dans la norme JPEG, trouvée ensuite. Notons qu’il serait préférable d’arrondir les 0.009267 à 0, comme dans la norme.
Avec ces formules, la transformation RGB vers YUV suivi de son inverse est invisible à l’oeil, malgré les légères erreurs d’arrondi lors de la conversion de la valeur réelle en un octet.
I. 3. Programmation d’un Plug-in GIMP
L’intégration dans GIMP n’a pas été la chose la plus facile du projet, car la documentation est assez elliptique sur ce sujet. Heureusement, il existe beaucoup de plugins pour GIMP OpenSource, ce qui m’a permis de comprendre le fonctionnement normal d’un Plugin.
Le plugin possède un code d’initialisation, qui se charge d’enregistrer la fonction dans GIMP, en inscrivant par exemple une entrée dans un menu. Lorsque ce menu est appelé, la fonction principale du plugin est appelée, en donnant en paramètre un pointeur vers l’image. GIMP possède une manière optimisée de traiter les images, en les découpant par carreaux. Pour ce plugin, qui n’a pas besoin d’une connaissance complète de l’image mais seulement d’un pixel pour opérer, nous avons opté pour cette méthode. Le traitement est donc inclus dans uns boucle, qui s’occupe de découper l’image en blocs, puis nous traitons ensuite, chaque pixel, ligne par ligne. GIMP s’occupe ensuite de gérer l’affichage et la gestion des blocs, ce qui permet par exemple d’annuler l’effet appliqué.
II. Utilisation
Ce plugin est distribué soit sous forme de fichier source à compiler, soit en un binaire pour windows, à placer dans le répertoire ‘plugins’ de GIMP. Il faut alors relancer GIMP, et les entrées ‘RGB to YUV’ et ‘YUV to RGB’ sont ajoutées dans le menu Image/Couleurs. Il suffit juste de cliquer sur une de ces entrées pour lancer le plugin.
En sortie, le canal Y sera placé dans le canal Rouge, le U dans le Vert, et le V dans le Bleu. Grâce à la boîte de dialogue des canaux, vous pouvez demander de ne modifier ou voir qu’un ou plusieurs de ces canaux YUV à la fois.
III. Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
<span style="color: #0000ff;">/*</span> <span style="color: #0000ff;"> * 2002 Peyronnet Rémi </span> <span style="color: #0000ff;"> *</span> <span style="color: #0000ff;"> * This plugin transforms your image RGB in YUV</span> <span style="color: #0000ff;"> *</span> <span style="color: #0000ff;"> * This program is free software; you can redistribute it and/or modify</span> <span style="color: #0000ff;"> * it under the terms of the GNU General Public License as published by</span> <span style="color: #0000ff;"> * the Free Software Foundation; either version 2 of the License, or</span> <span style="color: #0000ff;"> * (at your option) any later version.</span> <span style="color: #0000ff;"> *</span> <span style="color: #0000ff;"> * This program is distributed in the hope that it will be useful, </span> <span style="color: #0000ff;"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span> <span style="color: #0000ff;"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span> <span style="color: #0000ff;"> * GNU General Public License for more details.</span> <span style="color: #0000ff;"> *</span> <span style="color: #0000ff;"> * You should have received a copy of the GNU General Public License</span> <span style="color: #0000ff;"> * along with this program; if not, write to the Free Software</span> <span style="color: #0000ff;"> * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</span> <span style="color: #0000ff;"> *</span> <span style="color: #0000ff;"> */</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> Many parts of this code are borrowed from other plugins source code. */</span> <span style="color: #a020f0;">#include </span><span style="color: #ff00ff;"><stdio.h></span> <span style="color: #a020f0;">#include </span><span style="color: #ff00ff;"><stdlib.h></span> <span style="color: #a020f0;">#include </span><span style="color: #ff00ff;"><math.h></span> <span style="color: #a020f0;">#include </span><span style="color: #ff00ff;"><time.h></span> <span style="color: #a020f0;">#include </span><span style="color: #ff00ff;">"libgimp/gimp.h"</span> <span style="color: #a020f0;">#define MAX(x,y) ( ((x)>(y))?(x):(y) )</span> <span style="color: #a020f0;">#define MIN(x,y) ( ((x)<(y))?(x):(y) )</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;">* defines ***********************************************************/</span> <span style="color: #a020f0;">#define PLUG_IN_NAME </span><span style="color: #ff00ff;">"plug_in_yuv"</span> <span style="color: #a020f0;">#define PLUG_IN_VERSION </span><span style="color: #ff00ff;">"Feburar 2002, 1.0"</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;">* Plugin interface *********************************************************/</span> <span style="color: #2e8b57;"><b>void</b></span> query(<span style="color: #2e8b57;"><b>void</b></span>); <span style="color: #2e8b57;"><b>void</b></span> run(<span style="color: #2e8b57;"><b>char</b></span> *name, <span style="color: #2e8b57;"><b>int</b></span> nparams, GimpParam *param, <span style="color: #2e8b57;"><b>int</b></span> *nreturn_vals, GimpParam **return_vals); GimpPlugInInfo PLUG_IN_INFO = { <span style="color: #ff00ff;">NULL</span>, <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> init_proc */</span> <span style="color: #ff00ff;">NULL</span>, <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> quit_proc */</span> query, <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> query_proc */</span> run <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> run_proc */</span> }; MAIN() <span style="color: #2e8b57;"><b>void</b></span> query(<span style="color: #2e8b57;"><b>void</b></span>) { <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> Definition of parameters */</span> <span style="color: #2e8b57;"><b>static</b></span> GimpParamDef args[] = { { GIMP_PDB_INT32, <span style="color: #ff00ff;">"run_mode"</span>, <span style="color: #ff00ff;">"Interactive, non-interactive"</span> }, { GIMP_PDB_IMAGE, <span style="color: #ff00ff;">"image"</span>, <span style="color: #ff00ff;">"Input image (unused)"</span> }, { GIMP_PDB_DRAWABLE, <span style="color: #ff00ff;">"drawable"</span>, <span style="color: #ff00ff;">"Input drawable"</span> } }; <span style="color: #2e8b57;"><b>static</b></span> GimpParamDef *return_vals = <span style="color: #ff00ff;">NULL</span>; <span style="color: #2e8b57;"><b>static</b></span> <span style="color: #2e8b57;"><b>int</b></span> nargs = <span style="color: #804040;"><b>sizeof</b></span>(args) / <span style="color: #804040;"><b>sizeof</b></span>(args[<span style="color: #ff00ff;">0</span>]); <span style="color: #2e8b57;"><b>static</b></span> <span style="color: #2e8b57;"><b>int</b></span> nreturn_vals = <span style="color: #ff00ff;">0</span>; gimp_install_procedure( <span style="color: #ff00ff;">"plug_in_rgb_yuv"</span>, <span style="color: #ff00ff;">"Transform the image from RGB to YUV"</span>, <span style="color: #ff00ff;">"This plugin replaces the RGB channels with YUV values."</span>, <span style="color: #ff00ff;">"Rémi Peyronnet"</span>, <span style="color: #ff00ff;">"Rémi Peyronnet"</span>, PLUG_IN_VERSION, <span style="color: #ff00ff;">"<Image>/Image/Colors/RGB->YUV"</span>, <span style="color: #ff00ff;">"RGB*"</span>, GIMP_PLUGIN, nargs, nreturn_vals, args, return_vals); gimp_install_procedure( <span style="color: #ff00ff;">"plug_in_yuv_rgb"</span>, <span style="color: #ff00ff;">"Transform the image from YUV to RGB"</span>, <span style="color: #ff00ff;">"This plugin replaces the RGB channels of an YUV image with the good RGB values."</span>, <span style="color: #ff00ff;">"Rémi Peyronnet"</span>, <span style="color: #ff00ff;">"Rémi Peyronnet"</span>, PLUG_IN_VERSION, <span style="color: #ff00ff;">"<Image>/Image/Colors/YUV->RGB"</span>, <span style="color: #ff00ff;">"RGB*"</span>, GIMP_PLUGIN, nargs, nreturn_vals, args, return_vals); } <span style="color: #2e8b57;"><b>void</b></span> run(<span style="color: #2e8b57;"><b>char</b></span> *name, <span style="color: #2e8b57;"><b>int</b></span> nparams, GimpParam *param, <span style="color: #2e8b57;"><b>int</b></span> *nreturn_vals, GimpParam **return_vals) { <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> Return values */</span> <span style="color: #2e8b57;"><b>static</b></span> GimpParam values[<span style="color: #ff00ff;">1</span>]; gint sel_x1, sel_y1, sel_x2, sel_y2; gint img_height, img_width, img_bpp, img_has_alpha; GimpDrawable *drawable; GimpPixelRgn dest_rgn, src_rgn, *pr; GimpRunModeType run_mode; GimpPDBStatusType status; <span style="color: #2e8b57;"><b>double</b></span> progress, max_progress; guchar * dest_row, *src_row, *dest, *src; <span style="color: #2e8b57;"><b>double</b></span> r,g,b,a=<span style="color: #ff00ff;">0</span>,y,u,v,m,mi; gint row, col; *nreturn_vals = <span style="color: #ff00ff;">1</span>; *return_vals = values; status = GIMP_PDB_SUCCESS; <span style="color: #804040;"><b>if</b></span> (param[<span style="color: #ff00ff;">0</span>].type!= GIMP_PDB_INT32) status=GIMP_PDB_CALLING_ERROR; <span style="color: #804040;"><b>if</b></span> (param[<span style="color: #ff00ff;">2</span>].type!=GIMP_PDB_DRAWABLE) status=GIMP_PDB_CALLING_ERROR; run_mode = param[<span style="color: #ff00ff;">0</span>].data.d_int32; drawable = gimp_drawable_get(param[<span style="color: #ff00ff;">2</span>].data.d_drawable); img_width = gimp_drawable_width(drawable->id); img_height = gimp_drawable_height(drawable->id); img_bpp = gimp_drawable_bpp(drawable->id); img_has_alpha = gimp_drawable_has_alpha(drawable->id); gimp_drawable_mask_bounds(drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2); max_progress = (sel_x2-sel_x1)*(sel_y2-sel_y1); <span style="color: #804040;"><b>if</b></span> (status == GIMP_PDB_SUCCESS) { <span style="color: #0000ff;">// Tile </span> gimp_tile_cache_ntiles((drawable->width + gimp_tile_width() - <span style="color: #ff00ff;">1</span>) / gimp_tile_width()); <span style="color: #804040;"><b>if</b></span> (strcmp(<span style="color: #ff00ff;">"plug_in_rgb_yuv"</span>,name) == <span style="color: #ff00ff;">0</span>) { <span style="color: #0000ff;">// RGB -> YUV</span> <span style="color: #0000ff;">// !!! Warning !!! Duplicated code... 'cause it'is quick'n dirty :)</span> gimp_progress_init(<span style="color: #ff00ff;">"Converting RGB to YUV..."</span>); progress = <span style="color: #ff00ff;">0</span>; <span style="color: #0000ff;">// Process</span> gimp_pixel_rgn_init (&dest_rgn, drawable, sel_x1, sel_y1, (sel_x2-sel_x1), (sel_y2-sel_y1), TRUE, TRUE); gimp_pixel_rgn_init (&src_rgn, drawable, sel_x1, sel_y1, (sel_x2-sel_x1), (sel_y2-sel_y1), FALSE, FALSE); <span style="color: #0000ff;">// Methode de traitement par dest_rgns -----------------------</span> <span style="color: #804040;"><b>for</b></span> (pr = gimp_pixel_rgns_register (<span style="color: #ff00ff;">2</span>, &src_rgn, &dest_rgn); pr != <span style="color: #ff00ff;">NULL</span>; pr = gimp_pixel_rgns_process (pr)) { <span style="color: #0000ff;">//Fun Goes On Here</span> dest_row = dest_rgn.data; src_row = src_rgn.data; <span style="color: #804040;"><b>for</b></span> (row = <span style="color: #ff00ff;">0</span>; row < dest_rgn.h; row++) { dest = dest_row; src = src_row; <span style="color: #804040;"><b>for</b></span> (col = <span style="color: #ff00ff;">0</span>; col < dest_rgn.w; col++) { <span style="color: #0000ff;">// Début du traitement spécifique *************</span> r = *src++; <span style="color: #0000ff;">//y </span> g = *src++; <span style="color: #0000ff;">//u</span> b = *src++; <span style="color: #0000ff;">//v</span> <span style="color: #804040;"><b>if</b></span> (img_has_alpha) a = *src++; <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> First set of formula, probably not the best... ----</span> <span style="color: #0000ff;"> y = (0.257*r) + (0.504*g) + (0.098*b) + 16;</span> <span style="color: #0000ff;"> u = (0.439*r) - (0.368*g) + (0.071*b) + 128;</span> <span style="color: #0000ff;"> v = - (0.148*r) - (0.291*g) + (0.439*b) + 128;</span> <span style="color: #0000ff;"> // YUV->RGB</span> <span style="color: #0000ff;"> // r = 1.164 * (y-16) + 1.596*(v-128);</span> <span style="color: #0000ff;"> // g = 1.164 * (y-16) + 0.813*(v-128) - 0.391*(u-128);</span> <span style="color: #0000ff;"> // b = 1.164 * (y-16) + 2.018*(u-128);</span> <span style="color: #0000ff;"> */</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> Second set, not much better...*/</span> y = (<span style="color: #ff00ff;">0.299</span>*r) + (<span style="color: #ff00ff;">0.587</span>*g) + (<span style="color: #ff00ff;">0.114</span>*b); u = -(<span style="color: #ff00ff;">0.169</span>*r) - (<span style="color: #ff00ff;">0.331</span>*g) + (<span style="color: #ff00ff;">0.500</span>*b) + <span style="color: #ff00ff;">128.0</span>; v = (<span style="color: #ff00ff;">0.500</span>*r) - (<span style="color: #ff00ff;">0.419</span>*g) - (<span style="color: #ff00ff;">0.081</span>*b) + <span style="color: #ff00ff;">128.0</span>; <span style="color: #0000ff;">// YUV->RGB^M</span> <span style="color: #0000ff;">//r = y + 1.402*(v-128.0);</span> <span style="color: #0000ff;">//g = y - 0.34414*(u-128.0) + 0.71414*(v-128.0);</span> <span style="color: #0000ff;">//b = y + 1.772*(u-128.0);</span> <span style="color: #0000ff;">//</span> <span style="color: #0000ff;">// From SciLab : This is the good one.</span> <span style="color: #0000ff;">//r = 1 * y - 0.0009267*(u-128) + 1.4016868*(v-128);^M</span> <span style="color: #0000ff;">//g = 1 * y - 0.3436954*(u-128) - 0.7141690*(v-128);^M</span> <span style="color: #0000ff;">//b = 1 * y + 1.7721604*(u-128) + 0.0009902*(v-128);^M</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;">* Third : home-made...*/</span> <span style="color: #0000ff;">/*</span><span style="color: #0000ff;">y = 0.333 * r + 0.333 * g + 0.333 * b;</span> <span style="color: #0000ff;"> u = r - y;</span> <span style="color: #0000ff;"> v = g - y;</span> <span style="color: #0000ff;"> r = y + u;</span> <span style="color: #0000ff;"> g = y + v;</span> <span style="color: #0000ff;"> b = y -u -v;</span> <span style="color: #0000ff;"> */</span> *dest++ = (guchar) (y><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((y<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:y); *dest++ = (guchar) (u><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((u<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:u); *dest++ = (guchar) (v><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((v<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:v); <span style="color: #804040;"><b>if</b></span> (img_has_alpha) *dest++ = a; <span style="color: #0000ff;">// Fin du traitement spécifique ****************</span> } <span style="color: #0000ff;">// for</span> dest_row += dest_rgn.rowstride; src_row += src_rgn.rowstride; } <span style="color: #0000ff;">// for </span> <span style="color: #0000ff;">// Update progress </span> progress += dest_rgn.w * dest_rgn.h; gimp_progress_update((<span style="color: #2e8b57;"><b>double</b></span>) progress / max_progress); } } <span style="color: #804040;"><b>else</b></span> <span style="color: #804040;"><b>if</b></span> (strcmp(<span style="color: #ff00ff;">"plug_in_yuv_rgb"</span>,name) == <span style="color: #ff00ff;">0</span>) { <span style="color: #0000ff;">// RGB -> YUV</span> <span style="color: #0000ff;">// !!! Warning !!! Duplicated code... 'cause it'is quick'n dirty :)</span> <span style="color: #0000ff;">// You should consider just edit the previous version and copy/paste this one.</span> gimp_progress_init(<span style="color: #ff00ff;">"Converting YUV to RGB..."</span>); progress = <span style="color: #ff00ff;">0</span>; <span style="color: #0000ff;">// Process</span> gimp_pixel_rgn_init (&dest_rgn, drawable, sel_x1, sel_y1, (sel_x2-sel_x1), (sel_y2-sel_y1), TRUE, TRUE); gimp_pixel_rgn_init (&src_rgn, drawable, sel_x1, sel_y1, (sel_x2-sel_x1), (sel_y2-sel_y1), FALSE, FALSE); <span style="color: #0000ff;">// Methode de traitement par dest_rgns -----------------------</span> <span style="color: #804040;"><b>for</b></span> (pr = gimp_pixel_rgns_register (<span style="color: #ff00ff;">2</span>, &src_rgn, &dest_rgn); pr != <span style="color: #ff00ff;">NULL</span>; pr = gimp_pixel_rgns_process (pr)) { <span style="color: #0000ff;">//Fun Goes On Here</span> dest_row = dest_rgn.data; src_row = src_rgn.data; <span style="color: #804040;"><b>for</b></span> (row = <span style="color: #ff00ff;">0</span>; row < dest_rgn.h; row++) { dest = dest_row; src = src_row; <span style="color: #804040;"><b>for</b></span> (col = <span style="color: #ff00ff;">0</span>; col < dest_rgn.w; col++) { <span style="color: #0000ff;">// Début du traitement spécifique *************</span> y = *src++; u = *src++; v = *src++; <span style="color: #804040;"><b>if</b></span> (img_has_alpha) a = *src++; <span style="color: #0000ff;">/*</span><span style="color: #0000ff;"> Second set, not much better...*/</span> <span style="color: #0000ff;">//y = (0.299*r) + (0.587*g) + (0.114*b);</span> <span style="color: #0000ff;">//u = -(0.169*r) - (0.331*g) + (0.500*b) + 128.0;</span> <span style="color: #0000ff;">//v = (0.500*r) - (0.419*g) - (0.081*b) + 128.0;</span> <span style="color: #0000ff;">// From SciLab</span> r = <span style="color: #ff00ff;">1</span> * y - <span style="color: #ff00ff;">0.0009267</span>*(u-<span style="color: #ff00ff;">128</span>) + <span style="color: #ff00ff;">1.4016868</span>*(v-<span style="color: #ff00ff;">128</span>); g = <span style="color: #ff00ff;">1</span> * y - <span style="color: #ff00ff;">0.3436954</span>*(u-<span style="color: #ff00ff;">128</span>) - <span style="color: #ff00ff;">0.7141690</span>*(v-<span style="color: #ff00ff;">128</span>); b = <span style="color: #ff00ff;">1</span> * y + <span style="color: #ff00ff;">1.7721604</span>*(u-<span style="color: #ff00ff;">128</span>) + <span style="color: #ff00ff;">0.0009902</span>*(v-<span style="color: #ff00ff;">128</span>); *dest++ = (guchar) (r><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((r<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:r); *dest++ = (guchar) (g><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((g<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:g); *dest++ = (guchar) (b><span style="color: #ff00ff;">255</span>)?<span style="color: #ff00ff;">255</span>:((b<<span style="color: #ff00ff;">0</span>)?<span style="color: #ff00ff;">0</span>:b); <span style="color: #804040;"><b>if</b></span> (img_has_alpha) *dest++ = a; <span style="color: #0000ff;">// Fin du traitement spécifique ****************</span> } <span style="color: #0000ff;">// for</span> dest_row += dest_rgn.rowstride; src_row += src_rgn.rowstride; } <span style="color: #0000ff;">// for </span> <span style="color: #0000ff;">// Update progress </span> progress += dest_rgn.w * dest_rgn.h; gimp_progress_update((<span style="color: #2e8b57;"><b>double</b></span>) progress / max_progress); } } <span style="color: #804040;"><b>else</b></span> { <span style="color: #0000ff;">// Ouch, ugly :)</span> printf(<span style="color: #ff00ff;">"Plugin not found.</span><span style="color: #6a5acd;">n</span><span style="color: #ff00ff;">"</span>); } gimp_drawable_flush(drawable); gimp_drawable_merge_shadow(drawable->id, TRUE); gimp_drawable_update (drawable->id, sel_x1, sel_y1, (sel_x2-sel_x1), (sel_y2-sel_y1)); gimp_displays_flush(); } values[<span style="color: #ff00ff;">0</span>].type = GIMP_PDB_STATUS; values[<span style="color: #ff00ff;">0</span>].data.d_status = status; gimp_drawable_detach(drawable); } |
Conclusion
Voici donc un plugin Gimp complètement fonctionnel, permettant de convertir les images en YUV, de travailler dessus, puis de repasser dans le domaine RGB.
Références
- http://www.gimp.org/ : Le site officiel du logiciel libre GIMP
- http://registry.gimp.org : Répertoire des plugins GIMP.
- http://gimp-plug-ins.sourceforge.net/doc/libgimp/html/ : La référence de la libGIMP.
- http://gimp-plug-ins.sourceforge.net/doc/Writing/html/plug-in.html : Tutoriel sur le développement de plugins GIMP.
- http://www.cse.msu.edu/%7Ecbowen/docs/yuvtorgb.html [ Lien cassé, voir l’ancienne page sur archive.org ] : Formules de conversions, au comportement étrange.
- http://www.northpoleengineering.com/rgb2yuv.htm [ Lien cassé, voir l’ancienne page sur archive.org ] : Conversion YUV matérielle.
- http://www.cs.sfu.ca/undergrad/CourseMaterials/CMPT479/material/notes/Chap3/Chap3.3/Chap3.3.html [ Lien cassé, voir l’ancienne page sur archive.org ] : Présentation des différents espaces de couleurs.
- http://www.funducode.com/freec/Fileformats/format3/format3c.htm [ Lien cassé, voir l’ancienne page sur archive.org ] : Compression JPEG, comportant les formules utilisées par le JPEG
- http://www-rocq.inria.fr/scilab/ [ Lien cassé, voir le nouveau site de Scilab, une compilation de ressources et informations supplémentaires, ou pour information voir l’ancienne page sur archive.org] : Page d’accueil du logiciel SciLab