📄 rpng-x.c
字号:
if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) { fprintf(stderr, "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n", depth); return 2; } XMatchVisualInfo(display, screen, depth, (depth == 8)? PseudoColor : TrueColor, &visual_info); visual = visual_info.visual;#else if (depth != 16 && depth != 24 && depth != 32) { int visuals_matched = 0; Trace((stderr, "default depth is %d: checking other visuals\n", depth)) /* 24-bit first */ visual_info.screen = screen; visual_info.depth = 24; visual_list = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched); if (visuals_matched == 0) {/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */ fprintf(stderr, "default screen depth %d not supported, and no" " 24-bit visuals found\n", depth); return 2; } Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n", visuals_matched)) visual = visual_list[0].visual; depth = visual_list[0].depth;/* colormap_size = visual_list[0].colormap_size; visual_class = visual->class; visualID = XVisualIDFromVisual(visual); */ have_nondefault_visual = TRUE; need_colormap = TRUE; } else { XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info); visual = visual_info.visual; }#endif RMask = visual->red_mask; GMask = visual->green_mask; BMask = visual->blue_mask;/* GRR: add/check 8-bit support */ if (depth == 8 || need_colormap) { colormap = XCreateColormap(display, root, visual, AllocNone); if (!colormap) { fprintf(stderr, "XCreateColormap() failed\n"); return 2; } have_colormap = TRUE; } if (depth == 15 || depth == 16) { RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */ GShift = 15 - rpng_x_msb(GMask); BShift = 15 - rpng_x_msb(BMask); } else if (depth > 16) {#define NO_24BIT_MASKS#ifdef NO_24BIT_MASKS RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */ GShift = rpng_x_msb(GMask) - 7; BShift = rpng_x_msb(BMask) - 7;#else RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */ GShift = 7 - rpng_x_msb(GMask); BShift = 7 - rpng_x_msb(BMask);#endif } if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) { fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n"); return 2; }/*--------------------------------------------------------------------------- Finally, create the window. ---------------------------------------------------------------------------*/ attr.backing_store = Always; attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask; attrmask = CWBackingStore | CWEventMask; if (have_nondefault_visual) { attr.colormap = colormap; attr.background_pixel = 0; attr.border_pixel = 1; attrmask |= CWColormap | CWBackPixel | CWBorderPixel; } window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0, depth, InputOutput, visual, attrmask, &attr); if (window == None) { fprintf(stderr, "XCreateWindow() failed\n"); return 2; } else have_window = TRUE; if (depth == 8) XSetWindowColormap(display, window, colormap); if (!XStringListToTextProperty(&window_name, 1, pWindowName)) pWindowName = NULL; if (!XStringListToTextProperty(&icon_name, 1, pIconName)) pIconName = NULL; /* OK if any hints allocation fails; XSetWMProperties() allows NULLs */ if ((size_hints = XAllocSizeHints()) != NULL) { /* window will not be resizable */ size_hints->flags = PMinSize | PMaxSize; size_hints->min_width = size_hints->max_width = (int)image_width; size_hints->min_height = size_hints->max_height = (int)image_height; } if ((wm_hints = XAllocWMHints()) != NULL) { wm_hints->initial_state = NormalState; wm_hints->input = True; /* wm_hints->icon_pixmap = icon_pixmap; */ wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ; } if ((class_hints = XAllocClassHint()) != NULL) { class_hints->res_name = res_name; class_hints->res_class = res_class; } XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0, size_hints, wm_hints, class_hints); /* various properties and hints no longer needed; free memory */ if (pWindowName) XFree(pWindowName->value); if (pIconName) XFree(pIconName->value); if (size_hints) XFree(size_hints); if (wm_hints) XFree(wm_hints); if (class_hints) XFree(class_hints); XMapWindow(display, window); gc = XCreateGC(display, window, 0, &gcvalues); have_gc = TRUE;/*--------------------------------------------------------------------------- Fill window with the specified background color. ---------------------------------------------------------------------------*/ if (depth == 24 || depth == 32) { bg_pixel = ((ulg)bg_red << RShift) | ((ulg)bg_green << GShift) | ((ulg)bg_blue << BShift); } else if (depth == 16) { bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) | ((((ulg)bg_green << 8) >> GShift) & GMask) | ((((ulg)bg_blue << 8) >> BShift) & BMask); } else /* depth == 8 */ { /* GRR: add 8-bit support */ } XSetForeground(display, gc, bg_pixel); XFillRectangle(display, window, gc, 0, 0, image_width, image_height);/*--------------------------------------------------------------------------- Wait for first Expose event to do any drawing, then flush. ---------------------------------------------------------------------------*/ do XNextEvent(display, &e); while (e.type != Expose || e.xexpose.count); XFlush(display);/*--------------------------------------------------------------------------- Allocate memory for the X- and display-specific version of the image. ---------------------------------------------------------------------------*/ if (depth == 24 || depth == 32) { xdata = (uch *)malloc(4*image_width*image_height); pad = 32; } else if (depth == 16) { xdata = (uch *)malloc(2*image_width*image_height); pad = 16; } else /* depth == 8 */ { xdata = (uch *)malloc(image_width*image_height); pad = 8; } if (!xdata) { fprintf(stderr, PROGNAME ": unable to allocate image memory\n"); return 4; } ximage = XCreateImage(display, visual, depth, ZPixmap, 0, (char *)xdata, image_width, image_height, pad, 0); if (!ximage) { fprintf(stderr, PROGNAME ": XCreateImage() failed\n"); free(xdata); return 3; } /* to avoid testing the byte order every pixel (or doubling the size of * the drawing routine with a giant if-test), we arbitrarily set the byte * order to MSBFirst and let Xlib worry about inverting things on little- * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most * efficient approach (the giant if-test would be better), but in the * interest of clarity, we take the easy way out... */ ximage->byte_order = MSBFirst; return 0;} /* end function rpng_x_create_window() */static int rpng_x_display_image(void){ uch *src; char *dest; uch r, g, b, a; ulg i, row, lastrow = 0; ulg pixel; int ximage_rowbytes = ximage->bytes_per_line;/* int bpp = ximage->bits_per_pixel; */ Trace((stderr, "beginning display loop (image_channels == %d)\n", image_channels)) Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n", image_width, image_rowbytes, ximage_rowbytes)) Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel)) Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst? "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown"))) if (depth == 24 || depth == 32) { ulg red, green, blue; for (lastrow = row = 0; row < image_height; ++row) { src = image_data + row*image_rowbytes; dest = ximage->data + row*ximage_rowbytes; if (image_channels == 3) { for (i = image_width; i > 0; --i) { red = *src++; green = *src++; blue = *src++;#ifdef NO_24BIT_MASKS pixel = (red << RShift) | (green << GShift) | (blue << BShift); /* recall that we set ximage->byte_order = MSBFirst above */ /* GRR BUG: this assumes bpp == 32, but may be 24: */ *dest++ = (char)((pixel >> 24) & 0xff); *dest++ = (char)((pixel >> 16) & 0xff); *dest++ = (char)((pixel >> 8) & 0xff); *dest++ = (char)( pixel & 0xff);#else red = (RShift < 0)? red << (-RShift) : red >> RShift; green = (GShift < 0)? green << (-GShift) : green >> GShift; blue = (BShift < 0)? blue << (-BShift) : blue >> BShift; pixel = (red & RMask) | (green & GMask) | (blue & BMask); /* recall that we set ximage->byte_order = MSBFirst above */ *dest++ = (char)((pixel >> 24) & 0xff); *dest++ = (char)((pixel >> 16) & 0xff); *dest++ = (char)((pixel >> 8) & 0xff); *dest++ = (char)( pixel & 0xff);#endif } } else /* if (image_channels == 4) */ { for (i = image_width; i > 0; --i) { r = *src++; g = *src++; b = *src++; a = *src++; if (a == 255) { red = r; green = g; blue = b; } else if (a == 0) { red = bg_red; green = bg_green; blue = bg_blue; } else { /* this macro (from png.h) composites the foreground * and background values and puts the result into the * first argument */ alpha_composite(red, r, a, bg_red); alpha_composite(green, g, a, bg_green); alpha_composite(blue, b, a, bg_blue); } pixel = (red << RShift) | (green << GShift) | (blue << BShift); /* recall that we set ximage->byte_order = MSBFirst above */ *dest++ = (char)((pixel >> 24) & 0xff); *dest++ = (char)((pixel >> 16) & 0xff); *dest++ = (char)((pixel >> 8) & 0xff); *dest++ = (char)( pixel & 0xff); } } /* display after every 16 lines */ if (((row+1) & 0xf) == 0) { XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, (int)lastrow, image_width, 16); XFlush(display); lastrow = row + 1; } } } else if (depth == 16) { ush red, green, blue; for (lastrow = row = 0; row < image_height; ++row) { src = image_data + row*image_rowbytes; dest = ximage->data + row*ximage_rowbytes; if (image_channels == 3) { for (i = image_width; i > 0; --i) { red = ((ush)(*src) << 8); ++src; green = ((ush)(*src) << 8); ++src; blue = ((ush)(*src) << 8); ++src; pixel = ((red >> RShift) & RMask) | ((green >> GShift) & GMask) | ((blue >> BShift) & BMask); /* recall that we set ximage->byte_order = MSBFirst above */ *dest++ = (char)((pixel >> 8) & 0xff); *dest++ = (char)( pixel & 0xff); } } else /* if (image_channels == 4) */ { for (i = image_width; i > 0; --i) { r = *src++; g = *src++; b = *src++; a = *src++; if (a == 255) { red = ((ush)r << 8); green = ((ush)g << 8); blue = ((ush)b << 8); } else if (a == 0) { red = ((ush)bg_red << 8); green = ((ush)bg_green << 8); blue = ((ush)bg_blue << 8); } else { /* this macro (from png.h) composites the foreground * and background values and puts the result back into * the first argument (== fg byte here: safe) */ alpha_composite(r, r, a, bg_red); alpha_composite(g, g, a, bg_green); alpha_composite(b, b, a, bg_blue); red = ((ush)r << 8); green = ((ush)g << 8); blue = ((ush)b << 8); } pixel = ((red >> RShift) & RMask) | ((green >> GShift) & GMask) | ((blue >> BShift) & BMask); /* recall that we set ximage->byte_order = MSBFirst above */ *dest++ = (char)((pixel >> 8) & 0xff); *dest++ = (char)( pixel & 0xff); } } /* display after every 16 lines */ if (((row+1) & 0xf) == 0) { XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, (int)lastrow, image_width, 16); XFlush(display); lastrow = row + 1; } } } else /* depth == 8 */ { /* GRR: add 8-bit support */ } Trace((stderr, "calling final XPutImage()\n")) if (lastrow < image_height) { XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, (int)lastrow, image_width, image_height-lastrow); XFlush(display); } return 0;}static void rpng_x_cleanup(void){ if (image_data) { free(image_data); image_data = NULL; } if (ximage) { if (ximage->data) { free(ximage->data); /* we allocated it, so we free it */ ximage->data = (char *)NULL; /* instead of XDestroyImage() */ } XDestroyImage(ximage); ximage = NULL; } if (have_gc) XFreeGC(display, gc); if (have_window) XDestroyWindow(display, window); if (have_colormap) XFreeColormap(display, colormap); if (have_nondefault_visual) XFree(visual_list);}static int rpng_x_msb(ulg u32val){ int i; for (i = 31; i >= 0; --i) { if (u32val & 0x80000000L) break; u32val <<= 1; } return i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -