void i_box_filled(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_color *val) { i_img_dim x, y, width; i_palidx index; dIMCTXim(im); im_log((aIMCTX,1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n", im, i_DFcp(x1, y1), i_DFcp(x2,y2) ,val)); if (x1 > x2 || y1 > y2 || x2 < 0 || y2 < 0 || x1 >= im->xsize || y1 > im->ysize) return; if (x1 < 0) x1 = 0; if (x2 >= im->xsize) x2 = im->xsize - 1; if (y1 < 0) y1 = 0; if (y2 >= im->ysize) y2 = im->ysize - 1; width = x2 - x1 + 1; if (im->type == i_palette_type && i_findcolor(im, val, &index)) { i_palidx *line = mymalloc(sizeof(i_palidx) * width); for (x = 0; x < width; ++x) line[x] = index; for (y = y1; y <= y2; ++y) i_ppal(im, x1, x2+1, y, line); myfree(line); } else { i_color *line = mymalloc(sizeof(i_color) * width); for (x = 0; x < width; ++x) line[x] = *val; for (y = y1; y <= y2; ++y) i_plin(im, x1, x2+1, y, line); myfree(line); } }
i_img * imss_x11(unsigned long display_ul, int window_id, int left, int top, int right, int bottom) { Display *display = (Display *)display_ul; int own_display = 0; /* non-zero if we connect */ XImage *image; XWindowAttributes attr; i_img *result; i_color *line, *cp; int x, y; XColor *colors; XErrorHandler old_handler; int width, height; i_clear_error(); /* we don't want the default noisy error handling */ old_handler = XSetErrorHandler(my_handler); if (!display) { display = XOpenDisplay(NULL); ++own_display; if (!display) { XSetErrorHandler(old_handler); i_push_error(0, "No display supplied and cannot connect"); return NULL; } } if (!window_id) { int screen = DefaultScreen(display); window_id = RootWindow(display, screen); } if (!XGetWindowAttributes(display, window_id, &attr)) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "Cannot XGetWindowAttributes"); return NULL; } /* adjust negative/zero values to window size */ if (left < 0) left += attr.width; if (top < 0) top += attr.height; if (right <= 0) right += attr.width; if (bottom <= 0) bottom += attr.height; /* clamp */ if (left < 0) left = 0; if (right > attr.width) right = attr.width; if (top < 0) top = 0; if (bottom > attr.height) bottom = attr.height; /* validate */ if (right <= left || bottom <= top) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "image would be empty"); return NULL; } width = right - left; height = bottom - top; image = XGetImage(display, window_id, left, top, width, height, -1, ZPixmap); if (!image) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "Cannot XGetImage"); return NULL; } result = i_img_8_new(width, height, 3); line = mymalloc(sizeof(i_color) * width); colors = mymalloc(sizeof(XColor) * width); for (y = 0; y < height; ++y) { cp = line; /* XQueryColors seems to be a round-trip, so do one big request instead of one per pixel */ for (x = 0; x < width; ++x) { colors[x].pixel = XGetPixel(image, x, y); } XQueryColors(display, attr.colormap, colors, width); for (x = 0; x < width; ++x) { cp->rgb.r = colors[x].red >> 8; cp->rgb.g = colors[x].green >> 8; cp->rgb.b = colors[x].blue >> 8; ++cp; } i_plin(result, 0, width, y, line); } myfree(line); myfree(colors); XDestroyImage(image); XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_tags_setn(&result->tags, "ss_window_width", attr.width); i_tags_setn(&result->tags, "ss_window_height", attr.height); i_tags_set(&result->tags, "ss_type", "X11", 3); i_tags_setn(&result->tags, "ss_left", left); i_tags_setn(&result->tags, "ss_top", top); return result; }
i_img_dim (i_plin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { return i_plin(im, l, r, y, vals); }
i_img * imss_darwin(i_img_dim left, i_img_dim top, i_img_dim right, i_img_dim bottom) { CGDisplayCount count; CGDisplayErr err; CGRect rect; CGLPixelFormatObj pix; GLint npix; CGLContextObj ctx; i_img *im; CGDirectDisplayID disp; i_img_dim screen_width, screen_height; i_img_dim width, height; CGLPixelFormatAttribute pix_attrs[] = { kCGLPFADisplayMask, 0, /* filled in later */ kCGLPFAColorSize, 24, kCGLPFAAlphaSize, 0, kCGLPFAFullScreen, 0 }; i_clear_error(); disp = CGMainDisplayID(); if (!disp) { i_push_error(0, "No main display"); return NULL; } /* for now, only interested in the first display */ rect = CGDisplayBounds(disp); screen_width = rect.size.width; screen_height = rect.size.height; /* adjust negative/zero values to window size */ if (left < 0) left += screen_width; if (top < 0) top += screen_height; if (right <= 0) right += screen_width; if (bottom <= 0) bottom += screen_height; /* clamp */ if (left < 0) left = 0; if (right > screen_width) right = screen_width; if (top < 0) top = 0; if (bottom > screen_height) bottom = screen_height; /* validate */ if (right <= left || bottom <= top) { i_push_error(0, "image would be empty"); return NULL; } width = right - left; height = bottom - top; /* select a pixel format */ pix_attrs[1] = CGDisplayIDToOpenGLDisplayMask(disp); err = CGLChoosePixelFormat(pix_attrs, &pix, &npix); if (err) { i_push_errorf(err, "CGLChoosePixelFormat: %d", (int)err); return NULL; } if (!npix) { i_push_error(0, "No pixel format found - hidden display?"); return NULL; } /* make ourselves a context */ err = CGLCreateContext(pix, NULL, &ctx); CGLDestroyPixelFormat(pix); if (err) { i_push_errorf(err, "CGLCreateContext: %d", (int)err); return NULL; } err = CGLSetCurrentContext(ctx); if (err) { i_push_errorf(err, "CGLSetCurrentContext: %d", (int)err); return NULL; } err = CGLSetFullScreen(ctx); if (err) { i_push_errorf(err, "CGLSetFullScreen: %d", (int)err); return NULL; } /* capture */ im = i_img_8_new(width, height, 3); if (im) { size_t line_size = width * 4; size_t buf_size = line_size * height; unsigned char *buf = malloc(buf_size); i_img_dim y = height - 1; i_color *bufp = (i_color *)buf; /* hackish */ /* GL has the vertical axis going from bottom to top, so translate it */ glReadBuffer(GL_FRONT); glReadPixels(left, screen_height - top - height, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); /* transfer */ while (y >= 0) { i_plin(im, 0, width, y, bufp); bufp += width; --y; } free(buf); i_tags_setn(&im->tags, "ss_window_width", width); i_tags_setn(&im->tags, "ss_window_height", height); i_tags_set(&im->tags, "ss_type", "Darwin", 6); i_tags_set(&im->tags, "ss_variant", "<11", 3); i_tags_setn(&im->tags, "ss_left", left); i_tags_setn(&im->tags, "ss_top", top); } /* clean up */ CGLSetCurrentContext(NULL); CGLDestroyContext(ctx); return im; }