Este post va de programación. La mayoría de veces que hacemos programas que tienen que tratar con imágenes se da el caso de que el programa trabajará en un entorno de escritorio con su gestor de ventanas y con sus librerías para hacer interfaces gráficas. Pero como he dicho, eso será la mayoría de veces, que no todas.
Algunas veces nos encontraremos con que como mucho podremos hacer funcionar el servidor gráfico X, pero nada de GTK, Qt, KDE, XFCE, Enlightenment o pijadas por el estilo. Esto nos puede suceder cuando estamos programando algo para una máquina con pocos recursos y aun así tenemos que mostrar alguna que otra imagen por pantalla.
Una de las librerías más eficientes que existen para tratar imágenes es OpenCV . OpenCV provee (a parte de las rutinas de tratamiento de imagen) rutinas que permiten mostrar por pantalla las imágenes, en particular, permite mostrarlas en ventanas. El problema de estas rutinas es que dependen o bien de GTK o bien del entorno gráfico de Windows o bien de las librerías Carbon de Mac OS X . Por ello mostraré como transformar un objeto imagen de OpenCV en uno de las librerías Xlib para poder mostrar por pantalla las imágenes incluso en los entornos más austeros.
OpenCV maneja las imágenes a través de punteros a estructuras del tipo IplImage, Xlib las maneja a través de punteros a estructuras del tipo XImage. El siguiente código es una función que acepta como argumento un puntero a una estructura del tipo IplImage y devuelve un puntero a una estructura del tipo XImage (a la que luego se le tendrá que aplicar la función XDestroyImage una vez que hayamos acabado de usarla para liberar recursos). Me dejo de rollos y os cuelgo el código:
Ximage* OCVtoX(Display *display, IplImage* img, int depth) {
char *buf_result;
Ximage *img_result;
uchar *ptr, *ptr2;
uint n;
buf_result = (char*)malloc(sizeof(char)*4*img->width*img->height);
if(buf_result==0)
return 0;
img_result = XCreateImage(display, CopyFromParent, depth,
ZPixmap, 0, buf_result, img->width, img->height, 32, 0);
if(img_result==0) {
free(buf_result);
return 0;
}
// Normalmente sólo hay 3 canales, pero por si acaso hubiera 4
n = img->nChannels;
for(y=0; y < img->height; y++) {
ptr = (uchar*) (img->imageData + y*img->widthStep);
ptr2 = (uchar*) (buf_result + y*4*img->width);
for(x=0; x < img->width; x++) {
ptr2[4*x]=ptr[n*x];
ptr2[4*x+1]=ptr[n*x+1];
ptr2[4*x+2]=ptr[n*x+2];
}
}
return img_result;
}
Espero que a alguien le sirva... :p . (Por cierto, está licenciado bajo GPL 3.0 , xD.. aunque no lo vaya a utilizar nadie)