@ -6,7 +6,7 @@
*/
/**
* \ file net_java_sip_communicator_impl_neomedia_imgstreaming_ Unix ScreenCapture. c
* \ file net_java_sip_communicator_impl_neomedia_imgstreaming_ Native ScreenCapture. c
* \ brief X11 screen capture .
* \ author Sebastien Vincent
* \ date 2009
@ -14,6 +14,17 @@
# include <stdio.h>
# include <stdlib.h>
# if defined(_WIN32) || defined(_WIN64)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <wingdi.h>
typedef __int32 int32_t ;
# else /* Unix */
# include <stdint.h>
# include <sys/types.h>
@ -24,7 +35,166 @@
# include <X11/Xutil.h>
# include <X11/extensions/XShm.h>
# include "net_java_sip_communicator_impl_neomedia_imgstreaming_UnixScreenCapture.h"
# endif
# include "net_java_sip_communicator_impl_neomedia_imgstreaming_NativeScreenCapture.h"
# if defined(_WIN32) || defined (_WIN64)
/**
* \ brief Grab Windows screen .
* \ param data array that will contain screen capture
* \ param x x position to start capture
* \ param y y position to start capture
* \ param w capture width
* \ param h capture height
* \ return 0 if success , - 1 otherwise
*/
static int windows_grab_screen ( int32_t * data , int32_t x , int32_t y , int32_t w , int32_t h )
{
static const RGBQUAD redColor = { 0x00 , 0x00 , 0xFF , 0x00 } ;
static const RGBQUAD greenColor = { 0x00 , 0xFF , 0x00 , 0x00 } ;
static const RGBQUAD blueColor = { 0xFF , 0x00 , 0x00 , 0x00 } ;
HDC desktop = NULL ;
HDC dest = NULL ;
HBITMAP bitmap ;
HBITMAP oldBitmap ;
int width = 0 ;
int height = 0 ;
size_t size = 0 ;
BITMAPINFO * bitmap_info = NULL ;
BITMAPINFOHEADER * bitmap_hdr = NULL ;
RGBQUAD * pixels = NULL ;
size_t i = 0 ;
/* get handle to the entire screen of Windows */
desktop = GetDC ( NULL ) ;
if ( ! desktop )
{
fprintf ( stderr , " GetDC failed! \n " ) ;
return - 1 ;
}
/* get resolution */
width = GetDeviceCaps ( desktop , HORZRES ) ;
height = GetDeviceCaps ( desktop , VERTRES ) ;
/* check that user-defined parameters are in image */
if ( ( w + x ) > width | | ( h + y ) > height )
{
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
size = w * h ;
/* fprintf(stderr, "Resolution: %dx%d\n", width, height); */
dest = CreateCompatibleDC ( desktop ) ;
if ( ! dest )
{
fprintf ( stderr , " CreateCompatibleDC failed! \n " ) ;
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
bitmap = CreateCompatibleBitmap ( desktop , width , height ) ;
if ( ! bitmap )
{
fprintf ( stderr , " CreateCompatibleBitmap failed! \n " ) ;
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
/* select bitmap to be used by DC */
oldBitmap = SelectObject ( dest , bitmap ) ;
if ( BitBlt ( dest , 0 , 0 , w , h , desktop , x , y , SRCCOPY | CAPTUREBLT ) = = FALSE )
{
fprintf ( stderr , " BitBlt failed \n " ) ;
SelectObject ( dest , oldBitmap ) ; /* restore old state before delete */
DeleteDC ( dest ) ;
DeleteObject ( bitmap ) ;
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
/* allocate memory for bitmap header, it consists
* of header size and the uncompressed pixels
* GetDiBits with BI_BITFIELDS requires array of 3 RBGQUAD
* structures and BITMAPINFO structure has just one allocated
* RGBQUAD array
*/
bitmap_info = malloc ( sizeof ( BITMAPINFO ) + 3 * sizeof ( RGBQUAD ) + ( size * 4 ) ) ;
if ( ! bitmap_info )
{
fprintf ( stderr , " malloc failed \n " ) ;
SelectObject ( dest , oldBitmap ) ; /* restore old state before delete */
DeleteDC ( dest ) ;
DeleteObject ( bitmap ) ;
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
bitmap_hdr = & bitmap_info - > bmiHeader ;
bitmap_hdr - > biSize = sizeof ( BITMAPINFOHEADER ) ;
bitmap_hdr - > biWidth = w ;
bitmap_hdr - > biHeight = - h ; /* otherwise inverse screen */
bitmap_hdr - > biPlanes = 1 ;
bitmap_hdr - > biCompression = BI_BITFIELDS ;
bitmap_hdr - > biBitCount = 32 ;
bitmap_hdr - > biSizeImage = 0 ;
bitmap_hdr - > biXPelsPerMeter = 0 ;
bitmap_hdr - > biYPelsPerMeter = 0 ;
bitmap_hdr - > biClrImportant = 0 ;
bitmap_hdr - > biClrUsed = 0 ;
/* set up color */
/* red */
bitmap_info - > bmiColors [ 0 ] = redColor ;
/* green */
bitmap_info - > bmiColors [ 1 ] = greenColor ;
/* blue */
bitmap_info - > bmiColors [ 2 ] = blueColor ;
/* first data pixel begins after the array of color mask */
pixels = & bitmap_info - > bmiColors [ 2 ] ;
pixels + + ;
/* get raw bytes */
if ( GetDIBits ( dest , bitmap , 0 , height , pixels , bitmap_info , DIB_RGB_COLORS ) = = 0 )
{
fprintf ( stderr , " GetDIBits failed! \n " ) ;
free ( bitmap_info ) ;
SelectObject ( dest , oldBitmap ) ; /* restore old state before delete */
DeleteDC ( dest ) ;
DeleteObject ( bitmap ) ;
ReleaseDC ( NULL , desktop ) ;
return - 1 ;
}
for ( i = 0 ; i < size ; i + + )
{
RGBQUAD * pixel = & pixels [ i ] ;
data [ i ] = 0xFF000000 | pixel - > rgbRed < < 16 | pixel - > rgbGreen < < 8 | pixel - > rgbBlue ;
}
/* cleanup */
free ( bitmap_info ) ;
SelectObject ( dest , oldBitmap ) ; /* restore old state before delete */
DeleteDC ( dest ) ;
DeleteObject ( bitmap ) ;
ReleaseDC ( NULL , desktop ) ;
return 0 ;
}
# else /* Unix */
/**
* \ brief Grab X11 screen .
@ -190,18 +360,20 @@ static int x11_grab_screen(const char* x11display, int32_t* data, int32_t x, int
return 0 ;
}
# endif
/**
* \ brief JNI native method to grab desktop screen and retrieve ARGB pixels .
* \ param env JVM environment
* \ param obj UnixScreenCapture Java object
* \ param obj NativeScreenCapture Java class
* \ param x x position to start capture
* \ param y y position to start capture
* \ param width capture width
* \ param height capture height
* \ return array of ARGB pixels ( jint )
*/
JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_ Unix ScreenCapture_grabScreen
( JNIEnv * env , j object obj , jint x , jint y , jint width , jint height )
JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstreaming_ Native ScreenCapture_grabScreen
( JNIEnv * env , j class obj , jint x , jint y , jint width , jint height )
{
int32_t * data = NULL ; /* jint is always four-bytes signed integer */
size_t size = width * height ;
@ -223,7 +395,11 @@ JNIEXPORT jintArray JNICALL Java_net_java_sip_communicator_impl_neomedia_imgstre
return NULL ;
}
# if defined (_WIN32) || defined(_WIN64)
if ( windows_grab_screen ( data , x , y , width , height ) = = - 1 )
# else /* Unix */
if ( x11_grab_screen ( NULL , data , x , y , width , height ) = = - 1 )
# endif
{
( * env ) - > ReleaseIntArrayElements ( env , ret , data , 0 ) ;
return NULL ;