Re: how to get a bitmap from the screen and then inside lisp?
- From: George Neuner <gneuner2@xxxxxxxxxxx>
- Date: Mon, 15 Dec 2008 17:27:54 -0500
On Mon, 15 Dec 2008 09:39:14 -0800 (PST), christophamort@xxxxxxxx
wrote:
Is there a fast way to get the screen content (or part of it) inside
the lisp workspace, maybe as an array? I experiment with pattern
matching and would like to search the content of the screen or some
area of it to find certain patterns.
Until yet I've used some (non lisp) programs to take a shot of the
screen, save it to hard disk and read it in again into the lisp
workspace. That is quiet slow ... no wonder!
I've tried several times to install openGL or GTK+ didn't get until
the end, errors with the cffi interface or my lisp acl 7 is not
compatible ... . There must be easier solutions, than to shoot with
canons on sparrows!
Any recommendations for a win user?
c.
ps.: acl has functions to do this (also slow) but sooner or later I
would like to switch to open source.
A bit off topic, but who cares 8-)
Getting pixels off the screen quickly is a bit complicated and you
have to do some decoding of Windows bitmap data structures. You
probably should write your grab function in C and call it with CFFI.
If you're pattern matching, it's probably best to separate the color
planes - pattern matching on color is tough and you'll probably want
to experiment with different ways of calculating power.
Windows uses a device independent R<<16|G<<8|B color pixel internally
and you'll get that from most application windows, but if you copy
directly from the screen it could be pixel or planar depending on the
display board.
I didn't have any ready code to show you, so I quickly hacked up the
following. It does _NO_ error checking except shockingly fatal, but
it shows the basic ideas. Planar displays are left as an exercise.
Be sure to read up on the Windows GDI and the functions and structures
used. Adding traps for all the possible errors will likely double the
length of the code.
------------------------------------------------------------
include <windows.h>
void GetWindowPixels( char *windowName,
int x, int y, int w, int h,
int *R,
int *G,
int *B )
{
HWND window;
HDC winDC, tmpDC;
HBITMAP bitmap;
BITMAP info;
RGBTRIPLE *rgb;
RGBQUAD *rgba;
int count;
BYTE *pixels;
// alloc buffer
pixels = (BYTE*) calloc( h * w, sizeof(RGBQUAD) );
// get the window handle
window = NULL;
if ( windowName != NULL )
{
window = FindWindow( NULL, windowName );
if ( window == NULL ) return;
}
// get window DC (or screen DC if window is NULL)
winDC = GetDC(window);
if (winDC == NULL) return;
// create temp DC
tmpDC = CreateCompatibleDC(winDC);
// create bitmap
bitmap = CreateCompatibleBitmap(winDC, w,h );
// copy desktop ROI to bitmap
SelectObject( tmpDC, bitmap );
BitBlt( tmpDC, 0,0,w,h , winDC, x,y , SRCCOPY );
SelectObject( tmpDC, (HBITMAP) NULL);
// extract pixels from bitmap.
// TODO: handle planar bitmaps
GetObject( bitmap, sizeof(info), &info );
switch ( info.bmBitsPixel )
{
case 24:
count = h * w * sizeof(RGBTRIPLE);
break;
case 32:
count = h * w * sizeof(RGBQUAD);
break;
}
GetBitmapBits( bitmap, count, pixels );
// extract colors for each pixel
count = h * w;
switch ( info.bmBitsPixel )
{
case 24:
rgb = (RGBTRIPLE*) pixels;
while ( --count >= 0 )
{
*R++ = rgb->rgbtRed;
*G++ = rgb->rgbtGreen;
*B++ = rgb->rgbtBlue;
rgb++;
}
break;
case 32:
rgba = (RGBQUAD*) pixels;
while ( --count >= 0 )
{
*R++ = rgba->rgbRed;
*G++ = rgba->rgbGreen;
*B++ = rgba->rgbBlue;
rgba++;
}
break;
}
// cleanup
if (pixels) free(pixels);
if (bitmap) DeleteObject(bitmap);
if (tmpDC) DeleteDC(tmpDC);
ReleaseDC(window,winDC);
}
------------------------------------------------------------
When you study the GDI, you'll encounter the function GetPixel and
wonder why I didn't use it. The answer is that it's slower than
molasses for a moderate to large ROI. GDI functions are system calls
and there is a fair amount of overhead for each call. Even though the
bitmap BLiT is harder to set up, it's 1 BLiT call vs (10s of)
thousands of GetPixel calls.
George
.
- Follow-Ups:
- Re: how to get a bitmap from the screen and then inside lisp?
- From: christophamort
- Re: how to get a bitmap from the screen and then inside lisp?
- From: GP lisper
- Re: how to get a bitmap from the screen and then inside lisp?
- References:
- how to get a bitmap from the screen and then inside lisp?
- From: christophamort
- how to get a bitmap from the screen and then inside lisp?
- Prev by Date: Re: Mathematica 7 compares to other languages
- Next by Date: Re: weird problem with sbcl and slime on Vista
- Previous by thread: Re: how to get a bitmap from the screen and then inside lisp?
- Next by thread: Re: how to get a bitmap from the screen and then inside lisp?
- Index(es):
Relevant Pages
|