Imported from libpng-1.0.6.tar
diff --git a/contrib/gregbook/rpng-x.c b/contrib/gregbook/rpng-x.c
index 5f0a8a1..aea975d 100644
--- a/contrib/gregbook/rpng-x.c
+++ b/contrib/gregbook/rpng-x.c
@@ -5,8 +5,8 @@
This program decodes and displays PNG images, with gamma correction and
optionally with a user-specified background color (in case the image has
transparency). It is very nearly the most basic PNG viewer possible.
- This version is for the X Window System (tested under Unix, but may work
- under VMS or OS/2 with a little tweaking).
+ This version is for the X Window System (tested by author under Unix and
+ by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
to do:
- 8-bit support
@@ -14,7 +14,17 @@
---------------------------------------------------------------------------
- Copyright (c) 1998-1999 Greg Roelofs. All rights reserved.
+ Changelog:
+ - 1.01: initial public release
+ - 1.02: modified to allow abbreviated options; fixed long/ulong mis-
+ match; switched to png_jmpbuf() macro
+ - 1.10: added support for non-default visuals; fixed X pixel-conversion
+ - 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed
+ command-line parsing bug
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
This software is provided "as is," without warranty of any kind,
express or implied. In no event shall the author or contributors
@@ -41,7 +51,7 @@
#define PROGNAME "rpng-x"
#define LONGNAME "Simple PNG Viewer for X"
-#define VERSION "1.01 of 31 March 1999"
+#define VERSION "1.11 of 19 March 2000"
#include <stdio.h>
#include <stdlib.h>
@@ -54,7 +64,7 @@
/* #define DEBUG : this enables the Trace() macros */
-#include "readpng.h" /* typedefs, common macros, readpng prototypes */
+#include "readpng.h" /* typedefs, common macros, readpng prototypes */
/* could just include png.h, but this macro is the only thing we need
@@ -95,15 +105,16 @@
static char *displayname;
static XImage *ximage;
static Display *display;
-static int bitmap_order;
static int depth;
static Visual *visual;
-static int RPixelShift, GPixelShift, BPixelShift;
-static ulg RedMask, GreenMask, BlueMask;
+static XVisualInfo *visual_list;
+static int RShift, GShift, BShift;
+static ulg RMask, GMask, BMask;
static Window window;
static GC gc;
static Colormap colormap;
+static int have_nondefault_visual = FALSE;
static int have_colormap = FALSE;
static int have_window = FALSE;
/*
@@ -123,9 +134,9 @@
int rc, alen, flen;
int error = 0;
int have_bg = FALSE;
- double LUT_exponent; /* just the lookup table */
- double CRT_exponent = 2.2; /* just the monitor */
- double default_display_exponent; /* whole display system */
+ double LUT_exponent; /* just the lookup table */
+ double CRT_exponent = 2.2; /* just the monitor */
+ double default_display_exponent; /* whole display system */
XEvent e;
KeySym k;
@@ -188,24 +199,29 @@
/* Now parse the command line for options and the PNG filename. */
while (*++argv && !error) {
- if (!strcmp(*argv, "-display")) {
+ if (!strncmp(*argv, "-display", 2)) {
if (!*++argv)
++error;
- displayname = *argv;
- } else if (!strcmp(*argv, "-gamma")) {
- if (!*++argv)
- ++error;
- display_exponent = atof(*argv);
- if (display_exponent <= 0.0)
- ++error;
- } else if (!strcmp(*argv, "-bgcolor")) {
- if (!*++argv)
- ++error;
- bgstr = *argv;
- if (strlen(bgstr) != 7 || bgstr[0] != '#')
- ++error;
else
- have_bg = TRUE;
+ displayname = *argv;
+ } else if (!strncmp(*argv, "-gamma", 2)) {
+ if (!*++argv)
+ ++error;
+ else {
+ display_exponent = atof(*argv);
+ if (display_exponent <= 0.0)
+ ++error;
+ }
+ } else if (!strncmp(*argv, "-bgcolor", 2)) {
+ if (!*++argv)
+ ++error;
+ else {
+ bgstr = *argv;
+ if (strlen(bgstr) != 7 || bgstr[0] != '#')
+ ++error;
+ else
+ have_bg = TRUE;
+ }
} else {
if (**argv != '-') {
filename = *argv;
@@ -222,8 +238,7 @@
fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
++error;
} else {
- if ((rc = readpng_init(infile, (long *)(&image_width),
- (long *)(&image_height))) != 0) {
+ if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
switch (rc) {
case 1:
fprintf(stderr, PROGNAME
@@ -257,21 +272,25 @@
fclose(infile);
}
+
+ /* usage screen */
+
if (error) {
fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
readpng_version_info();
fprintf(stderr, "\n"
- "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
- " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
- " exp \ttransfer-function exponent (``gamma'') of the display\n"
- "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
- "\t\t to the product of the lookup-table exponent (varies)\n"
- "\t\t and the CRT exponent (usually 2.2); must be positive\n"
- " bg \tdesired background color in 7-character hex RGB format\n"
- "\t\t (e.g., ``#ff7f00'' for orange: same as HTML colors);\n"
- "\t\t used with transparent images\n"
- "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
- "\n", PROGNAME, default_display_exponent);
+ "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
+ " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
+ " exp \ttransfer-function exponent (``gamma'') of the display\n"
+ "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
+ "\t\t to the product of the lookup-table exponent (varies)\n"
+ "\t\t and the CRT exponent (usually 2.2); must be positive\n"
+ " bg \tdesired background color in 7-character hex RGB format\n"
+ "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
+ "\t\t used with transparent images\n"
+ "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
+ "is displayed) to quit.\n"
+ "\n", PROGNAME, default_display_exponent);
exit(1);
}
@@ -344,6 +363,10 @@
/* wait for the user to tell us when to quit */
+ printf(
+ "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
+ fflush(stdout);
+
do
XNextEvent(display, &e);
while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
@@ -362,11 +385,13 @@
-static int rpng_x_create_window()
+static int rpng_x_create_window(void)
{
uch *xdata;
+ int need_colormap = FALSE;
int screen, pad;
ulg bg_pixel = 0L;
+ ulg attrmask;
Window root;
XEvent e;
XGCValues gcvalues;
@@ -378,11 +403,15 @@
XWMHints *wm_hints;
- bitmap_order = BitmapBitOrder(display);
screen = DefaultScreen(display);
depth = DisplayPlanes(display, screen);
root = RootWindow(display, screen);
+#ifdef DEBUG
+ XSynchronize(display, True);
+#endif
+
+#if 0
/* GRR: add 8-bit support */
if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
fprintf(stderr,
@@ -394,27 +423,73 @@
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;
- RedMask = visual->red_mask;
- GreenMask = visual->green_mask;
- BlueMask = visual->blue_mask;
+ 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) {
+ if (depth == 8 || need_colormap) {
colormap = XCreateColormap(display, root, visual, AllocNone);
if (!colormap) {
fprintf(stderr, "XCreateColormap() failed\n");
return 2;
}
have_colormap = TRUE;
- } else if (depth == 16) {
- RPixelShift = 15 - rpng_x_msb(RedMask); /* these are right-shifts */
- GPixelShift = 15 - rpng_x_msb(GreenMask);
- BPixelShift = 15 - rpng_x_msb(BlueMask);
- } else /* if (depth > 16) */ {
- RPixelShift = rpng_x_msb(RedMask) - 7; /* these are left-shifts */
- GPixelShift = rpng_x_msb(GreenMask) - 7;
- BPixelShift = rpng_x_msb(BlueMask) - 7;
+ }
+ 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;
}
/*---------------------------------------------------------------------------
@@ -423,9 +498,16 @@
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, CWBackingStore | CWEventMask, &attr);
+ window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
+ depth, InputOutput, visual, attrmask, &attr);
if (window == None) {
fprintf(stderr, "XCreateWindow() failed\n");
@@ -446,8 +528,8 @@
if ((size_hints = XAllocSizeHints()) != NULL) {
/* window will not be resizable */
size_hints->flags = PMinSize | PMaxSize;
- size_hints->min_width = size_hints->max_width = image_width;
- size_hints->min_height = size_hints->max_height = image_height;
+ 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) {
@@ -469,13 +551,13 @@
---------------------------------------------------------------------------*/
if (depth == 24 || depth == 32) {
- bg_pixel = ((ulg)bg_red << RPixelShift) |
- ((ulg)bg_green << GPixelShift) |
- ((ulg)bg_blue << BPixelShift);
+ bg_pixel = ((ulg)bg_red << RShift) |
+ ((ulg)bg_green << GShift) |
+ ((ulg)bg_blue << BShift);
} else if (depth == 16) {
- bg_pixel = ((((ulg)bg_red << 8) >> RPixelShift) & RedMask) |
- ((((ulg)bg_green << 8) >> GPixelShift) & GreenMask) |
- ((((ulg)bg_blue << 8) >> BPixelShift) & BlueMask);
+ 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 */
@@ -524,7 +606,7 @@
return 3;
}
- /* to avoid testing the bitmap_order every pixel (or doubling the size of
+ /* 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
@@ -541,20 +623,24 @@
-static int rpng_x_display_image()
+static int rpng_x_display_image(void)
{
uch *src;
char *dest;
uch r, g, b, a;
- int ximage_rowbytes = ximage->bytes_per_line;
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",
+ 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;
@@ -567,14 +653,27 @@
red = *src++;
green = *src++;
blue = *src++;
- pixel = (red << RPixelShift) |
- (green << GPixelShift) |
- (blue << BPixelShift);
+#ifdef NO_24BIT_MASKS
+ pixel = (red << RShift) |
+ (green << GShift) |
+ (blue << BShift);
/* recall that we set ximage->byte_order = MSBFirst above */
- *dest++ = ((uch *)&pixel)[3];
- *dest++ = ((uch *)&pixel)[2];
- *dest++ = ((uch *)&pixel)[1];
- *dest++ = ((uch *)&pixel)[0];
+ /* 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) {
@@ -598,20 +697,20 @@
alpha_composite(green, g, a, bg_green);
alpha_composite(blue, b, a, bg_blue);
}
- pixel = (red << RPixelShift) |
- (green << GPixelShift) |
- (blue << BPixelShift);
+ pixel = (red << RShift) |
+ (green << GShift) |
+ (blue << BShift);
/* recall that we set ximage->byte_order = MSBFirst above */
- *dest++ = ((uch *)&pixel)[3];
- *dest++ = ((uch *)&pixel)[2];
- *dest++ = ((uch *)&pixel)[1];
- *dest++ = ((uch *)&pixel)[0];
+ *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, lastrow, 0, lastrow,
- image_width, 16);
+ XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+ (int)lastrow, image_width, 16);
XFlush(display);
lastrow = row + 1;
}
@@ -631,12 +730,12 @@
++src;
blue = ((ush)(*src) << 8);
++src;
- pixel = ((red >> RPixelShift) & RedMask) |
- ((green >> GPixelShift) & GreenMask) |
- ((blue >> BPixelShift) & BlueMask);
+ pixel = ((red >> RShift) & RMask) |
+ ((green >> GShift) & GMask) |
+ ((blue >> BShift) & BMask);
/* recall that we set ximage->byte_order = MSBFirst above */
- *dest++ = ((uch *)&pixel)[1];
- *dest++ = ((uch *)&pixel)[0];
+ *dest++ = (char)((pixel >> 8) & 0xff);
+ *dest++ = (char)( pixel & 0xff);
}
} else /* if (image_channels == 4) */ {
for (i = image_width; i > 0; --i) {
@@ -663,18 +762,18 @@
green = ((ush)g << 8);
blue = ((ush)b << 8);
}
- pixel = ((red >> RPixelShift) & RedMask) |
- ((green >> GPixelShift) & GreenMask) |
- ((blue >> BPixelShift) & BlueMask);
+ pixel = ((red >> RShift) & RMask) |
+ ((green >> GShift) & GMask) |
+ ((blue >> BShift) & BMask);
/* recall that we set ximage->byte_order = MSBFirst above */
- *dest++ = ((uch *)&pixel)[1];
- *dest++ = ((uch *)&pixel)[0];
+ *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, lastrow, 0, lastrow,
- image_width, 16);
+ XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+ (int)lastrow, image_width, 16);
XFlush(display);
lastrow = row + 1;
}
@@ -688,8 +787,8 @@
Trace((stderr, "calling final XPutImage()\n"))
if (lastrow < image_height) {
- XPutImage(display, window, gc, ximage, 0, lastrow, 0, lastrow,
- image_width, image_height-lastrow);
+ XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+ (int)lastrow, image_width, image_height-lastrow);
XFlush(display);
}
@@ -699,7 +798,7 @@
-static void rpng_x_cleanup()
+static void rpng_x_cleanup(void)
{
if (image_data) {
free(image_data);
@@ -722,6 +821,9 @@
if (have_colormap)
XFreeColormap(display, colormap);
+
+ if (have_nondefault_visual)
+ XFree(visual_list);
}