I want to get the average color of the screen content when running XBMC to change the color of a TV ambient light. XBMC is running on a small HTPC with OpenGL ES 2.0 hardware (Raspberry Pi) running a Debian-derived distribution. I guess I have to read from the screen frame buffer in which XBMC draws using OpenGL. (At least, I think and hope that XBMC renders everything using OpenGL.)
Is it possible to read the OpenGL frame buffer representing the whole screen output? What am I going to need to access it? Do I also need an own render context to access the frame buffer of the screen? (I don't render anything by myself to the screen, I only want to read).
Efficiently calculating the average color is the next task. I'm thinking about reading every 8th or 16th pixel per row/column (would be enough, we are talking about 1080p HD movies) and then calculating the average on the CPU. Any ideas for a better solution are welcome.
You should take a look at the source code of Boblight.
Extending Boblight seems like a viable alternative (if it does not support what you need already!).
If not, look at src/clients/
folder. boblight-getpixel.c
(for MS Windows) and boblight-X11.c
are 'pixel grabbers'; standalone programs that do exactly what you need, and then communicate the grabbed color to the boblight server.
In boblight-X11.c
you have examples of using XShmGetImage
or the slower XGetImage
to read portions of the screen using X11/extensions/XShm.h
, a portion of that code does:
[...]
if(!XShmGetImage(dpy, root_win, xim, 0, 0, AllPlanes))
{
sleep(1);
pthread_mutex_unlock(&grabmutex);
return;
}
XSync(dpy, True);
for (x = 0; x < width; x += xadd)
{
for (y = 0; y < height; y += yadd)
{
pixel = XGetPixel(xim, x, y);
RGB[0] = (pixel >> 16) & 0xff;
RGB[1] = (pixel >> 8) & 0xff;
RGB[2] = (pixel >> 0) & 0xff;
/*add it to the RGB array*/
boblight_add_pixel (&config, RGB, x, y);
}
}
[...]