Colorimètre numérique linux

Contenu du snippet

Emulation sous linux du colorimètre numérique MacOSX, en utilisant la librairie X11.
Codé en C et testé sur Ubuntu.

Dans mon cas, j'ai du ajouter dans le Makefile :
-L/usr/lib/i386-linux-gnu -lX11

Source / Exemple :


/*
Colorimètre numérique basé sur la librairie X11

3 sous fenetres composent cette application:
La 1ere est un zoom sur le voisinage du curseur. Le diaphragme y est représenté par un carré noir.
La 2eme est la couleur moyenne sur tous les pixels dans le diaphragme.
La 3eme liste les valeurs r, g, b, la taille du diaphragme et la position x, y du curseur.

Echap pour sortir. Les touches 'a' et 'z' permettent de réduire / agrandir le diaphragme.

  • /
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/keysym.h> #include <X11/cursorfont.h> #include <stdlib.h> #include <stdio.h> #include <string.h> // NPIX et TPIX sont le nombre et la taille des pixels de la sous-fenetre zoom // HEIGHT, WIDTH les dimensions de la fenetre application; SUBWIDTH la largeur de chaque 'sous fenetres' #define NPIX 15 #define TPIX 8 #define HEIGHT 120 #define WIDTH 360 #define SUBWIDTH 120 Display *dpy; int black, white; double r, g, b; unsigned int dpy_width, dpy_height; Window w, wroot; XTextProperty *title; GC gc; unsigned int x, y, x_im, y_im; XImage *image; XColor *c; //Colormap cmap; char str[5][32]; unsigned int i, j; unsigned int diaphragme; XEvent e; // redessiner la fenetre de l'application void redraw(){ // x, y coords souris // (x_im, y_im) coords de l'angle haut-gauche de la fenetre de zoom x_im= x- (NPIX- 1)/ 2; if (x_im< (NPIX- 1)/ 2) x_im= (NPIX- 1)/ 2; if (x_im> dpy_width- NPIX) x_im= dpy_width- NPIX; y_im= y- (NPIX- 1)/ 2; if (y_im< (NPIX- 1)/ 2) y_im= (NPIX- 1)/ 2; if (y_im> dpy_height- NPIX) y_im= dpy_height- NPIX; // recuperer l'image de l'écran entre (x_im, y_im) et (x_im+ NPIX, y_im+ NPIX) image= XGetImage(dpy, wroot, x_im, y_im, NPIX, NPIX, XAllPlanes(), ZPixmap); // Partie gauche // Dessin d'un rectangle pour chaque pixel r= g= b= 0.; for (i=0; i<NPIX; i++) for (j=0; j<NPIX; j++) { c->pixel= XGetPixel(image, i, j); // XQueryColor très lent => décomposition en red, green, blue de pixel //XQueryColor(dpy, cmap, c); c->red= c->pixel>> 16; c->green= (c->pixel>> 8) & 0xFF; c->blue= c->pixel & 0xFF; // Dessin des pixels zoomés XSetForeground(dpy, gc, c->pixel); XFillRectangle(dpy, w, gc, TPIX* i, TPIX* j, TPIX* (i+ 1), TPIX* (j+ 1)); // Si le pixel est dans le diaphragme, on ajoute sa contribution à la valeur moyenne if ( (i>= (NPIX- 1)/2- diaphragme+ 1) && (i< NPIX- ((NPIX- 1)/2- diaphragme+ 1)) && (j>= (NPIX- 1)/2- diaphragme+ 1) && (j< NPIX- ((NPIX- 1)/2- diaphragme+ 1)) ){ r+= (double)(c->red)/ ((2* diaphragme- 1)* (2* diaphragme- 1)); g+= (double)(c->green)/ ((2* diaphragme- 1)* (2* diaphragme- 1)); b+= (double)(c->blue)/ ((2* diaphragme- 1)* (2* diaphragme- 1)); } } // Dessin carré du diaphragme XSetForeground(dpy, gc, black); XDrawRectangle(dpy, w, gc, ((NPIX- 1)/ 2- diaphragme+ 1)* TPIX, ((NPIX- 1)/ 2- diaphragme+ 1)* TPIX, TPIX* (2* diaphragme- 1), TPIX* (2* diaphragme- 1)); // Partie centrale c->red= (unsigned int)(r); c->green= (unsigned int)(g); c->blue= (unsigned int)(b); c->pixel= c->blue+ (c->green<< 8)+ (c->red<< 16); XSetForeground(dpy, gc, c->pixel); XFillRectangle(dpy, w, gc, SUBWIDTH, 0, 2* SUBWIDTH, HEIGHT); // Partie droite sprintf(str[0], "X: %i; Y: %i", x, y); sprintf(str[1], "red : %i", c->red); sprintf(str[2], "green : %i", c->green); sprintf(str[3], "blue : %i", c->blue); sprintf(str[4], "diaph : %i", diaphragme); XSetForeground(dpy, gc, black); XFillRectangle(dpy, w, gc, 2* SUBWIDTH, 0, WIDTH, HEIGHT); XSetForeground(dpy, gc, white); for (i=0; i<5; i++) XDrawString(dpy, w, gc, 5+ 2* SUBWIDTH, 20*(i+ 1), str[i], strlen(str[i])); // Dessiner tout ca dans la fenetre XFlush(dpy); } // Initialisation void init(){ dpy= XOpenDisplay(NULL); if (dpy== NULL){ printf("Pas de display\n"); exit(1); } dpy_width= DisplayWidth(dpy, DefaultScreen(dpy)); dpy_height= DisplayHeight(dpy, DefaultScreen(dpy)); black= BlackPixel(dpy, DefaultScreen(dpy)); white= WhitePixel(dpy, DefaultScreen(dpy)); wroot= DefaultRootWindow(dpy); // Création fenetre w= XCreateSimpleWindow(dpy, wroot, 0, 0, WIDTH, HEIGHT, 0, black, black); // Donner un titre à la fenetre title= malloc(sizeof(XTextProperty)); title->value= (unsigned char *) "Colorimetre numerique"; title->encoding= XA_STRING; title->format= 8; title->nitems= strlen((char *) title->value); XSetWMName(dpy, w, title); // Selectionner events que l'on veut capter XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask | ExposureMask); // Afficher fenetre XMapWindow(dpy, w); // Creer un "Graphics Context" gc= XCreateGC(dpy, w, 0, NULL); // cmap Utile à XQueryColor : désactivé //cmap= DefaultColormap(dpy, DefaultScreen(dpy)); c= malloc(sizeof(XColor)); diaphragme= 1; // Attendre MapNotify event for(;;){ XNextEvent(dpy, &e); if (e.type == MapNotify) break; } XSync(dpy, False); // Grabber le curseur en lui assignant une forme (ici XC_cross) XGrabPointer(dpy, wroot, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, wroot, XCreateFontCursor(dpy, XC_cross), CurrentTime); // Déplacement du curseur au milieu de l'écran et 1er dessin x= dpy_width/ 2; y= dpy_height/ 2; XWarpPointer(dpy, None, wroot, 0, 0, 0, 0, x, y); redraw(); } // ----------------------------------------------------------- // Point entrée application // ----------------------------------------------------------- void main() { // Initialiser les variables init(); // Boucle principale for(;;){ XNextEvent(dpy, &e); // a : réduire diaphragme // z : augmenter diaphragme // esc : sortir du programme if (e.type== KeyPress){ if (XLookupKeysym(&e.xkey, 0)== XK_a){ diaphragme--; if (diaphragme< 1) diaphragme= 1; redraw(); } if (XLookupKeysym(&e.xkey, 0)== XK_z){ diaphragme++; if (2* diaphragme- 1> NPIX) diaphragme--; redraw(); } else if (XLookupKeysym(&e.xkey, 0)== XK_Escape){ break; } } // Mouvement curseur => redessiner fenetre else if (e.type== MotionNotify){ x= e.xmotion.x; y= e.xmotion.y; redraw(); } } // Libérer les resources XFree(image); XCloseDisplay(dpy); free(c); free(title); }

Conclusion :


Toutes les remarques sont les bienvenues.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.