81 #define PROGNAME "rpng-x" 82 #define LONGNAME "Simple PNG Viewer for X" 83 #define VERSION "2.01 of 16 March 2008" 84 #define RESNAME "rpng" 85 #define RESCLASS "Rpng" 92 #include <X11/Xutil.h> 94 #include <X11/keysym.h> 106 #define alpha_composite(composite, fg, alpha, bg) { \ 107 ush temp = ((ush)(fg)*(ush)(alpha) + \ 108 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ 109 (composite) = (uch)((temp + (temp >> 8)) >> 8); \ 114 static int rpng_x_create_window(
void);
115 static int rpng_x_display_image(
void);
116 static void rpng_x_cleanup(
void);
117 static int rpng_x_msb(
ulg u32val);
120 static char titlebar[1024], *window_name = titlebar;
123 static char *res_name =
RESNAME;
129 static uch bg_red=0, bg_green=0, bg_blue=0;
131 static double display_exponent;
134 static int image_channels;
138 static char *displayname;
139 static XImage *ximage;
140 static Display *display;
142 static Visual *visual;
143 static XVisualInfo *visual_list;
144 static int RShift, GShift, BShift;
145 static ulg RMask, GMask, BMask;
146 static Window window;
148 static Colormap colormap;
150 static int have_nondefault_visual =
FALSE;
151 static int have_colormap =
FALSE;
152 static int have_window =
FALSE;
153 static int have_gc =
FALSE;
162 int main(
int argc,
char **argv)
172 double CRT_exponent = 2.2;
173 double default_display_exponent;
178 displayname = (
char *)
NULL;
189 LUT_exponent = 1.0 / 2.2;
195 LUT_exponent = 1.0 / 1.7;
198 infile = fopen(
"/etc/config/system.glGammaVal",
"r");
202 fgets(tmpline, 80,
infile);
204 sgi_gamma = atof(tmpline);
206 LUT_exponent = 1.0 / sgi_gamma;
208 #elif defined(Macintosh) 209 LUT_exponent = 1.8 / 2.61;
219 default_display_exponent = LUT_exponent * CRT_exponent;
227 if ((p = getenv(
"SCREEN_GAMMA")) !=
NULL)
228 display_exponent = atof(p);
230 display_exponent = default_display_exponent;
235 while (*++argv && !error) {
236 if (!strncmp(*argv,
"-display", 2)) {
241 }
else if (!strncmp(*argv,
"-gamma", 2)) {
245 display_exponent = atof(*argv);
246 if (display_exponent <= 0.0)
249 }
else if (!strncmp(*argv,
"-bgcolor", 2)) {
254 if (strlen(bgstr) != 7 || bgstr[0] !=
'#')
279 "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n" 280 " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" 281 " exp \ttransfer-function exponent (``gamma'') of the display\n" 282 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" 283 "\t\t to the product of the lookup-table exponent (varies)\n" 284 "\t\t and the CRT exponent (usually 2.2); must be positive\n" 285 " bg \tdesired background color in 7-character hex RGB format\n" 286 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" 287 "\t\t used with transparent images\n" 288 "\nPress Q, Esc or mouse button 1 (within image window, after image\n" 289 "is displayed) to quit.\n" 290 "\n",
PROGNAME, default_display_exponent);
303 ": [%s] is not a PNG file: incorrect signature\n",
308 ": [%s] has bad IHDR (libpng longjmp)\n",
filename);
311 fprintf(stderr,
PROGNAME ": insufficient memory\n");
315 ": unknown readpng_init() error\n");
320 display = XOpenDisplay(displayname);
323 fprintf(stderr,
PROGNAME ": can't open X display [%s]\n",
324 displayname? displayname :
"default");
334 fprintf(stderr,
PROGNAME ": aborting.\n");
341 alen = strlen(appname);
343 if (alen + flen + 3 > 1023)
344 sprintf(titlebar,
"%s: ...%s", appname,
filename+(alen+flen+6-1023));
346 sprintf(titlebar,
"%s: %s", appname,
filename);
356 sscanf(bgstr+1,
"%2x%2x%2x", &r, &g, &b);
363 ": libpng error while checking for background color\n");
371 if (rpng_x_create_window())
377 Trace((stderr,
"calling readpng_get_image()\n"))
380 Trace((stderr,
"done with readpng_get_image()\n"))
390 fprintf(stderr,
PROGNAME ": unable to decode PNG image\n");
397 Trace((stderr,
"calling rpng_x_display_image()\n"))
398 if (rpng_x_display_image()) {
402 Trace((stderr,
"done with rpng_x_display_image()\n"))
408 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
412 XNextEvent(display, &e);
413 while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
414 !(e.type == KeyPress &&
415 ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
429 static int rpng_x_create_window(
void)
432 int need_colormap =
FALSE;
439 XSetWindowAttributes attr;
440 XTextProperty windowName, *pWindowName = &windowName;
441 XTextProperty iconName, *pIconName = &iconName;
442 XVisualInfo visual_info;
443 XSizeHints *size_hints;
445 XClassHint *class_hints;
448 screen = DefaultScreen(display);
449 depth = DisplayPlanes(display, screen);
450 root = RootWindow(display, screen);
453 XSynchronize(display, True);
460 "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
465 XMatchVisualInfo(display, screen,
depth,
466 (
depth == 8)? PseudoColor : TrueColor, &visual_info);
467 visual = visual_info.visual;
470 int visuals_matched = 0;
472 Trace((stderr,
"default depth is %d: checking other visuals\n",
476 visual_info.screen = screen;
477 visual_info.depth = 24;
478 visual_list = XGetVisualInfo(display,
479 VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
480 if (visuals_matched == 0) {
482 fprintf(stderr,
"default screen depth %d not supported, and no" 483 " 24-bit visuals found\n",
depth);
486 Trace((stderr,
"XGetVisualInfo() returned %d 24-bit visuals\n",
488 visual = visual_list[0].visual;
489 depth = visual_list[0].depth;
495 have_nondefault_visual =
TRUE;
496 need_colormap =
TRUE;
498 XMatchVisualInfo(display, screen,
depth, TrueColor, &visual_info);
499 visual = visual_info.visual;
503 RMask = visual->red_mask;
504 GMask = visual->green_mask;
505 BMask = visual->blue_mask;
508 if (
depth == 8 || need_colormap) {
509 colormap = XCreateColormap(display, root, visual, AllocNone);
511 fprintf(stderr,
"XCreateColormap() failed\n");
514 have_colormap =
TRUE;
517 RShift = 15 - rpng_x_msb(RMask);
518 GShift = 15 - rpng_x_msb(GMask);
519 BShift = 15 - rpng_x_msb(BMask);
520 }
else if (
depth > 16) {
521 #define NO_24BIT_MASKS 522 #ifdef NO_24BIT_MASKS 523 RShift = rpng_x_msb(RMask) - 7;
524 GShift = rpng_x_msb(GMask) - 7;
525 BShift = rpng_x_msb(BMask) - 7;
527 RShift = 7 - rpng_x_msb(RMask);
528 GShift = 7 - rpng_x_msb(GMask);
529 BShift = 7 - rpng_x_msb(BMask);
532 if (
depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
533 fprintf(stderr,
"rpng internal logic error: negative X shift(s)!\n");
541 attr.backing_store = Always;
542 attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
543 attrmask = CWBackingStore | CWEventMask;
544 if (have_nondefault_visual) {
545 attr.colormap = colormap;
546 attr.background_pixel = 0;
547 attr.border_pixel = 1;
548 attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
552 depth, InputOutput, visual, attrmask, &attr);
554 if (window == None) {
555 fprintf(stderr,
"XCreateWindow() failed\n");
561 XSetWindowColormap(display, window, colormap);
563 if (!XStringListToTextProperty(&window_name, 1, pWindowName))
565 if (!XStringListToTextProperty(&icon_name, 1, pIconName))
570 if ((size_hints = XAllocSizeHints()) !=
NULL) {
572 size_hints->flags = PMinSize | PMaxSize;
577 if ((wm_hints = XAllocWMHints()) !=
NULL) {
578 wm_hints->initial_state = NormalState;
579 wm_hints->input = True;
581 wm_hints->flags = StateHint | InputHint ;
584 if ((class_hints = XAllocClassHint()) !=
NULL) {
585 class_hints->res_name = res_name;
586 class_hints->res_class = res_class;
589 XSetWMProperties(display, window, pWindowName, pIconName,
NULL, 0,
590 size_hints, wm_hints, class_hints);
594 XFree(pWindowName->value);
596 XFree(pIconName->value);
604 XMapWindow(display, window);
606 gc = XCreateGC(display, window, 0, &gcvalues);
614 bg_pixel = ((
ulg)bg_red << RShift) |
615 ((
ulg)bg_green << GShift) |
616 ((
ulg)bg_blue << BShift);
617 }
else if (
depth == 16) {
618 bg_pixel = ((((
ulg)bg_red << 8) >> RShift) & RMask) |
619 ((((
ulg)bg_green << 8) >> GShift) & GMask) |
620 ((((
ulg)bg_blue << 8) >> BShift) & BMask);
627 XSetForeground(display, gc, bg_pixel);
635 XNextEvent(display, &e);
636 while (e.type != Expose || e.xexpose.count);
647 }
else if (
depth == 16) {
656 fprintf(stderr,
PROGNAME ": unable to allocate image memory\n");
660 ximage = XCreateImage(display, visual,
depth, ZPixmap, 0,
664 fprintf(stderr,
PROGNAME ": XCreateImage() failed\n");
686 static int rpng_x_display_image(
void)
693 int ximage_rowbytes = ximage->bytes_per_line;
697 Trace((stderr,
"beginning display loop (image_channels == %d)\n",
699 Trace((stderr,
" (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
701 Trace((stderr,
" (bpp = %d)\n", ximage->bits_per_pixel))
702 Trace((stderr,
" (byte_order = %s)\n", ximage->byte_order ==
MSBFirst?
703 "MSBFirst" : (ximage->byte_order ==
LSBFirst?
"LSBFirst" :
"unknown")))
710 dest = ximage->data + row*ximage_rowbytes;
711 if (image_channels == 3) {
716 #ifdef NO_24BIT_MASKS 717 pixel = (red << RShift) |
722 *dest++ = (char)((pixel >> 24) & 0xff);
723 *dest++ = (char)((pixel >> 16) & 0xff);
724 *dest++ = (char)((pixel >> 8) & 0xff);
725 *dest++ = (char)( pixel & 0xff);
727 red = (RShift < 0)? red << (-RShift) : red >> RShift;
728 green = (GShift < 0)? green << (-GShift) : green >> GShift;
729 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
730 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
732 *dest++ = (char)((pixel >> 24) & 0xff);
733 *dest++ = (char)((pixel >> 16) & 0xff);
734 *dest++ = (char)((pixel >> 8) & 0xff);
735 *dest++ = (char)( pixel & 0xff);
760 pixel = (red << RShift) |
764 *dest++ = (char)((pixel >> 24) & 0xff);
765 *dest++ = (char)((pixel >> 16) & 0xff);
766 *dest++ = (char)((pixel >> 8) & 0xff);
767 *dest++ = (char)( pixel & 0xff);
771 if (((row+1) & 0xf) == 0) {
772 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
779 }
else if (
depth == 16) {
784 dest = ximage->data + row*ximage_rowbytes;
785 if (image_channels == 3) {
787 red = ((
ush)(*src) << 8);
789 green = ((
ush)(*src) << 8);
791 blue = ((
ush)(*src) << 8);
793 pixel = ((red >> RShift) & RMask) |
794 ((green >> GShift) & GMask) |
795 ((blue >> BShift) & BMask);
797 *dest++ = (char)((pixel >> 8) & 0xff);
798 *dest++ = (char)( pixel & 0xff);
808 green = ((
ush)g << 8);
809 blue = ((
ush)b << 8);
811 red = ((
ush)bg_red << 8);
812 green = ((
ush)bg_green << 8);
813 blue = ((
ush)bg_blue << 8);
822 green = ((
ush)g << 8);
823 blue = ((
ush)b << 8);
825 pixel = ((red >> RShift) & RMask) |
826 ((green >> GShift) & GMask) |
827 ((blue >> BShift) & BMask);
829 *dest++ = (char)((pixel >> 8) & 0xff);
830 *dest++ = (char)( pixel & 0xff);
834 if (((row+1) & 0xf) == 0) {
835 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
848 Trace((stderr,
"calling final XPutImage()\n"))
850 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
861 static void rpng_x_cleanup(
void)
871 ximage->data = (
char *)
NULL;
873 XDestroyImage(ximage);
878 XFreeGC(display, gc);
881 XDestroyWindow(display, window);
884 XFreeColormap(display, colormap);
886 if (have_nondefault_visual)
894 static int rpng_x_msb(
ulg u32val)
898 for (i = 31; i >= 0; --
i) {
899 if (u32val & 0x80000000L)
GLboolean GLboolean GLboolean GLboolean a
GLint GLint GLsizei GLsizei GLsizei depth
GLboolean GLboolean GLboolean b
int main(int argc, char **argv)
#define alpha_composite(composite, fg, alpha, bg)
GLenum GLenum GLvoid * row
GLdouble GLdouble GLdouble r
uch * readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
void readpng_version_info(void)
int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
void readpng_cleanup(int free_image_data)
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)