Arxiu de la categoria: Programació amb GIMP

Programant amb GIMP II. Pintar pixels a la pantalla

La veritat és que no hi ha molta informació i exemples per programar plugins amb GIMP. Però el cert és que la llibreria està ben documentada i s’entén força ràpid si un està familiaritzat amb la programació d’altres APIs i els conceptes de GIMP (capes, brushes,…).

GIMP Library Reference Manual:

A mode d’exemple anem a fer allò que considerem més bàsic: pintar pixels individuals sobre la pantalla. De l’enllaç anterior fem un repàs a les diferents possibilitats que ens ofereix la llibreria i ens fixem en la següent entrada:

gimppixelfetcher — Functions for operating on pixel regions:

i aquí tenim unes poques funcions, concretament la que necessitarem per pintar pixels és

void gimp_pixel_fetcher_put_pixel (GimpPixelFetcher *pf,
gint x,
gint y,
const guchar *pixel);

el primer argument és un punter a un objecte GimpPixelFetcher que hem inicialitzat prèviament.

\tGimpPixelFetcher *pf;
\tpf = gimp_pixel_fetcher_new (drawable,FALSE);

S’inicialitza a partir del drawable, que representa la capa sobre la que volem pintar. Per tant aquest punter ens dóna un espai de memòria que podem associar a un pixel d’una capa.

Els arguments x, y són evidenment les coordenades on volem escriure el pixel.

Finalment el punter *pixel conté la informació del pixel, concretament les 3 components del color.

Seguidament mostrem la funció principal pintar_pixel() del nostre plugin, que el que fa és pintar 5 pixels per pantalla, en les posicions (20,0),…, (24,0). El codi (fitxer gimp_pixel_fetcher_put_pixel.c) el pots descarregar a la wiki, tot i que està una mica brut. El primer pixel tindrà el mateix color que el foreground que tinc seleccionat en aquell moment; per al segon pixel estableixo un color amb la funció gimp_rgb_set(); el tercer pixel serà igual que el pixel de la posició (0,0), utilitzo la funció gimp_pixel_fetcher_get_pixel(); per als quart i cinquè pixel fico directament les coordenades RGB del color.

Per compilar:

$ gimptool-2.0 –install gimp_pixel_fetcher_put_pixel.c

i el codi:

static void pintar_pixel (GimpDrawable *drawable)
{
\tGimpPixelFetcher *pf;
\tgint x1, y1;
\tguchar *px; //pixel is an array of bpp bytes.
\tGimpRGB color;

\tx1=0;
\ty1=0;

\tpf = gimp_pixel_fetcher_new (drawable,FALSE);
\tpx = g_new (guchar, 1);

\t//1. escric un pixel amb el color del foreground
\tgimp_context_get_foreground (&color);
\t//g_message (“%d,%d,%d”,(int)(&color)->r,(int)(&color)->g,(int)(&color)->b);
\tpx[0] = 255*(&color)->r; //vermell (0-255)
\tpx[1] = 255*(&color)->g; //verd (0-255)
\tpx[2] = 255*(&color)->b; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+20, y1, px);

\t//2. escric un pixel i dic quin color vull amb la funció gimp_rgb_set
\tgimp_rgb_set (&color, 0.0, 1.0, 1.0);
\tpx[0] = 255*(&color)->r; //vermell (0-255)
\tpx[1] = 255*(&color)->g; //verd (0-255)
\tpx[2] = 255*(&color)->b; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+21, y1, px);

\t//3. escric un pixel igual que el de la posició (0,0)
\tgimp_pixel_fetcher_get_pixel (pf,x1, y1, px);
\t//g_message (“%d,%d,%d”,(int)px[0],(int)px[1],(int)px[2]); //puc obtenir informació del pixel (components RGB)
\tgimp_pixel_fetcher_put_pixel (pf, x1+22, y1, px);

\t//4. escric un pixel i dic quin color vull
\tpx[0] = 255; //vermell (0-255)
\tpx[1] = 0; //verd (0-255)
\tpx[2] = 0; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+23, y1, px);
\t// o bé
\t*px=0; //vermell (0-255)
\t*(px+1)=0; //verd (0-255)
\t*(px+2)=255; //blau (0-255)
\tgimp_pixel_fetcher_put_pixel (pf, x1+24, y1, px);

\tg_free (px);

\tgimp_pixel_fetcher_destroy (pf);

\tgimp_drawable_flush (drawable);
\tgimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
\tgimp_drawable_update (drawable->drawable_id,20,0,5,1);

}

Programant amb GIMP I. Executar plugins des de la consola

