X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbccapture.C;h=e955a52730b03ed51f80c60dd21c5baa722cb1fc;hp=993cfe14fbc3279ee1cbf7c08943608416d5e441;hb=9d832a1fff11b11aaa1108c460690ed05e2bdc05;hpb=4fedf98530b3a6ff1ada6d2b9fbbc470e3df300c diff --git a/cinelerra-5.1/guicast/bccapture.C b/cinelerra-5.1/guicast/bccapture.C index 993cfe14..e955a527 100644 --- a/cinelerra-5.1/guicast/bccapture.C +++ b/cinelerra-5.1/guicast/bccapture.C @@ -23,15 +23,14 @@ #include "bcresources.h" #include "bcwindowbase.h" #include "bccmodels.h" +#include "bccolors.h" +#include "clip.h" #include "language.h" #include "vframe.h" #include #include #include - - - - +#include // Byte orders: // 24 bpp packed: bgr @@ -59,11 +58,10 @@ BC_Capture::~BC_Capture() int BC_Capture::init_window(const char *display_path) { int bits_per_pixel; - if(display_path && display_path[0] == 0) display_path = NULL; - if((display = XOpenDisplay(display_path)) == NULL) - { + if( display_path && display_path[0] == 0 ) display_path = NULL; + if( (display = XOpenDisplay(display_path)) == NULL ) { printf(_("cannot connect to X server.\n")); - if(getenv("DISPLAY") == NULL) + if( getenv("DISPLAY") == NULL ) printf(_("'DISPLAY' environment variable not set.\n")); exit(-1); return 1; @@ -93,8 +91,7 @@ int BC_Capture::init_window(const char *display_path) // test shared memory // This doesn't ensure the X Server is on the local host - if(use_shm && !XShmQueryExtension(display)) - { + if( use_shm && !XShmQueryExtension(display) ) { use_shm = 0; } return 0; @@ -104,14 +101,12 @@ int BC_Capture::init_window(const char *display_path) int BC_Capture::allocate_data() { // try shared memory - if(!display) return 1; - if(use_shm) - { + if( !display ) return 1; + if( use_shm ) { ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h); shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0600); - if(shm_info.shmid == -1) - { + if( shm_info.shmid == -1 ) { perror("BC_Capture::allocate_data shmget"); abort(); } @@ -124,16 +119,14 @@ int BC_Capture::allocate_data() BC_Resources::error = 0; XShmAttach(display, &shm_info); XSync(display, False); - if(BC_Resources::error) - { + if( BC_Resources::error ) { XDestroyImage(ximage); shmdt(shm_info.shmaddr); use_shm = 0; } } - if(!use_shm) - { + if( !use_shm ) { // need to use bytes_per_line for some X servers data = 0; ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0); @@ -144,8 +137,7 @@ int BC_Capture::allocate_data() } row_data = new unsigned char*[h]; - for(int i = 0; i < h; i++) - { + for( int i = 0; i < h; i++ ) { row_data[i] = &data[i * ximage->bytes_per_line]; } // This differs from the depth parameter of the top_level. @@ -155,17 +147,14 @@ int BC_Capture::allocate_data() int BC_Capture::delete_data() { - if(!display) return 1; - if(data) - { - if(use_shm) - { + if( !display ) return 1; + if( data ) { + if( use_shm ) { XShmDetach(display, &shm_info); XDestroyImage(ximage); shmdt(shm_info.shmaddr); } - else - { + else { XDestroyImage(ximage); } @@ -181,31 +170,22 @@ int BC_Capture::get_w() { return w; } int BC_Capture::get_h() { return h; } // Capture a frame from the screen -#define CAPTURE_FRAME_HEAD \ - for(int i = 0; i < h; i++) \ - { \ - unsigned char *input_row = row_data[i]; \ - unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \ - for(int j = 0; j < w; j++) \ - { - -#define CAPTURE_FRAME_TAIL \ - } \ - } +#define RGB_TO_YUV(y, u, v, r, g, b) { \ + YUV::yuv.rgb_to_yuv_8(r, g, b, y, u, v); \ + bclamp(y, 0,0xff); bclamp(u, 0,0xff); bclamp(v, 0,0xff); } - - -int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1) +int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1, + int do_cursor) // the scale of the cursor if nonzero { - if(!display) return 1; - if(x1 < 0) x1 = 0; - if(y1 < 0) y1 = 0; - if(x1 > get_top_w() - w) x1 = get_top_w() - w; - if(y1 > get_top_h() - h) y1 = get_top_h() - h; + if( !display ) return 1; + if( x1 < 0 ) x1 = 0; + if( y1 < 0 ) y1 = 0; + if( x1 > get_top_w() - w ) x1 = get_top_w() - w; + if( y1 > get_top_h() - h ) y1 = get_top_h() - h; // Read the raw data - if(use_shm) + if( use_shm ) XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff); else XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0); @@ -216,6 +196,72 @@ int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1) frame->get_w(), frame->get_h(), bitmap_color_model, frame->get_color_model(), 0, frame->get_w(), w); + + if( do_cursor ) { + XFixesCursorImage *cursor; + cursor = XFixesGetCursorImage(display); + if( cursor ) { +//printf("BC_Capture::capture_frame %d cursor=%p colormodel=%d\n", +// __LINE__, cursor, frame->get_color_model()); + int scale = do_cursor; + int cursor_x = cursor->x - x1 - cursor->xhot * scale; + int cursor_y = cursor->y - y1 - cursor->yhot * scale; + int w = frame->get_w(); + int h = frame->get_h(); + for( int i = 0; i < cursor->height; i++ ) { + for( int yscale = 0; yscale < scale; yscale++ ) { + if( cursor_y + i * scale + yscale >= 0 && + cursor_y + i * scale + yscale < h ) { + unsigned char *src = (unsigned char*)(cursor->pixels + + i * cursor->width); + int dst_y = cursor_y + i * scale + yscale; + int dst_x = cursor_x; + for( int j = 0; j < cursor->width; j++ ) { + for( int xscale = 0; xscale < scale ; xscale++ ) { + if( cursor_x + j * scale + xscale >= 0 && + cursor_x + j * scale + xscale < w ) { + int a = src[3]; + int invert_a = 0xff - a; + int r = src[2]; + int g = src[1]; + int b = src[0]; + switch( frame->get_color_model() ) { + case BC_RGB888: { + unsigned char *dst = frame->get_rows()[dst_y] + + dst_x * 3; + dst[0] = (r * a + dst[0] * invert_a) / 0xff; + dst[1] = (g * a + dst[1] * invert_a) / 0xff; + dst[2] = (b * a + dst[2] * invert_a) / 0xff; + break; } + + case BC_YUV420P: { + unsigned char *dst_y_ = frame->get_y() + + dst_y * w + dst_x; + unsigned char *dst_u = frame->get_u() + + (dst_y / 2) * (w / 2) + (dst_x / 2); + unsigned char *dst_v = frame->get_v() + + (dst_y / 2) * (w / 2) + (dst_x / 2); + int y, u, v; + RGB_TO_YUV(y, u, v, r, g, b); + + *dst_y_ = (y * a + *dst_y_ * invert_a) / 0xff; + *dst_u = (u * a + *dst_u * invert_a) / 0xff; + *dst_v = (v * a + *dst_v * invert_a) / 0xff; + break; } + } + } + dst_x++; + } + src += sizeof(long); + } + } + } + } + +// This frees cursor->pixels + XFree(cursor); + } + } return 0; }