diff options
author | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2000-03-21 05:13:06 -0600 |
---|---|---|
committer | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2009-04-06 16:04:52 -0500 |
commit | 520a764cd79aea2d282cb4d2b9187f0aafb72404 (patch) | |
tree | 0ca2fa9bece8a4d4eeeda049bd37b3fda61c6ee3 /contrib/gregbook | |
parent | a77ef625a6bb7d7808e0f084df2ca1d9d2627154 (diff) | |
download | libpng-520a764cd79aea2d282cb4d2b9187f0aafb72404.tar.gz |
Imported from libpng-1.0.6.tarv1.0.6
Diffstat (limited to 'contrib/gregbook')
-rw-r--r-- | contrib/gregbook/LICENSE | 26 | ||||
-rw-r--r-- | contrib/gregbook/Makefile.unx (renamed from contrib/gregbook/makefile.unx) | 47 | ||||
-rw-r--r-- | contrib/gregbook/Makefile.w32 (renamed from contrib/gregbook/makefile.w32) | 8 | ||||
-rw-r--r-- | contrib/gregbook/README | 231 | ||||
-rw-r--r-- | contrib/gregbook/README.w32 | 53 | ||||
-rw-r--r-- | contrib/gregbook/makevms.com | 28 | ||||
-rw-r--r-- | contrib/gregbook/readpng.c | 21 | ||||
-rw-r--r-- | contrib/gregbook/readpng.h | 4 | ||||
-rw-r--r-- | contrib/gregbook/readpng2.c | 27 | ||||
-rw-r--r-- | contrib/gregbook/readpng2.h | 5 | ||||
-rw-r--r-- | contrib/gregbook/rpng-win.c | 76 | ||||
-rw-r--r-- | contrib/gregbook/rpng-x.c | 292 | ||||
-rw-r--r-- | contrib/gregbook/rpng2-win.c | 191 | ||||
-rw-r--r-- | contrib/gregbook/rpng2-x.c | 425 | ||||
-rw-r--r-- | contrib/gregbook/toucan.png | bin | 0 -> 12901 bytes | |||
-rw-r--r-- | contrib/gregbook/wpng.c | 98 | ||||
-rw-r--r-- | contrib/gregbook/writepng.c | 18 | ||||
-rw-r--r-- | contrib/gregbook/writepng.h | 2 |
18 files changed, 1030 insertions, 522 deletions
diff --git a/contrib/gregbook/LICENSE b/contrib/gregbook/LICENSE new file mode 100644 index 000000000..5714772d6 --- /dev/null +++ b/contrib/gregbook/LICENSE @@ -0,0 +1,26 @@ + --------------------------------------------------------------------------- + + 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 + be held liable for any damages arising in any way from the use of + this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + --------------------------------------------------------------------------- diff --git a/contrib/gregbook/makefile.unx b/contrib/gregbook/Makefile.unx index 93d46d17f..ed2e4f403 100644 --- a/contrib/gregbook/makefile.unx +++ b/contrib/gregbook/Makefile.unx @@ -1,6 +1,6 @@ # Sample makefile for rpng-x / rpng2-x / wpng using gcc and make. # Greg Roelofs -# Last modified: 16 February 1999 +# Last modified: 28 February 2000 # # The programs built by this makefile are described in the book, # "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and @@ -9,11 +9,12 @@ # # Invoke this makefile from a shell prompt in the usual way; for example: # -# make -f makefile.unx +# make -f Makefile.unx # # This makefile assumes libpng and zlib have already been built or downloaded # and are both installed in /usr/local/{include,lib} (as indicated by the -# PNGPATH and ZPATH macros below). Edit as appropriate. +# PNG* and Z* macros below). Edit as appropriate--choose only ONE each of +# the PNGINC, PNGLIB, ZINC and ZLIB lines. # # This makefile builds statically linked executables (against libpng and zlib, # that is), but that can be changed by uncommenting the appropriate PNGLIB and @@ -22,30 +23,38 @@ # macros -------------------------------------------------------------------- -PNGPATH = /usr/local -PNGINC = -I$(PNGPATH)/include -#PNGLIB = -L$(PNGPATH)/lib -lpng -PNGLIB = $(PNGPATH)/lib/libpng.a - -ZPATH = /usr/local -ZINC = -I$(ZPATH)/include -#ZLIB = -L$(ZPATH)/lib -lz -ZLIB = $(ZPATH)/lib/libz.a - -#XPATH = /usr/X11 -XPATH = /usr/X11R6 -XINC = -I$(XPATH)/include -XLIB = -L$(XPATH)/lib -lX11 +PNGINC = -I/usr/local/include +#PNGLIB = -L/usr/local/lib -lpng # dynamically linked against libpng +PNGLIB = /usr/local/lib/libpng.a # statically linked against libpng +# or: +#PNGINC = -I../.. +#PNGLIB = -L../.. -lpng +#PNGLIB = ../../libpng.a + +ZINC = -I/usr/local/include +#ZLIB = -L/usr/local/lib -lz # dynamically linked against zlib +ZLIB = /usr/local/lib/libz.a # statically linked against zlib +#ZINC = -I../zlib +#ZLIB = -L../zlib -lz +#ZLIB = ../../../zlib/libz.a + +#XINC = -I/usr/include/X11 # old-style, stock X distributions +#XLIB = -L/usr/lib/X11 -lX11 +#XINC = -I/usr/openwin/include/X11 # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 +XINC = -I/usr/X11R6/include # new X distributions (XFree86, etc.) +XLIB = -L/usr/X11R6/lib -lX11 INCS = $(PNGINC) $(ZINC) $(XINC) RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm -WLIBS = $(PNGLIB) $(ZLIB) -lm +WLIBS = $(PNGLIB) $(ZLIB) CC = gcc LD = gcc RM = rm -f CFLAGS = -O -Wall $(INCS) -# [note that -Wall is a gcc-specific compilation flag ("all warnings on")] +# [note that -Wall is a gcc-specific compilation flag ("most warnings on")] +# [-ansi, -pedantic and -W can also be used] LDFLAGS = O = .o E = diff --git a/contrib/gregbook/makefile.w32 b/contrib/gregbook/Makefile.w32 index e520ae75c..2a840229e 100644 --- a/contrib/gregbook/makefile.w32 +++ b/contrib/gregbook/Makefile.w32 @@ -10,14 +10,14 @@ # Invoke this makefile from a DOS prompt window via: # # %devstudio%\vc\bin\vcvars32.bat -# nmake -nologo -f makefile.w32 +# nmake -nologo -f Makefile.w32 # # where %devstudio% is the installation directory for MSVC / DevStudio. If # you get "environment out of space" errors, create a desktop shortcut with # "c:\windows\command.com /e:4096" as the program command line and set the # working directory to this directory. Then double-click to open the new # DOS-prompt window with a bigger environment and retry the commands above. -# +# # This makefile assumes libpng and zlib have already been built or downloaded # and are in subdirectories at the same level as the current subdirectory # (as indicated by the PNGPATH and ZPATH macros below). Edit as appropriate. @@ -32,12 +32,12 @@ # macros -------------------------------------------------------------------- -PNGPATH = ../libpng +PNGPATH = ../.. PNGINC = -I$(PNGPATH) #PNGLIB = $(PNGPATH)/pngdll.lib PNGLIB = $(PNGPATH)/libpng.lib -ZPATH = ../zlib +ZPATH = ../../../zlib ZINC = -I$(ZPATH) #ZLIB = $(ZPATH)/zlibdll.lib ZLIB = $(ZPATH)/zlibstat.lib diff --git a/contrib/gregbook/README b/contrib/gregbook/README index fa3871a7d..a8bbc2874 100644 --- a/contrib/gregbook/README +++ b/contrib/gregbook/README @@ -1,52 +1,183 @@ -PNG: The Definitive Guide: Source Code + =========================== + PNG: The Definitive Guide + =========================== -Chapters 13, 14 and 15 of PNG: The Definitive Guide discuss three + Source Code + +Chapters 13, 14 and 15 of "PNG: The Definitive Guide" discuss three free, cross-platform demo programs that show how to use the libpng reference -library: rpng, rpng2 and wpng. rpng and rpng2 are viewers; the first is a -very simple example that that shows how a standard file-viewer might use -libpng, while the second is designed to process streaming data and shows how -a web browser might be written. wpng is a simple command-line program that -reads binary PPM files (the ``raw'' RGB subset of NetPBM) and converts them -to PNG. - -The source code for all three demo programs currently compiles only under -Unix and 32-bit Windows. It has been tested with gcc 2.7.2.3 under Linux and -Solaris and with Microsoft Visual C++ 5.0 under Windows 95. Brief -instructions for compiling the programs are included at the top of the -makefiles; makefile.unx is the Unix version, and makefile.w32 is (you -guessed it!) the version for 32-bit Windows. libpng and zlib are required. - ----------------------------------------------------------------------------- - -License - -The source code to the demo programs may be used and distributed freely -(even if you didn't buy the book--but feel free to do so at any time), -subject to the terms of the following BSD-like license: - - Copyright (c) 1998-1999 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 - be held liable for any damages arising in any way from the use of - this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. Redistributions of source code must retain the above - copyright notice, disclaimer, and this list of conditions. - 2. Redistributions in binary form must reproduce the above - copyright notice, disclaimer, and this list of conditions in - the documentation and/or other materials provided with the - distribution. - 3. All advertising materials mentioning features or use of this - software must display the following acknowledgment: - - This product includes software developed by Greg Roelofs - and contributors for the book, "PNG: The Definitive - Guide," published by O'Reilly and Associates. - ----------------------------------------------------------- -http://www.cdrom.com/pub/png/book/sources.html +library: rpng, rpng2 and wpng. rpng and rpng2 are viewers; the first is +a very simple example that that shows how a standard file-viewer might use +libpng, while the second is designed to process streaming data and shows +how a web browser might be written. wpng is a simple command-line program +that reads binary PGM and PPM files (the ``raw'' grayscale and RGB subsets +of PBMPLUS/NetPBM) and converts them to PNG. + +The source code for all three demo programs currently compiles under +Unix, OpenVMS, and 32-bit Windows. (Special thanks to Martin Zinser, +zinser@decus.de, for making the necessary changes for OpenVMS and for +providing an appropriate build script.) Build instructions can be +found below. + +Files: + + README this file + README.w32 additional Windows-specific information + LICENSE terms of distribution and reuse (BSD-like) + + Makefile.unx Unix makefile + Makefile.w32 Windows (MSVC) makefile + makevms.com OpenVMS build script + + rpng-win.c Windows front end for the basic viewer + rpng-x.c X Window System (Unix, OpenVMS) front end + readpng.c generic back end for the basic viewer + readpng.h header file for the basic viewer + + rpng2-win.c Windows front end for the progressive viewer + rpng2-x.c X front end for the progressive viewer + readpng2.c generic back end for the progressive viewer + readpng2.h header file for the progressive viewer + + wpng.c generic (text) front end for the converter + writepng.c generic back end for the converter + writepng.h header file for the converter + + toucan.png transparent PNG for testing (by Stefan Schneider) + +Note that the programs are designed to be functional, but their primary +purpose is to demonstrate how to use libpng to add PNG support to other +programs. As such, their user interfaces are crude and definitely not +intended for everyday use. + +Please see http://www.cdrom.com/pub/png/pngbook.html for further infor- +mation and links to the latest version of the source code, and Chapters +13-15 of the book for detailed discussion of the three programs. + +Greg Roelofs +19 March 2000 + + +BUILD INSTRUCTIONS + + - Prerequisites: + + - zlib ftp://ftp.cdrom.com/pub/infozip/zlib/zlib.html + - libpng http://www.cdrom.com/pub/png/pngcode.html + - pngbook http://www.cdrom.com/pub/png/book/sources.html + + The pngbook demo programs are explicitly designed to demonstrate proper + coding techniques for using the libpng reference library. As a result, + you need to download and build both zlib (on which libpng depends) and + libpng. A common build setup is to place the zlib, libpng and pngbook + subdirectory trees ("folders") in the same parent directory. Then the + libpng build can refer to files in ../zlib (or ..\zlib or [-.zlib]), + and similarly for the pngbook build. + + Note that all three packages are designed to be built from a command + line by default; those who wish to use a graphical or other integrated + development environments are on their own. + + + - Unix: + + Unpack the latest pngbook sources (which should correspond to this + README file) into a directory and change into that directory. + + Copy Makefile.unx to Makefile and edit the PNG* and Z* variables + appropriately (possibly also the X* variables if necessary). + + make + + There is no "install" target, so copy the three executables somewhere + in your path or run them from the current directory. All three will + print a basic usage screen when run without any command-line arguments; + see the book for more details. + + + - Windows: + + Unpack the latest pngbook sources (which should correspond to this + README file) into a folder, open a "DOS shell" or "command prompt" + or equivalent command-line window, and cd into the folder where you + unpacked the source code. + + For MSVC, set up the necessary environment variables by invoking + + %devstudio%\vc\bin\vcvars32.bat + + where where %devstudio% is the installation directory for MSVC / + DevStudio. If you get "environment out of space" errors under 95/98, + create a desktop shortcut with "c:\windows\command.com /e:4096" as + the program command line and set the working directory to the pngbook + directory. Then double-click to open the new DOS-prompt window with + a bigger environment and retry the commands above. + + Copy Makefile.w32 to Makefile and edit the PNGPATH and ZPATH variables + appropriately (possibly also the "INC" and "LIB" variables if needed). + Note that the names of the dynamic and static libpng and zlib libraries + used in the makefile may change in later releases of the libraries. + Also note that, as of libpng version 1.0.5, MSVC DLL builds do not work. + This makefile therefore builds statically linked executables, but if + the DLL problems ever get fixed, uncommenting the appropriate PNGLIB + and ZLIB lines will build dynamically linked executables instead. + + Do the build by typing + + nmake + + The result should be three executables: rpng-win.exe, rpng2-win.exe, + and wpng.exe. Copy them somewhere in your PATH or run them from the + current folder. Unlike the Unix versions, the two windowed programs + (rpng and rpng2) do not display a usage screen when invoked without + command-line arguments; see README.w32 for brief help or the book for + details. Note that the programs use the Unix-style "-" character to + specify options, instead of the more common DOS/Windows "/" character. + + + - OpenVMS: + + Unpack the pngbook sources into a subdirectory and change into that + subdirectory. + + Edit makevms.com appropriately, specifically the zpath and pngpath + variables. + + @makevms + + To run the programs, they probably first need to be set up as "foreign + symbols," with "disk" and "dir" set appropriately: + + $ rpng == "$disk:[dir]rpng-x.exe" + $ rpng2 == "$disk:[dir]rpng2-x.exe" + $ wpng == "$disk:[dir]wpng.exe" + + All three will print a basic usage screen when run without any command- + line arguments; see the book for more details. Note that the options + style is Unix-like, i.e., preceded by "-" rather than "/". + + +RUNNING THE PROGRAMS: (VERY) BRIEF INTRO + + rpng is a simple PNG viewer that can display transparent PNGs with a + specified background color; for example, + + rpng -bgcolor #ff0000 toucan.png + + would display the image with a red background. rpng2 is a progressive + viewer that simulates a web browser in some respects; it can display + images against either a background color or a dynamically generated + background image. For example: + + rpng2 -bgpat 16 toucan.png + + wpng is a purely command-line image converter from binary PBMPLUS/NetPBM + format (.pgm or .ppm) to PNG; for example, + + wpng -time < toucan.ppm > toucan.png + + would convert the specified PPM file (using redirection) to PNG, auto- + matically setting the PNG modification-time chunk. + + All options can be abbreviated to the shortest unique value; for example, + "-bgc" for -bgcolor (versus "-bgp" for -bgpat), or "-g" for -gamma. diff --git a/contrib/gregbook/README.w32 b/contrib/gregbook/README.w32 new file mode 100644 index 000000000..736c00145 --- /dev/null +++ b/contrib/gregbook/README.w32 @@ -0,0 +1,53 @@ +See the main README file for basic instructions on compiling and running +the programs. See http://www.cdrom.com/pub/png/pngbook.html for further +information and links to the source code, and Chapters 13-15 of the book +for detailed discussion of the three programs. + +Since the two viewers, rpng and rpng2, are both designed to write infor- +mation to the console (i.e., a DOS-window command line) while displaying +the image in a graphical window--and since I haven't yet figured out how +to do that under Windows--here are the usage screens for the two programs: + + +rpng-win 1.02 of 19 March 2000: Simple PNG Viewer for Windows + Compiled with libpng 1.0.5; using libpng 1.0.5. + Compiled with zlib 1.1.3; using zlib 1.1.3. + +Usage: rpng-win [-gamma exp] [-bgcolor bg] file.png + exp transfer-function exponent (``gamma'') of the display + system in floating-point format (e.g., ``2.2''); equal + to the product of the lookup-table exponent (varies) + and the CRT exponent (usually 2.2); must be positive + bg desired background color in 7-character hex RGB format + (e.g., ``#ff7f00'' for orange: same as HTML colors); + used with transparent images + +Press Q, Esc or mouse button 1 after image is displayed to quit. + + +rpng2-win 1.04 of 19 March 2000: Progressive PNG Viewer for Windows + Compiled with libpng 1.0.5; using libpng 1.0.5. + Compiled with zlib 1.1.3; using zlib 1.1.3. + +Usage: rpng2-win [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing] file.png + + exp transfer-function exponent (``gamma'') of the display + system in floating-point format (e.g., ``2.2''); equal + to the product of the lookup-table exponent (varies) + and the CRT exponent (usually 2.2); must be positive + bg desired background color in 7-character hex RGB format + (e.g., ``#ff7f00'' for orange: same as HTML colors); + used with transparent images; overrides -bgpat + pat desired background pattern number (1-16); used with + transparent images; overrides -bgcolor + -timing enables delay for every block read, to simulate modem + download of image (~36 Kbps) + +Press Q, Esc or mouse button 1 after image is displayed to quit. + + +The usage screen for the third (non-windowed) program, wpng, can be seen +simply by invoking it without any parameters (``wpng''). + +Greg Roelofs +19 March 2000 diff --git a/contrib/gregbook/makevms.com b/contrib/gregbook/makevms.com index 2ee2eb694..b8cbfae37 100644 --- a/contrib/gregbook/makevms.com +++ b/contrib/gregbook/makevms.com @@ -1,11 +1,22 @@ $!------------------------------------------------------------------------------ -$! make Contrib programs of libpng under OpenVMS +$! make "PNG: The Definitive Guide" demo programs (for X) under OpenVMS $! +$! Script created by Martin Zinser for libpng; modified by Greg Roelofs +$! for standalone pngbook source distribution. $! -$! Look for the compiler used $! -$ zlibsrc = "[---.zlib]" -$ ccopt="/include=(''zlibsrc',[--])" +$! Set locations where zlib and libpng sources live. +$! +$ zpath = "[-.zlib]" +$ pngpath = "[-.libpng]" +$! +$! USE THESE INSTEAD if building from libpng's [.contrib.gregbook] directory: +$! zpath = "[---.zlib]" +$! pngpath = "[--]" +$! +$! Look for the compiler used. +$! +$ ccopt="/include=(''zpath',''pngpath')" $ if f$getsyi("HW_MODEL").ge.1024 $ then $ ccopt = "/prefix=all"+ccopt @@ -29,13 +40,16 @@ $ comp = "__decc__=1" $ endif $ endif $ open/write lopt lib.opt -$ write lopt "[--]libpng.olb/lib" -$ write lopt "''zlibsrc'libz.olb/lib" +$ write lopt "''pngpath'libpng.olb/lib" +$ write lopt "''zpath'libz.olb/lib" $ close lopt $ open/write xopt x11.opt $ write xopt "sys$library:decw$xlibshr.exe/share" $ close xopt -$ write sys$output "Compiling PNG contrib programs ..." +$! +$! Build 'em. +$! +$ write sys$output "Compiling PNG book programs ..." $ CALL MAKE readpng.OBJ "cc ''CCOPT' readpng" - readpng.c readpng.h $ CALL MAKE readpng2.OBJ "cc ''CCOPT' readpng2" - diff --git a/contrib/gregbook/readpng.c b/contrib/gregbook/readpng.c index 546293f7d..dc948eecc 100644 --- a/contrib/gregbook/readpng.c +++ b/contrib/gregbook/readpng.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -32,8 +32,13 @@ #include <stdio.h> #include <stdlib.h> -#include "png.h" /* libpng header; includes zlib.h */ -#include "readpng.h" /* typedefs, common macros, public prototypes */ +#include "png.h" /* libpng header; includes zlib.h */ +#include "readpng.h" /* typedefs, common macros, public prototypes */ + +/* future versions of libpng will provide this macro: */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif static png_structp png_ptr = NULL; @@ -44,7 +49,7 @@ int bit_depth, color_type; uch *image_data = NULL; -void readpng_version_info() +void readpng_version_info(void) { fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); @@ -55,7 +60,7 @@ void readpng_version_info() /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ -int readpng_init(FILE *infile, long *pWidth, long *pHeight) +int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) { uch sig[8]; @@ -89,7 +94,7 @@ int readpng_init(FILE *infile, long *pWidth, long *pHeight) /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ - if (setjmp(png_jmp_env(png_ptr))) { + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } @@ -130,7 +135,7 @@ int readpng_get_bgcolor(uch *red, uch *green, uch *blue) /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ - if (setjmp(png_jmp_env(png_ptr))) { + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } @@ -184,7 +189,7 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ - if (setjmp(png_jmp_env(png_ptr))) { + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } diff --git a/contrib/gregbook/readpng.h b/contrib/gregbook/readpng.h index 31780c568..1c19aca99 100644 --- a/contrib/gregbook/readpng.h +++ b/contrib/gregbook/readpng.h @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -54,7 +54,7 @@ typedef unsigned long ulg; void readpng_version_info(void); -int readpng_init(FILE *infile, long *pWidth, long *pHeight); +int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight); int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue); diff --git a/contrib/gregbook/readpng2.c b/contrib/gregbook/readpng2.c index 19d1f18c2..8f70c834b 100644 --- a/contrib/gregbook/readpng2.c +++ b/contrib/gregbook/readpng2.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -30,10 +30,10 @@ ---------------------------------------------------------------------------*/ -#include <stdlib.h> /* for exit() prototype */ +#include <stdlib.h> /* for exit() prototype */ -#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ -#include "readpng2.h" /* typedefs, common macros, public prototypes */ +#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include "readpng2.h" /* typedefs, common macros, public prototypes */ /* local prototypes */ @@ -47,7 +47,7 @@ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg); -void readpng2_version_info() +void readpng2_version_info(void) { fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); @@ -70,7 +70,7 @@ int readpng2_check_sig(uch *sig, int num) int readpng2_init(mainprog_info *mainprog_ptr) { - png_structp png_ptr; /* note: temporary variables! */ + png_structp png_ptr; /* note: temporary variables! */ png_infop info_ptr; @@ -98,7 +98,7 @@ int readpng2_init(mainprog_info *mainprog_ptr) * but compatible error handlers must either use longjmp() themselves * (as in this program) or exit immediately, so here we are: */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } @@ -136,7 +136,7 @@ int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length) /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mainprog_ptr->png_ptr = NULL; mainprog_ptr->info_ptr = NULL; @@ -176,7 +176,7 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) mainprog_ptr = png_get_progressive_ptr(png_ptr); - if (mainprog_ptr == NULL) { /* we be hosed */ + if (mainprog_ptr == NULL) { /* we be hosed */ fprintf(stderr, "readpng2 error: main struct not recoverable in info_callback.\n"); fflush(stderr); @@ -283,7 +283,7 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) png_read_update_info(png_ptr, info_ptr); - mainprog_ptr->rowbytes = png_get_rowbytes(png_ptr, info_ptr); + mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr); @@ -323,6 +323,11 @@ static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, mainprog_ptr = png_get_progressive_ptr(png_ptr); + /* save the pass number for optional use by the front end */ + + mainprog_ptr->pass = pass; + + /* have libpng either combine the new row data with the existing row data * from previous passes (if interlaced) or else just copy the new row * into the main program's image buffer */ @@ -408,7 +413,7 @@ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg) fflush(stderr); mainprog_ptr = png_get_error_ptr(png_ptr); - if (mainprog_ptr == NULL) { /* we are completely hosed now */ + if (mainprog_ptr == NULL) { /* we are completely hosed now */ fprintf(stderr, "readpng2 severe error: jmpbuf not recoverable; terminating.\n"); fflush(stderr); diff --git a/contrib/gregbook/readpng2.h b/contrib/gregbook/readpng2.h index 2ffd77635..cbc1fd8c9 100644 --- a/contrib/gregbook/readpng2.h +++ b/contrib/gregbook/readpng2.h @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -61,7 +61,8 @@ typedef struct _mainprog_info { uch *image_data; uch **row_pointers; jmp_buf jmpbuf; - int passes; /* not used */ + int passes; /* not used */ + int pass; int rowbytes; int channels; int need_bgcolor; diff --git a/contrib/gregbook/rpng-win.c b/contrib/gregbook/rpng-win.c index a75e609fa..51e1974ed 100644 --- a/contrib/gregbook/rpng-win.c +++ b/contrib/gregbook/rpng-win.c @@ -16,7 +16,16 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + Changelog: + - 1.00: initial public release + - 1.01: modified to allow abbreviated options; fixed long/ulong mis- + match; switched to png_jmpbuf() macro + - 1.02: 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 @@ -43,7 +52,7 @@ #define PROGNAME "rpng-win" #define LONGNAME "Simple PNG Viewer for Windows" -#define VERSION "1.0 of 20 February 1999" +#define VERSION "1.02 of 19 March 2000" #include <stdio.h> #include <stdlib.h> @@ -53,7 +62,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 @@ -61,10 +70,10 @@ * only happen with alpha (which could easily be avoided with * "ush acopy = (alpha);") */ -#define alpha_composite(composite, fg, alpha, bg) { \ - ush temp = ((ush)(fg)*(ush)(alpha) + \ - (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ - (composite) = (uch)((temp + (temp >> 8)) >> 8); \ +#define alpha_composite(composite, fg, alpha, bg) { \ + ush temp = ((ush)(fg)*(ush)(alpha) + \ + (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ + (composite) = (uch)((temp + (temp >> 8)) >> 8); \ } @@ -78,7 +87,7 @@ LRESULT CALLBACK rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM); static char titlebar[1024], *window_name = titlebar; static char *progname = PROGNAME; static char *appname = LONGNAME; -static char *icon_name = PROGNAME; /* GRR: not (yet) used */ +static char *icon_name = PROGNAME; /* GRR: not (yet) used */ static char *filename; static FILE *infile; @@ -104,15 +113,15 @@ static HWND global_hwnd; int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) { - char *args[1024]; /* arbitrary limit, but should suffice */ + char *args[1024]; /* arbitrary limit, but should suffice */ char *p, *q, **argv = args; int argc = 0; 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 */ MSG msg; @@ -199,20 +208,24 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* Now parse the command line for options and the PNG filename. */ while (*++argv && !error) { - if (!strcmp(*argv, "-gamma")) { + if (!strncmp(*argv, "-gamma", 2)) { if (!*++argv) ++error; - display_exponent = atof(*argv); - if (display_exponent <= 0.0) - ++error; - } else if (!strcmp(*argv, "-bgcolor")) { + else { + display_exponent = atof(*argv); + if (display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 2)) { if (!*++argv) ++error; - bgstr = *argv; - if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; - else - have_bg = TRUE; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else + have_bg = TRUE; + } } else { if (**argv != '-') { filename = *argv; @@ -255,6 +268,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) fclose(infile); } + + /* usage screen */ + if (error) { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); readpng_version_info(); @@ -265,7 +281,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) "\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 (e.g., ``#ff7700'' 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); @@ -336,6 +352,10 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* 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); + while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -371,7 +391,7 @@ static int rpng_win_create_window(HINSTANCE hInst, int showmode) if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + wimage_rowbytes*image_height))) { - return 4; /* fail */ + return 4; /* fail */ } /*--------------------------------------------------------------------------- @@ -477,7 +497,7 @@ static int rpng_win_display_image() g = *src++; b = *src++; *dest++ = b; - *dest++ = g; /* note reverse order */ + *dest++ = g; /* note reverse order */ *dest++ = r; } } else /* if (image_channels == 4) */ { @@ -582,15 +602,15 @@ LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP) /* wait for the user to tell us when to quit */ case WM_CHAR: - switch (wP) { /* only need one, so ignore repeat count */ + switch (wP) { /* only need one, so ignore repeat count */ case 'q': case 'Q': - case 0x1B: /* Esc key */ + case 0x1B: /* Esc key */ PostQuitMessage(0); } return 0; - case WM_LBUTTONDOWN: /* another way of quitting */ + case WM_LBUTTONDOWN: /* another way of quitting */ case WM_DESTROY: PostQuitMessage(0); return 0; diff --git a/contrib/gregbook/rpng-x.c b/contrib/gregbook/rpng-x.c index 5f0a8a1fb..aea975d95 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 uch *image_data; 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 main(int argc, char **argv) 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 @@ int main(int argc, char **argv) /* 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")) { + else + displayname = *argv; + } else if (!strncmp(*argv, "-gamma", 2)) { if (!*++argv) ++error; - display_exponent = atof(*argv); - if (display_exponent <= 0.0) - ++error; - } else if (!strcmp(*argv, "-bgcolor")) { + else { + display_exponent = atof(*argv); + if (display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 2)) { if (!*++argv) ++error; - bgstr = *argv; - if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; - else - have_bg = TRUE; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else + have_bg = TRUE; + } } else { if (**argv != '-') { filename = *argv; @@ -222,8 +238,7 @@ int main(int argc, char **argv) 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 @@ int main(int argc, char **argv) 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 @@ int main(int argc, char **argv) /* 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 @@ int main(int argc, char **argv) -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 @@ static int rpng_x_create_window() 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 @@ static int rpng_x_create_window() 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 - RedMask = visual->red_mask; - GreenMask = visual->green_mask; - BlueMask = visual->blue_mask; + 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 @@ static int rpng_x_create_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, 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 @@ static int rpng_x_create_window() 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 @@ static int rpng_x_create_window() ---------------------------------------------------------------------------*/ 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 @@ static int rpng_x_create_window() 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_create_window() -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 @@ static int rpng_x_display_image() 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 @@ static int rpng_x_display_image() 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 @@ static int rpng_x_display_image() ++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 @@ static int rpng_x_display_image() 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 @@ static int rpng_x_display_image() 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 int rpng_x_display_image() -static void rpng_x_cleanup() +static void rpng_x_cleanup(void) { if (image_data) { free(image_data); @@ -722,6 +821,9 @@ static void rpng_x_cleanup() if (have_colormap) XFreeColormap(display, colormap); + + if (have_nondefault_visual) + XFree(visual_list); } diff --git a/contrib/gregbook/rpng2-win.c b/contrib/gregbook/rpng2-win.c index 66e682eef..9bc66c739 100644 --- a/contrib/gregbook/rpng2-win.c +++ b/contrib/gregbook/rpng2-win.c @@ -22,10 +22,13 @@ Changelog: - 1.01: initial public release - 1.02: fixed cut-and-paste error in usage screen (oops...) + - 1.03: modified to allow abbreviated options + - 1.04: removed bogus extra argument from usage fprintf() [Glenn R-P?]; + fixed command-line parsing bug --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -52,14 +55,14 @@ #define PROGNAME "rpng2-win" #define LONGNAME "Progressive PNG Viewer for Windows" -#define VERSION "1.02 of 22 September 1999" +#define VERSION "1.04 of 19 March 2000" #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */ +#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */ #include <time.h> -#include <math.h> /* only for PvdM background code */ +#include <math.h> /* only for PvdM background code */ #include <windows.h> /* all for PvdM background code: */ @@ -80,9 +83,9 @@ #define rgb2_max bg_bsat #define rgb2_min bg_brot -/* #define DEBUG */ /* this enables the Trace() macros */ +/* #define DEBUG */ /* this enables the Trace() macros */ -#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */ +#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */ /* could just include png.h, but this macro is the only thing we need @@ -90,18 +93,18 @@ * only happen with alpha (which could easily be avoided with * "ush acopy = (alpha);") */ -#define alpha_composite(composite, fg, alpha, bg) { \ - ush temp = ((ush)(fg)*(ush)(alpha) + \ - (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ - (composite) = (uch)((temp + (temp >> 8)) >> 8); \ +#define alpha_composite(composite, fg, alpha, bg) { \ + ush temp = ((ush)(fg)*(ush)(alpha) + \ + (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ + (composite) = (uch)((temp + (temp >> 8)) >> 8); \ } -#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this - * block size corresponds roughly to a download - * speed 10% faster than theoretical 33.6K maximum - * (assuming 8 data bits, 1 stop bit and no other - * overhead) */ +#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this + * block size corresponds roughly to a download + * speed 10% faster than theoretical 33.6K maximum + * (assuming 8 data bits, 1 stop bit and no other + * overhead) */ /* local prototypes */ static void rpng2_win_init(void); @@ -116,7 +119,7 @@ LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM); static char titlebar[1024], *window_name = titlebar; static char *progname = PROGNAME; static char *appname = LONGNAME; -static char *icon_name = PROGNAME; /* GRR: not (yet) used */ +static char *icon_name = PROGNAME; /* GRR: not (yet) used */ static char *filename; static FILE *infile; @@ -125,7 +128,7 @@ static mainprog_info rpng2_info; static uch inbuf[INBUFSIZE]; static int incount; -static int pat = 6; /* must be less than num_bgpat */ +static int pat = 6; /* must be less than num_bgpat */ static int bg_image = 0; static int bgscale = 16; static ulg bg_rowbytes; @@ -134,22 +137,22 @@ static uch *bg_data; static struct rgb_color { uch r, g, b; } rgb[] = { - { 0, 0, 0}, /* 0: black */ - {255, 255, 255}, /* 1: white */ - {173, 132, 57}, /* 2: tan */ - { 64, 132, 0}, /* 3: medium green */ - {189, 117, 1}, /* 4: gold */ - {253, 249, 1}, /* 5: yellow */ - { 0, 0, 255}, /* 6: blue */ - { 0, 0, 120}, /* 7: medium blue */ - {255, 0, 255}, /* 8: magenta */ - { 64, 0, 64}, /* 9: dark magenta */ - {255, 0, 0}, /* 10: red */ - { 64, 0, 0}, /* 11: dark red */ - {255, 127, 0}, /* 12: orange */ - {192, 96, 0}, /* 13: darker orange */ - { 24, 60, 0}, /* 14: dark green-yellow */ - { 85, 125, 200} /* 15: ice blue */ + { 0, 0, 0}, /* 0: black */ + {255, 255, 255}, /* 1: white */ + {173, 132, 57}, /* 2: tan */ + { 64, 132, 0}, /* 3: medium green */ + {189, 117, 1}, /* 4: gold */ + {253, 249, 1}, /* 5: yellow */ + { 0, 0, 255}, /* 6: blue */ + { 0, 0, 120}, /* 7: medium blue */ + {255, 0, 255}, /* 8: magenta */ + { 64, 0, 64}, /* 9: dark magenta */ + {255, 0, 0}, /* 10: red */ + { 64, 0, 0}, /* 11: dark red */ + {255, 127, 0}, /* 12: orange */ + {192, 96, 0}, /* 13: darker orange */ + { 24, 60, 0}, /* 14: dark green-yellow */ + { 85, 125, 200} /* 15: ice blue */ }; /* not used for now, but should be for error-checking: static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color); @@ -174,25 +177,25 @@ static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color); */ static struct background_pattern { ush type; - int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */ - int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/ + int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */ + int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/ } bg[] = { - {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */ - {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */ - {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */ - {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */ - {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */ - {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */ - {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */ - {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */ - {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */ - {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */ - {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */ - {1, 3,0, 0,0}, /* diamonds: medium green vs. black */ - {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */ - {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */ - {2, 16, 256, 100, 250}, /* radial: very tight spiral */ - {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */ + {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */ + {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */ + {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */ + {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */ + {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */ + {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */ + {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */ + {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */ + {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */ + {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */ + {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */ + {1, 3,0, 0,0}, /* diamonds: medium green vs. black */ + {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */ + {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */ + {2, 16, 256, 100, 250}, /* radial: very tight spiral */ + {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */ }; static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern); @@ -212,16 +215,17 @@ static int global_showmode; int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) { - char *args[1024]; /* arbitrary limit, but should suffice */ - char *p, *q, *bgstr = NULL, **argv = args; + char *args[1024]; /* arbitrary limit, but should suffice */ + char **argv = args; + char *p, *q, *bgstr = NULL; int argc = 0; int rc, alen, flen; int error = 0; int timing = FALSE; 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 */ MSG msg; @@ -316,33 +320,39 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* Now parse the command line for options and the PNG filename. */ while (*++argv && !error) { - if (!strcmp(*argv, "-gamma")) { + if (!strncmp(*argv, "-gamma", 2)) { if (!*++argv) ++error; - rpng2_info.display_exponent = atof(*argv); - if (rpng2_info.display_exponent <= 0.0) - ++error; - } else if (!strcmp(*argv, "-bgcolor")) { + else { + rpng2_info.display_exponent = atof(*argv); + if (rpng2_info.display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { if (!*++argv) ++error; - bgstr = *argv; - if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; else { - have_bg = TRUE; - bg_image = FALSE; + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + have_bg = TRUE; + bg_image = FALSE; + } } - } else if (!strcmp(*argv, "-bgpat")) { + } else if (!strncmp(*argv, "-bgpat", 4)) { if (!*++argv) ++error; - pat = atoi(*argv) - 1; - if (pat < 0 || pat >= num_bgpat) - ++error; else { - bg_image = TRUE; - have_bg = FALSE; + pat = atoi(*argv) - 1; + if (pat < 0 || pat >= num_bgpat) + ++error; + else { + bg_image = TRUE; + have_bg = FALSE; + } } - } else if (!strcmp(*argv, "-timing")) { + } else if (!strncmp(*argv, "-timing", 2)) { timing = TRUE; } else { if (**argv != '-') { @@ -387,6 +397,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) fclose(infile); } + + /* usage screen */ + if (error) { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); readpng2_version_info(); @@ -398,14 +411,14 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) "\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 (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images; overrides -bgpat\n" " pat \tdesired background pattern number (1-%d); used with\n" "\t\t transparent images; overrides -bgcolor\n" " -timing\tenables delay for every block read, to simulate modem\n" "\t\t download of image (~36 Kbps)\n" "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" - "\n", PROGNAME, " ", default_display_exponent, num_bgpat); + "\n", PROGNAME, default_display_exponent, num_bgpat); exit(1); } @@ -560,7 +573,7 @@ static int rpng2_win_create_window() if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + wimage_rowbytes*rpng2_info.height))) { - return 4; /* fail */ + return 4; /* fail */ } /*--------------------------------------------------------------------------- @@ -655,7 +668,7 @@ static int rpng2_win_create_window() TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len); ReleaseDC(global_hwnd, hdc); - rpng2_win_load_bg_image(); /* resets bg_image if fails */ + rpng2_win_load_bg_image(); /* resets bg_image if fails */ } if (!bg_image) { @@ -753,7 +766,7 @@ static int rpng2_win_load_bg_image() even_odd = even_odd_vert ^ even_odd_horiz; invert_column = (even_odd_horiz && (bg[pat].type & 0x10)); - if (even_odd == 0) { /* gradient #1 */ + if (even_odd == 0) { /* gradient #1 */ if (invert_column) { *dest++ = r1_inv; *dest++ = g1_inv; @@ -763,16 +776,16 @@ static int rpng2_win_load_bg_image() *dest++ = g1; *dest++ = b1; } - } else { /* gradient #2 */ + } else { /* gradient #2 */ if ((invert_column && invert_gradient2) || (!invert_column && !invert_gradient2)) { - *dest++ = r2; /* not inverted or */ - *dest++ = g2; /* doubly inverted */ + *dest++ = r2; /* not inverted or */ + *dest++ = g2; /* doubly inverted */ *dest++ = b2; } else { *dest++ = r2_inv; - *dest++ = g2_inv; /* singly inverted */ + *dest++ = g2_inv; /* singly inverted */ *dest++ = b2_inv; } } @@ -908,7 +921,7 @@ static int rpng2_win_load_bg_image() g1 = *src++; b1 = *src++; *dest++ = b1; - *dest++ = g1; /* note reverse order */ + *dest++ = g1; /* note reverse order */ *dest++ = r1; } } @@ -962,7 +975,7 @@ static void rpng2_win_display_row(ulg row) g = *src++; b = *src++; *dest++ = b; - *dest++ = g; /* note reverse order */ + *dest++ = g; /* note reverse order */ *dest++ = r; } } else /* if (rpng2_info.channels == 4) */ { @@ -1028,7 +1041,9 @@ static void rpng2_win_finish_display() * that the image is done */ rpng2_info.done = TRUE; - printf("Done. Press Q, Esc or mouse button 1 to quit.\n"); + printf( + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); + fflush(stdout); } @@ -1084,15 +1099,15 @@ LRESULT CALLBACK rpng2_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP) /* wait for the user to tell us when to quit */ case WM_CHAR: - switch (wP) { /* only need one, so ignore repeat count */ + switch (wP) { /* only need one, so ignore repeat count */ case 'q': case 'Q': - case 0x1B: /* Esc key */ + case 0x1B: /* Esc key */ PostQuitMessage(0); } return 0; - case WM_LBUTTONDOWN: /* another way of quitting */ + case WM_LBUTTONDOWN: /* another way of quitting */ case WM_DESTROY: PostQuitMessage(0); return 0; diff --git a/contrib/gregbook/rpng2-x.c b/contrib/gregbook/rpng2-x.c index 8e536e7bb..47ab5b9cb 100644 --- a/contrib/gregbook/rpng2-x.c +++ b/contrib/gregbook/rpng2-x.c @@ -6,9 +6,11 @@ a web browser (though the front end is only set up to read from files). It supports gamma correction, user-specified background colors, and user- specified background patterns (for transparent images). This version is - for the X Window System (tested under Unix, but may work under VMS or OS/2 - with a little tweaking). Thanks to Adam Costello and Pieter S. van der - Meulen for the "diamond" and "radial waves" patterns, respectively. + for the X Window System (tested by the author under Unix and by Martin + Zinser under OpenVMS; may work under OS/2 with a little tweaking). + + Thanks to Adam Costello and Pieter S. van der Meulen for the "diamond" + and "radial waves" patterns, respectively. to do: - 8-bit support @@ -17,7 +19,16 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + Changelog: + - 1.01: initial public release + - 1.02: modified to allow abbreviated options; fixed char/uchar mismatch + - 1.10: added support for non-default visuals; fixed X pixel-conversion + - 1.11: added -usleep option for demos; fixed command-line parsing bug + - 1.12: added -pause option for demos and testing + + --------------------------------------------------------------------------- + + 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 @@ -44,21 +55,21 @@ #define PROGNAME "rpng2-x" #define LONGNAME "Progressive PNG Viewer for X" -#define VERSION "1.01 of 31 March 1999" +#define VERSION "1.12 of 19 March 2000" #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */ +#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */ #include <time.h> -#include <math.h> /* only for PvdM background code */ +#include <math.h> /* only for PvdM background code */ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xos.h> -#include <X11/keysym.h> /* defines XK_* macros */ +#include <X11/keysym.h> /* defines XK_* macros */ #ifdef VMS -#include <unistd.h> +# include <unistd.h> #endif /* all for PvdM background code: */ @@ -79,9 +90,9 @@ #define rgb2_max bg_bsat #define rgb2_min bg_brot -/* #define DEBUG */ /* this enables the Trace() macros */ +/* #define DEBUG */ /* this enables the Trace() macros */ -#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */ +#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */ /* could just include png.h, but this macro is the only thing we need @@ -89,18 +100,18 @@ * only happen with alpha (which could easily be avoided with * "ush acopy = (alpha);") */ -#define alpha_composite(composite, fg, alpha, bg) { \ - ush temp = ((ush)(fg)*(ush)(alpha) + \ - (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ - (composite) = (uch)((temp + (temp >> 8)) >> 8); \ +#define alpha_composite(composite, fg, alpha, bg) { \ + ush temp = ((ush)(fg)*(ush)(alpha) + \ + (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ + (composite) = (uch)((temp + (temp >> 8)) >> 8); \ } -#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this - * block size corresponds roughly to a download - * speed 10% faster than theoretical 33.6K maximum - * (assuming 8 data bits, 1 stop bit and no other - * overhead) */ +#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this + * block size corresponds roughly to a download + * speed 10% faster than theoretical 33.6K maximum + * (assuming 8 data bits, 1 stop bit and no other + * overhead) */ /* local prototypes */ static void rpng2_x_init(void); @@ -123,12 +134,16 @@ static mainprog_info rpng2_info; static uch inbuf[INBUFSIZE]; static int incount; -static int pat = 6; /* must be less than num_bgpat */ +static int pat = 6; /* must be less than num_bgpat */ static int bg_image = 0; static int bgscale = 16; static ulg bg_rowbytes; static uch *bg_data; +int pause_after_pass = FALSE; +int demo_timing = FALSE; +ulg usleep_duration = 0L; + static struct rgb_color { uch r, g, b; } rgb[] = { @@ -201,12 +216,14 @@ static XImage *ximage; static Display *display; 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; @@ -294,37 +311,53 @@ int main(int argc, char **argv) /* 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")) { + else + displayname = *argv; + } else if (!strncmp(*argv, "-gamma", 2)) { if (!*++argv) ++error; - rpng2_info.display_exponent = atof(*argv); - if (rpng2_info.display_exponent <= 0.0) - ++error; - } else if (!strcmp(*argv, "-bgcolor")) { + else { + rpng2_info.display_exponent = atof(*argv); + if (rpng2_info.display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { if (!*++argv) ++error; - bgstr = *argv; - if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; else { - have_bg = TRUE; - bg_image = FALSE; + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + have_bg = TRUE; + bg_image = FALSE; + } } - } else if (!strcmp(*argv, "-bgpat")) { + } else if (!strncmp(*argv, "-bgpat", 4)) { if (!*++argv) ++error; - pat = atoi(*argv) - 1; - if (pat < 0 || pat >= num_bgpat) + else { + pat = atoi(*argv) - 1; + if (pat < 0 || pat >= num_bgpat) + ++error; + else { + bg_image = TRUE; + have_bg = FALSE; + } + } + } else if (!strncmp(*argv, "-usleep", 2)) { + if (!*++argv) ++error; else { - bg_image = TRUE; - have_bg = FALSE; + usleep_duration = (ulg)atol(*argv); + demo_timing = TRUE; } - } else if (!strcmp(*argv, "-timing")) { + } else if (!strncmp(*argv, "-pause", 2)) { + pause_after_pass = TRUE; + } else if (!strncmp(*argv, "-timing", 2)) { timing = TRUE; } else { if (**argv != '-') { @@ -377,25 +410,32 @@ int main(int argc, char **argv) fclose(infile); } + + /* usage screen */ + if (error) { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); readpng2_version_info(); fprintf(stderr, "\n" "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n" - " %*s [-timing] file.png\n\n" + " %*s [-usleep dur | -timing] [-pause] file.png\n\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 (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images; overrides -bgpat\n" " pat \tdesired background pattern number (1-%d); used with\n" "\t\t transparent images; overrides -bgcolor\n" + " dur \tduration in microseconds to wait after displaying each\n" + "\t\t row (for demo purposes)\n" " -timing\tenables delay for every block read, to simulate modem\n" "\t\t download of image (~36 Kbps)\n" - "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" + " -pause\tpauses after displaying each pass until key pressed\n" + "\nPress Q, Esc or mouse button 1 (within image window, after image\n" + "is displayed) to quit.\n" "\n", PROGNAME, strlen(PROGNAME), " ", default_display_exponent, num_bgpat); exit(1); @@ -489,7 +529,7 @@ int main(int argc, char **argv) * in turn is called by libpng after all of the pre-IDAT chunks have been * read and processed--i.e., we now have enough info to finish initializing */ -static void rpng2_x_init() +static void rpng2_x_init(void) { ulg i; ulg rowbytes = rpng2_info.rowbytes; @@ -531,12 +571,14 @@ static void rpng2_x_init() -static int rpng2_x_create_window() +static int rpng2_x_create_window(void) { ulg bg_red = rpng2_info.bg_red; ulg bg_green = rpng2_info.bg_green; ulg bg_blue = rpng2_info.bg_blue; ulg bg_pixel = 0L; + ulg attrmask; + int need_colormap = FALSE; int screen, pad; uch *xdata; Window root; @@ -556,39 +598,70 @@ static int rpng2_x_create_window() depth = DisplayPlanes(display, screen); root = RootWindow(display, screen); -/* GRR: add 8-bit support */ - 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; - } +#ifdef DEBUG + XSynchronize(display, True); +#endif - XMatchVisualInfo(display, screen, depth, - (depth == 8)? PseudoColor : TrueColor, &visual_info); - visual = visual_info.visual; + 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; + } - RedMask = visual->red_mask; - GreenMask = visual->green_mask; - BlueMask = visual->blue_mask; + 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; - bg_image = FALSE; /* gradient just wastes palette entries */ - } else if (depth == 16) { - RPixelShift = 15 - rpng2_x_msb(RedMask); /* these are right-shifts */ - GPixelShift = 15 - rpng2_x_msb(GreenMask); - BPixelShift = 15 - rpng2_x_msb(BlueMask); - } else /* if (depth > 16) */ { - RPixelShift = rpng2_x_msb(RedMask) - 7; /* these are left-shifts */ - GPixelShift = rpng2_x_msb(GreenMask) - 7; - BPixelShift = rpng2_x_msb(BlueMask) - 7; + if (depth == 8) + bg_image = FALSE; /* gradient just wastes palette entries */ + } + if (depth == 15 || depth == 16) { + RShift = 15 - rpng2_x_msb(RMask); /* these are right-shifts */ + GShift = 15 - rpng2_x_msb(GMask); + BShift = 15 - rpng2_x_msb(BMask); + } else if (depth > 16) { + RShift = rpng2_x_msb(RMask) - 7; /* these are left-shifts */ + GShift = rpng2_x_msb(GMask) - 7; + BShift = rpng2_x_msb(BMask) - 7; + } + if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) { + fprintf(stderr, "rpng2 internal logic error: negative X shift(s)!\n"); + return 2; } /*--------------------------------------------------------------------------- @@ -597,10 +670,16 @@ static int rpng2_x_create_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, rpng2_info.width, - rpng2_info.height, 0, depth, InputOutput, visual, - CWBackingStore | CWEventMask, &attr); + rpng2_info.height, 0, depth, InputOutput, visual, attrmask, &attr); if (window == None) { fprintf(stderr, "XCreateWindow() failed\n"); @@ -621,8 +700,9 @@ static int rpng2_x_create_window() if ((size_hints = XAllocSizeHints()) != NULL) { /* window will not be resizable */ size_hints->flags = PMinSize | PMaxSize; - size_hints->min_width = size_hints->max_width = rpng2_info.width; - size_hints->min_height = size_hints->max_height = rpng2_info.height; + size_hints->min_width = size_hints->max_width = (int)rpng2_info.width; + size_hints->min_height = size_hints->max_height = + (int)rpng2_info.height; } if ((wm_hints = XAllocWMHints()) != NULL) { @@ -668,7 +748,7 @@ static int rpng2_x_create_window() 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 (e.g., Linux/x86, old VAXen, etc.)--this is not the @@ -684,17 +764,17 @@ static int rpng2_x_create_window() ---------------------------------------------------------------------------*/ if (bg_image) - rpng2_x_load_bg_image(); /* resets bg_image if fails */ + rpng2_x_load_bg_image(); /* resets bg_image if fails */ if (!bg_image) { if (depth == 24 || depth == 32) { - bg_pixel = (bg_red << RPixelShift) | - (bg_green << GPixelShift) | - (bg_blue << BPixelShift); + bg_pixel = (bg_red << RShift) | + (bg_green << GShift) | + (bg_blue << BShift); } else if (depth == 16) { - bg_pixel = (((bg_red << 8) >> RPixelShift) & RedMask) | - (((bg_green << 8) >> GPixelShift) & GreenMask) | - (((bg_blue << 8) >> BPixelShift) & BlueMask); + bg_pixel = (((bg_red << 8) >> RShift) & RMask) | + (((bg_green << 8) >> GShift) & GMask) | + (((bg_blue << 8) >> BShift) & BMask); } else /* depth == 8 */ { /* GRR: add 8-bit support */ @@ -723,7 +803,7 @@ static int rpng2_x_create_window() -static int rpng2_x_load_bg_image() +static int rpng2_x_load_bg_image(void) { uch *src; char *dest; @@ -772,8 +852,8 @@ static int rpng2_x_load_bg_image() int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min; for (row = 0; row < rpng2_info.height; ++row) { - yidx = row % bgscale; - even_odd_vert = (row / bgscale) & 1; + yidx = (int)(row % bgscale); + even_odd_vert = (int)((row / bgscale) & 1); r1 = r1_min + (r1_diff * yidx) / yidx_max; g1 = g1_min + (g1_diff * yidx) / yidx_max; @@ -789,13 +869,13 @@ static int rpng2_x_load_bg_image() g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max; b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max; - dest = (char *)(bg_data + row*bg_rowbytes); + dest = (char *)bg_data + row*bg_rowbytes; for (i = 0; i < rpng2_info.width; ++i) { - even_odd_horiz = (i / bgscale) & 1; + even_odd_horiz = (int)((i / bgscale) & 1); even_odd = even_odd_vert ^ even_odd_horiz; invert_column = (even_odd_horiz && (bg[pat].type & 0x10)); - if (even_odd == 0) { /* gradient #1 */ + if (even_odd == 0) { /* gradient #1 */ if (invert_column) { *dest++ = r1_inv; *dest++ = g1_inv; @@ -805,16 +885,16 @@ static int rpng2_x_load_bg_image() *dest++ = g1; *dest++ = b1; } - } else { /* gradient #2 */ + } else { /* gradient #2 */ if ((invert_column && invert_gradient2) || (!invert_column && !invert_gradient2)) { - *dest++ = r2; /* not inverted or */ - *dest++ = g2; /* doubly inverted */ + *dest++ = r2; /* not inverted or */ + *dest++ = g2; /* doubly inverted */ *dest++ = b2; } else { *dest++ = r2_inv; - *dest++ = g2_inv; /* singly inverted */ + *dest++ = g2_inv; /* singly inverted */ *dest++ = b2_inv; } } @@ -839,12 +919,12 @@ static int rpng2_x_load_bg_image() b2 = rgb[bg[pat].rgb2_max].b; for (row = 0; row < rpng2_info.height; ++row) { - yidx = row % bgscale; + yidx = (int)(row % bgscale); if (yidx > hmax) yidx = bgscale-1 - yidx; - dest = (char *)(bg_data + row*bg_rowbytes); + dest = (char *)bg_data + row*bg_rowbytes; for (i = 0; i < rpng2_info.width; ++i) { - xidx = i % bgscale; + xidx = (int)(i % bgscale); if (xidx > hmax) xidx = bgscale-1 - xidx; k = xidx + yidx; @@ -871,8 +951,8 @@ static int rpng2_x_load_bg_image() PROGNAME); fflush(stderr); - hh = rpng2_info.height / 2; - hw = rpng2_info.width / 2; + hh = (int)(rpng2_info.height / 2); + hw = (int)(rpng2_info.width / 2); /* variables for radial waves: * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED] @@ -891,10 +971,10 @@ static int rpng2_x_load_bg_image() maxDist = (double)((hw*hw) + (hh*hh)); for (row = 0; row < rpng2_info.height; ++row) { - y = row - hh; - dest = (char *)(bg_data + row*bg_rowbytes); + y = (int)(row - hh); + dest = (char *)bg_data + row*bg_rowbytes; for (i = 0; i < rpng2_info.width; ++i) { - x = i - hw; + x = (int)(i - hw); angle = (x == 0)? PI_2 : atan((double)y / (double)x); gray = (double)MAX(ABS(y), ABS(x)) / grayspot; gray = MIN(1.0, gray); @@ -951,14 +1031,15 @@ static int rpng2_x_load_bg_image() red = *src++; green = *src++; blue = *src++; - 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]; + /* 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); } } @@ -969,18 +1050,15 @@ static int rpng2_x_load_bg_image() src = bg_data + row*bg_rowbytes; dest = ximage->data + row*ximage_rowbytes; for (i = rpng2_info.width; i > 0; --i) { - red = ((ush)(*src) << 8); - ++src; - green = ((ush)(*src) << 8); - ++src; - blue = ((ush)(*src) << 8); - ++src; - pixel = ((red >> RPixelShift) & RedMask) | - ((green >> GPixelShift) & GreenMask) | - ((blue >> BPixelShift) & BlueMask); + 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++ = ((uch *)&pixel)[1]; - *dest++ = ((uch *)&pixel)[0]; + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); } } @@ -1011,7 +1089,7 @@ static void rpng2_x_display_row(ulg row) uch r, g, b, a; int ximage_rowbytes = ximage->bytes_per_line; ulg i, pixel; - static int rows=0; + static int rows=0, prevpass=(-1); static ulg firstrow; /*--------------------------------------------------------------------------- @@ -1022,8 +1100,28 @@ static void rpng2_x_display_row(ulg row) Trace((stderr, "beginning rpng2_x_display_row()\n")) + if (rpng2_info.pass != prevpass) { + if (pause_after_pass && rpng2_info.pass > 0) { + XEvent e; + KeySym k; + + fprintf(stderr, + "%s: end of pass %d of 7; click in image window to continue\n", + PROGNAME, prevpass + 1); + do + XNextEvent(display, &e); + while (!(e.type == ButtonPress && e.xbutton.button == Button1) + && !(e.type == KeyPress && + ((k = XLookupKeysym(&e.xkey, 0)) == XK_q + || k == XK_Escape) )) ; + } + fprintf(stderr, "%s: pass %d of 7\r", PROGNAME, rpng2_info.pass + 1); + fflush(stderr); + prevpass = rpng2_info.pass; + } + if (rows == 0) - firstrow = row; /* first row not yet displayed */ + firstrow = row; /* first row that is not yet displayed */ ++rows; /* count of rows received but not yet displayed */ @@ -1046,14 +1144,15 @@ static void rpng2_x_display_row(ulg row) red = *src++; green = *src++; blue = *src++; - pixel = (red << RPixelShift) | - (green << GPixelShift) | - (blue << BPixelShift); - /* recall that we set ximage->byte_order = MSBFirst */ - *dest++ = ((uch *)&pixel)[3]; - *dest++ = ((uch *)&pixel)[2]; - *dest++ = ((uch *)&pixel)[1]; - *dest++ = ((uch *)&pixel)[0]; + 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 /* if (rpng2_info.channels == 4) */ { for (i = rpng2_info.width; i > 0; --i) { @@ -1082,14 +1181,15 @@ static void rpng2_x_display_row(ulg row) alpha_composite(green, g, a, bg_green); alpha_composite(blue, b, a, bg_blue); } - pixel = (red << RPixelShift) | - (green << GPixelShift) | - (blue << BPixelShift); - /* recall that we set ximage->byte_order = MSBFirst */ - *dest++ = ((uch *)&pixel)[3]; - *dest++ = ((uch *)&pixel)[2]; - *dest++ = ((uch *)&pixel)[1]; - *dest++ = ((uch *)&pixel)[0]; + 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); } } @@ -1108,12 +1208,12 @@ static void rpng2_x_display_row(ulg row) ++src; blue = ((ush)(*src) << 8); ++src; - pixel = ((red >> RPixelShift) & RedMask) | - ((green >> GPixelShift) & GreenMask) | - ((blue >> BPixelShift) & BlueMask); - /* recall that we set ximage->byte_order = MSBFirst */ - *dest++ = ((uch *)&pixel)[1]; - *dest++ = ((uch *)&pixel)[0]; + 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 (rpng2_info.channels == 4) */ { for (i = rpng2_info.width; i > 0; --i) { @@ -1145,12 +1245,12 @@ static void rpng2_x_display_row(ulg row) green = ((ush)g << 8); blue = ((ush)b << 8); } - pixel = ((red >> RPixelShift) & RedMask) | - ((green >> GPixelShift) & GreenMask) | - ((blue >> BPixelShift) & BlueMask); - /* recall that we set ximage->byte_order = MSBFirst */ - *dest++ = ((uch *)&pixel)[1]; - *dest++ = ((uch *)&pixel)[0]; + 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); } } @@ -1162,13 +1262,23 @@ static void rpng2_x_display_row(ulg row) /*--------------------------------------------------------------------------- - Display after every 16 rows or when on last row. (Region may include - previously displayed lines due to interlacing--i.e., not contiguous.) + Display after every 16 rows or when on one of last two rows. (Region + may include previously displayed lines due to interlacing--i.e., not + contiguous. Also, second-to-last row is final one in interlaced images + with odd number of rows.) For demos, flush (and delay) after every 16th + row so "sparse" passes don't go twice as fast. ---------------------------------------------------------------------------*/ - if ((rows & 0xf) == 0 || row == rpng2_info.height-1) { - XPutImage(display, window, gc, ximage, 0, firstrow, 0, firstrow, - rpng2_info.width, row - firstrow + 1); + if (demo_timing && (row - firstrow >= 16 || row >= rpng2_info.height-2)) { + XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0, + (int)firstrow, rpng2_info.width, row - firstrow + 1); + XFlush(display); + rows = 0; + usleep(usleep_duration); + } else + if (!demo_timing && ((rows & 0xf) == 0 || row >= rpng2_info.height-2)) { + XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0, + (int)firstrow, rpng2_info.width, row - firstrow + 1); XFlush(display); rows = 0; } @@ -1179,7 +1289,7 @@ static void rpng2_x_display_row(ulg row) -static void rpng2_x_finish_display() +static void rpng2_x_finish_display(void) { Trace((stderr, "beginning rpng2_x_finish_display()\n")) @@ -1188,14 +1298,16 @@ static void rpng2_x_finish_display() * the image is done */ rpng2_info.done = TRUE; - printf("Done. Press Q, Esc or mouse button 1 to quit.\n"); + printf( + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); + fflush(stdout); } -static void rpng2_x_cleanup() +static void rpng2_x_cleanup(void) { if (bg_image && bg_data) { free(bg_data); @@ -1228,6 +1340,9 @@ static void rpng2_x_cleanup() if (have_colormap) XFreeColormap(display, colormap); + + if (have_nondefault_visual) + XFree(visual_list); } diff --git a/contrib/gregbook/toucan.png b/contrib/gregbook/toucan.png Binary files differnew file mode 100644 index 000000000..03960d493 --- /dev/null +++ b/contrib/gregbook/toucan.png diff --git a/contrib/gregbook/wpng.c b/contrib/gregbook/wpng.c index 7709b33a0..d6e85148b 100644 --- a/contrib/gregbook/wpng.c +++ b/contrib/gregbook/wpng.c @@ -19,7 +19,15 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + Changelog: + - 1.01: initial public release + - 1.02: modified to allow abbreviated options + - 1.03: removed extraneous character from usage screen; fixed bug in + command-line parsing + + --------------------------------------------------------------------------- + + 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 @@ -45,7 +53,7 @@ ---------------------------------------------------------------------------*/ #define PROGNAME "wpng" -#define VERSION "1.01 of 31 March 1999" +#define VERSION "1.03 of 19 March 2000" #define APPNAME "Simple PGM/PPM/PAM to PNG Converter" #if defined(__MSDOS__) || defined(__OS2__) @@ -57,27 +65,27 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <setjmp.h> /* for jmpbuf declaration in writepng.h */ +#include <setjmp.h> /* for jmpbuf declaration in writepng.h */ #include <time.h> #ifdef DOS_OS2_W32 -# include <io.h> /* for isatty(), setmode() prototypes */ -# include <fcntl.h> /* O_BINARY for fdopen() without text translation */ +# include <io.h> /* for isatty(), setmode() prototypes */ +# include <fcntl.h> /* O_BINARY for fdopen() without text translation */ # ifdef __EMX__ # ifndef getch -# define getch() _read_kbd(0, 1, 0) /* need getche() */ +# define getch() _read_kbd(0, 1, 0) /* need getche() */ # endif # else /* !__EMX__ */ # ifdef __GO32__ # include <pc.h> -# define getch() getkey() /* GRR: need getche() */ +# define getch() getkey() /* GRR: need getche() */ # else -# include <conio.h> /* for getche() console input */ +# include <conio.h> /* for getche() console input */ # endif # endif /* ?__EMX__ */ # define FGETS(buf,len,stream) dos_kbd_gets(buf,len) #else -# include <unistd.h> /* for isatty() prototype */ +# include <unistd.h> /* for isatty() prototype */ # define FGETS fgets #endif @@ -87,7 +95,7 @@ text that includes control characters discouraged by the PNG spec; text that includes an escape character (27) must be re-entered regardless */ -#include "writepng.h" /* typedefs, common macros, writepng prototypes */ +#include "writepng.h" /* typedefs, common macros, writepng prototypes */ @@ -112,7 +120,7 @@ int main(int argc, char **argv) FILE *keybd; #endif #ifdef sgi - FILE *tmpfile; /* or we could just use keybd, since no overlap */ + FILE *tmpfile; /* or we could just use keybd, since no overlap */ char tmpline[80]; #endif char *inname = NULL, outname[256]; @@ -204,36 +212,40 @@ int main(int argc, char **argv) /* Now parse the command line for options and the PNM filename. */ while (*++argv && !error) { - if (!strcmp(*argv, "-interlaced")) { + if (!strncmp(*argv, "-i", 2)) { wpng_info.interlaced = TRUE; - } else if (!strcmp(*argv, "-time")) { + } else if (!strncmp(*argv, "-time", 3)) { wpng_info.modtime = time(NULL); wpng_info.have_time = TRUE; - } else if (!strcmp(*argv, "-text")) { + } else if (!strncmp(*argv, "-text", 3)) { text = TRUE; - } else if (!strcmp(*argv, "-gamma")) { + } else if (!strncmp(*argv, "-gamma", 2)) { if (!*++argv) ++error; - wpng_info.gamma = atof(*argv); - if (wpng_info.gamma <= 0.0) - ++error; - else if (wpng_info.gamma > 1.01) - fprintf(stderr, PROGNAME - " warning: file gammas are usually less than 1.0\n"); - } else if (!strcmp(*argv, "-bgcolor")) { + else { + wpng_info.gamma = atof(*argv); + if (wpng_info.gamma <= 0.0) + ++error; + else if (wpng_info.gamma > 1.01) + fprintf(stderr, PROGNAME + " warning: file gammas are usually less than 1.0\n"); + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { if (!*++argv) ++error; - bgstr = *argv; - if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; else { - unsigned r, g, b; /* this approach quiets compiler warnings */ - - sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); - wpng_info.bg_red = (uch)r; - wpng_info.bg_green = (uch)g; - wpng_info.bg_blue = (uch)b; - wpng_info.have_bg = TRUE; + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + unsigned r, g, b; /* this way quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + wpng_info.bg_red = (uch)r; + wpng_info.bg_green = (uch)g; + wpng_info.bg_blue = (uch)b; + wpng_info.have_bg = TRUE; + } } } else { if (**argv != '-') { @@ -362,7 +374,7 @@ int main(int argc, char **argv) "\t\t (where LUT = lookup-table exponent and CRT = CRT exponent;\n" "\t\t first varies, second is usually 2.2, all are positive)\n" " bg \tdesired background color for alpha-channel images, in\n" - "\t\t 7-character hex RGB format (e.g., ``#ff7f00'' for orange:\n" + "\t\t 7-character hex RGB format (e.g., ``#ff7700'' for orange:\n" "\t\t same as HTML colors)\n" " -text\tprompt interactively for text info (tEXt chunks)\n" " -time\tinclude a tIME chunk (last modification time)\n" @@ -419,7 +431,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_TITLE; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_TITLE; valid = FALSE; } @@ -449,7 +461,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_AUTHOR; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_AUTHOR; valid = FALSE; } @@ -489,7 +501,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_DESC; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_DESC; valid = FALSE; } @@ -519,7 +531,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_COPY; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_COPY; valid = FALSE; } @@ -549,7 +561,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_EMAIL; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_EMAIL; valid = FALSE; } @@ -579,7 +591,7 @@ int main(int argc, char **argv) wpng_info.have_text &= ~TEXT_URL; valid = FALSE; #else - if (p[result] == 27) { /* escape character */ + if (p[result] == 27) { /* escape character */ wpng_info.have_text &= ~TEXT_URL; valid = FALSE; } @@ -755,7 +767,7 @@ static int wpng_isvalid_latin1(uch *p, int len) -static void wpng_cleanup() +static void wpng_cleanup(void) { if (wpng_info.outfile) { fclose(wpng_info.outfile); @@ -791,11 +803,11 @@ static char *dos_kbd_gets(char *buf, int len) buf[count++] = ch = getche(); } while (ch != '\r' && count < len-1); - buf[count--] = '\0'; /* terminate string */ - if (buf[count] == '\r') /* Enter key makes CR, so change to newline */ + buf[count--] = '\0'; /* terminate string */ + if (buf[count] == '\r') /* Enter key makes CR, so change to newline */ buf[count] = '\n'; - fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */ + fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */ fflush(stderr); return buf; diff --git a/contrib/gregbook/writepng.c b/contrib/gregbook/writepng.c index b94c677f8..6802b12fb 100644 --- a/contrib/gregbook/writepng.c +++ b/contrib/gregbook/writepng.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 @@ -30,10 +30,10 @@ ---------------------------------------------------------------------------*/ -#include <stdlib.h> /* for exit() prototype */ +#include <stdlib.h> /* for exit() prototype */ -#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ -#include "writepng.h" /* typedefs, common macros, public prototypes */ +#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include "writepng.h" /* typedefs, common macros, public prototypes */ /* local prototype */ @@ -42,7 +42,7 @@ static void writepng_error_handler(png_structp png_ptr, png_const_charp msg); -void writepng_version_info() +void writepng_version_info(void) { fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); @@ -82,7 +82,7 @@ int writepng_init(mainprog_info *mainprog_ptr) * but compatible error handlers must either use longjmp() themselves * (as in this program) or exit immediately, so here we go: */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); return 2; } @@ -239,7 +239,7 @@ int writepng_encode_image(mainprog_info *mainprog_ptr) /* as always, setjmp() must be called in every function that calls a * PNG-writing libpng function */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); mainprog_ptr->png_ptr = NULL; mainprog_ptr->info_ptr = NULL; @@ -277,7 +277,7 @@ int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */ /* as always, setjmp() must be called in every function that calls a * PNG-writing libpng function */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); mainprog_ptr->png_ptr = NULL; mainprog_ptr->info_ptr = NULL; @@ -307,7 +307,7 @@ int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */ /* as always, setjmp() must be called in every function that calls a * PNG-writing libpng function */ - if (setjmp(png_jmp_env(mainprog_ptr))) { + if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); mainprog_ptr->png_ptr = NULL; mainprog_ptr->info_ptr = NULL; diff --git a/contrib/gregbook/writepng.h b/contrib/gregbook/writepng.h index 123d2d662..93c3da820 100644 --- a/contrib/gregbook/writepng.h +++ b/contrib/gregbook/writepng.h @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-1999 Greg Roelofs. All rights reserved. + 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 |