Amb aquest article vull encetar una sèrie de posts sobre la programació amb GIMP. No és un tutorial per aprendre a programar GIMP, tan sols és posar en ordre unes quantes idees enfocades a un futur projecte, que bàsicament és desenvolupar un framework per poder explicar històries tot dibuixant sobre la pantalla amb una wacom, i on es succeeixin múltiples efectes visuals i sonors. Si aquesta sèrie de posts s’acaba, en l’últim podrem veure com es toca una melodia on el pentagrama està dibuixat sobre el GIMP i les notes les dibuixo amb el ratolí o la wacom.

Primer de tot necessitem les llibreries de desenvolupament del GIMP:

$ sudo apt-get install libgimp2.0-dev

i aprenem a programar un plugin a partir d’un tutorial que si cerques per Google segur que trobes:

Amb aquest tutorial, que implementa un blur (difuminador) aprenem els conceptes bàsics de la programació amb GIMP. Els nostres plugins els programarem amb llenguatge C. Per compilar el plugin farem:

$ gimptool-2.0 –install myblur.c

Per executar el plugin ho farem des de dins del GIMP amb Filtres > Difumina > My Blur. O també ho podem fer amb un script Script-Fu: Filtres > Script-Fu > Consola

(plug-in-myblur run-mode image drawable)

on substituim run-mode, image i drawable pels valors correctes. Per exemple:

(plug-in-myblur RUN-NONINTERACTIVE 1 2)

Però a mi el que m’interessa és executar plugins des de fora del GIMP, des de la consola. La primera manera de fer-ho és amb el llenguatge de script propi del GIMP, el llenguatge Scheme.

example_script.scm:

(
define (example-script inputFilename outputFileName)
(
let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE inputFilename inputFilename)))
(drawable (car (gimp-image-get-active-layer image)))
)
(plug-in-myblur RUN-NONINTERACTIVE image drawable)
(gimp-file-save RUN-NONINTERACTIVE image drawable outputFileName outputFileName)
)
)

Els script l’he de guardar en la carpeta de scripts del GIMP: ~/.gimp-2.6/scripts. Per executar-lo puc invocar al GIMP en mode comanda (opció -b):

$ gimp -i -b “(example-script \\”confirmacion.jpg\\” \\”confirmacion_out.jpg\\”)” -b “(gimp-quit 0)”
batch command executed successfully

Però encara no em convenç aquesta manera de fer. Jo el que vull és poder aplicar un plugin a una imatge oberta del GIMP, executant el plugin des de la consola, no des de dins del GIMP. I la clau està en saber que el GIMP té un servidor, el servidor Script-Fu, que treballa per defecte pel port 10008 i que escolta les peticions TCP que li vénen de la xarxa (socket). Primer de tot hem d’arrencar el servidor:

Filtres > Script-Fu > Inicia el servidor

i efectivament puc connectar-me al servidor:

$ telnet localhost 10008

però això no serveix de res si no sé el protocol per comunicar-me amb aquest servidor. Aquest protocol està explicat en aquest enllaç:

no és un protocol difícil d’entendre o implementar. Per sort, al Google trobem el script servertest.py que implementa aquest protocol. Per exemple el podem trobar en un d’aquests enllaḉos:

Ara ja puc executar el meu plugin des de la shell:

$ python servertest.py
Trying ::1.
Trying 127.0.0.1.
Script-Fu-Remote – Testclient
> (plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success
>

servertest.py treballa de forma interactiva. No em convenç. Faig una modificació de manera que pugui treballar de forma totalment desatesa: script servertest_v2.py (http://wiki.joanillo.org/index.php/Programaci%C3%B3_GIMP#Servidor_Script-Fu)

$ python servertest_v2.py localhost 10008 “(plug-in-myblur RUN-NONINTERACTIVE 1 2)”
HOST: localhost
PORT: 10008
COMMAND: (plug-in-myblur RUN-NONINTERACTIVE 1 2)
Trying ::1.
Trying 127.0.0.1.
(plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success

És a dir, executo l’anterior comanda des de la consola, i de forma màgica la imatge que tinc oberta en el GIMP queda difuminada.

Ara només falta executar aquesta comanda no des de la consola, sinó des d’un executable de C, que és el meu llenguatge de referència per desenvolupar futurs projectes:

// gcc -o execute_blur execute_blur.c
int main(int argc, char *argv[])
{
\tsystem(“python servertest_v2.py localhost 10008 \\”(plug-in-myblur RUN-NONINTERACTIVE 1 2)\\””);
}

$ ./execute_blur

HOST: localhost
PORT: 10008
COMMAND: (plug-in-myblur RUN-NONINTERACTIVE 1 2)
Trying ::1.
Trying 127.0.0.1.
(plug-in-myblur RUN-NONINTERACTIVE 1 2)
(OK): Success

i la imatge que tinc oberta en el GIMP queda difuminada.