xloadimage.4.1/ 775 221 144 0 5470014510 6447 xloadimage.4.1/Imakefile 444 221 144 5070 5470014462 10351 # Imakefile for building within the X11 source tree. # This Imakefile was automatically generated from Makefile.std. # # If you have problems building, you should read the README file and # consider using Makefile.std. # # If you use gcc, you should read the README file and consider using # Makefile.std. SYSPATHFILE = $(XAPPLOADDIR)/Xloadimage DEFINES = -DSYSPATHFILE=\"$(SYSPATHFILE)\" DEPLIBS = $(DEPXLIB) LOCAL_LIBRARIES = $(XLIB) SYS_LIBRARIES = -lm #ifdef HPArchitecture CCOPTIONS = -Aa -D_HPUX_SOURCE #endif # Comment out either of the next two lines if you don't have TIFF or JPEG libs #define HAS_TIFF #define HAS_JPEG #ifdef HAS_TIFF TIFF_DEFS = -DHAS_TIFF -I/usr/local/include TIFF_LIB = -L/usr/local/lib/tiff -ltiff TIFF_SRC = tiff.c TIFF_OBJ = tiff.o #endif #ifdef HAS_JPEG JPEG_DEFS = -DHAS_JPEG -I/usr/local/include/jpeg JPEG_LIB = -L/usr/local/lib/jpeg -ljpeg JPEG_SRC = jpeg.c JPEG_OBJ = jpeg.o #endif EXTRA_DEFINES = $(TIFF_DEFS) $(JPEG_DEFS) LOCAL_LIBRARIES = $(TIFF_LIB) $(JPEG_LIB) $(XLIB) SRCS = new.c niff.c value.c zio.c cmuwmraster.c faces.c fbm.c gif.c imagetypes.c img.c mac.c mcidas.c mc_tables.c pbm.c pcx.c pdsuncomp.c rle.c rlelib.c sunraster.c vff.c vicar.c xbitmap.c xpixmap.c xwd.c bright.c clip.c compress.c dither.c fill.c halftone.c merge.c reduce.c rotate.c smooth.c undither.c zoom.c config.c misc.c options.c root.c send.c window.c xloadimage.c $(TIFF_SRC) $(JPEG_SRC) OBJS = new.o niff.o value.o zio.o cmuwmraster.o faces.o fbm.o gif.o imagetypes.o img.o mac.o mcidas.o mc_tables.o pbm.o pcx.o pdsuncomp.o rle.o rlelib.o sunraster.o vff.o vicar.o xbitmap.o xpixmap.o xwd.o bright.o clip.o compress.o dither.o fill.o halftone.o merge.o reduce.o rotate.o smooth.o undither.o zoom.o config.o misc.o options.o root.o send.o window.o xloadimage.o $(TIFF_OBJ) $(JPEG_OBJ) AllTarget(xloadimage uufilter) ComplexProgramTarget(xloadimage) NormalProgramTarget(uufilter,uufilter.o,,,) InstallProgram(uufilter,$(BINDIR)) InstallManPage(uufilter,$(MANDIR)) install:: $(SYSPATHFILE) $(RM) $(BINDIR)/xview $(BINDIR)/xsetbg cd $(BINDIR); $(LN) xloadimage xview; $(LN) xloadimage xsetbg clean:: /bin/rm -f build.c build.c: ./build-info $(SYSPATHFILE): @echo "*** Creating default $(SYSPATHFILE) since you" @echo "*** don't have one. This file is used to set up default places" @echo "*** and names to look for images. You probably want to edit" @echo "*** it for your site. See the xloadimage manual page for" @echo "*** details on the contents of this file." cp xloadimagerc $(SYSPATHFILE) chmod a+r $(SYSPATHFILE) xloadimage.4.1/Makefile 664 221 144 14575 5470014310 10226 # Makefile for xloadimage. this replaces the multiple makefiles used in # versions prior to xloadimage 2.00. # # WARNING: if you use gcc 1.37, there is an optimizer bug which causes GIF # images to come out black and colormap reduction to fail. Use gcc-1-37 as # your make target if you have gcc 1.37. # Include system configuration parameters include Make.conf CFLAGS=$(OPT_FLAGS) $(CC_FLAGS) $(CC_CONFIG_FLAGS) $(X11_INC_DIR) \ -DSYSPATHFILE=\"$(SYSPATHFILE)\" LIBS=$(X11_LIB_DIR) $(X11_LIB_NAME) $(SYS_LIBS) -lm # stuff that should eventually make the configuration file SYSPATHFILE=/usr/lib/X11/Xloadimage default: configure$(CONFIG_STYLE) $(MAKE) xloadimage $(MAKE) uufilter # this target gets hit automatically on the first run; it sets up # the Make.conf file and recursively calls make. autoconfig: autoconfig.c $(CC) -g -o autoconfig autoconfig.c # manual configuration target configure:: autoconfig ./autoconfig $(MAKE) configure-libraries # this is the default target for the initial compilation configure-auto:: autoconfig ./autoconfig $(MAKE) configure-libraries # target that doesn't do anything configure-skip:: @echo "Already configured, skipping configuration process." configure-clean:: autoconfig ./autoconfig -clean echo "# this will contain information generated by libconfig" > jpeg.conf echo "# this will contain information generated by libconfig" > tiff.conf cd jpeg ; make clean cd tiff ; make clean # specific configurations configure-bsd:: autoconfig ./autoconfig -bsd $(MAKE) configure-libraries configure-sysv:: autoconfig ./autoconfig -sysv $(MAKE) configure-libraries # this program configures optional libraries configure-libraries:: $(CC) $(CC_FLAGS) -g -o libconfig libconfig.c ./libconfig "$(CC)" "$(OPT_FLAGS)" MISC= Imakefile Makefile Makefile.std VMS_BUILD.COM README build-imake \ build-vms build-info buildshar.c packtar.c xloadimage.man \ xloadimage.txt autoconfig.c Make.conf libconfig.c \ makefloppy jpeg.c tiff.c uufilter.man uufilter.txt uufilter.c \ xloadimagerc # files for the loader library LOADER_HDRS= cmuwmraster.h fbm.h gif.h imagetypes.h img.h \ kljcpyrght.h mac.h mcidas.h mit.cpyrght mrmcpyrght.h \ niff.h pbm.h pcx.h pds.h rle.h sunraster.h xwd.h tgncpyrght.h LOADER_SRCS= cmuwmraster.c faces.c fbm.c gif.c imagetypes.c img.c \ mac.c mcidas.c mc_tables.c pbm.c pcx.c pdsuncomp.c \ rle.c rlelib.c sunraster.c vff.c vicar.c xbitmap.c xpixmap.c \ xwd.c LOADER_OBJS= ${LOADER_SRCS:.c=.o} # files for the image library IMAGE_HDRS= copyright.h image.h IMAGE_SRCS= new.c niff.c value.c zio.c IMAGE_OBJS= ${IMAGE_SRCS:.c=.o} # files for the image processing library PROCESS_HDRS= PROCESS_SRCS= bright.c clip.c compress.c dither.c fill.c halftone.c \ merge.c reduce.c rotate.c smooth.c undither.c zoom.c PROCESS_OBJS= ${PROCESS_SRCS:.c=.o} OPTIONAL_OBJS= ${OPTIONAL_SRCS:.c=.o} # files for xloadimage (X display utility) X_HDRS= options.h patchlevel xloadimage.h X_SRCS= config.c misc.c options.c root.c send.c window.c \ xloadimage.c X_OBJS= ${X_SRCS:.c=.o} INCS= $(IMAGE_HDRS) $(LOADER_HDRS) $(PROCESS_HDRS) $(X_HDRS) SRCS= $(IMAGE_SRCS) $(LOADER_SRCS) $(PROCESS_SRCS) $(X_SRCS) $(OPTIONAL_SRCS) OBJS= $(IMAGE_OBJS) $(LOADER_OBJS) $(PROCESS_OBJS) $(X_OBJS) $(OPTIONAL_OBJS) ALL= $(MISC) $(INCS) $(SRCS) .c.o: Make.conf xloadimage.h image.h $*.c $(CC) -c $(CFLAGS) $*.c jpeg.o: Make.conf image.h $(CC) -c $(CFLAGS) -Ijpeg $*.c uufilter: uufilter.c $(CC) -o uufilter $(CFLAGS) uufilter.c xloadimage: $(OBJS) $(OPTIONAL_LIBS) ./build-info $(CC) -c $(CFLAGS) build.c $(CC) -o xloadimage $(CFLAGS) build.o $(OBJS) $(OPTIONAL_LIBS) $(LIBS) install:: $(SYSPATHFILE) uufilter $(RM) $(INSTALLDIR)/xloadimage $(RM) $(INSTALLDIR)/xsetbg $(RM) $(INSTALLDIR)/xview $(RM) $(INSTALLDIR)/uufilter $(CP) xloadimage $(INSTALLDIR)/xloadimage $(LN) $(INSTALLDIR)/xloadimage $(INSTALLDIR)/xsetbg $(LN) $(INSTALLDIR)/xloadimage $(INSTALLDIR)/xview $(CP) uufilter $(INSTALLDIR)/uufilter clean:: rm -f autoconfig make configure-clean rm -f *.o *~ xloadimage uufilter autoconfig libconfig packtar \ buildshar doshar shar.* *.tar *.tar.Z *.tc $(SYSPATHFILE): @echo "*** Creating default $(SYSPATHFILE) since you" @echo "*** don't have one. This file is used to set up default places" @echo "*** and names to look for images. You probably want to edit" @echo "*** it for your site. See the xloadimage manual page for" @echo "*** details on the contents of this file." cp xloadimagerc $(SYSPATHFILE) # this is for building Imakefiles and such for distributions new-auxiliaries:: clean rm -f Imakefile Makefile.std VMS_BUILD.COM xloadimage.txt cp Makefile Makefile.std # backup in case they want it ./build-imake "$(SRCS)" "$(OBJS)" ./build-vms "$(SRCS)" "$(OBJS)" ./default-info nroff -Tcrt -man xloadimage.man > xloadimage.txt nroff -Tcrt -man uufilter.man > uufilter.txt # these targets are for building shar distributions buildshar: buildshar.o $(CC) -o buildshar buildshar.o shar:: buildshar new-auxiliaries rm -f shar.* doshar ./buildshar $(ALL) > doshar sh doshar rm -f doshar Makefile.std # targets for building tar distributions packtar: packtar.c $(CC) -o packtar packtar.c tar:: new-auxiliaries packtar ./packtar $(ALL) sample/* jpeg/* tiff/* rm -f Imakefile Makefile.std tar.Z: tar compress xloadimage.tar # create a floppy-disk distribution. floppy: new-auxiliaries ./makefloppy $(ALL) sample ./makefloppy tiff ./makefloppy jpeg rm -f Imakefile Makefile.std # these targets are for those of us who have CodeCenter/Saber-C # load all objects in CodeCenter. cl_obj: $(DEBUG_OBJS) #setopt ccargs -g $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #setopt load_flags $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #load build.o $(OBJS) $(OPTIONAL_LIBS) $(LIBS) #link # load all sources in CodeCenter. cl_src: #setopt ccargs -g $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #setopt load_flags $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #load build.c $(SRCS) $(OPTIONAL_LIBS) $(LIBS) #link # proof xloadimage using TestCenter. xloadimage.tc: proof -errors $(CC) -o xloadimage.tc build.o $(CFLAGS) $(OBJS) $(OPTIONAL_LIBS) $(LIBS) jpeg/libjpeg.a: cd jpeg ; $(MAKE) libjpeg.a tiff/libtiff.a: cd tiff ; $(MAKE) libtiff.a # a few dependencies imagetypes.o: imagetypes.h imagetypes.c AL_OBJS= ${OPTIONAL_SRCS:.c=.o} # files for xloadimage (X display utility) X_HDRS= options.h patchlevel xloadimage.h X_SRCS= confixloadimage.4.1/Makefile.std 664 221 144 14575 5470014461 11026 # Makefile for xloadimage. this replaces the multiple makefiles used in # versions prior to xloadimage 2.00. # # WARNING: if you use gcc 1.37, there is an optimizer bug which causes GIF # images to come out black and colormap reduction to fail. Use gcc-1-37 as # your make target if you have gcc 1.37. # Include system configuration parameters include Make.conf CFLAGS=$(OPT_FLAGS) $(CC_FLAGS) $(CC_CONFIG_FLAGS) $(X11_INC_DIR) \ -DSYSPATHFILE=\"$(SYSPATHFILE)\" LIBS=$(X11_LIB_DIR) $(X11_LIB_NAME) $(SYS_LIBS) -lm # stuff that should eventually make the configuration file SYSPATHFILE=/usr/lib/X11/Xloadimage default: configure$(CONFIG_STYLE) $(MAKE) xloadimage $(MAKE) uufilter # this target gets hit automatically on the first run; it sets up # the Make.conf file and recursively calls make. autoconfig: autoconfig.c $(CC) -g -o autoconfig autoconfig.c # manual configuration target configure:: autoconfig ./autoconfig $(MAKE) configure-libraries # this is the default target for the initial compilation configure-auto:: autoconfig ./autoconfig $(MAKE) configure-libraries # target that doesn't do anything configure-skip:: @echo "Already configured, skipping configuration process." configure-clean:: autoconfig ./autoconfig -clean echo "# this will contain information generated by libconfig" > jpeg.conf echo "# this will contain information generated by libconfig" > tiff.conf cd jpeg ; make clean cd tiff ; make clean # specific configurations configure-bsd:: autoconfig ./autoconfig -bsd $(MAKE) configure-libraries configure-sysv:: autoconfig ./autoconfig -sysv $(MAKE) configure-libraries # this program configures optional libraries configure-libraries:: $(CC) $(CC_FLAGS) -g -o libconfig libconfig.c ./libconfig "$(CC)" "$(OPT_FLAGS)" MISC= Imakefile Makefile Makefile.std VMS_BUILD.COM README build-imake \ build-vms build-info buildshar.c packtar.c xloadimage.man \ xloadimage.txt autoconfig.c Make.conf libconfig.c \ makefloppy jpeg.c tiff.c uufilter.man uufilter.txt uufilter.c \ xloadimagerc # files for the loader library LOADER_HDRS= cmuwmraster.h fbm.h gif.h imagetypes.h img.h \ kljcpyrght.h mac.h mcidas.h mit.cpyrght mrmcpyrght.h \ niff.h pbm.h pcx.h pds.h rle.h sunraster.h xwd.h tgncpyrght.h LOADER_SRCS= cmuwmraster.c faces.c fbm.c gif.c imagetypes.c img.c \ mac.c mcidas.c mc_tables.c pbm.c pcx.c pdsuncomp.c \ rle.c rlelib.c sunraster.c vff.c vicar.c xbitmap.c xpixmap.c \ xwd.c LOADER_OBJS= ${LOADER_SRCS:.c=.o} # files for the image library IMAGE_HDRS= copyright.h image.h IMAGE_SRCS= new.c niff.c value.c zio.c IMAGE_OBJS= ${IMAGE_SRCS:.c=.o} # files for the image processing library PROCESS_HDRS= PROCESS_SRCS= bright.c clip.c compress.c dither.c fill.c halftone.c \ merge.c reduce.c rotate.c smooth.c undither.c zoom.c PROCESS_OBJS= ${PROCESS_SRCS:.c=.o} OPTIONAL_OBJS= ${OPTIONAL_SRCS:.c=.o} # files for xloadimage (X display utility) X_HDRS= options.h patchlevel xloadimage.h X_SRCS= config.c misc.c options.c root.c send.c window.c \ xloadimage.c X_OBJS= ${X_SRCS:.c=.o} INCS= $(IMAGE_HDRS) $(LOADER_HDRS) $(PROCESS_HDRS) $(X_HDRS) SRCS= $(IMAGE_SRCS) $(LOADER_SRCS) $(PROCESS_SRCS) $(X_SRCS) $(OPTIONAL_SRCS) OBJS= $(IMAGE_OBJS) $(LOADER_OBJS) $(PROCESS_OBJS) $(X_OBJS) $(OPTIONAL_OBJS) ALL= $(MISC) $(INCS) $(SRCS) .c.o: Make.conf xloadimage.h image.h $*.c $(CC) -c $(CFLAGS) $*.c jpeg.o: Make.conf image.h $(CC) -c $(CFLAGS) -Ijpeg $*.c uufilter: uufilter.c $(CC) -o uufilter $(CFLAGS) uufilter.c xloadimage: $(OBJS) $(OPTIONAL_LIBS) ./build-info $(CC) -c $(CFLAGS) build.c $(CC) -o xloadimage $(CFLAGS) build.o $(OBJS) $(OPTIONAL_LIBS) $(LIBS) install:: $(SYSPATHFILE) uufilter $(RM) $(INSTALLDIR)/xloadimage $(RM) $(INSTALLDIR)/xsetbg $(RM) $(INSTALLDIR)/xview $(RM) $(INSTALLDIR)/uufilter $(CP) xloadimage $(INSTALLDIR)/xloadimage $(LN) $(INSTALLDIR)/xloadimage $(INSTALLDIR)/xsetbg $(LN) $(INSTALLDIR)/xloadimage $(INSTALLDIR)/xview $(CP) uufilter $(INSTALLDIR)/uufilter clean:: rm -f autoconfig make configure-clean rm -f *.o *~ xloadimage uufilter autoconfig libconfig packtar \ buildshar doshar shar.* *.tar *.tar.Z *.tc $(SYSPATHFILE): @echo "*** Creating default $(SYSPATHFILE) since you" @echo "*** don't have one. This file is used to set up default places" @echo "*** and names to look for images. You probably want to edit" @echo "*** it for your site. See the xloadimage manual page for" @echo "*** details on the contents of this file." cp xloadimagerc $(SYSPATHFILE) # this is for building Imakefiles and such for distributions new-auxiliaries:: clean rm -f Imakefile Makefile.std VMS_BUILD.COM xloadimage.txt cp Makefile Makefile.std # backup in case they want it ./build-imake "$(SRCS)" "$(OBJS)" ./build-vms "$(SRCS)" "$(OBJS)" ./default-info nroff -Tcrt -man xloadimage.man > xloadimage.txt nroff -Tcrt -man uufilter.man > uufilter.txt # these targets are for building shar distributions buildshar: buildshar.o $(CC) -o buildshar buildshar.o shar:: buildshar new-auxiliaries rm -f shar.* doshar ./buildshar $(ALL) > doshar sh doshar rm -f doshar Makefile.std # targets for building tar distributions packtar: packtar.c $(CC) -o packtar packtar.c tar:: new-auxiliaries packtar ./packtar $(ALL) sample/* jpeg/* tiff/* rm -f Imakefile Makefile.std tar.Z: tar compress xloadimage.tar # create a floppy-disk distribution. floppy: new-auxiliaries ./makefloppy $(ALL) sample ./makefloppy tiff ./makefloppy jpeg rm -f Imakefile Makefile.std # these targets are for those of us who have CodeCenter/Saber-C # load all objects in CodeCenter. cl_obj: $(DEBUG_OBJS) #setopt ccargs -g $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #setopt load_flags $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #load build.o $(OBJS) $(OPTIONAL_LIBS) $(LIBS) #link # load all sources in CodeCenter. cl_src: #setopt ccargs -g $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #setopt load_flags $(CC_FLAGS) $(X11_INC_DIR) -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" #load build.c $(SRCS) $(OPTIONAL_LIBS) $(LIBS) #link # proof xloadimage using TestCenter. xloadimage.tc: proof -errors $(CC) -o xloadimage.tc build.o $(CFLAGS) $(OBJS) $(OPTIONAL_LIBS) $(LIBS) jpeg/libjpeg.a: cd jpeg ; $(MAKE) libjpeg.a tiff/libtiff.a: cd tiff ; $(MAKE) libtiff.a # a few dependencies imagetypes.o: imagetypes.h imagetypes.c e.man \ xloadimage.txt autoconfig.c Make.conf libconfig.c \ makefloppy jpeg.c tiff.c uufilter.man uufilter.txt uufilterxloadimage.4.1/VMS_BUILD.COM 555 221 144 3362 5470014464 10473 $set noon $define sys sys$library $define x11 decw$include $! $write sys$output "Compiling..." $cc new.c:r $cc niff.c:r $cc value.c:r $cc zio.c:r $cc cmuwmraster.c:r $cc faces.c:r $cc fbm.c:r $cc gif.c:r $cc imagetypes.c:r $cc img.c:r $cc mac.c:r $cc mcidas.c:r $cc mc_tables.c:r $cc pbm.c:r $cc pcx.c:r $cc pdsuncomp.c:r $cc rle.c:r $cc rlelib.c:r $cc sunraster.c:r $cc vff.c:r $cc vicar.c:r $cc xbitmap.c:r $cc xpixmap.c:r $cc xwd.c:r $cc bright.c:r $cc clip.c:r $cc compress.c:r $cc dither.c:r $cc fill.c:r $cc halftone.c:r $cc merge.c:r $cc reduce.c:r $cc rotate.c:r $cc smooth.c:r $cc undither.c:r $cc zoom.c:r $cc config.c:r $cc misc.c:r $cc options.c:r $cc root.c:r $cc send.c:r $cc window.c:r $cc xloadimage.c:r $cc vms-build.c $! $write sys$output "Linking..." $link xloadimage, - new.o:r, - niff.o:r, - value.o:r, - zio.o:r, - cmuwmraster.o:r, - faces.o:r, - fbm.o:r, - gif.o:r, - imagetypes.o:r, - img.o:r, - mac.o:r, - mcidas.o:r, - mc_tables.o:r, - pbm.o:r, - pcx.o:r, - pdsuncomp.o:r, - rle.o:r, - rlelib.o:r, - sunraster.o:r, - vff.o:r, - vicar.o:r, - xbitmap.o:r, - xpixmap.o:r, - xwd.o:r, - bright.o:r, - clip.o:r, - compress.o:r, - dither.o:r, - fill.o:r, - halftone.o:r, - merge.o:r, - reduce.o:r, - rotate.o:r, - smooth.o:r, - undither.o:r, - zoom.o:r, - config.o:r, - misc.o:r, - options.o:r, - root.o:r, - send.o:r, - window.o:r, - vms-build.o, - sys$input:/options sys$share:decw$xlibshr/share $! $exit c8Xzoom.ciLvconfig.coom\.misc.cfp options.cscroot.cisend.cwindow.cend' xloadimage.cc@sampleajpeg tiffer.man uufilter.txt uufilterxloadimage.4.1/README 664 221 144 44357 5470013531 7453 XLOADIMAGE - X11 Image Loading Utility WHAT IS IT? This utility will view several types of images under X11, load images onto the root window, or dump processed images into one of several image file formats. The current version can read many different image file types; for a complete list type "xloadimage -supported". A variety of options are available to modify images prior to viewing. These options include clipping, dithering, depth reduction, zoom (either X or Y axis independently or both at once), brightening or darkening, and image merging. When applicable, these options are done automatically (eg a color image to be displayed on a monochrome screen will be dithered automatically). TIFF AND JPEG SUPPORT This version of xloadimage supports both JPEG and TIFF files through the IJG V4 JPEG library and the Sam Leffler's V3 TIFF library. The libraries are included almost in their entirety. The libconfig.c program is used to create appropriate Makefile configurations so that no special intervention is required to compile these libraries on most systems. If there are problems compiling these libraries on your system you can leave out support for them during the configuration process. In my tests on various machines there were never any problems building the supplied libraries. Unfortunately I cannot answer most questions regarding these libraries. You can direct such questions to: jpeg-info@uunet.uu.net tiff@ucbvax.berkeley.edu BUILDING THE RELEASE To build xloadimage simply type "make". If you prefer to use xmkmf or imake, please read the note below before doing so. Xloadimage will build a configuration program first and run it -- the configuration program will look at your system to try to determine what variety of system it is, where the X libraries and include files are, and whether or not some nonstandard libraries are likely to be needed. The configuration program is specifically designed to make the configuration process very painless on most systems available today, but it cannot predict all possible variations. If the configuration program cannot find something that it's looking for it will ask you where it is and it will attempt to verify the correctness of your response. You will also be prompted for the name of the C compiler you want to use, and where the TIFF and JPEG libraries and header files are located. The questions should be simple and straightforward; if you don't know the answer to a question you can usually hit "return" and the default will work. If you make a mistake during configuration you can interrupt the configuration program (using ^C or whatever the interrupt character is on your system); type "make" to restart. If you are building xloadimage on multiple systems you should type "make clean" to clean up the build on the previous system; the configuration will be re-run when you type "make". Once configured the xloadimage distribution will continue to use the same configuration parameters until a "make clean" or "make configure" is done. All configuration options are written into Make.conf; if you need to make changes and don't like the configuration utility you can always edit the file yourself. Keep another copy of any such changes because xloadimage will overwrite Make.conf whenever you do a "make clean" or if it needs to rebuild the configuration program. NOTE: The Makefile assumes that "cc" exists and can be used to build the configuration program. If your C compiler isn't called "cc" or is not found along your path you will need to edit the CC= line in Make.conf to provide the appropriate compiler name. NOTE: Many sites use the xmkmf to generate an appropriate Makefile from an Imakefile when building X applications. While xloadimage includes an Imakefile for this purpose IT IS STRONGLY RECOMMENDED THAT YOU DO NOT USE XMKMF OR IMAKE. There is not enough information included in the MIT releases to determine the appropriate configuration for xloadimage. For this reason some capabilities cannot be configured using xmkmf/imake. If you decide to use xmkmf and/or imake anyway and you have problems building the distribution you should copy Makefile.std into Makefile and follow the normal installation instructions. NOTE: If you are on a VMS system the automatic configuration code won't work at all. There is a VMS_BUILD.COM script included which should be close to what you need to build xloadimage. Unfortunately I cannot test this script so it may not be perfect -- you're on your own if you're using VMS (which is probably not surprising if you've done this kind of thing before). INSTALLATION After compiling and installing xloadimage, I recommend linking or symlinking to the executable with the names "xview" and "xsetbg". The default behavior is slightly different when invoked with these commands (they're also easier to type). If you have a public image area you should consider setting the SYSPATHFILE option in the makefile and setting up a system-wide configuration file. See the man page for information on the format of this file. IMPLEMENTATION Most functions are not particularly fast, and some functions use simple-minded algorithms deliberately over more advanced ones. I stressed portability over all and simplicity over performance, although many algorithms have become fairly complex over time. I believe the result is a usable, portable tool which should serve the needs of most users. The source code is basically in two parts: image manipulation routines and everything else. The image manipulation routines should be completely independent of X, thus allowing people to use them under other graphical systems. No guarantees here, but I tried. Performance-oriented people will notice that some operations are redundant. Xloadimage is designed to work fairly quickly for most operations but in some cases I opted for a cleaner internal design rather than pure performance. OWNERSHIP AND COMMERCIAL USE I used a modified version of the MIT X Consortium copyright with all of these functions, thereby allowing full freedom with the code so long as the copyright notices remain intact. All contributions have similar notices. Commercial sites are welcome to use the code even without special permission, licensing or royalty fees. I'm very happy to hear of this stuff going toward real products (it's in several that I am aware of) so I appreciate hearing of any use of some or all of the code in other applications. If you tell me you're using it I'm much more likely to keep you informed about new versions as well, so it works out well all around. Xloadimage does not require any form of licensing or royalty payment to use in a commercial product, but the MIT copyright does require mention of the copyright notice in accompanying documentation; xloadimage has several copyrights that may need inclusion. It's unlikely that I would ever prosecute someone for neglecting to follow the terms of the copyright. If you're using xloadimage in a commercial product beware that it adds handlers for common exceptions that print out my email address. While I'm happy to support any xloadimage user it is difficult to support them if I don't know about changes you have made. At the very least modifications should include changes to the patchlevel information to indicate your company and/or product name even if you do not change the email address. PRAISE, SUGGESTIONS AND BUG REPORTS Praise, suggestions, and bug reports should go to: Jim Frost CenterLine Software 10 Fawcett Street Cambridge, MA 02138 (617) 498-3000 jimf@centerline.com Please include the version number and sample image data if you are reporting a bug. Functions implementing new image types are welcomed; mail them to the same address and I'll do my best to distribute them. Please include a small sample image. Try to send them as public domain so I can keep the number of differing copyright messages to a minimum -- I'll use my standard message and leave the implementor's name and information in the file for credit. I wouldn't copyright this stuff at all except that it's a requirement for X11 distribution. If you particularly like xloadimage, feel free to drop me a line. It makes me feel good and I get a feel for who does what with it, which sometimes influences what parts are worked on. THANKS Special thanks to the crew at the Boston University Graphics Lab for their assistance and sample images, and to bzs@std.com for his simple dithering algorithm (or what's left of it). Real special thanks to Kirk L. Johnson (tuna@athena.mit.edu) for a very nice GIF loader and dithering routine, to Mark Snitily (zok!mark@apple.com) for 386/ix compatibility work, to Andreas Stolcke (stolcke@icsib12.berkeley.edu) for miscellaneous bug fixes, to Anthony A. Datri (datri@convex.com) for a number of things, to Mark Moraes (moraes@cs.toronto.edu) for the slideshow colormap fix, to Gregg Townsend (gmt@cs.arizona.edu) for a suggested dithering routine and other fixes, to Brian Frost (B1F5814@RIGEL.TAMU.EDU) for changes for VMS, to Chip Horstman for G3 FAX support, to Deron Dann Johnson (dj@eng.sun.com) for fixing the RetainTemporary bug, to Tom Tatlow (tatlow@dash.enet.dec.com) for image rotation code, to Mark A. Horstman (mhorstm@sarek.sbc.com) for tilde expansion in .xloadimagerc files and virtual-root support in root.c, to Tim Roper (timr@labtam.labtam.oz.au), Graeme Gill (graeme@labtam.oz.au) for gamma correction and Utah RLE image support, Mark Majhor (uunet!sequent!markm) for FBM and MacPaint support, Ian MacPhedran (macphed@dvinci.usask.ca) for PGM and PPM support, Per Fogelstrom (pf@diab.se) for a fix to send.c, Hans J. Albertsson (hans@Sweden.Sun.COM) for cleaning up GIF aborting, Graham Hudspith (gwh@inmos.com) for a geometry patch, Glenn P. Davis (davis@unidata.ucar.edu) for McIDAS areafile support, Keith S. Pickens (maxwell.nde.swri.edu!ksp) for fixing the RLE loader to work with the updated zio package, Mike Douglas (douglas@wilbur.coyote.trw.com) for normalization, Rod Johnson (johnson@wrl.epi.com) for speedup suggestions, Hal Peterson (hrp@cray.com) for his Imakefile fix, Matt Caprile (Matthew.Caprile@ec.bull.fr) for slideshow delay code, Bob Deroy (rwd@bucrsb.bu.edu) for mondo 24-bit Sun Rasterfile images that broke everything, Christos S. Zoulas (christo@ee.cornell.edu) for a first-cut 24-bit implementation, Gerald James Barnes (gjb@oasis.icl.stc.co.uk) for a first-cut forced-visual implementation, Michael Campanella (campanella@cvg.enet.dec.com) for more VMS changes, Kee Hinckley (nazgul@alfalfa.com) for robustness changes to the g3 and MacPaint loaders and the ZIO package, Tim Northrup (tim@brspyr1.brs.com) for PC Paintbrush and GEM image formats, Richard Weidner (richard@elroy.jpl.nasa.gov) for lots of 24-bit testing, Eckhard Rueggeberg (erueg@cfgauss.uni-math.gwdg.de) for a better PCX loader, and any others whose names I've missed. HISTORY Patch 01 contained a new Makefile.std, Makefile.gcc, and Imakefile. It contained a bug-fix to sendImageToX() which allowed bitmaps to be sent from little-endian machines (eg VAX, 80386) correctly, and a fix to xbitmapLoad() to allow correct loading of X10 bitmap images. An enhancement to imageInWindow() which allowed exiting from image windows by typing 'q' was submitted by Chris Tengi (tengi@idunno.princeton.edu) and was included. The previously missing file 'patchlevel' was included. Patch 02 contained modifications to the Makefiles, support for the X Pixmap image type, a different dithering algorithm that didn't blow the image up (with the old one moved to halftone.c), and a bug fix to zoom.c to correct problems when zooming bitmaps. Patch 03 contained a new loader for GIF files. The dither bits array in dither.c was changed so it worked properly, and both dither.c and halftone.c had minor bugs fixed. Merge.c was modified to correct bugs when merging RGB images. Pbm.c was modified to handle raw format images. Root.c was modified to deny image loads which would change the root window's colormap. Send.c was modified to use shared colors whenever possible and to handle color displays which have depths which are not a multiple of 8. Window.c was modified to avoid deleting the default colormap, allowing proper operation on some servers prior to X11R3 patchlevel 08. There were many miscellaneous bug fixes. Patchlevel 04 contained an enhancement to root.c to use RetainTemporary and KillClient(disp, AllTemporary) so that it could clean up after itself when reloading. The -quiet and -zoom options no longer cause garbage to be displayed for the image title. A small bug in new.c that caused incorrect allocation of bitmap images was fixed. Several calls to XCreateColormap were missing the "visual" parameter in send.c; this was fixed. A bug relating to -border and monochrome displays was fixed. There were several changes to the Imakefile and Makefiles. Patchlevel 05 contained enhancements to allow slideshows and fullscreen viewing, some bug fixes related to scrolling around within images, Saber-C makefile enhancements, a bug fix to the halftoning title, and the addition of greyscale Sun Rasterfile support. Patchlevel 06 contained support for G3 FAX images, bug fixes to merge.c to fix some signed/unsigned errors and clipping problems, changes to root.c to make previously allocated resources be freed properly, and a completely new dithering routine. Version 2, patchlevel 00 contained support for MacPaint, FBM, PGM, PPM, CMU, Utah RLE and XWD image formats, gamma equalization, image smoothing, and image rotation. G3 FAX support was modified to cut down on false positive identifications. The zio subsystem was modified to cache reads for performance improvements and to allow stdin to be used as an input source. Several loader functions which did not properly close their files were fixed. Color slideshows now work. Icon titles use an abbreviated titlebar title to enhance readability. The resource class name was changed from XLoadImage to xloadimage to be more predictable. Several options now propagate to all images following them if the -slideshow option is specified. Version 2.01 contained several fixes to window.c to work around a bug in twm/tvtwm which could crash servers. The resource class name was changed (again) to Xloadimage to conform with standard class naming practices. Several problems with System-V compilation were corrected. The gcc-1-37 make target was fixed to prevent a double-define. The GIF loader was patched to respond better to short GIF files. The Utah RLE image loader was patched to work with the updated ZIO package. Version 2.02 added the options -default, -gray, -normalize, and -private. The memToVal routines were macro-ized for substantial speed increases. The atom used for deleting previously allocated colors for the -onroot option was changed to correspond to that used by xsetroot. Dithering and halftoning were changed to use a lookup table for intensities to speed them up somewhat. Rle.h was changed to use memToValLSB() instead of its own byte-swapping algorithm for portability. Window.c was modified to eliminate the initial paint, moving it instead to within ConfigureNotify. A fix was made to xwd.c to fix its colormap loader for out-of-order colormaps. The G3 FAX identification function was fixed and the G3 loader moved to prior to the MacPaint loader so that both can be used. A bug in send.c where color images using the default colormap would not appear correctly if the display depth was not a multiple of 8 was corrected. The default gamma value used in rle.c was changed from 2 to 1. There were miscellaneous portability changes. Version 2.03 added -delay. Many minor programming errors were cleaned up. Hash.c was changed to use image.h instead of local typedefs (fixing a problem with PPM image loading). Window.c was changed to fix a problem with override redirect windows in fullscreen mode, and refresh problems with some servers in slideshow mode were fixed. Path.c was modified to ignore directories when searching for files. Send.c was modified to allow TrueColor and DirectColor visuals. Version 2.03-JPL contained interim code to handle 24-bit TrueColor and DirectColor displays pending the release of Version 3.0. Version 3.0 added full support for all server types. Internal support for 24-bit images was implemented (including the improvement of Sun Rasterfile and PPM support to use the 24-bit format internally). Many modifications to image processing routines to support or make use of 24-bit images. A much-improved colormap reduction algorithm replaced the primitive one in previous versions. The window display code was modified to work with the best possible visual. The window display code was modified to use backing store when available (and -pixmap was added to force the old technique). The -fit option was added to force an image to be fit into the default colormap if it didn't fit as supplied. The -fork option was added to allow automatic backgrounding. The -onroot -fullscreen options were modified to preserve aspect ratio. The -windowid option was added to allow the setting of the background pixmap of any window. The -onroot code was modified to work with DECWINDOWS servers. The -normalize option was improved for color images. The -slideshow option was removed (and made the default behavior) and -merge was added to allow more flexible image merging. The WM_DELETE protocol is now recognized. PC Paintbrush (PCX) and GEM bitmap image formats are now supported. The GIF 89a signature is now recognized (although no support for its additional capabilities has been implemented). Version 3.01 corrected color problems when merging RGB files and fixed a few small problems. Version 3.02 fixed a -zoom bug for 24-bit images, a bug in the imageOnRoot() function for DEC and NCD servers, and a couple of bugs in merging and smoothing. Version 3.03 added JPEG and color PCX image support and small fixes to smooth() and normalize(). Version 4.0 added color PCX support, VICAR image support, NIFF image support, -dump, -unhalftone, JPEG V4 and TIFF V3 integration, generic filtering, and fixed a lot of bugs and minor build problems on some systems. Options are now handled in the order they are given rather than a fixed order. G3 FAX loader was removed because it was totally unreliable. Version 4.1 fixed a number of ANSI-C compilation problems, enhanced the automated configuration to target HP and SGI machines automatically, corrected a few minor bugs, and included the IJG JPEG V4A code. a first-cut forced-visual implementation, Michael Campanella (campanella@cvg.enet.dec.com) for more VMS changes, Kee Hinckley (nazgul@alfalfa.com) for robustness changes to the g3 and MacPaint loaders and the ZIO package, Tim Northrup (tim@brspyr1.brs.com) for PC Paintbrusxloadimage.4.1/build-imake 775 221 144 4045 5463767760 10700 #! /bin/sh # this program is used for generating Imakefiles OUT=Imakefile cat > $OUT << END_OF_INPUT # Imakefile for building within the X11 source tree. # This Imakefile was automatically generated from Makefile.std. # # If you have problems building, you should read the README file and # consider using Makefile.std. # # If you use gcc, you should read the README file and consider using # Makefile.std. SYSPATHFILE = $(XAPPLOADDIR)/Xloadimage DEFINES = -DSYSPATHFILE=\"$(SYSPATHFILE)\" DEPLIBS = $(DEPXLIB) LOCAL_LIBRARIES = $(XLIB) SYS_LIBRARIES = -lm #ifdef HPArchitecture CCOPTIONS = -Aa -D_HPUX_SOURCE #endif # Comment out either of the next two lines if you don't have TIFF or JPEG libs #define HAS_TIFF #define HAS_JPEG #ifdef HAS_TIFF TIFF_DEFS = -DHAS_TIFF -I/usr/local/include TIFF_LIB = -L/usr/local/lib/tiff -ltiff TIFF_SRC = tiff.c TIFF_OBJ = tiff.o #endif #ifdef HAS_JPEG JPEG_DEFS = -DHAS_JPEG -I/usr/local/include/jpeg JPEG_LIB = -L/usr/local/lib/jpeg -ljpeg JPEG_SRC = jpeg.c JPEG_OBJ = jpeg.o #endif EXTRA_DEFINES = $(TIFF_DEFS) $(JPEG_DEFS) LOCAL_LIBRARIES = $(TIFF_LIB) $(JPEG_LIB) $(XLIB) END_OF_INPUT echo "SRCS = $1"' $(TIFF_SRC) $(JPEG_SRC)' >> $OUT echo "OBJS = $2"' $(TIFF_OBJ) $(JPEG_OBJ)' >> $OUT cat >> $OUT << END_OF_INPUT AllTarget(xloadimage uufilter) ComplexProgramTarget(xloadimage) NormalProgramTarget(uufilter,uufilter.o,,,) InstallProgram(uufilter,$(BINDIR)) InstallManPage(uufilter,$(MANDIR)) install:: $(SYSPATHFILE) $(RM) $(BINDIR)/xview $(BINDIR)/xsetbg cd $(BINDIR); $(LN) xloadimage xview; $(LN) xloadimage xsetbg clean:: /bin/rm -f build.c build.c: ./build-info $(SYSPATHFILE): @echo "*** Creating default $(SYSPATHFILE) since you" @echo "*** don't have one. This file is used to set up default places" @echo "*** and names to look for images. You probably want to edit" @echo "*** it for your site. See the xloadimage manual page for" @echo "*** details on the contents of this file." cp xloadimagerc $(SYSPATHFILE) chmod a+r $(SYSPATHFILE) END_OF_INPUT chmod 444 $OUT ng problems, changes to root.c to make previously allocated resources be freed properly, and a completely new dithering routine. Version 2, patchlevel 00 contained support for MacPaint, FBM, PGM, PPM, CMU, Utah RLE and XWD image formats, gamma equalization, image smoothing, and image rotation. G3 FAX support was modified to cut down on false positive identifications. The zio subsystem was modified to cache reads for performance improvements and to allow stdin to be usxloadimage.4.1/build-vms 775 221 144 1314 5461577441 10404 #! /bin/sh # this creates a VMS compilation script outfile=VMS_BUILD.COM cat > $outfile << END_OF_INPUT \$set noon \$define sys sys\$library \$define x11 decw\$include \$! \$write sys\$output "Compiling..." END_OF_INPUT for i in $1 do echo '$cc'" $i:r" >> $outfile done echo '$cc vms-build.c' >> $outfile cat >> $outfile << END_OF_INPUT \$! \$write sys\$output "Linking..." END_OF_INPUT echo '$link xloadimage, -' >> $outfile for i in $2 do if [ "$i" != "xloadimage.o" ]; then echo " $i:r, -" >> $outfile fi done echo " vms-build.o, -" >> $outfile cat >> $outfile << END_OF_INPUT sys\$input:/options sys\$share:decw\$xlibshr/share \$! \$exit END_OF_INPUT chmod -w+x $outfile pbm.hff8pcx.hm.9pds.hx.(=rle.hs.<D sunraster.hLVxwd.htedE tgncpyrght.hdxk options.hE patchlevelx xloadimage.hrnew.c.hniff.c.Hvalue.c3zio.clu  xloadimage.4.1/build-info 775 221 144 1452 5461577441 10535 #!/bin/sh # this generates the "build.c" file # try to find out the build date if [ -x /bin/date ]; then date='char *BuildDate= "'`/bin/date`'";' else date='char *BuildDate= (char *)0;' fi # try to find out who's doing the build. there are two common places # for 'id', /bin/id and /usr/bin/id. if [ -x /bin/id ]; then user='char *BuildUser= "'`/bin/id`'";' else if [ -x /usr/bin/id ]; then user='char *BuildUser= "'`/usr/bin/id`'";' else user='char *BuildUser= (char *)0;' fi fi # try to find out the system information if [ -x /bin/uname ]; then uname='char *BuildSystem= "'`/bin/uname -a`'";' else uname='char *BuildSystem= "";' fi echo '/* THIS FILE IS AUTOMATICALLY GENERATED */' > build.c echo $uname >> build.c echo $date >> build.c echo $user >> build.c E tgncpyrght.hdxk options.hd patchlevelE xloadimage.hrnew.c.hniff.c.Hvalue.c3zio.clu  cmuwmraster.cxloadimage.4.1/buildshar.c 664 221 144 5337 5461577404 10705 /* buildshar.c: * * utility program to figure out how to pack shar files. it doesn't try * very hard. * * this program is in the public domain. * * jim frost 09.25.90 */ #include #include #include /* this defines the size of the shar file not including anything that got * added by shar. should be considerably smaller than 64000. */ #define SHAR_SIZE 40000 struct file { char *name; int size; struct file *next; }; struct shar { struct file *file; struct shar *next; }; main(argc, argv) int argc; char **argv; { int num_files, files_left; struct file *files; struct stat sbuf; struct shar *shar_list; struct shar *cur_shar; struct file *cur_file; int shar_size, shar_num, num_shars; int a; if (argc < 2) { fprintf(stderr, "Usage: %s [files]\n", *argv); } /* build table of filenames */ files= (struct file *)malloc(sizeof(struct file) * (argc - 1)); for (a= 0, num_files= 0; *(++argv); a++) { if (stat(*argv, &sbuf) < 0) { perror(*argv); files[a].name= NULL; continue; } num_files++; files[a].name= *argv; files[a].size= sbuf.st_size; } /* try to fit files. this is not a bright algorithm. */ shar_list= cur_shar= (struct shar *)malloc(sizeof(struct shar)); cur_shar->file= NULL; cur_file= NULL; shar_size= 0; for (files_left= num_files; files_left;) { /* look for a file that'll fit in the current shar */ for (a= 0; a < num_files; a++) if (files[a].name && ((shar_size + files[a].size <= SHAR_SIZE) || ((shar_size == 0) && (files[a].size > SHAR_SIZE)))) { shar_size += files[a].size; if (cur_file) { cur_file->next= (struct file *)malloc(sizeof(struct file)); cur_file= cur_file->next; } else cur_shar->file= cur_file= (struct file *)malloc(sizeof(struct file)); cur_file->name= files[a].name; cur_file->next= NULL; files[a].name= NULL; files_left--; break; } /* if nothing fit, make a new shar file */ if (a == num_files) { cur_shar->next= (struct shar *)malloc(sizeof(struct shar)); cur_shar= cur_shar->next; cur_shar->file= NULL; cur_shar->next= NULL; cur_file= NULL; shar_size= 0; } } /* find out how many shar files we need for -e flag */ for (num_shars= 0, cur_shar= shar_list; cur_shar; num_shars++) cur_shar= cur_shar->next; /* output each shar command line */ for (shar_num= 1, cur_shar= shar_list; cur_shar; shar_num++) { printf("shar -n %d -e %d", shar_num, num_shars); for (cur_file= cur_shar->file; cur_file; cur_file= cur_file->next) printf(" %s", cur_file->name); cur_shar= cur_shar->next; printf(" > shar.%d\n", shar_num); } exit(0); } int shar_size, shar_num, num_shars; int a; if (argc < 2) { fprintf(stderr, "Usage: %s [files]\n", *argv); } /* build table of filenames */ files= (struct file *)malloc(sizeof(struct file) * (argc - 1)); for (a= 0, num_files= 0; *(++argv); a++) { if (stat(*argvxloadimage.4.1/packtar.c 664 221 144 4672 5470004426 10343 /* packtar.c: * * this generates a version-specific tar file by creating a shadow tree * containing every file listed on the command line. * * note that whole directories cannot be handled at once; each individual * file needs to be specified. */ #include "patchlevel" #include #include extern int errno; /* poor-man's varargs. good enough for now. */ int run(a0, a1, a2, a3, a4, a5, a6, a7, a8) char *a0, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; { int status; int pid; pid = fork(); switch (pid) { case -1: perror("fork"); return; case 0: execlp(a0, a0, a1, a2, a3, a4, a5, a6, a7, a8); perror(a0); exit(1); default: while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR)) /* EMPTY */ ; return(status); } } /* this creates a link for a file. for every directory name in the * file name it creates the appropriate directory. */ void link_file(dir, old_file) char *dir; char *old_file; { char new_file[1024]; char *p; strcpy(new_file, dir); /* target directory */ strcat(new_file, "/"); strcat(new_file, old_file); for (p = new_file; p = strchr(p, '/'); p++) { *p = '\0'; /* stomp directory separator */ if ((mkdir(new_file, 0775) < 0) && (errno != EEXIST)) { perror(new_file); return; } *p = '/'; /* repair directory separator */ } /* link the two files */ if (link(old_file, new_file) < 0) perror(new_file); } main(argc, argv) int argc; char *argv[]; { char dir_name[1024]; char tar_name[1024]; int i; /* create subdirectory with an appropriate name */ sprintf(dir_name, "xloadimage.%s.%s", VERSION, PATCHLEVEL); sprintf(tar_name, "xloadimage.%s.%s.tar", VERSION, PATCHLEVEL); if (mkdir(dir_name, 0775) < 0) { perror(dir_name); fprintf(stderr, "Couldn't create tar sub directory, sorry!\n"); exit(1); } /* create shadow in the subdirectory */ printf("Creating shadow tree in %s...\n", dir_name); for (i = 1; i < argc; i++) link_file(dir_name, argv[i]); /* invoke 'tar' on the shadow tree */ printf("Creating tar file %s....\n", tar_name); if (run("tar", "-cf", tar_name, dir_name, NULL) != 0) exit(1); /* clean up the shadow tree */ printf("Cleaning up shadow tree....\n"); if (run("rm", "-rf", dir_name, NULL) != 0) exit(1); printf("You now have your very own bouncing baby tar file.\n"); exit(0); /* all's well that ends well */ } o cache reads for performance improvements and to allow stdin to be usxloadimage.4.1/xloadimage.man 664 221 144 63567 5461577441 11425 .TH XLOADIMAGE 1 "8 May 1991" .SH NAME xloadimage, xsetbg, xview \- load images into an X11 window or onto the root window .SH SYNOPSIS \fIxloadimage\fR [global_options] {[image_options] image ...} .br \fIxloadimage\fR [global_options] [image_options] stdin < image .SH DESCRIPTION \fIXloadimage\fR displays images in an X11 window, loads them onto the root window, or writes them into a file. Many image types are recognized; use the \fI-supported\fR option to list them. .PP If the filename \fIstdin\fR is given, xloadimage will read the image from standard input if this capability is supported by the loader for that image type (most types do support reading from stdin). .PP If the destination display cannot support the number of colors in the image, the image will be dithered (monochrome destination) or have its colormap reduced (color destination) as appropriate. This can also be done forcibly with the \fI-halftone\fR, \fI-dither\fR, and \fI-colors\fR options. .PP A variety of image manipulations can be specified, including gamma correction, brightening, clipping, dithering, depth-reduction, rotation, and zooming. Most of these manipulations have simple implementations; speed was opted for above accuracy. .PP If you are viewing a large image in a window, the initial window will be at most 90% of the size of the display unless the window manager does not correctly handle window size requests or if you've used the \fI-fullscreen\fR option. You may move the image around in the window by dragging with the first mouse button. The cursor will indicate which directions you may drag, if any. You may exit the window by typing 'q' or '^C' when the keyboard focus is on the window. .PP If more than one image file is specified on the command line, each image will be shown in order (except if \fI-merge\fR or \fI-goto\fR are being used). .PP A wide variety of common image manipulations can be done by mixing and matching the available options. See the section entitled \fIHINTS FOR GOOD IMAGE DISPLAYS\fR for some ideas. .PP The \fI-dump\fR option causes an image to be written to a file rather than displayed after processing. This allows you to read an image, perform a number of processing operations on it, and save the resultant image. This also allows translation from any of the recognized image types into any of the formats that support dumping. .PP \fIXsetbg\fR is equivalent to \fIxloadimage -onroot -quiet\fR and \fIxview\fR is equivalent to \fIxloadimage -view -verbose\fR. .SH RESOURCE CLASS \fIXloadimage\fR uses the resource class name \fIXloadimage\fR for window managers which need this resource set. This name changed in version 2.00 and 2.01; some previous versions used the name \fIXLoadImage\fR (which was difficult to predict) or \fIxloadimage\fR (which conflicted with class naming conventions). .SH GLOBAL OPTIONS The following options affect the global operation of \fIxloadimage\fR. They may be specified anywhere on the command line. Additionally the \fI-global\fR option can be used to force an image option to apply to all images. .TP 8 -border \fIcolor\fR This sets the background portion of the window which is not covered by any images to be \fIcolor\fR. .TP -configuration Displays the image path, image suffixes, and supported filters which will be used when looking for and reading images. These are loaded from ~/.xloadimagerc and optionally from a systemwide file (normally /usr/lib/xloadimagerc). This replaces the -path option. .TP -default Use the default root weave as the image. This option forces \fI-onroot\fR. If \fI-default\fR is used alone, it is the same as \fIxsetroot\fR with no arguments. If used in conjunction with \fI-tile\fR this option can be used to place images on the default root weave (see \fBEXAMPLES\fR below). .TP -debug Talk to the X server in synchronous mode. This is useful for debugging. If an X error is seen while in this mode, a core will be dumped. .TP -delay \fIsecs\fR Automatically advance to the next image after \fIsecs\fR seconds. .TP -display \fIdisplay_name\fR X11 display name to send the image(s) to. .TP -dump \fIimage_type[,option[=value]]\fR \fIdump_file\fR Rather than displaying the loaded and processed image, dump it into an image file of the specified type. For a list of image types that can be dumped, use the \fI-supported\fR option. Some image types have options that affect the format of the file that's created. See \fBDUMP OPTIONS\fR below. An image can be dumped in any supported dump format regardless of the original image type, so image file type translation is possible using this option. .TP -fit Force image to use the default visual and colormap. This is useful if you do not want technicolor effects when the colormap focus is inside the image window, but it may reduce the quality of the displayed image. This is on by default if -onroot or -windowid is specified. .TP -fork Fork xloadimage. This causes xloadimage to disassociate itself from the shell. This option automatically turns on -quiet. .TP -fullscreen Use the entire screen to display images. If combined with -onroot, the image will be zoomed to fill the entire rootwindow. .TP -geometry \fIWxH[{+-X}{+-}Y]\fR This sets the size of the window onto which the images are loaded to a different value than the size of the image. When viewing an image in a window, this can be used to reduce the size of the destination window. When loading an image onto the root window, this option controls the size of the pixmap which will be loaded onto the root. If the size is smaller than that of the display, the image will be replicated. .TP -goto image_name Forces the next image to be displayed to be the image named \fIimage_name\fR. This is useful for generating looped slideshows. If more than one image of the same name as the target exists on the argument list, the first in the argument list is used. .TP -help [option ...] Give information on an option or list of options. If no option is given, a simple interactive help facility is invoked. .TP -identify Identify the supplied images rather than display them. .TP -install Forcibly install the image's colormap when the window is focused. This violates ICCCM standards and only exists to allow operation with naive window managers. Use this option only if your window manager does not install colormaps properly. .TP -list List the images which are along the image path. .TP -onroot Load image(s) onto the root window instead of viewing in a window. This option automatically sets the -fit option. This is the opposite of \fI-view\fR. \fIXSetbg\fR has this option set by default. .TP -path Displays miscellaneous information about the program configuration. This option is obsolete and has been replaced by -configuration. .TP -pixmap Force the use of a pixmap as backing-store. This is provided for servers where backing-store is broken (such as some versions of the AIXWindows server). It may improve scrolling performance on servers which provide backing-store. .TP -private Force the use of a private colormap. Normally colors are allocated shared unless there are not enough colors available. .TP -quiet Forces \fIxloadimage\fR and \fIxview\fR to be quiet. This is the default for \fIxsetbg\fR, but the others like to whistle. .TP -supported List the supported image types. .TP -type \fItype_name\fR Forces \fIxloadimage\fR to try to load the image as a particular file type rather than trying to guess. This often improves load performance noticably. .TP -verbose Causes \fIxloadimage\fR to be talkative, telling you what kind of image it's playing with and any special processing that it has to do. This is the default for \fIxview\fR and \fIxloadimage\fR. .TP -version Print the version number and patchlevel of this version of \fIxloadimage\fR. .TP -view View image(s) in a window. This is the opposite of \fI-onroot\fR and the default for \fIxview\fR and \fIxloadimage\fR. .TP -visual \fIvisual_name\fR Force the use of a specific visual type to display an image. Normally \fIxloadimage\fR tries to pick the best available image for a particular image type. The available visual types are: DirectColor, TrueColor, PseudoColor, StaticColor, GrayScale, and StaticGray. Nonconflicting names may be abbreviated and case is ignored. .TP -windowid \fIhex_window_id\fR Sets the background pixmap of a particular window ID. The argument must be in hexadecimal and must be preceeded by "0x" (\fIeg\fR -windowid 0x40000b. This is intended for setting the background pixmap of some servers which use untagged virtual roots (\fIeg\fR HP-VUE), but can have other interesting applications. .SH IMAGE OPTIONS The following options may preceed each image. These options are local to the image they preceed. .TP -at \fIX\fR,\fIY\fR Indicates coordinates to load the image at on the base image. If this is an option to the first image, and the \fI-onroot\fR option is specified, the image will be loaded at the given location on the display background. .TP -background \fIcolor\fR Use \fIcolor\fR as the background color instead of the default (usually white but this depends on the image type) if you are transferring a monochrome image to a color display. .TP -brighten \fIpercentage\fR Specify a percentage multiplier for a color image's colormap. A value of more than 100 will brighten an image, one of less than 100 will darken it. .TP -center Center the image on the base image loaded. If this is an option to the first image, and the \fI-onroot\fR option is specified, the image will be centered on the display background. .TP -clip \fIX\fR,\fIY\fR,\fIW\fR,\fIH\fR Clip the image before loading it. \fIX\fR and \fIY\fR define the upper-left corner of the clip area, and \fIW\fR and \fIH\fR define the extents of the area. A zero value for \fIW\fR or \fIH\fR will be interpreted as the remainder of the image. .TP -colors \fIn\fR Specify the maximum number of colors to use in the image. This is a way to forcibly reduce the depth of an image. .TP -dither Dither a color image to monochrome using a Floyd-Steinberg dithering algorithm. This happens by default when viewing color images on a monochrome display. This is slower than \fI-halftone\fR and affects the image accuracy but usually looks much better. .TP -foreground \fIcolor\fR Use \fIcolor\fR as the foreground color instead of black if you are transferring a monochrome image to a color display. This can also be used to invert the foreground and background colors of a monochrome image. .TP -gamma \fIdisplay_gamma\fR Specify the gamma correction for the display. The default value is 1.0, a typical display needs 2.0 to 2.5. .TP -global Force the following option to apply to all images rather than one specific image. Local image options will temporarily override any option specified with -global. .TP -gray Convert an image to grayscale. This is very useful when displaying colorful images on servers with limited color capability. It can also be used to convert a bitmap image into a grayscale image, although the resulting image will be smaller than the original. The optional spelling \fI-grey\fR may also be used. .TP -halftone Force halftone dithering of a color image when displaying on a monochrome display. This option is ignored on monochrome images. This dithering algorithm blows an image up by sixteen times; if you don't like this, the \fI-dither\fR option will not blow the image up but will take longer to process and will be less accurate. .TP -idelay \fIsecs\fR Set the delay to be used for this image to \fIsecs\fR seconds (see \fI-delay\fR). If \fI-delay\fR was specified, this overrides it. If it was not specified, this sets the automatic advance delay for this image while others will wait for the user to advance them. .TP -invert Inverts a monochrome image. This is shorthand for \fI-foreground white -background black\fR. .TP -merge Merge this image onto the base image after local processing. The base image is considered to be the first image specified or the last image that was not preceeded by \fI-merge\fR. If used in conjunction with \fI-at\fR and \fI-clip\fR, very complex images can be built up. This option is on by default for all images if the \fI-onroot\fR or \fI-windowid\fR options are specified. .TP -name \fIimage_name\fR Force the next argument to be treated as an image name. This is useful if the name of the image is \fI-dither\fR, for instance. .TP -newoptions Reset globally-specified options. .TP -normalize Normalize a color image. .TP -rotate \fIdegrees\fR Rotate the image by \fIdegrees\fR clockwise. The number must be a multiple of 90. .TP -shrink Shrink an image down to fit on the display. This is particularly useful with servers that do not support window sizes larger than the physical screen (eg DECWINDOWS servers). .TP -smooth Smooth a color image. This reduces blockiness after zooming an image up. If used on a monochrome image, nothing happens. This option can take awhile to perform, especially on large images. You may specify more than one \fI-smooth\fR option per image, causing multiple iterations of the smoothing algorithm. .TP -tile Tile this image (after any necessary merging or tiling) to create a fullscreen image. This is usually used to create a large background image on which to merge other images. \fI-geometry\fR can be used to set the new image size to something other than -fullscreen. .TP -title \fItitle\fR Change the title of the image. This sets the title bar title if displaying in a window or the NIFF file image title if dumping the image. .TP -xzoom \fIpercentage\fR Zoom the X axis of an image by \fIpercentage\fR. A number greater than 100 will expand the image, one smaller will compress it. A zero value will be ignored. This option, and the related \fI-yzoom\fR are useful for correcting the aspect ratio of images to be displayed. .TP -yzoom \fIpercentage\fR Zoom the Y axis of an image by \fIpercentage\fR. See \fI-xzoom\fR for more information. .TP -zoom \fIpercentage\fR Zoom both the X and Y axes by \fIpercentage\fR. See \fI-xzoom\fR for more information. Technically the percentage actually zoomed is the square of the number supplied since the zoom is to both axes, but I opted for consistency instead of accuracy. .SH EXAMPLES To load the rasterfile "my.image" onto the background and replicate it to fill the entire background: .sp .ti +5 xloadimage -onroot my.image .PP To center an image on the default root background: .sp .ti +5 xloadimage -default -tile my.image .sp If using a monochrome display and a color image you will probably want to dither the image for a cleaner (and faster) display: .sp .ti +5 xloadimage -default -tile -dither my.image .PP To load a monochrome image "my.image" onto the background, using red as the foreground color, replicate the image, and overlay "another.image" onto it at coordinate (10,10): .sp .ti +5 xloadimage -foreground red my.image -at 10,10 another.image .PP To center the rectangular region from 10 to 110 along the X axis and from 10 to the height of the image along the Y axis: .sp .ti +5 xloadimage -center -clip 10,10,100,0 my.image .PP To double the size of an image: .sp .ti +5 xloadimage -zoom 200 my.image .PP To halve the size of an image: .sp .ti +5 xloadimage -zoom 50 my.image .PP To brighten a dark image: .sp .ti +5 xloadimage -brighten 150 my.image .PP To darken a bright image: .sp .ti +5 xloadimage -brighten 50 my.image .SH HINTS FOR GOOD IMAGE DISPLAYS Since images are likely to come from a variety of sources, they may be in a variety of aspect ratios which may not be supported by your display. The \fI-xzoom\fR and \fI-yzoom\fR options can be used to change the aspect ratio of an image before display. If you use these options, it is recommended that you increase the size of one of the dimensions instead of shrinking the other, since shrinking looses detail. For instance, many GIF and G3 FAX images have an X:Y ratio of about 2:1. You can correct this for viewing on a 1:1 display with either \fI-xzoom 50\fR or \fI-yzoom 200\fR (reduce X axis to 50% of its size and expand Y axis to 200% of its size, respectively) but the latter should be used so no detail is lost in the conversion. .PP When zooming color images up you can reduce blockiness with \fI-smooth\fR. For zooms of 300% or more, I recommend two smoothing passes (although this can take awhile to do on slow machines). There will be a noticable improvement in the image. .PP You can perform image processing on a small portion of an image by loading the image more than once and using the \fI-merge\fR, \fI-at\fR and \fI-clip\fR options. Load the image, then merge it with a clipped, processed version of itself. To brighten a 100x100 rectangular portion of an image located at (50,50), for instance, you could type: .sp .ti +5 xloadimage my.image -merge -at 50,50 -clip 50,50,100,100 -brighten 150 my.image .PP If you're using a display with a small colormap to display colorful images, try using the \fI-gray\fR option to convert to grayscale. .SH PATHS AND EXTENSIONS The file ~/.xloadimagerc (and optionally a system-wide file) defines a number of configuration options that affect xloadimage. .PP This file is split into three section, the \fIpath\fR section, the \fIextension\fR section, and the \fIfilter\fR section. The sections are identified by typing the section name followed by an equals sign, eg "path =". .PP The \fIpath\fR statement is used to provide a set of search paths to use when looking for an image of a specified name. Separate each path in the list by whitespace (eg one or more spaces, tabs, or newlines). The path is searched in the order it is specified. For example: .PP .nf path = ~/images /usr/local/images ~fred .fi .PP will first look for the image name you specified, then look for the name in ~/images (the tilde is expanded to the value of $HOME), then in /usr/local/images, then in user fred's home directory. This allows easy use of image repositories. .PP The \fIextension\fR statement is used to provide a set of default extensions to use when looking for an image of a specified name. Separate each extension in the list by whitespace. The extensions are searched in the order in which they are specified. For example: .PP .nf extension = .gif .jpg .fi .PP If you have a file named \fImyimage.gif\fR you could specify the name \fImyimage\fR and xloadimage would append the \fI.gif\fR extension automatically. .PP The \fIfilter\fR statement is used to describe filter programs, such as "uncompress", which are to be applied to image files automatically. You specify one filter program and any number of recognized extensions following the \fIfilter\fR keyword. For example: .PP .nf filter = uncompress .Z .fi .PP specifies that the program \fIuncompress\fR should be used as a filter whenever an image file has a .Z extension. By default filters are provided for compressed (.Z) files and GNU zip (.gz) files. See the \fBFILTERS\fR section for more information on defining your own filters. .PP Any text on a line following a hash-mark (#) is ignored; if you wish to use a hash-mark in a path, extension, or filter you can escape it using a backslash (\\). .PP If you wish to include white-space in a filter program name, path, or extension you can enclose the entire text in double-quotes. For example: .PP .nf filter = "gzip -cd" .gz .fi .PP Use backslash (\\) characters to allow inclusion of double-quote marks or newlines. .PP The following is a sample ~/.xloadimagerc file: .PP .nf # paths to look for images in path = /usr/local/images # system image repository ~/images # personal images /usr/include/X11/bitmaps # standard X bitmaps # default extensions for images extension = .csun .msun .sun .face .xbm .bm # invoke GNU zip if a .z or .zip extension is found filter = "gzip -cd" .z .zip .fi .PP .SH IMAGE TYPES .PP \fIXloadimage\fR currently supports many common and some uncommon image types, and can create images in several formats. For a complete list use the \fI-supported\fR option. .SH DUMPING IMAGES Several image dumpers are included that can be used to create a new image after loading and processing. The NIFF (Native Image File Format) is the simplest and creates images that \fIxloadimage\fR can read the fastest; it is essentially a copy of the internal image format. .PP Some image dumpers allow options that affect the image output. These options are appended to the image type following a comma and are separated by commas. If a value is desired it can be specified following an equals-sign. For example, to create a monochrome JPEG image file with a quality factor of 80, you would use the following command line: .PP .nf xloadimage image_name -dump jpeg,quality=80,grayscale new_image.jpg .fi .PP Option names can be abbreviated but if the abbreviation is too short to be unique the option which will be used is indeterminate. .SH FILTERS Xloadimage supports automatic filtering by recognizing file extensions. By default "compress" and "gzip" files are recognized and their names passed to appropriate commands to decompress them. .PP The xloadimage distribution includes a special "smart" uudecoder, called \fIuufilter\fR that can be used to automatically uudecode files for processing. \fIUufilter\fR ignores extraneous lines in the file so it is particularly useful if the uuencoded file was created by concatenating email or news postings that had headers or line-break indicators included. .PP To make use of \fIuufilter\fR you can add the following to your \fI.xloadimagerc\fR file: .PP .nf filter = "uufilter -s" .uu .uue .fi The filter will be automatically invoked on any file with a .uu or .uue extension. .PP For a list of filters automatically recognized by xloadimage use the \fI-configuration\fR option. .PP .SH SUPPORTED IMAGE OPTIONS .PP The JPEG image dumper supports the following options: .TP 8 arithmetic Use arithmetic encoding. .TP grayscale Force a monochrome (grayscale) image to be created given a color image. .TP nointerleave Create a non-interleaved file. .TP optimize Enable entropy parameter optimization. .TP quality Adjust the quality of the image to be created. The default quality factor is 75; lower values create poorer images. .TP restart \fIinterval\fR Set the restart interval in MCU rows, or MCUs if 'b' follows the interval value. .TP smooth \fIsmoothing_factor\fR Set the smoothing factor. Value should be between 0 and 100, inclusive. .PP If you are not familiar with the meaning of these options you can ask the Independent JPEG Group (IJG) via email at jpeg@cs.columbia.edu. .PP The PBM image dumper supports the following options: .TP 8 normal Dump a normal (ascii) PBM/PPM file. .TP raw Dump a RawBits format PBM/PPM file. This is the default and results in significantly smaller image files than when using \fInormal\fR. .PP There is no way to dump a PGM format file or a "compact" PBM format file (sorry). .PP The TIFF image dumper supports the following options: .TP 8 compression Image data compression technique. Can be one of: \fInone\fR (no compression), \fIrle\fR (CCITT RLE compression), \fIg3fax\fR (CCITT Group 3 FAX compression), \fIg4fax\fR (CCITT Group 4 FAX compression), \fIlzw\fR (Limpel-Ziv-Welsh compression, the default), \fIjpeg\fR (JPEG compression), \fInext\fR (NeXT run-length compression), \fIrlew\fR (CCITT RLEW compression), \fImac\fR (Macintosh PackBits compression), \fIpackbits\fR (same as \fImac\fR), \fIthunderscan\fR (ThunderScan compression). .PP \fIXloadimage\fR will save using the MINISBLACK, MINISWHITE, COLORMAP, or RGB photometrics as appropriate for its internal image format. There is no way to specify a particular photometric or any other TIFF fields. .PP .SH AUTHOR .nf Jim Frost CenterLine Software jimf@centerline.com .fi .PP For a more-or-less complete list of other contributors (there are a \fIlot\fR of them), please see the README file enclosed with the distribution. .SH FILES .nf .in +5 xloadimage - the image loader and viewer xsetbg - pseudonym which quietly sets the background xview - pseudonym which views in a window /usr/lib/X11/Xloadimage - default system-wide configuration file ~/.xloadimagerc - user's personal configuration file .in -5 .fi .SH COPYRIGHT Copyright (c) 1989, 1993 Jim Frost and others. .PP \fIXloadimage\fR is copywritten material with a very loose copyright allowing unlimited modification and distribution if the copyright notices are left intact. Various portions are copywritten by various people, but all use a modification of the MIT copyright notice. Please check the source for complete copyright information. The intent is to keep the source free, not to stifle its distribution, so please write to me if you have any questions. .SH BUGS Zooming dithered images, especially downwards, is UGLY. .PP Images can come in a variety of aspect ratios. \fIXloadimage\fR cannot detect what aspect ratio the particular image being loaded has, nor the aspect ratio of the destination display, so images with differing aspect ratios from the destination display will appear distorted. See \fIHINTS FOR GOOD IMAGE DISPLAYS\fR for more information. .PP The GIF format allows more than one image to be stored in a single GIF file, but \fIxloadimage\fR will only display the first. .PP Only GIF87a format is supported. .PP One of the pseudonyms for \fIxloadimage\fR, \fIxview\fR, is the same name as Sun uses for their SunView-under-X package. This will be confusing if you're one of those poor souls who has to use Sun's XView. .PP Some window managers do not correctly handle window size requests. In particular, many versions of the twm window manager use the MaxSize hint instead of the PSize hint, causing images which are larger than the screen to display in a window larger than the screen, something which is normally avoided. Some versions of twm also ignore the MaxSize argument's real function, to limit the maximum size of the window, and allow the window to be resized larger than the image. If this happens, \fIxloadimage\fR merely places the image in the upper-left corner of the window and uses the zero-value'ed pixel for any space which is not covered by the image. This behavior is less-than-graceful but so are window managers which are cruel enough to ignore such details. cified. For example: .PP .nf extension = .gif .jpg .fi .PP If you have a file named \fImyimage.gif\fR you could specify the name \fImyxloadimage.4.1/xloadimage.txt 664 221 144 102726 5470014467 11472 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) NAME xloadimage, xsetbg, xview - load images into an X11 window or onto the root window SYNOPSIS _x_l_o_a_d_i_m_a_g_e [global_options] {[image_options] image ...} _x_l_o_a_d_i_m_a_g_e [global_options] [image_options] stdin < image DESCRIPTION _X_l_o_a_d_i_m_a_g_e displays images in an X11 window, loads them onto the root window, or writes them into a file. Many image types are recognized; use the -_s_u_p_p_o_r_t_e_d option to list them. If the filename _s_t_d_i_n is given, xloadimage will read the image from standard input if this capability is supported by the loader for that image type (most types do support read- ing from stdin). If the destination display cannot support the number of colors in the image, the image will be dithered (monochrome destination) or have its colormap reduced (color destina- tion) as appropriate. This can also be done forcibly with the -_h_a_l_f_t_o_n_e, -_d_i_t_h_e_r, and -_c_o_l_o_r_s options. A variety of image manipulations can be specified, including gamma correction, brightening, clipping, dithering, depth- reduction, rotation, and zooming. Most of these manipula- tions have simple implementations; speed was opted for above accuracy. If you are viewing a large image in a window, the initial window will be at most 90% of the size of the display unless the window manager does not correctly handle window size requests or if you've used the -_f_u_l_l_s_c_r_e_e_n option. You may move the image around in the window by dragging with the first mouse button. The cursor will indicate which direc- tions you may drag, if any. You may exit the window by typ- ing 'q' or '^C' when the keyboard focus is on the window. If more than one image file is specified on the command line, each image will be shown in order (except if -_m_e_r_g_e or -_g_o_t_o are being used). A wide variety of common image manipulations can be done by mixing and matching the available options. See the section entitled _H_I_N_T_S _F_O_R _G_O_O_D _I_M_A_G_E _D_I_S_P_L_A_Y_S for some ideas. The -_d_u_m_p option causes an image to be written to a file rather than displayed after processing. This allows you to read an image, perform a number of processing operations on it, and save the resultant image. This also allows Sun Release 4.1 Last change: 8 May 1991 1 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) translation from any of the recognized image types into any of the formats that support dumping. _X_s_e_t_b_g is equivalent to _x_l_o_a_d_i_m_a_g_e -_o_n_r_o_o_t -_q_u_i_e_t and _x_v_i_e_w is equivalent to _x_l_o_a_d_i_m_a_g_e -_v_i_e_w -_v_e_r_b_o_s_e. RESOURCE CLASS _X_l_o_a_d_i_m_a_g_e uses the resource class name _X_l_o_a_d_i_m_a_g_e for win- dow managers which need this resource set. This name changed in version 2.00 and 2.01; some previous versions used the name _X_L_o_a_d_I_m_a_g_e (which was difficult to predict) or _x_l_o_a_d_i_m_a_g_e (which conflicted with class naming conventions). GLOBAL OPTIONS The following options affect the global operation of _x_l_o_a_d_i_m_a_g_e. They may be specified anywhere on the command line. Additionally the -_g_l_o_b_a_l option can be used to force an image option to apply to all images. -border _c_o_l_o_r This sets the background portion of the window which is not covered by any images to be _c_o_l_o_r. -configuration Displays the image path, image suffixes, and sup- ported filters which will be used when looking for and reading images. These are loaded from ~/.xloadimagerc and optionally from a systemwide file (normally /usr/lib/xloadimagerc). This replaces the -path option. -default Use the default root weave as the image. This option forces -_o_n_r_o_o_t. If -_d_e_f_a_u_l_t is used alone, it is the same as _x_s_e_t_r_o_o_t with no arguments. If used in conjunction with -_t_i_l_e this option can be used to place images on the default root weave (see EXAMPLES below). -debug Talk to the X server in synchronous mode. This is useful for debugging. If an X error is seen while in this mode, a core will be dumped. -delay _s_e_c_s Automatically advance to the next image after _s_e_c_s seconds. -display _d_i_s_p_l_a_y__n_a_m_e X11 display name to send the image(s) to. -dump _i_m_a_g_e__t_y_p_e[,_o_p_t_i_o_n[=_v_a_l_u_e]] _d_u_m_p__f_i_l_e Rather than displaying the loaded and processed Sun Release 4.1 Last change: 8 May 1991 2 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) image, dump it into an image file of the specified type. For a list of image types that can be dumped, use the -_s_u_p_p_o_r_t_e_d option. Some image types have options that affect the format of the file that's created. See DUMP OPTIONS below. An image can be dumped in any supported dump format regardless of the original image type, so image file type transla- tion is possible using this option. -fit Force image to use the default visual and colormap. This is useful if you do not want technicolor effects when the colormap focus is inside the image window, but it may reduce the quality of the displayed image. This is on by default if -onroot or -windowid is specified. -fork Fork xloadimage. This causes xloadimage to disasso- ciate itself from the shell. This option automati- cally turns on -quiet. -fullscreen Use the entire screen to display images. If com- bined with -onroot, the image will be zoomed to fill the entire rootwindow. -geometry _W_x_H[{+-_X}{+-}_Y] This sets the size of the window onto which the images are loaded to a different value than the size of the image. When viewing an image in a window, this can be used to reduce the size of the destina- tion window. When loading an image onto the root window, this option controls the size of the pixmap which will be loaded onto the root. If the size is smaller than that of the display, the image will be replicated. -goto image_name Forces the next image to be displayed to be the image named _i_m_a_g_e__n_a_m_e. This is useful for generat- ing looped slideshows. If more than one image of the same name as the target exists on the argument list, the first in the argument list is used. -help [option ...] Give information on an option or list of options. If no option is given, a simple interactive help facility is invoked. -identify Identify the supplied images rather than display them. Sun Release 4.1 Last change: 8 May 1991 3 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) -install Forcibly install the image's colormap when the win- dow is focused. This violates ICCCM standards and only exists to allow operation with naive window managers. Use this option only if your window manager does not install colormaps properly. -list List the images which are along the image path. -onroot Load image(s) onto the root window instead of view- ing in a window. This option automatically sets the -fit option. This is the opposite of -_v_i_e_w. _X_S_e_t_b_g has this option set by default. -path Displays miscellaneous information about the program configuration. This option is obsolete and has been replaced by -configuration. -pixmap Force the use of a pixmap as backing-store. This is provided for servers where backing-store is broken (such as some versions of the AIXWindows server). It may improve scrolling performance on servers which provide backing-store. -private Force the use of a private colormap. Normally colors are allocated shared unless there are not enough colors available. -quiet Forces _x_l_o_a_d_i_m_a_g_e and _x_v_i_e_w to be quiet. This is the default for _x_s_e_t_b_g, but the others like to whis- tle. -supported List the supported image types. -type _t_y_p_e__n_a_m_e Forces _x_l_o_a_d_i_m_a_g_e to try to load the image as a par- ticular file type rather than trying to guess. This often improves load performance noticably. -verbose Causes _x_l_o_a_d_i_m_a_g_e to be talkative, telling you what kind of image it's playing with and any special pro- cessing that it has to do. This is the default for _x_v_i_e_w and _x_l_o_a_d_i_m_a_g_e. -version Print the version number and patchlevel of this ver- sion of _x_l_o_a_d_i_m_a_g_e. -view View image(s) in a window. This is the opposite of Sun Release 4.1 Last change: 8 May 1991 4 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) -_o_n_r_o_o_t and the default for _x_v_i_e_w and _x_l_o_a_d_i_m_a_g_e. -visual _v_i_s_u_a_l__n_a_m_e Force the use of a specific visual type to display an image. Normally _x_l_o_a_d_i_m_a_g_e tries to pick the best available image for a particular image type. The available visual types are: DirectColor, TrueColor, PseudoColor, StaticColor, GrayScale, and StaticGray. Nonconflicting names may be abbreviated and case is ignored. -windowid _h_e_x__w_i_n_d_o_w__i_d Sets the background pixmap of a particular window ID. The argument must be in hexadecimal and must be preceeded by "0x" (_e_g -windowid 0x40000b. This is intended for setting the background pixmap of some servers which use untagged virtual roots (_e_g HP- VUE), but can have other interesting applications. IMAGE OPTIONS The following options may preceed each image. These options are local to the image they preceed. -at _X,_Y Indicates coordinates to load the image at on the base image. If this is an option to the first image, and the -_o_n_r_o_o_t option is specified, the image will be loaded at the given location on the display background. -background _c_o_l_o_r Use _c_o_l_o_r as the background color instead of the default (usually white but this depends on the image type) if you are transferring a monochrome image to a color display. -brighten _p_e_r_c_e_n_t_a_g_e Specify a percentage multiplier for a color image's colormap. A value of more than 100 will brighten an image, one of less than 100 will darken it. -center Center the image on the base image loaded. If this is an option to the first image, and the -_o_n_r_o_o_t option is specified, the image will be centered on the display background. -clip _X,_Y,_W,_H Clip the image before loading it. _X and _Y define the upper-left corner of the clip area, and _W and _H define the extents of the area. A zero value for _W or _H will be interpreted as the remainder of the image. Sun Release 4.1 Last change: 8 May 1991 5 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) -colors _n Specify the maximum number of colors to use in the image. This is a way to forcibly reduce the depth of an image. -dither Dither a color image to monochrome using a Floyd- Steinberg dithering algorithm. This happens by default when viewing color images on a monochrome display. This is slower than -_h_a_l_f_t_o_n_e and affects the image accuracy but usually looks much better. -foreground _c_o_l_o_r Use _c_o_l_o_r as the foreground color instead of black if you are transferring a monochrome image to a color display. This can also be used to invert the fore- ground and background colors of a monochrome image. -gamma _d_i_s_p_l_a_y__g_a_m_m_a Specify the gamma correction for the display. The default value is 1.0, a typical display needs 2.0 to 2.5. -global Force the following option to apply to all images rather than one specific image. Local image options will temporarily override any option specified with -global. -gray Convert an image to grayscale. This is very useful when displaying colorful images on servers with limited color capability. It can also be used to convert a bitmap image into a grayscale image, although the resulting image will be smaller than the original. The optional spelling -_g_r_e_y may also be used. -halftone Force halftone dithering of a color image when display- ing on a monochrome display. This option is ignored on monochrome images. This dithering algorithm blows an image up by sixteen times; if you don't like this, the -_d_i_t_h_e_r option will not blow the image up but will take longer to process and will be less accurate. -idelay _s_e_c_s Set the delay to be used for this image to _s_e_c_s seconds (see -_d_e_l_a_y). If -_d_e_l_a_y was specified, this overrides it. If it was not specified, this sets the automatic advance delay for this image while others will wait for the user to advance them. Sun Release 4.1 Last change: 8 May 1991 6 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) -invert Inverts a monochrome image. This is shorthand for -_f_o_r_e_g_r_o_u_n_d _w_h_i_t_e -_b_a_c_k_g_r_o_u_n_d _b_l_a_c_k. -merge Merge this image onto the base image after local pro- cessing. The base image is considered to be the first image specified or the last image that was not pre- ceeded by -_m_e_r_g_e. If used in conjunction with -_a_t and -_c_l_i_p, very complex images can be built up. This option is on by default for all images if the -_o_n_r_o_o_t or -_w_i_n_d_o_w_i_d options are specified. -name _i_m_a_g_e__n_a_m_e Force the next argument to be treated as an image name. This is useful if the name of the image is -_d_i_t_h_e_r, for instance. -newoptions Reset globally-specified options. -normalize Normalize a color image. -rotate _d_e_g_r_e_e_s Rotate the image by _d_e_g_r_e_e_s clockwise. The number must be a multiple of 90. -shrink Shrink an image down to fit on the display. This is particularly useful with servers that do not support window sizes larger than the physical screen (eg DECWINDOWS servers). -smooth Smooth a color image. This reduces blockiness after zooming an image up. If used on a monochrome image, nothing happens. This option can take awhile to per- form, especially on large images. You may specify more than one -_s_m_o_o_t_h option per image, causing multiple iterations of the smoothing algorithm. -tile Tile this image (after any necessary merging or tiling) to create a fullscreen image. This is usually used to create a large background image on which to merge other images. -_g_e_o_m_e_t_r_y can be used to set the new image size to something other than -fullscreen. -title _t_i_t_l_e Change the title of the image. This sets the title bar title if displaying in a window or the NIFF file image Sun Release 4.1 Last change: 8 May 1991 7 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) title if dumping the image. -xzoom _p_e_r_c_e_n_t_a_g_e Zoom the X axis of an image by _p_e_r_c_e_n_t_a_g_e. A number greater than 100 will expand the image, one smaller will compress it. A zero value will be ignored. This option, and the related -_y_z_o_o_m are useful for correct- ing the aspect ratio of images to be displayed. -yzoom _p_e_r_c_e_n_t_a_g_e Zoom the Y axis of an image by _p_e_r_c_e_n_t_a_g_e. See -_x_z_o_o_m for more information. -zoom _p_e_r_c_e_n_t_a_g_e Zoom both the X and Y axes by _p_e_r_c_e_n_t_a_g_e. See -_x_z_o_o_m for more information. Technically the percentage actu- ally zoomed is the square of the number supplied since the zoom is to both axes, but I opted for consistency instead of accuracy. EXAMPLES To load the rasterfile "my.image" onto the background and replicate it to fill the entire background: xloadimage -onroot my.image To center an image on the default root background: xloadimage -default -tile my.image If using a monochrome display and a color image you will probably want to dither the image for a cleaner (and faster) display: xloadimage -default -tile -dither my.image To load a monochrome image "my.image" onto the background, using red as the foreground color, replicate the image, and overlay "another.image" onto it at coordinate (10,10): xloadimage -foreground red my.image -at 10,10 another.image To center the rectangular region from 10 to 110 along the X axis and from 10 to the height of the image along the Y axis: xloadimage -center -clip 10,10,100,0 my.image To double the size of an image: xloadimage -zoom 200 my.image Sun Release 4.1 Last change: 8 May 1991 8 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) To halve the size of an image: xloadimage -zoom 50 my.image To brighten a dark image: xloadimage -brighten 150 my.image To darken a bright image: xloadimage -brighten 50 my.image HINTS FOR GOOD IMAGE DISPLAYS Since images are likely to come from a variety of sources, they may be in a variety of aspect ratios which may not be supported by your display. The -_x_z_o_o_m and -_y_z_o_o_m options can be used to change the aspect ratio of an image before display. If you use these options, it is recommended that you increase the size of one of the dimensions instead of shrinking the other, since shrinking looses detail. For instance, many GIF and G3 FAX images have an X:Y ratio of about 2:1. You can correct this for viewing on a 1:1 display with either -_x_z_o_o_m _5_0 or -_y_z_o_o_m _2_0_0 (reduce X axis to 50% of its size and expand Y axis to 200% of its size, respectively) but the latter should be used so no detail is lost in the conversion. When zooming color images up you can reduce blockiness with -_s_m_o_o_t_h. For zooms of 300% or more, I recommend two smooth- ing passes (although this can take awhile to do on slow machines). There will be a noticable improvement in the image. You can perform image processing on a small portion of an image by loading the image more than once and using the -_m_e_r_g_e, -_a_t and -_c_l_i_p options. Load the image, then merge it with a clipped, processed version of itself. To brighten a 100x100 rectangular portion of an image located at (50,50), for instance, you could type: xloadimage my.image -merge -at 50,50 -clip 50,50,100,100 -brighten 150 my.image If you're using a display with a small colormap to display colorful images, try using the -_g_r_a_y option to convert to grayscale. PATHS AND EXTENSIONS The file ~/.xloadimagerc (and optionally a system-wide file) defines a number of configuration options that affect xloadimage. Sun Release 4.1 Last change: 8 May 1991 9 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) This file is split into three section, the _p_a_t_h section, the _e_x_t_e_n_s_i_o_n section, and the _f_i_l_t_e_r section. The sections are identified by typing the section name followed by an equals sign, eg "path =". The _p_a_t_h statement is used to provide a set of search paths to use when looking for an image of a specified name. Separate each path in the list by whitespace (eg one or more spaces, tabs, or newlines). The path is searched in the order it is specified. For example: path = ~/images /usr/local/images ~fred will first look for the image name you specified, then look for the name in ~/images (the tilde is expanded to the value of $HOME), then in /usr/local/images, then in user fred's home directory. This allows easy use of image repositories. The _e_x_t_e_n_s_i_o_n statement is used to provide a set of default extensions to use when looking for an image of a specified name. Separate each extension in the list by whitespace. The extensions are searched in the order in which they are specified. For example: extension = .gif .jpg If you have a file named _m_y_i_m_a_g_e._g_i_f you could specify the name _m_y_i_m_a_g_e and xloadimage would append the ._g_i_f extension automatically. The _f_i_l_t_e_r statement is used to describe filter programs, such as "uncompress", which are to be applied to image files automatically. You specify one filter program and any number of recognized extensions following the _f_i_l_t_e_r key- word. For example: filter = uncompress .Z specifies that the program _u_n_c_o_m_p_r_e_s_s should be used as a filter whenever an image file has a .Z extension. By default filters are provided for compressed (.Z) files and GNU zip (.gz) files. See the FILTERS section for more information on defining your own filters. Any text on a line following a hash-mark (#) is ignored; if you wish to use a hash-mark in a path, extension, or filter you can escape it using a backslash (\). If you wish to include white-space in a filter program name, path, or extension you can enclose the entire text in double-quotes. For example: Sun Release 4.1 Last change: 8 May 1991 10 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) filter = "gzip -cd" .gz Use backslash (\) characters to allow inclusion of double- quote marks or newlines. The following is a sample ~/.xloadimagerc file: # paths to look for images in path = /usr/local/images # system image repository ~/images # personal images /usr/include/X11/bitmaps # standard X bitmaps # default extensions for images extension = .csun .msun .sun .face .xbm .bm # invoke GNU zip if a .z or .zip extension is found filter = "gzip -cd" .z .zip IMAGE TYPES _X_l_o_a_d_i_m_a_g_e currently supports many common and some uncommon image types, and can create images in several formats. For a complete list use the -_s_u_p_p_o_r_t_e_d option. DUMPING IMAGES Several image dumpers are included that can be used to create a new image after loading and processing. The NIFF (Native Image File Format) is the simplest and creates images that _x_l_o_a_d_i_m_a_g_e can read the fastest; it is essen- tially a copy of the internal image format. Some image dumpers allow options that affect the image out- put. These options are appended to the image type following a comma and are separated by commas. If a value is desired it can be specified following an equals-sign. For example, to create a monochrome JPEG image file with a quality factor of 80, you would use the following command line: xloadimage image_name -dump jpeg,quality=80,grayscale new_image.jpg Option names can be abbreviated but if the abbreviation is too short to be unique the option which will be used is indeterminate. FILTERS Xloadimage supports automatic filtering by recognizing file extensions. By default "compress" and "gzip" files are recognized and their names passed to appropriate commands to decompress them. The xloadimage distribution includes a special "smart" uudecoder, called _u_u_f_i_l_t_e_r that can be used to automatically Sun Release 4.1 Last change: 8 May 1991 11 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) uudecode files for processing. _U_u_f_i_l_t_e_r ignores extraneous lines in the file so it is particularly useful if the uuen- coded file was created by concatenating email or news post- ings that had headers or line-break indicators included. To make use of _u_u_f_i_l_t_e_r you can add the following to your filter = "uufilter -s" .uu .uue The filter will be automatically invoked on any file with a .uu or For a list of filters automatically recognized by xloadimage use the -_c_o_n_f_i_g_u_r_a_t_i_o_n option. SUPPORTED IMAGE OPTIONS The JPEG image dumper supports the following options: arithmetic Use arithmetic encoding. grayscale Force a monochrome (grayscale) image to be created given a color image. nointerleave Create a non-interleaved file. optimize Enable entropy parameter optimization. quality Adjust the quality of the image to be created. The default quality factor is 75; lower values create poorer images. restart _i_n_t_e_r_v_a_l Set the restart interval in MCU rows, or MCUs if 'b' follows the interval value. smooth _s_m_o_o_t_h_i_n_g__f_a_c_t_o_r Set the smoothing factor. Value should be between 0 and 100, inclusive. If you are not familiar with the meaning of these options you can ask the Independent JPEG Group (IJG) via email at jpeg@cs.columbia.edu. The PBM image dumper supports the following options: normal Dump a normal (ascii) PBM/PPM file. raw Dump a RawBits format PBM/PPM file. This is the default and results in significantly smaller image Sun Release 4.1 Last change: 8 May 1991 12 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) files than when using _n_o_r_m_a_l. There is no way to dump a PGM format file or a "compact" PBM format file (sorry). The TIFF image dumper supports the following options: compression Image data compression technique. Can be one of: _n_o_n_e (no compression), _r_l_e (CCITT RLE compression), _g_3_f_a_x (CCITT Group 3 FAX compression), _g_4_f_a_x (CCITT Group 4 FAX compression), _l_z_w (Limpel-Ziv-Welsh compression, the default), _j_p_e_g (JPEG compression), _n_e_x_t (NeXT run-length compression), _r_l_e_w (CCITT RLEW compression), _m_a_c (Macintosh PackBits compression), _p_a_c_k_b_i_t_s (same as _m_a_c), _t_h_u_n_d_e_r_s_c_a_n (ThunderScan compression). _X_l_o_a_d_i_m_a_g_e will save using the MINISBLACK, MINISWHITE, COLORMAP, or RGB photometrics as appropriate for its inter- nal image format. There is no way to specify a particular photometric or any other TIFF fields. AUTHOR Jim Frost CenterLine Software jimf@centerline.com For a more-or-less complete list of other contributors (there are a _l_o_t of them), please see the README file enclosed with the distribution. FILES xloadimage - the image loader and viewer xsetbg - pseudonym which quietly sets the background xview - pseudonym which views in a window /usr/lib/X11/Xloadimage - default system-wide configuration file ~/.xloadimagerc - user's personal configuration file COPYRIGHT Copyright (c) 1989, 1993 Jim Frost and others. _X_l_o_a_d_i_m_a_g_e is copywritten material with a very loose copy- right allowing unlimited modification and distribution if the copyright notices are left intact. Various portions are copywritten by various people, but all use a modification of the MIT copyright notice. Please check the source for com- plete copyright information. The intent is to keep the source free, not to stifle its distribution, so please write to me if you have any questions. Sun Release 4.1 Last change: 8 May 1991 13 XLOADIMAGE(1) USER COMMANDS XLOADIMAGE(1) BUGS Zooming dithered images, especially downwards, is UGLY. Images can come in a variety of aspect ratios. _X_l_o_a_d_i_m_a_g_e cannot detect what aspect ratio the particular image being loaded has, nor the aspect ratio of the destination display, so images with differing aspect ratios from the destination display will appear distorted. See _H_I_N_T_S _F_O_R _G_O_O_D _I_M_A_G_E _D_I_S_P_L_A_Y_S for more information. The GIF format allows more than one image to be stored in a single GIF file, but _x_l_o_a_d_i_m_a_g_e will only display the first. Only GIF87a format is supported. One of the pseudonyms for _x_l_o_a_d_i_m_a_g_e, _x_v_i_e_w, is the same name as Sun uses for their SunView-under-X package. This will be confusing if you're one of those poor souls who has to use Sun's XView. Some window managers do not correctly handle window size requests. In particular, many versions of the twm window manager use the MaxSize hint instead of the PSize hint, causing images which are larger than the screen to display in a window larger than the screen, something which is nor- mally avoided. Some versions of twm also ignore the MaxSize argument's real function, to limit the maximum size of the window, and allow the window to be resized larger than the image. If this happens, _x_l_o_a_d_i_m_a_g_e merely places the image in the upper-left corner of the window and uses the zero- value'ed pixel for any space which is not covered by the image. This behavior is less-than-graceful but so are win- dow managers which are cruel enough to ignore such details. Sun Release 4.1 Last change: 8 May 1991 14 extension is found filter = "gzip -xloadimage.4.1/autoconfig.c 664 221 144 42665 5467457735 11125 /* autoconfig.c: * * automatic configuration program * * jim frost 09.05.93 */ #include #include #include #ifdef __STDC__ #include #endif /* system-specific configuration defaults */ #ifdef sgi /* C compiler has fixed-size parse tree table that overflows on some * of the macro translations. you'd think compiler writers would be * smarter, wouldn't you? */ #define DEF_CC "cc -Wf,XNh5000" #endif /* sgi */ /* default versions that work on most systems */ #ifndef DEF_CC #define DEF_CC "cc" #endif #ifndef DEF_OPT_FLAGS #define DEF_OPT_FLAGS "-O" #endif #ifndef DEF_INSTALL_DIR #define DEF_INSTALL_DIR "/usr/local/bin" #endif /* list of places to look for system libraries */ char *SysLibDirList[] = { "/lib", "/usr/lib", NULL }; /* typical system path for finding binaries */ char *SysProgPath[] = { "/bin", "/usr/bin", NULL }; /* a few miscellaneous names for places people might put graphics libraries */ char *MiscIncludeDirList[] = { "/usr/include", "/usr/local/include", "/usr/include/graphics", "/usr/local/include/graphics", ".", /* why not? */ NULL }; char *MiscLibDirList[] = { "/lib", "/usr/lib", "/usr/local/lib", "/usr/graphics/lib", "/usr/local/graphics/lib", ".", NULL }; struct X11_dir_list { char *inc_dir; char *lib_dir; } X11DirList[] = { { "/usr/include/X11R6", "/usr/lib/X11R6" }, /* HP style; must be first */ { "/usr/include/X11R5", "/usr/lib/X11R5" }, /* because they have an X11 */ { "/usr/include/X11R4", "/usr/lib/X11R4" }, /* dir too, but it's empty */ { "/usr/include", "/usr/lib" }, /* MIT standard */ { "/usr/openwin/include", "/usr/openwin/lib" }, /* SunOS */ { "/usr/X11R6/include", "/usr/X11R6/lib" }, { "/usr/X11R5/include", "/usr/X11R5/lib" }, { "/usr/X11R4/include", "/usr/X11R4/lib" }, { "/usr/local/X11R6/include", "/usr/local/X11R6/lib" }, { "/usr/local/X11R5/include", "/usr/local/X11R5/lib" }, { "/usr/local/X11R4/include", "/usr/local/X11R4/lib" }, { NULL, NULL } }; struct typical_sys_libs { char *name; char *desc; } TypicalSysLibs[] = { { "socket", "socket support" }, { "nsl", "network support" }, { NULL, NULL } }; char config_style[6]; /* configuration style */ char cflags[4096]; /* flags passed to C compiler */ char libs[4096]; /* extra libraries */ char X11_inc[1024]; /* X11 include path */ char X11_lib[1024]; /* X11 library path */ char X11_name[1024]; /* X11 library name */ char cc[1024]; /* C compiler */ char opt_flags[1024]; /* optimization flags */ char ranlib[1024]; /* ranlib program or /bin/true */ char install_dir[1024]; /* install directory */ char optional_srcs[4096]; /* optional source files */ char optional_libs[4096]; /* optional libraries */ /* this looks to see if there's a file matching a particular pattern. * it uses "echo" as a poor-man's glob. */ int hasFileNamed(pattern) char *pattern; { static char buf[1024]; FILE *p; int i; struct stat stat_buf; sprintf(buf, "echo %s", pattern); p = popen(buf, "r"); if (p == NULL) { /* bad news */ perror("popen"); return(0); } buf[1023] = '\0'; if (fgets(buf, 1023, p) == NULL) { pclose(p); return(0); } pclose(p); if ((buf[0] == ' ') || (buf[0] == '\0')) return(0); /* in shared-library environments we may get several matches. just look * for the first one to verify existance of any of them. */ for (i = 0; buf[i]; i++) { if ((buf[i] == ' ') || (buf[i] == '\n')) { buf[i] = '\0'; break; } } /* technically we could probably get away with avoiding stat() */ if (stat(buf, &stat_buf) < 0) return(0); return(1); } /* this tries to find an installed library. this uses "echo" as a * poor-man's "glob" so we can find shared libraries too. */ int hasSysLibrary(name) char *name; { char **d; char libname[1024]; for (d = SysLibDirList; *d != NULL; d++) { sprintf(libname, "%s/lib%s.*", *d, name); if (hasFileNamed(libname)) return(1); } return(0); } int hasProgram(name) char *name; { char **d; char pathname[1024]; for (d = SysProgPath; *d != NULL; d++) { sprintf(pathname, "%s/%s", *d, name); if (hasFileNamed(pathname)) return(1); } return(0); } /* functions to find include files and libraries */ char *findInclude(name) { char fullname[1024]; char **d; for (d= MiscIncludeDirList; *d; d++) { sprintf(fullname, "%s/%s", *d, name); if (hasFileNamed(fullname)) return(*d); } return(NULL); } char *findLibrary(name) char *name; { char libname[1024]; char fullname[1024]; char **d; if (!strncmp(name, "-l", 2)) sprintf(libname, "lib%s.*", &name[2]); /* skip -l and glob */ else strcpy(libname, X11_name); /* ok, go looking */ for (d= MiscLibDirList; *d; d++) { sprintf(fullname, "%s/%s", *d, libname); if (hasFileNamed(fullname)) return(*d); } return(NULL); } void addOptionalLibrary(desc, define, libdir, libname, srcname) char *desc; /* human-readable name of library */ char *define; /* define that activates support in xloadimage */ char *libdir; /* directory where file resides */ char *libname; /* name of library */ char *srcname; /* name of include file */ { char buf[1024]; if (!hasFileNamed(libdir)) { printf("\nI know how to use the %s library, but it doesn't seem to be\n\ included in this distribution, too bad.\n", libname); return; } printf("\n\ I can include support for the %s format. Would you like me to do so?\n\ (n=no, default=yes): ", desc); gets(buf); if (buf[0] == 'n') return; sprintf(&cflags[strlen(cflags)], " -D%s", define); sprintf(&optional_srcs[strlen(optional_srcs)], " %s", srcname); sprintf(&optional_libs[strlen(optional_libs)], " %s/%s", libdir, libname); } void writeConfigFile() { FILE *f; f = fopen("Make.conf", "w"); if (f == NULL) { perror("\n*** Could not open Make.conf"); printf("\ The permissions may be wrong on the file. Please correct the problem and\n\ try again.\n\n"); exit(1); } fprintf(f, "\ # Xloadimage Configuration file. Normally this file is created by the\n\ # autoconfig program. If you edit this file, make certain that the\n\ # CONFIG_STYLE line is set to -skip or autoconfig will overwrite your\n\ # changes.\n\ CONFIG_STYLE=%s\n\n", config_style); fprintf(f, "\ # C compiler to use, including special flags.\n\ CC=%s\n\n", cc); fprintf(f, "\ # Configuration and options flags for C compiler.\n\ CC_FLAGS=%s\n\n", cflags); fprintf(f, "\ # Optimization flags for C compiler.\n\ OPT_FLAGS=%s\n\n", opt_flags); fprintf(f, "\ # Miscellaneous system libraries.\n\ SYS_LIBS=%s\n\n", libs); fprintf(f, "\ # X11 include and library information.\n\ X11_INC_DIR=%s%s\n\ X11_LIB_DIR=%s%s\n\ X11_LIB_NAME=%s\n\n", (X11_inc[0] ? "-I" : ""), X11_inc, (X11_lib[0] ? "-L" : ""), X11_lib, X11_name); fprintf(f, "\ INSTALLDIR=%s\n\n", install_dir); fprintf(f, "\ # Optional source files, usually integrations for optional loaders.\n\ OPTIONAL_SRCS=%s\n\n", optional_srcs); fprintf(f, "\ # Optional libraries, usually loaders.\n\ OPTIONAL_LIBS=%s\n\n", optional_libs); fprintf(f, "# Ranlib program, or /bin/true if unnecessary\nRANLIB=%s\n\n", ranlib); fprintf(f, "# Other miscellaneous more-or-less standard programs\n"); fprintf(f, "RM=rm -f\n"); fprintf(f, "AR=ar cq\n"); fprintf(f, "CP=cp\n"); fprintf(f, "MV=mv\n"); fprintf(f, "LN=ln -s\n"); fprintf(f, "\n# These fix problems with make cmds that use $SHELL by default\n"); fprintf(f, "SHELL=/bin/sh\n"); fprintf(f, "MAKESHELL=/bin/sh\n"); fclose(f); } main(argc, argv) int argc; char *argv[]; { int i; int is_sysv = 0; int is_bsd = 0; int is_debugging = 0; int tries; char buf[1024]; /* misc input buffer */ struct typical_sys_libs *tsl; /* process command line arguments */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-clean")) { /* don't use the DEF_* macros here! these must be VERY generic! */ strcpy(config_style, "-auto"); strcpy(cc, "cc"); strcpy(cflags, ""); strcpy(opt_flags, ""); strcpy(libs, ""); strcpy(X11_inc, ""); strcpy(X11_lib, ""); strcpy(X11_name, "-lX11"); strcpy(ranlib, "ranlib"); strcpy(install_dir, "/usr/local/bin"); strcpy(optional_srcs, ""); strcpy(optional_libs, ""); writeConfigFile(); exit(0); } else if (!strcmp(argv[i], "-bsd")) { is_bsd = 1; is_sysv = 0; } else if (!strcmp(argv[i], "-sysv")) { is_bsd = 0; is_sysv = 1; } else printf("autoconfig: ignoring unknown option '%s'\n", argv[i]); } printf("\n\ Welcome to the Xloadimage Automatic Configuration Program.\n\n\ I will attempt to determine your machine configuration automatically\n\ and will ask you some questions about preferred compilers and flags.\n\n"); strcpy(config_style, "-skip"); strcpy(cflags, ""); strcpy(libs, ""); printf("Do you want a debugging version built? (y=yes, default=no): "); gets(buf); printf("\n"); if (buf[0] == 'y') { printf("I will compile this with debugging information and without optimization.\n"); is_debugging = 1; strcat(cflags, " -DDEBUG"); } if (is_bsd) printf("Assuming that this is a BSD-compatible system, as you specified.\n"); if (is_sysv) printf("Assuming that this is a System-V-compatible system, as you specified.\n"); /* if neither BSD nor SYSV was specified, try to guess which it is. * this could be more sophisticated. */ if (!is_bsd && !is_sysv) { if (hasFileNamed("/etc/ttytab")) { /* this is a definite BSD-ism */ printf("This looks like a BSD-compatible system.\n"); is_bsd = 1; } else { printf("This looks like a System-V-compatible system.\n"); is_sysv = 1; } } if (is_bsd) strcat(cflags, " -DIS_BSD"); if (is_sysv) strcat(cflags, " -DSYSV"); /* needed for at least */ /* see if exists. most SysV systems have select() * support but require this file to be included in order to use it. * if it doesn't exist, look for instead. */ if (hasFileNamed("/usr/include/sys/select.h")) { printf("This system has a special header-file for select, so I'll use it.\n"); strcat(cflags, " -DHAS_SELECT_INCLUDE"); } else if (!is_bsd && hasFileNamed("/usr/include/poll.h")) { printf("This system appears to support poll(), so I'll use it.\n"); strcat(cflags, " -DHAS_POLL"); } /* look for system libraries that are often needed */ for (tsl = TypicalSysLibs; tsl->name != NULL; tsl++) { if (hasSysLibrary(tsl->name)) { printf("This system appears to have a %s library (-l%s), so I'll use it.\n", tsl->desc, tsl->name); strcat(libs, " -l"); strcat(libs, tsl->name); } } if (hasProgram("ranlib")) { printf("This system has ranlib, so I'll use it.\n"); strcpy(ranlib, "ranlib"); } else strcpy(ranlib, "/bin/true"); /* now for the hard stuff -- we have to find the X11 libraries and * include files. */ for (i = 0; X11DirList[i].inc_dir != NULL; i++) { char include_path[1024]; char lib_path[1024]; sprintf(include_path, "%s/X11", X11DirList[i].inc_dir); sprintf(lib_path, "%s/libX11.*", X11DirList[i].lib_dir); if (hasFileNamed(include_path) && hasFileNamed(lib_path)) { printf("\nI found X11 include files in %s and\n\ the X11 library in %s.\n\ Do you want to use these? (n=no, default=yes): ", include_path, lib_path); gets(buf); if (buf[0] != 'n') break; } } if (X11DirList[i].inc_dir) { strcpy(X11_inc, X11DirList[i].inc_dir); strcpy(X11_lib, X11DirList[i].lib_dir); strcpy(X11_name, "-lX11"); } else { strcpy(X11_inc, ""); printf("\n\ I could not find the X11 include files and/or libraries, so you will need\n\ to specify them for me. If you don't know where these are you should ask\n\ to your system administrator.\n\n"); for (tries = 0;; tries++) { printf("Where are the include files (eg /usr/local/X11R5/include):\n"); gets(X11_inc); if ((X11_inc[0] == '\0') || (X11_inc[0] == '\n')) { printf("\n\ You didn't supply a path so I'm leaving this information out. You will need\n\ to modify the X11_INC_DIR line in Make.conf for the compilation to succeed,\n\ or type 'make configure' to try configuring the system again.\n"); strcpy(X11_inc, ""); break; } sprintf(buf, "%s/X11", X11_inc); if (hasFileNamed(buf)) break; if (tries < 3) printf("I cannot find %s. Please try again.\n", buf); else { printf("\n\ I'm sorry, but you seem to be having trouble specifying this path. I'm\n\ leaving it blank and proceeding. You will probably need to modify the\n\ X11_INC_DIR line in Make.conf for the compilation to succeed. If you want\n\ to try again, type 'make configure'.\n"); strcpy(X11_inc, ""); } } /* same thing for library path */ for (tries = 0;; tries++) { printf("\nWhere are the library files (eg /usr/local/X11R5/lib):\n"); gets(X11_lib); if ((X11_lib[0] == '\0') || (X11_lib[0] == '\n')) { printf("\n\ You didn't supply a path so I'm leaving this information out. You will need\n\ to modify the X11_LIB_DIR line in Make.conf for the compilation to succeed,\n\ or type 'make configure' to try configuring the system again.\n"); strcpy(X11_lib, ""); strcpy(X11_name, "-lX11"); break; } sprintf(buf, "%s/libX11.*", X11_lib); if (hasFileNamed(buf)) { strcpy(X11_name, "-lX11"); break; } printf("\n\ I can't find %s/libX11.a (or anything that looks like a shared library).\n\ If the library has a different name (eg -lX11R5) type it now, or leave\n\ blank to try again: ", X11_lib); gets(X11_name); if ((X11_name[0] != '\0') && (X11_name[0] != '\n')) { char tmp[1024]; if (!strncmp(X11_name, "-l", 2)) sprintf(tmp, "lib%s.*", &X11_name[2]); /* skip -l and glob */ else strcpy(tmp, X11_name); sprintf(buf, "%s/%s", X11_lib, tmp); if (hasFileNamed(buf)) break; printf("\n\ I couldn't find %s either,\n\ but I'll assume you know what you're doing. If you have trouble linking\n\ against this library you should edit Make.conf to make the appropriate\n\ changes.\n", buf); break; } if (tries < 3) printf("I cannot find %s. Please try again.\n", buf); else { printf("\n\ I'm sorry, but you seem to be having trouble specifying this path. I'm\n\ leaving it blank and proceeding. You will probably need to modify the\n\ X11_LIB_DIR line in Make.conf for the compilation to succeed. If you want\n\ to try again, type 'make configure'.\n"); strcpy(X11_lib, ""); strcpy(X11_name, "-lX11"); } } } /* ignore default paths */ if (!strcmp(X11_inc, "/usr/include")) strcpy(X11_inc, ""); if (!strcmp(X11_lib, "/usr/lib") || !strcmp(X11_lib, "/lib")) strcpy(X11_lib, ""); printf("\n\ The default C compiler on this system is:\n\n\ %s\n\n\ If you would like to use a different C compiler or add special compilation\n\ flags (other than optimization-related flags), specify its name and flags.\n\ (default %s): ", DEF_CC, DEF_CC); gets(cc); if ((cc[0] == '\0') || (cc[0] == '\n')) strcpy(cc, DEF_CC); printf("I will invoke the C compiler using %s.\n", cc); if (is_debugging) strcpy(opt_flags, "-g"); else { if ((strlen(cc) >= 3) && !strcmp(&cc[strlen(cc) - 3], "gcc")) { printf("\n\ You specified gcc. Significant performance improvements can be gained\n\ by using the optimization flags -fstrength-reduce -finline-functions.\n\ Would you like me to use those flags? (n=no, default=yes): "); gets(buf); if (buf[0] == 'n') goto get_opt_flags; /* ick, but expedient */ strcpy(opt_flags, "-O -fstrength-reduce -finline-functions"); printf("\n\ Gcc version 1.37 has some optimizer bugs that can cause problems, but I can\n\ work around them by supplying additional optimization flags. Do you have\n\ gcc 1.37? (n=no, default=yes, select default if you don't know): "); gets(buf); if (buf[0] == 'n') strcat(opt_flags, " -fforce-mem -fforce-addr"); } else { get_opt_flags: printf("\n\ On this system I use the following optimizer flag(s):\n\n\ %s\n\n\ If you would like to use a different flag or set of flags, enter it now or\n\ leave blank to use the above flag(s): ", DEF_OPT_FLAGS); gets(opt_flags); if ((opt_flags[0] == '\0') || (opt_flags[0] == '\n')) strcpy(opt_flags, DEF_OPT_FLAGS); } printf("Using optimization flags: %s\n", opt_flags); } /* ask about the install directory */ printf("\n\ Where would you like the installation installed? (Installation is NOT\n\ automatic -- you must type 'make install' from an account with the proper\n\ permissions to actually perform the installation.)\n\ (default=%s)? ", DEF_INSTALL_DIR); gets(install_dir); if ((install_dir[0] == '\0') || (install_dir[0] == '\n')) strcpy(install_dir, DEF_INSTALL_DIR); printf("Installation directory is %s.\n", install_dir); /* now ask about optional loaders we can support if the libraries * are present. */ addOptionalLibrary("JPEG", "HAS_JPEG", "jpeg", "libjpeg.a", "jpeg.c"); addOptionalLibrary("TIFF", "HAS_TIFF", "tiff", "libtiff.a", "tiff.c"); writeConfigFile(); printf("\n\ Automatic configuration is complete. If you need to reconfigure this\n\ installation, type 'make configure'. If there are problems during\n\ the build process you may need to edit the Make.conf file by hand.\n\n"); exit(0); } ed, try to guess which it is. * this could be more sophisticated. */ xloadimage.4.1/Make.conf 664 221 144 1664 5470014457 10301 # Xloadimage Configuration file. Normally this file is created by the # autoconfig program. If you edit this file, make certain that the # CONFIG_STYLE line is set to -skip or autoconfig will overwrite your # changes. CONFIG_STYLE=-auto # C compiler to use, including special flags. CC=cc # Configuration and options flags for C compiler. CC_FLAGS= # Optimization flags for C compiler. OPT_FLAGS= # Miscellaneous system libraries. SYS_LIBS= # X11 include and library information. X11_INC_DIR= X11_LIB_DIR= X11_LIB_NAME=-lX11 INSTALLDIR=/usr/local/bin # Optional source files, usually integrations for optional loaders. OPTIONAL_SRCS= # Optional libraries, usually loaders. OPTIONAL_LIBS= # Ranlib program, or /bin/true if unnecessary RANLIB=ranlib # Other miscellaneous more-or-less standard programs RM=rm -f AR=ar cq CP=cp MV=mv LN=ln -s # These fix problems with make cmds that use $SHELL by default SHELL=/bin/sh MAKESHELL=/bin/sh Ximg.cyph(mac.c|+mcidas.cac.* xloadimage.4.1/libconfig.c 664 221 144 13630 5467527560 10703 /* libconfig.c: * * this performs tests to configure external libraries. most of these * tests are used to determine a compiler's configuration. output * files are written into .conf for inclusion by a Makefile. * * jim frost 09.15.93 */ #include /* things determined by compilation switches */ #ifdef __STDC__ /* ANSI versus non-ANSI. Note that some compilers define __STDC__ * as zero when they are not fully ANSI-compliant. We don't care, * it's close enough. */ int is_ansi = 1; #else int is_ansi = 0; #endif #if defined(IS_BSD) int is_bsd = 1; #else int is_bsd = 0; #endif /* things determined on-the-fly */ int is_big_endian; int is_signed_char; int is_broken_right_shift; #ifdef HAS_TIFF void writeTIFFConfig() { FILE *f; f = fopen("tiff.conf", "w"); if (f == NULL) { perror("tiff.conf"); fprintf(stderr, "libconfig: Couldn't write TIFF library config, sorry.\n"); return; } printf("Writing TIFF library configuration file....\n"); fprintf(f, "\ # TIFF distribution configuration file; this is automagically configured by\n\ # 'libconfig.' If you must edit it, beware that reconfiguring the\n\ # distribution with rewrite this file.\n\n"); fprintf(f, "# Get system-configuration stuff\n"); fprintf(f, "include ../Make.conf\n\n"); fprintf(f, "# ANSI compatibility flags\n"); fprintf(f, "%sPROTOTYPES=-DUSE_PROTOTYPES\n", (is_ansi ? "" : "#")); fprintf(f, "%sVARARGS=-DUSE_VARARGS\n", (is_ansi ? "#" : "")); fprintf(f, "%sCONST=-DUSE_CONST\n", (is_ansi ? "" : "#")); fprintf(f, "\n"); fprintf(f, "# If not a BSD system, need -DSYSV to fix bcopy et al.\n"); fprintf(f, "%sSYSV=-DSYSV\n\n", (is_bsd ? "#" : "")); fprintf(f, "# Conglomerate of all TIFF flags\n"); fprintf(f, "TIFF_CC_FLAGS=$(PROTOTYPES) $(VARARGS) $(CONST) $(SYSV) -Dunix\n"); fclose(f); } #endif /* HAS_TIFF */ #ifdef HAS_JPEG void writeJPEGConfig() { FILE *f; f = fopen("jpeg.conf", "w"); if (f == NULL) { perror("jpeg.conf"); fprintf(stderr, "libconfig: Couldn't write JPEG library config, sorry.\n"); return; } printf("Writing JPEG library configuration file....\n"); fprintf(f, "\ # JPEG distribution configuration file; this is automagically configured by\n\ # 'libconfig.' If you must edit it, beware that reconfiguring the\n\ # distribution with rewrite this file and that changes made here must be\n\ # reflected in jpeg.conf.h.\n\n"); fprintf(f, "# Get system-configuration stuff\n"); fprintf(f, "include ../Make.conf\n\n"); fprintf(f, "# SysV or not.\n"); fprintf(f, "%sSYSV=-DSYSV\n\n", (is_bsd ? "#" : "")); fprintf(f, "# ANSI compatibility flags\n"); fprintf(f, "%sANSI=-DHAS_STDC\n\n", (is_ansi ? "" : "#")); fprintf(f, "# Default signed-ness of char type\n"); fprintf(f, "%sUNSIGNED_CHAR=-DCHAR_IS_UNSIGNED\n\n", (is_signed_char ? "#" : "")); fprintf(f, "# We need to know if the compiler has a broken right-shift operator\n"); fprintf(f, "%sBROKEN_SHIFT=-DRIGHT_SHIFT_IS_UNSIGNED\n\n", (is_broken_right_shift ? "" : "#")); fprintf(f, "# Extra flags we need\n"); fprintf(f, "OTHER=%s\n\n", (is_ansi ? "" : "-DHAVE_UNSIGNED_CHAR")); fprintf(f, "# Conglomerate of all JPEG flags\n\n"); fprintf(f, "JPEG_CC_FLAGS=$(OPT_FLAGS) $(SYSV) $(ANSI) $(UNSIGNED_CHAR) $(BROKEN_SHIFT) $(OTHER)\n"); /* JPEG stuff is all ANSI; we need to write out a .c.o target that * does the compilation correctly if either ANSI or K&R */ fprintf(f, "# .c to .o target; special work needs to be done if not an ANSI compiler.\n"); if (is_ansi) { fprintf(f, ".c.o:\n"); fprintf(f, "\t$(CC) $(JPEG_CC_FLAGS) -c $*.c\n"); } else { fprintf(f, ".c.o: ./ansi2knr\n"); fprintf(f, "\t./ansi2knr $*.c tmpansi.c\n"); fprintf(f, "\t$(CC) $(JPEG_CC_FLAGS) -c tmpansi.c\n"); fprintf(f, "\t$(MV) tmpansi.o $*.o\n"); fprintf(f, "\t$(RM) tmpansi.c\n"); } fclose(f); /* write jpeg.conf.h, used by jpeg.c to get the same defines as used by * the library. */ f = fopen("jpeg.conf.h", "w"); if (f == NULL) { perror("jpeg.conf"); fprintf(stderr, "libconfig: Couldn't write JPEG configuration header, sorry.\n"); return; } /* -DSYSV already done in Make.conf */ fprintf(f, "\ /* jpeg.conf.h:\n\ *\n\ * Configuration file that matches the Makefile configuration file jpeg.conf\n\ * for building jpeg.c. This file is automatically generated.\n\ */\n\n"); fprintf(f, "#define HAVE_UNSIGNED_CHAR 1\n"); if (is_ansi) { fprintf(f, "#define PROTO 1\n"); fprintf(f, "#define HAS_STDC 1\n"); } if (!is_signed_char) fprintf(f, "#define CHAR_IS_UNSIGNED 1\n"); if (is_broken_right_shift) fprintf(f, "#define RIGHT_SHIFT_IS_UNSIGNED 1\n"); fclose(f); } #endif /* HAS_JPEG */ main() { union { unsigned short s; char c[2]; } byte_test; char c = 0; int i; if (is_ansi) printf("C compiler recognizes ANSI constructs.\n"); else printf("C compiler is not ANSI-compatible.\n"); /* determine machine byte order */ byte_test.s = 0x00ff; if (byte_test.c[0] == 0) { printf("Machine has big-endian byte order.\n"); is_big_endian = 1; } else { printf("Machine has little-endian byte order.\n"); is_big_endian = 0; } /* determine default signed-ness of characters. */ if (--c > 0) { /* will wrap to 255 if unsigned */ printf("Compiler assumes unsigned characters by default.\n"); is_signed_char = 0; } else { printf("Compiler assumes signed characters by default.\n"); is_signed_char = 1; } /* determine if the compiler stupidly handles right-shift as a logical * shift rather than an arithmetic shift. this would be broken * behavior but JPEG wants to know.... */ i = -1; if ((i >> 1) > 0) { printf("\ Compiler stupidly treats a signed right-shift as a logical operation.\n"); is_broken_right_shift = 1; } else is_broken_right_shift = 0; #ifdef HAS_TIFF writeTIFFConfig(); #endif #ifdef HAS_JPEG writeJPEGConfig(); #endif exit(0); } stem-configuration stuff\n"); fprintf(f, "include ../Make.conf\n\n"); fprintf(f, "# SysV or not.\n"xloadimage.4.1/makefloppy 775 221 144 375 5461577442 10640 #!/bin/sh echo "Insert an empty floppy disk and push a key. If you want to abort" echo "the process, type q..." read answer if [ "$answer" == "q" ]; then exit 1 fi # format the floppy fdformat -f # tar the stuff onto the floppy tar cf /dev/fd0 $* fbm.hr.Hgif.hm.` imagetypes.h`p#img.h.h& kljcpyrght.h)mac.h.h,mcidas.h.hn mit.cpyrght/ mrmcpyrght.h2niff.hh6pbm.hff8pcx.xloadimage.4.1/jpeg.c 664 221 144 47506 5467510623 7675 /* * jpeg - This file provides interface routines to connect xloadimage to * the jpeg decoding routines taken from the Independent JPEG Group's * free JPEG software. See jpeg.README for more information. * * This code is based on example.c from the IJG v4 distribution. */ #include "image.h" /* xloadimage declarations */ #include "jpeg.conf.h" /* definitions used in jpeg directory */ #include "jpeg/jinclude.h" /* IJG declarations */ #include /* need setjmp/longjmp */ /* Error-catching routines */ static char *filename; static unsigned int verbose; static unsigned int identify; static jmp_buf setjmp_buffer; /* for return to caller */ static external_methods_ptr emethods; /* needed for access to message_parm */ static void trace_message (msgtext) char *msgtext; { fprintf(stderr, "jpegLoad: %s - ", filename); fprintf(stderr, msgtext, emethods->message_parm[0], emethods->message_parm[1], emethods->message_parm[2], emethods->message_parm[3], emethods->message_parm[4], emethods->message_parm[5], emethods->message_parm[6], emethods->message_parm[7]); fprintf(stderr, "\n"); /* there is no \n in the format string! */ } static void error_exit (msgtext) char *msgtext; { trace_message(msgtext); /* report the error message */ (*emethods->free_all) (); /* clean up memory allocation & temp files */ longjmp(setjmp_buffer, 1); /* return control to outer routine */ } /* Output-acceptance routines */ static Image *image; /* xloadimage image being returned */ static int rows_put; /* Number of rows copied to image */ static void output_init (cinfo) decompress_info_ptr cinfo; /* Initialize for output */ { int i; if (cinfo->out_color_space == CS_GRAYSCALE) { image = newRGBImage(cinfo->image_width,cinfo->image_height,8); image->title = dupString(filename); /* set a linear map */ for(i=0;i<256;i++) { *(image->rgb.red + i) = *(image->rgb.green + i) = *(image->rgb.blue + i) = i<<8; } image->rgb.used = 256; } else if (cinfo->out_color_space == CS_RGB) { image = newTrueImage(cinfo->image_width,cinfo->image_height); image->title = dupString(filename); } else { image = NULL; ERREXIT(cinfo->emethods, "Cannot cope with JPEG image colorspace"); } rows_put = 0; } static void put_color_map (cinfo, num_colors, colormap) decompress_info_ptr cinfo; int num_colors; JSAMPARRAY colormap; /* Write the color map -- should not be called */ { fprintf(stderr, "put_color_map called: there is a bug here somewhere!\n"); } static void put_pixel_rows (cinfo, num_rows, pixel_data) decompress_info_ptr cinfo; int num_rows; JSAMPIMAGE pixel_data; /* Write some rows of output data */ { register unsigned char *bufp; register JSAMPROW ptr0, ptr1, ptr2; register long col; long width = cinfo->image_width; int row; if (cinfo->out_color_space == CS_GRAYSCALE) { bufp = image->data + rows_put * width; /* Assume JSAMPLE == chars */ for (row = 0; row < num_rows; row++) { bcopy(pixel_data[0][row],bufp,width); bufp += width; } } else { bufp = image->data + rows_put * width * 3; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; for (col = width; col > 0; col--) { *bufp++ = *ptr0++; *bufp++ = *ptr1++; *bufp++ = *ptr2++; } } } rows_put += num_rows; } static void output_term (cinfo) decompress_info_ptr cinfo; /* Finish up at the end of the output */ { /* No work here */ } /* Input-file-reading routine */ static ZFILE * input_file; /* tells input routine where to read JPEG */ static int read_jpeg_data (cinfo) decompress_info_ptr cinfo; { cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET; cinfo->bytes_in_buffer = zread(input_file, (byte *)cinfo->next_input_byte, JPEG_BUF_SIZE); if (cinfo->bytes_in_buffer <= 0) { WARNMS(cinfo->emethods, "Premature EOF in JPEG file"); cinfo->next_input_byte[0] = (char) 0xFF; cinfo->next_input_byte[1] = (char) 0xD9; /* EOI marker */ cinfo->bytes_in_buffer = 2; } return JGETC(cinfo); } /* Required control-hook routine */ static void d_ui_method_selection (cinfo) decompress_info_ptr cinfo; { /* if grayscale input, force grayscale output; */ /* else leave the output colorspace as set by main routine. */ if (cinfo->jpeg_color_space == CS_GRAYSCALE) cinfo->out_color_space = CS_GRAYSCALE; /* Create display of image parameters */ if (verbose) { printf("%s is a %dx%d JPEG image, color space ", filename, cinfo->image_width, cinfo->image_height); switch (cinfo->jpeg_color_space) { case CS_UNKNOWN: printf("Unknown"); break; case CS_GRAYSCALE: printf("Grayscale"); break; case CS_RGB: printf("RGB"); break; case CS_YCbCr: printf("YCbCr"); break; case CS_YIQ: printf("YIQ"); break; case CS_CMYK: printf("CMYK"); break; } printf(", %d comp%s,", cinfo->num_components, cinfo->num_components ? "s." : "."); if (cinfo->arith_code) printf(" Arithmetic coding\n"); else printf(" Huffman coding\n"); } /* Turn off caching beyond this point of the file */ znocache(input_file); /* If we only wanted to identify the image, abort now */ if (identify) { (*emethods->free_all) (); /* clean up memory allocation & temp files */ longjmp(setjmp_buffer, 10); /* return control with success code */ } /* select output routines */ cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; cinfo->methods->put_pixel_rows = put_pixel_rows; cinfo->methods->output_term = output_term; } /* Main control routine for loading */ Image * jpegLoad (fullname, name, vbose) char *fullname, *name; unsigned int vbose; { struct Decompress_info_struct cinfo; struct Decompress_methods_struct dc_methods; struct External_methods_struct e_methods; input_file = zopen(fullname); /* Open the input file */ if (input_file == NULL) return NULL; /* Quick check to see if file starts with JPEG SOI marker */ if (zgetc(input_file) != 0xFF || zgetc(input_file) != 0xD8) { zclose(input_file); return NULL; } filename = name; /* copy parms to static vars */ verbose = vbose; identify = 0; image = NULL; /* in case we fail before creating image */ cinfo.methods = &dc_methods; /* links to method structs */ cinfo.emethods = &e_methods; emethods = &e_methods; /* save struct addr for possible access */ e_methods.error_exit = error_exit; /* supply error-exit routine */ e_methods.trace_message = trace_message; /* supply trace-message routine */ e_methods.trace_level = 0; /* default = no tracing */ e_methods.num_warnings = 0; /* no warnings emitted yet */ e_methods.first_warning_level = 0; /* display first corrupt-data warning */ e_methods.more_warning_level = 3; /* but suppress additional ones */ /* prepare setjmp context for possible exit from error_exit */ if (setjmp(setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ /* Return as much of the image as we could get. */ zclose(input_file); return image; } jselmemmgr(&e_methods); /* select std memory allocation routines */ /* Set up default decompression parameters. */ j_d_defaults(&cinfo, TRUE); /* Override default methods */ dc_methods.d_ui_method_selection = d_ui_method_selection; dc_methods.read_jpeg_data = read_jpeg_data; /* Insert fake SOI into the input buffer --- needed cause we read it above */ cinfo.next_input_byte = cinfo.input_buffer + MIN_UNGET; cinfo.next_input_byte[0] = (char) 0xFF; cinfo.next_input_byte[1] = (char) 0xD8; /* SOI marker */ cinfo.bytes_in_buffer = 2; /* Set up to read a JFIF or baseline-JPEG file. */ /* This is the only JPEG file format currently supported. */ jselrjfif(&cinfo); /* Here we go! */ jpeg_decompress(&cinfo); zclose(input_file); /* Done, close the input file */ return image; } /* Main control routine for identifying JPEG without loading */ int jpegIdent (fullname, name) char *fullname, *name; { struct Decompress_info_struct cinfo; struct Decompress_methods_struct dc_methods; struct External_methods_struct e_methods; input_file = zopen(fullname); /* Open the input file */ if (input_file == NULL) return 0; /* Quick check to see if file starts with JPEG SOI marker */ if (zgetc(input_file) != 0xFF || zgetc(input_file) != 0xD8) { zclose(input_file); return 0; } /* We want to find and display the image dimensions, and also * verify that the header markers are not corrupt. To do this, * we fire up the JPEG decoder as normal, but when d_ui_method_selection * is called, we abort the process by longjmp'ing back here. * This works nicely since the headers are all read at that point. */ filename = name; /* copy parms to static vars */ verbose = 1; identify = 1; cinfo.methods = &dc_methods; /* links to method structs */ cinfo.emethods = &e_methods; emethods = &e_methods; /* save struct addr for possible access */ e_methods.error_exit = error_exit; /* supply error-exit routine */ e_methods.trace_message = trace_message; /* supply trace-message routine */ e_methods.trace_level = 0; /* default = no tracing */ e_methods.num_warnings = 0; /* no warnings emitted yet */ e_methods.first_warning_level = 0; /* display first corrupt-data warning */ e_methods.more_warning_level = 3; /* but suppress additional ones */ /* prepare setjmp context for expected exit via longjmp */ switch (setjmp(setjmp_buffer)) { case 0: /* First time thru, keep going */ break; case 10: /* Successful exit from d_ui_method_selection; return A-OK */ zclose(input_file); return 1; default: /* If we get here, the JPEG code has signaled an error. */ /* Return 0 since error in the headers means the image is unloadable. */ zclose(input_file); return 0; } jselmemmgr(&e_methods); /* select std memory allocation routines */ /* Set up default decompression parameters. */ j_d_defaults(&cinfo, TRUE); /* Override default methods */ dc_methods.d_ui_method_selection = d_ui_method_selection; dc_methods.read_jpeg_data = read_jpeg_data; /* Insert fake SOI into the input buffer --- needed cause we read it above */ cinfo.next_input_byte = cinfo.input_buffer + MIN_UNGET; cinfo.next_input_byte[0] = (char) 0xFF; cinfo.next_input_byte[1] = (char) 0xD8; /* SOI marker */ cinfo.bytes_in_buffer = 2; /* Set up to read a JFIF or baseline-JPEG file. */ /* This is the only JPEG file format currently supported. */ jselrjfif(&cinfo); /* Here we go! */ jpeg_decompress(&cinfo); /* Don't expect to get here since d_ui_method_selection should do longjmp */ zclose(input_file); return 0; } /* information necessary to extract image data */ static struct { Image *image; byte *current_row; unsigned int bytes_per_row; } ReadInfo; static void input_init(cinfo) compress_info_ptr cinfo; { /* this is done in jpegDump() */ } static void input_term(cinfo) compress_info_ptr cinfo; { /* there is no shutdown necessary */ } /* this reads a single raster line */ static void read_row(cinfo, pixel_rows) compress_info_ptr cinfo; JSAMPARRAY pixel_rows; { register int x; register int pixlen; register byte *src_row_ptr; register byte *dest_red_ptr; register byte *dest_green_ptr; register byte *dest_blue_ptr; register Pixel pixval; register byte mask; switch (ReadInfo.image->type) { case IBITMAP: mask = 0x80; src_row_ptr = ReadInfo.current_row; dest_red_ptr = (byte *)pixel_rows[0]; for (x = 0; x < cinfo->image_width; x++) { pixval = ((*src_row_ptr & mask) > 0 ? 1 : 0); /* we use the "red" color value under the assumption that they * are all equal. that can be wrong if the user used -foreground * or -background. I don't care right now. */ *(dest_red_ptr++) = ReadInfo.image->rgb.red[pixval] >> 8; mask >>= 1; if (mask == 0) { mask = 0x80; src_row_ptr++; } } break; case IRGB: /* this expands the pixel value into its components */ pixlen = ReadInfo.image->pixlen; src_row_ptr = ReadInfo.current_row; dest_red_ptr = (byte *)pixel_rows[0]; dest_green_ptr = (byte *)pixel_rows[1]; dest_blue_ptr = (byte *)pixel_rows[2]; for (x = 0; x < cinfo->image_width; x++) { pixval = memToVal(src_row_ptr, pixlen); *(dest_red_ptr++) = ReadInfo.image->rgb.red[pixval] >> 8; *(dest_green_ptr++) = ReadInfo.image->rgb.green[pixval] >> 8; *(dest_blue_ptr++) = ReadInfo.image->rgb.blue[pixval] >> 8; src_row_ptr += pixlen; } break; case ITRUE: src_row_ptr = ReadInfo.current_row; dest_red_ptr = (byte *)pixel_rows[0]; dest_green_ptr = (byte *)pixel_rows[1]; dest_blue_ptr = (byte *)pixel_rows[2]; for (x = 0; x < cinfo->image_width; x++) { *(dest_red_ptr++) = *(src_row_ptr++); *(dest_green_ptr++) = *(src_row_ptr++); *(dest_blue_ptr++) = *(src_row_ptr++); } break; } ReadInfo.current_row += ReadInfo.bytes_per_row; } /* * This routine gets control after the input file header has been read. * It must determine what output JPEG file format is to be written, * and make any other compression parameter changes that are desirable. */ static void c_ui_method_selection (cinfo) compress_info_ptr cinfo; { /* If the input is gray scale, generate a monochrome JPEG file. */ if (cinfo->in_color_space == CS_GRAYSCALE) j_monochrome_default(cinfo); jselwjfif(cinfo); } /* parse options passed to jpegDump */ static void parseOptions(cinfo, options, verbose) compress_info_ptr cinfo; char *options; int verbose; { char *name, *value; /* (Re-)initialize the system-dependent error and memory managers. */ jselerror(cinfo->emethods); /* error/trace message routines */ jselmemmgr(cinfo->emethods); /* memory allocation routines */ cinfo->methods->c_ui_method_selection = c_ui_method_selection; /* Set up default JPEG parameters. */ /* Note that default -quality level here need not, and does not, * match the default scaling for an explicit -qtables argument. */ j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */ while (getNextTypeOption(&options, &name, &value) > 0) { if (!strncmp("arithmetic", name, strlen(name))) { /* Use arithmetic coding. */ #ifdef C_ARITH_CODING_SUPPORTED if (verbose) printf(" Using arithmetic coding.\n"); cinfo->arith_code = TRUE; #else fprintf(stderr, "jpegDump: sorry, arithmetic coding not supported\n"); } #endif else if (!strncmp("grayscale", name, strlen(name)) || !strncmp("greyscale", name, strlen(name)) || !strncmp("monochrome", name, strlen(name))) { /* Force a monochrome JPEG file to be generated. */ if (verbose) printf(" Creating a grayscale/monochrome file.\n"); j_monochrome_default(cinfo); } else if (!strncmp("nointerleave", name, strlen(name))) { /* Create noninterleaved file. */ #ifdef C_MULTISCAN_FILES_SUPPORTED if (verbose) printf(" Creating a noninterleaved file.\n"); cinfo->interleave = FALSE; #else fprintf(stderr, "jpegDump: sorry, multiple-scan support was not compiled\n"); #endif } else if (!strncmp("optimize", name, strlen(name)) || !strncmp("optimise", name, strlen(name))) { /* Enable entropy parm optimization. */ #ifdef ENTROPY_OPT_SUPPORTED if (verbose) printf(" Optimizing entropy.\n"); cinfo->optimize_coding = TRUE; #else fprintf(stderr, "jpegDump: sorry, entropy optimization was not compiled\n"); #endif } else if (!strncmp("quality", name, strlen(name))) { /* Quality factor (quantization table scaling factor). */ int val; if (!value || (sscanf(value, "%d", &val) != 1)) fprintf(stderr, "jpegDump: quality: Invalid quality factor specified.\n"); else { /* Set quantization tables (will be overridden if -qtables also given). * Note: we make force_baseline FALSE. * This means non-baseline JPEG files can be created with low Q values. * To ensure only baseline files are generated, pass TRUE instead. */ if (verbose) printf(" Using a quality factor of %d.\n", val); j_set_quality(cinfo, val, FALSE); #if 0 /* Change scale factor in case -qtables is present. */ q_scale_factor = j_quality_scaling(val); #endif } } #if 0 else if (!strncmp("qtables", name, strlen(name))) { /* Quantization tables fetched from file. */ if (!value || !*value) fprintf(stderr, "jpegDump: No file specified for quantization tables.\n"); else { if (verbose) printf(" Using quantization tables loaded from %s.\n", qtablefile); qtablefile = value; } /* we postpone actually reading the file in case -quality comes later */ } #endif else if (!strncmp("restart", name, strlen(name))) { /* Restart interval in MCU rows (or in MCUs with 'b'). */ long lval; char ch = 'x'; if (!value || (sscanf(value, "%ld%c", &lval, &ch) < 1) || (lval < 0) || (lval > 65535L)) { fprintf(stderr, "jpegDump: restart: Invalid restart interval specified.\n"); continue; } if (verbose) printf(" Using a restart interval of %s.\n", value); if (ch == 'b' || ch == 'B') cinfo->restart_interval = (UINT16) lval; else cinfo->restart_in_rows = (int) lval; } #if 0 else if (!strncmp("sample", name, strlen(name))) { /* Set sampling factors. */ if (!value) fprintf(stderr, "jpegDump: sample: No sampling factors specified.\n"); if (verbose) printf(" Using sampling factors of %s.\n", value); set_sample_factors(cinfo, value); } #endif else if (!strncmp("smooth", name, strlen(name))) { /* Set input smoothing factor. */ int val; if (!value || (sscanf(value, "%d", &val) != 1) || (val < 0) || (val > 100)) fprintf(stderr, "jpegDump: smooth: Invalid smoothing factor specified.\n"); else { if (verbose) printf(" Using a smoothing factor of %d.\n", val); cinfo->smoothing_factor = val; } } else fprintf(stderr, "jpegDump: Unknown option '%s'.\n", name); } } void jpegDump(image, options, file, verbose) Image *image; char *options; char *file; { struct Compress_info_struct cinfo; struct Compress_methods_struct c_methods; struct External_methods_struct e_methods; if (verbose) printf("Dumping JFIF-style JPEG image to %s.\n", file); /* Set up links to method structures. */ cinfo.methods = &c_methods; cinfo.emethods = &e_methods; /* set up "input methods" that handle "reading" from our image file */ cinfo.methods->input_init = input_init; cinfo.methods->input_term = input_term; cinfo.methods->get_input_row = read_row; /* set up output file; there is no input file */ cinfo.input_file = NULL; cinfo.output_file = fopen(file, "w"); if (cinfo.output_file == NULL) { perror(file); return; } ReadInfo.image = image; ReadInfo.current_row = image->data; /* parse the options the user gave us */ parseOptions(&cinfo, options, verbose); /* set up image information */ cinfo.image_width = image->width; cinfo.image_height = image->height; switch (image->type) { case IBITMAP: ReadInfo.bytes_per_row = (image->width / 8) + (image->width % 8 ? 1 : 0); cinfo.input_components = 1; cinfo.in_color_space = CS_GRAYSCALE; cinfo.data_precision = 8; break; case IRGB: ReadInfo.bytes_per_row = image->width * image->pixlen; cinfo.input_components = 3; cinfo.in_color_space = CS_RGB; cinfo.data_precision = 8; break; case ITRUE: ReadInfo.bytes_per_row = image->width * image->pixlen; cinfo.input_components = 3; cinfo.in_color_space = CS_RGB; cinfo.data_precision = 8; break; } /* compress, baby */ jpeg_compress(&cinfo); fclose(cinfo.output_file); return; } r used -foreground * or -background. I don't care right now. */ *(dest_red_ptr++) = ReadInfo.image->rgb.red[pixval] >> 8; mask >>= 1; if (mask == 0) { mxloadimage.4.1/tiff.c 664 221 144 42315 5467461236 7676 /* tiff.c: * * interface file for TIFF image format * * jim frost 09.05.93 */ #ifdef HAS_TIFF #include "image.h" #include "tiff/tiffio.h" /* this structure contains all the information we care about WRT a TIFF * image. */ struct tiff_info { unsigned short type; /* little- or big-endian */ int width; int height; int depth; unsigned short planarconfiguration; unsigned short photometric; unsigned short compression; unsigned short bitspersample; unsigned short samplesperpixel; unsigned short bytesperrow; char *title; }; static TIFF *is_tiff(fullname, name, info) char *fullname; char *name; struct tiff_info *info; { ZFILE *zf; TIFFHeader th; TIFF *tiff; zf = zopen(fullname); /* read TIFF header and see if it looks right */ if ((zread(zf, (byte *)&th, sizeof(TIFFHeader)) == sizeof(TIFFHeader)) && ((th.tiff_magic == TIFF_BIGENDIAN) || (th.tiff_magic == TIFF_LITTLEENDIAN))) { /* definitely a tiff file */ if (zf->type != ZSTANDARD) { printf("%s is a TIFF file, but TIFF files can't be read through pipes or filters, sorry.\n", name); return((TIFF *)-1); } info->type= th.tiff_magic; tiff = TIFFOpen(fullname, "r"); if (!tiff) return(0); /* ok, start sucking in information about this file */ /* find out gross information about this image */ TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGEWIDTH, &info->width); TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGELENGTH, &info->height); TIFFGetFieldDefaulted(tiff, TIFFTAG_PLANARCONFIG, &info->planarconfiguration); TIFFGetFieldDefaulted(tiff, TIFFTAG_PHOTOMETRIC, &info->photometric); TIFFGetFieldDefaulted(tiff, TIFFTAG_COMPRESSION, &info->compression); TIFFGetFieldDefaulted(tiff, TIFFTAG_BITSPERSAMPLE, &info->bitspersample); TIFFGetFieldDefaulted(tiff, TIFFTAG_SAMPLESPERPIXEL, &info->samplesperpixel); info->bytesperrow= TIFFScanlineSize(tiff); /* get the "title" of the image */ if (!TIFFGetField(tiff, TIFFTAG_DOCUMENTNAME, &info->title)) if (!TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &info->title)) info->title = NULL; /* make our own copy just to be safe */ if (info->title) info->title = dupString(info->title); #if 0 /* maybe it does */ /* convert byte orders. why the hell doesn't the TIFF stuff do this * for you? */ switch (info->type) { case TIFF_BIGENDIAN: #define convert(V) (V) = memToVal(&(V), sizeof(V)) convert(info->width); convert(info->height); convert(info->planarconfiguration); convert(info->photometric); convert(info->compression); convert(info->bitspersample); convert(info->samplesperpixel); #undef convert break; case TIFF_LITTLEENDIAN: #define convert(V) (V) = memToValLSB(&(V), sizeof(V)) convert(info->width); convert(info->height); convert(info->planarconfiguration); convert(info->photometric); convert(info->compression); convert(info->bitspersample); convert(info->samplesperpixel); #undef convert break; } #endif return(tiff); } zclose(zf); return(0); } static char *photometricName(info) struct tiff_info *info; { static char buf[32]; switch (info->photometric) { case PHOTOMETRIC_MINISBLACK: if (info->bitspersample > 1) { sprintf(buf, "%d-bit greyscale ", info->bitspersample); return(buf); } else return "white-on-black "; case PHOTOMETRIC_MINISWHITE: if (info->bitspersample > 1) { sprintf(buf, "%d-bit greyscale ", info->bitspersample); return(buf); } else return "black-on-white "; case PHOTOMETRIC_RGB: return "RGB "; case PHOTOMETRIC_PALETTE: return "colormap "; case PHOTOMETRIC_MASK: return "masked "; case PHOTOMETRIC_SEPARATED: return "color-separated "; case PHOTOMETRIC_YCBCR: return "YCBCR "; case PHOTOMETRIC_CIELAB: return "CIE L*a*b* "; default: return ""; } } static char *compressionName(compression) int compression; { switch (compression) { case COMPRESSION_NONE: return "standard "; case COMPRESSION_CCITTRLE: return "RLE "; case COMPRESSION_CCITTFAX3: return "G3FAX "; case COMPRESSION_CCITTFAX4: return "G4FAX "; case COMPRESSION_LZW: return "LZW "; case COMPRESSION_JPEG: return "JPEG "; case COMPRESSION_NEXT: return "NeXT "; case COMPRESSION_CCITTRLEW: return "RLEW "; case COMPRESSION_PACKBITS: return "Macintosh "; case COMPRESSION_THUNDERSCAN: return "Thunderscan "; default: return ""; } } static char *planarConfigName(config) int config; { switch (config) { case PLANARCONFIG_CONTIG: return "single-plane "; case PLANARCONFIG_SEPARATE: return "separate-plane "; default: return ""; } } static void babble(name, info) char *name; struct tiff_info *info; { switch (info->photometric) { case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: printf("%s is a %dx%d %s%s%sTIFF image", name, info->width, info->height, planarConfigName(info->planarconfiguration), photometricName(info), compressionName(info->compression)); break; default: printf("%s is a %dx%d %d-bit %s%s%sTIFF image", name, info->width, info->height, (info->bitspersample * info->samplesperpixel), planarConfigName(info->planarconfiguration), photometricName(info), compressionName(info->compression)); } if (info->title) printf("Titled \"%s\""); printf("\n"); } int tiffIdent(fullname, name) { TIFF *tiff; struct tiff_info info; tiff = is_tiff(fullname, name, &info); babble(name, info); if (tiff == NULL) return(0); if (tiff == (TIFF *)-1) /* is TIFF, but can't open it */ return(1); TIFFClose(tiff); babble(fullname, name, info); return(1); } Image *tiffLoad(fullname, name, verbose) char *fullname; char *name; int verbose; { TIFF *tiff; struct tiff_info info; Image *image; byte *row, *dest_line; int dest_line_len; register int pixlen; register byte *dest; register int x, y; tiff = is_tiff(fullname, name, &info); if ((tiff == NULL) || (tiff == (TIFF *)-1)) return(NULL); if (verbose) babble(name, &info); row = lmalloc(info.bytesperrow); /* decide which type of image to allocate based on photometric * information and set up the colormap as necessary */ switch (info.photometric) { case PHOTOMETRIC_MINISWHITE: /* bitmap and greyscale image types */ case PHOTOMETRIC_MINISBLACK: /* monochrome image */ if (info.bitspersample == 1) { dest_line_len = (info.width / 8) + (info.width % 8 ? 1 : 0); if (dest_line_len > info.bytesperrow) /* just in case */ dest_line_len = info.bytesperrow; image= newBitImage(info.width, info.height); /* default bit image colormap matches PHOTOMETRIC_MINISWHITE, so we * need to change it if it's the other type. */ if (info.photometric == PHOTOMETRIC_MINISBLACK) { image->rgb.red[0]= image->rgb.green[0]= image->rgb.blue[0]= 0; image->rgb.red[1]= image->rgb.green[1]= image->rgb.blue[1]= 65535; } /* read the image data and set the pixels */ dest = image->data; if (info.bitspersample == 1) { for (y = 0; y < info.height; y++) { if (TIFFReadScanline(tiff, row, y, 0) < 0) { fprintf(stderr, "%s: Short read in image data!\n", fullname); break; } /* isn't it nice when it's in the same data format we use? */ bcopy(row, dest, dest_line_len); dest += dest_line_len; } } break; } else { /* need to build the scale for greyscale images */ image = newRGBImage(info.width, info.height, info.bitspersample); for (x = 0; x < image->rgb.size; x++) { int value = (65535 * x) / (unsigned int)(image->rgb.size); if (info.photometric == PHOTOMETRIC_MINISWHITE) value = 65535 - value; image->rgb.red[x]= image->rgb.green[x]= image->rgb.blue[x]= value; } image->rgb.used = image->rgb.size; goto read_pallette_data; /* ugly but expedient */ } /* NOTREACHED */ case PHOTOMETRIC_PALETTE: /* this is a close match with the IRGB-style Image. */ image = newRGBImage(info.width, info.height, info.bitspersample); { unsigned short *red, *green, *blue; if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue)) { fprintf(stderr, "%s: Image has no colormap!\n", fullname); freeImage(image); image = NULL; break; } /* fill in our colormap with this data */ switch (info.type) { case TIFF_BIGENDIAN: for (x = 0; x < image->rgb.size; x++) { image->rgb.red[x] = memToVal(&red[x], 2); image->rgb.green[x] = memToVal(&green[x], 2); image->rgb.blue[x] = memToVal(&blue[x], 2); } break; case TIFF_LITTLEENDIAN: for (x = 0; x < image->rgb.size; x++) { image->rgb.red[x] = memToValLSB(&red[x], 2); image->rgb.green[x] = memToValLSB(&green[x], 2); image->rgb.blue[x] = memToValLSB(&blue[x], 2); } break; } image->rgb.used = image->rgb.size; /* all filled up */ } read_pallette_data: /* start reading image data */ dest_line_len = info.width * image->pixlen; if (dest_line_len > info.bytesperrow) /* just in case */ dest_line_len = info.bytesperrow; pixlen = image->pixlen; dest_line = image->data; switch (info.type) { case TIFF_LITTLEENDIAN: if (info.bitspersample > 8) { /* bummer, need to byte-swap */ for (y = 0; y < info.height; y++) { if (TIFFReadScanline(tiff, row, y, 0) < 0) { fprintf(stderr, "%s: Short read in image data!\n", fullname); break; } dest = dest_line; for (x = 0; x < info.width; x++) { valToMem(memToValLSB(dest, image->pixlen), dest, pixlen); dest += pixlen; } dest_line += dest_line_len; } } /* if the sample fits in 1 byte we don't need to byte swap so * we fall through into the big-endian reader which is much faster. */ /* FALLTHRU */ case TIFF_BIGENDIAN: /* bigendian is a nice match for our internal data format */ for (y = 0; y < info.height; y++) { if (TIFFReadScanline(tiff, row, y, 0) < 0) { fprintf(stderr, "%s: Short read in image data!\n", fullname); break; } bcopy(row, dest_line, dest_line_len); dest_line += dest_line_len; } break; } break; case PHOTOMETRIC_RGB: /* this is a close match with the ITRUE-style Image. */ if (info.samplesperpixel != 3) { fprintf(stderr, "%s: Can't handle TIFF RGB images with %d samples per pixel, sorry\n", info.samplesperpixel); image = NULL; break; } image = newTrueImage(info.width, info.height); dest_line_len = info.width * image->pixlen; if (dest_line_len > info.bytesperrow) /* just in case */ dest_line_len = info.bytesperrow; dest_line = image->data; /* quick-and-dirty copy if it's just what we're looking for */ switch (info.planarconfiguration) { case PLANARCONFIG_CONTIG: if (info.bitspersample == 8) { for (y = 0; y < info.height; y++) { if (TIFFReadScanline(tiff, row, y, 0) < 0) { fprintf(stderr, "%s: Short read in image data!\n", fullname); break; } bcopy(row, dest_line, dest_line_len); dest_line += dest_line_len; } } else { case PLANARCONFIG_SEPARATE: fprintf(stderr, "%s: %s is an unsupported planar configuration.\n", fullname, planarConfigName(info.planarconfiguration)); freeImage(image); image = NULL; } } break; case PHOTOMETRIC_MASK: case PHOTOMETRIC_SEPARATED: case PHOTOMETRIC_YCBCR: case PHOTOMETRIC_CIELAB: default: fprintf(stderr, "%s: %s is an unsupported TIFF photometric style, sorry.\n", fullname, photometricName(&info)); image = NULL; } if (image) { if (info.title) image->title = info.title; else image->title = dupString(name); } TIFFClose(tiff); lfree(row); return(image); } /* this is not what I'd call a well-designed TIFF dumping function but it * does do the job. */ void tiffDump(image, options, file, verbose) Image *image; char *options; char *file; int verbose; { TIFF *out; char *name, *value; int compression = COMPRESSION_LZW; int y; int srclinelen; byte *srcptr; out = TIFFOpen(file, "w"); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (unsigned long) image->width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, (unsigned long) image->height); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, 1); /* this sets the TIFF resolution, necessary for some packages. since * we have no concept of resolution (most input files don't retain that * information) we set it for 1:1 pixel resolution. */ TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE); TIFFSetField(out, TIFFTAG_XRESOLUTION, (float)1.0); TIFFSetField(out, TIFFTAG_YRESOLUTION, (float)1.0); /* process image options */ while (getNextTypeOption(&options, &name, &value) > 0) { if (!strncmp("compression", name, strlen(name))) { if (!strncmp("none", value, strlen(value))) compression = COMPRESSION_NONE; else if (!strncmp("rle", value, strlen(value))) compression = COMPRESSION_CCITTRLE; else if (!strncmp("g3fax", value, strlen(value))) compression = COMPRESSION_CCITTFAX3; else if (!strncmp("g4fax", value, strlen(value))) compression = COMPRESSION_CCITTFAX4; else if (!strncmp("lzw", value, strlen(value))) compression = COMPRESSION_LZW; /* default */ else if (!strncmp("jpeg", value, strlen(value))) compression = COMPRESSION_JPEG; else if (!strncmp("next", value, strlen(value))) compression = COMPRESSION_NEXT; else if (!strncmp("rlew", value, strlen(value))) compression = COMPRESSION_CCITTRLEW; else if (!strncmp("packbits", value, strlen(value)) || !strncmp("mac", value, strlen(value))) compression = COMPRESSION_PACKBITS; else if (!strncmp("thunderscan", value, strlen(value))) compression = COMPRESSION_THUNDERSCAN; else fprintf(stderr, "tiffDump: Unknown compression type '%s'.\n", value); } else fprintf(stderr, "tiffDump: Unknown option '%s'\n", name); } TIFFSetField(out, TIFFTAG_COMPRESSION, compression); switch (image->type) { case IBITMAP: /* should use pixel intensity but this will usually work */ if (image->rgb.red[0] > image->rgb.red[1]) { if (verbose) { printf("Dumping black-on-white "); if (compression != COMPRESSION_NONE) printf("%s", compressionName(compression)); printf("TIFF image to %s.\n", file); } TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); } else { if (verbose) { printf("Dumping white-on-black "); if (compression != COMPRESSION_NONE) printf("%s", compressionName(compression)); printf("TIFF image to %s.\n", file); } TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); } TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1); srclinelen = (image->width / 8) + (image->width % 8 ? 1 : 0); srcptr = image->data; for (y = 0; y < image->height; y++) { TIFFWriteScanline(out, srcptr, y, 0); srcptr += srclinelen; } break; case IRGB: TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8 * image->pixlen); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); if (verbose) { printf("Dumping colormap "); if (compression != COMPRESSION_NONE) printf("%s", compressionName(compression)); printf("TIFF image to %s.\n", file); } /* save the colormap */ { unsigned short *red, *green, *blue; red = (unsigned short *)lmalloc(image->rgb.size * sizeof(unsigned short)); green = (unsigned short *)lmalloc(image->rgb.size * sizeof(unsigned short)); blue = (unsigned short *)lmalloc(image->rgb.size * sizeof(unsigned short)); for (y = 0; y < image->rgb.used; y++) { valToMem(image->rgb.red[y], &red[y], 2); valToMem(image->rgb.green[y], &green[y], 2); valToMem(image->rgb.blue[y], &blue[y], 2); } while (y < image->rgb.size) { valToMem(0, &red[y], 2); valToMem(0, &green[y], 2); valToMem(0, &blue[y], 2); y++; } TIFFSetField(out, TIFFTAG_COLORMAP, red, green, blue); lfree((byte *)red); lfree((byte *)green); lfree((byte *)blue); } srclinelen = image->width * image->pixlen; srcptr = image->data; for (y = 0; y < image->height; y++) { TIFFWriteScanline(out, srcptr, y, 0); srcptr += srclinelen; } break; case ITRUE: if (verbose) { printf("Dumping RGB "); if (compression != COMPRESSION_NONE) printf("%s", compressionName(compression)); printf("TIFF image to %s.\n", file); } TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); srclinelen = image->width * image->pixlen; srcptr = image->data; for (y = 0; y < image->height; y++) { TIFFWriteScanline(out, srcptr, y, 0); srcptr += srclinelen; } break; } TIFFClose(out); } #else /* !HAS_TIFF */ static int unused; #endif /* !HAS_TIFF */ info.bytesperrow; pixlen = image->pixlen; dest_line = image->data; switch (info.type) { case TIFF_LITTLEENDIAN: if (info.bitspersample > 8) { /* bummer, need to byte-swap */ for (y = 0; y < info.height; y++) { if (TIFFReadScanline(tiff, row, y, 0) < 0) { fprintf(stderr, xloadimage.4.1/uufilter.man 664 221 144 2000 5466222016 11067 .TH UUFILTER 1 "21 October 1993" .SH NAME uufilter - decode uuencoded files to stdout .SH SYNOPSIS \fIuufilter\fR [-f \fIoutfilename\fR] [-l] [-s] [-v] [\fIinfilename\fR] .SH DESCRIPTION \fIUufilter\fR is a "smart" uuencoded file decoder that can optionally dump the file to stdout. .PP If no filename is supplied, input is read from stdin. .PP \fIUufilter\fR automatically ignores lines that do not appear to be part of the uuencoded file. This is particularly useful in uudecoding files that have been concatenated from several email or news postings without stripping off the headers or otherwise editting extraneous content. .SH OPTIONS .TP 8 -f \fIfilename\fR Dump output to \fIfilename\fR rather than the name specified in the uuencoded file. .TP -l Lenient mode. This is useful if passed through a mailer that adds trailing spaces. .TP -s Dump output to stdout rather than to the filename indicated in the uuencoded file. .TP -v Verbose mode; talks about what's going on. .SH AUTHOR Jim Frost (jimf@centerline.com) xloadimage.4.1/uufilter.txt 664 221 144 2517 5470014470 11146 UUFILTER(1) USER COMMANDS UUFILTER(1) NAME uufilter - decode uuencoded files to stdout SYNOPSIS _u_u_f_i_l_t_e_r [-f _o_u_t_f_i_l_e_n_a_m_e] [-l] [-s] [-v] [_i_n_f_i_l_e_n_a_m_e] DESCRIPTION _U_u_f_i_l_t_e_r is a "smart" uuencoded file decoder that can optionally dump the file to stdout. If no filename is supplied, input is read from stdin. _U_u_f_i_l_t_e_r automatically ignores lines that do not appear to be part of the uuencoded file. This is particularly useful in uudecoding files that have been concatenated from several email or news postings without stripping off the headers or otherwise editting extraneous content. OPTIONS -f _f_i_l_e_n_a_m_e Dump output to _f_i_l_e_n_a_m_e rather than the name speci- fied in the uuencoded file. -l Lenient mode. This is useful if passed through a mailer that adds trailing spaces. -s Dump output to stdout rather than to the filename indicated in the uuencoded file. -v Verbose mode; talks about what's going on. AUTHOR Jim Frost (jimf@centerline.com) Sun Release 4.1 Last change: 21 October 1993 1 ce.c(G undither.cc8Xzoom.ciLvconfig.coom\.misc.cfp options.cscroot.cisend.cwindow.cxloadimage.4.1/uufilter.c 664 221 144 11561 5463766523 10607 /* uufilter.c: * * "smart" uudecode function that skips junk lines and outputs data to * stdout rather than a filename. * * jim frost 10.21.93 * * 10.27.93 fixed a bug where short uuencoded lines were stripped out * due to a bad "short length" calculation. added -v flag at * the same time. */ #include main(argc, argv) int argc; char **argv; { FILE *inf, *outf; char *infilename = NULL; char *outfilename = NULL; int dump_to_file = 1; /* true if we're outputting to a file */ int stringent = 1; /* true if we're really stringent about data lines */ int verbose = 0; /* true if we're babbling about what we're skipping */ char buf[1024]; int i, len; int phase = 0; unsigned char outchar; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-s")) /* output to stdout */ dump_to_file = 0; else if (!strcmp(argv[i], "-l")) /* lenient mode */ stringent = 0; else if (!strcmp(argv[i], "-f")) { /* output to named file */ dump_to_file = 1; outfilename = argv[++i]; } else if (!strcmp(argv[i], "-v")) /* verbose output */ verbose = 1; else { infilename = argv[i]; break; } } if (infilename == NULL) { inf = stdin; infilename = "stdin"; } else { inf = fopen(infilename, "r"); if (inf == NULL) { perror(infilename); exit(1); } } /* scan for "begin" line */ while (fgets(buf, 1024, inf) != NULL) { if (!strncmp(buf, "begin ", 6)) break; if (verbose) fprintf(stderr, "Ignoring header line: %s\n", buf); } if (feof(inf)) { fprintf(stderr, "No 'begin' line, sorry.\n", infilename); exit(1); } if (dump_to_file) { int mode; /* ignored */ char tmp[1024]; if (!outfilename) { if (sscanf(buf, "begin %o %s", &mode, tmp) != 2) { fprintf(stderr, "%s: Bad format for 'begin' line (can't dump to file)\n", infilename); exit(1); } outfilename = tmp; } fprintf(stderr, "Decoding into file %s\n", outfilename); outf = fopen(outfilename, "w"); if (outf == NULL) { perror(outfilename); exit(1); } } else outf = stdout; for (;;) { char *bp; if (fgets(buf, 1024, inf) == NULL) { fprintf(stderr, "%s: Missing 'end' line.\n", infilename); break; } if (!strncmp(buf, "end", 3)) break; /* end of data */ /* strip off trailing characters */ len = strlen(buf) - 1; while ((buf[len] == '\n') || (buf[len] == '\r')) buf[len--] = '\0'; /* character conversion and "obvious" filtering */ for (; len >= 0; len--) { if ((buf[len] >= 'a') || (buf[len] < ' ')) break; /* garbage character seen */ if (buf[len] == '`') buf[len] = ' '; } if (len >= 0) { if (verbose) fprintf(stderr, "Ignoring garbage line: %s\n", buf); continue; /* line had garbage, ignore it */ } if (buf[0] == '\0') continue; /* line is blank, ignore it */ len = buf[0] - ' '; /* ok, see if the line length looks sane. */ { int line_len = strlen(buf) - 1; int allow_len; /* if the line is shorter than the absolute minimum * allowable then we're sure this is not a valid line. */ allow_len = ((len * 4) / 3) + ((len * 4) % 3); if (line_len < allow_len) { if (verbose) fprintf(stderr, "Ignoring short line: %s\n", buf); continue; } /* if we're being really stringent about the lines we allow * this filters out any lines that are too long, too. note * that this is still fairly lenient; it allows uuencode * programs to pad the line length out to a multiple of * 3 bytes. */ if (stringent) { allow_len = ((len + 2) * 4) / 3; if (line_len > allow_len) { if (verbose) fprintf(stderr, "Ignoring long line: %s\n", buf); continue; } } } /* ok, we have some characters -- process them! */ bp = &buf[1]; phase = 0; while (len > 0) { unsigned char c; c = (unsigned char)*(bp++) - ' '; switch (phase) { case 0: /* 1st 6 bits */ outchar = (c << 2); break; case 1: /* last 2 bits, 1st 4 bits */ outchar |= (c >> 4); fputc(outchar, outf); len--; outchar = (c & 0xf) << 4; break; case 2: /* last 4 bits, 1st 2 bits */ outchar |= (c >> 2); fputc(outchar, outf); len--; outchar = (c & 0x3) << 6; break; case 3: /* last 6 bits */ outchar |= c; fputc(outchar, outf); len--; phase = 0; continue; } phase++; } } /* flush output */ if (outf == stdout) fflush(outf); else fclose(outf); /* suck up the rest of the input file. this avoids "broken pipe" * errors if reading from stdin. */ if (inf == stdin) { while (fgets(buf, 1024, inf) != NULL) if (verbose) fprintf(stderr, "Ignoring trailing line: %s\n", buf); } else fclose(inf); exit(0); } */ if (info.samplesperpixel != 3) { fprintf(stderr, "%s: Can't handle TIFF RGB images with %d samples per pixel, sorry\n", xloadimage.4.1/xloadimagerc 664 221 144 1324 5461577570 11142 # Sample .xloadimagerc file path = /usr/local/images extension = .niff # NIFF image .jpg .jpeg # JPEG image .gif # CompuServe GIF image .sun .csun .msun # sun rasterfile .face # faces project .xwd # X window dump .xpm .pm .xbm .bm # X bitmap .fax # G3 FAX .fbm # fuzzy bitmap .mac # macpaint .pbm .pgm .ppm # PBMPLUS .img # GEM IMG .pcx # PCX image # add uufilter for automatic uudecoding of files ending in .uu or .uue filter = "uufilter -s" .uu .uue cm.Ht imagetypes.cHXimg.c.ch(mac.cg.|+mcidas.c* mc_tables.cpbm.clepcx.cm. pdsuncomp.crle.com>rlelib.csuC sunraster.c vff.cteIvicar.c0Pxloadimage.4.1/copyright.h 664 221 144 2141 5461577404 10733 #ifndef _JIM_COPYRIGHT_ /* * Copyright 1989, 1993 Jim Frost * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. The author makes no representations * about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __SABER__ static char *Copyright= "Copyright 1989, 1993 Jim Frost"; #endif #define _JIM_COPYRIGHT_ #endif cpdither.cessfill.ch halftone.cl-merge.c;reduce.cerg@rotate.ce.cBsmooth.ce.c(G undither.cc8Xzoom.ciLvconfig.coom\.misc.cfp options.cscroot.cisend.cwindow.cend' xloadimage.cc@sampleajpeg xloadimage.4.1/image.h 664 221 144 26030 5464006040 10012 /* image.h: * * portable image type declarations * * jim frost 10.02.89 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include /* ANSI-C stuff */ #if defined(__STDC__) #if !defined(_ArgProto) #define _ArgProto(ARGS) ARGS #endif #include #else /* !__STDC__ */ #if !defined(const) /* "const" is an ANSI thing */ #define const #endif #if !defined(_ArgProto) #define _ArgProto(ARGS) () #endif #endif /* !__STDC__ */ /* handle strings stuff that varies between BSD and ANSI/SYSV */ #if defined(IS_BSD) && !defined(__STDC__) #include #if !defined(strchr) && !defined(index) #define strchr index #endif #if !defined(strrchr) && !defined(rindex) #define strrchr rindex #endif #if !defined(memcpy) && !defined(bcopy) #define memcpy(D,S,L) bcopy((char *)(S),(char *)(D),(L)) #endif #if !defined(memset) && !defined(bzero) /* #define memset(D,V,L) bzero(D,L) */ #endif #else /* !IS_BSD || __STDC__ */ #include #if !defined(index) && !defined(strchr) #define index strchr #endif #if !defined(rindex) && !defined(strrchr) #define rindex strrchr #endif #if !defined(bcopy) && !defined(memcpy) #define bcopy(S,D,L) memcpy((void *)(D),(void *)(S),(L)) #endif #if !defined(bzero) && !defined(memset) #define bzero(D,L) memset((void *)(D),0,(L)) #endif #endif /* !IS_BSD || __STDC__ */ #ifdef VMS #define R_OK 4 #define NO_UNCOMPRESS #endif typedef unsigned long Pixel; /* what X thinks a pixel is */ typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ typedef unsigned char byte; /* byte type */ /* filter/extension pair for user-defined filters */ struct filter { char *extension; /* extension to match */ char *filter; /* filter to invoke */ struct filter *next; }; struct cache { int len; char buf[BUFSIZ]; struct cache *next; }; typedef struct { unsigned int type; /* ZIO file type */ unsigned int nocache; /* true if caching has been disabled */ FILE *stream; /* file input stream */ char *filename; /* filename */ struct cache *data; /* data cache */ struct cache *dataptr; /* ptr to current cache block */ int bufptr; /* ptr within current cache block */ } ZFILE; #define ZSTANDARD 0 /* standard file */ #define ZPIPE 1 /* file is a pipe (ie uncompress) */ #define ZSTDIN 2 /* file is stdin */ typedef struct rgbmap { unsigned int size; /* size of RGB map */ unsigned int used; /* number of colors used in RGB map */ unsigned int compressed; /* image uses colormap fully */ Intensity *red; /* color values in X style */ Intensity *green; Intensity *blue; } RGBMap; /* image structure */ typedef struct { char *title; /* name of image */ unsigned int type; /* type of image */ RGBMap rgb; /* RGB map of image if IRGB type */ unsigned int width; /* width of image in pixels */ unsigned int height; /* height of image in pixels */ unsigned int depth; /* depth of image in bits if IRGB type */ unsigned int pixlen; /* length of pixel if IRGB type */ float gamma; /* gamma of display the image is adjusted for */ byte *data; /* data rounded to full byte for each row */ } Image; #define IBAD 0 /* invalid image (used when freeing) */ #define IBITMAP 1 /* image is a bitmap */ #define IRGB 2 /* image is RGB */ #define ITRUE 3 /* image is true color */ #define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP) #define RGBP(IMAGE) ((IMAGE)->type == IRGB) #define TRUEP(IMAGE) ((IMAGE)->type == ITRUE) #define TRUE_RED(PIXVAL) (((PIXVAL) & 0xff0000) >> 16) #define TRUE_GREEN(PIXVAL) (((PIXVAL) & 0xff00) >> 8) #define TRUE_BLUE(PIXVAL) ((PIXVAL) & 0xff) #define RGB_TO_TRUE(R,G,B) \ (((unsigned int)((R) & 0xff00) << 8) | ((unsigned int)(G) & 0xff00) | \ ((unsigned int)(B) >> 8)) #ifdef NO_INLINE /* only inline 1-byte transfers. this is provided for systems whose C * compilers can't hash the complexity of the inlined functions. */ #define memToVal(PTR,LEN) ((LEN) == 1 ? (unsigned long)(*(PTR)) : \ doMemToVal(PTR,LEN)) #define memToValLSB(PTR,LEN) ((LEN) == 1 ? (unsigned long)(*(PTR)) : \ doMemToValLSB(PTR,LEN)) #define valToMem(VAL,PTR,LEN) ((LEN) == 1 ? \ (unsigned long)(*(PTR) = (byte)(VAL)) : \ doValToMem(VAL,PTR,LEN)) #define valToMemLSB(VAL,PTR,LEN) ((LEN) == 1 ? \ (unsigned long)(*(PTR) = (byte)(VAL)) : \ (int)doValToMemLSB(VAL,PTR,LEN)) #else /* !NO_INLINE */ /* inline these functions for speed. these only work for {len : 1,2,3,4}. */ #define memToVal(PTR,LEN) \ ((LEN) == 1 ? ((unsigned long)(*((byte *)PTR))) : \ ((LEN) == 3 ? ((unsigned long) \ (*(byte *)(PTR) << 16) | \ (*((byte *)(PTR) + 1) << 8) | \ (*((byte *)(PTR) + 2))) : \ ((LEN) == 2 ? ((unsigned long) \ (*(byte *)(PTR) << 8) | \ (*((byte *)(PTR) + 1))) : \ ((unsigned long)((*(byte *)(PTR) << 24) | \ (*((byte *)(PTR) + 1) << 16) | \ (*((byte *)(PTR) + 2) << 8) | \ (*((byte *)(PTR) + 3))))))) #define memToValLSB(PTR,LEN) \ ((LEN) == 1 ? ((unsigned long)(*(byte *)(PTR))) : \ ((LEN) == 3 ? ((unsigned long) \ (*(byte *)(PTR)) | \ (*((byte *)(PTR) + 1) << 8) | \ (*((byte *)(PTR) + 2) << 16)) : \ ((LEN) == 2 ? ((unsigned long) \ (*(byte *)(PTR)) | (*((byte *)(PTR) + 1) << 8)) : \ ((unsigned long)((*(byte *)(PTR)) | \ (*((byte *)(PTR) + 1) << 8) | \ (*((byte *)(PTR) + 2) << 16) | \ (*((byte *)(PTR) + 3) << 24)))))) #define valToMem(VAL,PTR,LEN) \ ((LEN) == 1 ? (*(byte *)(PTR) = ((unsigned int)(VAL) & 0xff)) : \ ((LEN) == 3 ? (((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff))) : \ ((LEN) == 2 ? (((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff))) : \ (((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff000000) >> 24), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*((byte *)(PTR) + 3)) = ((unsigned int)(VAL) & 0xff)))))) #define valToMemLSB(VAL,PTR,LEN) \ ((LEN) == 1 ? (*(byte *)(PTR) = ((unsigned int)(VAL) & 0xff)) : \ ((LEN) == 3 ? (((*(byte *)(PTR) + 2) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff))) : \ ((LEN) == 2 ? (((*((byte *)(PTR) + 1) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff)))) : \ (((*((byte *)(PTR) + 3)) = ((unsigned int)(VAL) & 0xff000000) >> 24), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff)))))) #endif /* !NO_INLINE */ /* SUPPRESS 558 */ /* function declarations */ /* clip.c */ Image *clip _ArgProto((Image *image, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int verbose)); /* bright.c */ void brighten _ArgProto((Image *image, unsigned int percent, unsigned int verbose)); void gammacorrect _ArgProto((Image *image, double disp_gam, unsigned int verbose)); void gray _ArgProto((Image *image, unsigned int verbose)); Image *normalize _ArgProto((Image *image, unsigned int verbose)); /* compress.c */ void compress _ArgProto((Image *image, unsigned int verbose)); /* dither.c */ Image *dither _ArgProto((Image *image, unsigned int verbose)); /* fill.c */ void fill _ArgProto((Image *image, unsigned int fx, unsigned int fy, unsigned int fw, unsigned int fh, Pixel pixval)); /* halftone.c */ Image *halftone _ArgProto((Image *image, unsigned int verbose)); /* imagetypes.c */ void goodImage _ArgProto((Image *image, char *where)); /* merge.c */ Image *merge _ArgProto((Image *dest, Image *src, int atx, int aty, unsigned int verbose)); Image *tile _ArgProto((Image *image, int x, int y, unsigned int width, unsigned int height, unsigned int verbose)); /* misc.c */ void memoryExhausted _ArgProto((void)); char *tail _ArgProto((char *)); void usage _ArgProto((void)); int errorHandler(); char *findstr _ArgProto((char *, char *)); /* new.c */ extern unsigned long DepthToColorsTable[]; unsigned long colorsToDepth(); char *dupString _ArgProto((char *s)); Image *newBitImage _ArgProto((unsigned int width, unsigned int height)); Image *newRGBImage _ArgProto((unsigned int width, unsigned int height, unsigned int depth)); Image *newTrueImage _ArgProto((unsigned int width, unsigned int height)); void freeImage _ArgProto((Image *image)); void freeImageData _ArgProto((Image *image)); void newRGBMapData _ArgProto((RGBMap *rgb, unsigned int size)); void freeRGBMapData _ArgProto((RGBMap *rgb)); byte *lcalloc _ArgProto((unsigned int size)); byte *lmalloc _ArgProto((unsigned int size)); void lfree _ArgProto((byte *area)); #define depthToColors(n) DepthToColorsTable[((n) < 32 ? (n) : 32)] /* reduce.c */ Image *reduce _ArgProto((Image *image, unsigned int n, unsigned int verbose)); Image *expand _ArgProto((Image *image)); Image *flatten _ArgProto((Image *image)); /* rotate.c */ Image *rotate _ArgProto((Image *image, unsigned int degrees, unsigned int verbose)); /* smooth.c */ Image *smooth _ArgProto((Image *image, int iterations, unsigned int verbose)); /* undither.c */ Image *undither _ArgProto((Image *oimage, unsigned int verbose)); /* doMemToVal and doMemToValLSB used to be void type but some compilers * (particularly the 4.1.1 SunOS compiler) couldn't handle the * (void)(thing= value) conversion used in the macros. */ /* value.c */ unsigned long doMemToVal _ArgProto((byte *p, unsigned int len)); unsigned long doValToMem _ArgProto((unsigned long val, byte *p, unsigned int len)); unsigned long doMemToValLSB _ArgProto((byte *p, unsigned int len)); unsigned long doValToMemLSB _ArgProto((unsigned long val, byte *p, unsigned int len)); void flipBits _ArgProto((byte *p, unsigned int len)); /* zio.c */ ZFILE *zopen _ArgProto((char *name)); int zread _ArgProto((ZFILE *zf, byte *buf, unsigned int len)); int zgetc _ArgProto((ZFILE *zf)); char *zgets _ArgProto((byte *buf, unsigned int size, ZFILE *zf)); void zclose _ArgProto((ZFILE *zf)); void znocache _ArgProto((ZFILE *zf)); void zreset _ArgProto((char *filename)); /* zoom.c */ Image *zoom _ArgProto((Image *image, unsigned int x, unsigned int y, unsigned int verbose)); /* this returns the (approximate) intensity of an RGB triple */ #define colorIntensity(R,G,B) \ (RedIntensity[(R) >> 8] + GreenIntensity[(G) >> 8] + BlueIntensity[(B) >> 8]) extern unsigned short RedIntensity[]; extern unsigned short GreenIntensity[]; extern unsigned short BlueIntensity[]; #ifdef DEBUG extern int _Xdebug; #define debug(ARGS) if (_Xdebug) printf ARGS #else /* !DEBUG */ #define debug(ARGS) #endif /* !DEBUG */ */ unsigned int depth; /* depth of image in bits if IRGB type */ unsigned int pixlen; /* length of pixel if IRGB type */ float gamma; /* gamma of display the image is adjusted for */ byte *data; /* data rounded to full byte for each row */ } Image; #define IBAD 0 /* invalid image (used when freeing) */ #define IBITMAP 1 /* image is a bitmap */ #define IRGB 2 /* image is RGB */ #define ITRUE 3 /* image is true color */ #define BITMAPP(IMAGE) ((IMAGE)->txloadimage.4.1/cmuwmraster.h 664 221 144 472 5461577404 11261 /* cmuwmraster.h * * this describes the header for ITC (CMU WM) raster files. It is * essentially a byte reversed Sun raster, 1 plane, no encoding. */ #include "copyright.h" struct cmuwm_header { byte magic[4]; byte width[4]; byte height[4]; byte depth[2]; }; #define CMUWM_MAGIC 0xf10040bb s.hm.(=rle.hx.<D sunraster.hLVxwd.hhdE tgncpyrght.hExk options.hx patchlevel xloadimage.hrnew.cxloadimage.4.1/fbm.h 664 221 144 3575 5461577405 7504 /***************************************************************** * fbm.h: FBM Library 0.9 (Beta Test) 07-Mar-89 Michael Mauldin * * Copyright (C) 1989 by Michael Mauldin. Permission is granted to * use this file in whole or in part provided that you do not sell it * for profit and that this copyright notice is retained unchanged. * * fbm.h: Fuzzy Bitmap Definition * *****************************************************************/ typedef unsigned char BYTE; /* 8 bits unsigned */ # define FBM_MAX_TITLE 80 /* For title and credits */ # define BIG 1 /* msb first byte order */ # define LITTLE 0 /* lsb first byte order */ #define FBMIN_SUCCESS 0 /* success */ #define FBMIN_ERR_BAD_SD -1 /* bad screen descriptor */ #define FBMIN_ERR_BAD_SIG -2 /* bad signature */ #define FBMIN_ERR_EOD -3 /* unexpected end of raster data */ #define FBMIN_ERR_EOF -4 /* unexpected end of input stream */ #define FBMIN_ERR_FAO -5 /* file already open */ #define FBMIN_ERR_IAO -6 /* image already open */ #define FBMIN_ERR_NFO -7 /* no file open */ #define FBMIN_ERR_NIO -8 /* no image open */ # define FBM_MAGIC "%bitmap" /* FBM bitmap headers in files (null terminated 12 character ascii strings) */ typedef struct fbm_filehdr_struct { char magic[8]; /* 2 bytes FBM_MAGIC number */ char cols[8]; /* Width in pixels */ char rows[8]; /* Height in pixels */ char planes[8]; /* Depth (1 for B+W, 3 for RGB) */ char bits[8]; /* Bits per pixel */ char physbits[8]; /* Bits to store each pixel */ char rowlen[12]; /* Length of a row in bytes */ char plnlen[12]; /* Length of a plane in bytes */ char clrlen[12]; /* Length of colormap in bytes */ char aspect[12]; /* ratio of Y to X of one pixel */ char title[FBM_MAX_TITLE]; /* Null terminated title */ char credits[FBM_MAX_TITLE]; /* Null terminated credits */ } FBMFILEHDR; BlueIntensity[]; #ifdef DEBUG extern int _Xdebug; #define debug(ARGS) if (_Xdebug) printf ARGS #else /* !DEBUG */ #define debug(ARxloadimage.4.1/gif.h 664 221 144 3734 5461577405 7502 /* gif.h: * * gifin.h * kirk johnson * november 1989 * external interface to gifin.c * * Copyright 1989 Kirk L. Johnson (see the included file * "kljcpyrght.h" for complete copyright information) */ /* * gifin return codes */ #define GIFIN_SUCCESS 0 /* success */ #define GIFIN_DONE 1 /* no more images */ #define GIFIN_ERR_BAD_SD -1 /* bad screen descriptor */ #define GIFIN_ERR_BAD_SEP -2 /* bad image separator */ #define GIFIN_ERR_BAD_SIG -3 /* bad signature */ #define GIFIN_ERR_EOD -4 /* unexpected end of raster data */ #define GIFIN_ERR_EOF -5 /* unexpected end of input stream */ #define GIFIN_ERR_FAO -6 /* file already open */ #define GIFIN_ERR_IAO -7 /* image already open */ #define GIFIN_ERR_NFO -8 /* no file open */ #define GIFIN_ERR_NIO -9 /* no image open */ /* * colormap indices */ #define GIF_RED 0 #define GIF_GRN 1 #define GIF_BLU 2 /* * typedef BYTE for convenience */ typedef unsigned char BYTE; static int gifin_open_file(); static int gifin_open_image(); static int gifin_get_pixel(); #if 0 static int gifin_close_image(); #endif static int gifin_close_file(); static int gifin_load_cmap(); static int gifin_skip_extension(); static int gifin_read_data_block(); static int gifin_push_string(); static int gifin_add_string(); static int gifin_fatal(); /* #defines, typedefs, and such */ #define GIF_SIG "GIF87a" #define GIF_SIG_89 "GIF89a" #define GIF_SIG_LEN 6 /* GIF signature length */ #define GIF_SD_SIZE 7 /* GIF screen descriptor size */ #define GIF_ID_SIZE 9 /* GIF image descriptor size */ #define GIF_SEPARATOR ',' /* GIF image separator */ #define GIF_EXTENSION '!' /* GIF extension block marker */ #define GIF_TERMINATOR ';' /* GIF terminator */ #define STAB_SIZE 4096 /* string table size */ #define PSTK_SIZE 4096 /* pixel stack size */ #define NULL_CODE -1 /* string table null code */ D_SIG -3 /* bad signature */ #defxloadimage.4.1/imagetypes.h 664 221 144 6273 5463502300 11065 /* imagetypes.h: * * supported image types and the imagetypes array declaration. when you * add a new image type, only the makefile and this header need to be * changed. * * jim frost 10.15.89 */ Image *niffLoad(); Image *facesLoad(); Image *pbmLoad(); Image *sunRasterLoad(); Image *gifLoad(); Image *rleLoad(); Image *xwdLoad(); Image *vffLoad(); Image *xbitmapLoad(); Image *xpixmapLoad(); Image *fbmLoad(); Image *pcxLoad(); Image *imgLoad(); Image *macLoad(); Image *cmuwmLoad(); Image *mcidasLoad(); #if 0 Image *pdsLoad(); #else Image *vicarLoad(); #endif #ifdef HAS_JPEG Image *jpegLoad(); #endif #ifdef HAS_TIFF Image *tiffLoad(); #endif int niffIdent(); int facesIdent(); int pbmIdent(); int sunRasterIdent(); int gifIdent(); int rleIdent(); int xwdIdent(); int vffIdent(); int xbitmapIdent(); int xpixmapIdent(); int fbmIdent(); int pcxIdent(); int imgIdent(); int macIdent(); int cmuwmIdent(); int mcidasIdent(); #if 0 int pdsIdent(); #else int vicarIdent(); #endif #ifdef HAS_JPEG int jpegIdent(); #endif #ifdef HAS_TIFF int tiffIdent(); #endif void niffDump(); #ifdef HAS_JPEG void jpegDump(); #endif #ifdef HAS_TIFF void tiffDump(); #endif void pbmDump(); /* some of these are order-dependent */ struct { int (*identifier)(); /* print out image info if this kind of image */ Image *(*loader)(); /* load image if this kind of image */ void (*dumper)(); /* dump image of this kind */ char *type; /* image type name */ char *name; /* name of this image format */ } ImageTypes[] = { niffIdent, niffLoad, niffDump, "niff", "Native Image File Format (NIFF)", sunRasterIdent, sunRasterLoad, NULL, "sunraster", "Sun Rasterfile", gifIdent, gifLoad, NULL, "gif", "GIF Image", #ifdef HAS_JPEG jpegIdent, jpegLoad, jpegDump, "jpeg", "JFIF-style JPEG Image", #endif #ifdef HAS_TIFF tiffIdent, tiffLoad, tiffDump, "tiff", "TIFF image", #endif fbmIdent, fbmLoad, NULL, "fbm", "FBM Image", cmuwmIdent, cmuwmLoad, NULL, "cmuraster", "CMU WM Raster", pbmIdent, pbmLoad, pbmDump, "pbm", "Portable Bit Map (PBM, PGM, PPM)", facesIdent, facesLoad, NULL, "faces", "Faces Project", rleIdent, rleLoad, NULL, "rle", "Utah RLE Image", xwdIdent, xwdLoad, NULL, "xwd", "X Window Dump", vffIdent, vffLoad, NULL, "vff", "Sun Visualization File Format", mcidasIdent, mcidasLoad, NULL, "mcidas", "McIDAS areafile", #if 0 pdsIdent, pdsLoad, NULL, "pds", "PDS/VICAR Image", #else vicarIdent, vicarLoad, NULL, "vicar", "VICAR Image", #endif pcxIdent, pcxLoad, NULL, "pcx", "PC Paintbrush Image", imgIdent, imgLoad, NULL, "gem", "GEM Bit Image", macIdent, macLoad, NULL, "macpaint", "MacPaint Image", xpixmapIdent, xpixmapLoad, NULL, "xpm", "X Pixmap", xbitmapIdent, xbitmapLoad, NULL, "xbm", "X Bitmap", NULL, NULL, NULL, NULL, NULL }; 1 ? (unsigned long)(*(PTR)) : \ doMemToValLSB(PTR,LEN)) #define valToMem(VAL,PTR,LEN) ((LEN) == 1 ? \ (unsigned long)(*(PTR) = (byte)(VAL)) : \ doValToMem(VAL,PTR,LEN)) #define valToMemLSB(VAL,PTR,LEN) ((LEN) == 1 ? \ (unsigned long)(*(PTR) = (byte)(VAL)) : \ (int)doValToMemLSB(VAL,PTR,LExloadimage.4.1/img.h 664 221 144 4261 5461577406 7506 /* ** img.h - structures/definitions for GEM Bit Image format conversion ** ** Tim Northrup ** ** Version 0.1 -- 4/25/91 -- Initial cut ** ** Copyright (C) 1991 Tim Northrup ** (see file "tgncpyrght.h" for complete copyright information) */ #ifndef GEM_H #define GEM_H /* ** Standard IMG Header Structure (8 words long) ** ** May be followed by implementation-dependent information, so the ** value of hlen should be checked on input. */ typedef struct { short vers, /* image version number */ hlen, /* header length (in words) */ colors, /* number of color planes (1=mono) */ patlen, /* pattern length (for encoding) */ pixw, pixh, /* pixel dimensions (in microns) */ llen, lines; /* pixels/line and number of lines */ } IMG_Header; /* ** Header record values used when creating an IMG file */ #define DEF_VERSION 1 /* default version number (on output) */ #define DEF_HLEN 8 /* always standard header */ #define DEF_COLORS 1 /* always B/W pics */ #define DEF_PATLEN 1 /* easiest pattern size */ #define DEF_PIXW 85 /* just a guess on this one */ #define DEF_PIXH 85 /* assumed 1:1 aspect ratio */ /* ** Program limits and other constants */ #define MAX_SCANLINE 1024 /* max bytes for 1 scanline */ #define MAX_SLREPEAT 255 /* max repititions of scanline */ #define MAX_PATREPEAT 255 /* max repititions of pattern */ #define MAX_BYTEREPEAT 127 /* max repititions of byte value */ #define MAX_LITERAL 255 /* max literal length allowed */ #define BYTE_FLAG 0x00 /* first byte 0 the ... */ #define BYTE_SLREPEAT 0x00 /* second 0 means scanline repeat */ #define BYTE_SLFLAG 0xFF /* always followed by FF (?) */ #define BYTE_LITERAL 0x80 /* char 80h - flag literal string */ #define BYTE_BLACK 0xFF /* byte is all 1's */ #define BIT_BLACK 1 /* single black bit */ #define BYTE_WHITE 0x00 /* byte is all 0's */ #define BIT_WHITE 0 /* single white bit */ #define RUN_BLACK 0x80 /* bit flag for run of all 0's or 1's */ #define RUN_WHITE 0x00 #define RUN_LENGTH(X) ((X) & 0x7F) #define RUN_COLOR(X) ((((X) & RUN_BLACK) == RUN_BLACK)?BIT_BLACK:BIT_WHITE) #define PIXEL_COLOR(X) ((((X) & 0x01) == 1)?BIT_BLACK:BIT_WHITE) #endif /* GEM_H */ (PBM, PGM, PPM)", facesIdent, facesLoad, NULL, "faces", "Faces Project", rleIdent, rleLoad, NULL, "rle", "Utah RLE Image", xwdIdent, xwdLoad, NULL, "xwd", "X Window Dump", vffIdent, vffLoad, NULL, "vff", "Sun Visualization File Formxloadimage.4.1/kljcpyrght.h 664 221 144 2144 5461577406 11111 #ifndef _KLJ_COPYRIGHT_ /**** Copyright 1989, 1990 Kirk L. Johnson Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****/ #ifndef __SABER__ static char *KLJCopyright = "Copyright 1989, 1990 Kirk L. Johnson"; #endif #define _KLJ_COPYRIGHT_ #endif (G undither.c(8Xzoom.ccLvconfig.cL\.misc.cmp options.cproot.ccsend.ciwindow.c' xloadimage.c'@samplejpegea tiffYTEREPEAT 127 /* max repititions of byte value */ #define MAX_LITERAL 255 /* max literal length allowed */ #define BYTE_FLAG 0x00 /* first byte xloadimage.4.1/mac.h 664 221 144 2312 5461577407 7466 /**************************************************************** * mac.h: * * adapted from code by Patrick Naughton (naughton@sun.soe.clarkson.edu) * * macin.h * Mark Majhor * August 1990 * * routines for reading MAC files * * Copyright 1990 Mark Majhor (see the included file * "mrmcpyrght.h" for complete copyright information) * ****************************************************************/ # define MAC_MAGIC 0x0 typedef unsigned char BYTE; /* 8 bits unsigned */ /* * macin return codes */ #define MACIN_SUCCESS 0 /* success */ #define MACIN_ERR_BAD_SD -1 /* bad screen descriptor */ #define MACIN_ERR_BAD_SIG -2 /* bad signature */ #define MACIN_ERR_EOD -3 /* unexpected end of raster data */ #define MACIN_ERR_EOF -4 /* unexpected end of input stream */ #define MACIN_ERR_FAO -5 /* file already open */ #define MACIN_ERR_IAO -6 /* image already open */ #define MACIN_ERR_NFO -7 /* no file open */ #define MACIN_ERR_NIO -8 /* no image open */ static int macin_open_image(); static int macin_close_file(); #if 0 static int macin_fatal(); #endif #define MAC_HDR_LEN 512 #define ADD_HDR_LEN 128 #define MAX_LINES 720 #define BYTES_LINE 72 isend.cwindow.cend' xloadimage.c@sampleajpeg tiffjpegea tiffYTEREPEAT 127 /* max repititions of byte value */ #define MAX_LITERAL 255 /* max literal length allowed */ #define BYTE_FLAG 0x00 /* first byte xloadimage.4.1/mcidas.h 664 221 144 4123 5461577407 10170 /* mcidas.h */ /* Argh, looks like the numbers are in vax byte order */ #define TYPELEN 4 /* Short strings used as identifiers */ #define COMMENTLEN 32 /* longer strings */ /* * McIdas AREA DIRECTORY, based on documentation dated 5/87 by R. Dengal */ struct area_dir { /* 1 */ unsigned long status ; /* 2 */ unsigned long type ; /* 3 */ unsigned long satid ; /* 4 */ unsigned long ndate ; /* YYDDD */ /* 5 */ unsigned long ntime ; /* HHMMSS */ /* 6 */ unsigned long lcor ; /* 7 */ unsigned long ecor ; /* 8 */ unsigned long zcor ; /* 9 */ unsigned long lsiz ; /* 10 */ unsigned long esiz ; /* 11 */ unsigned long zsiz ; /* 12 */ unsigned long lres ; /* 13 */ unsigned long eres ; /* 14 */ unsigned long bands ; /* 15 */ unsigned long yzprefix ; /* 16 */ unsigned long projnum ; /* 17 */ unsigned long cdate ; /* 18 */ unsigned long ctime ; /* 19 */ unsigned long filtmap ; /* 20 */ unsigned long imageid ; /* 21 */ unsigned long resvid[4] ; #define AREA_COMMENTS 24 /* 25 */ char comments[COMMENTLEN] ; #define AREA_CALKEY 32 /* 33 */ unsigned long calkey ; /* 34 */ unsigned long navkey ; /* 35 */ unsigned long navkey2 ; /* 36 */ unsigned long lprefix ; /* 37 */ unsigned long pdl[8] ; /* 45 */ unsigned long band8 ; /* 46 */ unsigned long idate ; /* 47 */ unsigned long itime ; /* 48 */ unsigned long startscan ; /* 49 */ unsigned long doclen ; /* 50 */ unsigned long callen ; /* 51 */ unsigned long levlen ; #define AREA_STYPE 51 /* 52 */ char stype[TYPELEN] ; /* 53 */ char ctype[TYPELEN] ; /* 54 */ unsigned long reserved[11] ; } ; /* * McIdas NAVIGATION CODICIL, based on documentation dated 5/87 by D. Santek * Only type 'GOES' used here currently */ struct navigation { /* 1 */ char type[TYPELEN] ; #define NAV_DATA 1 /* 2 */ unsigned long iddate ; /* 3 */ unsigned long itime ; /* 4 */ unsigned long fill[37] ; /* expand this later, if needed */ #define NAV_RESERVED 40 /* 41 */ unsigned long reserved[80] ; /* 121 */ char memo[COMMENTLEN] ; } ; struct mc_area { struct area_dir *dir ; struct navigation *nav ; unsigned char *image ; unsigned char *priv ; /* conveninence pointer */ } ; T_WHITE) #define PIXEL_COLOR(X) ((((X) & 0x01) == 1)?BIT_BLACK:BIT_WHITE) #endif /* GEM_H */ (PBM, PGM, PPM)", facesIdent, facesLoad, NULL, "faces", "Faces Project", rleIdent, rleLoad, NULL, "rle", "Utah RLE Image", xwdIdent, xwdLoad, NULL, "xwd", "X Window Dump", vffIdent, vffLoad, NULL, "vff", "Sun Visualization File Formxloadimage.4.1/mit.cpyrght 664 221 144 2445 5461577442 10756 #ifndef _MIT_COPYRIGHT_ /* * Copyright 1989 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __SABER__ static char *MitCopyright= "Copyright 1989 Massachusetts Institute of Technology"; #endif #define _MIT_COPYRIGHT_ #endif and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the softwarexloadimage.4.1/mrmcpyrght.h 664 221 144 2120 5461577407 11117 #ifndef _MRM_COPYRIGHT_ /**** Copyright 1990 Mark Majhor Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****/ #ifndef __SABER__ static char *MRMCopyright = "Copyright 1990 Mark Majhor"; #endif #define _MRM_COPYRIGHT_ #endif misc.ccp options.ccroot.c.send.ctwindow.cct' xloadimage.c@samplecjpegamp tiffpegamp tiffpegng startscan ; /* 49 */ unsigned long doclen ; /* 50 */ unsigned long callen ; /* 51 */ unsigned long levlen ; #define AREA_STYPE 51 /* 52 */ char stype[TYPELEN] ; /* 53 */ char ctype[TYPELEN] ; /* 54 */ unsigned long rexloadimage.4.1/niff.h 664 221 144 3163 5461577407 7655 /* niff.h: * * header information for xloadimage's native image file format (NIFF), * version 1. * * jimf 10.29.91 * * this is in the public domain */ #define NIFF_MAGIC 0x4e494646 /* "NIFF" */ #define NIFF_VERSION 1 /* this version */ /* types of image data */ #define NIFF_BITMAP 1 #define NIFF_RGB 2 #define NIFF_TRUE 3 /* colormap entry */ struct niff_cmap { char red[2]; char green[2]; char blue[2]; }; struct niff_header { char magic[4]; /* NIFF magic number */ char version[4]; /* NIFF version */ char width[4]; /* image dimensions */ char height[4]; char depth[4]; /* image depth in bits (true depth, not rounded) */ char type; /* image type */ char cmap_size[4]; /* size of colormap; zero NIFF_TRUE */ char title_len[4]; /* length of image title */ /* title */ /* cmap */ /* image data */ }; /* the image title follows the header unless title_len is zero. * * the image colormap follows the title unless the image is NIFF_TRUE * (there must always be at least one cmap entry for NIFF_BITMAP and * NIFF_RGB images). * * the image data follows the cmap data. * * NIFF_BITMAP data is padded to 8-bits, the highest-order bit is the * lowest bitmap pixel. * * NIFF_RGB data is padded to 8-bits per pixel, highest-order byte first. * the number of bytes per pixel is determined by cmap_size (calculate * bits-per-pixel using cmap_size and round up to an 8-bit boundary). * * NIFF_TRUE data is always 3-bytes per pixel - red followed by green * followed by blue, 8 bits each. depth must be 24 and cmap_size must be * zero. */ ES' used here currently */ struct navigation { /* 1 */ char type[TYPELEN] ; #define NAV_DATA 1 /* 2 */ unsigned long iddate ; /* 3 */ unsigned long itime ; /* 4 */ unsigned long fill[37] ; /* expand this later, if needed */ #define NAV_RESERVED 40 /* 41 */ unsigned long reserved[80] ; /* 121 */ char memo[COMMENTLEN] ; } ; struct mc_area { struct area_dir *dir ; struct navigation *nxloadimage.4.1/pbm.h 664 221 144 303 5461577410 7454 /* pbm.h: * * PBM header file * * jim frost 10.15.89 */ typedef struct { unsigned char width[2]; unsigned char height[2]; } PBMCompact; #define PM_SCALE(a, b, c) (long)((a) * (c))/(b) vel xloadimage.hrnew.cEniff.caHvalue.c3zio.cc  cmuwmraster.c faces.c fbm.cc0gif.cHt imagetypes.ctXimg.cm.h(mac.cyp|+mcidas.c|* mc_tables.cxloadimage.4.1/pcx.h 664 221 144 2616 5461577410 7521 /* pcx.h: * * PCX header file * * Eckhard R"uggeberg 15.10.91 */ typedef struct { byte Zred; byte Zgreen; byte Zblue; } PCXcolor; typedef struct { byte Zid; /* Id byte : 0x0a = ZSoft Z */ byte Zver; /* Version : 0 = 2.5 2 = 2.8 w palette 3 = 2.8 w/o pal. 5 = 3.0 */ byte Zenc; /* Encoding : 0 = uncompressed, 1 = compressed */ byte Zbpp; /* Bits per pixel per plane, recommended only 1 or 8 */ byte Zxminlo; byte Zxminhi; /* left Border Pixel coord. */ byte Zyminlo; byte Zyminhi; /* upper Border Pixel coord. */ byte Zxmaxlo; byte Zxmaxhi; /* right Border Pixel coord. */ byte Zymaxlo; byte Zymaxhi; /* lower Border Pixel coord. */ short Zhres; /* horiz. resolution, ignored */ short Zvres; /* vert. resolution, ignored */ PCXcolor Zcmap [16]; /* Colormap for 16-color pict. */ byte Zreserved; byte Znplanes; /* # of planes, recommended 1,4 */ byte Zbprlo; byte Zbprhi; /* bytes per row (always even) */ short Zpalinfo; /* Palette info, ignored */ byte Zfiller[58]; /* reserved Filler = 0 */ } PCXHeader; static PCXHeader *PCXH; /* To avoid a parameter for all */ /* procedures */ #define Word(LO,HI) (HI << 8) + LO /* to swap bytes in a word */ #define PCX_MAGIC 0x0a /* first byte in a PCX file */ #define PCX_MAPSTART 0x0c /* Start of appended colormap */ #define PCXHsize 128 /* Size of PCX Header */ * bits-per-pixel using cmap_size and round up to an 8-bit boundary). * * NIFF_TRUE data is always 3-bytes per pxloadimage.4.1/pds.h 664 221 144 127 5461577410 7470 #define PDSFIXED (1) #define PDSVARIABLE (2) #define PDSTRASH (-1) #define VICAR (3) dE tgncpyrght.hExk options.hx patchlevel xloadimage.hrnew.cniff.cHvalue.c3zio.cc  cmuwmraster.c faces.c fbm.cc0gif.ccHt imagetypes.ctXimg.cth(mac.ct|+mcidas.c|* mc_tables.cpbm.ccpcx.ccxloadimage.4.1/rle.h 664 221 144 12027 5461577410 7526 /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * svfb_global.h - externally visible variables for svfb. * * Author: Todd W. Fuqua * Computer Science Dept. * University of Utah * Date: Sun Jul 29 1984 * Copyright (c) 1984 Todd W. Fuqua * * Added optimised dither square size globals * 88/07/13 Graeme W. Gill */ enum sv_dispatch { RUN_DISPATCH }; /* some compilers have problems converting unsigned bytes to float */ #define BYTEBUG /* On BIGENDIAN machines swap the bytes. Everything but vax's and * pdp-11's (not sure if it's pdp11 or PDP11 ??) * are considered BIGENDIAN machines. */ #define SWAB(val) (val= memToValLSB((byte *)&val, sizeof(val))) /* **************************************************************** * TAG( rle_pixel rle_map ) * * Typedef for 8-bit (or less) pixel data. * * Typedef for 16-bit color map data. */ typedef unsigned char rle_pixel; typedef unsigned short rle_map; /* * Defines for traditional channel numbers */ #define SV_RED 0 /* red channel traditionally here */ #define SV_GREEN 1 /* green channel traditionally here */ #define SV_BLUE 2 /* blue channel traditionally here */ #define SV_ALPHA -1 /* Alpha channel here */ /* * Return values from rle_get_setup */ #define RLE_SUCCESS 0 #define RLE_NOT_RLE -1 #define RLE_NO_SPACE -2 #define RLE_EMPTY -3 #define RLE_EOF -4 /* * TAG( sv_globals ) * * Definition of "globals" structure used by RLE routines */ extern struct sv_globals { enum sv_dispatch sv_dispatch; /* type of file to create */ int sv_ncolors, /* number of color channels */ * sv_bg_color, /* pointer to bg color vector */ sv_alpha, /* if !0, save alpha channel */ sv_background, /* (background) 0->just save pixels, */ /* 1->overlay, 2->clear to bg first */ sv_xmin, /* lower X bound (left) */ sv_xmax, /* upper X bound (right) */ sv_ymin, /* lower Y bound (bottom) */ sv_ymax, /* upper Y bound (top) */ sv_ncmap, /* number of color channels in color map */ /* map only saved if != 0 */ sv_cmaplen; /* log2 of color map length */ rle_map * sv_cmap; /* pointer to color map array */ char ** sv_comments; /* pointer to array of pointers to comments */ ZFILE * svfb_fd; /* output file */ /* * Bit map of channels to read/save. Indexed by (channel mod 256). * Alpha channel sets bit 255. * * Indexing (0 <= c <= 255): * sv_bits[c/8] & (1 << (c%8)) */ #define SV_SET_BIT(glob,bit) \ ((glob).sv_bits[((bit)&0xff)/8] |= (1<<((bit)&0x7))) #define SV_CLR_BIT(glob,bit) \ ((glob).sv_bits[((bit)&0xff)/8] &= ~(1<<((bit)&0x7))) #define SV_BIT(glob,bit) \ ((glob).sv_bits[((bit)&0xff)/8] & (1<<((bit)&0x7))) char sv_bits[256/8]; /* * Local storage for rle_getrow & sv_putrow. * rle_getrow has * scan_y int current Y scanline * vert_skip int number of lines to skip * sv_putrow has * nblank int number of blank lines * brun short(*)[2] Array of background runs. * fileptr long Position in output file. */ union { struct { int scan_y, vert_skip; char is_eof, /* Set when EOF or EofOp encountered */ is_seek; /* If true, can seek input file */ } get; struct { int nblank; short (*brun)[2]; long fileptr; } put; } sv_private; } sv_globals; /* * buildmap - build a more usable colormap from data in globals struct. */ extern rle_pixel ** buildmap(); /* ( globals, minmap, gamma ) * struct sv_globals * globals; * int minmap; * double gamma; */ /* * rle_getcom - get a specific comment from the image comments. */ extern char * rle_getcom(); /* ( name, globals ) * char * name; * struct sv_globals * globals; */ /* * rle_putcom - put (or replace) a comment into the image comments. */ extern char * rle_putcom(); /* ( value, globals ) * char * value; * struct sv_globals * globals; */ /* * rle_delcom - delete a specific comment from the image comments. */ extern char * rle_delcom(); /* ( name, globals ) * char * name; * struct sv_globals * globals; */ /* * dither globals */ extern int dith_levels; /* target effective number of levels, default = 128 */ extern int dith_np2; /* set non-zero to use non-power_of_2 matrix size */ extern int dith_size; /* effective size of the dither matrix chosen */ = ((unsigned int)(VAL) & 0xff000000) >> 24), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*((byte *)(PTR) + 3)) = ((unsigned int)(VAL) & 0xff)))))) #define valToMemLSB(VAL,PTR,LEN) \ ((LEN) == 1 ? (*(byte *)(PTR) = ((unsigned int)(VAL) & 0xff)) : \ ((LEN) == 3 ? (((*(byte *)(PTR) + 2) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsignedxloadimage.4.1/sunraster.h 664 221 144 3431 5461577412 10753 /* sunraster.h * * this describes the header for Sun rasterfiles. if you have SunOS, a * better description is in /usr/include/rasterfile.h. this is used * instead to improve portability and to avoid distribution problems. * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" struct rheader { unsigned char magic[4]; /* magic number */ unsigned char width[4]; /* width of image in pixels */ unsigned char height[4]; /* height of image in pixels */ unsigned char depth[4]; /* depth of each pixel */ unsigned char length[4]; /* length of the image in bytes */ unsigned char type[4]; /* format of file */ unsigned char maptype[4]; /* type of colormap */ unsigned char maplen[4]; /* length of colormap in bytes */ }; /* following the header is the colormap (unless maplen is zero) then * the image. each row of the image is rounded to 2 bytes. */ #define RMAGICNUMBER 0x59a66a95 /* magic number of this file type */ /* these are the possible file formats */ #define ROLD 0 /* old format, see /usr/include/rasterfile.h */ #define RSTANDARD 1 /* standard format */ #define RRLENCODED 2 /* run length encoding to compress the image */ #define RRGB 3 /* RGB-format instead of BGR in 24 or 32-bit mode */ #define RTIFF 4 /* TIFF <-> rasterfile */ #define RIFF 5 /* IFF (TAAC) <-> rasterfile */ /* these are the possible colormap types. if it's in RGB format, * the map is made up of three byte arrays (red, green, then blue) * that are each 1/3 of the colormap length. */ #define RNOMAP 0 /* no colormap follows the header */ #define RRGBMAP 1 /* rgb colormap */ #define RRAWMAP 2 /* raw colormap; good luck */ #define RESC 128 /* run-length encoding escape character */ ??) * are considered BIGENDIAN machines. */ #define SWAB(val) (val= memToValLSB((byte *)&val, sizeof(val))) /* **************************************************************** * TAG( rle_pixel rle_map ) * * Typedef for 8-bixloadimage.4.1/xwd.h 664 221 144 6770 5461577414 7542 /* xwd.h: * * portable-ized xwd file information. they could have made this easier. * * jim frost 07.24.90 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #define XWD_VERSION 7 /* XWD version we support */ typedef struct { byte header_size[4]; /* Size of the entire file header (bytes). */ byte file_version[4]; /* XWD_FILE_VERSION */ byte pixmap_format[4]; /* Pixmap format */ byte pixmap_depth[4]; /* Pixmap depth */ byte pixmap_width[4]; /* Pixmap width */ byte pixmap_height[4]; /* Pixmap height */ byte xoffset[4]; /* Bitmap x offset */ byte byte_order[4]; /* MSBFirst, LSBFirst */ byte bitmap_unit[4]; /* Bitmap unit */ byte bitmap_bit_order[4]; /* MSBFirst, LSBFirst */ byte bitmap_pad[4]; /* Bitmap scanline pad */ byte bits_per_pixel[4]; /* Bits per pixel */ byte bytes_per_line[4]; /* Bytes per scanline */ byte visual_class[4]; /* Class of colormap */ byte red_mask[4]; /* Z red mask */ byte green_mask[4]; /* Z green mask */ byte blue_mask[4]; /* Z blue mask */ byte bits_per_rgb[4]; /* Log2 of distinct color values */ byte colormap_entries[4]; /* Number of entries in colormap */ byte ncolors[4]; /* Number of Color structures */ byte window_width[4]; /* Window width */ byte window_height[4]; /* Window height */ byte window_x[4]; /* Window upper left X coordinate */ byte window_y[4]; /* Window upper left Y coordinate */ byte window_bdrwidth[4]; /* Window border width */ } GenericXWDHeader; typedef struct { unsigned int header_size; /* Size of the entire file header (bytes). */ unsigned int file_version; /* XWD_FILE_VERSION */ unsigned int pixmap_format; /* Pixmap format */ unsigned int pixmap_depth; /* Pixmap depth */ unsigned int pixmap_width; /* Pixmap width */ unsigned int pixmap_height; /* Pixmap height */ unsigned int xoffset; /* Bitmap x offset */ unsigned int byte_order; /* MSBFirst, LSBFirst */ unsigned int bitmap_unit; /* Bitmap unit */ unsigned int bitmap_bit_order; /* MSBFirst, LSBFirst */ unsigned int bitmap_pad; /* Bitmap scanline pad */ unsigned int bits_per_pixel; /* Bits per pixel */ unsigned int bytes_per_line; /* Bytes per scanline */ unsigned int visual_class; /* Class of colormap */ /*unsigned int red_mask;*/ /* Z red mask */ /*unsigned int green_mask;*/ /* Z green mask */ /*unsigned int blue_mask;*/ /* Z blue mask */ /*unsigned int bits_per_rgb;*/ /* Log2 of distinct color values */ unsigned int colormap_entries; /* Number of entries in colormap */ unsigned int ncolors; /* Number of Color structures */ /*unsigned int window_width;*/ /* Window width */ /*unsigned int window_height;*/ /* Window height */ /*unsigned int window_x;*/ /* Window upper left X coordinate */ /*unsigned int window_y;*/ /* Window upper left Y coordinate */ /*unsigned int window_bdrwidth;*//* Window border width */ } XWDHeader; typedef struct { byte pixel[4]; /* pixel value for this color */ byte red[2]; /* red intensity */ byte green[2]; /* green intensity */ byte blue[2]; /* blue intensity */ byte flags; /* XColor flags (ignored) */ byte pad; } XWDColor; #define NOT_XWD 0 /* definitely not an XWD file */ #define XWD_MSB 1 /* looks like XWD file created on MSBFirst machine */ #define XWD_LSB 2 /* looks like XWD file created on LSBFirst machine */ * rle_gxloadimage.4.1/tgncpyrght.h 664 221 144 2126 5461577412 11116 #ifndef _TGN_COPYRIGHT_ /**** Copyright 1991 Tim Northrup Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****/ #ifndef __SABER__ static char *TGNCopyright = "Copyright (C) 1991 Tim Northrup"; #endif #define _TGN_COPYRIGHT_ #endif tiffampask[4]; /* Z blue mask */ byte bits_per_rgb[4]; /* Log2 of distinct color values */ byte colormap_entries[4]; /* Number of entries in colormap */ byte ncolors[4]; /* Number of Color structures */ byte window_width[4]; /* Window width */ byte window_height[4]; /* Window height */ byte window_x[4]; /* Window upper left X coordinate */ byte window_y[4]; /* Winxloadimage.4.1/options.h 664 221 144 6247 5463775314 10433 /* options.h: * * optionNumber() definitions * * jim frost 10.03.89 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ /* enum with the options in it. If you add one to this you also have to * add its information to Options[] in options.c before it becomes available. */ typedef enum option_id { /* global options */ OPT_NOTOPT= 0, OPT_BADOPT, OPT_SHORTOPT, OPT_IGNORE, BORDER, CONFIGURATION, DBUG, DEFAULT, DELAY, DISPLAY, DUMP, FIT, FORK, FULLSCREEN, GEOMETRY, HELP, IDENTIFY, INSTALL, LIST, ONROOT, PATH, PIXMAP, PRIVATE, QUIET, SHRINKTOFIT, SUPPORTED, VERBOSE, VER_NUM, VIEW, VISUAL, WINDOWID, /* local options */ AT, BACKGROUND, BRIGHT, CENTER, CLIP, COLORS, DITHER, FOREGROUND, GAMMA, GLOBAL, GOTO, GRAY, HALFTONE, IDELAY, INVERT, MERGE, NAME, NEWOPTIONS, NORMALIZE, ROTATE, SMOOTH, TITLE, TILE, TYPE, UNDITHER, XZOOM, YZOOM, ZOOM } OptionId; /* option structure */ typedef struct option { enum option_id type; union { struct { unsigned int x, y; /* location to load image at */ } at; char *background; /* background color for mono images */ char *border; /* border color */ unsigned int bright; /* brightness multiplier */ struct { unsigned int x, y, w, h; /* area of image to be used */ } clip; unsigned int colors; /* max # of colors to use for this image */ unsigned int delay; /* # of seconds delay before auto pic advance */ char *display; /* display name */ struct { char *type; /* image type */ char *file; /* file name */ } dump; char *foreground; /* foreground color for mono images */ float gamma; /* display gamma value */ struct { char *string; unsigned int w; unsigned int h; } geometry; char *go_to; /* label to go to */ char *name; /* name of image */ unsigned int rotate; /* # of degrees to rotate image */ char *title; /* title of image */ char *type; /* expected type of image */ unsigned int windowid; /* windowid for changing window backgrounds */ unsigned int visual; /* visual type to use */ struct { unsigned int x, y; /* zoom factors */ } zoom; } info; struct option *next; } Option; /* image name and option structure used when processing arguments */ typedef struct option_set { Option *options; /* image processing options */ struct option_set *next; } OptionSet; /* option information array */ typedef struct option_array { char *name; /* name of the option minus preceeding '-' */ OptionId option_id; /* OptionId of this option */ char *args; /* arguments this option uses or NULL if none */ char *description; /* description of this option */ } OptionArray; Option *getOption(); /* options.c */ Option *newOption(); OptionId optionNumber(); int getNextTypeOption(); /* imagetypes.c */ Image *loadImage _ArgProto((OptionSet *globalopts, OptionSet *options, char *name, unsigned int verbose)); void identifyImage _ArgProto((char *name)); green[2]; /* green intensity */ byte blue[2]; /* blue intensity */ byte flags; /* XColor flags (ignored) */ byte pad; } XWDColor; #define NOT_XWD 0 /* definitely not an XWD file */ #define XWD_MSB 1 /* looks like XWD file created on MSBFirst machine */ #define XWD_LSB 2 /* looks like XWD file created on LSBFirst machine */ * rle_gxloadimage.4.1/patchlevel 664 221 144 253 5467531040 10576 /* this defines the version and patchlevel of this version of xloadimage */ #define VERSION "4" #define PATCHLEVEL "1" #define AUTHOR_EMAIL "jimf@centerline.com" faces.c fbm.cce0gif.cm.Ht imagetypes.cHXimg.c.ch(mac.cg.|+mcidas.c* mc_tables.cpbm.clepcx.cm. pdsuncomp.crle.com>rlelib.csuC sunraster.c vff.cteIvicar.c0xloadimage.4.1/xloadimage.h 664 221 144 3132 5463771317 11037 /* xloadimage.h: * * jim frost 06.21.89 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include #include #include #include #include "image.h" #include "options.h" /* This struct holds the X-client side bits for a rendered image. */ typedef struct { Display *disp; /* destination display */ int scrn; /* destination screen */ int depth; /* depth of drawable we want/have */ Drawable drawable; /* drawable to send image to */ Pixel foreground; /* foreground and background pixels for mono images */ Pixel background; Colormap cmap; /* colormap used for image */ GC gc; /* cached gc for sending image */ XImage *ximage; /* ximage structure */ } XImageInfo; #ifndef MAXIMAGES #define MAXIMAGES BUFSIZ /* max # of images we'll try to load at once */ #endif /* function declarations */ void supportedImageTypes(); /* imagetypes.c */ char *tail(); /* misc.c */ void memoryExhausted(); void internalError(); void version(); void usage(); void goodImage(); int errorHandler(); char *expandPath(); /* path.c */ int findImage(); void listImages(); void loadPathsAndExts(); void showPath(); void imageOnRoot(); /* root.c */ void sendXImage(); /* send.c */ XImageInfo *imageToXImage(); Pixmap ximageToPixmap(); void freeXImage(); Visual *getBestVisual(); /* visual.c */ int visualClassFromName(); /* window.c */ char *nameOfVisualClass(); void cleanUpWindow(); char imageInWindow(); char *file; /* file name */ } dump; char *foreground; /* foreground color for mono images */ float gamma; /* display gamma value */ struct { char *string; unsigned int w; unsigned int h; } geometry; char *go_to; /* label to go to */ char *name; /* name of image */ unsigned int rotate; /* # of degrees to rotate imxloadimage.4.1/new.c 664 221 144 11267 5464000076 7525 /* new.c: * * functions to allocate and deallocate structures and structure data * * jim frost 09.29.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" extern int _Xdebug; /* this table is useful for quick conversions between depth and ncolors */ unsigned long DepthToColorsTable[] = { /* 0 */ 1, /* 1 */ 2, /* 2 */ 4, /* 3 */ 8, /* 4 */ 16, /* 5 */ 32, /* 6 */ 64, /* 7 */ 128, /* 8 */ 256, /* 9 */ 512, /* 10 */ 1024, /* 11 */ 2048, /* 12 */ 4096, /* 13 */ 8192, /* 14 */ 16384, /* 15 */ 32768, /* 16 */ 65536, /* 17 */ 131072, /* 18 */ 262144, /* 19 */ 524288, /* 20 */ 1048576, /* 21 */ 2097152, /* 22 */ 4194304, /* 23 */ 8388608, /* 24 */ 16777216, /* 25 */ 33554432, /* 26 */ 67108864, /* 27 */ 134217728, /* 28 */ 268435456, /* 29 */ 536870912, /* 30 */ 1073741824, /* 31 */ 2147483648, /* 32 */ 2147483648 /* bigger than unsigned int; this is good enough */ }; unsigned long colorsToDepth(ncolors) unsigned long ncolors; { unsigned long a; for (a= 0; (a < 32) && (DepthToColorsTable[a] < ncolors); a++) /* EMPTY */ ; return(a); } void goodImage(image, func) Image *image; char *func; { if (!image) { printf("%s: nil image\n", func); exit(0); } switch (image->type) { case IBITMAP: case IRGB: case ITRUE: break; default: printf("%s: bad destination image\n", func); exit(0); } } char *dupString(s) char *s; { char *d; if (!s) return(NULL); d= (char *)lmalloc(strlen(s) + 1); strcpy(d, s); return(d); } void newRGBMapData(rgb, size) RGBMap *rgb; unsigned int size; { rgb->used= 0; rgb->size= size; rgb->compressed= 0; rgb->red= (Intensity *)lmalloc(sizeof(Intensity) * size); rgb->green= (Intensity *)lmalloc(sizeof(Intensity) * size); rgb->blue= (Intensity *)lmalloc(sizeof(Intensity) * size); } void freeRGBMapData(rgb) RGBMap *rgb; { lfree((byte *)rgb->red); lfree((byte *)rgb->green); lfree((byte *)rgb->blue); } Image *newBitImage(width, height) unsigned int width, height; { Image *image; unsigned int linelen; image= (Image *)lmalloc(sizeof(Image)); image->type= IBITMAP; image->title= NULL; newRGBMapData(&(image->rgb), (unsigned int)2); *(image->rgb.red)= *(image->rgb.green)= *(image->rgb.blue)= 65535; *(image->rgb.red + 1)= *(image->rgb.green + 1)= *(image->rgb.blue + 1)= 0; image->rgb.used= 2; image->width= width; image->height= height; image->depth= 1; linelen= (width / 8) + (width % 8 ? 1 : 0); /* thanx johnh@amcc.com */ image->data= (unsigned char *)lcalloc(linelen * height); return(image); } Image *newRGBImage(width, height, depth) unsigned int width, height, depth; { Image *image; unsigned int pixlen, numcolors; pixlen= (depth / 8) + (depth % 8 ? 1 : 0); if (pixlen == 0) /* special case for `zero' depth image, which is */ pixlen= 1; /* sometimes interpreted as `one color' */ numcolors = depthToColors(depth); image= (Image *)lmalloc(sizeof(Image)); image->type= IRGB; image->title= NULL; newRGBMapData(&(image->rgb), numcolors); image->width= width; image->height= height; image->depth= depth; image->pixlen= pixlen; image->data= (unsigned char *)lmalloc(width * height * pixlen); return(image); } Image *newTrueImage(width, height) unsigned int width, height; { Image *image; image= (Image *)lmalloc(sizeof(Image)); image->type= ITRUE; image->title= NULL; image->rgb.used= image->rgb.size= 0; image->width= width; image->height= height; image->depth= 24; image->pixlen= 3; image->data= (unsigned char *)lmalloc(width * height * 3); return(image); } void freeImageData(image) Image *image; { if (image->title) { lfree((byte *)image->title); image->title= NULL; } if (!TRUEP(image)) freeRGBMapData(&(image->rgb)); lfree(image->data); } void freeImage(image) Image *image; { goodImage(image, "freeImage"); freeImageData(image); image->type= IBAD; lfree((byte *)image); } byte *lmalloc(size) unsigned int size; { byte *area; if (size == 0) { size= 1; if (_Xdebug) fprintf(stderr, "lcalloc given zero size!\n"); } if (!(area= (byte *)malloc(size))) { memoryExhausted(); /* NOTREACHED */ } return(area); } byte *lcalloc(size) unsigned int size; { byte *area; if (size == 0) { size= 1; if (_Xdebug) fprintf(stderr, "lcalloc given zero size!\n"); } if (!(area= (byte *)calloc(1, size))) { memoryExhausted(); /* NOTREACHED */ } return(area); } void lfree(area) byte *area; { free(area); } minmap, gamma ) * struct sv_globals * globals; * int minmap; * double gamma; */ /* * rle_getcom - get a specific comment from the image comments. */ extern char * rle_getcom(); /* ( name, globals ) * char * name; * struct sv_globals * globals; */ /* * rle_putcom - put (or replace) a comment into the image comments. xloadimage.4.1/niff.c 664 221 144 14714 5463770103 7662 /* niff.c: * * xloadimage native image format. This is used for loading and dumping * xloadimage images. * * jim frost 10.29.91 * * this is in the public domain. */ #include "image.h" #include "niff.h" static void babble(name, header, title) struct niff_header *header; char *title; { printf("%s is a %dx%d ", name, memToVal(header->width, 4), memToVal(header->height, 4), memToVal(header->depth, 4)); if (memToVal(header->version, 4) != NIFF_VERSION) printf("version %d ", memToVal(header->version, 4)); printf("NIFF "); switch (header->type) { case NIFF_BITMAP: printf("bitmap image"); break; case NIFF_RGB: printf("%d-bit RGB image with %d colors", memToVal(header->depth, 4), memToVal(header->cmap_size, 4)); break; case NIFF_TRUE: printf("%d-bit true color image", memToVal(header->depth, 4)); break; default: printf("image with an unknown type"); } if (title && title[0]) printf(" entitled \"%s\"", title); printf("\n"); } static int readHeader(zf, header, rtitle) ZFILE *zf; struct niff_header *header; char **rtitle; { unsigned int title_len; char *title = NULL; /* read in header */ if (zread(zf, (byte *)header, sizeof(struct niff_header)) != sizeof(struct niff_header)) { zclose(zf); return(0); } /* check magic number to see if this is a NIFF image */ if (memToVal(header->magic, 4) != NIFF_MAGIC) return(0); /* read in title if there is one */ title_len= memToVal(header->title_len, 4); if (title_len != 0) { title= (char *)lmalloc(title_len + 1); if (zread(zf, (byte *)title, title_len) != title_len) { lfree((byte *)title); return(0); } title[title_len]= '\0'; } if (rtitle) *rtitle= title; else lfree((byte *)title); return(1); } int niffIdent(fullname, name) char *fullname, *name; { ZFILE *zf; struct niff_header header; char *title; if (! (zf= zopen(fullname))) return(0); if (!readHeader(zf, &header, &title)) return(0); zclose(zf); babble(name, &header, title); lfree((byte *)title); return(1); } static int readColormap(zf, image) ZFILE *zf; Image *image; { unsigned int a; struct niff_cmap cmap; for (a= 0; a < image->rgb.used; a++) { if (zread(zf, (byte *)&cmap, sizeof(struct niff_cmap)) != sizeof(struct niff_cmap)) { fprintf(stderr, "niffLoad: short read in colormap!\n"); return(0); } image->rgb.red[a]= memToVal(cmap.red, 2); image->rgb.green[a]= memToVal(cmap.green, 2); image->rgb.blue[a]= memToVal(cmap.blue, 2); } return(1); } Image *niffLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; struct niff_header header; char *title; unsigned int width, height, depth; Image *image; unsigned int data_size; if (! (zf= zopen(fullname))) return(NULL); if (!readHeader(zf, &header, &title)) { zclose(zf); return(NULL); } if (verbose) babble(name, &header, title); znocache(zf); width= memToVal(header.width, 4); height= memToVal(header.height, 4); depth= memToVal(header.depth, 4); switch (header.type) { case NIFF_BITMAP: image= newBitImage(width, height); if (memToVal(header.cmap_size, 4) != 2) fprintf(stderr, "niffLoad: bitmap image has wrong number of colormap entries!\n"); if (!readColormap(zf, image)) { freeImage(image); zclose(zf); return(NULL); } data_size= ((image->width / 8) + (image->width % 8 ? 1 : 0)) * image->height; break; case NIFF_RGB: image= newRGBImage(width, height, depth); image->rgb.used= memToVal(header.cmap_size, 4); if (image->rgb.used > image->rgb.size) { fprintf(stderr, "niffLoad: too many colormap entries!\n"); image->rgb.used= image->rgb.size; } if (!readColormap(zf, image)) { freeImage(image); zclose(zf); return(NULL); } data_size= image->width * image->height * image->pixlen; break; case NIFF_TRUE: image= newTrueImage(width, height); data_size= image->width * image->height * 3; } image->title= title; /* read in image data */ if (zread(zf, image->data, data_size) != data_size) fprintf(stderr, "Short read on image data\n"); zclose(zf); return(image); } /* this takes an Image and dumps it into a file in NIFF format. returns * zero if successful. */ void niffDump(image, options, filename, verbose) Image *image; char *options; /* ignored */ char *filename; int verbose; { FILE *f; unsigned int a; struct niff_header header; struct niff_cmap cmap; unsigned int data_size; if (verbose) printf("Dumping NIFF image to %s.\n", filename); if (!(f= fopen(filename, "w"))) { perror(filename); return; } valToMem(NIFF_MAGIC, header.magic, 4); valToMem(NIFF_VERSION, header.version, 4); valToMem(image->width, header.width, 4); valToMem(image->height, header.height, 4); valToMem(image->depth, header.depth, 4); switch (image->type) { case IBITMAP: header.type= NIFF_BITMAP; valToMem(image->rgb.used, header.cmap_size, 4); data_size= ((image->width / 8) + (image->width % 8 ? 1 : 0)) * image->height; break; case IRGB: header.type= NIFF_RGB; valToMem(image->rgb.used, header.cmap_size, 4); data_size= image->width * image->height * image->pixlen; break; case ITRUE: header.type= NIFF_TRUE; valToMem(0, header.cmap_size, 4); data_size= image->width * image->height * 3; break; } valToMem((image->title ? strlen(image->title) : 0), header.title_len, 4); /* write header */ if (fwrite(&header, sizeof(struct niff_header), 1, f) != 1) { perror(filename); unlink(filename); return; } /* write title if there is one */ if (image->title && (strlen(image->title) > 0)) { if (fwrite(image->title, strlen(image->title), 1, f) != 1) { perror(filename); unlink(filename); return; } } /* write cmap if we need one */ switch (image->type) { case IBITMAP: case IRGB: for (a= 0; a < image->rgb.used; a++) { valToMem(image->rgb.red[a], cmap.red, 2); valToMem(image->rgb.green[a], cmap.green, 2); valToMem(image->rgb.blue[a], cmap.blue, 2); if (fwrite(&cmap, sizeof(struct niff_cmap), 1, f) != 1) { perror(filename); unlink(filename); return; } } } /* write image data */ if (fwrite(image->data, data_size, 1, f) != 1) { perror(filename); unlink(filename); return; } return; } void freeImage(image) Image *image; { goodIxloadimage.4.1/value.c 664 221 144 3135 5461577413 10036 /* value.c: * * routines for converting byte values to long values. these are pretty * portable although they are not necessarily the fastest things in the * world. * * jim frost 10.02.89 * * Copyright 1989 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" unsigned long doMemToVal(p, len) byte *p; unsigned int len; { unsigned int a; unsigned long i; i= 0; for (a= 0; a < len; a++) i= (i << 8) + *(p++); return(i); } unsigned long doValToMem(val, p, len) unsigned long val; byte *p; unsigned int len; { int a; for (a= len - 1; a >= 0; a--) { *(p + a)= val & 0xff; val >>= 8; } return(val); } unsigned long doMemToValLSB(p, len) byte *p; unsigned int len; { int val, a; val= 0; for (a= len - 1; a >= 0; a--) val= (val << 8) + *(p + a); return(val); } /* this is provided for orthagonality */ unsigned long doValToMemLSB(val, p, len) byte *p; unsigned long val; unsigned int len; { while (len--) { *(p++)= val & 0xff; val >>= 8; } return(val); } /* this flips all the bits in a byte array at byte intervals */ void flipBits(p, len) byte *p; unsigned int len; { static int init= 0; static byte flipped[256]; if (!init) { int a, b; byte norm; for (a= 0; a < 256; a++) { flipped[a]= 0; norm= a; for (b= 0; b < 8; b++) { flipped[a]= (flipped[a] << 1) | (norm & 1); norm >>= 1; } } } while (len--) p[len]= flipped[p[len]]; } f (verbose) printf("Dumping NIFF image to %s.\n", filename); if (!(f= fopen(filename, "w"))) { perror(filename); return; } valToMem(NIFF_MAGIC, header.magic, 4); valToMem(NIFF_VERSION, header.version, 4); valToMem(image->width, header.width, 4); valToMem(image->height, header.height, 4); valToMem(image->depth, header.depth, 4); switch (image->type) { case IBITMAP: header.type= NIFxloadimage.4.1/zio.c 664 221 144 15102 5463776352 7545 /* zio.c: * * this properly opens and reads from an image file, compressed or otherwise. * * jim frost 10.03.89 * * this was hacked on 09.12.90 to cache reads and to use stdin. * * Copyright 1989, 1990 Jim Frost. See included file "copyright.h" for * complete copyright information. */ #include "copyright.h" #include "image.h" #ifdef VMS #define NO_PIPES /* VMS doesn't have pipes */ #endif #ifndef NO_PIPES extern struct filter *Filters; #endif #define MAX_ZFILES 32 static ZFILE ZFileTable[MAX_ZFILES]; /* read some info through the read cache */ static int doRead(zf, buf, len) ZFILE *zf; byte *buf; int len; { int bread, readlen; /* loop through the read */ for (bread= 0; bread < len; bread += readlen, zf->bufptr += readlen) { /* read new or move to next data block if necessary */ if (!zf->dataptr || (zf->bufptr == zf->dataptr->len)) { if (zf->dataptr && (zf->dataptr->len == 0)) /* EOF */ return(bread); if (zf->dataptr && zf->dataptr->next) { zf->dataptr= zf->dataptr->next; } else { if (!zf->dataptr) { /* if the reader told us to stop caching, just do the read. */ if (zf->nocache) return(fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream)); zf->data= zf->dataptr= (struct cache *)lmalloc(sizeof(struct cache)); } else { zf->dataptr->next= (struct cache *)lmalloc(sizeof(struct cache)); zf->dataptr= zf->dataptr->next; } zf->dataptr->next= NULL; zf->dataptr->len= fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream); if (zf->dataptr->len < 0) { perror("fread"); exit(1); } } zf->bufptr= 0; } /* calculate length we can get out of read buffer */ readlen= (len - bread > zf->dataptr->len - zf->bufptr ? zf->dataptr->len - zf->bufptr : len - bread); if (!readlen) /* we're at EOF */ return(bread); bcopy(zf->dataptr->buf + zf->bufptr, buf + bread, readlen); } return(bread); } /* reset a read cache */ void zreset(filename) char *filename; { int a; struct cache *old; /* if NULL filename, reset the entire table */ if (!filename) { for (a= 0; a < MAX_ZFILES; a++) if (ZFileTable[a].filename) zreset(ZFileTable[a].filename); return; } for (a= 0; a < MAX_ZFILES; a++) if (ZFileTable[a].filename && !strcmp(filename, ZFileTable[a].filename)) break; if (a == MAX_ZFILES) /* no go joe */ return; if (ZFileTable[a].dataptr != ZFileTable[a].data) fprintf(stderr, "zreset: warning: ZFILE for %s was not closed properly\n", ZFileTable[a].filename); while (ZFileTable[a].data) { old= ZFileTable[a].data; ZFileTable[a].data= ZFileTable[a].data->next; free(old); } lfree((byte *)ZFileTable[a].filename); ZFileTable[a].filename= NULL; ZFileTable[a].dataptr= NULL; ZFileTable[a].bufptr= 0; ZFileTable[a].nocache= 0; switch(ZFileTable[a].type) { case ZSTANDARD: fclose(ZFileTable[a].stream); break; #ifndef NO_PIPES case ZPIPE: pclose(ZFileTable[a].stream); break; #endif /* NO_PIPES */ case ZSTDIN: break; default: fprintf(stderr, "zreset: bad ZFILE structure\n"); exit(1); } } ZFILE *zopen(name) char *name; { int a; ZFILE *zf; char buf[BUFSIZ]; struct filter *filter; debug(("zopen(\"%s\") called\n", name)); /* look for filename in open file table */ for (a= 0; a < MAX_ZFILES; a++) if (ZFileTable[a].filename && !strcmp(name, ZFileTable[a].filename)) { /* if we try to reopen a file whose caching was disabled, warn the user * and try to recover. we cannot recover if it was stdin. */ if (ZFileTable[a].nocache) { if (ZFileTable[a].type == ZSTDIN) { fprintf(stderr, "zopen: caching was disabled by previous caller; can't reopen stdin\n"); return(NULL); } fprintf(stderr, "zopen: warning: caching was disabled by previous caller\n"); zreset(ZFileTable[a].filename); break; } if (ZFileTable[a].dataptr != ZFileTable[a].data) fprintf(stderr, "zopen: warning: file doubly opened\n"); ZFileTable[a].dataptr= ZFileTable[a].data; ZFileTable[a].bufptr= 0; return(ZFileTable + a); } /* find open ZFileTable entry */ for (a= 0; (a < MAX_ZFILES) && ZFileTable[a].filename; a++) /* EMPTY */ ; if (a == MAX_ZFILES) { fprintf(stderr, "zopen: no more files available\n"); exit(1); } zf= ZFileTable + a; zf->filename= dupString(name); zf->dataptr= NULL; zf->bufptr= 0; zf->nocache= 0; /* file filename is `stdin' then use stdin */ if (!strcmp(name, "stdin")) { zf->type= ZSTDIN; zf->stream= stdin; return(zf); } #ifndef NO_PIPES /* check suffix against the table of filters and invoke the filter * if necessary. if your system doesn't support pipes you can * define NO_PIPES and this will not happen. */ for (filter= Filters; filter; filter= filter->next) { if ((strlen(name) > strlen(filter->extension)) && !strcmp(filter->extension, name + (strlen(name) - strlen(filter->extension)))) { debug(("Filtering image through '%s'\n", filter->filter)); zf->type= ZPIPE; sprintf(buf, "%s %s", filter->filter, name); if (! (zf->stream= popen(buf, "r"))) { lfree((byte *)zf->filename); zf->filename= NULL; return(NULL); } return(zf); } } #endif /* !NO_PIPES */ /* default to normal stream */ zf->type= ZSTANDARD; if (! #ifdef VMS (zf->stream= fopen(name, "r", "ctx=bin", "ctx=stm", "rfm=stmlf")) #else (zf->stream= fopen(name, "r")) #endif ) { lfree((byte *)zf->filename); zf->filename= NULL; return(NULL); } return(zf); } int zread(zf, buf, len) ZFILE *zf; byte *buf; unsigned int len; { return(doRead(zf, buf, len)); } int zgetc(zf) ZFILE *zf; { unsigned char c; if (doRead(zf, &c, 1) > 0) return(c); else return(EOF); } char *zgets(buf, size, zf) byte *buf; unsigned int size; ZFILE *zf; { int p= 0; while (doRead(zf, buf + p, 1) > 0) { if (p == size) return((char *)buf); if (*(buf + p) == '\n') { *(buf + p + 1)= '\0'; return((char *)buf); } p++; } return(NULL); } /* this turns off caching when an image has been identified and we will not * need to re-open it */ void znocache(zf) ZFILE *zf; { debug(("znocache(\"%s\") called\n", zf->filename)); zf->nocache= 1; } /* reset cache pointers in a ZFILE. nothing is actually reset until a * zreset() is called with the filename. */ void zclose(zf) ZFILE *zf; { debug(("zclose(\"%s\") called\n", zf->filename)); zf->dataptr= zf->data; zf->bufptr= 0; } , \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*((byte *)(PTR) + 3)) = ((unsigned int)(VAL) & 0xff)))))) #define valToMemLSB(VAL,PTR,LEN) \ ((LEN) == 1 ? (*(byte *)(PTR) = ((unsigned int)(VAL) & 0xff)) : \ ((LEN) == 3 ? (((*(byte *)(PTR) + 2) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsignedxloadimage.4.1/cmuwmraster.c 664 221 144 5301 5461577404 11270 /* * * handle CMU Window Manager (ITC) raster image type * * dan lovinger (dl2n+@andrew.cmu.edu) 07.11.90 * * the format is essentially a byte-reversed sun raster w/o encoding * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include "image.h" #include "cmuwmraster.h" /* SUPPRESS 558 */ int babble(name, headerp) char *name; struct cmuwm_header *headerp; { printf("%s is a %dx%d %d plane CMU WM raster\n", name, memToVal(headerp->width, sizeof(long)), memToVal(headerp->height, sizeof(long)), memToVal(headerp->depth, sizeof(short))); } int cmuwmIdent(fullname, name) char *fullname, *name; { ZFILE *zf; struct cmuwm_header header; int r; if (!(zf = zopen(fullname))) { perror("cmuwmIdent"); return(0); } switch (zread(zf, (byte *)&header, sizeof(struct cmuwm_header))) { case -1: perror("cmuwmIdent"); r =0; break; case sizeof(struct cmuwm_header): if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC) { r = 0; break; } babble(name, &header); r = 1; break; default: r = 0; break; } zclose(zf); return r; } Image* cmuwmLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; struct cmuwm_header header; Image *image; int height, width, row, linelen, r; byte *lineptr; if (!(zf= zopen(fullname))) { perror("cmuwmLoad"); return(NULL); } switch (zread(zf, (byte *)&header, sizeof(struct cmuwm_header))) { case -1: perror("cmuwmLoad"); zclose(zf); exit(1); case sizeof(struct cmuwm_header): if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC) { zclose(zf); return(NULL); } if (verbose) babble(name, &header); break; default: zclose(zf); return(NULL); } if (memToVal(header.depth, sizeof(short)) != 1) { fprintf(stderr,"CMU WM raster %s is of depth %d, must be 1", name, header.depth); return(NULL); } image = newBitImage(width = memToVal(header.width, sizeof(long)), height = memToVal(header.height, sizeof(long))); linelen = (width / 8) + (width % 8 ? 1 : 0); lineptr = image->data; for (row = 0; row < height; row++) { r = zread(zf, lineptr, linelen); if (r == -1) { perror("cmuwmLoad"); exit(1); } if (r != linelen) { printf("cmuwmLoad: short raster\n"); exit(1); } for (r = 0; r < linelen; r++) { lineptr[r] ^= 0xff; } lineptr += linelen; } zclose(zf); image->title = dupString(name); return image; } ZFILE *zf; struct cmuwm_header header; int r; if (!(zf = zopen(fullname))) { perror("cmuwmIdent"); return(0); } switch (zread(zf, (byte *)&header, sizeof(struct cmuwm_header))) { case -1: perror("cmuwmIdent"); r =0; break; case sizeof(struct cmuwm_hexloadimage.4.1/faces.c 664 221 144 7552 5461577405 10013 /* faces.c: * * faces format image loader * * jim frost 07.06.89 * * Copyright 1989 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" /* SUPPRESS 560 */ static short HexTable[256]; /* conversion value */ static unsigned int Initialized= 0; /* easier to fill in at run time */ #define HEXIGNORE -1 #define HEXBAD -2 /* build a hex digit value table with the bits inverted */ static void initHexTable() { int a; for (a= 0; a < 256; a++) HexTable[a]= HEXBAD; HexTable['0']= 0x0; HexTable['1']= 0x1; HexTable['2']= 0x2; HexTable['3']= 0x3; HexTable['4']= 0x4; HexTable['5']= 0x5; HexTable['6']= 0x6; HexTable['7']= 0x7; HexTable['8']= 0x8; HexTable['9']= 0x9; HexTable['A']= 0xa; HexTable['a']= HexTable['A']; HexTable['B']= 0xb; HexTable['b']= HexTable['B']; HexTable['C']= 0xc; HexTable['c']= HexTable['C']; HexTable['D']= 0xd; HexTable['d']= HexTable['D']; HexTable['E']= 0xe; HexTable['e']= HexTable['E']; HexTable['F']= 0xf; HexTable['f']= HexTable['F']; HexTable['\r']= HEXIGNORE; HexTable['\n']= HEXIGNORE; HexTable['\t']= HEXIGNORE; HexTable[' ']= HEXIGNORE; Initialized = 1; } /* read a hex value and return its value */ static int nextInt(zf, len) ZFILE *zf; unsigned int len; { int c; int value= 0; int count; len <<= 1; for (count= 0; count < len;) { c= zgetc(zf); if (c == EOF) return(-1); else { c= HexTable[c & 0xff]; switch(c) { case HEXIGNORE: break; case HEXBAD: return(-1); default: value= (value << 4) + c; count++; } } } return(value); } Image *facesLoad(fullname, name, verbose) char *fullname, *name; { ZFILE *zf; Image *image; char fname[BUFSIZ]; char lname[BUFSIZ]; char buf[BUFSIZ]; unsigned int w, h, d, iw, ih, id; unsigned int x, y; int value; unsigned int linelen; byte *lineptr, *dataptr; if (!Initialized) initHexTable(); if (! (zf= zopen(fullname))) return(NULL); w= h= d= 0; fname[0]= lname[0]= '\0'; while (zgets((byte *)buf, BUFSIZ - 1, zf)) { if (! strcmp(buf, "\n")) break; if (!strncmp(buf, "FirstName:", 10)) strcpy(fname, buf + 11); else if (!strncmp(buf, "LastName:", 9)) strcpy(lname, buf + 10); else if (!strncmp(buf, "Image:", 6)) { if (sscanf(buf + 7, "%d%d%d", &iw, &ih, &id) != 3) { printf("%s: Bad Faces Project image\n", fullname); exit(1); } } else if (!strncmp(buf, "PicData:", 8)) { if (sscanf(buf + 9, "%d%d%d", &w, &h, &d) != 3) { printf("%s: Bad Faces Project image\n", fullname); exit(1); } } } if (!w || !h || !d) { zclose(zf); return(NULL); } znocache(zf); if (verbose) printf("%s is a %dx%d %d-bit grayscale Faces Project image\n", name, w, h, d); image= newRGBImage(w, h, d); fname[strlen(fname) - 1]= ' '; strcat(fname, lname); fname[strlen(fname) - 1]= '\0'; image->title= dupString(fname); /* image is greyscale; build RGB map accordingly */ for (x= 0; x < image->rgb.size; x++) *(image->rgb.red + x)= *(image->rgb.green + x)= *(image->rgb.blue + x)= (65536 / image->rgb.size) * x; image->rgb.used= image->rgb.size; /* read in image data */ linelen= w * image->pixlen; lineptr= image->data + (h * linelen); for (y= 0; y < h; y++) { lineptr -= linelen; dataptr= lineptr; for (x= 0; x < w; x++) { if ((value= nextInt(zf, image->pixlen)) < 0) { printf("%s: Bad Faces Project image data\n", fullname); exit(1); } *(dataptr++)= value; } } zclose(zf); return(image); } int facesIdent(fullname, name) char *fullname, *name; { Image *image; if (image= facesLoad(fullname, name, 1)) { freeImage(image); return(1); } return(0); } en(name, "r", "ctx=bin", "ctx=stm", "rfm=stmlf")) #else (zf->stream= fopen(name, "r")) #endif ) { lfree((byte *)zf->filename); zf-xloadimage.4.1/fbm.c 664 221 144 17003 5461577405 7506 /* * fbm.c: * * adapted from code by Michael Mauldin, (mlm) at Carnegie-Mellon * University, (fbm tools) and Kirk L. Johnson, (tuna@athena.mit.edu), * (gif.c). * * fbmin.c * Mark Majhor * August 1990 * * routines for reading FBM files * * Copyright 1990 Mark Majhor (see the included file * "mrmcpyrght.h" for complete copyright information) */ # include # include # include # include "image.h" # include "fbm.h" /**** ** ** local variables ** ****/ static BYTE file_open = 0; /* status flags */ static BYTE image_open = 0; static ZFILE *ins; /* input stream */ static FBMFILEHDR phdr; /* header structure */ /**** ** ** global variables ** ****/ static int fbmin_img_width; /* image width */ static int fbmin_img_height; /* image height */ static int fbmin_img_depth; /* image depth */ static int fbmin_img_bits; /* color bits */ static int fbmin_img_rowlen; /* length of one row of data */ static int fbmin_img_plnlen; /* length of one plane of data */ static int fbmin_img_clrlen; /* length of the colormap */ static int fbmin_img_aspect; /* image aspect ratio */ static int fbmin_img_physbits; /* physical bits per pixel */ static char *fbmin_img_title; /* name of image */ static char *fbmin_img_credit; /* credit for image */ static fbmin_image_test() { if (fbmin_img_width < 1 || fbmin_img_width > 32767) { fprintf (stderr, "Invalid width (%d) on input\n", fbmin_img_width); return FBMIN_ERR_BAD_SD; } if (fbmin_img_height < 1 || fbmin_img_height > 32767) { fprintf (stderr, "Invalid height (%d) on input\n", fbmin_img_height); return (0); } if (fbmin_img_depth != 1 && fbmin_img_depth != 3) { fprintf (stderr, "Invalid number of planes (%d) on input %s\n", fbmin_img_depth, "(must be 1 or 3)"); return FBMIN_ERR_BAD_SD; } if (fbmin_img_bits < 1 || fbmin_img_bits > 8) { fprintf (stderr, "Invalid number of bits (%d) on input %s\n", fbmin_img_bits, "(must be [1..8])"); return FBMIN_ERR_BAD_SD; } if (fbmin_img_physbits != 1 && fbmin_img_physbits != 8) { fprintf (stderr, "Invalid number of physbits (%d) on input %s\n", fbmin_img_physbits, "(must be 1 or 8)"); return FBMIN_ERR_BAD_SD; } if (fbmin_img_rowlen < 1 || fbmin_img_rowlen > 32767) { fprintf (stderr, "Invalid row length (%d) on input\n", fbmin_img_rowlen); return FBMIN_ERR_BAD_SD; } if (fbmin_img_depth > 1 && fbmin_img_plnlen < 1) { fprintf (stderr, "Invalid plane length (%d) on input\n", fbmin_img_plnlen); return FBMIN_ERR_BAD_SD; } if (fbmin_img_aspect < 0.01 || fbmin_img_aspect > 100.0) { fprintf (stderr, "Invalid aspect ratio %lg on input\n", fbmin_img_aspect); return FBMIN_ERR_BAD_SD; } return FBMIN_SUCCESS; } /* * open FBM image in the input stream; returns FBMIN_SUCCESS if * successful. (might also return various FBMIN_ERR codes.) */ static int fbmin_open_image(s) ZFILE *s; { char *hp; /* header pointer */ /* make sure there isn't already a file open */ if (file_open) return(FBMIN_ERR_FAO); /* remember that we've got this file open */ file_open = 1; ins = s; /* read in the fbm file header */ hp = (char *) &phdr; if (zread(ins, (byte *)hp, sizeof(phdr)) != sizeof(phdr)) return FBMIN_ERR_EOF; if (strncmp(FBM_MAGIC, phdr.magic, sizeof(FBM_MAGIC)) != 0) return FBMIN_ERR_BAD_SIG; /* Now extract relevant features of FBM file header */ fbmin_img_width = atoi(phdr.cols); fbmin_img_height = atoi(phdr.rows); fbmin_img_depth = atoi(phdr.planes); fbmin_img_bits = atoi(phdr.bits); fbmin_img_rowlen = atoi(phdr.rowlen); fbmin_img_plnlen = atoi(phdr.plnlen); fbmin_img_clrlen = atoi(phdr.clrlen); fbmin_img_aspect = atoi(phdr.aspect); fbmin_img_physbits = atoi(phdr.physbits); fbmin_img_title = phdr.title; fbmin_img_credit = phdr.credits; if (fbmin_image_test() != FBMIN_SUCCESS) return FBMIN_ERR_BAD_SD; return FBMIN_SUCCESS; } /* * close an open FBM file */ static int fbmin_close_file() { /* make sure there's a file open */ if (!file_open) return FBMIN_ERR_NFO; /* mark file (and image) as closed */ file_open = 0; image_open = 0; /* done! */ return FBMIN_SUCCESS; } #if 0 /* * semi-graceful fatal error mechanism */ static fbmin_fatal(msg) char *msg; { printf("Error reading FBM file: %s\n", msg); exit(0); } #endif /* * these are the routines added for interfacing to xloadimage */ /* * tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(name) char *name; { if (fbmin_img_clrlen > 0) printf("%s is a %dx%d FBM image with %d colors\n", name, fbmin_img_width, fbmin_img_height, fbmin_img_clrlen / 3); else printf("%s is a %dx%d FBM image with %d greyscale planes\n", name, fbmin_img_width, fbmin_img_height, fbmin_img_bits); } Image *fbmLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; Image *image; register int x, y, j, k, rowlen, plnlen; unsigned char *pixptr, *cm; unsigned int map_size; extern int Scrn; unsigned char *r, *g, *b; if (! (zf= zopen(fullname))) return(NULL); if (fbmin_open_image(zf) != FBMIN_SUCCESS) { /* read image header */ fbmin_close_file(); zclose(zf); return(NULL); } if (verbose) tellAboutImage(name); znocache(zf); image = newRGBImage(fbmin_img_width, fbmin_img_height, fbmin_img_bits); /* if image has a local colormap, override global colormap */ if (fbmin_img_clrlen > 0) { cm = (unsigned char *) lmalloc(fbmin_img_clrlen); if (zread(ins, cm, fbmin_img_clrlen) != fbmin_img_clrlen) { fprintf (stderr, "can't read colormap (%d bytes)\n", fbmin_img_clrlen); return(NULL); } /* * fbm color map is organized as * buf[3][16] */ y = fbmin_img_clrlen / 3; r = &cm[0], g = &cm[y], b = &cm[2 * y]; for (x = 0; x < y; x++, r++, g++, b++) { image->rgb.red[x] = *r << 8; image->rgb.green[x] = *g << 8; image->rgb.blue[x] = *b << 8; } image->rgb.used = y; } else if (fbmin_img_bits > 0) { map_size = 3 * (int) pow(2.0, (double) fbmin_img_bits); cm = (unsigned char *) lmalloc(map_size); y = map_size / 3; for (x = 0; x < y; x++) { cm[x] = cm[y+x] = cm[2*y+x] = x; } r = &cm[0], g = &cm[y], b = &cm[2 * y]; for (x = 0; x < y; x++, r++, g++, b++) { image->rgb.red[x] = *r << 8; image->rgb.green[x] = *g << 8; image->rgb.blue[x] = *b << 8; } image->rgb.used = y; } else cm = NULL; rowlen = fbmin_img_rowlen; plnlen = fbmin_img_plnlen; for (k = 0; k < fbmin_img_depth; k++) { pixptr = &(image->data[k * plnlen]); for (j = 0; j < fbmin_img_height; j++, pixptr += rowlen) { if (zread(ins, pixptr, rowlen) != rowlen) { printf("%s: Short read within image data\n", fullname); exit(1); } } } if (cm != NULL) lfree(cm); fbmin_close_file(); zclose(zf); if (strlen(fbmin_img_title) != 0) image->title= dupString(fbmin_img_title); else image->title= dupString(name); return(image); } int fbmIdent(fullname, name) char *fullname, *name; { ZFILE *zf; unsigned int ret; if (! (zf= zopen(fullname))) return(0); if (fbmin_open_image(zf) == FBMIN_SUCCESS) { tellAboutImage(name); ret = 1; } else ret = 0; fbmin_close_file(); zclose(zf); return(ret); } t)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff))) : \ ((LEN) == 2 ? (((*((byte *)(PTR) + 1) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xff)))) : \ (((*((byte *)(PTR) + 3)) = ((unsigned int)(VAL) & 0xff000000) >> 24), \ ((*((byte *)(PTR) + 2)) = ((unsigned int)(VAL) & 0xff0000) >> 16), \ ((*((byte *)(PTR) + 1)) = ((unsigned int)(VAL) & 0xff00) >> 8), \ ((*(byte *)(PTR)) = ((unsigned int)(VAL) & 0xffxloadimage.4.1/gif.c 664 221 144 34267 5461577405 7522 /* gif.c: * * adapted from code by kirk johnson (tuna@athena.mit.edu). most of this * code is unchanged. -- jim frost 12.31.89 * * gifin.c * kirk johnson * november 1989 * * routines for reading GIF files * * Copyright 1989 Kirk L. Johnson (see the included file * "kljcpyrght.h" for complete copyright information) */ #include "image.h" #include "gif.h" #include "kljcpyrght.h" /**** ** ** local #defines ** ****/ #define PUSH_PIXEL(p) \ { \ if (pstk_idx == PSTK_SIZE) \ gifin_fatal("pixel stack overflow in PUSH_PIXEL()"); \ else \ pstk[pstk_idx++] = (p); \ } /**** ** ** local variables ** ****/ static int interlace_start[4]= { /* start line for interlacing */ 0, 4, 2, 1 }; static int interlace_rate[4]= { /* rate at which we accelerate vertically */ 8, 8, 4, 2 }; static BYTE file_open = 0; /* status flags */ static BYTE image_open = 0; static ZFILE *ins; /* input stream */ static int root_size; /* root code size */ static int clr_code; /* clear code */ static int eoi_code; /* end of information code */ static int code_size; /* current code size */ static int code_mask; /* current code mask */ static int prev_code; /* previous code */ /* * NOTE: a long is assumed to be at least 32 bits wide */ static long work_data; /* working bit buffer */ static int work_bits; /* working bit count */ static BYTE buf[256]; /* byte buffer */ static int buf_cnt; /* byte count */ static int buf_idx; /* buffer index */ static int table_size; /* string table size */ static int prefix[STAB_SIZE]; /* string table : prefixes */ static int extnsn[STAB_SIZE]; /* string table : extensions */ static BYTE pstk[PSTK_SIZE]; /* pixel stack */ static int pstk_idx; /* pixel stack pointer */ /**** ** ** global variables ** ****/ static int gifin_rast_width; /* raster width */ static int gifin_rast_height; /* raster height */ static BYTE gifin_g_cmap_flag; /* global colormap flag */ static int gifin_g_pixel_bits; /* bits per pixel, global colormap */ static int gifin_g_ncolors; /* number of colors, global colormap */ static BYTE gifin_g_cmap[3][256]; /* global colormap */ static int gifin_bg_color; /* background color index */ static int gifin_color_bits; /* bits of color resolution */ static int gifin_img_left; /* image position on raster */ static int gifin_img_top; /* image position on raster */ static int gifin_img_width; /* image width */ static int gifin_img_height; /* image height */ static BYTE gifin_l_cmap_flag; /* local colormap flag */ static int gifin_l_pixel_bits; /* bits per pixel, local colormap */ static int gifin_l_ncolors; /* number of colors, local colormap */ static BYTE gifin_l_cmap[3][256]; /* local colormap */ static BYTE gifin_interlace_flag; /* interlace image format flag */ /* * open a GIF file, using s as the input stream */ static int gifin_open_file(s) ZFILE *s; { /* make sure there isn't already a file open */ if (file_open) return GIFIN_ERR_FAO; /* remember that we've got this file open */ file_open = 1; ins = s; /* check GIF signature */ if (zread(ins, buf, GIF_SIG_LEN) != GIF_SIG_LEN) return GIFIN_ERR_EOF; buf[GIF_SIG_LEN] = '\0'; if ((strcmp((char *) buf, GIF_SIG) != 0) && (strcmp((char *) buf, GIF_SIG_89) != 0)) return GIFIN_ERR_BAD_SIG; /* read screen descriptor */ if (zread(ins, buf, GIF_SD_SIZE) != GIF_SD_SIZE) return GIFIN_ERR_EOF; /* decode screen descriptor */ gifin_rast_width = (buf[1] << 8) + buf[0]; gifin_rast_height = (buf[3] << 8) + buf[2]; gifin_g_cmap_flag = (buf[4] & 0x80) ? 1 : 0; gifin_color_bits = ((buf[4] & 0x70) >> 4) + 1; gifin_g_pixel_bits = (buf[4] & 0x07) + 1; gifin_bg_color = buf[5]; if (buf[6] != 0) return GIFIN_ERR_BAD_SD; /* load global colormap */ if (gifin_g_cmap_flag) { gifin_g_ncolors = (1 << gifin_g_pixel_bits); if (gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors) != GIFIN_SUCCESS) return GIFIN_ERR_EOF; } else { gifin_g_ncolors = 0; } /* done! */ return GIFIN_SUCCESS; } /* * open next GIF image in the input stream; returns GIFIN_SUCCESS if * successful. if there are no more images, returns GIFIN_DONE. (might * also return various GIFIN_ERR codes.) */ static int gifin_open_image() { int i; int separator; /* make sure there's a file open */ if (!file_open) return GIFIN_ERR_NFO; /* make sure there isn't already an image open */ if (image_open) return GIFIN_ERR_IAO; /* remember that we've got this image open */ image_open = 1; /* skip over any extension blocks */ do { separator = zgetc(ins); if (separator == GIF_EXTENSION) { if (gifin_skip_extension() != GIFIN_SUCCESS) return GIFIN_ERR_EOF; } } while (separator == GIF_EXTENSION); /* check for end of file marker */ if (separator == GIF_TERMINATOR) return GIFIN_DONE; /* make sure we've got an image separator */ if (separator != GIF_SEPARATOR) return GIFIN_ERR_BAD_SEP; /* read image descriptor */ if (zread(ins, buf, GIF_ID_SIZE) != GIF_ID_SIZE) return GIFIN_ERR_EOF; /* decode image descriptor */ gifin_img_left = (buf[1] << 8) + buf[0]; gifin_img_top = (buf[3] << 8) + buf[2]; gifin_img_width = (buf[5] << 8) + buf[4]; gifin_img_height = (buf[7] << 8) + buf[6]; gifin_l_cmap_flag = (buf[8] & 0x80) ? 1 : 0; gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0; gifin_l_pixel_bits = (buf[8] & 0x07) + 1; /* load local colormap */ if (gifin_l_cmap_flag) { gifin_l_ncolors = (1 << gifin_l_pixel_bits); if (gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors) != GIFIN_SUCCESS) return GIFIN_ERR_EOF; } else { gifin_l_ncolors = 0; } /* initialize raster data stream decoder */ root_size = zgetc(ins); clr_code = 1 << root_size; eoi_code = clr_code + 1; code_size = root_size + 1; code_mask = (1 << code_size) - 1; work_bits = 0; work_data = 0; buf_cnt = 0; buf_idx = 0; /* initialize string table */ for (i=0; i>= code_size; work_bits -= code_size; /* interpret the code */ if (code == clr_code) { /* reset decoder stream */ code_size = root_size + 1; code_mask = (1 << code_size) - 1; prev_code = NULL_CODE; table_size = eoi_code + 1; } else if (code == eoi_code) { /* Ooops! no more pixels */ return GIFIN_ERR_EOF; } else if (prev_code == NULL_CODE) { gifin_push_string(code); prev_code = code; } else { if (code < table_size) { first = gifin_push_string(code); } else { place = pstk_idx; PUSH_PIXEL(NULL_CODE); first = gifin_push_string(prev_code); pstk[place] = first; } gifin_add_string(prev_code, first); prev_code = code; } } /* pop a pixel off the pixel stack */ *pel = (int) pstk[--pstk_idx]; /* done! */ return GIFIN_SUCCESS; } #if 0 /* * close an open GIF image */ static int gifin_close_image() { /* make sure there's an image open */ if (!image_open) return GIFIN_ERR_NIO; /* skip any remaining raster data */ do { if (gifin_read_data_block() != GIFIN_SUCCESS) return GIFIN_ERR_EOF; } while (buf_cnt > 0); /* mark image as closed */ image_open = 0; /* done! */ return GIFIN_SUCCESS; } #endif /* * close an open GIF file */ static int gifin_close_file() { /* make sure there's a file open */ if (!file_open) return GIFIN_ERR_NFO; /* mark file (and image) as closed */ file_open = 0; image_open = 0; /* done! */ return GIFIN_SUCCESS; } /* * load a colormap from the input stream */ static int gifin_load_cmap(cmap, ncolors) BYTE cmap[3][256]; int ncolors; { int i; for (i=0; i 0); /* done! */ return GIFIN_SUCCESS; } /* * read a new data block from the input stream */ static int gifin_read_data_block() { /* read the data block header */ buf_cnt = zgetc(ins); /* read the data block body */ if (zread(ins, buf, buf_cnt) != buf_cnt) return GIFIN_ERR_EOF; buf_idx = 0; /* done! */ return GIFIN_SUCCESS; } /* * push a string (denoted by a code) onto the pixel stack * (returns the code of the first pixel in the string) */ static int gifin_push_string(code) int code; { int rslt; while (prefix[code] != NULL_CODE) { PUSH_PIXEL(extnsn[code]); code = prefix[code]; } PUSH_PIXEL(extnsn[code]); rslt = extnsn[code]; return rslt; } /* * add a new string to the string table */ static gifin_add_string(p, e) int p; int e; { prefix[table_size] = p; extnsn[table_size] = e; if ((table_size == code_mask) && (code_size < 12)) { code_size += 1; code_mask = (1 << code_size) - 1; } table_size += 1; } /* * semi-graceful fatal error mechanism */ static gifin_fatal(msg) char *msg; { printf("Error reading GIF file: %s\n", msg); exit(0); } /* these are the routines added for interfacing to xloadimage */ /* tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(name) char *name; { printf("%s is a %dx%d %sGIF image with %d colors\n", name, gifin_img_width, gifin_img_height, (gifin_interlace_flag ? "interlaced " : ""), (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors)); } Image *gifLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; Image *image; int x, y, pixel, pass, scanlen; byte *pixptr, *pixline; if (! (zf= zopen(fullname))) return(NULL); if ((gifin_open_file(zf) != GIFIN_SUCCESS) || /* read GIF header */ (gifin_open_image() != GIFIN_SUCCESS)) { /* read image header */ gifin_close_file(); zclose(zf); return(NULL); } if (verbose) tellAboutImage(name); znocache(zf); image= newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ? gifin_l_pixel_bits : gifin_g_pixel_bits)); for (x= 0; x < gifin_g_ncolors; x++) { image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8; image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8; image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8; } image->rgb.used= gifin_g_ncolors; /* if image has a local colormap, override global colormap */ if (gifin_l_cmap_flag) { for (x= 0; x < image->rgb.size; x++) { image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8; image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8; image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8; } image->rgb.used= gifin_l_ncolors; } /* interlaced image -- futz with the vertical trace. i wish i knew what * kind of drugs the GIF people were on when they decided that they * needed to support interlacing. */ if (gifin_interlace_flag) { scanlen= image->height * image->pixlen; /* interlacing takes four passes to read, each starting at a different * vertical point. */ for (pass= 0; pass < 4; pass++) { y= interlace_start[pass]; scanlen= image->width * image->pixlen * interlace_rate[pass]; pixline= image->data + (y * image->width * image->pixlen); while (y < gifin_img_height) { pixptr= pixline; for (x= 0; x < gifin_img_width; x++) { if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) { printf("%s: Short read within image data\n", fullname); y = gifin_img_height; x = gifin_img_width; } valToMem(pixel, pixptr, image->pixlen); pixptr += image->pixlen; } y += interlace_rate[pass]; pixline += scanlen; } } } /* not an interlaced image, just read in sequentially */ else { pixptr= image->data; for (y= 0; y < gifin_img_height; y++) for (x= 0; x < gifin_img_width; x++) { if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) { printf("%s: Short read within image data\n", fullname); y = gifin_img_height; x = gifin_img_width; } valToMem(pixel, pixptr, image->pixlen); pixptr += image->pixlen; } } gifin_close_file(); zclose(zf); image->title= dupString(name); return(image); } int gifIdent(fullname, name) char *fullname, *name; { ZFILE *zf; unsigned int ret; if (! (zf= zopen(fullname))) return(0); if ((gifin_open_file(zf) == GIFIN_SUCCESS) && (gifin_open_image() == GIFIN_SUCCESS)) { tellAboutImage(name); ret= 1; } else ret= 0; gifin_close_file(); zclose(zf); return(ret); } root_size = zgetc(ins); clr_code = 1 << root_size; eoi_code = clr_code + 1; code_size = root_size + 1; code_mask = (1 << code_size) - 1; work_bits = 0; work_data = 0; buf_cnt = 0; buf_idx = 0; /* initialize string table */ for (i=0; i /* SUPPRESS 560 */ extern int errno; /* load a named image */ Image *loadImage(globalopts, options, name, verbose) OptionSet *globalopts; OptionSet *options; char *name; unsigned int verbose; { char fullname[BUFSIZ]; Option *opt; Image *image; int a; if (findImage(name, fullname) < 0) { if (errno == ENOENT) fprintf(stderr, "%s: image not found\n", name); else perror(fullname); return(NULL); } /* see if there's a "type" option and use it if there is */ if (! (opt= getOption(globalopts, TYPE))) opt= getOption(options, TYPE); if (opt) { for (a= 0; ImageTypes[a].loader; a++) if (!strncmp(ImageTypes[a].type, opt->info.type, strlen(opt->info.type))) { if (image= ImageTypes[a].loader(fullname, name, verbose)) { zreset(NULL); /* this converts a 1-bit RGB image to a bitmap prior to blitting * it across. it's a transmission efficiency hack, and has the * beneficial side-effect of eliminating dithering on RGB images * that don't really need it. */ if (RGBP(image) && (image->rgb.used <= 2)) { Image *new_image; new_image = flatten(image); if (new_image != image) { freeImage(image); image = new_image; } } return(image); } fprintf(stderr, "%s does not look like a \"%s\" image (skipping).\n", fullname, opt->info.type); zreset(NULL); return(NULL); } fprintf(stderr, "\"%s\" is not a supported image type (will try to guess the type)\n", opt->info.type); /* fall through into the type determination loop */ } /* try to pick out the image type */ for (a= 0; ImageTypes[a].loader; a++) { debug(("Checking %s against loader for %s\n", fullname, ImageTypes[a].name)); if (image= ImageTypes[a].loader(fullname, name, verbose)) { zreset(NULL); /* this does the 1-bit conversion as above. */ if (RGBP(image) && (image->rgb.used <= 2)) { Image *new_image; new_image = flatten(image); if (new_image != image) { freeImage(image); image = new_image; } } return(image); } } fprintf(stderr, "%s: unknown or unsupported image type\n", fullname); zreset(NULL); return(NULL); } /* identify what kind of image a named image is */ void identifyImage(name) char *name; { char fullname[BUFSIZ]; int a; if (findImage(name, fullname) < 0) { if (errno == ENOENT) fprintf(stderr, "%s: image not found\n", name); else perror(fullname); return; } for (a= 0; ImageTypes[a].identifier; a++) { if (ImageTypes[a].identifier(fullname, name)) { zreset(NULL); return; } } zreset(NULL); fprintf(stderr, "%s: unknown or unsupported image type\n", fullname); } /* dump an image into an image file of the specified type */ void dumpImage(image, type, filename, verbose) Image *image; char *type; char *filename; int verbose; { int a; char typename[32]; char *optptr; /* find options if there are any */ optptr = index(type, ','); if (optptr) { strncpy(typename, type, optptr - type); typename[optptr - type] = '\0'; optptr++; /* skip comma */ } else strcpy(typename, type); for (a= 0; ImageTypes[a].loader; a++) if (!strncmp(ImageTypes[a].type, typename, strlen(typename))) { if (ImageTypes[a].dumper) ImageTypes[a].dumper(image, optptr, filename, verbose); else fprintf(stderr, "\ %s: I can read this image type but cannot write it (sorry).\n\ If you need a list of supported image types, use the -supported option.\n", type); return; } fprintf(stderr, "\ %s: unknown or unsupported image type. If you need a list\n\ of supported image types, use the -supported option.\n", type); } /* tell user what image types we support */ void supportedImageTypes() { int a; printf("Type Name Can Dump Description\n"); printf("---------- -------- -----------\n"); for (a= 0; ImageTypes[a].name; a++) printf("%-10s %-8s %s\n", ImageTypes[a].type, (ImageTypes[a].dumper ? "Yes" : "No"), ImageTypes[a].name); } pe determination loop */ } /* try to pick out the image type */ for (a= 0; ImageTypes[a].loader; a++) { debug(("Cxloadimage.4.1/img.c 664 221 144 44230 5463770307 7516 /* GEM-Images * * dieter fiebelkorn GEM image type * * dieter fiebelkorn 19.12.90 * * jimf 10.29.93 - lots of reworking to handle different byte-orders and * 32-bit integers. no color images to test it with... * */ #include #include #include #include #include "image.h" extern int errno; #define TRUE 1 #define FALSE 0 #define MAX_PLANES 8 #define ALL_PLANES 8 #define LEAVE {\ errorInLoad = errno;\ printf(" Short read within image data\n");\ return;\ } #define LEAVE_ON_ERROR(func) if ((func) <= 0) LEAVE static int vdiColorOrder = 0; static char *depthError = "Unsupported depth (%d) in IMG-file.\n"; static unsigned int out_depthError = 0; int errorInLoad; typedef struct IMGHEADER { byte im_version[2]; byte im_headlength[2]; byte im_nplanes[2]; byte im_patlen[2]; byte im_pixwidth[2]; byte im_pixheight[2]; byte im_scanwidth[2]; byte im_nlines[2]; } IMGHEADER; typedef struct ximg_header { byte im_version[2]; byte im_headlength[2]; byte im_nplanes[2]; byte im_patlen[2]; byte im_pixwidth[2]; byte im_pixheight[2]; byte im_scanwidth[2]; byte im_nlines[2]; char x_id [4]; /* must contain "XIMG" */ byte color_model[2]; /* 0 = RGB,1 = CYM,2 = HLS, etc. */ } XIMG_HEADER; void (*transf) (); static int vdi2pli(); static int pli2vdi(); static void transf0 (); static void transf1 (); static void transf2 (); static void transf3 (); static void xread_img (); static void xread_line (); static int ident_img (); static Image *load_img (); static int ident_ximg (); static Image *load_ximg (); IMGHEADER header; XIMG_HEADER xheader; unsigned int ScanByteBreite, max_planes, pattern_len, plane, x, y, ByteNr, height; unsigned char *ptr, Muster[ALL_PLANES][BUFSIZ], tmp[BUFSIZ]; static unsigned char *bitplane[ALL_PLANES], *lastbitplane; static void transf0(bitimage, plane, value, planes) unsigned char *bitimage; unsigned int plane; unsigned char value; unsigned int planes; { bitimage[x] = value; x++; } static void transf1(bitimage, plane, value, planes) unsigned char *bitimage; unsigned int plane; unsigned char value; unsigned int planes; { unsigned char bit; unsigned long off; bit= 0x80; off= 0; do { if (bit & value) bitimage[off + 8*x] |= (unsigned char)0x01 << plane; bit >>= 1; off++; } while (bit > 0); x++; } static void transf2(bitimage, plane, value, planes) unsigned char *bitimage; unsigned int plane; unsigned char value; unsigned int planes; { int i; if (bitimage != lastbitplane) { lastbitplane = bitimage; for (i = 0; i < planes; i++) bitplane[i] += ScanByteBreite + (ScanByteBreite % 2); } bitplane[plane][x] = value; x++; } static void transf3(bitimage, plane, value, planes) unsigned char *bitimage; unsigned int plane; unsigned char value; unsigned int planes; { unsigned char bit; unsigned long off; bit= 0x80; off= 0; do { if (bit & value) { if (plane < 8) bitimage[off + 24*x+2] |= (unsigned char)0x01 << plane; if (plane >= 8 && plane < 16) bitimage[off + 24*x+1] |= (unsigned char)0x01 << (plane-8); if (plane >= 16 && plane < 24) bitimage[off + 24*x ] |= (unsigned char)0x01 << (plane-16); } bit >>= 1; off+=3; } while (bit > 0); x++; } static void xread_line (file, planes) ZFILE *file; int planes; { ByteNr= 0; for (plane= 0; plane < planes; plane++) { do xread_img (file, TRUE, planes); while (ByteNr < ScanByteBreite); ByteNr= 0; x= 0; } } static void xread_img (file, linie, planes) ZFILE *file; unsigned int linie; int planes; { unsigned int wert, i, k; unsigned char status; wert = zgetc(file); switch (wert) { case EOF: LEAVE; case 0x00: wert = zgetc(file); switch (wert) { case EOF: LEAVE; case 0x00: /* Vertical Run */ LEAVE_ON_ERROR(zread(file, tmp, 2L)); if (tmp[0] == 0xFF && !linie) { wert = tmp[1]; xread_line (file, planes); } else { errorInLoad = 1; printf(" Wrong (X)IMG format!"); return; } if (y + wert > height) wert = height - y; if (planes == 1) { for (k= 0; k < wert; k++) { for (i= 0; i < ScanByteBreite; i++) *ptr++ = Muster[0][i]; if (ScanByteBreite % 2 == 1) *ptr++ = 0x00; } ByteNr = ScanByteBreite; if (ByteNr % 2 == 1) ByteNr++; x = 0; y += (wert - 1); } else { for (k= 0; k < wert; k++) { int plane; for (plane= 0; plane < planes; plane++) { x= 0; for (ByteNr= 0; ByteNr < ScanByteBreite; ByteNr++) (*transf)(ptr, plane, Muster[plane][ByteNr], planes); } ptr += max_planes * (ScanByteBreite + (ScanByteBreite % 2)); y++; } x = 0; ptr -= max_planes * (ScanByteBreite + (ScanByteBreite % 2)); y--; } break; default : /* Pattern Run */ if (!linie) { LEAVE_ON_ERROR(zread(file, tmp, (long)pattern_len)); if (planes == 1) { for (k= 0; k < wert && ByteNr < ScanByteBreite; k++) { for (i= 0; i < pattern_len; i++) *ptr++ = tmp[i]; ByteNr += pattern_len; } } else { for (k= 0; k < wert && ByteNr < ScanByteBreite; k++) { for (i= 0; i < pattern_len; i++) (*transf)(ptr, plane, tmp[i], planes); ByteNr += pattern_len; } } } else { LEAVE_ON_ERROR(zread(file, tmp, (long)pattern_len)); for (k= 0; k < wert && ByteNr < ScanByteBreite; k++) for (i= 0; i < pattern_len; i++) Muster[plane][ByteNr++] = tmp[i]; } } break; case 0x80: wert = zgetc(file); if (wert == EOF) LEAVE; i = wert; if (ByteNr + i > ScanByteBreite) i = ScanByteBreite - ByteNr; wert -= i; if (!linie) { if (planes == 1) { zread(file, ptr, (long)i); ptr += i; ByteNr += i; if (wert) LEAVE_ON_ERROR(zread(file, tmp, (long)wert)); } else { zread(file, tmp, (long)i); for (k = 0; k < i; k++) { (*transf)(ptr, plane, tmp[k], planes); ByteNr++; } if (wert) LEAVE_ON_ERROR(zread(file, tmp, (long)wert)); } } else { zread(file, &Muster[plane][ByteNr], (long)i); ByteNr += i; if (wert) LEAVE_ON_ERROR(zread(file, tmp, (long)wert)); } break; default : if (wert & 0x80) status = 0xff; else status = 0x00; wert &= 0x7f; if (!linie) { if (planes == 1) for (i= 0; i < wert && ByteNr < ScanByteBreite; i++) { *ptr++ = status; ByteNr++; } else for (i= 0; i < wert && ByteNr < ScanByteBreite; i++) { (*transf)(ptr, plane, status, planes); ByteNr++; } } else for (i= 0; i < wert && ByteNr < ScanByteBreite; i++) Muster[plane][ByteNr++] = status; } } static int ident_img(name) char *name; { ZFILE *file; long size = 0; int w, h, nplanes; char extention[5]; #if 0 strncpy (extention, name+strlen(name)-4, 4); extention[4] = '\0'; if (strcmp(extention, ".IMG") != 0 && strcmp(extention, ".img") != 0) return (0); #endif if ((file= zopen(name)) == NULL) { printf(" Error reading IMG!"); return(0); } size = zread(file, (byte *)&header, sizeof(header)); zclose(file); if (size < sizeof(header) || memToVal(header.im_version, 2) > 2) return (0); w = memToVal(header.im_scanwidth, 2); h = memToVal(header.im_nlines, 2); nplanes = memToVal(header.im_nplanes, 2); if ((nplanes > 4 && nplanes != 24) || nplanes == 0) { if (out_depthError == 0) printf(depthError, header.im_nplanes); return(0); } if (nplanes == 1) printf("%s is a %dx%d monochrome IMG-file\n",name , w, h); else if (nplanes != 24) printf("%s is a %dx%d IMG-file with %ld colors\n",name , w, h, (1 << nplanes)); else printf("%s is a %dx%d %d-bit IMG-file\n",name , w, h, nplanes); return (1); } static Image *load_img(name) char *name; { ZFILE *file; Image *image; unsigned long w, h, nplanes, headlength, scanwidth; int colors; long i, dummy; if ((file = zopen(name)) == NULL) { printf(" Error reading IMG!"); return(NULL); } zread(file, (byte *)&header, sizeof(header)); headlength = memToVal(header.im_headlength, 2); for (i=0; i<(headlength-(int)(sizeof(header)/2)); i++) zread(file, (byte *)&dummy, 2L); w = memToVal(header.im_scanwidth, 2); w = 16L * (w / 16L + (w % 16L ? 1 : 0)); h = memToVal(header.im_nlines, 2); pattern_len = memToVal(header.im_patlen, 2); max_planes = 8; nplanes = memToVal(header.im_nplanes, 2); scanwidth = memToVal(header.im_scanwidth, 2); if (nplanes == 1) { transf = transf0; image= newBitImage(w, h); if (!image) { zclose(file); return(image); } plane = 0; ptr= image->data; x = y = ByteNr = 0; height = (int) h; ScanByteBreite = (scanwidth + 7) / 8; do { xread_img (file, FALSE, 1); if (ByteNr >= ScanByteBreite) { if (ByteNr % 2 == 1) *ptr++ = 0x00; ByteNr = 0; y++; x = 0; } } while (y < height && !errorInLoad); } if ((nplanes > 1 && nplanes <= 8) || nplanes == 24) { if (nplanes <= 8) { image= newRGBImage(w, h, nplanes); if (!image) { zclose(file); return(image); } transf = transf1; colors = 1 << nplanes; } else { image= newTrueImage(w, h); if (!image) { zclose(file); return(image); } transf = transf3; colors = 0; max_planes = 24; } if (nplanes >= 2 && nplanes <= 8) { image->rgb.red[ 0]= 0xFF00; image->rgb.green[ 0]= 0xFF00; image->rgb.blue[ 0]= 0xFF00; image->rgb.red[ 1]= 0xFF00; image->rgb.green[ 1]= 0x0000; image->rgb.blue[ 1]= 0x0000; image->rgb.red[ 2]= 0x0000; image->rgb.green[ 2]= 0xFF00; image->rgb.blue[ 2]= 0x0000; image->rgb.red[ 3]= 0x0000; image->rgb.green[ 3]= 0x0000; image->rgb.blue[ 3]= 0x0000; } if (nplanes >= 3 && nplanes <= 8) { image->rgb.red[ 3]= 0xFF00; image->rgb.green[ 3]= 0xFF00; image->rgb.blue[ 3]= 0x0000; image->rgb.red[ 4]= 0x0000; image->rgb.green[ 4]= 0x0000; image->rgb.blue[ 4]= 0xFF00; image->rgb.red[ 5]= 0xFF00; image->rgb.green[ 5]= 0x0000; image->rgb.blue[ 5]= 0xFF00; image->rgb.red[ 6]= 0x0000; image->rgb.green[ 6]= 0xFF00; image->rgb.blue[ 6]= 0xFF00; image->rgb.red[ 7]= 0x0000; image->rgb.green[ 7]= 0x0000; image->rgb.blue[ 7]= 0x0000; } if (nplanes >= 4 && nplanes <= 8) { image->rgb.red[ 7]= 0xDA00; image->rgb.green[ 7]= 0xDA00; image->rgb.blue[ 7]= 0xDA00; image->rgb.red[ 8]= 0x6D00; image->rgb.green[ 8]= 0x6D00; image->rgb.blue[ 8]= 0x6D00; image->rgb.red[ 9]= 0xB600; image->rgb.green[ 9]= 0x0000; image->rgb.blue[ 9]= 0x0000; image->rgb.red[10]= 0x0000; image->rgb.green[10]= 0xB600; image->rgb.blue[10]= 0x0000; image->rgb.red[11]= 0xB600; image->rgb.green[11]= 0xB600; image->rgb.blue[11]= 0x0000; image->rgb.red[12]= 0x0000; image->rgb.green[12]= 0x0000; image->rgb.blue[12]= 0xB600; image->rgb.red[13]= 0xB600; image->rgb.green[13]= 0x0000; image->rgb.blue[13]= 0xB600; image->rgb.red[14]= 0x0000; image->rgb.green[14]= 0xB600; image->rgb.blue[14]= 0xB600; image->rgb.red[15]= 0x0000; image->rgb.green[15]= 0x0000; image->rgb.blue[15]= 0x0000; } /* colors 17 to 255 undefined in this kind of IMG-File */ image->rgb.used= colors; ptr= image->data; x = y = ByteNr = 0; height = (int) h; ScanByteBreite = (scanwidth + 7) / 8; do { for (plane= 0; plane < nplanes && !errorInLoad; plane++) { do xread_img (file, FALSE, nplanes); while (ByteNr < ScanByteBreite && !errorInLoad); ByteNr = 0; x = 0; } if (nplanes != 1) ptr += max_planes * (ScanByteBreite + (ScanByteBreite % 2)); y++; } while (y < height && !errorInLoad); } if (errorInLoad > 0) { freeImage(image); image = NULL; zclose(file); return(image); } image->title= dupString(name); zclose(file); return(image); } static int ident_ximg(name) char *name; { ZFILE *file; long size = 0; int w, h, nplanes; char extention[5]; if ((file = zopen(name)) == NULL) { printf(" Error reading XIMG!"); return(0); } size = zread(file, (byte *)&xheader, sizeof(xheader)); zclose(file); if (size < sizeof(xheader)) return (0); if (strncmp(xheader.x_id, "XIMG", 4)) /* || (xheader.color_model != 0 && xheader.color_model != 'TC')) */ return (0); w = memToVal(xheader.im_scanwidth, 2); h = memToVal(xheader.im_nlines, 2); nplanes = memToVal(xheader.im_nplanes, 2); if ((nplanes > MAX_PLANES && nplanes != 24) || nplanes == 0) { printf(depthError, xheader.im_nplanes); out_depthError = 1; return(0); } printf("%s\n is a %dx%d ",name, w, h); if (nplanes != 24) printf("RGB XIMG-file with %ld colors\n", 1<= 16) return(vdi); return(vdi2pli[vdi]); } static int pli2vdi(pli, plimax) int pli, plimax; { static char pli2vdi[] = {0, 2, 3, 6, 4, 7, 5, 8, 9, 10, 11, 14, 12, 15, 13, 1 }; if (pli == plimax-1) return(1); if (pli >= 16) return(pli); return(pli2vdi[pli]); } static Image *load_ximg(name) char *name; { void transferRGBMap(); ZFILE *file; Image *image; unsigned long w, h, nplanes, scanwidth; int i, color, colors; struct RGB_LIST { unsigned int red; unsigned int green; unsigned int blue; } rgb_list; if ((file = zopen(name)) == NULL) { printf(" Error reading XIMG!"); return(NULL); } zread(file, (byte *)&xheader, sizeof(xheader)); w = scanwidth = memToVal(xheader.im_scanwidth, 2); w = 16L * (w / 16L + (w % 16L ? 1 : 0)); h = memToVal(xheader.im_nlines, 2); nplanes = memToVal(xheader.im_nplanes, 2); pattern_len = memToVal(xheader.im_patlen, 2); max_planes = 8; if (nplanes == 1) { image= newBitImage(w, h); if (!image) { zclose(file); return(image); } transf = transf0; } if (nplanes > 1 && nplanes <= 8) { image= newRGBImage(w, h, nplanes); if (!image) { zclose(file); return(image); } transf = transf1; } colors = 1 << nplanes; if (nplanes == 24) { image= newTrueImage(w, h); if (!image) { zclose(file); return(image); } transf = transf0; nplanes = 1; colors = 0; max_planes =24; } for (color = 0; color < colors; color++) { zread (file, (byte *)&rgb_list, sizeof(rgb_list)); if (vdiColorOrder) { image->rgb.red[vdi2pli(color, colors)] = ((unsigned int) (255 * rgb_list.red / 1000)) << 8; image->rgb.green[vdi2pli(color, colors)] = ((unsigned int) (255 * rgb_list.green / 1000)) << 8; image->rgb.blue[vdi2pli(color, colors)] = ((unsigned int) (255 * rgb_list.blue / 1000)) << 8; } else { image->rgb.red[color] = ((unsigned int) (255 * rgb_list.red / 1000)) << 8; image->rgb.green[color] = ((unsigned int) (255 * rgb_list.green / 1000)) << 8; image->rgb.blue[color] = ((unsigned int) (255 * rgb_list.blue / 1000)) << 8; } } if (colors != 0) image->rgb.used= (unsigned int) 1<rgb.used= 0; ptr= image->data; x = y = ByteNr = 0; height = (int) h; if (colors != 0) ScanByteBreite = (scanwidth + 7) / 8; else ScanByteBreite = 24 * ((scanwidth + 7) / 8); do { for (plane= 0; plane < nplanes && !errorInLoad; plane++) { do xread_img (file, FALSE, nplanes); while (ByteNr < ScanByteBreite && !errorInLoad); if (nplanes == 1 && ByteNr % 2 == 1) *ptr++ = 0x00; ByteNr = 0; x = 0; } if (nplanes != 1) ptr += max_planes * (ScanByteBreite + (ScanByteBreite % 2)); y++; } while (y < height && !errorInLoad); if (errorInLoad > 0) { freeImage(image); image = NULL; zclose(file); return(image); } image->title= dupString(name); zclose(file); return(image); } int imgIdent(name, name2, verbose) char *name; char *name2; int verbose; { int identified; if ((identified = ident_ximg(name)) != 0) return(identified); identified = ident_img(name); return(identified); } Image *imgLoad(name, name2, verbose) char *name; char *name2; int verbose; { errorInLoad = 0; out_depthError = 0; if (ident_ximg(name) != 0) return(load_ximg(name)); if (ident_img(name) != 0) return(load_img(name)); return(NULL); } yteNr >= ScanByteBreite) { if (ByteNr % 2 == 1) *ptr++ = 0x00; ByteNr = 0; y++; x = 0; } } while (y < height && !errorInLoad); } if ((nplanes > 1 && nplanes <= 8) || nplanes == 24) { if (nplanes <= 8) { image= newRGBImage(w, h, nplanes); if (!image) { zclosexloadimage.4.1/mac.c 664 221 144 11673 5461577407 7513 /* * mac.c: * * adapted from code by Patrick Naughton (naughton@sun.soe.clarkson.edu) * * macin.c * Mark Majhor * August 1990 * * routines for reading MAC files * * Copyright 1990 Mark Majhor (see the included file * "mrmcpyrght.h" for complete copyright information) */ /* Edit History 04/15/91 2 nazgul Check for end of file instead of using -1 as a runlength! */ # include # include # include # include "image.h" # include "mac.h" /**** ** ** local variables ** ****/ static BYTE file_open = 0; /* status flags */ static BYTE image_open = 0; static ZFILE *ins; /* input stream */ /**** ** ** global variables ** ****/ static int macin_img_width; /* image width */ static int macin_img_height; /* image height */ static int macin_img_depth; /* image depth */ static int macin_img_planes; /* image planes */ static int macin_img_BPL; /* image bytes per line */ /* * open MAC image in the input stream; returns MACIN_SUCCESS if * successful. (might also return various MACIN_ERR codes.) */ /* ARGSUSED */ static int macin_open_image(s) ZFILE *s; { BYTE mhdr[MAC_HDR_LEN]; char *hp; /* header pointer */ /* make sure there isn't already a file open */ if (file_open) return(MACIN_ERR_FAO); /* remember that we've got this file open */ file_open = 1; ins = s; /* * the mac paint files that came with xmac had an extra * 128 byte header on the front, with a image name in it. * true mac paint images don't seem to have this extra * header. The following code tries to figure out what * type the image is and read the right amount of file * header (512 or 640 bytes). */ /* read in the mac file header */ hp = (char *) mhdr; if (zread(ins, (byte *)hp, ADD_HDR_LEN) != ADD_HDR_LEN) return MACIN_ERR_EOF; if (mhdr[0] != MAC_MAGIC) return MACIN_ERR_BAD_SD; /* Get image name (if available) */ if (mhdr[1] != 0) { /* if name header */ if (zread(ins, (byte *)hp, MAC_HDR_LEN) != MAC_HDR_LEN) return MACIN_ERR_EOF; } else /* else read rest of header */ if (zread(ins, (byte *)hp, MAC_HDR_LEN - ADD_HDR_LEN) != MAC_HDR_LEN - ADD_HDR_LEN) return MACIN_ERR_EOF; /* Now set relevant values */ macin_img_width = BYTES_LINE * 8; macin_img_height = MAX_LINES; macin_img_depth = 1; /* always monochrome */ macin_img_planes = 1; /* always 1 */ macin_img_BPL = BYTES_LINE; return MACIN_SUCCESS; } /* * close an open MAC file */ static int macin_close_file() { /* make sure there's a file open */ if (!file_open) return MACIN_ERR_NFO; /* mark file (and image) as closed */ file_open = 0; image_open = 0; /* done! */ return MACIN_SUCCESS; } #if 0 /* * semi-graceful fatal error mechanism */ static macin_fatal(msg) char *msg; { printf("Error reading MacPaint file: %s\n", msg); exit(0); } #endif /* * these are the routines added for interfacing to xloadimage */ /* * tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(name) char *name; { printf("%s is a %dx%d MacPaint image\n", name, macin_img_width, macin_img_height); } Image *macLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; Image *image; BYTE *pixptr, ch; int eof; register int scanLine; register unsigned int i, j, k; if (! (zf = zopen(fullname))) return(NULL); if (macin_open_image(zf) != MACIN_SUCCESS) { /* read image header */ macin_close_file(); zclose(zf); return(NULL); } image = newBitImage(macin_img_width, macin_img_height); pixptr = &(image->data[0]); scanLine = 0; k = 0; while (scanLine < macin_img_height) { if ((eof = zgetc(zf)) == -1) break; ch = (BYTE) eof; /* Count byte */ i = (unsigned int) ch; if (ch < 0x80) { /* Unpack next (I+1) chars as is */ for (j = 0; j <= i; j++) { if (scanLine < macin_img_height) { if ((eof = zgetc(zf)) == -1) break; *pixptr++ = (BYTE) eof; k++; if (!(k %= BYTES_LINE)) { scanLine++; } } } } else { /* Repeat next char (2's comp I) times */ if ((eof = zgetc(zf)) == -1) break; ch = (BYTE) eof; for (j = 0; j <= 256 - i; j++) { if (scanLine < macin_img_height) { *pixptr++ = (BYTE) ch; k++; if (!(k %= BYTES_LINE)) { scanLine++; } } } } } if (scanLine < macin_img_height) { zclose(zf); return NULL; } macin_close_file(); if (verbose) tellAboutImage(name); zclose(zf); image->title = dupString(name); return(image); } int macIdent(fullname, name) char *fullname, *name; { ZFILE *zf; unsigned int ret; if (! (zf = zopen(fullname))) return(0); if (macin_open_image(zf) == MACIN_SUCCESS) { tellAboutImage(name); ret = 1; } else ret = 0; macin_close_file(); zclose(zf); return(ret); } MACIN_SUCCESS; } /* * close an open MAC file */ static int macin_xloadimage.4.1/mcidas.c 664 221 144 10660 5461577407 10206 /* mcidas.c: * * McIDAS areafile support. contributed by Glenn P. Davis * (davis@unidata.ucar.edu). */ #include "xloadimage.h" #include "mcidas.h" char *mc_sensor(); static struct { int days; char *name; } month_info[13] = { { 0, "Pad" }, { 31, "Jan" }, { 29, "Feb" }, /* longest */ { 31, "Mar" }, { 30, "Apr" }, { 31, "May" }, { 30, "Jun" }, { 31, "Jul" }, { 31, "Aug" }, { 30, "Sep" }, { 31, "Oct" }, { 30, "Nov" }, { 31, "Dec" } }; /* convert numeric dates to human-readable */ static char *convert_date(time, date) int time, date; { static char buf[30]; int hour; int minute; int second; int year; int month; int day; year = date / 1000; if (year > 50) /* gives us a range from 1950 - 2050, probably good enough */ year += 1900; else year += 2000; day = date % 1000; /* adjust day for non-leap-years if necessary */ if ((day > 31 + 28) && ((year % 4) || (year == 2000))) day++; /* find month in year that this day falls in */ for (month= 1; day > month_info[month].days; day -= month_info[month].days) month++; /* break time-of-day up */ hour = time / 10000; minute = (time % 10000) / 100; second = (time % 100); sprintf(buf, "%d:%2.2d:%2.2d %s %d, %d (day %d)", hour, minute, second, month_info[month].name, day, year, (date % 1000)); return(buf); } /* * convert from little endian to big endian four byte object */ static unsigned long vhtonl(lend) unsigned long lend ; { unsigned long bend ; unsigned char *lp, *bp ; lp = ((unsigned char *)&lend) + 3 ; bp = (unsigned char *) &bend ; *bp++ = *lp-- ; *bp++ = *lp-- ; *bp++ = *lp-- ; *bp = *lp ; return(bend) ; } static void babble(name, dir) char *name; struct area_dir *dir; { printf("%s is a %dx%d McIDAS areafile from %s at %s (%d, %d) (%d, %d)\n", name, dir->esiz, dir->lsiz, mc_sensor(dir->satid), convert_date(dir->itime, dir->idate), dir->lcor, dir->ecor, dir->lres, dir->eres) ; } static void swap_bytes(dir) struct area_dir *dir; { unsigned long *begin ; unsigned long *ulp ; begin = (unsigned long *)dir ; for(ulp = begin ; ulp < &begin[AREA_COMMENTS] ; ulp++) *ulp = vhtonl(*ulp) ; for(ulp = &begin[AREA_CALKEY] ; ulp < &begin[AREA_STYPE] ; ulp++) *ulp = vhtonl(*ulp) ; } /* ARGSUSED */ int mcidasIdent(fullname, name) char *fullname, *name; { ZFILE *zf; struct area_dir dir ; int r; if (! (zf= zopen(fullname))) { perror("mcidasIdent"); return(0); } switch (zread(zf, (byte *)&dir, sizeof(struct area_dir))) { case -1: perror("mcidasIdent"); r= 0; break; case sizeof(struct area_dir): if (memToValLSB((char *)&dir.type, 4) != 4) { r= 0; break; } if (dir.type != 4) swap_bytes(&dir); babble(name, &dir); r= 1; break; default: r= 0; break; } zclose(zf); return(r); } Image *mcidasLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; struct area_dir dir; struct navigation nav; Image *image; unsigned int y; int doswap = 0 ; if (! (zf= zopen(fullname))) { perror("mcidasLoad"); return(NULL); } switch (zread(zf, (byte *)&dir, sizeof(struct area_dir))) { case -1: perror("mcidasLoad"); zclose(zf); exit(1); case sizeof(struct area_dir): if (memToValLSB((char *)&dir.type, 4) != 4) { zclose(zf); return(NULL) ; } if (dir.type != 4) swap_bytes(&dir); break; default: zclose(zf); return(NULL); } if (verbose) babble(name, &dir); znocache(zf); /* skip the nav */ if( zread(zf, (byte *)&nav, sizeof(struct navigation)) != sizeof(struct navigation)) { zclose(zf); return(NULL) ; } /* get an image to put the data in */ image= newRGBImage(dir.esiz, dir.lsiz, dir.zsiz * 8); /* set up the colormap, linear grey scale */ for (y= 0; y < image->rgb.size; y++) { *(image->rgb.red + y)= *(image->rgb.green + y)= *(image->rgb.blue + y)= y * (65536 / image->rgb.size) ; } image->rgb.used= image->rgb.size ; /* read the first band from the image and warn if there are other bands * we can't read. */ zread(zf, image->data, dir.esiz * dir.lsiz * dir.zsiz) ; if (dir.bands > 1) printf("Warning: Only showing first of %d bands\n", dir.bands); zclose(zf); image->title= dupString(name); return(image); } char *name; char *name2; int verbose; { errorInLoad = 0; oxloadimage.4.1/mc_tables.c 664 221 144 4661 5461577407 10663 /* * From McIDAS Reference Manual * Introduction - pg 21 * Table 1, UD-14 9/88, * * Given the "SS Code" (word three of the area directory) * return a string describing the sensor source. * */ char * mc_sensor(sscode) int sscode ; { switch (sscode) { case 0 : return("Non-Image Derived Data") ; case 1 : return("Test patterns") ; case 2 : return("Graphics") ; case 3 : return("Miscellaneous") ; case 4 : return("PDUS Meteosat Visible") ; case 5 : return("PDUS Meteosat Infrared") ; case 6 : return("PDUS Meteosat Water Vapor") ; case 7 : return("Radar") ; case 8 : return("Miscellaneous Aircraft Data (MAMS)") ; case 12 : return("GMS Visible") ; case 13 : return("GMS Infrared") ; case 14 : return("ATS 6 Visible") ; case 15 : return("ATS 6 Infrared") ; case 16 : return("SMS-1 Visible") ; case 17 : return("SMS-1 Infrared") ; case 18 : return("SMS-2 Visible") ; case 19 : return("SMS-2 Infrared") ; case 20 : return("GOES-1 Visible") ; case 21 : return("GOES-1 Infrared") ; case 22 : return("GOES-2 Visible") ; case 23 : return("GOES-2 Infrared") ; case 24 : return("GOES-3 Visible") ; case 25 : return("GOES-3 Infrared") ; case 26 : return("GOES-4 Visible (VAS)") ; case 27 : return("GOES-4 Infrared and Water Vapor (VAS)") ; case 28 : return("GOES-5 Visible (VAS)") ; case 29 : return("GOES-5 Infrared and Water Vapor (VAS)") ; case 30 : return("GOES-6 Visible") ; case 31 : return("GOES-6 Infrared") ; case 32 : return("GOES-Visible, Block 1 Auxiliary Data") ; case 33 : return("GOES-7 Infrared") ; case 34 : case 36 : case 37 : case 38 : case 39 : case 40 : return("NOAA Series Satellites") ; case 41 : return("TIROS-N") ; case 42 : return("NOAA-6") ; case 43 : return("NOAA-7") ; case 44 : return("NOAA-8") ; case 45 : return("NOAA-9") ; case 46 : return("Venus") ; case 47 : return("Voyager 1") ; case 48 : return("Voyager 2") ; case 50 : return("Hubble St.") ; case 60 : return("NOAA-10") ; case 61 : return("NOAA-11") ; case 70 : return("GOES-I (IMAGER)") ; case 71 : return("GOES-I (SOUNDER)") ; case 72 : return("GOES-J (IMAGER)") ; case 73 : return("GOES-J (SOUNDER)") ; case 74 : return("GOES-K (IMAGER)") ; case 75 : return("GOES-K (SOUNDER)") ; case 76 : return("GOES-L (IMAGER)") ; case 77 : return("GOES-L (SOUNDER)") ; case 78 : return("GOES-M (IMAGER)") ; case 79 : return("GOES-M (SOUNDER)") ; case 80 : return("ERBE") ; case 90 : return("RAW METEOSAT") ; } return("Unknown") ; } (! (zf= zopen(fullname))) { perror("mcidasIdent"); return(0); } swxloadimage.4.1/pbm.c 664 221 144 32772 5464001743 7520 /* pbm.c: * * portable bit map (pbm) format images * * jim frost 09.27.89 * * patched by W. David Higgins (wdh@mkt.csd.harris.com) to support * raw-format PBM files. * * patched by Ian MacPhedran (macphed@dvinci.usask.ca) to support * PGM and PPM files (03-July-1990) */ #include "image.h" #include "pbm.h" /* SUPPRESS 558 */ static int IntTable[256]; static unsigned int Initialized= 0; #define NOTINT -1 #define COMMENT -2 #define SPACE -3 #define NEWLINE -4 #define BADREAD 0 /* read error */ #define NOTPBM 1 /* not a pbm file */ #define PBMNORMAL 2 /* pbm normal type file */ #define PBMCOMPACT 3 /* pbm compacty type file */ #define PBMRAWBITS 4 /* pbm raw bits type file */ #define PGMNORMAL 5 /* pgm normal type file */ #define PGMRAWBITS 6 /* pgm raw bytes type file */ #define PPMNORMAL 7 /* ppm normal type file */ #define PPMRAWBITS 8 /* ppm raw bytes type file */ static void initializeTable() { unsigned int a; for (a= 0; a < 256; a++) IntTable[a]= NOTINT; IntTable['#']= COMMENT; IntTable['\n']= NEWLINE; IntTable['\r']= IntTable['\t']= IntTable[' ']= SPACE; IntTable['0']= 0; IntTable['1']= 1; IntTable['2']= 2; IntTable['3']= 3; IntTable['4']= 4; IntTable['5']= 5; IntTable['6']= 6; IntTable['7']= 7; IntTable['8']= 8; IntTable['9']= 9; Initialized= 1; } static int pbmReadChar(zf) ZFILE *zf; { int c; if ((c= zgetc(zf)) == EOF) { zclose(zf); return(-1); } if (IntTable[c] == COMMENT) do { if ((c= zgetc(zf)) == EOF) return(-1); } while (IntTable[c] != NEWLINE); return(c); } static int pbmReadInt(zf) ZFILE *zf; { int c, value; for (;;) { c= pbmReadChar(zf); if (c < 0) return(-1); if (IntTable[c] >= 0) break; }; value= IntTable[c]; for (;;) { c= pbmReadChar(zf); if (c < 0) return(-1); if (IntTable[c] < 0) return(value); value= (value * 10) + IntTable[c]; } } static int isPBM(zf, name, width, height, maxval, verbose) ZFILE *zf; char *name; int *width, *height, *maxval; unsigned int verbose; { byte buf[4]; if (! Initialized) initializeTable(); if (zread(zf, buf, 2) != 2) return(NOTPBM); if (memToVal((byte *)buf, 2) == memToVal((byte *)"P1", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = 1; if (verbose) printf("%s is a %dx%d PBM image\n", name, *width, *height); return(PBMNORMAL); } if (memToVal((byte *)buf, 2) == memToVal((byte *)"P4", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = 1; if (verbose) printf("%s is a %dx%d RawBits PBM image\n", name, *width, *height); return(PBMRAWBITS); } if (memToVal(buf, 2) == 0x2a17) { if (zread(zf, buf, 4) != 4) return(NOTPBM); *width= memToVal((byte *)buf, 2); *height= memToVal((byte *)(buf + 2), 2); *maxval = 1; if (verbose) printf("%s is a %dx%d Compact PBM image\n", name, *width, *height); return(PBMCOMPACT); } if (memToVal(buf, 2) == memToVal((byte *)"P2", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = pbmReadInt(zf); if (verbose) printf("%s is a %dx%d PGM image with %d levels\n", name, *width, *height, (*maxval+1)); return(PGMNORMAL); } if (memToVal(buf, 2) == memToVal((byte *)"P5", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = pbmReadInt(zf); if (verbose) printf("%s is a %dx%d Raw PGM image with %d levels\n", name, *width, *height, (*maxval+1)); return(PGMRAWBITS); } if (memToVal(buf, 2) == memToVal((byte *)"P3", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = pbmReadInt(zf); if (verbose) printf("%s is a %dx%d PPM image with %d levels\n", name, *width, *height, (*maxval+1)); return(PPMNORMAL); } if (memToVal(buf, 2) == memToVal((byte *)"P6", 2)) { if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) return(NOTPBM); *maxval = pbmReadInt(zf); if (verbose) printf("%s is a %dx%d Raw PPM image with %d levels\n", name, *width, *height, (*maxval+1)); return(PPMRAWBITS); } return(NOTPBM); } int pbmIdent(fullname, name) char *fullname, *name; { ZFILE *zf; int width, height, maxval, ret; if (! (zf= zopen(fullname))) return(0); ret= isPBM(zf, name, &width, &height, &maxval, (unsigned int)1); zclose(zf); return(ret != NOTPBM); } Image *pbmLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; Image *image; int pbm_type; int x, y; int width, height, maxval, depth; unsigned int linelen; byte srcmask, destmask; byte *destptr, *destline; int src, size; int red, grn, blu; if (! (zf= zopen(fullname))) return(NULL); pbm_type= isPBM(zf, name, &width, &height, &maxval, verbose); if (pbm_type == NOTPBM) { zclose(zf); return(NULL); } znocache(zf); switch (pbm_type) { case PBMNORMAL: image= newBitImage(width, height); linelen= (width / 8) + (width % 8 ? 1 : 0); destline= image->data; for (y= 0; y < height; y++) { destptr= destline; destmask= 0x80; for (x= 0; x < width; x++) { do { if ((src= pbmReadChar(zf)) < 0) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } if (IntTable[src] == NOTINT) { fprintf(stderr, "%s: Bad image data\n", fullname); zclose(zf); return(image); } } while (IntTable[src] < 0); switch (IntTable[src]) { case 1: *destptr |= destmask; case 0: if (! (destmask >>= 1)) { destmask= 0x80; destptr++; } break; default: fprintf(stderr, "%s: Bad image data\n", fullname); zclose(zf); return(image); } } destline += linelen; } break; case PBMRAWBITS: image= newBitImage(width, height); destline= image->data; linelen= (width + 7) / 8; srcmask= 0; /* force initial read */ for (y= 0; y < height; y++) { destptr= destline; destmask= 0x80; if (srcmask != 0x80) { srcmask= 0x80; src= zgetc(zf); if (src == EOF) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } } for (x= 0; x < width; x++) { if (src & srcmask) *destptr |= destmask; if (! (destmask >>= 1)) { destmask= 0x80; destptr++; } if (! (srcmask >>= 1)) { srcmask= 0x80; src = zgetc(zf); if (src == EOF) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } } } destline += linelen; } break; case PBMCOMPACT: image= newBitImage(width, height); destline= image->data; linelen= (width / 8) + (width % 8 ? 1 : 0); srcmask= 0x80; destmask= 0x80; src = zgetc(zf); if (src == EOF) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } for (y= 0; y < height; y++) { destptr= destline; destmask= 0x80; for (x= 0; x < width; x++) { if (src & srcmask) *destptr |= destmask; if (! (destmask >>= 1)) { destmask= 0x80; destptr++; } if (! (srcmask >>= 1)) { srcmask= 0x80; src = zgetc(zf); if (src == EOF) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } } } destline += linelen; } break; case PGMRAWBITS: depth= colorsToDepth(maxval); if (depth > 8) image = newTrueImage(width, height); else { image = newRGBImage(width, height, depth); for (y = 0; y <= maxval; y++) { /* As in sunraster.c, use simple ramp for grey scale */ *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff); *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff); *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff); } image->rgb.used = maxval+1; } size= height * width; switch (image->type) { case IRGB: /* read in the image in a chunk */ if (zread(zf, image->data, size) != size) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); freeImage(image); return(NULL); } break; case ITRUE: destptr = image->data; for (y = 0; y < size; y++) { if ((src = zgetc(zf)) == EOF) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); freeImage(image); return(NULL); } src = PM_SCALE(src, maxval, 0xff); *(destptr++) = src; /* red */ *(destptr++) = src; /* green */ *(destptr++) = src; /* blue */ } break; } break; case PGMNORMAL: depth= colorsToDepth(maxval); if (depth > 8) image= newTrueImage(width, height); else { image= newRGBImage(width, height, depth); for (y= 0; y <= maxval; y++) { /* As in sunraster.c, use simple ramp for grey scale */ *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff); *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff); *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff); } image->rgb.used = maxval+1; } destptr= image->data; size= height * width; for (y= 0; y < size; y++) { if ((src = pbmReadInt(zf)) < 0) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } else { if (TRUEP(image)) { src= PM_SCALE(src, maxval, 0xff); *(destptr++) = src; /* red */ *(destptr++) = src; /* green */ *(destptr++) = src; /* blue */ } else *(destptr++) = src; } } break; case PPMRAWBITS: /* this is nice because the bit format is exactly what we want except * for scaling. */ image= newTrueImage(width, height); size= height * width * 3; if (zread(zf, image->data, size) != size) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); freeImage(image); return(NULL); } destptr= image->data; for (y= 0; y < size; y++) { *destptr= PM_SCALE(*destptr, maxval, 0xff); destptr++; } break; case PPMNORMAL: image= newTrueImage(width, height); size= height * width; destptr= image->data; for (y= 0; y < size; y++) { if (((red= pbmReadInt(zf)) == EOF) || ((grn= pbmReadInt(zf)) == EOF) || ((blu= pbmReadInt(zf)) == EOF)) { fprintf(stderr, "%s: Short image\n", fullname); zclose(zf); return(image); } *(destptr++)= PM_SCALE(red, maxval, 0xff); *(destptr++)= PM_SCALE(grn, maxval, 0xff); *(destptr++)= PM_SCALE(blu, maxval, 0xff); } break; } image->title= dupString(name); zclose(zf); return(image); } void pbmDump(image, options, file, verbose) Image *image; char *options; char *file; int verbose; { FILE *f; byte *srcptr; int srclinelen; int x, y; int normal = 0; /* raw by default */ int white, black; int mask; Pixel pixval; int pixlen; char *name, *value; while (getNextTypeOption(&options, &name, &value) > 0) { if (!strncmp("normal", name, strlen(name))) normal = 1; else if (!strncmp("raw", name, strlen(name))) normal = 0; else fprintf(stderr, "pbmDump: unknown option '%s'\n", name); } f = fopen(file, "w"); if (f == NULL) { perror(file); return; } srcptr = image->data; switch (image->type) { case IBITMAP: if (verbose) printf("Dumping %sPBM image to %s.\n", (normal ? "" : "RawBits "), file); if (image->rgb.red[1] > image->rgb.red[0]) { white = 1; black = 0; } else { white = 0; black = 1; } if (normal) { fprintf(f, "P1 %d %d\n", image->width, image->height); mask = 0x80; for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { fprintf(f, "%d ", (*srcptr & mask ? black : white)); mask >>= 1; if (mask == 0) { mask = 0x80; srcptr++; } } } } else { srclinelen = (image->width / 8) + (image->width % 8 ? 1 : 0); fprintf(f, "P4 %d %d\n", image->width, image->height); for (y = 0; y < image->height; y++) { if (black == 1) { fwrite(srcptr, srclinelen, 1, f); srcptr += srclinelen; } else for (x = 0; x < image->width; x++) fputc(*(srcptr++) ^ 0xff, f); } } break; case IRGB: if (verbose) printf("Dumping %sPPM image to %s.\n", (normal ? "" : "RawBits "), file); /* technically we could dump this with 2-byte values but that's * a lot bigger and most of the readers don't support it anyway. */ fprintf(f, "P%c %d %d 255\n", (normal ? '3' : '6'), image->width, image->height); pixlen = image->pixlen; for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { pixval = memToVal(srcptr, pixlen); srcptr += pixlen; fprintf(f, (normal ? "%d %d %d " : "%c%c%c"), image->rgb.red[pixval] >> 8, image->rgb.green[pixval] >> 8, image->rgb.blue[pixval] >> 8); } } break; case ITRUE: if (verbose) printf("Dumping %sPPM image to %s.\n", (normal ? "" : "RawBits "), file); fprintf(f, "P%c %d %d 257\n", (normal ? '3' : '6'), image->width, image->height); for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { if (normal) { fprintf(f, "%d %d %d ", *srcptr, *(srcptr + 1), *(srcptr + 2)); srcptr += 3; } else { fputc(*(srcptr++), f); fputc(*(srcptr++), f); fputc(*(srcptr++), f); } } } break; } fclose(f); } ) { xloadimage.4.1/pcx.c 664 221 144 25440 5463770664 7544 /* ** pcx.c - load a ZSoft PC Paintbrush (PCX) file for use inside xloadimage ** ** Tim Northrup ** Adapted from code by Jef Poskanzer (see Copyright below). ** ** Version 0.1 -- 4/25/91 -- Initial cut ** ** Copyright (c) 1991 Tim Northrup ** (see file "tgncpyrght.h" for complete copyright information) */ /* ** Copyright (C) 1988 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. ** ** This program (pcxtopbm) is based on the pcx2rf program by: ** Mike Macgirvin ** Stanford Relativity Gyro Program GP-B ** Stanford, Calif. 94503 ** ARPA: mike@relgyro.stanford.edu */ #include #include "image.h" #include "tgncpyrght.h" #include "pcx.h" /* ** pcxIdent ** ** Identify passed file as a PC Paintbrush image or not ** ** Returns 1 if file is a PCX file, 0 otherwise */ unsigned int pcxIdent ( fullname, name ) char *fullname, *name; { ZFILE *zf; unsigned int ret; int xmin; int xmax; int ymin; int ymax; int colors; char *type; ret = 0; if (! (zf = zopen ( fullname ))) return ( 0 ); PCXH = (PCXHeader *) lmalloc ( PCXHsize ); if (zread ( zf, (byte *)PCXH, PCXHsize ) == PCXHsize) { if ((PCXH->Zid == PCX_MAGIC) && (PCXH->Zver <= 5)) { xmin = Word ( PCXH->Zxminlo, PCXH->Zxminhi); xmax = Word ( PCXH->Zxmaxlo, PCXH->Zxmaxhi); ymin = Word ( PCXH->Zyminlo, PCXH->Zyminhi); ymax = Word ( PCXH->Zymaxlo, PCXH->Zymaxhi); xmax = xmax - xmin + 1; ymax = ymax - ymin + 1; colors = 1 << (PCXH->Zbpp * PCXH->Znplanes); type = " PC Paintbrush image\n"; if (colors == 2) printf ( "%s is a %dx%d monochrome%s", name, xmax, ymax, type ); else printf ( "%s is a %dx%d %d color%s", name, xmax, ymax, colors, type ); ret = 1; } } zclose ( zf ); lfree ( (byte *)PCXH ); return ( ret ); } /* ** PCX_Load_Raster ** ** Load raster image data into passed image structure. Raster Data ** ** means : Every bit is a pixel (if depth is 1) or every byte is a ** ** pixel (if depth is 8). ** ** Returns no value (void function) */ static void PCX_Load_Raster ( zf, image, depth ) ZFILE *zf; Image *image; int depth; /* Assertion : depth is 1 or 8 */ { byte *ptr = &(image->data[0]); int row = 0; int by_this_row = 0; int by_per_row; int linelen; int corrector; int i, b, cnt; by_per_row = Word ( PCXH->Zbprlo, PCXH->Zbprhi); if (depth == 1) linelen = (image->width / 8) + (image->width % 8 ? 1 : 0); else linelen = image->width; corrector = by_per_row - linelen; /* bytes per row is always even, which means that there is an */ /* excess byte if an odd nr of bytes would be sufficient. */ /* As newBitImage allocated memory without this excess, we have */ /* to read one less. But as there are two cases of reading, */ /* inside and outside of a run, I correct it afterwards, when */ /* the line is complete. */ while ((b = zgetc(zf)) != EOF) { /* Are we done ? */ if ((b & 0xC0) == 0xC0) { /* have a rep. count */ cnt = b & 0x3F; /* mask rep. bits out */ b = zgetc ( zf ); /* get real bits */ if (b == EOF) { /* Shouldn't happen ! */ printf ( "Unexpected EOF\n" ); return; } } else cnt = 1; /* no repeating this one*/ if (depth ==1) b = 255 - b; /* Have to invert */ for ( i = 0; i < cnt; i++ ) { /* store count times */ *ptr++ = (byte) b; if (++by_this_row == by_per_row) { row++; /* start of a new line */ by_this_row = 0; /* reset counter */ if (corrector) ptr--; /*evtlly correct pointer*/ if ( row >= image->height ) { #if 0 /* happens a lot on valid images - jimf 10.28.91 */ if (depth == 1) /* Color : Map follows */ printf ("Warning: excess data ignored\n"); #endif return; } } } } } /* ** PCX_Planes ** ** Load plane image data into passed image structure. Plane data ** ** means : There are N planes, each containing M bits of a pixel ** ** byte, where N * M is not greater than 8 and M divides 8. (The ** ** cases M = 1 or 8, N = 1 are covered by PCX_Load_Raster). ** ** Returns no value (void function) */ static void PCX_Planes ( zf, image, bpp, nr_pl ) ZFILE *zf; Image *image; int bpp, nr_pl; /* Assertion : */ /* bpp is 1, 2 or 4 only, dividing 8 without remainder anyways, */ /* bpp * nr_pl <= 8 */ { byte *ptr, *sptr; register byte *tptr; int row = 0; int by_this_row = 0; int by_per_row; int this_plane = 0; int shifter = 0; register int j; int i, b, cnt; ptr = &(image->data[0]); by_per_row = Word ( PCXH->Zbprlo, PCXH->Zbprhi); sptr = tptr = (byte *) lcalloc ( by_per_row*8 ); /* We can't correct as easy as above, because we handle several */ /* bit planes simultaneously, and we must not load beyond row */ /* limits. So we load into a temporary row and copy it into */ /* image structure when the row is completed. */ while ((b = zgetc(zf)) != EOF) { if ((b & 0xC0) == 0xC0) { /* Get count and data as above */ cnt = b & 0x3F; b = zgetc ( zf ); if (b == EOF) { printf ( "Unexpected EOF\n" ); return; } } else cnt = 1; for ( i = 0; i < cnt; i++ ) { /* Load data into temp. */ switch (bpp) { case 1 : *tptr++ |= (byte) (((b & 0x80 ) >> 7) << shifter); *tptr++ |= (byte) (((b & 0x40 ) >> 6) << shifter); *tptr++ |= (byte) (((b & 0x20 ) >> 5) << shifter); *tptr++ |= (byte) (((b & 0x10 ) >> 4) << shifter); *tptr++ |= (byte) (((b & 0x08 ) >> 3) << shifter); *tptr++ |= (byte) (((b & 0x04 ) >> 2) << shifter); *tptr++ |= (byte) (((b & 0x02 ) >> 1) << shifter); *tptr++ |= (byte) ((b & 0x01 ) << shifter); /* This is not a loop for performance reasons. */ /* Can't write e.g. ">> 2 - shifter", because */ /* that expression would get negative. */ break; case 2 : *tptr++ |= (byte) (((b & 0xC0 ) >> 6) << shifter); *tptr++ |= (byte) (((b & 0x30 ) >> 4) << shifter); *tptr++ |= (byte) (((b & 0x0C ) >> 2) << shifter); *tptr++ |= (byte) ((b & 0x03 ) << shifter); break; case 4 : *tptr++ |= (byte) (((b & 0xF0) >> 4) << shifter); *tptr++ |= (byte) ((b & 0x0F) << shifter); break; default :; /* Can't happen if assertion holds */ } if (++by_this_row == by_per_row) { /* Row done ? */ by_this_row = 0; /* reset counter */ if (++this_plane == nr_pl) { /* was it last plane ? */ row++; /* inc counter */ tptr = sptr; /* get saved ptr */ this_plane = shifter = 0;/* reset plane Nr */ for (j = 0; j < image->width; j++) { *ptr++ = *tptr; /* store final data */ *tptr++ = 0; /* clear temp data */ } if ( row >= image->height ) return; /* Done with image ? */ } else /* Prepare next plane */ shifter = this_plane * bpp; tptr = sptr; /* Get saved ptr */ } } } } /* ** PCX_LoadImage ** ** Load PC Paintbrush file into the passed Image structure. ** ** Returns no value (void function) */ static void PCX_LoadImage ( zf ,image ) ZFILE *zf; Image *image; { int pl; switch (PCXH->Zbpp) { /* What kind of plane do we have ? */ case 1 : /* Bit planes */ if (PCXH->Znplanes == 1) /* Only one : Read it */ PCX_Load_Raster ( zf, image, 1 ); else PCX_Planes ( zf, image, 1, PCXH->Znplanes ); break; case 2 : /* Two or four bits per plane */ case 4 : /* are read plane by plane */ PCX_Planes ( zf, image, PCXH->Zbpp, PCXH->Znplanes ); break; case 8 : /* Byte planes */ if (PCXH->Znplanes == 1) /* Only one : Read it */ PCX_Load_Raster ( zf, image, 8 ); else { /* More not allowed */ printf ("Only 1 plane allowed if 8 bits per plane\n"); exit (1); } break; default : /* Neither case found */ printf ("%d bits per plane not supported\n", PCXH->Zbpp ); exit (1); } } /* ** pcxLoad ** ** Load PCX Paintbrush file into an Image structure. ** ** Returns pointer to allocated struct if successful, NULL otherwise */ Image *pcxLoad ( fullname, name, verbose ) char *fullname, *name; unsigned int verbose; { ZFILE *zf; unsigned int i, ret; int xmin; int xmax; int ymin; int ymax; int colors; PCXcolor *cmap; int clen; Image *image; if ( ! (zf = zopen ( fullname ))) /* Open input file */ return ( (Image *) NULL); PCXH = (PCXHeader *) lmalloc ( PCXHsize ); if (zread ( zf, (byte *)PCXH, PCXHsize ) != PCXHsize) { /* Read header */ zclose ( zf ); return ( (Image *) NULL ); } if ((PCXH->Zid != PCX_MAGIC) || (PCXH->Zver > 5)) { zclose ( zf ); /* Is it PCX, Version less 5 ? */ return ( (Image *) NULL ); } znocache(zf); /* don't need caching anymore */ xmin = Word ( PCXH->Zxminlo, PCXH->Zxminhi); /* Calculate sizes */ xmax = Word ( PCXH->Zxmaxlo, PCXH->Zxmaxhi); ymin = Word ( PCXH->Zyminlo, PCXH->Zyminhi); ymax = Word ( PCXH->Zymaxlo, PCXH->Zymaxhi); xmax = xmax - xmin + 1; ymax = ymax - ymin + 1; colors = 1 << (PCXH->Zbpp * PCXH->Znplanes); /* Calculate colors*/ if (verbose) { /* Print Information */ if (colors == 2) printf ( "%s is a %dx%d monochrome PC Paintbrush image\n", name, xmax, ymax ); else printf ( "%s is a %dx%d %d color PC Paintbrush image\n", name, xmax, ymax, colors ); } if (colors > 256) { printf ( "No more than 256 colors allowed in PCX format\n" ); exit (1); } if (PCXH->Zenc == 0) { printf ( "Unencoded PCX format not yet supported. Please" ); printf ( " email the uuencoded image\n to erueg@cfgauss." ); printf ( "uni-math.gwdg.de\n" ); exit (1); } if (colors == 2) /* Allocate appropriate pbm array */ image = newBitImage ( xmax, ymax ); else { image = newRGBImage ( xmax, ymax, 8 ); } PCX_LoadImage ( zf, image ); if (colors > 16) { /* Handle external colormap */ while ((i = zgetc(zf)) != PCX_MAPSTART); clen = colors * 3; cmap = (PCXcolor *) lmalloc ( clen ); if (zread ( zf, (byte *)cmap, clen ) != clen) { printf ( "EOF while reading colormap" ); exit (1); } for ( i = 0; i < colors; i++) { *(image->rgb.red + i) = (cmap [i].Zred << 8); *(image->rgb.green + i) = (cmap [i].Zgreen << 8); *(image->rgb.blue + i) = (cmap [i].Zblue << 8); } image->rgb.used = colors; lfree ( (byte *)cmap ); } else if (colors > 2) { /* Handle internal colormap */ for ( i = 0; i < colors; i++) { *(image->rgb.red + i) = (PCXH->Zcmap [i].Zred << 8); *(image->rgb.green + i) = (PCXH->Zcmap [i].Zgreen << 8); *(image->rgb.blue + i) = (PCXH->Zcmap [i].Zblue << 8); } image->rgb.used = colors; } zclose ( zf ); lfree ( (byte *)PCXH ); image->title = dupString(name); return ( image ); } ( row >= image->height ) { #if 0 /* happens a lot on valid images - jimf 10.28.91 */ if (depth == 1) /* Color : Map follows */ printf ("Warning: excess data ignored\n"); #endif return; } } } }xloadimage.4.1/pdsuncomp.c 664 221 144 36411 5463770502 10751 /* jimf@saber.com, 05.06.91 * * fairly major modifications to get this to work well in the xloadimage * view of the world. rather than a standalone program, this is now designed * to be run as a subroutine. a lot of comments on how to build and use * this on different kinds of hosts have been removed. removed or rewrote * all the host-portability stuff. lobotomized its ability to dump any but * VICAR format. */ /* datri@convex.com, 4-14-91 This file is taken almost unchanged from the NASA CD-ROMS of the Voyager images. I can find no copyright anywhere near this code. All I've done is added - as a special case for the output filename to go to stdout, and made informational messages go to stderr instead of stdout, removing some of the silly ones. I've also corrected some of the places where fools assume that VAX and VMS are synonymous */ /********************************************************************/ /* Voyager Image Decompression Program - C Version for PC, VAX, */ /* UNIX and Macintosh systems. */ /* */ /* Decompresses images using Kris Becker's subroutine DECOMP.C */ /* which is included in this program in a shortened version. */ /* */ /* Reads a variable length compressed VOYAGER image and outputs a */ /* fixed length uncompressed image file in PDS format with */ /* labels, image histogram, engineering table and 800 lines of */ /* 836 bytes (800 samples, 36 engineering bytes); or an 800 by */ /* 800 array with FITS, VICAR or no labels. If used on a non- */ /* byte-swapped machine the image histogram is un-swapped. */ /* */ /********************************************************************/ /* HIST */ /* AUG89 Added code to get command line arguments for filenames */ /* and output format; routines to free memory used by the Huffman */ /* tree); fixed the SFDU label output length; and modified the */ /* I/O routines so that the open for Host type 2 uses binary I/O. */ /* JUN89 Fixed READVAR, to get length on 16-bit unswapped hosts. */ /* JUL88 C driver to decompress standard Voyager Compressed images */ /* by Mike Martin 1989/06/10 */ /* */ /* Inputs - Input file to be decompressed. */ /* */ /* Outputs - Output file containing decompressed image. */ /* */ /********************************************************************/ #include "image.h" #include "pds.h" #define RECORD_BYTES 836 typedef struct leaf { struct leaf *right; short int dn; struct leaf *left; } NODE; NODE *tree; /* huffman tree pointer */ static long hist[511]; /* histogram for huffman code */ static int Decompressing= 0; /* flag for pdsRead() */ static NODE *new_node(); static long int free_node(); NODE *huff_tree(hist) /**************************************************************************** *_TITLE huff_tree - constructs the Huffman tree; returns pointer to root * *_ARGS TYPE NAME I/O DESCRIPTION */ long int *hist; /* I First difference histogram */ { /* Local variables used */ long int freq_list[512]; /* Histogram frequency list */ NODE **node_list; /* DN pointer array list */ register long int *fp; /* Frequency list pointer */ register NODE **np; /* Node list pointer */ register long int num_freq; /* Number non-zero frequencies in histogram */ long int sum; /* Sum of all frequencies */ register short int num_nodes; /* Counter for DN initialization */ register short int cnt; /* Miscellaneous counter */ short int znull = -1; /* Null node value */ register NODE *temp; /* Temporary node pointer */ /* Functions called */ void sort_freq(); /*************************************************************************** Allocate the array of nodes from memory and initialize these with numbers corresponding with the frequency list. There are only 511 possible permutations of first difference histograms. There are 512 allocated here to adhere to the FORTRAN version. ****************************************************************************/ fp = freq_list; node_list = (NODE **) lmalloc(sizeof(temp)*512); if (node_list == NULL) { fprintf(stderr,"\nOut of memory in huff_tree!\n"); exit(1); } np = node_list; for (num_nodes=1, cnt=512 ; cnt-- ; num_nodes++) { /************************************************************************** The following code has been added to standardize the VAX byte order for the "long int" type. This code is intended to make the routine as machine independant as possible. ***************************************************************************/ unsigned char *cp = (unsigned char *) hist++; unsigned long int j; short int i; for (i=4 ; --i >= 0 ; j = (j << 8) | *(cp+i)) ; /* Now make the assignment */ *fp++ = j; temp = new_node(num_nodes); *np++ = temp; } (*--fp) = 0; /* Ensure the last element is zeroed out. */ /*************************************************************************** Now, sort the frequency list and eliminate all frequencies of zero. ****************************************************************************/ num_freq = 512; sort_freq(freq_list,node_list,num_freq); fp = freq_list; np = node_list; for (num_freq=512 ; (*fp) == 0 && (num_freq) ; fp++, np++, num_freq--) /* EMPTY */ ; /*************************************************************************** Now create the tree. Note that if there is only one difference value, it is returned as the root. On each interation, a new node is created and the least frequently occurring difference is assigned to the right pointer and the next least frequency to the left pointer. The node assigned to the left pointer now becomes the combination of the two nodes and it's frequency is the sum of the two combining nodes. ****************************************************************************/ for (temp=(*np) ; (num_freq--) > 1 ; ) { temp = new_node(znull); temp->right = (*np++); temp->left = (*np); *np = temp; *(fp+1) = *(fp+1) + *fp; *fp++ = 0; sort_freq(fp,np,num_freq); } return temp; } static NODE *new_node(value) /**************************************************************************** *_TITLE new_node - allocates a NODE structure and returns a pointer to it * *_ARGS TYPE NAME I/O DESCRIPTION */ short int value; /* I Value to assign to DN field */ { NODE *temp; /* Pointer to the memory block */ /*************************************************************************** Allocate the memory and intialize the fields. ****************************************************************************/ temp = (NODE *) lmalloc(sizeof(NODE)); temp->right = NULL; temp->dn = value; temp->left = NULL; return temp; } void sort_freq(freq_list,node_list,num_freq) /**************************************************************************** *_TITLE sort_freq - sorts frequency and node lists in increasing freq. order* *_ARGS TYPE NAME I/O DESCRIPTION */ long int *freq_list; /* I Pointer to frequency list */ NODE **node_list; /* I Pointer to array of node pointers */ long int num_freq; /* I Number of values in freq list */ { /* Local Variables */ register long int *i; /* primary pointer into freq_list */ register long int *j; /* secondary pointer into freq_list */ register NODE **k; /* primary pointer to node_list */ register NODE **l; /* secondary pointer into node_list */ long int temp1; /* temporary storage for freq_list */ NODE *temp2; /* temporary storage for node_list */ register long int cnt; /* count of list elements */ /************************************************************************ Save the current element - starting with the second - in temporary storage. Compare with all elements in first part of list moving each up one element until the element is larger. Insert current element at this point in list. *************************************************************************/ if (num_freq <= 0) return; /* If no elements or invalid, return */ for (i=freq_list, k=node_list, cnt=num_freq ; --cnt ; *j=temp1, *l=temp2) { temp1 = *(++i); temp2 = *(++k); for (j = i, l = k ; *(j-1) > temp1 ; ) { *j = *(j-1); *l = *(l-1); j--; l--; if ( j <= freq_list) break; } } return; } /* free_tree - free memory of all allocated nodes * * This routine is supplied to the programmer to free up all the * allocated memory required to build the huffman tree. The count * of the nodes freed is returned in the parameter 'nfreed'. The * purpose of the routine is so if the user wishes to decompress more * than one file per run, the program will not keep allocating new * memory without first deallocating all previous nodes associated * with the previous file decompression. * * 16-AUG-89 Kris Becker USGS, Flagstaff Original Version */ static void free_tree(nfreed) long int *nfreed; /* Return of total count of nodes freed. */ { long int total_free = 0; /* Simply call the free_node routine and return the result. */ *nfreed = free_node(tree,total_free); return; } /* free_node - deallocates an allocated NODE pointer * * free_node will check both right and left pointers of a node * and then free the current node using the free() C utility. * Note that all nodes attached to the node via right or left * pointers area also freed, so be sure that this is the desired * result when calling this routine. * * This routine is supplied to allow successive calls to the * decmpinit routine. It will free up the memory allocated * by previous calls to the decmpinit routine. The call to free * a previous huffman tree is: total = free_node(tree,(long) 0); * This call must be done by the programmer application routine * and is not done by any of these routines. * * 16-AUG-89 Kris Becker U.S.G.S Flagstaff Original Version */ static long int free_node(pnode,total_free) NODE *pnode; /* I Pointer to node to free */ long int total_free; /* I Total number of freed nodes */ { if (pnode == (NODE *) NULL) return(total_free); if (pnode->right != (NODE *) NULL) total_free = free_node(pnode->right,total_free); if (pnode->left != (NODE *) NULL) total_free = free_node(pnode->left,total_free); lfree((byte *) pnode); return(total_free + 1); } /* pdsDecompress - decompresses Huffman coded compressed image lines */ static int decompress(ibuf,obuf,nin,nout) char *ibuf; /* I Compressed data buffer */ char *obuf; /* O Decompressed image line */ long int *nin; /* I Number of bytes on input buffer */ long int *nout; /* I Number of bytes in output buffer */ { /* Local Variables */ register NODE *ptr = tree; /* pointer to position in tree */ register unsigned char test; /* test byte for bit set */ register unsigned char idn; /* input compressed byte */ register char odn; /* last dn value decompressed */ char *ilim = ibuf + *nin; /* end of compressed bytes */ char *olim = obuf + *nout; /* end of output buffer */ char *obuf_start= obuf; /* Check for valid input values for nin, nout and make initial assignments. */ if (ilim > ibuf && olim > obuf) odn = *obuf++ = *ibuf++; else { fprintf(stderr,"\nInvalid byte count in dcmprs!\n"); return(-1); } /* Decompress the input buffer. Assign the first byte to the working * variable, idn. An arithmatic and (&) is performed using the variable * 'test' that is bit shifted to the right. If the result is 0, then * go to right else go to left. */ for (idn=(*ibuf) ; ibuf < ilim ; idn =(*++ibuf)) { for (test=0x80 ; test ; test >>= 1) { ptr = (test & idn) ? ptr->left : ptr->right; if (ptr->dn != -1) { if (obuf >= olim) return(obuf - obuf_start); odn -= ptr->dn + 256; *obuf++ = odn; ptr = tree; } } } return(obuf - obuf_start); } /*********************************************************************/ /* */ /* subroutine read_var - read variable length records from input file*/ /* */ /*********************************************************************/ static int read_var(zf, ibuf) ZFILE *zf; char *ibuf; { int length,result,nlen; unsigned int value; unsigned char buf[2]; length = 0; result = zread(zf,buf,2); length= memToValLSB(buf, 2); nlen = zread(zf,(byte *)ibuf,length+(length%2)); return(length); } skip_record(zf) ZFILE *zf; { unsigned int value; unsigned char buf[2]; char *dummy; zread(zf, buf, 2); value= memToValLSB(buf, 2); dummy= (char *)lmalloc(value); zread(zf, (byte *)dummy, value); lfree((byte *)dummy); } /* initialize pdsRead() stuff. if this is a huffman-encoded file, this * reads the histogram table and initializes the huffman tree. */ void pdsInit(zf, type) ZFILE *zf; int type; { if (type == PDSVARIABLE) { char buf[2]; int len; char *dummy; Decompressing= 1; /* flag pdsRead() to do decompressions */ /* skip label and image histogram */ skip_record(zf); skip_record(zf); /* read in huffman encoding histogram */ read_var(zf, (char *)hist); read_var(zf, (char *)hist+836); read_var(zf, (char *)hist+1672); tree = huff_tree(hist); } else Decompressing= 0; } /* function which will read pds data and do decompression if necessary. */ int pdsRead(zf, buf, size) ZFILE *zf; char *buf; int size; { static char obuf[2048]; char ibuf[2048]; int left; int in_length; static int out_length= 2048, out_ptr= 0; if (Decompressing) { left= size; while (left) { if (out_ptr == out_length) { in_length= read_var(zf, ibuf); if (in_length < 0) return(-1); out_length= decompress(ibuf, obuf, &in_length, &out_length); if (out_length < 0) return(-1); out_ptr= 0; } if (left <= (out_length - out_ptr)) { bcopy(obuf + out_ptr, buf, size); out_ptr += left; return(size); } else { bcopy(obuf + out_ptr, buf, out_length - out_ptr); left= left - (out_length - out_ptr); out_ptr= out_length; } } return(size); } else return(zread(zf, (byte *)buf, size)); } cate the memory and intialize the fields. ****************************************************************************/ temp = (NODE *) lmalloc(sizeof(NODE)); temp->right = NULL; temp->dn = value; temp->left = NULL; return temp; } voidxloadimage.4.1/rle.c 664 221 144 26332 5467532170 7525 /* * rle - read in a Utah RLE Toolkit type image. * * Author: Graeme Gill * Date: 30/5/90 * * Bugs - doesn't free up memory used by rle functions. * */ #define MIN(a,b) ( (a)<(b) ? (a) : (b)) #include #include #include "image.h" #include "rle.h" #undef DEBUG #undef debug #ifdef DEBUG # define debug(xx) fprintf(stderr,xx) #else # define debug(xx) #endif void dithermap(); /* input file stuff */ static int ptype; /* picture type : */ #define BW_NM 0 /* black and white, no map */ #define BW_M 1 /* black and white, and a map */ #define SC_M 2 /* single colour channel and colour map */ #define C_NM 3 /* full colour, no maps */ #define C_M 4 /* full colour with colour maps */ static rle_pixel **fmaps; /* file colour maps from buildmap() */ static unsigned char **scan; /* buffer for input data */ static int x_min; /* copy of picture x_min */ static int y_min; /* copy of picture y_min */ /* option stuff (Not functional) */ static float disp_gam = 1.0; /* default display gamma correction factor */ static int iflag=0; /* user suplied image gamma */ static float img_gam = 1.0; /* image gamma */ static int bwflag = 0; /* black and white flag */ static int gammamap[256]; static int background[3] = {0,0,0}; /* our background colour */ /* stuff for dithering colour pictures */ int colmap[216][3]; /* for dither map */ int magic[16][16]; int modN[256]; int divN[256]; int rleIdent(fullname, name) char *fullname, *name; { ZFILE *rlefile; int x_len,y_len; int rv; debug("rleIdent called\n"); rlefile = zopen(fullname); if(!rlefile) { perror("rleIdent: Unable to open file"); return(0); } debug("rleIdent: Opened file ok\n"); sv_globals.svfb_fd = rlefile; rv = rle_get_setup(&sv_globals); debug("rleIdent: got setup ok\n"); zclose(rlefile); debug("rleIdent: closed file ok\n"); switch(rv) { case -1: return 0; /* Not rle format */ case 0: /* now figure out the picture type */ switch(sv_globals.sv_ncolors) { case 0: perror("rleIdent: no colour channels to display"); return(0); case 1: x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; printf("%s is a %dx%d", name, x_len, y_len); switch(sv_globals.sv_ncmap) { case 0: /* black and white, no map */ printf(" 8 bit grey scale RLE image with no map\n"); break; case 1: /* black and white with a map */ printf(" 8 bit grey scale RLE image with map\n"); break; case 3: /* single channel encoded colour with decoding map */ printf(" 8 bit color RLE image with color map\n"); break; default: perror(" 8 bit RLE image with an illegal color map\n"); return 0; } break; case 3: x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; printf("%s is a %dx%d", name, x_len, y_len); switch(sv_globals.sv_ncmap) { case 0: printf(" 24 bit color RLE image with no map\n"); break; case 3: printf(" 24 bit color RLE image with colour map\n"); break; default: printf(" 24 bit color RLE image with an illegal color map\n"); return 0; } break; default: x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; printf("%s is a %dx%d", name, x_len, y_len); printf(" RLE image with an illegal number of color planes\n"); return 0; } return 1; default: /* Some sort of error */ /* perror("rleIdent");*/ return 0; } } Image *rleLoad(fullname,name,verbose) char *fullname,*name; unsigned int verbose; { int x_len, y_len; int i,j; ZFILE *rlefile; int ncol; /* number of colors */ int depth; unsigned char *bufp; Image *image; unsigned char *buf; dith_levels = 256; /* aim for 128 levels of each colour */ debug("rleLoad called\n"); rlefile = zopen(fullname); if(!rlefile) { perror("rleLoad: Cannot open input file"); return(NULL); } sv_globals.svfb_fd = rlefile; debug("rleLoad: About to call get_setup\n"); if(rle_get_setup( &sv_globals )) { zclose(rlefile); return(NULL); } debug("rleLoad: get_setup called ok\n"); if(iflag == 1) /* -i flag */ img_gam = 1.0/img_gam; /* convert to display gamma */ /* If no image gamma on command line, check comments in file */ if (!iflag) { char * v; if ( (v = rle_getcom( "image_gamma", &sv_globals )) != NULL ) { img_gam = atof( v ); /* Protect against bogus information */ if ( img_gam == 0.0 ) img_gam = 1.0; else img_gam = 1.0 / img_gam; /* convert to display gamma */ } else if ( (v = rle_getcom( "display_gamma", &sv_globals )) != NULL ) { img_gam = atof( v ); /* Protect */ if ( img_gam == 0.0 ) img_gam = 1.0; } } x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; x_min = sv_globals.sv_xmin; y_min = sv_globals.sv_ymin; /* fix this so that we don't waste space */ sv_globals.sv_xmax -= sv_globals.sv_xmin; sv_globals.sv_xmin = 0; /* turn off the alpha channel (don't waste time and space)*/ sv_globals.sv_alpha = 0; SV_CLR_BIT(sv_globals,SV_ALPHA); /* for now, force background clear */ if(sv_globals.sv_background ==1) /* danger setting */ { debug("Forcing clear of background\n"); sv_globals.sv_background = 2; if(sv_globals.sv_bg_color==0) /* if none allocated */ sv_globals.sv_bg_color = background; /* use this one */ } /* now figure out the picture type */ switch(sv_globals.sv_ncolors) { case 0: perror("rleLoad: no colour channels to display"); zclose(rlefile); return(NULL); case 1: switch(sv_globals.sv_ncmap) { case 0: ptype = BW_NM; /* black and white, no map */ break; case 1: ptype = BW_M; /* black and white with a map */ break; case 3: ptype = SC_M; /* single channel encoded colour with decoding map */ break; default: zclose(rlefile); perror("rleLoad: Illegal number of maps for one colour channel"); return(NULL); } break; case 3: switch(sv_globals.sv_ncmap) { case 0: ptype = C_NM; /* colour, no map */ break; case 3: ptype = C_M; /* colour with maps */ break; default: perror("rleLoad: Illegal number of maps for colour picture"); zclose(rlefile); return(NULL); } break; default: perror("rleLoad: Illegal number of colour channels"); zclose(rlefile); return(NULL); } if(verbose) { printf("%s is a %dx%d",name,x_len,y_len); switch(ptype) { case BW_NM: printf(" 8 bit grey scale RLE image with no map"); break; case BW_M: printf(" 8 bit grey scale RLE image with map"); break; case SC_M: printf(" 8 bit RLE image with colour map"); break; case C_NM: printf(" 24 bit RLE image with no map (will dither to 8 bits)"); break; case C_M: printf(" 24 bit RLE image with color map (will dither to 8 bits)"); break; } printf(", with gamma of %4.2f\n",img_gam); } znocache(rlefile); if(ptype==SC_M) { /* don't mess with the image, but change their colour map a bit if needed */ disp_gam /= img_gam; /* amount to change their map */ img_gam = 1.0; /* not to the image coming in */ } /* get hold of the colour maps, and set to undo their images gamma */ fmaps = buildmap(&sv_globals,sv_globals.sv_ncolors,img_gam); /* now we had better sort out the picture data */ debug("done colour map\n"); /* rle stufff */ /* Get space for a full colour scan line */ scan = (unsigned char **) lmalloc( (sv_globals.sv_ncolors + sv_globals.sv_alpha) * sizeof( unsigned char * ) ); for ( i = 0; i < sv_globals.sv_ncolors + sv_globals.sv_alpha; i++ ) scan[i] = (unsigned char *)lmalloc(x_len); if ( sv_globals.sv_alpha ) scan++; debug("got space for get_row\n"); depth = 8; /* We always supply 8bit images */ image = newRGBImage(x_len,y_len,depth); image->title = dupString(name); debug("got image structure\n"); buf = image->data; /* If we are going to dither - then create the dither matrix. */ if(!bwflag && ptype!=SC_M && ptype != BW_NM && ptype != BW_M) { dith_np2 = 1; /* allow non-power of 2 dither map size */ dithermap( 6, disp_gam, colmap, divN, modN, magic ); } debug("About to read image in\n"); bufp = buf + (y_len-1) * x_len; for(j=y_len;j>0;j--,bufp -= x_len) { rle_getrow(&sv_globals,scan); switch(ptype) { case SC_M: memcpy(bufp,&scan[0][0],x_len); break; case BW_NM: case BW_M: bw_m_line(bufp,x_len); break; case C_NM: case C_M: c_m_line(bufp,x_len,j); break; } } debug("Image Read in\n"); /* Deal with colour maps */ /* set up our gamma correction */ make_gamma(disp_gam,gammamap); /* we'll need it */ debug("Creating color map\n"); /* now load an appropriate colour map */ if(!bwflag && ptype==SC_M) { /* use their maps & correct their gamma */ ncol = 1<rgb.red + i) = gammamap[fmaps[0][i]]<<8; *(image->rgb.green + i) = gammamap[fmaps[1][i]]<<8; *(image->rgb.blue + i) = gammamap[fmaps[2][i]]<<8; } } else if(bwflag || ptype == BW_NM || ptype == BW_M) { /* load a black and white map (gamma corrected for this display)*/ ncol = 256; /* don't know whats been used */ for(i=0;irgb.red + i) = *(image->rgb.green + i) = *(image->rgb.blue + i) = gammamap[i]<<8; } } else { /* must be colour, so use dither map (gamma corrected for this display)*/ ncol = 6*6*6; /* Dither map has already been created above */ for(i = 0; i < ncol; i++) { *(image->rgb.red + i) = colmap[i][0]<<8; *(image->rgb.green + i) = colmap[i][1]<<8; *(image->rgb.blue + i) = colmap[i][2]<<8; } } image->rgb.used = ncol; zclose(rlefile); debug("finished\n"); return(image); } #define DMAP(v,x,y) (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v]) /* run the black and white through its map */ bw_m_line(dp,number) int number; register unsigned char *dp; { register unsigned char *r; register int i; for(i=number,r= &scan[0][0];i>0;i--,r++,dp++) { *dp = fmaps[0][*r]; } } /* convert a colour line with map to 8 bits per pixel */ c_m_line(dp,number,line) int number,line; register unsigned char *dp; { register unsigned char *r, *g, *b; register int i, col, row; if(!bwflag) { for ( row = line % dith_size, col = x_min % dith_size, i = number, r = &scan[0][0] ,g= &scan[1][0], b= &scan[2][0]; i > 0; i--, r++, g++, b++, dp++, col = ((col + 1) % dith_size) ) { *dp = DMAP(fmaps[0][*r], col, row) + DMAP(fmaps[1][*g], col, row) * 6 + DMAP(fmaps[2][*b], col, row) * 36; } } else { int red,green,blue; for (i = number, r= &scan[0][0], g= &scan[1][0] ,b= &scan[2][0]; i>0;i--,r++,g++,b++,dp++) { red = fmaps[0][*r];green=fmaps[1][*g];blue = fmaps[2][*b]; *dp = 0.35* red + 0.55* green + 0.1* blue; } } } e); return(total_free + 1); } /* pdsDecompress - decompresses Huffman coded compressed image lines */ static int decompress(ibuf,obuf,nin,nout) char *ibuf; /* I Compressed data buffer */ char *obuf; /* O Decompressed image line xloadimage.4.1/rlelib.c 664 221 144 136325 5461577411 10241 /* * Utah RLE Toolkit library routines. * * Read image support only. * * Cobbled from Utah RLE include and library source files. * * By Graeme Gill * 30/5/90 * */ #include #include #include #include #include "image.h" /* need ZFILE definition */ #include "rle.h" /* SUPPRESS 530 */ /* SUPPRESS 558 */ /* SUPPRESS 590 */ #define zeof(zfp) feof((zfp)->stream) #define zclearerr(zfp) clearerr((zfp)->stream) /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * Runsv.h - Definitions for Run Length Encoding. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Mon Aug 9 1982 * Copyright (c) 1982 Spencer W. Thomas */ #ifndef XTNDRUNSV #define XTNDRUNSV /* * Opcode definitions */ #define LONG 0x40 #define RSkipLinesOp 1 #define RSetColorOp 2 #define RSkipPixelsOp 3 #define RByteDataOp 5 #define RRunDataOp 6 #define REOFOp 7 #define H_CLEARFIRST 0x1 /* clear framebuffer flag */ #define H_NO_BACKGROUND 0x2 /* if set, no bg color supplied */ #define H_ALPHA 0x4 /* if set, alpha channel (-1) present */ #define H_COMMENT 0x8 /* if set, comments present */ struct XtndRsetup { short h_xpos, h_ypos, h_xlen, h_ylen; char h_flags, h_ncolors, h_pixelbits, h_ncmap, h_cmaplen; }; #define SETUPSIZE ((4*2)+5) /* "Old" RLE format magic numbers */ #define RMAGIC ('R' << 8) /* top half of magic number */ #define WMAGIC ('W' << 8) /* black&white rle image */ #define XtndRMAGIC ((short)0xcc52) /* RLE file magic number */ #endif /* XTNDRUNSV */ /* "svfb.h" */ /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * svfb.h - Definitions and a few global variables for svfb. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Mon Aug 9 1982 * Copyright (c) 1982 Spencer W. Thomas */ /* **************************************************************** * Dispatch table for different output types. */ typedef void sv_fn(); struct sv_dispatch_tab { char *magic; /* magic type flags */ sv_fn *setup, /* startup function */ *skipBlankLines, *setColor, *skipPixels, *newScanLine, *putdat, /* put a set of differing pixels */ *putrn, /* put a run all the same */ *blockHook, /* hook called at start of new */ /* output block */ *putEof; /* write EOF marker (if possible) */ }; /* * These definitions presume the existence of a variable called * "fileptr", declared "long * fileptr". *fileptr should be * initialized to 0 before calling Setup(). * A pointer "globals" declared "struct sv_globals * globals" is also * presumed to exist. */ #define sv_magic (sv_DTable[(int)globals->sv_dispatch].magic) #define Setup() (*sv_DTable[(int)globals->sv_dispatch].setup)(globals) #define SkipBlankLines(n) (*sv_DTable[(int)globals->sv_dispatch].skipBlankLines)(n, globals) #define SetColor(c) (*sv_DTable[(int)globals->sv_dispatch].setColor)(c, globals) #define SkipPixels(n, l, r) (*sv_DTable[(int)globals->sv_dispatch].skipPixels)(n,l,r, globals) #define NewScanLine(flag) (*sv_DTable[(int)globals->sv_dispatch].newScanLine)(flag, globals) #define putdata(buf, len) (*sv_DTable[(int)globals->sv_dispatch].putdat)(buf, len, globals) #define putrun(val, len, f) (*sv_DTable[(int)globals->sv_dispatch].putrn)(val,len,f, globals) #define BlockHook() (*sv_DTable[(int)globals->sv_dispatch].blockHook)(globals) #define PutEof() (*sv_DTable[(int)globals->sv_dispatch].putEof)(globals) /* * States for run detection */ #define DATA 0 #define RUN2 1 #define RUN3 2 #define RUN4 3 #define INRUN -1 /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. * * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire * to have all "void" functions so declared. */ /* * svfb_global.c - Global variable initialization for svfb routines. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Thu Apr 25 1985 * Copyright (c) 1985,1986 Spencer W. Thomas */ void RunSetup(), RunSkipBlankLines(), RunSetColor(), RunSkipPixels(), RunNewScanLine(), Runputdata(), Runputrun(), RunputEof(); void DefaultBlockHook(); void NullputEof(); struct sv_dispatch_tab sv_DTable[10] = { { " OB", RunSetup, RunSkipBlankLines, RunSetColor, RunSkipPixels, RunNewScanLine, Runputdata, Runputrun, DefaultBlockHook, RunputEof }, }; static int sv_bg_color[3] = { 0, 0, 0 }; struct sv_globals sv_globals = { RUN_DISPATCH, /* dispatch value */ 3, /* 3 colors */ sv_bg_color, /* background color */ 0, /* (alpha) if 1, save alpha channel */ 2, /* (background) 0->just save pixels, */ /* 1->overlay, 2->clear to bg first */ 0, 511, /* (xmin, xmax) X bounds to save */ 0, 479, /* (ymin, ymax) Y bounds to save */ 0, /* ncmap (if != 0, save color map) */ 8, /* cmaplen (log2 of length of color map) */ NULL, /* pointer to color map */ NULL, /* pointer to comment strings */ NULL, /* output file */ { 7 } /* RGB channels only */ /* Can't initialize the union */ }; /* ARGSUSED */ void NullputEof(globals) struct sv_globals * globals; { /* do nothing */ } /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. * * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire * to have all "void" functions so declared. */ /* * Runsv.c - General purpose Run Length Encoding for svfb. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Mon Aug 9 1982 * Copyright (c) 1982,1986 Spencer W. Thomas */ /* THIS IS WAY OUT OF DATE. See rle.5. * The output file format is: * * Word 0: A "magic" number. The top byte of the word contains * the letter 'R' or the letter 'W'. 'W' indicates that * only black and white information was saved. The bottom * byte is one of the following: * ' ': Means a straight "box" save, -S flag was given. * 'B': Image saved with background color, clear screen to * background before restoring image. * 'O': Image saved in overlay mode. * * Words 1-6: The structure * { short xpos, * Lower left corner * ypos, * xsize, * Size of saved box * ysize; * char rgb[3]; * Background color * char map; * flag for map presence * } * * If the map flag is non-zero, then the color map will follow as * 3*256 16 bit words, first the red map, then the green map, and * finally the blue map. * * Following the setup information is the Run Length Encoded image. * Each instruction consists of a 4-bit opcode, a 12-bit datum and * possibly one or more following words (all words are 16 bits). The * instruction opcodes are: * * SkipLines (1): The bottom 10 bits are an unsigned number to be added to * current Y position. * * SetColor (2): The datum indicates which color is to be loaded with * the data described by the following ByteData and * RunData instructions. 0->red, 1->green, 2->blue. The * operation also resets the X position to the initial * X (i.e. a carriage return operation is performed). * * SkipPixels (3): The bottom 10 bits are an unsigned number to be * added to the current X position. * * ByteData (5): The datum is one less than the number of bytes of * color data following. If the number of bytes is * odd, a filler byte will be appended to the end of * the byte string to make an integral number of 16-bit * words. The bytes are in PDP-11 order. The X * position is incremented to follow the last byte of * data. * * RunData (6): The datum is one less than the run length. The * following word contains (in its lower 8 bits) the * color of the run. The X position is incremented to * follow the last byte in the run. */ #define UPPER 255 /* anything bigger ain't a byte */ /* Predefine LITTLE_ENDIAN for vax and pdp11 machines */ #if defined(vax) || defined(pdp11) #define LITTLE_ENDIAN #endif /* * Macros to make writing instructions with correct byte order easier. */ union { short s; char c[2]; } arg; #ifdef LITTLE_ENDIAN #define put16(a) arg.s=a,putc(arg.c[0],sv_fd), putc(arg.c[1],sv_fd) #else #define put16(a) arg.s=a,putc(arg.c[1],sv_fd), putc(arg.c[0],sv_fd) #endif /* short instructions */ #define mk_short_1(oper,a1) /* one argument short */ \ putc(oper,sv_fd), putc((char)a1,sv_fd) #define mk_short_2(oper,a1,a2) /* two argument short */ \ putc(oper,sv_fd), putc((char)a1,sv_fd), put16(a2) /* long instructions */ #define mk_long_1(oper,a1) /* one argument long */ \ putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), put16(a1) #define mk_long_2(oper,a1,a2) /* two argument long */ \ putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), \ put16(a1), put16(a2) /* choose between long and short format instructions */ /* NOTE: these macros can only be used where a STATEMENT is legal */ #define mk_inst_1(oper,a1) /* one argument inst */ \ if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1)) #define mk_inst_2(oper,a1,a2) /* two argument inst */ \ if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2)) /* * Opcode definitions */ #define RSkipLines(n) mk_inst_1(RSkipLinesOp,(n)) #define RSetColor(c) mk_short_1(RSetColorOp,(c)) /* has side effect of performing */ /* "carriage return" action */ #define RSkipPixels(n) mk_inst_1(RSkipPixelsOp,(n)) #define RNewLine RSkipLines(1) #define RByteData(n) mk_inst_1(RByteDataOp,n) /* followed by ((n+1)/2)*2 bytes */ /* of data. If n is odd, last */ /* byte will be ignored */ /* "cursor" is left at pixel */ /* following last pixel written */ #define RRunData(n,c) mk_inst_2(RRunDataOp,(n),(c)) /* next word contains color data */ /* "cursor" is left at pixel after */ /* end of run */ #define REOF mk_inst_1(REOFOp,0) /* Really opcode only */ /***************************************************************** * TAG( RunSetup ) * Put out initial setup data for RLE svfb files. */ void RunSetup(globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( RunSkipBlankLines ) * Skip one or more blank lines in the RLE file. */ void RunSkipBlankLines(nblank, globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( RunSetColor ) * Select a color and do carriage return. * color: 0 = Red, 1 = Green, 2 = Blue. */ void RunSetColor(c, globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( RunSkipPixels ) * Skip a run of background. */ /* ARGSUSED */ void RunSkipPixels(nskip, last, wasrun, globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( RunNewScanLine ) * Perform a newline action. Since CR is implied by the Set Color * operation, only generate code if the newline flag is true. */ void RunNewScanLine(flag, globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( Runputdata ) * Put one or more pixels of byte data into the output file. */ void Runputdata(buf, n, globals) rle_pixel * buf; register struct sv_globals * globals; { } /***************************************************************** * TAG( Runputrun ) * Output a single color run. */ /* ARGSUSED */ void Runputrun(color, n, last, globals) register struct sv_globals * globals; { } /***************************************************************** * TAG( RunputEof ) * Output an EOF opcode */ void RunputEof( globals ) register struct sv_globals * globals; { } /*ARGSUSED*/ void DefaultBlockHook(globals) struct sv_globals * globals; { } /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * buildmap.c - Build a color map from the RLE file color map. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Sat Jan 24 1987 * Copyright (c) 1987, University of Utah */ /***************************************************************** * TAG( buildmap ) * * Returns a color map that can easily be used to map the pixel values in * an RLE file. Map is built from the color map in the input file. * Inputs: * globals: sv_globals structure containing color map. * minmap: Minimum number of channels in output map. * gamma: Adjust color map for this image gamma value * (1.0 means no adjustment). * Outputs: * Returns an array of pointers to arrays of rle_pixels. The array * of pointers contains max(sv_ncolors, sv_ncmap) elements, each * array of pixels contains 2^sv_cmaplen elements. The pixel arrays * should be considered read-only. * Assumptions: * [None] * Algorithm: * Ensure that there are at least sv_ncolors rows in the map, and * that each has at least 256 elements in it (largest map that can * be addressed by an rle_pixel). */ rle_pixel ** buildmap( globals, minmap, gamma ) struct sv_globals *globals; int minmap; double gamma; { rle_pixel ** cmap, * gammap; register int i, j; int maplen, cmaplen, ncmap, nmap; if ( globals->sv_ncmap == 0 ) /* make identity map */ { nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap; cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); cmap[0] = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) ); for ( i = 0; i < 256; i++ ) cmap[0][i] = i; for ( i = 1; i < nmap; i++ ) cmap[i] = cmap[0]; maplen = 256; ncmap = 1; /* number of unique rows */ } else /* make map from globals */ { /* Map is at least 256 long */ cmaplen = (1 << globals->sv_cmaplen); if ( cmaplen < 256 ) maplen = 256; else maplen = cmaplen; if ( globals->sv_ncmap == 1 ) /* make "b&w" map */ { nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap; cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); cmap[0] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); for ( i = 0; i < maplen; i++ ) if ( i < cmaplen ) cmap[0][i] = globals->sv_cmap[i] >> 8; else cmap[0][i] = i; for ( i = 1; i < nmap; i++ ) cmap[i] = cmap[0]; ncmap = 1; } else if ( globals->sv_ncolors <= globals->sv_ncmap ) { nmap = (minmap < globals->sv_ncmap) ? globals->sv_ncmap : minmap; cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); for ( j = 0; j < globals->sv_ncmap; j++ ) { cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); for ( i = 0; i < maplen; i++ ) if ( i < cmaplen ) cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8; else cmap[j][i] = i; } for ( i = j, j--; i < nmap; i++ ) cmap[i] = cmap[j]; ncmap = globals->sv_ncmap; } else /* ncolors > ncmap */ { nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap; cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); for ( j = 0; j < globals->sv_ncmap; j++ ) { cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); for ( i = 0; i < maplen; i++ ) if ( i < cmaplen ) cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8; else cmap[j][i] = i; } for( i = j, j--; i < nmap; i++ ) cmap[i] = cmap[j]; ncmap = globals->sv_ncmap; } } /* Gamma compensate if requested */ if ( gamma != 1.0 ) { gammap = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) ); for ( i = 0; i < 256; i++ ) { #ifdef BYTEBUG int byteb1; byteb1 = (int)(0.5 + 255.0 * pow( i / 255.0, gamma )); gammap[i] = byteb1; #else gammap[i] = (int)(0.5 + 255.0 * pow( i / 255.0, gamma )); #endif } for ( i = 0; i < ncmap; i++ ) for ( j = 0; j < maplen; j++ ) cmap[i][j] = gammap[cmap[i][j]]; } return cmap; } /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * rle_getcom.c - Get specific comments from globals structure. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Sun Jan 25 1987 * Copyright (c) 1987, University of Utah */ /***************************************************************** * TAG( match ) * * Match a name against a test string for "name=value" or "name". * If it matches name=value, return pointer to value part, if just * name, return pointer to NUL at end of string. If no match, return NULL. * * Inputs: * n: Name to match. May also be "name=value" to make it easier * to replace comments. * v: Test string. * Outputs: * Returns pointer as above. * Assumptions: * [None] * Algorithm: * [None] */ static char * match( n, v ) register char *n; register char *v; { for ( ; *n != '\0' && *n != '=' && *n == *v; n++, v++ ) ; if (*n == '\0' || *n == '=') if ( *v == '\0' ) return v; else if ( *v == '=' ) return ++v; return NULL; } /***************************************************************** * TAG( rle_getcom ) * * Return a pointer to the value part of a name=value pair in the comments. * Inputs: * name: Name part of the comment to search for. * globals: sv_globals structure. * Outputs: * Returns pointer to value part of comment or NULL if no match. * Assumptions: * [None] * Algorithm: * [None] */ char * rle_getcom( name, globals ) char *name; struct sv_globals *globals; { char ** cp; char * v; if ( globals->sv_comments == NULL ) return NULL; for ( cp = globals->sv_comments; *cp; cp++ ) if ( (v = match( name, *cp )) != NULL ) return v; return NULL; } /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. * * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire * to have all "void" functions so declared. */ /* * rle_getrow.c - Read an RLE file in. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Wed Apr 10 1985 * Copyright (c) 1985 Spencer W. Thomas * */ /* * Automatically define LITTLE_ENDIAN on vax and pdp11 machines */ #if defined(vax) || defined(pdp11) #define LITTLE_ENDIAN #endif struct inst { unsigned opcode:8, datum:8; }; #define BREAD(type, var, len)\ zread( infile, (byte *)&var,len ) #define OPCODE(inst) (inst.opcode & ~LONG) #define LONGP(inst) (inst.opcode & LONG) #define DATUM(inst) (0x00ff & inst.datum) static int debug_f; /* if non-zero, print debug info */ static void bfill(); /***************************************************************** * TAG( rle_get_setup ) * * Read the initialization information from an RLE file. * Inputs: * globals: Contains pointer to the input file. * Outputs: * globals: Initialized with information from the * input file. * Returns 0 on success, -1 if the file is not an RLE file, * -2 if malloc of the color map failed, -3 if an immediate EOF * is hit (empty input file), and -4 if an EOF is encountered reading * the setup information. * Assumptions: * infile points to the "magic" number in an RLE file (usually * byte 0 in the file). * Algorithm: * Read in the setup info and fill in sv_globals. */ rle_get_setup( globals ) struct sv_globals * globals; { struct XtndRsetup setup; short magic; /* assume 16 bits */ register ZFILE *infile = globals->svfb_fd; rle_pixel * bg_color; register int i; char * comment_buf; zclearerr(infile); BREAD( short, magic, sizeof magic ); SWAB(magic); if ( zeof( infile ) ) return -3; if ( magic != XtndRMAGIC ) return -1; BREAD( struct XtndRsetup, setup, SETUPSIZE ); /* assume VAX packing */ if ( zeof( infile ) ) return -4; SWAB( setup.h_xpos ); SWAB( setup.h_ypos ); SWAB( setup.h_xlen ); SWAB( setup.h_ylen ); /* Extract information from setup */ globals->sv_ncolors = setup.h_ncolors; for ( i = 0; i < globals->sv_ncolors; i++ ) SV_SET_BIT( *globals, i ); if ( !(setup.h_flags & H_NO_BACKGROUND) ) { globals->sv_bg_color = (int *)lmalloc( (unsigned)(sizeof(int) * setup.h_ncolors) ); bg_color = (rle_pixel *)lmalloc( (unsigned)(1 + (setup.h_ncolors / 2) * 2) ); zread( infile, (byte *)bg_color, 1 + (setup.h_ncolors / 2) * 2 ); for ( i = 0; i < setup.h_ncolors; i++ ) globals->sv_bg_color[i] = bg_color[i]; lfree( bg_color ); } else zgetc( infile ); /* skip filler byte */ if ( setup.h_flags & H_NO_BACKGROUND ) globals->sv_background = 0; else if ( setup.h_flags & H_CLEARFIRST ) globals->sv_background = 2; else globals->sv_background = 1; if ( setup.h_flags & H_ALPHA ) { globals->sv_alpha = 1; SV_SET_BIT( *globals, SV_ALPHA ); } else globals->sv_alpha = 0; globals->sv_xmin = setup.h_xpos; globals->sv_ymin = setup.h_ypos; globals->sv_xmax = globals->sv_xmin + setup.h_xlen - 1; globals->sv_ymax = globals->sv_ymin + setup.h_ylen - 1; globals->sv_ncmap = setup.h_ncmap; globals->sv_cmaplen = setup.h_cmaplen; if ( globals->sv_ncmap > 0 ) { register int maplen = globals->sv_ncmap * (1 << globals->sv_cmaplen); globals->sv_cmap = (rle_map *)lmalloc( (unsigned)(sizeof(rle_map) * maplen) ); if ( globals->sv_cmap == NULL ) { fprintf( stderr, "Malloc failed for color map of size %d*%d in rle_get_setup\n", globals->sv_ncmap, (1 << globals->sv_cmaplen) ); return -2; } zread( infile, (byte *)globals->sv_cmap, sizeof(short) * maplen ); #ifndef LITTLE_ENDIAN /* Swap bytes on bigendian machines */ for ( i = 0; i < maplen; i++ ) SWAB( globals->sv_cmap[i] ); #endif } /* Check for comments */ if ( setup.h_flags & H_COMMENT ) { short comlen, evenlen; register char * cp; BREAD( short, comlen, sizeof comlen ); /* get comment length */ SWAB( comlen ); evenlen = (comlen + 1) & ~1; /* make it even */ comment_buf = (char *)lmalloc( (unsigned) evenlen ); if ( comment_buf == NULL ) { fprintf( stderr, "Malloc failed for comment buffer of size %d in rle_get_setup\n", comlen ); return -2; } zread( infile, (byte *)comment_buf, evenlen ); /* Count the comments */ for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ ) if ( *cp == 0 ) i++; i++; /* extra for NULL pointer at end */ /* Get space to put pointers to comments */ globals->sv_comments = (char **)lmalloc( (unsigned)(i * sizeof(char *)) ); if ( globals->sv_comments == NULL ) { fprintf( stderr, "Malloc failed for %d comment pointers in rle_get_setup\n", i ); return -2; } /* Get pointers to the comments */ *globals->sv_comments = comment_buf; for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ ) if ( *(cp - 1) == 0 ) globals->sv_comments[i++] = cp; globals->sv_comments[i] = NULL; } else globals->sv_comments = NULL; /* Initialize state for rle_getrow */ globals->sv_private.get.scan_y = globals->sv_ymin; globals->sv_private.get.vert_skip = 0; globals->sv_private.get.is_eof = 0; globals->sv_private.get.is_seek = 0; /* Can't do seek on zfile */ debug_f = 0; if ( !zeof( infile ) ) return 0; /* success! */ else { globals->sv_private.get.is_eof = 1; return -4; } } /***************************************************************** * TAG( rle_get_error ) * * Print an error message for the return code from rle_get_setup * Inputs: * code: The return code from rle_get_setup. * pgmname: Name of this program (argv[0]). * fname: Name of the input file. * Outputs: * Prints an error message on standard output. * Returns code. */ rle_get_error( code, pgmname, fname ) char *pgmname; char *fname; { switch( code ) { case 0: /* success */ break; case -1: /* Not an RLE file */ fprintf( stderr, "%s: %s is not an RLE file\n", pgmname, fname ); break; case -2: /* malloc failed */ fprintf( stderr, "%s: Malloc failed reading header of file %s\n", pgmname, fname ); break; case -3: fprintf( stderr, "%s: %s is an empty file\n", pgmname, fname ); break; case -4: fprintf( stderr, "%s: RLE header of %s is incomplete (premature EOF)\n", pgmname, fname ); break; default: fprintf( stderr, "%s: Error encountered reading header of %s\n", pgmname, fname ); break; } return code; } /***************************************************************** * TAG( rle_get_setup_ok ) * * Read the initialization information from an RLE file. * Inputs: * globals: Contains pointer to the input file. * prog_name: Program name to be printed in the error message. * file_name: File name to be printed in the error message. * If NULL, the string "stdin" is generated. * Outputs: * globals: Initialized with information from the * input file. * If reading the globals fails, it prints an error message * and exits with the appropriate status code. * Algorithm: * sv_get_setup does all the work. */ void rle_get_setup_ok( globals, prog_name, file_name ) struct sv_globals * globals; char *prog_name; char *file_name; { int code; if (! file_name) file_name = "stdin"; code = rle_get_error( rle_get_setup( globals ), prog_name, file_name ); if (code) exit( code ); } /***************************************************************** * TAG( rle_debug ) * * Turn RLE debugging on or off. * Inputs: * on_off: if 0, stop debugging, else start. * Outputs: * Sets internal debug flag. * Assumptions: * [None] * Algorithm: * [None] */ void rle_debug( on_off ) int on_off; { debug_f = on_off; } /***************************************************************** * TAG( rle_getrow ) * * Get a scanline from the input file. * Inputs: * globals: sv_globals structure containing information about * the input file. * Outputs: * scanline: an array of pointers to the individual color * scanlines. Scanline is assumed to have * globals->sv_ncolors pointers to arrays of rle_pixel, * each of which is at least globals->sv_xmax+1 long. * Returns the current scanline number. * Assumptions: * rle_get_setup has already been called. * Algorithm: * If a vertical skip is being executed, and clear-to-background is * specified (globals->sv_background is true), just set the * scanlines to the background color. If clear-to-background is * not set, just increment the scanline number and return. * * Otherwise, read input until a vertical skip is encountered, * decoding the instructions into scanline data. */ rle_getrow( globals, scanline ) struct sv_globals * globals; rle_pixel *scanline[]; { register rle_pixel * scanc; register int nc; register ZFILE *infile = globals->svfb_fd; int scan_x = globals->sv_xmin, /* current X position */ channel = 0; /* current color channel */ short word, long_data; struct inst inst; /* Clear to background if specified */ if ( globals->sv_background == 2 ) { if ( globals->sv_alpha && SV_BIT( *globals, -1 ) ) bfill( (char *)scanline[-1], globals->sv_xmax + 1, 0 ); for ( nc = 0; nc < globals->sv_ncolors; nc++ ) if ( SV_BIT( *globals, nc ) ) bfill( (char *)scanline[nc], globals->sv_xmax+1, globals->sv_bg_color[nc] ); } /* If skipping, then just return */ if ( globals->sv_private.get.vert_skip > 0 ) { globals->sv_private.get.vert_skip--; globals->sv_private.get.scan_y++; if ( globals->sv_private.get.vert_skip > 0 ) return globals->sv_private.get.scan_y; } /* If EOF has been encountered, return also */ if ( globals->sv_private.get.is_eof ) return ++globals->sv_private.get.scan_y; /* Otherwise, read and interpret instructions until a skipLines * instruction is encountered. */ if ( SV_BIT( *globals, channel ) ) scanc = scanline[channel] + scan_x; else scanc = NULL; for (;;) { BREAD(struct inst, inst, 2 ); if ( zeof(infile) ) { globals->sv_private.get.is_eof = 1; break; /* <--- one of the exits */ } switch( OPCODE(inst) ) { case RSkipLinesOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); globals->sv_private.get.vert_skip = long_data; } else globals->sv_private.get.vert_skip = DATUM(inst); if (debug_f) fprintf(stderr, "Skip %d Lines (to %d)\n", globals->sv_private.get.vert_skip, globals->sv_private.get.scan_y + globals->sv_private.get.vert_skip ); break; /* need to break for() here, too */ case RSetColorOp: channel = DATUM(inst); /* select color channel */ if ( channel == 255 ) channel = -1; scan_x = globals->sv_xmin; if ( SV_BIT( *globals, channel ) ) scanc = scanline[channel]+scan_x; if ( debug_f ) fprintf( stderr, "Set color to %d (reset x to %d)\n", channel, scan_x ); break; case RSkipPixelsOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); scan_x += long_data; scanc += long_data; if ( debug_f ) fprintf( stderr, "Skip %d pixels (to %d)\n", long_data, scan_x ); } else { scan_x += DATUM(inst); scanc += DATUM(inst); if ( debug_f ) fprintf( stderr, "Skip %d pixels (to %d)\n", DATUM(inst), scan_x ); } break; case RByteDataOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); nc = (int)long_data; } else nc = DATUM(inst); nc++; if ( SV_BIT( *globals, channel ) ) { zread( infile, (byte *)scanc, nc ); if ( nc & 1 ) (void)zgetc( infile ); /* throw away odd byte */ } else { /* Emulate a forward fseek */ register int ii; for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- ) (void) zgetc( infile ); /* discard it */ } scanc += nc; scan_x += nc; if ( debug_f ) if ( SV_BIT( *globals, channel ) ) { rle_pixel * cp = scanc - nc; fprintf( stderr, "Pixel data %d (to %d):", nc, scan_x ); for ( ; nc > 0; nc-- ) fprintf( stderr, "%02x", *cp++ ); putc( '\n', stderr ); } else fprintf( stderr, "Pixel data %d (to %d)\n", nc, scan_x ); break; case RRunDataOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); nc = long_data; } else nc = DATUM(inst); scan_x += nc + 1; BREAD( short, word, sizeof(short) ); SWAB( word ); if ( debug_f ) fprintf( stderr, "Run length %d (to %d), data %02x\n", nc + 1, scan_x, word ); if ( SV_BIT( *globals, channel ) ) { if ( nc >= 10 ) /* break point for 785, anyway */ { bfill( (char *)scanc, nc + 1, word ); scanc += nc + 1; } else for ( ; nc >= 0; nc--, scanc++ ) *scanc = word; } break; case REOFOp: globals->sv_private.get.is_eof = 1; break; default: fprintf( stderr, "rle_getrow: Unrecognized opcode: %d\n", inst.opcode ); exit(1); } if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp ) break; /* <--- the other loop exit */ } return globals->sv_private.get.scan_y; } /* Fill buffer at s with n copies of character c. N must be <= 65535*/ /* ARGSUSED */ static void bfill( s, n, c ) char *s; int n, c; { #if defined(vax) && !defined(VMS) asm(" movc5 $0,*4(ap),12(ap),8(ap),*4(ap)"); #else while ( n-- > 0 ) *s++ = c; #endif } /* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. * * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire * to have all "void" functions so declared. * * Modified to generate an apropriate size dither map (ie 2x2, 4x4, 8x8 * or 16x16) rather than use fixed 16x16 map. Use a large enough map * to give a minimum of 128 effective levels rather than aiming for 256. * This should give less grainy pictures. * Two global variables can modify this: * dith_levels = 128 (default) * dith_np2 = 0 (default). Nonzero to enable non power of 2 dither mapping. * dith_size = actual dither matrix size chosen. * * Graeme Gill 3 June 88 */ /* * dither.c - Functions for RGB color dithering. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Mon Feb 2 1987 * Copyright (c) 1987, University of Utah */ void make_square(); /* dither globals */ int dith_levels = 128; int dith_np2 = 0; int dith_size = 16; /* basic dithering macro */ #define DMAP(v,x,y) (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v]) /***************************************************************** * TAG( dithermap ) * * Create a color dithering map with a specified number of intensity levels. * Inputs: * levels: Intensity levels per primary. * gamma: Display gamma value. * Outputs: * rgbmap: Generated color map. * divN: "div" function for dithering. * modN: "mod" function for dithering. * Assumptions: * rgbmap will hold levels^3 entries. * Algorithm: * Compute gamma compensation map. * N = 255.0 / (levels - 1) is number of pixel values per level. * Compute rgbmap with red ramping fastest, green slower, and blue * slowest (treat it as if it were rgbmap[levels][levels][levels][3]). * Call make_square to get divN, modN, and magic * * Note: * Call dithergb( x, y, r, g, b, levels, divN, modN, magic ) to get index * into rgbmap for a given color/location pair, or use * row = y % 16; col = x % 16; * DMAP(v,col,row) =def (divN[v] + (modN[v]>magic[col][row] ? 1 : 0)) * DMAP(r,col,row) + DMAP(g,col,row)*levels + DMAP(b,col,row)*levels^2 * if you don't want function call overhead. */ void dithermap( levels, gamma, rgbmap, divN, modN, magic ) double gamma; int rgbmap[][3]; int divN[256]; int modN[256]; int magic[16][16]; { double N; register int i; int levelsq, levelsc; int gammamap[256]; make_gamma(gamma,gammamap); levelsq = levels*levels; /* squared */ levelsc = levels*levelsq; /* and cubed */ N = 255.0 / (levels - 1); /* Get size of each step */ /* * Set up the color map entries. */ for(i = 0; i < levelsc; i++) { rgbmap[i][0] = gammamap[(int)(0.5 + (i%levels) * N)]; rgbmap[i][1] = gammamap[(int)(0.5 + ((i/levels)%levels) * N)]; rgbmap[i][2] = gammamap[(int)(0.5 + ((i/levelsq)%levels) * N)]; } make_square( N, divN, modN, magic ); } /***************************************************************** * TAG( bwdithermap ) * * Create a color dithering map with a specified number of intensity levels. * Inputs: * levels: Intensity levels. * gamma: Display gamma value. * Outputs: * bwmap: Generated black & white map. * divN: "div" function for dithering. * modN: "mod" function for dithering. * Assumptions: * bwmap will hold levels entries. * Algorithm: * Compute gamma compensation map. * N = 255.0 / (levels - 1) is number of pixel values per level. * Compute bwmap for levels entries. * Call make_square to get divN, modN, and magic. * Note: * Call ditherbw( x, y, val, divN, modN, magic ) to get index into * bwmap for a given color/location pair, or use * row = y % 16; col = x % 16; * divN[val] + (modN[val]>magic[col][row] ? 1 : 0) * if you don't want function call overhead. * On a 1-bit display, use * divN[val] > magic[col][row] ? 1 : 0 */ void bwdithermap( levels, gamma, bwmap, divN, modN, magic ) double gamma; int bwmap[]; int divN[256]; int modN[256]; int magic[16][16]; { double N; register int i; int gammamap[256]; make_gamma(gamma,gammamap); N = 255.0 / (levels - 1); /* Get size of each step */ /* * Set up the color map entries. */ for(i = 0; i < levels; i++) bwmap[i] = gammamap[(int)(0.5 + i * N)]; make_square( N, divN, modN, magic ); } /***************************************************************** * TAG( make_square ) * * Build the magic square for a given number of levels. * Inputs: * N: Pixel values per level (255.0 / (levels-1)). * (global) dith_levels = 128 (default) - number of effective levels to aim for * (global) dith_np2 = 0 (default) - non-zero if non power of two size is permissable. * Outputs: * divN: Integer value of pixval / N * modN: Integer remainder between pixval and divN[pixval]*N * magic: Magic square for dithering to N sublevels. * (global) dith_size = magic square size chosen. * Assumptions: * * Algorithm: * divN[pixval] = (int)(pixval / N) maps pixval to its appropriate level. * modN[pixval] = pixval - (int)(N * divN[pixval]) maps pixval to * its sublevel, and is used in the dithering computation. */ void make_square( N, divN, modN, magic ) double N; int divN[256]; int modN[256]; int magic[16][16] ; { register int i, j, k, l; double magicfact; for ( i = 0; i < 256; i++ ) { divN[i] = (int)(i / N); modN[i] = i - (int)(N * divN[i]); } modN[255] = 0; /* always */ /* figure out how big a square will give */ /* the desired number of levels */ if(dith_np2) for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size++ ); else for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size *=2); /* make the basic square up */ /* ( will have numbers 0 - size * size ) */ make_magic(dith_size,magic); /* divN gives 0 - levels-1 */ /* modN gives 0 - N-1 */ /* dither is if(modN(pix) > magic[][] so */ /* scale magic it to have levels 0 to N-2 */ /* (ie takes account of magic square size allows size * size +1 levels */ magicfact = (N-2)/((double)((dith_size * dith_size)-1)); for(i=0;i0?0:dith_size;l<16;l += dith_size) { for(i=0;ili && magic16x16[xx][yy] < bi) { bx = xx; by = yy; bi = magic16x16[xx][yy]; } } } magic[bx][by] = i; i++; li = bi; } } /***************************************************************** * TAG( make_gamma ) * * Makes a gamma compenstation map. * Inputs: * gamma: desired gamma * gammamap: gamma mapping array * Outputs: * Changes gamma array entries. */ make_gamma( gamma, gammamap ) double gamma; int gammamap[256]; { register int i; for ( i = 0; i < 256; i++ ) { #ifdef BYTEBUG int byteb1; byteb1 = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma )); gammamap[i] = byteb1; #else gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma )); #endif } } /***************************************************************** * TAG( dithergb ) * * Return dithered RGB value. * Inputs: * x: X location on screen of this pixel. * y: Y location on screen of this pixel. * r, g, b: Color at this pixel (0 - 255 range). * levels: Number of levels in this map. * divN, modN: From dithermap. * magic: Magic square from dithermap. * Outputs: * Returns color map index for dithered pixelv value. * Assumptions: * divN, modN, magic were set up properly. * Algorithm: * see "Note:" in dithermap comment. */ dithergb( x, y, r, g, b, levels, divN, modN, magic ) int divN[256]; int modN[256]; int magic[16][16]; { int col = x % 16, row = y % 16; return DMAP(r, col, row) + DMAP(g, col, row) * levels + DMAP(b, col, row) * levels*levels; } /***************************************************************** * TAG( ditherbw ) * * Return dithered black & white value. * Inputs: * x: X location on screen of this pixel. * y: Y location on screen of this pixel. * val: Intensity at this pixel (0 - 255 range). * divN, modN: From dithermap. * magic: Magic square from dithermap. * Outputs: * Returns color map index for dithered pixel value. * Assumptions: * divN, modN, magic were set up properly. * Algorithm: * see "Note:" in bwdithermap comment. */ ditherbw( x, y, val, divN, modN, magic ) int divN[256]; int modN[256]; int magic[16][16]; { int col = x % 16, row = y % 16; return DMAP(val, col, row); } ; register int i; int levelsq, levelsc; int gammamap[256]; make_gamma(gamma,gammamap); levelsq = levels*levels; /* squared */ levelsc = levels*levelsq; /* and cubed */ N = 255.0 / (levels - 1); /* Get size of each step */ /* * Set up the color map entrixloadimage.4.1/sunraster.c 664 221 144 20052 5461577412 10764 /* sunraster.c: * * sun rasterfile image type * * jim frost 09.27.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" #include "sunraster.h" /* SUPPRESS 558 */ /* SUPPRESS 560 */ static void babble(name, header) char *name; struct rheader *header; { printf("%s is a", name); switch (memToVal(header->type, 4)) { case ROLD: printf("n old-style"); break; case RSTANDARD: printf(" standard"); break; case RRLENCODED: printf(" run-length encoded"); break; case RRGB: printf(" RGB"); /* RGB format instead of BGR */ break; case RTIFF: printf(" TIFF"); break; case RIFF: printf(" RIFF"); break; default: printf(" unknown-type"); } printf(" %dx%d", memToVal(header->width, 4), memToVal(header->height, 4)); switch (memToVal(header->depth, 4)) { case 1: printf(" monochrome"); break; case 8: printf(" 8 plane %s", memToVal(header->maplen, 4) > 0 ? "color" : "greyscale"); break; case 24: printf(" 24 plane color"); break; case 32: /* isn't it nice how the sunraster.h file doesn't bother to mention that * 32-bit depths are allowed? */ printf(" 32 plane color"); break; } printf(" Sun rasterfile\n"); } int sunRasterIdent(fullname, name) char *fullname, *name; { ZFILE *zf; struct rheader header; int r; if (! (zf= zopen(fullname))) { perror("sunRasterIdent"); return(0); } switch (zread(zf, (byte *)&header, sizeof(struct rheader))) { case -1: perror("sunRasterIdent"); r= 0; break; case sizeof(struct rheader): if (memToVal(header.magic, 4) != RMAGICNUMBER) { r= 0; break; } babble(name, &header); r= 1; break; default: r= 0; break; } zclose(zf); return(r); } /* read either rl-encoded or normal image data */ static void sunread(zf, buf, len, enc) ZFILE *zf; byte *buf; unsigned int len; unsigned int enc; /* true if encoded file */ { static byte repchar, remaining= 0; /* rl-encoded read */ if (enc) { while (len--) if (remaining) { remaining--; *(buf++)= repchar; } else { if (zread(zf, &repchar, 1) != 1) { printf("sunRasterLoad: Bad read on image data\n"); exit(1); } if (repchar == RESC) { if (zread(zf, &remaining, 1) != 1) { printf("sunRasterLoad: Bad read on image data\n"); exit(1); } if (remaining == 0) *(buf++)= RESC; else { if (zread(zf, &repchar, 1) != 1) { printf("sunRasterLoad: Bad read on image data\n"); exit(1); } *(buf++)= repchar; } } else *(buf++)= repchar; } } /* normal read */ else { if (zread(zf, buf, len) < len) { printf("sunRasterLoad: Bad read on image data\n"); exit(1); } } } Image *sunRasterLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; struct rheader header; unsigned int mapsize; byte *map; byte *mapred, *mapgreen, *mapblue; unsigned int depth; unsigned int linelen; /* length of raster line in bytes */ unsigned int fill; /* # of fill bytes per raster line */ unsigned int enc; unsigned int rgb_format; byte fillchar; Image *image; byte *lineptr; unsigned int x, y; if (! (zf= zopen(fullname))) { perror("sunRasterLoad"); return(NULL); } switch (zread(zf, (byte *)&header, sizeof(struct rheader))) { case -1: perror("sunRasterLoad"); zclose(zf); exit(1); case sizeof(struct rheader): if (memToVal(header.magic, 4) != RMAGICNUMBER) { zclose(zf); return(NULL); } if (verbose) babble(name, &header); break; default: zclose(zf); return(NULL); } znocache(zf); /* turn off caching; we don't need it anymore */ /* get an image to put the data in */ depth= memToVal(header.depth, 4); switch(depth) { case 1: image= newBitImage(memToVal(header.width, 4), memToVal(header.height, 4)); break; case 8: image= newRGBImage(memToVal(header.width, 4), memToVal(header.height, 4), memToVal(header.depth, 4)); break; case 24: case 32: image= newTrueImage(memToVal(header.width, 4), memToVal(header.height, 4)); break; default: printf("sunRasterLoad: Bad depth %d (only 1, 8, 24 are valid)\n", depth); exit(1); } /* figure out which format it is */ enc= 0; rgb_format= 0; switch (memToVal(header.type, 4)) { case ROLD: case RSTANDARD: break; case RRLENCODED: enc= 1; break; case RRGB: rgb_format= 1; break; case RTIFF: /* sorry, don't even know what these are */ case RIFF: default: fprintf(stderr, "%s: Unsupported Sun Rasterfile image type (sorry)\n"); return(NULL); } /* set up the colormap */ if (depth == 1) linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); else linelen= image->width * image->pixlen; fill= (linelen % 2 ? 1 : 0); /* * Handle color... */ if (mapsize= memToVal(header.maplen, 4)) { map= lmalloc(mapsize); if (zread(zf, map, mapsize) < mapsize) { printf("sunRasterLoad: Bad read on colormap\n"); exit(1); } mapsize /= 3; mapred= map; mapgreen= mapred + mapsize; mapblue= mapgreen + mapsize; if (image->rgb.size == 0) newRGBMapData(&image->rgb, mapsize); else if (mapsize > image->rgb.size) mapsize= image->rgb.size; for (y= 0; y < mapsize; y++) { *(image->rgb.red + y)= (*(mapred++) << 8); *(image->rgb.green + y)= (*(mapgreen++) << 8); *(image->rgb.blue + y)= (*(mapblue++) << 8); } lfree(map); image->rgb.used= mapsize; } /* * Handle 8-bit greyscale via a simple ramp function... */ else if (depth == 8) { mapsize = 256*3; map= lmalloc(mapsize); for (y = 0; y < 256; y += 1) { map[y] = map[256+y] = map[2*256+y] = y; } mapsize /= 3; mapred= map; mapgreen= mapred + mapsize; mapblue= mapgreen + mapsize; if (image->rgb.size == 0) newRGBMapData(&image->rgb, mapsize); for (y= 0; y < mapsize; y++) { *(image->rgb.red + y)= (*(mapred++) << 8); *(image->rgb.green + y)= (*(mapgreen++) << 8); *(image->rgb.blue + y)= (*(mapblue++) << 8); } lfree(map); image->rgb.used= mapsize; } /* 24-bit and 32-bit handle themselves. currently we don't support * a colormap for them. */ lineptr= image->data; /* if it's a 32-bit image, we read the line and then strip off the * top byte of each pixel to get truecolor format */ if (depth >= 24) { byte *buf, *bp; buf= lmalloc(image->width * (depth == 24 ? 3 : 4)); for (y= 0; y < image->height; y++) { sunread(zf, buf, image->width * (depth == 24 ? 3 : 4), enc); bp= buf; if (depth == 24) { if (rgb_format) for (x= 0; x < image->width; x++) { *(lineptr++)= *(bp++); /* red */ *(lineptr++)= *(bp++); /* green */ *(lineptr++)= *(bp++); /* blue */ } else for (x= 0; x < image->width; x++) { *(lineptr++)= *(bp + 2); /* red */ *(lineptr++)= *(bp + 1); /* green */ *(lineptr++)= *bp; /* blue */ bp += 3; } } else { if (rgb_format) for (x= 0; x < image->width; x++) { bp++; /* skip byte */ *(lineptr++)= *(bp++); /* red */ *(lineptr++)= *(bp++); /* green */ *(lineptr++)= *(bp++); /* blue */ } else for (x= 0; x < image->width; x++) { *(lineptr++)= *(bp + 3); /* red */ *(lineptr++)= *(bp + 2); /* green */ *(lineptr++)= *(bp + 1); /* blue */ bp += 4; } } if (fill) sunread(zf, &fillchar, fill, enc); } lfree(buf); } else { for (y= 0; y < image->height; y++) { sunread(zf, lineptr, linelen, enc); lineptr += linelen; if (fill) sunread(zf, &fillchar, fill, enc); } } zclose(zf); image->title= dupString(name); return(image); } case RRLENCODED: printf(" run-length encoded"); break; case RRGB: printf(" RGB"); /* RGB format instead of BGR */ break; case RTIFF: printf(" TIFF"); break; case RIFF: printf(" RIFF"); break; default: printf(" unknown-type"); } printf(" %dx%d", memToVal(header->width, 4), memToVal(header->height, 4)); switch (memToVal(header->depth, 4)) { case 1: printf(" monochrome"); break; case 8: printf(" 8 plaxloadimage.4.1/vff.c 664 221 144 23001 5463502102 7476 /* vff.c * Sun Visualization File Format images * * -ksp 8 June 91 */ /* * Copyright (c) 1991 Southwest Research Institute * All rights reserved. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. The name of Southwest Research * Institute may not be used to endorse or promote products derived * from this software without specific prior written permission. The * author makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express * or implied warranty. * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "image.h" #define HEAD_BUF_SIZE 2048 #define MAX_HEAD_LINES 100 static char *header[MAX_HEAD_LINES]; static int width, height, bands, cmsize; static unsigned char rm[256], gm[256], bm[256]; static int readHeader(); static int parseHeader(); static int readImage(); static void freeheader(); Image * vffLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; char buf[4]; Image *image = NULL; if (!(zf = zopen(fullname))) return(NULL); if (zread(zf, (unsigned char *)buf, 4) != 4) { zclose(zf); return(NULL); } if (strncmp(buf, "ncaa", 4) != 0) { zclose(zf); return(NULL); } if (readHeader(zf)) { zclose(zf); return(NULL); } if (parseHeader()) { zclose(zf); return(NULL); } if (bands == 1) { image = newRGBImage(width, height, 8); } else if (bands == 2) { printf("Only Sun VFF files with one or three+ bands are supported.\n"); zclose(zf); return(NULL); } else if (bands >= 3) { image = newTrueImage(width, height); } image->title = dupString(name); if (verbose) { if (bands == 1) { printf("%s is a %dx%d Sun VFF image with 1 band\n", name, width, height); } else { printf("%s is a %dx%d Sun VFF image with %d bands\n", name, width, height, bands); } } if (readImage(zf, image)) { freeImage(image); zclose(zf); return(NULL); } zclose(zf); return(image); } static int readImage(zf, image) ZFILE *zf; Image *image; { byte *buf; byte *op, *ip; int x, y, skip, linewidth, i; void memoryExhausted(); if (bands == 1) { if (cmsize == 0) { /* build a grey ramp */ for (i = 0; i < 256; i++) { *(image->rgb.red + i) = i * 256; *(image->rgb.green + i) = i * 256; *(image->rgb.blue + i) = i * 256; } image->rgb.used = 256; } else { if (cmsize > 256) { cmsize = 256; } for (i = 0; i < cmsize; i++) { *(image->rgb.red + i) = rm[i] * 256; *(image->rgb.green + i) = gm[i] * 256; *(image->rgb.blue + i) = bm[i] * 256; } image->rgb.used = cmsize; } op = image->data; for (y = 0; y < height; y++) { if (zread(zf, op, width) != width) { printf("%s: short read line %d\n", image->title, y); return(0); /* show what we got */ } op += width; } } else { op = image->data; skip = bands - 3; linewidth = bands * width; buf = (unsigned char *)malloc((unsigned)linewidth); if (buf == NULL) { memoryExhausted(); } for (y = 0; y < height; y++) { ip = buf; if (zread(zf, buf, linewidth) != linewidth) { printf("%s: short read line %d\n", image->title, y); return(0); /* show what we got */ } for (x = 0; x < width; x++) { ip += skip; *(op++) = *(ip+2); *(op++) = *(ip+1); *(op++) = *(ip); ip += 3; } } free(buf); } return(0); } static int parseHeader() { int bits; int line; /* KISS ? */ for (line = 0; ((line < MAX_HEAD_LINES) && (header[line] != NULL)); line++) { if (strncmp(header[line], "type", 4) == 0) { if (strncmp(header[line], "type raster", 11) != 0) { printf("Only Sun VFF files of type `raster' are supported.\n"); freeheader(); return(1); } } if (strncmp(header[line], "bands", 5) == 0) { sscanf(header[line], "bands %d", &bands); } if (strncmp(header[line], "bits", 4) == 0) { sscanf(header[line], "bits %d", &bits); /* only check one band */ if (bits != 8) { printf("Only Sun VFF files with 8-bit bands are supported.\n"); freeheader(); return(1); } } if (strncmp(header[line],"components", 10) == 0) { printf("Only Sun VFF files of type `raster' are supported.\n"); freeheader(); return(1); } if ((strncmp(header[line], "colormap", 8) == 0) && (strncmp(header[line], "colormapsize", 12) != 0)) { { char *cp; int i, r, g, b; /* ship colormap */ cp = header[line]+8; /* find the first entry */ while (*cp && !isxdigit(*cp)) { cp++; } for (i = 0; i < 256; i++) { if (sscanf(cp, "%02x%02x%02x", &b, &g, &r) != 3) break; bm[i] = b; gm[i] = g; rm[i] = r; cp += 6; while (*cp && !isxdigit(*cp)) { cp++; } } cmsize = i; } } if (strncmp(header[line], "size", 4) == 0) { sscanf(header[line], "size %d %d", &width, &height); } } freeheader(); return(0); } static void freeheader() { int line; for (line = 0; ((line < MAX_HEAD_LINES) && (header[line] != NULL)); line++) { free(header[line]); } } static int readHeader(zf) ZFILE *zf; { char buf[HEAD_BUF_SIZE]; int count, c, lines; char *cp; cp = buf; count = 0; lines = 0; while (lines < MAX_HEAD_LINES) { while ((((c = zgetc(zf)) != '\f')) && (c != EOF) && (c != '=')) { switch(c) { case '\n': case ' ': case '\t': case '\r': continue; case ';': printf("Malformed Sun VFF header line: a `;' was found before a `='.\n" ); return(1); default: if (count < HEAD_BUF_SIZE) { *cp = (char)c; cp++; count++; } else { printf("Malformed Sun VFF header line: a line longer then %d bytes was found.\n", HEAD_BUF_SIZE); return(0); /* go ahead and try to parse what we got (geometry file?) */ } break; } } if (c == '=') { if (count < HEAD_BUF_SIZE) { *cp = ' '; cp++; count++; } else { printf("Malformed Sun VFF header line: a line longer then %d bytes was found.\n", HEAD_BUF_SIZE); return(0); } while ((c = zgetc(zf)) != ';') { switch(c) { case EOF: printf("Malformed Sun VFF header line: a `EOF' was found before a `;'.\n" ); return(1); case '\f': printf("Malformed Sun VFF header line: a `\f' was found before a `;'.\n" ); return(1); case '\n': printf("Malformed Sun VFF header line: a `\\n' was found before a `;'.\n" ); return(1); case '\\': if ((c = zgetc(zf)) == EOF) { printf("Malformed Sun VFF header line: a `EOF' was found after a `\\'.\n" ); return(1); } default: if (count < HEAD_BUF_SIZE) { *cp = (char)c; cp++; count++; } else { printf("Malformed Sun VFF header line: a line longer then %d bytes was found.\n", HEAD_BUF_SIZE); return(0); } } } if (count < HEAD_BUF_SIZE) { *cp = '\0'; cp++; count++; } else { printf("Malformed Sun VFF header line: a line longer then %d bytes was found.\n", HEAD_BUF_SIZE-1); return(0); } if ((header[lines] = (char *)malloc((unsigned)count+1)) == NULL) { memoryExhausted(); } bcopy(buf, header[lines], count); count = 0; cp = buf; lines++; } else if (c == EOF) { printf("Malformed Sun VFF header line: EOF found before the end of the header.\n"); return(1); } else if (c == '\f') { /* read the \n after the \f */ c = zgetc(zf); if (c == EOF) { printf("Malformed Sun VFF header line: EOF found before the end of the header.\n"); return(1); } return(0); } } printf("Malformed Sun VFF header: more then %d lines found.\n", MAX_HEAD_LINES); return(0); /* so that we try and see what was wrong */ } vffIdent(fullname, name) char *fullname, *name; { ZFILE *zf; char buf[4]; if (!(zf = zopen(fullname))) return(0); if (zread(zf, (unsigned char *)buf, 4) != 4) { zclose(zf); return(0); } if (strncmp(buf, "ncaa", 4) != 0) { zclose(zf); return(0); } if (readHeader(zf)) { zclose(zf); return(0); } if (parseHeader()) { zclose(zf); return(0); } if (bands == 1) { printf("%s is a %dx%d Sun VFF image with 1 band\n", name, width, height); } else { printf("%s is a %dx%d Sun VFF image with %d bands\n", name, width, height, bands); } return(1); } gb.red + i) = i * 256; *(image->rgb.green + i) = i * 256; *(image->rgb.blue + i) = i * 256; } image->rgb.used = 256; } else { if (cmsize > 256) { cmsize = 256; } for (i = 0; i < cmsize; i++) { *(image->rgb.red + i) = rm[i] * 256; *(image->rgb.green + i) = gm[i] * 256; *(image->rgb.blue + i) = bm[i] * 256; } image->rgb.used = cmsize; } op = image->data; for (y = 0; y < height; y++) { if (zread(zf,xloadimage.4.1/vicar.c 664 221 144 7154 5461577413 10033 /* ** vic.c - load a VICAR Image file for use inside xloadimage ** ** Khalid Soofi (August 1992) */ #define TRUE 1 #define FALSE 0 #define DEPTH 8 #define LBLSIZE label[0] #define LINES label[8] #define SAMPLES label[6] #include #include #include "image.h" #include FILE *fp,*fopen(); int label[10]; char labstr[80]; int flag=0; /* ** vicarIdent ** ** Identify passed file a VICAR Image ** return 1 for true ** return 0 otherwise ** */ unsigned int vicarIdent (fullname, name) char *fullname, *name; { int i=0; char IDENT[7]; char c; if ( ! (fp = fopen(fullname,"r")) ) return(0); /* identify the VICAR IMAGE */ fscanf(fp,"%6s",IDENT); if ( strcmp(IDENT,"LBLSIZ") == 0 ) { printf("%s is a VICAR Image: ",fullname); fclose(fp); } else return(0); /* Fill up the label block of image */ fp = fopen(fullname,"r"); while ( i < 10) { fscanf(fp,"%c",&c); if ( c == '=' ) fscanf(fp,"%d",&label[i++]); } printf("%d lines and %d samples\n", LINES , SAMPLES ); fclose(fp); return(1); } /* vicHeader - print the history record */ static void vicarHeader(ptr) char *ptr; { int i; int prflag; int rtflag; printf("\n ---HISTORY RECORD------------------------------------\n"); for ( i=0, prflag=FALSE, rtflag=0 ; i < LBLSIZE ; i++ ) { if ( *(ptr++) == '\'' ) { prflag = !prflag; rtflag++; } if ( prflag && (char)(*ptr) != '\'' ) printf("%c",(char)(*ptr)); if ( rtflag == 2 ) { printf("\n"); rtflag = 0; } } printf("\n -----------------------------------------------------\n"); } /* ** vicarLoad ** ** Load Vicar image into an Image structure. ** ** Return pointer to allocated struct if successful, NULL otherwise ** */ Image *vicarLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { char c; int i,j; unsigned int mapsize, size; Image *image; byte *lineptr; byte *map; byte *mapred,*mapgreen,*mapblue; byte *buf; ZFILE *zf; if ( vicarIdent(fullname,name,verbose) == 0 ) return(0); /* define the image structure */ image = newRGBImage( SAMPLES , LINES , DEPTH ); image->width = SAMPLES ; image->height = LINES ; image->depth = DEPTH ; image->title = dupString(name); /* * Set up the grey scale lookup table:- * From Jim frost 09.27.89 (sunraster.c) * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ mapsize = 256*3; map= lmalloc(mapsize); for (i = 0; i < 256; i += 1) { map[i] = map[256+i] = map[2*256+i] = i; } mapsize /= 3; mapred= map; mapgreen= mapred + mapsize; mapblue= mapgreen + mapsize; if (image->rgb.size == 0) newRGBMapData(&image->rgb, mapsize); for (i= 0; i < mapsize; i++) { *(image->rgb.red + i)= (*(mapred++) << 8); *(image->rgb.green + i)= (*(mapgreen++) << 8); *(image->rgb.blue + i)= (*(mapblue++) << 8); } lfree(map); image->rgb.used= mapsize; /* * Finally start the image data */ lineptr = image->data; if ( !(zf=zopen(fullname))) { perror(fullname); zclose(zf); exit(1); } if ( verbose ){ zread(zf,lineptr,LBLSIZE); /* dump label */ vicarHeader(lineptr); } else zread(zf,lineptr,LBLSIZE); /* skip label */ size = image->width * image->height; if (zread(zf,lineptr,size) != size) fprintf(stderr, "%s: Warning, image data was missing\n", fullname); zclose(zf); return(image); } * width; buf = (unsigned char *)malloc((unsigned)linewidth); if (buf == NULL) { memoryExhausted(); } for (y = 0; y < height; y++) { ip = buf; if (zread(zf, buf, linewidth) != linewidth) { printf("%s: short read line %d\n", image->title, y); return(0); /* show what we got */ } for (x = 0; x < width; x++) { ip += skip; *(op+xloadimage.4.1/xbitmap.c 664 221 144 12437 5461577413 10413 /* xbitmap.c: * * at one time this was XRdBitF.c. it bears very little resemblence to it * now. that was ugly code. this is cleaner, faster, and more reliable * in most cases. * * jim frost 10.06.89 * * Copyright, 1987, Massachusetts Institute of Technology * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "mit.cpyrght" #include "copyright.h" #include #include "image.h" /* SUPPRESS 560 */ #define MAX_SIZE 255 static short HexTable[256]; /* conversion value */ static unsigned int Initialized= 0; /* easier to fill in at run time */ #define b0000 0 /* things make more sense if you see them by bit */ #define b0001 1 #define b0010 2 #define b0011 3 #define b0100 4 #define b0101 5 #define b0110 6 #define b0111 7 #define b1000 8 #define b1001 9 #define b1010 10 #define b1011 11 #define b1100 12 #define b1101 13 #define b1110 14 #define b1111 15 #define HEXSTART -1 #define HEXDELIM -2 #define HEXBAD -3 /* build a hex digit value table with the bits inverted */ static void initHexTable() { int a; for (a= 0; a < 256; a++) HexTable[a]= HEXBAD; HexTable['0']= b0000; HexTable['1']= b1000; HexTable['2']= b0100; HexTable['3']= b1100; HexTable['4']= b0010; HexTable['5']= b1010; HexTable['6']= b0110; HexTable['7']= b1110; HexTable['8']= b0001; HexTable['9']= b1001; HexTable['A']= b0101; HexTable['a']= HexTable['A']; HexTable['B']= b1101; HexTable['b']= HexTable['B']; HexTable['C']= b0011; HexTable['c']= HexTable['C']; HexTable['D']= b1011; HexTable['d']= HexTable['D']; HexTable['E']= b0111; HexTable['e']= HexTable['E']; HexTable['F']= b1111; HexTable['f']= HexTable['F']; HexTable['x']= HEXSTART; HexTable['\r']= HEXDELIM; HexTable['\n']= HEXDELIM; HexTable['\t']= HEXDELIM; HexTable[' ']= HEXDELIM; HexTable[',']= HEXDELIM; HexTable['}']= HEXDELIM; Initialized = 1; } /* read a hex value and return its value */ static int nextInt(zf) ZFILE *zf; { int c; int value= 0; int shift= 0; for (;;) { c= zgetc(zf); if (c == EOF) return(-1); else { c= HexTable[c & 0xff]; switch(c) { case HEXSTART: shift= 0; /* reset shift counter */ break; case HEXDELIM: if (shift == 4) return(value << 4); if (shift) return(value); break; case HEXBAD: return(-1); default: value += (c << shift); shift += 4; } } } } static void badFile(name) char *name; { printf("%s: bad X bitmap file\n", name); exit(1); } Image *xbitmapLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; Image *image; char line[MAX_SIZE]; char name_and_type[MAX_SIZE]; char *type; int value; int v10p; unsigned int linelen, dlinelen; unsigned int x, y; unsigned int w = 0, h = 0; byte *dataptr; if (!Initialized) initHexTable(); if (! (zf= zopen(fullname))) return(NULL); /* get width/height values */ while (zgets((byte *)line, MAX_SIZE, zf)) { if (strlen(line) == MAX_SIZE-1) { zclose(zf); return(NULL); } /* width/height/hot_x/hot_y scanning */ if (sscanf(line,"#define %s %d", name_and_type, &value) == 2) { if (!(type = rindex(name_and_type, '_'))) type = name_and_type; else type++; if (!strcmp("width", type)) w= (unsigned int)value; if (!strcmp("height", type)) h= (unsigned int)value; } /* if start of data, determine if it's X10 or X11 data and break */ if (sscanf(line, "static short %s = {", name_and_type) == 1) { v10p = 1; break; } if ((sscanf(line,"static unsigned char %s = {", name_and_type) == 1) || (sscanf(line, "static char %s = {", name_and_type) == 1)) { v10p = 0; break; } } if (!w || !h) { zclose(zf); return(NULL); } image= newBitImage(w, h); /* get title of bitmap if any */ if ((type = rindex(name_and_type, '_')) && !strcmp("bits[]", type + 1)) { *type= '\0'; image->title= dupString(name_and_type); } /* read bitmap data */ linelen= (w / 8) + (w % 8 ? 1 : 0); /* internal line length */ if (v10p) { dlinelen= (w / 8) + (w % 16 ? 2 : 0); dataptr= image->data; for (y= 0; y < h; y++) { for (x= 0; x < dlinelen; x++) { if ((value= nextInt(zf)) < 0) { freeImage(image); zclose(zf); return(NULL); } *(dataptr++)= value >> 8; if (++x < linelen) *(dataptr++)= value & 0xff; } } } else { dataptr= image->data; for (y= 0; y < h; y++) for (x= 0; x < linelen; x++) { if ((value= nextInt(zf)) < 0) badFile(name); *(dataptr++)= value; } } if (verbose) { printf("%s is a %dx%d X", name, image->width, image->height); if (v10p) printf("10"); else printf("11"); if (image->title) printf(" bitmap file titled '%s'", image->title); printf("\n"); } zclose(zf); return(image); } /* this is the easiest way to do this. it's not likely we'll have mondo * x bitmaps anyway given their size */ int xbitmapIdent(fullname, name) char *fullname, *name; { Image *image; if (image= xbitmapLoad(fullname, name, (unsigned int)1)) { freeImage(image); return(1); } return(0); } &b, &g, &r) != 3) break; bm[i] = b; gm[i] = g; rm[i] = r; cp += 6; while (*cp && !isxdigit(*cp)) { cp++; } } cmsize = i; } } if (strncmp(header[line], "size", 4) == xloadimage.4.1/xpixmap.c 664 221 144 13347 5461577414 10437 /* xpixmap.c: * * XPixMap format file read and identify routines. these can handle any * "format 1" XPixmap file with up to BUFSIZ - 1 chars per pixel. it's * not nearly as picky as it might be. * * unlike most image loading routines, this is X specific since it * requires X color name parsing. to handle this we have global X * variables for display and screen. it's ugly but it keeps the rest * of the image routines clean. * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include "xloadimage.h" /* SUPPRESS 530 */ /* SUPPRESS 560 */ extern Display *Disp; /* X display, null if in "identify" mode */ extern int Scrn; /* X screen number */ #define XPM_FORMAT 1 static void corrupted(fullname, zf) char *fullname; ZFILE *zf; { zclose(zf); printf("%s: X Pixmap file is corrupted\n", fullname); exit(1); } Image *xpixmapLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { ZFILE *zf; char buf[BUFSIZ]; char what[BUFSIZ]; char *p; char *imagetitle; unsigned int value; unsigned int format; /* image format */ unsigned int w, h; /* image dimensions */ unsigned int cpp; /* chars per pixel */ unsigned int ncolors; /* number of colors */ unsigned int depth; /* depth of image */ char **ctable; /* color table */ Image *image; XColor xcolor; unsigned int a, b, x, y; int c; byte *dptr; if (! (zf= zopen(fullname))) return(NULL); /* read #defines until we have all that are necessary or until we * get an error */ format= w= h= ncolors= 0; for (;;) { if (! zgets((byte *)buf, BUFSIZ - 1, zf)) { zclose(zf); return(NULL); } if (!strncmp(buf, "#define", 7)) { if (sscanf(buf, "#define %s %d", what, &value) != 2) { zclose(zf); return(NULL); } if (! (p= rindex(what, '_'))) p= what; else p++; if (!strcmp(p, "format")) format= value; else if (!strcmp(p, "width")) w= value; else if (!strcmp(p, "height")) h= value; else if (!strcmp(p, "ncolors")) ncolors= value; /* this one is ugly */ else if (!strcmp(p, "pixel")) { /* this isn't pretty but it works */ if (p == what) continue; *(--p)= '\0'; if (!(p= rindex(what, '_')) || (p == what) || strcmp(++p, "per")) continue; *(--p)= '\0'; if (!(p= rindex(what, '_'))) p= what; if (strcmp(++p, "chars")) continue; cpp= value; } } else if ((sscanf(buf, "static char * %s", what) == 1) && (p= rindex(what, '_')) && !strcmp(++p, "colors[]")) break; } if ((format != XPM_FORMAT) || !w || !h || !ncolors || !cpp) { zclose(zf); return(NULL); } if (p= rindex(what, '_')) { /* get the name in the image if there is */ *p= '\0'; /* one */ imagetitle= dupString(what); } else { p= what; imagetitle= dupString(name); } if (verbose) printf("%s is a %dx%d X Pixmap image with %d colors titled '%s'\n", name, w, h, ncolors, imagetitle); for (depth= 1, value= 2; value < ncolors; value <<= 1, depth++) ; image= newRGBImage(w, h, depth); image->rgb.used= ncolors; image->title= dupString(imagetitle); /* read the colors array and build the image colormap */ ctable= (char **)lmalloc(sizeof(char *) * ncolors); xcolor.flags= DoRed | DoGreen | DoBlue; for (a= 0; a < ncolors; a++) { /* read pixel value */ *(ctable + a)= (char *)lmalloc(cpp); while (((c= zgetc(zf)) != EOF) && (c != '"')) ; if (c == EOF) corrupted(fullname, zf); for (b= 0; b < cpp; b++) { if ((c= zgetc(zf)) == '\\') c= zgetc(zf); if (c == EOF) corrupted(fullname, zf); *(*(ctable + a) + b)= (char)c; } if (((c= zgetc(zf)) == EOF) || (c != '"')) corrupted(fullname, zf); /* read color definition and parse it */ while (((c= zgetc(zf)) != EOF) && (c != '"')) ; if (c == EOF) corrupted(fullname, zf); for (b= 0; ((c= zgetc(zf)) != EOF) && (c != '"'); b++) { if (c == '\\') c= zgetc(zf); if (c == EOF) corrupted(fullname, zf); buf[b]= (char)c; } buf[b]= '\0'; if (Disp) { if (! XParseColor(Disp, DefaultColormap(Disp, Scrn), buf, &xcolor)) { printf("%s: %s: Bad color name\n", fullname, buf); exit(1); } *(image->rgb.red + a)= xcolor.red; *(image->rgb.green + a)= xcolor.green; *(image->rgb.blue + a)= xcolor.blue; } } for (;;) { if (! zgets((byte *)buf, BUFSIZ - 1, zf)) corrupted(fullname, zf); if (sscanf(buf, "static char * %s", what) == 1) break; } if (p= rindex(what, '_')) p++; else p= what; if (strcmp(p, "pixels[]")) corrupted(fullname, zf); /* read in image data */ dptr= image->data; for (y= 0; y < h; y++) { while (((c= zgetc(zf)) != EOF) && (c != '"')) ; for (x= 0; x < w; x++) { for (a= 0; a < cpp; a++) { if ((c= zgetc(zf)) == '\\') c= zgetc(zf); if (c == EOF) corrupted(fullname, zf); buf[a]= (char)c; } for (a= 0; a < ncolors; a++) if (!strncmp(*(ctable + a), buf, cpp)) break; if (a == ncolors) { /* major uncool */ zclose(zf); printf("%s: Pixel data doesn't match color data\n", fullname); exit(1); } valToMem((unsigned long)a, dptr, image->pixlen); dptr += image->pixlen; } if ((c= zgetc(zf)) != '"') corrupted(fullname, zf); } zclose(zf); return(image); } int xpixmapIdent(fullname, name) char *fullname, *name; { Image *image; if (image= xpixmapLoad(fullname, name, (unsigned int)1)) { freeImage(image); return(1); } return(0); } extInt(zf)) < 0) { freeImage(image); zclose(zf); return(NULL); } *(dataptr++)= value >> 8; if (++x < linelen) *(dataptr++)= value & 0xff; } } } else { dataptr= image->data; for (y= 0; y < h; y++) for (x= 0; x < linelen; x++) { if ((valuexloadimage.4.1/xwd.c 664 221 144 34770 5461577414 7556 /* xwd.c: * * XWD file reader. unfortunately the bozo who thought up this format didn't * define anything at all that we can use as an identifier or even to tell * what kind of machine dumped the format. what this does is read the * header and look at several fields to decide if this *might* be an XWD * file and if it is what byte order machine wrote it. * * jim frost 07.24.90 * * Copyright 1990 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include "xloadimage.h" #include "xwd.h" /* SUPPRESS 558 */ /* this reads the header and does the magic to determine if it is indeed * an XWD file. */ static int isXWD(name, zf, header, verbose) char *name; ZFILE *zf; XWDHeader *header; int verbose; { GenericXWDHeader gh; int a; if (zread(zf, (byte *)&gh, sizeof(GenericXWDHeader)) != sizeof(GenericXWDHeader)) return(0); /* first try -- see if XWD version number matches in either MSB or LSB order */ if (memToVal(gh.file_version, 4) != XWD_VERSION) return(0); /* convert fields to fill out header. things we don't care about * are commented out. */ header->header_size= memToVal(gh.header_size, 4); header->file_version= memToVal(gh.file_version, 4); header->pixmap_format= memToVal(gh.pixmap_format, 4); header->pixmap_depth= memToVal(gh.pixmap_depth, 4); header->pixmap_width= memToVal(gh.pixmap_width, 4); header->pixmap_height= memToVal(gh.pixmap_height, 4); header->xoffset= memToVal(gh.xoffset, 4); header->byte_order= memToVal(gh.byte_order, 4); header->bitmap_unit= memToVal(gh.bitmap_unit, 4); header->bitmap_bit_order= memToVal(gh.bitmap_bit_order, 4); header->bitmap_pad= memToVal(gh.bitmap_pad, 4); header->bits_per_pixel= memToVal(gh.bits_per_pixel, 4); header->bytes_per_line= memToVal(gh.bytes_per_line, 4); header->visual_class= memToVal(gh.visual_class, 4); /*header->red_mask= memToVal(gh.red_mask, 4);*/ /*header->green_mask= memToVal(gh.green_mask, 4);*/ /*header->blue_mask= memToVal(gh.blue_mask, 4);*/ /*header->bits_per_rgb= memToVal(gh.bits_per_rgb, 4);*/ header->colormap_entries= memToVal(gh.colormap_entries, 4); header->ncolors= memToVal(gh.ncolors, 4); /*header->window_width= memToVal(gh.window_width, 4);*/ /*header->window_height= memToVal(gh.window_height, 4);*/ /*header->window_x= memToVal(gh.window_x, 4);*/ /*header->window_y= memToVal(gh.window_y, 4);*/ /*header->window_bdrwidth= memToVal(gh.window_bdrwidth, 4);*/ /* if header size isn't either 100 or 104 bytes, this isn't an XWD file */ if (header->header_size < sizeof(GenericXWDHeader)) return(0); for (a= header->header_size - sizeof(GenericXWDHeader); a; a--) zgetc(zf); /* look at a variety of the XImage fields to see if they are sane. if * they are, this passes our tests. */ switch (header->pixmap_format) { case XYBitmap: case XYPixmap: case ZPixmap: break; default: return(0); } switch (header->visual_class) { case StaticGray: case GrayScale: case StaticColor: case PseudoColor: /* the following are unsupported but recognized */ case TrueColor: case DirectColor: break; default: return(0); } if (verbose) { printf("%s is a %dx%d XWD image in ", name, header->pixmap_width, header->pixmap_height); switch (header->pixmap_format) { case XYBitmap: printf("XYBitmap"); break; case XYPixmap: printf("%d bit XYPixmap", header->pixmap_depth); break; case ZPixmap: printf("%d bit ZPixmap", header->pixmap_depth); break; } printf(" format\n"); } /* if it got this far, we're pretty damned certain we've got the right * file type and know what order it's in. */ znocache(zf); return(1); } int xwdIdent(fullname, name) char *fullname, *name; { ZFILE *zf; XWDHeader header; int ret; if (! (zf= zopen(fullname))) return(0); ret= isXWD(name, zf, &header, 1); zclose(zf); return(ret); } static Image *loadXYBitmap(fullname, zf, header) char *fullname; ZFILE *zf; XWDHeader header; { Image *image; int dlinelen; /* length of scan line in data file */ int ilinelen; /* length of line within image structure */ int unit; /* # of bytes in a bitmap unit */ int xoffset; /* xoffset within line */ int xunits; /* # of units across the whole scan line */ int trailer; /* # of bytes in last bitmap unit on a line */ int shift; /* # of bits to shift last byte set */ int x, y; /* horizontal and vertical counters */ byte *line; /* input scan line */ byte *dptr, *iptr; /* image data pointers */ unsigned long (*loader)(); /* unit loading function */ image= newBitImage(header.pixmap_width, header.pixmap_height); ilinelen= (header.pixmap_width / 8) + (header.pixmap_width % 8 ? 1 : 0); if (header.bitmap_unit > 7) /* supposed to be 8, 16, or 32 but appears */ unit= header.bitmap_unit / 8; /* to often be the byte count. this will */ else /* accept either. */ unit= header.bitmap_unit; xoffset= (header.xoffset / (unit * 8)) * unit; if (header.bytes_per_line) dlinelen= header.bytes_per_line; else dlinelen= unit * header.pixmap_width; xunits= (header.pixmap_width / (unit * 8)) + (header.pixmap_width % (unit * 8) ? 1 : 0); trailer= unit - ((xunits * unit) - ilinelen); xunits--; /* we want to use one less than the actual # of units */ shift= (unit - trailer) * 8; if (header.byte_order == MSBFirst) loader= doMemToVal; else loader= doMemToValLSB; line= (byte *)lmalloc(dlinelen); for (y= 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *)line, dlinelen) != dlinelen) { fprintf(stderr, "%s: Short read while reading data! (returning partial image)\n", fullname); lfree(line); return(image); } dptr= line + xoffset; iptr= image->data + (y * ilinelen); if (header.bitmap_bit_order == LSBFirst) flipBits(line, dlinelen); for (x= 0; x < xunits; x++) { valToMem(loader(dptr, unit), iptr, unit); dptr += unit; iptr += unit; } /* take care of last unit on this line */ valToMem(loader(dptr, unit) >> shift, iptr, trailer); } lfree(line); return(image); } /* this is a lot like the above function but OR's planes together to * build the destination. 1-bit images are handled by XYBitmap. */ static Image *loadXYPixmap(fullname, zf, header) char *fullname; ZFILE *zf; XWDHeader header; { Image *image; int plane; int dlinelen; /* length of scan line in data file */ int ilinelen; /* length of line within image structure */ int unit; /* # of bytes in a bitmap unit */ int unitbits; /* # of bits in a bitmap unit */ int unitmask; /* mask for current bit within current unit */ int xoffset; /* xoffset within data */ int xunits; /* # of units across the whole scan line */ int x, x2, y; /* horizontal and vertical counters */ int index; /* index within image scan line */ byte *line; /* input scan line */ byte *dptr, *iptr; /* image data pointers */ unsigned long pixvals; /* bits for pixels in this unit */ unsigned long mask; unsigned long (*loader)(); /* unit loading function */ image= newRGBImage(header.pixmap_width, header.pixmap_height, header.pixmap_depth); ilinelen= image->width * image->pixlen; if (header.bitmap_unit > 7) /* supposed to be 8, 16, or 32 but appears */ unit= header.bitmap_unit / 8; /* to often be the byte count. this will */ else /* accept either. */ unit= header.bitmap_unit; unitbits= unit * 8; unitmask= 1 << (unitbits - 1); xoffset= (header.xoffset / unitbits) * unit; if (header.bytes_per_line) dlinelen= header.bytes_per_line; else dlinelen= unit * header.pixmap_width; xunits= (header.pixmap_width / (unit * 8)) + (header.pixmap_width % (unit * 8) ? 1 : 0); if (header.byte_order == MSBFirst) loader= doMemToVal; else loader= doMemToValLSB; line= (byte *)lmalloc(dlinelen); /* for each plane, load in the bitmap and or it into the image */ for (plane= 0; plane < header.pixmap_depth; plane++) { Pixel plane_mask; plane_mask = (1 << (header.pixmap_depth - plane - 1)); for (y= 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *)line, dlinelen) != dlinelen) { fprintf(stderr, "%s: Short read while reading data! (returning partial image)\n", fullname); lfree(line); return(image); } dptr= line + xoffset; iptr= image->data + (y * ilinelen); index= 0; if (header.bitmap_bit_order == LSBFirst) flipBits(line, dlinelen); for (x= 0; x < xunits; x++) { pixvals= loader(dptr, unit); mask= unitmask; for (x2= 0; x2 < unitbits; x2++) { if (pixvals & mask) valToMem(memToVal(iptr + index, image->pixlen) | plane_mask, iptr + index, image->pixlen); index += image->pixlen; if (index > ilinelen) { x= xunits; break; } if (! (mask >>= 1)) mask= unitmask; } dptr += unit; } } } lfree(line); return(image); } /* this loads a ZPixmap format image. note that this only supports depths * of 4, 8, 16, 24, or 32 bits as does Xlib. You gotta 6-bit image, * you gotta problem. 1-bit images are handled by XYBitmap. */ static Image *loadZPixmap(fullname, zf, header) char *fullname; ZFILE *zf; XWDHeader header; { Image *image; int dlinelen; /* length of scan line in data file */ int ilinelen; /* length of scan line in image file */ int depth; /* depth rounded up to 8-bit value */ int pixlen; /* length of pixel in bytes */ int x, y; /* horizontal and vertical counters */ byte *line; /* input scan line */ byte *dptr, *iptr; /* image data pointers */ unsigned long pixmask; /* bit mask within pixel */ unsigned long pixel; /* pixel we're working on */ unsigned long (*loader)(); /* unit loading function */ image= newRGBImage(header.pixmap_width, header.pixmap_height, header.pixmap_depth); /* for pixmaps that aren't simple depths, we round to a depth of 8. this * is what Xlib does, be it right nor not. */ if ((header.pixmap_depth != 4) && (header.pixmap_depth % 8)) depth= header.pixmap_depth + 8 - (header.pixmap_depth % 8); else depth= header.pixmap_depth; pixmask= 0xffffffff >> (32 - header.pixmap_depth); pixlen= image->pixlen; if (header.bytes_per_line) dlinelen= header.bytes_per_line; else dlinelen= depth * header.pixmap_width; ilinelen= image->width * image->pixlen; if (header.byte_order == MSBFirst) loader= doMemToVal; else loader= doMemToValLSB; line= (byte *)lmalloc(dlinelen); for (y= 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *)line, dlinelen) != dlinelen) { fprintf(stderr, "%s: Short read while reading data! (returning partial image)\n", fullname); lfree(line); return(image); } dptr= line; iptr= image->data + (y * ilinelen); if (header.bitmap_bit_order == LSBFirst) flipBits(line, dlinelen); for (x= 0; x < header.pixmap_width; x++) { switch (depth) { case 4: pixel= memToVal(dptr, 1); if (header.bitmap_bit_order == LSBFirst) { /* nybbles are reversed */ valToMem(pixel & 0xf, iptr++, 1); /* by flipBits */ if (++x < header.pixmap_width) valToMem(pixel >> 4, iptr++, 1); } else { valToMem(pixel >> 4, iptr++, 1); if (++x < header.pixmap_width) valToMem(pixel & 0xf, iptr++, 1); } break; case 8: pixel= ((unsigned long)*(dptr++)) & pixmask; /* loader isn't needed */ valToMem(pixel, iptr++, 1); break; case 16: case 24: case 32: valToMem(loader(dptr, pixlen) & pixmask, iptr, pixlen); dptr += pixlen; iptr += pixlen; break; default: fprintf(stderr, "%s: ZPixmaps of depth %d are not supported (sorry).\n", fullname, header.pixmap_depth); exit(1); } } } lfree(line); return(image); } Image *xwdLoad(fullname, name, verbose) char *fullname, *name; int verbose; { ZFILE *zf; XWDHeader header; int cmaplen; XWDColor *cmap; Image *image; int a; if (! (zf= zopen(fullname))) return(NULL); if (! isXWD(name, zf, &header, verbose)) { zclose(zf); return(NULL); } /* complain if we don't understand the visual */ switch (header.visual_class) { case StaticGray: case GrayScale: case StaticColor: case PseudoColor: break; case TrueColor: case DirectColor: fprintf(stderr, "Unsupported visual type, sorry\n"); exit(1); } if ((header.pixmap_width == 0) || (header.pixmap_height == 0)) { fprintf(stderr, "Zero-size image -- header might be corrupted.\n"); exit(1); } /* read in colormap */ cmaplen= header.ncolors * sizeof(XWDColor); cmap= (XWDColor *)lmalloc(cmaplen); if (zread(zf, (byte *)cmap, cmaplen) != cmaplen) { fprintf(stderr, "Short read in colormap!\n"); exit(1); } /* any depth 1 image is basically a XYBitmap so we fake it here */ if (header.pixmap_depth == 1) header.pixmap_format= XYBitmap; /* we can't realistically support images of more than depth 16 with the * RGB image format so this nukes them for the time being. */ if (header.pixmap_depth > 16) { fprintf(stderr, "%s: Sorry, cannot load images deeper than 16 bits (yet)\n", fullname); exit(1); } switch (header.pixmap_format) { case XYBitmap: image= loadXYBitmap(fullname, zf, header); zclose(zf); image->title= dupString(name); return(image); /* we used to goof w/ the cmap but we gave up */ case XYPixmap: image= loadXYPixmap(fullname, zf, header); break; case ZPixmap: image= loadZPixmap(fullname, zf, header); break; } zclose(zf); image->title= dupString(name); /* load the colormap. we should probably use pixval instead of the color * number but the value seems pretty system-dependent and most colormaps * seem to be just dumped in order. */ image->rgb.used= header.ncolors; for (a= 0; a < header.ncolors; a++) { image->rgb.red[memToVal(cmap[a].pixel, 4)]= memToVal(cmap[a].red, 2); image->rgb.green[memToVal(cmap[a].pixel, 4)]= memToVal(cmap[a].green, 2); image->rgb.blue[memToVal(cmap[a].pixel, 4)]= memToVal(cmap[a].blue, 2); } lfree((byte *)cmap); return(image); } p(fullnaxloadimage.4.1/bright.c 664 221 144 14401 5463771223 10214 /* bright.c * * miscellaneous colormap altering functions * * jim frost 10.10.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" /* alter an image's brightness by a given percentage */ void brighten(image, percent, verbose) Image *image; unsigned int percent; unsigned int verbose; { int a; unsigned int newrgb; float fperc; unsigned int size; byte *destptr; goodImage(image, "brighten"); if (BITMAPP(image)) /* we're AT&T */ return; if (verbose) { printf(" Brightening colormap by %d%%...", percent); fflush(stdout); } fperc= (float)percent / 100.0; switch (image->type) { case IRGB: for (a= 0; a < image->rgb.used; a++) { newrgb= *(image->rgb.red + a) * fperc; if (newrgb > 65535) newrgb= 65535; *(image->rgb.red + a)= newrgb; newrgb= *(image->rgb.green + a) * fperc; if (newrgb > 65535) newrgb= 65535; *(image->rgb.green + a)= newrgb; newrgb= *(image->rgb.blue + a) * fperc; if (newrgb > 65535) newrgb= 65535; *(image->rgb.blue + a)= newrgb; } break; case ITRUE: size= image->width * image->height * 3; destptr= image->data; for (a= 0; a < size; a++) { newrgb= *destptr * fperc; if (newrgb > 255) newrgb= 255; *(destptr++)= newrgb; } break; } if (verbose) printf("done\n"); } void gammacorrect(image, disp_gam, verbose) Image *image; double disp_gam; unsigned int verbose; { int a; int gammamap[256]; unsigned int size; byte *destptr; goodImage(image, "gammacorrect"); if (BITMAPP(image)) /* we're AT&T */ return; if (verbose) { printf(" Adjusting colormap for display gamma of %4.2f...", disp_gam); fflush(stdout); } make_gamma(disp_gam,gammamap); switch (image->type) { case IRGB: for (a= 0; a < image->rgb.used; a++) { *(image->rgb.red + a)= gammamap[(*(image->rgb.red + a))>>8]<<8; *(image->rgb.green + a)= gammamap[(*(image->rgb.green + a))>>8]<<8; *(image->rgb.blue + a)= gammamap[(*(image->rgb.blue + a))>>8]<<8; } break; case ITRUE: size= image->width * image->height * 3; destptr= image->data; for (a= 0; a < size; a++) { *destptr= gammamap[*destptr]; destptr++; } break; } if (verbose) printf("done\n"); } /* this initializes a lookup table for doing normalization */ static void setupNormalizationArray(min, max, array, verbose) unsigned int min, max; byte *array; unsigned int verbose; { int a; unsigned int new; float factor; if (verbose) { printf("scaling %d:%d to 0:255...", min, max); fflush(stdout); } factor= 256.0 / (max - min); for (a= min; a <= max; a++) { new= (float)(a - min) * factor; array[a]= (new > 255 ? 255 : new); } } /* normalize an image. */ Image *normalize(image, verbose) Image *image; unsigned int verbose; { unsigned int a, x, y; unsigned int min, max; Pixel pixval; Image *newimage; byte *srcptr, *destptr; byte array[256]; goodImage(image, "normalize"); if (BITMAPP(image)) return(image); if (verbose) { printf(" Normalizing..."); fflush(stdout); } switch (image->type) { case IRGB: min= 256; max = 0; for (a= 0; a < image->rgb.used; a++) { byte red, green, blue; red= image->rgb.red[a] >> 8; green= image->rgb.green[a] >> 8; blue= image->rgb.blue[a] >> 8; if (red < min) min= red; if (red > max) max= red; if (green < min) min= green; if (green > max) max= green; if (blue < min) min= blue; if (blue > max) max= blue; } setupNormalizationArray(min, max, array, verbose); newimage= newTrueImage(image->width, image->height); if (image->title) { newimage->title = (char *)lmalloc(strlen(image->title) + 14); sprintf(newimage->title, "%s (normalized)", image->title); } srcptr= image->data; destptr= newimage->data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixval= memToVal(srcptr, image->pixlen); *destptr= array[image->rgb.red[pixval] >> 8]; *destptr++; *destptr= array[image->rgb.green[pixval] >> 8]; *destptr++; *destptr= array[image->rgb.blue[pixval] >> 8]; *destptr++; srcptr += image->pixlen; } break; case ITRUE: srcptr= image->data; min= 255; max= 0; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { if (*srcptr < min) min= *srcptr; if (*srcptr > max) max= *srcptr; srcptr++; if (*srcptr < min) min= *srcptr; if (*srcptr > max) max= *srcptr; srcptr++; if (*srcptr < min) min= *srcptr; if (*srcptr > max) max= *srcptr; srcptr++; } setupNormalizationArray(min, max, array, verbose); srcptr= image->data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { *srcptr= array[*srcptr]; srcptr++; *srcptr= array[*srcptr]; srcptr++; *srcptr= array[*srcptr]; srcptr++; } newimage= image; } if (verbose) printf("done\n"); return(newimage); } /* convert to grayscale */ void gray(image, verbose) Image *image; unsigned int verbose; { int a; unsigned int size; Intensity intensity, red, green, blue; byte *destptr; goodImage(image, "gray"); if (BITMAPP(image)) return; if (verbose) { printf(" Converting image to grayscale..."); fflush(stdout); } switch (image->type) { case IRGB: for (a= 0; a < image->rgb.used; a++) { intensity= colorIntensity(image->rgb.red[a], image->rgb.green[a], image->rgb.blue[a]); image->rgb.red[a]= intensity; image->rgb.green[a]= intensity; image->rgb.blue[a]= intensity; } break; case ITRUE: size= image->width * image->height; destptr= image->data; for (a= 0; a < size; a++) { red= *destptr << 8; green= *(destptr + 1) << 8; blue= *(destptr + 2) << 8; intensity= colorIntensity(red, green, blue) >> 8; *(destptr++)= intensity; /* red */ *(destptr++)= intensity; /* green */ *(destptr++)= intensity; /* blue */ } break; } if (verbose) printf("done\n"); } * 3; destptr= image->data; for (a= 0; a < size; a++) { *destptr= gammamap[*destptr]; destptr++; } break; } if (verbose) printf("done\n"); } /* this initializes a lookup table for doing normalization */ static void sxloadimage.4.1/clip.c 664 221 144 5470 5461577404 7655 /* clip.c: * * return a new image which is a clipped subsection of the old image * * jim frost 10.04.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" Image *clip(simage, clipx, clipy, clipw, cliph, verbose) Image *simage; unsigned int clipx, clipy, clipw, cliph; unsigned int verbose; { Image *image; unsigned int x, y; unsigned int slinelen, dlinelen; unsigned int start; byte startmask, smask, dmask; byte *sp, *sline, *dp, *dline; goodImage(simage, "clip"); if (verbose) { printf(" Clipping image..."); fflush(stdout); } /* sane-ify clip area with respect to image */ if (clipx + clipw > simage->width) clipw -= (simage->width - (clipx + clipw)); if (clipy + cliph > simage->height) cliph -= (simage->height - (clipy + cliph)); switch (simage->type) { case IBITMAP: /* this could be sped up; i don't care */ image= newBitImage(clipw, cliph); for (x= 0; x < simage->rgb.used; x++) { *(image->rgb.red + x)= *(simage->rgb.red + x); *(image->rgb.green + x)= *(simage->rgb.green + x); *(image->rgb.blue + x)= *(simage->rgb.blue + x); } slinelen= (simage->width / 8) + (simage->width % 8 ? 1 : 0); dlinelen= (clipw / 8) + (clipw % 8 ? 1 : 0); start= clipx / 8; startmask= 0x80 >> (clipx % 8); sline= simage->data + (slinelen * clipy); dline= image->data; for (y= 0; y < cliph; y++) { sp= sline + start; dp= dline; smask= startmask; dmask= 0x80; for (x= 0; x < clipw; x++) { if (*sp & smask) *dp |= dmask; if (! (smask >>= 1)) { smask= 0x80; sp++; } if (! (dmask >>= 1)) { dmask= 0x80; dp++; } } sline += slinelen; dline += dlinelen; } break; case IRGB: case ITRUE: if (RGBP(simage)) { image= newRGBImage(clipw, cliph, simage->depth); for (x= 0; x < simage->rgb.used; x++) { *(image->rgb.red + x)= *(simage->rgb.red + x); *(image->rgb.green + x)= *(simage->rgb.green + x); *(image->rgb.blue + x)= *(simage->rgb.blue + x); } image->rgb.used= simage->rgb.used; } else image= newTrueImage(clipw, cliph); slinelen= simage->width * simage->pixlen; start= clipx * simage->pixlen; sline= simage->data + (clipy * slinelen); dp= image->data; for (y= 0; y < cliph; y++) { sp= sline + start; for (x= 0; x < clipw; x++) { valToMem(memToVal(sp, simage->pixlen), dp, simage->pixlen); sp += simage->pixlen; dp += simage->pixlen; } sline += slinelen; } break; default: printf("clip: Unsupported image type\n"); exit(1); } image->title= dupString(simage->title); if (verbose) printf("done\n"); return(image); } normalize(image, verbose) Image *image; unsigned int verbose; { unsigned int a, x, y; unsigned int min, max; Pixel pixval; Image *newimage; byte *srcxloadimage.4.1/compress.c 664 221 144 10542 5461577404 10575 /* compress.c: * * compress a colormap by removing unused or duplicate RGB colors. this * uses a 15-bit true color pixel as an index into a hash table of pixel * values (similar to the technique used in reduce.c). * * jim frost 10.05.89 * * Copyright 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" /* this converts a TLA-style pixel into a 15-bit true color pixel */ #define TLA_TO_15BIT(TABLE,PIXEL) \ ((((TABLE).red[PIXEL] & 0xf800) >> 1) | \ (((TABLE).green[PIXEL] & 0xf800) >> 6) | \ (((TABLE).blue[PIXEL] & 0xf800) >> 11)) /* these macros extract color intensities from a 15-bit true color pixel */ #define RED_INTENSITY(P) (((P) & 0x7c00) >> 10) #define GREEN_INTENSITY(P) (((P) & 0x03e0) >> 5) #define BLUE_INTENSITY(P) ((P) & 0x001f) #define NIL_PIXEL 0xffffffff void compress(image, verbose) Image *image; unsigned int verbose; { Pixel hash_table[32768]; Pixel *pixel_table; Pixel *pixel_map; Pixel index, oldpixval, newpixval; byte *pixptr; unsigned int x, y, badcount, dupcount; RGBMap rgb; goodImage(image, "compress"); if (!RGBP(image) || image->rgb.compressed) /* we're AT&T */ return; if (verbose) { printf(" Compressing colormap..."); fflush(stdout); } /* initialize hash table and allocate new RGB intensity tables */ for (x= 0; x < 32768; x++) hash_table[x]= NIL_PIXEL; newRGBMapData(&rgb, image->rgb.used); rgb.size= image->rgb.used; rgb.used= 0; pixel_table= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used); pixel_map= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used); for (x= 0; x < image->rgb.used; x++) pixel_map[x]= NIL_PIXEL; pixptr= image->data; dupcount= badcount= 0; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { oldpixval= memToVal(pixptr, image->pixlen); if (oldpixval > image->rgb.used) { badcount++; oldpixval= 0; } /* if we don't already know what value the new pixel will have, * look for a similar pixel in hash table. */ if (pixel_map[oldpixval] == NIL_PIXEL) { index= TLA_TO_15BIT(image->rgb, oldpixval); /* nothing similar */ if (hash_table[index] == NIL_PIXEL) { newpixval= rgb.used++; hash_table[index]= newpixval; } /* we've seen one like this before; try to find out if it's an * exact match */ else { newpixval= hash_table[index]; for (;;) { /* if the color is the same as another color we've seen, * use the pixel that the other color is using */ if ((rgb.red[newpixval] == image->rgb.red[oldpixval]) && (rgb.green[newpixval] == image->rgb.green[oldpixval]) && (rgb.blue[newpixval] == image->rgb.blue[oldpixval])) { pixel_map[oldpixval]= newpixval; /* same color */ dupcount++; goto move_pixel; } /* if we're at the end of the chain, we're the first pixel * of this color */ if (pixel_table[newpixval] == NIL_PIXEL) /* end of the chain */ break; newpixval= pixel_table[newpixval]; } pixel_table[newpixval]= rgb.used; newpixval= rgb.used++; } pixel_map[oldpixval]= newpixval; pixel_table[newpixval]= NIL_PIXEL; rgb.red[newpixval]= image->rgb.red[oldpixval]; rgb.green[newpixval]= image->rgb.green[oldpixval]; rgb.blue[newpixval]= image->rgb.blue[oldpixval]; } /* change the pixel */ move_pixel: valToMem(pixel_map[oldpixval], pixptr, image->pixlen); pixptr += image->pixlen; } lfree((byte *)pixel_table); lfree((byte *)pixel_map); if (badcount) if (verbose) printf("%d out-of-range pixels, ", badcount); else fprintf(stderr, "Warning: %d out-of-range pixels were seen\n", badcount); if (verbose) { if ((rgb.used == image->rgb.used) && !badcount) printf("no improvment\n"); else { int unused= image->rgb.used - rgb.used - dupcount; if (dupcount) printf("%d duplicate%s and %d unused color%s removed...", dupcount, (dupcount == 1 ? "" : "s"), unused, (unused == 1 ? "" : "s")); printf("%d unique color%s\n", rgb.used, (rgb.used == 1 ? "" : "s")); } } /* image is converted; now fix up its colormap */ freeRGBMapData(&(image->rgb)); image->rgb= rgb; image->rgb.compressed= 1; } *newimage; byte *srcptr, *destptr; byte array[256]; goodImage(image, "normalize"); if (BITMAPP(image)) return(image); if (verxloadimage.4.1/dither.c 664 221 144 13645 5461775317 10233 /* dither.c * * completely reworked dithering module for xloadimage * uses error-diffusion dithering (floyd-steinberg) instead * of simple 4x4 ordered-dither that was previously used * * the previous version of this code was written by steve losen * (scl@virginia.edu) * * jim frost 07.10.89 * Steve Losen 11.17.89 * kirk johnson 06.04.90 * * Copyright 1990 Kirk L. Johnson (see the included file * "kljcpyrght.h" for complete copyright information) * * Copyright 1989, 1990 Jim Frost and Steve Losen. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "kljcpyrght.h" #include "image.h" #define MaxIntensity 65536 /* maximum possible Intensity */ #define MaxGrey 32768 /* limits on the grey levels used */ #define Threshold 16384 /* in the dithering process */ #define MinGrey 0 static unsigned int tone_scale_adjust(); static void LeftToRight(); static void RightToLeft(); /* * simple floyd-steinberg dither with serpentine raster processing */ Image *dither(cimage, verbose) Image *cimage; unsigned int verbose; { Image *image; /* destination image */ unsigned int *grey; /* grey map for source image */ unsigned int spl; /* source pixel length in bytes */ unsigned int dll; /* destination line length in bytes */ unsigned char *src; /* source data */ unsigned char *dst; /* destination data */ int *curr; /* current line buffer */ int *next; /* next line buffer */ int *swap; /* for swapping line buffers */ Pixel color; /* pixel color */ unsigned int level; /* grey level */ unsigned int i, j; /* loop counters */ /* * check the source image */ goodImage(cimage, "dither"); if (BITMAPP(cimage)) return(NULL); /* * allocate destination image */ if (verbose) { printf(" Dithering image..."); fflush(stdout); } image = newBitImage(cimage->width, cimage->height); if (cimage->title) { image->title = (char *)lmalloc(strlen(cimage->title) + 12); sprintf(image->title, "%s (dithered)", cimage->title); } /* * if the number of entries in the colormap isn't too large, compute * the grey level for each entry and store it in grey[]. else the * grey levels will be computed on the fly. */ if (RGBP(cimage) && (cimage->depth <= 16)) { grey = (unsigned int *)lmalloc(sizeof(unsigned int) * cimage->rgb.used); for (i=0; irgb.used; i++) grey[i]= (colorIntensity(cimage->rgb.red[i], cimage->rgb.green[i], cimage->rgb.blue[i]) >> 1); for (i=0; irgb.used; i++) grey[i] = tone_scale_adjust(grey[i]); } else { grey = NULL; } /* * dither setup */ spl = cimage->pixlen; dll = (image->width / 8) + (image->width % 8 ? 1 : 0); src = cimage->data; dst = image->data; curr = (int *)lmalloc(sizeof(int) * (cimage->width + 2)); next = (int *)lmalloc(sizeof(int) * (cimage->width + 2)); curr += 1; next += 1; for (j=0; jwidth; j++) { curr[j] = 0; next[j] = 0; } /* * primary dither loop */ for (i=0; iheight; i++) { /* copy the row into the current line */ for (j=0; jwidth; j++) { color = memToVal(src, spl); src += spl; if (RGBP(cimage)) { if (grey == NULL) level = tone_scale_adjust(colorIntensity(cimage->rgb.red[color], cimage->rgb.green[color], cimage->rgb.blue[color]) >> 1); else level = grey[color]; } else { level = tone_scale_adjust(colorIntensity((TRUE_RED(color) << 8), (TRUE_GREEN(color) << 8), (TRUE_BLUE(color) << 8)) >> 1); } curr[j] += level; } /* dither the current line */ if (i & 0x01) RightToLeft(curr, next, cimage->width); else LeftToRight(curr, next, cimage->width); /* copy the dithered line to the destination image */ for (j=0; jwidth; j++) if (curr[j] < Threshold) dst[j / 8] |= 1 << (7 - (j & 7)); dst += dll; /* circulate the line buffers */ swap = curr; curr = next; next = swap; for (j=0; jwidth; j++) next[j] = 0; } /* * clean up */ if (grey) lfree((byte *)grey); lfree((byte *)(curr-1)); lfree((byte *)(next-1)); if (verbose) printf("done\n"); return(image); } /* * a _very_ simple tone scale adjustment routine. provides a piecewise * linear mapping according to the following: * * input: output: * 0 (MinGrey) 0 (MinGrey) * Threshold Threshold/2 * MaxGrey MaxGrey * * this should help things look a bit better on most displays. */ static unsigned int tone_scale_adjust(val) unsigned int val; { unsigned int rslt; if (val < Threshold) rslt = val / 2; else rslt = (((val - Threshold) * (MaxGrey-(Threshold/2))) / (MaxGrey-Threshold)) + (Threshold/2); return rslt; } /* * dither a line from left to right */ static void LeftToRight(curr, next, width) int *curr; int *next; int width; { int idx; int error; int output; for (idx=0; idx Threshold) ? MaxGrey : MinGrey; error = curr[idx] - output; curr[idx] = output; next[idx-1] += error * 3 / 16; next[idx] += error * 5 / 16; next[idx+1] += error * 1 / 16; curr[idx+1] += error * 7 / 16; } } /* * dither a line from right to left */ static void RightToLeft(curr, next, width) int *curr; int *next; int width; { int idx; int error; int output; for (idx=(width-1); idx>=0; idx--) { output = (curr[idx] > Threshold) ? MaxGrey : MinGrey; error = curr[idx] - output; curr[idx] = output; next[idx+1] += error * 3 / 16; next[idx] += error * 5 / 16; next[idx-1] += error * 1 / 16; curr[idx-1] += error * 7 / 16; } } st; /* destination data */ int *curr; /* current line buffer */ int xloadimage.4.1/fill.c 664 221 144 2772 5461577405 7657 /* fill.c: * * fill an image area with a particular pixel value * * jim frost 10.02.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" void fill(image, fx, fy, fw, fh, pixval) Image *image; unsigned int fx, fy, fw, fh; Pixel pixval; { unsigned int x, y; unsigned int linelen, start; byte *lineptr, *pixptr; byte startmask, mask; goodImage(image, "fill"); switch(image->type) { case IBITMAP: /* this could be made a lot faster */ linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); lineptr= image->data + (linelen * fy); start= (fx / 8) + (fx % 8 ? 1 : 0); startmask= 0x80 >> (fx % 8); for (y= fy; y < fy + fh; y++) { mask= startmask; pixptr= lineptr + start; for (x= fx; x < fw; x++) { if (pixval) *pixptr |= mask; else *pixptr &= ~mask; if (!(mask >>= 1)) { mask= 0x80; pixptr++; } } lineptr += linelen; } break; case IRGB: case ITRUE: linelen= image->width * image->pixlen; start= image->pixlen * fx; lineptr= image->data + (linelen * fy); for (y= fy; y < fy + fh; y++) { pixptr= lineptr + start; for (x= fx; x < fw; x++) { valToMem(pixval, pixptr, image->pixlen); pixptr += image->pixlen; } lineptr += linelen; } break; default: printf("fill: Unsupported image type (ignored)\n"); return; } } ixel cxloadimage.4.1/halftone.c 664 221 144 23003 5461577405 10537 /* dither.c: * * routine for dithering a color image to monochrome based on color * intensity. this is loosely based on an algorithm which barry shein * (bzs@std.com) used in his "xf" program. * * jim frost 07.10.89 * * Copyright 1989, 1990 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" /* RGB intensity tables. red is (val * 0.30), green is (val * 0.59), blue * is (val * .11), where val is intensity >> 8. these are used by the * colorIntensity() macro in images.h. */ unsigned short RedIntensity[256]= { 0, 76, 153, 230, 307, 384, 460, 537, 614, 691, 768, 844, 921, 998, 1075, 1152, 1228, 1305, 1382, 1459, 1536, 1612, 1689, 1766, 1843, 1920, 1996, 2073, 2150, 2227, 2304, 2380, 2457, 2534, 2611, 2688, 2764, 2841, 2918, 2995, 3072, 3148, 3225, 3302, 3379, 3456, 3532, 3609, 3686, 3763, 3840, 3916, 3993, 4070, 4147, 4224, 4300, 4377, 4454, 4531, 4608, 4684, 4761, 4838, 4915, 4992, 5068, 5145, 5222, 5299, 5376, 5452, 5529, 5606, 5683, 5760, 5836, 5913, 5990, 6067, 6144, 6220, 6297, 6374, 6451, 6528, 6604, 6681, 6758, 6835, 6912, 6988, 7065, 7142, 7219, 7296, 7372, 7449, 7526, 7603, 7680, 7756, 7833, 7910, 7987, 8064, 8140, 8217, 8294, 8371, 8448, 8524, 8601, 8678, 8755, 8832, 8908, 8985, 9062, 9139, 9216, 9292, 9369, 9446, 9523, 9600, 9676, 9753, 9830, 9907, 9984, 10060, 10137, 10214, 10291, 10368, 10444, 10521, 10598, 10675, 10752, 10828, 10905, 10982, 11059, 11136, 11212, 11289, 11366, 11443, 11520, 11596, 11673, 11750, 11827, 11904, 11980, 12057, 12134, 12211, 12288, 12364, 12441, 12518, 12595, 12672, 12748, 12825, 12902, 12979, 13056, 13132, 13209, 13286, 13363, 13440, 13516, 13593, 13670, 13747, 13824, 13900, 13977, 14054, 14131, 14208, 14284, 14361, 14438, 14515, 14592, 14668, 14745, 14822, 14899, 14976, 15052, 15129, 15206, 15283, 15360, 15436, 15513, 15590, 15667, 15744, 15820, 15897, 15974, 16051, 16128, 16204, 16281, 16358, 16435, 16512, 16588, 16665, 16742, 16819, 16896, 16972, 17049, 17126, 17203, 17280, 17356, 17433, 17510, 17587, 17664, 17740, 17817, 17894, 17971, 18048, 18124, 18201, 18278, 18355, 18432, 18508, 18585, 18662, 18739, 18816, 18892, 18969, 19046, 19123, 19200, 19276, 19353, 19430, 19507, 19584 }; unsigned short GreenIntensity[256]= { 0, 151, 302, 453, 604, 755, 906, 1057, 1208, 1359, 1510, 1661, 1812, 1963, 2114, 2265, 2416, 2567, 2718, 2869, 3020, 3171, 3322, 3473, 3624, 3776, 3927, 4078, 4229, 4380, 4531, 4682, 4833, 4984, 5135, 5286, 5437, 5588, 5739, 5890, 6041, 6192, 6343, 6494, 6645, 6796, 6947, 7098, 7249, 7400, 7552, 7703, 7854, 8005, 8156, 8307, 8458, 8609, 8760, 8911, 9062, 9213, 9364, 9515, 9666, 9817, 9968,10119,10270,10421,10572,10723, 10874,11025,11176,11328,11479,11630,11781,11932, 12083,12234,12385,12536,12687,12838,12989,13140, 13291,13442,13593,13744,13895,14046,14197,14348, 14499,14650,14801,14952,15104,15255,15406,15557, 15708,15859,16010,16161,16312,16463,16614,16765, 16916,17067,17218,17369,17520,17671,17822,17973, 18124,18275,18426,18577,18728,18880,19031,19182, 19333,19484,19635,19786,19937,20088,20239,20390, 20541,20692,20843,20994,21145,21296,21447,21598, 21749,21900,22051,22202,22353,22504,22656,22807, 22958,23109,23260,23411,23562,23713,23864,24015, 24166,24317,24468,24619,24770,24921,25072,25223, 25374,25525,25676,25827,25978,26129,26280,26432, 26583,26734,26885,27036,27187,27338,27489,27640, 27791,27942,28093,28244,28395,28546,28697,28848, 28999,29150,29301,29452,29603,29754,29905,30056, 30208,30359,30510,30661,30812,30963,31114,31265, 31416,31567,31718,31869,32020,32171,32322,32473, 32624,32775,32926,33077,33228,33379,33530,33681, 33832,33984,34135,34286,34437,34588,34739,34890, 35041,35192,35343,35494,35645,35796,35947,36098, 36249,36400,36551,36702,36853,37004,37155,37306, 37457,37608,37760,37911,38062,38213,38364,38515 }; unsigned short BlueIntensity[256]= { 0, 28, 56, 84, 112, 140, 168, 197, 225, 253, 281, 309, 337, 366, 394, 422, 450, 478, 506, 535, 563, 591, 619, 647, 675, 704, 732, 760, 788, 816, 844, 872, 901, 929, 957, 985, 1013, 1041, 1070, 1098, 1126, 1154, 1182, 1210, 1239, 1267, 1295, 1323, 1351, 1379, 1408, 1436, 1464, 1492, 1520, 1548, 1576, 1605, 1633, 1661, 1689, 1717, 1745, 1774, 1802, 1830, 1858, 1886, 1914, 1943, 1971, 1999, 2027, 2055, 2083, 2112, 2140, 2168, 2196, 2224, 2252, 2280, 2309, 2337, 2365, 2393, 2421, 2449, 2478, 2506, 2534, 2562, 2590, 2618, 2647, 2675, 2703, 2731, 2759, 2787, 2816, 2844, 2872, 2900, 2928, 2956, 2984, 3013, 3041, 3069, 3097, 3125, 3153, 3182, 3210, 3238, 3266, 3294, 3322, 3351, 3379, 3407, 3435, 3463, 3491, 3520, 3548, 3576, 3604, 3632, 3660, 3688, 3717, 3745, 3773, 3801, 3829, 3857, 3886, 3914, 3942, 3970, 3998, 4026, 4055, 4083, 4111, 4139, 4167, 4195, 4224, 4252, 4280, 4308, 4336, 4364, 4392, 4421, 4449, 4477, 4505, 4533, 4561, 4590, 4618, 4646, 4674, 4702, 4730, 4759, 4787, 4815, 4843, 4871, 4899, 4928, 4956, 4984, 5012, 5040, 5068, 5096, 5125, 5153, 5181, 5209, 5237, 5265, 5294, 5322, 5350, 5378, 5406, 5434, 5463, 5491, 5519, 5547, 5575, 5603, 5632, 5660, 5688, 5716, 5744, 5772, 5800, 5829, 5857, 5885, 5913, 5941, 5969, 5998, 6026, 6054, 6082, 6110, 6138, 6167, 6195, 6223, 6251, 6279, 6307, 6336, 6364, 6392, 6420, 6448, 6476, 6504, 6533, 6561, 6589, 6617, 6645, 6673, 6702, 6730, 6758, 6786, 6814, 6842, 6871, 6899, 6927, 6955, 6983, 7011, 7040, 7068, 7096, 7124, 7152, 7180 }; /* 4x4 arrays used for dithering, arranged by nybble */ #define GRAYS 17 /* ((4 * 4) + 1) patterns for a good dither */ #define GRAYSTEP ((unsigned long)(65536 / GRAYS)) static byte DitherBits[GRAYS][4] = { 0xf, 0xf, 0xf, 0xf, 0xe, 0xf, 0xf, 0xf, 0xe, 0xf, 0xb, 0xf, 0xa, 0xf, 0xb, 0xf, 0xa, 0xf, 0xa, 0xf, 0xa, 0xd, 0xa, 0xf, 0xa, 0xd, 0xa, 0x7, 0xa, 0x5, 0xa, 0x7, 0xa, 0x5, 0xa, 0x5, 0x8, 0x5, 0xa, 0x5, 0x8, 0x5, 0x2, 0x5, 0x0, 0x5, 0x2, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x4, 0x0, 0x5, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; /* simple dithering algorithm, really optimized for the 4x4 array */ Image *halftone(cimage, verbose) Image *cimage; unsigned int verbose; { Image *image; unsigned char *sp, *dp, *dp2; /* data pointers */ unsigned int dindex; /* index into dither array */ unsigned int spl; /* source pixel length in bytes */ unsigned int dll; /* destination line length in bytes */ Pixel color; /* pixel color */ unsigned int *index; /* index into dither array for a given pixel */ unsigned int a, x, y; /* random counters */ goodImage(cimage, "dither"); if (BITMAPP(cimage)) return(NULL); /* set up */ if (verbose) { printf(" Halftoning image..."); fflush(stdout); } image= newBitImage(cimage->width * 4, cimage->height * 4); if (cimage->title) { image->title= (char *)lmalloc(strlen(cimage->title) + 13); sprintf(image->title, "%s (halftoned)", cimage->title); } spl= cimage->pixlen; dll= (image->width / 8) + (image->width % 8 ? 1 : 0); /* if the number of possible pixels isn't very large, build an array * which we index by the pixel value to find the dither array index * by color brightness. we do this in advance so we don't have to do * it for each pixel. things will break if a pixel value is greater * than (1 << depth), which is bogus anyway. this calculation is done * on a per-pixel basis if the colormap is too big. */ if (RGBP(cimage) && (cimage->depth <= 16)) { index= (unsigned int *)lmalloc(sizeof(unsigned int) * cimage->rgb.used); for (x= 0; x < cimage->rgb.used; x++) { *(index + x)= ((unsigned long)colorIntensity(*(cimage->rgb.red + x), *(cimage->rgb.green + x), *(cimage->rgb.blue + x))) / GRAYSTEP; if (*(index + x) >= GRAYS) /* rounding errors can do this */ *(index + x)= GRAYS - 1; } } else index= NULL; /* dither each pixel */ sp= cimage->data; dp= image->data; for (y= 0; y < cimage->height; y++) { for (x= 0; x < cimage->width; x++) { dp2= dp + (x >> 1); color= memToVal(sp, spl); if (RGBP(cimage)) { if (index) dindex= *(index + color); else { dindex= ((unsigned long)colorIntensity(cimage->rgb.red[color], cimage->rgb.green[color], cimage->rgb.blue[color])) / GRAYSTEP; } } else { dindex= ((unsigned long)colorIntensity((TRUE_RED(color) << 8), (TRUE_GREEN(color) << 8), (TRUE_BLUE(color) << 8))) / GRAYSTEP; } if (dindex >= GRAYS) /* rounding errors can do this */ dindex= GRAYS - 1; /* loop for the four Y bits in the dither pattern, putting all * four X bits in at once. if you think this would be hard to * change to be an NxN dithering array, you're right, since we're * banking on the fact that we need only shift the mask based on * whether x is odd or not. an 8x8 array wouldn't even need that, * but blowing an image up by 64x is probably not a feature. */ if (x & 1) for (a= 0; a < 4; a++, dp2 += dll) *dp2 |= DitherBits[dindex][a]; else for (a= 0; a < 4; a++, dp2 += dll) *dp2 |= (DitherBits[dindex][a] << 4); sp += spl; } dp += (dll << 2); /* (dll * 4) but I like shifts */ } if (verbose) printf("done\n"); return(image); } Pixmap format image. note that this only supports depths * of 4, 8, 16, 24, or 32 bits as does Xlib. You gotta 6-bit image, * you gotta problem. 1-bit images are handled by XYBitmap. */ static Image *loadZPixmap(fullname, zf, header) char *fullname; ZFILE *zf; XWDHeader header; { Image *image; int dlinelen; /* length of scan line in data file */ int ilinelen; /* length of scan line in image file */ int depth; /* depth rounded up to 8-bit value */ xloadimage.4.1/merge.c 664 221 144 15017 5461577407 10046 /* merge.c: * * merge two images * * jim frost 09.27.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" /* if merging bitmaps they don't have to be converted to * 24-bit. this saves a lot of space. */ static Image *bitmapToBitmap(src, dest, atx, aty, clipw, cliph, verbose) Image *src, *dest; unsigned int atx, aty, clipw, cliph; unsigned int verbose; { unsigned int destlinelen, srclinelen; unsigned int deststart; unsigned int flip; unsigned int x, y; byte *destline, *srcline; byte deststartmask; byte destmask, srcmask; byte *destpixel, *srcpixel; destlinelen= (dest->width / 8) + (dest->width % 8 ? 1 : 0); srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0); destline= dest->data + (aty * destlinelen); srcline= src->data; deststart= atx / 8; deststartmask= 0x80 >> (atx % 8); flip= ((*dest->rgb.red == *(src->rgb.red + 1)) && (*dest->rgb.green == *(src->rgb.green + 1)) && (*dest->rgb.blue == *(src->rgb.blue + 1))); for (y= 0; y < cliph; y++) { destpixel= destline + deststart; srcpixel= srcline; destmask= deststartmask; srcmask= 0x80; for (x= 0; x < clipw; x++) { if (flip) if (*srcpixel & srcmask) *destpixel &= ~destmask; else *destpixel |= destmask; else if (*srcpixel & srcmask) *destpixel |= destmask; else *destpixel &= ~destmask; destmask >>= 1; srcmask >>= 1; if (destmask == 0) { destmask= 0x80; destpixel++; } if (srcmask == 0) { srcmask= 0x80; srcpixel++; } } destline += destlinelen; srcline += srclinelen; } if (verbose) printf("done\n"); return(dest); } static Image *anyToTrue(src, dest, atx, aty, clipw, cliph, verbose) Image *src, *dest; unsigned int atx, aty, clipw, cliph; unsigned int verbose; { Pixel fg, bg; unsigned int destlinelen, srclinelen; unsigned int deststart; unsigned int x, y; byte *destline, *srcline; byte *destpixel, *srcpixel; byte srcmask; Pixel pixval; if (!TRUEP(dest)) dest= expand(dest); switch (src->type) { case IBITMAP: fg= RGB_TO_TRUE(src->rgb.red[1], src->rgb.green[1], src->rgb.blue[1]); bg= RGB_TO_TRUE(src->rgb.red[0], src->rgb.green[0], src->rgb.blue[0]); destlinelen= dest->width * dest->pixlen; srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0); destline= dest->data + (aty * destlinelen); srcline= src->data; deststart= atx * dest->pixlen; for (y= 0; y < cliph; y++) { destpixel= destline + deststart; srcpixel= srcline; srcmask= 0x80; for (x= 0; x < clipw; x++) { valToMem((*srcpixel & srcmask ? fg : bg), destpixel, 3); destpixel += 3; srcmask >>= 1; if (srcmask == 0) { srcpixel++; srcmask= 0x80; } } destline += destlinelen; srcline += srclinelen; } break; case IRGB: destlinelen= dest->width * dest->pixlen; srclinelen= src->width * src->pixlen; deststart= atx * dest->pixlen; destline= dest->data + (aty * destlinelen); srcline= src->data; for (y= 0; y < cliph; y++) { destpixel= destline + deststart; srcpixel= srcline; for (x= 0; x < clipw; x++) { pixval= memToVal(srcpixel, src->pixlen); *(destpixel++)= src->rgb.red[pixval] >> 8; *(destpixel++)= src->rgb.green[pixval] >> 8; *(destpixel++)= src->rgb.blue[pixval] >> 8; srcpixel += src->pixlen; } destline += destlinelen; srcline += srclinelen; } break; case ITRUE: destlinelen= dest->width * dest->pixlen; srclinelen= src->width * src->pixlen; deststart= atx * dest->pixlen; destline= dest->data + (aty * destlinelen); srcline= src->data; for (y= 0; y < cliph; y++) { destpixel= destline + deststart; srcpixel= srcline; for (x= 0; x < clipw; x++) { *(destpixel++)= *(srcpixel++); *(destpixel++)= *(srcpixel++); *(destpixel++)= *(srcpixel++); } destline += destlinelen; srcline += srclinelen; } break; } if (verbose) printf("done\n"); return(dest); } /* put src image on dest image */ Image *merge(dest, src, atx, aty, verbose) Image *dest; Image *src; int atx, aty; unsigned int verbose; { int clipw, cliph; int clipped = 0; Image *newimage; goodImage(dest, "merge"); goodImage(src, "merge"); if (verbose) { printf(" Merging..."); fflush(stdout); } /* adjust clipping of src to fit within dest */ clipw= src->width; cliph= src->height; if ((atx + clipw < 0) || (aty + cliph < 0) || (atx >= (int)dest->width) || (aty >= (int)dest->height)) { /* not on dest, ignore */ if (verbose) printf("not on destination\n"); return(dest); } if (atx + clipw > dest->width) clipw = dest->width - atx; if (aty + cliph > dest->height) cliph = dest->height - aty; /* extra clipping required for negative offsets */ if ( atx < 0 || aty < 0 ) { int clipx, clipy; if ( atx < 0 ) { clipx = -atx; clipw += atx; atx = 0; } else clipx = 0; if ( aty < 0 ) { clipy = -aty; cliph += aty; aty = 0; } else clipy = 0; clipped = 1; src = clip(src, clipx, clipy, clipw, cliph, verbose); } if (BITMAPP(dest) && BITMAPP(src)) newimage= bitmapToBitmap(src, dest, (unsigned int)atx, (unsigned int)aty, clipw, cliph, verbose); else newimage= anyToTrue(src, dest, (unsigned int)atx, (unsigned int)aty, clipw, cliph, verbose); if (clipped) freeImage(src); return(newimage); } /* this creates an image of the specified size by tiling a base image */ Image *tile(image, x, y, width, height, verbose) Image *image; int x, y; unsigned int width, height, verbose; { Image *base, *tmp; if (verbose) { printf(" Tiling..."); fflush(stdout); } /* if the image is a bitmap merge onto a bitmap image (so we don't * need do dither on some displays). otherwise promote to truecolor * since that's what merge() will do anyway. */ if (BITMAPP(image)) base = newBitImage(width, height); else base = newTrueImage(width, height); while (x < base->width) { while(y < base->height) { tmp = merge(base, image, x, y, 0); if (tmp != base) { freeImage(base); base = tmp; } y += image->width; } x += image->width; } printf("done.\n"); return(base); } an image up by 64x is probably not a feature. */ if (x & 1) for (a= 0; a < 4; a++, dp2 += dll) *dp2 |= DitherBits[dindex][a]; else for (a= 0; a < 4; a++, dp2 += dll) *dp2 |= (DitherBits[dindex][a] << 4); sp += spl; } dp += (dll << 2); /* (dll * 4) but I like shifts */ } if (verbose) printf("done\n"); return(image); } Pixmap format image. note that this only supports depths * of 4, 8, 16, 24, or 32 bits as does Xlib. You gotta 6-bit imagexloadimage.4.1/reduce.c 664 221 144 41244 5461577410 10211 /* reduce.c: * * reduce an image's colormap usage to a set number of colors. this also * translates a true color image to a TLA-style image of `n' colors. * * this uses an algorithm by Paul Heckbert discussed in `Color Image * Quantization for Frame Buffer Display,' _Computer Graphics_ 16(3), * pp 297-307. this implementation is based on one discussed in * 'A Few Good Colors,' _Computer Language_, Aug. 1990, pp 32-41 by * Dave Pomerantz. * * this function cannot reduce to any number of colors larger than 32768. * * jim frost 04.18.91 * * Copyright 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" #define DIST(A, B) ((A) < (B) ? (B) - (A) : (A) - (B)) /* find the distance between two colors. we loose some accuracy here because * a triple squared short may not fit in a long. we use a table lookup * to help speed this up; it's an O(exp(n,2)) algorithm. */ unsigned int squareInit= 0; unsigned long squareTable[32768]; void initSquareTable() { unsigned long a; for (a= 0; a < 32768; a++) squareTable[a]= a * a; squareInit= 1; } unsigned long colorDistance(rgb, a, b) RGBMap *rgb; Pixel a, b; { return(squareTable[DIST(*(rgb->red + a), *(rgb->red + b)) >> 1] + squareTable[DIST(*(rgb->green + a), *(rgb->green + b)) >> 1] + squareTable[DIST(*(rgb->blue + a), *(rgb->blue + b)) >> 1]); } /* this converts a TLA-style pixel into a 15-bit true color pixel */ #define TLA_TO_15BIT(TABLE,PIXEL) \ ((((TABLE).red[PIXEL] & 0xf800) >> 1) | \ (((TABLE).green[PIXEL] & 0xf800) >> 6) | \ (((TABLE).blue[PIXEL] & 0xf800) >> 11)) /* this converts a 24-bit true color pixel into a 15-bit true color pixel */ #define TRUE_TO_15BIT(PIXEL) \ ((((PIXEL) & 0xf80000) >> 9) | \ (((PIXEL) & 0x00f800) >> 6) | \ (((PIXEL) & 0x0000f8) >> 3)) /* these macros extract color intensities from a 15-bit true color pixel */ #define RED_INTENSITY(P) (((P) & 0x7c00) >> 10) #define GREEN_INTENSITY(P) (((P) & 0x03e0) >> 5) #define BLUE_INTENSITY(P) ((P) & 0x001f) /* this structure defines a color area which is made up of an array of pixel * values and a count of the total number of image pixels represented by * the area. color areas are kept in a list sorted by the number of image * pixels they represent. */ struct color_area { unsigned short *pixels; /* array of pixel values in this area */ unsigned short num_pixels; /* size of above array */ int (*sort_func)(); /* predicate func to sort with before * splitting */ unsigned long pixel_count; /* # of image pixels we represent */ struct color_area *prev, *next; }; /* predicate functions for qsort */ static sortRGB(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (red1 == red2) if (green1 == green2) if (blue1 < blue2) return(-1); else return(1); else if (green1 < green2) return(-1); else return(1); else if (red1 < red2) return(-1); else return(1); } static sortRBG(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (red1 == red2) if (blue1 == blue2) if (green1 < green2) return(-1); else return(1); else if (blue1 < blue2) return(-1); else return(1); else if (red1 < red2) return(-1); else return(1); } static sortGRB(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (green1 == green2) if (red1 == red2) if (blue1 < blue2) return(-1); else return(1); else if (red1 < red2) return(-1); else return(1); else if (green1 < green2) return(-1); else return(1); } static sortGBR(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (green1 == green2) if (blue1 == blue2) if (red1 < red2) return(-1); else return(1); else if (blue1 < blue2) return(-1); else return(1); else if (green1 < green2) return(-1); else return(1); } static sortBRG(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (blue1 == blue2) if (red1 == red2) if (green1 < green2) return(-1); else return(1); else if (red1 < red2) return(-1); else return(1); else if (blue1 < blue2) return(-1); else return(1); } static sortBGR(p1, p2) unsigned short *p1, *p2; { unsigned int red1, green1, blue1, red2, green2, blue2; red1= RED_INTENSITY(*p1); green1= GREEN_INTENSITY(*p1); blue1= BLUE_INTENSITY(*p1); red2= RED_INTENSITY(*p2); green2= GREEN_INTENSITY(*p2); blue2= BLUE_INTENSITY(*p2); if (blue1 == blue2) if (green1 == green2) if (red1 < red2) return(-1); else return(1); else if (green1 < green2) return(-1); else return(1); else if (blue1 < blue2) return(-1); else return(1); } /* this does calculations on a color area following a split and inserts * the color area in the list of color areas. */ static insertColorArea(pixel_counts, rlargest, rsmallest, area) unsigned long *pixel_counts; struct color_area **rlargest, **rsmallest, *area; { int a; unsigned int red, green, blue; unsigned int min_red, min_green, min_blue; unsigned int max_red, max_green, max_blue= 0; struct color_area *largest, *smallest, *tmp_area; min_red= min_green= min_blue= 31; max_red= max_green= max_blue= 0; /* update pixel count for this area and find RGB intensity widths */ area->pixel_count= 0; for (a= 0; a < area->num_pixels; a++) { area->pixel_count += pixel_counts[area->pixels[a]]; red= RED_INTENSITY(area->pixels[a]); green= GREEN_INTENSITY(area->pixels[a]); blue= BLUE_INTENSITY(area->pixels[a]); if (red < min_red) min_red= red; if (red > max_red) max_red= red; if (green < min_green) min_green= green; if (green > max_green) max_green= green; if (blue < min_blue) min_blue= blue; if (blue > max_blue) max_blue= blue; } /* calculate widths and determine which predicate function to use based * on the result */ red= max_red - min_red; green= max_green - min_green; blue= max_blue - min_blue; if (red > green) if (green > blue) area->sort_func= sortRGB; else if (red > blue) area->sort_func= sortRBG; else area->sort_func= sortBRG; else if (green > blue) if (red > blue) area->sort_func= sortGRB; else area->sort_func= sortGBR; else area->sort_func= sortBGR; /* insert color area in color area list sorted by number of pixels that * the area represents */ largest= *rlargest; smallest= *rsmallest; if (!largest) { largest= smallest= area; area->prev= area->next= (struct color_area *)NULL; } /* if we only have one element, our pixel count is immaterial so we get * stuck on the end of the list. */ else if (area->num_pixels < 2) { smallest->next= area; area->prev= smallest; area->next= (struct color_area *)NULL; smallest= area; } /* insert node into list */ else { for (tmp_area= largest; tmp_area; tmp_area= tmp_area->next) if ((area->pixel_count > tmp_area->pixel_count) || (tmp_area->num_pixels < 2)) { area->prev= tmp_area->prev; area->next= tmp_area; tmp_area->prev= area; if (area->prev) area->prev->next= area; else largest= area; break; } if (!tmp_area) { area->prev= smallest; area->next= (struct color_area *)NULL; smallest->next= area; smallest= area; } } *rlargest= largest; *rsmallest= smallest; } Image *reduce(image, n, verbose) Image *image; unsigned int n, verbose; { unsigned long pixel_counts[32768]; /* pixel occurrance histogram */ unsigned short pixel_array[32768]; unsigned long count, midpoint; int x, y, num_pixels, allocated, depth, ncolors; byte *pixel, *dpixel; struct color_area *areas, *largest_area, *smallest_area; struct color_area *new_area, *old_area; Image *new_image; Pixel pixval; char buf[BUFSIZ]; goodImage(image, "reduce"); if (n > 32768) /* max # of colors we can handle */ n= 32768; /* create a histogram of particular pixel occurrances */ bzero(pixel_counts, 32768 * sizeof(unsigned long)); switch (image->type) { case IBITMAP: return(image); case IRGB: if (image->rgb.used <= n) return(image); if (verbose) { printf(" Reducing RGB image color usage to %d colors...", n); fflush(stdout); } pixel= image->data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixel_counts[TLA_TO_15BIT(image->rgb, memToVal(pixel, image->pixlen))]++; pixel += image->pixlen; } break; case ITRUE: if (image->pixlen != 3) { fprintf(stderr, "reduce: true color image has strange pixel length?\n"); return(image); } if (verbose) { printf(" Converting true color image to RGB image with %d colors...", n); fflush(stdout); } pixel= image->data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixel_counts[TRUE_TO_15BIT(memToVal(pixel, 3))]++; pixel += 3; } break; default: return(image); /* not something we can reduce, thank you anyway */ } /* create array of 15-bit pixel values that actually occur in the image */ num_pixels= 0; for (x= 0; x < 32768; x++) if (pixel_counts[x] > 0) pixel_array[num_pixels++]= (short)x; if (verbose) { printf("image uses %d colors...", num_pixels); fflush(stdout); } /* create color area array and initialize first element */ areas= (struct color_area *)lmalloc(n * sizeof(struct color_area)); areas[0].pixels= pixel_array; areas[0].num_pixels= num_pixels; largest_area= smallest_area= (struct color_area *)NULL; insertColorArea(pixel_counts, &largest_area, &smallest_area, areas); allocated= 1; /* keep splitting the color area until we have as many color areas as we * need */ while (allocated < n) { /* if our largest area can't be broken down, we can't even get the * number of colors they asked us to */ if (largest_area->num_pixels < 2) break; /* find midpoint of largest area and do split */ qsort(largest_area->pixels, largest_area->num_pixels, sizeof(short), largest_area->sort_func); count= 0; midpoint= largest_area->pixel_count / 2; for (x= 0; x < largest_area->num_pixels; x++) { count += pixel_counts[largest_area->pixels[x]]; if (count > midpoint) break; } if (x == 0) /* degenerate case; divide in half */ x= 1; new_area= areas + allocated; new_area->pixels= largest_area->pixels + x; new_area->num_pixels= largest_area->num_pixels - x; largest_area->num_pixels= x; old_area= largest_area; largest_area= largest_area->next; if (largest_area) largest_area->prev= (struct color_area *)NULL; else smallest_area= (struct color_area *)NULL; /* recalculate for each area of split and insert in the area list */ insertColorArea(pixel_counts, &largest_area, &smallest_area, old_area); insertColorArea(pixel_counts, &largest_area, &smallest_area, new_area); allocated++; } /* get destination image */ depth= colorsToDepth(n); new_image= newRGBImage(image->width, image->height, depth); sprintf(buf, "%s (%d colors)", image->title, n); new_image->title= dupString(buf); /* calculate RGB table from each color area. this should really calculate * a new color by weighting the intensities by the number of pixels, but * it's a pain to scale so this just averages all the intensities. it * works pretty well regardless. */ for (x= 0; x < allocated; x++) { long red, green, blue, count, pixel; red= green= blue= 0; count= areas[x].pixel_count; for (y= 0; y < areas[x].num_pixels; y++) { pixel= areas[x].pixels[y]; red += RED_INTENSITY(pixel); green += GREEN_INTENSITY(pixel); blue += BLUE_INTENSITY(pixel); pixel_counts[pixel]= x; } red /= areas[x].num_pixels; green /= areas[x].num_pixels; blue /= areas[x].num_pixels; new_image->rgb.red[x]= (unsigned short)(red << 11); new_image->rgb.green[x]= (unsigned short)(green << 11); new_image->rgb.blue[x]= (unsigned short)(blue << 11); }; new_image->rgb.used= allocated; new_image->rgb.compressed= 1; lfree((byte *)areas); /* copy old image into new image */ pixel= image->data; dpixel= new_image->data; switch(image->type) { case IRGB: for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { /* we use pixval as a temporary because some compilers have * trouble with the complexity of the inlined statements otherwise. */ pixval = pixel_counts[TLA_TO_15BIT(image->rgb, memToVal(pixel, image->pixlen))]; valToMem(pixval, dpixel, new_image->pixlen); pixel += image->pixlen; dpixel += new_image->pixlen; } break; case ITRUE: for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixval = pixel_counts[TRUE_TO_15BIT(memToVal(pixel, 3))]; valToMem(pixval, dpixel, new_image->pixlen); pixel += 3; dpixel += new_image->pixlen; } break; } if (verbose) printf("done\n"); return(new_image); } /* expand an image into a true color image */ Image *expand(image) Image *image; { Image *new_image; int x, y; Pixel spixval; byte *spixel, *dpixel, *line; unsigned int linelen; byte mask; goodImage(image, "expand"); if TRUEP(image) return(image); new_image= newTrueImage(image->width, image->height); new_image->title= dupString(image->title); switch (image->type) { case IBITMAP: line= image->data; dpixel= new_image->data; linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); for (y= 0; y < image->height; y++) { spixel= line; mask= 0x80; for (x= 0; x < image->width; x++) { valToMem((mask & *spixel ? 0L : 0xffffff), dpixel, 3); mask >>= 1; if (!mask) { mask= 0x80; spixel++; } dpixel += new_image->pixlen; } line += linelen; } break; case IRGB: spixel= image->data; dpixel= new_image->data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { spixval= memToVal(spixel, image->pixlen); valToMem(RGB_TO_TRUE(image->rgb.red[spixval], image->rgb.green[spixval], image->rgb.blue[spixval]), dpixel, new_image->pixlen); spixel += image->pixlen; dpixel += new_image->pixlen; } break; } return(new_image); } /* this function "flattens" a 1-bit RGB image into a bitmap image if possible. */ Image *flatten(image) Image *image; { int x, y, linelen; Image *new; byte *sp, *dp, *last_dp, mask; /* if it's not a one-bit image then forget it */ if (!RGBP(image) || (image->rgb.used > 2)) return(image); new = newBitImage(image->width, image->height); new->title = dupString(image->title); /* copy colormap */ if (image->rgb.used > 0) { new->rgb.red[0] = image->rgb.red[0]; new->rgb.green[0] = image->rgb.green[0]; new->rgb.blue[0] = image->rgb.blue[0]; } if (image->rgb.used > 1) { new->rgb.red[1] = image->rgb.red[1]; new->rgb.green[1] = image->rgb.green[1]; new->rgb.blue[1] = image->rgb.blue[1]; } /* convert image data */ sp = image->data; last_dp = new->data; linelen = (new->width / 8) + (new->width % 8 ? 1 : 0); for (y = 0; y < image->height; y++) { dp = last_dp; mask = 0x80; for (x = 0; x < image->width; x++) { if (memToVal(sp, image->pixlen) != 0) *dp |= mask; sp += image->pixlen; mask >>= 1; if (mask == 0) { mask = 0x80; dp += 1; } } last_dp += linelen; } return(new); } long pixel_counts[32768]; /* pixel occurrance histogram */ unsigned short pixel_array[32768]; unsigned long count, midpoint; int x, y, num_pixels, allocated, depth, ncolors; byte *pixel, *dpixel; struct color_area *areas, *largest_area, *smallest_area; struct color_area *new_area, *old_area; Image *new_image; Pixel pixval; charxloadimage.4.1/rotate.c 664 221 144 7734 5461577411 10227 /* rotate.c * * rotate an image * * Contributed by Tom Tatlow (tatlow@dash.enet.dec.com) */ #include "copyright.h" #include "image.h" /* rotate_bitmap() * converts an old bitmap bit position into a new one */ void rotate_bitmap(num, pos, width, height, new_num, new_pos) int num; /* Source byte number */ int pos; /* Source bit position */ int width; /* Width of source bitmap */ int height; /* Height of source bitmap */ int *new_num; /* Destination byte number */ int *new_pos; /* Destination bit position */ { int slen; /* Length of source line */ int dlen; /* Length of destination line */ int sx, sy; int dx, dy; slen = (width / 8) + (width % 8 ? 1 : 0); dlen = (height / 8) + (height % 8 ? 1 : 0); sy = num / slen; sx = ((num - (sy * slen)) * 8) + pos; dx = (height - sy) - 1; dy = sx; *new_num = (dx / 8) + (dy * dlen); *new_pos = dx % 8; } /* rotate() * rotates an image */ Image *rotate(simage, degrees, verbose) Image *simage; /* Image to rotate */ unsigned int degrees; /* Number of degrees to rotate */ unsigned int verbose; { char buf[BUFSIZ]; /* New title */ Image *image1; /* Source image */ Image *image2; /* Destination image */ byte *sp; /* Pointer to source data */ byte *dp; /* Pointer to destination data */ int slinelen; /* Length of source line */ int dlinelen; /* Length of destination line */ int bit[8]; /* Array of hex values */ int x, y; int i, b; int newx, newy; int newi, newb; byte **yptr; bit[0] = 128; bit[1] = 64; bit[2] = 32; bit[3] = 16; bit[4] = 8; bit[5] = 4; bit[6] = 2; bit[7] = 1; goodImage(simage, "rotate"); if (verbose) { printf(" Rotating image by %d degrees...", degrees); fflush(stdout); } sprintf(buf, "%s (rotated by %d degrees)", simage->title, degrees); image1 = simage; do { degrees -= 90; switch (image1->type) { case IBITMAP: image2= newBitImage(image1->height, image1->width); for (x= 0; x < image1->rgb.used; x++) { *(image2->rgb.red + x)= *(image1->rgb.red + x); *(image2->rgb.green + x)= *(image1->rgb.green + x); *(image2->rgb.blue + x)= *(image1->rgb.blue + x); } slinelen= (image1->width / 8) + (image1->width % 8 ? 1 : 0); sp = image1->data; dp = image2->data; for (i = 0; i < (slinelen * image1->height); i++) for (b = 0; b < 8; b++) if (sp[i] & bit[b]) { rotate_bitmap(i, b, image1->width, image1->height, &newi, &newb); dp[newi] |= bit[newb]; } break; case IRGB: image2= newRGBImage(image1->height, image1->width, image1->depth); for (x= 0; x < image1->rgb.used; x++) { *(image2->rgb.red + x)= *(image1->rgb.red + x); *(image2->rgb.green + x)= *(image1->rgb.green + x); *(image2->rgb.blue + x)= *(image1->rgb.blue + x); } image2->rgb.used= image1->rgb.used; /* FALLTHRU */ case ITRUE: if (TRUEP(image1)) image2= newTrueImage(image1->height, image1->width); /* build array of y axis ptrs into destination image */ yptr= (byte **)lmalloc(image1->width * sizeof(char *)); dlinelen= image1->height * image1->pixlen; for (y= 0; y < image1->width; y++) yptr[y]= image2->data + (y * dlinelen); /* rotate */ sp= image1->data; for (y = 0; y < image1->height; y++) for (x = 0; x < image1->width; x++) { valToMem(memToVal(sp, image1->pixlen), yptr[x] + ((image1->height - y - 1) * image1->pixlen), image1->pixlen); sp += image1->pixlen; } lfree((byte *)yptr); break; default: printf("rotate: Unsupported image type\n"); exit(1); } if (image1 != simage) freeImage(image1); image1 = image2; } while (degrees); image1->title= dupString(buf); if (verbose) printf("done\n"); return(image1); } temporary because some compilers havxloadimage.4.1/smooth.c 664 221 144 4416 5461577411 10234 /* smooth.c: * * this performs a smoothing convolution using a 3x3 area. * * jim frost 09.20.90 * * Copyright 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "image.h" static Image *doSmooth(image) Image *image; { Image *old, *new; int x, y, x1, y1, linelen; int xindex[3]; byte *yindex[3]; byte *destptr; Pixel pixval; unsigned long avgred, avggreen, avgblue; /* build true color image from old image and allocate new image */ old= expand(image); new= newTrueImage(image->width, image->height); if (image->title) { new->title= (char *)lmalloc(strlen(image->title) + 12); sprintf(new->title, "%s (smoothed)", image->title); } /* run through image and take a guess as to what the color should * actually be. */ destptr= new->data; linelen= old->pixlen * old->width; for (y= 0; y < old->height; y++) { yindex[1]= old->data + (y * linelen); yindex[0]= yindex[1] - (y > 0 ? linelen : 0); yindex[2]= yindex[1] + (y < old->height - 1 ? linelen : 0); for (x= 0; x < old->width; x++) { avgred= avggreen= avgblue= 0; xindex[1]= x * old->pixlen; xindex[0]= xindex[1] - (x > 0 ? old->pixlen : 0); xindex[2]= xindex[1] + (x < old->width - 1 ? old->pixlen : 0); for (y1= 0; y1 < 3; y1++) { for (x1= 0; x1 < 3; x1++) { pixval= memToVal(yindex[y1] + xindex[x1], old->pixlen); avgred += TRUE_RED(pixval); avggreen += TRUE_GREEN(pixval); avgblue += TRUE_BLUE(pixval); } } /* average the pixel values */ avgred= ((avgred + 8) / 9); avggreen= ((avggreen + 8) / 9); avgblue= ((avgblue + 8) / 9); pixval= (avgred << 16) | (avggreen << 8) | avgblue; valToMem(pixval, destptr, new->pixlen); destptr += new->pixlen; } } if (old != image) freeImage(old); return(new); } Image *smooth(image, iterations, verbose) Image *image; unsigned int verbose; { int a; Image *old, *new; if (verbose) { printf(" Smoothing..."); fflush(stdout); } old= image; for (a= 0; a < iterations; a++) { new= doSmooth(old); if (image != old) freeImage(old); old= new; } if (verbose) printf("done\n"); return(old); } *(image1->rgb.green + x); *(image2->rgb.blue + x)= *(image1->rgb.blue + x); } image2->rgb.used= image1->rgb.used; /* FALLTHRU */ case ITRUE: if (TRUEP(image1)) image2= newTrueImage(image1->height, image1->width)xloadimage.4.1/undither.c 664 221 144 4120 5461577412 10536 /* undither.c: * * this converts a bitmap image into a greyscale image. * * Eckhard R"uggeberg (erueg@cfgauss.uni-math.gwdg.de). */ #include "image.h" Image *undither(oimage, verbose) Image *oimage; unsigned int verbose; { Image *nimage; /* new image to build */ byte *optr, *nptr; /* Ptr into old/new data */ int i, j, k; /* Loop counters */ int hi, lo; /* 2 new Pixels constructed */ register int scanned; /* byte scanned in old data */ int newX, newY; /* new sizes */ int bitskip, byteskip; /* skips for ptr in old data */ int scantimes; /* how often to scan a byte */ int oddness; /* If newX is odd */ if (!BITMAPP(oimage)) return(oimage); if (verbose) { printf ( " Undithering image into grayscale..." ); fflush(stdout); } newX = (oimage->width / 4); oddness = newX & 1; newY = oimage->height / 4; nimage = newRGBImage ( newX, newY, 8 ); if (oimage->title) { nimage->title = (char *) lmalloc ( strlen (oimage->title) + 13 ); sprintf ( nimage->title, "%s (grayscaled)", oimage->title ); } nimage->rgb.used = 17; for ( i = 0; i < 17; i++ ) *(nimage->rgb.red + i) = *(nimage->rgb.green + i) = *(nimage->rgb.blue + i) = 65535.0 * (16 - i) / 16.0; bitskip = (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); byteskip = (bitskip << 2); scantimes = (newX >> 1) + oddness; optr = oimage->data; nptr = nimage->data; for ( i = 0; i < newY; i++ ) { /* for each new row */ for ( j = 0; j < scantimes; j++ ) { /* for each new colunm */ lo = hi = 0; for ( k = 0; k < 4; k++ ) { /* for each of the 4 */ scanned = *(optr + j + k*bitskip); /* old rows */ if (scanned & 0x80) hi++; if (scanned & 0x40) hi++; if (scanned & 0x20) hi++; if (scanned & 0x10) hi++; if (scanned & 0x08) lo++; if (scanned & 0x04) lo++; if (scanned & 0x02) lo++; if (scanned & 0x01) lo++; } *nptr++ = hi; /* store new data */ *nptr++ = lo; } if (oddness) nptr--; /* correct at end of row*/ optr += byteskip; } if (verbose) printf("done\n"); return(nimage); } ex[0]= xindex[1] - (x > 0 ? old->pixlen : 0); xindex[2]= xindex[1] + (x < old->width - 1 ? old->pixlen : 0); for (y1= 0; y1 < 3; y1++) { for (x1= 0; x1 < 3; x1++) { pixval= memToVal(yindex[y1] + xindex[x1], old->pixlen); avgred += TRUE_RED(pixval); avggreen += TRUE_GREEN(pixval); avgblue += TRUE_BLUE(pixval); } } /* average the pixel values */ avgred= ((avgred + 8) / 9); xloadimage.4.1/zoom.c 664 221 144 10615 5461577414 7730 /* zoom.c: * * zoom an image * * jim frost 10.11.89 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "copyright.h" #include "image.h" static unsigned int *buildIndex(width, zoom, rwidth) unsigned int width; unsigned int zoom; unsigned int *rwidth; { float fzoom; unsigned int *index; unsigned int a; if (!zoom) { fzoom= 100.0; *rwidth= width; } else { fzoom= (float)zoom / 100.0; *rwidth= fzoom * width; } index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth); for (a= 0; a < *rwidth; a++) if (zoom) *(index + a)= (float)a / fzoom; else *(index + a)= a; return(index); } Image *zoom(oimage, xzoom, yzoom, verbose) Image *oimage; unsigned int xzoom, yzoom; unsigned int verbose; { char buf[BUFSIZ]; Image *image; unsigned int *xindex, *yindex; unsigned int xwidth, ywidth; unsigned int x, y, xsrc, ysrc; unsigned int pixlen; unsigned int srclinelen; unsigned int destlinelen; byte *srcline, *srcptr; byte *destline, *destptr; byte srcmask, destmask, bit; Pixel value; goodImage(oimage, "zoom"); if (!xzoom && !yzoom) /* stupid user */ return(NULL); if (!xzoom) { if (verbose) printf(" Zooming image Y axis by %d%%...", yzoom); sprintf(buf, "%s (Y zoom %d%%)", oimage->title, yzoom); } else if (!yzoom) { if (verbose) printf(" Zooming image X axis by %d%%...", xzoom); sprintf(buf, "%s (X zoom %d%%)", oimage->title, xzoom); } else if (xzoom == yzoom) { if (verbose) printf(" Zooming image by %d%%...", xzoom); sprintf(buf, "%s (%d%% zoom)", oimage->title, xzoom); } else { if (verbose) printf(" Zooming image X axis by %d%% and Y axis by %d%%...", xzoom, yzoom); sprintf(buf, "%s (X zoom %d%% Y zoom %d%%)", oimage->title, xzoom, yzoom); } if (verbose) fflush(stdout); xindex= buildIndex(oimage->width, xzoom, &xwidth); yindex= buildIndex(oimage->height, yzoom, &ywidth); switch (oimage->type) { case IBITMAP: image= newBitImage(xwidth, ywidth); for (x= 0; x < oimage->rgb.used; x++) { *(image->rgb.red + x)= *(oimage->rgb.red + x); *(image->rgb.green + x)= *(oimage->rgb.green + x); *(image->rgb.blue + x)= *(oimage->rgb.blue + x); } image->rgb.used= oimage->rgb.used; destline= image->data; destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0); srcline= oimage->data; srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) { while (ysrc != *(yindex + y)) { ysrc++; srcline += srclinelen; } srcptr= srcline; destptr= destline; srcmask= 0x80; destmask= 0x80; bit= srcmask & *srcptr; for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) { if (xsrc != *(xindex + x)) { do { xsrc++; if (!(srcmask >>= 1)) { srcmask= 0x80; srcptr++; } } while (xsrc != *(xindex + x)); bit= srcmask & *srcptr; } if (bit) *destptr |= destmask; if (!(destmask >>= 1)) { destmask= 0x80; destptr++; } } destline += destlinelen; } break; case IRGB: image= newRGBImage(xwidth, ywidth, oimage->depth); for (x= 0; x < oimage->rgb.used; x++) { *(image->rgb.red + x)= *(oimage->rgb.red + x); *(image->rgb.green + x)= *(oimage->rgb.green + x); *(image->rgb.blue + x)= *(oimage->rgb.blue + x); } image->rgb.used= oimage->rgb.used; /* FALLTHRU */ case ITRUE: if (!RGBP(oimage)) image= newTrueImage(xwidth, ywidth); pixlen= oimage->pixlen; destptr= image->data; srcline= oimage->data; srclinelen= oimage->width * pixlen; for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) { while (ysrc != *(yindex + y)) { ysrc++; srcline += srclinelen; } srcptr= srcline; value= memToVal(srcptr, pixlen); for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) { if (xsrc != *(xindex + x)) { do { xsrc++; srcptr += image->pixlen; } while (xsrc != *(xindex + x)); value= memToVal(srcptr, pixlen); } valToMem(value, destptr, pixlen); destptr += pixlen; } } break; } image->title= dupString(buf); lfree((byte *)xindex); lfree((byte *)yindex); if (verbose) printf("done\n"); return(image); } l ? 0L : 0xffffff), dpixel, 3); mask >>= 1; if (!mask) { mask= 0x80; spixel++; } dpixel += new_image->pixxloadimage.4.1/config.c 664 221 144 24067 5463772532 10217 /* config.c: * * functions that deal with the particular configuration. * * jim frost 10.03.89 * * Copyright 1989, 1990, 1991, 1993 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include /* must here for debugging version under AIX */ #include "xloadimage.h" #include #include #ifndef VMS #include #endif #include #ifndef IS_BSD #include #endif /* SUPPRESS 530 */ /* SUPPRESS 560 */ extern int errno; struct filter *Filters = (struct filter *)NULL; static unsigned int NumPaths= 0; static unsigned int NumExts= 0; static char *Paths[BUFSIZ]; static char *Exts[BUFSIZ]; static char *PathToken= "path"; static char *ExtToken= "extension"; static char *FilterToken= "filter"; static void addFilter(extension, filter) char *extension, *filter; { struct filter *f, *t; f= (struct filter *)lmalloc(sizeof(struct filter)); f->extension= dupString(extension); f->filter= dupString(filter); f->next= NULL; if (Filters) { for (t= Filters; t->next; t= t->next) /* EMPTY */ ; t->next= f; } else Filters= f; } enum parse_state { parse_void, parse_state_token, parse_path, parse_extension, parse_filter_name, parse_filter_extension }; /* this function eats up whitespace, incrementing the line number at * each newline */ static void skip_whitespace(f, linenum) FILE *f; unsigned int *linenum; { int c; for (;;) { c = fgetc(f); switch (c) { case EOF: return; case '\n': (*linenum)++; /* FALLTHRU */ case '\r': case ' ': case '\t': continue; default: ungetc(c, f); return; } } } static void readPathsAndExts(name) char *name; { FILE *f; char buf[BUFSIZ]; char filter_name[BUFSIZ]; enum parse_state state; unsigned int linenum; unsigned int a; int c; if (! (f= fopen(name, "r"))) return; state = parse_void; linenum= 0; /* this is the token scanner. i suppose i could have used lex. */ a = 0; for (;;) { c = fgetc(f); if (a >= BUFSIZ) { fprintf(stderr, "%s: %d: Buffer overflow (token too long, sorry).\n", name, linenum); fclose(f); return; } switch (c) { case EOF: return; case '\n': /* increment line count */ linenum++; /* FALLTHRU */ case '\r': /* treated as generic white space */ case ' ': case '\t': buf[a] = '\0'; a = 0; /* skip forward until next character */ skip_whitespace(f, &linenum); c = fgetc(f); if (c == '=') { state = parse_state_token; skip_whitespace(f, &linenum); } else if (c != EOF) ungetc(c, f); break; case '=': buf[a] = '\0'; a = 0; state = parse_state_token; skip_whitespace(f, &linenum); break; case '#': /* comment */ for (;;) { c = fgetc(f); switch (c) { /* eat everything to newline or EOF */ case '\n': linenum++; case EOF: break; default: continue; } break; } /* terminate token */ buf[a] = '\0'; a = 0; break; case '"': /* search for end quote */ while ((c = fgetc(f)) != EOF) { if (a >= BUFSIZ) { fprintf(stderr, "%s: %d: Buffer overflow while reading string literal.\n", name, linenum); fclose(f); return; } switch (c) { case '"': goto done_quote; case '\r': fprintf(stderr, "%s: %d: Unquoted return character inside string literal.\n", name, linenum); fclose(f); return; case '\n': fprintf(stderr, "%s: %d: Unquoted newline inside string literal.\n", name, linenum); fclose(f); return; case '\\': c = fgetc(f); if (c == EOF) goto done_quote; if (c == '\n') linenum++; /* FALLTHRU */ default: buf[a++] = c; continue; } } done_quote: continue; case '\\': /* literal quote */ c = fgetc(f); if (c == EOF) continue; if (c == '\n') linenum++; /* FALLTHRU */ default: buf[a++] = c; continue; } /* this disallows nil-string tokens. thus "" is always ignored. */ if (buf[0] == '\0') continue; /* this handles a token depending on the parser state */ switch (state) { case parse_void: fprintf(stderr, "%s: %d: Syntax error in defaults file\n", name, linenum); fclose(f); return; case parse_state_token: if (!strncmp(buf, PathToken, strlen(PathToken))) state= parse_path; else if (!strncmp(buf, ExtToken, strlen(ExtToken))) state= parse_extension; else if (!strncmp(buf, FilterToken, strlen(FilterToken))) state= parse_filter_name; else { fprintf(stderr, "%s: %d: Unknown section specifier '%s'.\n", name, linenum, buf); return; } break; case parse_path: if (NumPaths < BUFSIZ - 1) Paths[NumPaths++]= expandPath(buf); else { fprintf(stderr, "%s: %d: Path table overflow\n", name, linenum); fclose(f); return; } break; case parse_extension: if (NumExts < BUFSIZ - 1) Exts[NumExts++]= dupString(buf); else { fprintf(stderr, "%s: %d: Extension table overflow\n", name, linenum); fclose(f); return; } break; case parse_filter_name: /* name of filter program */ strcpy(filter_name, buf); state= parse_filter_extension; break; case parse_filter_extension: addFilter(buf, filter_name); break; } } } void loadPathsAndExts() { static int havepaths= 0; #ifndef VMS struct passwd *pw; #endif char buf[BUFSIZ]; if (havepaths) return; havepaths= 1; #ifdef VMS sprintf(buf, "/sys$login:xloadimage.rc"); #else /* !VMS */ addFilter(".Z", "uncompress -c"); /* std UNIX uncompress */ addFilter(".gz", "gzip -cd"); /* same, new extension */ if (! (pw= (struct passwd *)getpwuid(getuid()))) { printf("Can't find your password file entry?!?\n"); return; } sprintf(buf, "%s/.xloadimagerc", pw->pw_dir); #endif /* !VMS */ if (! access(buf, R_OK)) { readPathsAndExts(buf); return; /* don't read system file if user has one */ } #ifdef SYSPATHFILE readPathsAndExts(SYSPATHFILE); #endif } static int fileIsOk(fullname, sbuf) char *fullname; struct stat *sbuf; { if ((sbuf->st_mode & S_IFMT) == S_IFDIR) /* is a directory */ return(0); return(access(fullname, R_OK)); /* we can read it */ } /* find an image with paths and extensions from defaults files. returns * -1 if access denied or not found, 0 if ok. */ int findImage(name, fullname) char *name, *fullname; { unsigned int p, e; struct stat sbuf; strcpy(fullname, name); if (!strcmp(name, "stdin")) /* stdin is special name */ return(0); /* look for name and name with compress extension */ if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #ifndef NO_COMPRESS strcat(fullname, ".Z"); if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #endif for (p= 0; p < NumPaths; p++) { #ifdef VMS sprintf(fullname, "%s%s", Paths[p], name); #else sprintf(fullname, "%s/%s", Paths[p], name); #endif if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #ifndef NO_COMPRESS strcat(fullname, ".Z"); if (! stat(fullname, &sbuf)) #endif return(fileIsOk(fullname, &sbuf)); for (e= 0; e < NumExts; e++) { #ifdef VMS sprintf(fullname, "%s%s%s", Paths[p], name, Exts[e]); #else sprintf(fullname, "%s/%s%s", Paths[p], name, Exts[e]); #endif if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #ifndef NO_COMPRESS strcat(fullname, ".Z"); if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #endif } } for (e= 0; e < NumExts; e++) { sprintf(fullname, "%s%s", name, Exts[e]); if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #ifndef NO_COMPRESS strcat(fullname, ".Z"); if (! stat(fullname, &sbuf)) return(fileIsOk(fullname, &sbuf)); #endif } errno= ENOENT; /* file not found */ return(-1); } /* list images along our path */ void listImages() { unsigned int a; char buf[BUFSIZ]; if (!NumPaths) { printf("No image path\n"); return; } for (a= 0; a < NumPaths; a++) { printf("%s:\n", Paths[a]); fflush(stdout); #ifdef VMS sprintf(buf, "directory %s", Paths[a]); #else sprintf(buf, "ls %s", Paths[a]); #endif if (system(buf) < 0) { #ifdef VMS perror("directory"); #else perror("ls"); #endif return; } } return; } void showConfiguration() { int a; struct filter *f; if (NumPaths) { printf("Image path:"); for (a= 0; a < NumPaths; a++) printf(" %s", Paths[a]); printf("\n"); } else printf("No image path\n"); if (NumExts) { printf("Image extensions:"); for (a= 0; a < NumExts; a++) printf(" %s", Exts[a]); printf("\n"); } else printf("No image extensions\n"); if (Filters) { printf("Filters:\n"); for (f= Filters; f; f= f->next) printf(" \"%s\" -> \"%s\"\n", f->extension, f->filter); printf("\n"); } else printf("No filters\n"); } char *expandPath(p) char *p; { char buf1[BUFSIZ], buf2[BUFSIZ]; int b1, b2, var; char *ptr; char *getenv(); buf1[0] = '\0'; buf2[0] = '\0'; b1 = 0; b2 = 0; var = 0; while(*p) { if(isspace(*p)) break; #ifndef VMS if (*p == '$') var++; #endif else if(*p == '~') { buf1[b1] = '\0'; strcat(buf1, getenv("HOME")); b1 = strlen(buf1); var = 0; } else if(*p == '/' || *p == '}') { if(var) { buf1[b1] = '\0'; buf2[b2] = '\0'; strcat(buf1, getenv(buf2)); b1 = strlen(buf1); buf2[0] = '\0'; b2 = 0; var = 0; } if(*p == '/') { buf1[b1] = *p; b1++; } } else if(var) { if(*p != '{') { buf2[b2] = *p; b2++; } } else { buf1[b1] = *p; b1++; } p++; } buf1[b1] = '\0'; if((b2 = strlen(buf1)) > 0) { ptr = (char *)lmalloc((unsigned) b2+1); strcpy(ptr, buf1); return(ptr); } else return(NULL); } /* this is the token scanner. i suppose i could have used lex. */ a = 0; for (;;) { c = fgetc(f); if (a >= BUFSIZ) { fprintf(stderr, "%s: %d: Buffer overflow (token too long, sorry).\n", name, linenum); fclose(f); return; } switch (c) { case EOF: return; case '\n': /* increment line count */ linenum++; /* FALLTHRU */ case '\r': /* treated as generic white space */ case ' ': xloadimage.4.1/misc.c 664 221 144 14225 5461577407 7702 /* misc.c: * * miscellaneous funcs * * jim frost 10.05.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xloadimage.h" #ifdef VMS #include "patchlevel." #else #include "patchlevel" #endif #include extern int _Xdebug; extern char *ProgramName; extern Display *Disp; extern int Scrn; extern char *BuildDate; extern char *BuildUser; extern char *BuildSystem; static char *signalName(sig) int sig; { static char buf[32]; switch (sig) { case SIGSEGV: return("SEGV"); case SIGBUS: return("BUS"); case SIGFPE: return("FPE"); case SIGILL: return("ILL"); default: sprintf(buf, "Signal %d", sig); return(buf); } } void memoryExhausted() { fprintf(stderr, "\n\nMemory has been exhausted; operation cannot continue (sorry).\n"); if (_Xdebug) abort(); else exit(1); } void internalError(sig) int sig; { static int handling_error= 0; int a, b; Screen *screen; switch(handling_error++) { case 0: printf("\n\n\ An internal error (%s) has occurred. If you would like to file a bug\n\ report, please send email to %s\n\ with a description of how you triggered the bug, the output of xloadimage\n\ before the failure, and the following information:\n\n", signalName(sig), AUTHOR_EMAIL); printf("Xloadimage Version %s.%s\n\n", VERSION, PATCHLEVEL); if (BuildUser) printf("Built by: %s\n", BuildUser); if (BuildDate) printf("Built on: %s\n", BuildDate); printf("Build system: %s\n", BuildSystem); if (Disp) { screen= ScreenOfDisplay(Disp, Scrn); printf("Server: %s Version %d\n", ServerVendor(Disp), VendorRelease(Disp)); printf("Depths and visuals supported:\n"); for (a= 0; a < screen->ndepths; a++) { printf("%2d:", screen->depths[a].depth); for (b= 0; b < screen->depths[a].nvisuals; b++) printf(" %s", nameOfVisualClass(screen->depths[a].visuals[b].class)); printf("\n"); } } else printf("[No information on server; error occurred before connection]\n"); break; case 1: fprintf(stderr, "\n\n\ An internal error has occurred within the internal error handler. No more\n\ information about the error is available, sorry.\n"); exit(1); break; } if (_Xdebug) /* dump core if -debug is on */ abort(); exit(1); } void version() { printf("Xloadimage version %s.%s by Jim Frost.\n", VERSION, PATCHLEVEL); printf("Built on %s\n", BuildSystem); printf("Please send email to %s for\npraise or bug reports.\n", AUTHOR_EMAIL); } void usageHelp() { printf("\nUsage: %s [global options] {[image options] image_name ...}\n\n", tail(ProgramName)); printf("\ Type `%s -help [option ...]' for information on a particular option, or\n\ `%s -help' to enter the interactive help facility.\n", tail(ProgramName), tail(ProgramName)); exit(1); } void usage() { version(); usageHelp(); /* NOTREACHED */ } char *tail(path) char *path; { int s; char *t; t= path; for (s= 0; *(path + s) != '\0'; s++) if (*(path + s) == '/') t= path + s + 1; return(t); } /* simple error handler. this provides us with some kind of error recovery. */ int errorHandler(disp, error) Display *disp; XErrorEvent *error; { char errortext[BUFSIZ]; XGetErrorText(disp, error->error_code, errortext, BUFSIZ); fprintf(stderr, "xloadimage: X Error: %s on 0x%x\n", errortext, error->resourceid); if (_Xdebug) /* if -debug mode is enabled, dump a core when we hit this */ abort(); else return(0); } /* findstr - public-domain implementation of standard C 'strstr' library function (renamed and slightly modified to avoid naming conflicts - jimf) last edit: 02-Sep-1990 D A Gwyn This is an original implementation based on an idea by D M Sunday, essentially the "quick search" algorithm described in CACM V33 N8. Unlike Sunday's implementation, this one does not wander past the ends of the strings (which can cause malfunctions under certain circumstances), nor does it require the length of the searched text to be determined in advance. There are numerous other subtle improvements too. The code is intended to be fully portable, but in environments that do not conform to the C standard, you should check the sections below marked "configure as required". There are also a few compilation options, as follows: */ #define BYTE_MAX 255 #define EOS '\0' /* C string terminator */ char * /* returns -> leftmost occurrence, or null pointer if not present */ findstr( s1, s2 ) char *s1; /* -> string to be searched */ char *s2; /* -> search-pattern string */ { register byte *t; /* -> text character being tested */ register byte *p; /* -> pattern char being tested */ register byte *tx; /* -> possible start of match */ register unsigned int m; /* length of pattern */ register byte *top; /* -> high water mark in text */ unsigned int shift[BYTE_MAX + 1]; /* pattern shift table */ if ( s1 == NULL || s2 == NULL ) return NULL; /* certainly, no match is found! */ /* Precompute shift intervals based on the pattern; the length of the pattern is determined as a side effect: */ bzero(&shift[1], (BYTE_MAX * sizeof(unsigned int))); /* Note: shift[0] is undefined at this point (fixed later). */ for ( m = 1, p = (byte *)s2; *p != EOS; ++m, ++p ) shift[(byte)*p] = m; { register byte c; c = BYTE_MAX; do shift[c] = m - shift[c]; while ( --c > 0 ); /* Note: shift[0] is still undefined at this point. */ } shift[0] = --m; /* shift[EOS]; important details! */ /* Try to find the pattern in the text string: */ for ( top = tx = (byte *)s1; ; tx += shift[*(top = t)] ) { for ( t = tx, p = (byte *)s2; ; ++t, ++p ) { if ( *p == EOS ) /* entire pattern matched */ return (char *)tx; if ( *p != *t ) break; } if ( t < top ) /* idea due to ado@elsie.nci.nih.gov */ t = top; /* already scanned this far for EOS */ do { if ( *t == EOS ) return NULL; /* no match */ } while ( ++t - tx != m ); /* < */ } } lete copyright information. */ #include "copyright.h" #include "xloadimage.h" #ifdef VMS #include "patchlevel." #else #include "patchlevel" #endif #include extern int _Xdebug; extern char *ProgramName; extern Display *Disp; extern int Scrn; extern char *BuildDate; extern char *BuildUser; extern char *BuildSystem; static charxloadimage.4.1/options.c 664 221 144 61037 5463770765 10451 /* options.c: * * finds which option in an array an argument matches * * jim frost 10.03.89 * * Copyright 1989 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include #include "image.h" #include "options.h" extern char *ProgramName; /* options array and definitions. If you add something to this you also * need to add its OptionId in options.h. */ static OptionArray Options[] = { /* global options */ { "border", BORDER, "color", "\ Set the color used for the border around centered or placed images.", }, { "configuration", CONFIGURATION, NULL, "\ Show the current configuration including any information loaded from\n\ the ~/.xloadimagerc configuration file.", }, #ifdef DEBUG { "debug", DBUG, NULL, "\ Turn on synchronous mode for debugging.", }, #endif /* DEBUG */ { "default", DEFAULT, NULL, "\ Set the root background to the default pattern and colors.", }, { "display", DISPLAY, NULL, "\ Indicate the X display you would like to use.", }, { "dump", DUMP, "type[,options] filename", "\ Dump loaded image into an image file of the specified type and name. Use\n\ the -path or -configuration options to determine the possible formats.\n\ Some image types may allow options; these are specified following a comma.\n\ If the image type retains a title, -title can be used to set or change it." }, { "fit", FIT, NULL, "\ Force the image(s) to use the default colormap.", }, { "fork", FORK, NULL, "\ Background automatically. Turns on -quiet.", }, { "fullscreen", FULLSCREEN, NULL, "\ Use the whole screen for displaying an image. If -onroot is also specified,\n\ the image will be zoomed to fit the size of the screen.", }, { "geometry", GEOMETRY, "window_geometry", "\ Specify the size of the display window. Ignored if -fullscreen is given.\n\ If used in conjunction with -onroot, this defines the size of the base image.", }, { "help", HELP, "[option ...]", "\ Give help on a particular option or series of options. If no option is\n\ supplied, a list of available options is given.", }, { "identify", IDENTIFY, NULL, "\ Identify images rather than displaying them.", }, { "install", INSTALL, NULL, "\ Force colormap installation. This option is useful for naive window managers\n\ which do not know how to handle colormap installation, but should be avoided\n\ unless necessary.", }, { "list", LIST, NULL, "\ List the images along the image path. Use `xloadimage -path' to see the\n\ current image path.", }, { "onroot", ONROOT, NULL, "\ Place the image on the root window. If used in conjunction with -fullscreen,\n\ the image will be zoomed to fit. -border, -at, and -center also affect the\n\ results.", }, { "path", PATH, NULL, "\ Display the image path and default extensions that are loaded from the\n\ .xloadimagerc file. This option is identical to the -configuration option\n\ and is provided for backwards compatibility.", }, { "pixmap", PIXMAP, NULL, "\ Force the use of a pixmap as backing store. This may improve performance but\n\ may not work on memory-limited servers.", }, { "private", PRIVATE, NULL, "\ Force the use of a private colormap. This happens automatically if a visual\n\ other than the default is used. This is the opposite of -fit.", }, { "quiet", QUIET, NULL, "\ Turn off verbose mode. This is the default if using -onroot or -windowid.", }, { "shrink", SHRINKTOFIT, NULL, "\ Shrink a images larger than screen to fit. This is particularly useful with\n\ DEC servers that don't allow creation of windows larger than the screen.", }, { "slideshow", OPT_IGNORE, NULL, "\ Compatibility switch for older versions of xloadimage. Since this is the\n\ the default for versions 3.0 and newer, it does nothing.", }, { "supported", SUPPORTED, NULL, "\ Give a list of the supported image types.", }, { "verbose", VERBOSE, NULL, "\ Turn on verbose mode. This is the default if using -view.", }, { "version", VER_NUM, NULL, "\ Show the version number of this version of xloadimage.", }, { "view", VIEW, NULL, "\ View an image in a window. This is the default for all but xsetbg.", }, { "visual", VISUAL, NULL, "\ Force the use of a particular visual to display an image. Normally xloadimage\n\ will attempt to pick a visual which is reasonable for the supplied image.", }, { "windowid", WINDOWID, "window_id", "\ Set the background of a particular window. This is similar to -onroot and\n\ is useful for servers which use an untagged virtual root. The window ID\n\ should be supplied as a hexadecimal number, eg 0x40003.", }, /* image options */ { "at", AT, NULL, "\ Load the image onto the base image (if using -merge) or the root window (if\n\ using -onroot) at a specific location. If used in conjunction with -onroot\n\ this forces the -fullscreen flag on.", }, { "background", BACKGROUND, "color", "\ Set the background pixel color for a monochrome image. See -foreground and\n\ -invert.", }, { "brighten", BRIGHT, "percentage", "\ Brighten or darken the image by a percentage. Values greater than 100 will\n\ brighten the image, values smaller than 100 will darken it.", }, { "center", CENTER, NULL, "\ Center the image on the base image (if using -merge) or the root window (if\n\ using -onroot). If used in conjunction with -onroot this forces the\n\ -fullscreen flag on.", }, { "clip", CLIP, "X,Y,W,H", "\ Clip out the rectangle specified by X,Y,W,H and use that as the image.", }, { "colors", COLORS, "number_of_colors", "\ Specify the maximum number of colors to be used in displaying the image.\n\ Values of 1-32768 are acceptable although low values will not look good.\n\ This is done automatically if the server cannot support the depth of the\n\ image.", }, { "delay", DELAY, "seconds", "\ Set the automatic advance delay.", }, { "dither", DITHER, NULL, "\ Dither the image into monochrome. This happens automatically if sent to\n\ a monochrome display.", }, { "foreground", FOREGROUND, "color", "\ Set the foreground pixel color for a monochrome image. See -background and\n\ -invert.", }, { "gamma", GAMMA, "value", "\ Adjust the image's colors by a gamma value. 1.0 is the default, which does\n\ nothing. Values under 1.0 darken the image, values higher brighten it.\n\ Typically a dark image needs a value of 2.0 to 2.5. This option is similar\n\ to -brighten but often works better.", }, { "global", GLOBAL, NULL, "\ Force the next option to apply to all images rather that to the current\n\ image.", }, { "goto", GOTO, "image_name", "\ Start displaying a particlar image. This is useful for creating image display\newn\ loops. If two images with the target name exist, the first in the argument list\n\ will be used.", }, { "gray", GRAY, NULL, "\ Convert an image to grayscale. Will \"undither\" a bitmap image. Also\n\ called -grey.", }, { "grey", GRAY, NULL, "\ See -gray.", }, { "halftone", HALFTONE, NULL, "\ Dither the image into monochrome using a halftone dither. This preserves\n\ image detail but blows the image up by sixteen times.", }, { "idelay", IDELAY, NULL, "\ This option is no longer supported due to the addition of -global. The\n\ same functionality can be had with -delay.", }, { "invert", INVERT, NULL, "\ Invert a monochrome image. This is the same as specifying `-foreground black'\n\ and `-background white'.", }, { "merge", MERGE, NULL, "\ Merge this image onto the previous image. When used in conjunction with\n\ -at, -center, and -clip you can generate collages.", }, { "name", NAME, NULL, "\ Specify that the next argument is to be the name of an image. This is\n\ useful for loading images whose names look to be options.", }, { "newoptions", NEWOPTIONS, NULL, "\ This option is no longer supported.", }, { "normalize", NORMALIZE, NULL, "\ Normalize the image. This expands color coverage to fit the colormap as\n\ closely as possible. It may have good effects on an image which is too\n\ bright or too dark.", }, { "rotate", ROTATE, "degrees", "\ Rotate the image by 90, 180, or 270 degrees.", }, { "smooth", SMOOTH, NULL, "\ Perform a smoothing convolution on the image. This is useful for making\n\ a zoomed image look less blocky. Multiple -smooth arguments will run\n\ the smoother multiple times. This option can be quite slow on large images.", }, { "tile", TILE, NULL, "\ Tile this image (after any merging or processing) to create a full-screen\n\ image. This is usually used to create a background to merge other images\n\ onto. -geometry can be used to set the size after tiling, otherwise it\n\ defaults to the size of the display.", }, { "title", TITLE, "image_title", "\ Title for the image (used in title bars and with -dump).", }, { "type", TYPE, "type_name", "\ Specifies the type of image so that run-time determination is unnecessary.\n\ This generally speeds up loading but is usually not necessary. Use the\n\ -supported option to get a list of image types supported along with their\n\ type_name.", }, { "xzoom", XZOOM, "percentage", "\ Zoom the image along the X axis by a percentage. See -zoom.", }, { "yzoom", YZOOM, "percentage", "\ Zoom the image along the X axis by a percentage. See -zoom.", }, { "zoom", ZOOM, NULL, "\ Zoom the image along both axes. Values smaller than 100 will reduce the\n\ size of the image, values greater than 100 will enlarge it. See also\n\ -xzoom and -yzoom.", }, { NULL, OPT_NOTOPT, NULL, NULL } }; static void listOptions() { int a, width; printf("\nThe options are:\n\n"); width= 0; for (a= 0; Options[a].name; a++) { width += strlen(Options[a].name) + 2; if (width > 78) { printf("\n"); width= strlen(Options[a].name) + 2; } printf("%s%s", Options[a].name, (Options[a + 1].name ? ", " : "\n\n")); } } static int helpOnOption(option) char *option; { int a, foundone; if (*option == '-') option++; foundone= 0; for (a= 0; Options[a].name; a++) if (!strncmp(Options[a].name, option, strlen(option))) { printf("Option: %s\nUsage: %s -%s %s\nDescription:\n%s\n\n", Options[a].name, ProgramName, Options[a].name, (Options[a].args ? Options[a].args : ""), Options[a].description); foundone= 1; } if (!foundone) printf("No option `%s'.\n", option); return(foundone); } static void literalMindedUser(s) char *s; { printf("The quotes around %s are unnecessary. You don't have to be so\n\ literal-minded!\n", s); } void help(option) char *option; { char buf[BUFSIZ]; /* batch help facility */ if (option) { if (!helpOnOption(option)) printf("\ Type `xloadimage -help [option ...]' to get help on a particular option or\n\ `xloadimage -help' to enter the interactive help facility.\n\n"); return; } /* interactive help facility */ printf("\nXloadimage Interactive Help Facility\n\n"); printf("\ Type `?' for a list of options, or `.' or `quit' to leave the interactive\n\ help facility.\n"); for (;;) { printf("help> "); buf[BUFSIZ - 1]= '\0'; if (fgets(buf, BUFSIZ - 1, stdin) == NULL) { printf("quit\n"); exit(0); } while(buf[0] && buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1]= '\0'; /* help keywords */ if (!strcmp(buf, "")) { printf("Type `?' for a list of options\n"); continue; } if (!strcmp(buf, "?")) ; else if (!strcmp(buf, "quit") || !strcmp(buf, ".")) exit(0); else if (!strcmp(buf, "`?'")) literalMindedUser("the question mark"); else if (!strcmp(buf, "`quit'")) { literalMindedUser("quit"); exit(0); } else if (!strcmp(buf, "`.'")) { literalMindedUser("the period"); exit(0); } else if (helpOnOption(buf)) continue; listOptions(); printf("\ You may get this list again by typing `?' at the `help>' prompt, or leave\n\ the interactive help facility with `.' or `quit'.\n"); } } OptionSet *newOptionSet() { OptionSet *optset; optset= (OptionSet *)lmalloc(sizeof(OptionSet)); optset->options= NULL; optset->next= NULL; return(optset); } Option *newOption(type) OptionId type; { Option *opt; opt= (Option *)lmalloc(sizeof(Option)); opt->type= type; opt->next= NULL; return(opt); } void addOption(optset, newopt) OptionSet *optset; Option *newopt; { Option *opt; if (optset->options) { for (opt= optset->options; opt->next; opt= opt->next) /* EMPTY */ ; opt->next= newopt; } else optset->options= newopt; } /* return the option structure for a typed option */ Option *getOption(optset, type) OptionSet *optset; OptionId type; { Option *opt; if (optset) for (opt= optset->options; opt; opt= opt->next) if (type == opt->type) return(opt); return(NULL); } /* this kills all options of a particular type in a particular set */ void killOption(optset, type) OptionSet *optset; OptionId type; { Option *opt; if (!optset) return; for (opt= optset->options; opt; opt= opt->next) if (opt->type == type) opt->type= OPT_IGNORE; } OptionId optionNumber(arg) char *arg; { int a, b; if ((*arg) != '-') return(OPT_NOTOPT); for (a= 0; Options[a].name; a++) { if (!strncmp(arg + 1, Options[a].name, strlen(arg) - 1)) { for (b= a + 1; Options[b].name; b++) if (!strncmp(arg + 1, Options[b].name, strlen(arg) - 1)) return(OPT_SHORTOPT); return(Options[a].option_id); } } return(OPT_BADOPT); } static char *optionName(type) OptionId type; { int a; for (a= 0; Options[a].name; a++) if (Options[a].option_id == type) return(Options[a].name); return(""); } static void optionUsage(type) OptionId type; { helpOnOption(optionName(type)); exit(1); } static int getInteger(type, s) OptionId type; char *s; { unsigned int ret; if (strncmp(s, "0x", 2)) { if (sscanf(s, "%d", &ret) == 1) return(ret); } else if (sscanf(s + 2, "%x", &ret) == 1) return(ret); fprintf(stderr, "Bad integer argument for the %s option\n", optionName(type)); usageHelp(); /* NOTREACHED */ } static float getFloat(type, s) char *s; { float ret; if (sscanf(s, "%f", &ret) != 1) { fprintf(stderr, "Bad floating point argument for the %s option\n", optionName(type)); usageHelp(); /* NOTREACHED */ } return(ret); } /* process the argument list into an option array. the first option in * the returned list is the set of global options. */ void processOptions(argc, argv, rglobal, rimage) int argc; char *argv[]; OptionSet **rglobal; OptionSet **rimage; { OptionSet *global_options= newOptionSet(); OptionSet *image_options, *curset; Option *newopt; int a, global_opt= 0; if (!strcmp(tail(argv[0]), "xview")) { newopt= newOption(VERBOSE); addOption(global_options, newopt); } else if (!strcmp(tail(argv[0]), "xsetbg")) { newopt= newOption(ONROOT); addOption(global_options, newopt); } else { newopt= newOption(VERBOSE); addOption(global_options, newopt); } image_options= curset= newOptionSet(); for (a= 1; a < argc; a++) { newopt= newOption(optionNumber(argv[a])); switch (newopt->type) { case OPT_BADOPT: printf("%s: Bad option\n", argv[a]); usageHelp(); /* NOTREACHED */ case OPT_IGNORE: lfree((byte *)newopt); continue; case NAME: if (++a >= argc) optionUsage(NAME); /* FALLTHRU */ case OPT_NOTOPT: newopt->type= NAME; newopt->info.name= dupString(argv[a]); addOption(curset, newopt); curset->next= newOptionSet(); curset= curset->next; continue; case OPT_SHORTOPT: printf("%s: Not enough characters to identify option\n", argv[a]); usageHelp(); /* NOTREACHED */ /* process options global to everything */ case BORDER: if (++a >= argc) optionUsage(BORDER); newopt->info.border= argv[a]; global_opt= 1; break; case CONFIGURATION: showConfiguration(); exit(0); #ifdef DEBUG case DBUG: _Xdebug= 1; continue; #endif /* DEBUG */ case DEFAULT: addOption(curset, newopt); curset->next= newOptionSet(); curset= curset->next; newopt= newOption(ONROOT); /* assume -onroot */ addOption(global_options, newopt); newopt= newOption(FIT); /* assume -fit */ global_opt= 1; break; case DISPLAY: if (++a >= argc) optionUsage(DISPLAY); newopt->info.display= argv[a]; global_opt= 1; break; case DUMP: if (a + 2 >= argc) optionUsage(DUMP); newopt->info.dump.type= argv[++a]; newopt->info.dump.file= argv[++a]; global_opt= 1; break; case FIT: global_opt= 1; break; case FORK: #ifdef NO_FORK fprintf(stderr, "%s is not supported under this operating system", optionName(FORK)); continue; #else global_opt= 1; break; #endif case FULLSCREEN: global_opt= 1; break; case GEOMETRY: if (++a >= argc) optionUsage(GEOMETRY); if (sscanf(argv[a], "%dx%d", &newopt->info.geometry.w, &newopt->info.geometry.h) != 2) { optionUsage(GEOMETRY); } newopt->info.geometry.string= argv[a]; global_opt= 1; break; case GLOBAL: global_opt= 1; /* next option will be put on global argument list */ continue; case HELP: if (++a >= argc) help(NULL); else do { help(argv[a++]); } while (a < argc); exit(0); case IDENTIFY: global_opt= 1; break; case LIST: listImages(); exit(0); case INSTALL: global_opt= 1; break; case ONROOT: addOption(global_options, newopt); newopt= newOption(FIT); /* assume -fit */ global_opt= 1; break; case PIXMAP: global_opt= 1; break; case PRIVATE: global_opt= 1; break; case QUIET: killOption(global_options, VERBOSE); global_opt= 1; break; case SHRINKTOFIT: global_opt= 1; break; case SUPPORTED: supportedImageTypes(); exit(0); case VERBOSE: global_opt= 1; break; case VER_NUM: version(); exit(0); case VIEW: killOption(global_options, DUMP); killOption(global_options, ONROOT); global_opt= 1; break; case VISUAL: if (++a >= argc) optionUsage(VISUAL); newopt->info.visual= visualClassFromName(argv[a]); global_opt= 1; break; case WINDOWID: if (++a >= argc) optionUsage(WINDOWID); killOption(global_options, DUMP); killOption(global_options, VIEW); newopt->info.windowid= getInteger(WINDOWID, argv[a]); addOption(global_options, newopt); newopt= newOption(ONROOT); addOption(global_options, newopt); newopt= newOption(FIT); global_opt= 1; break; /* process options local to an image */ case AT: if (!argv[++a]) break; if (sscanf(argv[a], "%d,%d", &newopt->info.at.x, &newopt->info.at.y) != 2) optionUsage(AT); break; case BACKGROUND: if (++a >= argc) optionUsage(BACKGROUND); newopt->info.background= argv[a]; break; case BRIGHT: if (++a >= argc) optionUsage(BRIGHT); newopt->info.bright= getInteger(BRIGHT, argv[a]); break; case CENTER: break; case CLIP: if (++a >= argc) optionUsage(CLIP); if (sscanf(argv[a], "%d,%d,%d,%d", &newopt->info.clip.x, &newopt->info.clip.y, &newopt->info.clip.w, &newopt->info.clip.h) != 4) optionUsage(CLIP); break; case COLORS: if (++a >= argc) optionUsage(COLORS); newopt->info.colors= getInteger(COLORS, argv[a]); if (newopt->info.colors < 2) { printf("Argument to %s is too low (ignored)\n", optionName(COLORS)); newopt->type= OPT_IGNORE; } else if (newopt->info.colors > 65536) { printf("Argument to %s is too high (ignored)\n", optionName(COLORS)); newopt->type= OPT_IGNORE; } break; case IDELAY: fprintf(stderr, "%s has been superceded by %s (translating)\n", optionName(IDELAY), optionName(DELAY)); /* FALLTHRU */ case DELAY: if (++a >= argc) optionUsage(DELAY); #ifdef NO_DELAY fprintf(stderr, "%s is not supported on this operating system (ignored)\n", optionName(DELAY)); continue; #else /* !NO_DELAY */ newopt->info.delay= getInteger(DELAY, argv[a]); break; #endif /* !NO_DELAY */ case DITHER: break; case FOREGROUND: if (++a >= argc) optionUsage(FOREGROUND); newopt->info.foreground= argv[a]; break; case GAMMA: if (++a >= argc) optionUsage(GAMMA); newopt->info.gamma= getFloat(GAMMA, argv[a]); break; case GOTO: if (++a >= argc) optionUsage(GOTO); newopt->info.go_to= argv[a]; break; case GRAY: break; case HALFTONE: if (global_opt) killOption(global_options, DITHER); else killOption(curset, DITHER); break; case INVERT: killOption(curset, FOREGROUND); killOption(curset, BACKGROUND); newopt->type= FOREGROUND; newopt->info.foreground= "white"; if (global_opt) addOption(global_options, newopt); else addOption(curset, newopt); newopt= newOption(BACKGROUND); newopt->info.background= "black"; break; case MERGE: break; case NEWOPTIONS: fprintf(stderr, "%s is no longer supported (sorry)\n", optionName(NEWOPTIONS)); newopt->type= OPT_IGNORE; break; case NORMALIZE: break; case ROTATE: if (++a >= argc) optionUsage(ROTATE); newopt->info.rotate= getInteger(ROTATE, argv[a]); if (newopt->info.rotate % 90) { fprintf(stderr, "Argument to %s must be a multiple of 90 (ignored)\n", optionName(ROTATE)); newopt->type= OPT_IGNORE; } else { while (newopt->info.rotate < 0) newopt->info.rotate += 360; while (newopt->info.rotate > 360) newopt->info.rotate -= 360; } break; case SMOOTH: break; case TILE: break; case TITLE: if (++a >= argc) optionUsage(TITLE); newopt->info.title= argv[a]; break; case TYPE: if (++a >= argc) optionUsage(TYPE); newopt->info.type= argv[a]; break; case XZOOM: if (++a >= argc) optionUsage(XZOOM); newopt->type= ZOOM; newopt->info.zoom.x= getInteger(XZOOM, argv[a]); newopt->info.zoom.y= 0; break; case YZOOM: if (++a >= argc) optionUsage(YZOOM); newopt->type= ZOOM; newopt->info.zoom.x= 0; newopt->info.zoom.y= getInteger(YZOOM, argv[a]); break; case ZOOM: if (++a >= argc) optionUsage(ZOOM); newopt->info.zoom.x= newopt->info.zoom.y= getInteger(ZOOM, argv[a]); if (global_opt) addOption(global_options, newopt); else addOption(curset, newopt); newopt= newOption(YZOOM); newopt->info.zoom.y= getInteger(ZOOM, argv[a]); break; default: /* this should not happen! */ printf("%s: Internal error parsing arguments\n", argv[0]); exit(1); } if (global_opt) { addOption(global_options, newopt); global_opt= 0; } else addOption(curset, newopt); } *rglobal= global_options; *rimage= image_options; } /* this is used by readers/dumpers to parse options strings of the * form name[=value][,...] */ int getNextTypeOption(opt_string, name, value) char **opt_string; char **name; char **value; { static char option_name[BUFSIZ]; static char option_value[BUFSIZ]; char *p; /* if no string, don't get anything */ if (!opt_string || !*opt_string || !**opt_string) return 0; /* look for comma, the option delimiter */ p = index(*opt_string, ','); if (p != NULL) { strncpy(option_name, *opt_string, p - *opt_string); option_name[p - *opt_string] = '\0'; *opt_string = p + 1; /* increment to next option */ } else { strcpy(option_name, *opt_string); *opt_string += strlen(*opt_string); /* increment to end of string */ } *name = option_name; /* look for equals sign, the start of a value */ p = index(option_name, '='); if (p != NULL) { strcpy(option_value, p + 1); *p = '\0'; /* stomp equals sign */ *value = option_value; } else *value = NULL; /* no value */ return(1); } newopt= newOption(FIT); /* assume -fit */ global_opt= 1; break; case DISPLAY: if (++a >= argc) optionUsage(DISPLAY); newopt->info.display= argv[a]; global_opt= 1; break; case DUMP: if (a + 2 >= argc) optionUsage(DUMP); newopt->info.dump.type= argv[++a]; newopt->info.dump.file= argv[++a]; global_opt= 1; break; case FIT: global_opt= 1; break; case FORK: #ifdef NO_FORK xloadimage.4.1/root.c 664 221 144 14237 5467532220 7723 /* root.c: * * this loads an image onto the root window. changes to allow proper * freeing of previously allocated resources made by Deron Dann Johnson * (dj@eng.sun.com). * * jim frost 10.03.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xloadimage.h" #include #define RETAIN_PROP_NAME "_XSETROOT_ID" void updateProperty(dpy, w, name, type, format, data, nelem) Display *dpy; Window w; char *name; Atom type; int format; int data; int nelem; { /* intern the property name */ Atom atom = XInternAtom(dpy, name, 0); /* create or replace the property */ XChangeProperty(dpy, w, atom, type, format, PropModeReplace, (unsigned char *)&data, nelem); } /* Sets the close-down mode of the client to 'RetainPermanent' * so all client resources will be preserved after the client * exits. Puts a property on the default root window containing * an XID of the client so that the resources can later be killed. */ static void preserveResource(dpy, w) Display *dpy; Window w; { /* create dummy resource */ Pixmap pm= XCreatePixmap(dpy, w, 1, 1, 1); /* create/replace the property */ updateProperty(dpy, w, RETAIN_PROP_NAME, XA_PIXMAP, 32, (int)pm, 1); /* retain all client resources until explicitly killed */ XSetCloseDownMode(dpy, RetainPermanent); } /* Flushes any resources previously retained by the client, * if any exist. */ static void freePrevious(dpy, w) Display *dpy; Window w; { Pixmap *pm; Atom actual_type; /* NOTUSED */ int format; int nitems; int bytes_after; /* intern the property name */ Atom atom = XInternAtom(dpy, RETAIN_PROP_NAME, 0); /* look for existing resource allocation */ if ((XGetWindowProperty(dpy, w, atom, 0, 1, 1/*delete*/, AnyPropertyType, &actual_type, &format, (unsigned long *)&nitems, (unsigned long *)&bytes_after, (unsigned char **)&pm) == Success) && nitems == 1) if ((actual_type == XA_PIXMAP) && (format == 32) && (nitems == 1) && (bytes_after == 0)) { /* blast it away */ XKillClient(dpy, (XID) *pm); XFree((char *)pm); } else if (actual_type != None) { fprintf(stderr, "%s: warning: invalid format encountered for property %s\n", RETAIN_PROP_NAME, "xloadimage"); } } #if FIND_DEC_ROOTWINDOW /* this returns the root window for DECWindows servers. this is right * out of xsetroot with minor formatting changes. */ static Window getWmRootWindow(dpy, root) Display *dpy; Window root; { Window parent; Window *child; unsigned int nchildren; XWindowAttributes rootatt, childatt; if (!XGetWindowAttributes (dpy, root, &rootatt)) return(0); if (XQueryTree (dpy, root, &root, &parent, &child, &nchildren)) { int i; for (i = 0; i < nchildren; i++) { if (!XGetWindowAttributes (dpy, child[i], &childatt)) continue; if ((rootatt.width == childatt.width) && (rootatt.height == childatt.height)) return child[i]; } return root; } else return((Window)0); } static Window getDECRootWindow(dpy, root) Display *dpy; Window root; { Window temporary_rootW; if (!(temporary_rootW = getWmRootWindow(dpy, root)) || !(temporary_rootW = getWmRootWindow(dpy, temporary_rootW))) { fprintf(stderr, "Can't find false root window on DECWINDOWS server, using true root\n"); return(root); } return(temporary_rootW); } #endif /* FIND_DEC_ROOTWINDOW */ void imageOnRoot(disp, scrn, image, options, verbose) Display *disp; int scrn; Image *image; OptionSet *options; unsigned int verbose; { Option *opt; Pixmap pixmap; XImageInfo *ximageinfo; Atom __SWM_VROOT = None; Window root, rootReturn, parentReturn, *children; unsigned int numChildren; int i; char *s; if (opt= getOption(options, WINDOWID)) root= opt->info.windowid; else { root = RootWindow(disp, scrn); #ifdef FIND_DEC_ROOTWINDOW /* look for DECWindows servers because they do strange stuff with the * root window. they should be shot for that one. * * some X terminal vendors put DECWINDOWS in their vendor string to * get DEC X utilities to work. to get around them, we look for * the string "DECWINDOWS Digital" because as of this writing DEC's * vendorstrings look like "DECWINDOWS DigitalEquipmentCorporation". */ for (s= ServerVendor(disp); *s; s++) if (!strncmp(s, "DECWINDOWS Digital", 18)) root= getDECRootWindow(disp, scrn); #endif /* FIND_DEC_ROOTWINDOW */ /* Added for window managers like swm and tvtwm that follow solbourne's * virtual root window concept. */ __SWM_VROOT = XInternAtom(disp, "__SWM_VROOT", False); XQueryTree(disp, root, &rootReturn, &parentReturn, &children, &numChildren); for(i = 0; i < numChildren; i++) { Atom actual_type; int actual_format; long nitems, bytesafter; Window *newRoot = NULL; if (XGetWindowProperty (disp, children[i], __SWM_VROOT,0,1, False, XA_WINDOW, &actual_type, &actual_format, (unsigned long *)&nitems, (unsigned long *)&bytesafter, (unsigned char **) &newRoot) == Success && newRoot) { root = *newRoot; break; } } } freePrevious(disp, root); if (! (ximageinfo= imageToXImage(disp, scrn, DefaultVisual(disp, scrn), DefaultDepth(disp, scrn), image, False, True, verbose))) { fprintf(stderr, "Cannot convert Image to XImage\n"); exit(1); } if ((pixmap= ximageToPixmap(disp, root, ximageinfo)) == None) { printf("Cannot create background (not enough resources, sorry)\n"); exit(1); } /* changing the root colormap is A Bad Thing, so deny it. */ if (ximageinfo->cmap != DefaultColormap(disp, scrn)) { printf("Loading image onto root would change default colormap (sorry)\n"); XFreePixmap(disp, pixmap); exit(1); } XSetWindowBackgroundPixmap(disp, root, pixmap); XClearWindow(disp, root); XFreePixmap(disp, pixmap); freeXImage(image, ximageinfo); preserveResource(disp, root); } dpy, name, 0); /* create or replace the property */ XChangeProperty(dpy, w, atom, type, format, PropModeReplace, (unsigned char *)&data, nelem); } /* Sets the close-down mode of the client to 'RetainPermanent' * so all client resources will be preserved after the client * exits. Puts a property on the default root window containing * axloadimage.4.1/send.c 664 221 144 42037 5467532246 7700 /* send.c: * * send an Image to an X pixmap * * jim frost 10.02.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xloadimage.h" static int GotError; static int pixmapErrorTrap(disp, pErrorEvent) Display *disp; XErrorEvent * pErrorEvent; { #define MAXERRORLEN 100 char buf[MAXERRORLEN+1]; GotError = 1; XGetErrorText(disp, pErrorEvent->error_code, buf, MAXERRORLEN); printf("serial #%d (request code %d) Got Error %s\n", pErrorEvent->serial, pErrorEvent->request_code, buf); return(0); } Pixmap ximageToPixmap(disp, parent, ximageinfo) Display *disp; Window parent; XImageInfo *ximageinfo; { int (*old_handler)(); Pixmap pixmap; GotError = 0; old_handler = XSetErrorHandler(pixmapErrorTrap); XSync(disp, False); pixmap= XCreatePixmap(disp, parent, ximageinfo->ximage->width, ximageinfo->ximage->height, ximageinfo->depth); (void)XSetErrorHandler(old_handler); if (GotError) return(None); ximageinfo->drawable= pixmap; sendXImage(ximageinfo, 0, 0, 0, 0, ximageinfo->ximage->width, ximageinfo->ximage->height); return(pixmap); } /* find the best pixmap depth supported by the server for a particular * visual and return that depth. * * this is complicated by R3's lack of XListPixmapFormats so we fake it * by looking at the structure ourselves. */ static unsigned int bitsPerPixelAtDepth(disp, scrn, depth) Display *disp; int scrn; unsigned int depth; { #if XlibSpecificationRelease < 4 /* the way things were */ unsigned int a; for (a= 0; a < disp->nformats; a++) if (disp->pixmap_format[a].depth == depth) return(disp->pixmap_format[a].bits_per_pixel); #else /* the way things should be */ XPixmapFormatValues *xf; unsigned int nxf, a; xf = XListPixmapFormats(disp, (int *)&nxf); for (a = 0; a < nxf; a++) if (xf[a].depth == depth) return(xf[a].bits_per_pixel); #endif /* this should never happen; if it does, we're in trouble */ fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); exit(1); } XImageInfo *imageToXImage(disp, scrn, visual, ddepth, image, private_cmap, fit, verbose) Display *disp; int scrn; Visual *visual; /* visual to use */ unsigned int ddepth; /* depth of the visual to use */ Image *image; unsigned int private_cmap; unsigned int fit; unsigned int verbose; { Pixel *index, *redvalue, *greenvalue, *bluevalue; unsigned int a, b, newmap, x, y, linelen, dpixlen, dbits; XColor xcolor; XGCValues gcv; XImageInfo *ximageinfo; Image *orig_image; goodImage(image, "imageToXimage"); xcolor.flags= DoRed | DoGreen | DoBlue; index= redvalue= greenvalue= bluevalue= NULL; orig_image= image; ximageinfo= (XImageInfo *)lmalloc(sizeof(XImageInfo)); ximageinfo->disp= disp; ximageinfo->scrn= scrn; ximageinfo->depth= 0; ximageinfo->drawable= None; ximageinfo->foreground= ximageinfo->background= 0; ximageinfo->gc= NULL; ximageinfo->ximage= NULL; /* process image based on type of visual we're sending to */ switch (image->type) { case ITRUE: switch (visual->class) { case TrueColor: case DirectColor: /* goody goody */ break; default: if (visual->bits_per_rgb > 1) image= reduce(image, depthToColors(visual->bits_per_rgb), verbose); else image= dither(image, verbose); } break; case IRGB: switch(visual->class) { case TrueColor: case DirectColor: /* no problem, we handle this just fine */ break; default: if (visual->bits_per_rgb < 2) image= dither(image, verbose); break; } case IBITMAP: /* no processing ever needs to be done for bitmaps */ break; } /* do color allocation */ switch (visual->class) { case TrueColor: case DirectColor: if (!BITMAPP(image)) { /* bitmaps don't need all of this */ Pixel pixval; unsigned int redcolors, greencolors, bluecolors; unsigned int redstep, greenstep, bluestep; unsigned int redbottom, greenbottom, bluebottom; unsigned int redtop, greentop, bluetop; redvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); greenvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); bluevalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); if (visual == DefaultVisual(disp, scrn)) ximageinfo->cmap= DefaultColormap(disp, scrn); else ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); retry_direct: /* tag we hit if a DirectColor allocation fails on * default colormap */ /* calculate number of distinct colors in each band */ redcolors= greencolors= bluecolors= 1; for (pixval= 1; pixval; pixval <<= 1) { if (pixval & visual->red_mask) redcolors <<= 1; if (pixval & visual->green_mask) greencolors <<= 1; if (pixval & visual->blue_mask) bluecolors <<= 1; } /* sanity check */ if ((redcolors > visual->map_entries) || (greencolors > visual->map_entries) || (bluecolors > visual->map_entries)) { fprintf(stderr, "\ Warning: inconsistency in color information (this may be ugly)\n"); } redstep= 256 / redcolors; greenstep= 256 / greencolors; bluestep= 256 / bluecolors; redbottom= greenbottom= bluebottom= 0; for (a= 0; a < visual->map_entries; a++) { if (redbottom < 256) redtop= redbottom + redstep; if (greenbottom < 256) greentop= greenbottom + greenstep; if (bluebottom < 256) bluetop= bluebottom + bluestep; xcolor.red= (redtop - 1) << 8; xcolor.green= (greentop - 1) << 8; xcolor.blue= (bluetop - 1) << 8; if (! XAllocColor(disp, ximageinfo->cmap, &xcolor)) { /* if an allocation fails for a DirectColor default visual then * we should create a private colormap and try again. */ if ((visual->class == DirectColor) && (visual == DefaultVisual(disp, scrn))) { ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); goto retry_direct; } /* something completely unexpected happened */ fprintf(stderr, "\ imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); return(NULL); } /* fill in pixel values for each band at this intensity */ while ((redbottom < 256) && (redbottom < redtop)) redvalue[redbottom++]= xcolor.pixel & visual->red_mask; while ((greenbottom < 256) && (greenbottom < greentop)) greenvalue[greenbottom++]= xcolor.pixel & visual->green_mask; while ((bluebottom < 256) && (bluebottom < bluetop)) bluevalue[bluebottom++]= xcolor.pixel & visual->blue_mask; } break; } /* bitmaps will fall through to the default case */ /* FALLTHRU */ default: retry: /* this tag is used when retrying because we couldn't get a fit */ compress(image, verbose); index= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used); /* private_cmap flag is invalid if not a dynamic visual */ switch (visual->class) { case StaticColor: case StaticGray: private_cmap= 0; } /* get the colormap to use. */ if (private_cmap) { /* user asked us to use a private cmap */ newmap= 1; fit= 0; } else if ((visual == DefaultVisual(disp, scrn)) || (visual->class == StaticGray) || (visual->class == StaticColor) || (visual->class == TrueColor) || (visual->class == DirectColor)) { /* if we're using the default visual, try to alloc colors shareable. * otherwise we're using a static visual and should treat it * accordingly. */ if (visual == DefaultVisual(disp, scrn)) ximageinfo->cmap= DefaultColormap(disp, scrn); else ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); newmap= 0; /* allocate colors shareable (if we can) */ for (a= 0; a < image->rgb.used; a++) { xcolor.red= *(image->rgb.red + a); xcolor.green= *(image->rgb.green + a); xcolor.blue= *(image->rgb.blue + a); if (! XAllocColor(disp, ximageinfo->cmap, &xcolor)) if ((visual->class == StaticColor) || (visual->class == StaticGray) || (visual->class == TrueColor) || (visual->class == DirectColor)) { printf("imageToXImage: XAllocColor failed on a static visual\n"); return(NULL); } else { /* we can't allocate the colors shareable so free all the colors * we had allocated and create a private colormap (or fit * into the default cmap if `fit' is true). */ XFreeColors(disp, ximageinfo->cmap, index, a, 0); newmap= 1; break; } *(index + a)= xcolor.pixel; } } else { newmap= 1; fit= 0; } if (newmap) { /* either create a new colormap or fit the image into the one we * have. to create a new one, we create a private cmap and allocate * the colors writable. fitting the colors is harder, we have to: * 1. grab the server so no one can goof with the colormap. * 2. count the available colors using XAllocColorCells. * 3. free the colors we just allocated. * 4. reduce the depth of the image to fit. * 5. allocate the colors again shareable. * 6. ungrab the server and continue on our way. * someone should shoot the people who designed X color allocation. */ if (fit) { if (verbose) printf(" Fitting image into default colormap\n"); XGrabServer(disp); } else { if (verbose) printf(" Using private colormap\n"); /* create new colormap */ ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); } for (a= 0; a < image->rgb.used; a++) /* count entries we got */ if (! XAllocColorCells(disp, ximageinfo->cmap, False, NULL, 0, index + a, 1)) break; if (fit) { if (a > 0) XFreeColors(disp, ximageinfo->cmap, index, a, 0); if (a <= 2) { if (verbose) { printf(" Cannot fit into default colormap, dithering..."); fflush(stdout); } image= dither(image, 0); if (verbose) printf("done\n"); fit= 0; lfree((byte *)index); XUngrabServer(disp); goto retry; } } if (a == 0) { fprintf(stderr, "imageToXImage: Color allocation failed!\n"); lfree((byte *)index); XUngrabServer(disp); return(NULL); } if (a < image->rgb.used) image= reduce(image, a, verbose); if (fit) { for (a= 0; a < image->rgb.used; a++) { xcolor.red= *(image->rgb.red + a); xcolor.green= *(image->rgb.green + a); xcolor.blue= *(image->rgb.blue + a); /* if this fails we're in trouble */ if (! XAllocColor(disp, ximageinfo->cmap, &xcolor)) { XUngrabServer(disp); printf("XAllocColor failed while fitting colormap!\n"); return(NULL); } *(index + a)= xcolor.pixel; } XUngrabServer(disp); } else { for (b= 0; b < a; b++) { xcolor.pixel= *(index + b); xcolor.red= *(image->rgb.red + b); xcolor.green= *(image->rgb.green + b); xcolor.blue= *(image->rgb.blue + b); XStoreColor(disp, ximageinfo->cmap, &xcolor); } } } break; } /* create an XImage and related colormap based on the image type * we have. */ if (verbose) { printf(" Building XImage..."); fflush(stdout); } switch (image->type) { case IBITMAP: { byte *data; /* we copy the data to be more consistent */ data= lmalloc((image->width + 7) / 8 * image->height); bcopy(image->data, data, ((image->width + 7) / 8) * image->height); gcv.function= GXcopy; ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap, 0, (char *)data, image->width, image->height, 8, 0); ximageinfo->depth= ddepth; ximageinfo->foreground= *(index + 1); ximageinfo->background= *index; ximageinfo->ximage->bitmap_bit_order= MSBFirst; ximageinfo->ximage->byte_order= MSBFirst; break; } case IRGB: case ITRUE: /* modify image data to match visual and colormap */ dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); ximageinfo->depth= ddepth; dpixlen= (dbits + 7) / 8; switch (visual->class) { case DirectColor: case TrueColor: { byte *data, *destptr, *srcptr; Pixel pixval, newpixval; ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0, NULL, image->width, image->height, 8, 0); data= lmalloc(image->width * image->height * dpixlen); ximageinfo->ximage->data= (char *)data; destptr= data; srcptr= image->data; switch (image->type) { case ITRUE: for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixval= memToVal(srcptr, image->pixlen); newpixval= redvalue[TRUE_RED(pixval)] | greenvalue[TRUE_GREEN(pixval)] | bluevalue[TRUE_BLUE(pixval)]; valToMem(newpixval, destptr, dpixlen); srcptr += image->pixlen; destptr += dpixlen; } break; case IRGB: for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { pixval= memToVal(srcptr, image->pixlen); pixval= redvalue[image->rgb.red[pixval] >> 8] | greenvalue[image->rgb.green[pixval] >> 8] | bluevalue[image->rgb.blue[pixval] >> 8]; valToMem(pixval, destptr, dpixlen); srcptr += image->pixlen; destptr += dpixlen; } break; default: /* something's broken */ printf("Unexpected image type for DirectColor/TrueColor visual!\n"); exit(0); } ximageinfo->ximage->byte_order= MSBFirst; /* trust me, i know what * i'm talking about */ break; } default: /* only IRGB images make it this far. */ /* if our XImage doesn't have modulus 8 bits per pixel, it's unclear * how to pack bits so we instead use an XYPixmap image. this is * slower. */ if (dbits % 8) { byte *data, *destdata, *destptr, *srcptr, mask; Pixel pixmask, pixval; ximageinfo->ximage = XCreateImage(disp, visual, ddepth, XYPixmap, 0, NULL, image->width, image->height, 8, 0); data= (byte *)lmalloc(image->width * image->height * dpixlen); ximageinfo->ximage->data= (char *)data; bzero(data, image->width * image->height * dpixlen); ximageinfo->ximage->bitmap_bit_order= MSBFirst; ximageinfo->ximage->byte_order= MSBFirst; linelen= (image->width + 7) / 8; for (a= 0; a < dbits; a++) { pixmask= 1 << a; destdata= data + ((ddepth - a - 1) * image->height * linelen); srcptr= image->data; for (y= 0; y < image->height; y++) { destptr= destdata + (y * linelen); *destptr= 0; mask= 0x80; for (x= 0; x < image->width; x++) { pixval= memToVal(srcptr, image->pixlen); srcptr += image->pixlen; if (index[pixval] & pixmask) *destptr |= mask; mask >>= 1; if (mask == 0) { mask= 0x80; destptr++; } } } } } else { byte *data, *srcptr, *destptr; ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0, NULL, image->width, image->height, 8, 0); dpixlen= (ximageinfo->ximage->bits_per_pixel + 7) / 8; data= (byte *)lmalloc(image->width * image->height * dpixlen); ximageinfo->ximage->data= (char *)data; ximageinfo->ximage->byte_order= MSBFirst; /* trust me, i know what * i'm talking about */ srcptr= image->data; destptr= data; for (y= 0; y < image->height; y++) for (x= 0; x < image->width; x++) { valToMem(index[memToVal(srcptr, image->pixlen)], destptr, dpixlen); srcptr += image->pixlen; destptr += dpixlen; } } break; } } if (verbose) printf("done\n"); if (index) lfree((byte *)index); if (redvalue) { lfree((byte *)redvalue); lfree((byte *)greenvalue); lfree((byte *)bluevalue); } if (image != orig_image) freeImage(image); return(ximageinfo); } /* Given an XImage and a drawable, move a rectangle from the Ximage * to the drawable. */ void sendXImage(ximageinfo, src_x, src_y, dst_x, dst_y, w, h) XImageInfo *ximageinfo; int src_x, src_y, dst_x, dst_y; unsigned int w, h; { XGCValues gcv; int a, orig_depth; char *orig_data; /* build and cache the GC */ if (!ximageinfo->gc) { gcv.function= GXcopy; if (ximageinfo->ximage->depth == 1) { gcv.foreground= ximageinfo->foreground; gcv.background= ximageinfo->background; ximageinfo->gc= XCreateGC(ximageinfo->disp, ximageinfo->drawable, GCFunction | GCForeground | GCBackground, &gcv); } else ximageinfo->gc= XCreateGC(ximageinfo->disp, ximageinfo->drawable, GCFunction, &gcv); } XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc, ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h); } /* free up anything cached in the local Ximage structure. */ void freeXImage(image, ximageinfo) Image *image; XImageInfo *ximageinfo; { if (ximageinfo->gc) XFreeGC(ximageinfo->disp, ximageinfo->gc); lfree((byte *)ximageinfo->ximage->data); ximageinfo->ximage->data= NULL; XDestroyImage(ximageinfo->ximage); lfree((byte *)ximageinfo); } r so no one can goof with the colormap. * 2. count the available colors using XAllocColorCells. * 3. free the colors we just allocated. * 4. reduce the depth of the image to fit. * 5. allocate the colors again shareable. * 6. ungrab the server and continue on our way. * someone should shoot the people who designed X color allocation. */ if (fit) { if (verbose) printf(" Fitting image into default colormap\n"); Xxloadimage.4.1/window.c 664 221 144 67207 5467532272 10263 /* window.c: * * display an image in a window * * jim frost 10.03.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include #include "xloadimage.h" #include #include #include #include #include #ifdef HAS_POLL #include #else /* !HAS_POLL */ #ifdef HAS_SELECT_INCLUDE #include #endif /* HAS_SELECT_INCLUDE */ #endif /* !HAS_POLL */ /* we can use timeouts if either select() or poll() are available. */ #if IS_BSD #define ENABLE_TIMEOUT #endif #if defined(HAS_SELECT_INCLUDE) || defined(HAS_POLL) #define ENABLE_TIMEOUT #endif /* SUPPRESS 560 */ extern int errno; /* not defined in errno.h on some systems */ static Window ImageWindow= 0; static Window ViewportWin= 0; static Colormap ImageColormap; #ifdef ENABLE_TIMEOUT static int AlarmWentOff = 0; static void delayAlarmHandler() { AlarmWentOff = 1; } /* this is a bogus function whose only purpose is to interrupt * the XNextEvent signal call in imageInWindow(). * This is added to allow automatic cycling through the specified list * of pictures. The amount of wait time is specified using the -delay * option, which is the number of seconds to pause between pictures. * - mfc 90/10/08 */ static int getNextEventWithTimeout(disp, event) Display *disp; XEvent *event; { #ifdef HAS_POLL struct pollfd fds[1]; #else fd_set rmask; #endif /* force any output to occur before we set & spin */ XFlush(disp); /* wait for alarm */ while (AlarmWentOff == 0) { if (XPending(disp)) { XNextEvent(disp, event); return(1); } #ifdef HAS_POLL fds[0].fd = ConnectionNumber(disp); fds[0].events = POLLIN; if ((poll(fds, 1, 0) == -1) && (errno != EINTR)) perror("poll"); #else /* !HAS_POLL */ FD_ZERO(&rmask); FD_SET(ConnectionNumber(disp), &rmask); if ((select(ConnectionNumber(disp)+1, &rmask, (fd_set *) 0, (fd_set *) 0, /*(struct timeval *)*/0) == -1) && (errno != EINTR)) perror("select"); #endif } return(0); } #endif /* ENABLE_TIMEOUT */ static void setCursor(disp, window, iw, ih, ww, wh, cursor) Display *disp; Window window; unsigned int iw, ih; unsigned int ww, wh; Cursor *cursor; { XSetWindowAttributes swa; if ((ww >= iw) && (wh >= ih)) swa.cursor= XCreateFontCursor(disp, XC_icon); else if ((ww < iw) && (wh >= ih)) swa.cursor= XCreateFontCursor(disp, XC_sb_h_double_arrow); else if ((ww >= iw) && (wh < ih)) swa.cursor= XCreateFontCursor(disp, XC_sb_v_double_arrow); else swa.cursor= XCreateFontCursor(disp, XC_fleur); XChangeWindowAttributes(disp, window, CWCursor, &swa); XFreeCursor(disp, *cursor); *cursor= swa.cursor; } /* place an image */ static void placeImage(disp, width, height, winwidth, winheight, rx, ry) Display *disp; int width, height, winwidth, winheight; int *rx, *ry; /* supplied and returned */ { int pixx, pixy; pixx= *rx; pixy= *ry; if (winwidth > width) pixx= (winwidth - width) / 2; else { if ((pixx < 0) && (pixx + width < winwidth)) pixx= winwidth - width; if (pixx > 0) pixx= 0; } if (winheight > height) pixy= (winheight - height) / 2; else { if ((pixy < 0) && (pixy + height < winheight)) pixy= winheight - height; if (pixy > 0) pixy= 0; } *rx= pixx; *ry= pixy; XMoveWindow(disp, ImageWindow, pixx, pixy); } /* blit an image */ static void blitImage(ximageinfo, width, height, x, y, w, h) XImageInfo *ximageinfo; unsigned int width, height; int x, y, w, h; { if (w > width) w= width; if (h > height) h= height; if (x < 0) { XClearArea(ximageinfo->disp, ximageinfo->drawable, x, y, -x, h, False); w -= (0 - x); x= 0; } if (y < 0) { XClearArea(ximageinfo->disp, ximageinfo->drawable, x, y, w, -y, False); h -= (0 - y); y= 0; } if (x + w > width) { XClearArea(ximageinfo->disp, ximageinfo->drawable, x + width, y, x + w - width, h, False); w -= x + w - width; } if (y + h > height) { XClearArea(ximageinfo->disp, ximageinfo->drawable, x, y + height, w, y + h - height, False); h -= y + h - height; } sendXImage(ximageinfo, x, y, x, y, w, h); } /* clean up static window if we're through with it */ void cleanUpWindow(disp) Display *disp; { if (ImageWindow) XDestroyWindow(disp, ImageWindow); ImageWindow= 0; if (ViewportWin) XDestroyWindow(disp, ViewportWin); ViewportWin= 0; } /* clean up after displaying an image */ static void cleanUpImage(disp, scrn, cursor, pixmap, image, ximageinfo) Display *disp; int scrn; Cursor cursor; Pixmap pixmap; Image *image; XImageInfo *ximageinfo; { XFreeCursor(disp, cursor); if (pixmap != None) XFreePixmap(disp, pixmap); freeXImage(image, ximageinfo); } /* this sets the colormap and WM_COLORMAP_WINDOWS properly for the * viewport. */ void setViewportColormap(disp, scrn, visual) Display *disp; int scrn; Visual *visual; { XSetWindowAttributes swa; static cmap_atom= None; Window cmap_windows[2]; if (cmap_atom == None) cmap_atom = XInternAtom(disp, "WM_COLORMAP_WINDOWS", False); /* if the visual we're using is the same as the default visual (used by * the viewport window) then we can set the viewport window to use the * image's colormap. this keeps most window managers happy. */ if (visual == DefaultVisual(disp, scrn)) { swa.colormap= ImageColormap; XChangeWindowAttributes(disp, ViewportWin, CWColormap, &swa); XDeleteProperty(disp, ViewportWin, cmap_atom); } /* smart window managers can handle it when we use a different colormap * in our subwindow so long as we set the WM_COLORMAP_WINDOWS property * ala ICCCM. */ else { cmap_windows[0]= ImageWindow; cmap_windows[1]= ViewportWin; XChangeProperty(disp, ViewportWin, cmap_atom, XA_WINDOW, 32, PropModeReplace, (unsigned char *)cmap_windows, 2); } } /* this attempts to convert an image title into a reasonable icon name */ static char *iconName(s) char *s; { static char buf[BUFSIZ]; char *t; if (!s) return("Unnamed"); buf[BUFSIZ - 1]= '\0'; strncpy(buf, s, BUFSIZ - 1); t= index(buf, ' '); /* strip off stuff following 1st word. this strips */ if (t) /* info added by processing functions too. */ *t= '\0'; /* strip off leading path. if you don't use unix-style paths, you might * want to change this. */ if (t= rindex(buf, '/')) { for (s= buf, t++; *t; s++, t++) *s= *t; *s= '\0'; } t= index(buf, '.'); /* look for an extension and strip it off */ if (t) *t= '\0'; return(buf); } /* visual class to name table */ static struct visual_class_name { int class; /* numerical value of class */ char *name; /* actual name of class */ } VisualClassName[] = { TrueColor, "TrueColor", DirectColor, "DirectColor", PseudoColor, "PseudoColor", StaticColor, "StaticColor", GrayScale, "GrayScale", StaticGray, "StaticGray", StaticGray, "StaticGrey", -1, NULL }; int visualClassFromName(name) char *name; { int a; char *s1, *s2; int class= -1; for (a= 0; VisualClassName[a].name; a++) { for (s1= VisualClassName[a].name, s2= name; *s1 && *s2; s1++, s2++) if ((isupper(*s1) ? tolower(*s1) : *s1) != (isupper(*s2) ? tolower(*s2) : *s2)) break; if ((*s1 == '\0') || (*s2 == '\0')) { /* check for uniqueness. we special-case StaticGray because we have two * spellings but they are unique if either is found */ if ((class != -1) && (class != StaticGray)) { fprintf(stderr, "%s does not uniquely describe a visual class (ignored)\n", name); return(-1); } class= VisualClassName[a].class; } } if (class == -1) fprintf(stderr, "%s is not a visual class (ignored)\n", name); return(class); } char *nameOfVisualClass(class) int class; { int a; for (a= 0; VisualClassName[a].name; a++) if (VisualClassName[a].class == class) return(VisualClassName[a].name); return("[Unknown Visual Class]"); } /* find the best visual of a particular class with a particular depth */ static Visual *bestVisualOfClassAndDepth(disp, scrn, class, depth) Display *disp; int scrn; int class; unsigned int depth; { Visual *best= NULL; XVisualInfo template, *info; int nvisuals; template.screen= scrn; template.class= class; template.depth= depth; if (! (info= XGetVisualInfo(disp, VisualScreenMask | VisualClassMask | VisualDepthMask, &template, &nvisuals))) return(NULL); /* no visuals of this depth */ /* not sure what to do if this gives more than one visual of a particular * class and depth, so just return the first one. */ best= info->visual; XFree((char *)info); return(best); } /* this tries to determine the best available visual to use for a particular * image */ static void bestVisual(disp, scrn, image, rvisual, rdepth) Display *disp; int scrn; Image *image; Visual **rvisual; unsigned int *rdepth; { unsigned int depth, a; Screen *screen; Visual *visual, *default_visual; /* figure out the best depth the server supports. note that some servers * (such as the HP 11.3 server) actually say they support some depths but * have no visuals that support that depth. seems silly to me.... */ depth= 0; screen= ScreenOfDisplay(disp, scrn); for (a= 0; a < screen->ndepths; a++) { if (screen->depths[a].nvisuals && ((!depth || ((depth < image->depth) && (screen->depths[a].depth > depth)) || ((screen->depths[a].depth >= image->depth) && (screen->depths[a].depth < depth))))) depth= screen->depths[a].depth; } if (!depth) { /* this shouldn't happen */ printf("bestVisual: didn't find any depths?!?\n"); depth= DefaultDepth(disp, scrn); } /* given this depth, find the best possible visual */ default_visual= DefaultVisual(disp, scrn); switch (image->type) { case ITRUE: /* if the default visual is DirectColor or TrueColor prioritize such * that we use the default type if it exists at this depth */ if (default_visual->class == TrueColor) { visual= bestVisualOfClassAndDepth(disp, scrn, TrueColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, DirectColor, depth); } else { visual= bestVisualOfClassAndDepth(disp, scrn, DirectColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, TrueColor, depth); } if (!visual || ((depth <= 8) && bestVisualOfClassAndDepth(disp, scrn, PseudoColor, depth))) visual= bestVisualOfClassAndDepth(disp, scrn, PseudoColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, GrayScale, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticGray, depth); break; case IRGB: /* if it's an RGB image, we want PseudoColor if we can get it */ visual= bestVisualOfClassAndDepth(disp, scrn, PseudoColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, DirectColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, TrueColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, GrayScale, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticGray, depth); break; case IBITMAP: visual= bestVisualOfClassAndDepth(disp, scrn, PseudoColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, GrayScale, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, StaticGray, depth); /* it seems pretty wasteful to use a TrueColor or DirectColor visual * to display a bitmap (2-color) image, so we look for those last */ if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, DirectColor, depth); if (!visual) visual= bestVisualOfClassAndDepth(disp, scrn, TrueColor, depth); break; } if (!visual) { /* this shouldn't happen */ fprintf(stderr, "bestVisual: couldn't find one?!?\n"); depth= DefaultDepth(disp, scrn); visual= DefaultVisual(disp, scrn); } *rvisual= visual; *rdepth= depth; } /* given a visual class, try to find the best visual of that class at * the best depth. returns a null visual and depth if it couldn't find * any visual of that type at any depth */ void bestVisualOfClass(disp, scrn, image, visual_class, rvisual, rdepth) Display *disp; int scrn; Image *image; int visual_class; Visual **rvisual; unsigned int *rdepth; { Visual *visual; Screen *screen; unsigned int a, b, depth; /* loop through depths looking for a visual of a good depth which matches * our visual class. */ screen= ScreenOfDisplay(disp, scrn); visual= (Visual *)NULL; depth= 0; for (a= 0; a < screen->ndepths; a++) { for (b= 0; b < screen->depths[a].nvisuals; b++) { if ((screen->depths[a].visuals[b].class == visual_class) && (!depth || ((depth < image->depth) && (screen->depths[a].depth > depth)) || ((screen->depths[a].depth >= image->depth) && (screen->depths[a].depth < depth)))) { depth= screen->depths[a].depth; visual= &(screen->depths[a].visuals[b]); } } } *rvisual= visual; *rdepth= depth; } char imageInWindow(disp, scrn, image, global_options, image_options, argc, argv, verbose) Display *disp; int scrn; Image *image; OptionSet *global_options; OptionSet *image_options; int argc; char *argv[]; unsigned int verbose; { Pixmap pixmap = None; XImageInfo *ximageinfo; Visual *visual; unsigned int depth; Window oldimagewindow; Colormap oldcmap; XSetWindowAttributes swa_img; XSetWindowAttributes swa_view; XClassHint classhint; unsigned int wa_mask_img; XSizeHints sh; XWMHints wmh; int pixx= -1, pixy= -1; int lastx, lasty, mousex, mousey; int paint; static int old_width= -1, old_height= -1; static Atom proto_atom= None, delete_atom= None; union { XEvent event; XAnyEvent any; XButtonEvent button; XKeyEvent key; XConfigureEvent configure; XExposeEvent expose; XMotionEvent motion; XResizeRequestEvent resize; XClientMessageEvent message; } event; Option *opt; unsigned int winx, winy, winwidth, winheight; unsigned int delay; unsigned int fullscreen; unsigned int fit; unsigned int install; unsigned int private_cmap; int visual_class; /* get values from options that we'll use a lot */ fit= (getOption(global_options, FIT) != NULL); fullscreen= (getOption(global_options, FULLSCREEN) != NULL); install= (getOption(global_options, INSTALL) != NULL); private_cmap= (getOption(global_options, PRIVATE) != NULL); if (opt= getOption(image_options, DELAY)) delay= opt->info.delay; else if (opt= getOption(global_options, DELAY)) delay= opt->info.delay; else delay= 0; if (opt= getOption(image_options, VISUAL)) visual_class= opt->info.visual; else visual_class= -1; /* figure out the window size. unless specifically requested to do so, * we will not exceed 90% of display real estate. */ opt= getOption(global_options, GEOMETRY); if (opt == NULL) winx= winy= winwidth= winheight= 0; else { char def_geom[30]; sprintf(def_geom, "%ux%u+0+0", image->width, image->height); XGeometry(disp, scrn, opt->info.geometry.string, def_geom, 0, 1, 1, 0, 0, (int *)&winx, (int *)&winy, (int *)&winwidth, (int *)&winheight); } if (fullscreen) { winwidth= DisplayWidth(disp, scrn); winheight= DisplayHeight(disp, scrn); } else { lastx= (winwidth || winheight); /* user set size flag */ if (!winwidth) { winwidth= image->width; if (winwidth > DisplayWidth(disp, scrn) * 0.9) winwidth= DisplayWidth(disp, scrn) * 0.9; } if (!winheight) { winheight= image->height; if (winheight > DisplayHeight(disp, scrn) * 0.9) winheight= DisplayHeight(disp, scrn) * 0.9; } } /* if the user told us to fit the colormap, we must use the default * visual. */ if (fit) { visual= DefaultVisual(disp, scrn); depth= DefaultDepth(disp, scrn); } else { visual= (Visual *)NULL; if (visual_class == -1) { /* try to pick the best visual for the image. */ bestVisual(disp, scrn, image, &visual, &depth); if (verbose && (visual != DefaultVisual(disp, scrn))) printf(" Using %s visual\n", nameOfVisualClass(visual->class)); } else { /* try to find a visual of the specified class */ bestVisualOfClass(disp, scrn, image, visual_class, &visual, &depth); if (!visual) { bestVisual(disp, scrn, image, &visual, &depth); fprintf(stderr, "Server does not support %s visual, using %s\n", nameOfVisualClass(visual_class), nameOfVisualClass(visual->class)); } } } /* if we're in slideshow mode and the user told us to fit the colormap, * free it here. */ if (ViewportWin) { if (fit) { XDestroyWindow(disp, ImageWindow); ImageWindow= 0; ImageColormap= 0; } /* for the 1st image we display we can use the default cmap. subsequent * images use a private colormap (unless they're bitmaps) so we don't get * color erosion when switching images. */ else if (!BITMAPP(image)) private_cmap= 1; } if (! (ximageinfo= imageToXImage(disp, scrn, visual, depth, image, private_cmap, fit, verbose))) { fprintf(stderr, "Cannot convert Image to XImage\n"); exit(1); } swa_view.background_pixel= WhitePixel(disp,scrn); swa_view.backing_store= NotUseful; swa_view.cursor= XCreateFontCursor(disp, XC_watch); swa_view.event_mask= ButtonPressMask | Button1MotionMask | KeyPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask; swa_view.save_under= False; classhint.res_class = "Xloadimage"; classhint.res_name = "xloadimage"; if (!ViewportWin) { ViewportWin= XCreateWindow(disp, RootWindow(disp, scrn), winx, winy, winwidth, winheight, 0, DefaultDepth(disp, scrn), InputOutput, DefaultVisual(disp, scrn), CWBackingStore | CWBackPixel | CWCursor | CWEventMask | CWSaveUnder, &swa_view); oldimagewindow= 0; XSetCommand(disp, ViewportWin, argv, argc); XSetClassHint(disp,ViewportWin,&classhint); proto_atom = XInternAtom(disp, "WM_PROTOCOLS", False); delete_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False); if ((proto_atom != None) && (delete_atom != None)) XChangeProperty(disp, ViewportWin, proto_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&delete_atom, 1); paint= 0; } else { oldimagewindow= ImageWindow; oldcmap= ImageColormap; paint= 1; } /* create image window */ swa_img.bit_gravity= NorthWestGravity; swa_img.save_under= False; swa_img.colormap= ximageinfo->cmap; swa_img.border_pixel= 0; ImageWindow= XCreateWindow(disp, ViewportWin, winx, winy, image->width, image->height, 0, ximageinfo->depth, InputOutput, visual, CWBitGravity | CWColormap | CWSaveUnder | CWBorderPixel, &swa_img); ImageColormap= ximageinfo->cmap; XSetCommand(disp, ImageWindow, argv, argc); XSetClassHint(disp,ImageWindow,&classhint); /* decide how we're going to handle repaints. we have three modes: * use backing-store, use background pixmap, and use exposures. * if the server supports backing-store, we enable it and use it. * this really helps servers which are memory constrained. if the * server does not have backing-store, we try to send the image to * a pixmap and use that as backing-store. if that fails, we use * exposures to blit the image (which is ugly but it works). * * the "use_pixmap" flag forces background pixmap mode, which may * improve performance. */ ximageinfo->drawable= ImageWindow; if ((DoesBackingStore(ScreenOfDisplay(disp,scrn)) == NotUseful) || getOption(global_options, PIXMAP)) { if (((pixmap= ximageToPixmap(disp, ImageWindow, ximageinfo)) == None) && verbose) printf(" Cannot create image in server, repaints will be ugly!\n"); } /* build window attributes for the image window */ wa_mask_img= 0; if (pixmap == None) { /* No pixmap. Must paint over the wire. Ask for BackingStore * to cut down on the painting. But, ask for Exposures so we can * paint both viewables and backingstore. */ swa_img.background_pixel= WhitePixel(disp,scrn); wa_mask_img |= CWBackPixel; swa_img.event_mask= ExposureMask; wa_mask_img |= CWEventMask; swa_img.backing_store= WhenMapped; wa_mask_img |= CWBackingStore; } else { /* we have a pixmap so tile the window. to move the image we only * have to move the window and the server should do the rest. */ swa_img.background_pixmap= pixmap; wa_mask_img |= CWBackPixmap; swa_img.event_mask= 0; /* no exposures please */ wa_mask_img |= CWEventMask; swa_img.backing_store= NotUseful; wa_mask_img |= CWBackingStore; } XChangeWindowAttributes(disp, ImageWindow, wa_mask_img, &swa_img); if (image->title) XStoreName(disp, ViewportWin, image->title); else XStoreName(disp, ViewportWin, "Unnamed"); XSetIconName(disp, ViewportWin, iconName(image->title)); sh.width= winwidth; sh.height= winheight; if (fullscreen) { sh.min_width= sh.max_width= winwidth; sh.min_height= sh.max_height= winheight; } else { sh.min_width= 1; sh.min_height= 1; sh.max_width= image->width; sh.max_height= image->height; } sh.width_inc= 1; sh.height_inc= 1; sh.flags= PMinSize | PMaxSize | PResizeInc; if (lastx || fullscreen) sh.flags |= USSize; else sh.flags |= PSize; if (fullscreen) { sh.x= sh.y= 0; sh.flags |= USPosition; } else if (winx || winy) { sh.x= winx; sh.y= winy; sh.flags |= USPosition; } XSetNormalHints(disp, ViewportWin, &sh); sh.min_width= sh.max_width; sh.min_height= sh.max_height; XSetNormalHints(disp, ImageWindow, &sh); /* Image doesn't shrink */ wmh.input= True; wmh.flags= InputHint; XSetWMHints(disp, ViewportWin, &wmh); setViewportColormap(disp, scrn, visual); /* map windows and clean up old window if there was one. */ XMapWindow(disp, ImageWindow); XMapWindow(disp, ViewportWin); if (oldimagewindow) { if (oldcmap && (oldcmap != DefaultColormap(disp, scrn))) XFreeColormap(disp, oldcmap); XDestroyWindow(disp, oldimagewindow); } /* start displaying image */ placeImage(disp, image->width, image->height, winwidth, winheight, &pixx, &pixy); if (paint) { if ((winwidth != old_width) || (winheight != old_height)) { XResizeWindow(disp, ViewportWin, winwidth, winheight); } XResizeWindow(disp, ImageWindow, image->width, image->height); /* Clear the image window. Ask for exposure if there is no tile. */ XClearArea(disp, ImageWindow, 0, 0, 0, 0, (pixmap == None)); } old_width= winwidth; old_height= winheight; /* flush output. this is so that -delay will be close to what was * asked for (i.e., do the flushing of output outside of the loop). */ XSync(disp,False); setCursor(disp, ViewportWin, image->width, image->height, winwidth, winheight, &(swa_view.cursor)); lastx= lasty= -1; if (delay) { /* reset alarm to -delay seconds after every event */ #ifdef ENABLE_TIMEOUT AlarmWentOff = 0; signal(SIGALRM, delayAlarmHandler); alarm(delay); #endif /* ENABLE_TIMEOUT */ } for (;;) { #ifdef ENABLE_TIMEOUT if (delay) { if (!getNextEventWithTimeout(disp, &event.event)) { Cursor cursor= swa_view.cursor; /* timeout expired. clean up and exit. */ swa_view.cursor= XCreateFontCursor(disp, XC_watch); XChangeWindowAttributes(disp, ImageWindow, CWCursor, &swa_view); XFreeCursor(disp, cursor); XFlush(disp); cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, ximageinfo); return('n'); } } else #endif /* ENABLE_TIMEOUT */ XNextEvent(disp, &event.event); switch (event.any.type) { case ButtonPress: if (event.button.button == 1) { lastx= event.button.x; lasty= event.button.y; break; } break; case KeyPress: { char buf[128]; KeySym ks; XComposeStatus status; char ret; Cursor cursor; if (XLookupString(&event.key,buf,128,&ks,&status) != 1) break; ret= buf[0]; if (isupper(ret)) ret= tolower(ret); switch (ret) { case ' ': case 'n': case 'p': case '<': case '>': if (delay) alarm(0); cursor= swa_view.cursor; swa_view.cursor= XCreateFontCursor(disp, XC_watch); XChangeWindowAttributes(disp, ViewportWin, CWCursor, &swa_view); XFreeCursor(disp, cursor); XFlush(disp); cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, ximageinfo); return(ret); case '\003': /* ^C */ case 'q': if (delay) alarm(0); cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, ximageinfo); return(ret); } break; } case MotionNotify: if ((image->width <= winwidth) && (image->height <= winheight)) break; /* we're AT&T */ mousex= event.button.x; mousey= event.button.y; /*XSync(disp, False); */ while (XCheckTypedEvent(disp, MotionNotify, (XEvent*)&event) == True) { mousex= event.button.x; mousey= event.button.y; } pixx -= (lastx - mousex); pixy -= (lasty - mousey); lastx= mousex; lasty= mousey; placeImage(disp, image->width, image->height, winwidth, winheight, &pixx, &pixy); break; case ConfigureNotify: winwidth= old_width= event.configure.width; winheight= old_height= event.configure.height; placeImage(disp, image->width, image->height, winwidth, winheight, &pixx, &pixy); /* configure the cursor to indicate which directions we can drag */ setCursor(disp, ViewportWin, image->width, image->height, winwidth, winheight, &(swa_view.cursor)); break; case DestroyNotify: cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, ximageinfo); return('\0'); case Expose: blitImage(ximageinfo, image->width, image->height, event.expose.x, event.expose.y, event.expose.width, event.expose.height); break; case EnterNotify: if (install) XInstallColormap(disp, ximageinfo->cmap); break; case LeaveNotify: if (install) XUninstallColormap(disp, ximageinfo->cmap); break; case ClientMessage: /* if we get a client message for the viewport window which has the * value of the delete atom, it means the window manager wants us to * die. */ if ((event.message.window == ViewportWin) && (event.message.data.l[0] == delete_atom)) { cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, ximageinfo); return('q'); } break; } } } under= False; swa_img.colormap= ximageinfo->cmap; swa_img.border_pixel= 0; ImageWindow= XCreateWindow(disp, ViewportWin, winx, winy, image->width, image->height, 0, ximageinfo->depth, InputOutput, visual, CWBitGravity | CWColormap | CWSaveUnder | CWBorderPixel, &swa_img); ImageColormap= ximageinfo->cmap; XSetCommand(disp, ImageWindowxloadimage.4.1/xloadimage.c 664 221 144 35601 5466457442 11063 /* xloadimage.c: * * generic image loader for X11 * * jim frost 09.27.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xloadimage.h" #ifdef VMS #include "patchlevel." #define NO_FORK #else #include "patchlevel" #endif #include extern double atof(); char *ProgramName= "xloadimage"; /* if an image loader needs to have our display and screen, it will get * them from here. this is done to keep most of the image routines * clean */ Display *Disp= NULL; int Scrn= 0; /* used for the -default option. this is the root weave bitmap with * the bits in the order that xloadimage likes. */ #define root_weave_width 4 #define root_weave_height 4 static byte root_weave_bits[] = { 0xe0, 0xb0, 0xd0, 0x70 }; static Image *doProcessOnImage(image, option, verbose) Image *image; Option *option; { Image *retimage= image; XColor xcolor; /* color for foreground/background */ switch (option->type) { case BACKGROUND: if (image->depth > 1) break; XParseColor(Disp, DefaultColormap(Disp, Scrn), option->info.background, &xcolor); image->rgb.red[0]= xcolor.red; image->rgb.green[0]= xcolor.green; image->rgb.blue[0]= xcolor.blue; break; case BRIGHT: brighten(image, option->info.bright, verbose); break; case CLIP: retimage= clip(image, option->info.clip.x, option->info.clip.y, option->info.clip.w, option->info.clip.h, verbose); break; case COLORS: retimage= reduce(image, option->info.colors, verbose); break; case DITHER: retimage= dither(image, verbose); break; case FOREGROUND: if (image->depth > 1) break; XParseColor(Disp, DefaultColormap(Disp, Scrn), option->info.foreground, &xcolor); image->rgb.red[1]= xcolor.red; image->rgb.green[1]= xcolor.green; image->rgb.blue[1]= xcolor.blue; break; case GAMMA: gammacorrect(image, option->info.gamma, verbose); break; case GRAY: if (BITMAPP(image)) retimage= undither(image, verbose); else gray(image, verbose); break; case HALFTONE: retimage= halftone(image, verbose); break; case NORMALIZE: retimage= normalize(image, verbose); break; case ROTATE: retimage= rotate(image, option->info.rotate, verbose); break; case SMOOTH: retimage= smooth(image, 1, verbose); break; case TITLE: if (image->title) lfree((byte *)image->title); image->title= dupString(option->info.title); break; case ZOOM: retimage= zoom(image, option->info.zoom.x, option->info.zoom.y, verbose); break; } return(retimage); } /* process a list of options on an image */ static Image *processImage(image, global_options, image_options) Image *image; OptionSet *global_options; OptionSet *image_options; { Option *opt; Image *tmpimage; unsigned int verbose; verbose= (getOption(global_options, VERBOSE) != NULL); /* go through the global options and process them */ for (opt= global_options->options; opt; opt= opt->next) { /* if option already exists locally for this image, ignore it */ if (getOption(image_options, opt->type)) continue; tmpimage= doProcessOnImage(image, opt, verbose); if (tmpimage != image) { freeImage(image); image= tmpimage; } } /* go through local options */ for (opt= image_options->options; opt; opt= opt->next) { tmpimage= doProcessOnImage(image, opt, verbose); if (tmpimage != image) { freeImage(image); image= tmpimage; } } return(image); } /* the real thing */ main(argc, argv) int argc; char *argv[]; { Option *opt; char *dname; Image *dispimage; /* image that will be sent to the display */ Image *newimage; /* new image we're loading */ Image *tmpimage; Display *disp; /* display we're sending to */ int scrn; /* screen we're sending to */ char *border; /* name of border color */ XColor xcolor; /* color for border option */ OptionSet *global_options; /* set of global options */ OptionSet *image_options; /* set of image options */ OptionSet *optset, *tmpset; Option *dump; unsigned int fullscreen; unsigned int onroot; unsigned int verbose; unsigned int winwidth, winheight; /* geometry of image */ unsigned int shrinktofit; /* set up internal error handlers */ signal(SIGSEGV, internalError); signal(SIGBUS, internalError); signal(SIGFPE, internalError); signal(SIGILL, internalError); #if defined(_AIX) && defined(_IBMR2) /* the RS/6000 (AIX 3.1) has a new signal, SIGDANGER, which you get * when memory is exhausted. since malloc() can overcommit, it's a good * idea to trap this one. */ signal(SIGDANGER, memoryExhausted); #endif ProgramName= argv[0]; if (argc < 2) usage(); /* defaults and other initial settings. some of these depend on what * our name was when invoked. */ loadPathsAndExts(); processOptions(argc, argv, &global_options, &image_options); verbose= (getOption(global_options, VERBOSE) != NULL); /* if no images are specified and we're not setting the default root, * this invocation is a no-op */ if ((image_options->next == NULL) && (getOption(image_options, NAME) == NULL) && (getOption(global_options, DEFAULT) == NULL)) { fprintf(stderr, "%s: No images were specified.\n", argv[0]); usageHelp(); /* NOTREACHED */ } if (getOption(global_options, IDENTIFY)) { for (optset= image_options; optset; optset= optset->next) { if (opt= getOption(optset, NAME)) identifyImage(opt->info.name); } exit(0); } /* start talking to the display */ opt= getOption(global_options, DISPLAY); dname= (opt ? opt->info.display : NULL); if (! (Disp= disp= XOpenDisplay(dname))) { printf("%s: Cannot open display\n", XDisplayName(dname)); exit(1); } Scrn= scrn= DefaultScreen(disp); XSetErrorHandler(errorHandler); /* background ourselves if the user asked us to */ #ifndef NO_FORK if (getOption(global_options, FORK)) switch(fork()) { case -1: perror("fork"); /* FALLTHRU */ case 0: break; default: exit(0); } #endif /* !NO_FORK */ dispimage= NULL; onroot= (getOption(global_options, ONROOT) != NULL); fullscreen= (getOption(global_options, FULLSCREEN) != NULL); shrinktofit= (getOption(global_options, SHRINKTOFIT) != NULL); if (opt= getOption(global_options, GEOMETRY)) { winwidth= opt->info.geometry.w; winheight= opt->info.geometry.h; } else { winwidth= 0; winheight= 0; } /* find out if we're supposed to dump this silly thing */ dump= getOption(global_options, DUMP); if (!getOption(global_options, DEFAULT) && (dump || onroot) && (winwidth || winheight || getOption(image_options, CENTER) || getOption(image_options, AT) || fullscreen)) { if (!winwidth) winwidth= DisplayWidth(disp, scrn); if (!winheight) winheight= DisplayHeight(disp, scrn); opt= getOption(global_options, BORDER); border= (opt ? opt->info.border : NULL); if (border) XParseColor(disp, DefaultColormap(disp, scrn), border, &xcolor); else xcolor.red= xcolor.green= xcolor.blue = 65535; if (DefaultDepth(disp, scrn) == 1) { dispimage= newBitImage(winwidth, winheight); *(dispimage->rgb.red)= xcolor.red; *(dispimage->rgb.green)= xcolor.green; *(dispimage->rgb.blue)= xcolor.blue; if (xcolor.red || xcolor.blue || xcolor.green) { *(dispimage->rgb.red + 1)= 0; *(dispimage->rgb.green + 1)= 0; *(dispimage->rgb.blue + 1)= 0; } else { *(dispimage->rgb.red + 1)= 65535; *(dispimage->rgb.green + 1)= 65535; *(dispimage->rgb.blue + 1)= 65535; } fill(dispimage, 0, 0, winwidth, winheight, 0); } else { dispimage= newTrueImage(winwidth, winheight); dispimage->rgb.used= 1; fill(dispimage, 0, 0, winwidth, winheight, RGB_TO_TRUE(xcolor.red, xcolor.green, xcolor.blue)); } dispimage->title= dupString("Root Image"); } /* load in each named image */ for (optset= image_options; optset; optset= optset->next) { get_another_image: /* handle -default option. this creates a base image using the * default tile weave. */ if (getOption(image_options, DEFAULT)) { newimage= newBitImage(root_weave_width, root_weave_height); bcopy(root_weave_bits, newimage->data, ((root_weave_width / 8) + (root_weave_width % 8 ? 1 : 0)) * root_weave_height); } else if (! (opt= getOption(optset, NAME))) { /* this gets post-processing accomplished for -dump and -onroot. */ if (dispimage) dispimage= processImage(dispimage, global_options, optset); continue; } else if (! (newimage= loadImage(global_options, optset, opt->info.name, verbose))) continue; /* retitle the image if we were asked to */ if (opt= getOption(optset, TITLE)) { if (newimage->title) lfree((byte *)newimage->title); newimage->title= dupString(opt->info.title); } /* if this is the first image and we're putting it on the root window * in fullscreen mode, set the zoom factors and * location to something reasonable. */ if ((optset == image_options) && onroot && fullscreen && !getOption(optset, ZOOM) && !getOption(optset, AT) && !getOption(optset, CENTER)) { opt= newOption(ZOOM); if ((newimage->width > DisplayWidth(disp, scrn)) || (newimage->height > DisplayHeight(disp, scrn))) { opt->info.zoom.x= opt->info.zoom.y= (newimage->width - DisplayWidth(disp, scrn) > newimage->height - DisplayHeight(disp, scrn) ? (float)DisplayWidth(disp, scrn) / (float)newimage->width * 100.0 : (float)DisplayHeight(disp, scrn) / (float)newimage->height * 100.0); } else { opt->info.zoom.x= opt->info.zoom.y= (DisplayWidth(disp, scrn) - newimage->width < DisplayHeight(disp, scrn) - newimage->height ? (float)DisplayWidth(disp, scrn) / (float)newimage->width * 100.0 : (float)DisplayHeight(disp, scrn) / (float)newimage->height * 100.0); } addOption(optset, opt); opt= newOption(CENTER); addOption(optset, opt); } if ((optset == image_options) && shrinktofit && !onroot && !getOption(optset, ZOOM)) { opt= newOption(ZOOM); opt->info.zoom.x= opt->info.zoom.y= (newimage->width - (DisplayWidth(disp, scrn) * 0.9) > newimage->height - (DisplayHeight(disp, scrn) * 0.9) ? ((float)DisplayWidth(disp, scrn) * 0.9) / (float)newimage->width * 100.0 : ((float)DisplayHeight(disp, scrn) * 0.9) / (float)newimage->height * 100.0); addOption(optset, opt); } newimage= processImage(newimage, global_options, optset); /* handle -center */ if (dispimage && getOption(optset, CENTER)) { tmpimage= merge(dispimage, newimage, (int)(dispimage->width - newimage->width) / 2, (int)(dispimage->height - newimage->height) / 2, verbose); if (dispimage != tmpimage) { freeImage(dispimage); dispimage= tmpimage; } } /* merge onto previous image */ else if (dispimage) { if (! dispimage->title) dispimage->title= dupString(newimage->title); /* handle -at */ if (opt= getOption(optset, AT)) tmpimage= merge(dispimage, newimage, opt->info.at.x, opt->info.at.y, verbose); else tmpimage= merge(dispimage, newimage, 0, 0, verbose); if (dispimage != tmpimage) { freeImage(dispimage); dispimage= tmpimage; } freeImage(newimage); } else dispimage= newimage; /* if the user asked for tiling we tile the image now */ if (getOption(optset, TILE)) { if (!winwidth) winwidth= DisplayWidth(disp, scrn); if (!winheight) winheight= DisplayHeight(disp, scrn); dispimage= tile(newimage, 0, 0, winwidth, winheight, verbose); } /* if next image is to be merged onto this one, read it */ if (dump || onroot || (getOption(optset->next, MERGE))) continue; redisplay_in_window: switch(imageInWindow(disp, scrn, dispimage, global_options, optset, argc, argv, verbose)) { case '\0': /* window got nuked by someone */ XCloseDisplay(disp); exit(1); case '\003': case 'q': /* user quit */ cleanUpWindow(disp); XCloseDisplay(disp); exit(0); case ' ': case 'n': /* next image */ if (opt= getOption(optset->next, GOTO)) { char *tag= opt->info.go_to; for (tmpset= image_options; tmpset; tmpset= tmpset->next) { if ((opt= getOption(tmpset, NAME)) && !strcmp(tag, opt->info.name)) { optset= tmpset; freeImage(dispimage); dispimage= NULL; goto get_another_image; /* ick */ } } fprintf(stderr, "Target for -goto %s was not found\n", tag); } break; case 'p': /* previous image */ for (tmpset= image_options; tmpset && (tmpset->next != optset); tmpset= tmpset->next) /* EMPTY */ ; if (!tmpset) goto redisplay_in_window; /* ick */ optset= tmpset; goto get_another_image; /* ick */ case '<': if ((opt = getOption(optset,ZOOM)) == NULL) { opt= newOption(ZOOM); opt->info.zoom.x= opt->info.zoom.y= 50.0; addOption(optset, opt); } else { opt->info.zoom.x= opt->info.zoom.x ? opt->info.zoom.x * 0.5 : 50; opt->info.zoom.y= opt->info.zoom.y ? opt->info.zoom.y * 0.5 : 50; } tmpimage= dispimage; dispimage= zoom(dispimage, 50, 50, (getOption(global_options, VERBOSE) != NULL)); if (tmpimage != dispimage) free(tmpimage); goto redisplay_in_window; /* ick */ case '>': if ((opt = getOption(optset,ZOOM)) == NULL) { opt= newOption(ZOOM); opt->info.zoom.x= opt->info.zoom.y= 200.0; addOption(optset, opt); } else { opt->info.zoom.x= opt->info.zoom.x ? opt->info.zoom.x * 2.0 : 200; opt->info.zoom.y= opt->info.zoom.y ? opt->info.zoom.y * 2.0 : 200; } tmpimage= dispimage; dispimage= zoom(dispimage, 200, 200, (getOption(global_options, VERBOSE) != NULL)); if (tmpimage != dispimage) free(tmpimage); goto redisplay_in_window; /* ick */ } freeImage(dispimage); dispimage= NULL; } /* dump image into a NIFF file rather than displaying */ if (dump && dispimage) { for (optset= image_options; optset && optset->next; optset= optset->next) /* EMPTY */ ; if (opt= getOption(optset, NAME)) { if (dispimage->title) lfree((byte *)dispimage->title); dispimage->title= dupString(opt->info.title); } dumpImage(dispimage, dump->info.dump.type, dump->info.dump.file, verbose); freeImage(dispimage); dispimage= NULL; exit(0); } /* display image on root */ if (onroot && dispimage) imageOnRoot(disp, scrn, dispimage, global_options, verbose); /* shut down */ XCloseDisplay(disp); exit(0); } h || winheight || getOption(image_options, CENTER) || getOption(image_options, AT) || fullscreen)) { if (xloadimage.4.1/sample/ 775 221 144 0 5470014501 7730 xloadimage.4.1/sample/jimf.face 644 221 144 67366 5461577462 11646 FirstName: James LastName: Frost E-mail: jimf@centerline.com Telephone: 617-498-3254 Company: CenterLine Software Address1: 10 Fawcett Street Address2: CityStateZip: Cambridge, MA 02138 Date: Jun 13 1989 PicData: 108 128 8 Image: 96 128 8 6C7D83807A77706D7C8689827F8283827C6969747C7F736D6F5E59 645318000000000000083A4E5767706A6F6C66696D767A76737373 6F70736A6664676F6A6663545E6766666C707171706D675E60616C 7073746F6D6D5B61642E0000121B12140F0F0B0805010000000000 F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F1F8F8F8F8F8F8F7C99B 5D2F2218110E0F18193283CCDEF8F8F8F8F7F7F8F8F8F8F8F8F8F8 F8F8F8F4F2F8F8F8F8F5E8C9E8F8F4F5F8F8F8F8F8F8EDDFE5EEF8 F8F8F8F8F8F0DBE8EB6C1419566051514A44413D352F28241E1912 F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F4F8F8F8F8F8F8E26A2A21 1F271B140C0911281E2D82C4E2F8F7F8F8E8F4F8F8F8F8F8F8F8F8 F8F8F8E8F4F8F8F8F7F7DCCCE7F4F1F2F8F8F8F8F8F5DFD8E1F7F8 F8F8F8F8F8C1BBCEB6400615566053504B44434035312B241F1811 F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F5D4933E21171F 241F1B11090E1522372A53B3F0F2C8E4D8CCE8F8F8F8F8F8F8F8F8 F8F2CFD8EEF8F8F4F0EBCFC1D8E5EBF1F8F8F8F8F8E5CED4DFF4F8 F8F7F8F8DA5D38443B0C08195A5953504B44433E38322B241E1912 F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8CF874328272D1E171C 211E150F090F18212519213873853D5A5D50669CD8F7F8F8F8F8F8 F899475779899CA9AEAF9974809FB8CFEAF7F8F8F1C19F9CA8C5DA E4EAF1F29F2211191503061E5E5E51514B4B433D38342D27211B14 F8F8F8F8F8F8F8F8F8F8F8F8F8F7F8E4BC762E2825242D251B1821 1F1B11090B141C24171E182A37322B31342E343A44619BD7F2F8F8 BC321C2B2E2D2B3131312B27272E3543638FC1D5BB60342B2A3448 678FACA8470C14190F050B1B50514E504E4A433D35312B271C180F 9FA3C1C9BFD2DCDCCBA98A7F70533B38312F2B27212B271B141B21 1F170B09141C221419272E2B2B2F2E2F2E2B28242A2D344879B5B3 4E1F1E252222242221251F1E191B1921222A31403E281B1C191717 1E212B2205060F140302090F2D50544E4A4A44403A312F25211914 18171C21191C2D28272A22212A2B282F2F2E272A2D2818121B2421 1712091119241912181E2B3822272B2B2E323434271C212A31352D 1B1B282A2F2B2F2E2A27211F1F22211F1B1B1C1F1E211F1E1F1C18 1517180600060C090001090F314E5350504547403B2F2D27221B14 1111181918191F1E24241F1E2727282D2B2725271F191418251F19 0E0C0B171F1E1111171E282219222222272827242A2D2D25252212 0C1415191F1F221F211E181719181B1F2222221E19171519171218 1B1C140000060F010002081C445356514B47454138312D24211817 15141519181B191B1E1F1F222221272A2422211F18121824271F14 110B0E1E1F1714151F2124181F1F1F242224221C1B1C2A34311506 0E15181B1C1C1F1E1B1E17111719181515191B17110E1214140B09 0F11000000050500000311344E5653514E4A473B3B322E25211C15 17141812151517191917191B1E22252422241F1812142524241912 0F1215211819181B1F24191B1F1F1E211F1C1817171C1F22180B0C 1214191E1F1C1C1F1B191217171717151217140F0B0E0F110C090C 1206000000050200000621454E5353514E4844403D342D271F1C17 18151212141212141717151C1E21222124211817122228211E1415 1115211C1C19171B2118181E1C1B1E1C1B181414181F221E0B0811 171C1C1E1C1C1E1B1F1B14151715181412150F0B0C12120F0E0C0C 09000000050B0100000E354E59535151514A45403D352F28221C18 1414110F0F0E0F0F171719191E212122211B17141F2A251E191511 181B241B1C1F1F22181515140F121715181214121722210C060B12 1B1C1E1B1C1C1C1E181915171718151412150E0B0F120F0C0B0C0B 0000000002050000011B3A505B535451504D48443D38312A271E15 1715120E0F11111215181E1E1E241F1F1E1C17222B28211E1B1417 1E221E1F1E21221403080B05080B0F12121214191E22190809121B 1C1B1C1E1C1F1C18181B15141917141414120C0F0F0F0B0B030300 00000000020000000C283B3E4D535354544D4A433E3A322B251E18 11141111110E11121514191C1E1F211E1B181F2A2D27251B17151C 25211C1F211E0E0000000002060509110F1417171E1F0B0B11181E 1B1E211C221B18181919181717121415180F0E0E0C090600000000 00000008080000032A2F3540414E515353504D4A3E37372E272119 0B120E0E0C0E0E1215151C191E1F1F191B242D2B28252117171B27 21211F1F2411000000000000050609090F0F171C1E0B0B0F151C1F 1C1F1C1C1F1F1B1C1C19141515151214150C09090B030000000000 00000008060306183E3A2F3532455451564E4D45403A342D272119 0212110C09090F0E1215171C1B1E1B1B24282A25271F1815182124 1F2222241800000000000000000103090F12191F0F050E151E211E 211E1C1B1C1C181919141112151811120F09050803000000000000 0000010906031531453D2E312E374D51504E4D44403D352E25211B 000E120E0C060B111815181B1E1E1E1F25282524211E1B18222524 2125221F0000000000000000000001060F191B14080E141E1F1F1F 1F1E1F1C1C1B1B191C120F14181517120905060500000000000000 0000060F0E061831312D2E2E2F374E5351514B474137322B28211B 030B1812090B0E0F151718191E1E21252427251F1C1B1922272525 28252109000000000000000000000308141918090B121F2124241E 1F211C1E1C1C1E1C19121411151515110505050000000000000000 0003000000112F3A31222E2E323D4E5457564E474340352D28221E 080315140C0B0C111415181B1C191F242424211F1B1F242A272425 2A21120000050800000000000000060E17170B0C14192224212121 1F1E1E1C1C1E1E1B18121515141717080305010000000000000000 000000000C21353B32222B343A43505756565347433A35312A221F 0E0111170F0E0E0E111818191C1E212121211E1F22252827282422 24180C00050605000000000000000B18190C08121924271F1E1F21 1F1E1C1B1E191C1C19111514151712060202000000000000000000 0000000F2D353A382D2A383E47545B5651514B47433A38322A251E 1505091515110C0E12181C1B1C1C21211B1F222227272828222221 191500000306000000000000000815180E0F111B22252121211E1F 1F1F1E171E1E211C1917151518170C080200000000000000000000 00000B242B2A2B272738484A5054545353514B45443D382F2E2522 14090312180F110E0F121717191B1B1F1E1F1F2125282D2524211B 181400060503000000000000021219110E0E1B1E221F1F1C1C1E1F 1E1B18191E1F1B1C17181715120F06050000000000000000000000 010514191B222825283B53535459535051514E47413D38342F2A22 1509060617150E0F0E11111517191C1C1F1E1F2422252525211B1C 1901000609010000000000000F18140F0F181C1F1C1C1E1E1C1C19 1B1919171B1E1E1B17171715120B08000000000000000000000000 030E17181518222E384B5E59575A565154514B4B433E38352E2824 1F0B06030815120F0E0F111515191E1E1F211F212121211E1B1B1B 110000090600000000000011180E090C141F1F1814191B18181519 171817171B191B19171714120E0601000000000000000000000002 060B1719171F2E3D474E5953575653515051504D45433B34322824 2A110505060F141211110F14141915191E1C1C21211F1C181C1F15 0000060100000000000012170900030915181719242F3E4B505D60 594E3D271818191815141112080300000000000000000000000002 0517212A31373E43484D5051575759575753535348433E352F2D27 37210805060914110F1115141518191B1C1C1F211E19191B1C190C 00000000001E00000000030000000006122B4B6D8A9CA2ACB2BEC1 BEBBAB9066351714140F0C0B050000000000000000000000000306 112232383E44444448505156565A5959575A564D4D4440352F2F28 4A351505080909111211151715171B1E1B1B1E1F1C1B1C1C191505 000000002B745600000000000000000F477D9FB1B9C5CFD2D4D2D5 CECBC5BEAF924B150F0C0905000000000000000000000000030E18 2A373E45474B474E535456595757595B595956534D47403D372F2A 5144220C05090B0B0E121215151518191C1E1F1F18191E1C191200 000000002F690B0000000006060C1119255D9CB6BEB8B8BFB9B3AE ABA8A2A0ABAF953B0E09050500000000000000000000000211242E 4140474D4B4E565A575759575A5A5B5A5B575A544D4A403A372F28 5A513817080909090E141412141717191C1E1F1B1E1C1917150600 0000000000000000000F3554564A4432352F4B86A0B2B9BEBCB1AE ACA5A5A099A0AB741706050000000000000000000000031225313E 534D4D4A475056565457575A575B595D5B5757544E4A433B38312A 56534A2A0F090906080E1412141415181E21211E1B1C18180F0000 00000000000000083180BCD4CFBEA37D695B434B96A8B9BCBBB3B1 A8A69F9C9892A59D350501000000000000000000000314282A2B48 534B48474B5654535754575D59595B59575D56544E45443D372D2B 5B564E41210E0B0908090F121214181B1C1F211B1C181812000000 0000000000001B56B5E1F5EADFD7C9B99F877140699BABB3BBBFC4 BEBEBBB3A69295A557050000000000000000000000021B32252A4B 4D4A454A4D535753565457575D5A5A595D5657534E4A453D372F2B 6363594B3A180E0B080B0F151415171C1F211F1B19181B01000000 0000000001287ADFF8F8F4F1EDEADBD1C29C8D6C5A8AA8BEC8BFA2 8A767A8596A08D9F5E00000000000000000000000003273B1F2E4A 504B4D4B515356545659595B5A5D5B5B5D5B56515048453E3A322B 535A594B472E1511090C09111818181B1E1E1E1C1B190500000000 000000032F82E7F8F7F8F8F5EEEBE5D8C8AE988356797F836F5B45 2E2725323D7192925000000000000000000000000005252E1C2E51 514B4D4D515354535453575A5A5D5E5D5B5956514E47434038342B 15485345433E1F0F0B09080C151819191F1F1C1C180C0000000000 0000002E82E1F4F8F8F8F8F7F7EDE4DFC8AB7D663A4D4E504D4340 3A3B382A28458A862D0000000000000000000000000924281B2D54 534A4B53535459535656595A5B5D605D5D5B5954534A453E37322A 001547484A3B2A120B09090B0F181B1B1B1C1B140B000000000000 00002470CBEEF8F8F8F8F8F8F8F4E1BC8C67594B3E43484B474340 434B5448312F76700900000000000000000000000005212A1F2F53 53485054535657575457575B5B5D605D5B5B5754534D47403B342E 01000E3E4E402D12060906090E121C191717140800000000000000 000F54B3F0F8F8F8F8F8F8F8E7BF99836D6153473E444A48434141 4850565347324850050B000000000000000000000002242A243254 514B545453545757575459595B5B5B5B5B5B5957514B47413B342E 190100062F352517060505060C0F151715170B0000000000000000 003AA5E2F8F8F8F8F8F8EEC4A092867A7361594E474B4A48414744 4D5351534D412F321C090000000000000000000000021F2D223E59 534E565751595A5759595A5B5B5D5D5E5D5B5657544D4845403832 371B06020019221403000100030C0E121409000000000000000000 027AC5EAF2F8F8F7F0C4A89B9990897D736D5E545153504D474745 4B4B4543433E352725030000000000000000000000001F3124485B 57505353575B575B565A595B5B5E63605A5B5B5959534B47413D32 6744250E0000020C0B000000000508060000000000000000000000 31AEF0F8F8F1DEBE9F999696908F8780796C645B56505047433835 312F272A2E3131270B000000000000000000000000001E2B2D565E 595156575A5759595B5B595D5D5E606161605B5A57514D47433D35 7A74532D1406000003050000000000000000000000000000000000 77CFF2EEDFBE9995908A92968F877F766D615D534A444131282119 140E0B0B111822241B0000000000000000000000000018272E5060 575650575B575B5A5A5A5E5B5E5E606360605D5B59565048413D34 7C797359321B0B000003060000000000000000000000000000002D A9D1D5BCA0908D8A8F8D93908C7D736A5953453E34271B140C0300 000000000001081521060000000000000000000000001128354D5D 5E4E505A575D5D605A5E5D5B635E6363615E615A5D544E4A453D32 7F7C7A715A3D21110000000000000000000000000000000000005E 999F928C898F908690928F8A7C77696056473A2718110803000000 00000000000000000905000000000000000000000000092445485B 5B534B5A5B5E5B60605E5E616164616466635D6059545348453D38 7F8079766F5E48270F000000000000000E0000000000000000005A 676D7A8285898A8C928D837F796A6357472E1B0F06000000000000 000000000000020505080600000000000000000000000222454A57 59514759605E60605D615E5D6363666666615E5E5B59514D473E38 827D7C7974736A4D2809000000000014090000000000000000003E 53607380838787898C86827C70635A432515080200000003020000 0001050F1C253137403D3D372B190000000000000000001F444850 5B51445A6060636463605E606667676969646360605B574E4D413D 827F7D7C7977736950170000000000000000000000000000000B34 435D717977838985827F7D7667563E25110601030506060506080B 14192B3141506169696461645D4E38180000000000000018454A50 5A54435661616466646161636766666A696961615E5A59514D443D 82827F7D7F7D736A531C0000000000000000000000000000000327 375769737D7D82807F7C7469543A1C0C060305080B0E111518212F 3A434553697983878A82808083775E471F0000000000000E455154 61574459636164666464636167676A6967696663615E59574D4740 83827D7D7C79716638210201000000000000000000000000000518 3254666F76767A7A7C76695131150B0306080912181C2535384853 606369778598A3ABACA0A3A2958979614D2400000000000B3B5B59 6154445E636463666664616466696A6769696764615B5B544B453E 8682827C7C7C70672E2B12170E0100000000000000000000000011 2B4A5E666F7073767A6C4A28110B06080B111B212A354854616D73 76797993A0B1B5BCC4B9B9AEA0958974645325000000000835595A 5D544861616464676666646767646769696769665E6059564D4841 83837A7F7A7A735E2B2D171B240C0000000000000000000000000B 2745535E64676F736A4522120B050C11191F2D35435061717A7A7D 808392A3A9B6B9C1C2C2B5A9A0988F806F605625000000063B5454 57514E606063636366666669675969696D69676764615D56564844 8583827F807C7A632B281B17322801000000000000000000000005 223A505A5B676D6A431E12090B0E141F2B343B455366717A857C7C 8287909BA8B2B9BBB6B6ABA8A3999085716460512800000F405454 594E56636166666967676A6667666C6A6D6A6A6969635B5A534D43 89898782827C776D2B312705313511000000000000000000000000 1C384A545967663819120E0C0E18222F38404A5361747D83808282 7C8292989CA2AEB2B1AEACA59F96827A79676761512A001741575B 594B5963666669676C69676A696A6A6C6C6A706A69676159544B43 87878A83827D7C732E38310808351C000000000000000000000000 1C35434D5D60371C110E0C121824343D434D57616C7C80858F8A82 85838C939998989999959299938A796F7A6D6C70664E2A1F405B57 5159646767676A6A6C69696766696D6F706F6D6D6967645E544D45 8987868383827A793D34382100111B000000000000000000000000 1B2F434D5B3D19110F0F1217252F3A47575B676A7680898D8D877C 8C909390939090938C8785898A877F7F76736C7076644B3A4B5653 535E666464696A67676A6C696A6A6D70716C6F6C6A696660574B47 868686868583837A50324431080005000000000000000000000000 182F40534721150C120F17252F3747595E636C737C898C8F909693 8D8D8D8F9290958F897F7F80838682827C6F6A737A775E4E515356 5D63666666696964666A6A6C6A6C6D716F6F6C6A6766665A575048 878A87878386807A663753401C0000000000000000000000000000 172B434D2A180F1212171F2D384456606A697077828A9299A5A59D 8F908D8D96969692837F7F80838D8A86767471777F8073594E565B 676964636C6667696D6C6A696C6A6F7071706D6C696764615A4E4B 898C898C8985827D713A3E5B371200000000000000000000000000 172D41371B150F15151C2A3747515E63646A7077858F989C9DA3A0 93938A8F959D9DA09F9DA0A098938680797A858786897A63535D63 666767696D6A696D6C6C6C6D6D6C7073777170706C6961635B534B 8D8F908D89878680795A284A532E06000000000000000000000000 152F3D2A171115171B22343B4B566463616771778292959586858A 827D76767C838F989B999898988A7D706C73858C898A836A575B66 676C696F6F6D706D6F6D6D6F6F707074737473706F6D69635D564B 90928F96908D86827D6F4024454A25000000000000000000000000 19323524140F1919222A3D474D5B6061676A767A838C8D8C7F5431 2B27282D2E3445504E4D5456513D31252A3E567182858573595769 676A6C6F706C736D706F707070707071767671706F6C64635D544E 93959592928C8A8680776431283235220000000000000000000000 1E2F2F190C121B1F243240484D5D606369707780838A929389745E 535B6A6D67696467696771746A5648474E4A486D7D7D7A735E5463 6D6F6D6F6D706F6F6D6C706F706F7173737473716D6D6A645A5650 9592989593928985857C71572A1822220C00000000000000000001 1B322D1709171F1E2B3544454B575E676A73768089939696989089 85868F9298A0A6A09FA0A2AEAB9686837366646D807D767161515D 73737071717370706F6D6C7071706F707174737373707167615650 9595939390908983827D776D561C000F1B00000000000000000000 1C312A140C181F242B3A404145535E646A6F7C838F969B9FA69F9B 999B95A0A6A8A8ABB3B9A8A6AFAC988D7A746F707477767669575A 737671747173716D6D6A6D6D71706F6F7074717373736F69615A51 999692938F908A85827C7A76634711000308000000000000000000 1E2F24110B1C212A323A3D3A445661666C73838A96989BA0A8AEA9 A6A6A3A5A5A59DA0A8A69D9CA5A59382807C737173777D80766954 697470737170736C706F706D71707070717774777474716A615D53 9695958D8F8F8D877F7D7A797666450B0000000000000000000000 1C2A220C0C1E252D3238373D4356606D707C8C9099A2A8A6AEB5B5 B3B5B3AEAB9C8C92999D8A869093827F8683807A8585878D897963 697A736F737073737170717070716F71717473747373706C636056 939393928D8C898C7D7A7A76796F540F0000000000000000000000 19241C091221252F373535374759666C79858A96A09DAEB6BCB8B6 B3B3B3B3A598897D7A7A6D696F7166707D807F8390999F99908774 6C7A76737373737371706D6D6F7070707373737771716F69665D54 959598938C87827D777674736F6945140000000000000000000000 141C1509191F28343432323750667074808F96A6A8ACBCC5C2BFB9 ACA8A99D7D5D434A5B5945353E47383D5E747C8D9BACAFA99F9380 6F76797A7473747374746D6D6D70717477777673716D6F6A635E57 999892929285797369606363676332150000000000000000000000 000000051C242D3434312E3D576C79838C939DA8B1BFCCD2D2CEBE A8A59F6A40484A24181B172B3A3B2A062561809BAEB6B9B5A89B85 717A7977737673767473706F707073747374747373706D6C69635B 9D9B9698908C7D705D47484E505324120000000000000000000000 0000000F21252D342E2E31445D73838992959DA8B2BECCD7D7D7C9 AFA599505473807C6751505D6C796A4B56748AAEB9BBBCB3A99882 717F7C777671747473716D6F6F6D7476797976797670736D6A605B 9B9C9C99928F8A7C665034343A310C01000000000000000000002E 5057443724272A2B2D2D3A4B63768A9395999BA2B3BCCBCFCED4CC C4B8A360576F8589827F80879DAFA6867A7FA2B9BBBCB2AFA3907A 707F7C7A767473717374717074707677777679797777706D6C635E 9C9B9B9B99968D867961442A1F1100000000000000000000094E61 6A70663E2525282B282D3D51677A8F999FA3A3A6AFB1BFBCC1C4C2 C5C2BB865B66747C7C8698A9C9CEB69B8587B6B6B3B1B1A999877A 73807F7777767674747371747373767677797779777773716C6760 9F9C9F9F96958F857D6F5E441E00000000000000000000033E5963 69665B3E2221252B2D3244576D7D929DA9AEB3B3B1B2B2B8B6B5B6 B5BCBCA37666676977879CA5B1B6A8928298A8A9ACAEAEA290867F 71827D79797374747773767377767A76797A797A7A7676736C6761 9D9C999B99959287827764563506000000000000000000383B5A7D 7359513A1E1922272E3B505E748795A8B2B2B6BFBFBEB8AFACA8AB ABABA99D8F76706F798D99A2A3A09D857F939C9F9D9FA09D998979 76837F777676717673777773747679767C797C797A79767371665E 9C999C9999968F8A897A6C5944220000000000000000253E3D6D89 562841210903192832445A697A909BACB6BBAFAFB8B6B8B6B5A9A9 A5A39C95867F7A747A8DA2A8ACA590797F8F9C9C999690958F8777 777D7F7C79737676747773777479767A7A7A7D7A797677766C6961 9F9C999D9C98908F8C7F6750412F00000000000000003145483E4D 2B21220000001228374B61778293A2ACB1B3ABA8AFAEACABABACAC A9A5958F877D7D7C7C8DA0B3B2A57C74828C877F76768283827D79 717F7A79767776767674767674747779797C7A7C79797979736964 A09D9B999B9998958C7C6A56412D0000000000000000171C15182A 0F000C000000122740546C7D8695A3A8A9A3A09B908D8F95909896 9D9C8D7D7D7A7A7C7C96B5BEB59C746C7467636A797473717C7A76 747F7F807C7C7773777774767776797C7A7D807C7F7C7A77736D64 A0999D9B9B9B99938F87714D3D0F00000000000000030000000000 0000000000000B2A435770808C98A2A8A89C8C857776797C747A7F 807474766D6D6F707A96C1CBBB9D66676661595664706C63677476 5774777D7C7A7977767A76767976797C7C807F7C7F7D7C79736F67 A09D9F9D9D9C99928F877345370000000000000000000000000000 0000000000000225435D6F7F9098A3A29282776756565737244189 9379606971605B5A7399C4CFBF935153351F050C6D5E4331436167 14284474797A7A7C7676777676767A7D7F7D7D7D7F7F7C7D77706A A0999C9D9B9896958C8976442D0000000000000000000000000000 000000000000001843576D79858A8C83614843321E311200000061 BE905945574E444E6C9DC2CFBC80353400000000435A1500224D53 0000005D737A777A777A77797679797A7C7C8380837F807C747169 A29F9D9F9D9D98928F8D7D43180000000000000000000000000000 000000000000000E35566676767C705E45382F1909000000001748 9B512A2425252D4870A0C8D4B9771C0800000000090600092A4547 0000002F6A7D7C777A79777D7977767C7C7A7A7D7F7C7D7C767069 A3A39DA09F9D9896938D7D44020000000000000000000000000000 00000000000000012D4D5E696D675B4B41444544372D1809020619 191B1B22282B3551749CBCCBB38A4824181719242F3B404A51533A 0000000E577A7A79797C797779777776777A7C7A7C7F7C797A746C A5A0A2A0A09D9B96908A804B000000000000000000000000000000 0000000000000000113B565D605D53433E474E5D636A6F70717471 6A5D5141373845607C96B3BBAB937C54312B324D6671716F675727 000000003B797A7A767A79797C79777A7D797D7F807F7F7D79776D A3A2A2A0A59F9C998F8A8056000000000000000000000000000000 000000000000000000183B565E564E372B353E4A536A77807D746D 5A3E22151E344A6989A2B6BBB29D9076572E0C010C1F31352F2205 00000000317D7C7A7D7D7C79777C7A7A7F7F80837F7F8382797671 A6A3A59FA3A39D96928A8661000000000000000000000000000000 0000000000000000000518455A5A574E3A1C141522343E38250F00 0000000014456C899DB2BBC1B9AEA2876D56190000000000000000 000000002E7D7C79797C79797D77797A7C7D8082838782807F7371 A3A9A5A2A59F9D96928D8066000000000000000000000000000000 000000000000000000000635575B5E5E5343210E090E1206080000 050E22416992A3B1B6C5C8C8C2B9B2A08D896A442B12170F000000 00000000377C7C7D797D7979747A7A7A7C7D8383858583807D7774 A5A8A5A3A3A0A09692908566010000000000000000000000000000 000000000000000000000027515E6063665E5651482A1727344359 67778FB2C7D1CECCD5DFDCDFD4D4C7B9B6B8B1A6836D60482E3119 000000003D7F7F7C7A797F7C7C7A797A7F80828385838683807A74 A9ABA5A3A2A09D958F8A82660E0000000000000000000000000000 00000000000000000000001C515D63616764696D79736A768792A0 A9B2BBC7CFD4CCCBD7E2DFD7D1B2A693A5AFAB997A6D605B53571B 00000000407F7C7D7C777C7A777D7C7A7C7F828382868586807973 A9A8A6A3A29D99958F898670240000000000000000000000000000 00000000000000000000000B374D5A5E616469717686908D909C95 95958C969392AC8D8CA6A6A59B7F66577482806D5137283B454814 00000000487F797F7C7C7C7C7D79777A7D7F858583858986827976 A5A6A8A6A39B9992908C8277400000000000000000000000000000 0000000000000000000000000B1C2832475A636F768586898D7C70 7066645B5948515432405E6D644B502B3E4B4347250B151B1E0C03 00000000607C7A79777D7F7C7C7D7C7A7D7A7F8586878789837D74 A9A8A5A3A29D9B958F8C87805E0200000000000000000000000000 0000000000000000000000000619120809223E5969707476797763 594E453E2A25141719122844483A3B221F281C2201030301000000 0000000C6F7F7D777A7A7C777A7D797F7D80808585878787877F77 A6A6A9ABA29D98928F8D8683702D00000000000000000000000000 00000000000000000000000000111C1B0E08212D404334414E4E4E 4D4537241B1414120B0C0F242A1822121B210B0300000000000000 000000156D827A777D7A777A7A7F7A7D7C7F80808585878A86827A A8A5A8A6A69F9C9B98908A87806108000000000000000000000000 000000000000000000000000000617151102000B11171511152F41 3E342A190C0B1515150F080E1806110F1111080000000000000000 0000001766827F7A7A7974777A7A7C7C7F827D8285878987858079 A8A9A9ACA8A09C9C96938D8A85793B000000000000000000000000 000000000000000000000000000000000000000000000000000C24 2D2F1F1406030B12120F0B0B0908090B0C08020000000000000000 0000002B74827C797A7A79797979797A7D7F7F83868A8C8A89807C ABA9A9ABA8A39D9B9892898A857F6A150000000000000000000000 000000000000000000000000000000000000000000000000000002 171E180C09090C11090F0E0C020603050200000000000000000000 0000003573837C77737674797D797A7C7D7F8586868A8D8D878276 A9A9A6A6A6A59D9995958F8C87867C440000000000000000000000 000000000000000000000000000000000000000000000000000000 010E14050006090B000B0C03000300000000000000000000000000 00000144707C7D7A7A7777797A7A797A8083858A8C908A8C8A807C AEABA8A9A5A2A09696928F8C87867D6D1F00000000000000000000 000000000000000000000000000000000000000000000000000000 010108010000030500000300000000000000000000000000000000 0000054E7A807D7D7A7A7A7C7A7C7F7D8083868C8A8F8C8A878377 ABA9A6A6A5A29D9899958F8A8983807D4B02000000000000000000 000000000000000000000000000000000000000000000000000000 000002000000000000000000000000000000000000000000000000 00000F537D827F807A7D7C7A7C7C7C7D7F8787898C8F8C8D86827D AEABA6A3A8A39D98958F8F8A8685857F712E000000000000000000 000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000 00002263877F7D797C7C827D7F797A7A7F85858A8D8A8785837F79 AFACA9A5A5A39F9898928D8D878683837F631B0000000000000000 000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000 0002377987857D807F7D7D7A7A797C7D7F83838689868787828380 AFA8A9A8A3A59D999690938A89858986827A440300000000000000 000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000050F09 091F566D8286837F7D7C7D7C7A7A797F7F82828385858A87898785 B3AEA8A3A5A5A29892938F8A8A8786838079642A00000000000000 000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000208000000 0E253E6A8A9285807F7F7C7D7C80807F82807F828686898C908D87 B2B2AEA8A6A5A39B9592928C8A89857F7C7C745914000000000000 000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000060501000002 192E5B8A928C878585807F7D7F7C7D82827F838286898A8F92908A B1AFACA6A5A6A39B95938F8D87837F7D7D7D7A6C44090000000000 000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000E0C0000000000 1E5A8A9890938A878383828580807A7F7F7A8083858C8F93938F89 B3AFA9A9A9A9A39F988F8F86807F7C7A7A7F807964240000000000 000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000001120608000000000B 3E839D9B96908D8686828383837F80827D7D7F82858A8F8F928F89 B2B1ABAFA6A8A3A09C8F87837F807D7D7F7F807F774E1100000000 000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000030F0609000000000922 779B9B9D99908C8A86838382827D7F7A807D7F82868A8D8F8F8C89 B2B1AFABA8A5A29D9287828582808283838285827A662F08000000 000000000000000000000000000000000000000000000000000000 01000000000000001F11000000000000000F0E08030103010B1940 86999998968F8C878383838082807C807C7F828589868D8C8F8F87 B5B1AFACA5A69F9892878682858785898789878580705724030000 000000000000000000000000000000000000000000000002000001 000111171415060C172E0100000000000B12090503090F171E3169 909F9D9893928A8683838282807D82807F828387878D8C8F908C89 B6B5B5AEA6A09998928D8A898A8A8C8D8989878780767150170000 0000000000000000000000000000000100000000000000000C0000 0000050F120C0E141E2D0000000000000209030E121521222E6392 9B9D9B999690898983808082807D7F7F808585878C8D908F8D8C89 B8B5B2A9A3A0989395928D8D928D908F8C8F8D8D857F7C7F561C03 000000000000000000000001000000000000000000000301020300 140B01143D351C21212712000000000002030B121E272E2E4E8C9D A09D9D9B96908C838083858682827F838385868A8C9092928F8F8C B8B2AFA89F9D9B999596959290908F8D8F8C8D8D857C7D8587440E 02080503000000000000000002090000000000000000000B0C0301 03312F34596F2F2F341B110000000103030E1B25272E324D7A989F A29D9D9B99928C85837F8383858380808286878D9093928D908F8C B6B1ABA8A5A2A29C9D9B98959392908F8F8D8F8F8A827F898A701C 050102000000000000000000021519190B05090501000000111719 253E6070637A4D54212B09000109030617272F3B433D51809BA0A0 9DA09F9D9998908A85838386828083828686898F8D8F909592908A B2AFAFA8ABA8A6A29D9B9996938F9590908F908C8C837D86938956 190500000000000108020000060E0E1C25221E171B191B1114192A 4D76A59695514A610E22150B06060E1F32414443404E85999DA2A3 A3A0A09F9D96908D86868683838285838789898A8F8A909292908D B6AEAEAEABAEABA5A09B969390908F90908D8C8D8A83828795997D 481408060200000001080100000312191F24272A2D2825322F2E4B 7985BF9387541F3219483511152238474B4D4137507D9C9D9DA0A2 A0A09F9D9C938F878785827F808085858389868C8C8C9093928F8D B2B3B1AEB1ACACA8A09892908F8F92928D8F908D89857D86939FA0 7F3D1B120B0C0808090C0E0C0F050C19221C211F253D4D5960777A 98ABBB674D2A176C63835E50504B564E4D4D3D5376969DA0A09FA3 A09D9B9C98958F89858580838282868385898D8C898C909696938D B8B6B3B3AFB1A8A39C92908F898C8A8C8987878C8A807A85929FA9 9F7A4322171B190E0E121E1B1512000212241F253A435B8DA09DB5 D2ED9C5E210C126795BFB18A715E564E51545B79939C9F9C9D9D9B 9F9B9D9B99928D8986838383808686898C898A8D8C8C8D9292928D BBB3B8B5AEACA89F9C9595928D8A878987898A87857F7C83909BA8 AB9D773524242A2D2B2525272A2521181719273A4D80AEAC98B2B3 BFBC893E0F063876C1F8E2A97C5D505E53595E82999C9D9D9F9F9D 9DA09F9C99928F898982878083838386898A8D8D8D909093959393 BFB9B8B1B1ACABA89C9C968F8D8A8A8989898D8989837D808DA0A8 ABA2966A432F2F2E3A41403B48454143322D3B53638DACCBAB876D 60593B0C0C2248A2DCF4B3776D5D5D5A50646F969B9D9F9F9C9D9D A09D9DA29893938C89858382808286898A878F8F908F9295959090 C1C1BCB8B3AFA8A3A29F9693908F8C8C8C8C8F8C8A867D828C9FA9 AEACA58F765A414041445664677C7785897F73748A8790907F512E 0C0011121B458FE5F2DCB896826D64535A698A9DA0A0A09CA09DA0 A59FA0A09995958F8983827F7F8383878A8D8C8C8F909096969693 C4BCB8B9B3AEA9ACA5A09995908F8F8C8A8D8D8D8F8780808C9BAB B5AEA9A28D795D5044546C8390ACAC8D8D8D8F9FA3988A5457441E 1C1C1E3E579DE8F8F8F8DABEA3A6A39D98AEB1A5A2A0A0A09DA09D A5A0A0A09C969289868682827F868587898D8C8D8D929393959598 C2BFBBB5B2AEACA9A6A09999929292908C8F8F8C8C8980828D9DAB B3B2AFABA08C796959536383A8CCEBDBC8D2C8AE7A4D594D4E3D22 272E3D5E7FCEF8F8F8F8C98F7971718098A2A9A6A0A09CA2A0A2A2 A2A29F9D9D99908D83857D8080838587878C878F8F8F9296939399 C2BEBCB5B2B1AEABA6A39F9B9395908F8F908D8D8D8C82828F9DAC B6B6B1A8A29B8D867361576479ACF2F8F8F0DBC89B6C5E51515B54 4741547CACF8F8F8F8D7AE8070798FA2A3A0A5A2A6A2A29FA5A0A5 A3A5A39F9D96958C8683828582828687868D8C8F90929696989896 C2C1B9B6B3AFAFA9A59F9D9899928F908D8C8D8D8F8A857F8A99A8 B2B5ABA69F9B96968C7A6A5E7199D7EEEACEB3A88F737673747A77 7C908798C9F8F8F8F8C89D9B9DA6ABACA9A8A6A5A5A3A39D9FA3A2 A5A6A39F9C98958F8C85838283878A85898D8F909295939B9B9B99 C4BEBBBBB3B1ACACA5A09F9999959290928C928D8F8C87828A98A6 ABACABA59D9B9695938A85807A77859CB1B2A695867A878F8A969F ABC4CFC4D2E2F7F1D2B8B3BBBCBFB3A9AEAFA9A5A39DA2A3A2A2A6 A8A5A59F9D99938C87878685838A89898D8D959592959F999D9C99 C5C1BEB9B8B3AEACA6A29F989695938F8C8D928D8F8C877F8592A3 AEAEA8A09D989B9995938D8D959092B8C2B9BBA09C9090868C929B A8BBCEC9D2DFDBC5BEB8B9B6B8B3B1ACAFAEAEA8A69FA0A2A3A2A3 A5A8A3A2A09C9392898685858387898A8A8F9292939696989B9B9C C8C1BBBCB6B3AFAEA3A2A39D9896928F8F928F9095908D828690A0 ABB1A6A09D9D9DA09CA0A09DA29DA3B1B5BBB1A3A3A2A28F8F9399 99A2ABAEACB6B3B9B6B3B1AFACAEAEABACA8A8ABA8A39FA2A2A2A6 A6A6A5A5A09F96908C8A858687868A8C8A8C8D939298999C9D9C9D C4BEBBB9B8B5AFA8A6A0A09F9998958D908F959393928A8385959D A9ACA8A29D9C9D9FA6A5A5A8ACAFB1AFA89C96A0B1B8A896969596 9699969BA0A8A9A9AEB1B3AFAFAEAFB2AEAEACA9A8A5A0A2A3A3A5 A3A6A5A8A09D98938A8C8786878987898D8A8F8D929598999BA29F C7C1BEB8B9B5AFACA8A39D9B9896928D8F8D96929695938686939B A8ABA69FA39C9CA3A5A5A8AEAEB8B6B2B1A99FA5A8A09C969B9998 9DA09C9B9FA2A8A9B1B2B1B1B1B2AEB2B1AEACA8A8A6A2A3A2A3A2 A6A9A5A2A099968F8C898785858A89898C90908F95989C9CA0A2A6 C5C1C1BEB8BBAFA9A6A2A09B999392908F8F909396938F8A87909C A8ABA69DA09BA0A0A6A5ACACB3B6BBB2B1A9A6A39F9C9D9B9B9DA3 AEAEA39D999DA3A5ACAEAEB1B1AEB1AEACACABA9A8A5A5A5A6A8A5 A5A5A0A29F9C98908A8986868989898D8A8C8D9095959C9DA3A2A5 C9BFC2BCBCB6B3ACABA6A09B96988D8F908F959395959087868999 A3ABA8A09F9FA0A5A3A5A8AEB1B3B2B2AEA6A6A0A5A29F9F9D9D9F A6AE9D999B9CA3ABABAFAFB1AFAFAFAEACA9AEABA9A9A5A8A3A6A9 A8A6A5A69FA09695908987868C8C8A8D8A8D8C9395969CA0A2A6A5 0001766827F7A7A7974777A7A7C7C7F827D8285878987858079 A8A9A9ACA8A09C9C96938D8A85793B000000000000000000000000 000000000000000000000000000000000000000000000000000C24 2D2F1F1406030B12120F0B0B0908090B0C08020000000000000000 0000002B74827C797A7A79797979797A7D7F7F83868A8C8A8xloadimage.4.1/jpeg/ 775 221 144 0 5470014510 7374 xloadimage.4.1/jpeg/CHANGELOG 644 221 144 13422 5340775672 10736 CHANGELOG for Independent JPEG Group's JPEG software Version 4A 18-Feb-93 -------------------- Substantial speedup for grayscale output from color JPEG file (suppress processing of chrominance components). Lesser speedups in Huffman decoding and in compression quantization. Can switch stdin/stdout to binary mode with either fdopen() or setmode(); this allows use of one-file command line style on a wider range of systems. Also added -outfile switch so that makefile test scripts don't have to depend on the command line style. New makefile.icc for Code Builder; makefile.sas is updated for SAS C 6.x. Hook added to allow surrounding application to read and write COM (comment) blocks. Bugfixes (DOS only): jmemdos.c code for accessing expanded memory only worked if struct fields are packed on byte boundaries. This is not true by default for Microsoft C. Furthermore, Microsoft C needs an _fheapmin() call to clean up the far heap correctly. Version 4 10-Dec-92 -------------------- Revised user interface: switches now use names instead of single letters. (Old switch letters are acceptable abbreviations of new switch names, EXCEPT for djpeg's old -g, -D, -1 switches.) cjpeg has several new switches. Provision for smoothing the input image added to cjpeg. This helps a lot with converting dithered GIFs to JPEG. Decoder upsampling now uses interpolation instead of pixel replication; this improves rendering of sharp colored edges. The decompressor will now try to continue after detecting an error in the compressed data, instead of just aborting. If the input file has restart markers, full synchronization will usually be regained at the next undamaged restart marker. (But you're still out of luck if any of the header markers are corrupt.) Substantial improvements in speed; DCT accuracy improved too. Numerous minor changes to improve portability. egetopt.c, which was by far the worst portability problem, is gone altogether. A few bugfixes, sigh (mostly affecting DOS implementations only). Bugfix: on DOS machines, cjpeg -o would fail on grayscale input files. Bugfix: one-pass quantization to more than 64 color levels would fail on 16-bit-int machines. This could only happen with quantized grayscale output. A couple of changes affect code that calls the JPEG subroutine library: 1. The parameter struct tag names are now capitalized (Compress_info_struct, Compress_methods_struct, Decompress_info_struct, Decompress_methods_struct, and External_methods_struct). This makes it easier to live with brain-damaged compilers with short identifier lengths. (All identifiers used in the JPEG code are now unique within the first 16 characters.) 2. If you are not calling jselerror(), you need to initialize three new fields in the emethods structure, typically as follows: e_methods.num_warnings = 0; /* no warnings emitted yet */ e_methods.first_warning_level = 0; /* display first corrupt-data warning */ e_methods.more_warning_level = 3; /* but suppress additional ones */ These fields control handling of corrupt-data warnings. Version 3 17-Mar-92 -------------------- Memory manager is finally capable of swapping to temp files. There are separate versions of jmemsys.c for no temp files (same behavior as older versions), simple temp files with or without tmpfile(), and a DOS-specific version (including special code for EMS and XMS). This is probably much more system-dependent than any of the older code; some bugs may surface here. Hooks added for user interface to install progress monitoring routine (percent-done bar, etc). See comments with dummy progress_monitor routines in jcdeflts.c, jddeflts.c. Two-pass color quantization (finally!). This is now the default method when quantizing; say '-1' to djpeg for quick-and-ugly 1-pass method. There is a test file for checking 2-pass quantization and GIF output. Fixed bug in jcopy_block_row that broke cjpeg -o option and djpeg -b option on MSDOS machines. Miscellaneous small speedups; notably, DCT computation rearranged so that GCC "inline" feature is no longer needed for good code quality. File config.c renamed ckconfig.c to avoid name conflict with /etc/config on Unix systems. Added example.c to document usage of JPEG subroutines better. Memory manager now knows how to release all storage during error exit --- avoids memory leak when using JPEG as subroutines. This implies a couple small changes to the subroutine interface: the old free_defaults subroutines are no longer needed, but if you have a replacement error_exit method then it must call the new free_all method. Also, jselvirtmem renamed to jselmemmgr. Code for reading Targa files with 32-bit pixels was incorrect. Colorspace conversion slightly faster and more accurate; because of this, old "test" files will no longer match bit-for-bit. Version 2 13-Dec-91 -------------------- Documentation improved a little --- there are man pages now. Installation instructions moved from README to a separate file SETUP. New program config.c is provided to help you get the configuration options right. This should make installation a lot more foolproof. Sense of djpeg -D switch reversed: dithering is now ON by default. RLE image file support added (thanks to Mike Lijewski). Targa image file support added (thanks to Lee Crocker). PPM input now accepts all PPM and PGM files. Bug fix: on machines where 'int' is 16 bits, high-Q-setting JPEG files were not decoded correctly. Numerous changes to improve portability. There should be few or no compiler warnings now. Makefiles cleaned up; defaults now appropriate for production use rather than debugging. Subroutine interface cleaned up. If you wrote code based on version 1's jcmain/jdmain, you'll need to change it, but it should get a little shorter and simpler. Version 1 7-Oct-91 -------------------- Initial public release. m_warnings = 0; /* no warnings emitted yet */ e_methods.first_warning_level = 0; /* display first corrupt-data warning */ e_methods.more_warning_level = 3; /* but suppress additional ones */ These fields control handling of corrupxloadimage.4.1/jpeg/Makefile 664 221 144 13230 5467535637 11170 # Makefile for Independent JPEG Group's software using the xloadimage # configuration information. This is loosely based on makefile.unix. include ../Make.conf include ../jpeg.conf CFLAGS= $(CC_OPT_FLAGS) $(JPEG_CC_FLAGS) # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. # In particular, on some versions of HP-UX (and probably other SysV-derived # systems) there is a faster alternate malloc(3) library that you can use # by adding "-lmalloc" to this line. LDLIBS= # miscellaneous OS-dependent stuff # linker LD= $(CC) # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.mms makefile.vms makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o # compression objectfiles CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \ jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \ jrdrle.o jrdtarga.o COBJECTS= jcmain.o $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.o jddeflts.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \ jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o jrdjfif.o \ jwrgif.o jwrppm.o jwrrle.o jwrtarga.o DOBJECTS= jdmain.o $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: ansi2knr libjpeg.a ansi2knr: ansi2knr.c $(CC) $(CFLAGS) -o ansi2knr ansi2knr.c cjpeg: ansi2knr $(COBJECTS) $(LD) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS) djpeg: ansi2knr $(DOBJECTS) $(LD) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS) # libjpeg.a is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.a: ansi2knr $(LIBOBJECTS) $(RM) libjpeg.a $(AR) libjpeg.a $(LIBOBJECTS) $(RANLIB) libjpeg.a #if there isn't a jmemsys, use the one most unix systems like jmemsys.c: $(CP) jmemnobs.c jmemsys.c clean: $(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core tmpansi.* testout.* *~ distribute: $(RM) jpegsrc.tar* tar cvf jpegsrc.tar $(DISTFILES) compress -v jpegsrc.tar test: cjpeg djpeg $(RM) testout.ppm testout.gif testout.jpg ./djpeg testorig.jpg >testout.ppm ./djpeg -gif testorig.jpg >testout.gif ./cjpeg testimg.ppm >testout.jpg cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.o : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.o : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.o : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h s of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefilxloadimage.4.1/jpeg/README 644 221 144 51441 5340776640 10403 The Independent JPEG Group's JPEG software ========================================== README for release 4A of 18-Feb-93 ================================== This distribution contains a BETA TEST release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. For installation instructions, see file SETUP. For usage instructions, see file USAGE (or the cjpeg.1 and djpeg.1 manual pages; but USAGE contains a "hints" section not found in the manual pages). Useful information can also be found in the JPEG FAQ (Frequently Asked Questions) article; see ARCHIVE LOCATIONS below to obtain the FAQ article. This software is still undergoing revision. Updated versions may be obtained by FTP or UUCP to UUNET and other archive sites; see ARCHIVE LOCATIONS below for details. Serious users of this software (particularly those incorporating it into larger programs) should contact jpeg-info@uunet.uu.net to be added to our electronic mailing list. Mailing list members are notified of updates and have a chance to participate in technical discussions, etc. This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Lee Crocker, George Phillips, Ge' Weijers, and other members of the Independent JPEG Group. DISCLAIMER ========== THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED. It is not guaranteed to be useful for anything, nor to be compatible with subsequent releases, nor to be an accurate implementation of the JPEG standard. (See LEGAL ISSUES for even more disclaimers.) Despite that, we believe that this software is pretty good, and if you find any problems with it, we'd like to know about them. Please report problems by e-mail to jpeg-info@uunet.uu.net. WHAT'S HERE =========== This distribution contains C software to implement JPEG image compression and decompression. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG is intended for compressing "real-world" scenes; cartoons and other non-realistic images are not its strong suit. JPEG is lossy, meaning that the output image is not necessarily identical to the input image. Hence you must not use JPEG if you have to have identical output bits. However, on typical images of real-world scenes, very good compression levels can be obtained with no visible change, and amazingly high compression levels are possible if you can tolerate a low-quality image. For more details, see the references, or just experiment with various compression settings. The software implements JPEG baseline and extended-sequential compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. For legal reasons, we are not distributing code for the arithmetic-coding process; see LEGAL ISSUES. At present we have made no provision for supporting the progressive, hierarchical, or lossless processes defined in the standard. In order to support file conversion and viewing software, we have included considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out if not required for a particular application. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, the software is not intended to be read as a tutorial on JPEG. (See the REFERENCES section for introductory material.) While we hope that the entire package will someday be industrial-strength code, much remains to be done in performance tuning and in improving the capabilities of individual modules. This software can be used on several levels: * As canned software for JPEG compression and decompression. Just edit the Makefile and configuration files as needed (see file SETUP), compile and go. Members of the Independent JPEG Group will improve the out-of-the-box functionality and speed as time goes on. * As the basis for other JPEG programs. For example, you could incorporate the decompressor into a general image viewing package by replacing the output module with write-to-screen functions. For an implementation on specific hardware, you might want to replace some of the inner loops with assembly code. For a non-command-line-driven system, you might want a different user interface. (Members of the group will be producing Macintosh and Amiga versions with more appropriate user interfaces, for example.) * As a toolkit for experimentation with JPEG and JPEG-like algorithms. Most of the individual decisions you might want to mess with are packaged up into separate modules. For example, the details of color-space conversion and subsampling techniques are each localized in one compressor and one decompressor module. You'd probably also want to extend the user interface to give you more detailed control over the JPEG compression parameters. In particular, we welcome the use of this software as a component of commercial products; no royalty is required. ARCHIVE LOCATIONS ================= [Version 4A is a beta-test release and will not be publicly archived. The following paragraphs refer to the most recent official release.] The "official" archive site for this software is ftp.uu.net (Internet address 137.39.1.9 or 192.48.96.9). The most recent released version can always be found there in directory graphics/jpeg. This particular version will be archived as jpegsrc.v4.tar.Z. If you are on the Internet, you can retrieve files from UUNET by anonymous FTP. If you don't have FTP access, UUNET's archives are also available via UUCP; contact postmaster@uunet.uu.net for information on retrieving files that way. Numerous Internet sites maintain copies of the UUNET files; in particular, you can probably find a copy at any site that archives comp.sources.misc submissions. However, only ftp.uu.net is guaranteed to have the latest official version. You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum (GO PICS), library 15; this version will be file jpsrc4.zip. Again, CompuServe is not guaranteed to have the very latest version. The JPEG FAQ (Frequently Asked Questions) article is a useful source of general information about JPEG. It is updated constantly and therefore is not included in this distribution. The FAQ is posted every two weeks to Usenet newsgroups comp.graphics, news.answers, and other groups. You can always obtain the latest version from the news.answers archive at rtfm.mit.edu (18.172.1.27). By FTP, fetch /pub/usenet/news.answers/jpeg-faq. If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu with body "send usenet/news.answers/jpeg-faq". SUPPORTING SOFTWARE =================== You will probably want Jef Poskanzer's PBMPLUS image software, which provides many useful operations on PPM-format image files. In particular, it can convert PPM images to and from a wide range of other formats. You can FTP this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). Unfortunately PBMPLUS is not nearly as portable as the JPEG software is; you are likely to have difficulty making it work on any non-Unix machine. If you are using X Windows you might want to use the xv or xloadimage viewers to save yourself the trouble of converting PPM to some other format. Both of these can be found in the contrib directory at export.lcs.mit.edu. Actually, xv version 2.00 and up incorporates our software and thus can read and write JPEG files directly. (NOTE: since xv internally reduces all images to 8 bits/pixel, a JPEG file written by xv will not be very high quality; and xv cannot fully exploit a 24-bit display. These problems are expected to go away in the next xv release, planned for early 1993. In the meantime, use xloadimage for 24-bit displays.) For DOS machines, Lee Crocker's free Piclab program is a useful companion to the JPEG software. The latest version, currently 1.91, is available by FTP from SIMTEL20 and its various mirror sites, file piclb191.zip. CompuServe also has it, in the same library as the JPEG software. SOFTWARE THAT'S NO HELP AT ALL ============================== Handmade Software's shareware PC program GIF2JPG produces files that are totally incompatible with our programs. They use a proprietary format that is an amalgam of GIF and JPEG representations. However, you can force GIF2JPG to produce compatible files with its -j switch, and their decompression program JPG2GIF can read our files (at least ones produced with our default option settings). Some commercial JPEG implementations are also incompatible as of this writing, especially programs released before summer 1991. The root of the problem is that the ISO JPEG committee failed to specify a concrete file format. Some vendors "filled in the blanks" on their own, creating proprietary formats that no one else could read. (For example, none of the early commercial JPEG implementations for the Macintosh were able to exchange compressed files.) The file format we have adopted is called JFIF (see REFERENCES). This format has been agreed to by a number of major commercial JPEG vendors, and we expect that it will become the de facto standard. JFIF is a minimal representation; work is also going forward to incorporate JPEG compression into the TIFF 6.0 standard, for use in "high end" applications that need to record a lot of additional data about an image. We intend to support TIFF 6.0 in the future. We hope that these two formats will be sufficient and that other, incompatible JPEG file formats will not proliferate. Indeed, part of the reason for developing and releasing this free software is to help force rapid convergence to de facto standards for JPEG file formats. SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or TIFF 6.0! USING JPEG AS A SUBROUTINE IN A LARGER PROGRAM ============================================== You can readily incorporate the JPEG compression and decompression routines in a larger program. The file example.c provides a skeleton of the interface routines you'll need for this purpose. Essentially, you replace jcmain.c (for compression) and/or jdmain.c (for decompression) with your own code. Note that the fewer JPEG options you allow the user to twiddle, the less code you need; all the default options are set up automatically. (Alternately, if you know a lot about JPEG or have a special application, you may want to twiddle the default options even more extensively than jcmain/jdmain do.) Most likely, you will want the uncompressed image to come from memory (for compression) or go to memory or the screen (for decompression). For this purpose you must provide image reading or writing routines that match the interface used by the image file I/O modules (jrdXXX or jwrXXX); again, example.c shows a skeleton of what is required. In this situation, you won't need any of the non-JPEG image file I/O modules used by cjpeg and djpeg. By default, any error detected inside the JPEG routines will cause a message to be printed on stderr, followed by exit(). You can override this behavior by supplying your own message-printing and/or error-exit routines; again, example.c shows how. We recommend you create libjpeg.a as shown in the Makefile, then link that with your surrounding program. (If your linker is at all reasonable, only the code you actually need will get loaded.) Include the files jconfig.h and jpegdata.h in C files that need to call the JPEG routines. CAUTION: some people have tried to compile JPEG and their surrounding code with different compilers, e.g., cc for JPEG and c++ or gcc for the rest. This is a Real Bad Move and you will deserve what happens to you if you try it. (Hint: the parameter structures can get laid out differently with no warning.) Read our "architecture" file for more info. If it seems to you that the software structure doesn't accommodate what you want to do, please contact the authors. Beginning with version 3, we will endeavor to hold the interface described by example.c constant, so that you can plug in updated versions of the JPEG code just by recompiling. However, we can't guarantee this, especially if you choose to twiddle any JPEG options not listed in example.c. Check the CHANGELOG when installing any new version, and compare example.c against the prior version. Recompile your calling software (don't just relink), as we may add or subtract fields in the parameter structures. REFERENCES ========== We highly recommend reading one or more of these references before trying to understand the innards of any JPEG software. The best short technical introduction to the JPEG compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PostScript file containing a revised version of the article is available at ftp.uu.net, graphics/jpeg/wallace.ps.Z. The file (actually a preprint for an article to appear in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, and it may not be used for commercial purposes. A somewhat less technical, more leisurely introduction to JPEG can be found in "The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and example C code for a multitude of compression methods including JPEG. It is an excellent source if you are comfortable reading C code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... A new textbook about JPEG is "JPEG Still Image Data Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95. This book includes the complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2). This is by far the most complete exposition of JPEG in existence, and I highly recommend it. If you read the entire book, you will probably know more about JPEG than I do. The JPEG standard itself is not available electronically; you must order a paper copy through ISO. (Unless you are concerned about having a certified official copy, I recommend buying the Pennebaker and Mitchell book instead; it's much cheaper and includes a great deal of useful explanatory material.) In the US, copies of the standard may be ordered from ANSI Sales at (212) 642-4900. It's not cheap: as of 1992, Part 1 is $95 and Part 2 is $47, plus 7% shipping/handling. The standard is divided into two parts, Part 1 being the actual specification, while Part 2 covers compliance testing methods. As of early 1992, Part 1 has Draft International Standard status. It is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document number ISO/IEC DIS 10918-1. Part 2 is still at Committee Draft status. It is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document number ISO/IEC CD 10918-2. (NOTE: I'm told that the final version of Part 2 will differ considerably from the CD draft.) The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, revision 1.02. A copy of the JFIF spec is available from: Literature Department C-Cube Microsystems, Inc. 399A West Trimble Road San Jose, CA 95131 (408) 944-6300 A PostScript version of this document is available at ftp.uu.net, file graphics/jpeg/jfif.ps.Z. It can also be obtained by e-mail from the C-Cube mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg" to the server to obtain the JFIF document; send the message "help" if you have trouble. The TIFF 6.0 file format specification can be obtained by FTP from sgi.com (192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed copy from Aldus Corp. at (206) 628-6593. It should be noted that the TIFF 6.0 spec of 3-June-92 has a number of serious problems in its JPEG features. A clarification note will probably be needed to ensure that TIFF JPEG files are compatible across different implementations. The IJG does not intend to support TIFF 6.0 until these problems are resolved. If you want to understand this implementation, start by reading the "architecture" documentation file. Please read "codingrules" if you want to contribute any code. LEGAL ISSUES ============ The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991, 1992, Thomas G. Lane. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. ansi2knr.c is NOT covered by the above copyright and conditions, but instead by the usual distribution terms of the Free Software Foundation; principally, that you must include source code if you redistribute it. (See the file ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part of any program generated from the JPEG code, this does not limit you more than the foregoing paragraphs do. It appears that the arithmetic coding option of the JPEG spec is covered by patents owned by IBM and AT&T, as well as a pending Japanese patent of Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining one or more licenses. For this reason, support for arithmetic coding has been removed from the free JPEG software. (Since arithmetic coding provides only a marginal gain over the unpatented Huffman mode, it is unlikely that very many implementors will support it. If you do obtain the necessary licenses, contact jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.) So far as we are aware, there are no patent restrictions on the remaining code. We are required to state that "The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated." TO DO ===== The next major release will probably be a significant rewrite to allow use of this code in conjunction with Sam Leffler's free TIFF library (assuming the bugs in the TIFF 6.0 specification get resolved). Many of the modules need fleshing out to provide more complete implementations, or to provide faster paths for common cases. Speeding things up is still high on our priority list. We'd appreciate it if people would compile and check out the code on as wide a variety of systems as possible, and report any portability problems encountered (with solutions, if possible). Checks of file compatibility with other JPEG implementations would also be of interest. Finally, we would appreciate code profiles showing where the most time is spent, especially on unusual systems. Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. G compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picturexloadimage.4.1/jpeg/SETUP 644 221 144 66437 5340727121 10347 SETUP instructions for the Independent JPEG Group's JPEG software ================================================================= This file explains how to configure and compile the JPEG software. We have tried to make this software extremely portable and flexible, so that it can be adapted to almost any environment. The downside of this decision is that the installation process is not very automatic; you will need at least a little familiarity with C programming and program build procedures for your system. This file contains general instructions, then sections of specific hints for certain systems. You may save yourself considerable time if you scan the whole file before starting to do anything. Before installing the software you must unpack the distributed source code. Since you are reading this file, you have probably already succeeded in this task. However, there is one potential trap if you are on a non-Unix system: you may need to convert these files to the local standard text file format (for example, if you are on MS-DOS you probably have to convert LF end-of-line to CR/LF). If so, apply the conversion to all the files EXCEPT those whose names begin with "test". The test files contain binary data; if you change them in any way then the self-test will give bad results. STEP 1: PREPARE A MAKEFILE ========================== First, select a makefile and copy it to "Makefile" (or whatever your version of make uses as the default makefile name; for example, "makefile.mak" for old versions of Borland C). We include several standard makefiles in the distribution: makefile.ansi: for Unix systems with ANSI-compatible C compilers. makefile.unix: for Unix systems with non-ANSI C compilers. makefile.mc5: for Microsoft C 5.x under MS-DOS. makefile.mc6: for Microsoft C 6.x and up under MS-DOS. makefile.bcc: for Borland C (Turbo C) under MS-DOS. makefile.icc: for Intel's Code Builder C under MS-DOS. makefile.manx: for Manx Aztec C on Amigas. makefile.sas: for SAS C on Amigas. makcjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C. makdjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C. makljpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C. makefile.mms: for VAX/VMS systems with MMS. makefile.vms: for VAX/VMS systems without MMS. If you don't see a makefile for your system, we recommend starting from either makefile.ansi or makefile.unix, depending on whether your compiler accepts ANSI C or not. Actually you should start with makefile.ansi whenever your compiler supports ANSI-style function definitions; you don't need full ANSI compatibility. The difference between the two makefiles is that makefile.unix preprocesses the source code to convert function definitions to old-style C. (Our thanks to Peter Deutsch of Aladdin Enterprises for the ansi2knr program.) If you don't know whether your compiler supports ANSI-style function definitions, then take a look at ckconfig.c. It is a test program that will help you figure out this fact, as well as some other facts you'll need in later steps. You must compile and execute ckconfig.c by hand; the makefiles don't provide any support for this. ckconfig.c may not compile the first try (in fact, the whole idea is for it to fail if anything is going to). If you get compile errors, fix them by editing ckconfig.c according to the directions given in ckconfig.c. Once you get it to run, select a makefile according to the advice it prints out, and make any other changes it recommends. Look over the selected Makefile and adjust options as needed. In particular you may want to change the CC and CFLAGS definitions. For instance, if you are using GCC, set CC=gcc. If you had to use any compiler switches to get ckconfig.c to work, make sure the same switches are in CFLAGS. If you are on a system that doesn't use makefiles, you'll need to set up project files (or whatever you do use) to compile all the source files and link them into executable files cjpeg and djpeg. See the file lists in any of the makefiles to find out which files go into each program. As a last resort, you can make a batch script that just compiles everything and links it all together; makefile.vms is an example of this (it's for VMS systems that have no make-like utility). STEP 2: EDIT JCONFIG.H ====================== Look over jconfig.h and adjust #defines to reflect the properties of your system and C compiler. If you prefer, you can usually leave jconfig.h unmodified and add -Dsymbol switches to the Makefile's CFLAGS definition. (This is already done if you used a compiler-specific makefile in step 1.) However, putting the switches in the Makefile is a bad idea if you are going to incorporate the JPEG software into other programs --- you'd need to include the same -D switches in the other programs' Makefiles. Better to change jconfig.h. If you have an ANSI-compliant C compiler, no changes should be necessary except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE. For older compilers other changes may be needed, depending on what ANSI features are supported. If you don't know enough about C programming to understand the questions in jconfig.h, then use ckconfig.c to figure out what to change. (See description of ckconfig.c in step 1.) A note about TWO_FILE_COMMANDLINE: defining this selects the command line syntax in which the input and output files are both named on the command line. If it's not defined, the output image goes to standard output, and the input can optionally come from standard input. You MUST use two-file style on any system that doesn't cope well with binary data fed through stdin/stdout; this is true for most MS-DOS compilers, for example. If you're not on a Unix system, it's probably safest to assume you need two-file style. (But if your compiler provides either the Posix-standard fdopen() library routine or a Microsoft-compatible setmode() routine, you can use the Unix command line style, by defining USE_FDOPEN or USE_SETMODE respectively.) STEP 3: SELECT SYSTEM-DEPENDENT FILES ===================================== A few places in the JPEG software are so system-dependent that we have to provide several different implementations and let you select the one you need. The only system-dependent file in the current version is jmemsys.c. This file controls use of temporary files for big images that won't fit in main memory. You'll notice there is no file named jmemsys.c in the distribution; you must select one of the provided versions and copy, rename, or link it to jmemsys.c. Here are the provided versions: jmemansi.c This is a reasonably portable version that should work on most ANSI and near-ANSI C compilers. It uses the ANSI-standard library routine tmpfile(), which not all non-ANSI systems have. On some systems tmpfile() may put the temporary file in a non-optimal location; if you don't like what it does, use jmemname.c. jmemname.c This version constructs the temp file name by itself. For anything except a Unix machine, you'll need to configure the select_file_name() routine appropriately; see the comments near the head of jmemname.c. If you use this version, define NEED_SIGNAL_CATCHER in jconfig.h or in the Makefile to make sure the temp files are removed if the program is aborted. jmemnobs.c (That stands for No Backing Store :-). This will compile on almost any system, but it assumes you have enough main memory or virtual memory to hold the biggest images you need to work with. jmemdos.c This should be used in most MS-DOS installations; see the system-specific notes about MS-DOS for more info. IMPORTANT: if you use this, also copy jmemdos.h to jmemsys.h, replacing the standard version. ALSO, include the assembly file jmemdosa.asm in the programs. (This last is already done if you used one of the supplied MS-DOS-specific makefiles.) If you have plenty of (real or virtual) main memory, just use jmemnobs.c. "Plenty" means at least ten bytes for every pixel in the largest images you plan to process, so a lot of systems don't meet this criterion. If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have to use jmemname.c; be sure to adjust select_file_name() for local conditions. You may also need to change unlink() to remove() in close_backing_store(). Except with jmemnobs.c, you need to adjust the #define DEFAULT_MAX_MEM to a reasonable value for your system (either by editing jmemsys.c, or by adding a -D switch to the Makefile). This value limits the amount of data space the program will attempt to allocate. Code and static data space isn't counted, so the actual memory needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory setting. Larger max-memory settings reduce the amount of I/O needed to process a large image, but too large a value can result in "insufficient memory" failures. On most Unix machines (and other systems with virtual memory), just set DEFAULT_MAX_MEM to several million and forget it. At the other end of the spectrum, for MS-DOS machines you probably can't go much above 300K to 400K. (On MS-DOS the value refers to conventional memory; extended/expanded memory is handled separately by jmemdos.c.) STEP 4: MAKE ============ Now you should be able to "make" the software. If you have trouble with missing system include files or inclusion of the wrong ones, look at jinclude.h (or use ckconfig.c, if you are not a C expert). If your compiler complains about big_sarray_control and big_barray_control being undefined structures, you should be able to shut it up by adding -DINCOMPLETE_TYPES_BROKEN to CFLAGS (or add #define INCOMPLETE_TYPES_BROKEN to jconfig.h). If you don't have a getenv() library routine, define NO_GETENV. There are a fair number of routines that do not use all of their parameters; some compilers will issue warnings about this, which you can ignore. Any other warning deserves investigation. STEP 5: TEST ============ As a quick test of functionality we've included a small sample image in several forms: testorig.jpg A reduced section of the well-known Lenna picture. testimg.ppm The output of djpeg testorig.jpg testimg.gif The output of djpeg -gif testorig.jpg testimg.jpg The output of cjpeg testimg.ppm (The two .jpg files aren't identical since JPEG is lossy.) If you can generate duplicates of the testimg.* files then you probably have working programs. With most of the makefiles, "make test" will perform the necessary comparisons. If you started with makefile.ansi or makefile.unix, and you defined TWO_FILE_COMMANDLINE, then change the makefile's test script to use two-file syntax (i.e., delete the ">" character from the invocations of cjpeg and djpeg). The other makefiles will work with either command-line syntax. If you're using a makefile that doesn't provide the test option, run djpeg and cjpeg by hand to generate testout.ppm, testout.gif, and testout.jpg, then compare these to testimg.* with whatever binary file comparison tool you have. The files should be bit-for-bit identical. If the cjpeg test run fails with "Missing Huffman code table entry", it's a good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to step 2 and run ckconfig.c. (This is a good plan for any other test failure, too.) If you are using Unix (one-file) command line style on a non-Unix system, it's a good idea to check that binary I/O through stdin/stdout actually works. You should get the same results from "djpeg out.ppm" as from "djpeg -outfile out.ppm testorig.jpg". Note that the non-Unix makefiles use the latter style and therefore do not exercise stdin/stdout. If this test fails, try recompiling jcmain.c & jdmain.c with USE_SETMODE and/or USE_FDOPEN. If your choice of jmemsys.c was anything other than jmemnobs.c, you should test that temporary-file usage works. Try "djpeg -gif -max 0 testorig.jpg" and make sure its output matches testimg.gif. If you have any really large images handy, try compressing them with -optimize and/or decompressing with -gif to make sure your DEFAULT_MAX_MEM setting is not too large. NOTE: this is far from an exhaustive test of the JPEG software; some modules, such as 1-pass color quantization, are not exercised at all. It's just a quick test to give you some confidence that you haven't missed something major. STEP 6: INSTALLATION ==================== Once you're done with the above steps, you can install the software by copying the executable files (cjpeg and djpeg) to wherever you normally install programs. On Unix systems, you'll also want to put cjpeg.1 and djpeg.1 in the corresponding manual directory. (The makefiles don't support this step since there's such a wide variety of installation procedures on different systems.) To learn to use the programs, read the file USAGE (or manual pages cjpeg(1) and djpeg(1) on Unix). Note that the man pages cjpeg.1/djpeg.1 only describe the Unix-style command line syntax; if you want to use these files with a version that uses two-file command line syntax, you'll have to modify the text accordingly. The USAGE file describes both styles. OPTIMIZATION ============ Unless you own a Cray, you'll probably be interested in making the JPEG software go as fast as possible. This section covers some machine-dependent optimizations you may want to try. We suggest that before trying any of this, you first get the basic installation to pass the self-test (step 5 above). Repeat the self-test after any optimization to make sure that you haven't broken anything. The JPEG DCT routines perform a lot of multiplications. These multiplications must yield 32-bit results, but none of their input values are more than 16 bits wide. On many machines, notably the 680x0 and 80x86 CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32 bit multiply. Unfortunately there is no portable way to specify such a multiplication in C, but some compilers can generate one when you use the right combination of casts. See the MULTIPLY macro definitions in jfwddct.c and jrevdct.c. If your compiler makes "int" be 32 bits and "short" be 16 bits, defining SHORTxSHORT_32 is fairly likely to work. When experimenting with alternate definitions, be sure to test not only whether the code still works (use the self-test step), but also whether it is actually faster --- on some compilers, alternate definitions may compute the right answer, yet be slower than the default. Timing cjpeg on a large PPM input file is the best way to check this, as the DCT will be the largest fraction of the runtime in that mode. (Note: some of the distributed compiler-specific makefiles already contain -D switches to select an appropriate MULTIPLY definition.) If access to "short" arrays is slow on your machine, it may be a win to define type DCTELEM as int rather than as JCOEF (which is normally defined as short). This will cause the DCT routines to operate on int arrays instead of short arrays. If shorts are slow and you have lots of memory to burn, you might even make JCOEF itself be int. If your compiler can compile function calls in-line, make sure the INLINE macro in jconfig.h is defined as the keyword that marks a function inline-able. Some compilers have a switch that tells the compiler to inline any function it thinks is profitable (e.g., -finline-functions for gcc). Enabling such a switch is likely to make the compiled code bigger but faster. In general, it's worth trying the maximum optimization level of your compiler, and experimenting with any optional optimizations such as loop unrolling. (Unfortunately, far too many compilers have optimizer bugs ... be prepared to back off if the code fails self-test.) If you do any experimentation along these lines, please report the optimal settings to jpeg-info@uunet.uu.net so we can mention them in future releases. Be sure to specify your machine and compiler version. OPTIONAL STUFF ============== Progress monitor: If you like, you can #define PROGRESS_REPORT (in jconfig.h or in the Makefile) to enable display of percent-done progress reports. The routines provided in jcmain.c/jdmain.c merely print percentages to stderr, but you can customize them to do something fancier. Utah RLE file format support: We distribute the software with support for RLE image files (Utah Raster Toolkit format) disabled, because the RLE support won't compile without the Utah library. If you have URT version 3.0, you can enable RLE support as follows: 1. #define RLE_SUPPORTED in jconfig.h or in the Makefile. 2. Add a -I option to CFLAGS in the Makefile for the directory containing the URT .h files (typically the "include" subdirectory of the URT distribution). 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies the directory containing the URT "librle.a" file (typically the "lib" subdirectory of the URT distribution). JPEG library: If you want to incorporate the JPEG code as subroutines in a larger program, we recommend that you make libjpeg.a, then link that into your surrounding program. See file README for more info. CAUTION: When you use the JPEG code as subroutines, we recommend that you make any required configuration changes by modifying jconfig.h, not by adding -D switches to the Makefile. Otherwise you must be sure to provide the same -D switches when compiling any program that includes the JPEG .h files, to ensure that the parameter structures are interpreted the same way. (This is only critical for the first few symbols mentioned in jconfig.h, down through NEED_FAR_POINTERS.) Removing code: If you need to make a smaller version of the JPEG software, some optional functions can be removed at compile time. See the xxx_SUPPORTED #defines in jconfig.h. If at all possible, we recommend that you leave in decoder support for all valid JPEG files, to ensure that you can read anyone's output. Restricting your encoder, or removing optional functions like block smoothing, won't hurt compatibility. Taking out support for image file formats that you don't use is the most painless way to make the programs smaller. NOTES FOR SPECIFIC SYSTEMS ========================== We welcome reports on changes needed for systems not mentioned here. Submit 'em to jpeg-info@uunet.uu.net. Also, if ckconfig.c is wrong about how to configure the JPEG software for your system, please let us know. Amiga: Makefiles are provided for Manx Aztec C and SAS C. I have also heard from people who have compiled with the free DICE compiler, using makefile.ansi as a starting point (set "CC= dcc" and "CFLAGS= -c -DAMIGA -DTWO_FILE_COMMANDLINE -DNEED_SIGNAL_CATCHER" in the makefile). For all compilers, we recommend you use jmemname.c as the system-dependent memory manager. Assuming you have -DAMIGA in the makefile, jmemname.c will put temporary files in JPEGTMP:. Change jmemname.c if you don't like this. Atari: The project files provided should work as-is with Pure C. For Turbo C, change library filenames "PC..." to "TC..." in the project files for cjpeg.ttp and djpeg.ttp. Don't forget to select a jmemsys.c file, see Step 3 (we recommend jmemansi.c). Also adjust the DEFAULT_MAX_MEM setting --- you probably want it to be a couple hundred K less than your normal free memory. Note that you must make jpeg.lib before making cjpeg.ttp or cjpeg.ttp. You'll have to perform the self-test (Step 5) by hand. There is a bug in some older versions of the Turbo C library which causes the space used by temporary files created with "tmpfile()" not to be freed after an abnormal program exit. If you check your disk afterwards, you will find cluster chains that are allocated but not used by a file. This should not happen in cjpeg or djpeg, since we enable a signal catcher to explicitly close temp files before exiting. But if you use the JPEG library with your own code, be sure to supply a signal catcher, or else use a different system-dependent memory manager. Cray: Should you be so fortunate as to be running JPEG on a Cray YMP, there is a compiler bug in Cray's Standard C versions prior to 3.1. You'll need to insert a line reading "#pragma novector" just before the loop for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; in fix_huff_tbl (in V4A, line 42 of jchuff.c and line 39 of jdhuff.c). The usual symptom of not adding this line is a core-dump. See Cray's SPR 48222. HP/Apollo DOMAIN: With system release 10.4 or later, makefile.ansi should work OK. If you have version 10.3.anything, you need to figure out whether you have the ANSI C compiler (version 6.7 or later) and whether you've installed the ANSI C include files (if so, the first line of will mention ANSI C). If you have the ANSI C compiler but not the ANSI C include files, use makefile.ansi and add -DNONANSI_INCLUDES to CFLAGS. If you have both, then makefile.ansi should work as is. If neither, use makefile.unix. HP-UX: If you have HP-UX 7.05 or later with the "software development" C compiler, then you can use makefile.ansi. Add "-Aa" to the CFLAGS line in the makefile to make the compiler work in ANSI mode. If you have a pre-7.05 system, or if you are using the non-ANSI C compiler delivered with a minimum HP-UX 8.0 system, then you must use makefile.unix (and do NOT add -Aa). Also, adding "-lmalloc" to LDLIBS is recommended if you have libmalloc.a (it seems not to be present in minimum 8.0). On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior to A.08.07. If you get complaints about "not a typedef name", you'll have to convert the code to K&R style (i.e., use makefile.unix). Macintosh MPW: We don't directly support MPW in the current release, but Larry Rosenstein reports that the JPEG code can be ported without very much trouble. There's useful notes and conversion scripts in his kit for porting PBMPLUS to MPW. You can obtain the kit by FTP to ftp.apple.com, file /pub/lsr/pbmplus-port*. Macintosh Think C: You'll have to prepare project files for cjpeg and djpeg; we don't include those in the distribution since they are not text files. The COBJECTS and DOBJECTS lists in makefile.unix show which files should be included in each project. Also add the ANSI and Unix C libraries in a separate segment. You may need to divide the JPEG files into more than one segment; you can do this pretty much as you please. If you have Think C version 5.0 you need not modify jconfig.h; instead you should turn on both the ANSI Settings and Language Extensions option buttons (so that both __STDC__ and THINK_C are predefined). With version 4.0 you must edit jconfig.h. (You can #define HAVE_STDC to do the right thing for all options except const; you must also #define const.) jcmain and jdmain are set up to provide the usual command-line interface by means of Think's ccommand() library routine. A more Mac-like interface is in the works. MS-DOS, generic comments: The JPEG code is designed to be compiled with 80x86 "small" or "medium" memory models (i.e., data pointers are 16 bits unless explicitly declared "far"; code pointers can be either size). You should be able to use small model to compile cjpeg or djpeg by itself, but you will probably have to go to medium model if you include the JPEG code in a larger application. This shouldn't hurt performance much. You *will* take a noticeable performance hit if you compile in a large-data memory model, and you should avoid "huge" model if at all possible. Be sure that NEED_FAR_POINTERS is defined by jconfig.h or by the Makefile if you use a small-data model; be sure it is NOT defined if you use a large-data memory model. (As distributed, jconfig.h defines NEED_FAR_POINTERS if MSDOS is defined.) The DOS-specific memory manager, jmemdos.c, should be used if possible. (Be sure to install jmemdos.h and jmemdosa.asm along with it.) If you can't use jmemdos.c for some reason --- for example, because you don't have a Microsoft-compatible assembler to assemble jmemdosa.asm --- you'll have to fall back to jmemansi.c or jmemname.c. IMPORTANT: if you use either of the latter two files, you will have to compile in a large-data memory model in order to get the right stdio library. Too bad. None of the above advice applies if you are using a 386 flat-memory-space environment, such as DJGPP or Watcom C. (And you should use one if you have it, as performance will be much better than 8086-compatible code!) For flat-memory-space compilers, do NOT define NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual memory, otherwise use jmemansi.c or jmemname.c. Most MS-DOS compilers treat stdin/stdout as text files, so you must use two-file command line style. But if your compiler has either fdopen() or setmode(), you can use one-file style if you like. To do this, define USE_FDOPEN or USE_SETMODE so that stdin/stdout will be set to binary mode. (USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You should test that I/O through stdin/stdout produces the same results as I/O to explicitly named files... the "make test" procedures in the DOS-specific makefiles do NOT use stdin/stdout. If you add more switches to CFLAGS in the DOS-specific makefiles, you are likely to run up against DOS' 128-byte command line length limit. In that case, remove some "-Dsymbol" switches from CFLAGS and instead put corresponding "#define symbol" lines at the head of jinclude.h. MS-DOS, Borland C: Be sure to convert all the source files to DOS text format (CR/LF newlines). Although Borland C will often work OK with unmodified Unix (LF newlines) source files, sometimes it will give bogus compile errors. "Illegal character '#'" is the most common such error. Some versions of Borland's MAKE erroneously display the warning message about creating jmemsys.c, even after you have done so. If this happens to you, delete the four lines beginning with "jmemsys.c:" from the Makefile. If you want one-file command line style, define USE_SETMODE. fdopen() does not work correctly. MS-DOS, DJGPP: Use makefile.ansi and jmemnobs.c, and put "-UMSDOS" in CFLAGS to undo the compiler's automatic definition of MSDOS. Also put either "-DUSE_SETMODE" or "-DTWO_FILE_COMMANDLINE" in CFLAGS, depending on whether you prefer one-file or two-file command line style. You'll also need to put the object-file lists into response files in order to circumvent DOS's 128-byte command line length limit at the final linking step. MS-DOS, Microsoft C: Old versions of MS C fail with an "out of macro expansion space" error because they can't cope with the macro TRACEMS8 (defined in jpegdata.h). If this happens to you, the easiest solution is to change TRACEMS8 to expand to nothing. You'll lose the ability to dump out JPEG coefficient tables with djpeg -debug -debug, but at least you can compile. Original MS C 6.0 is buggy; it compiles incorrect code unless you turn off optimization (remove -O from CFLAGS). That problem seems to have been fixed in 6.00A and later versions. 6.00A still generates a bogus "conditional expression is constant" warning in jrdppm.c, but the emitted code seems OK. If you want one-file command line style, define USE_SETMODE. fdopen() does not work correctly, at least not in 6.00A. SGI: Use makefile.ansi, but set "AR2= ar -ts" rather than "AR2= ranlib". Also make any changes recommended by ckconfig.c. Sun: Don't forget to add -DBSD to CFLAGS. If you are using GCC on SunOS 4.0.1 or earlier, you will need to add -DNONANSI_INCLUDES to CFLAGS (your compiler may be ANSI, but your system include files aren't). I've gotten conflicting reports on whether this is still necessary on SunOS 4.1 or later. exit. If you check your disk afterwards, you will find cluster chains that are allocated but not used by a file. This should not happen in cjpeg or djpeg, since we enable a signal catcher to explicitly close temp files befxloadimage.4.1/jpeg/USAGE 644 221 144 35031 5340514314 10273 USAGE instructions for the Independent JPEG Group's JPEG software ================================================================= INTRODUCTION This distribution contains software to implement JPEG image compression and decompression. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG is designed to handle "real-world" scenes, for example scanned photographs. Cartoons, line drawings, and other non-realistic images are not JPEG's strong suit; on this sort of material you may get poor image quality and/or little compression. JPEG is lossy, meaning that the output image is not necessarily identical to the input image. Hence you should not use JPEG if you have to have identical output bits. However, on typical real-world images, very good compression levels can be obtained with no visible change, and amazingly high compression is possible if you can tolerate a low-quality image. You can trade off image quality against file size by adjusting the compressor's "quality" setting. This file describes usage of the standard programs "cjpeg" and "djpeg" that can be built directly from the distributed C code. See the README file for hints on incorporating the JPEG software into other programs. If you are on a Unix machine you may prefer to read the Unix-style manual pages in files cjpeg.1 and djpeg.1. But also see the HINTS section below, which is not present in either manual page. NOTE: the switch syntax has been redesigned since the v3 release of cjpeg/djpeg. Switch names are now words instead of single letters. GENERAL USAGE We provide two programs, cjpeg to compress an image file into JPEG format, and djpeg to decompress a JPEG file back into a conventional image format. On Unix-like systems, you say: cjpeg [switches] [imagefile] >jpegfile or djpeg [switches] [jpegfile] >imagefile The programs read the specified input file, or standard input if none is named. They always write to standard output (with trace/error messages to standard error). These conventions are handy for piping images between programs. On most non-Unix systems, you say: cjpeg [switches] imagefile jpegfile or djpeg [switches] jpegfile imagefile i.e., both the input and output files are named on the command line. This style is a little more foolproof, and it loses no functionality if you don't have pipes. (You can get this style on Unix too, if you prefer, by defining TWO_FILE_COMMANDLINE when you compile the programs; see SETUP.) You can also say: cjpeg [switches] -outfile jpegfile imagefile or djpeg [switches] -outfile imagefile jpegfile This syntax works on all systems, so it is useful for scripts. The currently supported image file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available.) cjpeg recognizes the input image format automatically, with the exception of some Targa-format files. You have to tell djpeg which format to generate. The only JPEG file format currently supported is the JFIF format. Support for the TIFF 6.0 JPEG format will probably be added at some future date. All switch names may be abbreviated; for example, -grayscale may be written -gray or -gr. Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (-GIF is the same as -gif). British spellings are also accepted (e.g., -greyscale), though for brevity these are not mentioned below. CJPEG DETAILS The basic command line switches for cjpeg are: -quality N Scale quantization tables to adjust image quality. Quality is 0 (worst) to 100 (best); default is 75. (See below for more info.) -grayscale Create monochrome JPEG file from color input. Be sure to use this switch when compressing a grayscale GIF file, because cjpeg isn't bright enough to notice whether a GIF file uses only shades of gray. By saying -grayscale, you'll get a smaller JPEG file that takes less time to process. -optimize Perform optimization of entropy encoding parameters. Without this, default encoding parameters are used. -optimize usually makes the JPEG file a little smaller, but cjpeg runs somewhat slower and needs much more memory. Image quality and speed of decompression are unaffected by -optimize. -targa Input file is Targa format. Targa files that contain an "identification" field will not be automatically recognized by cjpeg; for such files you must specify -targa to make cjpeg treat the input as Targa format. The -quality switch lets you trade off compressed file size against quality of the reconstructed image: the higher the quality setting, the larger the JPEG file, and the closer the output image will be to the original input. Normally you want to use the lowest quality setting (smallest file) that decompresses into something visually indistinguishable from the original image. For this purpose the quality setting should be between 50 and 95; the default of 75 is often about right. If you see defects at -quality 75, then go up 5 or 10 counts at a time until you are happy with the output image. (The optimal setting will vary from one image to another.) -quality 100 will generate a quantization table of all 1's, eliminating loss in the quantization step (but there is still information loss in subsampling, as well as roundoff error). This setting is mainly of interest for experimental purposes. Quality values above about 95 are NOT recommended for normal use; the compressed file size goes up dramatically for hardly any gain in output image quality. In the other direction, quality values below 50 will produce very small files of low image quality. Settings around 5 to 10 might be useful in preparing an index of a large image library, for example. Try -quality 2 (or so) for some amusing Cubist effects. (Note: quality values below about 25 generate 2-byte quantization tables, which are considered optional in the JPEG standard. cjpeg emits a warning message when you give such a quality value, because some commercial JPEG programs may be unable to decode the resulting file.) Switches for advanced users: -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -restart N Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. -restart 0 (the default) means no restart markers. -smooth N Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. The -restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage to a compressed file will usually ruin the image from the point of the error to the end of the image; with restart markers, the damage is usually confined to the portion of the image up to the next restart marker. Of course, the restart markers occupy extra space. We recommend -restart 1 for images that will be transmitted across unreliable networks such as Usenet. The -smooth option filters the input to eliminate fine-scale noise. This is often useful when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50 gets rid of dithering patterns in the input file, resulting in a smaller JPEG file and a better-looking image. Too large a smoothing factor will visibly blur the image, however. Switches for wizards: -arithmetic Use arithmetic coding rather than Huffman coding. (Not currently supported for legal reasons.) -nointerleave Generate noninterleaved JPEG file (not yet supported). -qtables file Use the quantization tables given in the specified file. The file should contain one to four tables (64 values each) as plain text. Comments preceded by '#' may be included in the file. The tables are implicitly numbered 0,1,etc. If -quality N is also specified, the values in the file are scaled according to cjpeg's quality scaling curve. -sample HxV[,...] Set JPEG sampling factors. If you specify fewer H/V pairs than there are components, the remaining components are set to 1x1 sampling. The default setting is equivalent to "-sample 2x2". The "wizard" switches are intended for experimentation with JPEG. If you don't know what you are doing, DON'T USE THEM. You can easily produce files with worse image quality and/or poorer compression than you'll get from the default settings. Furthermore, these switches should not be used when making files intended for general use, because not all JPEG implementations will support unusual JPEG parameter settings. DJPEG DETAILS The basic command line switches for djpeg are: -colors N Reduce image to at most N colors. This reduces the or -quantize N number of colors used in the output image, so that it can be displayed on a colormapped display or stored in a colormapped file format. For example, if you have an 8-bit display, you'd need to reduce to 256 or fewer colors. (-colors is the recommended name, -quantize is provided only for backwards compatibility.) -gif Select GIF output format. Since GIF does not support more than 256 colors, -colors 256 is assumed (unless you specify a smaller number of colors). -pnm Select PBMPLUS (PPM/PGM) output format (this is the default format). PGM is emitted if the JPEG file is gray-scale or if -grayscale is specified; otherwise PPM is emitted. -rle Select RLE output format. (Requires URT library.) -targa Select Targa output format. Gray-scale format is emitted if the JPEG file is gray-scale or if -grayscale is specified; otherwise, colormapped format is emitted if -colors is specified; otherwise, 24-bit full-color format is emitted. Switches for advanced users: -blocksmooth Perform cross-block smoothing. This is slow, quite memory-intensive, and only seems to improve the image at very low quality settings (-quality 10 to 20 or so). At normal quality settings it may make things worse. -grayscale Force gray-scale output even if JPEG file is color. Useful for viewing on monochrome displays. -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -nodither Do not use dithering in color quantization. By default, Floyd-Steinberg dithering is applied when quantizing colors, but on some images dithering may result in objectionable "graininess". If that happens, you can turn off dithering with -nodither. -nodither is ignored unless you also say -colors N. -onepass Use one-pass instead of two-pass color quantization. The one-pass method is faster and needs less memory, but it produces a lower-quality image. -onepass is ignored unless you also say -colors N. Also, the one-pass method is always used for gray-scale output (the two-pass method is no improvement then). -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. HINTS Color GIF files are not the ideal input for JPEG; JPEG is really intended for compressing full-color (24-bit) images. In particular, don't try to convert cartoons, line drawings, and other images that have only a few distinct colors. GIF works great on these, JPEG does not. If you want to convert a GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options to get a satisfactory conversion. -smooth 10 or so is often helpful. Avoid running an image through a series of JPEG compression/decompression cycles. Image quality loss will accumulate; after ten or so cycles the image may be noticeably worse than it was after one cycle. It's best to use a lossless format while manipulating an image, then convert to JPEG format when you are ready to file the image away. The -optimize option to cjpeg is worth using when you are making a "final" version for posting or archiving. It's also a win when you are using low quality settings to make very small JPEG files; the percentage improvement is often a lot more than it is on larger files. When making images to be posted on Usenet, we recommend using cjpeg's option -restart 1. This option limits the damage done to a compressed image by netnews transmission errors. The default memory usage limit (-maxmemory) is set when the software is compiled. If you get an "insufficient memory" error, try specifying a smaller -maxmemory value, even -maxmemory 0 to use the absolute minimum space. You may want to recompile with a smaller default value if this happens often. On machines that have "environment" variables, you can define the environment variable JPEGMEM to set the default memory limit. The value is specified as described for the -maxmemory switch. JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit -maxmemory switch. On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to use. (Extended or expanded memory is also used if available.) Most DOS-specific versions of this software do their own memory space estimation and do not need -maxmemory. djpeg with two-pass color quantization requires a good deal of memory; on MS-DOS machines it may run out of memory even with -maxmemory 0. In that case you can still decompress, with some loss of image quality, by specifying -onepass for one-pass quantization. If more space is needed than will fit in the available main memory (as determined by -maxmemory), temporary files will be used. (MS-DOS versions will try to get extended or expanded memory first.) The temporary files are often rather large: in typical cases they occupy three bytes per pixel, for example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough free disk space, leave out -optimize (for cjpeg) or specify -onepass (for djpeg). On MS-DOS, the temporary files are created in the directory named by the TMP or TEMP environment variable, or in the current directory if neither of those exist. Amiga implementations put the temp files in the directory named by JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free space. the default) means no restart markers. -smooth N Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. The -restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage xloadimage.4.1/jpeg/ansi2knr.c 644 221 144 37544 5276000572 11416 /* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved. Distributed by Free Software Foundation, Inc. This file is part of Ghostscript. Ghostscript is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the Ghostscript General Public License for full details. Everyone is granted permission to copy, modify and redistribute Ghostscript, but only under the conditions described in the Ghostscript General Public License. A copy of this license is supposed to have been given to you along with Ghostscript so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* ---------- Here is the GhostScript file COPYING, referred to above ---------- ----- These terms do NOT apply to the JPEG software itself; see README ------ GHOSTSCRIPT GENERAL PUBLIC LICENSE (Clarified 11 Feb 1988) Copyright (C) 1988 Richard M. Stallman Everyone is permitted to copy and distribute verbatim copies of this license, but changing it is not allowed. You can also use this wording to make the terms for other programs. The license agreements of most software companies keep you at the mercy of those companies. By contrast, our general public license is intended to give everyone the right to share Ghostscript. To make sure that you get the rights we want you to have, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. Hence this license agreement. Specifically, we want to make sure that you have the right to give away copies of Ghostscript, that you receive source code or else can get it if you want it, that you can change Ghostscript or use pieces of it in new free programs, and that you know you can do these things. To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of Ghostscript, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. Also, for our own protection, we must make certain that everyone finds out that there is no warranty for Ghostscript. If Ghostscript is modified by someone else and passed on, we want its recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation. Therefore we (Richard M. Stallman and the Free Software Foundation, Inc.) make the following terms which say what you must do to be allowed to distribute or change Ghostscript. COPYING POLICIES 1. You may copy and distribute verbatim copies of Ghostscript source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright and license notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved. Distributed by Free Software Foundation, Inc." (or with whatever year is appropriate); keep intact the notices on all files that refer to this License Agreement and to the absence of any warranty; and give any other recipients of the Ghostscript program a copy of this License Agreement along with the program. You may charge a distribution fee for the physical act of transferring a copy. 2. You may modify your copy or copies of Ghostscript or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains or is a derivative of Ghostscript or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third parties, at your option). c) You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms. 3. You may copy and distribute Ghostscript (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs. 4. You may not copy, sublicense, distribute or transfer Ghostscript except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer Ghostscript is void and your rights to use the program under this License agreement shall be automatically terminated. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated so long as such parties remain in full compliance. 5. If you wish to incorporate parts of Ghostscript into other free programs whose distribution conditions are different, write to the Free Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software. Your comments and suggestions about our licensing policies and our software are welcome! Please contact the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. NO WARRANTY BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. -------------------- End of file COPYING ------------------------------ */ /* ansi2knr.c */ /* Convert ANSI function declarations to K&R syntax */ #include #include #ifdef BSD #include #define strchr index #else #ifdef VMS extern char *strcat(), *strchr(), *strcpy(), *strupr(); extern int strcmp(), strlen(), strncmp(); #else #include #endif #endif #ifdef MSDOS #include #else #ifdef VMS extern char *malloc(); extern void free(); #else extern char *malloc(); extern int free(); #endif #endif /* Usage: ansi2knr input_file output_file * If no output_file is supplied, output goes to stdout. * There are no error messages. * * ansi2knr recognizes functions by seeing a non-keyword identifier * at the left margin, followed by a left parenthesis, * with a right parenthesis as the last character on the line. * It will recognize a multi-line header if the last character * on each line but the last is a left parenthesis or comma. * These algorithms ignore whitespace and comments, except that * the function name must be the first thing on the line. * The following constructs will confuse it: - Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call). - Macros that tinker with the syntax of the function header. */ /* Scanning macros */ #define isidchar(ch) (isalnum(ch) || (ch) == '_') #define isidfirstchar(ch) (isalpha(ch) || (ch) == '_') main(argc, argv) int argc; char *argv[]; { FILE *in, *out; #define bufsize 5000 /* arbitrary size */ char *buf; char *line; switch ( argc ) { default: printf("Usage: ansi2knr input_file [output_file]\n"); exit(0); case 2: out = stdout; break; case 3: out = fopen(argv[2], "w"); if ( out == NULL ) { fprintf(stderr, "Cannot open %s\n", argv[2]); exit(1); } } in = fopen(argv[1], "r"); if ( in == NULL ) { fprintf(stderr, "Cannot open %s\n", argv[1]); exit(1); } fprintf(out, "#line 1 \"%s\"\n", argv[1]); buf = malloc(bufsize); line = buf; while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) { switch ( test1(buf) ) { case 1: /* a function */ convert1(buf, out); break; case -1: /* maybe the start of a function */ line = buf + strlen(buf); if ( line != buf + (bufsize - 1) ) /* overflow check */ continue; /* falls through */ default: /* not a function */ fputs(buf, out); break; } line = buf; } if ( line != buf ) fputs(buf, out); free(buf); fclose(out); fclose(in); return 0; } /* Skip over space and comments, in either direction. */ char * skipspace(p, dir) register char *p; register int dir; /* 1 for forward, -1 for backward */ { for ( ; ; ) { while ( isspace(*p) ) p += dir; if ( !(*p == '/' && p[dir] == '*') ) break; p += dir; p += dir; while ( !(*p == '*' && p[dir] == '/') ) { if ( *p == 0 ) return p; /* multi-line comment?? */ p += dir; } p += dir; p += dir; } return p; } /* * Write blanks over part of a string. */ int writeblanks(start, end) char *start; char *end; { char *p; for ( p = start; p < end; p++ ) *p = ' '; return 0; } /* * Test whether the string in buf is a function definition. * The string may contain and/or end with a newline. * Return as follows: * 0 - definitely not a function definition; * 1 - definitely a function definition; * -1 - may be the beginning of a function definition, * append another line and look again. */ int test1(buf) char *buf; { register char *p = buf; char *bend; char *endfn; int contin; if ( !isidfirstchar(*p) ) return 0; /* no name at left margin */ bend = skipspace(buf + strlen(buf) - 1, -1); switch ( *bend ) { case ')': contin = 1; break; case '(': case ',': contin = -1; break; default: return 0; /* not a function */ } while ( isidchar(*p) ) p++; endfn = p; p = skipspace(p, 1); if ( *p++ != '(' ) return 0; /* not a function */ p = skipspace(p, 1); if ( *p == ')' ) return 0; /* no parameters */ /* Check that the apparent function name isn't a keyword. */ /* We only need to check for keywords that could be followed */ /* by a left parenthesis (which, unfortunately, is most of them). */ { static char *words[] = { "asm", "auto", "case", "char", "const", "double", "extern", "float", "for", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "switch", "typedef", "unsigned", "void", "volatile", "while", 0 }; char **key = words; char *kp; int len = endfn - buf; while ( (kp = *key) != 0 ) { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) return 0; /* name is a keyword */ key++; } } return contin; } int convert1(buf, out) char *buf; FILE *out; { char *endfn = strchr(buf, '(') + 1; register char *p; char **breaks; unsigned num_breaks = 2; /* for testing */ char **btop; char **bp; char **ap; top: p = endfn; breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); if ( breaks == 0 ) { /* Couldn't allocate break table, give up */ fprintf(stderr, "Unable to allocate break table!\n"); fputs(buf, out); return -1; } btop = breaks + num_breaks * 2 - 2; bp = breaks; /* Parse the argument list */ do { int level = 0; char *end = NULL; if ( bp >= btop ) { /* Filled up break table. */ /* Allocate a bigger one and start over. */ free((char *)breaks); num_breaks <<= 1; goto top; } *bp++ = p; /* Find the end of the argument */ for ( ; end == NULL; p++ ) { switch(*p) { case ',': if ( !level ) end = p; break; case '(': level++; break; case ')': if ( --level < 0 ) end = p; break; case '/': p = skipspace(p, 1) - 1; break; default: ; } } p--; /* back up over terminator */ /* Find the name being declared. */ /* This is complicated because of procedure and */ /* array modifiers. */ for ( ; ; ) { p = skipspace(p - 1, -1); switch ( *p ) { case ']': /* skip array dimension(s) */ case ')': /* skip procedure args OR name */ { int level = 1; while ( level ) switch ( *--p ) { case ']': case ')': level++; break; case '[': case '(': level--; break; case '/': p = skipspace(p, -1) + 1; break; default: ; } } if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) { /* We found the name being declared */ while ( !isidfirstchar(*p) ) p = skipspace(p, 1) + 1; goto found; } break; default: goto found; } } found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) { p++; if ( bp == breaks + 1 ) /* sole argument */ writeblanks(breaks[0], p); else writeblanks(bp[-1] - 1, p); bp--; } else { while ( isidchar(*p) ) p--; *bp++ = p+1; } p = end; } while ( *p++ == ',' ); *bp = p; /* Make a special check for 'void' arglist */ if ( bp == breaks+2 ) { p = skipspace(breaks[0], 1); if ( !strncmp(p, "void", 4) ) { p = skipspace(p+4, 1); if ( p == breaks[2] - 1 ) { bp = breaks; /* yup, pretend arglist is empty */ writeblanks(breaks[0], p + 1); } } } /* Put out the function name */ p = buf; while ( p != endfn ) putc(*p, out), p++; /* Put out the declaration */ for ( ap = breaks+1; ap < bp; ap += 2 ) { p = *ap; while ( isidchar(*p) ) putc(*p, out), p++; if ( ap < bp - 1 ) fputs(", ", out); } fputs(") ", out); /* Put out the argument declarations */ for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';'; fputs(breaks[0], out); free((char *)breaks); return 0; } BOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE ORxloadimage.4.1/jpeg/architecture 644 221 144 201766 5307004523 12142 JPEG SYSTEM ARCHITECTURE 1-DEC-92 This file provides an overview of the "architecture" of the portable JPEG software; that is, the functions of the various modules in the system and the interfaces between modules. For more precise details about any data structure or calling convention, see the header files. Important note: when I say "module" I don't mean "a C function", which is what some people seem to think the term means. A separate C source file is closer to the mark. Also, it is frequently the case that several different modules present a common interface to callers; the term "object" or "method" refers to this common interface (see "Poor man's object-oriented programming", below). JPEG-specific terminology follows the JPEG standard: A "component" means a color channel, e.g., Red or Luminance. A "sample" is a pixel component value (i.e., one number in the image data). A "coefficient" is a frequency coefficient (a DCT transform output number). The term "block" refers to an 8x8 group of samples or coefficients. "MCU" (minimum coded unit) is the same as "MDU" of the R8 draft; i.e., an interleaved set of blocks of size determined by the sampling factors, or a single block in a noninterleaved scan. *** System requirements *** We must support compression and decompression of both Huffman and arithmetic-coded JPEG files. Any set of compression parameters allowed by the JPEG spec should be readable for decompression. (We can be more restrictive about what formats we can generate.) (Note: for legal reasons no arithmetic coding implementation is currently included in the publicly available sources. However, the architecture still supports it.) We need to be able to handle both raw JPEG files (more specifically, the JFIF format) and JPEG-in-TIFF (C-cubed's format, and perhaps Kodak's). Even if we don't implement TIFF ourselves, other people will want to use our code for that. This means that generation and scanning of the file header has to be separated out. Perhaps we should be prepared to support the JPEG lossless mode (also referred to in the spec as spatial DPCM coding). A lot of people seem to believe they need this... whether they really do is debatable, but the customer is always right. On the other hand, there will not be much sharable code between the lossless and lossy modes! At best, a lossless program could be derived from parts of the lossy version. For now we will only worry about the lossy mode. I see no real value in supporting the JPEG progressive modes (note that spectral selection and successive approximation are two different progressive modes). These are only of interest when painting the decompressed image in real-time, which nobody is going to do with a pure software implementation. There is some value in supporting the hierarchical mode, which allows for successive frames of higher resolution. This could be of use for including "thumbnail" representations. However, this appears to add a lot more complexity than it is worth. A variety of uncompressed image file formats and user interfaces must be supported. These aspects therefore have to be kept separate from the rest of the system. A particularly important issue is whether color quantization of the output is needed (i.e., whether a colormap is used). We should be able to support both adaptive quantization (which requires two or more passes over the image) and nonadaptive (quantization to a prespecified colormap, which can be done in one pass). Memory usage is an important concern, since we will port this code to 80x86 and other limited-memory machines. For large intermediate structures, we should be able to use either virtual memory or temporary files. It should be possible to build programs that handle compression only, decompression only, or both, without much duplicate or unused code in any version. (In particular, a decompression-only version should have no extra baggage.) *** Compression overview *** The *logical* steps needed in (non-lossless) JPEG compression are: 1. Conversion from incoming image format to a standardized internal form (either RGB or grayscale). 2. Color space conversion (e.g., RGB to YCbCr). This is a null step for grayscale (unless we support mapping color inputs to grayscale, which would most easily be done here). Gamma adjustment may also be needed here. 3. Downsampling (reduction of number of samples in some color components). This step operates independently on each color component. 4. MCU extraction (creation of a single sequence of 8x8 sample blocks). This step and the following ones are performed once for each scan in the output JPEG file, i.e., once if making an interleaved file and more than once for a noninterleaved file. Note: both this step and the previous one must deal with edge conditions for pictures that aren't a multiple of the MCU dimensions. Alternately, we could expand the picture to a multiple of an MCU before doing these two steps. (The latter seems better and has been adopted below.) 5. DCT transformation of each 8x8 block. 6. Quantization scaling and zigzag reordering of the elements in each 8x8 block. 7. Huffman or arithmetic encoding of the transformed block sequence. 8. Output of the JPEG file with whatever headers/markers are wanted. Of course, the actual implementation will combine some of these logical steps for efficiency. The trick is to keep these logical functions as separate as possible without losing too much performance. In addition to these logical pipeline steps, we need various modules that aren't part of the data pipeline. These are: A. Overall control (sequencing of other steps & management of data passing). B. User interface; this will determine the input and output files, and supply values for some compression parameters. Note that this module is highly platform-dependent. C. Compression parameter selection: some parameters should be chosen automatically rather than requiring the user to find a good value. The prototype only does this for the back-end (Huffman or arithmetic) parameters, but further in the future, more might be done. A straightforward approach to selection is to try several values; this requires being able to repeatedly apply some portion of the pipeline and inspect the results (without actually outputting them). Probably only entropy encoding parameters can reasonably be done this way; optimizing earlier steps would require too much data to be reprocessed (not to mention the problem of interactions between parameters for different steps). What other facilities do we need to support automatic parameter selection? D. A memory management module to deal with small-memory machines. This must create the illusion of virtual memory for certain large data structures (e.g., the downsampled image or the transformed coefficients). The interface to this must be defined to minimize the overhead incurred, especially on virtual-memory machines where the module won't do much. In many cases we can arrange things so that a data stream is produced in segments by one module and consumed by another without the need to hold it all in (virtual) memory. This is obviously not possible for any data that must be scanned more than once, so it won't work everywhere. The major variable at this level of detail is whether the JPEG file is to be interleaved or not; that affects the order of processing so fundamentally that the central control module must know about it. Some of the other modules may need to know it too. It would simplify life if we didn't need to support noninterleaved images, but that is not reasonable. Many of these steps operate independently on each color component; the knowledge of how many components there are, and how they are interleaved, ought to be confined to the central control module. (Color space conversion and MCU extraction probably have to know it too.) *** Decompression overview *** Decompression is roughly the inverse process from compression, but there are some additional steps needed to produce a good output image. The *logical* steps needed in (non-lossless) JPEG decompression are: 1. Scanning of the JPEG file, decoding of headers/markers etc. 2. Huffman or arithmetic decoding of the coefficient sequence. 3. Quantization descaling and zigzag reordering of the elements in each 8x8 block. 4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8 blocks back to separate components in pixel map order). 5. (Optional) Cross-block smoothing per JPEG section K.8 or a similar algorithm. (Steps 5-8 operate independently on each component.) 6. Inverse DCT transformation of each 8x8 block. 7. Upsampling. At this point a pixel image of the original dimensions has been recreated. 8. Post-upsampling smoothing. This can be combined with upsampling, by using a convolution-like calculation to generate each output pixel directly from one or more input pixels. 9. Cropping to the original pixel dimensions (throwing away duplicated pixels at the edges). It is most convenient to do this now, as the preceding steps are simplified by not having to worry about odd picture sizes. 10. Color space reconversion (e.g., YCbCr to RGB). This is a null step for grayscale. (Note that mapping a color JPEG to grayscale output is most easily done in this step.) Gamma adjustment may also be needed here. 11. Color quantization (only if a colormapped output format is requested). NOTE: it is probably preferable to perform quantization in the internal (JPEG) colorspace rather than the output colorspace. Doing it that way, color conversion need only be applied to the colormap entries, not to every pixel; and quantization gets to operate in a non-gamma-corrected space. But the internal space may not be suitable for some algorithms. The system design is such that only the color quantizer module knows whether color conversion happens before or after quantization. 12. Writing of the desired image format. As before, some of these will be combined into single steps. When dealing with a noninterleaved JPEG file, steps 2-9 will be performed once for each scan; the resulting data will need to be buffered up so that steps 10-12 can process all the color components together. The same auxiliary modules are needed as before, except for compression parameter selection. Note that rerunning a pipeline stage should never be needed during decompression. This may allow a simpler control module. The user interface might also be simpler since it need not supply any compression parameters. As before, not all of these steps require the whole image to be stored. Actually, two-pass color quantization is the only step that logically requires this; everything else could be done a few raster lines at a time (at least for interleaved images). We might want to make color quantization be a separate program because of this fact. Again, many of the steps should be able to work on one color component in ignorance of the other components. *** Implications of noninterleaved formats *** Much of the work can be done in a single pass if an interleaved JPEG file format is used. With a noninterleaved JPEG file, separating or recombining the components will force use of virtual memory (on a small-memory machine, we probably would want one temp file per color component). If any of the image formats we read or write are noninterleaved, the opposite condition might apply: processing a noninterleaved JPEG file would be more efficient. Offhand, though, I can't think of any popular image formats that work that way; besides the win would only come if the same color space were used in JPEG and non-JPEG files. It's not worth the complexity to make the system design accommodate that case efficiently. An argument against interleaving is that it makes the decompressor need more memory for cross-block smoothing (since the minimum processable chunk of the image gets bigger). With images more than 1000 pixels across, 80x86 machines are likely to have difficulty in handling this feature. Another argument against interleaving is that the noninterleaved format allows a wider range of sampling factors, since the limit of ten blocks per MCU no longer applies. We could get around this by blithely ignoring the spec's limit of ten blocks, but that seems like a bad idea (especially since it makes the above problem worse). The upshot is that we need to support both interleaved and noninterleaved JPEG formats, since for any given machine and picture size one may be much more efficient than the other. However, the non-JPEG format we convert to or from will be assumed to be an interleaved format (i.e., it produces or stores all the components of a pixel together). I do not think it is necessary for the compressor to be able to output partially-interleaved formats (multiple scans, some of which interleave a subset of the components). However, the decompressor must be able to read such files to conform to the spec. *** Data formats *** Pipeline steps that work on pixel sample values will use the following data structure: typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE typedef JSAMPLE *JSAMPROW; ptr to a row of samples typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays The basic element type JSAMPLE will be one of unsigned char, (signed) char, or unsigned short. Unsigned short will be used if samples wider than 8 bits are to be supported (this is a compile-time option). Otherwise, unsigned char is used if possible. If the compiler only supports signed chars, then it is necessary to mask off the value when reading. Thus, all reads of sample values should be coded as "GETJSAMPLE(value)", where the macro will be defined as "((value)&0xFF)" on signed-char machines and "(value)" elsewhere. With these conventions, JSAMPLE values can be assumed to be >= 0. This should simplify correct rounding during downsampling, etc. The JPEG draft's specification that sample values run from -128..127 will be accommodated by subtracting 128 just as the sample value is copied into the source array for the DCT step (this will be an array of signed shorts or longs). Similarly, during decompression the output of the IDCT step will be immediately shifted back to 0..255. (NB: different values are required when 12-bit samples are in use. The code should be written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be #defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 and 2048 in a 12-bit implementation.) On compilers that don't support "unsigned short", signed short can be used for a 12-bit implementation. To support lossless coding (which allows up to 16-bit data precision) masking with 0xFFFF in GETJSAMPLE might be necessary. (But if "int" is 16 bits then using "unsigned int" is the best solution.) Notice that we use a pointer per row, rather than a two-dimensional JSAMPLE array. This choice costs only a small amount of memory and has several benefits: * Code using the data structure doesn't need to know the allocated width of the rows. This will simplify edge expansion/compression, since we can work in an array that's wider than the logical picture width. * The rows forming a component array may be allocated at different times without extra copying. This will simplify working a few scanlines at a time, especially in smoothing steps that need access to the previous and next rows. * Indexing doesn't require multiplication; this is a performance win on many machines. Note that each color component is stored in a separate array; we don't use the traditional structure in which the components of a pixel are stored together. This simplifies coding of steps that work on each component independently, because they don't need to know how many components there are. Furthermore, we can read or write each component to a temp file independently, which is helpful when dealing with noninterleaved JPEG files. A specific sample value will be accessed by code such as GETJSAMPLE(image[colorcomponent][row][col]) where col is measured from the image left edge, but row is measured from the first sample row currently in memory. Either of the first two indexings can be precomputed by copying the relevant pointer. Pipeline steps that work on frequency-coefficient values will use the following data structure: typedef short JCOEF; a 16-bit signed integer typedef JCOEF JBLOCK[64]; an 8x8 block of coefficients typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays The underlying type is always a 16-bit signed integer (this is "short" on all machines of interest, but let's use the typedef name anyway). These are grouped into 8x8 blocks (we should use #defines DCTSIZE and DCTSIZE2 rather than "8" and "64"). The contents of a block may be either in "natural" or zigzagged order, and may be true values or divided by the quantization coefficients, depending on where the block is in the pipeline. Notice that the allocation unit is now a row of 8x8 blocks, corresponding to eight rows of samples. Otherwise the structure is much the same as for samples, and for the same reasons. On machines where malloc() can't handle a request bigger than 64Kb, this data structure limits us to rows of less than 512 JBLOCKs, which would be a picture width of 4000 pixels. This seems an acceptable restriction. On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) must be declared as "far" pointers, but the upper levels can be "near" (implying that the pointer lists are allocated in the DS segment). To simplify sharing code, we'll have a #define symbol FAR, which expands to the "far" keyword when compiling on 80x86 machines and to nothing elsewhere. The data arrays used as input and output of the DCT transform subroutine will be declared using a separate typedef; they could be arrays of "short", "int" or "long" independently of the above choices. This would depend on what is needed to make the compiler generate correct and efficient multiply/add code in the DCT inner loops. No significant speed or memory penalty will be paid to have a different representation than is used in the main image storage arrays, since some additional value-by-value processing is done at the time of creation or extraction of the DCT data anyway (e.g., add/subtract 128). *** Poor man's object-oriented programming *** It should be pretty clear by now that we have a lot of quasi-independent steps, many of which have several possible behaviors. To avoid cluttering the code with lots of switch statements, we'll use a simple form of object-style programming to separate out the different possibilities. For example, Huffman and arithmetic coding will be implemented as two separate modules that present the same external interface; at runtime, the calling code will access the proper module indirectly through an "object". We can get the limited features we need while staying within portable C. The basic tool is a function pointer. An "object" is just a struct containing one or more function pointer fields, each of which corresponds to a method name in real object-oriented languages. During initialization we fill in the function pointers with references to whichever module we have determined we need to use in this run. Then invocation of the module is done by indirecting through a function pointer; on most architectures this is no more expensive (and possibly cheaper) than a switch, which would be the only other way of making the required run-time choice. The really significant benefit, of course, is keeping the source code clean and well structured. For example, the interface for entropy decoding (Huffman or arithmetic decoding) might look like this: struct function_ptr_struct { ... /* Entropy decoding methods */ void (*prepare_for_scan) (); void (*get_next_mcu) (); ... }; typedef struct function_ptr_struct * function_ptrs; The struct pointer is what will actually be passed around. A call site might look like this: some_function (function_ptrs fptrs) { ... (*fptrs->get_next_mcu) (...); ... } (It might be worth inventing some specialized macros to hide the rather ugly syntax for method definition and call.) Note that the caller doesn't know how many different get_next_mcu procedures there are, what their real names are, nor how to choose which one to call. An important benefit of this scheme is that it is easy to provide multiple versions of any method, each tuned to a particular case. While a lot of precalculation might be done to select an optimal implementation of a method, the cost per invocation is constant. For example, the MCU extraction step might have a "generic" method, plus one or more "hardwired" methods for the most popular sampling factors; the hardwired methods would be faster because they'd use straight-line code instead of for-loops. The cost to determine which method to use is paid only once, at startup, and the selection criteria are hidden from the callers of the method. This plan differs a little bit from usual object-oriented structures, in that only one instance of each object class will exist during execution. The reason for having the class structure is that on different runs we may create different instances (choose to execute different modules). To minimize the number of object pointers that have to be passed around, it will be easiest to have just a few big structs containing all the method pointers. We'll actually use two such structs, one for "system-dependent" methods (memory allocation and error handling) and one for everything else. Because of this choice, it's best not to think of an "object" as a specific data structure. Rather, an "object" is just a group of related methods. There would typically be one or more C modules (source files) providing concrete implementations of those methods. You can think of the term "method" as denoting the common interface presented by some set of functions, and "object" as denoting a group of common method interfaces, or the total shared interface behavior of a group of modules. *** Data chunk sizes *** To make the cost of this object-oriented style really minimal, we should make sure that each method call does a fair amount of computation. To do that we should pass large chunks of data around; for example, the colorspace conversion method should process much more than one pixel per call. For many steps, the most natural unit of data seems to be an "MCU row". This consists of one complete horizontal strip of the image, as high as an MCU. In a noninterleaved scan, an MCU row is always eight samples high (when looking at samples) or one 8x8 block high (when looking at coefficients). In an interleaved scan, an MCU row consists of all the data for one horizontal row of MCUs; this may be from one to four blocks high (eight to thirty-two samples) depending on the sampling factors. The height and width of an MCU row may be different in each component. (Note that the height and width of an MCU row changes at the downsampling and upsampling steps. An unsubsampled image has the same size in each component. The preceding statements apply to the downsampled dimensions.) For example, consider a 1024-pixel-wide image using (2h:2v)(1h:1v)(1h:1v) subsampling. In the noninterleaved case, an MCU row of Y would contain 8x1024 samples or the same number of frequency coefficients, so it would occupy 8K bytes (samples) or 16K bytes (coefficients). An MCU row of Cb or Cr would contain 8x512 samples and occupy half as much space. In the interleaved case, an MCU row would contain 16x1024 Y samples, 8x512 Cb and 8x512 Cr samples, so a total of 24K (samples) or 48K (coefficients) would be needed. This is a reasonable amount of data to expect to retain in memory at one time. (Bear in mind that we'll usually need to have several MCU rows resident in memory at once, at the inputs and outputs to various pipeline steps.) The worst case is probably (2h:4v)(1h:1v)(1h:1v) interleaving (this uses 10 blocks per MCU, which is the maximum allowed by the spec). An MCU will then contain 32 sample rows worth of Y, so it would occupy 40K or 80K bytes for a 1024-pixel-wide image. The most memory-intensive step is probably cross-block smoothing, for which we'd need 3 MCU rows of coefficients as input and another one as output; that would be 320K of working storage. Anything much larger would not fit in an 80x86 machine. (To decompress wider pictures on an 80x86, we'll have to skip cross-block smoothing or else use temporary files.) This unit is thus a reasonable-sized chunk for passing through the pipeline. Of course, its major advantage is that it is a natural chunk size for the MCU assembly and disassembly steps to work with. For the entropy (Huffman or arithmetic) encoding/decoding steps, the most convenient chunk is a single MCU: one 8x8 block if not interleaved, three to ten such blocks if interleaved. The advantage of this is that when handling interleaved data, the blocks have the same sequence of component membership on each call. (For example, Y,Y,Y,Y,Cb,Cr when using (2h:2v)(1h:1v)(1h:1v) subsampling.) The code needs to know component membership so that it can apply the right set of compression coefficients to each block. A prebuilt array describing this membership can be used during each call. This chunk size also makes it easy to handle restart intervals: just count off one MCU per call and reinitialize when the count reaches zero (restart intervals are specified in numbers of MCU). For similar reasons, one MCU is also the best chunk size for the frequency coefficient quantization and dequantization steps. For downsampling and upsampling, the best chunk size is to have each call transform Vk sample rows from or to Vmax sample rows (Vk = this component's vertical sampling factor, Vmax = largest vertical sampling factor). There are eight such chunks in each MCU row. Using a whole MCU row as the chunk size would reduce function call overhead a fraction, but would imply more buffering to provide context for cross-pixel smoothing. *** Compression object structure *** I propose the following set of objects for the compressor. Here an "object" is the common interface for one or more modules having comparable functions. Most of these objects can be justified as information-hiding modules. I've indicated what information is private to each object/module. Note that in all cases, the caller of a method is expected to have allocated any storage needed for it to return its result. (Typically this storage can be re-used in successive calls, so malloc'ing and free'ing once per call is not reasonable.) Also, much of the context required (compression parameters, image size, etc) will be passed around in large common data structures, which aren't described here; see the header files. Notice that any object that might need to allocate working storage receives an "init" and a "term" call; "term" should be careful to free all allocated storage so that the JPEG system can be used multiple times during a program run. (For the same reason, depending on static initialization of variables is a no-no. The only exception to the free-all-allocated-storage rule is that storage allocated for the entire processing of an image need not be explicitly freed, since the memory manager's free_all cleanup will free it.) 1. Input file conversion to standardized form. This provides these methods: input_init: read the file header, report image size & component count. get_input_row: read one pixel row, return it in our standard format. input_term: finish up at the end. In implementations that support multiple input formats, input_init could set up an appropriate get_input_row method depending on the format it finds. Note that in most applications, the selection and opening of the input file will be under the control of the user interface module; and indeed the user interface may have already read the input header, so that all that input_init may have to do is return previously saved values. The behind-the-scenes interaction between this object and the user interface is not specified by this architecture. (Hides format of input image and mechanism used to read it. This code is likely to vary considerably from one implementation to another. Note that the color space and number of color components of the source are not hidden; but they are used only by the next object.) 2. Gamma and color space conversion. This provides three methods: colorin_init: initialization. get_sample_rows: read, convert, and return a specified number of pixel rows (not more than remain in the picture). colorin_term: finish up at the end. The most efficient approach seems to be for this object to call get_input_row directly, rather than being passed the input data; that way, any intermediate storage required can be local to this object. (get_sample_rows might tell get_input_row to read directly into its own output area and then convert in place; or it may do something different. For example, conversion in place wouldn't work if it is changing the number of color components.) The output of this step is in the standardized sample array format shown previously. (Hides all knowledge of color space semantics and conversion. Remaining modules only need to know the number of JPEG components.) 3. Edge expansion: needs only a single method. edge_expand: Given an NxM sample array, expand to a desired size (a multiple of the MCU dimensions) by duplicating the last row or column. Repeat for each component. Expansion will occur in place, so the caller must have pre-allocated enough storage. (I'm assuming that it is easier and faster to do this expansion than it is to worry about boundary conditions in the next two steps. Notice that vertical expansion will occur only once, at the bottom of the picture, so only horizontal expansion by a few pixels is speed-critical.) (This doesn't really hide any information, so maybe it could be a simple subroutine instead of a method. Depends on whether we want to be able to use alternative, optimized methods.) 4. Downsampling: this will be applied to one component at a time. downsample_init: initialize (precalculate convolution factors, for example). This will be called once per scan. downsample: Given a sample array, reduce it to a smaller number of samples using specified sampling factors. downsample_term: clean up at the end of a scan. If the current component has vertical sampling factor Vk and the largest sampling factor is Vmax, then the input is always Vmax sample rows (whose width is a multiple of Hmax) and the output is always Vk sample rows. Vmax additional rows above and below the nominal input rows are also passed for use by partial-pixel-averaging sampling methods. (Is this necessary?) At the top and bottom of the image, these extra rows are copies of the first or last actual input row. (This hides whether and how cross-pixel averaging occurs.) 5. MCU extraction (creation of a single sequence of 8x8 sample blocks). extract_init: initialize as needed. This will be called once per scan. extract_MCUs: convert a sample array to a sequence of MCUs. extract_term: clean up at the end of a scan. Given one or more MCU rows worth of image data, extract sample blocks in the appropriate order; pass these off to subsequent steps one MCU at a time. The input must be a multiple of the MCU dimensions. It will probably be most convenient for the DCT transform, frequency quantization, and zigzag reordering of each block to be done as simple subroutines of this step. Once a transformed MCU has been completed, it'll be passed off to a method call, which will be passed as a parameter to extract_MCUs. That routine might either encode and output the MCU immediately, or buffer it up for later output if we want to do global optimization of the entropy encoding coefficients. Note: when outputting a noninterleaved file this object will be called separately for each component. Direct output could be done for the first component, but the others would have to be buffered. (Again, an object mainly on the grounds that multiple instantiations might be useful.) 6. DCT transformation of each 8x8 block. This probably doesn't have to be a full-fledged method, but just a plain subroutine that will be called by MCU extraction. One 8x8 block will be processed per call. 7. Quantization scaling and zigzag reordering of the elements in each 8x8 block. (This can probably be a plain subroutine called once per block by MCU extraction; hard to see a need for multiple instantiations here.) 8. Entropy encoding (Huffman or arithmetic). entropy_encode_init: prepare for one scan. entropy_encode: accepts an MCU's worth of quantized coefficients, encodes and outputs them. entropy_encode_term: finish up at end of a scan (dump any buffered bytes, for example). The data output by this module will be sent to the entropy_output method provided by the pipeline controller. (It will probably be worth using buffering to pass multiple bytes per call of the output method.) The output method could be just write_jpeg_data, but might also be a dummy routine that counts output bytes (for use during cut-and-try coefficient optimization). (This hides which entropy encoding method is in use.) 9. JPEG file header construction. This will provide these methods: write_file_header: output the initial header. write_scan_header: output scan header (called once per component if noninterleaved mode). write_jpeg_data: the actual data output method for the preceding step. write_scan_trailer: finish up after one scan. write_file_trailer: finish up at end of file. Note that compressed data is passed to the write_jpeg_data method, in case a simple fwrite isn't appropriate for some reason. (This hides which variant JPEG file format is being written. Also, the actual mechanism for writing the file is private to this object and the user interface.) 10. Pipeline control. This object will provide the "main loop" that invokes all the pipeline objects. Note that we will need several different main loops depending on the situation (interleaved output or not, global optimization of encoding parameters or not, etc). This object will do most of the memory allocation, since it will provide the working buffers that are the inputs and outputs of the pipeline steps. (An object mostly to support multiple instantiations; however, overall memory management and sequencing of operations are known only here.) 11. Overall control. This module will provide at least two routines: jpeg_compress: the main entry point to the compressor. per_scan_method_selection: called by pipeline controllers for secondary method selection passes. jpeg_compress is invoked from the user interface after the UI has selected the input and output files and obtained values for all compression parameters that aren't dynamically determined. jpeg_compress performs basic initialization (e.g., calculating the size of MCUs), does the "global" method selection pass, and finally calls the selected pipeline control object. (Per-scan method selections will be invoked by the pipeline controller.) Note that jpeg_compress can't be a method since it is invoked prior to method selection. 12. User interface; this is the architecture's term for "the rest of the application program", i.e., that which invokes the JPEG compressor. In a standalone JPEG compression program the UI need be little more than a C main() routine and argument parsing code; but we can expect that the JPEG compressor may be incorporated into complex graphics applications, wherein the UI is much more complex. Much of the UI will need to be written afresh for each non-Unix-like platform the compressor is ported to. The UI is expected to supply input and output files and values for all non-automatically-chosen compression parameters. (Hence defaults are determined by the UI; we should provide helpful routines to fill in the recommended defaults.) The UI must also supply error handling routines and some mechanism for trace messages. (This module hides the user interface provided --- command line, interactive, etc. Except for error/message handling, the UI calls the portable JPEG code, not the other way around.) 13. (Optional) Compression parameter selection control. entropy_optimize: given an array of MCUs ready to be fed to entropy encoding, find optimal encoding parameters. The actual optimization algorithm ought to be separated out as an object, even though a special pipeline control method will be needed. (The pipeline controller only has to understand that the output of extract_MCUs must be built up as a virtual array rather than fed directly to entropy encoding and output. This pipeline behavior may also be useful for future implementation of hierarchical modes, etc.) To minimize the amount of control logic in the optimization module, the pipeline control doesn't actually hand over big-array pointers, but rather an "iterator": a function which knows how to scan the stored image. (This hides the details of the parameter optimization algorithm.) The present design doesn't allow for multiple passes at earlier points in the pipeline, but allowing that would only require providing some new pipeline control methods; nothing else need change. 14. A memory management object. This will provide methods to allocate "small" things and "big" things. Small things have to fit in memory and you get back direct pointers (this could be handled by direct calls to malloc, but it's cleaner not to assume malloc is the right routine). "Big" things mean buffered images for multiple passes, noninterleaved output, etc. In this case the memory management object will give you room for a few MCU rows and you have to ask for access to the next few; dumping and reloading in a temporary file will go on behind the scenes. (All big objects are image arrays containing either samples or coefficients, and will be scanned top-to-bottom some number of times, so we can apply this access model easily.) On a platform with virtual memory, the memory manager can treat small and big things alike: just malloc up enough virtual memory for the whole image, and let the operating system worry about swapping the image to disk. Most of the actual calls on the memory manager will be made from pipeline control objects; changing any data item from "small" to "big" status would require a new pipeline control object, since it will contain the logic to ask for a new chunk of a big thing. Thus, one way in which pipeline controllers will vary is in which structures they treat as big. The memory manager will need to be told roughly how much space is going to be requested overall, so that it can figure out how big a buffer is safe to allocate for a "big" object. (If it happens that you are dealing with a small image, you'd like to decide to keep it all in memory!) The most flexible way of doing this is to divide allocation of "big" objects into two steps. First, there will be one or more "request" calls that indicate the desired object sizes; then an "instantiate" call causes the memory manager to actually construct the objects. The instantiation must occur before the contents of any big object can be accessed. For 80x86 CPUs, we would like the code to be compilable under small or medium model, meaning that pointers are 16 bits unless explicitly declared FAR. Hence space allocated by the "small" allocator must fit into the 64Kb default data segment, along with stack space and global/static data. For normal JPEG operations we seem to need only about 32Kb of such space, so we are within the target (and have a reasonable slop for the needs of a surrounding application program). However, some color quantization algorithms need 64Kb or more of all-in-memory space in order to create color histograms. For this purpose, we will also support "medium" size things. These are semantically the same as "small" things but are referenced through FAR pointers. The following methods will be needed: alloc_small: allocate an object of given size; use for any random data that's not an image array. free_small: release same. alloc_medium: like alloc_small, but returns a FAR pointer. Use for any object bigger than a couple kilobytes. free_medium: release same. alloc_small_sarray: construct an all-in-memory image sample array. free_small_sarray: release same. alloc_small_barray, free_small_barray: ditto for block (coefficient) arrays. request_big_sarray: request a virtual image sample array. The size of the in-memory buffer will be determined by the memory manager, but it will always be a multiple of the passed-in MCU height. request_big_barray: ditto for block (coefficient) arrays. alloc_big_arrays: instantiate all the big arrays previously requested. This call will also pass some info about future memory demands, so that the memory manager can figure out how much space to leave unallocated. access_big_sarray: obtain access to a specified portion of a virtual image sample array. free_big_sarray: release a virtual sample array. access_big_barray, free_big_barray: ditto for block (coefficient) arrays. free_all: release any remaining storage. This is called before normal or error termination; the main reason why it must exist is to ensure that any temporary files will be deleted upon error termination. alloc_big_arrays will be called by the pipeline controller, which does most of the memory allocation anyway. The only reason for having separate request calls is to allow some of the other modules to get big arrays. The pipeline controller is required to give an upper bound on total future small-array requests, so that this space can be discounted. (A fairly conservative estimate will be adequate.) Future small-object requests aren't counted; the memory manager has to use a slop factor for those. 10K or so seems to be sufficient. (In an 80x86, small objects aren't an issue anyway, since they don't compete for far-heap space. "Medium"-size objects will have to be counted separately.) The distinction between sample and coefficient array routines is annoying, but it has to be maintained for machines in which "char *" is represented differently from "int *". On byte-addressable machines some of these methods could perhaps point to the same code. The array routines will operate on only 2-D arrays (one component at a time), since different components may require different-size arrays. (This object hides the knowledge of whether virtual memory is available, as well as the actual interface to OS and library support routines.) Note that any given implementation will presumably contain only one instantiation of input file header reading, overall control, user interface, and memory management. Thus these could be called as simple subroutines, without bothering with an object indirection. This is essential for overall control (which has to initialize the object structure); for consistency we will impose objectness on the other three. *** Decompression object structure *** I propose the following set of objects for decompression. The general comments at the top of the compression object section also apply here. 1. JPEG file scanning. This will provide these methods: read_file_header: read the file header, determine which variant JPEG format is in use, read everything through SOF. read_scan_header: read scan header (up through SOS). This is called after read_file_header and again after each scan; it returns TRUE if it finds SOS, FALSE if EOI. read_jpeg_data: fetch data for entropy decoder. resync_to_restart: try to recover from bogus data (see below). read_scan_trailer: finish up after one scan, prepare for another call of read_scan_header (may be a no-op). read_file_trailer: finish up at end of file (probably a no-op). The entropy decoder must deal with restart markers, but all other JPEG marker types will be handled in this object; useful data from the markers will be extracted into data structures available to subsequent routines. Note that on exit from read_file_header, only the SOF-marker data should be assumed valid (image size, component IDs, sampling factors); other data such as Huffman tables may not appear until after the SOF. The overall image size and colorspace can be determined after read_file_header, but not whether or how the data is interleaved. (This hides which variant JPEG file format is being read. In particular, for JPEG-in-TIFF the read_header routines might not be scanning standard JPEG markers at all; they could extract the data from TIFF tags. The user interface will already have opened the input file and possibly read part of the header before read_file_header is called.) When reading a file with a nonzero restart interval, the entropy decoder expects to see a correct sequence of restart markers. In some cases, these markers may be synthesized by the file-format module (a TIFF reader might do so, for example, using tile boundary pointers to determine where the restart intervals fall). If the incoming data is corrupted, the entropy decoder will read as far as the next JPEG marker, which may or may not be the expected next restart marker. If it isn't, resync_to_restart is called to try to locate a good place to resume reading. We make this heuristic a file-format-dependent operation since some file formats may have special info that's not available to the entropy decoder (again, TIFF is an example). Note that resync_to_restart is NOT called at the end of a scan; it is read_scan_trailer's responsibility to resync there. NOTE: for JFIF/raw-JPEG file format, the read_jpeg_data routine is actually supplied by the user interface; the jrdjfif module uses read_jpeg_data internally to scan the input stream. This makes it possible for the user interface module to single-handedly implement special applications like reading from a non-stdio source. For JPEG-in-TIFF format, the need for random access will make it impossible for this to work; hence the TIFF header module will override the UI-supplied read_jpeg_data routine. Non-stdio input from a TIFF file will require extensive surgery to the TIFF header module, if indeed it is practical at all. 2. Entropy (Huffman or arithmetic) decoding of the coefficient sequence. entropy_decode_init: prepare for one scan. entropy_decode: decodes and returns an MCU's worth of quantized coefficients per call. entropy_decode_term: finish up after a scan (may be a no-op). This will read raw data by calling the read_jpeg_data method (I don't see any reason to provide a further level of indirection). (This hides which entropy encoding method is in use.) 3. Quantization descaling and zigzag reordering of the elements in each 8x8 block. This will be folded into entropy_decode for efficiency reasons: many of the coefficients are zeroes, and this can be exploited most easily within entropy_decode since the encoding explicitly skips zeroes. 4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8 blocks back to separate components in pixel map order). disassemble_init: initialize. This will be called once per scan. disassemble_MCU: Given an MCU's worth of dequantized blocks, distribute them into the proper locations in a coefficient image array. disassemble_term: clean up at the end of a scan. Probably this should be called once per MCU row and should call the entropy decoder repeatedly to obtain the row's data. The output is always a multiple of an MCU's dimensions. (An object on the grounds that multiple instantiations might be useful.) 5. Cross-block smoothing per JPEG section K.8 or a similar algorithm. smooth_coefficients: Given three block rows' worth of a single component, emit a smoothed equivalent of the middle row. The "above" and "below" pointers may be NULL if at top/bottom of image. The pipeline controller will do the necessary buffering to provide the above/below context. Smoothing will be optional since a good deal of extra memory is needed to buffer the additional block rows. (This object hides the details of the smoothing algorithm.) 6. Inverse DCT transformation of each 8x8 block. reverse_DCT: given an MCU row's worth of blocks, perform inverse DCT on each block and output the results into an array of samples. We put this method into the jdmcu module for symmetry with the division of labor in compression. Note that the actual IDCT code is a separate source file. 7. Upsampling and smoothing: this will be applied to one component at a time. Note that cross-pixel smoothing, which was a separate step in the prototype code, will now be performed simultaneously with expansion. upsample_init: initialize (precalculate convolution factors, for example). This will be called once per scan. upsample: Given a sample array, enlarge it by specified sampling factors. upsample_term: clean up at the end of a scan. If the current component has vertical sampling factor Vk and the largest sampling factor is Vmax, then the input is always Vk sample rows (whose width is a multiple of Hk) and the output is always Vmax sample rows. Vk additional rows above and below the nominal input rows are also passed for use in cross-pixel smoothing. At the top and bottom of the image, these extra rows are copies of the first or last actual input row. (This hides whether and how cross-pixel smoothing occurs.) 8. Cropping to the original pixel dimensions (throwing away duplicated pixels at the edges). This won't be a separate object, just an adjustment of the nominal image size in the pipeline controller. 9. Color space reconversion and gamma adjustment. colorout_init: initialization. This will be passed the component data from read_file_header, and will determine the number of output components. color_convert: convert a specified number of pixel rows. Input and output are image arrays of same size but possibly different numbers of components. colorout_term: cleanup (probably a no-op except for memory dealloc). In practice will usually be given an MCU row's worth of pixel rows, except at the bottom where a smaller number of rows may be left over. Note that this object works on all the components at once. When quantizing colors, color_convert may be applied to the colormap instead of actual pixel data. color_convert is called by the color quantizer in this case; the pipeline controller calls color_convert directly only when not quantizing. (Hides all knowledge of color space semantics and conversion. Remaining modules only need to know the number of JPEG and output components.) 10. Color quantization (used only if a colormapped output format is requested). We use two different strategies depending on whether one-pass (on-the-fly) or two-pass quantization is requested. Note that the two-pass interface is actually designed to let the quantizer make any number of passes. color_quant_init: initialization, allocate working memory. In 1-pass quantization, should call put_color_map. color_quantize: convert a specified number of pixel rows. Input and output are image arrays of same size, but input is N coefficients and output is only one. (Used only in 1-pass quantization.) color_quant_prescan: prescan a specified number of pixel rows in 2-pass quantization. color_quant_doit: perform multi-pass color quantization. Input is a "big" sample image, output is via put_color_map and put_pixel_rows. (Used only in 2-pass quantization.) color_quant_term: cleanup (probably a no-op except for memory dealloc). The input to the color quantizer is always in the unconverted colorspace; its output colormap must be in the converted colorspace. The quantizer has the choice of which space to work in internally. It must call color_convert either on its input data or on the colormap it sends to the output module. For one-pass quantization the image is simply processed by color_quantize, a few rows at a time. For two-pass quantization, the pipeline controller accumulates the output of steps 1-8 into a "big" sample image. The color_quant_prescan method is invoked during this process so that the quantizer can accumulate statistics. (If the input file has multiple scans, the prescan may be done during the final scan or as a separate pass.) At the end of the image, color_quant_doit is called; it must create and output a colormap, then rescan the "big" image and pass mapped data to the output module. Additional scans of the image could be made before the output pass is done (in fact, prescan could be a no-op). As with entropy parameter optimization, the pipeline controller actually passes an iterator function rather than direct access to the big image. (Hides color quantization algorithm.) 11. Writing of the desired image format. output_init: produce the file header given data from read_file_header. put_color_map: output colormap, if any (called by color quantizer). If used, must be called before any pixel data is output. put_pixel_rows: output image data in desired format. output_term: finish up at the end. The actual timing of I/O may differ from that suggested by the routine names; for instance, writing of the file header may be delayed until put_color_map time if the actual number of colors is needed in the header. Also, the colormap is available to put_pixel_rows and output_term as well as put_color_map. Note that whether colormapping is needed will be determined by the user interface object prior to method selection. In implementations that support multiple output formats, the actual output format will also be determined by the user interface. (Hides format of output image and mechanism used to write it. Note that several other objects know the color model used by the output format. The actual mechanism for writing the file is private to this object and the user interface.) 12. Pipeline control. This object will provide the "main loop" that invokes all the pipeline objects. Note that we will need several different main loops depending on the situation (interleaved input or not, whether to apply cross-block smoothing or not, etc). We may want to divvy up the pipeline controllers into two levels, one that retains control over the whole file and one that is invoked per scan. This object will do most of the memory allocation, since it will provide the working buffers that are the inputs and outputs of the pipeline steps. (An object mostly to support multiple instantiations; however, overall memory management and sequencing of operations are known only here.) 13. Overall control. This module will provide at least two routines: jpeg_decompress: the main entry point to the decompressor. per_scan_method_selection: called by pipeline controllers for secondary method selection passes. jpeg_decompress is invoked from the user interface after the UI has selected the input and output files and obtained values for all user-specified options (e.g., output file format, whether to do block smoothing). jpeg_decompress calls read_file_header, performs basic initialization (e.g., calculating the size of MCUs), does the "global" method selection pass, and finally calls the selected pipeline control object. (Per-scan method selections will be invoked by the pipeline controller.) Note that jpeg_decompress can't be a method since it is invoked prior to method selection. 14. User interface; this is the architecture's term for "the rest of the application program", i.e., that which invokes the JPEG decompressor. The UI is expected to supply input and output files and values for all operational parameters. The UI must also supply error handling routines. (This module hides the user interface provided --- command line, interactive, etc. Except for error handling, the UI calls the portable JPEG code, not the other way around.) 15. A memory management object. This will be identical to the memory management for compression (and will be the same code, in combined programs). See above for details. *** Initial method selection *** The main ugliness in this design is the portion of startup that will select which of several instantiations should be used for each of the objects. (For example, Huffman or arithmetic for entropy encoding; one of several pipeline controllers depending on interleaving, the size of the image, etc.) It's not really desirable to have a single chunk of code that knows the names of all the possible instantiations and the conditions under which to select each one. The best approach seems to be to provide a selector function for each object (group of related method calls). This function knows about each possible instantiation of its object and how to choose the right one; but it doesn't know about any other objects. Note that there will be several rounds of method selection: at initial startup, after overall compression parameters are determined (after the file header is read, if decompressing), and one in preparation for each scan (this occurs more than once if the file is noninterleaved). Each object method will need to be clearly identified as to which round sets it up. *** Implications of DNL marker *** Some JPEG files may use a DNL marker to postpone definition of the image height (this would be useful for a fax-like scanner's output, for instance). In these files the SOF marker claims the image height is 0, and you only find out the true image height at the end of the first scan. We could handle these files as follows: 1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). 2. When the DNL is found, update the image height in the global image descriptor. This implies that pipeline control objects must avoid making copies of the image height, and must re-test for termination after each MCU row. This is no big deal. In situations where image-size data structures are allocated, this approach will result in very inefficient use of virtual memory or much-larger-than-necessary temporary files. This seems acceptable for something that probably won't be a mainstream usage. People might have to forgo use of memory-hogging options (such as two-pass color quantization or noninterleaved JPEG files) if they want efficient conversion of such files. (One could improve efficiency by demanding a user-supplied upper bound for the height, less than 65536; in most cases it could be much less.) Alternately, we could insist that DNL-using files be preprocessed by a separate program that reads ahead to the DNL, then goes back and fixes the SOF marker. This is a much simpler solution and is probably far more efficient. Even if one wants piped input, buffering the first scan of the JPEG file needs a lot smaller temp file than is implied by the maximum-height method. For this approach we'd simply treat DNL as a no-op in the decompressor (at most, check that it matches the SOF image height). We will not worry about making the compressor capable of outputting DNL. Something similar to the first scheme above could be applied if anyone ever wants to make that work. *** Memory manager internal structure *** The memory manager contains the most potential for system dependencies. To isolate system dependencies as much as possible, we have broken the memory manager into two parts. There is a reasonably system-independent "front end" (jmemmgr.c) and a "back end" that contains only the code likely to change across systems. All of the memory management methods outlined above are implemented by the front end. The back end provides the following routines for use by the front end (none of these routines are known to the rest of the JPEG code): jmem_init, jmem_term system-dependent initialization/shutdown jget_small, jfree_small interface to malloc and free library routines jget_large, jfree_large interface to FAR malloc/free in MS-DOS machines; otherwise same as jget_small/jfree_small jmem_available estimate available memory jopen_backing_store create a backing-store object read_backing_store, manipulate a backing store object write_backing_store, close_backing_store On some systems there will be more than one type of backing-store object (specifically, in MS-DOS a backing store file might be an area of extended memory as well as a disk file). jopen_backing_store is responsible for choosing how to implement a given object. The read/write/close routines are method pointers in the structure that describes a given object; this lets them be different for different object types. It may be necessary to ensure that backing store objects are explicitly released upon abnormal program termination. (For example, MS-DOS won't free extended memory by itself.) To support this, we will expect the main program or surrounding application to arrange to call the free_all method upon abnormal termination; this may require a SIGINT signal handler, for instance. (We don't want to have the system-dependent module install its own signal handler, because that would pre-empt the surrounding application's ability to control signal handling.) *** Notes for MS-DOS implementors *** The standalone cjpeg and djpeg applications can be compiled in "small" memory model, at least at the moment; as the code grows we may be forced to switch to "medium" model. (Small = both code and data pointers are near by default; medium = far code pointers, near data pointers.) Medium model will slow down calls through method pointers, but I don't think this will amount to any significant speed penalty. When integrating the JPEG code into a larger application, it's a good idea to stay with a small-data-space model if possible. An 8K stack is much more than sufficient for the JPEG code, and its static data requirements are less than 1K. When executed, it will typically malloc about 10K-20K worth of near heap space (and lots of far heap, but that doesn't count in this calculation). This figure will vary depending on image size and other factors, but figuring 30K should be more than sufficient. Thus you have about 25K available for other modules' static data and near heap requirements before you need to go to a larger memory model. The C library's static data will account for several K of this, but that still leaves a good deal for your needs. (If you are tight on space, you could reduce JPEG_BUF_SIZE from 4K to 1K to save 3K of near heap space.) As the code is improved, we will endeavor to hold the near data requirements to the range given above. This does imply that certain data structures will be allocated as FAR although they would fit in near space if we assumed the JPEG code is stand-alone. (The LZW tables in jrdgif/jwrgif are examples.) To make an optimal implementation, you might want to move these structures back to near heap if you know there is sufficient space. FAR data space may also be a tight resource when you are dealing with large images. The most memory-intensive case is decompression with two-pass color quantization. This requires a 128Kb color histogram plus strip buffers amounting to about 150 bytes per column for typical sampling ratios (eg, about 96000 bytes for a 640-pixel-wide image). You may not be able to process wide images if you have large data structures of your own. *** Potential optimizations *** For colormapped input formats it might be worthwhile to merge the input file reading and the colorspace conversion steps; in other words, do the colorspace conversion by hacking up the colormap before inputting the image body, rather than doing the conversion on each pixel independently. Not clear if this is worth the uglification involved. In the above design for the compressor, only the colorspace conversion step ever sees the output of get_input_row, so this sort of thing could be done via private agreement between those two modules. Level shift from 0..255 to -128..127 may be done either during colorspace conversion, or at the moment of converting an 8x8 sample block into the format used by the DCT step (which will be signed short or long int). This could be selectable by a compile-time flag, so that the intermediate steps can work on either signed or unsigned chars as samples, whichever is most easily handled by the platform. However, making sure that rounding is done right will be a lot easier if we can assume positive values. At the moment I think that benefit is worth the overhead of "& 0xFF" when reading out sample values on signed-char-only machines. nding on ixloadimage.4.1/jpeg/cjpeg.1 644 221 144 17236 5276101171 10666 .TH CJPEG 1 "4 November 1992" .SH NAME cjpeg \- compress an image file to a JPEG file .SH SYNOPSIS .B cjpeg [ .BI \-quality " N" ] [ .B \-grayscale ] [ .B \-optimize ] [ .B \-targa ] [ .BI \-maxmemory " N" ] [ .BI \-restart " N" ] [ .BI \-smooth " N" ] [ .B \-verbose ] [ .B \-debug ] [ .B \-arithmetic ] [ .B \-nointerleave ] [ .BI \-qtables " file" ] [ .BI \-sample " HxV[,...]" ] [ .I filename ] .LP .SH DESCRIPTION .LP .B cjpeg compresses the named image file, or the standard input if no file is named, and produces a JPEG/JFIF file on the standard output. The currently supported input file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available.) .SH OPTIONS All switch names may be abbreviated; for example, .B \-grayscale may be written .B \-gray or .BR \-gr . Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (thus .B \-GIF is the same as .BR \-gif ). British spellings are also accepted (e.g., .BR \-greyscale ), though for brevity these are not mentioned below. .PP The basic switches are: .TP .BI \-quality " N" Scale quantization tables to adjust image quality. Quality is 0 (worst) to 100 (best); default is 75. (See below for more info.) .TP .B \-grayscale Create monochrome JPEG file from color input. Be sure to use this switch when compressing a grayscale GIF file, because .B cjpeg isn't bright enough to notice whether a GIF file uses only shades of gray. By saying .BR \-grayscale , you'll get a smaller JPEG file that takes less time to process. .TP .B \-optimize Perform optimization of entropy encoding parameters. Without this, default encoding parameters are used. .B \-optimize usually makes the JPEG file a little smaller, but .B cjpeg runs somewhat slower and needs much more memory. Image quality and speed of decompression are unaffected by .BR \-optimize . .TP .B \-targa Input file is Targa format. Targa files that contain an "identification" field will not be automatically recognized by .BR cjpeg ; for such files you must specify .B \-targa to make .B cjpeg treat the input as Targa format. .PP The .B \-quality switch lets you trade off compressed file size against quality of the reconstructed image: the higher the quality setting, the larger the JPEG file, and the closer the output image will be to the original input. Normally you want to use the lowest quality setting (smallest file) that decompresses into something visually indistinguishable from the original image. For this purpose the quality setting should be between 50 and 95; the default of 75 is often about right. If you see defects at .B \-quality 75, then go up 5 or 10 counts at a time until you are happy with the output image. (The optimal setting will vary from one image to another.) .PP .B \-quality 100 will generate a quantization table of all 1's, eliminating loss in the quantization step (but there is still information loss in subsampling, as well as roundoff error). This setting is mainly of interest for experimental purposes. Quality values above about 95 are .B not recommended for normal use; the compressed file size goes up dramatically for hardly any gain in output image quality. .PP In the other direction, quality values below 50 will produce very small files of low image quality. Settings around 5 to 10 might be useful in preparing an index of a large image library, for example. Try .B \-quality 2 (or so) for some amusing Cubist effects. (Note: quality values below about 25 generate 2-byte quantization tables, which are considered optional in the JPEG standard. .B cjpeg emits a warning message when you give such a quality value, because some commercial JPEG programs may be unable to decode the resulting file.) .PP Switches for advanced users: .TP .BI \-maxmemory " N" Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. .TP .BI \-restart " N" Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. .B \-restart 0 (the default) means no restart markers. .TP .BI \-smooth " N" Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. .TP .B \-verbose Enable debug printout. More .BR \-v 's give more output. Also, version information is printed at startup. .TP .B \-debug Same as .BR \-verbose . .PP The .B \-restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage to a compressed file will usually ruin the image from the point of the error to the end of the image; with restart markers, the damage is usually confined to the portion of the image up to the next restart marker. Of course, the restart markers occupy extra space. We recommend .B \-restart 1 for images that will be transmitted across unreliable networks such as Usenet. .PP The .B \-smooth option filters the input to eliminate fine-scale noise. This is often useful when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50 gets rid of dithering patterns in the input file, resulting in a smaller JPEG file and a better-looking image. Too large a smoothing factor will visibly blur the image, however. .PP Switches for wizards: .TP .B \-arithmetic Use arithmetic coding rather than Huffman coding. (Not currently supported for legal reasons.) .TP .B \-nointerleave Generate noninterleaved JPEG file (not yet supported). .TP .BI \-qtables " file" Use the quantization tables given in the specified file. The file should contain one to four tables (64 values each) as plain text. Comments preceded by '#' may be included in the file. The tables are implicitly numbered 0,1,etc. If .B \-quality N is also specified, the values in the file are scaled according to .BR cjpeg 's quality scaling curve. .TP .BI \-sample " HxV[,...]" Set JPEG sampling factors. If you specify fewer H/V pairs than there are components, the remaining components are set to 1x1 sampling. The default setting is equivalent to \fB\-sample 2x2\fR. .PP The "wizard" switches are intended for experimentation with JPEG. If you don't know what you are doing, \fBdon't use them\fR. You can easily produce files with worse image quality and/or poorer compression than you'll get from the default settings. Furthermore, these switches should not be used when making files intended for general use, because not all JPEG implementations will support unusual JPEG parameter settings. .SH EXAMPLES .LP This example compresses the PPM file foo.ppm with a quality factor of 60 and saves the output as foo.jpg: .IP .B cjpeg \-quality .I 60 foo.ppm .B > .I foo.jpg .SH ENVIRONMENT .TP .B JPEGMEM If this environment variable is set, its value is the default memory limit. The value is specified as described for the .B \-maxmemory switch. .B JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit .BR \-maxmemory . .SH SEE ALSO .BR djpeg (1) .br .BR ppm (5), .BR pgm (5) .br Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. .SH AUTHOR Independent JPEG Group .SH BUGS Arithmetic coding and interleaved output not yet supported. .PP Not all variants of Targa file format are supported. .PP The .B -targa switch is not a bug, it's a feature. (It would be a bug if the Targa format designers had not been clueless.) .PP Still not as fast as we'd like. group of related method calls). This function knows about each possible instantiation of its object and how to choose the right one; but it doesn't know about any other objects. Note that there will be several rounds of method selection: at initial startup, after overall compression parameters are determined (after the file header is read, if decomprxloadimage.4.1/jpeg/ckconfig.c 644 221 144 31335 5234102150 11427 /* * ckconfig.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. */ /* * This program is intended to help you determine how to configure the JPEG * software for installation on a particular system. The idea is to try to * compile and execute this program. If your compiler fails to compile the * program, make changes as indicated in the comments below. Once you can * compile the program, run it, and it will tell you how to set the various * switches in jconfig.h and in your Makefile. * * This could all be done automatically if we could assume we were on a Unix * system, but we don't want to assume that, so you'll have to edit and * recompile this program until it works. * * As a general rule, each time you try to compile this program, * pay attention only to the *first* error message you get from the compiler. * Many C compilers will issue lots of spurious error messages once they * have gotten confused. Go to the line indicated in the first error message, * and read the comments preceding that line to see what to change. * * Almost all of the edits you may need to make to this program consist of * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL", * or vice versa. This is called defining or undefining that symbol. */ /* First we must see if your system has the include files we need. * We start out with the assumption that your system follows the ANSI * conventions for include files. If you get any error in the next dozen * lines, undefine INCLUDES_ARE_ANSI. */ #define INCLUDES_ARE_ANSI /* replace 'define' by 'undef' if error here */ #ifdef INCLUDES_ARE_ANSI /* this will be skipped if you undef... */ #include /* If you ain't got this, you ain't got C. */ #ifdef __SASC /* Amiga SAS C provides size_t in stddef.h. */ #include /* (They are wrong...) */ #endif #include /* size_t might be here too. */ typedef size_t my_size_t; /* The payoff: do we have size_t now? */ #include /* Check other ANSI includes we use. */ #endif /* If your system doesn't follow the ANSI conventions, we have to figure out * what it does follow. If you didn't get an error before this line, you can * ignore everything down to "#define HAVE_ANSI_DEFINITIONS". */ #ifndef INCLUDES_ARE_ANSI /* skip these tests if INCLUDES_ARE_ANSI */ #include /* If you ain't got this, you ain't got C. */ /* jinclude.h will try to include if you don't set * INCLUDES_ARE_ANSI. We need to test whether that include file is provided. * If you get an error here, undefine HAVE_TYPES_H. */ #define HAVE_TYPES_H #ifdef HAVE_TYPES_H #include #endif /* We have to see if your string functions are defined by * strings.h (BSD convention) or string.h (everybody else). * We try the non-BSD convention first; define BSD if the compiler * says it can't find string.h. */ #undef BSD #ifdef BSD #include #else #include #endif /* Usually size_t is defined in stdio.h, sys/types.h, and/or string.h. * If not, you'll get an error on the "typedef size_t my_size_t;" line below. * In that case, you'll have to search through your system library to * figure out which include file defines "size_t". Look for a line that * says "typedef something-or-other size_t;" (stddef.h and stdlib.h are * good places to look first). Then, change the line below that says * "#include " to instead include the file * you found size_t in, and define NEED_SPECIAL_INCLUDE. */ #undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ #ifdef NEED_SPECIAL_INCLUDE #include #endif typedef size_t my_size_t; /* The payoff: do we have size_t now? */ #endif /* INCLUDES_ARE_ANSI */ /* The next question is whether your compiler supports ANSI-style function * definitions. You need to know this in order to choose between using * makefile.ansi and using makefile.unix. * The #define line below is set to assume you have ANSI function definitions. * If you get an error in this group of lines, undefine HAVE_ANSI_DEFINITIONS. */ #define HAVE_ANSI_DEFINITIONS #ifdef HAVE_ANSI_DEFINITIONS int testfunction (int arg1, int * arg2); /* check prototypes */ struct methods_struct { /* check method-pointer declarations */ int (*error_exit) (char *msgtext); int (*trace_message) (char *msgtext); int (*another_method) (void); }; int testfunction (int arg1, int * arg2) /* check definitions */ { return arg2[arg1]; } int testfunction1 (void) /* check void arg list */ { return 0; } #endif /* Now we want to find out if your compiler knows what "unsigned char" means. * If you get an error on the "unsigned char un_char;" line, * then undefine HAVE_UNSIGNED_CHAR. */ #define HAVE_UNSIGNED_CHAR #ifdef HAVE_UNSIGNED_CHAR unsigned char un_char; #endif /* Now we want to find out if your compiler knows what "unsigned short" means. * If you get an error on the "unsigned short un_short;" line, * then undefine HAVE_UNSIGNED_SHORT. */ #define HAVE_UNSIGNED_SHORT #ifdef HAVE_UNSIGNED_SHORT unsigned short un_short; #endif /* Now we want to find out if your compiler understands type "void". * If you get an error anywhere in here, undefine HAVE_VOID. */ #define HAVE_VOID #ifdef HAVE_VOID typedef void * void_ptr; /* check void * */ typedef void (*void_func) (); /* check ptr to function returning void */ void testfunction2 (arg1, arg2) /* check void function result */ void_ptr arg1; void_func arg2; { char * locptr = (char *) arg1; /* check casting to and from void * */ arg1 = (void *) locptr; (*arg2) (1, 2); /* check call of fcn returning void */ } #endif /* Now we want to find out if your compiler knows what "const" means. * If you get an error here, undefine HAVE_CONST. */ #define HAVE_CONST #ifdef HAVE_CONST static const int carray[3] = {1, 2, 3}; int testfunction3 (arg1) const int arg1; { return carray[arg1]; } #endif /************************************************************************ * OK, that's it. You should not have to change anything beyond this * point in order to compile and execute this program. (You might get * some warnings, but you can ignore them.) * When you run the program, it will make a couple more tests that it * can do automatically, and then it will print out a summary of the changes * that you need to make to the makefile and jconfig.h. ************************************************************************ */ static int any_changes = 0; int new_change () { if (! any_changes) { printf("\nMost of the changes recommended by this program can be made either\n"); printf("by editing jconfig.h, or by adding -Dsymbol switches to the CFLAGS\n"); printf("line in your Makefile. (Some PC compilers expect /Dsymbol instead.)\n"); printf("The CFLAGS method is simpler, but if your compiler doesn't support -D,\n"); printf("then you must change jconfig.h. Also, it's best to change jconfig.h\n"); printf("if you plan to use the JPEG software as a library for other programs.\n"); any_changes = 1; } printf("\n"); /* blank line before each problem report */ return 0; } int test_char_sign (arg) int arg; { if (arg == 189) { /* expected result for unsigned char */ new_change(); printf("You should add -DCHAR_IS_UNSIGNED to CFLAGS,\n"); printf("or else remove the /* */ comment marks from the line\n"); printf("/* #define CHAR_IS_UNSIGNED */ in jconfig.h.\n"); printf("(Be sure to delete the space before the # character too.)\n"); } else if (arg != -67) { /* expected result for signed char */ new_change(); printf("Hmm, it seems 'char' is less than eight bits wide on your machine.\n"); printf("I fear the JPEG software will not work at all.\n"); } return 0; } int test_shifting (arg) long arg; /* See whether right-shift on a long is signed or not. */ { long res = arg >> 4; if (res == 0x80817F4L) { /* expected result for unsigned */ new_change(); printf("You must add -DRIGHT_SHIFT_IS_UNSIGNED to CFLAGS,\n"); printf("or else remove the /* */ comment marks from the line\n"); printf("/* #define RIGHT_SHIFT_IS_UNSIGNED */ in jconfig.h.\n"); } else if (res != -0x7F7E80CL) { /* expected result for signed */ new_change(); printf("Right shift isn't acting as I expect it to.\n"); printf("I fear the JPEG software will not work at all.\n"); } return 0; } int main (argc, argv) int argc; char ** argv; { char signed_char_check = (char) (-67); printf("Results of configuration check for Independent JPEG Group's software:\n"); printf("\nIf there's not a specific makefile provided for your compiler,\n"); #ifdef HAVE_ANSI_DEFINITIONS printf("you should use makefile.ansi as the starting point for your Makefile.\n"); #else printf("you should use makefile.unix as the starting point for your Makefile.\n"); #endif /* Check whether we have all the ANSI features, */ /* and whether this agrees with __STDC__ being predefined. */ #ifdef __STDC__ #define HAVE_STDC /* ANSI compilers won't allow redefining __STDC__ */ #endif #ifdef HAVE_ANSI_DEFINITIONS #ifdef HAVE_UNSIGNED_CHAR #ifdef HAVE_UNSIGNED_SHORT #ifdef HAVE_CONST #define HAVE_ALL_ANSI_FEATURES #endif #endif #endif #endif #ifdef HAVE_ALL_ANSI_FEATURES #ifndef HAVE_STDC new_change(); printf("Your compiler doesn't claim to be ANSI-compliant, but it is close enough\n"); printf("for me. Either add -DHAVE_STDC to CFLAGS, or add #define HAVE_STDC at the\n"); printf("beginning of jconfig.h.\n"); #define HAVE_STDC #endif #else /* !HAVE_ALL_ANSI_FEATURES */ #ifdef HAVE_STDC new_change(); printf("Your compiler claims to be ANSI-compliant, but it is lying!\n"); printf("Delete the line #define HAVE_STDC near the beginning of jconfig.h.\n"); #undef HAVE_STDC #endif #endif /* HAVE_ALL_ANSI_FEATURES */ #ifndef HAVE_STDC #ifdef HAVE_ANSI_DEFINITIONS new_change(); printf("You should add -DPROTO to CFLAGS, or else take out the several\n"); printf("#ifdef/#else/#endif lines surrounding #define PROTO in jconfig.h.\n"); printf("(Leave only one #define PROTO line.)\n"); #endif #ifdef HAVE_UNSIGNED_CHAR #ifdef HAVE_UNSIGNED_SHORT new_change(); printf("You should add -DHAVE_UNSIGNED_CHAR and -DHAVE_UNSIGNED_SHORT\n"); printf("to CFLAGS, or else take out the #ifdef HAVE_STDC/#endif lines\n"); printf("surrounding #define HAVE_UNSIGNED_CHAR and #define HAVE_UNSIGNED_SHORT\n"); printf("in jconfig.h.\n"); #else /* only unsigned char */ new_change(); printf("You should add -DHAVE_UNSIGNED_CHAR to CFLAGS,\n"); printf("or else move #define HAVE_UNSIGNED_CHAR outside the\n"); printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n"); #endif #else /* !HAVE_UNSIGNED_CHAR */ #ifdef HAVE_UNSIGNED_SHORT new_change(); printf("You should add -DHAVE_UNSIGNED_SHORT to CFLAGS,\n"); printf("or else move #define HAVE_UNSIGNED_SHORT outside the\n"); printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n"); #endif #endif /* HAVE_UNSIGNED_CHAR */ #ifdef HAVE_CONST new_change(); printf("You should delete the #define const line from jconfig.h.\n"); #endif #endif /* HAVE_STDC */ test_char_sign((int) signed_char_check); test_shifting(-0x7F7E80B1L); #ifndef HAVE_VOID new_change(); printf("You should add -Dvoid=char to CFLAGS,\n"); printf("or else remove the /* */ comment marks from the line\n"); printf("/* #define void char */ in jconfig.h.\n"); printf("(Be sure to delete the space before the # character too.)\n"); #endif #ifdef INCLUDES_ARE_ANSI #ifndef __STDC__ new_change(); printf("You should add -DINCLUDES_ARE_ANSI to CFLAGS, or else add\n"); printf("#define INCLUDES_ARE_ANSI at the beginning of jinclude.h (NOT jconfig.h).\n"); #endif #else /* !INCLUDES_ARE_ANSI */ #ifdef __STDC__ new_change(); printf("You should add -DNONANSI_INCLUDES to CFLAGS, or else add\n"); printf("#define NONANSI_INCLUDES at the beginning of jinclude.h (NOT jconfig.h).\n"); #endif #ifdef NEED_SPECIAL_INCLUDE new_change(); printf("In jinclude.h, change the line reading #include \n"); printf("to instead include the file you found size_t in.\n"); #else /* !NEED_SPECIAL_INCLUDE */ #ifndef HAVE_TYPES_H new_change(); printf("In jinclude.h, delete the line reading #include .\n"); #endif #endif /* NEED_SPECIAL_INCLUDE */ #ifdef BSD new_change(); printf("You should add -DBSD to CFLAGS, or else add\n"); printf("#define BSD at the beginning of jinclude.h (NOT jconfig.h).\n"); #endif #endif /* INCLUDES_ARE_ANSI */ if (any_changes) { printf("\nI think that's everything...\n"); } else { printf("\nI think jconfig.h is OK as distributed.\n"); } return any_changes; } . * If you get an error on the "unsigned char un_char;" line, * then undefine HAVE_UNSIGNED_CHAR. */ #define HAVE_UNSIGNED_CHAR #ifdef HAVE_UNSIGNED_CHAR unsigned char un_char; #endif /* Now we want to find out if your compiler knows what "unsigned short" means. * If you get an erroxloadimage.4.1/jpeg/codingrules 644 221 144 7554 5070761607 11747 JPEG SYSTEM CODING RULES 27-SEP-91 Since numerous people will be contributing code and bug fixes, it's important to establish a common coding style. The goal of using similar coding styles is much more important than the details of just what that style is. I suggest we follow the recommendations of "Recommended C Style and Coding Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and Brader). I have placed a copy of this document in the jpeg FTP archive (see jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). Unless someone has a real strong objection, let's do block comments thusly: /* * Block comments in this style. */ and indent statements in K&R style, e.g., if (test) { then-part; } else { else-part; } I suggest that multi-word names be written in the style multi_word_name rather than multiWordName, but I am open to argument on this. I would like to use function prototypes everywhere, and rely on automatic source code transformation to feed non-ANSI C compilers. The best tool I have so far found for this is 'ansi2knr.c', which is part of Ghostscript. ansi2knr is not very bright, so it imposes a format requirement on function declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions should be written in the following style: static int * function_name (int a, char *b) { code... } ansi2knr won't help with method declarations (function pointers in structs). I suggest we use a macro to declare method pointers, something like this: #ifdef PROTO #define METHOD(type,methodname,arglist) type (*methodname) arglist #else #define METHOD(type,methodname,arglist) type (*methodname) () #endif which is used like this: struct function_pointers { METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp)); METHOD(void, term_entropy_encoder, (void)); }; Note the set of parentheses surrounding the parameter list. A similar solution is used for external function declarations (see the PP macro in jpegdata.h). If the code is to work on non-ANSI compilers, you cannot rely on a prototype declaration to coerce actual parameters into the right types. Therefore, use explicit casts on actual parameters whenever the actual parameter type is not identical to the formal parameter. Beware of implicit conversions to "int". It seems there are some non-ANSI compilers in which the sizeof() operator is defined to return int, while size_t is defined as long. Needless to say, this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), so that the result is guaranteed to be of type size_t. We can expect that the JPEG compressor and decompressor will be incorporated into larger programs. Therefore, the following rules are important: 1. Avoid direct use of any file I/O, "malloc", error report printouts, etc; pass these through the common routines provided. 2. Assume that the JPEG code may be invoked more than once per program run; therefore, do not rely on static initialization of variables, and be careful to release all allocated storage at the end of processing. 3. Minimize global namespace pollution. Functions should be declared static wherever possible. (Note that our method-based calling conventions help this a lot: in many modules only the method-selector function will ever need to be called directly, so only that function need be externally visible.) All global function names should begin with "j", and should be unique in the first six characters for portability reasons. Don't use global variables at all; anything that must be used in another module should be put into parameters (there'll be some large structs passed around for this purpose). 4. Source file names should also begin with "j"; remember to keep them to eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Do not put code for both compression and decompression into the same source file. *************************************************** */ static int any_changes = 0; int new_change () { if (! any_changes) { printf("\nMostxloadimage.4.1/jpeg/djpeg.1 644 221 144 10662 5340514466 10672 .TH DJPEG 1 "17 February 1993" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS .B djpeg [ .BI \-colors " N" ] [ .B \-gif ] [ .B \-pnm ] [ .B \-rle ] [ .B \-targa ] [ .B \-blocksmooth ] [ .B \-grayscale ] [ .BI \-maxmemory " N" ] [ .B \-nodither ] [ .B \-onepass ] [ .B \-verbose ] [ .B \-debug ] [ .I filename ] .LP .SH DESCRIPTION .LP .B djpeg decompresses the named JPEG file, or the standard input if no file is named, and produces an image file on the standard output. PBMPLUS (PPM/PGM), GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected. (RLE is supported only if the URT library is available.) .SH OPTIONS All switch names may be abbreviated; for example, .B \-grayscale may be written .B \-gray or .BR \-gr . Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (thus .B \-GIF is the same as .BR \-gif ). British spellings are also accepted (e.g., .BR \-greyscale ), though for brevity these are not mentioned below. .PP The basic switches are: .TP .BI \-colors " N" Reduce image to at most N colors. This reduces the number of colors used in the output image, so that it can be displayed on a colormapped display or stored in a colormapped file format. For example, if you have an 8-bit display, you'd need to reduce to 256 or fewer colors. .TP .BI \-quantize " N" Same as .BR \-colors . .B \-colors is the recommended name, .B \-quantize is provided only for backwards compatibility. .TP .B \-gif Select GIF output format. Since GIF does not support more than 256 colors, .B \-colors 256 is assumed (unless you specify a smaller number of colors). .TP .B \-pnm Select PBMPLUS (PPM/PGM) output format (this is the default format). PGM is emitted if the JPEG file is gray-scale or if .B \-grayscale is specified; otherwise PPM is emitted. .TP .B \-rle Select RLE output format. (Requires URT library.) .TP .B \-targa Select Targa output format. Gray-scale format is emitted if the JPEG file is gray-scale or if .B \-grayscale is specified; otherwise, colormapped format is emitted if .B \-colors is specified; otherwise, 24-bit full-color format is emitted. .PP Switches for advanced users: .TP .B \-blocksmooth Perform cross-block smoothing. This is slow, quite memory-intensive, and only seems to improve the image at very low quality settings (\fB\-quality\fR 10 to 20 or so). At normal quality settings it may make the image worse. .TP .B \-grayscale Force gray-scale output even if JPEG file is color. Useful for viewing on monochrome displays. .TP .BI \-maxmemory " N" Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. .TP .B \-nodither Do not use dithering in color quantization. By default, Floyd-Steinberg dithering is applied when quantizing colors, but on some images dithering may result in objectionable "graininess". If that happens, you can turn off dithering with .BR \-nodither . .B \-nodither is ignored unless you also say .B \-colors .IR N . .TP .B \-onepass Use one-pass instead of two-pass color quantization. The one-pass method is faster and needs less memory, but it produces a lower-quality image. .B \-onepass is ignored unless you also say .B \-colors .IR N . Also, the one-pass method is always used for gray-scale output (the two-pass method is no improvement then). .TP .B \-verbose Enable debug printout. More .BR \-v 's give more output. Also, version information is printed at startup. .TP .B \-debug Same as .BR \-verbose . .SH EXAMPLES .LP This example decompresses the JPEG file foo.jpg, automatically quantizes to 256 colors, and saves the output in GIF format in foo.gif: .IP .B djpeg \-gif .I foo.jpg .B > .I foo.gif .SH ENVIRONMENT .TP .B JPEGMEM If this environment variable is set, its value is the default memory limit. The value is specified as described for the .B \-maxmemory switch. .B JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit .BR \-maxmemory . .SH SEE ALSO .BR cjpeg (1) .br .BR ppm (5), .BR pgm (5) .br Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. .SH AUTHOR Independent JPEG Group .SH BUGS Arithmetic coding is not supported for legal reasons. .PP Still not as fast as we'd like. made either\n"); printf("by editing jconfig.h, or by adding -Dsymbol switxloadimage.4.1/jpeg/example.c 644 221 144 64376 5323675233 11332 /* * example.c * * This file is not actually part of the JPEG software. Rather, it provides * a skeleton that may be useful for constructing applications that use the * JPEG software as subroutines. This code will NOT do anything useful as is. * * This file illustrates how to use the JPEG code as a subroutine library * to read or write JPEG image files. We assume here that you are not * merely interested in converting the image to yet another image file format * (if you are, you should be adding another I/O module to cjpeg/djpeg, not * constructing a new application). Instead, we show how to pass the * decompressed image data into or out of routines that you provide. For * example, a viewer program might use the JPEG decompressor together with * routines that write the decompressed image directly to a display. * * We present these routines in the same coding style used in the JPEG code * (ANSI function definitions, etc); but you are of course free to code your * routines in a different style if you prefer. */ /* * Include file for declaring JPEG data structures. * This file also includes some system headers like ; * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead. */ #include "jinclude.h" /* * is used for the optional error recovery mechanism shown in * the second part of the example. */ #include /******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ /* This half of the example shows how to feed data into the JPEG compressor. * We present a minimal version that does not worry about refinements such * as error recovery (the JPEG code will just exit() if it gets an error). */ /* * To supply the image data for compression, you must define three routines * input_init, get_input_row, and input_term. These routines will be called * from the JPEG compressor via function pointer values that you store in the * cinfo data structure; hence they need not be globally visible and the exact * names don't matter. (In fact, the "METHODDEF" macro expands to "static" if * you use the unmodified JPEG include files.) * * The input file reading modules (jrdppm.c, jrdgif.c, jrdtarga.c, etc) may be * useful examples of what these routines should actually do, although each of * them is encrusted with a lot of specialized code for its own file format. */ METHODDEF void input_init (compress_info_ptr cinfo) /* Initialize for input; return image size and component data. */ { /* This routine must return five pieces of information about the incoming * image, and must do any setup needed for the get_input_row routine. * The image information is returned in fields of the cinfo struct. * (If you don't care about modularity, you could initialize these fields * in the main JPEG calling routine, and make this routine be a no-op.) * We show some example values here. */ cinfo->image_width = 640; /* width in pixels */ cinfo->image_height = 480; /* height in pixels */ /* JPEG views an image as being a rectangular array of pixels, with each * pixel having the same number of "component" values (color channels). * You must specify how many components there are and the colorspace * interpretation of the components. Most applications will use RGB data or * grayscale data. If you want to use something else, you'll need to study * and perhaps modify jcdeflts.c, jccolor.c, and jdcolor.c. */ cinfo->input_components = 3; /* or 1 for grayscale */ cinfo->in_color_space = CS_RGB; /* or CS_GRAYSCALE for grayscale */ cinfo->data_precision = 8; /* bits per pixel component value */ /* In the current JPEG software, data_precision must be set equal to * BITS_IN_JSAMPLE, which is 8 unless you twiddle jconfig.h. Future * versions might allow you to say either 8 or 12 if compiled with * 12-bit JSAMPLEs, or up to 16 in lossless mode. In any case, * it is up to you to scale incoming pixel values to the range * 0 .. (1<input_components-1, and column runs * from 0 to cinfo->image_width-1 (column 0 is left edge of image). Note that * this is actually an array of pointers to arrays rather than a true 2D array, * since C does not support variable-size multidimensional arrays. * JSAMPLE is typically typedef'd as "unsigned char". */ METHODDEF void get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* Read next row of pixels into pixel_row[][] */ { /* This example shows how you might read RGB data (3 components) * from an input file in which the data is stored 3 bytes per pixel * in left-to-right, top-to-bottom order. */ register FILE * infile = cinfo->input_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = 0; col < cinfo->image_width; col++) { *ptr0++ = (JSAMPLE) getc(infile); /* red */ *ptr1++ = (JSAMPLE) getc(infile); /* green */ *ptr2++ = (JSAMPLE) getc(infile); /* blue */ } } METHODDEF void input_term (compress_info_ptr cinfo) /* Finish up at the end of the input */ { /* This termination routine will very often have no work to do, */ /* but you must provide it anyway. */ /* Note that the JPEG code will only call it during successful exit; */ /* if you want it called during error exit, you gotta do that yourself. */ } /* * That's it for the routines that deal with reading the input image data. * Now we have overall control and parameter selection routines. */ /* * This routine must determine what output JPEG file format is to be written, * and make any other compression parameter changes that are desirable. * This routine gets control after the input file header has been read * (i.e., right after input_init has been called). You could combine its * functions into input_init, or even into the main control routine, but * if you have several different input_init routines, it's a definite win * to keep this separate. You MUST supply this routine even if it's a no-op. */ METHODDEF void c_ui_method_selection (compress_info_ptr cinfo) { /* If the input is gray scale, generate a monochrome JPEG file. */ if (cinfo->in_color_space == CS_GRAYSCALE) j_monochrome_default(cinfo); /* For now, always select JFIF output format. */ jselwjfif(cinfo); } /* * OK, here is the main function that actually causes everything to happen. * We assume here that the target filename is supplied by the caller of this * routine, and that all JPEG compression parameters can be default values. */ GLOBAL void write_JPEG_file (char * filename) { /* These three structs contain JPEG parameters and working data. * They must survive for the duration of parameter setup and one * call to jpeg_compress; typically, making them local data in the * calling routine is the best strategy. */ struct Compress_info_struct cinfo; struct Compress_methods_struct c_methods; struct External_methods_struct e_methods; /* Initialize the system-dependent method pointers. */ cinfo.methods = &c_methods; /* links to method structs */ cinfo.emethods = &e_methods; /* Here we use the default JPEG error handler, which will just print * an error message on stderr and call exit(). See the second half of * this file for an example of more graceful error recovery. */ jselerror(&e_methods); /* select std error/trace message routines */ /* Here we use the standard memory manager provided with the JPEG code. * In some cases you might want to replace the memory manager, or at * least the system-dependent part of it, with your own code. */ jselmemmgr(&e_methods); /* select std memory allocation routines */ /* If the compressor requires full-image buffers (for entropy-coding * optimization or a noninterleaved JPEG file), it will create temporary * files for anything that doesn't fit within the maximum-memory setting. * (Note that temp files are NOT needed if you use the default parameters.) * You can change the default maximum-memory setting by changing * e_methods.max_memory_to_use after jselmemmgr returns. * On some systems you may also need to set up a signal handler to * ensure that temporary files are deleted if the program is interrupted. * (This is most important if you are on MS-DOS and use the jmemdos.c * memory manager back end; it will try to grab extended memory for * temp files, and that space will NOT be freed automatically.) * See jcmain.c or jdmain.c for an example signal handler. */ /* Here, set up pointers to your own routines for input data handling * and post-init parameter selection. */ c_methods.input_init = input_init; c_methods.get_input_row = get_input_row; c_methods.input_term = input_term; c_methods.c_ui_method_selection = c_ui_method_selection; /* Set up default JPEG parameters in the cinfo data structure. */ j_c_defaults(&cinfo, 75, FALSE); /* Note: 75 is the recommended default quality level; you may instead pass * a user-specified quality level. Be aware that values below 25 will cause * non-baseline JPEG files to be created (and a warning message to that * effect to be emitted on stderr). This won't bother our decoder, but some * commercial JPEG implementations may choke on non-baseline JPEG files. * If you want to force baseline compatibility, pass TRUE instead of FALSE. * (If non-baseline files are fine, but you could do without that warning * message, set e_methods.trace_level to -1.) */ /* At this point you can modify the default parameters set by j_c_defaults * as needed. For a minimal implementation, you shouldn't need to change * anything. See jcmain.c for some examples of what you might change. */ /* Select the input and output files. * Note that cinfo.input_file is only used if your input reading routines * use it; otherwise, you can just make it NULL. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ cinfo.input_file = NULL; /* if no actual input file involved */ if ((cinfo.output_file = fopen(filename, "wb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } /* Here we go! */ jpeg_compress(&cinfo); /* That's it, son. Nothin' else to do, except close files. */ /* Here we assume only the output file need be closed. */ fclose(cinfo.output_file); /* Note: if you want to compress more than one image, we recommend you * repeat this whole routine. You MUST repeat the j_c_defaults()/alter * parameters/jpeg_compress() sequence, as some data structures allocated * in j_c_defaults are freed upon exit from jpeg_compress. */ } /******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ /* This half of the example shows how to read data from the JPEG decompressor. * It's a little more refined than the above in that we show how to do your * own error recovery. If you don't care about that, you don't need these * next two routines. */ /* * These routines replace the default trace/error routines included with the * JPEG code. The example trace_message routine shown here is actually the * same as the standard one, but you could modify it if you don't want messages * sent to stderr. The example error_exit routine is set up to return * control to read_JPEG_file() rather than calling exit(). You can use the * same routines for both compression and decompression error recovery. */ /* These static variables are needed by the error routines. */ static jmp_buf setjmp_buffer; /* for return to caller */ static external_methods_ptr emethods; /* needed for access to message_parm */ /* This routine is used for any and all trace, debug, or error printouts * from the JPEG code. The parameter is a printf format string; up to 8 * integer data values for the format string have been stored in the * message_parm[] field of the external_methods struct. */ METHODDEF void trace_message (const char *msgtext) { fprintf(stderr, msgtext, emethods->message_parm[0], emethods->message_parm[1], emethods->message_parm[2], emethods->message_parm[3], emethods->message_parm[4], emethods->message_parm[5], emethods->message_parm[6], emethods->message_parm[7]); fprintf(stderr, "\n"); /* there is no \n in the format string! */ } /* * The error_exit() routine should not return to its caller. The default * routine calls exit(), but here we assume that we want to return to * read_JPEG_file, which has set up a setjmp context for the purpose. * You should make sure that the free_all method is called, either within * error_exit or after the return to the outer-level routine. */ METHODDEF void error_exit (const char *msgtext) { trace_message(msgtext); /* report the error message */ (*emethods->free_all) (); /* clean up memory allocation & temp files */ longjmp(setjmp_buffer, 1); /* return control to outer routine */ } /* * To accept the image data from decompression, you must define four routines * output_init, put_color_map, put_pixel_rows, and output_term. * * You must understand the distinction between full color output mode * (N independent color components) and colormapped output mode (a single * output component representing an index into a color map). You should use * colormapped mode to write to a colormapped display screen or output file. * Colormapped mode is also useful for reducing grayscale output to a small * number of gray levels: when using the 1-pass quantizer on grayscale data, * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you * can regard the indexes as directly representing gray levels at reduced * precision. In any other case, you should not depend on the colormap * entries having any particular order. * To get colormapped output, set cinfo->quantize_colors to TRUE and set * cinfo->desired_number_of_colors to the maximum number of entries in the * colormap. This can be done either in your main routine or in * d_ui_method_selection. For grayscale quantization, also set * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used * (presently this is the default, but it may not be so in the future). * * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be * useful examples of what these routines should actually do, although each of * them is encrusted with a lot of specialized code for its own file format. */ METHODDEF void output_init (decompress_info_ptr cinfo) /* This routine should do any setup required */ { /* This routine can initialize for output based on the data passed in cinfo. * Useful fields include: * image_width, image_height Pretty obvious, I hope. * data_precision bits per pixel value; typically 8. * out_color_space output colorspace previously requested * color_out_comps number of color components in same * final_out_comps number of components actually output * final_out_comps is 1 if quantize_colors is true, else it is equal to * color_out_comps. * * If you have requested color quantization, the colormap is NOT yet set. * You may wish to defer output initialization until put_color_map is called. */ } /* * This routine is called if and only if you have set cinfo->quantize_colors * to TRUE. It is given the selected colormap and can complete any required * initialization. This call will occur after output_init and before any * calls to put_pixel_rows. Note that the colormap pointer is also placed * in a cinfo field, whence it can be used by put_pixel_rows or output_term. * num_colors will be less than or equal to desired_number_of_colors. * * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as * JSAMPLE colormap[component][indexvalue] * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue * runs from 0 to num_colors-1. Note that this is actually an array of * pointers to arrays rather than a true 2D array, since C does not support * variable-size multidimensional arrays. * JSAMPLE is typically typedef'd as "unsigned char". If you want your code * to be as portable as the JPEG code proper, you should always access JSAMPLE * values with the GETJSAMPLE() macro, which will do the right thing if the * machine has only signed chars. */ METHODDEF void put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap) /* Write the color map */ { /* You need not provide this routine if you always set cinfo->quantize_colors * FALSE; but a safer practice is to provide it and have it just print an * error message, like this: */ fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n"); } /* * This function is called repeatedly, with a few more rows of pixels supplied * on each call. With the current JPEG code, some multiple of 8 rows will be * passed on each call except the last, but it is extremely bad form to depend * on this. You CAN assume num_rows > 0. * The data is supplied in top-to-bottom row order (the standard order within * a JPEG file). If you cannot readily use the data in that order, you'll * need an intermediate array to hold the image. See jwrrle.c for an example * of outputting data in bottom-to-top order. * * The data is supplied as a 3-D array of JSAMPLEs, indexed as * JSAMPLE pixel_data[component][row][column] * where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to * num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is * left edge of image). Note that this is actually an array of pointers to * pointers to arrays rather than a true 3D array, since C does not support * variable-size multidimensional arrays. * JSAMPLE is typically typedef'd as "unsigned char". If you want your code * to be as portable as the JPEG code proper, you should always access JSAMPLE * values with the GETJSAMPLE() macro, which will do the right thing if the * machine has only signed chars. * * If quantize_colors is true, then there is only one component, and its values * are indexes into the previously supplied colormap. Otherwise the values * are actual data in your selected output colorspace. */ METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) /* Write some rows of output data */ { /* This example shows how you might write full-color RGB data (3 components) * to an output file in which the data is stored 3 bytes per pixel. */ register FILE * outfile = cinfo->output_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; register int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; for (col = 0; col < cinfo->image_width; col++) { putc(GETJSAMPLE(*ptr0), outfile); /* red */ ptr0++; putc(GETJSAMPLE(*ptr1), outfile); /* green */ ptr1++; putc(GETJSAMPLE(*ptr2), outfile); /* blue */ ptr2++; } } } METHODDEF void output_term (decompress_info_ptr cinfo) /* Finish up at the end of the output */ { /* This termination routine may not need to do anything. */ /* Note that the JPEG code will only call it during successful exit; */ /* if you want it called during error exit, you gotta do that yourself. */ } /* * That's it for the routines that deal with writing the output image. * Now we have overall control and parameter selection routines. */ /* * This routine gets control after the JPEG file header has been read; * at this point the image size and colorspace are known. * The routine must determine what output routines are to be used, and make * any decompression parameter changes that are desirable. For example, * if it is found that the JPEG file is grayscale, you might want to do * things differently than if it is color. You can also delay setting * quantize_colors and associated options until this point. * * j_d_defaults initializes out_color_space to CS_RGB. If you want grayscale * output you should set out_color_space to CS_GRAYSCALE. Note that you can * force grayscale output from a color JPEG file (though not vice versa). */ METHODDEF void d_ui_method_selection (decompress_info_ptr cinfo) { /* if grayscale input, force grayscale output; */ /* else leave the output colorspace as set by main routine. */ if (cinfo->jpeg_color_space == CS_GRAYSCALE) cinfo->out_color_space = CS_GRAYSCALE; /* select output routines */ cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; cinfo->methods->put_pixel_rows = put_pixel_rows; cinfo->methods->output_term = output_term; } /* * OK, here is the main function that actually causes everything to happen. * We assume here that the JPEG filename is supplied by the caller of this * routine, and that all decompression parameters can be default values. * The routine returns 1 if successful, 0 if not. */ GLOBAL int read_JPEG_file (char * filename) { /* These three structs contain JPEG parameters and working data. * They must survive for the duration of parameter setup and one * call to jpeg_decompress; typically, making them local data in the * calling routine is the best strategy. */ struct Decompress_info_struct cinfo; struct Decompress_methods_struct dc_methods; struct External_methods_struct e_methods; /* Select the input and output files. * In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * Note that cinfo.output_file is only used if your output handling routines * use it; otherwise, you can just make it NULL. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((cinfo.input_file = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); return 0; } cinfo.output_file = NULL; /* if no actual output file involved */ /* Initialize the system-dependent method pointers. */ cinfo.methods = &dc_methods; /* links to method structs */ cinfo.emethods = &e_methods; /* Here we supply our own error handler; compare to use of standard error * handler in the previous write_JPEG_file example. */ emethods = &e_methods; /* save struct addr for possible access */ e_methods.error_exit = error_exit; /* supply error-exit routine */ e_methods.trace_message = trace_message; /* supply trace-message routine */ e_methods.trace_level = 0; /* default = no tracing */ e_methods.num_warnings = 0; /* no warnings emitted yet */ e_methods.first_warning_level = 0; /* display first corrupt-data warning */ e_methods.more_warning_level = 3; /* but suppress additional ones */ /* prepare setjmp context for possible exit from error_exit */ if (setjmp(setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * Memory allocation has already been cleaned up (see free_all call in * error_exit), but we need to close the input file before returning. * You might also need to close an output file, etc. */ fclose(cinfo.input_file); return 0; } /* Here we use the standard memory manager provided with the JPEG code. * In some cases you might want to replace the memory manager, or at * least the system-dependent part of it, with your own code. */ jselmemmgr(&e_methods); /* select std memory allocation routines */ /* If the decompressor requires full-image buffers (for two-pass color * quantization or a noninterleaved JPEG file), it will create temporary * files for anything that doesn't fit within the maximum-memory setting. * You can change the default maximum-memory setting by changing * e_methods.max_memory_to_use after jselmemmgr returns. * On some systems you may also need to set up a signal handler to * ensure that temporary files are deleted if the program is interrupted. * (This is most important if you are on MS-DOS and use the jmemdos.c * memory manager back end; it will try to grab extended memory for * temp files, and that space will NOT be freed automatically.) * See jcmain.c or jdmain.c for an example signal handler. */ /* Here, set up the pointer to your own routine for post-header-reading * parameter selection. You could also initialize the pointers to the * output data handling routines here, if they are not dependent on the * image type. */ dc_methods.d_ui_method_selection = d_ui_method_selection; /* Set up default decompression parameters. */ j_d_defaults(&cinfo, TRUE); /* TRUE indicates that an input buffer should be allocated. * In unusual cases you may want to allocate the input buffer yourself; * see jddeflts.c for commentary. */ /* At this point you can modify the default parameters set by j_d_defaults * as needed; for example, you can request color quantization or force * grayscale output. See jdmain.c for examples of what you might change. */ /* Set up to read a JFIF or baseline-JPEG file. */ /* This is the only JPEG file format currently supported. */ jselrjfif(&cinfo); /* Here we go! */ jpeg_decompress(&cinfo); /* That's it, son. Nothin' else to do, except close files. */ /* Here we assume only the input file need be closed. */ fclose(cinfo.input_file); /* You might want to test e_methods.num_warnings to see if bad data was * detected. In this example, we just blindly forge ahead. */ return 1; /* indicate success */ /* Note: if you want to decompress more than one image, we recommend you * repeat this whole routine. You MUST repeat the j_d_defaults()/alter * parameters/jpeg_decompress() sequence, as some data structures allocated * in j_d_defaults are freed upon exit from jpeg_decompress. */ } typically typedef'd as "unsigned char". If you want your code * to be as portable as the JPEG code proper, you should always access JSAMPLE * values with the GETJSAMPLE() macro, which will do the right thing if the * machine has only signed chars. * *xloadimage.4.1/jpeg/jbsmooth.c 644 221 144 6273 5275021313 11462 /* * jbsmooth.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains cross-block smoothing routines. * These routines are invoked via the smooth_coefficients method. */ #include "jinclude.h" #ifdef BLOCK_SMOOTHING_SUPPORTED /* * Cross-block coefficient smoothing. */ METHODDEF void smooth_coefficients (decompress_info_ptr cinfo, jpeg_component_info *compptr, JBLOCKROW above, JBLOCKROW currow, JBLOCKROW below, JBLOCKROW output) { QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]; long blocks_in_row = compptr->downsampled_width / DCTSIZE; long col; /* First, copy the block row as-is. * This takes care of the first & last blocks in the row, the top/bottom * special cases, and the higher-order coefficients in each block. */ jcopy_block_row(currow, output, blocks_in_row); /* Now apply the smoothing calculation, but not to any blocks on the * edges of the image. */ if (above != NULL && below != NULL) { for (col = 1; col < blocks_in_row-1; col++) { /* See section K.8 of the JPEG standard. * * As I understand it, this produces approximations * for the low frequency AC components, based on the * DC values of the block and its eight neighboring blocks. * (Thus it can't be used for blocks on the image edges.) */ /* The layout of these variables corresponds to text and figure in K.8 */ JCOEF DC1, DC2, DC3; JCOEF DC4, DC5, DC6; JCOEF DC7, DC8, DC9; long AC01, AC02; long AC10, AC11; long AC20; DC1 = above [col-1][0]; DC2 = above [col ][0]; DC3 = above [col+1][0]; DC4 = currow[col-1][0]; DC5 = currow[col ][0]; DC6 = currow[col+1][0]; DC7 = below [col-1][0]; DC8 = below [col ][0]; DC9 = below [col+1][0]; #define DIVIDE_256(x) x = ( (x) < 0 ? -((128-(x))/256) : ((x)+128)/256 ) AC01 = (36 * (DC4 - DC6)); DIVIDE_256(AC01); AC10 = (36 * (DC2 - DC8)); DIVIDE_256(AC10); AC20 = (9 * (DC2 + DC8 - 2*DC5)); DIVIDE_256(AC20); AC11 = (5 * ((DC1 - DC3) - (DC7 - DC9))); DIVIDE_256(AC11); AC02 = (9 * (DC4 + DC6 - 2*DC5)); DIVIDE_256(AC02); /* I think that this checks to see if the quantisation * on the transmitting side would have produced this * answer. If so, then we use our (hopefully better) * estimate. */ #define ABS(x) ((x) < 0 ? -(x) : (x)) #define COND_ASSIGN(_ac,_n,_z) if ((ABS(output[col][_n] - (_ac))<<1) <= Qptr[_z]) output[col][_n] = (JCOEF) (_ac) COND_ASSIGN(AC01, 1, 1); COND_ASSIGN(AC02, 2, 5); COND_ASSIGN(AC10, 8, 2); COND_ASSIGN(AC11, 9, 4); COND_ASSIGN(AC20, 16, 3); } } } /* * The method selection routine for cross-block smoothing. */ GLOBAL void jselbsmooth (decompress_info_ptr cinfo) { /* just one implementation for now */ cinfo->methods->smooth_coefficients = smooth_coefficients; } #endif /* BLOCK_SMOOTHING_SUPPORTED */ t_file = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); return 0; } cinfo.output_file = NULL; /* if no actual output file involved */ /* Initialize the system-dependent method pointers. */ cinfo.methods = &dc_methods; /* links to method structs */ cinfo.emethods = &e_methxloadimage.4.1/jpeg/jcarith.c 644 221 144 2214 5300071531 11244 /* * jcarith.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains arithmetic entropy encoding routines. * These routines are invoked via the methods entropy_encode, * entropy_encode_init/term, and entropy_optimize. */ #include "jinclude.h" #ifdef C_ARITH_CODING_SUPPORTED /* * The arithmetic coding option of the JPEG standard specifies Q-coding, * which is covered by patents held by IBM (and possibly AT&T and Mitsubishi). * At this time it does not appear to be legal for the Independent JPEG * Group to distribute software that implements arithmetic coding. * We have therefore removed arithmetic coding support from the * distributed source code. * * We're not happy about it either. */ /* * The method selection routine for arithmetic entropy encoding. */ GLOBAL void jselcarithmetic (compress_info_ptr cinfo) { if (cinfo->arith_code) { ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding"); } } #endif /* C_ARITH_CODING_SUPPORTED */ makefile.manxd| makefile.mc5| makefile.mc6 makefile.mms  makefile.sas  makefile.unix makefile.vms makljpeg.icc, makljpeg.st@ makvms.optTM testimg.gifhN testimg.jpg|L testimg.ppmK testorig.jpg)); DIxloadimage.4.1/jpeg/jccolor.c 644 221 144 25744 5240600355 11315 /* * jccolor.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input colorspace conversion routines. * These routines are invoked via the methods get_sample_rows * and colorin_init/term. */ #include "jinclude.h" static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */ /**************** RGB -> YCbCr conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + MAXJSAMPLE/2 * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + MAXJSAMPLE/2 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The MAXJSAMPLE/2 offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #ifdef SIXTEEN_BIT_SAMPLES #define SCALEBITS 14 /* avoid overflow */ #else #define SCALEBITS 16 /* speedier right-shift on some machines */ #endif #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< table for RGB to YCbCr conversion */ #define R_Y_OFF 0 /* offset to R => Y section */ #define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ #define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ #define R_CB_OFF (3*(MAXJSAMPLE+1)) #define G_CB_OFF (4*(MAXJSAMPLE+1)) #define B_CB_OFF (5*(MAXJSAMPLE+1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ #define G_CR_OFF (6*(MAXJSAMPLE+1)) #define B_CR_OFF (7*(MAXJSAMPLE+1)) #define TABLE_SIZE (8*(MAXJSAMPLE+1)) /* * Initialize for colorspace conversion. */ METHODDEF void rgb_ycc_init (compress_info_ptr cinfo) { INT32 i; /* Allocate a workspace for the result of get_input_row. */ pixel_row = (*cinfo->emethods->alloc_small_sarray) (cinfo->image_width, (long) cinfo->input_components); /* Allocate and fill in the conversion tables. */ rgb_ycc_tab = (INT32 *) (*cinfo->emethods->alloc_small) (TABLE_SIZE * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1); /* B=>Cb and R=>Cr tables are the same rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1); */ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; } } /* * Fetch some rows of pixels from get_input_row and convert to the * JPEG colorspace. */ METHODDEF void get_rgb_ycc_rows (compress_info_ptr cinfo, int rows_to_read, JSAMPIMAGE image_data) { #ifdef SIXTEEN_BIT_SAMPLES register UINT16 r, g, b; #else register int r, g, b; #endif register INT32 * ctab = rgb_ycc_tab; register JSAMPROW inptr0, inptr1, inptr2; register JSAMPROW outptr0, outptr1, outptr2; register long col; long width = cinfo->image_width; int row; for (row = 0; row < rows_to_read; row++) { /* Read one row from the source file */ (*cinfo->methods->get_input_row) (cinfo, pixel_row); /* Convert colorspace */ inptr0 = pixel_row[0]; inptr1 = pixel_row[1]; inptr2 = pixel_row[2]; outptr0 = image_data[0][row]; outptr1 = image_data[1][row]; outptr2 = image_data[2][row]; for (col = 0; col < width; col++) { r = GETJSAMPLE(inptr0[col]); g = GETJSAMPLE(inptr1[col]); b = GETJSAMPLE(inptr2[col]); /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /**************** Cases other than RGB -> YCbCr **************/ /* * Fetch some rows of pixels from get_input_row and convert to the * JPEG colorspace. * This version handles RGB->grayscale conversion, which is the same * as the RGB->Y portion of RGB->YCbCr. * We assume rgb_ycc_init has been called (we only use the Y tables). */ METHODDEF void get_rgb_gray_rows (compress_info_ptr cinfo, int rows_to_read, JSAMPIMAGE image_data) { #ifdef SIXTEEN_BIT_SAMPLES register UINT16 r, g, b; #else register int r, g, b; #endif register INT32 * ctab = rgb_ycc_tab; register JSAMPROW inptr0, inptr1, inptr2; register JSAMPROW outptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < rows_to_read; row++) { /* Read one row from the source file */ (*cinfo->methods->get_input_row) (cinfo, pixel_row); /* Convert colorspace */ inptr0 = pixel_row[0]; inptr1 = pixel_row[1]; inptr2 = pixel_row[2]; outptr = image_data[0][row]; for (col = 0; col < width; col++) { r = GETJSAMPLE(inptr0[col]); g = GETJSAMPLE(inptr1[col]); b = GETJSAMPLE(inptr2[col]); /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); } } } /* * Initialize for colorspace conversion. */ METHODDEF void colorin_init (compress_info_ptr cinfo) { /* Allocate a workspace for the result of get_input_row. */ pixel_row = (*cinfo->emethods->alloc_small_sarray) (cinfo->image_width, (long) cinfo->input_components); } /* * Fetch some rows of pixels from get_input_row and convert to the * JPEG colorspace. * This version handles grayscale output with no conversion. * The source can be either plain grayscale or YCbCr (since Y == gray). */ METHODDEF void get_grayscale_rows (compress_info_ptr cinfo, int rows_to_read, JSAMPIMAGE image_data) { int row; for (row = 0; row < rows_to_read; row++) { /* Read one row from the source file */ (*cinfo->methods->get_input_row) (cinfo, pixel_row); /* Convert colorspace (gamma mapping needed here) */ jcopy_sample_rows(pixel_row, 0, image_data[0], row, 1, cinfo->image_width); } } /* * Fetch some rows of pixels from get_input_row and convert to the * JPEG colorspace. * This version handles multi-component colorspaces without conversion. */ METHODDEF void get_noconvert_rows (compress_info_ptr cinfo, int rows_to_read, JSAMPIMAGE image_data) { int row, ci; for (row = 0; row < rows_to_read; row++) { /* Read one row from the source file */ (*cinfo->methods->get_input_row) (cinfo, pixel_row); /* Convert colorspace (gamma mapping needed here) */ for (ci = 0; ci < cinfo->input_components; ci++) { jcopy_sample_rows(pixel_row, ci, image_data[ci], row, 1, cinfo->image_width); } } } /* * Finish up at the end of the file. */ METHODDEF void colorin_term (compress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /* * The method selection routine for input colorspace conversion. */ GLOBAL void jselccolor (compress_info_ptr cinfo) { /* Make sure input_components agrees with in_color_space */ switch (cinfo->in_color_space) { case CS_GRAYSCALE: if (cinfo->input_components != 1) ERREXIT(cinfo->emethods, "Bogus input colorspace"); break; case CS_RGB: case CS_YCbCr: case CS_YIQ: if (cinfo->input_components != 3) ERREXIT(cinfo->emethods, "Bogus input colorspace"); break; case CS_CMYK: if (cinfo->input_components != 4) ERREXIT(cinfo->emethods, "Bogus input colorspace"); break; default: ERREXIT(cinfo->emethods, "Unsupported input colorspace"); break; } /* Standard init/term methods (may override below) */ cinfo->methods->colorin_init = colorin_init; cinfo->methods->colorin_term = colorin_term; /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case CS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); if (cinfo->in_color_space == CS_GRAYSCALE) cinfo->methods->get_sample_rows = get_grayscale_rows; else if (cinfo->in_color_space == CS_RGB) { cinfo->methods->colorin_init = rgb_ycc_init; cinfo->methods->get_sample_rows = get_rgb_gray_rows; } else if (cinfo->in_color_space == CS_YCbCr) cinfo->methods->get_sample_rows = get_grayscale_rows; else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; case CS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); if (cinfo->in_color_space == CS_RGB) { cinfo->methods->colorin_init = rgb_ycc_init; cinfo->methods->get_sample_rows = get_rgb_ycc_rows; } else if (cinfo->in_color_space == CS_YCbCr) cinfo->methods->get_sample_rows = get_noconvert_rows; else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; case CS_CMYK: if (cinfo->num_components != 4) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); if (cinfo->in_color_space == CS_CMYK) cinfo->methods->get_sample_rows = get_noconvert_rows; else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; default: ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace"); break; } } loc_small_sarray) (cinfo->xloadimage.4.1/jpeg/jcdeflts.c 644 221 144 34634 5340016753 11462 /* * jcdeflts.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains optional default-setting code for the JPEG compressor. * User interfaces do not have to use this file, but those that don't use it * must know a lot more about the innards of the JPEG code. */ #include "jinclude.h" /* Default do-nothing progress monitoring routine. * This can be overridden by a user interface that wishes to * provide progress monitoring; just set methods->progress_monitor * after j_c_defaults is done. The routine will be called periodically * during the compression process. * * During any one pass, loopcounter increases from 0 up to (not including) * looplimit; the step size is not necessarily 1. Both the step size and * the limit may differ between passes. The expected total number of passes * is in cinfo->total_passes, and the number of passes already completed is * in cinfo->completed_passes. Thus the fraction of work completed may be * estimated as * completed_passes + (loopcounter/looplimit) * ------------------------------------------ * total_passes * ignoring the fact that the passes may not be equal amounts of work. */ METHODDEF void progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit) { /* do nothing */ } /* * Huffman table setup routines */ LOCAL void add_huff_table (compress_info_ptr cinfo, HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) /* Define a Huffman table */ { if (*htblptr == NULL) *htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL)); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, val, SIZEOF((*htblptr)->huffval)); /* Initialize sent_table FALSE so table will be written to JPEG file. * In an application where we are writing non-interchange JPEG files, * it might be desirable to save space by leaving default Huffman tables * out of the file. To do that, just initialize sent_table = TRUE... */ (*htblptr)->sent_table = FALSE; } LOCAL void std_huff_tables (compress_info_ptr cinfo) /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ /* IMPORTANT: these are only valid for 8-bit data precision! */ { static const UINT8 dc_luminance_bits[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 dc_luminance_val[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 dc_chrominance_bits[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 dc_chrominance_val[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 ac_luminance_bits[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 ac_luminance_val[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static const UINT8 ac_chrominance_bits[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 ac_chrominance_val[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], dc_luminance_bits, dc_luminance_val); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], ac_luminance_bits, ac_luminance_val); add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], dc_chrominance_bits, dc_chrominance_val); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], ac_chrominance_bits, ac_chrominance_val); } /* * Quantization table setup routines */ GLOBAL void j_add_quant_table (compress_info_ptr cinfo, int which_tbl, const QUANT_VAL *basic_table, int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries * are limited to 1..255 for JPEG baseline compatibility. */ { QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; int i; long temp; if (*qtblptr == NULL) *qtblptr = (QUANT_TBL_PTR) (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL)); for (i = 0; i < DCTSIZE2; i++) { temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; /* limit the values to the valid range */ if (temp <= 0L) temp = 1L; #ifdef EIGHT_BIT_SAMPLES if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */ #else if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */ #endif if (force_baseline && temp > 255L) temp = 255L; /* limit to baseline range if requested */ (*qtblptr)[i] = (QUANT_VAL) temp; } } GLOBAL int j_quality_scaling (int quality) /* Convert a user-specified quality rating to a percentage scaling factor * for an underlying quantization table, using our recommended scaling curve. * The input 'quality' factor should be 0 (terrible) to 100 (very good). */ { /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; /* The basic table is used as-is (scaling 100) for a quality of 50. * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * note that at Q=100 the scaling is 0, which will cause j_add_quant_table * to make all the table entries 1 (hence, no quantization loss). * Qualities 1..50 are converted to scaling percentage 5000/Q. */ if (quality < 50) quality = 5000 / quality; else quality = 200 - quality*2; return quality; } GLOBAL void j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables * would use the preceding two routines directly. */ { /* This is the sample quantization table given in the JPEG spec section K.1, * but expressed in zigzag order (as are all of our quant. tables). * The spec says that the values given produce "good" quality, and * when divided by 2, "very good" quality. (These two settings are * selected by quality=50 and quality=75 respectively.) */ static const QUANT_VAL std_luminance_quant_tbl[DCTSIZE2] = { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101, 103, 99 }; static const QUANT_VAL std_chrominance_quant_tbl[DCTSIZE2] = { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; /* Convert user 0-100 rating to percentage scaling */ quality = j_quality_scaling(quality); /* Set up two quantization tables using the specified quality scaling */ j_add_quant_table(cinfo, 0, std_luminance_quant_tbl, quality, force_baseline); j_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, quality, force_baseline); } /* Default parameter setup for compression. * * User interfaces that don't choose to use this routine must do their * own setup of all these parameters. Alternately, you can call this * to establish defaults and then alter parameters selectively. This * is the recommended approach since, if we add any new parameters, * your code will still work (they'll be set to reasonable defaults). * * See above for the meaning of the 'quality' and 'force_baseline' parameters. * Typically, the application's default quality setting will be passed to this * routine. A later call on j_set_quality() can be used to change to a * user-specified quality setting. * * This routine sets up for a color image; to output a grayscale image, * do this first and call j_monochrome_default() afterwards. * (The latter can be called within c_ui_method_selection, so the * choice can depend on the input file header.) * Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr, * you should also change the component ID codes, and you should NOT emit * a JFIF header (set write_JFIF_header = FALSE). * * CAUTION: if you want to compress multiple images per run, it's necessary * to call j_c_defaults before *each* call to jpeg_compress, since subsidiary * structures like the Huffman tables are automatically freed during cleanup. */ GLOBAL void j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline) /* NB: the external methods must already be set up. */ { short i; jpeg_component_info * compptr; /* Initialize pointers as needed to mark stuff unallocated. */ cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->data_precision = BITS_IN_JSAMPLE; /* default; can be overridden by input_init */ cinfo->density_unit = 0; /* Pixel size is unknown by default */ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; cinfo->input_gamma = 1.0; /* no gamma correction by default */ cinfo->write_JFIF_header = TRUE; /* write a JFIF marker */ cinfo->comment_text = NULL; /* but no COM block */ /* Prepare three color components; first is luminance which is also usable */ /* for grayscale. The others are assumed to be UV or similar chrominance. */ cinfo->jpeg_color_space = CS_YCbCr; cinfo->num_components = 3; cinfo->comp_info = (jpeg_component_info *) (*cinfo->emethods->alloc_small) (4 * SIZEOF(jpeg_component_info)); /* Note: we allocate a 4-entry comp_info array so that user interface can * easily change over to CMYK color space if desired. */ compptr = &cinfo->comp_info[0]; compptr->component_index = 0; compptr->component_id = 1; /* JFIF specifies IDs 1,2,3 */ compptr->h_samp_factor = 2; /* default to 2x2 subsamples of chrominance */ compptr->v_samp_factor = 2; compptr->quant_tbl_no = 0; /* use tables 0 for luminance */ compptr->dc_tbl_no = 0; compptr->ac_tbl_no = 0; compptr = &cinfo->comp_info[1]; compptr->component_index = 1; compptr->component_id = 2; compptr->h_samp_factor = 1; compptr->v_samp_factor = 1; compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */ compptr->dc_tbl_no = 1; compptr->ac_tbl_no = 1; compptr = &cinfo->comp_info[2]; compptr->component_index = 2; compptr->component_id = 3; compptr->h_samp_factor = 1; compptr->v_samp_factor = 1; compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */ compptr->dc_tbl_no = 1; compptr->ac_tbl_no = 1; /* Set up two quantization tables using the specified quality scaling */ j_set_quality(cinfo, quality, force_baseline); /* Set up two Huffman tables in case user interface wants Huffman coding */ std_huff_tables(cinfo); /* Initialize default arithmetic coding conditioning */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } /* Use Huffman coding, not arithmetic coding, by default */ cinfo->arith_code = FALSE; /* Color images are interleaved by default */ cinfo->interleave = TRUE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; /* No input smoothing */ cinfo->smoothing_factor = 0; /* No restart markers */ cinfo->restart_interval = 0; cinfo->restart_in_rows = 0; /* Install default do-nothing progress monitoring method. */ cinfo->methods->progress_monitor = progress_monitor; } GLOBAL void j_monochrome_default (compress_info_ptr cinfo) /* Change the j_c_defaults() values to emit a monochrome JPEG file. */ { jpeg_component_info * compptr; cinfo->jpeg_color_space = CS_GRAYSCALE; cinfo->num_components = 1; /* Set single component to 1x1 subsampling */ compptr = &cinfo->comp_info[0]; compptr->h_samp_factor = 1; compptr->v_samp_factor = 1; } _grayscale_rows; else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); xloadimage.4.1/jpeg/jcexpand.c 644 221 144 3634 5275021342 11431 /* * jcexpand.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains image edge-expansion routines. * These routines are invoked via the edge_expand method. */ #include "jinclude.h" /* * Expand an image so that it is a multiple of the MCU dimensions. * This is to be accomplished by duplicating the rightmost column * and/or bottommost row of pixels. The image has not yet been * downsampled, so all components have the same dimensions. */ METHODDEF void edge_expand (compress_info_ptr cinfo, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPIMAGE image_data) { /* Expand horizontally */ if (input_cols < output_cols) { register JSAMPROW ptr; register JSAMPLE pixval; register long count; register int row; short ci; long numcols = output_cols - input_cols; for (ci = 0; ci < cinfo->num_components; ci++) { for (row = 0; row < input_rows; row++) { ptr = image_data[ci][row] + (input_cols-1); pixval = GETJSAMPLE(*ptr++); for (count = numcols; count > 0; count--) *ptr++ = pixval; } } } /* Expand vertically */ /* This happens only once at the bottom of the image, */ /* so it needn't be super-efficient */ if (input_rows < output_rows) { register int row; short ci; JSAMPARRAY this_component; for (ci = 0; ci < cinfo->num_components; ci++) { this_component = image_data[ci]; for (row = input_rows; row < output_rows; row++) { jcopy_sample_rows(this_component, input_rows-1, this_component, row, 1, output_cols); } } } } /* * The method selection routine for edge expansion. */ GLOBAL void jselexpand (compress_info_ptr cinfo) { /* just one implementation for now */ cinfo->methods->edge_expand = edge_expand; } 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; /* Convert user 0-100 rating to percentxloadimage.4.1/jpeg/jchuff.c 644 221 144 47023 5336330224 11122 /* * jchuff.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. * These routines are invoked via the methods entropy_encode, * entropy_encode_init/term, and entropy_optimize. */ #include "jinclude.h" /* Static variables to avoid passing 'round extra parameters */ static compress_info_ptr cinfo; static INT32 huff_put_buffer; /* current bit-accumulation buffer */ static int huff_put_bits; /* # of bits now in it */ static char * output_buffer; /* output buffer */ static int bytes_in_buffer; LOCAL void fix_huff_tbl (HUFF_TBL * htbl) /* Compute derived values for a Huffman table */ { int p, i, l, lastp, si; char huffsize[257]; UINT16 huffcode[257]; UINT16 code; /* Figure C.1: make table of Huffman code length for each symbol */ /* Note that this is in code-length order. */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* Note that this is in code-length order. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set any codeless symbols to have code length 0; * this allows emit_bits to detect any attempt to emit such symbols. */ MEMZERO(htbl->priv.enc.ehufsi, SIZEOF(htbl->priv.enc.ehufsi)); for (p = 0; p < lastp; p++) { htbl->priv.enc.ehufco[htbl->huffval[p]] = huffcode[p]; htbl->priv.enc.ehufsi[htbl->huffval[p]] = huffsize[p]; } } /* Outputting bytes to the file */ LOCAL void flush_bytes (void) { if (bytes_in_buffer) (*cinfo->methods->entropy_output) (cinfo, output_buffer, bytes_in_buffer); bytes_in_buffer = 0; } #define emit_byte(val) \ MAKESTMT( if (bytes_in_buffer >= JPEG_BUF_SIZE) \ flush_bytes(); \ output_buffer[bytes_in_buffer++] = (char) (val); ) /* Outputting bits to the file */ /* Only the right 24 bits of huff_put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in huff_put_buffer * between calls, so 24 bits are sufficient. */ INLINE LOCAL void emit_bits (UINT16 code, int size) { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = code; register int put_bits = huff_put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(cinfo->emethods, "Missing Huffman code table entry"); put_buffer &= (((INT32) 1) << size) - 1; /* Mask off any excess bits in code */ put_bits += size; /* new number of bits in buffer */ put_buffer <<= 24 - put_bits; /* align incoming bits */ put_buffer |= huff_put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte(c); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte(0); } put_buffer <<= 8; put_bits -= 8; } huff_put_buffer = put_buffer; /* Update global variables */ huff_put_bits = put_bits; } LOCAL void flush_bits (void) { emit_bits((UINT16) 0x7F, 7); /* fill any partial byte with ones */ huff_put_buffer = 0; /* and reset bit-buffer to empty */ huff_put_bits = 0; } /* Encode a single block's worth of coefficients */ /* Note that the DC coefficient has already been converted to a difference */ LOCAL void encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl) { register int temp, temp2; register int nbits; register int k, r, i; /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0]; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Emit the Huffman-coded symbol for the number of bits */ emit_bits(dctbl->priv.enc.ehufco[nbits], dctbl->priv.enc.ehufsi[nbits]); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ emit_bits((UINT16) temp2, nbits); /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[k]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { emit_bits(actbl->priv.enc.ehufco[0xF0], actbl->priv.enc.ehufsi[0xF0]); r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while (temp >>= 1) nbits++; /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; emit_bits(actbl->priv.enc.ehufco[i], actbl->priv.enc.ehufsi[i]); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ emit_bits((UINT16) temp2, nbits); r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) emit_bits(actbl->priv.enc.ehufco[0], actbl->priv.enc.ehufsi[0]); } /* * Initialize for a Huffman-compressed scan. * This is invoked after writing the SOS marker. * The pipeline controller must establish the entropy_output method pointer * before calling this routine. */ METHODDEF void huff_init (compress_info_ptr xinfo) { short ci; jpeg_component_info * compptr; /* Initialize static variables */ cinfo = xinfo; huff_put_buffer = 0; huff_put_bits = 0; /* Initialize the output buffer */ output_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) JPEG_BUF_SIZE); bytes_in_buffer = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Make sure requested tables are present */ if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL || cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL) ERREXIT(cinfo->emethods, "Use of undefined Huffman table"); /* Compute derived values for Huffman tables */ /* We may do this more than once for same table, but it's not a big deal */ fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]); fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]); /* Initialize DC predictions to 0 */ cinfo->last_dc_val[ci] = 0; } /* Initialize restart stuff */ cinfo->restarts_to_go = cinfo->restart_interval; cinfo->next_restart_num = 0; } /* * Emit a restart marker & resynchronize predictions. */ LOCAL void emit_restart (compress_info_ptr cinfo) { short ci; flush_bits(); emit_byte(0xFF); emit_byte(RST0 + cinfo->next_restart_num); /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) cinfo->last_dc_val[ci] = 0; /* Update restart state */ cinfo->restarts_to_go = cinfo->restart_interval; cinfo->next_restart_num++; cinfo->next_restart_num &= 7; } /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ METHODDEF void huff_encode (compress_info_ptr cinfo, JBLOCK *MCU_data) { short blkn, ci; jpeg_component_info * compptr; JCOEF temp; /* Account for restart interval, emit restart marker if needed */ if (cinfo->restart_interval) { if (cinfo->restarts_to_go == 0) emit_restart(cinfo); cinfo->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Convert DC value to difference, update last_dc_val */ temp = MCU_data[blkn][0]; MCU_data[blkn][0] -= cinfo->last_dc_val[ci]; cinfo->last_dc_val[ci] = temp; encode_one_block(MCU_data[blkn], cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no], cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]); } } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF void huff_term (compress_info_ptr cinfo) { /* Flush out the last data */ flush_bits(); flush_bytes(); /* Release the I/O buffer */ (*cinfo->emethods->free_small) ((void *) output_buffer); } /* * Huffman coding optimization. * * This actually is optimization, in the sense that we find the best possible * Huffman table(s) for the given data. We first scan the supplied data and * count the number of uses of each symbol that is to be Huffman-coded. * (This process must agree with the code above.) Then we build an * optimal Huffman coding tree for the observed counts. */ #ifdef ENTROPY_OPT_SUPPORTED /* These are static so htest_one_block can find 'em */ static long * dc_count_ptrs[NUM_HUFF_TBLS]; static long * ac_count_ptrs[NUM_HUFF_TBLS]; LOCAL void gen_huff_coding (compress_info_ptr cinfo, HUFF_TBL *htbl, long freq[]) /* Generate the optimal coding for the given counts */ { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ short codesize[257]; /* codesize[k] = code length of symbol k */ short others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; long v; /* This algorithm is explained in section K.2 of the JPEG standard */ MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ freq[256] = 1; /* make sure there is a nonzero count */ /* including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 * will be placed in the largest codeword category. */ /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { /* Find the smallest nonzero frequency, set c1 = its symbol */ /* In case of ties, take the larger symbol number */ c1 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; } } /* Find the next smallest nonzero frequency, set c2 = its symbol */ /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } others[c1] = c2; /* chain c2 onto c1's tree branch */ /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo->emethods, "Huffman code size table overflow"); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. * Here is what the JPEG spec says about how this next bit works: * Since symbols are paired for the longest Huffman code, the symbols are * removed from this length category two at a time. The prefix for the pair * (which is one bit shorter) is allocated to one of the pair; then, * skipping the BITS entry for that prefix length, a code word from the next * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) j--; bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ bits[j]--; /* symbol of this length is now a prefix */ } } /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. */ p = 0; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { htbl->huffval[p] = (UINT8) j; p++; } } } } /* Process a single block's worth of coefficients */ /* Note that the DC coefficient has already been converted to a difference */ LOCAL void htest_one_block (JBLOCK block, JCOEF block0, long dc_counts[], long ac_counts[]) { register INT32 temp; register int nbits; register int k, r; /* Encode the DC coefficient difference per section F.1.2.1 */ /* Find the number of bits needed for the magnitude of the coefficient */ temp = block0; if (temp < 0) temp = -temp; for (nbits = 0; temp; nbits++) temp >>= 1; /* Count the Huffman symbol for the number of bits */ dc_counts[nbits]++; /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[k]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { ac_counts[0xF0]++; r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ if (temp < 0) temp = -temp; for (nbits = 0; temp; nbits++) temp >>= 1; /* Count Huffman symbol for run length / number of bits */ ac_counts[(r << 4) + nbits]++; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) ac_counts[0]++; } /* * Trial-encode one MCU's worth of Huffman-compressed coefficients. */ LOCAL void htest_encode (compress_info_ptr cinfo, JBLOCK *MCU_data) { short blkn, ci; jpeg_component_info * compptr; /* Take care of restart intervals if needed */ if (cinfo->restart_interval) { if (cinfo->restarts_to_go == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) cinfo->last_dc_val[ci] = 0; /* Update restart state */ cinfo->restarts_to_go = cinfo->restart_interval; } cinfo->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* NB: unlike the real entropy encoder, we may not change the input data */ htest_one_block(MCU_data[blkn], (JCOEF) (MCU_data[blkn][0] - cinfo->last_dc_val[ci]), dc_count_ptrs[compptr->dc_tbl_no], ac_count_ptrs[compptr->ac_tbl_no]); cinfo->last_dc_val[ci] = MCU_data[blkn][0]; } } /* * Find the best coding parameters for a Huffman-coded scan. * When called, the scan data has already been converted to a sequence of * MCU groups of quantized coefficients, which are stored in a "big" array. * The source_method knows how to iterate through that array. * On return, the MCU data is unmodified, but the Huffman tables referenced * by the scan components may have been altered. */ METHODDEF void huff_optimize (compress_info_ptr cinfo, MCU_output_caller_ptr source_method) /* Optimize Huffman-coding parameters (Huffman symbol table) */ { int i, tbl; HUFF_TBL **htblptr; /* Allocate and zero the count tables */ /* Note that gen_huff_coding expects 257 entries in each table! */ for (i = 0; i < NUM_HUFF_TBLS; i++) { dc_count_ptrs[i] = NULL; ac_count_ptrs[i] = NULL; } for (i = 0; i < cinfo->comps_in_scan; i++) { /* Create DC table */ tbl = cinfo->cur_comp_info[i]->dc_tbl_no; if (dc_count_ptrs[tbl] == NULL) { dc_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small) (257 * SIZEOF(long)); MEMZERO(dc_count_ptrs[tbl], 257 * SIZEOF(long)); } /* Create AC table */ tbl = cinfo->cur_comp_info[i]->ac_tbl_no; if (ac_count_ptrs[tbl] == NULL) { ac_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small) (257 * SIZEOF(long)); MEMZERO(ac_count_ptrs[tbl], 257 * SIZEOF(long)); } } /* Initialize DC predictions to 0 */ for (i = 0; i < cinfo->comps_in_scan; i++) { cinfo->last_dc_val[i] = 0; } /* Initialize restart stuff */ cinfo->restarts_to_go = cinfo->restart_interval; /* Scan the MCU data, count symbol uses */ (*source_method) (cinfo, htest_encode); /* Now generate optimal Huffman tables */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { if (dc_count_ptrs[tbl] != NULL) { htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; if (*htblptr == NULL) *htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL)); /* Set sent_table FALSE so updated table will be written to JPEG file. */ (*htblptr)->sent_table = FALSE; /* Compute the optimal Huffman encoding */ gen_huff_coding(cinfo, *htblptr, dc_count_ptrs[tbl]); /* Release the count table */ (*cinfo->emethods->free_small) ((void *) dc_count_ptrs[tbl]); } if (ac_count_ptrs[tbl] != NULL) { htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; if (*htblptr == NULL) *htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL)); /* Set sent_table FALSE so updated table will be written to JPEG file. */ (*htblptr)->sent_table = FALSE; /* Compute the optimal Huffman encoding */ gen_huff_coding(cinfo, *htblptr, ac_count_ptrs[tbl]); /* Release the count table */ (*cinfo->emethods->free_small) ((void *) ac_count_ptrs[tbl]); } } } #endif /* ENTROPY_OPT_SUPPORTED */ /* * The method selection routine for Huffman entropy encoding. */ GLOBAL void jselchuffman (compress_info_ptr cinfo) { if (! cinfo->arith_code) { cinfo->methods->entropy_encode_init = huff_init; cinfo->methods->entropy_encode = huff_encode; cinfo->methods->entropy_encode_term = huff_term; #ifdef ENTROPY_OPT_SUPPORTED cinfo->methods->entropy_optimize = huff_optimize; /* The standard Huffman tables are only valid for 8-bit data precision. * If the precision is higher, force optimization on so that usable * tables will be computed. This test can be removed if default tables * are supplied that are valid for the desired precision. */ if (cinfo->data_precision > 8) cinfo->optimize_coding = TRUE; if (cinfo->optimize_coding) cinfo->total_passes++; /* one pass needed for entropy optimization */ #endif } } he number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo->emethods, "Huffman code size table overflow"); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. xloadimage.4.1/jpeg/jcmain.c 644 221 144 53177 5340274623 11132 /* * jcmain.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for the JPEG compressor. * It should work on any system with Unix- or MS-DOS-style command lines. * * Two different command line styles are permitted, depending on the * compile-time switch TWO_FILE_COMMANDLINE: * cjpeg [options] inputfile outputfile * cjpeg [options] [inputfile] * In the second style, output is always to standard output, which you'd * normally redirect to a file or pipe to some other program. Input is * either from a named file or from standard input (typically redirected). * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. * To simplify script writing, the "-outfile" switch is provided. The syntax * cjpeg [options] -outfile outputfile inputfile * works regardless of which command line style is used. */ #include "jinclude.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare exit() */ #endif #include /* to declare isupper(), tolower() */ #ifdef NEED_SIGNAL_CATCHER #include /* to declare signal() */ #endif #ifdef USE_SETMODE #include /* to declare setmode() */ #endif #ifdef THINK_C #include /* command-line reader for Macintosh */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define WRITE_BINARY "w" #else #define READ_BINARY "rb" #define WRITE_BINARY "wb" #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS #ifdef VMS #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ #else #define EXIT_SUCCESS 0 #endif #endif #include "jversion.h" /* for version message */ /* * This routine determines what format the input file is, * and selects the appropriate input-reading module. * * To determine which family of input formats the file belongs to, * we may look only at the first byte of the file, since C does not * guarantee that more than one character can be pushed back with ungetc. * Looking at additional bytes would require one of these approaches: * 1) assume we can fseek() the input file (fails for piped input); * 2) assume we can push back more than one character (works in * some C implementations, but unportable); * 3) provide our own buffering as is done in djpeg (breaks input readers * that want to use stdio directly, such as the RLE library); * or 4) don't put back the data, and modify the input_init methods to assume * they start reading after the start of file (also breaks RLE library). * #1 is attractive for MS-DOS but is untenable on Unix. * * The most portable solution for file types that can't be identified by their * first byte is to make the user tell us what they are. This is also the * only approach for "raw" file types that contain only arbitrary values. * We presently apply this method for Targa files. Most of the time Targa * files start with 0x00, so we recognize that case. Potentially, however, * a Targa file could start with any byte value (byte 0 is the length of the * seldom-used ID field), so we provide a switch to force Targa input mode. */ static boolean is_targa; /* records user -targa switch */ LOCAL void select_file_type (compress_info_ptr cinfo) { int c; if (is_targa) { #ifdef TARGA_SUPPORTED jselrtarga(cinfo); #else ERREXIT(cinfo->emethods, "Targa support was not compiled"); #endif return; } if ((c = getc(cinfo->input_file)) == EOF) ERREXIT(cinfo->emethods, "Empty input file"); switch (c) { #ifdef GIF_SUPPORTED case 'G': jselrgif(cinfo); break; #endif #ifdef PPM_SUPPORTED case 'P': jselrppm(cinfo); break; #endif #ifdef RLE_SUPPORTED case 'R': jselrrle(cinfo); break; #endif #ifdef TARGA_SUPPORTED case 0x00: jselrtarga(cinfo); break; #endif default: #ifdef TARGA_SUPPORTED ERREXIT(cinfo->emethods, "Unrecognized input file format --- perhaps you need -targa"); #else ERREXIT(cinfo->emethods, "Unrecognized input file format"); #endif break; } if (ungetc(c, cinfo->input_file) == EOF) ERREXIT(cinfo->emethods, "ungetc failed"); } /* * This routine gets control after the input file header has been read. * It must determine what output JPEG file format is to be written, * and make any other compression parameter changes that are desirable. */ METHODDEF void c_ui_method_selection (compress_info_ptr cinfo) { /* If the input is gray scale, generate a monochrome JPEG file. */ if (cinfo->in_color_space == CS_GRAYSCALE) j_monochrome_default(cinfo); /* For now, always select JFIF output format. */ #ifdef JFIF_SUPPORTED jselwjfif(cinfo); #else You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */ #endif } /* * Signal catcher to ensure that temporary files are removed before aborting. * NB: for Amiga Manx C this is actually a global routine named _abort(); * see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus... */ #ifdef NEED_SIGNAL_CATCHER static external_methods_ptr emethods; /* for access to free_all */ GLOBAL void signal_catcher (int signum) { if (emethods != NULL) { emethods->trace_level = 0; /* turn off trace output */ (*emethods->free_all) (); /* clean up memory allocation & temp files */ } exit(EXIT_FAILURE); } #endif /* * Optional routine to display a percent-done figure on stderr. * See jcdeflts.c for explanation of the information used. */ #ifdef PROGRESS_REPORT METHODDEF void progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit) { if (cinfo->total_passes > 1) { fprintf(stderr, "\rPass %d/%d: %3d%% ", cinfo->completed_passes+1, cinfo->total_passes, (int) (loopcounter*100L/looplimit)); } else { fprintf(stderr, "\r %3d%% ", (int) (loopcounter*100L/looplimit)); } fflush(stderr); } #endif /* * Argument-parsing code. * The switch parser is designed to be useful with DOS-style command line * syntax, ie, intermixed switches and file names, where only the switches * to the left of a given file name affect processing of that file. * The main program in this file doesn't actually use this capability... */ static char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ LOCAL void usage (void) /* complain about bad command line */ { fprintf(stderr, "usage: %s [switches] ", progname); #ifdef TWO_FILE_COMMANDLINE fprintf(stderr, "inputfile outputfile\n"); #else fprintf(stderr, "[inputfile]\n"); #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n"); fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); #ifdef ENTROPY_OPT_SUPPORTED fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); #endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); #endif fprintf(stderr, "Switches for advanced users:\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); #ifdef INPUT_SMOOTHING_SUPPORTED fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); #endif fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, "Switches for wizards:\n"); #ifdef C_ARITH_CODING_SUPPORTED fprintf(stderr, " -arithmetic Use arithmetic coding\n"); #endif #ifdef C_MULTISCAN_FILES_SUPPORTED fprintf(stderr, " -nointerleave Create noninterleaved JPEG file\n"); #endif fprintf(stderr, " -qtables file Use quantization tables given in file\n"); fprintf(stderr, " -sample HxV[,...] Set JPEG sampling factors\n"); exit(EXIT_FAILURE); } LOCAL boolean keymatch (char * arg, const char * keyword, int minchars) /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ /* keyword is the constant keyword (must be lower case already), */ /* minchars is length of minimum legal abbreviation. */ { register int ca, ck; register int nmatched = 0; while ((ca = *arg++) != '\0') { if ((ck = *keyword++) == '\0') return FALSE; /* arg longer than keyword, no good */ if (isupper(ca)) /* force arg to lcase (assume ck is already) */ ca = tolower(ca); if (ca != ck) return FALSE; /* no good */ nmatched++; /* count matched characters */ } /* reached end of argument; fail if it's too short for unique abbrev */ if (nmatched < minchars) return FALSE; return TRUE; /* A-OK */ } LOCAL int qt_getc (FILE * file) /* Read next char, skipping over any comments (# to end of line) */ /* A comment/newline sequence is returned as a newline */ { register int ch; ch = getc(file); if (ch == '#') { do { ch = getc(file); } while (ch != '\n' && ch != EOF); } return ch; } LOCAL long read_qt_integer (FILE * file) /* Read an unsigned decimal integer from a quantization-table file */ /* Swallows one trailing character after the integer */ { register int ch; register long val; /* Skip any leading whitespace, detect EOF */ do { ch = qt_getc(file); if (ch == EOF) return EOF; } while (isspace(ch)); if (! isdigit(ch)) { fprintf(stderr, "%s: bogus data in quantization file\n", progname); exit(EXIT_FAILURE); } val = ch - '0'; while (ch = qt_getc(file), isdigit(ch)) { val *= 10; val += ch - '0'; } return val; } LOCAL void read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor) /* Read a set of quantization tables from the specified file. * The file is plain ASCII text: decimal numbers with whitespace between. * Comments preceded by '#' may be included in the file. * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values. * The tables are implicitly numbered 0,1,etc. */ { /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */ /* read in natural order (left to right, top to bottom). */ static const short ZIG[DCTSIZE2] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; FILE * fp; int tblno, i; long val; QUANT_TBL table; if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, filename); exit(EXIT_FAILURE); } tblno = 0; while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */ if (tblno >= NUM_QUANT_TBLS) { fprintf(stderr, "%s: too many tables in file %s\n", progname, filename); exit(EXIT_FAILURE); } table[0] = (QUANT_VAL) val; for (i = 1; i < DCTSIZE2; i++) { if ((val = read_qt_integer(fp)) == EOF) { fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename); exit(EXIT_FAILURE); } table[ZIG[i]] = (QUANT_VAL) val; } j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE); tblno++; } fclose(fp); } LOCAL void set_sample_factors (compress_info_ptr cinfo, char *arg) /* Process a sample-factors parameter string, of the form */ /* HxV[,HxV,...] */ { #define MAX_COMPONENTS 4 /* # of comp_info slots made by jcdeflts.c */ int ci, val1, val2; char ch1, ch2; for (ci = 0; ci < MAX_COMPONENTS; ci++) { if (*arg) { ch2 = ','; /* if not set by sscanf, will be ',' */ if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) usage(); if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') usage(); /* syntax check */ if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { fprintf(stderr, "JPEG sampling factors must be 1..4\n"); exit(EXIT_FAILURE); } cinfo->comp_info[ci].h_samp_factor = val1; cinfo->comp_info[ci].v_samp_factor = val2; while (*arg && *arg++ != ',') /* advance to next segment of arg string */ ; } else { /* reached end of parameter, set remaining components to 1x1 sampling */ cinfo->comp_info[ci].h_samp_factor = 1; cinfo->comp_info[ci].v_samp_factor = 1; } } } LOCAL int parse_switches (compress_info_ptr cinfo, int last_file_arg_seen, int argc, char **argv) /* Initialize cinfo with default switch settings, then parse option switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) */ { int argn; char * arg; char * qtablefile = NULL; /* saves -qtables filename if any */ int q_scale_factor = 100; /* default to no scaling for -qtables */ /* (Re-)initialize the system-dependent error and memory managers. */ jselerror(cinfo->emethods); /* error/trace message routines */ jselmemmgr(cinfo->emethods); /* memory allocation routines */ cinfo->methods->c_ui_method_selection = c_ui_method_selection; /* Now OK to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER emethods = cinfo->emethods; #endif /* Set up default JPEG parameters. */ /* Note that default -quality level here need not, and does not, * match the default scaling for an explicit -qtables argument. */ j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */ is_targa = FALSE; outfilename = NULL; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processed */ } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ if (keymatch(arg, "arithmetic", 1)) { /* Use arithmetic coding. */ #ifdef C_ARITH_CODING_SUPPORTED cinfo->arith_code = TRUE; #else fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0) fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n", JVERSION, JCOPYRIGHT); cinfo->emethods->trace_level++; } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { /* Force a monochrome JPEG file to be generated. */ j_monochrome_default(cinfo); } else if (keymatch(arg, "maxmemory", 1)) { /* Maximum memory in Kb (or Mb with 'm'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (ch == 'm' || ch == 'M') lval *= 1000L; cinfo->emethods->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nointerleave", 3)) { /* Create noninterleaved file. */ #ifdef C_MULTISCAN_FILES_SUPPORTED cinfo->interleave = FALSE; #else fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { /* Enable entropy parm optimization. */ #ifdef ENTROPY_OPT_SUPPORTED cinfo->optimize_coding = TRUE; #else fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "outfile", 3)) { /* Set output file name. */ if (++argn >= argc) /* advance to next argument */ usage(); outfilename = argv[argn]; /* save it away for later use */ } else if (keymatch(arg, "quality", 1)) { /* Quality factor (quantization table scaling factor). */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); /* Set quantization tables (will be overridden if -qtables also given). * Note: we make force_baseline FALSE. * This means non-baseline JPEG files can be created with low Q values. * To ensure only baseline files are generated, pass TRUE instead. */ j_set_quality(cinfo, val, FALSE); /* Change scale factor in case -qtables is present. */ q_scale_factor = j_quality_scaling(val); } else if (keymatch(arg, "qtables", 2)) { /* Quantization tables fetched from file. */ if (++argn >= argc) /* advance to next argument */ usage(); qtablefile = argv[argn]; /* we postpone actually reading the file in case -quality comes later */ } else if (keymatch(arg, "restart", 1)) { /* Restart interval in MCU rows (or in MCUs with 'b'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (lval < 0 || lval > 65535L) usage(); if (ch == 'b' || ch == 'B') cinfo->restart_interval = (UINT16) lval; else cinfo->restart_in_rows = (int) lval; } else if (keymatch(arg, "sample", 2)) { /* Set sampling factors. */ if (++argn >= argc) /* advance to next argument */ usage(); set_sample_factors(cinfo, argv[argn]); } else if (keymatch(arg, "smooth", 2)) { /* Set input smoothing factor. */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); if (val < 0 || val > 100) usage(); cinfo->smoothing_factor = val; } else if (keymatch(arg, "targa", 1)) { /* Input file is Targa format. */ is_targa = TRUE; } else { usage(); /* bogus switch */ } } /* Post-switch-scanning cleanup */ if (qtablefile != NULL) /* process -qtables if it was present */ read_quant_tables(cinfo, qtablefile, q_scale_factor); return argn; /* return index of next arg (file name) */ } /* * The main program. */ GLOBAL int main (int argc, char **argv) { struct Compress_info_struct cinfo; struct Compress_methods_struct c_methods; struct External_methods_struct e_methods; int file_index; /* On Mac, fetch a command line. */ #ifdef THINK_C argc = ccommand(&argv); #endif progname = argv[0]; /* Set up links to method structures. */ cinfo.methods = &c_methods; cinfo.emethods = &e_methods; /* Install, but don't yet enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER emethods = NULL; signal(SIGINT, signal_catcher); #ifdef SIGTERM /* not all systems have SIGTERM */ signal(SIGTERM, signal_catcher); #endif #endif /* Scan command line: set up compression parameters, find file names. */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdin), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdin\n", progname); exit(EXIT_FAILURE); } #else cinfo.input_file = stdin; #endif } /* Open the output file. */ if (outfilename != NULL) { if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdout), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdout\n", progname); exit(EXIT_FAILURE); } #else cinfo.output_file = stdout; #endif } /* Figure out the input file format, and set up to read it. */ select_file_type(&cinfo); #ifdef PROGRESS_REPORT /* Start up progress display, unless trace output is on */ if (e_methods.trace_level == 0) c_methods.progress_monitor = progress_monitor; #endif /* Do it to it! */ jpeg_compress(&cinfo); #ifdef PROGRESS_REPORT /* Clear away progress display */ if (e_methods.trace_level == 0) { fprintf(stderr, "\r \r"); fflush(stderr); } #endif /* All done. */ exit(EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ } FALSE; outfilename = NULL; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processexloadimage.4.1/jpeg/jcmaster.c 644 221 144 10156 5300071635 11461 /* * jcmaster.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main control for the JPEG compressor. * The system-dependent (user interface) code should call jpeg_compress() * after doing appropriate setup of the compress_info_struct parameter. */ #include "jinclude.h" METHODDEF void c_per_scan_method_selection (compress_info_ptr cinfo) /* Central point for per-scan method selection */ { /* Edge expansion */ jselexpand(cinfo); /* Downsampling of pixels */ jseldownsample(cinfo); /* MCU extraction */ jselcmcu(cinfo); } LOCAL void c_initial_method_selection (compress_info_ptr cinfo) /* Central point for initial method selection */ { /* Input image reading method selection is already done. */ /* So is output file header formatting (both are done by user interface). */ /* Gamma and color space conversion */ jselccolor(cinfo); /* Entropy encoding: either Huffman or arithmetic coding. */ #ifdef C_ARITH_CODING_SUPPORTED jselcarithmetic(cinfo); #else cinfo->arith_code = FALSE; /* force Huffman mode */ #endif jselchuffman(cinfo); /* Pipeline control */ jselcpipeline(cinfo); /* Overall control (that's me!) */ cinfo->methods->c_per_scan_method_selection = c_per_scan_method_selection; } LOCAL void initial_setup (compress_info_ptr cinfo) /* Do computations that are needed before initial method selection */ { short ci; jpeg_component_info *compptr; /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo->emethods, "Bogus sampling factors"); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute logical downsampled dimensions of components */ for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor + cinfo->max_h_samp_factor - 1) / cinfo->max_h_samp_factor; compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor + cinfo->max_v_samp_factor - 1) / cinfo->max_v_samp_factor; } } /* * This is the main entry point to the JPEG compressor. */ GLOBAL void jpeg_compress (compress_info_ptr cinfo) { /* Init pass counts to 0 --- total_passes is adjusted in method selection */ cinfo->total_passes = 0; cinfo->completed_passes = 0; /* Read the input file header: determine image size & component count. * NOTE: the user interface must have initialized the input_init method * pointer (eg, by calling jselrppm) before calling me. * The other file reading methods (get_input_row etc.) were probably * set at the same time, but could be set up by input_init itself, * or by c_ui_method_selection. */ (*cinfo->methods->input_init) (cinfo); /* Give UI a chance to adjust compression parameters and select */ /* output file format based on results of input_init. */ (*cinfo->methods->c_ui_method_selection) (cinfo); /* Now select methods for compression steps. */ initial_setup(cinfo); c_initial_method_selection(cinfo); /* Initialize the output file & other modules as needed */ /* (entropy_encoder is inited by pipeline controller) */ (*cinfo->methods->colorin_init) (cinfo); (*cinfo->methods->write_file_header) (cinfo); /* And let the pipeline controller do the rest. */ (*cinfo->methods->c_pipeline_controller) (cinfo); /* Finish output file, release working storage, etc */ (*cinfo->methods->write_file_trailer) (cinfo); (*cinfo->methods->colorin_term) (cinfo); (*cinfo->methods->input_term) (cinfo); (*cinfo->emethods->free_all) (); /* My, that was easy, wasn't it? */ } info->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo->emethods, "Bogus sampling factors"); cinfo->max_h_samp_factor = MAX(cinfo->max_xloadimage.4.1/jpeg/jcmcu.c 644 221 144 14753 5313122760 10761 /* * jcmcu.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains MCU extraction routines and quantization scaling. * These routines are invoked via the extract_MCUs and * extract_init/term methods. */ #include "jinclude.h" /* * If this file is compiled with -DDCT_ERR_STATS, it will reverse-DCT each * block and sum the total errors across the whole picture. This provides * a convenient method of using real picture data to test the roundoff error * of a DCT algorithm. DCT_ERR_STATS should *not* be defined for a production * compression program, since compression is much slower with it defined. * Also note that jrevdct.o must be linked into the compressor when this * switch is defined. */ #ifdef DCT_ERR_STATS static int dcterrorsum; /* these hold the error statistics */ static int dcterrormax; static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine */ #endif /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ static const int ZAG[DCTSIZE2] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; LOCAL void extract_block (JSAMPARRAY input_data, int start_row, long start_col, JBLOCK output_data, QUANT_TBL_PTR quanttbl) /* Extract one 8x8 block from the specified location in the sample array; */ /* perform forward DCT, quantization scaling, and zigzag reordering on it. */ { /* This routine is heavily used, so it's worth coding it tightly. */ DCTBLOCK block; #ifdef DCT_ERR_STATS DCTBLOCK svblock; /* saves input data for comparison */ #endif { register JSAMPROW elemptr; register DCTELEM *localblkptr = block; register int elemr; for (elemr = DCTSIZE; elemr > 0; elemr--) { elemptr = input_data[start_row++] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); } } #endif } } #ifdef DCT_ERR_STATS MEMCOPY(svblock, block, SIZEOF(DCTBLOCK)); #endif j_fwd_dct(block); { register JCOEF temp; register QUANT_VAL qval; register int i; for (i = 0; i < DCTSIZE2; i++) { qval = *quanttbl++; temp = (JCOEF) block[ZAG[i]]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) (a >= b) ? (a /= b) : (a = 0) #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } *output_data++ = temp; } } #ifdef DCT_ERR_STATS j_rev_dct(block); { register int diff; register int i; for (i = 0; i < DCTSIZE2; i++) { diff = block[i] - svblock[i]; if (diff < 0) diff = -diff; dcterrorsum += diff; if (dcterrormax < diff) dcterrormax = diff; } dctcoefcount += DCTSIZE2; } #endif } /* * Extract samples in MCU order, process & hand off to output_method. * The input is always exactly N MCU rows worth of data. */ METHODDEF void extract_MCUs (compress_info_ptr cinfo, JSAMPIMAGE image_data, int num_mcu_rows, MCU_output_method_ptr output_method) { JBLOCK MCU_data[MAX_BLOCKS_IN_MCU]; int mcurow; long mcuindex; short blkn, ci, xpos, ypos; jpeg_component_info * compptr; QUANT_TBL_PTR quant_ptr; for (mcurow = 0; mcurow < num_mcu_rows; mcurow++) { for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Extract data from the image array, DCT it, and quantize it */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { for (xpos = 0; xpos < compptr->MCU_width; xpos++) { extract_block(image_data[ci], (mcurow * compptr->MCU_height + ypos)*DCTSIZE, (mcuindex * compptr->MCU_width + xpos)*DCTSIZE, MCU_data[blkn], quant_ptr); blkn++; } } } /* Send the MCU whereever the pipeline controller wants it to go */ (*output_method) (cinfo, MCU_data); } } } /* * Initialize for processing a scan. */ METHODDEF void extract_init (compress_info_ptr cinfo) { /* no work for now */ #ifdef DCT_ERR_STATS dcterrorsum = dcterrormax = dctcoefcount = 0; #endif } /* * Clean up after a scan. */ METHODDEF void extract_term (compress_info_ptr cinfo) { /* no work for now */ #ifdef DCT_ERR_STATS TRACEMS3(cinfo->emethods, 0, "DCT roundoff errors = %d/%d, max = %d", dcterrorsum, dctcoefcount, dcterrormax); #endif } /* * The method selection routine for MCU extraction. */ GLOBAL void jselcmcu (compress_info_ptr cinfo) { /* just one implementation for now */ cinfo->methods->extract_init = extract_init; cinfo->methods->extract_MCUs = extract_MCUs; cinfo->methods->extract_term = extract_term; } nt; /* This will probxloadimage.4.1/jpeg/jconfig.h 644 221 144 27442 5340324636 11311 /* * jconfig.h * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains preprocessor declarations that help customize * the JPEG software for a particular application, machine, or compiler. * Edit these declarations as needed (or add -D flags to the Makefile). */ /* * These symbols indicate the properties of your machine or compiler. * The conditional definitions given may do the right thing already, * but you'd best look them over closely, especially if your compiler * does not handle full ANSI C. An ANSI-compliant C compiler should * provide all the necessary features; __STDC__ is supposed to be * predefined by such compilers. */ /* * HAVE_STDC is tested below to see whether ANSI features are available. * We avoid testing __STDC__ directly for arcane reasons of portability. * (On some compilers, __STDC__ is only defined if a switch is given, * but the switch also disables machine-specific features we need to get at. * In that case, -DHAVE_STDC in the Makefile is a convenient solution.) */ #ifdef __STDC__ /* if compiler claims to be ANSI, believe it */ #define HAVE_STDC #endif /* Does your compiler support function prototypes? */ /* (If not, you also need to use ansi2knr, see SETUP) */ #ifdef HAVE_STDC /* ANSI C compilers always have prototypes */ #define PROTO #else #ifdef __cplusplus /* So do C++ compilers */ #define PROTO #endif #endif /* Does your compiler support the declaration "unsigned char" ? */ /* How about "unsigned short" ? */ #ifdef HAVE_STDC /* ANSI C compilers must support both */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT #endif /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then it doesn't matter very much. */ /* #define CHAR_IS_UNSIGNED */ /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ /* #define RIGHT_SHIFT_IS_UNSIGNED */ /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define const as empty if your compiler doesn't know the "const" keyword. */ /* (Even if it does, defining const as empty won't break anything.) */ #ifndef HAVE_STDC /* ANSI C and C++ compilers should know it. */ #ifndef __cplusplus #define const #endif #endif /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #ifdef MSDOS #define NEED_FAR_POINTERS #endif /* The next three symbols only affect the system-dependent user interface * modules (jcmain.c, jdmain.c). You can ignore these if you are supplying * your own user interface code. */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of jcmain.c or jdmain.c. */ #ifdef MSDOS /* two-file style is needed for PCs */ #ifndef USE_FDOPEN /* unless you have fdopen() or setmode() */ #ifndef USE_SETMODE #define TWO_FILE_COMMANDLINE #endif #endif #endif #ifdef THINK_C /* it's needed for Macintosh too */ #define TWO_FILE_COMMANDLINE #endif /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #ifdef MSDOS #define NEED_SIGNAL_CATCHER #endif /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ /* #define DONT_USE_B_MODE */ /* If you're getting bored, that's the end of the symbols you HAVE to * worry about. Go fix the makefile and compile. */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE /* default is to define it as empty */ #define INLINE #endif /* On a few systems, type boolean and/or macros FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * In that case you need only comment out these definitions. */ typedef int boolean; #undef FALSE /* in case these macros already exist */ #undef TRUE #define FALSE 0 /* values of boolean */ #define TRUE 1 /* This defines the size of the I/O buffers for entropy compression * and decompression; you could reduce it if memory is tight. */ #define JPEG_BUF_SIZE 4096 /* bytes */ /* These symbols determine the JPEG functionality supported. */ /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * program file. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ /* Encoder capability options: */ #undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ #define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ /* these defines indicate which JPEG file formats are allowed */ #define JFIF_SUPPORTED /* JFIF or "raw JPEG" files */ #undef JTIFF_SUPPORTED /* JPEG-in-TIFF (not yet implemented) */ /* these defines indicate which image (non-JPEG) file formats are allowed */ #define GIF_SUPPORTED /* GIF image file format */ /* #define RLE_SUPPORTED */ /* RLE image file format (by default, no) */ #define PPM_SUPPORTED /* PPM/PGM image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #undef TIFF_SUPPORTED /* TIFF image file format (not yet impl.) */ /* more capability options later, no doubt */ /* * Define exactly one of these three symbols to indicate whether you want * 8-bit, 12-bit, or 16-bit sample (pixel component) values. 8-bit is the * default and is nearly always the right thing to use. You can use 12-bit if * you need to support image formats with more than 8 bits of resolution in a * color value. 16-bit should only be used for the lossless JPEG mode (not * currently supported). Note that 12- and 16-bit values take up twice as * much memory as 8-bit! * Note: if you select 12- or 16-bit precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. */ #define EIGHT_BIT_SAMPLES #undef TWELVE_BIT_SAMPLES #undef SIXTEEN_BIT_SAMPLES /* * The remaining definitions don't need to be hand-edited in most cases. * You may need to change these if you have a machine with unusual data * types; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* First define the representation of a single pixel element value. */ #ifdef EIGHT_BIT_SAMPLES /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. * If you have only signed chars, and you are more worried about speed than * memory usage, it might be a win to make JSAMPLE be short. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not CHAR_IS_UNSIGNED */ typedef char JSAMPLE; #define GETJSAMPLE(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define BITS_IN_JSAMPLE 8 #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* EIGHT_BIT_SAMPLES */ #ifdef TWELVE_BIT_SAMPLES /* JSAMPLE should be the smallest type that will hold the values 0..4095. */ /* On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) (value) #define BITS_IN_JSAMPLE 12 #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* TWELVE_BIT_SAMPLES */ #ifdef SIXTEEN_BIT_SAMPLES /* JSAMPLE should be the smallest type that will hold the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not HAVE_UNSIGNED_SHORT */ /* If int is 32 bits this'll be horrendously inefficient storage-wise. * But since we don't actually support 16-bit samples (ie lossless coding) yet, * I'm not going to worry about making a smarter definition ... */ typedef unsigned int JSAMPLE; #define GETJSAMPLE(value) (value) #endif /* HAVE_UNSIGNED_SHORT */ #define BITS_IN_JSAMPLE 16 #define MAXJSAMPLE 65535 #define CENTERJSAMPLE 32768 #endif /* SIXTEEN_BIT_SAMPLES */ /* Here we define the representation of a DCT frequency coefficient. * This should be a signed 16-bit value; "short" is usually right. * It's important that this be exactly 16 bits, no more and no less; * more will cost you a BIG hit of memory, less will give wrong answers. */ typedef short JCOEF; /* The remaining typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif /* INT32 must hold signed 32-bit values; if your machine happens */ /* to have 64-bit longs, you might want to change this. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif rs for entropy compression * and decompression; you could reduce it if memory is tight. */ #define JPEG_BUF_SIZE 4096 /* bytes */ /* These symbols determine the JPEG functionality supported. */ /* * These defines ixloadimage.4.1/jpeg/jcpipe.c 644 221 144 64431 5300071725 11130 /* * jcpipe.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression pipeline controllers. * These routines are invoked via the c_pipeline_controller method. * * There are four basic pipeline controllers, one for each combination of: * single-scan JPEG file (single component or fully interleaved) * vs. multiple-scan JPEG file (noninterleaved or partially interleaved). * * optimization of entropy encoding parameters * vs. usage of default encoding parameters. * * Note that these conditions determine the needs for "big" arrays: * multiple scans imply a big array for splitting the color components; * entropy encoding optimization needs a big array for the MCU data. * * All but the simplest controller (single-scan, no optimization) can be * compiled out through configuration options, if you need to make a minimal * implementation. */ #include "jinclude.h" /* * About the data structures: * * The processing chunk size for downsampling is referred to in this file as * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of * any component after downsampling, or Vmax (max_v_samp_factor) unsubsampled * rows. In an interleaved scan each MCU row contains exactly DCTSIZE row * groups of each component in the scan. In a noninterleaved scan an MCU row * is one row of blocks, which might not be an integral number of row groups; * for convenience we use a buffer of the same size as in interleaved scans, * and process Vk MCU rows in each burst of downsampling. * To provide context for the downsampling step, we have to retain the last * two row groups of the previous MCU row while reading in the next MCU row * (or set of Vk MCU rows). To do this without copying data about, we create * a rather strange data structure. Exactly DCTSIZE+2 row groups of samples * are allocated, but we create two different sets of pointers to this array. * The second set swaps the last two pairs of row groups. By working * alternately with the two sets of pointers, we can access the data in the * desired order. */ /* * Utility routines: common code for pipeline controllers */ LOCAL void interleaved_scan_setup (compress_info_ptr cinfo) /* Compute all derived info for an interleaved (multi-component) scan */ /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */ { short ci, mcublks; jpeg_component_info *compptr; if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->MCUs_per_row = (cinfo->image_width + cinfo->max_h_samp_factor*DCTSIZE - 1) / (cinfo->max_h_samp_factor*DCTSIZE); cinfo->MCU_rows_in_scan = (cinfo->image_height + cinfo->max_v_samp_factor*DCTSIZE - 1) / (cinfo->max_v_samp_factor*DCTSIZE); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* for interleaved scan, sampling factors give # of blocks per component */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) (compptr->MCU_width*DCTSIZE)); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) (compptr->MCU_height*DCTSIZE)); /* Sanity check */ if (compptr->downsampled_width != (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE))) ERREXIT(cinfo->emethods, "I'm confused about the image width"); /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan"); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row; cinfo->restart_interval = (UINT16) MIN(nominal, 65535L); } (*cinfo->methods->c_per_scan_method_selection) (cinfo); } LOCAL void noninterleaved_scan_setup (compress_info_ptr cinfo) /* Compute all derived info for a noninterleaved (single-component) scan */ /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */ { jpeg_component_info *compptr = cinfo->cur_comp_info[0]; /* for noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) DCTSIZE); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) DCTSIZE); cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE; cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row; cinfo->restart_interval = (UINT16) MIN(nominal, 65535L); } (*cinfo->methods->c_per_scan_method_selection) (cinfo); } LOCAL void alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2], long fullsize_width) /* Create a pre-downsampling data buffer having the desired structure */ /* (see comments at head of file) */ { short ci, vs, i; vs = cinfo->max_v_samp_factor; /* row group height */ /* Get top-level space for array pointers */ fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < cinfo->num_components; ci++) { /* Allocate the real storage */ fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray) (fullsize_width, (long) (vs * (DCTSIZE+2))); /* Create space for the scrambled-order pointers */ fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small) (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW)); /* Duplicate the first DCTSIZE-2 row groups */ for (i = 0; i < vs * (DCTSIZE-2); i++) { fullsize_data[1][ci][i] = fullsize_data[0][ci][i]; } /* Copy the last four row groups in swapped order */ for (i = 0; i < vs * 2; i++) { fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i]; fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i]; } } } #if 0 /* this routine not currently needed */ LOCAL void free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2]) /* Release a sampling buffer created by alloc_sampling_buffer */ { short ci; for (ci = 0; ci < cinfo->num_components; ci++) { /* Free the real storage */ (*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]); /* Free the scrambled-order pointers */ (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]); } /* Free the top-level space */ (*cinfo->emethods->free_small) ((void *) fullsize_data[0]); (*cinfo->emethods->free_small) ((void *) fullsize_data[1]); } #endif LOCAL void downsample (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data, JSAMPIMAGE sampled_data, long fullsize_width, short above, short current, short below, short out) /* Do downsampling of a single row group (of each component). */ /* above, current, below are indexes of row groups in fullsize_data; */ /* out is the index of the target row group in sampled_data. */ /* Special case: above, below can be -1 to indicate top, bottom of image. */ { jpeg_component_info *compptr; JSAMPARRAY above_ptr, below_ptr; JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */ short ci, vs, i; vs = cinfo->max_v_samp_factor; /* row group height */ for (ci = 0; ci < cinfo->num_components; ci++) { compptr = & cinfo->comp_info[ci]; if (above >= 0) above_ptr = fullsize_data[ci] + above * vs; else { /* Top of image: make a dummy above-context with copies of 1st row */ /* We assume current=0 in this case */ for (i = 0; i < vs; i++) dummy[i] = fullsize_data[ci][0]; above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */ } if (below >= 0) below_ptr = fullsize_data[ci] + below * vs; else { /* Bot of image: make a dummy below-context with copies of last row */ for (i = 0; i < vs; i++) dummy[i] = fullsize_data[ci][(current+1)*vs-1]; below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */ } (*cinfo->methods->downsample[ci]) (cinfo, (int) ci, fullsize_width, (int) vs, compptr->downsampled_width, (int) compptr->v_samp_factor, above_ptr, fullsize_data[ci] + current * vs, below_ptr, sampled_data[ci] + out * compptr->v_samp_factor); } } /* These variables are initialized by the pipeline controller for use by * MCU_output_catcher. * To avoid a lot of row-pointer overhead, we cram as many MCUs into each * row of whole_scan_MCUs as we can get without exceeding 32Kbytes per row. * NOTE: the "arbitrary" constant here must not exceed MAX_ALLOC_CHUNK * defined in jmemsys.h, which is 64K-epsilon in most DOS implementations. */ #define MAX_WHOLE_ROW_BLOCKS ((int) (32768L / SIZEOF(JBLOCK))) /* max blocks/row */ static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */ static int MCUs_in_big_row; /* # of MCUs in each row of whole_scan_MCUs */ static long next_whole_row; /* next row to access in whole_scan_MCUs */ static int next_MCU_index; /* next MCU in current row */ METHODDEF void MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data) /* Output method for siphoning off extract_MCUs output into a big array */ { static JBLOCKARRAY rowptr; if (next_MCU_index >= MCUs_in_big_row) { rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs, next_whole_row, TRUE); next_whole_row++; next_MCU_index = 0; } /* * note that on 80x86, the cast applied to MCU_data implies * near to far pointer conversion. */ jcopy_block_row((JBLOCKROW) MCU_data, rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU, (long) cinfo->blocks_in_MCU); next_MCU_index++; } METHODDEF void dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method) /* Dump the MCUs saved in whole_scan_MCUs to the output method. */ /* The method may be either the entropy encoder or some routine supplied */ /* by the entropy optimizer. */ { /* On an 80x86 machine, the entropy encoder expects the passed data block * to be in NEAR memory (for performance reasons), so we have to copy it * back from the big array to a local array. On less brain-damaged CPUs * we needn't do that. */ #ifdef NEED_FAR_POINTERS JBLOCK MCU_data[MAX_BLOCKS_IN_MCU]; #endif long mcurow, mcuindex, next_row; int next_index; JBLOCKARRAY rowptr = NULL; /* init only to suppress compiler complaint */ next_row = 0; next_index = MCUs_in_big_row; for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) { (*cinfo->methods->progress_monitor) (cinfo, mcurow, cinfo->MCU_rows_in_scan); for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { if (next_index >= MCUs_in_big_row) { rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs, next_row, FALSE); next_row++; next_index = 0; } #ifdef NEED_FAR_POINTERS jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU, (JBLOCKROW) MCU_data, /* casts near to far pointer! */ (long) cinfo->blocks_in_MCU); (*output_method) (cinfo, MCU_data); #else (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU); #endif next_index++; } } cinfo->completed_passes++; } /* * Compression pipeline controller used for single-scan files * with no optimization of entropy parameters. */ METHODDEF void single_ccontroller (compress_info_ptr cinfo) { int rows_in_mem; /* # of sample rows in full-size buffers */ long fullsize_width; /* # of samples per row in full-size buffers */ long cur_pixel_row; /* counts # of pixel rows processed */ long mcu_rows_output; /* # of MCU rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for pre-downsampling data (see comments at head of file) */ JSAMPIMAGE fullsize_data[2]; /* Work buffer for downsampled data */ JSAMPIMAGE sampled_data; int rows_this_time; short ci, whichss, i; /* Prepare for single scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Vk block rows constitute the same number of MCU rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row contains Vk block rows */ mcu_rows_per_loop = 1; } cinfo->total_passes++; /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate working memory: */ /* fullsize_data is sample data before downsampling */ alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width); /* sampled_data is sample data after downsampling */ sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < cinfo->num_components; ci++) { sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray) (cinfo->comp_info[ci].downsampled_width, (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE)); } /* Tell the memory manager to instantiate big arrays. * We don't need any big arrays in this controller, * but some other module (like the input file reader) may need one. */ (*cinfo->emethods->alloc_big_arrays) ((long) 0, /* no more small sarrays */ (long) 0, /* no more small barrays */ (long) 0); /* no more "medium" objects */ /* Initialize output file & do per-scan object init */ (*cinfo->methods->write_scan_header) (cinfo); cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data; (*cinfo->methods->entropy_encode_init) (cinfo); (*cinfo->methods->downsample_init) (cinfo); (*cinfo->methods->extract_init) (cinfo); /* Loop over input image: rows_in_mem pixel rows are processed per loop */ mcu_rows_output = 0; whichss = 1; /* arrange to start with fullsize_data[0] */ for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height; cur_pixel_row += rows_in_mem) { (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row, cinfo->image_height); whichss ^= 1; /* switch to other fullsize_data buffer */ /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */ /* Then we have exactly DCTSIZE row groups for downsampling. */ rows_this_time = (int) MIN((long) rows_in_mem, cinfo->image_height - cur_pixel_row); (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time, fullsize_data[whichss]); (*cinfo->methods->edge_expand) (cinfo, cinfo->image_width, rows_this_time, fullsize_width, rows_in_mem, fullsize_data[whichss]); /* Downsample the data (all components) */ /* First time through is a special case */ if (cur_pixel_row) { /* Downsample last row group of previous set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* and dump the previous set's downsampled data */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, mcu_rows_per_loop, cinfo->methods->entropy_encode); mcu_rows_output += mcu_rows_per_loop; /* Downsample first row group of this set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Downsample first row group with dummy above-context */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Downsample second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of outer loop */ /* Downsample the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* Dump the remaining data (may be less than full height if uninterleaved) */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, (int) (cinfo->MCU_rows_in_scan - mcu_rows_output), cinfo->methods->entropy_encode); /* Finish output file */ (*cinfo->methods->extract_term) (cinfo); (*cinfo->methods->downsample_term) (cinfo); (*cinfo->methods->entropy_encode_term) (cinfo); (*cinfo->methods->write_scan_trailer) (cinfo); cinfo->completed_passes++; /* Release working memory */ /* (no work -- we let free_all release what's needful) */ } /* * Compression pipeline controller used for single-scan files * with optimization of entropy parameters. */ #ifdef ENTROPY_OPT_SUPPORTED METHODDEF void single_eopt_ccontroller (compress_info_ptr cinfo) { int rows_in_mem; /* # of sample rows in full-size buffers */ long fullsize_width; /* # of samples per row in full-size buffers */ long cur_pixel_row; /* counts # of pixel rows processed */ long mcu_rows_output; /* # of MCU rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for pre-downsampling data (see comments at head of file) */ JSAMPIMAGE fullsize_data[2]; /* Work buffer for downsampled data */ JSAMPIMAGE sampled_data; int rows_this_time; int blocks_in_big_row; short ci, whichss, i; /* Prepare for single scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Vk block rows constitute the same number of MCU rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row contains Vk block rows */ mcu_rows_per_loop = 1; } cinfo->total_passes += 2; /* entropy encoder must add # passes it uses */ /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate working memory: */ /* fullsize_data is sample data before downsampling */ alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width); /* sampled_data is sample data after downsampling */ sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < cinfo->num_components; ci++) { sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray) (cinfo->comp_info[ci].downsampled_width, (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE)); } /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */ MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU; blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU; /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */ whole_scan_MCUs = (*cinfo->emethods->request_big_barray) ((long) blocks_in_big_row, (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan + MCUs_in_big_row-1) / MCUs_in_big_row, 1L); /* unit height is 1 row */ next_whole_row = 0; /* init output ptr for MCU_output_catcher */ next_MCU_index = MCUs_in_big_row; /* forces access on first call! */ /* Tell the memory manager to instantiate big arrays */ (*cinfo->emethods->alloc_big_arrays) ((long) 0, /* no more small sarrays */ (long) 0, /* no more small barrays */ (long) 0); /* no more "medium" objects */ /* Do per-scan object init */ (*cinfo->methods->downsample_init) (cinfo); (*cinfo->methods->extract_init) (cinfo); /* Loop over input image: rows_in_mem pixel rows are processed per loop */ /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */ mcu_rows_output = 0; whichss = 1; /* arrange to start with fullsize_data[0] */ for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height; cur_pixel_row += rows_in_mem) { (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row, cinfo->image_height); whichss ^= 1; /* switch to other fullsize_data buffer */ /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */ /* Then we have exactly DCTSIZE row groups for downsampling. */ rows_this_time = (int) MIN((long) rows_in_mem, cinfo->image_height - cur_pixel_row); (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time, fullsize_data[whichss]); (*cinfo->methods->edge_expand) (cinfo, cinfo->image_width, rows_this_time, fullsize_width, rows_in_mem, fullsize_data[whichss]); /* Downsample the data (all components) */ /* First time through is a special case */ if (cur_pixel_row) { /* Downsample last row group of previous set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* and dump the previous set's downsampled data */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, mcu_rows_per_loop, MCU_output_catcher); mcu_rows_output += mcu_rows_per_loop; /* Downsample first row group of this set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Downsample first row group with dummy above-context */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Downsample second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of outer loop */ /* Downsample the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* Dump the remaining data (may be less than full height if uninterleaved) */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, (int) (cinfo->MCU_rows_in_scan - mcu_rows_output), MCU_output_catcher); /* Clean up after that stuff, then find the optimal entropy parameters */ (*cinfo->methods->extract_term) (cinfo); (*cinfo->methods->downsample_term) (cinfo); cinfo->completed_passes++; (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs); /* Emit scan to output file */ /* Note: we can't do write_scan_header until entropy parameters are set! */ (*cinfo->methods->write_scan_header) (cinfo); cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data; (*cinfo->methods->entropy_encode_init) (cinfo); dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode); (*cinfo->methods->entropy_encode_term) (cinfo); (*cinfo->methods->write_scan_trailer) (cinfo); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ } #endif /* ENTROPY_OPT_SUPPORTED */ /* * Compression pipeline controller used for multiple-scan files * with no optimization of entropy parameters. */ #ifdef C_MULTISCAN_FILES_SUPPORTED METHODDEF void multi_ccontroller (compress_info_ptr cinfo) { ERREXIT(cinfo->emethods, "Not implemented yet"); } #endif /* C_MULTISCAN_FILES_SUPPORTED */ /* * Compression pipeline controller used for multiple-scan files * with optimization of entropy parameters. */ #ifdef C_MULTISCAN_FILES_SUPPORTED #ifdef ENTROPY_OPT_SUPPORTED METHODDEF void multi_eopt_ccontroller (compress_info_ptr cinfo) { ERREXIT(cinfo->emethods, "Not implemented yet"); } #endif /* ENTROPY_OPT_SUPPORTED */ #endif /* C_MULTISCAN_FILES_SUPPORTED */ /* * The method selection routine for compression pipeline controllers. */ GLOBAL void jselcpipeline (compress_info_ptr cinfo) { if (cinfo->interleave || cinfo->num_components == 1) { /* single scan needed */ #ifdef ENTROPY_OPT_SUPPORTED if (cinfo->optimize_coding) cinfo->methods->c_pipeline_controller = single_eopt_ccontroller; else #endif cinfo->methods->c_pipeline_controller = single_ccontroller; } else { /* multiple scans needed */ #ifdef C_MULTISCAN_FILES_SUPPORTED #ifdef ENTROPY_OPT_SUPPORTED if (cinfo->optimize_coding) cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller; else #endif cinfo->methods->c_pipeline_controller = multi_ccontroller; #else ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled"); #endif } } * # of sample rows in full-size buffers */ long fullsize_width; /* # of samples per row in full-size buffers */ long cur_pixel_row; /* counts # of pixel rows processed */ long mcu_rows_output; /* # of MCU rows actually emixloadimage.4.1/jpeg/jcsample.c 644 221 144 40130 5276241655 11457 /* * jcsample.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains downsampling routines. * These routines are invoked via the downsample and * downsample_init/term methods. * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. * * The downsampling algorithm used here is a simple average of the source * pixels covered by the output pixel. The hi-falutin sampling literature * refers to this as a "box filter". In general the characteristics of a box * filter are not very good, but for the specific cases we normally use (1:1 * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not * nearly so bad. If you intend to use other sampling ratios, you'd be well * advised to improve this code. * * A simple input-smoothing capability is provided. This is mainly intended * for cleaning up color-dithered GIF input files (if you find it inadequate, * we suggest using an external filtering program such as pnmconvol). When * enabled, each input pixel P is replaced by a weighted sum of itself and its * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, * where SF = (smoothing_factor / 1024). * Currently, smoothing is only supported for 2h2v sampling factors. */ #include "jinclude.h" /* * Initialize for downsampling a scan. */ METHODDEF void downsample_init (compress_info_ptr cinfo) { /* no work for now */ } /* * Downsample pixel values of a single component. * This version handles arbitrary integral sampling ratios, without smoothing. * Note that this version is not actually used for customary sampling ratios. */ METHODDEF void int_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; long outcol, outcol_h; /* outcol_h == outcol*h_expand */ JSAMPROW inptr, outptr; INT32 outvalue; #ifdef DEBUG /* for debugging pipeline controller */ if (output_rows != compptr->v_samp_factor || input_rows != cinfo->max_v_samp_factor || (output_cols % compptr->h_samp_factor) != 0 || (input_cols % cinfo->max_h_samp_factor) != 0 || input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus downsample parameters"); #endif h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; numpix = h_expand * v_expand; numpix2 = numpix/2; inrow = 0; for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { outvalue = 0; for (v = 0; v < v_expand; v++) { inptr = input_data[inrow+v] + outcol_h; for (h = 0; h < h_expand; h++) { outvalue += (INT32) GETJSAMPLE(*inptr++); } } *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; } } /* * Downsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 1:1 vertical, * without smoothing. */ METHODDEF void h2v1_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { int outrow; long outcol; register JSAMPROW inptr, outptr; #ifdef DEBUG /* for debugging pipeline controller */ jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; if (output_rows != compptr->v_samp_factor || input_rows != cinfo->max_v_samp_factor || (output_cols % compptr->h_samp_factor) != 0 || (input_cols % cinfo->max_h_samp_factor) != 0 || input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus downsample parameters"); #endif for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + 1) >> 1); inptr += 2; } } } /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * without smoothing. */ METHODDEF void h2v2_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { int inrow, outrow; long outcol; register JSAMPROW inptr0, inptr1, outptr; #ifdef DEBUG /* for debugging pipeline controller */ jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; if (output_rows != compptr->v_samp_factor || input_rows != cinfo->max_v_samp_factor || (output_cols % compptr->h_samp_factor) != 0 || (input_cols % cinfo->max_h_samp_factor) != 0 || input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus downsample parameters"); #endif inrow = 0; for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + 2) >> 2); inptr0 += 2; inptr1 += 2; } inrow += 2; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * without smoothing. */ METHODDEF void fullsize_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { #ifdef DEBUG /* for debugging pipeline controller */ if (input_cols != output_cols || input_rows != output_rows) ERREXIT(cinfo->emethods, "Pipeline controller messed up"); #endif jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols); } #ifdef INPUT_SMOOTHING_SUPPORTED /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * with smoothing. */ METHODDEF void h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { int inrow, outrow; long colctr; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; #ifdef DEBUG /* for debugging pipeline controller */ jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; if (output_rows != compptr->v_samp_factor || input_rows != cinfo->max_v_samp_factor || (output_cols % compptr->h_samp_factor) != 0 || (input_cols % cinfo->max_h_samp_factor) != 0 || input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus downsample parameters"); #endif /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four * smoothed values. Each of the four member pixels contributes a fraction * (1-8*SF) to its own smoothed image and a fraction SF to each of the three * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final * output. The four corner-adjacent neighbor pixels contribute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; if (inrow == 0) above_ptr = above[input_rows-1]; else above_ptr = input_data[inrow-1]; if (inrow >= input_rows-2) below_ptr = below[0]; else below_ptr = input_data[inrow+2]; /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768L) >> 16); inrow += 2; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * with smoothing. */ METHODDEF void fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { int outrow; long colctr; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; #ifdef DEBUG /* for debugging pipeline controller */ if (input_cols != output_cols || input_rows != output_rows) ERREXIT(cinfo->emethods, "Pipeline controller messed up"); #endif /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; if (outrow == 0) above_ptr = above[input_rows-1]; else above_ptr = input_data[outrow-1]; if (outrow >= input_rows-1) below_ptr = below[0]; else below_ptr = input_data[outrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16); lastcolsum = colsum; colsum = nextcolsum; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768L) >> 16); } } #endif /* INPUT_SMOOTHING_SUPPORTED */ /* * Clean up after a scan. */ METHODDEF void downsample_term (compress_info_ptr cinfo) { /* no work for now */ } /* * The method selection routine for downsampling. * Note that we must select a routine for each component. */ GLOBAL void jseldownsample (compress_info_ptr cinfo) { short ci; jpeg_component_info * compptr; boolean smoothok = TRUE; if (cinfo->CCIR601_sampling) ERREXIT(cinfo->emethods, "CCIR601 downsampling not implemented yet"); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (compptr->h_samp_factor == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) cinfo->methods->downsample[ci] = fullsize_smooth_downsample; else #endif cinfo->methods->downsample[ci] = fullsize_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { smoothok = FALSE; cinfo->methods->downsample[ci] = h2v1_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) cinfo->methods->downsample[ci] = h2v2_smooth_downsample; else #endif cinfo->methods->downsample[ci] = h2v2_downsample; } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { smoothok = FALSE; cinfo->methods->downsample[ci] = int_downsample; } else ERREXIT(cinfo->emethods, "Fractional downsampling not implemented yet"); } #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor && !smoothok) TRACEMS(cinfo->emethods, 0, "Smoothing not supported with nonstandard sampling ratios"); #endif cinfo->methods->downsample_init = downsample_init; cinfo->methods->downsample_term = downsample_term; } ibute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighsxloadimage.4.1/jpeg/jdarith.c 644 221 144 2173 5300071765 11262 /* * jdarith.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains arithmetic entropy decoding routines. * These routines are invoked via the methods entropy_decode * and entropy_decode_init/term. */ #include "jinclude.h" #ifdef D_ARITH_CODING_SUPPORTED /* * The arithmetic coding option of the JPEG standard specifies Q-coding, * which is covered by patents held by IBM (and possibly AT&T and Mitsubishi). * At this time it does not appear to be legal for the Independent JPEG * Group to distribute software that implements arithmetic coding. * We have therefore removed arithmetic coding support from the * distributed source code. * * We're not happy about it either. */ /* * The method selection routine for arithmetic entropy decoding. */ GLOBAL void jseldarithmetic (decompress_info_ptr cinfo) { if (cinfo->arith_code) { ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding"); } } #endif /* D_ARITH_CODING_SUPPORTED */  makvms.optTM testimg.gifhN testimg.jpg|L testimg.ppmK testorig.jpg * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for (outrow = 0; outrow < output_rows; outrow++) { ouxloadimage.4.1/jpeg/jdcolor.c 644 221 144 22337 5340456205 11315 /* * jdcolor.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains output colorspace conversion routines. * These routines are invoked via the methods color_convert * and colorout_init/term. */ #include "jinclude.h" /**************** YCbCr -> RGB conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * R = Y + 1.40200 * Cr * G = Y - 0.34414 * Cb - 0.71414 * Cr * B = Y + 1.77200 * Cb * where Cb and Cr represent the incoming values less MAXJSAMPLE/2. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * Notice that Y, being an integral input, does not contribute any fraction * so it need not participate in the rounding. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. */ #ifdef SIXTEEN_BIT_SAMPLES #define SCALEBITS 14 /* avoid overflow */ #else #define SCALEBITS 16 /* speedier right-shift on some machines */ #endif #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< table for Cr to R conversion */ static int * Cb_b_tab; /* => table for Cb to B conversion */ static INT32 * Cr_g_tab; /* => table for Cr to G conversion */ static INT32 * Cb_g_tab; /* => table for Cb to G conversion */ /* * Initialize for colorspace conversion. */ METHODDEF void ycc_rgb_init (decompress_info_ptr cinfo) { INT32 i, x2; SHIFT_TEMPS Cr_r_tab = (int *) (*cinfo->emethods->alloc_small) ((MAXJSAMPLE+1) * SIZEOF(int)); Cb_b_tab = (int *) (*cinfo->emethods->alloc_small) ((MAXJSAMPLE+1) * SIZEOF(int)); Cr_g_tab = (INT32 *) (*cinfo->emethods->alloc_small) ((MAXJSAMPLE+1) * SIZEOF(INT32)); Cb_g_tab = (INT32 *) (*cinfo->emethods->alloc_small) ((MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */ x2 = 2*i - MAXJSAMPLE; /* twice x */ /* Cr=>R value is nearest int to 1.40200 * x */ Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS); /* Cb=>B value is nearest int to 1.77200 * x */ Cb_b_tab[i] = (int) RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS); /* Cr=>G value is scaled-up -0.71414 * x */ Cr_g_tab[i] = (- FIX(0.71414/2)) * x2; /* Cb=>G value is scaled-up -0.34414 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF; } } /* * Convert some rows of samples to the output colorspace. */ METHODDEF void ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows, long num_cols, JSAMPIMAGE input_data, JSAMPIMAGE output_data) { #ifdef SIXTEEN_BIT_SAMPLES register INT32 y; register UINT16 cb, cr; #else register int y, cb, cr; #endif register JSAMPROW inptr0, inptr1, inptr2; register JSAMPROW outptr0, outptr1, outptr2; register long col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = Cr_r_tab; register int * Cbbtab = Cb_b_tab; register INT32 * Crgtab = Cr_g_tab; register INT32 * Cbgtab = Cb_g_tab; int row; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { inptr0 = input_data[0][row]; inptr1 = input_data[1][row]; inptr2 = input_data[2][row]; outptr0 = output_data[0][row]; outptr1 = output_data[1][row]; outptr2 = output_data[2][row]; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Note: if the inputs were computed directly from RGB values, * range-limiting would be unnecessary here; but due to possible * noise in the DCT/IDCT phase, we do need to apply range limits. */ outptr0[col] = range_limit[y + Crrtab[cr]]; /* red */ outptr1[col] = range_limit[y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr2[col] = range_limit[y + Cbbtab[cb]]; /* blue */ } } } /* * Finish up at the end of the file. */ METHODDEF void ycc_rgb_term (decompress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /**************** Cases other than YCbCr -> RGB **************/ /* * Initialize for colorspace conversion. */ METHODDEF void null_init (decompress_info_ptr cinfo) /* colorout_init for cases where no setup is needed */ { /* no work needed */ } /* * Color conversion for no colorspace change: just copy the data. */ METHODDEF void null_convert (decompress_info_ptr cinfo, int num_rows, long num_cols, JSAMPIMAGE input_data, JSAMPIMAGE output_data) { short ci; for (ci = 0; ci < cinfo->num_components; ci++) { jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0, num_rows, num_cols); } } /* * Color conversion for grayscale: just copy the data. * This also works for YCbCr/YIQ -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF void grayscale_convert (decompress_info_ptr cinfo, int num_rows, long num_cols, JSAMPIMAGE input_data, JSAMPIMAGE output_data) { jcopy_sample_rows(input_data[0], 0, output_data[0], 0, num_rows, num_cols); } /* * Finish up at the end of the file. */ METHODDEF void null_term (decompress_info_ptr cinfo) /* colorout_term for cases where no teardown is needed */ { /* no work needed */ } /* * The method selection routine for output colorspace conversion. */ GLOBAL void jseldcolor (decompress_info_ptr cinfo) { int ci; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case CS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); break; case CS_RGB: case CS_YCbCr: case CS_YIQ: if (cinfo->num_components != 3) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); break; case CS_CMYK: if (cinfo->num_components != 4) ERREXIT(cinfo->emethods, "Bogus JPEG colorspace"); break; default: ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace"); break; } /* Set color_out_comps and conversion method based on requested space. */ /* Also clear the component_needed flags for any unused components, */ /* so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case CS_GRAYSCALE: cinfo->color_out_comps = 1; if (cinfo->jpeg_color_space == CS_GRAYSCALE || cinfo->jpeg_color_space == CS_YCbCr || cinfo->jpeg_color_space == CS_YIQ) { cinfo->methods->color_convert = grayscale_convert; cinfo->methods->colorout_init = null_init; cinfo->methods->colorout_term = null_term; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->cur_comp_info[ci]->component_needed = FALSE; } else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; case CS_RGB: cinfo->color_out_comps = 3; if (cinfo->jpeg_color_space == CS_YCbCr) { cinfo->methods->color_convert = ycc_rgb_convert; cinfo->methods->colorout_init = ycc_rgb_init; cinfo->methods->colorout_term = ycc_rgb_term; } else if (cinfo->jpeg_color_space == CS_RGB) { cinfo->methods->color_convert = null_convert; cinfo->methods->colorout_init = null_init; cinfo->methods->colorout_term = null_term; } else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; default: /* Permit null conversion from CMYK or YCbCr to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->color_out_comps = cinfo->num_components; cinfo->methods->color_convert = null_convert; cinfo->methods->colorout_init = null_init; cinfo->methods->colorout_term = null_term; } else /* unsupported non-null conversion */ ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; } if (cinfo->quantize_colors) cinfo->final_out_comps = 1; /* single colormapped output component */ else cinfo->final_out_comps = cinfo->color_out_comps; } d 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; if (outrow == 0) above_ptr = above[input_rows-1]; else above_ptr = input_datxloadimage.4.1/jpeg/jddeflts.c 644 221 144 16207 5340023725 11454 /* * jddeflts.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains optional default-setting code for the JPEG decompressor. * User interfaces do not have to use this file, but those that don't use it * must know more about the innards of the JPEG code. */ #include "jinclude.h" /* Default do-nothing progress monitoring routine. * This can be overridden by a user interface that wishes to * provide progress monitoring; just set methods->progress_monitor * after j_d_defaults is done. The routine will be called periodically * during the decompression process. * * During any one pass, loopcounter increases from 0 up to (not including) * looplimit; the step size is not necessarily 1. Both the step size and * the limit may differ between passes. The expected total number of passes * is in cinfo->total_passes, and the number of passes already completed is * in cinfo->completed_passes. Thus the fraction of work completed may be * estimated as * completed_passes + (loopcounter/looplimit) * ------------------------------------------ * total_passes * ignoring the fact that the passes may not be equal amounts of work. * * When decompressing, the total_passes figure is an estimate that may be * on the high side; completed_passes will jump by more than one if some * passes are skipped. */ METHODDEF void progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit) { /* do nothing */ } /* Default comment-block processing routine. * This can be overridden by an application that wishes to examine * COM blocks found in the JPEG file. The default routine does nothing. * CAUTION: the comment processing routine MUST call JGETC() exactly * comment_length times to read the comment data, whether it intends * to do anything with the data or not! * Keep in mind that (a) there may be more than one COM block in a file; * (b) there's no guarantee that what's in the block is ASCII data. */ METHODDEF void process_comment (decompress_info_ptr cinfo, long comment_length) { while (comment_length-- > 0) { (void) JGETC(cinfo); } } /* * Reload the input buffer after it's been emptied, and return the next byte. * See the JGETC macro for calling conditions. Note in particular that * read_jpeg_data may NOT return EOF. If no more data is available, it must * exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker). * In the present implementation, we insert an EOI marker; this might not be * appropriate for non-JFIF file formats, but it usually allows us to handle * a truncated JFIF file. * * This routine can be overridden by the system-dependent user interface, * in case the data source is not a stdio stream or some other special * condition applies. Note, however, that this capability only applies for * JFIF or similar serial-access JPEG file formats. The input file control * module for a random-access format such as TIFF/JPEG would most likely * override the read_jpeg_data method with its own routine. */ METHODDEF int read_jpeg_data (decompress_info_ptr cinfo) { cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET; cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file, cinfo->next_input_byte, JPEG_BUF_SIZE); if (cinfo->bytes_in_buffer <= 0) { WARNMS(cinfo->emethods, "Premature EOF in JPEG file"); cinfo->next_input_byte[0] = (char) 0xFF; cinfo->next_input_byte[1] = (char) 0xD9; /* EOI marker */ cinfo->bytes_in_buffer = 2; } return JGETC(cinfo); } /* Default parameter setup for decompression. * * User interfaces that don't choose to use this routine must do their * own setup of all these parameters. Alternately, you can call this * to establish defaults and then alter parameters selectively. This * is the recommended approach since, if we add any new parameters, * your code will still work (they'll be set to reasonable defaults). * * standard_buffering should be TRUE to cause an input buffer to be allocated * (the normal case); if FALSE, the user interface must provide a buffer. * This option is most useful in the case that the buffer must not be freed * at the end of an image. (For example, when reading a sequence of images * from a single file, the remaining data in the buffer represents the * start of the next image and mustn't be discarded.) To handle this, * allocate the input buffer yourself at startup, WITHOUT using alloc_small * (probably a direct call to malloc() instead). Then pass FALSE on each * call to j_d_defaults to ensure the buffer state is not modified. * * If the source of the JPEG data is not a stdio stream, override the * read_jpeg_data method with your own routine after calling j_d_defaults. * You can still use the standard buffer if it's appropriate. * * CAUTION: if you want to decompress multiple images per run, it's necessary * to call j_d_defaults before *each* call to jpeg_decompress, since subsidiary * structures like the quantization tables are automatically freed during * cleanup. */ GLOBAL void j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering) /* NB: the external methods must already be set up. */ { short i; /* Initialize pointers as needed to mark stuff unallocated. */ /* Outer application may fill in default tables for abbreviated files... */ cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->colormap = NULL; /* Default to RGB output */ /* UI can override by changing out_color_space */ cinfo->out_color_space = CS_RGB; cinfo->jpeg_color_space = CS_UNKNOWN; /* Setting any other value in jpeg_color_space overrides heuristics in */ /* jrdjfif.c. That might be useful when reading non-JFIF JPEG files, */ /* but ordinarily the UI shouldn't change it. */ /* Default to no gamma correction of output */ cinfo->output_gamma = 1.0; /* Default to no color quantization */ cinfo->quantize_colors = FALSE; /* but set reasonable default parameters for quantization, */ /* so that turning on quantize_colors is sufficient to do something useful */ cinfo->two_pass_quantize = TRUE; cinfo->use_dithering = TRUE; cinfo->desired_number_of_colors = 256; /* Default to no smoothing */ cinfo->do_block_smoothing = FALSE; cinfo->do_pixel_smoothing = FALSE; /* Allocate memory for input buffer, unless outer application provides it. */ if (standard_buffering) { cinfo->input_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) (JPEG_BUF_SIZE + MIN_UNGET)); cinfo->bytes_in_buffer = 0; /* initialize buffer to empty */ } /* Install standard buffer-reloading method (outer code may override). */ cinfo->methods->read_jpeg_data = read_jpeg_data; /* Install default do-nothing progress monitoring method. */ cinfo->methods->progress_monitor = progress_monitor; /* Install default comment-block processing method. */ cinfo->methods->process_comment = process_comment; } ing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < output_rows; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; if (outrow == 0) above_ptr = above[input_rows-1]; else above_ptr = input_data[outrow-1]; if (outrow >= input_rows-1) below_ptr = below[0]; else below_ptr = input_data[outrow+1]; /xloadimage.4.1/jpeg/jdhuff.c 644 221 144 36203 5336536461 11134 /* * jdhuff.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines. * These routines are invoked via the methods entropy_decode * and entropy_decode_init/term. */ #include "jinclude.h" /* Static variables to avoid passing 'round extra parameters */ static decompress_info_ptr dcinfo; static INT32 get_buffer; /* current bit-extraction buffer */ static int bits_left; /* # of unused bits in it */ static boolean printed_eod; /* flag to suppress multiple end-of-data msgs */ LOCAL void fix_huff_tbl (HUFF_TBL * htbl) /* Compute derived values for a Huffman table */ { int p, i, l, si; int lookbits, ctr; char huffsize[257]; UINT16 huffcode[257]; UINT16 code; /* Figure C.1: make table of Huffman code length for each symbol */ /* Note that this is in code-length order. */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; } huffsize[p] = 0; /* Figure C.2: generate the codes themselves */ /* Note that this is in code-length order. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->bits[l]) { htbl->priv.dec.valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ htbl->priv.dec.mincode[l] = huffcode[p]; /* minimum code of length l */ p += htbl->bits[l]; htbl->priv.dec.maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { htbl->priv.dec.maxcode[l] = -1; /* -1 if no codes of this length */ } } htbl->priv.dec.maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ /* Compute lookahead tables to speed up decoding. * First we set all the table entries to 0, indicating "too long"; * then we iterate through the Huffman codes that are short enough and * fill in all the entries that correspond to bit sequences starting * with that code. */ MEMZERO(htbl->priv.dec.look_nbits, SIZEOF(htbl->priv.dec.look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { /* l = current code's length, p = its index in huffcode[] & huffval[]. */ /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { htbl->priv.dec.look_nbits[lookbits] = l; htbl->priv.dec.look_sym[lookbits] = htbl->huffval[p]; lookbits++; } } } } /* * Code for extracting the next N bits from the input stream. * (N never exceeds 15 for JPEG data.) * This needs to go as fast as possible! * * We read source bytes into get_buffer and dole out bits as needed. * If get_buffer already contains enough bits, they are fetched in-line * by the macros check_bit_buffer and get_bits. When there aren't enough * bits, fill_bit_buffer is called; it will attempt to fill get_buffer to * the "high water mark" (not just to the number of bits needed; this reduces * the function-call overhead cost of entering fill_bit_buffer). * On return, fill_bit_buffer guarantees that get_buffer contains at least * the requested number of bits --- dummy zeroes are inserted if necessary. * * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width * of get_buffer to be used. (On machines with wider words, an even larger * buffer could be used.) However, on some machines 32-bit shifts are * relatively slow and take time proportional to the number of places shifted. * (This is true with most PC compilers, for instance.) In this case it may * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the * average shift distance at the cost of more calls to fill_bit_buffer. */ #ifdef SLOW_SHIFT_32 #define MIN_GET_BITS 15 /* minimum allowable value */ #else #define MIN_GET_BITS 25 /* max value for 32-bit get_buffer */ #endif LOCAL void fill_bit_buffer (int nbits) /* Load up the bit buffer to a depth of at least nbits */ { /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ /* (It is assumed that no request will be for more than that many bits.) */ while (bits_left < MIN_GET_BITS) { register int c = JGETC(dcinfo); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == 0xFF) { int c2 = JGETC(dcinfo); if (c2 != 0) { /* Oops, it's actually a marker indicating end of compressed data. */ /* Better put it back for use later */ JUNGETC(c2,dcinfo); JUNGETC(c,dcinfo); /* There should be enough bits still left in the data segment; */ /* if so, just break out of the while loop. */ if (bits_left >= nbits) break; /* Uh-oh. Report corrupted data to user and stuff zeroes into * the data stream, so that we can produce some kind of image. * Note that this will be repeated for each byte demanded for the * rest of the segment; this is a bit slow but not unreasonably so. * The main thing is to avoid getting a zillion warnings, hence * we use a flag to ensure that only one warning appears. */ if (! printed_eod) { WARNMS(dcinfo->emethods, "Corrupt JPEG data: premature end of data segment"); printed_eod = TRUE; } c = 0; /* insert a zero byte into bit buffer */ } } /* OK, load c into get_buffer */ get_buffer = (get_buffer << 8) | c; bits_left += 8; } } /* * These macros provide the in-line portion of bit fetching. * Correct usage is: * check_bit_buffer(n); ensure there are N bits in get_buffer * val = get_bits(n); fetch N bits * The value n should be a simple variable, not an expression, because it * is evaluated multiple times. * peek_bits() fetches next N bits without removing them from the buffer. */ #define check_bit_buffer(nbits) \ { if (bits_left < (nbits)) fill_bit_buffer(nbits); } #define get_bits(nbits) \ (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) #define peek_bits(nbits) \ (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) /* * Routines to extract next Huffman-coded symbol from input bit stream. * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits * without looping. Usually, more than 95% of the Huffman codes will be 8 * or fewer bits long. The few overlength codes are handled with a loop. * The primary case is made a macro for speed reasons; the secondary * routine slow_DECODE is rarely entered and need not be inline code. * * Notes about the huff_DECODE macro: * 1. The first if-test is coded to call fill_bit_buffer only when necessary. * 2. If the lookahead succeeds, we need only decrement bits_left to remove * the proper number of bits from get_buffer. * 3. If the lookahead table contains no entry, the next code must be * more than HUFF_LOOKAHEAD bits long. * 4. Near the end of the data segment, we may fail to get enough bits * for a lookahead. In that case, we do it the hard way. */ #define huff_DECODE(htbl,result) \ { register int nb, look; \ if (bits_left >= HUFF_LOOKAHEAD || \ (fill_bit_buffer(0), bits_left >= HUFF_LOOKAHEAD)) { \ look = peek_bits(HUFF_LOOKAHEAD); \ if ((nb = htbl->priv.dec.look_nbits[look]) != 0) { \ bits_left -= nb; \ result = htbl->priv.dec.look_sym[look]; \ } else \ result = slow_DECODE(htbl, HUFF_LOOKAHEAD+1); \ } else \ result = slow_DECODE(htbl, 1); \ } LOCAL int slow_DECODE (HUFF_TBL * htbl, int min_bits) { register int l = min_bits; register INT32 code; /* huff_DECODE has determined that the code is at least min_bits */ /* bits long, so fetch that many bits in one swoop. */ check_bit_buffer(l); code = get_bits(l); /* Collect the rest of the Huffman code one bit at a time. */ /* This is per Figure F.16 in the JPEG spec. */ while (code > htbl->priv.dec.maxcode[l]) { code <<= 1; check_bit_buffer(1); code |= get_bits(1); l++; } /* With garbage input we may reach the sentinel value l = 17. */ if (l > 16) { WARNMS(dcinfo->emethods, "Corrupt JPEG data: bad Huffman code"); return 0; /* fake a zero as the safest result */ } return htbl->huffval[ htbl->priv.dec.valptr[l] + ((int) (code - htbl->priv.dec.mincode[l])) ]; } /* Figure F.12: extend sign bit. * On some machines, a shift and add will be faster than a table lookup. */ #ifdef AVOID_TABLES #define huff_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) #else #define huff_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; #endif /* AVOID_TABLES */ /* * Initialize for a Huffman-compressed scan. * This is invoked after reading the SOS marker. */ METHODDEF void decoder_init (decompress_info_ptr cinfo) { short ci; jpeg_component_info * compptr; /* Initialize static variables */ dcinfo = cinfo; bits_left = 0; printed_eod = FALSE; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Make sure requested tables are present */ if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL || cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL) ERREXIT(cinfo->emethods, "Use of undefined Huffman table"); /* Compute derived values for Huffman tables */ /* We may do this more than once for same table, but it's not a big deal */ fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]); fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]); /* Initialize DC predictions to 0 */ cinfo->last_dc_val[ci] = 0; } /* Initialize restart stuff */ cinfo->restarts_to_go = cinfo->restart_interval; cinfo->next_restart_num = 0; } /* * Check for a restart marker & resynchronize decoder. */ LOCAL void process_restart (decompress_info_ptr cinfo) { int c, nbytes; short ci; /* Throw away any unused bits remaining in bit buffer */ nbytes = bits_left / 8; /* count any full bytes loaded into buffer */ bits_left = 0; printed_eod = FALSE; /* next segment can get another warning */ /* Scan for next JPEG marker */ do { do { /* skip any non-FF bytes */ nbytes++; c = JGETC(cinfo); } while (c != 0xFF); do { /* skip any duplicate FFs */ /* we don't increment nbytes here since extra FFs are legal */ c = JGETC(cinfo); } while (c == 0xFF); } while (c == 0); /* repeat if it was a stuffed FF/00 */ if (nbytes != 1) WARNMS2(cinfo->emethods, "Corrupt JPEG data: %d extraneous bytes before marker 0x%02x", nbytes-1, c); if (c != (RST0 + cinfo->next_restart_num)) { /* Uh-oh, the restart markers have been messed up too. */ /* Let the file-format module try to figure out how to resync. */ (*cinfo->methods->resync_to_restart) (cinfo, c); } else TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num); /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) cinfo->last_dc_val[ci] = 0; /* Update restart state */ cinfo->restarts_to_go = cinfo->restart_interval; cinfo->next_restart_num = (cinfo->next_restart_num + 1) & 7; } /* ZAG[i] is the natural-order position of the i'th element of zigzag order. * If the incoming data is corrupted, decode_mcu could attempt to * reference values beyond the end of the array. To avoid a wild store, * we put some extra zeroes after the real entries. */ static const short ZAG[DCTSIZE2+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */ 0, 0, 0, 0, 0, 0, 0, 0 }; /* * Decode and return one MCU's worth of Huffman-compressed coefficients. * This routine also handles quantization descaling and zigzag reordering * of coefficient values. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. * (Wholesale zeroing is usually a little faster than retail...) */ METHODDEF void decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) { register int s, k, r; short blkn, ci; register JBLOCKROW block; register QUANT_TBL_PTR quanttbl; HUFF_TBL *dctbl; HUFF_TBL *actbl; jpeg_component_info * compptr; /* Account for restart interval, process restart marker if needed */ if (cinfo->restart_interval) { if (cinfo->restarts_to_go == 0) process_restart(cinfo); cinfo->restarts_to_go--; } /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; quanttbl = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]; actbl = cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]; dctbl = cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ huff_DECODE(dctbl, s); if (s) { check_bit_buffer(s); r = get_bits(s); s = huff_EXTEND(r, s); } /* Convert DC difference to actual value, update last_dc_val */ s += cinfo->last_dc_val[ci]; cinfo->last_dc_val[ci] = (JCOEF) s; /* Descale and output the DC coefficient (assumes ZAG[0] = 0) */ (*block)[0] = (JCOEF) (((JCOEF) s) * quanttbl[0]); /* Section F.2.2.2: decode the AC coefficients */ /* Since zero values are skipped, output area must be zeroed beforehand */ for (k = 1; k < DCTSIZE2; k++) { huff_DECODE(actbl, s); r = s >> 4; s &= 15; if (s) { k += r; check_bit_buffer(s); r = get_bits(s); s = huff_EXTEND(r, s); /* Descale coefficient and output in natural (dezigzagged) order */ (*block)[ZAG[k]] = (JCOEF) (((JCOEF) s) * quanttbl[k]); } else { if (r != 15) break; k += 15; } } } } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF void decoder_term (decompress_info_ptr cinfo) { /* No work needed */ } /* * The method selection routine for Huffman entropy decoding. */ GLOBAL void jseldhuffman (decompress_info_ptr cinfo) { if (! cinfo->arith_code) { cinfo->methods->entropy_decode_init = decoder_init; cinfo->methods->entropy_decode = decode_mcu; cinfo->methods->entropy_decode_term = decoder_term; } } lookahead. In that case, we do it the hard way. */ #define huff_DECODE(htbl,result) \ { register int nb, look; \ if (bits_left >= HUFF_LOOKAHEAD || \ (fill_bit_buffer(0), bits_left >= HUFF_LOOKAHEAD)) { \ look = peek_bits(HUFF_LOOKAHEAD); \ if ((nb = htbl->priv.dec.look_nbits[look]) != 0) { \ bits_left -= nb; \ result = htbl->priv.xloadimage.4.1/jpeg/jdmain.c 644 221 144 35436 5340275621 11130 /* * jdmain.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for the JPEG decompressor. * It should work on any system with Unix- or MS-DOS-style command lines. * * Two different command line styles are permitted, depending on the * compile-time switch TWO_FILE_COMMANDLINE: * djpeg [options] inputfile outputfile * djpeg [options] [inputfile] * In the second style, output is always to standard output, which you'd * normally redirect to a file or pipe to some other program. Input is * either from a named file or from standard input (typically redirected). * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. * To simplify script writing, the "-outfile" switch is provided. The syntax * djpeg [options] -outfile outputfile inputfile * works regardless of which command line style is used. */ #include "jinclude.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare exit() */ #endif #include /* to declare isupper(), tolower() */ #ifdef NEED_SIGNAL_CATCHER #include /* to declare signal() */ #endif #ifdef USE_SETMODE #include /* to declare setmode() */ #endif #ifdef THINK_C #include /* command-line reader for Macintosh */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define WRITE_BINARY "w" #else #define READ_BINARY "rb" #define WRITE_BINARY "wb" #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS #ifdef VMS #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ #else #define EXIT_SUCCESS 0 #endif #endif #include "jversion.h" /* for version message */ /* * This list defines the known output image formats * (not all of which need be supported by a given version). * You can change the default output format by defining DEFAULT_FMT; * indeed, you had better do so if you undefine PPM_SUPPORTED. */ typedef enum { FMT_GIF, /* GIF format */ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ FMT_RLE, /* RLE format */ FMT_TARGA, /* Targa format */ FMT_TIFF /* TIFF format */ } IMAGE_FORMATS; #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ #define DEFAULT_FMT FMT_PPM #endif static IMAGE_FORMATS requested_fmt; /* * This routine gets control after the input file header has been read. * It must determine what output file format is to be written, * and make any other decompression parameter changes that are desirable. */ METHODDEF void d_ui_method_selection (decompress_info_ptr cinfo) { /* if grayscale or CMYK input, force similar output; */ /* else leave the output colorspace as set by options. */ if (cinfo->jpeg_color_space == CS_GRAYSCALE) cinfo->out_color_space = CS_GRAYSCALE; else if (cinfo->jpeg_color_space == CS_CMYK) cinfo->out_color_space = CS_CMYK; /* select output file format */ /* Note: jselwxxx routine may make additional parameter changes, * such as forcing color quantization if it's a colormapped format. */ switch (requested_fmt) { #ifdef GIF_SUPPORTED case FMT_GIF: jselwgif(cinfo); break; #endif #ifdef PPM_SUPPORTED case FMT_PPM: jselwppm(cinfo); break; #endif #ifdef RLE_SUPPORTED case FMT_RLE: jselwrle(cinfo); break; #endif #ifdef TARGA_SUPPORTED case FMT_TARGA: jselwtarga(cinfo); break; #endif default: ERREXIT(cinfo->emethods, "Unsupported output file format"); break; } } /* * Signal catcher to ensure that temporary files are removed before aborting. * NB: for Amiga Manx C this is actually a global routine named _abort(); * see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus... */ #ifdef NEED_SIGNAL_CATCHER static external_methods_ptr emethods; /* for access to free_all */ GLOBAL void signal_catcher (int signum) { if (emethods != NULL) { emethods->trace_level = 0; /* turn off trace output */ (*emethods->free_all) (); /* clean up memory allocation & temp files */ } exit(EXIT_FAILURE); } #endif /* * Optional routine to display a percent-done figure on stderr. * See jddeflts.c for explanation of the information used. */ #ifdef PROGRESS_REPORT METHODDEF void progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit) { if (cinfo->total_passes > 1) { fprintf(stderr, "\rPass %d/%d: %3d%% ", cinfo->completed_passes+1, cinfo->total_passes, (int) (loopcounter*100L/looplimit)); } else { fprintf(stderr, "\r %3d%% ", (int) (loopcounter*100L/looplimit)); } fflush(stderr); } #endif /* * Argument-parsing code. * The switch parser is designed to be useful with DOS-style command line * syntax, ie, intermixed switches and file names, where only the switches * to the left of a given file name affect processing of that file. * The main program in this file doesn't actually use this capability... */ static char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ LOCAL void usage (void) /* complain about bad command line */ { fprintf(stderr, "usage: %s [switches] ", progname); #ifdef TWO_FILE_COMMANDLINE fprintf(stderr, "inputfile outputfile\n"); #else fprintf(stderr, "[inputfile]\n"); #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); #ifdef GIF_SUPPORTED fprintf(stderr, " -gif Select GIF output format\n"); #endif #ifdef PPM_SUPPORTED fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format (default)\n"); #endif fprintf(stderr, " -quantize N Same as -colors N\n"); #ifdef RLE_SUPPORTED fprintf(stderr, " -rle Select Utah RLE output format\n"); #endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Select Targa output format\n"); #endif fprintf(stderr, "Switches for advanced users:\n"); #ifdef BLOCK_SMOOTHING_SUPPORTED fprintf(stderr, " -blocksmooth Apply cross-block smoothing\n"); #endif fprintf(stderr, " -grayscale Force grayscale output\n"); fprintf(stderr, " -nodither Don't use dithering in quantization\n"); #ifdef QUANT_1PASS_SUPPORTED fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); #endif fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); exit(EXIT_FAILURE); } LOCAL boolean keymatch (char * arg, const char * keyword, int minchars) /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ /* keyword is the constant keyword (must be lower case already), */ /* minchars is length of minimum legal abbreviation. */ { register int ca, ck; register int nmatched = 0; while ((ca = *arg++) != '\0') { if ((ck = *keyword++) == '\0') return FALSE; /* arg longer than keyword, no good */ if (isupper(ca)) /* force arg to lcase (assume ck is already) */ ca = tolower(ca); if (ca != ck) return FALSE; /* no good */ nmatched++; /* count matched characters */ } /* reached end of argument; fail if it's too short for unique abbrev */ if (nmatched < minchars) return FALSE; return TRUE; /* A-OK */ } LOCAL int parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen, int argc, char **argv) /* Initialize cinfo with default switch settings, then parse option switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) */ { int argn; char * arg; /* (Re-)initialize the system-dependent error and memory managers. */ jselerror(cinfo->emethods); /* error/trace message routines */ jselmemmgr(cinfo->emethods); /* memory allocation routines */ cinfo->methods->d_ui_method_selection = d_ui_method_selection; /* Now OK to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER emethods = cinfo->emethods; #endif /* Set up default JPEG parameters. */ j_d_defaults(cinfo, TRUE); requested_fmt = DEFAULT_FMT; /* set default output file format */ outfilename = NULL; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processed */ } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ if (keymatch(arg, "blocksmooth", 1)) { /* Enable cross-block smoothing. */ cinfo->do_block_smoothing = TRUE; } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { /* Do color quantization. */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); cinfo->desired_number_of_colors = val; cinfo->quantize_colors = TRUE; } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0) fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", JVERSION, JCOPYRIGHT); cinfo->emethods->trace_level++; } else if (keymatch(arg, "gif", 1)) { /* GIF output format. */ requested_fmt = FMT_GIF; } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { /* Force monochrome output. */ cinfo->out_color_space = CS_GRAYSCALE; } else if (keymatch(arg, "maxmemory", 1)) { /* Maximum memory in Kb (or Mb with 'm'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (ch == 'm' || ch == 'M') lval *= 1000L; cinfo->emethods->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nodither", 3)) { /* Suppress dithering in color quantization. */ cinfo->use_dithering = FALSE; } else if (keymatch(arg, "onepass", 1)) { /* Use fast one-pass quantization. */ cinfo->two_pass_quantize = FALSE; } else if (keymatch(arg, "outfile", 3)) { /* Set output file name. */ if (++argn >= argc) /* advance to next argument */ usage(); outfilename = argv[argn]; /* save it away for later use */ } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { /* PPM/PGM output format. */ requested_fmt = FMT_PPM; } else if (keymatch(arg, "rle", 1)) { /* RLE output format. */ requested_fmt = FMT_RLE; } else if (keymatch(arg, "targa", 1)) { /* Targa output format. */ requested_fmt = FMT_TARGA; } else { usage(); /* bogus switch */ } } return argn; /* return index of next arg (file name) */ } /* * The main program. */ GLOBAL int main (int argc, char **argv) { struct Decompress_info_struct cinfo; struct Decompress_methods_struct dc_methods; struct External_methods_struct e_methods; int file_index; /* On Mac, fetch a command line. */ #ifdef THINK_C argc = ccommand(&argv); #endif progname = argv[0]; /* Set up links to method structures. */ cinfo.methods = &dc_methods; cinfo.emethods = &e_methods; /* Install, but don't yet enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER emethods = NULL; signal(SIGINT, signal_catcher); #ifdef SIGTERM /* not all systems have SIGTERM */ signal(SIGTERM, signal_catcher); #endif #endif /* Scan command line: set up compression parameters, find file names. */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdin), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdin\n", progname); exit(EXIT_FAILURE); } #else cinfo.input_file = stdin; #endif } /* Open the output file. */ if (outfilename != NULL) { if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdout), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdout\n", progname); exit(EXIT_FAILURE); } #else cinfo.output_file = stdout; #endif } /* Set up to read a JFIF or baseline-JPEG file. */ /* A smarter UI would inspect the first few bytes of the input file */ /* to determine its type. */ #ifdef JFIF_SUPPORTED jselrjfif(&cinfo); #else You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */ #endif #ifdef PROGRESS_REPORT /* Start up progress display, unless trace output is on */ if (e_methods.trace_level == 0) dc_methods.progress_monitor = progress_monitor; #endif /* Do it to it! */ jpeg_decompress(&cinfo); #ifdef PROGRESS_REPORT /* Clear away progress display */ if (e_methods.trace_level == 0) { fprintf(stderr, "\r \r"); fflush(stderr); } #endif /* All done. */ exit(EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ } tant keyword (must be lower case already), */ /* minchars is length of minimum legal abbreviation. */ { register int ca, ck; register int nmatched = 0; while ((ca = *arg++) != '\0') { if ((ck = *keyword++) == '\0') xloadimage.4.1/jpeg/jdmaster.c 644 221 144 13066 5340455301 11465 /* * jdmaster.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main control for the JPEG decompressor. * The system-dependent (user interface) code should call jpeg_decompress() * after doing appropriate setup of the decompress_info_struct parameter. */ #include "jinclude.h" METHODDEF void d_per_scan_method_selection (decompress_info_ptr cinfo) /* Central point for per-scan method selection */ { /* MCU disassembly */ jseldmcu(cinfo); /* Upsampling of pixels */ jselupsample(cinfo); } LOCAL void d_initial_method_selection (decompress_info_ptr cinfo) /* Central point for initial method selection (after reading file header) */ { /* JPEG file scanning method selection is already done. */ /* So is output file format selection (both are done by user interface). */ /* Gamma and color space conversion */ /* NB: this may change the component_needed flags */ jseldcolor(cinfo); /* Color quantization selection rules */ #ifdef QUANT_1PASS_SUPPORTED #ifdef QUANT_2PASS_SUPPORTED /* We have both, check for conditions in which 1-pass should be used */ if (cinfo->num_components != 3 || cinfo->jpeg_color_space != CS_YCbCr) cinfo->two_pass_quantize = FALSE; /* 2-pass only handles YCbCr input */ if (cinfo->out_color_space == CS_GRAYSCALE) cinfo->two_pass_quantize = FALSE; /* Should use 1-pass for grayscale out */ #else /* not QUANT_2PASS_SUPPORTED */ cinfo->two_pass_quantize = FALSE; /* only have 1-pass */ #endif #else /* not QUANT_1PASS_SUPPORTED */ #ifdef QUANT_2PASS_SUPPORTED cinfo->two_pass_quantize = TRUE; /* only have 2-pass */ #else /* not QUANT_2PASS_SUPPORTED */ if (cinfo->quantize_colors) { ERREXIT(cinfo->emethods, "Color quantization was not compiled"); } #endif #endif #ifdef QUANT_1PASS_SUPPORTED jsel1quantize(cinfo); #endif #ifdef QUANT_2PASS_SUPPORTED jsel2quantize(cinfo); #endif /* Cross-block smoothing */ #ifdef BLOCK_SMOOTHING_SUPPORTED jselbsmooth(cinfo); #else cinfo->do_block_smoothing = FALSE; #endif /* Entropy decoding: either Huffman or arithmetic coding. */ #ifdef D_ARITH_CODING_SUPPORTED jseldarithmetic(cinfo); #else if (cinfo->arith_code) { ERREXIT(cinfo->emethods, "Arithmetic coding not supported"); } #endif jseldhuffman(cinfo); /* Pipeline control */ jseldpipeline(cinfo); /* Overall control (that's me!) */ cinfo->methods->d_per_scan_method_selection = d_per_scan_method_selection; } LOCAL void initial_setup (decompress_info_ptr cinfo) /* Do computations that are needed before initial method selection */ { short ci; jpeg_component_info *compptr; /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo->emethods, "Bogus sampling factors"); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute logical downsampled dimensions of components */ for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor + cinfo->max_h_samp_factor - 1) / cinfo->max_h_samp_factor; compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor + cinfo->max_v_samp_factor - 1) / cinfo->max_v_samp_factor; } } /* * This is the main entry point to the JPEG decompressor. */ GLOBAL void jpeg_decompress (decompress_info_ptr cinfo) { /* Init pass counts to 0 --- total_passes is adjusted in method selection */ cinfo->total_passes = 0; cinfo->completed_passes = 0; /* Read the JPEG file header markers; everything up through the first SOS * marker is read now. NOTE: the user interface must have initialized the * read_file_header method pointer (eg, by calling jselrjfif or jselrtiff). * The other file reading methods (read_scan_header etc.) were probably * set at the same time, but could be set up by read_file_header itself. */ (*cinfo->methods->read_file_header) (cinfo); if (! ((*cinfo->methods->read_scan_header) (cinfo))) ERREXIT(cinfo->emethods, "Empty JPEG file"); /* Give UI a chance to adjust decompression parameters and select */ /* output file format based on info from file header. */ (*cinfo->methods->d_ui_method_selection) (cinfo); /* Now select methods for decompression steps. */ initial_setup(cinfo); d_initial_method_selection(cinfo); /* Initialize the output file & other modules as needed */ /* (modules needing per-scan init are called by pipeline controller) */ (*cinfo->methods->output_init) (cinfo); (*cinfo->methods->colorout_init) (cinfo); if (cinfo->quantize_colors) (*cinfo->methods->color_quant_init) (cinfo); /* And let the pipeline controller do the rest. */ (*cinfo->methods->d_pipeline_controller) (cinfo); /* Finish output file, release working storage, etc */ if (cinfo->quantize_colors) (*cinfo->methods->color_quant_term) (cinfo); (*cinfo->methods->colorout_term) (cinfo); (*cinfo->methods->output_term) (cinfo); (*cinfo->methods->read_file_trailer) (cinfo); (*cinfo->emethods->free_all) (); /* My, that was easy, wasn't it? */ } o.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdin\n", progname); exit(EXIT_FAILURE); } #else cinfo.input_file = stdin; #endif } /* Open the output file. */ if (outfilename != NULL) { if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* defauxloadimage.4.1/jpeg/jdmcu.c 644 221 144 14425 5340460131 10753 /* * jdmcu.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains MCU disassembly and IDCT control routines. * These routines are invoked via the disassemble_MCU, reverse_DCT, and * disassemble_init/term methods. */ #include "jinclude.h" /* * Fetch one MCU row from entropy_decode, build coefficient array. * This version is used for noninterleaved (single-component) scans. */ METHODDEF void disassemble_noninterleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[1]; long mcuindex; /* this is pretty easy since there is one component and one block per MCU */ /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ jzero_far((void FAR *) image_data[0][0], (size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK))); for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spot in the image array for this MCU */ MCU_data[0] = image_data[0][0] + mcuindex; /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } } /* * Fetch one MCU row from entropy_decode, build coefficient array. * This version is used for interleaved (multi-component) scans. */ METHODDEF void disassemble_interleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[MAX_BLOCKS_IN_MCU]; long mcuindex; short blkn, ci, xpos, ypos; jpeg_component_info * compptr; JBLOCKROW image_ptr; /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { jzero_far((void FAR *) image_data[ci][ypos], (size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK))); } } for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spots in the image array for this MCU */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width); for (xpos = 0; xpos < compptr->MCU_width; xpos++) { MCU_data[blkn] = image_ptr; image_ptr++; blkn++; } } } /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } } /* * Perform inverse DCT on each block in an MCU row's worth of data; * output the results into a sample array starting at row start_row. * NB: start_row can only be nonzero when dealing with a single-component * scan; otherwise we'd have to pass different offsets for different * components, since the heights of interleaved MCU rows can vary. * But the pipeline controller logic is such that this is not necessary. */ METHODDEF void reverse_DCT (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data, int start_row) { DCTBLOCK block; JBLOCKROW browptr; JSAMPARRAY srowptr; jpeg_component_info * compptr; long blocksperrow, bi; short numrows, ri; short ci; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* don't bother to IDCT an uninteresting component */ if (! compptr->component_needed) continue; /* calculate size of an MCU row in this component */ blocksperrow = compptr->downsampled_width / DCTSIZE; numrows = compptr->MCU_height; /* iterate through all blocks in MCU row */ for (ri = 0; ri < numrows; ri++) { browptr = coeff_data[ci][ri]; srowptr = output_data[ci] + (ri * DCTSIZE + start_row); for (bi = 0; bi < blocksperrow; bi++) { /* copy the data into a local DCTBLOCK. This allows for change of * representation (if DCTELEM != JCOEF). On 80x86 machines it also * brings the data back from FAR storage to NEAR storage. */ { register JCOEFPTR elemptr = browptr[bi]; register DCTELEM *localblkptr = block; register int elem = DCTSIZE2; while (--elem >= 0) *localblkptr++ = (DCTELEM) *elemptr++; } j_rev_dct(block); /* perform inverse DCT */ /* Output the data into the sample array. * Note change from signed to unsigned representation: * DCT calculation works with values +-CENTERJSAMPLE, * but sample arrays always hold 0..MAXJSAMPLE. * We have to do range-limiting because of quantization errors in the * DCT/IDCT phase. We use the sample_range_limit[] table to do this * quickly; the CENTERJSAMPLE offset is folded into table indexing. */ { register JSAMPROW elemptr; register DCTELEM *localblkptr = block; register JSAMPLE *range_limit = cinfo->sample_range_limit + CENTERJSAMPLE; #if DCTSIZE != 8 register int elemc; #endif register int elemr; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = srowptr[elemr] + (bi * DCTSIZE); #if DCTSIZE == 8 /* unroll the inner loop */ *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; #else for (elemc = DCTSIZE; elemc > 0; elemc--) { *elemptr++ = range_limit[*localblkptr++]; } #endif } } } } } } /* * Initialize for processing a scan. */ METHODDEF void disassemble_init (decompress_info_ptr cinfo) { /* no work for now */ } /* * Clean up after a scan. */ METHODDEF void disassemble_term (decompress_info_ptr cinfo) { /* no work for now */ } /* * The method selection routine for MCU disassembly. */ GLOBAL void jseldmcu (decompress_info_ptr cinfo) { if (cinfo->comps_in_scan == 1) cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU; else cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU; cinfo->methods->reverse_DCT = reverse_DCT; cinfo->methods->disassemble_init = disassemble_init; cinfo->methods->disassemble_term = disassemble_term; } for (ypos = 0; ypos < compptr->MCU_height; ypos++) { image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width); for (xpos = 0; xpos < compptr->MCU_width; xpos++) { MCU_data[blkn] = image_ptr; image_ptr++; blkn++; xloadimage.4.1/jpeg/jdpipe.c 644 221 144 112773 5340461150 11153 /* * jdpipe.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression pipeline controllers. * These routines are invoked via the d_pipeline_controller method. * * There are two basic pipeline controllers. The simpler one handles a * single-scan JPEG file (single component or fully interleaved) with no * color quantization or 1-pass quantization. In this case, the file can * be processed in one top-to-bottom pass. The more complex controller is * used when 2-pass color quantization is requested and/or the JPEG file * has multiple scans (noninterleaved or partially interleaved). In this * case, the entire image must be buffered up in a "big" array. * * If you need to make a minimal implementation, the more complex controller * can be compiled out by disabling the appropriate configuration options. * We don't recommend this, since then you can't handle all legal JPEG files. */ #include "jinclude.h" #ifdef D_MULTISCAN_FILES_SUPPORTED /* wish we could assume ANSI's defined() */ #define NEED_COMPLEX_CONTROLLER #else #ifdef QUANT_2PASS_SUPPORTED #define NEED_COMPLEX_CONTROLLER #endif #endif /* * About the data structures: * * The processing chunk size for upsampling is referred to in this file as * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of * any component while downsampled, or Vmax (max_v_samp_factor) unsubsampled * rows. In an interleaved scan each MCU row contains exactly DCTSIZE row * groups of each component in the scan. In a noninterleaved scan an MCU row * is one row of blocks, which might not be an integral number of row groups; * therefore, we read in Vk MCU rows to obtain the same amount of data as we'd * have in an interleaved scan. * To provide context for the upsampling step, we have to retain the last * two row groups of the previous MCU row while reading in the next MCU row * (or set of Vk MCU rows). To do this without copying data about, we create * a rather strange data structure. Exactly DCTSIZE+2 row groups of samples * are allocated, but we create two different sets of pointers to this array. * The second set swaps the last two pairs of row groups. By working * alternately with the two sets of pointers, we can access the data in the * desired order. * * Cross-block smoothing also needs context above and below the "current" row. * Since this is an optional feature, I've implemented it in a way that is * much simpler but requires more than the minimum amount of memory. We * simply allocate three extra MCU rows worth of coefficient blocks and use * them to "read ahead" one MCU row in the file. For a typical 1000-pixel-wide * image with 2x2,1x1,1x1 sampling, each MCU row is about 50Kb; an 80x86 * machine may be unable to apply cross-block smoothing to wider images. */ /* * These variables are logically local to the pipeline controller, * but we make them static so that scan_big_image can use them * without having to pass them through the quantization routines. */ static int rows_in_mem; /* # of sample rows in full-size buffers */ /* Work buffer for data being passed to output module. */ /* This has color_out_comps components if not quantizing, */ /* but only one component when quantizing. */ static JSAMPIMAGE output_workspace; #ifdef NEED_COMPLEX_CONTROLLER /* Full-size image array holding upsampled, but not color-processed data. */ static big_sarray_ptr *fullsize_image; static JSAMPIMAGE fullsize_ptrs; /* workspace for access_big_sarray() result */ #endif /* * Utility routines: common code for pipeline controllers */ LOCAL void interleaved_scan_setup (decompress_info_ptr cinfo) /* Compute all derived info for an interleaved (multi-component) scan */ /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */ { short ci, mcublks; jpeg_component_info *compptr; if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->MCUs_per_row = (cinfo->image_width + cinfo->max_h_samp_factor*DCTSIZE - 1) / (cinfo->max_h_samp_factor*DCTSIZE); cinfo->MCU_rows_in_scan = (cinfo->image_height + cinfo->max_v_samp_factor*DCTSIZE - 1) / (cinfo->max_v_samp_factor*DCTSIZE); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* for interleaved scan, sampling factors give # of blocks per component */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) (compptr->MCU_width*DCTSIZE)); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) (compptr->MCU_height*DCTSIZE)); /* Sanity check */ if (compptr->downsampled_width != (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE))) ERREXIT(cinfo->emethods, "I'm confused about the image width"); /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan"); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } (*cinfo->methods->d_per_scan_method_selection) (cinfo); } LOCAL void noninterleaved_scan_setup (decompress_info_ptr cinfo) /* Compute all derived info for a noninterleaved (single-component) scan */ /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */ { jpeg_component_info *compptr = cinfo->cur_comp_info[0]; /* for noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) DCTSIZE); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) DCTSIZE); cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE; cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; (*cinfo->methods->d_per_scan_method_selection) (cinfo); } LOCAL JSAMPIMAGE alloc_sampimage (decompress_info_ptr cinfo, int num_comps, long num_rows, long num_cols) /* Allocate an in-memory sample image (all components same size) */ { JSAMPIMAGE image; int ci; image = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (num_comps * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < num_comps; ci++) { image[ci] = (*cinfo->emethods->alloc_small_sarray) (num_cols, num_rows); } return image; } #if 0 /* this routine not currently needed */ LOCAL void free_sampimage (decompress_info_ptr cinfo, JSAMPIMAGE image, int num_comps) /* Release a sample image created by alloc_sampimage */ { int ci; for (ci = 0; ci < num_comps; ci++) { (*cinfo->emethods->free_small_sarray) (image[ci]); } (*cinfo->emethods->free_small) ((void *) image); } #endif LOCAL JBLOCKIMAGE alloc_MCU_row (decompress_info_ptr cinfo) /* Allocate one MCU row's worth of coefficient blocks */ { JBLOCKIMAGE image; int ci; image = (JBLOCKIMAGE) (*cinfo->emethods->alloc_small) (cinfo->comps_in_scan * SIZEOF(JBLOCKARRAY)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { image[ci] = (*cinfo->emethods->alloc_small_barray) (cinfo->cur_comp_info[ci]->downsampled_width / DCTSIZE, (long) cinfo->cur_comp_info[ci]->MCU_height); } return image; } #ifdef NEED_COMPLEX_CONTROLLER /* not used by simple controller */ LOCAL void free_MCU_row (decompress_info_ptr cinfo, JBLOCKIMAGE image) /* Release a coefficient block array created by alloc_MCU_row */ { int ci; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { (*cinfo->emethods->free_small_barray) (image[ci]); } (*cinfo->emethods->free_small) ((void *) image); } #endif LOCAL void alloc_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE sampled_data[2]) /* Create a downsampled-data buffer having the desired structure */ /* (see comments at head of file) */ { short ci, vs, i; /* Get top-level space for array pointers */ sampled_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->comps_in_scan * SIZEOF(JSAMPARRAY)); sampled_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->comps_in_scan * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { vs = cinfo->cur_comp_info[ci]->v_samp_factor; /* row group height */ /* Allocate the real storage */ sampled_data[0][ci] = (*cinfo->emethods->alloc_small_sarray) (cinfo->cur_comp_info[ci]->downsampled_width, (long) (vs * (DCTSIZE+2))); /* Create space for the scrambled-order pointers */ sampled_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small) (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW)); /* Duplicate the first DCTSIZE-2 row groups */ for (i = 0; i < vs * (DCTSIZE-2); i++) { sampled_data[1][ci][i] = sampled_data[0][ci][i]; } /* Copy the last four row groups in swapped order */ for (i = 0; i < vs * 2; i++) { sampled_data[1][ci][vs*DCTSIZE + i] = sampled_data[0][ci][vs*(DCTSIZE-2) + i]; sampled_data[1][ci][vs*(DCTSIZE-2) + i] = sampled_data[0][ci][vs*DCTSIZE + i]; } } } #ifdef NEED_COMPLEX_CONTROLLER /* not used by simple controller */ LOCAL void free_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE sampled_data[2]) /* Release a sampling buffer created by alloc_sampling_buffer */ { short ci; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { /* Free the real storage */ (*cinfo->emethods->free_small_sarray) (sampled_data[0][ci]); /* Free the scrambled-order pointers */ (*cinfo->emethods->free_small) ((void *) sampled_data[1][ci]); } /* Free the top-level space */ (*cinfo->emethods->free_small) ((void *) sampled_data[0]); (*cinfo->emethods->free_small) ((void *) sampled_data[1]); } #endif /* * Several decompression processes need to range-limit values to the range * 0..MAXJSAMPLE; the input value may fall somewhat outside this range * due to noise introduced by quantization, roundoff error, etc. These * processes are inner loops and need to be as fast as possible. On most * machines, particularly CPUs with pipelines or instruction prefetch, * a (range-check-less) C table lookup * x = sample_range_limit[x]; * is faster than explicit tests * if (x < 0) x = 0; * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; * These processes all use a common table prepared by the routine below. * * The table will work correctly for x within MAXJSAMPLE+1 of the legal * range. This is a much wider range than is needed for most cases, * but the wide range is handy for color quantization. * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. */ LOCAL void prepare_range_limit_table (decompress_info_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE * table; int i; table = (JSAMPLE *) (*cinfo->emethods->alloc_small) (3 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); cinfo->sample_range_limit = table + (MAXJSAMPLE+1); for (i = 0; i <= MAXJSAMPLE; i++) { table[i] = 0; /* sample_range_limit[x] = 0 for x<0 */ table[i+(MAXJSAMPLE+1)] = (JSAMPLE) i; /* sample_range_limit[x] = x */ table[i+(MAXJSAMPLE+1)*2] = MAXJSAMPLE; /* x beyond MAXJSAMPLE */ } } LOCAL void duplicate_row (JSAMPARRAY image_data, long num_cols, int source_row, int num_rows) /* Duplicate the source_row at source_row+1 .. source_row+num_rows */ /* This happens only at the bottom of the image, */ /* so it needn't be super-efficient */ { register int row; for (row = 1; row <= num_rows; row++) { jcopy_sample_rows(image_data, source_row, image_data, source_row + row, 1, num_cols); } } LOCAL void expand (decompress_info_ptr cinfo, JSAMPIMAGE sampled_data, JSAMPIMAGE fullsize_data, long fullsize_width, short above, short current, short below, short out) /* Do upsampling expansion of a single row group (of each component). */ /* above, current, below are indexes of row groups in sampled_data; */ /* out is the index of the target row group in fullsize_data. */ /* Special case: above, below can be -1 to indicate top, bottom of image. */ { jpeg_component_info *compptr; JSAMPARRAY above_ptr, below_ptr; JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */ short ci, vs, i; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* don't bother to upsample an uninteresting component */ if (! compptr->component_needed) continue; vs = compptr->v_samp_factor; /* row group height */ if (above >= 0) above_ptr = sampled_data[ci] + above * vs; else { /* Top of image: make a dummy above-context with copies of 1st row */ /* We assume current=0 in this case */ for (i = 0; i < vs; i++) dummy[i] = sampled_data[ci][0]; above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */ } if (below >= 0) below_ptr = sampled_data[ci] + below * vs; else { /* Bot of image: make a dummy below-context with copies of last row */ for (i = 0; i < vs; i++) dummy[i] = sampled_data[ci][(current+1)*vs-1]; below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */ } (*cinfo->methods->upsample[ci]) (cinfo, (int) ci, compptr->downsampled_width, (int) vs, fullsize_width, (int) cinfo->max_v_samp_factor, above_ptr, sampled_data[ci] + current * vs, below_ptr, fullsize_data[ci] + out * cinfo->max_v_samp_factor); } } LOCAL void emit_1pass (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE fullsize_data, JSAMPARRAY dummy) /* Do color processing and output of num_rows full-size rows. */ /* This is not used when doing 2-pass color quantization. */ /* The dummy argument simply lets this be called via scan_big_image. */ { if (cinfo->quantize_colors) { (*cinfo->methods->color_quantize) (cinfo, num_rows, fullsize_data, output_workspace[0]); } else { (*cinfo->methods->color_convert) (cinfo, num_rows, cinfo->image_width, fullsize_data, output_workspace); } (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, output_workspace); } /* * Support routines for complex controller. */ #ifdef NEED_COMPLEX_CONTROLLER METHODDEF void scan_big_image (decompress_info_ptr cinfo, quantize_method_ptr quantize_method) /* Apply quantize_method to entire image stored in fullsize_image[]. */ /* This is the "iterator" routine used by the 2-pass color quantizer. */ /* We also use it directly in some cases. */ { long pixel_rows_output; short ci; for (pixel_rows_output = 0; pixel_rows_output < cinfo->image_height; pixel_rows_output += rows_in_mem) { (*cinfo->methods->progress_monitor) (cinfo, pixel_rows_output, cinfo->image_height); /* Realign the big buffers */ for (ci = 0; ci < cinfo->num_components; ci++) { fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray) (fullsize_image[ci], pixel_rows_output, FALSE); } /* Let the quantizer have its way with the data. * Note that output_workspace is simply workspace for the quantizer; * when it's ready to output, it must call put_pixel_rows itself. */ (*quantize_method) (cinfo, (int) MIN((long) rows_in_mem, cinfo->image_height - pixel_rows_output), fullsize_ptrs, output_workspace[0]); } cinfo->completed_passes++; } #endif /* NEED_COMPLEX_CONTROLLER */ /* * Support routines for cross-block smoothing. */ #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL void smooth_mcu_row (decompress_info_ptr cinfo, JBLOCKIMAGE above, JBLOCKIMAGE input, JBLOCKIMAGE below, JBLOCKIMAGE output) /* Apply cross-block smoothing to one MCU row's worth of coefficient blocks. */ /* above,below are NULL if at top/bottom of image. */ { jpeg_component_info *compptr; short ci, ri, last; JBLOCKROW prev; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* don't bother to smooth an uninteresting component */ if (! compptr->component_needed) continue; last = compptr->MCU_height - 1; if (above == NULL) prev = NULL; else prev = above[ci][last]; for (ri = 0; ri < last; ri++) { (*cinfo->methods->smooth_coefficients) (cinfo, compptr, prev, input[ci][ri], input[ci][ri+1], output[ci][ri]); prev = input[ci][ri]; } if (below == NULL) (*cinfo->methods->smooth_coefficients) (cinfo, compptr, prev, input[ci][last], (JBLOCKROW) NULL, output[ci][last]); else (*cinfo->methods->smooth_coefficients) (cinfo, compptr, prev, input[ci][last], below[ci][0], output[ci][last]); } } LOCAL void get_smoothed_row (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data, JBLOCKIMAGE bsmooth[3], int * whichb, long cur_mcu_row) /* Get an MCU row of coefficients, applying cross-block smoothing. */ /* The output row is placed in coeff_data. bsmooth and whichb hold */ /* working state, and cur_row is needed to check for image top/bottom. */ /* This routine just takes care of the buffering logic. */ { int prev, cur, next; /* Special case for top of image: need to pre-fetch a row & init whichb */ if (cur_mcu_row == 0) { (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[0]); if (cinfo->MCU_rows_in_scan > 1) { (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[1]); smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], bsmooth[1], coeff_data); } else { smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], (JBLOCKIMAGE) NULL, coeff_data); } *whichb = 1; /* points to next bsmooth[] element to use */ return; } cur = *whichb; /* set up references */ prev = (cur == 0 ? 2 : cur - 1); next = (cur == 2 ? 0 : cur + 1); *whichb = next; /* advance whichb for next time */ /* Special case for bottom of image: don't read another row */ if (cur_mcu_row >= cinfo->MCU_rows_in_scan - 1) { smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], (JBLOCKIMAGE) NULL, coeff_data); return; } /* Normal case: read ahead a new row, smooth the one I got before */ (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[next]); smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], bsmooth[next], coeff_data); } #endif /* BLOCK_SMOOTHING_SUPPORTED */ /* * Decompression pipeline controller used for single-scan files * without 2-pass color quantization. */ METHODDEF void simple_dcontroller (decompress_info_ptr cinfo) { long fullsize_width; /* # of samples per row in full-size buffers */ long cur_mcu_row; /* counts # of MCU rows processed */ long pixel_rows_output; /* # of pixel rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for dequantized coefficients (IDCT input) */ JBLOCKIMAGE coeff_data; /* Work buffer for cross-block smoothing input */ #ifdef BLOCK_SMOOTHING_SUPPORTED JBLOCKIMAGE bsmooth[3]; /* this is optional */ int whichb; #endif /* Work buffer for downsampled image data (see comments at head of file) */ JSAMPIMAGE sampled_data[2]; /* Work buffer for upsampled data */ JSAMPIMAGE fullsize_data; int whichss, ri; short i; /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Prepare for single scan containing all components */ if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Need to read Vk MCU rows to obtain Vk block rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row provides Vk block rows */ mcu_rows_per_loop = 1; } cinfo->total_passes++; /* Allocate working memory: */ prepare_range_limit_table(cinfo); /* coeff_data holds a single MCU row of coefficient blocks */ coeff_data = alloc_MCU_row(cinfo); /* if doing cross-block smoothing, need extra space for its input */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { bsmooth[0] = alloc_MCU_row(cinfo); bsmooth[1] = alloc_MCU_row(cinfo); bsmooth[2] = alloc_MCU_row(cinfo); } #endif /* sampled_data is sample data before upsampling */ alloc_sampling_buffer(cinfo, sampled_data); /* fullsize_data is sample data after upsampling */ fullsize_data = alloc_sampimage(cinfo, (int) cinfo->num_components, (long) rows_in_mem, fullsize_width); /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); /* Tell the memory manager to instantiate big arrays. * We don't need any big arrays in this controller, * but some other module (like the output file writer) may need one. */ (*cinfo->emethods->alloc_big_arrays) ((long) 0, /* no more small sarrays */ (long) 0, /* no more small barrays */ (long) 0); /* no more "medium" objects */ /* NB: if quantizer needs any "medium" size objects, it must get them */ /* at color_quant_init time */ /* Initialize to read scan data */ (*cinfo->methods->entropy_decode_init) (cinfo); (*cinfo->methods->upsample_init) (cinfo); (*cinfo->methods->disassemble_init) (cinfo); /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */ pixel_rows_output = 0; whichss = 1; /* arrange to start with sampled_data[0] */ for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan; cur_mcu_row += mcu_rows_per_loop) { (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row, cinfo->MCU_rows_in_scan); whichss ^= 1; /* switch to other downsampled-data buffer */ /* Obtain v_samp_factor block rows of each component in the scan. */ /* This is a single MCU row if interleaved, multiple MCU rows if not. */ /* In the noninterleaved case there might be fewer than v_samp_factor */ /* block rows remaining; if so, pad with copies of the last pixel row */ /* so that upsampling doesn't have to treat it as a special case. */ for (ri = 0; ri < mcu_rows_per_loop; ri++) { if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) { /* OK to actually read an MCU row. */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) get_smoothed_row(cinfo, coeff_data, bsmooth, &whichb, cur_mcu_row + ri); else #endif (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data); (*cinfo->methods->reverse_DCT) (cinfo, coeff_data, sampled_data[whichss], ri * DCTSIZE); } else { /* Need to pad out with copies of the last downsampled row. */ /* This can only happen if there is just one component. */ duplicate_row(sampled_data[whichss][0], cinfo->cur_comp_info[0]->downsampled_width, ri * DCTSIZE - 1, DCTSIZE); } } /* Upsample the data */ /* First time through is a special case */ if (cur_mcu_row) { /* Expand last row group of previous set */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* and dump the previous set's expanded data */ emit_1pass (cinfo, rows_in_mem, fullsize_data, (JSAMPARRAY) NULL); pixel_rows_output += rows_in_mem; /* Expand first row group of this set */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Expand first row group with dummy above-context */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Expand second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of outer loop */ /* Expand the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* and dump the remaining data (may be less than full height) */ emit_1pass (cinfo, (int) (cinfo->image_height - pixel_rows_output), fullsize_data, (JSAMPARRAY) NULL); /* Clean up after the scan */ (*cinfo->methods->disassemble_term) (cinfo); (*cinfo->methods->upsample_term) (cinfo); (*cinfo->methods->entropy_decode_term) (cinfo); (*cinfo->methods->read_scan_trailer) (cinfo); cinfo->completed_passes++; /* Verify that we've seen the whole input file */ if ((*cinfo->methods->read_scan_header) (cinfo)) WARNMS(cinfo->emethods, "Didn't expect more than one scan"); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ } /* * Decompression pipeline controller used for multiple-scan files * and/or 2-pass color quantization. * * The current implementation places the "big" buffer at the stage of * upsampled, non-color-processed data. This is the only place that * makes sense when doing 2-pass quantization. For processing multiple-scan * files without 2-pass quantization, it would be possible to develop another * controller that buffers the downsampled data instead, thus reducing the size * of the temp files (by about a factor of 2 in typical cases). However, * our present upsampling logic is dependent on the assumption that * upsampling occurs during a scan, so it's much easier to do the * enlargement as the JPEG file is read. This also simplifies life for the * memory manager, which would otherwise have to deal with overlapping * access_big_sarray() requests. * At present it appears that most JPEG files will be single-scan, * so it doesn't seem worthwhile to worry about this optimization. */ #ifdef NEED_COMPLEX_CONTROLLER METHODDEF void complex_dcontroller (decompress_info_ptr cinfo) { long fullsize_width; /* # of samples per row in full-size buffers */ long cur_mcu_row; /* counts # of MCU rows processed */ long pixel_rows_output; /* # of pixel rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for dequantized coefficients (IDCT input) */ JBLOCKIMAGE coeff_data; /* Work buffer for cross-block smoothing input */ #ifdef BLOCK_SMOOTHING_SUPPORTED JBLOCKIMAGE bsmooth[3]; /* this is optional */ int whichb; #endif /* Work buffer for downsampled image data (see comments at head of file) */ JSAMPIMAGE sampled_data[2]; int whichss, ri; short ci, i; boolean single_scan; /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate all working memory that doesn't depend on scan info */ prepare_range_limit_table(cinfo); /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); /* Get a big image: fullsize_image is sample data after upsampling. */ fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(big_sarray_ptr)); for (ci = 0; ci < cinfo->num_components; ci++) { fullsize_image[ci] = (*cinfo->emethods->request_big_sarray) (fullsize_width, jround_up(cinfo->image_height, (long) rows_in_mem), (long) rows_in_mem); } /* Also get an area for pointers to currently accessible chunks */ fullsize_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); /* Tell the memory manager to instantiate big arrays */ (*cinfo->emethods->alloc_big_arrays) /* extra sarray space is for downsampled-data buffers: */ ((long) (fullsize_width /* max width in samples */ * cinfo->max_v_samp_factor*(DCTSIZE+2) /* max height */ * cinfo->num_components), /* max components per scan */ /* extra barray space is for MCU-row buffers: */ (long) ((fullsize_width / DCTSIZE) /* max width in blocks */ * cinfo->max_v_samp_factor /* max height */ * cinfo->num_components /* max components per scan */ * (cinfo->do_block_smoothing ? 4 : 1)),/* how many of these we need */ /* no extra "medium"-object space */ (long) 0); /* NB: if quantizer needs any "medium" size objects, it must get them */ /* at color_quant_init time */ /* If file is single-scan, we can do color quantization prescan on-the-fly * during the scan (we must be doing 2-pass quantization, else this method * would not have been selected). If it is multiple scans, we have to make * a separate pass after we've collected all the components. (We could save * some I/O by doing CQ prescan during the last scan, but the extra logic * doesn't seem worth the trouble.) */ single_scan = (cinfo->comps_in_scan == cinfo->num_components); /* Account for passes needed (color quantizer adds its passes separately). * If multiscan file, we guess that each component has its own scan, * and increment completed_passes by the number of components in the scan. */ if (single_scan) cinfo->total_passes++; /* the single scan */ else { cinfo->total_passes += cinfo->num_components; /* guessed # of scans */ if (cinfo->two_pass_quantize) cinfo->total_passes++; /* account for separate CQ prescan pass */ } if (! cinfo->two_pass_quantize) cinfo->total_passes++; /* count output pass unless quantizer does it */ /* Loop over scans in file */ do { /* Prepare for this scan */ if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Need to read Vk MCU rows to obtain Vk block rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row provides Vk block rows */ mcu_rows_per_loop = 1; } /* Allocate scan-local working memory */ /* coeff_data holds a single MCU row of coefficient blocks */ coeff_data = alloc_MCU_row(cinfo); /* if doing cross-block smoothing, need extra space for its input */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { bsmooth[0] = alloc_MCU_row(cinfo); bsmooth[1] = alloc_MCU_row(cinfo); bsmooth[2] = alloc_MCU_row(cinfo); } #endif /* sampled_data is sample data before upsampling */ alloc_sampling_buffer(cinfo, sampled_data); /* line up the big buffers for components in this scan */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray) (fullsize_image[cinfo->cur_comp_info[ci]->component_index], (long) 0, TRUE); } /* Initialize to read scan data */ (*cinfo->methods->entropy_decode_init) (cinfo); (*cinfo->methods->upsample_init) (cinfo); (*cinfo->methods->disassemble_init) (cinfo); /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */ pixel_rows_output = 0; whichss = 1; /* arrange to start with sampled_data[0] */ for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan; cur_mcu_row += mcu_rows_per_loop) { (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row, cinfo->MCU_rows_in_scan); whichss ^= 1; /* switch to other downsampled-data buffer */ /* Obtain v_samp_factor block rows of each component in the scan. */ /* This is a single MCU row if interleaved, multiple MCU rows if not. */ /* In the noninterleaved case there might be fewer than v_samp_factor */ /* block rows remaining; if so, pad with copies of the last pixel row */ /* so that upsampling doesn't have to treat it as a special case. */ for (ri = 0; ri < mcu_rows_per_loop; ri++) { if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) { /* OK to actually read an MCU row. */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) get_smoothed_row(cinfo, coeff_data, bsmooth, &whichb, cur_mcu_row + ri); else #endif (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data); (*cinfo->methods->reverse_DCT) (cinfo, coeff_data, sampled_data[whichss], ri * DCTSIZE); } else { /* Need to pad out with copies of the last downsampled row. */ /* This can only happen if there is just one component. */ duplicate_row(sampled_data[whichss][0], cinfo->cur_comp_info[0]->downsampled_width, ri * DCTSIZE - 1, DCTSIZE); } } /* Upsample the data */ /* First time through is a special case */ if (cur_mcu_row) { /* Expand last row group of previous set */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* If single scan, can do color quantization prescan on-the-fly */ if (single_scan) (*cinfo->methods->color_quant_prescan) (cinfo, rows_in_mem, fullsize_ptrs, output_workspace[0]); /* Realign the big buffers */ pixel_rows_output += rows_in_mem; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray) (fullsize_image[cinfo->cur_comp_info[ci]->component_index], pixel_rows_output, TRUE); } /* Expand first row group of this set */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Expand first row group with dummy above-context */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Expand second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of loop over scan's data */ /* Expand the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* If single scan, finish on-the-fly color quantization prescan */ if (single_scan) (*cinfo->methods->color_quant_prescan) (cinfo, (int) (cinfo->image_height - pixel_rows_output), fullsize_ptrs, output_workspace[0]); /* Clean up after the scan */ (*cinfo->methods->disassemble_term) (cinfo); (*cinfo->methods->upsample_term) (cinfo); (*cinfo->methods->entropy_decode_term) (cinfo); (*cinfo->methods->read_scan_trailer) (cinfo); if (single_scan) cinfo->completed_passes++; else cinfo->completed_passes += cinfo->comps_in_scan; /* Release scan-local working memory */ free_MCU_row(cinfo, coeff_data); #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { free_MCU_row(cinfo, bsmooth[0]); free_MCU_row(cinfo, bsmooth[1]); free_MCU_row(cinfo, bsmooth[2]); } #endif free_sampling_buffer(cinfo, sampled_data); /* Repeat if there is another scan */ } while ((!single_scan) && (*cinfo->methods->read_scan_header) (cinfo)); if (single_scan) { /* If we expected just one scan, make SURE there's just one */ if ((*cinfo->methods->read_scan_header) (cinfo)) WARNMS(cinfo->emethods, "Didn't expect more than one scan"); /* We did the CQ prescan on-the-fly, so we are all set. */ } else { /* For multiple-scan file, do the CQ prescan as a separate pass. */ /* The main reason why prescan is passed the output_workspace is */ /* so that we can use scan_big_image to call it... */ if (cinfo->two_pass_quantize) scan_big_image(cinfo, cinfo->methods->color_quant_prescan); } /* Now that we've collected the data, do color processing and output */ if (cinfo->two_pass_quantize) (*cinfo->methods->color_quant_doit) (cinfo, scan_big_image); else scan_big_image(cinfo, emit_1pass); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ } #endif /* NEED_COMPLEX_CONTROLLER */ /* * The method selection routine for decompression pipeline controllers. * Note that at this point we've already read the JPEG header and first SOS, * so we can tell whether the input is one scan or not. */ GLOBAL void jseldpipeline (decompress_info_ptr cinfo) { /* simplify subsequent tests on color quantization */ if (! cinfo->quantize_colors) cinfo->two_pass_quantize = FALSE; if (cinfo->comps_in_scan == cinfo->num_components) { /* It's a single-scan file */ if (cinfo->two_pass_quantize) { #ifdef NEED_COMPLEX_CONTROLLER cinfo->methods->d_pipeline_controller = complex_dcontroller; #else ERREXIT(cinfo->emethods, "2-pass quantization support was not compiled"); #endif } else cinfo->methods->d_pipeline_controller = simple_dcontroller; } else { /* It's a multiple-scan file */ #ifdef NEED_COMPLEX_CONTROLLER cinfo->methods->d_pipeline_controller = complex_dcontroller; #else ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled"); #endif } } n. xloadimage.4.1/jpeg/jdsample.c 644 221 144 22701 5276276056 11467 /* * jdsample.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * These routines are invoked via the upsample and * upsample_init/term methods. * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. */ #include "jinclude.h" /* * Initialize for upsampling a scan. */ METHODDEF void upsample_init (decompress_info_ptr cinfo) { /* no work for now */ } /* * Upsample pixel values of a single component. * This version handles any integral sampling ratios. * * This is not used for typical JPEG files, so it need not be fast. * Nor, for that matter, is it particularly accurate: the algorithm is * simple replication of the input pixel onto the corresponding output * pixels. The hi-falutin sampling literature refers to this as a * "box filter". A box filter tends to introduce visible artifacts, * so if you are actually going to use 3:1 or 4:1 sampling ratios * you would be well advised to improve this code. */ METHODDEF void int_upsample (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; register JSAMPROW inptr, outptr; register JSAMPLE invalue; register short h_expand, h; short v_expand, v; int inrow, outrow; register long incol; #ifdef DEBUG /* for debugging pipeline controller */ if (input_rows != compptr->v_samp_factor || output_rows != cinfo->max_v_samp_factor || (input_cols % compptr->h_samp_factor) != 0 || (output_cols % cinfo->max_h_samp_factor) != 0 || output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus upsample parameters"); #endif h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; outrow = 0; for (inrow = 0; inrow < input_rows; inrow++) { for (v = 0; v < v_expand; v++) { inptr = input_data[inrow]; outptr = output_data[outrow++]; for (incol = 0; incol < input_cols; incol++) { invalue = GETJSAMPLE(*inptr++); for (h = 0; h < h_expand; h++) { *outptr++ = invalue; } } } } } /* * Upsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 1:1 vertical. * * The upsampling algorithm is linear interpolation between pixel centers, * also known as a "triangle filter". This is a good compromise between * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 * of the way between input pixel centers. */ METHODDEF void h2v1_upsample (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { register JSAMPROW inptr, outptr; register int invalue; int inrow; register long colctr; #ifdef DEBUG /* for debugging pipeline controller */ jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; if (input_rows != compptr->v_samp_factor || output_rows != cinfo->max_v_samp_factor || (input_cols % compptr->h_samp_factor) != 0 || (output_cols % cinfo->max_h_samp_factor) != 0 || output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus upsample parameters"); #endif for (inrow = 0; inrow < input_rows; inrow++) { inptr = input_data[inrow]; outptr = output_data[inrow]; /* Special case for first column */ invalue = GETJSAMPLE(*inptr++); *outptr++ = (JSAMPLE) invalue; *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); for (colctr = input_cols - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ invalue = GETJSAMPLE(*inptr++) * 3; *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 2) >> 2); *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); } /* Special case for last column */ invalue = GETJSAMPLE(*inptr); *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 2) >> 2); *outptr++ = (JSAMPLE) invalue; } } /* * Upsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 2:1 vertical. * * The upsampling algorithm is linear interpolation between pixel centers, * also known as a "triangle filter". This is a good compromise between * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 * of the way between input pixel centers. */ METHODDEF void h2v2_upsample (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { register JSAMPROW inptr0, inptr1, outptr; #ifdef EIGHT_BIT_SAMPLES register int thiscolsum, lastcolsum, nextcolsum; #else register INT32 thiscolsum, lastcolsum, nextcolsum; #endif int inrow, outrow, v; register long colctr; #ifdef DEBUG /* for debugging pipeline controller */ jpeg_component_info * compptr = cinfo->cur_comp_info[which_component]; if (input_rows != compptr->v_samp_factor || output_rows != cinfo->max_v_samp_factor || (input_cols % compptr->h_samp_factor) != 0 || (output_cols % cinfo->max_h_samp_factor) != 0 || output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor) ERREXIT(cinfo->emethods, "Bogus upsample parameters"); #endif outrow = 0; for (inrow = 0; inrow < input_rows; inrow++) { for (v = 0; v < 2; v++) { /* inptr0 points to nearest input row, inptr1 points to next nearest */ inptr0 = input_data[inrow]; if (v == 0) { /* next nearest is row above */ if (inrow == 0) inptr1 = above[input_rows-1]; else inptr1 = input_data[inrow-1]; } else { /* next nearest is row below */ if (inrow == input_rows-1) inptr1 = below[0]; else inptr1 = input_data[inrow+1]; } outptr = output_data[outrow++]; /* Special case for first column */ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for (colctr = input_cols - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); } } } /* * Upsample pixel values of a single component. * This version handles the special case of a full-size component. */ METHODDEF void fullsize_upsample (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data) { #ifdef DEBUG /* for debugging pipeline controller */ if (input_cols != output_cols || input_rows != output_rows) ERREXIT(cinfo->emethods, "Pipeline controller messed up"); #endif jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols); } /* * Clean up after a scan. */ METHODDEF void upsample_term (decompress_info_ptr cinfo) { /* no work for now */ } /* * The method selection routine for upsampling. * Note that we must select a routine for each component. */ GLOBAL void jselupsample (decompress_info_ptr cinfo) { short ci; jpeg_component_info * compptr; if (cinfo->CCIR601_sampling) ERREXIT(cinfo->emethods, "CCIR601 upsampling not implemented yet"); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (compptr->h_samp_factor == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) cinfo->methods->upsample[ci] = fullsize_upsample; else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) cinfo->methods->upsample[ci] = h2v1_upsample; else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) cinfo->methods->upsample[ci] = h2v2_upsample; else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) cinfo->methods->upsample[ci] = int_upsample; else ERREXIT(cinfo->emethods, "Fractional upsampling not implemented yet"); } cinfo->methods->upsample_init = upsample_init; cinfo->methods->upsample_term = upsample_term; } ) { invalue = GETJSAMPLE(*inptr++); for (h = 0; h < h_expand;xloadimage.4.1/jpeg/jerror.c 644 221 144 5120 5301262436 11131 /* * jerror.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains simple error-reporting and trace-message routines. * These are suitable for Unix-like systems and others where writing to * stderr is the right thing to do. If the JPEG software is integrated * into a larger application, you may well need to replace these. * * The error_exit() routine should not return to its caller. Within a * larger application, you might want to have it do a longjmp() to return * control to the outer user interface routine. This should work since * the portable JPEG code doesn't use setjmp/longjmp. You should make sure * that free_all is called either within error_exit or after the return to * the outer-level routine. * * These routines are used by both the compression and decompression code. */ #include "jinclude.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare exit() */ #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif static external_methods_ptr methods; /* saved for access to message_parm, free_all */ METHODDEF void trace_message (const char *msgtext) { fprintf(stderr, msgtext, methods->message_parm[0], methods->message_parm[1], methods->message_parm[2], methods->message_parm[3], methods->message_parm[4], methods->message_parm[5], methods->message_parm[6], methods->message_parm[7]); fprintf(stderr, "\n"); } METHODDEF void error_exit (const char *msgtext) { (*methods->trace_message) (msgtext); (*methods->free_all) (); /* clean up memory allocation */ exit(EXIT_FAILURE); } /* * The method selection routine for simple error handling. * The system-dependent setup routine should call this routine * to install the necessary method pointers in the supplied struct. */ GLOBAL void jselerror (external_methods_ptr emethods) { methods = emethods; /* save struct addr for later access */ emethods->error_exit = error_exit; emethods->trace_message = trace_message; emethods->trace_level = 0; /* default = no tracing */ emethods->num_warnings = 0; /* no warnings emitted yet */ /* By default, the first corrupt-data warning will be displayed, * but additional ones will appear only if trace level is at least 3. * A corrupt data file could generate many warnings, so it's a good idea * to suppress additional messages except at high tracing levels. */ emethods->first_warning_level = 0; emethods->more_warning_level = 3; } orithm is linear interpolation between pixel centers, * also known as a "triangle filter". This is a good compromise between * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 * of the way between input pixel centers. */ METHODDEF void h2v1_upsample (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRxloadimage.4.1/jpeg/jfwddct.c 644 221 144 26760 5300067503 11305 /* * jfwddct.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the basic DCT (Discrete Cosine Transform) * transformation subroutine. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #include "jinclude.h" /* * This routine is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * The poop on this scaling stuff is as follows: * * Each 1-D DCT step produces outputs which are a factor of sqrt(N) * larger than the true DCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D DCT, * because the y0 and y4 outputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 25. Error analysis * shows that the values given below are the most effective. */ #ifdef EIGHT_BIT_SAMPLES #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 0 /* lose a little precision to avoid overflow */ #endif #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * some C compilers will do the right thing if you provide the correct * combination of casts. * NB: for 12-bit samples, a full 32-bit multiplication will be needed. */ #ifdef EIGHT_BIT_SAMPLES #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #endif #ifndef MULTIPLY /* default definition */ #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the forward DCT on one block of samples. */ GLOBAL void j_fwd_dct (DCTBLOCK data) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; register DCTELEM *dataptr; int rowctr; SHIFT_TEMPS /* Pass 1: process rows. */ /* Note results are scaled up by sqrt(8) compared to a true DCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+3); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+3); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS+PASS1_BITS+3); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS+PASS1_BITS+3); dataptr++; /* advance pointer to next column */ } } around this we uxloadimage.4.1/jpeg/jinclude.h 644 221 144 7504 5340461777 11454 /* * jinclude.h * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This is the central file that's #include'd by all the JPEG .c files. * Its purpose is to provide a single place to fix any problems with * including the wrong system include files. * You can edit these declarations if you use a system with nonstandard * system include files. */ /* * Normally the __STDC__ macro can be taken as indicating that the system * include files conform to the ANSI C standard. However, if you are running * GCC on a machine with non-ANSI system include files, that is not the case. * In that case change the following, or add -DNONANSI_INCLUDES to your CFLAGS. */ #ifdef __STDC__ #ifndef NONANSI_INCLUDES #define INCLUDES_ARE_ANSI /* this is what's tested before including */ #endif #endif /* * is included to get the FILE typedef and NULL macro. * Note that the core portable-JPEG files do not actually do any I/O * using the stdio library; only the user interface, error handler, * and file reading/writing modules invoke any stdio functions. * (Well, we did cheat a bit in jmemmgr.c, but only if MEM_STATS is defined.) */ #include /* * We need the size_t typedef, which defines the parameter type of malloc(). * In an ANSI-conforming implementation this is provided by , * but on non-ANSI systems it's more likely to be in . * On some not-quite-ANSI systems you may find it in . */ #ifndef INCLUDES_ARE_ANSI /* shouldn't need this if ANSI C */ #include #endif #ifdef __SASC /* Amiga SAS C provides it in stddef.h. */ #include #endif /* * In ANSI C, and indeed any rational implementation, size_t is also the * type returned by sizeof(). However, it seems there are some irrational * implementations out there, in which sizeof() returns an int even though * size_t is defined as long or unsigned long. To ensure consistent results * we always use this SIZEOF() macro in place of using sizeof() directly. */ #undef SIZEOF /* in case you included X11/xmd.h */ #define SIZEOF(object) ((size_t) sizeof(object)) /* * fread() and fwrite() are always invoked through these macros. * On some systems you may need to twiddle the argument casts. * CAUTION: argument order is different from underlying functions! */ #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) /* * We need the memcpy() and strcmp() functions, plus memory zeroing. * ANSI and System V implementations declare these in . * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). * Some systems may declare memset and memcpy in . * * NOTE: we assume the size parameters to these functions are of type size_t. * Change the casts in these macros if not! */ #ifdef INCLUDES_ARE_ANSI #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #else /* not ANSI */ #ifdef BSD #include #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume Sys V or compatible */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #endif /* BSD */ #endif /* ANSI */ /* Now include the portable JPEG definition files. */ #include "jconfig.h" #include "jpegdata.h" bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * somexloadimage.4.1/jpeg/jmemansi.c 644 221 144 10317 5160246210 11450 /* * jmemansi.c (jmemsys.c) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a simple generic implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that you have the ANSI-standard library routine tmpfile(). * Also, the problem of determining the amount of memory available * is shoved onto the user. */ #include "jinclude.h" #include "jmemsys.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare malloc(), free() */ #else extern void * malloc PP((size_t size)); extern void free PP((void *ptr)); #endif #ifndef SEEK_SET /* pre-ANSI systems may not define this; */ #define SEEK_SET 0 /* if not, assume 0 is correct */ #endif static external_methods_ptr methods; /* saved for access to error_exit */ static long total_used; /* total memory requested so far */ /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jget_small (size_t sizeofobject) { total_used += sizeofobject; return (void *) malloc(sizeofobject); } GLOBAL void jfree_small (void * object) { free(object); } /* * We assume NEED_FAR_POINTERS is not defined and so the separate entry points * jget_large, jfree_large are not needed. */ /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ #endif GLOBAL long jmem_available (long min_bytes_needed, long max_bytes_needed) { return methods->max_memory_to_use - total_used; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jmem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ METHODDEF void read_backing_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(methods, "fseek failed on temporary file"); if (JFREAD(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(methods, "fread failed on temporary file"); } METHODDEF void write_backing_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(methods, "fseek failed on temporary file"); if (JFWRITE(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?"); } METHODDEF void close_backing_store (backing_store_ptr info) { fclose(info->temp_file); /* Since this implementation uses tmpfile() to create the file, * no explicit file deletion is needed. */ } /* * Initial opening of a backing-store object. * * This version uses tmpfile(), which constructs a suitable file name * behind the scenes. We don't have to use temp_name[] at all; * indeed, we can't even find out the actual name of the temp file. */ GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { if ((info->temp_file = tmpfile()) == NULL) ERREXIT(methods, "Failed to create temporary file"); info->read_backing_store = read_backing_store; info->write_backing_store = write_backing_store; info->close_backing_store = close_backing_store; } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = DEFAULT_MAX_MEM; total_used = 0; } GLOBAL void jmem_term (void) { /* no work */ } e) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume Sys V or compatible */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) xloadimage.4.1/jpeg/jmemdos.c 644 221 144 44556 5315467553 11340 /* * jmemdos.c (jmemsys.c) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides an MS-DOS-compatible implementation of the system- * dependent portion of the JPEG memory manager. Temporary data can be * stored in extended or expanded memory as well as in regular DOS files. * * If you use this file, you must be sure that NEED_FAR_POINTERS is defined * if you compile in a small-data memory model; it should NOT be defined if * you use a large-data memory model. This file is not recommended if you * are using a flat-memory-space 386 environment such as DJGCC or Watcom C. * Also, this code will NOT work if struct fields are aligned on greater than * 2-byte boundaries. * * Based on code contributed by Ge' Weijers. */ /* * If you have both extended and expanded memory, you may want to change the * order in which they are tried in jopen_backing_store. On a 286 machine * expanded memory is usually faster, since extended memory access involves * an expensive protected-mode-and-back switch. On 386 and better, extended * memory is usually faster. As distributed, the code tries extended memory * first (what? not everyone has a 386? :-). * * You can disable use of extended/expanded memory entirely by altering these * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0). */ #ifndef XMS_SUPPORTED #define XMS_SUPPORTED 1 #endif #ifndef EMS_SUPPORTED #define EMS_SUPPORTED 1 #endif #include "jinclude.h" #include "jmemsys.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare malloc(), free(), getenv() */ #else extern void * malloc PP((size_t size)); extern void free PP((void *ptr)); extern char * getenv PP((const char * name)); #endif #ifdef NEED_FAR_POINTERS #ifdef __TURBOC__ /* These definitions work for Borland C (Turbo C) */ #include /* need farmalloc(), farfree() */ #define far_malloc(x) farmalloc(x) #define far_free(x) farfree(x) #else /* These definitions work for Microsoft C and compatible compilers */ #include /* need _fmalloc(), _ffree() */ #define far_malloc(x) _fmalloc(x) #define far_free(x) _ffree(x) #endif #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #else #define READ_BINARY "rb" #endif /* * Declarations for assembly-language support routines (see jmemdosa.asm). * * The functions are declared "far" as are all pointer arguments; * this ensures the assembly source code will work regardless of the * compiler memory model. We assume "short" is 16 bits, "long" is 32. */ typedef void far * XMSDRIVER; /* actually a pointer to code */ typedef struct { /* registers for calling XMS driver */ unsigned short ax, dx, bx; void far * ds_si; } XMScontext; typedef struct { /* registers for calling EMS driver */ unsigned short ax, dx, bx; void far * ds_si; } EMScontext; EXTERN short far jdos_open PP((short far * handle, char far * filename)); EXTERN short far jdos_close PP((short handle)); EXTERN short far jdos_seek PP((short handle, long offset)); EXTERN short far jdos_read PP((short handle, void far * buffer, unsigned short count)); EXTERN short far jdos_write PP((short handle, void far * buffer, unsigned short count)); EXTERN void far jxms_getdriver PP((XMSDRIVER far *)); EXTERN void far jxms_calldriver PP((XMSDRIVER, XMScontext far *)); EXTERN short far jems_available PP((void)); EXTERN void far jems_calldriver PP((EMScontext far *)); static external_methods_ptr methods; /* saved for access to error_exit */ static long total_used; /* total FAR memory requested so far */ /* * Selection of a file name for a temporary file. * This is highly system-dependent, and you may want to customize it. */ static int next_file_num; /* to distinguish among several temp files */ LOCAL void select_file_name (char * fname) { const char * env; char * ptr; FILE * tfile; /* Keep generating file names till we find one that's not in use */ for (;;) { /* Get temp directory name from environment TMP or TEMP variable; * if none, use "." */ if ((env = (const char *) getenv("TMP")) == NULL) if ((env = (const char *) getenv("TEMP")) == NULL) env = "."; if (*env == '\0') /* null string means "." */ env = "."; ptr = fname; /* copy name to fname */ while (*env != '\0') *ptr++ = *env++; if (ptr[-1] != '\\' && ptr[-1] != '/') *ptr++ = '\\'; /* append backslash if not in env variable */ /* Append a suitable file name */ next_file_num++; /* advance counter */ sprintf(ptr, "JPG%03d.TMP", next_file_num); /* Probe to see if file name is already in use */ if ((tfile = fopen(fname, READ_BINARY)) == NULL) break; fclose(tfile); /* oops, it's there; close tfile & try again */ } } /* * Near-memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jget_small (size_t sizeofobject) { /* near data space is NOT counted in total_used */ #ifndef NEED_FAR_POINTERS total_used += sizeofobject; #endif return (void *) malloc(sizeofobject); } GLOBAL void jfree_small (void * object) { free(object); } /* * Far-memory allocation and freeing */ #ifdef NEED_FAR_POINTERS GLOBAL void FAR * jget_large (size_t sizeofobject) { total_used += sizeofobject; return (void FAR *) far_malloc(sizeofobject); } GLOBAL void jfree_large (void FAR * object) { far_free(object); } #endif /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */ #endif GLOBAL long jmem_available (long min_bytes_needed, long max_bytes_needed) { return methods->max_memory_to_use - total_used; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jmem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ /* * For MS-DOS we support three types of backing storage: * 1. Conventional DOS files. We access these by direct DOS calls rather * than via the stdio package. This provides a bit better performance, * but the real reason is that the buffers to be read or written are FAR. * The stdio library for small-data memory models can't cope with that. * 2. Extended memory, accessed per the XMS V2.0 specification. * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification. * You'll need copies of those specs to make sense of the related code. * The specs are available by Internet FTP from SIMTEL20 and its various * mirror sites; see microsoft/xms20.arc and info/limems41.zip. */ /* * Access methods for a DOS file. */ METHODDEF void read_file_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (jdos_seek(info->handle.file_handle, file_offset)) ERREXIT(methods, "seek failed on temporary file"); /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ if (byte_count > 65535L) /* safety check */ ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K"); if (jdos_read(info->handle.file_handle, buffer_address, (unsigned short) byte_count)) ERREXIT(methods, "read failed on temporary file"); } METHODDEF void write_file_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (jdos_seek(info->handle.file_handle, file_offset)) ERREXIT(methods, "seek failed on temporary file"); /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ if (byte_count > 65535L) /* safety check */ ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K"); if (jdos_write(info->handle.file_handle, buffer_address, (unsigned short) byte_count)) ERREXIT(methods, "write failed on temporary file --- out of disk space?"); } METHODDEF void close_file_store (backing_store_ptr info) { jdos_close(info->handle.file_handle); /* close the file */ remove(info->temp_name); /* delete the file */ /* If your system doesn't have remove(), try unlink() instead. * remove() is the ANSI-standard name for this function, but * unlink() was more common in pre-ANSI systems. */ TRACEMS1(methods, 1, "Closed DOS file %d", info->handle.file_handle); } LOCAL boolean open_file_store (backing_store_ptr info, long total_bytes_needed) { short handle; char tracemsg[TEMP_NAME_LENGTH+40]; select_file_name(info->temp_name); if (jdos_open((short far *) & handle, (char far *) info->temp_name)) { /* hack to get around TRACEMS' inability to handle string parameters */ sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name); ERREXIT(methods, tracemsg); /* jopen_backing_store will fail anyway */ return FALSE; } info->handle.file_handle = handle; info->read_backing_store = read_file_store; info->write_backing_store = write_file_store; info->close_backing_store = close_file_store; /* hack to get around TRACEMS' inability to handle string parameters */ sprintf(tracemsg, "Opened DOS file %d %s", handle, info->temp_name); TRACEMS(methods, 1, tracemsg); return TRUE; /* succeeded */ } /* * Access methods for extended memory. */ #if XMS_SUPPORTED static XMSDRIVER xms_driver; /* saved address of XMS driver */ typedef union { /* either long offset or real-mode pointer */ long offset; void far * ptr; } XMSPTR; typedef struct { /* XMS move specification structure */ long length; XMSH src_handle; XMSPTR src; XMSH dst_handle; XMSPTR dst; } XMSspec; #define ODD(X) (((X) & 1L) != 0) METHODDEF void read_xms_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { XMScontext ctx; XMSspec spec; char endbuffer[2]; /* The XMS driver can't cope with an odd length, so handle the last byte * specially if byte_count is odd. We don't expect this to be common. */ spec.length = byte_count & (~ 1L); spec.src_handle = info->handle.xms_handle; spec.src.offset = file_offset; spec.dst_handle = 0; spec.dst.ptr = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) ERREXIT(methods, "read from extended memory failed"); if (ODD(byte_count)) { read_xms_store(info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0]; } } METHODDEF void write_xms_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { XMScontext ctx; XMSspec spec; char endbuffer[2]; /* The XMS driver can't cope with an odd length, so handle the last byte * specially if byte_count is odd. We don't expect this to be common. */ spec.length = byte_count & (~ 1L); spec.src_handle = 0; spec.src.ptr = buffer_address; spec.dst_handle = info->handle.xms_handle; spec.dst.offset = file_offset; ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) ERREXIT(methods, "write to extended memory failed"); if (ODD(byte_count)) { read_xms_store(info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L]; write_xms_store(info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); } } METHODDEF void close_xms_store (backing_store_ptr info) { XMScontext ctx; ctx.dx = info->handle.xms_handle; ctx.ax = 0x0a00; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); TRACEMS1(methods, 1, "Freed XMS handle %u", info->handle.xms_handle); /* we ignore any error return from the driver */ } LOCAL boolean open_xms_store (backing_store_ptr info, long total_bytes_needed) { XMScontext ctx; /* Get address of XMS driver */ jxms_getdriver((XMSDRIVER far *) & xms_driver); if (xms_driver == NULL) return FALSE; /* no driver to be had */ /* Get version number, must be >= 2.00 */ ctx.ax = 0x0000; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax < (unsigned short) 0x0200) return FALSE; /* Try to get space (expressed in kilobytes) */ ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10); ctx.ax = 0x0900; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) return FALSE; /* Succeeded, save the handle and away we go */ info->handle.xms_handle = ctx.dx; info->read_backing_store = read_xms_store; info->write_backing_store = write_xms_store; info->close_backing_store = close_xms_store; TRACEMS1(methods, 1, "Obtained XMS handle %u", ctx.dx); return TRUE; /* succeeded */ } #endif /* XMS_SUPPORTED */ /* * Access methods for expanded memory. */ #if EMS_SUPPORTED /* The EMS move specification structure requires word and long fields aligned * at odd byte boundaries. Some compilers will align struct fields at even * byte boundaries. While it's usually possible to force byte alignment, * that causes an overall performance penalty and may pose problems in merging * JPEG into a larger application. Instead we accept some rather dirty code * here. Note this code would fail if the hardware did not allow odd-byte * word & long accesses, but all 80x86 CPUs do. */ typedef void far * EMSPTR; typedef union { /* EMS move specification structure */ long length; /* It's easy to access first 4 bytes */ char bytes[18]; /* Misaligned fields in here! */ } EMSspec; /* Macros for accessing misaligned fields */ #define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset]))) #define SRC_TYPE(spec) FIELD_AT(spec,4,char) #define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH) #define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short) #define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short) #define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR) #define DST_TYPE(spec) FIELD_AT(spec,11,char) #define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH) #define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short) #define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short) #define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR) #define EMSPAGESIZE 16384L /* gospel, see the EMS specs */ #define HIBYTE(W) (((W) >> 8) & 0xFF) #define LOBYTE(W) ((W) & 0xFF) METHODDEF void read_ems_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { EMScontext ctx; EMSspec spec; spec.length = byte_count; SRC_TYPE(spec) = 1; SRC_HANDLE(spec) = info->handle.ems_handle; SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); DST_TYPE(spec) = 0; DST_HANDLE(spec) = 0; DST_PTR(spec) = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) ERREXIT(methods, "read from expanded memory failed"); } METHODDEF void write_ems_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { EMScontext ctx; EMSspec spec; spec.length = byte_count; SRC_TYPE(spec) = 0; SRC_HANDLE(spec) = 0; SRC_PTR(spec) = buffer_address; DST_TYPE(spec) = 1; DST_HANDLE(spec) = info->handle.ems_handle; DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) ERREXIT(methods, "write to expanded memory failed"); } METHODDEF void close_ems_store (backing_store_ptr info) { EMScontext ctx; ctx.ax = 0x4500; ctx.dx = info->handle.ems_handle; jems_calldriver((EMScontext far *) & ctx); TRACEMS1(methods, 1, "Freed EMS handle %u", info->handle.ems_handle); /* we ignore any error return from the driver */ } LOCAL boolean open_ems_store (backing_store_ptr info, long total_bytes_needed) { EMScontext ctx; /* Is EMS driver there? */ if (! jems_available()) return FALSE; /* Get status, make sure EMS is OK */ ctx.ax = 0x4000; jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) return FALSE; /* Get version, must be >= 4.0 */ ctx.ax = 0x4600; jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40) return FALSE; /* Try to allocate requested space */ ctx.ax = 0x4300; ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE); jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) return FALSE; /* Succeeded, save the handle and away we go */ info->handle.ems_handle = ctx.dx; info->read_backing_store = read_ems_store; info->write_backing_store = write_ems_store; info->close_backing_store = close_ems_store; TRACEMS1(methods, 1, "Obtained EMS handle %u", ctx.dx); return TRUE; /* succeeded */ } #endif /* EMS_SUPPORTED */ /* * Initial opening of a backing-store object. */ GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { /* Try extended memory, then expanded memory, then regular file. */ #if XMS_SUPPORTED if (open_xms_store(info, total_bytes_needed)) return; #endif #if EMS_SUPPORTED if (open_ems_store(info, total_bytes_needed)) return; #endif if (open_file_store(info, total_bytes_needed)) return; ERREXIT(methods, "Failed to create temporary file"); } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = DEFAULT_MAX_MEM; total_used = 0; next_file_num = 0; } GLOBAL void jmem_term (void) { /* Microsoft C, at least in v6.00A, will not successfully reclaim freed * blocks of size > 32Kbytes unless we give it a kick in the rear, like so: */ #ifdef NEED_FHEAPMIN _fheapmin(); #endif } fset; spec.dst_handle = 0; spec.dst.ptr = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_callxloadimage.4.1/jpeg/jmemdos.h 644 221 144 13076 5236325073 11326 /* * jmemdos.h (jmemsys.h) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file defines the interface between the system-independent * and system-dependent portions of the JPEG memory manager. (The system- * independent portion is jmemmgr.c; there are several different versions * of the system-dependent portion, and of this file for that matter.) * * This version is suitable for MS-DOS (80x86) implementations. */ /* * These two functions are used to allocate and release small chunks of * memory (typically the total amount requested through jget_small is * no more than 20Kb or so). Behavior should be the same as for the * standard library functions malloc and free; in particular, jget_small * returns NULL on failure. On most systems, these ARE malloc and free. * On an 80x86 machine using small-data memory model, these manage near heap. */ EXTERN void * jget_small PP((size_t sizeofobject)); EXTERN void jfree_small PP((void * object)); /* * These two functions are used to allocate and release large chunks of * memory (up to the total free space designated by jmem_available). * The interface is the same as above, except that on an 80x86 machine, * far pointers are used. On other systems these ARE the same as above. */ #ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */ EXTERN void FAR * jget_large PP((size_t sizeofobject)); EXTERN void jfree_large PP((void FAR * object)); #else #define jget_large(sizeofobject) jget_small(sizeofobject) #define jfree_large(object) jfree_small(object) #endif /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may * be requested in a single call on jget_large (and jget_small for that * matter, but that case should never come into play). This macro is needed * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. * On machines with flat address spaces, any large constant may be used here. */ #define MAX_ALLOC_CHUNK 65440L /* leave room for malloc overhead */ /* * This routine computes the total space available for allocation by * jget_large. If more space than this is needed, backing store will be used. * NOTE: any memory already allocated must not be counted. * * There is a minimum space requirement, corresponding to the minimum * feasible buffer sizes; jmemmgr.c will request that much space even if * jmem_available returns zero. The maximum space needed, enough to hold * all working storage in memory, is also passed in case it is useful. * * It is OK for jmem_available to underestimate the space available (that'll * just lead to more backing-store access than is really necessary). * However, an overestimate will lead to failure. Hence it's wise to subtract * a slop factor from the true available space, especially if jget_small space * comes from the same pool. 5% should be enough. * * On machines with lots of virtual memory, any large constant may be returned. * Conversely, zero may be returned to always use the minimum amount of memory. */ EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed)); /* * This structure holds whatever state is needed to access a single * backing-store object. The read/write/close method pointers are called * by jmemmgr.c to manipulate the backing-store object; all other fields * are private to the system-dependent backing store routines. */ #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ typedef unsigned short XMSH; /* type of extended-memory handles */ typedef unsigned short EMSH; /* type of expanded-memory handles */ typedef union { short file_handle; /* DOS file handle if it's a temp file */ XMSH xms_handle; /* handle if it's a chunk of XMS */ EMSH ems_handle; /* handle if it's a chunk of EMS */ } handle_union; typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ METHOD(void, read_backing_store, (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); METHOD(void, write_backing_store, (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); METHOD(void, close_backing_store, (backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ /* For the MS-DOS environment, we need: */ handle_union handle; /* reference to backing-store storage object */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ } backing_store_info; /* * Initial opening of a backing-store object. This must fill in the * read/write/close pointers in the object. The read/write routines * may take an error exit if the specified maximum file size is exceeded. * (If jmem_available always returns a large value, this routine can just * take an error exit.) */ EXTERN void jopen_backing_store PP((backing_store_ptr info, long total_bytes_needed)); /* * These routines take care of any system-dependent initialization and * cleanup required. The system methods struct address should be saved * by jmem_init in case an error exit must be taken. jmem_term may assume * that all requested memory has been freed and that all opened backing- * store objects have been closed. * NB: jmem_term may be called more than once, and must behave reasonably * if that happens. */ EXTERN void jmem_init PP((external_methods_ptr emethods)); EXTERN void jmem_term PP((void)); 0) return FALSE; /* Try to allocate requested space */ ctx.ax = 0x4300; ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE); jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) return FALSE; /* Succeeded, save the handle and away we go */ info->handle.ems_handle = ctx.dx; info->read_backing_store = read_ems_store; info->write_backing_store = write_ems_store; info->close_bacxloadimage.4.1/jpeg/jmemdosa.asm 644 221 144 20172 5160260365 12011 ; ; jmemdosa.asm ; ; Copyright (C) 1992, Thomas G. Lane. ; This file is part of the Independent JPEG Group's software. ; For conditions of distribution and use, see the accompanying README file. ; ; This file contains low-level interface routines to support the MS-DOS ; backing store manager (jmemdos.c). Routines are provided to access disk ; files through direct DOS calls, and to access XMS and EMS drivers. ; ; This file should assemble with Microsoft's MASM or any compatible ; assembler (including Borland's Turbo Assembler). If you haven't got ; a compatible assembler, better fall back to jmemansi.c or jmemname.c. ; ; To minimize dependence on the C compiler's register usage conventions, ; we save and restore all 8086 registers, even though most compilers only ; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return ; values, which everybody returns in AX. ; ; Based on code contributed by Ge' Weijers. ; JMEMDOSA_TXT segment byte public 'CODE' assume cs:JMEMDOSA_TXT public _jdos_open public _jdos_close public _jdos_seek public _jdos_read public _jdos_write public _jxms_getdriver public _jxms_calldriver public _jems_available public _jems_calldriver ; ; short far jdos_open (short far * handle, char far * filename) ; ; Create and open a temporary file ; _jdos_open proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov cx,0 ; normal file attributes lds dx,dword ptr [bp+10] ; get filename pointer mov ah,3ch ; create file int 21h jc open_err ; if failed, return error code lds bx,dword ptr [bp+6] ; get handle pointer mov word ptr [bx],ax ; save the handle xor ax,ax ; return zero for OK open_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_open endp ; ; short far jdos_close (short handle) ; ; Close the file handle ; _jdos_close proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle mov ah,3eh ; close file int 21h jc close_err ; if failed, return error code xor ax,ax ; return zero for OK close_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_close endp ; ; short far jdos_seek (short handle, long offset) ; ; Set file position ; _jdos_seek proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle mov dx,word ptr [bp+8] ; LS offset mov cx,word ptr [bp+10] ; MS offset mov ax,4200h ; absolute seek int 21h jc seek_err ; if failed, return error code xor ax,ax ; return zero for OK seek_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_seek endp ; ; short far jdos_read (short handle, void far * buffer, unsigned short count) ; ; Read from file ; _jdos_read proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,3fh ; read file int 21h jc read_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes were read je read_ok mov ax,1 ; else return 1 for not OK jmp short read_err read_ok: xor ax,ax ; return zero for OK read_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_read endp ; ; short far jdos_write (short handle, void far * buffer, unsigned short count) ; ; Write to file ; _jdos_write proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,40h ; write file int 21h jc write_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes written je write_ok mov ax,1 ; else return 1 for not OK jmp short write_err write_ok: xor ax,ax ; return zero for OK write_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_write endp ; ; void far jxms_getdriver (XMSDRIVER far *) ; ; Get the address of the XMS driver, or NULL if not available ; _jxms_getdriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov ax,4300h ; call multiplex interrupt with int 2fh ; a magic cookie, hex 4300 cmp al,80h ; AL should contain hex 80 je xmsavail xor dx,dx ; no XMS driver available xor ax,ax ; return a nil pointer jmp short xmsavail_done xmsavail: mov ax,4310h ; fetch driver address with int 2fh ; another magic cookie mov dx,es ; copy address to dx:ax mov ax,bx xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value mov word ptr es:[bx],ax mov word ptr es:[bx+2],dx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jxms_getdriver endp ; ; void far jxms_calldriver (XMSDRIVER, XMScontext far *) ; ; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers. ; These are loaded, the XMS call is performed, and the new values of the ; AX,DX,BX registers are written back to the context structure. ; _jxms_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+10] ; get XMScontext pointer mov ax,word ptr es:[bx] ; load registers mov dx,word ptr es:[bx+2] mov si,word ptr es:[bx+6] mov ds,word ptr es:[bx+8] mov bx,word ptr es:[bx+4] call dword ptr [bp+6] ; call the driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+10] ; get XMScontext pointer mov word ptr es:[bx],ax ; put back ax,dx,bx mov word ptr es:[bx+2],dx mov word ptr es:[bx+4],cx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jxms_calldriver endp ; ; short far jems_available (void) ; ; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs) ; _jems_available proc far push si ; save all registers for safety push di push bx push cx push dx push es push ds mov ax,3567h ; get interrupt vector 67h int 21h push cs pop ds mov di,000ah ; check offs 10 in returned seg lea si,ASCII_device_name ; against literal string mov cx,8 cld repe cmpsb jne no_ems mov ax,1 ; match, it's there jmp short avail_done no_ems: xor ax,ax ; it's not there avail_done: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si ret ASCII_device_name db "EMMXXXX0" _jems_available endp ; ; void far jems_calldriver (EMScontext far *) ; ; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. ; These are loaded, the EMS trap is performed, and the new values of the ; AX,DX,BX registers are written back to the context structure. ; _jems_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+6] ; get EMScontext pointer mov ax,word ptr es:[bx] ; load registers mov dx,word ptr es:[bx+2] mov si,word ptr es:[bx+6] mov ds,word ptr es:[bx+8] mov bx,word ptr es:[bx+4] int 67h ; call the EMS driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+6] ; get EMScontext pointer mov word ptr es:[bx],ax ; put back ax,dx,bx mov word ptr es:[bx+2],dx mov word ptr es:[bx+4],cx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jems_calldriver endp JMEMDOSA_TXT ends end at jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = DEFAULT_MAX_MEM; total_used = 0; next_file_num = 0; } GLOBAL void jmem_term (void) { /* Microsoft C, at least in v6.00A, will not successfully reclaim freed * blocks of sizexloadimage.4.1/jpeg/jmemmgr.c 644 221 144 111552 5314164324 11334 /* * jmemmgr.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides the standard system-independent memory management * routines. This code is usable across a wide variety of machines; most * of the system dependencies have been isolated in a separate file. * The major functions provided here are: * * bookkeeping to allow all allocated memory to be freed upon exit; * * policy decisions about how to divide available memory among the * various large arrays; * * control logic for swapping virtual arrays between main memory and * backing storage. * The separate system-dependent file provides the actual backing-storage * access code, and it contains the policy decision about how much total * main memory to use. * This file is system-dependent in the sense that some of its functions * are unnecessary in some systems. For example, if there is enough virtual * memory so that backing storage will never be used, much of the big-array * control logic could be removed. (Of course, if you have that much memory * then you shouldn't care about a little bit of unused code...) * * These routines are invoked via the methods alloc_small, free_small, * alloc_medium, free_medium, alloc_small_sarray, free_small_sarray, * alloc_small_barray, free_small_barray, request_big_sarray, * request_big_barray, alloc_big_arrays, access_big_sarray, access_big_barray, * free_big_sarray, free_big_barray, and free_all. */ #define AM_MEMORY_MANAGER /* we define big_Xarray_control structs */ #include "jinclude.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef NO_GETENV #ifdef INCLUDES_ARE_ANSI #include /* to declare getenv() */ #else extern char * getenv PP((const char * name)); #endif #endif /* * On many systems it is not necessary to distinguish alloc_small from * alloc_medium; the main case where they must be distinguished is when * FAR pointers are distinct from regular pointers. However, you might * want to keep them separate if you have different system-dependent logic * for small and large memory requests (i.e., jget_small and jget_large * do different things). */ #ifdef NEED_FAR_POINTERS #define NEED_ALLOC_MEDIUM /* flags alloc_medium really exists */ #endif /* * Many machines require storage alignment: longs must start on 4-byte * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() * always returns pointers that are multiples of the worst-case alignment * requirement, and we had better do so too. This means the headers that * we tack onto allocated structures had better have length a multiple of * the alignment requirement. * There isn't any really portable way to determine the worst-case alignment * requirement. In this code we assume that the alignment requirement is * multiples of sizeof(align_type). Here we define align_type as double; * with this definition, the code will run on all machines known to me. * If your machine has lesser alignment needs, you can save a few bytes * by making align_type smaller. */ typedef double align_type; /* * Some important notes: * The allocation routines provided here must never return NULL. * They should exit to error_exit if unsuccessful. * * It's not a good idea to try to merge the sarray and barray routines, * even though they are textually almost the same, because samples are * usually stored as bytes while coefficients are shorts. Thus, in machines * where byte pointers have a different representation from word pointers, * the resulting machine code could not be the same. */ static external_methods_ptr methods; /* saved for access to error_exit */ #ifdef MEM_STATS /* optional extra stuff for statistics */ /* These macros are the assumed overhead per block for malloc(). * They don't have to be accurate, but the printed statistics will be * off a little bit if they are not. */ #define MALLOC_OVERHEAD (SIZEOF(void *)) /* overhead for jget_small() */ #define MALLOC_FAR_OVERHEAD (SIZEOF(void FAR *)) /* for jget_large() */ static long total_num_small = 0; /* total # of small objects alloced */ static long total_bytes_small = 0; /* total bytes requested */ static long cur_num_small = 0; /* # currently alloced */ static long max_num_small = 0; /* max simultaneously alloced */ #ifdef NEED_ALLOC_MEDIUM static long total_num_medium = 0; /* total # of medium objects alloced */ static long total_bytes_medium = 0; /* total bytes requested */ static long cur_num_medium = 0; /* # currently alloced */ static long max_num_medium = 0; /* max simultaneously alloced */ #endif static long total_num_sarray = 0; /* total # of sarray objects alloced */ static long total_bytes_sarray = 0; /* total bytes requested */ static long cur_num_sarray = 0; /* # currently alloced */ static long max_num_sarray = 0; /* max simultaneously alloced */ static long total_num_barray = 0; /* total # of barray objects alloced */ static long total_bytes_barray = 0; /* total bytes requested */ static long cur_num_barray = 0; /* # currently alloced */ static long max_num_barray = 0; /* max simultaneously alloced */ LOCAL void print_mem_stats (void) { /* since this is only a debugging stub, we can cheat a little on the * trace message mechanism... helpful 'cuz trace_message can't handle longs. */ fprintf(stderr, "total_num_small = %ld\n", total_num_small); fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small); if (cur_num_small) fprintf(stderr, "cur_num_small = %ld\n", cur_num_small); fprintf(stderr, "max_num_small = %ld\n", max_num_small); #ifdef NEED_ALLOC_MEDIUM fprintf(stderr, "total_num_medium = %ld\n", total_num_medium); fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium); if (cur_num_medium) fprintf(stderr, "cur_num_medium = %ld\n", cur_num_medium); fprintf(stderr, "max_num_medium = %ld\n", max_num_medium); #endif fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray); fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray); if (cur_num_sarray) fprintf(stderr, "cur_num_sarray = %ld\n", cur_num_sarray); fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray); fprintf(stderr, "total_num_barray = %ld\n", total_num_barray); fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray); if (cur_num_barray) fprintf(stderr, "cur_num_barray = %ld\n", cur_num_barray); fprintf(stderr, "max_num_barray = %ld\n", max_num_barray); } #endif /* MEM_STATS */ LOCAL void out_of_memory (int which) /* Report an out-of-memory error and stop execution */ /* If we compiled MEM_STATS support, report alloc requests before dying */ { #ifdef MEM_STATS if (methods->trace_level <= 0) /* don't do it if free_all() will */ print_mem_stats(); /* print optional memory usage statistics */ #endif ERREXIT1(methods, "Insufficient memory (case %d)", which); } /* * Management of "small" objects. * These are all-in-memory, and are in near-heap space on an 80x86. */ typedef union small_struct * small_ptr; typedef union small_struct { small_ptr next; /* next in list of allocated objects */ align_type dummy; /* ensures alignment of following storage */ } small_hdr; static small_ptr small_list; /* head of list */ METHODDEF void * alloc_small (size_t sizeofobject) /* Allocate a "small" object */ { small_ptr result; sizeofobject += SIZEOF(small_hdr); /* add space for header */ #ifdef MEM_STATS total_num_small++; total_bytes_small += sizeofobject + MALLOC_OVERHEAD; cur_num_small++; if (cur_num_small > max_num_small) max_num_small = cur_num_small; #endif result = (small_ptr) jget_small(sizeofobject); if (result == NULL) out_of_memory(1); result->next = small_list; small_list = result; result++; /* advance past header */ return (void *) result; } METHODDEF void free_small (void *ptr) /* Free a "small" object */ { small_ptr hdr; small_ptr * llink; hdr = (small_ptr) ptr; hdr--; /* point back to header */ /* Remove item from list -- linear search is fast enough */ llink = &small_list; while (*llink != hdr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_small request"); llink = &( (*llink)->next ); } *llink = hdr->next; jfree_small((void *) hdr); #ifdef MEM_STATS cur_num_small--; #endif } /* * Management of "medium-size" objects. * These are just like small objects except they are in the FAR heap. */ #ifdef NEED_ALLOC_MEDIUM typedef union medium_struct FAR * medium_ptr; typedef union medium_struct { medium_ptr next; /* next in list of allocated objects */ align_type dummy; /* ensures alignment of following storage */ } medium_hdr; static medium_ptr medium_list; /* head of list */ METHODDEF void FAR * alloc_medium (size_t sizeofobject) /* Allocate a "medium-size" object */ { medium_ptr result; sizeofobject += SIZEOF(medium_hdr); /* add space for header */ #ifdef MEM_STATS total_num_medium++; total_bytes_medium += sizeofobject + MALLOC_FAR_OVERHEAD; cur_num_medium++; if (cur_num_medium > max_num_medium) max_num_medium = cur_num_medium; #endif result = (medium_ptr) jget_large(sizeofobject); if (result == NULL) out_of_memory(2); result->next = medium_list; medium_list = result; result++; /* advance past header */ return (void FAR *) result; } METHODDEF void free_medium (void FAR *ptr) /* Free a "medium-size" object */ { medium_ptr hdr; medium_ptr FAR * llink; hdr = (medium_ptr) ptr; hdr--; /* point back to header */ /* Remove item from list -- linear search is fast enough */ llink = (medium_ptr FAR *) &medium_list; while (*llink != hdr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_medium request"); llink = &( (*llink)->next ); } *llink = hdr->next; jfree_large((void FAR *) hdr); #ifdef MEM_STATS cur_num_medium--; #endif } #endif /* NEED_ALLOC_MEDIUM */ /* * Management of "small" (all-in-memory) 2-D sample arrays. * The pointers are in near heap, the samples themselves in FAR heap. * The header structure is adjacent to the row pointers. * To minimize allocation overhead and to allow I/O of large contiguous * blocks, we allocate the sample rows in groups of as many rows as possible * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. * Note that the big-array control routines, later in this file, know about * this chunking of rows ... and also how to get the rowsperchunk value! */ typedef struct small_sarray_struct * small_sarray_ptr; typedef struct small_sarray_struct { small_sarray_ptr next; /* next in list of allocated sarrays */ long numrows; /* # of rows in this array */ long rowsperchunk; /* max # of rows per allocation chunk */ JSAMPROW dummy; /* ensures alignment of following storage */ } small_sarray_hdr; static small_sarray_ptr small_sarray_list; /* head of list */ METHODDEF JSAMPARRAY alloc_small_sarray (long samplesperrow, long numrows) /* Allocate a "small" (all-in-memory) 2-D sample array */ { small_sarray_ptr hdr; JSAMPARRAY result; JSAMPROW workspace; long rowsperchunk, currow, i; #ifdef MEM_STATS total_num_sarray++; cur_num_sarray++; if (cur_num_sarray > max_num_sarray) max_num_sarray = cur_num_sarray; #endif /* Calculate max # of rows allowed in one allocation chunk */ rowsperchunk = MAX_ALLOC_CHUNK / (samplesperrow * SIZEOF(JSAMPLE)); if (rowsperchunk <= 0) ERREXIT(methods, "Image too wide for this implementation"); /* Get space for header and row pointers; this is always "near" on 80x86 */ hdr = (small_sarray_ptr) alloc_small((size_t) (numrows * SIZEOF(JSAMPROW) + SIZEOF(small_sarray_hdr))); result = (JSAMPARRAY) (hdr+1); /* advance past header */ /* Insert into list now so free_all does right thing if I fail */ /* after allocating only some of the rows... */ hdr->next = small_sarray_list; hdr->numrows = 0; hdr->rowsperchunk = rowsperchunk; small_sarray_list = hdr; /* Get the rows themselves; on 80x86 these are "far" */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); #ifdef MEM_STATS total_bytes_sarray += rowsperchunk * samplesperrow * SIZEOF(JSAMPLE) + MALLOC_FAR_OVERHEAD; #endif workspace = (JSAMPROW) jget_large((size_t) (rowsperchunk * samplesperrow * SIZEOF(JSAMPLE))); if (workspace == NULL) out_of_memory(3); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += samplesperrow; } hdr->numrows = currow; } return result; } METHODDEF void free_small_sarray (JSAMPARRAY ptr) /* Free a "small" (all-in-memory) 2-D sample array */ { small_sarray_ptr hdr; small_sarray_ptr * llink; long i; hdr = (small_sarray_ptr) ptr; hdr--; /* point back to header */ /* Remove item from list -- linear search is fast enough */ llink = &small_sarray_list; while (*llink != hdr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_small_sarray request"); llink = &( (*llink)->next ); } *llink = hdr->next; /* Free the rows themselves; on 80x86 these are "far" */ /* Note we only free the row-group headers! */ for (i = 0; i < hdr->numrows; i += hdr->rowsperchunk) { jfree_large((void FAR *) ptr[i]); } /* Free header and row pointers */ free_small((void *) hdr); #ifdef MEM_STATS cur_num_sarray--; #endif } /* * Management of "small" (all-in-memory) 2-D coefficient-block arrays. * This is essentially the same as the code for sample arrays, above. */ typedef struct small_barray_struct * small_barray_ptr; typedef struct small_barray_struct { small_barray_ptr next; /* next in list of allocated barrays */ long numrows; /* # of rows in this array */ long rowsperchunk; /* max # of rows per allocation chunk */ JBLOCKROW dummy; /* ensures alignment of following storage */ } small_barray_hdr; static small_barray_ptr small_barray_list; /* head of list */ METHODDEF JBLOCKARRAY alloc_small_barray (long blocksperrow, long numrows) /* Allocate a "small" (all-in-memory) 2-D coefficient-block array */ { small_barray_ptr hdr; JBLOCKARRAY result; JBLOCKROW workspace; long rowsperchunk, currow, i; #ifdef MEM_STATS total_num_barray++; cur_num_barray++; if (cur_num_barray > max_num_barray) max_num_barray = cur_num_barray; #endif /* Calculate max # of rows allowed in one allocation chunk */ rowsperchunk = MAX_ALLOC_CHUNK / (blocksperrow * SIZEOF(JBLOCK)); if (rowsperchunk <= 0) ERREXIT(methods, "Image too wide for this implementation"); /* Get space for header and row pointers; this is always "near" on 80x86 */ hdr = (small_barray_ptr) alloc_small((size_t) (numrows * SIZEOF(JBLOCKROW) + SIZEOF(small_barray_hdr))); result = (JBLOCKARRAY) (hdr+1); /* advance past header */ /* Insert into list now so free_all does right thing if I fail */ /* after allocating only some of the rows... */ hdr->next = small_barray_list; hdr->numrows = 0; hdr->rowsperchunk = rowsperchunk; small_barray_list = hdr; /* Get the rows themselves; on 80x86 these are "far" */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); #ifdef MEM_STATS total_bytes_barray += rowsperchunk * blocksperrow * SIZEOF(JBLOCK) + MALLOC_FAR_OVERHEAD; #endif workspace = (JBLOCKROW) jget_large((size_t) (rowsperchunk * blocksperrow * SIZEOF(JBLOCK))); if (workspace == NULL) out_of_memory(4); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += blocksperrow; } hdr->numrows = currow; } return result; } METHODDEF void free_small_barray (JBLOCKARRAY ptr) /* Free a "small" (all-in-memory) 2-D coefficient-block array */ { small_barray_ptr hdr; small_barray_ptr * llink; long i; hdr = (small_barray_ptr) ptr; hdr--; /* point back to header */ /* Remove item from list -- linear search is fast enough */ llink = &small_barray_list; while (*llink != hdr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_small_barray request"); llink = &( (*llink)->next ); } *llink = hdr->next; /* Free the rows themselves; on 80x86 these are "far" */ /* Note we only free the row-group headers! */ for (i = 0; i < hdr->numrows; i += hdr->rowsperchunk) { jfree_large((void FAR *) ptr[i]); } /* Free header and row pointers */ free_small((void *) hdr); #ifdef MEM_STATS cur_num_barray--; #endif } /* * About "big" array management: * * To allow machines with limited memory to handle large images, * all processing in the JPEG system is done a few pixel or block rows * at a time. The above "small" array routines are only used to allocate * strip buffers (as wide as the image, but just a few rows high). * In some cases multiple passes must be made over the data. In these * cases the "big" array routines are used. The array is still accessed * a strip at a time, but the memory manager must save the whole array * for repeated accesses. The intended implementation is that there is * a strip buffer in memory (as high as is possible given the desired memory * limit), plus a backing file that holds the rest of the array. * * The request_big_array routines are told the total size of the image (in case * it is useful to know the total file size that will be needed). They are * also given the unit height, which is the number of rows that will be * accessed at once; the in-memory buffer should be made a multiple of * this height for best efficiency. * * The request routines create control blocks (and may open backing files), * but they don't create the in-memory buffers. This is postponed until * alloc_big_arrays is called. At that time the total amount of space needed * is known (approximately, anyway), so free memory can be divided up fairly. * * The access_big_array routines are responsible for making a specific strip * area accessible (after reading or writing the backing file, if necessary). * Note that the access routines are told whether the caller intends to modify * the accessed strip; during a read-only pass this saves having to rewrite * data to disk. * * The typical access pattern is one top-to-bottom pass to write the data, * followed by one or more read-only top-to-bottom passes. However, other * access patterns may occur while reading. For example, translation of image * formats that use bottom-to-top scan order will require bottom-to-top read * passes. The memory manager need not support multiple write passes nor * funny write orders (meaning that rearranging rows must be handled while * reading data out of the big array, not while putting it in). * * In current usage, the access requests are always for nonoverlapping strips; * that is, successive access start_row numbers always differ by exactly the * unitheight. This allows fairly simple buffer dump/reload logic if the * in-memory buffer is made a multiple of the unitheight. It would be * possible to keep downsampled rather than fullsize data in the "big" arrays, * thus reducing temp file size, if we supported overlapping strip access * (access requests differing by less than the unitheight). At the moment * I don't believe this is worth the extra complexity. */ /* The control blocks for virtual arrays. * System-dependent info for the associated backing store is hidden inside * the backing_store_info struct. */ struct big_sarray_control { long rows_in_array; /* total virtual array height */ long samplesperrow; /* width of array (and of memory buffer) */ long unitheight; /* # of rows accessed by access_big_sarray() */ JSAMPARRAY mem_buffer; /* the in-memory buffer */ long rows_in_mem; /* height of memory buffer */ long rowsperchunk; /* allocation chunk size in mem_buffer */ long cur_start_row; /* first logical row # in the buffer */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ big_sarray_ptr next; /* link to next big sarray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; static big_sarray_ptr big_sarray_list; /* head of list */ struct big_barray_control { long rows_in_array; /* total virtual array height */ long blocksperrow; /* width of array (and of memory buffer) */ long unitheight; /* # of rows accessed by access_big_barray() */ JBLOCKARRAY mem_buffer; /* the in-memory buffer */ long rows_in_mem; /* height of memory buffer */ long rowsperchunk; /* allocation chunk size in mem_buffer */ long cur_start_row; /* first logical row # in the buffer */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ big_barray_ptr next; /* link to next big barray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; static big_barray_ptr big_barray_list; /* head of list */ METHODDEF big_sarray_ptr request_big_sarray (long samplesperrow, long numrows, long unitheight) /* Request a "big" (virtual-memory) 2-D sample array */ { big_sarray_ptr result; /* get control block */ result = (big_sarray_ptr) alloc_small(SIZEOF(struct big_sarray_control)); result->rows_in_array = numrows; result->samplesperrow = samplesperrow; result->unitheight = unitheight; result->mem_buffer = NULL; /* marks array not yet realized */ result->b_s_open = FALSE; /* no associated backing-store object */ result->next = big_sarray_list; /* add to list of big arrays */ big_sarray_list = result; return result; } METHODDEF big_barray_ptr request_big_barray (long blocksperrow, long numrows, long unitheight) /* Request a "big" (virtual-memory) 2-D coefficient-block array */ { big_barray_ptr result; /* get control block */ result = (big_barray_ptr) alloc_small(SIZEOF(struct big_barray_control)); result->rows_in_array = numrows; result->blocksperrow = blocksperrow; result->unitheight = unitheight; result->mem_buffer = NULL; /* marks array not yet realized */ result->b_s_open = FALSE; /* no associated backing-store object */ result->next = big_barray_list; /* add to list of big arrays */ big_barray_list = result; return result; } METHODDEF void alloc_big_arrays (long extra_small_samples, long extra_small_blocks, long extra_medium_space) /* Allocate the in-memory buffers for any unrealized "big" arrays */ /* 'extra' values are upper bounds for total future small-array requests */ /* and far-heap requests */ { long total_extra_space = extra_small_samples * SIZEOF(JSAMPLE) + extra_small_blocks * SIZEOF(JBLOCK) + extra_medium_space; long space_per_unitheight, maximum_space, avail_mem; long unitheights, max_unitheights; big_sarray_ptr sptr; big_barray_ptr bptr; /* Compute the minimum space needed (unitheight rows in each buffer) * and the maximum space needed (full image height in each buffer). * These may be of use to the system-dependent jmem_available routine. */ space_per_unitheight = 0; maximum_space = total_extra_space; for (sptr = big_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ space_per_unitheight += sptr->unitheight * sptr->samplesperrow * SIZEOF(JSAMPLE); maximum_space += sptr->rows_in_array * sptr->samplesperrow * SIZEOF(JSAMPLE); } } for (bptr = big_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ space_per_unitheight += bptr->unitheight * bptr->blocksperrow * SIZEOF(JBLOCK); maximum_space += bptr->rows_in_array * bptr->blocksperrow * SIZEOF(JBLOCK); } } if (space_per_unitheight <= 0) return; /* no unrealized arrays, no work */ /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jmem_available(space_per_unitheight + total_extra_space, maximum_space); /* If the maximum space needed is available, make all the buffers full * height; otherwise parcel it out with the same number of unitheights * in each buffer. */ if (avail_mem >= maximum_space) max_unitheights = 1000000000L; else { max_unitheights = (avail_mem - total_extra_space) / space_per_unitheight; /* If there doesn't seem to be enough space, try to get the minimum * anyway. This allows a "stub" implementation of jmem_available(). */ if (max_unitheights <= 0) max_unitheights = 1; } /* Allocate the in-memory buffers and initialize backing store as needed. */ for (sptr = big_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ unitheights = (sptr->rows_in_array + sptr->unitheight - 1L) / sptr->unitheight; if (unitheights <= max_unitheights) { /* This buffer fits in memory */ sptr->rows_in_mem = sptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ sptr->rows_in_mem = max_unitheights * sptr->unitheight; jopen_backing_store(& sptr->b_s_info, (long) (sptr->rows_in_array * sptr->samplesperrow * SIZEOF(JSAMPLE))); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_small_sarray(sptr->samplesperrow, sptr->rows_in_mem); /* Reach into the small_sarray header and get the rowsperchunk field. * Yes, I know, this is horrible coding practice. */ sptr->rowsperchunk = ((small_sarray_ptr) sptr->mem_buffer)[-1].rowsperchunk; sptr->cur_start_row = 0; sptr->dirty = FALSE; } } for (bptr = big_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ unitheights = (bptr->rows_in_array + bptr->unitheight - 1L) / bptr->unitheight; if (unitheights <= max_unitheights) { /* This buffer fits in memory */ bptr->rows_in_mem = bptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ bptr->rows_in_mem = max_unitheights * bptr->unitheight; jopen_backing_store(& bptr->b_s_info, (long) (bptr->rows_in_array * bptr->blocksperrow * SIZEOF(JBLOCK))); bptr->b_s_open = TRUE; } bptr->mem_buffer = alloc_small_barray(bptr->blocksperrow, bptr->rows_in_mem); /* Reach into the small_barray header and get the rowsperchunk field. */ bptr->rowsperchunk = ((small_barray_ptr) bptr->mem_buffer)[-1].rowsperchunk; bptr->cur_start_row = 0; bptr->dirty = FALSE; } } } LOCAL void do_sarray_io (big_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a "big" sample array */ { long bytesperrow, file_offset, byte_count, rows, i; bytesperrow = ptr->samplesperrow * SIZEOF(JSAMPLE); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); /* Transfer no more than fits in file */ rows = MIN(rows, ptr->rows_in_array - (ptr->cur_start_row + i)); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (& ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (& ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } LOCAL void do_barray_io (big_barray_ptr ptr, boolean writing) /* Do backing store read or write of a "big" coefficient-block array */ { long bytesperrow, file_offset, byte_count, rows, i; bytesperrow = ptr->blocksperrow * SIZEOF(JBLOCK); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); /* Transfer no more than fits in file */ rows = MIN(rows, ptr->rows_in_array - (ptr->cur_start_row + i)); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (& ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (& ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } METHODDEF JSAMPARRAY access_big_sarray (big_sarray_ptr ptr, long start_row, boolean writable) /* Access the part of a "big" sample array starting at start_row */ /* and extending for ptr->unitheight rows. writable is true if */ /* caller intends to modify the accessed area. */ { /* debugging check */ if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_array || ptr->mem_buffer == NULL) ERREXIT(methods, "Bogus access_big_sarray request"); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(methods, "Virtual array controller messed up"); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_sarray_io(ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target address is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { ptr->cur_start_row = start_row + ptr->unitheight - ptr->rows_in_mem; if (ptr->cur_start_row < 0) ptr->cur_start_row = 0; /* don't fall off front end of file */ } /* If reading, read in the selected part of the array. * If we are writing, we need not pre-read the selected portion, * since the access sequence constraints ensure it would be garbage. */ if (! writable) { do_sarray_io(ptr, FALSE); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF JBLOCKARRAY access_big_barray (big_barray_ptr ptr, long start_row, boolean writable) /* Access the part of a "big" coefficient-block array starting at start_row */ /* and extending for ptr->unitheight rows. writable is true if */ /* caller intends to modify the accessed area. */ { /* debugging check */ if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_array || ptr->mem_buffer == NULL) ERREXIT(methods, "Bogus access_big_barray request"); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(methods, "Virtual array controller messed up"); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_barray_io(ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target address is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { ptr->cur_start_row = start_row + ptr->unitheight - ptr->rows_in_mem; if (ptr->cur_start_row < 0) ptr->cur_start_row = 0; /* don't fall off front end of file */ } /* If reading, read in the selected part of the array. * If we are writing, we need not pre-read the selected portion, * since the access sequence constraints ensure it would be garbage. */ if (! writable) { do_barray_io(ptr, FALSE); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF void free_big_sarray (big_sarray_ptr ptr) /* Free a "big" (virtual-memory) 2-D sample array */ { big_sarray_ptr * llink; /* Remove item from list -- linear search is fast enough */ llink = &big_sarray_list; while (*llink != ptr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_big_sarray request"); llink = &( (*llink)->next ); } *llink = ptr->next; if (ptr->b_s_open) /* there may be no backing store */ (*ptr->b_s_info.close_backing_store) (& ptr->b_s_info); if (ptr->mem_buffer != NULL) /* just in case never realized */ free_small_sarray(ptr->mem_buffer); free_small((void *) ptr); /* free the control block too */ } METHODDEF void free_big_barray (big_barray_ptr ptr) /* Free a "big" (virtual-memory) 2-D coefficient-block array */ { big_barray_ptr * llink; /* Remove item from list -- linear search is fast enough */ llink = &big_barray_list; while (*llink != ptr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_big_barray request"); llink = &( (*llink)->next ); } *llink = ptr->next; if (ptr->b_s_open) /* there may be no backing store */ (*ptr->b_s_info.close_backing_store) (& ptr->b_s_info); if (ptr->mem_buffer != NULL) /* just in case never realized */ free_small_barray(ptr->mem_buffer); free_small((void *) ptr); /* free the control block too */ } /* * Cleanup: free anything that's been allocated since jselmemmgr(). */ METHODDEF void free_all (void) { /* First free any open "big" arrays -- these may release small arrays */ while (big_sarray_list != NULL) free_big_sarray(big_sarray_list); while (big_barray_list != NULL) free_big_barray(big_barray_list); /* Free any open small arrays -- these may release small objects */ /* +1's are because we must pass a pointer to the data, not the header */ while (small_sarray_list != NULL) free_small_sarray((JSAMPARRAY) (small_sarray_list + 1)); while (small_barray_list != NULL) free_small_barray((JBLOCKARRAY) (small_barray_list + 1)); /* Free any remaining small objects */ while (small_list != NULL) free_small((void *) (small_list + 1)); #ifdef NEED_ALLOC_MEDIUM while (medium_list != NULL) free_medium((void FAR *) (medium_list + 1)); #endif jmem_term(); /* system-dependent cleanup */ #ifdef MEM_STATS if (methods->trace_level > 0) print_mem_stats(); /* print optional memory usage statistics */ #endif } /* * The method selection routine for virtual memory systems. * The system-dependent setup routine should call this routine * to install the necessary method pointers in the supplied struct. */ GLOBAL void jselmemmgr (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->alloc_small = alloc_small; emethods->free_small = free_small; #ifdef NEED_ALLOC_MEDIUM emethods->alloc_medium = alloc_medium; emethods->free_medium = free_medium; #else emethods->alloc_medium = alloc_small; emethods->free_medium = free_small; #endif emethods->alloc_small_sarray = alloc_small_sarray; emethods->free_small_sarray = free_small_sarray; emethods->alloc_small_barray = alloc_small_barray; emethods->free_small_barray = free_small_barray; emethods->request_big_sarray = request_big_sarray; emethods->request_big_barray = request_big_barray; emethods->alloc_big_arrays = alloc_big_arrays; emethods->access_big_sarray = access_big_sarray; emethods->access_big_barray = access_big_barray; emethods->free_big_sarray = free_big_sarray; emethods->free_big_barray = free_big_barray; emethods->free_all = free_all; /* Initialize list headers to empty */ small_list = NULL; #ifdef NEED_ALLOC_MEDIUM medium_list = NULL; #endif small_sarray_list = NULL; small_barray_list = NULL; big_sarray_list = NULL; big_barray_list = NULL; jmem_init(emethods); /* system-dependent initialization */ /* Check for an environment variable JPEGMEM; if found, override the * default max_memory setting from jmem_init. Note that a command line * -m argument may again override this value. * If your system doesn't support getenv(), define NO_GETENV to disable * this feature. */ #ifndef NO_GETENV { char * memenv; if ((memenv = getenv("JPEGMEM")) != NULL) { long lval; char ch = 'x'; if (sscanf(memenv, "%ld%c", &lval, &ch) > 0) { if (ch == 'm' || ch == 'M') lval *= 1000L; emethods->max_memory_to_use = lval * 1000L; } } } #endif } ; /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || start_row+ptr->unitheight > ptr->cur_stxloadimage.4.1/jpeg/jmemname.c 644 221 144 17143 5234070352 11446 /* * jmemname.c (jmemsys.c) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a generic implementation of the system-dependent * portion of the JPEG memory manager. This implementation assumes that * you must explicitly construct a name for each temp file. * Also, the problem of determining the amount of memory available * is shoved onto the user. */ #include "jinclude.h" #include "jmemsys.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare malloc(), free() */ #else extern void * malloc PP((size_t size)); extern void free PP((void *ptr)); #endif #ifndef SEEK_SET /* pre-ANSI systems may not define this; */ #define SEEK_SET 0 /* if not, assume 0 is correct */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define RW_BINARY "w+" #else #define READ_BINARY "rb" #define RW_BINARY "w+b" #endif static external_methods_ptr methods; /* saved for access to error_exit */ static long total_used; /* total memory requested so far */ /* * Selection of a file name for a temporary file. * This is system-dependent! * * The code as given is suitable for most Unix systems, and it is easily * modified for most non-Unix systems. Some notes: * 1. The temp file is created in the directory named by TEMP_DIRECTORY. * The default value is /usr/tmp, which is the conventional place for * creating large temp files on Unix. On other systems you'll probably * want to change the file location. You can do this by editing the * #define, or by defining TEMP_DIRECTORY in CFLAGS in the Makefile. * For example, you might say * CFLAGS= ... '-DTEMP_DIRECTORY="/tmp/"' * Note that double quotes are needed in the text of the macro. * With most make systems you have to put single quotes around the * -D construct to preserve the double quotes. * (Amiga SAS C has trouble with ":" and such in command-line options, * so we've put in a special case for the preferred Amiga temp directory.) * * 2. If you need to change the file name as well as its location, * you can override the TEMP_FILE_NAME macro. (Note that this is * actually a printf format string; it must contain %s and %d.) * Few people should need to do this. * * 3. mktemp() is used to ensure that multiple processes running * simultaneously won't select the same file names. If your system * doesn't have mktemp(), define NO_MKTEMP to do it the hard way. * * 4. You probably want to define NEED_SIGNAL_CATCHER so that jcmain/jdmain * will cause the temp files to be removed if you stop the program early. */ #ifndef TEMP_DIRECTORY /* so can override from Makefile */ #ifdef AMIGA #define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ #else #define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */ #endif #endif static int next_file_num; /* to distinguish among several temp files */ #ifdef NO_MKTEMP #ifndef TEMP_FILE_NAME /* so can override from Makefile */ #define TEMP_FILE_NAME "%sJPG%03d.TMP" #endif LOCAL void select_file_name (char * fname) { FILE * tfile; /* Keep generating file names till we find one that's not in use */ for (;;) { next_file_num++; /* advance counter */ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); if ((tfile = fopen(fname, READ_BINARY)) == NULL) break; fclose(tfile); /* oops, it's there; close tfile & try again */ } } #else /* ! NO_MKTEMP */ /* Note that mktemp() requires the initial filename to end in six X's */ #ifndef TEMP_FILE_NAME /* so can override from Makefile */ #define TEMP_FILE_NAME "%sJPG%dXXXXXX" #endif LOCAL void select_file_name (char * fname) { next_file_num++; /* advance counter */ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); mktemp(fname); /* make sure file name is unique */ /* mktemp replaces the trailing XXXXXX with a unique string of characters */ } #endif /* NO_MKTEMP */ /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jget_small (size_t sizeofobject) { total_used += sizeofobject; return (void *) malloc(sizeofobject); } GLOBAL void jfree_small (void * object) { free(object); } /* * We assume NEED_FAR_POINTERS is not defined and so the separate entry points * jget_large, jfree_large are not needed. */ /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ #endif GLOBAL long jmem_available (long min_bytes_needed, long max_bytes_needed) { return methods->max_memory_to_use - total_used; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jmem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ METHODDEF void read_backing_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(methods, "fseek failed on temporary file"); if (JFREAD(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(methods, "fread failed on temporary file"); } METHODDEF void write_backing_store (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(methods, "fseek failed on temporary file"); if (JFWRITE(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?"); } METHODDEF void close_backing_store (backing_store_ptr info) { fclose(info->temp_file); /* close the file */ unlink(info->temp_name); /* delete the file */ /* If your system doesn't have unlink(), use remove() instead. * remove() is the ANSI-standard name for this function, but if * your system was ANSI you'd be using jmemansi.c, right? */ } GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { char tracemsg[TEMP_NAME_LENGTH+40]; select_file_name(info->temp_name); if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) { /* hack to get around ERREXIT's inability to handle string parameters */ sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name); ERREXIT(methods, tracemsg); } info->read_backing_store = read_backing_store; info->write_backing_store = write_backing_store; info->close_backing_store = close_backing_store; /* hack to get around TRACEMS' inability to handle string parameters */ sprintf(tracemsg, "Using temp file %s", info->temp_name); TRACEMS(methods, 1, tracemsg); } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = DEFAULT_MAX_MEM; total_used = 0; next_file_num = 0; } GLOBAL void jmem_term (void) { /* no work */ } t mktemp() requires the initial filename to end in six X's */ #ifndef TEMP_FILE_NAME /* so can override from Makefile */ #define TEMP_FILE_NAME "%sJPG%dXXXXXX" #endif LOCAL void select_file_name (char * fname) { next_file_num++; /* advance counter */ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); mktemp(fname); /* make sure file name is unique */ /* mktemp replaces the trailing XXXxloadimage.4.1/jpeg/jmemnobs.c 644 221 144 4327 5153565204 11454 /* * jmemnobs.c (jmemsys.c) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a really simple implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that no backing-store files are needed: all required space * can be obtained from malloc(). * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. * Note that the max_memory_to_use option is ignored by this implementation. */ #include "jinclude.h" #include "jmemsys.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare malloc(), free() */ #else extern void * malloc PP((size_t size)); extern void free PP((void *ptr)); #endif static external_methods_ptr methods; /* saved for access to error_exit */ /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jget_small (size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jfree_small (void * object) { free(object); } /* * We assume NEED_FAR_POINTERS is not defined and so the separate entry points * jget_large, jfree_large are not needed. */ /* * This routine computes the total memory space available for allocation. * Here we always say, "we got all you want bud!" */ GLOBAL long jmem_available (long min_bytes_needed, long max_bytes_needed) { return max_bytes_needed; } /* * Backing store (temporary file) management. * This should never be called and we just error out. */ GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { ERREXIT(methods, "Backing store not supported"); } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = 0; } GLOBAL void jmem_term (void) { /* no work */ } e() is the ANSI-standard name for this function, but if * your system was ANSI you'd be using jmemansi.c, right? */ } GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { char tracemsg[TEMP_NAME_LENGTH+40]; select_file_name(info->temp_name); if ((info->texloadimage.4.1/jpeg/jmemsys.c 644 221 144 4327 5467536727 11351 /* * jmemnobs.c (jmemsys.c) * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a really simple implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that no backing-store files are needed: all required space * can be obtained from malloc(). * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. * Note that the max_memory_to_use option is ignored by this implementation. */ #include "jinclude.h" #include "jmemsys.h" #ifdef INCLUDES_ARE_ANSI #include /* to declare malloc(), free() */ #else extern void * malloc PP((size_t size)); extern void free PP((void *ptr)); #endif static external_methods_ptr methods; /* saved for access to error_exit */ /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jget_small (size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jfree_small (void * object) { free(object); } /* * We assume NEED_FAR_POINTERS is not defined and so the separate entry points * jget_large, jfree_large are not needed. */ /* * This routine computes the total memory space available for allocation. * Here we always say, "we got all you want bud!" */ GLOBAL long jmem_available (long min_bytes_needed, long max_bytes_needed) { return max_bytes_needed; } /* * Backing store (temporary file) management. * This should never be called and we just error out. */ GLOBAL void jopen_backing_store (backing_store_ptr info, long total_bytes_needed) { ERREXIT(methods, "Backing store not supported"); } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ emethods->max_memory_to_use = 0; } GLOBAL void jmem_term (void) { /* no work */ } ted"); } /* * These routines take care of any system-dependent initialization and * cleanup required. Keep in mind that jmem_term may be called more than * once. */ GLOBAL void jmem_init (external_methods_ptr emethods) { methods = emethods; /* save struct addr for error exit access */ xloadimage.4.1/jpeg/jmemsys.h 644 221 144 12431 5154443574 11357 /* * jmemsys.h * * Copyright (C) 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file defines the interface between the system-independent * and system-dependent portions of the JPEG memory manager. (The system- * independent portion is jmemmgr.c; there are several different versions * of the system-dependent portion, and of this file for that matter.) * * This is a "generic" skeleton that may need to be modified for particular * systems. It should be usable as-is on the majority of non-MSDOS machines. */ /* * These two functions are used to allocate and release small chunks of * memory (typically the total amount requested through jget_small is * no more than 20Kb or so). Behavior should be the same as for the * standard library functions malloc and free; in particular, jget_small * returns NULL on failure. On most systems, these ARE malloc and free. * On an 80x86 machine using small-data memory model, these manage near heap. */ EXTERN void * jget_small PP((size_t sizeofobject)); EXTERN void jfree_small PP((void * object)); /* * These two functions are used to allocate and release large chunks of * memory (up to the total free space designated by jmem_available). * The interface is the same as above, except that on an 80x86 machine, * far pointers are used. On other systems these ARE the same as above. */ #ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */ EXTERN void FAR * jget_large PP((size_t sizeofobject)); EXTERN void jfree_large PP((void FAR * object)); #else #define jget_large(sizeofobject) jget_small(sizeofobject) #define jfree_large(object) jfree_small(object) #endif /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may * be requested in a single call on jget_large (and jget_small for that * matter, but that case should never come into play). This macro is needed * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. * On machines with flat address spaces, any large constant may be used here. */ #define MAX_ALLOC_CHUNK 1000000000L /* * This routine computes the total space available for allocation by * jget_large. If more space than this is needed, backing store will be used. * NOTE: any memory already allocated must not be counted. * * There is a minimum space requirement, corresponding to the minimum * feasible buffer sizes; jmemmgr.c will request that much space even if * jmem_available returns zero. The maximum space needed, enough to hold * all working storage in memory, is also passed in case it is useful. * * It is OK for jmem_available to underestimate the space available (that'll * just lead to more backing-store access than is really necessary). * However, an overestimate will lead to failure. Hence it's wise to subtract * a slop factor from the true available space, especially if jget_small space * comes from the same pool. 5% should be enough. * * On machines with lots of virtual memory, any large constant may be returned. * Conversely, zero may be returned to always use the minimum amount of memory. */ EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed)); /* * This structure holds whatever state is needed to access a single * backing-store object. The read/write/close method pointers are called * by jmemmgr.c to manipulate the backing-store object; all other fields * are private to the system-dependent backing store routines. */ #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ METHOD(void, read_backing_store, (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); METHOD(void, write_backing_store, (backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); METHOD(void, close_backing_store, (backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ /* For a typical implementation with temp files, we might need: */ FILE * temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ } backing_store_info; /* * Initial opening of a backing-store object. This must fill in the * read/write/close pointers in the object. The read/write routines * may take an error exit if the specified maximum file size is exceeded. * (If jmem_available always returns a large value, this routine can just * take an error exit.) */ EXTERN void jopen_backing_store PP((backing_store_ptr info, long total_bytes_needed)); /* * These routines take care of any system-dependent initialization and * cleanup required. The system methods struct address should be saved * by jmem_init in case an error exit must be taken. jmem_term may assume * that all requested memory has been freed and that all opened backing- * store objects have been closed. * NB: jmem_term may be called more than once, and must behave reasonably * if that happens. */ EXTERN void jmem_init PP((external_methods_ptr emethods)); EXTERN void jmem_term PP((void)); /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, xloadimage.4.1/jpeg/jpegdata.h 644 221 144 117451 5340454464 11474 /* * jpegdata.h * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines shared data structures for the various JPEG modules. */ /* * You might need to change some of the following declarations if you are * using the JPEG software within a surrounding application program * or porting it to an unusual system. */ /* If the source or destination of image data is not to be stdio streams, * these types may need work. You can replace them with some kind of * pointer or indicator that is useful to you, or just ignore 'em. * Note that the user interface and the various jrdxxx/jwrxxx modules * will also need work for non-stdio input/output. */ typedef FILE * JFILEREF; /* source or dest of JPEG-compressed data */ typedef FILE * IFILEREF; /* source or dest of non-JPEG image data */ /* These defines are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions, * as is shown below for use with C++. Another application would be to make * all functions global for use with code profilers that require it. * NOTE: the C++ test does the right thing if you are reading this include * file in a C++ application to link to JPEG code that's been compiled with a * regular C compiler. I'm not sure it works if you try to compile the JPEG * code with C++. */ #define METHODDEF static /* a function called through method pointers */ #define LOCAL static /* a function used only in its module */ #define GLOBAL /* a function referenced thru EXTERNs */ #ifdef __cplusplus #define EXTERN extern "C" /* a reference to a GLOBAL function */ #else #define EXTERN extern /* a reference to a GLOBAL function */ #endif /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif /* The remaining declarations are not system-dependent, we hope. */ /* * NOTE: if you have an ancient, strict-K&R C compiler, it may choke on the * similarly-named fields in Compress_info_struct and Decompress_info_struct. * If this happens, you can get around it by rearranging the two structs so * that the similarly-named fields appear first and in the same order in * each struct. Since such compilers are now pretty rare, we haven't done * this in the portable code, preferring to maintain a logical ordering. */ /* This macro is used to declare a "method", that is, a function pointer. */ /* We want to supply prototype parameters if the compiler can cope. */ /* Note that the arglist parameter must be parenthesized! */ #ifdef PROTO #define METHOD(type,methodname,arglist) type (*methodname) arglist #else #define METHOD(type,methodname,arglist) type (*methodname) () #endif /* Forward references to lists of method pointers */ typedef struct External_methods_struct * external_methods_ptr; typedef struct Compress_methods_struct * compress_methods_ptr; typedef struct Decompress_methods_struct * decompress_methods_ptr; /* Data structures for images containing either samples or coefficients. */ /* Note that the topmost (leftmost) index is always color component. */ /* On 80x86 machines, the image arrays are too big for near pointers, */ /* but the pointer arrays can fit in near memory. */ typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ /* The input and output data of the DCT transform subroutines are of * the following type, which need not be the same as JCOEF. * For example, on a machine with fast floating point, it might make sense * to recode the DCT routines to use floating point; then DCTELEM would be * 'float' or 'double'. */ typedef JCOEF DCTELEM; typedef DCTELEM DCTBLOCK[DCTSIZE2]; /* Types for JPEG compression parameters and working tables. */ typedef enum { /* defines known color spaces */ CS_UNKNOWN, /* error/unspecified */ CS_GRAYSCALE, /* monochrome (only 1 component) */ CS_RGB, /* red/green/blue */ CS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ CS_YIQ, /* Y/I/Q */ CS_CMYK /* C/M/Y/K */ } COLOR_SPACE; typedef struct { /* Basic info about one component */ /* These values are fixed over the whole image */ /* For compression, they must be supplied by the user interface; */ /* for decompression, they are read from the SOF marker. */ short component_id; /* identifier for this component (0..255) */ short component_index; /* its index in SOF or cinfo->comp_info[] */ short h_samp_factor; /* horizontal sampling factor (1..4) */ short v_samp_factor; /* vertical sampling factor (1..4) */ short quant_tbl_no; /* quantization table selector (0..3) */ /* These values may vary between scans */ /* For compression, they must be supplied by the user interface; */ /* for decompression, they are read from the SOS marker. */ short dc_tbl_no; /* DC entropy table selector (0..3) */ short ac_tbl_no; /* AC entropy table selector (0..3) */ /* These values are computed during compression or decompression startup */ long true_comp_width; /* component's image width in samples */ long true_comp_height; /* component's image height in samples */ /* the above are the logical dimensions of the downsampled image */ /* These values are computed before starting a scan of the component */ short MCU_width; /* number of blocks per MCU, horizontally */ short MCU_height; /* number of blocks per MCU, vertically */ short MCU_blocks; /* MCU_width * MCU_height */ long downsampled_width; /* image width in samples, after expansion */ long downsampled_height; /* image height in samples, after expansion */ /* the above are the true_comp_xxx values rounded up to multiples of */ /* the MCU dimensions; these are the working dimensions of the array */ /* as it is passed through the DCT or IDCT step. NOTE: these values */ /* differ depending on whether the component is interleaved or not!! */ /* This flag is used only for decompression. In cases where some of the */ /* components will be ignored (eg grayscale output from YCbCr image), */ /* we can skip IDCT etc. computations for the unused components. */ boolean component_needed; /* do we need the value of this component? */ } jpeg_component_info; /* DCT coefficient quantization tables. * For 8-bit precision, 'INT16' should be good enough for quantization values; * for more precision, we go for the full 16 bits. 'INT16' provides a useful * speedup on many machines (multiplication & division of JCOEFs by * quantization values is a significant chunk of the runtime). * Note: the values in a QUANT_TBL are always given in zigzag order. */ #ifdef EIGHT_BIT_SAMPLES typedef INT16 QUANT_VAL; /* element of a quantization table */ #else typedef UINT16 QUANT_VAL; /* element of a quantization table */ #endif typedef QUANT_VAL QUANT_TBL[DCTSIZE2]; /* A quantization table */ typedef QUANT_VAL * QUANT_TBL_PTR; /* pointer to same */ /* Huffman coding tables. */ #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. */ boolean sent_table; /* TRUE when table has been output */ /* The remaining fields are computed from the above to allow more efficient * coding and decoding. These fields should be considered private to the * Huffman compression & decompression modules. We use a union since only * one set of fields is needed at a time. */ union { struct { /* encoding tables: */ UINT16 ehufco[256]; /* code for each symbol */ char ehufsi[256]; /* length of code for each symbol */ } enc; struct { /* decoding tables: */ /* Basic tables: (element [0] of each array is unused) */ INT32 mincode[17]; /* smallest code of length k */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ int valptr[17]; /* huffval[] index of 1st symbol of length k */ /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of * the input data stream. If the next Huffman code is no more * than HUFF_LOOKAHEAD bits long, we can obtain its length and * the corresponding symbol directly from these tables. */ int look_nbits[1< 0, MCU rows per restart interval */ /* * These fields are computed during jpeg_compress startup */ short max_h_samp_factor; /* largest h_samp_factor */ short max_v_samp_factor; /* largest v_samp_factor */ /* * These fields may be useful for progress monitoring */ int total_passes; /* number of passes expected */ int completed_passes; /* number of passes completed so far */ /* * These fields are valid during any one scan */ short comps_in_scan; /* # of JPEG components output this time */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ long MCUs_per_row; /* # of MCUs across the image */ long MCU_rows_in_scan; /* # of MCU rows in the image */ short blocks_in_MCU; /* # of DCT blocks per MCU */ short MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* these fields are private data for the entropy encoder */ JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */ JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */ UINT16 restarts_to_go; /* MCUs left in this restart interval */ short next_restart_num; /* # of next RSTn marker (0..7) */ }; typedef struct Compress_info_struct * compress_info_ptr; /* Working data for decompression */ struct Decompress_info_struct { /* * These fields shall be established by the user interface before * calling jpeg_decompress. * Most parameters can be set to reasonable defaults by j_d_defaults. * Note that the UI must supply the storage for the main methods struct, * though it sets only a few of the methods there. */ decompress_methods_ptr methods; /* Points to list of methods to use */ external_methods_ptr emethods; /* Points to list of methods to use */ JFILEREF input_file; /* tells input routines where to read JPEG */ IFILEREF output_file; /* tells output routines where to write image */ /* these can be set at d_ui_method_selection time: */ COLOR_SPACE out_color_space; /* colorspace of output */ double output_gamma; /* image gamma wanted in output */ boolean quantize_colors; /* T if output is a colormapped format */ /* the following are ignored if not quantize_colors: */ boolean two_pass_quantize; /* use two-pass color quantization? */ boolean use_dithering; /* want color dithering? */ int desired_number_of_colors; /* max number of colors to use */ boolean do_block_smoothing; /* T = apply cross-block smoothing */ boolean do_pixel_smoothing; /* T = apply post-upsampling smoothing */ /* * These fields are used for efficient buffering of data between read_jpeg_data * and the entropy decoding object. By using a shared buffer, we avoid copying * data and eliminate the need for an "unget" operation at the end of a scan. * The actual source of the data is known only to read_jpeg_data; see the * JGETC macro, below. * Note: the user interface is expected to allocate the input_buffer and * initialize bytes_in_buffer to 0. Also, for JFIF/raw-JPEG input, the UI * actually supplies the read_jpeg_data method. This is all handled by * j_d_defaults in a typical implementation. */ char * input_buffer; /* start of buffer (private to input code) */ char * next_input_byte; /* => next byte to read from buffer */ int bytes_in_buffer; /* # of bytes remaining in buffer */ /* * These fields are set by read_file_header or read_scan_header */ long image_width; /* overall image width */ long image_height; /* overall image height */ short data_precision; /* bits of precision in image data */ COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */ /* These three values are not used by the JPEG code, merely copied */ /* from the JFIF APP0 marker (if any). */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ short num_components; /* # of color components in JPEG image */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ UINT16 restart_interval;/* MCUs per restart interval, or 0 for no restart */ /* * These fields are computed during jpeg_decompress startup */ short max_h_samp_factor; /* largest h_samp_factor */ short max_v_samp_factor; /* largest v_samp_factor */ short color_out_comps; /* # of color components output by color_convert */ /* (need not match num_components) */ short final_out_comps; /* # of color components sent to put_pixel_rows */ /* (1 when quantizing colors, else same as color_out_comps) */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ /* * When quantizing colors, the color quantizer leaves a pointer to the output * colormap in these fields. The colormap is valid from the time put_color_map * is called (must be before any put_pixel_rows calls) until shutdown (more * specifically, until free_all is called to release memory). */ int actual_number_of_colors; /* actual number of entries */ JSAMPARRAY colormap; /* NULL if not valid */ /* map has color_out_comps rows * actual_number_of_colors columns */ /* * These fields may be useful for progress monitoring */ int total_passes; /* number of passes expected */ int completed_passes; /* number of passes completed so far */ /* * These fields are valid during any one scan */ short comps_in_scan; /* # of JPEG components input this time */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ long MCUs_per_row; /* # of MCUs across the image */ long MCU_rows_in_scan; /* # of MCU rows in the image */ short blocks_in_MCU; /* # of DCT blocks per MCU */ short MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* these fields are private data for the entropy encoder */ JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */ JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */ UINT16 restarts_to_go; /* MCUs left in this restart interval */ short next_restart_num; /* # of next RSTn marker (0..7) */ }; typedef struct Decompress_info_struct * decompress_info_ptr; /* Macros for reading data from the decompression input buffer */ #ifdef CHAR_IS_UNSIGNED #define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \ (*(cinfo)->methods->read_jpeg_data) (cinfo) : \ (int) (*(cinfo)->next_input_byte++) ) #else #define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \ (*(cinfo)->methods->read_jpeg_data) (cinfo) : \ (int) (*(cinfo)->next_input_byte++) & 0xFF ) #endif #define JUNGETC(ch,cinfo) ((cinfo)->bytes_in_buffer++, \ *(--((cinfo)->next_input_byte)) = (char) (ch)) #define MIN_UNGET 4 /* may always do at least 4 JUNGETCs */ /* A virtual image has a control block whose contents are private to the * memory manager module (and may differ between managers). The rest of the * code only refers to virtual images by these pointer types, and never * dereferences the pointer. */ typedef struct big_sarray_control * big_sarray_ptr; typedef struct big_barray_control * big_barray_ptr; /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * add -DINCOMPLETE_TYPES_BROKEN to CFLAGS in your Makefile. Then we will * pseudo-define the structs as containing a single "dummy" field. * The memory managers #define AM_MEMORY_MANAGER before including this file, * so that they can make their own definitions of the structs. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef AM_MEMORY_MANAGER struct big_sarray_control { long dummy; }; struct big_barray_control { long dummy; }; #endif #endif /* Method types that need typedefs */ typedef METHOD(void, MCU_output_method_ptr, (compress_info_ptr cinfo, JBLOCK *MCU_data)); typedef METHOD(void, MCU_output_caller_ptr, (compress_info_ptr cinfo, MCU_output_method_ptr output_method)); typedef METHOD(void, downsample_ptr, (compress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data)); typedef METHOD(void, upsample_ptr, (decompress_info_ptr cinfo, int which_component, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below, JSAMPARRAY output_data)); typedef METHOD(void, quantize_method_ptr, (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_workspace)); typedef METHOD(void, quantize_caller_ptr, (decompress_info_ptr cinfo, quantize_method_ptr quantize_method)); /* These structs contain function pointers for the various JPEG methods. */ /* Routines to be provided by the surrounding application, rather than the * portable JPEG code proper. These are the same for compression and * decompression. */ struct External_methods_struct { /* User interface: error exit and trace message routines */ /* NOTE: the string msgtext parameters will eventually be replaced * by an enumerated-type code so that non-English error messages * can be substituted easily. This will not be done until all the * code is in place, so that we know what messages are needed. */ METHOD(void, error_exit, (const char *msgtext)); METHOD(void, trace_message, (const char *msgtext)); /* Working data for error/trace facility */ /* See macros below for the usage of these variables */ int trace_level; /* level of detail of tracing messages */ /* Use level 0 for important warning messages (nonfatal errors) */ /* Use levels 1, 2, 3 for successively more detailed trace options */ /* For recoverable corrupt-data errors, we emit a warning message and * keep going. A surrounding application can check for bad data by * seeing if num_warnings is nonzero at the end of processing. */ long num_warnings; /* number of corrupt-data warnings */ int first_warning_level; /* trace level for first warning */ int more_warning_level; /* trace level for subsequent warnings */ int message_parm[8]; /* store numeric parms for messages here */ /* Memory management */ /* NB: alloc routines never return NULL. They exit to */ /* error_exit if not successful. */ METHOD(void *, alloc_small, (size_t sizeofobject)); METHOD(void, free_small, (void *ptr)); METHOD(void FAR *, alloc_medium, (size_t sizeofobject)); METHOD(void, free_medium, (void FAR *ptr)); METHOD(JSAMPARRAY, alloc_small_sarray, (long samplesperrow, long numrows)); METHOD(void, free_small_sarray, (JSAMPARRAY ptr)); METHOD(JBLOCKARRAY, alloc_small_barray, (long blocksperrow, long numrows)); METHOD(void, free_small_barray, (JBLOCKARRAY ptr)); METHOD(big_sarray_ptr, request_big_sarray, (long samplesperrow, long numrows, long unitheight)); METHOD(big_barray_ptr, request_big_barray, (long blocksperrow, long numrows, long unitheight)); METHOD(void, alloc_big_arrays, (long extra_small_samples, long extra_small_blocks, long extra_medium_space)); METHOD(JSAMPARRAY, access_big_sarray, (big_sarray_ptr ptr, long start_row, boolean writable)); METHOD(JBLOCKARRAY, access_big_barray, (big_barray_ptr ptr, long start_row, boolean writable)); METHOD(void, free_big_sarray, (big_sarray_ptr ptr)); METHOD(void, free_big_barray, (big_barray_ptr ptr)); METHOD(void, free_all, (void)); long max_memory_to_use; /* maximum amount of memory to use */ }; /* Macros to simplify using the error and trace message stuff */ /* The first parameter is generally cinfo->emethods */ /* Fatal errors (print message and exit) */ #define ERREXIT(emeth,msg) ((*(emeth)->error_exit) (msg)) #define ERREXIT1(emeth,msg,p1) ((emeth)->message_parm[0] = (p1), \ (*(emeth)->error_exit) (msg)) #define ERREXIT2(emeth,msg,p1,p2) ((emeth)->message_parm[0] = (p1), \ (emeth)->message_parm[1] = (p2), \ (*(emeth)->error_exit) (msg)) #define ERREXIT3(emeth,msg,p1,p2,p3) ((emeth)->message_parm[0] = (p1), \ (emeth)->message_parm[1] = (p2), \ (emeth)->message_parm[2] = (p3), \ (*(emeth)->error_exit) (msg)) #define ERREXIT4(emeth,msg,p1,p2,p3,p4) ((emeth)->message_parm[0] = (p1), \ (emeth)->message_parm[1] = (p2), \ (emeth)->message_parm[2] = (p3), \ (emeth)->message_parm[3] = (p4), \ (*(emeth)->error_exit) (msg)) #define MAKESTMT(stuff) do { stuff } while (0) /* Nonfatal errors (we'll keep going, but the data is probably corrupt) */ /* Note that warning count is incremented as a side-effect! */ #define WARNMS(emeth,msg) \ MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \ (emeth)->more_warning_level : (emeth)->first_warning_level)){ \ (*(emeth)->trace_message) (msg); } ) #define WARNMS1(emeth,msg,p1) \ MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \ (emeth)->more_warning_level : (emeth)->first_warning_level)){ \ (emeth)->message_parm[0] = (p1); \ (*(emeth)->trace_message) (msg); } ) #define WARNMS2(emeth,msg,p1,p2) \ MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \ (emeth)->more_warning_level : (emeth)->first_warning_level)){ \ (emeth)->message_parm[0] = (p1); \ (emeth)->message_parm[1] = (p2); \ (*(emeth)->trace_message) (msg); } ) /* Informational/debugging messages */ #define TRACEMS(emeth,lvl,msg) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ (*(emeth)->trace_message) (msg); } ) #define TRACEMS1(emeth,lvl,msg,p1) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ (emeth)->message_parm[0] = (p1); \ (*(emeth)->trace_message) (msg); } ) #define TRACEMS2(emeth,lvl,msg,p1,p2) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ (emeth)->message_parm[0] = (p1); \ (emeth)->message_parm[1] = (p2); \ (*(emeth)->trace_message) (msg); } ) #define TRACEMS3(emeth,lvl,msg,p1,p2,p3) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ int * _mp = (emeth)->message_parm; \ *_mp++ = (p1); *_mp++ = (p2); *_mp = (p3); \ (*(emeth)->trace_message) (msg); } ) #define TRACEMS4(emeth,lvl,msg,p1,p2,p3,p4) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ int * _mp = (emeth)->message_parm; \ *_mp++ = (p1); *_mp++ = (p2); *_mp++ = (p3); *_mp = (p4); \ (*(emeth)->trace_message) (msg); } ) #define TRACEMS8(emeth,lvl,msg,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \ int * _mp = (emeth)->message_parm; \ *_mp++ = (p1); *_mp++ = (p2); *_mp++ = (p3); *_mp++ = (p4); \ *_mp++ = (p5); *_mp++ = (p6); *_mp++ = (p7); *_mp = (p8); \ (*(emeth)->trace_message) (msg); } ) /* Methods used during JPEG compression. */ struct Compress_methods_struct { /* Hook for user interface to get control after input_init */ METHOD(void, c_ui_method_selection, (compress_info_ptr cinfo)); /* Hook for user interface to do progress monitoring */ METHOD(void, progress_monitor, (compress_info_ptr cinfo, long loopcounter, long looplimit)); /* Input image reading & conversion to standard form */ METHOD(void, input_init, (compress_info_ptr cinfo)); METHOD(void, get_input_row, (compress_info_ptr cinfo, JSAMPARRAY pixel_row)); METHOD(void, input_term, (compress_info_ptr cinfo)); /* Color space and gamma conversion */ METHOD(void, colorin_init, (compress_info_ptr cinfo)); METHOD(void, get_sample_rows, (compress_info_ptr cinfo, int rows_to_read, JSAMPIMAGE image_data)); METHOD(void, colorin_term, (compress_info_ptr cinfo)); /* Expand picture data at edges */ METHOD(void, edge_expand, (compress_info_ptr cinfo, long input_cols, int input_rows, long output_cols, int output_rows, JSAMPIMAGE image_data)); /* Downsample pixel values of a single component */ /* There can be a different downsample method for each component */ METHOD(void, downsample_init, (compress_info_ptr cinfo)); downsample_ptr downsample[MAX_COMPS_IN_SCAN]; METHOD(void, downsample_term, (compress_info_ptr cinfo)); /* Extract samples in MCU order, process & hand off to output_method */ /* The input is always exactly N MCU rows worth of data */ METHOD(void, extract_init, (compress_info_ptr cinfo)); METHOD(void, extract_MCUs, (compress_info_ptr cinfo, JSAMPIMAGE image_data, int num_mcu_rows, MCU_output_method_ptr output_method)); METHOD(void, extract_term, (compress_info_ptr cinfo)); /* Entropy encoding parameter optimization */ METHOD(void, entropy_optimize, (compress_info_ptr cinfo, MCU_output_caller_ptr source_method)); /* Entropy encoding */ METHOD(void, entropy_encode_init, (compress_info_ptr cinfo)); METHOD(void, entropy_encode, (compress_info_ptr cinfo, JBLOCK *MCU_data)); METHOD(void, entropy_encode_term, (compress_info_ptr cinfo)); /* JPEG file header construction */ METHOD(void, write_file_header, (compress_info_ptr cinfo)); METHOD(void, write_scan_header, (compress_info_ptr cinfo)); METHOD(void, write_jpeg_data, (compress_info_ptr cinfo, char *dataptr, int datacount)); METHOD(void, write_scan_trailer, (compress_info_ptr cinfo)); METHOD(void, write_file_trailer, (compress_info_ptr cinfo)); /* Pipeline control */ METHOD(void, c_pipeline_controller, (compress_info_ptr cinfo)); METHOD(void, entropy_output, (compress_info_ptr cinfo, char *dataptr, int datacount)); /* Overall control */ METHOD(void, c_per_scan_method_selection, (compress_info_ptr cinfo)); }; /* Methods used during JPEG decompression. */ struct Decompress_methods_struct { /* Hook for user interface to get control after reading file header */ METHOD(void, d_ui_method_selection, (decompress_info_ptr cinfo)); /* Hook for user interface to process comment blocks */ METHOD(void, process_comment, (decompress_info_ptr cinfo, long comment_length)); /* Hook for user interface to do progress monitoring */ METHOD(void, progress_monitor, (decompress_info_ptr cinfo, long loopcounter, long looplimit)); /* JPEG file scanning */ METHOD(void, read_file_header, (decompress_info_ptr cinfo)); METHOD(boolean, read_scan_header, (decompress_info_ptr cinfo)); METHOD(int, read_jpeg_data, (decompress_info_ptr cinfo)); METHOD(void, resync_to_restart, (decompress_info_ptr cinfo, int marker)); METHOD(void, read_scan_trailer, (decompress_info_ptr cinfo)); METHOD(void, read_file_trailer, (decompress_info_ptr cinfo)); /* Entropy decoding */ METHOD(void, entropy_decode_init, (decompress_info_ptr cinfo)); METHOD(void, entropy_decode, (decompress_info_ptr cinfo, JBLOCKROW *MCU_data)); METHOD(void, entropy_decode_term, (decompress_info_ptr cinfo)); /* MCU disassembly: fetch MCUs from entropy_decode, build coef array */ /* The reverse_DCT step is in the same module for symmetry reasons */ METHOD(void, disassemble_init, (decompress_info_ptr cinfo)); METHOD(void, disassemble_MCU, (decompress_info_ptr cinfo, JBLOCKIMAGE image_data)); METHOD(void, reverse_DCT, (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data, int start_row)); METHOD(void, disassemble_term, (decompress_info_ptr cinfo)); /* Cross-block smoothing */ METHOD(void, smooth_coefficients, (decompress_info_ptr cinfo, jpeg_component_info *compptr, JBLOCKROW above, JBLOCKROW currow, JBLOCKROW below, JBLOCKROW output)); /* Upsample pixel values of a single component */ /* There can be a different upsample method for each component */ METHOD(void, upsample_init, (decompress_info_ptr cinfo)); upsample_ptr upsample[MAX_COMPS_IN_SCAN]; METHOD(void, upsample_term, (decompress_info_ptr cinfo)); /* Color space and gamma conversion */ METHOD(void, colorout_init, (decompress_info_ptr cinfo)); METHOD(void, color_convert, (decompress_info_ptr cinfo, int num_rows, long num_cols, JSAMPIMAGE input_data, JSAMPIMAGE output_data)); METHOD(void, colorout_term, (decompress_info_ptr cinfo)); /* Color quantization */ METHOD(void, color_quant_init, (decompress_info_ptr cinfo)); METHOD(void, color_quantize, (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data)); METHOD(void, color_quant_prescan, (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE image_data, JSAMPARRAY workspace)); METHOD(void, color_quant_doit, (decompress_info_ptr cinfo, quantize_caller_ptr source_method)); METHOD(void, color_quant_term, (decompress_info_ptr cinfo)); /* Output image writing */ METHOD(void, output_init, (decompress_info_ptr cinfo)); METHOD(void, put_color_map, (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)); METHOD(void, put_pixel_rows, (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)); METHOD(void, output_term, (decompress_info_ptr cinfo)); /* Pipeline control */ METHOD(void, d_pipeline_controller, (decompress_info_ptr cinfo)); /* Overall control */ METHOD(void, d_per_scan_method_selection, (decompress_info_ptr cinfo)); }; /* External declarations for routines that aren't called via method ptrs. */ /* Note: use "j" as first char of names to minimize namespace pollution. */ /* The PP macro hides prototype parameters from compilers that can't cope. */ #ifdef PROTO #define PP(arglist) arglist #else #define PP(arglist) () #endif /* main entry for compression */ EXTERN void jpeg_compress PP((compress_info_ptr cinfo)); /* default parameter setup for compression */ EXTERN void j_c_defaults PP((compress_info_ptr cinfo, int quality, boolean force_baseline)); EXTERN void j_monochrome_default PP((compress_info_ptr cinfo)); EXTERN void j_set_quality PP((compress_info_ptr cinfo, int quality, boolean force_baseline)); /* advanced compression parameter setup aids */ EXTERN void j_add_quant_table PP((compress_info_ptr cinfo, int which_tbl, const QUANT_VAL *basic_table, int scale_factor, boolean force_baseline)); EXTERN int j_quality_scaling PP((int quality)); /* main entry for decompression */ EXTERN void jpeg_decompress PP((decompress_info_ptr cinfo)); /* default parameter setup for decompression */ EXTERN void j_d_defaults PP((decompress_info_ptr cinfo, boolean standard_buffering)); /* forward DCT */ EXTERN void j_fwd_dct PP((DCTBLOCK data)); /* inverse DCT */ EXTERN void j_rev_dct PP((DCTBLOCK data)); /* utility routines in jutils.c */ EXTERN long jround_up PP((long a, long b)); EXTERN void jcopy_sample_rows PP((JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, long num_cols)); EXTERN void jcopy_block_row PP((JBLOCKROW input_row, JBLOCKROW output_row, long num_blocks)); EXTERN void jzero_far PP((void FAR * target, size_t bytestozero)); /* method selection routines for compression modules */ EXTERN void jselcpipeline PP((compress_info_ptr cinfo)); /* jcpipe.c */ EXTERN void jselchuffman PP((compress_info_ptr cinfo)); /* jchuff.c */ EXTERN void jselcarithmetic PP((compress_info_ptr cinfo)); /* jcarith.c */ EXTERN void jselexpand PP((compress_info_ptr cinfo)); /* jcexpand.c */ EXTERN void jseldownsample PP((compress_info_ptr cinfo)); /* jcsample.c */ EXTERN void jselcmcu PP((compress_info_ptr cinfo)); /* jcmcu.c */ EXTERN void jselccolor PP((compress_info_ptr cinfo)); /* jccolor.c */ /* The user interface should call one of these to select input format: */ EXTERN void jselrgif PP((compress_info_ptr cinfo)); /* jrdgif.c */ EXTERN void jselrppm PP((compress_info_ptr cinfo)); /* jrdppm.c */ EXTERN void jselrrle PP((compress_info_ptr cinfo)); /* jrdrle.c */ EXTERN void jselrtarga PP((compress_info_ptr cinfo)); /* jrdtarga.c */ /* and one of these to select output header format: */ EXTERN void jselwjfif PP((compress_info_ptr cinfo)); /* jwrjfif.c */ /* method selection routines for decompression modules */ EXTERN void jseldpipeline PP((decompress_info_ptr cinfo)); /* jdpipe.c */ EXTERN void jseldhuffman PP((decompress_info_ptr cinfo)); /* jdhuff.c */ EXTERN void jseldarithmetic PP((decompress_info_ptr cinfo)); /* jdarith.c */ EXTERN void jseldmcu PP((decompress_info_ptr cinfo)); /* jdmcu.c */ EXTERN void jselbsmooth PP((decompress_info_ptr cinfo)); /* jbsmooth.c */ EXTERN void jselupsample PP((decompress_info_ptr cinfo)); /* jdsample.c */ EXTERN void jseldcolor PP((decompress_info_ptr cinfo)); /* jdcolor.c */ EXTERN void jsel1quantize PP((decompress_info_ptr cinfo)); /* jquant1.c */ EXTERN void jsel2quantize PP((decompress_info_ptr cinfo)); /* jquant2.c */ /* The user interface should call one of these to select input format: */ EXTERN void jselrjfif PP((decompress_info_ptr cinfo)); /* jrdjfif.c */ /* and one of these to select output image format: */ EXTERN void jselwgif PP((decompress_info_ptr cinfo)); /* jwrgif.c */ EXTERN void jselwppm PP((decompress_info_ptr cinfo)); /* jwrppm.c */ EXTERN void jselwrle PP((decompress_info_ptr cinfo)); /* jwrrle.c */ EXTERN void jselwtarga PP((decompress_info_ptr cinfo)); /* jwrtarga.c */ /* method selection routines for system-dependent modules */ EXTERN void jselerror PP((external_methods_ptr emethods)); /* jerror.c */ EXTERN void jselmemmgr PP((external_methods_ptr emethods)); /* jmemmgr.c */ /* We assume that right shift corresponds to signed division by 2 with * rounding towards minus infinity. This is correct for typical "arithmetic * shift" instructions that shift in copies of the sign bit. But some * C compilers implement >> with an unsigned shift. For these machines you * must define RIGHT_SHIFT_IS_UNSIGNED. * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. * It is only applied with constant shift counts. SHIFT_TEMPS must be * included in the variables of any routine using RIGHT_SHIFT. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ ((shift_temp = (x)) < 0 ? \ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ (shift_temp >> (shft))) #else #define SHIFT_TEMPS #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* Miscellaneous useful macros */ #undef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define RST0 0xD0 /* RST0 marker code */ eader, (decompress_info_ptr cinfo)); METHOD(int, read_jpeg_data, (decompress_info_ptr cinfo)); METHOD(void, resync_to_restart, (decompress_info_ptr cinfo, int marker)); METHOD(void, read_scan_trailer, (decoxloadimage.4.1/jpeg/jquant1.c 644 221 144 55354 5331110334 11237 /* * jquant1.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 1-pass color quantization (color mapping) routines. * These routines are invoked via the methods color_quantize * and color_quant_init/term. */ #include "jinclude.h" #ifdef QUANT_1PASS_SUPPORTED /* * The main purpose of 1-pass quantization is to provide a fast, if not very * high quality, colormapped output capability. A 2-pass quantizer usually * gives better visual quality; however, for quantized grayscale output this * quantizer is perfectly adequate. Dithering is highly recommended with this * quantizer, though you can turn it off if you really want to. * * This implementation quantizes in the output colorspace. This has a couple * of disadvantages: each pixel must be individually color-converted, and if * the color conversion includes gamma correction then quantization is done in * a nonlinear space, which is less desirable. The major advantage is that * with the usual output color spaces (RGB, grayscale) an orthogonal grid of * representative colors can be used, thus permitting the very simple and fast * color lookup scheme used here. The standard JPEG colorspace (YCbCr) cannot * be effectively handled this way, because only about a quarter of an * orthogonal grid would fall within the gamut of realizable colors. Another * advantage is that when the user wants quantized grayscale output from a * color JPEG file, this quantizer can provide a high-quality result with no * special hacking. * * The gamma-correction problem could be eliminated by adjusting the grid * spacing to counteract the gamma correction applied by color_convert. * At this writing, gamma correction is not implemented by jdcolor, so * nothing is done here. * * In 1-pass quantization the colormap must be chosen in advance of seeing the * image. We use a map consisting of all combinations of Ncolors[i] color * values for the i'th component. The Ncolors[] values are chosen so that * their product, the total number of colors, is no more than that requested. * (In most cases, the product will be somewhat less.) * * Since the colormap is orthogonal, the representative value for each color * component can be determined without considering the other components; * then these indexes can be combined into a colormap index by a standard * N-dimensional-array-subscript calculation. Most of the arithmetic involved * can be precalculated and stored in the lookup table colorindex[]. * colorindex[i][j] maps pixel value j in component i to the nearest * representative value (grid plane) for that component; this index is * multiplied by the array stride for component i, so that the * index of the colormap entry closest to a given pixel value is just * sum( colorindex[component-number][pixel-component-value] ) * Aside from being fast, this scheme allows for variable spacing between * representative values with no additional lookup cost. */ #define MAX_COMPONENTS 4 /* max components I can handle */ static JSAMPARRAY colormap; /* The actual color map */ /* colormap[i][j] = value of i'th color component for output pixel value j */ static JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into * JSAMPLEs, the entries of this array will too. */ static JSAMPARRAY input_buffer; /* color conversion workspace */ /* Since our input data is presented in the JPEG colorspace, we have to call * color_convert to get it into the output colorspace. input_buffer is a * one-row-high workspace for the result of color_convert. */ /* Declarations for Floyd-Steinberg dithering. * * Errors are accumulated into the array fserrors[], at a resolution of * 1/16th of a pixel count. The error at a given pixel is propagated * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * * We can get away with a single array (holding one row's worth of errors) * by using it to store the current row's errors at pixel columns not yet * processed, but the next row's errors at columns already processed. We * need only a few extra variables to hold the errors immediately around the * current column. (If we are lucky, those variables are in registers, but * even if not, they're probably cheaper to access than array elements are.) * * The fserrors[] array is indexed [component#][position]. * We provide (#columns + 2) entries per component; the extra entry at each * end saves us from special-casing the first and last pixels. * * Note: on a wide image, we might not have enough room in a PC's near data * segment to hold the error array; so it is allocated with alloc_medium. */ #ifdef EIGHT_BIT_SAMPLES typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else typedef INT32 FSERROR; /* may need more than 16 bits */ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ static FSERRPTR fserrors[MAX_COMPONENTS]; /* accumulated errors */ static boolean on_odd_row; /* flag to remember which row we are on */ /* * Policy-making subroutines for color_quant_init: these routines determine * the colormap to be used. The rest of the module only assumes that the * colormap is orthogonal. * * * select_ncolors decides how to divvy up the available colors * among the components. * * output_value defines the set of representative values for a component. * * largest_input_value defines the mapping from input values to * representative values for a component. * Note that the latter two routines may impose different policies for * different components, though this is not currently done. */ LOCAL int select_ncolors (decompress_info_ptr cinfo, int Ncolors[]) /* Determine allocation of desired colors to components, */ /* and fill in Ncolors[] array to indicate choice. */ /* Return value is total number of colors (product of Ncolors[] values). */ { int nc = cinfo->color_out_comps; /* number of color components */ int max_colors = cinfo->desired_number_of_colors; int total_colors, iroot, i; long temp; boolean changed; /* We can allocate at least the nc'th root of max_colors per component. */ /* Compute floor(nc'th root of max_colors). */ iroot = 1; do { iroot++; temp = iroot; /* set temp = iroot ** nc */ for (i = 1; i < nc; i++) temp *= iroot; } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ iroot--; /* now iroot = floor(root) */ /* Must have at least 2 color values per component */ if (iroot < 2) ERREXIT1(cinfo->emethods, "Cannot quantize to fewer than %d colors", (int) temp); if (cinfo->out_color_space == CS_RGB && nc == 3) { /* We provide a special policy for quantizing in RGB space. * If 256 colors are requested, we allocate 8 red, 8 green, 4 blue levels; * this corresponds to the common 3/3/2-bit scheme. For other totals, * the counts are set so that the number of colors allocated to each * component are roughly in the proportion R 3, G 4, B 2. * For low color counts, it's easier to hardwire the optimal choices * than try to tweak the algorithm to generate them. */ if (max_colors == 256) { Ncolors[0] = 8; Ncolors[1] = 8; Ncolors[2] = 4; return 256; } if (max_colors < 12) { /* Fixed mapping for 8 colors */ Ncolors[0] = Ncolors[1] = Ncolors[2] = 2; } else if (max_colors < 18) { /* Fixed mapping for 12 colors */ Ncolors[0] = 2; Ncolors[1] = 3; Ncolors[2] = 2; } else if (max_colors < 24) { /* Fixed mapping for 18 colors */ Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 2; } else if (max_colors < 27) { /* Fixed mapping for 24 colors */ Ncolors[0] = 3; Ncolors[1] = 4; Ncolors[2] = 2; } else if (max_colors < 36) { /* Fixed mapping for 27 colors */ Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 3; } else { /* these weights are readily derived with a little algebra */ Ncolors[0] = (iroot * 266) >> 8; /* R weight is 1.0400 */ Ncolors[1] = (iroot * 355) >> 8; /* G weight is 1.3867 */ Ncolors[2] = (iroot * 177) >> 8; /* B weight is 0.6934 */ } total_colors = Ncolors[0] * Ncolors[1] * Ncolors[2]; /* The above computation produces "floor" values, so we may be able to * increment the count for one or more components without exceeding * max_colors. We try in the order B, G, R. */ do { changed = FALSE; for (i = 2; i >= 0; i--) { /* calculate new total_colors if Ncolors[i] is incremented */ temp = total_colors / Ncolors[i]; temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */ if (temp <= (long) max_colors) { Ncolors[i]++; /* OK, apply the increment */ total_colors = (int) temp; changed = TRUE; } } } while (changed); /* loop until no increment is possible */ } else { /* For any colorspace besides RGB, treat all the components equally. */ /* Initialize to iroot color values for each component */ total_colors = 1; for (i = 0; i < nc; i++) { Ncolors[i] = iroot; total_colors *= iroot; } /* We may be able to increment the count for one or more components without * exceeding max_colors, though we know not all can be incremented. */ for (i = 0; i < nc; i++) { /* calculate new total_colors if Ncolors[i] is incremented */ temp = total_colors / Ncolors[i]; temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */ if (temp > (long) max_colors) break; /* won't fit, done */ Ncolors[i]++; /* OK, apply the increment */ total_colors = (int) temp; } } return total_colors; } LOCAL int output_value (decompress_info_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ /* The output values must fall in 0..MAXJSAMPLE in increasing order */ { /* We always provide values 0 and MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); } LOCAL int largest_input_value (decompress_info_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); } /* * Initialize for one-pass color quantization. */ METHODDEF void color_quant_init (decompress_info_ptr cinfo) { int total_colors; /* Number of distinct output colors */ int Ncolors[MAX_COMPONENTS]; /* # of values alloced to each component */ int i,j,k, nci, blksize, blkdist, ptr, val; /* Make sure my internal arrays won't overflow */ if (cinfo->num_components > MAX_COMPONENTS || cinfo->color_out_comps > MAX_COMPONENTS) ERREXIT1(cinfo->emethods, "Cannot quantize more than %d color components", MAX_COMPONENTS); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) ERREXIT1(cinfo->emethods, "Cannot request more than %d quantized colors", MAXJSAMPLE+1); /* Select number of colors for each component */ total_colors = select_ncolors(cinfo, Ncolors); /* Report selected color counts */ if (cinfo->color_out_comps == 3) TRACEMS4(cinfo->emethods, 1, "Quantizing to %d = %d*%d*%d colors", total_colors, Ncolors[0], Ncolors[1], Ncolors[2]); else TRACEMS1(cinfo->emethods, 1, "Quantizing to %d colors", total_colors); /* Allocate and fill in the colormap and color index. */ /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ colormap = (*cinfo->emethods->alloc_small_sarray) ((long) total_colors, (long) cinfo->color_out_comps); colorindex = (*cinfo->emethods->alloc_small_sarray) ((long) (MAXJSAMPLE+1), (long) cinfo->color_out_comps); /* blksize is number of adjacent repeated entries for a component */ /* blkdist is distance between groups of identical entries for a component */ blkdist = total_colors; for (i = 0; i < cinfo->color_out_comps; i++) { /* fill in colormap entries for i'th color component */ nci = Ncolors[i]; /* # of distinct values for this color */ blksize = blkdist / nci; for (j = 0; j < nci; j++) { /* Compute j'th output value (out of nci) for component */ val = output_value(cinfo, i, j, nci-1); /* Fill in all colormap entries that have this value of this component */ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) colormap[i][ptr+k] = (JSAMPLE) val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ /* fill in colorindex entries for i'th color component */ /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ val = 0; k = largest_input_value(cinfo, i, 0, nci-1); for (j = 0; j <= MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci-1); /* premultiply so that no multiplication needed in main processing */ colorindex[i][j] = (JSAMPLE) (val * blksize); } } /* Pass the colormap to the output module. */ /* NB: the output module may continue to use the colormap until shutdown. */ cinfo->colormap = colormap; cinfo->actual_number_of_colors = total_colors; (*cinfo->methods->put_color_map) (cinfo, total_colors, colormap); /* Allocate workspace to hold one row of color-converted data */ input_buffer = (*cinfo->emethods->alloc_small_sarray) (cinfo->image_width, (long) cinfo->color_out_comps); /* Allocate Floyd-Steinberg workspace if necessary */ if (cinfo->use_dithering) { size_t arraysize = (size_t) ((cinfo->image_width + 2L) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->color_out_comps; i++) { fserrors[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); /* Initialize the propagated errors to zero. */ jzero_far((void FAR *) fserrors[i], arraysize); } on_odd_row = FALSE; } } /* * Subroutines for color conversion methods. */ LOCAL void do_color_conversion (decompress_info_ptr cinfo, JSAMPIMAGE input_data, int row) /* Convert the indicated row of the input data into output colorspace */ /* in input_buffer. This requires a little trickery since color_convert */ /* expects to deal with 3-D arrays; fortunately we can fake it out */ /* at fairly low cost. */ { short ci; JSAMPARRAY input_hack[MAX_COMPONENTS]; JSAMPARRAY output_hack[MAX_COMPONENTS]; /* create JSAMPIMAGE pointing at specified row of input_data */ for (ci = 0; ci < cinfo->num_components; ci++) input_hack[ci] = input_data[ci] + row; /* Create JSAMPIMAGE pointing at input_buffer */ for (ci = 0; ci < cinfo->color_out_comps; ci++) output_hack[ci] = &(input_buffer[ci]); (*cinfo->methods->color_convert) (cinfo, 1, cinfo->image_width, input_hack, output_hack); } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF void color_quantize (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data) /* General case, no dithering */ { register int pixcode, ci; register JSAMPROW ptrout; register long col; int row; long width = cinfo->image_width; register int nc = cinfo->color_out_comps; for (row = 0; row < num_rows; row++) { do_color_conversion(cinfo, input_data, row); ptrout = output_data[row]; for (col = 0; col < width; col++) { pixcode = 0; for (ci = 0; ci < nc; ci++) { pixcode += GETJSAMPLE(colorindex[ci] [GETJSAMPLE(input_buffer[ci][col])]); } *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF void color_quantize3 (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data) /* Fast path for color_out_comps==3, no dithering */ { register int pixcode; register JSAMPROW ptr0, ptr1, ptr2, ptrout; register long col; int row; JSAMPROW colorindex0 = colorindex[0]; JSAMPROW colorindex1 = colorindex[1]; JSAMPROW colorindex2 = colorindex[2]; long width = cinfo->image_width; for (row = 0; row < num_rows; row++) { do_color_conversion(cinfo, input_data, row); ptr0 = input_buffer[0]; ptr1 = input_buffer[1]; ptr2 = input_buffer[2]; ptrout = output_data[row]; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptr0++)]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptr1++)]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptr2++)]); *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF void color_quantize_dither (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data) /* General case, with Floyd-Steinberg dithering */ { register LOCFSERROR cur; /* current error or pixel value */ LOCFSERROR belowerr; /* error for pixel below cur */ LOCFSERROR bpreverr; /* error for below/prev col */ LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; int pixcode; int dir; /* 1 for left-to-right, -1 for right-to-left */ int ci; int nc = cinfo->color_out_comps; int row; long col_counter; long width = cinfo->image_width; JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { do_color_conversion(cinfo, input_data, row); /* Initialize output values to 0 so can process components separately */ jzero_far((void FAR *) output_data[row], (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buffer[ci]; output_ptr = output_data[row]; if (on_odd_row) { /* work right to left in this row */ input_ptr += width - 1; /* so point to rightmost pixel */ output_ptr += width - 1; dir = -1; errorptr = fserrors[ci] + (width+1); /* point to entry after last column */ } else { /* work left to right in this row */ dir = 1; errorptr = fserrors[ci]; /* point to entry before first real column */ } colorindex_ci = colorindex[ci]; colormap_ci = colormap[ci]; /* Preset error values: no error propagated to first pixel from left */ cur = 0; /* and no error propagated to row below yet */ belowerr = bpreverr = 0; for (col_counter = width; col_counter > 0; col_counter--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr + cur); cur += delta; /* form error * 5 */ bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ input_ptr += dir; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } on_odd_row = (on_odd_row ? FALSE : TRUE); } } /* * Finish up at the end of the file. */ METHODDEF void color_quant_term (decompress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ /* Note that we *mustn't* free the colormap before free_all, */ /* since output module may use it! */ } /* * Prescan some rows of pixels. * Not used in one-pass case. */ METHODDEF void color_quant_prescan (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE image_data, JSAMPARRAY workspace) { ERREXIT(cinfo->emethods, "Should not get here!"); } /* * Do two-pass quantization. * Not used in one-pass case. */ METHODDEF void color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method) { ERREXIT(cinfo->emethods, "Should not get here!"); } /* * The method selection routine for 1-pass color quantization. */ GLOBAL void jsel1quantize (decompress_info_ptr cinfo) { if (! cinfo->two_pass_quantize) { cinfo->methods->color_quant_init = color_quant_init; if (cinfo->use_dithering) { cinfo->methods->color_quantize = color_quantize_dither; } else { if (cinfo->color_out_comps == 3) cinfo->methods->color_quantize = color_quantize3; else cinfo->methods->color_quantize = color_quantize; } cinfo->methods->color_quant_prescan = color_quant_prescan; cinfo->methods->color_quant_doit = color_quant_doit; cinfo->methods->color_quant_term = color_quant_term; } } #endif /* QUANT_1PASS_SUPPORTED */ / LOCAL void do_color_conversion (decompress_info_ptr cinfo, JSAMPIMAGE input_data, int row) /* Convert the indicated row of the input data into output colorspace */ /* in input_buffer. This requires a little trickery since color_convert */ /* expects to deal with 3-D arrayxloadimage.4.1/jpeg/jquant2.c 644 221 144 126431 5340457202 11263 /* * jquant2.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 2-pass color quantization (color mapping) routines. * These routines are invoked via the methods color_quant_prescan, * color_quant_doit, and color_quant_init/term. */ #include "jinclude.h" #ifdef QUANT_2PASS_SUPPORTED /* * This module implements the well-known Heckbert paradigm for color * quantization. Most of the ideas used here can be traced back to * Heckbert's seminal paper * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. * * In the first pass over the image, we accumulate a histogram showing the * usage count of each possible color. (To keep the histogram to a reasonable * size, we reduce the precision of the input; typical practice is to retain * 5 or 6 bits per color, so that 8 or 4 different input values are counted * in the same histogram cell.) Next, the color-selection step begins with a * box representing the whole color space, and repeatedly splits the "largest" * remaining box until we have as many boxes as desired colors. Then the mean * color in each remaining box becomes one of the possible output colors. * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires * considerable care. * * Heckbert-style quantizers vary a good deal in their policies for choosing * the "largest" box and deciding where to cut it. The particular policies * used here have proved out well in experimental comparisons, but better ones * may yet be found. * * The most significant difference between this quantizer and others is that * this one is intended to operate in YCbCr colorspace, rather than RGB space * as is usually done. Actually we work in scaled YCbCr colorspace, where * Y distances are inflated by a factor of 2 relative to Cb or Cr distances. * The empirical evidence is that distances in this space correspond to * perceptual color differences more closely than do distances in RGB space; * and working in this space is inexpensive within a JPEG decompressor, since * the input data is already in YCbCr form. (We could transform to an even * more perceptually linear space such as Lab or Luv, but that is very slow * and doesn't yield much better results than scaled YCbCr.) */ #define Y_SCALE 2 /* scale Y distances up by this much */ #define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ /* * First we have the histogram data structure and routines for creating it. * * For work in YCbCr space, it is useful to keep more precision for Y than * for Cb or Cr. We recommend keeping 6 bits for Y and 5 bits each for Cb/Cr. * If you have plenty of memory and cycles, 6 bits all around gives marginally * better results; if you are short of memory, 5 bits all around will save * some space but degrade the results. * To maintain a fully accurate histogram, we'd need to allocate a "long" * (preferably unsigned long) for each cell. In practice this is overkill; * we can get by with 16 bits per cell. Few of the cell counts will overflow, * and clamping those that do overflow to the maximum value will give close- * enough results. This reduces the recommended histogram size from 256Kb * to 128Kb, which is a useful savings on PC-class machines. * (In the second pass the histogram space is re-used for pixel mapping data; * in that capacity, each cell must be able to store zero to the number of * desired colors. 16 bits/cell is plenty for that too.) * Since the JPEG code is intended to run in small memory model on 80x86 * machines, we can't just allocate the histogram in one chunk. Instead * of a true 3-D array, we use a row of pointers to 2-D arrays. Each * pointer corresponds to a Y value (typically 2^6 = 64 pointers) and * each 2-D array has 2^5^2 = 1024 or 2^6^2 = 4096 entries. Note that * on 80x86 machines, the pointer row is in near memory but the actual * arrays are in far memory (same arrangement as we use for image arrays). */ #ifndef HIST_Y_BITS /* so you can override from Makefile */ #define HIST_Y_BITS 6 /* bits of precision in Y histogram */ #endif #ifndef HIST_C_BITS /* so you can override from Makefile */ #define HIST_C_BITS 5 /* bits of precision in Cb/Cr histogram */ #endif #define HIST_Y_ELEMS (1<image_width; for (row = 0; row < num_rows; row++) { ptr0 = image_data[0][row]; ptr1 = image_data[1][row]; ptr2 = image_data[2][row]; for (col = width; col > 0; col--) { /* get pixel value and index into the histogram */ c0 = GETJSAMPLE(*ptr0++) >> Y_SHIFT; c1 = GETJSAMPLE(*ptr1++) >> C_SHIFT; c2 = GETJSAMPLE(*ptr2++) >> C_SHIFT; histp = & histogram[c0][c1][c2]; /* increment, check for overflow and undo increment if so. */ /* We assume unsigned representation here! */ if (++(*histp) == 0) (*histp)--; } } } /* * Now we have the really interesting routines: selection of a colormap * given the completed histogram. * These routines work with a list of "boxes", each representing a rectangular * subset of the input color space (to histogram precision). */ typedef struct { /* The bounds of the box (inclusive); expressed as histogram indexes */ int c0min, c0max; int c1min, c1max; int c2min, c2max; /* The number of nonzero histogram cells within this box */ long colorcount; } box; typedef box * boxptr; static boxptr boxlist; /* array with room for desired # of boxes */ static int numboxes; /* number of boxes currently in boxlist */ static JSAMPARRAY my_colormap; /* the finished colormap (in YCbCr space) */ LOCAL boxptr find_biggest_color_pop (void) /* Find the splittable box with the largest color population */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register long max = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > max) { if (boxp->c0max > boxp->c0min || boxp->c1max > boxp->c1min || boxp->c2max > boxp->c2min) { which = boxp; max = boxp->colorcount; } } } return which; } LOCAL boxptr find_biggest_volume (void) /* Find the splittable box with the largest (scaled) volume */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register INT32 max = 0; register INT32 norm, c0,c1,c2; boxptr which = NULL; /* We use 2-norm rather than real volume here. * Some care is needed since the differences are expressed in * histogram-cell units; if HIST_Y_BITS != HIST_C_BITS, we have to * adjust the scaling to get the proper scaled-YCbCr-space distance. * This code won't work right if HIST_Y_BITS < HIST_C_BITS, * but that shouldn't ever be true. * Note norm > 0 iff box is splittable, so need not check separately. */ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { c0 = (boxp->c0max - boxp->c0min) * Y_SCALE; c1 = (boxp->c1max - boxp->c1min) << (HIST_Y_BITS-HIST_C_BITS); c2 = (boxp->c2max - boxp->c2min) << (HIST_Y_BITS-HIST_C_BITS); norm = c0*c0 + c1*c1 + c2*c2; if (norm > max) { which = boxp; max = norm; } } return which; } LOCAL void update_box (boxptr boxp) /* Shrink the min/max bounds of a box to enclose only nonzero elements, */ /* and recompute its population */ { histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long ccount; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0min = c0min = c0; goto have_c0min; } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0max = c0max = c0; goto have_c0max; } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1min = c1min = c1; goto have_c1min; } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1max = c1max = c1; goto have_c1max; } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C_ELEMS) if (*histp != 0) { boxp->c2min = c2min = c2; goto have_c2min; } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C_ELEMS) if (*histp != 0) { boxp->c2max = c2max = c2; goto have_c2max; } } have_c2max: /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) if (*histp != 0) { ccount++; } } boxp->colorcount = ccount; } LOCAL void median_cut (int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; int c0,c1,c2,cmax; register boxptr b1,b2; while (numboxes < desired_colors) { /* Select box to split */ /* Current algorithm: by population for first half, then by volume */ if (numboxes*2 <= desired_colors) { b1 = find_biggest_color_pop(); } else { b1 = find_biggest_volume(); } if (b1 == NULL) /* no splittable boxes left! */ break; b2 = &boxlist[numboxes]; /* where new box will go */ /* Copy the color bounds to the new box. */ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; /* Choose which axis to split the box on. * Current algorithm: longest scaled axis. * See notes in find_biggest_volume about scaling... */ c0 = (b1->c0max - b1->c0min) * Y_SCALE; c1 = (b1->c1max - b1->c1min) << (HIST_Y_BITS-HIST_C_BITS); c2 = (b1->c2max - b1->c2min) << (HIST_Y_BITS-HIST_C_BITS); cmax = c0; n = 0; if (c1 > cmax) { cmax = c1; n = 1; } if (c2 > cmax) { n = 2; } /* Choose split point along selected axis, and update box bounds. * Current algorithm: split at halfway point. * (Since the box has been shrunk to minimum volume, * any split will produce two nonempty subboxes.) * Note that lb value is max for lower box, so must be < old max. */ switch (n) { case 0: lb = (b1->c0max + b1->c0min) / 2; b1->c0max = lb; b2->c0min = lb+1; break; case 1: lb = (b1->c1max + b1->c1min) / 2; b1->c1max = lb; b2->c1min = lb+1; break; case 2: lb = (b1->c2max + b1->c2min) / 2; b1->c2max = lb; b2->c2min = lb+1; break; } /* Update stats for boxes */ update_box(b1); update_box(b2); numboxes++; } } LOCAL void compute_color (boxptr boxp, int icolor) /* Compute representative color for a box, put it in my_colormap[icolor] */ { /* Current algorithm: mean weighted by pixels (not colors) */ /* Note it is important to get the rounding correct! */ histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long count; long total = 0; long c0total = 0; long c1total = 0; long c2total = 0; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { if ((count = *histp++) != 0) { total += count; c0total += ((c0 << Y_SHIFT) + ((1<>1)) * count; c1total += ((c1 << C_SHIFT) + ((1<>1)) * count; c2total += ((c2 << C_SHIFT) + ((1<>1)) * count; } } } my_colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); my_colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); my_colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); } LOCAL void remap_colormap (decompress_info_ptr cinfo) /* Remap the internal colormap to the output colorspace */ { /* This requires a little trickery since color_convert expects to * deal with 3-D arrays (a 2-D sample array for each component). * We must promote the colormaps into one-row 3-D arrays. */ short ci; JSAMPARRAY input_hack[3]; JSAMPARRAY output_hack[10]; /* assume no more than 10 output components */ for (ci = 0; ci < 3; ci++) input_hack[ci] = &(my_colormap[ci]); for (ci = 0; ci < cinfo->color_out_comps; ci++) output_hack[ci] = &(cinfo->colormap[ci]); (*cinfo->methods->color_convert) (cinfo, 1, (long) cinfo->actual_number_of_colors, input_hack, output_hack); } LOCAL void select_colors (decompress_info_ptr cinfo) /* Master routine for color selection */ { int desired = cinfo->desired_number_of_colors; int i; /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->emethods->alloc_small) (desired * SIZEOF(box)); /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; boxlist[0].c0max = MAXJSAMPLE >> Y_SHIFT; boxlist[0].c1min = 0; boxlist[0].c1max = MAXJSAMPLE >> C_SHIFT; boxlist[0].c2min = 0; boxlist[0].c2max = MAXJSAMPLE >> C_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(& boxlist[0]); /* Perform median-cut to produce final box list */ median_cut(desired); /* Compute the representative color for each box, fill my_colormap[] */ for (i = 0; i < numboxes; i++) compute_color(& boxlist[i], i); cinfo->actual_number_of_colors = numboxes; /* Produce an output colormap in the desired output colorspace */ remap_colormap(cinfo); TRACEMS1(cinfo->emethods, 1, "Selected %d colors for quantization", numboxes); /* Done with the box list */ (*cinfo->emethods->free_small) ((void *) boxlist); } /* * These routines are concerned with the time-critical task of mapping input * colors to the nearest color in the selected colormap. * * We re-use the histogram space as an "inverse color map", essentially a * cache for the results of nearest-color searches. All colors within a * histogram cell will be mapped to the same colormap entry, namely the one * closest to the cell's center. This may not be quite the closest entry to * the actual input color, but it's almost as good. A zero in the cache * indicates we haven't found the nearest color for that cell yet; the array * is cleared to zeroes before starting the mapping pass. When we find the * nearest color for a cell, its colormap index plus one is recorded in the * cache for future use. The pass2 scanning routines call fill_inverse_cmap * when they need to use an unfilled entry in the cache. * * Our method of efficiently finding nearest colors is based on the "locally * sorted search" idea described by Heckbert and on the incremental distance * calculation described by Spencer W. Thomas in chapter III.1 of Graphics * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that * the distances from a given colormap entry to each cell of the histogram can * be computed quickly using an incremental method: the differences between * distances to adjacent cells themselves differ by a constant. This allows a * fairly fast implementation of the "brute force" approach of computing the * distance from every colormap entry to every histogram cell. Unfortunately, * it needs a work array to hold the best-distance-so-far for each histogram * cell (because the inner loop has to be over cells, not colormap entries). * The work array elements have to be INT32s, so the work array would need * 256Kb at our recommended precision. This is not feasible in DOS machines. * Another disadvantage of the brute force approach is that it computes * distances to every cell of the cubical histogram. When working with YCbCr * input, only about a quarter of the cube represents realizable colors, so * many of the cells will never be used and filling them is wasted effort. * * To get around these problems, we apply Thomas' method to compute the * nearest colors for only the cells within a small subbox of the histogram. * The work array need be only as big as the subbox, so the memory usage * problem is solved. A subbox is processed only when some cell in it is * referenced by the pass2 routines, so we will never bother with cells far * outside the realizable color volume. An additional advantage of this * approach is that we can apply Heckbert's locality criterion to quickly * eliminate colormap entries that are far away from the subbox; typically * three-fourths of the colormap entries are rejected by Heckbert's criterion, * and we need not compute their distances to individual cells in the subbox. * The speed of this approach is heavily influenced by the subbox size: too * small means too much overhead, too big loses because Heckbert's criterion * can't eliminate as many colormap entries. Empirically the best subbox * size seems to be about 1/512th of the histogram (1/8th in each direction). * * Thomas' article also describes a refined method which is asymptotically * faster than the brute-force method, but it is also far more complex and * cannot efficiently be applied to small subboxes. It is therefore not * useful for programs intended to be portable to DOS machines. On machines * with plenty of memory, filling the whole histogram in one shot with Thomas' * refined method might be faster than the present code --- but then again, * it might not be any faster, and it's certainly more complicated. */ #ifndef BOX_Y_LOG /* so you can override from Makefile */ #define BOX_Y_LOG (HIST_Y_BITS-3) /* log2(hist cells in update box, Y axis) */ #endif #ifndef BOX_C_LOG /* so you can override from Makefile */ #define BOX_C_LOG (HIST_C_BITS-3) /* log2(hist cells in update box, C axes) */ #endif #define BOX_Y_ELEMS (1<actual_number_of_colors; int maxc0, maxc1, maxc2; int centerc0, centerc1, centerc2; int i, x, ncolors; INT32 minmaxdist, min_dist, max_dist, tdist; INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ /* Compute true coordinates of update box's upper corner and center. * Actually we compute the coordinates of the center of the upper-corner * histogram cell, which are the upper bounds of the volume we care about. * Note that since ">>" rounds down, the "center" values may be closer to * min than to max; hence comparisons to them must be "<=", not "<". */ maxc0 = minc0 + ((1 << BOX_Y_SHIFT) - (1 << Y_SHIFT)); centerc0 = (minc0 + maxc0) >> 1; maxc1 = minc1 + ((1 << BOX_C_SHIFT) - (1 << C_SHIFT)); centerc1 = (minc1 + maxc1) >> 1; maxc2 = minc2 + ((1 << BOX_C_SHIFT) - (1 << C_SHIFT)); centerc2 = (minc2 + maxc2) >> 1; /* For each color in colormap, find: * 1. its minimum squared-distance to any point in the update box * (zero if color is within update box); * 2. its maximum squared-distance to any point in the update box. * Both of these can be found by considering only the corners of the box. * We save the minimum distance for each color in mindist[]; * only the smallest maximum distance is of interest. * Note we have to scale Y to get correct distance in scaled space. */ minmaxdist = 0x7FFFFFFFL; for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ x = GETJSAMPLE(my_colormap[0][i]); if (x < minc0) { tdist = (x - minc0) * Y_SCALE; min_dist = tdist*tdist; tdist = (x - maxc0) * Y_SCALE; max_dist = tdist*tdist; } else if (x > maxc0) { tdist = (x - maxc0) * Y_SCALE; min_dist = tdist*tdist; tdist = (x - minc0) * Y_SCALE; max_dist = tdist*tdist; } else { /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { tdist = (x - maxc0) * Y_SCALE; max_dist = tdist*tdist; } else { tdist = (x - minc0) * Y_SCALE; max_dist = tdist*tdist; } } x = GETJSAMPLE(my_colormap[1][i]); if (x < minc1) { tdist = x - minc1; min_dist += tdist*tdist; tdist = x - maxc1; max_dist += tdist*tdist; } else if (x > maxc1) { tdist = x - maxc1; min_dist += tdist*tdist; tdist = x - minc1; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { tdist = x - maxc1; max_dist += tdist*tdist; } else { tdist = x - minc1; max_dist += tdist*tdist; } } x = GETJSAMPLE(my_colormap[2][i]); if (x < minc2) { tdist = x - minc2; min_dist += tdist*tdist; tdist = x - maxc2; max_dist += tdist*tdist; } else if (x > maxc2) { tdist = x - maxc2; min_dist += tdist*tdist; tdist = x - minc2; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { tdist = x - maxc2; max_dist += tdist*tdist; } else { tdist = x - minc2; max_dist += tdist*tdist; } } mindist[i] = min_dist; /* save away the results */ if (max_dist < minmaxdist) minmaxdist = max_dist; } /* Now we know that no cell in the update box is more than minmaxdist * away from some colormap entry. Therefore, only colors that are * within minmaxdist of some part of the box need be considered. */ ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) colorlist[ncolors++] = (JSAMPLE) i; } return ncolors; } LOCAL void find_best_colors (decompress_info_ptr cinfo, int minc0, int minc1, int minc2, int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. * This routine uses Thomas' incremental distance calculation method to * find the distance from a colormap entry to successive cells in the box. */ { int ic0, ic1, ic2; int i, icolor; register INT32 * bptr; /* pointer into bestdist[] array */ JSAMPLE * cptr; /* pointer into bestcolor[] array */ INT32 dist0, dist1; /* initial distance values */ register INT32 dist2; /* current distance in inner loop */ INT32 xx0, xx1; /* distance increments */ register INT32 xx2; INT32 inc0, inc1, inc2; /* initial values for increments */ /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_Y_ELEMS * BOX_C_ELEMS * BOX_C_ELEMS]; /* Initialize best-distance for each cell of the update box */ bptr = bestdist; for (i = BOX_Y_ELEMS*BOX_C_ELEMS*BOX_C_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. * Note we have to scale Y to get correct distance in scaled space. */ /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_Y ((1 << Y_SHIFT) * Y_SCALE) #define STEP_C (1 << C_SHIFT) for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ inc0 = (minc0 - (int) GETJSAMPLE(my_colormap[0][icolor])) * Y_SCALE; dist0 = inc0*inc0; inc1 = minc1 - (int) GETJSAMPLE(my_colormap[1][icolor]); dist0 += inc1*inc1; inc2 = minc2 - (int) GETJSAMPLE(my_colormap[2][icolor]); dist0 += inc2*inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_Y) + STEP_Y * STEP_Y; inc1 = inc1 * (2 * STEP_C) + STEP_C * STEP_C; inc2 = inc2 * (2 * STEP_C) + STEP_C * STEP_C; /* Now loop over all cells in box, updating distance per Thomas method */ bptr = bestdist; cptr = bestcolor; xx0 = inc0; for (ic0 = BOX_Y_ELEMS-1; ic0 >= 0; ic0--) { dist1 = dist0; xx1 = inc1; for (ic1 = BOX_C_ELEMS-1; ic1 >= 0; ic1--) { dist2 = dist1; xx2 = inc2; for (ic2 = BOX_C_ELEMS-1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; *cptr = (JSAMPLE) icolor; } dist2 += xx2; xx2 += 2 * STEP_C * STEP_C; bptr++; cptr++; } dist1 += xx1; xx1 += 2 * STEP_C * STEP_C; } dist0 += xx0; xx0 += 2 * STEP_Y * STEP_Y; } } } LOCAL void fill_inverse_cmap (decompress_info_ptr cinfo, int c0, int c1, int c2) /* Fill the inverse-colormap entries in the update box that contains */ /* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ /* we can fill as many others as we wish.) */ { int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; register JSAMPLE * cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_Y_ELEMS * BOX_C_ELEMS * BOX_C_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_Y_LOG; c1 >>= BOX_C_LOG; c2 >>= BOX_C_LOG; /* Compute true coordinates of update box's origin corner. * Actually we compute the coordinates of the center of the corner * histogram cell, which are the lower bounds of the volume we care about. */ minc0 = (c0 << BOX_Y_SHIFT) + ((1 << Y_SHIFT) >> 1); minc1 = (c1 << BOX_C_SHIFT) + ((1 << C_SHIFT) >> 1); minc2 = (c2 << BOX_C_SHIFT) + ((1 << C_SHIFT) >> 1); /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_Y_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_C_LOG; c2 <<= BOX_C_LOG; cptr = bestcolor; for (ic0 = 0; ic0 < BOX_Y_ELEMS; ic0++) { for (ic1 = 0; ic1 < BOX_C_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_C_ELEMS; ic2++) { *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } } /* * These routines perform second-pass scanning of the image: map each pixel to * the proper colormap index, and output the indexes to the output file. * * output_workspace is a one-component array of pixel dimensions at least * as large as the input image strip; it can be used to hold the converted * pixels' colormap indexes. */ METHODDEF void pass2_nodither (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE image_data, JSAMPARRAY output_workspace) /* This version performs no dithering */ { register JSAMPROW ptr0, ptr1, ptr2, outptr; register histptr cachep; register int c0, c1, c2; int row; long col; long width = cinfo->image_width; /* Convert data to colormap indexes, which we save in output_workspace */ for (row = 0; row < num_rows; row++) { ptr0 = image_data[0][row]; ptr1 = image_data[1][row]; ptr2 = image_data[2][row]; outptr = output_workspace[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the cache */ c0 = GETJSAMPLE(*ptr0++) >> Y_SHIFT; c1 = GETJSAMPLE(*ptr1++) >> C_SHIFT; c2 = GETJSAMPLE(*ptr2++) >> C_SHIFT; cachep = & histogram[c0][c1][c2]; /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } } /* Emit converted rows to the output file */ (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, &output_workspace); } /* Declarations for Floyd-Steinberg dithering. * * Errors are accumulated into the array fserrors[], at a resolution of * 1/16th of a pixel count. The error at a given pixel is propagated * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * * We can get away with a single array (holding one row's worth of errors) * by using it to store the current row's errors at pixel columns not yet * processed, but the next row's errors at columns already processed. We * need only a few extra variables to hold the errors immediately around the * current column. (If we are lucky, those variables are in registers, but * even if not, they're probably cheaper to access than array elements are.) * * The fserrors[] array has (#columns + 2) entries; the extra entry at * each end saves us from special-casing the first and last pixels. * Each entry is three values long, one value for each color component. * * Note: on a wide image, we might not have enough room in a PC's near data * segment to hold the error array; so it is allocated with alloc_medium. */ #ifdef EIGHT_BIT_SAMPLES typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else typedef INT32 FSERROR; /* may need more than 16 bits */ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ static FSERRPTR fserrors; /* accumulated errors */ static boolean on_odd_row; /* flag to remember which row we are on */ METHODDEF void pass2_dither (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE image_data, JSAMPARRAY output_workspace) /* This version performs Floyd-Steinberg dithering */ { register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ JSAMPROW ptr0, ptr1, ptr2; /* => current input pixel */ JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing errorptr */ int row; long col; long width = cinfo->image_width; JSAMPLE *range_limit = cinfo->sample_range_limit; JSAMPROW colormap0 = my_colormap[0]; JSAMPROW colormap1 = my_colormap[1]; JSAMPROW colormap2 = my_colormap[2]; SHIFT_TEMPS /* Convert data to colormap indexes, which we save in output_workspace */ for (row = 0; row < num_rows; row++) { ptr0 = image_data[0][row]; ptr1 = image_data[1][row]; ptr2 = image_data[2][row]; outptr = output_workspace[row]; if (on_odd_row) { /* work right to left in this row */ ptr0 += width - 1; /* so point to rightmost pixel */ ptr1 += width - 1; ptr2 += width - 1; outptr += width - 1; dir = -1; dir3 = -3; errorptr = fserrors + (width+1)*3; /* point to entry after last column */ on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; dir3 = 3; errorptr = fserrors; /* point to entry before first real column */ on_odd_row = TRUE; /* flip for next time */ } /* Preset error values: no error propagated to first pixel from left */ cur0 = cur1 = cur2 = 0; /* and no error propagated to row below yet */ belowerr0 = belowerr1 = belowerr2 = 0; bpreverr0 = bpreverr1 = bpreverr2 = 0; for (col = width; col > 0; col--) { /* curN holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur0 += GETJSAMPLE(*ptr0); cur1 += GETJSAMPLE(*ptr1); cur2 += GETJSAMPLE(*ptr2); cur0 = GETJSAMPLE(range_limit[cur0]); cur1 = GETJSAMPLE(range_limit[cur1]); cur2 = GETJSAMPLE(range_limit[cur2]); /* Index into the cache with adjusted pixel value */ cachep = & histogram[cur0 >> Y_SHIFT][cur1 >> C_SHIFT][cur2 >> C_SHIFT]; /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, cur0>>Y_SHIFT, cur1>>C_SHIFT, cur2>>C_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; *outptr = (JSAMPLE) pixcode; /* Compute representation error for this pixel */ cur0 -= GETJSAMPLE(colormap0[pixcode]); cur1 -= GETJSAMPLE(colormap1[pixcode]); cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ { register LOCFSERROR bnexterr, delta; bnexterr = cur0; /* Process component 0 */ delta = cur0 * 2; cur0 += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr0 + cur0); cur0 += delta; /* form error * 5 */ bpreverr0 = belowerr0 + cur0; belowerr0 = bnexterr; cur0 += delta; /* form error * 7 */ bnexterr = cur1; /* Process component 1 */ delta = cur1 * 2; cur1 += delta; /* form error * 3 */ errorptr[1] = (FSERROR) (bpreverr1 + cur1); cur1 += delta; /* form error * 5 */ bpreverr1 = belowerr1 + cur1; belowerr1 = bnexterr; cur1 += delta; /* form error * 7 */ bnexterr = cur2; /* Process component 2 */ delta = cur2 * 2; cur2 += delta; /* form error * 3 */ errorptr[2] = (FSERROR) (bpreverr2 + cur2); cur2 += delta; /* form error * 5 */ bpreverr2 = belowerr2 + cur2; belowerr2 = bnexterr; cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ ptr0 += dir; /* Advance pixel pointers to next column */ ptr1 += dir; ptr2 += dir; outptr += dir; errorptr += dir3; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error values into the * final fserrors[] entry. Note we need not unload belowerrN because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ errorptr[1] = (FSERROR) bpreverr1; errorptr[2] = (FSERROR) bpreverr2; } /* Emit converted rows to the output file */ (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, &output_workspace); } /* * Initialize for two-pass color quantization. */ METHODDEF void color_quant_init (decompress_info_ptr cinfo) { int i; /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (cinfo->desired_number_of_colors < 8) ERREXIT(cinfo->emethods, "Cannot request less than 8 quantized colors"); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (cinfo->desired_number_of_colors > MAXNUMCOLORS) ERREXIT1(cinfo->emethods, "Cannot request more than %d quantized colors", MAXNUMCOLORS); /* Allocate and zero the histogram */ histogram = (hist3d) (*cinfo->emethods->alloc_small) (HIST_Y_ELEMS * SIZEOF(hist2d)); for (i = 0; i < HIST_Y_ELEMS; i++) { histogram[i] = (hist2d) (*cinfo->emethods->alloc_medium) (HIST_C_ELEMS*HIST_C_ELEMS * SIZEOF(histcell)); jzero_far((void FAR *) histogram[i], HIST_C_ELEMS*HIST_C_ELEMS * SIZEOF(histcell)); } /* Allocate storage for the internal and external colormaps. */ /* We do this now since it is FAR storage and may affect the memory */ /* manager's space calculations. */ my_colormap = (*cinfo->emethods->alloc_small_sarray) ((long) cinfo->desired_number_of_colors, (long) 3); cinfo->colormap = (*cinfo->emethods->alloc_small_sarray) ((long) cinfo->desired_number_of_colors, (long) cinfo->color_out_comps); /* Allocate Floyd-Steinberg workspace if necessary */ /* This isn't needed until pass 2, but again it is FAR storage. */ if (cinfo->use_dithering) { size_t arraysize = (size_t) ((cinfo->image_width + 2L) * (3 * SIZEOF(FSERROR))); fserrors = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); /* Initialize the propagated errors to zero. */ jzero_far((void FAR *) fserrors, arraysize); on_odd_row = FALSE; } /* Indicate number of passes needed, excluding the prescan pass. */ cinfo->total_passes++; /* I always use one pass */ } /* * Perform two-pass quantization: rescan the image data and output the * converted data via put_color_map and put_pixel_rows. * The source_method is a routine that can scan the image data; it can * be called as many times as desired. The processing routine called by * source_method has the same interface as color_quantize does in the * one-pass case, except it must call put_pixel_rows itself. (This allows * me to use multiple passes in which earlier passes don't output anything.) */ METHODDEF void color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method) { int i; /* Select the representative colors */ select_colors(cinfo); /* Pass the external colormap to the output module. */ /* NB: the output module may continue to use the colormap until shutdown. */ (*cinfo->methods->put_color_map) (cinfo, cinfo->actual_number_of_colors, cinfo->colormap); /* Re-zero the histogram so pass 2 can use it as nearest-color cache */ for (i = 0; i < HIST_Y_ELEMS; i++) { jzero_far((void FAR *) histogram[i], HIST_C_ELEMS*HIST_C_ELEMS * SIZEOF(histcell)); } /* Perform pass 2 */ if (cinfo->use_dithering) (*source_method) (cinfo, pass2_dither); else (*source_method) (cinfo, pass2_nodither); } /* * Finish up at the end of the file. */ METHODDEF void color_quant_term (decompress_info_ptr cinfo) { /* no work (we let free_all release the histogram/cache and colormaps) */ /* Note that we *mustn't* free the external colormap before free_all, */ /* since output module may use it! */ } /* * Map some rows of pixels to the output colormapped representation. * Not used in two-pass case. */ METHODDEF void color_quantize (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data) { ERREXIT(cinfo->emethods, "Should not get here!"); } /* * The method selection routine for 2-pass color quantization. */ GLOBAL void jsel2quantize (decompress_info_ptr cinfo) { if (cinfo->two_pass_quantize) { /* Make sure jdmaster didn't give me a case I can't handle */ if (cinfo->num_components != 3 || cinfo->jpeg_color_space != CS_YCbCr) ERREXIT(cinfo->emethods, "2-pass quantization only handles YCbCr input"); cinfo->methods->color_quant_init = color_quant_init; cinfo->methods->color_quant_prescan = color_quant_prescan; cinfo->methods->color_quant_doit = color_quant_doit; cinfo->methods->color_quant_term = color_quant_term; cinfo->methods->color_quantize = color_quantize; /* Quantized grayscale output is normally done by jquant1.c (which will do * a much better job of it). But if the program is configured with only * 2-pass quantization, then I have to do the job. In this situation, * jseldcolor's clearing of the Cb/Cr component_needed flags is incorrect, * because I will look at those components before conversion. */ cinfo->cur_comp_info[1]->component_needed = TRUE; cinfo->cur_comp_info[2]->component_needed = TRUE; } } #endif /* QUANT_2PASS_SUPPORTED */ = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets thxloadimage.4.1/jpeg/jrdgif.c 644 221 144 50000 5307154634 11116 /* * jrdgif.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in GIF format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; input_init may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed GIF format). * * These routines are invoked via the methods get_input_row * and input_init/term. */ /* * This code is loosely based on giftoppm from the PBMPLUS distribution * of Feb. 1991. That file contains the following copyright notice: * +-------------------------------------------------------------------+ * | Copyright 1990, David Koblas. | * | Permission to use, copy, modify, and distribute this software | * | and its documentation for any purpose and without fee is hereby | * | granted, provided that the above copyright notice appear in all | * | copies and that both that copyright notice and this permission | * | notice appear in supporting documentation. This software is | * | provided "as is" without express or implied warranty. | * +-------------------------------------------------------------------+ * * We are also required to state that * "The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated." */ #include "jinclude.h" #ifdef GIF_SUPPORTED #define MAXCOLORMAPSIZE 256 /* max # of colors in a GIF colormap */ #define NUMCOLORS 3 /* # of colors */ #define CM_RED 0 /* color component numbers */ #define CM_GREEN 1 #define CM_BLUE 2 static JSAMPARRAY colormap; /* the colormap to use */ /* colormap[i][j] = value of i'th color component for pixel value j */ #define MAX_LZW_BITS 12 /* maximum LZW code size */ #define LZW_TABLE_SIZE (1< table of prefix symbols */ static UINT8 FAR *symbol_tail; /* => table of suffix bytes */ static UINT8 FAR *symbol_stack; /* stack for symbol expansions */ static UINT8 FAR *sp; /* stack pointer */ /* Static state for interlaced image processing */ static boolean is_interlaced; /* TRUE if have interlaced image */ static big_sarray_ptr interlaced_image; /* full image in interlaced order */ static long cur_row_number; /* need to know actual row number */ static long pass2_offset; /* # of pixel rows in pass 1 */ static long pass3_offset; /* # of pixel rows in passes 1&2 */ static long pass4_offset; /* # of pixel rows in passes 1,2,3 */ /* Forward declarations */ METHODDEF void load_interlaced_image PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row)); METHODDEF void get_interlaced_row PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row)); LOCAL int ReadByte (compress_info_ptr cinfo) /* Read next byte from GIF file */ { register FILE * infile = cinfo->input_file; int c; if ((c = getc(infile)) == EOF) ERREXIT(cinfo->emethods, "Premature EOF in GIF file"); return c; } LOCAL int GetDataBlock (compress_info_ptr cinfo, char *buf) /* Read a GIF data block, which has a leading count byte */ /* A zero-length block marks the end of a data block sequence */ { int count; count = ReadByte(cinfo); if (count > 0) { if (! ReadOK(cinfo->input_file, buf, count)) ERREXIT(cinfo->emethods, "Premature EOF in GIF file"); } return count; } LOCAL void SkipDataBlocks (compress_info_ptr cinfo) /* Skip a series of data blocks, until a block terminator is found */ { char buf[256]; while (GetDataBlock(cinfo, buf) > 0) /* skip */; } LOCAL void ReInitLZW (void) /* (Re)initialize LZW state; shared code for startup and Clear processing */ { code_size = input_code_size+1; limit_code = clear_code << 1; /* 2^code_size */ max_code = clear_code + 2; /* first unused code value */ sp = symbol_stack; /* init stack to empty */ } LOCAL void InitLZWCode (void) /* Initialize for a series of LZWReadByte (and hence GetCode) calls */ { /* GetCode initialization */ last_byte = 2; /* make safe to "recopy last two bytes" */ last_bit = 0; /* nothing in the buffer */ cur_bit = 0; /* force buffer load on first call */ out_of_blocks = FALSE; /* LZWReadByte initialization */ clear_code = 1 << input_code_size; /* compute special code values */ end_code = clear_code + 1; /* note that these do not change */ first_time = TRUE; ReInitLZW(); } LOCAL int GetCode (compress_info_ptr cinfo) /* Fetch the next code_size bits from the GIF data */ /* We assume code_size is less than 16 */ { register INT32 accum; int offs, ret, count; if ( (cur_bit+code_size) > last_bit) { /* Time to reload the buffer */ if (out_of_blocks) { WARNMS(cinfo->emethods, "Ran out of GIF bits"); return end_code; /* fake something useful */ } /* preserve last two bytes of what we have -- assume code_size <= 16 */ code_buf[0] = code_buf[last_byte-2]; code_buf[1] = code_buf[last_byte-1]; /* Load more bytes; set flag if we reach the terminator block */ if ((count = GetDataBlock(cinfo, &code_buf[2])) == 0) { out_of_blocks = TRUE; WARNMS(cinfo->emethods, "Ran out of GIF bits"); return end_code; /* fake something useful */ } /* Reset counters */ cur_bit = (cur_bit - last_bit) + 16; last_byte = 2 + count; last_bit = last_byte * 8; } /* Form up next 24 bits in accum */ offs = cur_bit >> 3; /* byte containing cur_bit */ #ifdef CHAR_IS_UNSIGNED accum = code_buf[offs+2]; accum <<= 8; accum |= code_buf[offs+1]; accum <<= 8; accum |= code_buf[offs]; #else accum = code_buf[offs+2] & 0xFF; accum <<= 8; accum |= code_buf[offs+1] & 0xFF; accum <<= 8; accum |= code_buf[offs] & 0xFF; #endif /* Right-align cur_bit in accum, then mask off desired number of bits */ accum >>= (cur_bit & 7); ret = ((int) accum) & ((1 << code_size) - 1); cur_bit += code_size; return ret; } LOCAL int LZWReadByte (compress_info_ptr cinfo) /* Read an LZW-compressed byte */ { static int oldcode; /* previous LZW symbol */ static int firstcode; /* first byte of oldcode's expansion */ register int code; /* current working code */ int incode; /* saves actual input code */ /* First time, just eat the expected Clear code(s) and return next code, */ /* which is expected to be a raw byte. */ if (first_time) { first_time = FALSE; code = clear_code; /* enables sharing code with Clear case */ } else { /* If any codes are stacked from a previously read symbol, return them */ if (sp > symbol_stack) return (int) *(--sp); /* Time to read a new symbol */ code = GetCode(cinfo); } if (code == clear_code) { /* Reinit static state, swallow any extra Clear codes, and */ /* return next code, which is expected to be a raw byte. */ ReInitLZW(); do { code = GetCode(cinfo); } while (code == clear_code); if (code > clear_code) { /* make sure it is a raw byte */ WARNMS(cinfo->emethods, "Corrupt data in GIF file"); code = 0; /* use something valid */ } firstcode = oldcode = code; /* make firstcode, oldcode valid! */ return code; } if (code == end_code) { /* Skip the rest of the image, unless GetCode already read terminator */ if (! out_of_blocks) { SkipDataBlocks(cinfo); out_of_blocks = TRUE; } /* Complain that there's not enough data */ WARNMS(cinfo->emethods, "Premature end of GIF image"); /* Pad data with 0's */ return 0; /* fake something usable */ } /* Got normal raw byte or LZW symbol */ incode = code; /* save for a moment */ if (code >= max_code) { /* special case for not-yet-defined symbol */ /* code == max_code is OK; anything bigger is bad data */ if (code > max_code) { WARNMS(cinfo->emethods, "Corrupt data in GIF file"); incode = 0; /* prevent creation of loops in symbol table */ } *sp++ = (UINT8) firstcode; /* it will be defined as oldcode/firstcode */ code = oldcode; } /* If it's a symbol, expand it into the stack */ while (code >= clear_code) { *sp++ = symbol_tail[code]; /* tail of symbol: a simple byte value */ code = symbol_head[code]; /* head of symbol: another LZW symbol */ } /* At this point code just represents a raw byte */ firstcode = code; /* save for possible future use */ /* If there's room in table, */ if ((code = max_code) < LZW_TABLE_SIZE) { /* Define a new symbol = prev sym + head of this sym's expansion */ symbol_head[code] = oldcode; symbol_tail[code] = (UINT8) firstcode; max_code++; /* Is it time to increase code_size? */ if ((max_code >= limit_code) && (code_size < MAX_LZW_BITS)) { code_size++; limit_code <<= 1; /* keep equal to 2^code_size */ } } oldcode = incode; /* save last input symbol for future use */ return firstcode; /* return first byte of symbol's expansion */ } LOCAL void ReadColorMap (compress_info_ptr cinfo, int cmaplen, JSAMPARRAY cmap) /* Read a GIF colormap */ { int i; for (i = 0; i < cmaplen; i++) { cmap[CM_RED][i] = (JSAMPLE) ReadByte(cinfo); cmap[CM_GREEN][i] = (JSAMPLE) ReadByte(cinfo); cmap[CM_BLUE][i] = (JSAMPLE) ReadByte(cinfo); } } LOCAL void DoExtension (compress_info_ptr cinfo) /* Process an extension block */ /* Currently we ignore 'em all */ { int extlabel; /* Read extension label byte */ extlabel = ReadByte(cinfo); TRACEMS1(cinfo->emethods, 1, "Ignoring GIF extension block of type 0x%02x", extlabel); /* Skip the data block(s) associated with the extension */ SkipDataBlocks(cinfo); } /* * Read the file header; return image size and component count. */ METHODDEF void input_init (compress_info_ptr cinfo) { char hdrbuf[10]; /* workspace for reading control blocks */ UINT16 width, height; /* image dimensions */ int colormaplen, aspectRatio; int c; /* Allocate space to store the colormap */ colormap = (*cinfo->emethods->alloc_small_sarray) ((long) MAXCOLORMAPSIZE, (long) NUMCOLORS); /* Read and verify GIF Header */ if (! ReadOK(cinfo->input_file, hdrbuf, 6)) ERREXIT(cinfo->emethods, "Not a GIF file"); if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') ERREXIT(cinfo->emethods, "Not a GIF file"); /* Check for expected version numbers. * If unknown version, give warning and try to process anyway; * this is per recommendation in GIF89a standard. */ if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') && (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a')) TRACEMS3(cinfo->emethods, 1, "Warning: unexpected GIF version number '%c%c%c'", hdrbuf[3], hdrbuf[4], hdrbuf[5]); /* Read and decipher Logical Screen Descriptor */ if (! ReadOK(cinfo->input_file, hdrbuf, 7)) ERREXIT(cinfo->emethods, "Premature EOF in GIF file"); width = LM_to_uint(hdrbuf[0],hdrbuf[1]); height = LM_to_uint(hdrbuf[2],hdrbuf[3]); colormaplen = 2 << (hdrbuf[4] & 0x07); /* we ignore the color resolution, sort flag, and background color index */ aspectRatio = hdrbuf[6] & 0xFF; if (aspectRatio != 0 && aspectRatio != 49) TRACEMS(cinfo->emethods, 1, "Warning: nonsquare pixels in input"); /* Read global colormap if header indicates it is present */ if (BitSet(hdrbuf[4], COLORMAPFLAG)) ReadColorMap(cinfo, colormaplen, colormap); /* Scan until we reach start of desired image. * We don't currently support skipping images, but could add it easily. */ for (;;) { c = ReadByte(cinfo); if (c == ';') /* GIF terminator?? */ ERREXIT(cinfo->emethods, "Too few images in GIF file"); if (c == '!') { /* Extension */ DoExtension(cinfo); continue; } if (c != ',') { /* Not an image separator? */ TRACEMS1(cinfo->emethods, 1, "Bogus input char 0x%02x, ignoring", c); continue; } /* Read and decipher Local Image Descriptor */ if (! ReadOK(cinfo->input_file, hdrbuf, 9)) ERREXIT(cinfo->emethods, "Premature EOF in GIF file"); /* we ignore top/left position info, also sort flag */ width = LM_to_uint(hdrbuf[4],hdrbuf[5]); height = LM_to_uint(hdrbuf[6],hdrbuf[7]); is_interlaced = BitSet(hdrbuf[8], INTERLACE); /* Read local colormap if header indicates it is present */ /* Note: if we wanted to support skipping images, */ /* we'd need to skip rather than read colormap for ignored images */ if (BitSet(hdrbuf[8], COLORMAPFLAG)) { colormaplen = 2 << (hdrbuf[8] & 0x07); ReadColorMap(cinfo, colormaplen, colormap); } input_code_size = ReadByte(cinfo); /* get minimum-code-size byte */ if (input_code_size < 2 || input_code_size >= MAX_LZW_BITS) ERREXIT1(cinfo->emethods, "Bogus codesize %d", input_code_size); /* Reached desired image, so break out of loop */ /* If we wanted to skip this image, */ /* we'd call SkipDataBlocks and then continue the loop */ break; } /* Prepare to read selected image: first initialize LZW decompressor */ symbol_head = (UINT16 FAR *) (*cinfo->emethods->alloc_medium) (LZW_TABLE_SIZE * SIZEOF(UINT16)); symbol_tail = (UINT8 FAR *) (*cinfo->emethods->alloc_medium) (LZW_TABLE_SIZE * SIZEOF(UINT8)); symbol_stack = (UINT8 FAR *) (*cinfo->emethods->alloc_medium) (LZW_TABLE_SIZE * SIZEOF(UINT8)); InitLZWCode(); /* * If image is interlaced, we read it into a full-size sample array, * decompressing as we go; then get_input_row selects rows from the * sample array in the proper order. */ if (is_interlaced) { /* We request the big array now, but can't access it until the pipeline * controller causes all the big arrays to be allocated. Hence, the * actual work of reading the image is postponed until the first call * of get_input_row. */ interlaced_image = (*cinfo->emethods->request_big_sarray) ((long) width, (long) height, 1L); cinfo->methods->get_input_row = load_interlaced_image; cinfo->total_passes++; /* count file reading as separate pass */ } /* Return info about the image. */ cinfo->input_components = NUMCOLORS; cinfo->in_color_space = CS_RGB; cinfo->image_width = width; cinfo->image_height = height; cinfo->data_precision = 8; /* always, even if 12-bit JSAMPLEs */ TRACEMS3(cinfo->emethods, 1, "%ux%ux%d GIF image", (unsigned int) width, (unsigned int) height, colormaplen); } /* * Read one row of pixels. * This version is used for noninterlaced GIF images: * we read directly from the GIF file. */ METHODDEF void get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { register JSAMPROW ptr0, ptr1, ptr2; register long col; register int c; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { c = LZWReadByte(cinfo); *ptr0++ = colormap[CM_RED][c]; *ptr1++ = colormap[CM_GREEN][c]; *ptr2++ = colormap[CM_BLUE][c]; } } /* * Read one row of pixels. * This version is used for the first call on get_input_row when * reading an interlaced GIF file: we read the whole image into memory. */ METHODDEF void load_interlaced_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { JSAMPARRAY image_ptr; register JSAMPROW sptr; register long col; long row; /* Read the interlaced image into the big array we've created. */ for (row = 0; row < cinfo->image_height; row++) { (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height); image_ptr = (*cinfo->emethods->access_big_sarray) (interlaced_image, row, TRUE); sptr = image_ptr[0]; for (col = cinfo->image_width; col > 0; col--) { *sptr++ = (JSAMPLE) LZWReadByte(cinfo); } } cinfo->completed_passes++; /* Replace method pointer so subsequent calls don't come here. */ cinfo->methods->get_input_row = get_interlaced_row; /* Initialize for get_interlaced_row, and perform first call on it. */ cur_row_number = 0; pass2_offset = (cinfo->image_height + 7L) / 8L; pass3_offset = pass2_offset + (cinfo->image_height + 3L) / 8L; pass4_offset = pass3_offset + (cinfo->image_height + 1L) / 4L; get_interlaced_row(cinfo, pixel_row); } /* * Read one row of pixels. * This version is used for interlaced GIF images: * we read from the big in-memory image. */ METHODDEF void get_interlaced_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { JSAMPARRAY image_ptr; register JSAMPROW sptr, ptr0, ptr1, ptr2; register long col; register int c; long irow; /* Figure out which row of interlaced image is needed, and access it. */ switch ((int) (cur_row_number & 7L)) { case 0: /* first-pass row */ irow = cur_row_number >> 3; break; case 4: /* second-pass row */ irow = (cur_row_number >> 3) + pass2_offset; break; case 2: /* third-pass row */ case 6: irow = (cur_row_number >> 2) + pass3_offset; break; default: /* fourth-pass row */ irow = (cur_row_number >> 1) + pass4_offset; break; } image_ptr = (*cinfo->emethods->access_big_sarray) (interlaced_image, irow, FALSE); /* Scan the row, expand colormap, and output */ sptr = image_ptr[0]; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { c = GETJSAMPLE(*sptr++); *ptr0++ = colormap[CM_RED][c]; *ptr1++ = colormap[CM_GREEN][c]; *ptr2++ = colormap[CM_BLUE][c]; } cur_row_number++; /* for next time */ } /* * Finish up at the end of the file. */ METHODDEF void input_term (compress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /* * The method selection routine for GIF format input. * Note that this must be called by the user interface before calling * jpeg_compress. If multiple input formats are supported, the * user interface is responsible for discovering the file format and * calling the appropriate method selection routine. */ GLOBAL void jselrgif (compress_info_ptr cinfo) { cinfo->methods->input_init = input_init; cinfo->methods->get_input_row = get_input_row; /* assume uninterlaced */ cinfo->methods->input_term = input_term; } #endif /* GIF_SUPPORTED */ xloadimage.4.1/jpeg/jrdjfif.c 644 221 144 56446 5340454637 11316 /* * jrdjfif.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to decode standard JPEG file headers/markers. * This code will handle "raw JPEG" and JFIF-convention JPEG files. * * You can also use this module to decode a raw-JPEG or JFIF-standard data * stream that is embedded within a larger file. To do that, you must * position the file to the JPEG SOI marker (0xFF/0xD8) that begins the * data sequence to be decoded. If nothing better is possible, you can scan * the file until you see the SOI marker, then use JUNGETC to push it back. * * This module relies on the JGETC macro and the read_jpeg_data method (which * is provided by the user interface) to read from the JPEG data stream. * Therefore, this module is not dependent on any particular assumption about * the data source; it need not be a stdio stream at all. (This fact does * NOT carry over to more complex JPEG file formats such as JPEG-in-TIFF; * those format control modules may well need to assume stdio input.) * * These routines are invoked via the methods read_file_header, * read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer. */ #include "jinclude.h" #ifdef JFIF_SUPPORTED typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* * Reload the input buffer after it's been emptied, and return the next byte. * This is exported for direct use by the entropy decoder. * See the JGETC macro for calling conditions. Note in particular that * read_jpeg_data may NOT return EOF. If no more data is available, it must * exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker). * For error recovery purposes, synthesizing an EOI marker is probably best. * * For this header control module, read_jpeg_data is supplied by the * user interface. However, header formats that require random access * to the input file would need to supply their own code. This code is * left here to indicate what is required. */ #if 0 /* not needed in this module */ METHODDEF int read_jpeg_data (decompress_info_ptr cinfo) { cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET; cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file, cinfo->next_input_byte, JPEG_BUF_SIZE); if (cinfo->bytes_in_buffer <= 0) { WARNMS(cinfo->emethods, "Premature EOF in JPEG file"); cinfo->next_input_byte[0] = (char) 0xFF; cinfo->next_input_byte[1] = (char) M_EOI; cinfo->bytes_in_buffer = 2; } return JGETC(cinfo); } #endif /* * Routines to parse JPEG markers & save away the useful info. */ LOCAL INT32 get_2bytes (decompress_info_ptr cinfo) /* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */ { INT32 a; a = JGETC(cinfo); return (a << 8) + JGETC(cinfo); } LOCAL void skip_variable (decompress_info_ptr cinfo, int code) /* Skip over an unknown or uninteresting variable-length marker */ { INT32 length; length = get_2bytes(cinfo); TRACEMS2(cinfo->emethods, 1, "Skipping marker 0x%02x, length %u", code, (int) length); for (length -= 2; length > 0; length--) (void) JGETC(cinfo); } LOCAL void get_dht (decompress_info_ptr cinfo) /* Process a DHT marker */ { INT32 length; UINT8 bits[17]; UINT8 huffval[256]; int i, index, count; HUFF_TBL **htblptr; length = get_2bytes(cinfo)-2; while (length > 0) { index = JGETC(cinfo); TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index); bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { bits[i] = (UINT8) JGETC(cinfo); count += bits[i]; } length -= 1 + 16; TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d", bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]); TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d", bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]); if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo->emethods, "Bogus DHT counts"); for (i = 0; i < count; i++) huffval[i] = (UINT8) JGETC(cinfo); length -= count; if (index & 0x10) { /* AC table definition */ index -= 0x10; htblptr = &cinfo->ac_huff_tbl_ptrs[index]; } else { /* DC table definition */ htblptr = &cinfo->dc_huff_tbl_ptrs[index]; } if (index < 0 || index >= NUM_HUFF_TBLS) ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index); if (*htblptr == NULL) *htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL)); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } } LOCAL void get_dac (decompress_info_ptr cinfo) /* Process a DAC marker */ { INT32 length; int index, val; length = get_2bytes(cinfo)-2; while (length > 0) { index = JGETC(cinfo); val = JGETC(cinfo); TRACEMS2(cinfo->emethods, 1, "Define Arithmetic Table 0x%02x: 0x%02x", index, val); if (index < 0 || index >= (2*NUM_ARITH_TBLS)) ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index); if (index >= NUM_ARITH_TBLS) { /* define AC table */ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; } else { /* define DC table */ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); cinfo->arith_dc_U[index] = (UINT8) (val >> 4); if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val); } length -= 2; } } LOCAL void get_dqt (decompress_info_ptr cinfo) /* Process a DQT marker */ { INT32 length; int n, i, prec; UINT16 tmp; QUANT_TBL_PTR quant_ptr; length = get_2bytes(cinfo) - 2; while (length > 0) { n = JGETC(cinfo); prec = n >> 4; n &= 0x0F; TRACEMS2(cinfo->emethods, 1, "Define Quantization Table %d precision %d", n, prec); if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo->emethods, "Bogus table number %d", n); if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = (QUANT_TBL_PTR) (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL)); quant_ptr = cinfo->quant_tbl_ptrs[n]; for (i = 0; i < DCTSIZE2; i++) { tmp = JGETC(cinfo); if (prec) tmp = (tmp<<8) + JGETC(cinfo); quant_ptr[i] = tmp; } for (i = 0; i < DCTSIZE2; i += 8) { TRACEMS8(cinfo->emethods, 2, " %4u %4u %4u %4u %4u %4u %4u %4u", quant_ptr[i ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3], quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]); } length -= DCTSIZE2+1; if (prec) length -= DCTSIZE2; } } LOCAL void get_dri (decompress_info_ptr cinfo) /* Process a DRI marker */ { if (get_2bytes(cinfo) != 4) ERREXIT(cinfo->emethods, "Bogus length in DRI"); cinfo->restart_interval = (UINT16) get_2bytes(cinfo); TRACEMS1(cinfo->emethods, 1, "Define Restart Interval %u", cinfo->restart_interval); } LOCAL void get_app0 (decompress_info_ptr cinfo) /* Process an APP0 marker */ { #define JFIF_LEN 14 INT32 length; UINT8 b[JFIF_LEN]; int buffp; length = get_2bytes(cinfo) - 2; /* See if a JFIF APP0 marker is present */ if (length >= JFIF_LEN) { for (buffp = 0; buffp < JFIF_LEN; buffp++) b[buffp] = (UINT8) JGETC(cinfo); length -= JFIF_LEN; if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) { /* Found JFIF APP0 marker: check version */ /* Major version must be 1 */ if (b[5] != 1) ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d", b[5], b[6]); /* Minor version should be 0..2, but try to process anyway if newer */ if (b[6] > 2) TRACEMS2(cinfo->emethods, 1, "Warning: unknown JFIF revision number %d.%02d", b[5], b[6]); /* Save info */ cinfo->density_unit = b[7]; cinfo->X_density = (b[8] << 8) + b[9]; cinfo->Y_density = (b[10] << 8) + b[11]; /* Assume colorspace is YCbCr, unless UI has overridden me */ if (cinfo->jpeg_color_space == CS_UNKNOWN) cinfo->jpeg_color_space = CS_YCbCr; TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d %d", cinfo->X_density, cinfo->Y_density, cinfo->density_unit); if (b[12] | b[13]) TRACEMS2(cinfo->emethods, 1, " with %d x %d thumbnail image", b[12], b[13]); if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3)) TRACEMS1(cinfo->emethods, 1, "Warning: thumbnail image size does not match data length %u", (int) length); } else { TRACEMS1(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF), length %u", (int) length + JFIF_LEN); } } else { TRACEMS1(cinfo->emethods, 1, "Short APP0 marker, length %u", (int) length); } while (--length >= 0) /* skip any remaining data */ (void) JGETC(cinfo); } LOCAL void get_com (decompress_info_ptr cinfo) /* Process a COM marker */ /* Actually we just pass this off to an application-supplied routine */ { INT32 length; length = get_2bytes(cinfo) - 2; TRACEMS1(cinfo->emethods, 1, "Comment, length %u", (int) length); (*cinfo->methods->process_comment) (cinfo, (long) length); } LOCAL void get_sof (decompress_info_ptr cinfo, int code) /* Process a SOFn marker */ { INT32 length; short ci; int c; jpeg_component_info * compptr; length = get_2bytes(cinfo); cinfo->data_precision = JGETC(cinfo); cinfo->image_height = get_2bytes(cinfo); cinfo->image_width = get_2bytes(cinfo); cinfo->num_components = JGETC(cinfo); TRACEMS4(cinfo->emethods, 1, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d", code, (int) cinfo->image_width, (int) cinfo->image_height, cinfo->num_components); /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)"); #ifdef EIGHT_BIT_SAMPLES if (cinfo->data_precision != 8) ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); #endif #ifdef TWELVE_BIT_SAMPLES if (cinfo->data_precision != 12) /* this needs more thought?? */ ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); #endif #ifdef SIXTEEN_BIT_SAMPLES if (cinfo->data_precision != 16) /* this needs more thought?? */ ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); #endif if (length != (cinfo->num_components * 3 + 8)) ERREXIT(cinfo->emethods, "Bogus SOF length"); cinfo->comp_info = (jpeg_component_info *) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0; ci < cinfo->num_components; ci++) { compptr = &cinfo->comp_info[ci]; compptr->component_index = ci; compptr->component_id = JGETC(cinfo); c = JGETC(cinfo); compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; compptr->quant_tbl_no = JGETC(cinfo); compptr->component_needed = TRUE; /* assume all components are wanted */ TRACEMS4(cinfo->emethods, 1, " Component %d: %dhx%dv q=%d", compptr->component_id, compptr->h_samp_factor, compptr->v_samp_factor, compptr->quant_tbl_no); } } LOCAL void get_sos (decompress_info_ptr cinfo) /* Process a SOS marker */ { INT32 length; int i, ci, n, c, cc; jpeg_component_info * compptr; length = get_2bytes(cinfo); n = JGETC(cinfo); /* Number of components */ cinfo->comps_in_scan = n; length -= 3; if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Bogus SOS length"); TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n); for (i = 0; i < n; i++) { cc = JGETC(cinfo); c = JGETC(cinfo); length -= 2; for (ci = 0; ci < cinfo->num_components; ci++) if (cc == cinfo->comp_info[ci].component_id) break; if (ci >= cinfo->num_components) ERREXIT(cinfo->emethods, "Invalid component number in SOS"); compptr = &cinfo->comp_info[ci]; cinfo->cur_comp_info[i] = compptr; compptr->dc_tbl_no = (c >> 4) & 15; compptr->ac_tbl_no = (c ) & 15; TRACEMS3(cinfo->emethods, 1, " c%d: [dc=%d ac=%d]", cc, compptr->dc_tbl_no, compptr->ac_tbl_no); } while (length > 0) { (void) JGETC(cinfo); length--; } } LOCAL void get_soi (decompress_info_ptr cinfo) /* Process an SOI marker */ { int i; TRACEMS(cinfo->emethods, 1, "Start of Image"); /* Reset all parameters that are defined to be reset by SOI */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } cinfo->restart_interval = 0; cinfo->density_unit = 0; /* set default JFIF APP0 values */ cinfo->X_density = 1; cinfo->Y_density = 1; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */ } LOCAL int next_marker (decompress_info_ptr cinfo) /* Find the next JPEG marker */ /* Note that the output might not be a valid marker code, */ /* but it will never be 0 or FF */ { int c, nbytes; nbytes = 0; do { do { /* skip any non-FF bytes */ nbytes++; c = JGETC(cinfo); } while (c != 0xFF); do { /* skip any duplicate FFs */ /* we don't increment nbytes here since extra FFs are legal */ c = JGETC(cinfo); } while (c == 0xFF); } while (c == 0); /* repeat if it was a stuffed FF/00 */ if (nbytes != 1) WARNMS2(cinfo->emethods, "Corrupt JPEG data: %d extraneous bytes before marker 0x%02x", nbytes-1, c); return c; } LOCAL int process_tables (decompress_info_ptr cinfo) /* Scan and process JPEG markers that can appear in any order */ /* Return when an SOI, EOI, SOFn, or SOS is found */ { int c; for (;;) { c = next_marker(cinfo); switch (c) { case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_JPG: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: case M_SOI: case M_EOI: case M_SOS: return c; case M_DHT: get_dht(cinfo); break; case M_DAC: get_dac(cinfo); break; case M_DQT: get_dqt(cinfo); break; case M_DRI: get_dri(cinfo); break; case M_APP0: get_app0(cinfo); break; case M_COM: get_com(cinfo); break; case M_RST0: /* these are all parameterless */ case M_RST1: case M_RST2: case M_RST3: case M_RST4: case M_RST5: case M_RST6: case M_RST7: case M_TEM: TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c); break; default: /* must be DNL, DHP, EXP, APPn, JPGn, or RESn */ skip_variable(cinfo, c); break; } } } /* * Initialize and read the file header (everything through the SOF marker). */ METHODDEF void read_file_header (decompress_info_ptr cinfo) { int c; /* Demand an SOI marker at the start of the file --- otherwise it's * probably not a JPEG file at all. If the user interface wants to support * nonstandard headers in front of the SOI, it must skip over them itself * before calling jpeg_decompress(). */ if (JGETC(cinfo) != 0xFF || JGETC(cinfo) != (int) M_SOI) ERREXIT(cinfo->emethods, "Not a JPEG file"); get_soi(cinfo); /* OK, process SOI */ /* Process markers until SOF */ c = process_tables(cinfo); switch (c) { case M_SOF0: case M_SOF1: get_sof(cinfo, c); cinfo->arith_code = FALSE; break; case M_SOF9: get_sof(cinfo, c); cinfo->arith_code = TRUE; break; default: ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c); break; } /* Figure out what colorspace we have */ /* (too bad the JPEG committee didn't provide a real way to specify this) */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = CS_GRAYSCALE; break; case 3: /* if we saw a JFIF marker, leave it set to YCbCr; */ /* also leave it alone if UI has provided a value */ if (cinfo->jpeg_color_space == CS_UNKNOWN) { short cid0 = cinfo->comp_info[0].component_id; short cid1 = cinfo->comp_info[1].component_id; short cid2 = cinfo->comp_info[2].component_id; if (cid0 == 1 && cid1 == 2 && cid2 == 3) cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */ else if (cid0 == 1 && cid1 == 4 && cid2 == 5) cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */ else { TRACEMS3(cinfo->emethods, 1, "Unrecognized component IDs %d %d %d, assuming YCbCr", cid0, cid1, cid2); cinfo->jpeg_color_space = CS_YCbCr; } } break; case 4: cinfo->jpeg_color_space = CS_CMYK; break; default: cinfo->jpeg_color_space = CS_UNKNOWN; break; } } /* * Read the start of a scan (everything through the SOS marker). * Return TRUE if find SOS, FALSE if find EOI. */ METHODDEF boolean read_scan_header (decompress_info_ptr cinfo) { int c; /* Process markers until SOS or EOI */ c = process_tables(cinfo); switch (c) { case M_SOS: get_sos(cinfo); return TRUE; case M_EOI: TRACEMS(cinfo->emethods, 1, "End Of Image"); return FALSE; default: ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c); break; } return FALSE; /* keeps lint happy */ } /* * The entropy decoder calls this routine if it finds a marker other than * the restart marker it was expecting. (This code is *not* used unless * a nonzero restart interval has been declared.) The passed parameter is * the marker code actually found (might be anything, except 0 or FF). * The desired restart marker is that indicated by cinfo->next_restart_num. * This routine is supposed to apply whatever error recovery strategy seems * appropriate in order to position the input stream to the next data segment. * For some file formats (eg, TIFF) extra information such as tile boundary * pointers may be available to help in this decision. * * This implementation is substantially constrained by wanting to treat the * input as a data stream; this means we can't back up. (For instance, we * generally can't fseek() if the input is a Unix pipe.) Therefore, we have * only the following actions to work with: * 1. Do nothing, let the entropy decoder resume at next byte of file. * 2. Read forward until we find another marker, discarding intervening * data. (In theory we could look ahead within the current bufferload, * without having to discard data if we don't find the desired marker. * This idea is not implemented here, in part because it makes behavior * dependent on buffer size and chance buffer-boundary positions.) * 3. Push back the passed marker (with JUNGETC). This will cause the * entropy decoder to process an empty data segment, inserting dummy * zeroes, and then re-read the marker we pushed back. * #2 is appropriate if we think the desired marker lies ahead, while #3 is * appropriate if the found marker is a future restart marker (indicating * that we have missed the desired restart marker, probably because it got * corrupted). * We apply #2 or #3 if the found marker is a restart marker no more than * two counts behind or ahead of the expected one. We also apply #2 if the * found marker is not a legal JPEG marker code (it's certainly bogus data). * If the found marker is a restart marker more than 2 counts away, we do #1 * (too much risk that the marker is erroneous; with luck we will be able to * resync at some future point). * For any valid non-restart JPEG marker, we apply #3. This keeps us from * overrunning the end of a scan. An implementation limited to single-scan * files might find it better to apply #2 for markers other than EOI, since * any other marker would have to be bogus data in that case. */ METHODDEF void resync_to_restart (decompress_info_ptr cinfo, int marker) { int desired = cinfo->next_restart_num; int action = 1; /* Always put up a warning. */ WARNMS2(cinfo->emethods, "Corrupt JPEG data: found 0x%02x marker instead of RST%d", marker, desired); /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) action = 2; /* invalid marker */ else if (marker < (int) M_RST0 || marker > (int) M_RST7) action = 3; /* valid non-restart marker */ else { if (marker == ((int) M_RST0 + ((desired+1) & 7)) || marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ else action = 1; /* desired restart or too far away */ } TRACEMS2(cinfo->emethods, 4, "At marker 0x%02x, recovery action %d", marker, action); switch (action) { case 1: /* Let entropy decoder resume processing. */ return; case 2: /* Scan to the next marker, and repeat the decision loop. */ marker = next_marker(cinfo); break; case 3: /* Put back this marker & return. */ /* Entropy decoder will be forced to process an empty segment. */ JUNGETC(marker, cinfo); JUNGETC(0xFF, cinfo); return; } } } /* * Finish up after a compressed scan (series of read_jpeg_data calls); * prepare for another read_scan_header call. */ METHODDEF void read_scan_trailer (decompress_info_ptr cinfo) { /* no work needed */ } /* * Finish up at the end of the file. */ METHODDEF void read_file_trailer (decompress_info_ptr cinfo) { /* no work needed */ } /* * The method selection routine for standard JPEG header reading. * Note that this must be called by the user interface before calling * jpeg_decompress. When a non-JFIF file is to be decompressed (TIFF, * perhaps), the user interface must discover the file type and call * the appropriate method selection routine. */ GLOBAL void jselrjfif (decompress_info_ptr cinfo) { cinfo->methods->read_file_header = read_file_header; cinfo->methods->read_scan_header = read_scan_header; /* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */ #if 0 cinfo->methods->read_jpeg_data = read_jpeg_data; #endif cinfo->methods->resync_to_restart = resync_to_restart; cinfo->methods->read_scan_trailer = read_scan_trailer; cinfo->methods->read_file_trailer = read_file_trailer; } #endif /* JFIF_SUPPORTED */ 0: /* these are all parameterless */ case M_RST1: case M_RST2: case M_RST3: case M_RST4: case M_RST5: case M_RST6: case M_RST7: case M_TEM: TRACEMS1(cinfo->emethods, 1, "Unexpectexloadimage.4.1/jpeg/jrdppm.c 644 221 144 31425 5315652650 11157 /* * jrdppm.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in PPM format. * The PBMPLUS library is NOT required to compile this software, * but it is highly useful as a set of PPM image manipulation programs. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; input_init may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed PPM format). * * These routines are invoked via the methods get_input_row * and input_init/term. */ #include "jinclude.h" #ifdef PPM_SUPPORTED /* Portions of this code are based on the PBMPLUS library, which is: ** ** Copyright (C) 1988 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ /* Macros to deal with unsigned chars as efficiently as compiler allows */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char U_CHAR; #define UCH(x) ((int) (x)) #else /* !HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char U_CHAR; #define UCH(x) ((int) (x)) #else typedef char U_CHAR; #define UCH(x) ((int) (x) & 0xFF) #endif #endif /* HAVE_UNSIGNED_CHAR */ #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) /* * On most systems, reading individual bytes with getc() is drastically less * efficient than buffering a row at a time with fread(). But we must * allocate the row buffer in near data space on PCs, because we are assuming * small-data memory model, wherein fread() can't reach far memory. If you * need to process very wide images on a PC, you may have to use the getc() * approach. In that case, define USE_GETC_INPUT. */ #ifndef USE_GETC_INPUT static U_CHAR * row_buffer; /* holds 1 pixel row's worth of raw input */ #endif static JSAMPLE * rescale; /* => maxval-remapping array, or NULL */ LOCAL int pbm_getc (FILE * file) /* Read next char, skipping over any comments */ /* A comment/newline sequence is returned as a newline */ { register int ch; ch = getc(file); if (ch == '#') { do { ch = getc(file); } while (ch != '\n' && ch != EOF); } return ch; } LOCAL unsigned int read_pbm_integer (compress_info_ptr cinfo) /* Read an unsigned decimal integer from the PPM file */ /* Swallows one trailing character after the integer */ /* Note that on a 16-bit-int machine, only values up to 64k can be read. */ /* This should not be a problem in practice. */ { register int ch; register unsigned int val; /* Skip any leading whitespace */ do { ch = pbm_getc(cinfo->input_file); if (ch == EOF) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); if (ch < '0' || ch > '9') ERREXIT(cinfo->emethods, "Bogus data in PPM file"); val = ch - '0'; while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') { val *= 10; val += ch - '0'; } return val; } /* * Read one row of pixels. * * We provide several different versions depending on input file format. * In all cases, input is scaled to the size of JSAMPLE; it's possible that * when JSAMPLE is 12 bits, this would not really be desirable. * * Note that a really fast path is provided for reading raw files with * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs). */ METHODDEF void get_text_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading text-format PGM files with any maxval */ { register JSAMPROW ptr0; register unsigned int val; register long col; ptr0 = pixel_row[0]; for (col = cinfo->image_width; col > 0; col--) { val = read_pbm_integer(cinfo); if (rescale != NULL) val = rescale[val]; *ptr0++ = (JSAMPLE) val; } } METHODDEF void get_text_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading text-format PPM files with any maxval */ { register JSAMPROW ptr0, ptr1, ptr2; register unsigned int val; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { val = read_pbm_integer(cinfo); if (rescale != NULL) val = rescale[val]; *ptr0++ = (JSAMPLE) val; val = read_pbm_integer(cinfo); if (rescale != NULL) val = rescale[val]; *ptr1++ = (JSAMPLE) val; val = read_pbm_integer(cinfo); if (rescale != NULL) val = rescale[val]; *ptr2++ = (JSAMPLE) val; } } #ifdef USE_GETC_INPUT METHODDEF void get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PGM files with any maxval */ { register FILE * infile = cinfo->input_file; register JSAMPROW ptr0; register long col; ptr0 = pixel_row[0]; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = rescale[getc(infile)]; } } METHODDEF void get_scaled_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PPM files with any maxval */ { register FILE * infile = cinfo->input_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = rescale[getc(infile)]; *ptr1++ = rescale[getc(infile)]; *ptr2++ = rescale[getc(infile)]; } } METHODDEF void get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */ { register FILE * infile = cinfo->input_file; register JSAMPROW ptr0; register long col; ptr0 = pixel_row[0]; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = (JSAMPLE) getc(infile); } } METHODDEF void get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */ { register FILE * infile = cinfo->input_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = (JSAMPLE) getc(infile); *ptr1++ = (JSAMPLE) getc(infile); *ptr2++ = (JSAMPLE) getc(infile); } } #else /* use row buffering */ METHODDEF void get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PGM files with any maxval */ { register JSAMPROW ptr0; register U_CHAR * row_bufferptr; register long col; if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width)) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); ptr0 = pixel_row[0]; row_bufferptr = row_buffer; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = rescale[UCH(*row_bufferptr++)]; } } METHODDEF void get_scaled_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PPM files with any maxval */ { register JSAMPROW ptr0, ptr1, ptr2; register U_CHAR * row_bufferptr; register long col; if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width)) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; row_bufferptr = row_buffer; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = rescale[UCH(*row_bufferptr++)]; *ptr1++ = rescale[UCH(*row_bufferptr++)]; *ptr2++ = rescale[UCH(*row_bufferptr++)]; } } METHODDEF void get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */ { register JSAMPROW ptr0; register U_CHAR * row_bufferptr; register long col; if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width)) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); ptr0 = pixel_row[0]; row_bufferptr = row_buffer; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = (JSAMPLE) UCH(*row_bufferptr++); } } METHODDEF void get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */ { register JSAMPROW ptr0, ptr1, ptr2; register U_CHAR * row_bufferptr; register long col; if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width)) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; row_bufferptr = row_buffer; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = (JSAMPLE) UCH(*row_bufferptr++); *ptr1++ = (JSAMPLE) UCH(*row_bufferptr++); *ptr2++ = (JSAMPLE) UCH(*row_bufferptr++); } } #endif /* USE_GETC_INPUT */ /* * Read the file header; return image size and component count. */ METHODDEF void input_init (compress_info_ptr cinfo) { int c; unsigned int w, h, maxval; if (getc(cinfo->input_file) != 'P') ERREXIT(cinfo->emethods, "Not a PPM file"); c = getc(cinfo->input_file); /* save format discriminator for a sec */ w = read_pbm_integer(cinfo); /* while we fetch the header info */ h = read_pbm_integer(cinfo); maxval = read_pbm_integer(cinfo); if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ ERREXIT(cinfo->emethods, "Not a PPM file"); switch (c) { case '2': /* it's a text-format PGM file */ cinfo->methods->get_input_row = get_text_gray_row; cinfo->input_components = 1; cinfo->in_color_space = CS_GRAYSCALE; TRACEMS2(cinfo->emethods, 1, "%ux%u text PGM image", w, h); break; case '3': /* it's a text-format PPM file */ cinfo->methods->get_input_row = get_text_rgb_row; cinfo->input_components = 3; cinfo->in_color_space = CS_RGB; TRACEMS2(cinfo->emethods, 1, "%ux%u text PPM image", w, h); break; case '5': /* it's a raw-format PGM file */ if (maxval == MAXJSAMPLE) cinfo->methods->get_input_row = get_raw_gray_row; else cinfo->methods->get_input_row = get_scaled_gray_row; cinfo->input_components = 1; cinfo->in_color_space = CS_GRAYSCALE; #ifndef USE_GETC_INPUT /* allocate space for row buffer: 1 byte/pixel */ row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small) ((size_t) (SIZEOF(U_CHAR) * (long) w)); #endif TRACEMS2(cinfo->emethods, 1, "%ux%u PGM image", w, h); break; case '6': /* it's a raw-format PPM file */ if (maxval == MAXJSAMPLE) cinfo->methods->get_input_row = get_raw_rgb_row; else cinfo->methods->get_input_row = get_scaled_rgb_row; cinfo->input_components = 3; cinfo->in_color_space = CS_RGB; #ifndef USE_GETC_INPUT /* allocate space for row buffer: 3 bytes/pixel */ row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small) ((size_t) (3 * SIZEOF(U_CHAR) * (long) w)); #endif TRACEMS2(cinfo->emethods, 1, "%ux%u PPM image", w, h); break; default: ERREXIT(cinfo->emethods, "Not a PPM file"); break; } /* Compute the rescaling array if necessary */ /* This saves per-pixel calculation */ if (maxval == MAXJSAMPLE) rescale = NULL; /* no rescaling required */ else { INT32 val, half_maxval; /* On 16-bit-int machines we have to be careful of maxval = 65535 */ rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small) ((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE))); half_maxval = maxval / 2; for (val = 0; val <= (INT32) maxval; val++) { /* The multiplication here must be done in 32 bits to avoid overflow */ rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval); } } cinfo->image_width = w; cinfo->image_height = h; cinfo->data_precision = BITS_IN_JSAMPLE; } /* * Finish up at the end of the file. */ METHODDEF void input_term (compress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /* * The method selection routine for PPM format input. * Note that this must be called by the user interface before calling * jpeg_compress. If multiple input formats are supported, the * user interface is responsible for discovering the file format and * calling the appropriate method selection routine. */ GLOBAL void jselrppm (compress_info_ptr cinfo) { cinfo->methods->input_init = input_init; /* cinfo->methods->get_input_row is set by input_init */ cinfo->methods->input_term = input_term; } #endif /* PPM_SUPPORTED */ > 0; col--) { *ptr0++ = rescale[getc(infile)]; *ptr1++ = rescale[getc(infile)]; *ptr2++ = rescale[getc(infile)]; } } METHODDEF void get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is forxloadimage.4.1/jpeg/jrdrle.c 644 221 144 26143 5154504725 11146 /* * jrdrle.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in Utah RLE format. * The Utah Raster Toolkit library is required (version 3.0). * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; input_init may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed RLE format). * * These routines are invoked via the methods get_input_row * and input_init/term. * * Based on code contributed by Mike Lijewski. */ #include "jinclude.h" #ifdef RLE_SUPPORTED /* rle.h is provided by the Utah Raster Toolkit. */ #include /* * load_image assumes that JSAMPLE has the same representation as rle_pixel, * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. */ #ifndef EIGHT_BIT_SAMPLES Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ #endif /* * We support the following types of RLE files: * * GRAYSCALE - 8 bits, no colormap * PSEUDOCOLOR - 8 bits, colormap * TRUECOLOR - 24 bits, colormap * DIRECTCOLOR - 24 bits, no colormap * * For now, we ignore any alpha channel in the image. */ typedef enum { GRAYSCALE, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind; static rle_kind visual; /* actual type of input file */ /* * Since RLE stores scanlines bottom-to-top, we have to invert the image * to conform to JPEG's top-to-bottom order. To do this, we read the * incoming image into a virtual array on the first get_input_row call, * then fetch the required row from the virtual array on subsequent calls. */ static big_sarray_ptr image; /* single array for GRAYSCALE/PSEUDOCOLOR */ static big_sarray_ptr red_channel; /* three arrays for TRUECOLOR/DIRECTCOLOR */ static big_sarray_ptr green_channel; static big_sarray_ptr blue_channel; static long cur_row_number; /* last row# read from virtual array */ static rle_hdr header; /* Input file information */ static rle_map *colormap; /* RLE colormap, if any */ /* * Read the file header; return image size and component count. */ METHODDEF void input_init (compress_info_ptr cinfo) { long width, height; /* Use RLE library routine to get the header info */ header.rle_file = cinfo->input_file; switch (rle_get_setup(&header)) { case RLE_SUCCESS: /* A-OK */ break; case RLE_NOT_RLE: ERREXIT(cinfo->emethods, "Not an RLE file"); break; case RLE_NO_SPACE: ERREXIT(cinfo->emethods, "Insufficient memory for RLE header"); break; case RLE_EMPTY: ERREXIT(cinfo->emethods, "Empty RLE file"); break; case RLE_EOF: ERREXIT(cinfo->emethods, "Premature EOF in RLE header"); break; default: ERREXIT(cinfo->emethods, "Bogus RLE error code"); break; } /* Figure out what we have, set private vars and return values accordingly */ width = header.xmax - header.xmin + 1; height = header.ymax - header.ymin + 1; header.xmin = 0; /* realign horizontally */ header.xmax = width-1; cinfo->image_width = width; cinfo->image_height = height; cinfo->data_precision = 8; /* we can only handle 8 bit data */ if (header.ncolors == 1 && header.ncmap == 0) { visual = GRAYSCALE; TRACEMS(cinfo->emethods, 1, "Gray-scale RLE file"); } else if (header.ncolors == 1 && header.ncmap == 3) { visual = PSEUDOCOLOR; colormap = header.cmap; TRACEMS1(cinfo->emethods, 1, "Colormapped RLE file with map of length %d", 1 << header.cmaplen); } else if (header.ncolors == 3 && header.ncmap == 3) { visual = TRUECOLOR; colormap = header.cmap; TRACEMS1(cinfo->emethods, 1, "Full-color RLE file with map of length %d", 1 << header.cmaplen); } else if (header.ncolors == 3 && header.ncmap == 0) { visual = DIRECTCOLOR; TRACEMS(cinfo->emethods, 1, "Full-color RLE file"); } else ERREXIT(cinfo->emethods, "Can't handle this RLE setup"); switch (visual) { case GRAYSCALE: /* request one big array to hold the grayscale image */ image = (*cinfo->emethods->request_big_sarray) (width, height, 1L); cinfo->in_color_space = CS_GRAYSCALE; cinfo->input_components = 1; break; case PSEUDOCOLOR: /* request one big array to hold the pseudocolor image */ image = (*cinfo->emethods->request_big_sarray) (width, height, 1L); cinfo->in_color_space = CS_RGB; cinfo->input_components = 3; break; case TRUECOLOR: case DIRECTCOLOR: /* request three big arrays to hold the RGB channels */ red_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L); green_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L); blue_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L); cinfo->in_color_space = CS_RGB; cinfo->input_components = 3; break; } cinfo->total_passes++; /* count file reading as separate pass */ } /* * Read one row of pixels. * These are called only after load_image has read the image into * the virtual array(s). */ METHODDEF void get_grayscale_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This is used for GRAYSCALE images */ { JSAMPROW inputrows[1]; /* a pseudo JSAMPARRAY structure */ cur_row_number--; /* work down in array */ inputrows[0] = *((*cinfo->emethods->access_big_sarray) (image, cur_row_number, FALSE)); jcopy_sample_rows(inputrows, 0, pixel_row, 0, 1, cinfo->image_width); } METHODDEF void get_pseudocolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This is used for PSEUDOCOLOR images */ { long col; JSAMPROW image_ptr, ptr0, ptr1, ptr2; int val; cur_row_number--; /* work down in array */ image_ptr = *((*cinfo->emethods->access_big_sarray) (image, cur_row_number, FALSE)); ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { val = GETJSAMPLE(*image_ptr++); *ptr0++ = colormap[val ] >> 8; *ptr1++ = colormap[val + 256] >> 8; *ptr2++ = colormap[val + 512] >> 8; } } METHODDEF void get_truecolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This is used for TRUECOLOR images */ /* The colormap consists of 3 independent lookup tables */ { long col; JSAMPROW red_ptr, green_ptr, blue_ptr, ptr0, ptr1, ptr2; cur_row_number--; /* work down in array */ red_ptr = *((*cinfo->emethods->access_big_sarray) (red_channel, cur_row_number, FALSE)); green_ptr = *((*cinfo->emethods->access_big_sarray) (green_channel, cur_row_number, FALSE)); blue_ptr = *((*cinfo->emethods->access_big_sarray) (blue_channel, cur_row_number, FALSE)); ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { *ptr0++ = colormap[GETJSAMPLE(*red_ptr++) ] >> 8; *ptr1++ = colormap[GETJSAMPLE(*green_ptr++) + 256] >> 8; *ptr2++ = colormap[GETJSAMPLE(*blue_ptr++) + 512] >> 8; } } METHODDEF void get_directcolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This is used for DIRECTCOLOR images */ { JSAMPROW inputrows[3]; /* a pseudo JSAMPARRAY structure */ cur_row_number--; /* work down in array */ inputrows[0] = *((*cinfo->emethods->access_big_sarray) (red_channel, cur_row_number, FALSE)); inputrows[1] = *((*cinfo->emethods->access_big_sarray) (green_channel, cur_row_number, FALSE)); inputrows[2] = *((*cinfo->emethods->access_big_sarray) (blue_channel, cur_row_number, FALSE)); jcopy_sample_rows(inputrows, 0, pixel_row, 0, 3, cinfo->image_width); } /* * Load the color channels into separate arrays. We have to do * this because RLE files start at the lower left while the JPEG standard * has them starting in the upper left. This is called the first time * we want to get a row of input. What we do is load the RLE data into * big arrays and then call the appropriate routine to read one row from * the big arrays. We also change cinfo->methods->get_input_row so that * subsequent calls go straight to the row-reading routine. */ METHODDEF void load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { long row; rle_pixel *rle_row[3]; /* Read the RLE data into our virtual array(s). * We assume here that (a) rle_pixel is represented the same as JSAMPLE, * and (b) we are not on a machine where FAR pointers differ from regular. */ RLE_CLR_BIT(header, RLE_ALPHA); /* don't read the alpha channel */ switch (visual) { case GRAYSCALE: case PSEUDOCOLOR: for (row = 0; row < cinfo->image_height; row++) { (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height); /* * Read a row of the image directly into our big array. * Too bad this doesn't seem to return any indication of errors :-(. */ rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray) (image, row, TRUE)); rle_getrow(&header, rle_row); } break; case TRUECOLOR: case DIRECTCOLOR: for (row = 0; row < cinfo->image_height; row++) { (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height); /* * Read a row of the image directly into our big arrays. * Too bad this doesn't seem to return any indication of errors :-(. */ rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray) (red_channel, row, TRUE)); rle_row[1] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray) (green_channel, row, TRUE)); rle_row[2] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray) (blue_channel, row, TRUE)); rle_getrow(&header, rle_row); } break; } cinfo->completed_passes++; /* Set up to call proper row-extraction routine in future */ switch (visual) { case GRAYSCALE: cinfo->methods->get_input_row = get_grayscale_row; break; case PSEUDOCOLOR: cinfo->methods->get_input_row = get_pseudocolor_row; break; case TRUECOLOR: cinfo->methods->get_input_row = get_truecolor_row; break; case DIRECTCOLOR: cinfo->methods->get_input_row = get_directcolor_row; break; } /* And fetch the topmost (bottommost) row */ cur_row_number = cinfo->image_height; (*cinfo->methods->get_input_row) (cinfo, pixel_row); } /* * Finish up at the end of the file. */ METHODDEF void input_term (compress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /* * The method selection routine for RLE format input. * Note that this must be called by the user interface before calling * jpeg_compress. If multiple input formats are supported, the * user interface is responsible for discovering the file format and * calling the appropriate method selection routine. */ GLOBAL void jselrrle (compress_info_ptr cinfo) { cinfo->methods->input_init = input_init; cinfo->methods->get_input_row = load_image; /* until first call */ cinfo->methods->input_term = input_term; } #endif /* RLE_SUPPORTED */ s accordingly */ width = header.xmax - header.xmin + 1; height = header.ymax - header.ymin + 1; header.xmin = 0; /* realign horizontally */ header.xmax = width-1; cinfo->image_width = width; cinfo->image_height = height; cinfo->data_precision = 8; /* we can only handle 8 bit data */ if (header.ncolors == 1 && header.ncmap == 0) { visual = GRAYSCALE; TRACEMS(cinfo-xloadimage.4.1/jpeg/jrdtarga.c 644 221 144 32167 5307153517 11464 /* * jrdtarga.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in Targa format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; input_init may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed Targa format). * * These routines are invoked via the methods get_input_row * and input_init/term. * * Based on code contributed by Lee Daniel Crocker. */ #include "jinclude.h" #ifdef TARGA_SUPPORTED /* Macros to deal with unsigned chars as efficiently as compiler allows */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char U_CHAR; #define UCH(x) ((int) (x)) #else /* !HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char U_CHAR; #define UCH(x) ((int) (x)) #else typedef char U_CHAR; #define UCH(x) ((int) (x) & 0xFF) #endif #endif /* HAVE_UNSIGNED_CHAR */ #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) static JSAMPARRAY colormap; /* Targa colormap (converted to my format) */ static big_sarray_ptr whole_image; /* Needed if funny input row order */ static long current_row; /* Current logical row number to read */ /* Pointer to routine to extract next Targa pixel from input file */ static void (*read_pixel) PP((compress_info_ptr cinfo)); /* Result of read_pixel is delivered here: */ static U_CHAR tga_pixel[4]; static int pixel_size; /* Bytes per Targa pixel (1 to 4) */ /* State info for reading RLE-coded pixels; both counts must be init to 0 */ static int block_count; /* # of pixels remaining in RLE block */ static int dup_pixel_count; /* # of times to duplicate previous pixel */ /* This saves the correct pixel-row-expansion method for preload_image */ static void (*get_pixel_row) PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row)); /* For expanding 5-bit pixel values to 8-bit with best rounding */ static const UINT8 c5to8bits[32] = { 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255 }; LOCAL int read_byte (compress_info_ptr cinfo) /* Read next byte from Targa file */ { register FILE *infile = cinfo->input_file; register int c; if ((c = getc(infile)) == EOF) ERREXIT(cinfo->emethods, "Premature EOF in Targa file"); return c; } LOCAL void read_colormap (compress_info_ptr cinfo, int cmaplen, int mapentrysize) /* Read the colormap from a Targa file */ { int i; /* Presently only handles 24-bit BGR format */ if (mapentrysize != 24) ERREXIT(cinfo->emethods, "Unsupported Targa colormap format"); for (i = 0; i < cmaplen; i++) { colormap[2][i] = (JSAMPLE) read_byte(cinfo); colormap[1][i] = (JSAMPLE) read_byte(cinfo); colormap[0][i] = (JSAMPLE) read_byte(cinfo); } } /* * read_pixel methods: get a single pixel from Targa file into tga_pixel[] */ LOCAL void read_non_rle_pixel (compress_info_ptr cinfo) /* Read one Targa pixel from the input file; no RLE expansion */ { register FILE * infile = cinfo->input_file; register int i; for (i = 0; i < pixel_size; i++) { tga_pixel[i] = (U_CHAR) getc(infile); } } LOCAL void read_rle_pixel (compress_info_ptr cinfo) /* Read one Targa pixel from the input file, expanding RLE data as needed */ { register FILE * infile = cinfo->input_file; register int i; /* Duplicate previously read pixel? */ if (dup_pixel_count > 0) { dup_pixel_count--; return; } /* Time to read RLE block header? */ if (--block_count < 0) { /* decrement pixels remaining in block */ i = read_byte(cinfo); if (i & 0x80) { /* Start of duplicate-pixel block? */ dup_pixel_count = i & 0x7F; /* number of duplications after this one */ block_count = 0; /* then read new block header */ } else { block_count = i & 0x7F; /* number of pixels after this one */ } } /* Read next pixel */ for (i = 0; i < pixel_size; i++) { tga_pixel[i] = (U_CHAR) getc(infile); } } /* * Read one row of pixels. * * We provide several different versions depending on input file format. */ METHODDEF void get_8bit_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading 8-bit grayscale pixels */ { register JSAMPROW ptr0; register long col; ptr0 = pixel_row[0]; for (col = cinfo->image_width; col > 0; col--) { (*read_pixel) (cinfo); /* Load next pixel into tga_pixel */ *ptr0++ = (JSAMPLE) UCH(tga_pixel[0]); } } METHODDEF void get_8bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading 8-bit colormap indexes */ { register int t; register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { (*read_pixel) (cinfo); /* Load next pixel into tga_pixel */ t = UCH(tga_pixel[0]); *ptr0++ = colormap[0][t]; *ptr1++ = colormap[1][t]; *ptr2++ = colormap[2][t]; } } METHODDEF void get_16bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading 16-bit pixels */ { register int t; register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { (*read_pixel) (cinfo); /* Load next pixel into tga_pixel */ t = UCH(tga_pixel[0]); t += UCH(tga_pixel[1]) << 8; /* We expand 5 bit data to 8 bit sample width. * The format of the 16-bit (LSB first) input word is * xRRRRRGGGGGBBBBB */ *ptr2++ = (JSAMPLE) c5to8bits[t & 0x1F]; t >>= 5; *ptr1++ = (JSAMPLE) c5to8bits[t & 0x1F]; t >>= 5; *ptr0++ = (JSAMPLE) c5to8bits[t & 0x1F]; } } METHODDEF void get_24bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) /* This version is for reading 24-bit pixels */ { register JSAMPROW ptr0, ptr1, ptr2; register long col; ptr0 = pixel_row[0]; ptr1 = pixel_row[1]; ptr2 = pixel_row[2]; for (col = cinfo->image_width; col > 0; col--) { (*read_pixel) (cinfo); /* Load next pixel into tga_pixel */ *ptr0++ = (JSAMPLE) UCH(tga_pixel[2]); /* convert BGR to RGB order */ *ptr1++ = (JSAMPLE) UCH(tga_pixel[1]); *ptr2++ = (JSAMPLE) UCH(tga_pixel[0]); } } /* * Targa also defines a 32-bit pixel format with order B,G,R,A. * We presently ignore the attribute byte, so the code for reading * these pixels is identical to the 24-bit routine above. * This works because the actual pixel length is only known to read_pixel. */ #define get_32bit_row get_24bit_row /* * This method is for re-reading the input data in standard top-down * row order. The entire image has already been read into whole_image * with proper conversion of pixel format, but it's in a funny row order. */ METHODDEF void get_memory_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { JSAMPARRAY image_ptr; long source_row; /* Compute row of source that maps to current_row of normal order */ /* For now, assume image is bottom-up and not interlaced. */ /* NEEDS WORK to support interlaced images! */ source_row = cinfo->image_height - current_row - 1; /* Fetch that row from virtual array */ image_ptr = (*cinfo->emethods->access_big_sarray) (whole_image, source_row * cinfo->input_components, FALSE); jcopy_sample_rows(image_ptr, 0, pixel_row, 0, cinfo->input_components, cinfo->image_width); current_row++; } /* * This method loads the image into whole_image during the first call on * get_input_row. The get_input_row pointer is then adjusted to call * get_memory_row on subsequent calls. */ METHODDEF void preload_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row) { JSAMPARRAY image_ptr; long row; /* Read the data into a virtual array in input-file row order */ for (row = 0; row < cinfo->image_height; row++) { (*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height); image_ptr = (*cinfo->emethods->access_big_sarray) (whole_image, row * cinfo->input_components, TRUE); (*get_pixel_row) (cinfo, image_ptr); } cinfo->completed_passes++; /* Set up to read from the virtual array in unscrambled order */ cinfo->methods->get_input_row = get_memory_row; current_row = 0; /* And read the first row */ get_memory_row(cinfo, pixel_row); } /* * Read the file header; return image size and component count. */ METHODDEF void input_init (compress_info_ptr cinfo) { U_CHAR targaheader[18]; int idlen, cmaptype, subtype, flags, interlace_type, components; UINT16 width, height, maplen; boolean is_bottom_up; #define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \ (((unsigned int) UCH(targaheader[offset+1])) << 8)) if (! ReadOK(cinfo->input_file, targaheader, 18)) ERREXIT(cinfo->emethods, "Unexpected end of file"); /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ if (targaheader[16] == 15) targaheader[16] = 16; idlen = UCH(targaheader[0]); cmaptype = UCH(targaheader[1]); subtype = UCH(targaheader[2]); maplen = GET_2B(5); width = GET_2B(12); height = GET_2B(14); pixel_size = UCH(targaheader[16]) >> 3; flags = UCH(targaheader[17]); /* Image Descriptor byte */ is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ interlace_type = flags >> 6; /* bits 6/7 are interlace code */ if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ pixel_size < 1 || pixel_size > 4 || (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ interlace_type != 0) /* currently don't allow interlaced image */ ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); if (subtype > 8) { /* It's an RLE-coded file */ read_pixel = read_rle_pixel; block_count = dup_pixel_count = 0; subtype -= 8; } else { /* Non-RLE file */ read_pixel = read_non_rle_pixel; } /* Now should have subtype 1, 2, or 3 */ components = 3; /* until proven different */ cinfo->in_color_space = CS_RGB; switch (subtype) { case 1: /* colormapped image */ if (pixel_size == 1 && cmaptype == 1) get_pixel_row = get_8bit_row; else ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); TRACEMS2(cinfo->emethods, 1, "%ux%u colormapped Targa image", width, height); break; case 2: /* RGB image */ switch (pixel_size) { case 2: get_pixel_row = get_16bit_row; break; case 3: get_pixel_row = get_24bit_row; break; case 4: get_pixel_row = get_32bit_row; break; default: ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); break; } TRACEMS2(cinfo->emethods, 1, "%ux%u RGB Targa image", width, height); break; case 3: /* Grayscale image */ components = 1; cinfo->in_color_space = CS_GRAYSCALE; if (pixel_size == 1) get_pixel_row = get_8bit_gray_row; else ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); TRACEMS2(cinfo->emethods, 1, "%ux%u grayscale Targa image", width, height); break; default: ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); break; } if (is_bottom_up) { whole_image = (*cinfo->emethods->request_big_sarray) ((long) width, (long) height * components, (long) components); cinfo->methods->get_input_row = preload_image; cinfo->total_passes++; /* count file reading as separate pass */ } else { whole_image = NULL; cinfo->methods->get_input_row = get_pixel_row; } while (idlen--) /* Throw away ID field */ (void) read_byte(cinfo); if (maplen > 0) { if (maplen > 256 || GET_2B(3) != 0) ERREXIT(cinfo->emethods, "Colormap too large"); /* Allocate space to store the colormap */ colormap = (*cinfo->emethods->alloc_small_sarray) ((long) maplen, 3L); /* and read it from the file */ read_colormap(cinfo, (int) maplen, UCH(targaheader[7])); } else { if (cmaptype) /* but you promised a cmap! */ ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file"); colormap = NULL; } cinfo->input_components = components; cinfo->image_width = width; cinfo->image_height = height; cinfo->data_precision = 8; /* always, even if 12-bit JSAMPLEs */ } /* * Finish up at the end of the file. */ METHODDEF void input_term (compress_info_ptr cinfo) { /* no work (we let free_all release the workspace) */ } /* * The method selection routine for Targa format input. * Note that this must be called by the user interface before calling * jpeg_compress. If multiple input formats are supported, the * user interface is responsible for discovering the file format and * calling the appropriate method selection routine. */ GLOBAL void jselrtarga (compress_info_ptr cinfo) { cinfo->methods->input_init = input_init; /* cinfo->methods->get_input_row is set by input_init */ cinfo->methods->input_term = input_term; } #endif /* TARGA_SUPPORTED */ r) (cinfo, row, cinfo->image_height); /* * Read a row of the image directly into our big arrays. * Too bad this doesn't seem to return any indication of errors :-(. */ rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarraxloadimage.4.1/jpeg/jrevdct.c 644 221 144 33412 5300067657 11323 /* * jrevdct.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the basic inverse-DCT transformation subroutine. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #include "jinclude.h" /* * This routine is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * The poop on this scaling stuff is as follows: * * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) * larger than the true IDCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D IDCT, * because the y0 and y4 inputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data further, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #ifdef EIGHT_BIT_SAMPLES #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * some C compilers will do the right thing if you provide the correct * combination of casts. * NB: for 12-bit samples, a full 32-bit multiplication will be needed. */ #ifdef EIGHT_BIT_SAMPLES #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #endif #ifndef MULTIPLY /* default definition */ #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the inverse DCT on one block of coefficients. */ GLOBAL void j_rev_dct (DCTBLOCK data) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; register DCTELEM *dataptr; int rowctr; SHIFT_TEMPS /* Pass 1: process rows. */ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any row in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * row DCT calculations can be simplified this way. */ if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] | dataptr[5] | dataptr[6] | dataptr[7]) == 0) { /* AC terms all zero */ DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS); dataptr[0] = dcval; dataptr[1] = dcval; dataptr[2] = dcval; dataptr[3] = dcval; dataptr[4] = dcval; dataptr[5] = dcval; dataptr[6] = dcval; dataptr[7] = dcval; dataptr += DCTSIZE; /* advance pointer to next row */ continue; } /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = (INT32) dataptr[2]; z3 = (INT32) dataptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS; tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) dataptr[7]; tmp1 = (INT32) dataptr[5]; tmp2 = (INT32) dataptr[3]; tmp3 = (INT32) dataptr[1]; z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { /* Columns of zeroes can be exploited in the same way as we did with rows. * However, the row calculation has created many nonzero AC terms, so the * simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_COLUMN_TEST if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] | dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] | dataptr[DCTSIZE*7]) == 0) { /* AC terms all zero */ DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3); dataptr[DCTSIZE*0] = dcval; dataptr[DCTSIZE*1] = dcval; dataptr[DCTSIZE*2] = dcval; dataptr[DCTSIZE*3] = dcval; dataptr[DCTSIZE*4] = dcval; dataptr[DCTSIZE*5] = dcval; dataptr[DCTSIZE*6] = dcval; dataptr[DCTSIZE*7] = dcval; dataptr++; /* advance pointer to next column */ continue; } #endif /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = (INT32) dataptr[DCTSIZE*2]; z3 = (INT32) dataptr[DCTSIZE*6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS; tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) dataptr[DCTSIZE*7]; tmp1 = (INT32) dataptr[DCTSIZE*5]; tmp2 = (INT32) dataptr[DCTSIZE*3]; tmp3 = (INT32) dataptr[DCTSIZE*1]; z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3); dataptr++; /* advance pointer to next column */ } } BLOCK data) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; register DCTELEM *dataptr; int rowctr; SHIFT_TEMPS /* Pass 1: process rows. */ /* Note results are scaled up by sqrt(8) compaxloadimage.4.1/jpeg/jutils.c 644 221 144 6433 5276551007 11156 /* * jutils.c * * Copyright (C) 1991, 1992, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains miscellaneous utility routines needed for both * compression and decompression. * Note we prefix all global names with "j" to minimize conflicts with * a surrounding application. */ #include "jinclude.h" GLOBAL long jround_up (long a, long b) /* Compute a rounded up to next multiple of b; a >= 0, b > 0 */ { a += b-1; return a - (a % b); } /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays * and coefficient-block arrays. This won't work on 80x86 because the arrays * are FAR and we're assuming a small-pointer memory model. However, some * DOS compilers provide far-pointer versions of memcpy() and memset() even * in the small-model libraries. These will be used if USE_FMEM is defined. * Otherwise, the routines below do it the hard way. (The performance cost * is not all that great, because these routines aren't very heavily used.) */ #ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) #define FMEMZERO(target,size) MEMZERO(target,size) #else /* 80x86 case, define if we can */ #ifdef USE_FMEM #define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) #define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) #endif #endif GLOBAL void jcopy_sample_rows (JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, long num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas should not overlap. * The source and destination arrays must be at least as wide as num_cols. */ { register JSAMPROW inptr, outptr; #ifdef FMEMCOPY register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); #else register long count; #endif register int row; input_array += source_row; output_array += dest_row; for (row = num_rows; row > 0; row--) { inptr = *input_array++; outptr = *output_array++; #ifdef FMEMCOPY FMEMCOPY(outptr, inptr, count); #else for (count = num_cols; count > 0; count--) *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ #endif } } GLOBAL void jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, long num_blocks) /* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); #else register JCOEFPTR inptr, outptr; register long count; inptr = (JCOEFPTR) input_row; outptr = (JCOEFPTR) output_row; for (count = num_blocks * DCTSIZE2; count > 0; count--) { *outptr++ = *inptr++; } #endif } GLOBAL void jzero_far (void FAR * target, size_t bytestozero) /* Zero out a chunk of FAR memory. */ /* This might be sample-array data, block-array data, or alloc_medium data. */ { #ifdef FMEMZERO FMEMZERO(target, bytestozero); #else register char FAR * ptr = (char FAR *) target; register size_t count; for (count = bytestozero; count > 0; count--) { *ptr++ = 0; } #endif } * advance pointer to next row */ } /* Pass 2: process columns. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ dataptr = data; for (rowctr = DCTSIxloadimage.4.1/jpeg/jversion.h 644 221 144 554 5340775257 11475 /* * jversion.h * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains software version identification. */ #define JVERSION "4A 18-Feb-93" #define JCOPYRIGHT "Copyright (C) 1993, Thomas G. Lane" .icc, makljpeg.st@ makvms.optTM testimg.gifhN testimg.jpg|L testimg.ppmK testorigxloadimage.4.1/jpeg/jwrgif.c 644 221 144 33421 5334764273 11157 /* * jwrgif.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in GIF format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. * * These routines are invoked via the methods put_pixel_rows, put_color_map, * and output_init/term. */ /* * This code is loosely based on ppmtogif from the PBMPLUS distribution * of Feb. 1991. That file contains the following copyright notice: * Based on GIFENCODE by David Rowley . * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al. * Copyright (C) 1989 by Jef Poskanzer. * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. * * We are also required to state that * "The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated." */ #include "jinclude.h" #ifdef GIF_SUPPORTED static decompress_info_ptr dcinfo; /* to avoid passing to all functions */ #define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */ typedef INT16 code_int; /* must hold -1 .. 2**MAX_LZW_BITS */ #define LZW_TABLE_SIZE ((code_int) 1 << MAX_LZW_BITS) #define HSIZE 5003 /* hash table size for 80% occupancy */ typedef int hash_int; /* must hold -2*HSIZE..2*HSIZE */ static int n_bits; /* current number of bits/code */ static code_int maxcode; /* maximum code, given n_bits */ #define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) static int init_bits; /* initial n_bits ... restored after clear */ static code_int ClearCode; /* clear code (doesn't change) */ static code_int EOFCode; /* EOF code (ditto) */ static code_int free_code; /* first not-yet-used symbol code */ /* * The LZW hash table consists of three parallel arrays: * hash_code[i] code of symbol in slot i, or 0 if empty slot * hash_prefix[i] symbol's prefix code; undefined if empty slot * hash_suffix[i] symbol's suffix character; undefined if empty slot * where slot values (i) range from 0 to HSIZE-1. * * Algorithm: use open addressing double hashing (no chaining) on the * prefix code / suffix character combination. We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime * secondary probe. * * The hash tables are allocated from FAR heap space since they would use up * rather a lot of the near data space in a PC. */ static code_int FAR *hash_code; /* => hash table of symbol codes */ static code_int FAR *hash_prefix; /* => hash table of prefix symbols */ static UINT8 FAR *hash_suffix; /* => hash table of suffix bytes */ /* * Routines to package compressed data bytes into GIF data blocks. * A data block consists of a count byte (1..255) and that many data bytes. */ static int bytesinpkt; /* # of bytes in current packet */ static char packetbuf[256]; /* workspace for accumulating packet */ LOCAL void flush_packet (void) /* flush any accumulated data */ { if (bytesinpkt > 0) { /* never write zero-length packet */ packetbuf[0] = (char) bytesinpkt++; if (JFWRITE(dcinfo->output_file, packetbuf, bytesinpkt) != (size_t) bytesinpkt) ERREXIT(dcinfo->emethods, "Output file write error --- out of disk space?"); bytesinpkt = 0; } } /* Add a character to current packet; flush to disk if necessary */ #define CHAR_OUT(c) \ { packetbuf[++bytesinpkt] = (char) (c); \ if (bytesinpkt >= 255) \ flush_packet(); \ } /* Routine to convert variable-width codes into a byte stream */ static INT32 cur_accum; /* holds bits not yet output */ static int cur_bits; /* # of bits in cur_accum */ LOCAL void output (code_int code) /* Emit a code of n_bits bits */ /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ { cur_accum |= ((INT32) code) << cur_bits; cur_bits += n_bits; while (cur_bits >= 8) { CHAR_OUT(cur_accum & 0xFF); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. We do this here to ensure * that it's done in sync with the decoder's codesize increases. */ if (free_code > maxcode) { n_bits++; if (n_bits == MAX_LZW_BITS) maxcode = LZW_TABLE_SIZE; /* free_code will never exceed this */ else maxcode = MAXCODE(n_bits); } } /* The LZW algorithm proper */ static code_int waiting_code; /* symbol not yet output; may be extendable */ static boolean first_byte; /* if TRUE, waiting_code is not valid */ LOCAL void clear_hash (void) /* Fill the hash table with empty entries */ { /* It's sufficient to zero hash_code[] */ jzero_far((void FAR *) hash_code, HSIZE * SIZEOF(code_int)); } LOCAL void clear_block (void) /* Reset compressor and issue a Clear code */ { clear_hash(); /* delete all the symbols */ free_code = ClearCode + 2; output(ClearCode); /* inform decoder */ n_bits = init_bits; /* reset code size */ maxcode = MAXCODE(n_bits); } LOCAL void compress_init (int i_bits) /* Initialize LZW compressor */ { /* init all the static variables */ n_bits = init_bits = i_bits; maxcode = MAXCODE(n_bits); ClearCode = ((code_int) 1 << (init_bits - 1)); EOFCode = ClearCode + 1; free_code = ClearCode + 2; first_byte = TRUE; /* no waiting symbol yet */ /* init output buffering vars */ bytesinpkt = 0; cur_accum = 0; cur_bits = 0; /* clear hash table */ clear_hash(); /* GIF specifies an initial Clear code */ output(ClearCode); } LOCAL void compress_byte (int c) /* Accept and compress one 8-bit byte */ { register hash_int i; register hash_int disp; if (first_byte) { /* need to initialize waiting_code */ waiting_code = c; first_byte = FALSE; return; } /* Probe hash table to see if a symbol exists for * waiting_code followed by c. * If so, replace waiting_code by that symbol and return. */ i = ((hash_int) c << (MAX_LZW_BITS-8)) + waiting_code; /* i is less than twice 2**MAX_LZW_BITS, therefore less than twice HSIZE */ if (i >= HSIZE) i -= HSIZE; if (hash_code[i] != 0) { /* is first probed slot empty? */ if (hash_prefix[i] == waiting_code && hash_suffix[i] == (UINT8) c) { waiting_code = hash_code[i]; return; } if (i == 0) /* secondary hash (after G. Knott) */ disp = 1; else disp = HSIZE - i; while (1) { i -= disp; if (i < 0) i += HSIZE; if (hash_code[i] == 0) break; /* hit empty slot */ if (hash_prefix[i] == waiting_code && hash_suffix[i] == (UINT8) c) { waiting_code = hash_code[i]; return; } } } /* here when hashtable[i] is an empty slot; desired symbol not in table */ output(waiting_code); if (free_code < LZW_TABLE_SIZE) { hash_code[i] = free_code++; /* add symbol to hashtable */ hash_prefix[i] = waiting_code; hash_suffix[i] = (UINT8) c; } else clear_block(); waiting_code = c; } LOCAL void compress_term (void) /* Clean up at end */ { /* Flush out the buffered code */ if (! first_byte) output(waiting_code); /* Send an EOF code */ output(EOFCode); /* Flush the bit-packing buffer */ if (cur_bits > 0) { CHAR_OUT(cur_accum & 0xFF); } /* Flush the packet buffer */ flush_packet(); } /* GIF header construction */ LOCAL void put_word (UINT16 w) /* Emit a 16-bit word, LSB first */ { putc(w & 0xFF, dcinfo->output_file); putc((w >> 8) & 0xFF, dcinfo->output_file); } LOCAL void put_3bytes (int val) /* Emit 3 copies of same byte value --- handy subr for colormap construction */ { putc(val, dcinfo->output_file); putc(val, dcinfo->output_file); putc(val, dcinfo->output_file); } LOCAL void emit_header (int num_colors, JSAMPARRAY colormap) /* Output the GIF file header, including color map */ /* If colormap==NULL, synthesize a gray-scale colormap */ { int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte; int cshift = dcinfo->data_precision - 8; int i; if (num_colors > 256) ERREXIT(dcinfo->emethods, "GIF can only handle 256 colors"); /* Compute bits/pixel and related values */ BitsPerPixel = 1; while (num_colors > (1 << BitsPerPixel)) BitsPerPixel++; ColorMapSize = 1 << BitsPerPixel; if (BitsPerPixel <= 1) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Write the GIF header. * Note that we generate a plain GIF87 header for maximum compatibility. */ putc('G', dcinfo->output_file); putc('I', dcinfo->output_file); putc('F', dcinfo->output_file); putc('8', dcinfo->output_file); putc('7', dcinfo->output_file); putc('a', dcinfo->output_file); /* Write the Logical Screen Descriptor */ put_word((UINT16) dcinfo->image_width); put_word((UINT16) dcinfo->image_height); FlagByte = 0x80; /* Yes, there is a global color table */ FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */ FlagByte |= (BitsPerPixel-1); /* size of global color table */ putc(FlagByte, dcinfo->output_file); putc(0, dcinfo->output_file); /* Background color index */ putc(0, dcinfo->output_file); /* Reserved in GIF87 (aspect ratio in GIF89) */ /* Write the Global Color Map */ /* If the color map is more than 8 bits precision, */ /* we reduce it to 8 bits by shifting */ for (i=0; i < ColorMapSize; i++) { if (i < num_colors) { if (colormap != NULL) { if (dcinfo->out_color_space == CS_RGB) { /* Normal case: RGB color map */ putc(GETJSAMPLE(colormap[0][i]) >> cshift, dcinfo->output_file); putc(GETJSAMPLE(colormap[1][i]) >> cshift, dcinfo->output_file); putc(GETJSAMPLE(colormap[2][i]) >> cshift, dcinfo->output_file); } else { /* Grayscale "color map": possible if quantizing grayscale image */ put_3bytes(GETJSAMPLE(colormap[0][i]) >> cshift); } } else { /* Create a gray-scale map of num_colors values, range 0..255 */ put_3bytes((i * 255 + (num_colors-1)/2) / (num_colors-1)); } } else { /* fill out the map to a power of 2 */ put_3bytes(0); } } /* Write image separator and Image Descriptor */ putc(',', dcinfo->output_file); /* separator */ put_word((UINT16) 0); /* left/top offset */ put_word((UINT16) 0); put_word((UINT16) dcinfo->image_width); /* image size */ put_word((UINT16) dcinfo->image_height); /* flag byte: not interlaced, no local color map */ putc(0x00, dcinfo->output_file); /* Write Initial Code Size byte */ putc(InitCodeSize, dcinfo->output_file); /* Initialize for LZW compression of image data */ compress_init(InitCodeSize+1); } /* * Initialize for GIF output. */ METHODDEF void output_init (decompress_info_ptr cinfo) { dcinfo = cinfo; /* save for use by local routines */ if (cinfo->final_out_comps != 1) /* safety check */ ERREXIT(cinfo->emethods, "GIF output got confused"); /* Allocate space for hash table */ hash_code = (code_int FAR *) (*cinfo->emethods->alloc_medium) (HSIZE * SIZEOF(code_int)); hash_prefix = (code_int FAR *) (*cinfo->emethods->alloc_medium) (HSIZE * SIZEOF(code_int)); hash_suffix = (UINT8 FAR *) (*cinfo->emethods->alloc_medium) (HSIZE * SIZEOF(UINT8)); /* * If we aren't quantizing, put_color_map won't be called, * so emit the header now. This only happens with gray scale output. * (If we are quantizing, wait for the color map to be provided.) */ if (! cinfo->quantize_colors) emit_header(256, (JSAMPARRAY) NULL); } /* * Write the color map. */ METHODDEF void put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap) { emit_header(num_colors, colormap); } /* * Write some pixel data. */ METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register JSAMPROW ptr; register long col; register long width = cinfo->image_width; register int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; for (col = width; col > 0; col--) { compress_byte(GETJSAMPLE(*ptr)); ptr++; } } } /* * Finish up at the end of the file. */ METHODDEF void output_term (decompress_info_ptr cinfo) { /* Flush LZW mechanism */ compress_term(); /* Write a zero-length data block to end the series */ putc(0, cinfo->output_file); /* Write the GIF terminator mark */ putc(';', cinfo->output_file); /* Make sure we wrote the output file OK */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); /* Free space */ /* no work (we let free_all release the workspace) */ } /* * The method selection routine for GIF format output. * This should be called from d_ui_method_selection if GIF output is wanted. */ GLOBAL void jselwgif (decompress_info_ptr cinfo) { cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; cinfo->methods->put_pixel_rows = put_pixel_rows; cinfo->methods->output_term = output_term; if (cinfo->out_color_space != CS_GRAYSCALE && cinfo->out_color_space != CS_RGB) ERREXIT(cinfo->emethods, "GIF output must be grayscale or RGB"); /* Force quantization if color or if > 8 bits input */ if (cinfo->out_color_space == CS_RGB || cinfo->data_precision > 8) { /* Force quantization to at most 256 colors */ cinfo->quantize_colors = TRUE; if (cinfo->desired_number_of_colors > 256) cinfo->desired_number_of_colors = 256; } } #endif /* GIF_SUPPORTED */ RUE; /* no waiting symbol yet */ /* init output buffering vars */ bytesinpkt = 0; cur_accum = 0; cur_bits = 0; /* clear hash table */ clear_hash(); /* GIF specifies an initial Clear code */ output(ClearCode); } LOCAL voixloadimage.4.1/jpeg/jwrjfif.c 644 221 144 30360 5340472667 11327 /* * jwrjfif.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write standard JPEG file headers/markers. * The file format created is a raw JPEG data stream with (optionally) an * APP0 marker per the JFIF spec. This will handle baseline and * JFIF-convention JPEG files, although there is currently no provision * for inserting a thumbnail image in the JFIF header. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. However, the changes to write to something * else are localized in the macros appearing just below. * * These routines are invoked via the methods write_file_header, * write_scan_header, write_jpeg_data, write_scan_trailer, and * write_file_trailer. */ #include "jinclude.h" #ifdef JFIF_SUPPORTED /* * To output to something other than a stdio stream, you'd need to redefine * these macros. */ /* Write a single byte */ #define emit_byte(cinfo,x) putc((x), cinfo->output_file) /* Write some bytes from a (char *) buffer */ #define WRITE_BYTES(cinfo,dataptr,datacount) \ { if (JFWRITE(cinfo->output_file, dataptr, datacount) \ != (size_t) (datacount)) \ ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* Clean up and verify successful output */ #define CHECK_OUTPUT(cinfo) \ { fflush(cinfo->output_file); \ if (ferror(cinfo->output_file)) \ ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* End of stdio-specific code. */ typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; LOCAL void emit_marker (compress_info_ptr cinfo, JPEG_MARKER mark) /* Emit a marker code */ { emit_byte(cinfo, 0xFF); emit_byte(cinfo, mark); } LOCAL void emit_2bytes (compress_info_ptr cinfo, int value) /* Emit a 2-byte integer; these are always MSB first in JPEG files */ { emit_byte(cinfo, (value >> 8) & 0xFF); emit_byte(cinfo, value & 0xFF); } LOCAL int emit_dqt (compress_info_ptr cinfo, int index) /* Emit a DQT marker */ /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ { QUANT_TBL_PTR data = cinfo->quant_tbl_ptrs[index]; int prec = 0; int i; for (i = 0; i < DCTSIZE2; i++) { if (data[i] > 255) prec = 1; } emit_marker(cinfo, M_DQT); emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); for (i = 0; i < DCTSIZE2; i++) { if (prec) emit_byte(cinfo, data[i] >> 8); emit_byte(cinfo, data[i] & 0xFF); } return prec; } LOCAL void emit_dht (compress_info_ptr cinfo, int index, boolean is_ac) /* Emit a DHT marker */ { HUFF_TBL * htbl; int length, i; if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ } else { htbl = cinfo->dc_huff_tbl_ptrs[index]; } if (htbl == NULL) ERREXIT1(cinfo->emethods, "Huffman table 0x%02x was not defined", index); if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); htbl->sent_table = TRUE; } } LOCAL void emit_dac (compress_info_ptr cinfo) /* Emit a DAC marker */ /* Since the useful info is so small, we want to emit all the tables in */ /* one DAC marker. Therefore this routine does its own scan of the table. */ { char dc_in_use[NUM_ARITH_TBLS]; char ac_in_use[NUM_ARITH_TBLS]; int length, i; for (i = 0; i < NUM_ARITH_TBLS; i++) dc_in_use[i] = ac_in_use[i] = 0; for (i = 0; i < cinfo->num_components; i++) { dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1; ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) length += dc_in_use[i] + ac_in_use[i]; emit_marker(cinfo, M_DAC); emit_2bytes(cinfo, length*2 + 2); for (i = 0; i < NUM_ARITH_TBLS; i++) { if (dc_in_use[i]) { emit_byte(cinfo, i); emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); } if (ac_in_use[i]) { emit_byte(cinfo, i + 0x10); emit_byte(cinfo, cinfo->arith_ac_K[i]); } } } LOCAL void emit_dri (compress_info_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); } LOCAL void emit_sof (compress_info_ptr cinfo, JPEG_MARKER code) /* Emit a SOF marker */ { int i; emit_marker(cinfo, code); emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ if (cinfo->image_height > 65535L || cinfo->image_width > 65535L) ERREXIT(cinfo->emethods, "Maximum image dimension for JFIF is 65535 pixels"); emit_byte(cinfo, cinfo->data_precision); emit_2bytes(cinfo, (int) cinfo->image_height); emit_2bytes(cinfo, (int) cinfo->image_width); emit_byte(cinfo, cinfo->num_components); for (i = 0; i < cinfo->num_components; i++) { emit_byte(cinfo, cinfo->comp_info[i].component_id); emit_byte(cinfo, (cinfo->comp_info[i].h_samp_factor << 4) + cinfo->comp_info[i].v_samp_factor); emit_byte(cinfo, cinfo->comp_info[i].quant_tbl_no); } } LOCAL void emit_sos (compress_info_ptr cinfo) /* Emit a SOS marker */ { int i; emit_marker(cinfo, M_SOS); emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ emit_byte(cinfo, cinfo->comps_in_scan); for (i = 0; i < cinfo->comps_in_scan; i++) { emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id); emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4) + cinfo->cur_comp_info[i]->ac_tbl_no); } emit_byte(cinfo, 0); /* Spectral selection start */ emit_byte(cinfo, DCTSIZE2-1); /* Spectral selection end */ emit_byte(cinfo, 0); /* Successive approximation */ } LOCAL void emit_jfif_app0 (compress_info_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ { /* * Length of APP0 block (2 bytes) * Block ID (4 bytes - ASCII "JFIF") * Zero byte (1 byte to terminate the ID string) * Version Major, Minor (2 bytes - 0x01, 0x01) * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) * Xdpu (2 bytes - dots per unit horizontal) * Ydpu (2 bytes - dots per unit vertical) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ emit_marker(cinfo, M_APP0); emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x49); emit_byte(cinfo, 0x46); emit_byte(cinfo, 0); emit_byte(cinfo, 1); /* Major version */ emit_byte(cinfo, 1); /* Minor version */ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ emit_2bytes(cinfo, (int) cinfo->X_density); emit_2bytes(cinfo, (int) cinfo->Y_density); emit_byte(cinfo, 0); /* No thumbnail image */ emit_byte(cinfo, 0); } LOCAL void emit_com (compress_info_ptr cinfo, char * dataptr, size_t datalen) /* Emit a COM marker */ { if ((unsigned) datalen <= (unsigned) 65533) { /* safety check */ emit_marker(cinfo, M_COM); emit_2bytes(cinfo, (int) (datalen + 2)); /* length */ while (datalen--) { emit_byte(cinfo, *dataptr); dataptr++; } } } /* * Write the file header. */ METHODDEF void write_file_header (compress_info_ptr cinfo) { char qt_in_use[NUM_QUANT_TBLS]; int i, prec; boolean is_baseline; emit_marker(cinfo, M_SOI); /* first the SOI */ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ emit_jfif_app0(cinfo); if (cinfo->comment_text != NULL) /* and an optional COM block */ emit_com(cinfo, cinfo->comment_text, (size_t) (strlen(cinfo->comment_text))); /* Emit DQT for each quantization table. */ /* Note that doing it here means we can't adjust the QTs on-the-fly. */ /* If we did want to do that, we'd have a problem with checking precision */ /* for the is_baseline determination. */ for (i = 0; i < NUM_QUANT_TBLS; i++) qt_in_use[i] = 0; for (i = 0; i < cinfo->num_components; i++) qt_in_use[cinfo->comp_info[i].quant_tbl_no] = 1; prec = 0; for (i = 0; i < NUM_QUANT_TBLS; i++) { if (qt_in_use[i]) prec += emit_dqt(cinfo, i); } /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. */ /* Note we assume that Huffman table numbers won't be changed later. */ is_baseline = TRUE; if (cinfo->arith_code || (cinfo->data_precision != 8)) is_baseline = FALSE; for (i = 0; i < cinfo->num_components; i++) { if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1) is_baseline = FALSE; } if (prec && is_baseline) { is_baseline = FALSE; /* If it's baseline except for quantizer size, warn the user */ TRACEMS(cinfo->emethods, 0, "Caution: quantization tables are too coarse for baseline JPEG"); } /* Emit the proper SOF marker */ if (cinfo->arith_code) emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } /* * Write the start of a scan (everything through the SOS marker). */ METHODDEF void write_scan_header (compress_info_ptr cinfo) { int i; if (cinfo->arith_code) { /* Emit arith conditioning info. We will have some duplication * if the file has multiple scans, but it's so small it's hardly * worth worrying about. */ emit_dac(cinfo); } else { /* Emit Huffman tables. Note that emit_dht takes care of * suppressing duplicate tables. */ for (i = 0; i < cinfo->comps_in_scan; i++) { emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE); emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE); } } /* Emit DRI if required --- note that DRI value could change for each scan. * If it doesn't, a tiny amount of space is wasted in multiple-scan files. * We assume DRI will never be nonzero for one scan and zero for a later one. */ if (cinfo->restart_interval) emit_dri(cinfo); emit_sos(cinfo); } /* * Write some bytes of compressed data within a scan. */ METHODDEF void write_jpeg_data (compress_info_ptr cinfo, char *dataptr, int datacount) { WRITE_BYTES(cinfo, dataptr, datacount); } /* * Finish up after a compressed scan (series of write_jpeg_data calls). */ METHODDEF void write_scan_trailer (compress_info_ptr cinfo) { /* no work needed in this format */ } /* * Finish up at the end of the file. */ METHODDEF void write_file_trailer (compress_info_ptr cinfo) { emit_marker(cinfo, M_EOI); /* Make sure we wrote the output file OK */ CHECK_OUTPUT(cinfo); } /* * The method selection routine for standard JPEG header writing. * This should be called from c_ui_method_selection if appropriate. */ GLOBAL void jselwjfif (compress_info_ptr cinfo) { cinfo->methods->write_file_header = write_file_header; cinfo->methods->write_scan_header = write_scan_header; cinfo->methods->write_jpeg_data = write_jpeg_data; cinfo->methods->write_scan_trailer = write_scan_trailer; cinfo->methods->write_file_trailer = write_file_trailer; } #endif /* JFIF_SUPPORTED */ image data */ compress_init(InitCodeSize+1); } /* * Initialize for GIF output. */ METHODDEF void output_init (decompress_info_ptr cinfo) { dcinfo = cinfo; /* save for use by local routines */ if (cinfo->final_out_comps != 1) /* safety check */ ERREXIT(cixloadimage.4.1/jpeg/jwrppm.c 644 221 144 21640 5334764234 11203 /* * jwrppm.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in PPM/PGM format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. * * These routines are invoked via the methods put_pixel_rows, put_color_map, * and output_init/term. */ #include "jinclude.h" #ifdef PPM_SUPPORTED /* * Haven't yet got around to making this work with text-format output, * hence cannot handle pixels wider than 8 bits. */ #ifndef EIGHT_BIT_SAMPLES Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ #endif /* * On most systems, writing individual bytes with putc() is drastically less * efficient than buffering a row at a time for fwrite(). But we must * allocate the row buffer in near data space on PCs, because we are assuming * small-data memory model, wherein fwrite() can't reach far memory. If you * need to process very wide images on a PC, you may have to use the putc() * approach. Also, there are still a few systems around wherein fwrite() is * actually implemented as a putc() loop, in which case this buffer is a waste * of space. So the putc() method can be used by defining USE_PUTC_OUTPUT. */ #ifndef USE_PUTC_OUTPUT static char * row_buffer; /* holds 1 pixel row's worth of output */ #endif /* * Write the file header. */ METHODDEF void output_init (decompress_info_ptr cinfo) { if (cinfo->out_color_space == CS_GRAYSCALE) { /* emit header for raw PGM format */ fprintf(cinfo->output_file, "P5\n%ld %ld\n%d\n", cinfo->image_width, cinfo->image_height, 255); #ifndef USE_PUTC_OUTPUT /* allocate space for row buffer: 1 byte/pixel */ row_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) (SIZEOF(char) * cinfo->image_width)); #endif } else if (cinfo->out_color_space == CS_RGB) { /* emit header for raw PPM format */ fprintf(cinfo->output_file, "P6\n%ld %ld\n%d\n", cinfo->image_width, cinfo->image_height, 255); #ifndef USE_PUTC_OUTPUT /* allocate space for row buffer: 3 bytes/pixel */ row_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) (3 * SIZEOF(char) * cinfo->image_width)); #endif } else { ERREXIT(cinfo->emethods, "PPM output must be grayscale or RGB"); } } /* * Write some pixel data. */ #ifdef USE_PUTC_OUTPUT METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; for (col = width; col > 0; col--) { putc(GETJSAMPLE(*ptr0), outfile); ptr0++; putc(GETJSAMPLE(*ptr1), outfile); ptr1++; putc(GETJSAMPLE(*ptr2), outfile); ptr2++; } } } METHODDEF void put_gray_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr0; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; for (col = width; col > 0; col--) { putc(GETJSAMPLE(*ptr0), outfile); ptr0++; } } } #else /* use row buffering */ METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { FILE * outfile = cinfo->output_file; register JSAMPROW ptr0, ptr1, ptr2; register char * row_bufferptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++); *row_bufferptr++ = (char) GETJSAMPLE(*ptr1++); *row_bufferptr++ = (char) GETJSAMPLE(*ptr2++); } (void) JFWRITE(outfile, row_buffer, 3*width); } } METHODDEF void put_gray_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { FILE * outfile = cinfo->output_file; register JSAMPROW ptr0; register char * row_bufferptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++); } (void) JFWRITE(outfile, row_buffer, width); } } #endif /* USE_PUTC_OUTPUT */ /* * Write some pixel data when color quantization is in effect. */ #ifdef USE_PUTC_OUTPUT METHODDEF void put_demapped_rgb (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register JSAMPROW color_map1 = cinfo->colormap[1]; register JSAMPROW color_map2 = cinfo->colormap[2]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); putc(GETJSAMPLE(color_map0[pixval]), outfile); putc(GETJSAMPLE(color_map1[pixval]), outfile); putc(GETJSAMPLE(color_map2[pixval]), outfile); } } } METHODDEF void put_demapped_gray (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); putc(GETJSAMPLE(color_map0[pixval]), outfile); } } } #else /* use row buffering */ METHODDEF void put_demapped_rgb (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register char * row_bufferptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register JSAMPROW color_map1 = cinfo->colormap[1]; register JSAMPROW color_map2 = cinfo->colormap[2]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]); *row_bufferptr++ = (char) GETJSAMPLE(color_map1[pixval]); *row_bufferptr++ = (char) GETJSAMPLE(color_map2[pixval]); } (void) JFWRITE(outfile, row_buffer, 3*width); } } METHODDEF void put_demapped_gray (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register char * row_bufferptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]); } (void) JFWRITE(outfile, row_buffer, width); } } #endif /* USE_PUTC_OUTPUT */ /* * Write the color map. * For PPM output, we just remember to demap the output data! */ METHODDEF void put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap) { if (cinfo->out_color_space == CS_RGB) cinfo->methods->put_pixel_rows = put_demapped_rgb; else cinfo->methods->put_pixel_rows = put_demapped_gray; } /* * Finish up at the end of the file. */ METHODDEF void output_term (decompress_info_ptr cinfo) { /* No work except to make sure we wrote the output file OK; */ /* we let free_all release any workspace */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* * The method selection routine for PPM format output. * This should be called from d_ui_method_selection if PPM output is wanted. */ GLOBAL void jselwppm (decompress_info_ptr cinfo) { cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; if (cinfo->out_color_space == CS_RGB) cinfo->methods->put_pixel_rows = put_pixel_rows; else cinfo->methods->put_pixel_rows = put_gray_rows; cinfo->methods->output_term = output_term; } #endif /* PPM_SUPPORTED */ ss * efficient than buffering a row at a time for fwrite(). But we must * allocate the row buxloadimage.4.1/jpeg/jwrrle.c 644 221 144 15161 5334764246 11175 /* * jwrrle.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in RLE format. * The Utah Raster Toolkit library is required (version 3.0). * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. * * These routines are invoked via the methods put_pixel_rows, put_color_map, * and output_init/term. * * Based on code contributed by Mike Lijewski. */ #include "jinclude.h" #ifdef RLE_SUPPORTED /* rle.h is provided by the Utah Raster Toolkit. */ #include /* * output_term assumes that JSAMPLE has the same representation as rle_pixel, * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. */ #ifndef EIGHT_BIT_SAMPLES Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ #endif /* * Since RLE stores scanlines bottom-to-top, we have to invert the image * from JPEG's top-to-bottom order. To do this, we save the outgoing data * in virtual array(s) during put_pixel_row calls, then actually emit the * RLE file during output_term. We use one virtual array if the output is * grayscale or colormapped, more if it is full color. */ #define MAX_CHANS 4 /* allow up to four color components */ static big_sarray_ptr channels[MAX_CHANS]; /* Virtual arrays for saved data */ static long cur_output_row; /* next row# to write to virtual array(s) */ /* * For now, if we emit an RLE color map then it is always 256 entries long, * though not all of the entries need be used. */ #define CMAPBITS 8 #define CMAPLENGTH (1<<(CMAPBITS)) static rle_map *output_colormap; /* RLE-style color map, or NULL if none */ static int number_colors; /* Number of colors actually used */ /* * Write the file header. * * In this module it's easier to wait till output_term to actually write * anything; here we just request the big arrays we'll need. */ METHODDEF void output_init (decompress_info_ptr cinfo) { short ci; if (cinfo->final_out_comps > MAX_CHANS) ERREXIT1(cinfo->emethods, "Cannot handle %d output channels for RLE", cinfo->final_out_comps); for (ci = 0; ci < cinfo->final_out_comps; ci++) { channels[ci] = (*cinfo->emethods->request_big_sarray) (cinfo->image_width, cinfo->image_height, 1L); } output_colormap = NULL; /* No output colormap as yet */ number_colors = 0; cur_output_row = 0; /* Start filling virtual arrays at row 0 */ cinfo->total_passes++; /* count file writing as separate pass */ } /* * Write some pixel data. * * This routine just saves the data away in virtual arrays. */ METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { JSAMPROW outputrow[1]; /* a pseudo JSAMPARRAY structure */ int row; short ci; for (row = 0; row < num_rows; row++) { for (ci = 0; ci < cinfo->final_out_comps; ci++) { outputrow[0] = *((*cinfo->emethods->access_big_sarray) (channels[ci], cur_output_row, TRUE)); jcopy_sample_rows(pixel_data[ci], row, outputrow, 0, 1, cinfo->image_width); } cur_output_row++; } } /* * Write the color map. * * For RLE output we just save the colormap for the output stage. */ METHODDEF void put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap) { size_t cmapsize; short ci; int i; if (num_colors > CMAPLENGTH) ERREXIT1(cinfo->emethods, "Cannot handle %d colormap entries for RLE", num_colors); /* Allocate storage for RLE-style cmap, zero any extra entries */ cmapsize = cinfo->color_out_comps * CMAPLENGTH * SIZEOF(rle_map); output_colormap = (rle_map *) (*cinfo->emethods->alloc_small) (cmapsize); MEMZERO(output_colormap, cmapsize); /* Save away data in RLE format --- note 8-bit left shift! */ /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */ for (ci = 0; ci < cinfo->color_out_comps; ci++) { for (i = 0; i < num_colors; i++) { output_colormap[ci * CMAPLENGTH + i] = GETJSAMPLE(colormap[ci][i]) << 8; } } number_colors = num_colors; } /* * Finish up at the end of the file. * * Here is where we really output the RLE file. */ METHODDEF void output_term (decompress_info_ptr cinfo) { rle_hdr header; /* Output file information */ rle_pixel *output_rows[MAX_CHANS]; char cmapcomment[80]; short ci; long row; /* Initialize the header info */ MEMZERO(&header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */ header.rle_file = cinfo->output_file; header.xmin = 0; header.xmax = cinfo->image_width - 1; header.ymin = 0; header.ymax = cinfo->image_height - 1; header.alpha = 0; header.ncolors = cinfo->final_out_comps; for (ci = 0; ci < cinfo->final_out_comps; ci++) { RLE_SET_BIT(header, ci); } if (number_colors > 0) { header.ncmap = cinfo->color_out_comps; header.cmaplen = CMAPBITS; header.cmap = output_colormap; /* Add a comment to the output image with the true colormap length. */ sprintf(cmapcomment, "color_map_length=%d", number_colors); rle_putcom(cmapcomment, &header); } /* Emit the RLE header and color map (if any) */ rle_put_setup(&header); /* Now output the RLE data from our virtual array(s). * We assume here that (a) rle_pixel is represented the same as JSAMPLE, * and (b) we are not on a machine where FAR pointers differ from regular. */ for (row = cinfo->image_height-1; row >= 0; row--) { (*cinfo->methods->progress_monitor) (cinfo, cinfo->image_height-row-1, cinfo->image_height); for (ci = 0; ci < cinfo->final_out_comps; ci++) { output_rows[ci] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray) (channels[ci], row, FALSE)); } rle_putrow(output_rows, (int) cinfo->image_width, &header); } cinfo->completed_passes++; /* Emit file trailer */ rle_puteof(&header); fflush(cinfo->output_file); if (ferror(cinfo->output_file)) ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); /* Release memory */ /* no work (we let free_all release the workspace) */ } /* * The method selection routine for RLE format output. * This should be called from d_ui_method_selection if RLE output is wanted. */ GLOBAL void jselwrle (decompress_info_ptr cinfo) { cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; cinfo->methods->put_pixel_rows = put_pixel_rows; cinfo->methods->output_term = output_term; } #endif /* RLE_SUPPORTED */ rptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]); }xloadimage.4.1/jpeg/jwrtarga.c 644 221 144 22521 5334764262 11505 /* * jwrtarga.c * * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in Targa format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. * * These routines are invoked via the methods put_pixel_rows, put_color_map, * and output_init/term. * * Based on code contributed by Lee Daniel Crocker. */ #include "jinclude.h" #ifdef TARGA_SUPPORTED /* * To support 12-bit JPEG data, we'd have to scale output down to 8 bits. * This is not yet implemented. */ #ifndef EIGHT_BIT_SAMPLES Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ #endif /* * On most systems, writing individual bytes with putc() is drastically less * efficient than buffering a row at a time for fwrite(). But we must * allocate the row buffer in near data space on PCs, because we are assuming * small-data memory model, wherein fwrite() can't reach far memory. If you * need to process very wide images on a PC, you may have to use the putc() * approach. Also, there are still a few systems around wherein fwrite() is * actually implemented as a putc() loop, in which case this buffer is a waste * of space. So the putc() method can be used by defining USE_PUTC_OUTPUT. */ #ifndef USE_PUTC_OUTPUT static char * row_buffer; /* holds 1 pixel row's worth of output */ #endif LOCAL void write_header (decompress_info_ptr cinfo, int num_colors) /* Create and write a Targa header */ { char targaheader[18]; /* Set unused fields of header to 0 */ MEMZERO(targaheader, SIZEOF(targaheader)); if (num_colors > 0) { targaheader[1] = 1; /* color map type 1 */ targaheader[5] = (char) (num_colors & 0xFF); targaheader[6] = (char) (num_colors >> 8); targaheader[7] = 24; /* 24 bits per cmap entry */ } targaheader[12] = (char) (cinfo->image_width & 0xFF); targaheader[13] = (char) (cinfo->image_width >> 8); targaheader[14] = (char) (cinfo->image_height & 0xFF); targaheader[15] = (char) (cinfo->image_height >> 8); targaheader[17] = 0x20; /* Top-down, non-interlaced */ if (cinfo->out_color_space == CS_GRAYSCALE) { targaheader[2] = 3; /* image type = uncompressed gray-scale */ targaheader[16] = 8; /* bits per pixel */ } else { /* must be RGB */ if (num_colors > 0) { targaheader[2] = 1; /* image type = colormapped RGB */ targaheader[16] = 8; } else { targaheader[2] = 2; /* image type = uncompressed RGB */ targaheader[16] = 24; } } if (JFWRITE(cinfo->output_file, targaheader, 18) != (size_t) 18) ERREXIT(cinfo->emethods, "Could not write Targa header"); } /* * Write the file header. */ METHODDEF void output_init (decompress_info_ptr cinfo) { if (cinfo->out_color_space == CS_GRAYSCALE) { /* Targa doesn't have a mapped grayscale format, so we will */ /* demap quantized gray output. Never emit a colormap. */ write_header(cinfo, 0); #ifndef USE_PUTC_OUTPUT /* allocate space for row buffer: 1 byte/pixel */ row_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) (SIZEOF(char) * cinfo->image_width)); #endif } else if (cinfo->out_color_space == CS_RGB) { /* For quantized output, defer writing header until put_color_map time. */ if (! cinfo->quantize_colors) write_header(cinfo, 0); #ifndef USE_PUTC_OUTPUT /* allocate space for row buffer: 3 bytes/pixel */ row_buffer = (char *) (*cinfo->emethods->alloc_small) ((size_t) (3 * SIZEOF(char) * cinfo->image_width)); #endif } else { ERREXIT(cinfo->emethods, "Targa output must be grayscale or RGB"); } } /* * Write some pixel data. */ #ifdef USE_PUTC_OUTPUT METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) /* used for unquantized full-color output */ { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr0, ptr1, ptr2; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; for (col = width; col > 0; col--) { putc(GETJSAMPLE(*ptr2), outfile); /* write in BGR order */ ptr2++; putc(GETJSAMPLE(*ptr1), outfile); ptr1++; putc(GETJSAMPLE(*ptr0), outfile); ptr0++; } } } METHODDEF void put_gray_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) /* used for grayscale OR quantized color output */ { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr0; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; for (col = width; col > 0; col--) { putc(GETJSAMPLE(*ptr0), outfile); ptr0++; } } } #else /* use row buffering */ METHODDEF void put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) /* used for unquantized full-color output */ { FILE * outfile = cinfo->output_file; register JSAMPROW ptr0, ptr1, ptr2; register char * row_bufferptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; ptr1 = pixel_data[1][row]; ptr2 = pixel_data[2][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { *row_bufferptr++ = (char) GETJSAMPLE(*ptr2++); /* BGR order */ *row_bufferptr++ = (char) GETJSAMPLE(*ptr1++); *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++); } (void) JFWRITE(outfile, row_buffer, 3*width); } } METHODDEF void put_gray_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) /* used for grayscale OR quantized color output */ { FILE * outfile = cinfo->output_file; register JSAMPROW ptr0; register char * row_bufferptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++); } (void) JFWRITE(outfile, row_buffer, width); } } #endif /* USE_PUTC_OUTPUT */ /* * Write some demapped pixel data when color quantization is in effect. * For Targa, this is only applied to grayscale data. */ #ifdef USE_PUTC_OUTPUT METHODDEF void put_demapped_gray (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { register FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); putc(GETJSAMPLE(color_map0[pixval]), outfile); } } } #else /* use row buffering */ METHODDEF void put_demapped_gray (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data) { FILE * outfile = cinfo->output_file; register JSAMPROW ptr; register char * row_bufferptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register int pixval; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr = pixel_data[0][row]; row_bufferptr = row_buffer; for (col = width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]); } (void) JFWRITE(outfile, row_buffer, width); } } #endif /* USE_PUTC_OUTPUT */ /* * Write the color map. */ METHODDEF void put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap) { register FILE * outfile = cinfo->output_file; int i; if (cinfo->out_color_space == CS_RGB) { /* We only support 8-bit colormap indexes, so only 256 colors */ if (num_colors > 256) ERREXIT(cinfo->emethods, "Too many colors for Targa output"); /* Time to write the header */ write_header(cinfo, num_colors); /* Write the colormap. Note Targa uses BGR byte order */ for (i = 0; i < num_colors; i++) { putc(GETJSAMPLE(colormap[2][i]), outfile); putc(GETJSAMPLE(colormap[1][i]), outfile); putc(GETJSAMPLE(colormap[0][i]), outfile); } } else { cinfo->methods->put_pixel_rows = put_demapped_gray; } } /* * Finish up at the end of the file. */ METHODDEF void output_term (decompress_info_ptr cinfo) { /* No work except to make sure we wrote the output file OK */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* * The method selection routine for Targa format output. * This should be called from d_ui_method_selection if Targa output is wanted. */ GLOBAL void jselwtarga (decompress_info_ptr cinfo) { cinfo->methods->output_init = output_init; cinfo->methods->put_color_map = put_color_map; if (cinfo->out_color_space == CS_GRAYSCALE || cinfo->quantize_colors) cinfo->methods->put_pixel_rows = put_gray_rows; else cinfo->methods->put_pixel_rows = put_pixel_rows; cinfo->methods->output_term = output_term; } #endif /* TARGA_SUPPORTED */ [1] = 1; /* color map type 1 */ targaheader[5] = (char) (num_colors & 0xFF); targaheader[6] = (char) (num_colors >> 8); targaheader[7] = 24; /* 24 bits per cmap exloadimage.4.1/jpeg/makcjpeg.st 644 221 144 2655 5340774664 11643 ; Project file for Independent JPEG Group's software ; ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. ; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de) ; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de). ; ; To use this file, rename it to CJPEG.PRJ. ; If you are using Turbo C, change filenames beginning with "PC..." to "TC..." ; Read SETUP instructions before trying to make the program! ; ; ; * * * Output file * * * cjpeg.ttp ; ; * * * DEFINES * * * .C[-DHAVE_STDC] .C[-DINCLUDES_ARE_ANSI] .C[-DNEED_SIGNAL_CATCHER] ; It's safer to have a signal catcher. .C[-DTWO_FILE_COMMANDLINE] ; If you like the UNIX - style with ; I/O redirection, comment this line out. .C[-DPROGRESS_REPORT] ; This enables the % progress indicator ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" .C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures .C[-wsig] ; warn if significant digits may be lost .C[-w-cln] ; no "constant is long" warnings = ; * * * * List of modules * * * * PCSTART.O jcmain.c (jinclude.h,jconfig.h,jpegdata.h,jversion.h) JPEG.LIB ; built by LIB_JPEG.PRJ ;PCFLTLIB.LIB ; floating point library -- you shouldn't need this PCSTDLIB.LIB ; standard library PCEXTLIB.LIB ; extended library put_color_map = put_color_map; if (cinfo->out_color_space == CS_GRAYSCALE || cinfxloadimage.4.1/jpeg/makdjpeg.st 644 221 144 2655 5340774666 11646 ; Project file for Independent JPEG Group's software ; ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. ; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de) ; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de). ; ; To use this file, rename it to DJPEG.PRJ. ; If you are using Turbo C, change filenames beginning with "PC..." to "TC..." ; Read SETUP instructions before trying to make the program! ; ; ; * * * Output file * * * djpeg.ttp ; ; * * * DEFINES * * * .C[-DHAVE_STDC] .C[-DINCLUDES_ARE_ANSI] .C[-DNEED_SIGNAL_CATCHER] ; It's safer to have a signal catcher. .C[-DTWO_FILE_COMMANDLINE] ; If you like the UNIX - style with ; I/O redirection, comment this line out. .C[-DPROGRESS_REPORT] ; This enables the % progress indicator ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" .C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures .C[-wsig] ; warn if significant digits may be lost .C[-w-cln] ; no "constant is long" warnings = ; * * * * List of modules * * * * PCSTART.O jdmain.c (jinclude.h,jconfig.h,jpegdata.h,jversion.h) JPEG.LIB ; built by LIB_JPEG.PRJ ;PCFLTLIB.LIB ; floating point library -- you shouldn't need this PCSTDLIB.LIB ; standard library PCEXTLIB.LIB ; extended library ixel_rows = put_gray_rows; else cinfo->methods->put_pixel_rows = put_pixel_roxloadimage.4.1/jpeg/makefile.ansi 644 221 144 14435 5340774657 12164 # Makefile for Independent JPEG Group's software # This makefile is suitable for Unix-like systems with ANSI-capable compilers. # If you have a non-ANSI compiler, makefile.unix is a better starting point. # Read SETUP instructions before saying "make" !! # The name of your C compiler: CC= cc # You may need to adjust these cc options: CFLAGS= -O # In particular: # Add -DBSD if on a pure BSD system (see jinclude.h). # Add -DMEM_STATS to enable gathering of memory usage statistics. # You may also want to add -DTWO_FILE_COMMANDLINE or -D switches for other # symbols listed in jconfig.h, if you prefer not to change jconfig.h. # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. # In particular, on some versions of HP-UX (and probably other SysV-derived # systems) there is a faster alternate malloc(3) library that you can use # by adding "-lmalloc" to this line. LDLIBS= # miscellaneous OS-dependent stuff # linker LN= $(CC) # file deletion command RM= rm -f # library (.a) file creation command AR= ar rc # second step in .a creation (use "touch" if not needed) AR2= ranlib # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o # compression objectfiles CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \ jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \ jrdrle.o jrdtarga.o COBJECTS= jcmain.o $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.o jddeflts.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \ jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o jrdjfif.o \ jwrgif.o jwrppm.o jwrrle.o jwrtarga.o DOBJECTS= jdmain.o $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: cjpeg djpeg # By default, libjpeg.a is not built unless you explicitly request it. # You can add libjpeg.a to the line above if you want it built by default. cjpeg: $(COBJECTS) $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS) djpeg: $(DOBJECTS) $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS) # libjpeg.a is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.a: $(LIBOBJECTS) $(RM) libjpeg.a $(AR) libjpeg.a $(LIBOBJECTS) $(AR2) libjpeg.a jmemsys.c: echo You must select a system-dependent jmemsys.c file. echo Please read the SETUP directions. exit 1 clean: $(RM) *.o cjpeg djpeg libjpeg.a core testout.* distribute: $(RM) jpegsrc.tar* tar cvf jpegsrc.tar $(DISTFILES) compress -v jpegsrc.tar test: cjpeg djpeg $(RM) testout.ppm testout.gif testout.jpg ./djpeg testorig.jpg >testout.ppm ./djpeg -gif testorig.jpg >testout.gif ./cjpeg testimg.ppm >testout.jpg cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.o : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.o : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.o : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h >output_file; register JSAMPROW ptr0, ptr1, ptr2; register char * row_bufferptr; register long col; long width = cinfo->image_width; int row; for (row = 0; row < num_rows; row++) { ptr0 = pixel_data[0][row]; xloadimage.4.1/jpeg/makefile.bcc 644 221 144 16723 5340774675 11763 # Makefile for Independent JPEG Group's software # This makefile is suitable for Borland C (Turbo C) on MS-DOS. # It is set up for Borland C++, revision 3.0 or later. # For older versions (pre-3.0), replace "-O2" with "-O -G -Z" in CFLAGS. # If you have an even older version of Turbo C, you may be able to make it # work by saying "CC= tcc" below. (Very early versions of Turbo C++, # like 1.01, are so buggy that you may as well forget it.) # Thanks to Tom Wright and Ge' Weijers for this file. # Read SETUP instructions before saying "make" !! # The name of your C compiler: CC= bcc # You may need to adjust these cc options: CFLAGS= -DHAVE_STDC -DINCLUDES_ARE_ANSI \ -ms -DMSDOS -DUSE_FMEM -DINCOMPLETE_TYPES_BROKEN -w-par -O2 # -DHAVE_STDC -DINCLUDES_ARE_ANSI enable ANSI-C features (we DON'T want -A) # -ms selects small memory model for most efficient code # -DMSDOS enables DOS-specific code # -DUSE_FMEM indicates we have _fmemcpy() and _fmemset() # -DINCOMPLETE_TYPES_BROKEN suppresses bogus warning about undefined structures # -w-par suppresses warnings about unused function parameters # -O2 enables full code optimization (for pre-3.0 Borland C++, use -O -G -Z) # If you run up against DOS' 128-character limit on command line length, # you can get rid of some of the -D switches by adding equivalent #define # commands to the head of jinclude.h. # Link-time cc options: LDFLAGS= -ms # memory model option here must match CFLAGS! # need linker response file because file list > 128 chars RFILE= libjpeg.ans # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj jmemdosa.obj # compression objectfiles CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \ jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \ jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.obj jddeflts.obj jbsmooth.obj jdarith.obj jdcolor.obj \ jdhuff.obj jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj \ jquant2.obj jrevdct.obj jrdjfif.obj jwrgif.obj jwrppm.obj \ jwrrle.obj jwrtarga.obj DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: cjpeg.exe djpeg.exe # libjpeg.lib is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.lib: $(LIBOBJECTS) $(RFILE) del libjpeg.lib tlib @$(RFILE) # linker response file for same $(RFILE) : Makefile del $(RFILE) echo libjpeg.lib & >$(RFILE) echo +jcmaster.obj +jcdeflts.obj +jcarith.obj +jccolor.obj & >>$(RFILE) echo +jcexpand.obj +jchuff.obj +jcmcu.obj +jcpipe.obj & >>$(RFILE) echo +jcsample.obj +jfwddct.obj +jwrjfif.obj +jrdgif.obj & >>$(RFILE) echo +jrdppm.obj +jrdrle.obj +jrdtarga.obj +jdmaster.obj & >>$(RFILE) echo +jddeflts.obj +jbsmooth.obj +jdarith.obj +jdcolor.obj & >>$(RFILE) echo +jdhuff.obj +jdmcu.obj +jdpipe.obj +jdsample.obj & >>$(RFILE) echo +jquant1.obj +jquant2.obj +jrevdct.obj +jrdjfif.obj & >>$(RFILE) echo +jwrgif.obj +jwrppm.obj +jwrrle.obj +jwrtarga.obj & >>$(RFILE) echo +jutils.obj +jerror.obj +jmemmgr.obj +jmemsys.obj & >>$(RFILE) echo +jmemdosa.obj >>$(RFILE) cjpeg.exe: jcmain.obj libjpeg.lib $(CC) $(LDFLAGS) -ecjpeg.exe jcmain.obj libjpeg.lib djpeg.exe: jdmain.obj libjpeg.lib $(CC) $(LDFLAGS) -edjpeg.exe jdmain.obj libjpeg.lib .c.obj: $(CC) $(CFLAGS) -c $< jmemsys.c: echo You must select a system-dependent jmemsys.c file. echo Please read the SETUP directions. exit 1 clean: del *.obj del libjpeg.lib del cjpeg.exe del djpeg.exe del testout.* test: del testout.* djpeg -outfile testout.ppm testorig.jpg djpeg -gif -outfile testout.gif testorig.jpg cjpeg -outfile testout.jpg testimg.ppm fc /b testimg.ppm testout.ppm fc /b testimg.gif testout.gif fc /b testimg.jpg testout.jpg jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.obj : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.obj : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.obj : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.obj : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.obj : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.obj : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.obj : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.obj : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.obj : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.obj : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.obj : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.obj : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.obj : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.obj : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.obj : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.obj : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.obj : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.obj : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.obj : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h jmemdosa.obj : jmemdosa.asm tasm /mx jmemdosa.asm ow_buffer; for (col = width; col > 0; colxloadimage.4.1/jpeg/makefile.icc 644 221 144 13631 5340774677 11767 # Makefile for Independent JPEG Group's software # This makefile is for Intel's Code Builder 32-bit DOS/Windows compiler. # Thanks to Bailey Brown. # Read SETUP instructions before saying "make" !! # The name of your C compiler: CC= icc # You may want to adjust these cc options: CFLAGS= /O3 /Ll /DTWO_FILE_COMMANDLINE # Link-time cc options: LDFLAGS= /F /xregion=4M # /F removes floating-point support, which we don't need. # /xregionsize sets virtual memory region size. # To link any special libraries, add the necessary -l commands here. LDLIBS= # miscellaneous OS-dependent stuff # linker LN= $(CC) # library (.lib) file creation command AR= lib32 # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj # compression objectfiles CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \ jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \ jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.obj jddeflts.obj jbsmooth.obj jdarith.obj jdcolor.obj \ jdhuff.obj jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj \ jquant2.obj jrevdct.obj jrdjfif.obj jwrgif.obj jwrppm.obj \ jwrrle.obj jwrtarga.obj DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: cjpeg.exe djpeg.exe # By default, libjpeg.lib is not built unless you explicitly request it. # You can add libjpeg.lib to the line above if you want it built by default. cjpeg.exe: $(COBJECTS) echo $(COBJECTS) >cjpeg.rsp $(LN) $(LDFLAGS) /ecjpeg.exe @cjpeg.rsp $(LDLIBS) djpeg.exe: $(DOBJECTS) echo $(DOBJECTS) >djpeg.rsp $(LN) $(LDFLAGS) /edjpeg.exe @djpeg.rsp $(LDLIBS) # libjpeg.lib is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.lib: $(LIBOBJECTS) del libjpeg.lib $(AR) libjpeg.lib nobackup batch 128 chars RFILE = libjpeg.ans # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj jmemdosa.obj # compression objectfiles CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \ jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \ jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.obj jddeflts.obj jbsmooth.obj jdarith.obj jdcolor.obj \ jdhuff.obj jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj \ jquant2.obj jrevdct.obj jrdjfif.obj jwrgif.obj jwrppm.obj \ jwrrle.obj jwrtarga.obj DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: cjpeg.exe djpeg.exe # libjpeg.lib is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.lib: $(LIBOBJECTS) $(RFILE) del libjpeg.lib lib @$(RFILE) ; # linker response file for same $(RFILE) : Makefile del $(RFILE) echo libjpeg.lib >$(RFILE) # silly want-to-create-it prompt: echo y >>$(RFILE) echo +jcmaster.obj +jcdeflts.obj +jcarith.obj +jccolor.obj & >>$(RFILE) echo +jcexpand.obj +jchuff.obj +jcmcu.obj +jcpipe.obj & >>$(RFILE) echo +jcsample.obj +jfwddct.obj +jwrjfif.obj +jrdgif.obj & >>$(RFILE) echo +jrdppm.obj +jrdrle.obj +jrdtarga.obj +jdmaster.obj & >>$(RFILE) echo +jddeflts.obj +jbsmooth.obj +jdarith.obj +jdcolor.obj & >>$(RFILE) echo +jdhuff.obj +jdmcu.obj +jdpipe.obj +jdsample.obj & >>$(RFILE) echo +jquant1.obj +jquant2.obj +jrevdct.obj +jrdjfif.obj & >>$(RFILE) echo +jwrgif.obj +jwrppm.obj +jwrrle.obj +jwrtarga.obj & >>$(RFILE) echo +jutils.obj +jerror.obj +jmemmgr.obj +jmemsys.obj & >>$(RFILE) echo +jmemdosa.obj >>$(RFILE) cjpeg.exe: jcmain.obj libjpeg.lib link /STACK:4096 /EXEPACK jcmain.obj, cjpeg.exe, , libjpeg.lib, ; djpeg.exe: jdmain.obj libjpeg.lib link /STACK:4096 /EXEPACK jdmain.obj, djpeg.exe, , libjpeg.lib, ; jmemsys.c: echo You must select a system-dependent jmemsys.c file. echo Please read the SETUP directions. exit 1 clean: del *.obj del libjpeg.lib del cjpeg.exe del djpeg.exe del testout.* test: del testout.* djpeg -outfile testout.ppm testorig.jpg djpeg -gif -outfile testout.gif testorig.jpg cjpeg -outfile testout.jpg testimg.ppm fc /b testimg.ppm testout.ppm fc /b testimg.gif testout.gif fc /b testimg.jpg testout.jpg jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.obj : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.obj : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.obj : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.obj : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.obj : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.obj : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.obj : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.obj : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.obj : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.obj : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.obj : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.obj : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.obj : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.obj : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.obj : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.obj : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.obj : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.obj : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.obj : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h jmemdosa.obj : jmemdosa.asm masm /mx $*; able memory usage statistics (optional) # You might also want to add -G2 if you have an 80286, etc. # If you run up against DOS' 128-character limit on command line length, # you can get rid of some of the -D switches by adding equivalent #define # commands to the head of jinclude.h. CFLAGS = -AS -Ox -W3 -DHAVE_STDC -DINCLUDES_ARE_ANSI -DMSDOS -DUSE_FMEM -DNEED_FHEAPMIN -DSHORTxLCONST_32 # need linker response file because file list > 128 chars RFILE = libjpeg.ans # souxloadimage.4.1/jpeg/makefile.mms 644 221 144 15543 5340774703 12017 # Makefile for Independent JPEG Group's software # This makefile is for use with MMS on VAX/VMS systems. # Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) # and Tim Bell (tbell@netcom.com) for their help. # Read SETUP instructions before saying "MMS" !! CFLAGS= $(CFLAGS) /NoDebug /Optimize /Define = (TWO_FILE_COMMANDLINE,HAVE_STDC,INCLUDES_ARE_ANSI) OPT= Sys$Disk:[]MAKVMS.OPT # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj # compression objectfiles CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \ jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \ jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.obj jddeflts.obj jbsmooth.obj jdarith.obj jdcolor.obj \ jdhuff.obj jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj \ jquant2.obj jrevdct.obj jrdjfif.obj jwrgif.obj jwrppm.obj \ jwrrle.obj jwrtarga.obj DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.olb LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # objectfile lists with commas --- what a crock COBJLIST= jcmain.obj,jcmaster.obj,jcdeflts.obj,jcarith.obj,jccolor.obj,\ jcexpand.obj,jchuff.obj,jcmcu.obj,jcpipe.obj,jcsample.obj,\ jfwddct.obj,jwrjfif.obj,jrdgif.obj,jrdppm.obj,jrdrle.obj,\ jrdtarga.obj,jutils.obj,jerror.obj,jmemmgr.obj,jmemsys.obj DOBJLIST= jdmain.obj,jdmaster.obj,jddeflts.obj,jbsmooth.obj,jdarith.obj,\ jdcolor.obj,jdhuff.obj,jdmcu.obj,jdpipe.obj,jdsample.obj,\ jquant1.obj,jquant2.obj,jrevdct.obj,jrdjfif.obj,jwrgif.obj,\ jwrppm.obj,jwrrle.obj,jwrtarga.obj,jutils.obj,jerror.obj,\ jmemmgr.obj,jmemsys.obj LIBOBJLIST= jcmaster.obj,jcdeflts.obj,jcarith.obj,jccolor.obj,jcexpand.obj,\ jchuff.obj,jcmcu.obj,jcpipe.obj,jcsample.obj,jfwddct.obj,\ jwrjfif.obj,jrdgif.obj,jrdppm.obj,jrdrle.obj,jrdtarga.obj,\ jdmaster.obj,jddeflts.obj,jbsmooth.obj,jdarith.obj,jdcolor.obj,\ jdhuff.obj,jdmcu.obj,jdpipe.obj,jdsample.obj,jquant1.obj,\ jquant2.obj,jrevdct.obj,jrdjfif.obj,jwrgif.obj,jwrppm.obj,\ jwrrle.obj,jwrtarga.obj,jutils.obj,jerror.obj,jmemmgr.obj,\ jmemsys.obj .first @ Define Sys Sys$Library # By default, libjpeg.olb is not built unless you explicitly request it. # You can add libjpeg.olb to the next line if you want it built by default. ALL : cjpeg.exe djpeg.exe @ Continue cjpeg.exe : $(COBJECTS) $(LINK) $(LFLAGS) /Executable = cjpeg.exe $(COBJLIST),$(OPT)/Option djpeg.exe : $(DOBJECTS) $(LINK) $(LFLAGS) /Executable = djpeg.exe $(DOBJLIST),$(OPT)/Option # libjpeg.olb is useful if you are including the JPEG software in a larger # program; you'd include it in your link, rather than the individual modules. libjpeg.olb : $(LIBOBJECTS) Library /Create libjpeg.olb $(LIBOBJLIST) clean : @- Set Protection = Owner:RWED *.*;-1 @- Set Protection = Owner:RWED *.OBJ - Purge /NoLog /NoConfirm *.* - Delete /NoLog /NoConfirm *.OBJ; test : cjpeg.exe djpeg.exe mcr sys$disk:[]djpeg testorig.jpg testout.ppm mcr sys$disk:[]djpeg -gif testorig.jpg testout.gif mcr sys$disk:[]cjpeg testimg.ppm testout.jpg - Backup /Compare/Log testimg.ppm testout.ppm - Backup /Compare/Log testimg.gif testout.gif - Backup /Compare/Log testimg.jpg testout.jpg jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.obj : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.obj : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.obj : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.obj : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.obj : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.obj : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.obj : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.obj : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.obj : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.obj : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.obj : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.obj : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.obj : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.obj : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.obj : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.obj : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.obj : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.obj : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.obj : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h l source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jxloadimage.4.1/jpeg/makefile.sas 644 221 144 15057 5340774661 12014 # Makefile for Independent JPEG Group's software # This makefile is for Amiga systems using SAS C 6.0 and up. # Thanks to Ed Hanway, Mark Rinfret, and Jim Zepeda. # Read SETUP instructions before saying "make" !! # Use jmemname.c as the system-dependent memory manager. # The name of your C compiler: CC= sc # Uncomment the following lines for generic 680x0 version ARCHFLAGS= cpu=any SUFFIX= # Uncomment the following lines for 68030-only version #ARCHFLAGS= cpu=68030 #SUFFIX=.030 # You may need to adjust these cc options: CFLAGS= nostackcheck data=near parms=register optimize $(ARCHFLAGS) \ ignore=104 ignore=304 ignore=306 \ define HAVE_STDC define INCLUDES_ARE_ANSI \ define AMIGA define TWO_FILE_COMMANDLINE \ define NO_MKTEMP define NEED_SIGNAL_CATCHER define SHORTxSHORT_32 # ignore=104 disables warnings for mismatched const qualifiers # ignore=304 disables warnings for variables being optimized out # ignore=306 disables warnings for the inlining of functions # Link-time cc options: LDFLAGS= SC SD ND BATCH # To link any special libraries, add the necessary commands here. LDLIBS= LIB LIB:scm.lib LIB:sc.lib # miscellaneous OS-dependent stuff # linker LN= slink # file deletion command RM= delete quiet # library (.lib) file creation command AR= oml # source files (independently compilable files) SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ jwrppm.c jwrrle.c jwrtarga.c # virtual source files (not present in distribution file, see SETUP) VIRTSOURCES= jmemsys.c # system-dependent implementations of virtual source files SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ jmemdosa.asm # files included by source files INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h # documentation, test, and support files DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o # compression objectfiles CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \ jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \ jrdrle.o jrdtarga.o COBJECTS= jcmain.o $(CLIBOBJECTS) $(COMOBJECTS) # decompression objectfiles DLIBOBJECTS= jdmaster.o jddeflts.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \ jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o jrdjfif.o \ jwrgif.o jwrppm.o jwrrle.o jwrtarga.o DOBJECTS= jdmain.o $(DLIBOBJECTS) $(COMOBJECTS) # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) all: cjpeg$(SUFFIX) djpeg$(SUFFIX) # By default, libjpeg.lib is not built unless you explicitly request it. # You can add libjpeg.lib to the line above if you want it built by default. cjpeg$(SUFFIX): $(COBJECTS) $(LN) testout.ppm ./djpeg -gif testorig.jpg >testout.gif ./cjpeg testimg.ppm >testout.jpg cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h jddeflts.o : jddeflts.c jinclude.h jconfig.h jpegdata.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h jrdrle.o : jrdrle.c jinclude.h jconfig.h jpegdata.h jrdtarga.o : jrdtarga.c jinclude.h jconfig.h jpegdata.h jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h xxloadimage.4.1/jpeg/makefile.vms 644 221 144 4607 5340774705 12011 $! Makefile for Independent JPEG Group's software $! $! This is a command procedure for use on VAX/VMS systems that do not have MMS. $! It builds the JPEG software by brute force, recompiling everything whether $! or not it is necessary. It then runs the basic self-test. $! Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) $! and Tim Bell (tbell@netcom.com) for their help. $! $! Read SETUP instructions before running this!! $! $ DoCompile := CC /NoDebug /Optimize /Define = (TWO_FILE_COMMANDLINE,HAVE_STDC,INCLUDES_ARE_ANSI) $! $ DoCompile jcmain.c $ DoCompile jdmain.c $ DoCompile jcmaster.c $ DoCompile jcdeflts.c $ DoCompile jcarith.c $ DoCompile jccolor.c $ DoCompile jcexpand.c $ DoCompile jchuff.c $ DoCompile jcmcu.c $ DoCompile jcpipe.c $ DoCompile jcsample.c $ DoCompile jfwddct.c $ DoCompile jwrjfif.c $ DoCompile jrdgif.c $ DoCompile jrdppm.c $ DoCompile jrdrle.c $ DoCompile jrdtarga.c $ DoCompile jdmaster.c $ DoCompile jddeflts.c $ DoCompile jbsmooth.c $ DoCompile jdarith.c $ DoCompile jdcolor.c $ DoCompile jdhuff.c $ DoCompile jdmcu.c $ DoCompile jdpipe.c $ DoCompile jdsample.c $ DoCompile jquant1.c $ DoCompile jquant2.c $ DoCompile jrevdct.c $ DoCompile jrdjfif.c $ DoCompile jwrgif.c $ DoCompile jwrppm.c $ DoCompile jwrrle.c $ DoCompile jwrtarga.c $ DoCompile jutils.c $ DoCompile jerror.c $ DoCompile jmemmgr.c $ DoCompile jmemsys.c $! $ Library /Create libjpeg.olb jcmaster.obj,jcdeflts.obj,jcarith.obj, - jccolor.obj,jcexpand.obj,jchuff.obj,jcmcu.obj,jcpipe.obj, - jcsample.obj,jfwddct.obj,jwrjfif.obj,jrdgif.obj,jrdppm.obj, - jrdrle.obj,jrdtarga.obj,jdmaster.obj,jddeflts.obj,jbsmooth.obj, - jdarith.obj,jdcolor.obj,jdhuff.obj,jdmcu.obj,jdpipe.obj, - jdsample.obj,jquant1.obj,jquant2.obj,jrevdct.obj,jrdjfif.obj, - jwrgif.obj,jwrppm.obj,jwrrle.obj,jwrtarga.obj,jutils.obj, - jerror.obj,jmemmgr.obj,jmemsys.obj $! $ Link /Executable = cjpeg.exe jcmain.obj,libjpeg.olb/Library,Sys$Disk:[]MAKVMS.OPT/Option $! $ Link /Executable = djpeg.exe jdmain.obj,libjpeg.olb/Library,Sys$Disk:[]MAKVMS.OPT/Option $! $! Run the self-test $! $ mcr sys$disk:[]djpeg testorig.jpg testout.ppm $ mcr sys$disk:[]djpeg -gif testorig.jpg testout.gif $ mcr sys$disk:[]cjpeg testimg.ppm testout.jpg $ Backup /Compare/Log testimg.ppm testout.ppm $ Backup /Compare/Log testimg.gif testout.gif $ Backup /Compare/Log testimg.jpg testout.jpg $! $ Exit $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # objectfiles common to cjpeg and djpeg COMOBJECTS= jutils.o jerror.o jmxloadimage.4.1/jpeg/makljpeg.icc 644 221 144 1106 5340774700 11741 add jcmaster.obj add jcdeflts.obj add jcarith.obj add jccolor.obj add jcexpand.obj add jchuff.obj add jcmcu.obj add jcpipe.obj add jcsample.obj add jfwddct.obj add jwrjfif.obj add jrdgif.obj add jrdppm.obj add jrdrle.obj add jrdtarga.obj add jdmaster.obj add jddeflts.obj add jbsmooth.obj add jdarith.obj add jdcolor.obj add jdhuff.obj add jdmcu.obj add jdpipe.obj add jdsample.obj add jquant1.obj add jquant2.obj add jrevdct.obj add jrdjfif.obj add jwrgif.obj add jwrppm.obj add jwrrle.obj add jwrtarga.obj add jutils.obj add jerror.obj add jmemmgr.obj add jmemsys.obj update quit .c $ DoCompile jcmcu.c $ DoCompile jcpipe.c $ DoCompile jcsample.c $ DoCompile jfwddct.c $ DoCompile jwrjfif.c $ DoCompile jrdgif.c $ DoCompile jrdppm.c $ DoCompile jrdrle.c $ DoCompile jrdtarga.c $ DoCompile jdmaster.c $ DoCompile jddeflts.c $ DoCompile jbsmooth.c $ DoCompile jdarith.c $ DoCompile jdcolor.c $ DoCompile jdhuff.c $ DoCompile jdmcu.c $ DoCompile jdpipe.c $ DoCompile jdsample.c $ DoCompile jquant1.c $ DoCompile jquant2.c $ Dxloadimage.4.1/jpeg/makljpeg.st 644 221 144 4764 5340774667 11662 ; Project file for Independent JPEG Group's software ; ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. ; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de) ; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de). ; ; To use this file, rename it to LIB_JPEG.PRJ. ; Read SETUP instructions before trying to make the library! ; ; ; * * * Output file * * * jpeg.lib ; ; * * * DEFINES * * * .C[-DHAVE_STDC] .C[-DINCLUDES_ARE_ANSI] ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" .C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures .C[-wsig] ; warn if significant digits may be lost .C[-w-cln] ; no "constant is long" warnings .L[-J] ; link new Obj-format (so we get a library) = ; * * * * List of modules * * * * jbsmooth.c (jinclude.h,jconfig.h,jpegdata.h) jcarith.c (jinclude.h,jconfig.h,jpegdata.h) jccolor.c (jinclude.h,jconfig.h,jpegdata.h) jcdeflts.c (jinclude.h,jconfig.h,jpegdata.h) jcexpand.c (jinclude.h,jconfig.h,jpegdata.h) jchuff.c (jinclude.h,jconfig.h,jpegdata.h) jcmaster.c (jinclude.h,jconfig.h,jpegdata.h) jcmcu.c (jinclude.h,jconfig.h,jpegdata.h) jcpipe.c (jinclude.h,jconfig.h,jpegdata.h) jcsample.c (jinclude.h,jconfig.h,jpegdata.h) jdarith.c (jinclude.h,jconfig.h,jpegdata.h) jdcolor.c (jinclude.h,jconfig.h,jpegdata.h) jddeflts.c (jinclude.h,jconfig.h,jpegdata.h) jdhuff.c (jinclude.h,jconfig.h,jpegdata.h) jdmaster.c (jinclude.h,jconfig.h,jpegdata.h) jdmcu.c (jinclude.h,jconfig.h,jpegdata.h) jdpipe.c (jinclude.h,jconfig.h,jpegdata.h) jdsample.c (jinclude.h,jconfig.h,jpegdata.h) jerror.c (jinclude.h,jconfig.h,jpegdata.h) jquant1.c (jinclude.h,jconfig.h,jpegdata.h) jquant2.c (jinclude.h,jconfig.h,jpegdata.h) jfwddct.c (jinclude.h,jconfig.h,jpegdata.h) jrevdct.c (jinclude.h,jconfig.h,jpegdata.h) jutils.c (jinclude.h,jconfig.h,jpegdata.h) jmemmgr.c (jinclude.h,jconfig.h,jpegdata.h,jmemsys.h) jrdjfif.c (jinclude.h,jconfig.h,jpegdata.h) jrdgif.c (jinclude.h,jconfig.h,jpegdata.h) jrdppm.c (jinclude.h,jconfig.h,jpegdata.h) jrdrle.c (jinclude.h,jconfig.h,jpegdata.h) jrdtarga.c (jinclude.h,jconfig.h,jpegdata.h) jwrjfif.c (jinclude.h,jconfig.h,jpegdata.h) jwrgif.c (jinclude.h,jconfig.h,jpegdata.h) jwrppm.c (jinclude.h,jconfig.h,jpegdata.h) jwrrle.c (jinclude.h,jconfig.h,jpegdata.h) jwrtarga.c (jinclude.h,jconfig.h,jpegdata.h) jmemsys.c (jinclude.h,jconfig.h,jpegdata.h,jmemsys.h) $(CLIBOBJECTxloadimage.4.1/jpeg/makvms.opt 644 221 144 216 5340774706 11500 ! a pointer to the VAX/VMS C Run-Time Shareable Library ! This file is needed by makefile.mms and makefile.vms Sys$Library:VAXCRTL.EXE /Share se this file, rename it to LIB_JPEG.PRJ. ; Read SETUP instructions before trying to make the library! ; ; ; * * * Output file * * * jpeg.lib ; ; * * * DEFINES * * * .C[-DHAVE_STDC] .C[-DINCLUDES_ARE_ANSI] ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" xloadimage.4.1/jpeg/testimg.gif 444 221 144 36557 5276040036 11666 GIF87a}}6hjm2JתŠMcQ0xx_`~AYȼܗb$@㿠f?Ln-^ZcOX|}Q@4@w$2K|ϔqr&F&Zz>qݨpt葆b!Rv룝`3~]nQou~ӟExjnt5䇐;`ߕc\"D8x r/xLAJ]K   ab @?\((;^h!B <.CK_$G98 @q&N>O N(>QML),Q"@@/xB zC 1 C0Wd8A A Rxp[s,_N}@ Mg Yj,ڄYczG1 0=6q x`9x?\  2qt)aY v4( ,0)G(4)`A=} %D%~sC%- Mlz|!1P؄@ll `uRĂ2v*WXP@(\`!zF8No0 0@X4o-D$"E]tLKX9`,H,&`E)Jar l8D7._rn0i)Kب\P@NZ@ `ġ6p.KOAvK-`C)X&8R38a98 z" H6055 `e1Mhae`"a# D@,` X*x4P=İ8! {7B# ;x;6: h*~ F@g7Mf70`OH@_ҁb["LGnZ0h O|0yzz`r >L:fs_!B㠆v: WBcp@0M=A*[IP 0FUaSpfJ7l >JZ@C{hy$ &.;w$~83`hءp A;8 ^ȁA {A(zoa$BKk`3+O6;nXB5A ,xC"XOL4xE :1H"X8wD pCGW?:0v@X d{ ŐV^ PPOvp`i@ %`ELP@5) 2 E r`~ `@&lcx@ijP C9N0 v \g T p 0d0p  vkOAPD @`5O`%f^`x{mxYS LXn X0 v`Uj@$=@Pz ^ef Y_P5W[H"/P|5{ m3j:3P 5᠎`PBx g~а?HI wcv vpduTz@`Gv HV_axفxH0؁b 'p UjP 3P?`քEG9xp<5X 2@ gz:`Tu: 3'{O Y`%kwv҈&遈ҘU".h RY< pާ)  < x}Q^Y0 qCE dZhNp=Ix`j=e`vV"ũ 0aZ' ~ q 0. F=P X` cj7s I:zĥN@ Kx^ q0@jW[x */pxh `Cp UΉ0m b 60?G 㧉`sl:`W3GNJv Ax@ ɀ a Za!%z&L2}ٗ' );i> (K0K4۶mj;j?(- :ِ9Y8 $d `RV`| 7`6PI!k2jp%DO:0uP02P?. q0  mhB@`Ѐ8 E`j^{mP 5 `TZ :E0DP@PU()`%r0 б뱬 uv0 6`? p[9j<:~c0~ < x`xJ$MP P^p 9@ ZGXps sD0f*j/5J# Oڜ͙ 1uP-PN& `0 pI0`Uh z52jpYGI 'OmY{@ Po 01@Fm$w _P{;;&\)# E0`bsP 8z lM l  Y =@hYzPj$@P P H^'/$qɛpmKu@01 ``  ` `l8=m7ynPpxתx @O 4pA<yi `@rp;™P 1p1@_ ِ yPm { ԛN Tӫ037s$O$:p ِP ؐ_O0c 5`W  _pVi()\O}0 1@[Ӈ税7J@ xɰxOz{^P X #WA0ZB ۠!ru]͜pYȐ u+1}P h0`̉s7;~CWP_^x$ZzKS*Y 9H&b sнf3/!P)B(Axpzܼ} -[ 0xk@6[~*h:O$ f^ EE +p0 *jE( a("qp `_uZ)]+\ x p` ep 6m oڈܐ$p9d_]`xm;Vӭ+Mx >P e:ɉVmx[JpKo̰ ЋSPՀ L"fܬ!UvCp]p kνV%< w x @ɘ P oLޙ- @{+9 $Wշ uf.ErO21Vq ` q8PJ0E;p w O Pp.h@ xr OLԛ̣Av$JB:0~M㛅@ o p5i |_@ cJ;?}tqtJpӞTy֗OX"T]  y(fx0e'16$äSd @%6{4T!M=4|m̡cf9f3㥉`f8B6DX4xA@6V`O(R» (J< a@[f4LAA 8; jXmT' 96ѫjYUY/giKD l#-$*I8#JFJ@!J%_\L($X=hxN@6 L` Ts7Rc6YHX' b|zR٣fg ^ 0gDm^@VA`>`Q(7 r X@`C=0)7B<0) 't Tb!sJqut<@ /T!z[g/ >h'`j&wlA `Vt*AG1Q'$NfĆ lxHF7ހ YCƥ7(h0Q,ziQbx* 3`R E 'DX&cm} > }HƏ(AG>d 2̔ 1\xneX%X0bl1d 1 ޸ >yC#1 AxT*0' S/t<] " l h2ƞ!\A0 "BBܐg2Ȅ'!d#\(W5*0!f4i_x jD:_D>A؀! ,Ă6bDB>dA5j^f&Īf80C(sJ<N <+H  @jvl(A;:`a j7J\` p@.<(<\Xbpp氄#+U" h,B=0'm,4C &|d fPdLšJP"~0 qvAh7B$p .(QE9ҁ?@]rA ?865VX*C [ LQ M'he<#ɁNH>|`4%DF88V|?ND!L ~f` @HW?  X8B S" CU](kXCIFШ+6l9XD)@P 3r^t @[E(+Q# ?֛7[B5p 0y؋_C=:Nq+xSQ,QcYl(,İ9|C Wp}AAA3Ol"ʭ9* &'Hd*0HxIC87JHE! {XA2`&07A7 4B LG x(GX;q x쐌6 r^pvِCFAKOIWH72@1n/ :;# A( NCN%p-Ա +^0^p5Ơ  pAR=!!^ZU4[P> hD)< /ar j !8֠[E8nzw߁=db P2ENe ˀ]8A4bW{C< ,(aކ>~ sk :O3\0,ȃw<84y#Ax(A_;Ә@{X."x9cdc,h#(Xa<@P(0c@Tуu0#=^PRȆ60H8MɁn荤8)`Hx (8/^rl\ JG5SXS.HGȻJW`@A5CDW`<_xpB=bx 05` 4>{")gyK kho,lLR0x#mPR(ckځI GGhP(<6p;`h؅{&Dzt!X$NXHȂ!v >8ҁi|pq/HyfІ[yxīIr\SS\2I2;iY}xlPDT6 Bvx ك *(fhX>0y;QJPRHÙ" X(y"hԊ$ӆon@A!=,/PP t,hP+--E0AP0U&^hAgq - 9(<B#x4Tg|"@|y`2,Q.yBZ9ś#{13!JPxA3XJOUlB:zB XUyj05Eit hg<PiZ8h /08l|)"R-IR! ЬiBF {=p{uDĞ!Pt/(W]1%;hDzhPIX5h$8TA]{@CJXՀl~0%0uXJ@8V`KHFRx }Pr3#z{|O2ģp֌m>]]PN3VX8g+J` q//;֔d(* tH "G{h U5>M; 1uQ0yjn +-jJh*([BA$؆m(n9w_c dԡvZx=!M3Pþ 4S?c.0*0WW5c؁}g>0Tp$x!y.x#`RcINJ$-;n|߳9?MWPfҺK{ X`TH@9B⃚Yo`/`F-L@me`Y7(xvkNצ;tHґw[MPJ*`{Ȼ/IX+X7XbUm@y7X^3gJn0#)~.v w?!_ʋ#%Z xfD/LaaŁ $/,8 X4od= J@54/HjL`qHԚf0@p0# 0Q1Q䎘ڜ?_6Qu? YE@\ =`(-ؠC#@H8% !o<>gԡ:ԥT? [x,Mхe$B<8>Æ04`.Vnhu0x<Á#@K3ߗog(&PΊJۜ#t7$WˤhԉZt '؇TxD>pqTʁ A P]Wj\Qo^sF ٩+X$l4h$G#(JGh?r^hghJm JXWr(/ L㥂E`?8!}xh08@`<569`IF:0oPDŽ_w$AwWgdؑ/uTj)yg‚*'|u"ӗ5s(!Cg@QA P bA<"Q s Ca{Y " q2TY4Xo`"#䗐w\иq3 Wr<)aѭ CF{[ЇDu9Ɔ^WKa% $m)rą4u1{dzeXD DĿ,*d,a <[|!DH[8p6kPbȐo!la>AEm{1%T#OpF/('XL P 6AQ6a2Q$qQo84ՕDHt:hQGL2fa6~BNk#l!Jk`Cl봑L2pAE6`*TC C";ȳX 3 51?@)`mॏ^oC,a w4Qd?1GP>v><Y찅 UA$xm^O*lCc("h/<+X)M4hP`S G^D*~2*/Ut)Rk(H&@ApQt 43G!趽C k[ 3ҍ 5xaɂqAD'L0jEH*jj ;l:8Ȁ=XGfqPDL<z.cMv,zKN:n-pĂ"9Y,oLP0S4, w.``bGмF2qÄ0mĒ=g!L':aNC80,N(딠@%K >,ÃĠoy d)jt/Qj8hs ?IjK,~BO( !'" ;^&  +|sr(l05 AkCz =6 0d`0(Ri#ʋ0`HC.!KEP@. o1B6@ h*%LME@@9 >f/Et0 t?bj+xA]".RA˟GY$)/x&X0ӍoM&%~TwңRGW4T\x:TI1UTɐVΐ 5~C@@cCy  hC$@u,:pL!> XJGm0)hnpa4U&r-( Jڂd >VA0 jJ@ ȣ|o*`  Wr/$,|ІW$#ppJ8s#b_"^< IC#d!`f2ༀ)AQ5c0%(05,B ^A>;T`"LV h O [HS;\r:D1tˀ"b}[E€ +a9+5[Q0[hx v50T[XPhh_ vȿ8RfU-63;`]$h:@0t_іb"Hh,`[(ml (CC{@ڴ)0mJ|)جD;IԑujV؁@=(NaWāHB)ؠ (mJ`4N,N6ˬ4 RxW w A6ucRݒVт$ "A5>t|0&zR^XaйrL" `h@ﬓwDwxwvr:n X@c͑^|DVлhB _f6$`\kȡC1pn}Bvi !9âw22u(%_сwX@ 6o']hA>a[f`<Ë UBok ܔ|; Oޜ -@ A (=@C5P@q0>$]K2ȁ%YH!lP%\ ƽwHlt[\1HA]L؀i_+P8J ,tA}4  >8 C2|t <{A _ I_pPPչaBE˭%A@*@u ),GDI=d,]^K]~CS 0WE<c`7T@lpЎlp_AA |הyKaƹ1Kv7@c  .%N:<4Cn`,4T'U A5XȀZ@0q>l|,4E:Z8 =^A8`6=PƊ:́ف@pT9!nC$٠AC[AS ؃ZZa6U8 c],t vdn M2Xx /p OKPCa~7t= w@c70 X|qP6%dUbă'5@@KTm^)\VG%AʨJ_E_ ]88܂tC>8H080A %p&Mö,`Tif"&BTUXA&(S4~2a^e^A%Ԏ ':`O.}7@<+ h7$lT'c1AT g/{{& xBŎ$PtC&#TL]o4h8G`K}Z D*g@$e7I4FTN@ YQ(bK 4@6h@ \^dxX^ʅ)XkF%`½k8+"C 0pxǏpȪ7wfGjҝ>fg= uV]c'ڦ7+)+1lW^j05"G+>Vu,PA$;d{WWSG4fvi<[C+O:RKc)w>kRUO18ޛ+|}+Ե0[l!c$8E8)hv\Rαr*@ĤV nea^@S-/]H #k;bmu*s]8'&Ga/%̜D#r3,$q@=j[a1v^cz4o6m=0 1[2@ēָS敖Ib9OWf cg.\䞃me$fFEPqƼ[uvKur>B(F8 񒾕I$Cjڴ=:ižu]9*H_Oޯk~ Ӽ3nyMNս`xbm\!H=&kJyjANŦlMw%vQF@*ؑ]JD+%p'v92B-#Cr6Goy>δPPVDʣm,M[A?7z~I'T=IVv>may緰*:g /-4I\LcEl"˸AT}Azaة MW/GVqEHz=nieqCn&]IiݢV-X "mǿ򨥜c#czXoVX=gɭ}F+׮T7ͱ: k-= $XzW7kjDVr m!hA[;XXy?|bE]kǺvbݑIŞ ]h`El7~/̚IJ \=o Q\lV ~u{R53eN?IB!/# ۇП5?.C"1<Գd ݫnצV .8V"mi/ +6@'9~aI`9u tʠ4d 1''\\m-5DGq ~ldN5G*|7$`eA\KTTpE#|zz}I⽧JOӼ뭑G28 +R˗¹4x$hI#J•G[aWGuˮoOh*t d5ΚXw=y]ܗxvOc I>n}FkvZ݊\Hj'?le?1[:Z#U-Uvڻ(K [锕r?: Lz]0RFAk+b좽O"յgeH#Bz1sVcjrk{'/o)U}#5ks0ɘuFtHN[[K|bSnXXZkl<9?*|p9C%5Ѳ:9~U\hvn,w1@clMf6%`2XHMKJ.\M_6'۵X;7ť2-W^>jWhEoQ(?կ@=k%COȽ%~OzݷUۡW^KYCwrYWXUXb g9#2YirxZNܭ#Zj3QG8HdVMXC{VLyOY#4ۨDѕ=R,4 ۺ&B=..DH8\BUmhQӵ[1VKbm䶈Hzw=gR^ZZ R;"O.n]guvq$ܰ_B\ʻ勑Zwju @9~+*rYch ru9cGn{Q'߳&KTta ZyjO'oݎZ;׉Cy,ғ,X!= p1Mw zpդӺ=UTy+d Z&>aZ6D7 NBj?g(R["PQҵ8žW[ kL'UZ9;5J[ %=aLHgb穫j$-ν ++#.T=·CE?*|遜dU&G|5ZgF)`dgDKS|Cŧ]W27睠䙍7bMm_{tpZsOiCbf&Iu4[o-ZApLxN):Vtҍ詫竦ǏǓѠج޳޶ḫ伳⺴ٴ߻߽߽ݻ۸ڷۺݼط߾÷¶¶÷ö³ƷɹŴʹ̼öȽǿ馤ԋjlQW5B0?@LJPFF_[Җ촮̂HWM(W:W]QWQW^dkqntkqhnntiodjbh`f^dbhioipjq`gnthmt|pyxۀfuVhcywt\|GhY~Mt2[2\~0[p&Pn&QItz{ՑuŁadQzTJ}~Crq6cU~}Djl1Th.Oi/Pn3Vp5ZZF`$OOBTIYEP ,p)Bω͏̗Ӣ㷝缢濥佧㼬徲⽴ܷߺ߽߽ݺ۸ڷۺݼ߾࿱ݾۼ޿ĸǺķĶȷϾʹּ̾˿ߡ·opW[EJ9B=H8E=EGL^^ȅ䧥鲱ֳ}^$6I 'R6KQNTX^hnrxpviodjjpdj_eagciciflkqjqho^ehnks{s~nz\lZlf|yv\}KnKpLv:e?lM{P6eAoZ_qhyTXv5^o0\i0dIHv@udL|LCb,W{EnK=W IYIF 6SERDPDH 2m*Ej|⡮ӕÉϙץ軣§濥຤޸๫ฯݵ޹߻߻޺۸ڷܹ޻ῴῴ޼ܺݾĹøܿŷ³ǹ̿żޮИ}|`bNSBI7@4?8C=F@K;F:GDNACYYhh͂짩槯櫶UeI%Z8U8M0[c_ghppxpxiqgoiq]e[c^fgoltjrgodm^ecklvmvp{juanWg`sg~fXxRuYchTJyS@q6hgQo)^j'\m+`}=qYSOz:mCsHyZwAtv@us=ta)aQQ{C{j0g_&ZQGF 8Q=L4L1Jfڟܠvw՞բ䵨뿭濩㼦ἣ຤ụṨว߷߷޷߸๭߸۶۶ݸߺڷᾳ㿶ྴ¸Ⱦ౮bdOSJ5C5C@MKWR^^ikqІ~ژ½s{n,>L "S.d!CR3`Ar*Qdlfnksowjr`h[cZb^f_gckiqhpckaibkmweopzgqepIWWfcu`vifVzFn>i9h2c=n9jpQgMjSh!V\Nk)`PPdCz~Bw]!V}AtP]Irp8f~Buw;rTPy:wn-h=3VFO8g)I_uᤲϓpqe]ڥ۪ᵥ乩ˣز߹ٶ۵ݷݵٯ٭ܰ޶߶߶߶ݶݶ߷Ṱ໱໱ߺߺὴ㿶ݹׯ˚Šx|`fHQEQHWAQ7Hix,[aEn%TL{Hwq+YU=s/[W?aJf!OT??qfR_q.c]PTG[OMGw`0[}OzxFtU OA8G:Q}7eO/9ZwՒphƊ{겢취浧ᰢګ֩֩ح۰ݲݲܱݱ޲ްۭ٪߲പߴܱܱᶩ仮㾲Ĺڶ֫㱷ΕyIBPbuodAcQGncDgHgJcFaBQVV[]ebmdq_oYkThVlVl\qeyk}j|i{k}H^1LB`:[+N4]v'U8h;l|7ii&Xs2cj)XR@m-YIv]GYAO 7f M=k>mv,^YCdRdSdVCz?xs5mPr8s= F{Ke\%XD 8fҕ}WctwҘ篧괩䱤ⱡⴥܯ٭֪թ׫ج֪թҦҦҦФϣѥ׫ܰر۴ߴ㴧칭골ϓqmy:gE\pe"Tm,_TFH 9F5y:hkn,YO 6\A^Cn%SAq{0bY BdP]Ln&]n(`_TN Fp2jLG Ig/rov?zyBscZsKYux⮩㰤浧繪纬㸩ڱլدԫӧԨتتӥϟȘ͟Ԧש֪׫ٰݴܵ۴׬դ⫟矜҃4;r(RgGj JiGb@];`ibmdrgwgzeyax]wQm_}f^|]|aXyHk=h;h.]8ip#T5g?rJ~]OTFF9[N\MAog_JX@_DhMp'V~3ev+]^GaJv,bU D^N[OZPAw}?wHIv>aYiH^kqđݬ渧繨޲ٱ޵ڳϧԫѨѥӧשبӣО˙ѡ٩ۭ٭׫ٰ֭Ѫٰܱݬ鲦mv];`khsiwbrXkVjXoZs_z^{QqMo\\Ag)Sv"O2c8i3d;mI|Dvr/cc!V\P[ND7c"SM~V]JW@j$R7f]CeLaHjQm!V;o{4iDyF{m+`Qz=pf*aHTU{ck{ēѡްۯۯݳ޶ܵխΦΥլجѥТ֦ץѝҞץ۫ܮجթԫ֭ܳ൨䷩뺭q{Pa9R2Q=c]]s7bAkgvsitz|類㛕ԌOLi%^$X,V4Y@[CZ>aBgHiJiHhGhEiFjGfCa>]9]9cncn[iR`O`Uh]q^w^y\zbdTz:a'Pv L|)Z{+_z-`}2d=pDv=qr1d^QXL\ORDl+\z9j?pg%TdOh"Pv0^dJiQaHfMaH^Fx.`l%XXEaPCtd%Ui,_LHLkmΝңթթիخׯԭΦɡ̣Фϣ͟ϟԢԠқڣաҠѡէڮ޲ബᴪ⵫帬뺬量\l?W2S.Sne PYDP :W=T :eJbG[@dJV ;L3\Cr.Zi'SIxt8mi0dKw[~sȗșФӧ֪֬Ө̣ɠǞѥ͡͠ң֢֠ן١ۣԜϙҞ۬䷭幯帮絯絭淬뺬lxJa;Y$HnCw2ZHq@hn)Oaluǀ|ovV]r)4Y![,]6Z;YAYAeHiHkJlIkFjDjDkEjDg?b:^6^8R_Xe^kbqgvj{gz`viA]DdY{Hm9a5`u&Vn!TdM]GdNr+^{6hu2dj)\t3fp/bb!TZKw4hbQp*_ZOl*YTA_JdL^DgL]AhLX:]=[jtuƯ̑եӦجۯ٭Ѥ˞țɛУ͠ңڨ٣љәݡ֚Ԛןણ鷯軱㴫쵱뵮趬身뺪v}UiC^)Ji:eDu1YJpt-PFgoo~sVfw-?]*Y-V 1V7Z@[AhIjGkHlGlFlDm En!Di?e;a9^6^8GTTaboivjwhwatZnUl=a<]p(Gofv҅sG^r%>].Z0W2Z8aDdFgFiDjDkCn!Do"Ep#Dq$Ef:c7`6_7_9P^Ygaocpbpaq_p[oMc1Jp:a4]9t*T~8cm'TY?eLbJW ?`Jy4d};jo-\u2d:lm'\WEw/fgTaMr*a`^b#S^N]HX?]@X8U 2S/L&s&IdVsHdGbx~բץП۪߯౨ݮץ̚ƓƓǕΜԢܩݥԘˍӑޚ䠜ꨣﱫ귭꼭`kbGcI\B^Fl'Uu3`u3bp+[w2dp)^_M~3kjV]K^M~>qtJzIyBqq+XYZyԆJeRj~֛Ïrޫ߭٨㲴⯭߬ڨҟɖǑȒʔ֥کܦ՜Ҕ֖ޚ䞘즠﫥쳩뵪ưƬjrCT8P&C`1[1_28Uw+HLky~܎rx)Mf;b8f>_9\6]8Y4f@h@i?m Ap$Bq%Bo#@l =b3`2_3`6b:_lZgR`M[Q`UgPeG`E_.Kb3b:|2Z:ef$PS;Y>]A`E`E\C_Gk'Sx3ap+Yq,\o([g U7om"ZcQbSo2euo4eZMWFT>Q 4T 2H"m A`~{g|K\؏䟭Ɏ‹bqÎգϟ͝ܭ߰ܬ֤ϛ˓ʑΒѓࣙࣗښΌόݗ䞗㛕즟öȳȯìvzR_?U} <` +c4Z .u(I4Uy,M}̀؋qo"C_3^4a9^6`:e@d?gAiAj@n!Bq%Cp$Bl =h9a2_1_3a7c;[hP^Rb@Q.CdIg#Ow2`e PdQj$Y;qn(^m'_`Tg)_j{DtH?:.VEM4B ]1SlтgtS[ՎώʊܝowÓΥٳӫϦΟҜӗՓڔ䘓啋݌؇{ۋ╌靖ﺭ콰µŶųIJðቈdmBX)Gx9d3_ 9_>5]t)NY{ш؏˂s*Db3j!=e<_:hEfDiGb?f@jDo%Gq'Io%Ej @e;^4_5b8f^CcHaHcLn)Yi$V^Mn7Y6Z?m#Ov,TCdщъ|{5If6j#sfSIRA9Z5Ha}veox{颟䤜ϗܤΕ٠y~ϠΤׯݳ⶯Ԥ̖ѕژܖ׌Յցvڃxኀ蓈阎뛑駱ﬢﶫ︬뿭´ĶƷǷǶƴñ霓wyRa2N@q 8Y6[@`B}3[v.OӋԍ|BVk$;i";c8aXoYqNhHe5Uh@dBgLhMV <]EY AEweK]D^DbGk#NgJ^A_DcJaH_Gf!Qg"TR A`ON?tD|~s 7^ 9X =]?z0Xp(IɁܕ~K_m&=e7`5adAfCfCTsGg,L})JjB^=z4_?mYAY B`HP8;m7fw3_]C]Bk"PfK_DbI`H^Hg Sp+]h"WMN @?nMrg$?kw]bfe同䔌ч}ݝ䯠حײ۷ͨqrΝ就꯰妦ҏҋӋ֋֊Ԇֈݍᑉ啋痍╊○蟒煮Ŷȷ˷̶̲̰ǮߔloHW*D?g@R7aCa?}5VSpߘӌPdl%<`2^3b=k!IfFiIi Di!Bj"Ck#Dj!EgBb?_=_=bBdDbD^@4_u!LeBs+VT>R?Aq`PYHeQaJ]DY?g!Nf"Lf"L~8ex/]_E[Ag QZFYE}6k]Mq+adT`P\N\NM[MJ:TCcJSvZqzgmebۅ}܍ɀq؜߭Ԭطյ̩wy֢鮱票ݕуЁӂ׆؇ׇڊߏ㓋嘏嘏㖍嚎죖짙ﭞõǷʸ̵̱̯ʭ曏stP]2I$FjCX =]?^<9ZEb֏ޗSgn'>c5b7d?k!IfFk!Kk"Fm%Do'Hm%FhCc>`=_=aAcCdFaE[?z'Xo Pn%Tx6eF5G ;Pr2ed!Uh!V\FgOM3X?f%NNwCpw.\T :S ;fRZFZH=tXHh"XeUi#Y\N\M[k&XE1W=L*FcrfnTTهփt׈xؒȎ|П߸Բ˫Ӱԫ١២ߖ܍܉ۃۄ߈ߊތ斐蚔癓嘏眐砓煮µǷɷ˴˰ʭȮ蝏wvT_7K'Gd;W ^;a?fDcCgIgKS7bGjYi#[KRHPIGATDwSEO <_I`Hu1]v4`Cku5^f K]@X=\B\F\JcRo'^M?bRAwaP]L=lf$QbGafDeEhHiKY=m"Qv-iy5o>wI BSOSOby=pOATA\F]Eo+We%Pa&Ma#KV:^?^CZ@[EeSi!XeTS Co)_Bw^Kl*Wx6b^FW6h7Kd}Zdce覟棗ύ{ᛈ硎ߚˊ{ȍ֣⵫ⴭ簬ݜ̅Z^69=BIP^f^gajjpv|ト덒옑睍蟏ꤓﲨﲦ︭﹮홒w|KX#9v/ebE]B^Hi"Us,au-dYIx2gGyXCu3__GV@NQ]bKSNVGPAJ?JHSXcmwy폘듎홎웎㗈睋룐ﯤ쯣øᏈvuX`5E1u0f?S8V 8];i!Bm%BRk衸ʄOfh!:i!>s*Nj Ho%Oj Jr)Mq)Jo'Hi!Bb=_:a>dAfC`>`>[9z0Z?|JTLKF["VL}el/aL ;XCYAeMn,Xd&P[!Js8_bDa?^?^A[C_Ip)^6};iBV ;X:];f?l$AD]柶̆Zqi";h =q(Lo%Mo%Oo%Or)Mo'Hj!Ed?`;_:`;b=n%IdAc@a>=c@}h$`PHZRGyn5gSIyG4S>[Cs.\n,Xe'QY"Jp7]x5YfDX7Yd?h AGh6r]QaXw9oK~VNl1b\UBU>^Fy5a^ITBM>a(NGko(KV5T 5U_:_8b;c_8g@q)HSrp,fj(_r2hVo4eQEM@Zd"OZC^Fy5aR>Md^>q'Qu*Qm"Gb=^9aL?]Nz8gPcNI6[IUCUAWBO5[<[5\1Y (\svR_ܐߝޢ䮛켩鿬ṨͤӦ屭꯰ȂER0@=Q1HG^(Bs,*F} :Ry7}#@n5t;w>l4l9k;X +f:X *`0f1o1 >Abs^l\d^cbfilrvu|x낂掉禙Ⱎ湥긦쭟\g>Q|+Es!@v%Eb1e2e0k3t:x=w>{C$Ls!Hc?^;T 1`=y.Ur(H҉ܔ]qL`p(?g;z/Tl Kv(Sq"Hi>b:`>_B]D_HcK]@V2j!>Pgsj3dHyL|bb%UN=VBv6bV@s1]^IYO=`PO@N >P=z5eO~Sv5fN >O=WC\DN /O '^/pnft陟睗ܚ՝۫Ấ⿨຦޳춭触|BOs-t2v 6i-d*j2h1d.g4e4d6l$AId{0UkJs%PmDf;a9_=`A]D^FbHY:W3s*F]rz|EvHyRZ[ OQ@UAp0\P:x6b[FT`M`NWGR@M 8X@x6cTBtg&W^LVAM 5L -CNe{JWܔՖӡܵêܸ౤ՆCO"4);t/\ j1i1x"@n8` ,c2`4l)DNgː̑]qx2Fa'a7*]i]f_fchgkjpktowz~鎌បʽ좜\``w%8b)m;.P5VWvfB^k4] %i1u?wCn?c:^:b?[8c@u*Qj @ޖdxCW{3Jl#@|1VkJm!Lh@c;^:`>aB^C^CaFX9_98Ri~πW{DwVL|SGVES?f&RM 7f"NV?Bp=l\IWGO=T<[Ah$P]FXEx5gy6hR =Q 9S4g!?{gtbj䜙襝ᦙجضؿ⾬ڍEN%6(?~-k%k/g07Rp8y#Ay'FY *_6|?Wt>Qӡ՞s;Lu.2F2DMXPXY^`deihnirktuy쏎បƶʼrnn 'm-f,W!d3x)MfWxߑd.Hb*f.ra9_;a?bC`A]@^A];n&EJdrcv@s\|DtNBXIP=`KTW@x3aZaNVEQ<[?U7`FO 7G2dQe RQ ;^EbAVruU_䟠ؚ͊٦ܴ޽Ʊı㶨够RW>K+? 9.m "g(x)?Fb3S+J/Lx/Io.Ek3Gh6Fޱ詵o{5D9JQ`BNGPRX[_afekgpktuzꤛɼȼܙJH{,8u%9}.Eq!?m@w(LAeQrߑtG_r!;c-g2l8j;e<_;c@]:fCw,Si?}᙮m;OCZw.K:_r&Qn"Me=b:`qh}EuNB[LO<]H`HV>ZBf!OYl'WUB\F[=J+_CbHV?Q ;I5YAYc-d.i6h9d;]9a>^;iFz/Vh>w坲r9MI`y0M;`q%PkJd@a;b>fCfEa@]<\:d=D`lvs}gr?ssJ{NF] PO>]Hh$PZBU=P 8Drl'UT?d"NX9U4f#HY>R 9]CS ;aF_?Wx\rOZӔˍĈwީ۳ᾱ徲ⷪ赫姡xvBDajVdXh^qOe0E}2|3IdMkFb3Mt#:t,@euݨ緾ڇfqDRQ^IUKUQXTZX^^ffrnz}Ƽ봩e_TWivZp1KA_8Z8\Sv闷䓭uF]q6d,j4k8c4b9[7`=_b?gDgFa?\:\5d9LfstovNr?seSY!Qb%U[JI4cK[CY>^EbIaIaJe!M[>O .]?g"JT 7S7_@X 7:ayK]‚ޡɐؠܾ֩ع߳類`bFKfmXb_kivn}gyUj=S.EC]Qla{_wYpr❫䜡{juboT`^iRZPWX^^d\d`ljv{ߩfa=Aboi}f~NkGgk撲摩j@So0l0q8f0p?f;\8fCdAv+Ss(Ok!Acّؐ;O>UB_}2Wo#NgFZ8b?^<\:eBgD_:\3p'CYnunylqhQUƓǙbx?qPCn/]\GZBTUJb`wjj{ޙ驰띢vgsT`ZeRZSZZ`^d[c_kiv|䮧}{fiVbdwqop݅葭ۂh}L^1Au/|#:&Ao6s@f;]9gDfCv+Ss(Oi?_{ڒ׏CW];^pDso0^T?W?T:U:Y>]B\C\C]EX@cGdGP/T 0U-[ .KirEUӏΕԟ鹤ඡǾݜW\=GN\]i[ffmknqstys}n|ex`vSgOaOaPcPa_no}nzkupw~݋鋔myU`S[X_^d^dYa]iiuy糮ӒφyxwmflazDY=N-<'6#41G1Lu8t[:cBk"Hb=e;x/KPhnxovosgdnu?tUbVEK 6\D[A\A]B]B[@ZAZA`H_GR 7X6Y 1P#~.JrP_blសѓڣܫܰ꾮뾴ڠ]_9@MZUcR_grntqsttuwtyq|k}h{{htYgO]LYYehtis_geltzހ瀊xcnS]U]]dag^dYb\igss}긲Ֆԋ}pxdrYiRgZoSg;N.<*60<0>9M3Mw5t;d7[7hEiFy.Vr'Nd:Xtّؐ_s7NFcn#HjI_AdE]<\;i"Gm$H]6d89T]spr}mqstxJ_rbzr7hO>_J[C]C_B`A^A^A]@ZA]HaLI0Y7R(^*ausV]ʁؖ͑貧Ϡگƹ᠝RV7>LVP\Ucdqbkswtuvuxxvztznzlxw~msjpjreoktr|qzv~y׃܅|zucoV_Yacgeh^dYb[hdpt~ꑔ؛Ռy{oslugraocr]mKY9C:BCM>J=N0Gz3|?b4Y5hEiFz/Wr'Nd:Vr׏ۓk8O@]m"GfE`BbCY<]^A`C^FVEf UP 8R/S&3K|X^ihߕܙ؝ܦ߲ޫX[vWo8kL}g(X]HT<[@^?Z;Y:^?bE_G[M_Q[CO.s"BaunxQS}x롗䡕媝פǻ˿jf*2ETERDP^h]eX]qttvvwzz退넄醇腆䃃푋}煃{|뇐팖ꐘ䎔员䐗ވކltbjeljngjaf\e\h_ju~䎒窨Ľƿ嬬뤣䎈~yywswfmdnhpelW\SVVZLVGW9P; Cg7\8iFiFw,Tn#J]3OkӋ㛯s?Vu,Ir'L^=hJ\=Z=^=fDc>X.q%@Wmqr~mtsś}`h9nwEyu@py~BoH4ZDY?`EbE[>V9[>_B^Gd"YN B\DX 2Ic}QV^Z䝒禙؝뻵zu235@6EP\ZePX\amrgiwyyz||킁툇늈銉䊅钊ވ勄푍ꋊꊍ푕꒗⌐㏕撘搔玓߁ipipkqkqflag]e[g]how⌐뭩ž૪夣䒋}儂鄅u|irbkY`\aTVUXMTM\?U7~:l;b:mGkFw)Rk GZ0LhҊ枲tBWn%Au+M[8k!M[>]>_=c?a7\,z-Fatp|qynpvsІ`~Ogyco2UV8l'Mh I[>_DdKX>O5X<_!IWMPC\>o>tahIGڏٚ尡ޯ帮Εj'/3<9ADMQZT]W\\adijnrutw{|邂뉇댉茈指땑엓ꕑ摍㑎畒蕔咑㐏咑锓뒓狍၄vzptpsmqfmbi\g[fYdZdlqق棡¾䷳ߨ囓瑉{}qxjsdnaj\a[_TWQWQ[p!Ip!I{,TkBY +=XІ园ЉG\v-I_7Z8j L\A\>iCk=e .w7J\luvwrmulǂvӌ`l5eVGN6u7Uvn>[~3Xa?U 8\C]EYAX?T>Q@W?j BreqRT{r馚ᬝ뾲廴湷]bKk,9KBKLRU[V\W\\adijnrutvyz煃ꋈ돋쒍욕蘒昒蚔盔嗑Ꚕ뙔헓풐싋胄{}w{vxtvlsdo]iYfYe[dgm}~枛亷٦ܙ␉߇}s}kucn^f\b^aZ]Y_WaBO&:z9g5jAo Hs$L~/Wi@W )5Pυᗩ̅]rn%A_7Y7dFY>_AjCg9e ,)BXgqztutnypʅyӌLF :='Z^>`EYARO#8v7e3lCmFv'O3[i@W )z.I΄ݓ~pg8\2Y6`@\?dFjC` 0d +4Kcqu{rqwqv͈zӍ}u4gWCZ>e!?Vl#@_<_BW=P:S>T=O -n%AyiuX\{ߨ೩伶̡N&M l4,H8QJVQWW]W]W]]cdifknrqtvx{{~煃썊훔윔윔蘐뙒얐쒍ꋈ愂}}yywwuvtxothp^iYeZe]fel{}嘗ý٩ڔ wnxep`g[`_c[`Y`TaSkwuzpo{u̇{ь~Ԏ~}6g[BM)U)@Qn{kwguOdn"=O(Q 0T:U?R>K 1Y.H]xdkVT஦罸֯yMUF]-m5/R0MIVRXW]X^Y_^dbhdikopsuwyz{{恀鈆쒋뛑疌뗎铋鏈爃}{xvusrqsqvnsfn]hXdYd]fely{䓑ڪڔገᆆဂxpygqbi^ccf^dYaRb9Nz8p7b2mBb9v'O7]e:X *n#;ˁُuʂu,FY/X5[;j"MhHe<_ -r5K`q}rupmȁxӎՐӍ}t(WbAY/i6KY\fZcςo9OX.O-Q 6RN 0r%c5v>#J5UHWPVW]X^Y`^eagbghmnrtwwyzz||鄃닆ꏆ뚎唈蔉葇荄zyutqqnnnnrkqem\dW`Xa]fciux⍌﨧تەገᆆဂw~qzisek`dch]cV`M^3Js8k6c4o D_6t%K6\`5V 'g4}ُwχB\\2Y6Y9l$MeCc:h5,E[mvqqrk̅xٔؓӌc?g@a/f-HUU\@DYb曩ey}4Qb>O 2H0N9T2?Px~`aWT멢嬤빳ΧO&3G*V4o@r8G6WFVOUV\Y_Za^eag_egllqtwvyxy{{瀀ꈄꌄ똋擆蓇ꑆꌃ~yxsroomikkojpbkZbW_Ya]dbhrvþǾتە⌈w~rykrfl_caf[bS]I[-Hl6c5e6r#G^5t%K5[]2S$b/zڐzӌSj`4Y4W 5l$Mb?c8p;:PetyomsiΈxܗڕӌmCh:v$Au%9R^mtkp}09Vd΃}[5Y:X<<"g!?q~\_[Xrl춯淴c;EH-I-`>x%Jo3(O/N?MHNQXX_[b]d`gdjfkjoptuxxz|}ꁁ鄁舁ꏅ않蓇璆蓇琅ꏅꊂ|yyunka`ilci`e`fZbUZUZ[bdkkqݰՏ߉߂z}szovipejcf^b^d[gDY}#@e6c8i>o Dg>~/U7[_2U &f3hz؏szlf:S ._=eDgD]0n7Rfr~qtqk|p̆uԐ~גՎ7]j7z'B4GYf҃ڋ@Kn"5j΅h!BN ,L -P /AZ_glj[VӏU)9B'I ,e@~'Kq3&J-IAOJPRYX_Za[b^e`gekinostwwzz|郀釁ꌃ쓈钇葆葆菄쎅늂|}xvsmkcbgkbiaf`f[`UZUZZ_dijoや丮Տވށz}sznuhoejce^d^eXf>Wv?b9`;h=q#Dj?0V7[`3T%c._o؏|lf:Q,`>eDc>_0w&>Yks}qrskq͇vӏ}ՑԎ~|(Ib.5NPcgt虦Uf_)@]ce?I#F `8Xknthehb쪣˹I*H.@&N /m E/Tw5%E-EDOKQSZX_X`Ya[c^edjinmrrvuxx{|~ꆀ舀鋂ꏅꑆꑆ鐅猂쌄퉂zyutqljddbeaf`eaf[_UZTYV[`fgm}혗ùՏ݇y|tynuhndi`e`e^fQa5Om<_;_>e;s%FmB1U6Z`3S"`+Rb֍͆˄lj!>R -`=cA^9b25Ldst|qpuk΄tЊwӏ{ӏ}ы{p:.IVmZn[mۍh~g8g=}5V[4K!Et2EshiJFҌ沵rAMG)G-F+U 4v$K9\}7(@3EBMJPRYW^X`Ya[c^fbigmlqpuswvyy|~}~zy|芁ꏅꏅ荃牀닃뇀~xvrqnihbc\`]c_e`e[_VZRWSX[bcjx}鐑ב݅}y}u{nuhndi`dbi]gHZ+Fh:]>aCc9u'Hq"F1U5Y`3S"\'IY҉ҋɂnu,HV/^;_=X1h8FZlzu{roxkӉwҍwҎzЌzωy3Kc{d{:N|-AWlbzLiZ2X5l#IS ,O $Z(OZŀ`^f`᪩_e;W 9M2Q 4\7y$L@`8):6AAJGMPWW^X`Zb]e`hahekkpnsqutwwz{{{~x}wy鋃荄拂戀釁~{wsqmlde\]V[Zb_c_c]`YZTVQVZbaiu{狍쥢ۓ܄{}z~w}ovhnfjadbiYe>Qy">d9^CcGa9x*Kt%I0T3Ta2T#[&BR˂ы~q>Z]6\9X4U .r%@Uip|swtoyk֌xҍwЌvΊv͇wG^|m?Ry-B@Xz1Nl!FT 2Z:_=L%k&>FTbgXY`[Ԍ禡ۡďZ%0;@#Q7X:_ 6z!HCb"7(35;@FFLOVV]X`Zb]e`h_gcjiomrnsquuxx{|z}w}wy|牁牁~zwtqpkk_`QVRZZb`eae`a^_Y[SV]bbhtx犌ۓڂy{y}w}nuflei`cagQ]3En6`9`GbH`8z,Kv(I}.R~0Qa2V %[%7DzҌ|xOkd=Y6R .W.4Ocwr~rtxq{m֌xҍuϋu͉u͇w>Rfymg{DZ?[o%Ga?[?W ;S 3_8]twtuQMZT}w{ȏpu[&3V5J .U:\ ;^4{EJf(9(/48BHFMPWV]W_Ya\d^f^fcjhnkpmrpttwvyxv{x~{|}~䅀懂憁~zxttprjmY]HMRZ\dejfjfgef`bX[\a_epu憉룠ƿڒ|uww{v|krcicg^a]cJU&;f0^8_IaI^6{-Lw)Jz,M{-Nb3Y&]'o&3q|֐ǀ~\xh AX3O+]4D_nr~su~t~n֍vьt΋r͉sΈxf0u*BI`^vh">Z3S0T1W 8O1V6C\ϐ͎ΌΊvt|}יᦫMXS)D"V9X;^=^ 5{"GQl.?)048CJGOPXU]W]X^Z`\b^dbgfkknlqossvuxuu{y}~||~憁煁|xvrrqsilVZBGS[^fhmjnimhmci[aV]Y`ioや랛Ĺڐ|zsrvwtxin`fai\dYfDVy:^ 0Z;]I_E^6|.My(H{*J{*Ld5[ ,^-`,lyٕʆ˄czk!CX 2O%b5Neus|vuԃyЁqՌuҊsΉq͉sωxZ 2W3LoKny:`Z?O-\5f>Q *3Ŗҟ٘⟗ۛ詵֗Zid"4R'Q,P /[>V7Z 4|)LE`4G%05=>GEMOVV]Y]Y]Z]\__abdgijklnnpqttwvwvwxxzy}z|~~}{vvqrikY]KOUZejgmV^NWWa_j]hJTWacltx떔~x{v}ywsljmniqZg^rQk(Ja5_>]BYAgJi?p >2Ot!>*Nh;_ 9_:]4fxϐϐx~izw(L] 4\ *a)Vgzx|}{{q֊{ՊvӉuщtЈsφvhH]w[I;'S :oMc;N#Hg0>ѢÕᮡ講訟謵ljUgi$8Q !N"U-Z8^?V7X5|+MGb7L'58D=FCLLSRYTYUYXY[\^_cbghklnpoqsvtxtvuwvwxx|z|}~~~}{vvrskm]`PSaf^cGM#+!-3A9GO\V`\djn⊉枘؃yuxrupliklgpZk\wAdqFZ 9Z?[CZBdEkAt"A/Ju;(Jk>dBdDV 1YnˍΒtukz.R\2g0t$6cp|vx|x~s֊{Չxԉu҈tІtφvo+Umme$KU9U6b@I#K!V'LYВ՛봩ާ氧꯼f|_5JR $V+W1Z8`AZ9Z6~-OKfK>JBMHPNU^a؀룞ޔxuqnrnjihkdoZnVs.Qd:Z;Z?[D_G`Am Cz(G-Fv <}%Gk>hEgGQ,G\ɋҖrqr9]] 1r8=Kr~suzv̀uՉzԈwԈwчuІt΅uZXl$MS 2p+P_>i+Gd'?i);AQR`ktьΒƗ己zz;UL #P %i"=m%B`9U3`AY8[71SPkAV0=?JFOIROVRYTYVZ[\_`]]``egjklooqrvuyqsrtuvxx{z~{|}}~}|yxwuulmbdOTW^\cYaYa]eV`KT?FKPZ^lnމ蠛ݒ⊉vvqnqpjjdlcp^sFdu?^7cE\CYCb!JdEn!D0O-F|'@}%Fl=jEeES 0z8Mlj؜qpxBdb1u#8PZ}πurztфyԈzԈyӇvчuІv΅vS|IqY6H$x1Rz;T[k[hbmmwXfU`]frsخǢb+AV3J$W/o%Ew-Mk"F[9]>X8\84VVpFX1>>HHQKSPWRYTXVY[\_`[[__cehijmmoptrvoqprsuxxzz}{|||~}z{yyxssklZ`]d[bW^Z`bgbh]b\_pqㆇ햕䜗ڍuvssstglbjap\q/Ng6^;f K[EWAb!Jh#Ip!E8X-F.H~&En=jE`@V 3l)A؛opzBah4y%4[a}~~xt}tӈ|҇yӉy҈xчw΅v΄z`Fu0X~3Z|2TPjO_ovЖpwJVO]NZҎ~Z_I+U6W5Z3d:o"Em"IcA^>X8\85WXrHZ2?=GFOJROVQXRVTWXY\][[^^bdfhhkkmlqnslonqrtvwzz}{~{{|~{|y{yywrrrwlsek^ccfpqy{}}ts⌈謁ᛕ؋uytwptfmdp]mLds:b7^?cKYDT=^Dk&Ko D?_,E3L~'Cp=mF`>X6_6u}Ӗpqw;Xq91]BXC[FX?^Bq*Mo DCd}(@4J~$?t>uKeC[9W/kuϐuvv7O-EFLvswryq΁vqՊ|҉yшyΈx͆y̅z̓}e>~3Xwm˞֨١LKCI:Dj{ٕk:GJ0T>\BdEk Hq"Jr#Ir#Kr$MkJ_<^81SUoI]7EEOJRMUTZW]W[WZYZ[\``bbeghjhlilkpmrimloqsuwzz{{}{}z|胀胀~{{x}z}zxwqtptqstt|蒌ڙ㣘驠ښՊ}u~oxfphsl|Phx ?b9h I[ER?\F^EbCv/PnCDez#<2G{"9uW1etΎy}x7K;NXZՁzvmxn҃vqԋ{ӊ{ωy·z͆{̅|͂~1Tyʍѧ㬨}xGG@ECMlzy7LK'U:\D\CbBfAh?s!Hx&OkEb=gBY 1q @VpG[AO@KJSNVSXSYTXY[Z[XY]^``cegihlhlhmgldhilnpoqqruuzy|zwu{x}z}z{xzwyvxvqsxzzzxvۅ쟖ߧء곧譢࠘΃zbmzq|_mbu:Td1_k@eAX 9P ,K]łŀx~4GO^bawlzowkq҈xφw͇w·żyˆz˃}˃~B`́Ԯ繳ӕTUEIQXAK颯Na\4[7Y7cH_FcCd>e:qEz'Nr Ic_KSFUFYB^?o(Io"C-T<^~(>0@}#4}$=pChD[>Q 0H]łǂsy9GWcdavkznwjπr҈xφw͇w͈ż{˅|ʄ}˃~Mcty边ުkl9?EMGPˆxP)P+b9jBh KaFeBd;c3o>}(N{(Md;g>^3i8OkF\HZ:GFOKRRWTYVZ[]\]Z[^__`ceehglhmiohnjmhkgjjlmooqpqrrttuuvvvuuttsutvutu{{~|{⎇ƻ諟ߢ뮤꧟ݗՄowyfsfuj};Sg4\9YC^!QTHVGYB^>s*Gv%E/W7Y|&:,;|#2z!8sBeA^BQ 2AYłˆloANaig`vjzlxiЁs҈xφwΈẋyʇ{Ɇ|ʄ}˃~\ekrޭ૪vvKPCMDPanךY!3O,W3qF(WfF^?d>f;d2q<*L-Pj=e:`5e4LhCZL]6BBJIOPUTYX[\^]^[\]^_`bddhglhmhoiohkdgcfgjlnlnlnnplmmnppppppppssuutvz{}}~獈唒}hpudso]qx!;_2W:VG]%UTLVHZBa=x*H{'G1W1S&;-:~%2w3uBb =]?P2}7RϊcgJRfljdxjylxj҃u҈x΅vΉ{ʇ{Ɇzȅ{ȅ{Ƀ|粱}NUFRLYbpږyBQJ)O-\6/\3cb?Y9c;k:i5t;+L/OrBc4c4c1Jf=TM_1>X0_0k5o3u7(B)E2R\ *`1d2Lg-FG[-<1:1X{#E0B2:&/l#-OnI[ ?X ;e055:+0168>?EBHCIBICI:C7@5@6A:D@LMXVaZeQ[9C9COXPXKS]gjxzk~|&`8\oҊ_`||okyo|nxk|n׈zԉ{̆vΌ}ȇxdžwƅvƃwȃwX[QX3@ap埰tU/S2X8\;\9^9h@p Jn!F`8_3io=u%C5Sj8b0c/Hb,E?X6L2B:GGPNWQWSUUUYWVUXVZZ]_`eciemgnsuqpnmiide_`XZSVGKBG>DAGHNNUPXR\NZS`UdSdRbUf\ocvgwyguXakqnrdfptztD]d0]/`<]A_J[HWCQ;^Cv(Px'Ks>v=7W(D+C8N|!9j-}+K0V\:_?W1KaՌpt|zrjրr|l|nӃsՆvчwЇwЊzˆvɇvɇvˆxˆx`eX]JRhrܘΎo1GZ5[8_>`@];\9c>lFm Eb:^4g=mBlAm@r$C0Nl:e1e1B\x'Ap7y'G6Y\8]aBbB^<[7_9f@kCb:^6e=j@j@m@r$C{+Io=i5f2:Tt#=8R6O(=0B?NIUMUOTQSRSTSUTWXZ\]``dchchprpqprprmphlaf\aW^ZaZbV_Q[Q[Wa]hlzt~xfojpwyvvouj~4Q_/\2^9Z;]A`HT:[>`?hDnCi9k7)G>Y$>5P0L{=x ?s!A<_]9\:W2G]ӊx|~zxmցu}o~oӄtӇvчuЇwЊyˆvˆvˆvˆv̅xFC]Zeh䜣ܗXjS+c#BZ>\@bDdE_=Z6^6dj@kAn As%F{*Jt$Bi7h44Qw&@7Q3L#:+?:JESLUMTNROPQOQPSTVVY[\^^backmmnnpqsqsmpei`eW]W^X_U]R[S\V`[eanixqvvusstixcmfmu{w{jsTjp?V *_7_<^?cG]EU;\?a@hBm@d3i4,HA[}$=;U.H}!=~&EoV:ZC]Ed Jf!IcB^8b8h>gAd@c=gAlBm Co"Cs%Fz,Kv(Gh6h62N|,H7Q/I!:'=4G@PIUKTLQMONOPNRPUUYX[\__`agiijkmoqprmpgkbg_d[aX^W^Y`YaX`WaZg`nhvn~pnlj}`rarhvmzozwrz`m5Of;]5`<\;aDf"LZ@\@]@^e3j3/H?X'@;S-G%A(En;Cgd?]9]5@TφЂԂ}tׄwӀsrԅwԈyЇw͇wΉẏyʈyʈẏẏ{υ{҈ļvq-?b9e"F]E]I`Mg"Pj$OgFb=e;m Ae?eAgAiCm Eo"Ep#Fq$Ex*Iy+Jg5i7~.J/K7Q/H:$=.E:MCQGRIOHKNPOORPUSZY]\`_c`dcfghjkmnpmohkdhej`e[`Y_[aY`U\RZU_Wc[g^l`m_n]l]k[hgvp~txr|\fHYr:d<`<\:X;_DbHY?e!I`A]9f>m!?g3m64M;S-F8O.H*F%BoOAMBKDJFHIJNMSPXU[X]\cecgeihljokpjohmbgejfkdi`e^c`ebg^d\bZ`[a_edjhnjrsznycptbp3A|!7c8cFYi =j;a-p!8CZ1F9O-D2J5Ov9w!A;^q$G_8g!=:N˂؍҂zԃw׆z҃vσu҇{҉|͈zʈỷ}ʉ|ʉ|ʉ|ʉ~ʉ~PQZd#2a9W8^F^K^MbQi"Uk%SfG`i9n >v(F}+H'Gz8#@1J+A4HETCOBKEJJKQRWVZYYVXWehejgkimjnjnimgkdhfjhkehbeehlosvrvx{||zzyz{|{|y|{y~lur}sCSu,,Ec?[BW>V>[C`HcId Hm(N`$@~&G3Vy,OeOBQGSIRMRPTUVWXYXZ[bebgdheigkhlhkhkilloproqmonptvz}恂熆臅愂~~|⁁x{s|wdt*>c&w*E_@WBT?XA\DaId Je Ho'Nc>h@h:g7a/k5Kb;O.D'C)J6Wu'He;f:n(;}҅zی|q̀uЅyӉҋ΋ˊ}ʉ~Ȉ}Ȉ}Ȉ}ȈȈm->Y+[1c!hBk EiAm#Cn"@h:e7i;o!?s#A})Io8w<*F$@":0E;N>NCPGQLSPUUY]_cgchcjdkflhniokqmrmqquwzy|y{y{|~、ꍎ쑏쒍茈艄爃䅀߀}ᄃuy||L_b*['r*IZ@UCUAXC\FbJd Jf!Im%Le@l"Dk=h8c1o;PgR5K'@*F+K7Xs%Fj @d6m':ӈ|ڎyńwӈ~Ջы̉ˊʊLJ~ň~ň~ŇŇg(D]<^?^AW9]Ad J]C_FdIj%Mj%KcA\8bjDh@l"Dm Ah:f8i;m=m>y(Hl:p<)H%@v47-B2E8HANEQIROWYbbhaibicjdkgmjpnsrvmqtw{}恂傃䁂も㄃萏钑铏掉獆荄剃߃܁wyقt5KZ)e9o*OVAUDVCYE^Ha Ie!Ig"Hj#HfAo%Gl@g8d5s#ASm>R4G?S5K'@,F+K3Uw&Hv)Je7l&7ǁݕцz׋}wku҈~ӌωɈ}Ȉ}ɉć}Ć~Ć~Ć~Ć~y9be%N[D^F]E[A_C_C`Af!Gn'Lm&Kb>[7b>n'J\;`AcBa@\9Z7`;gBh@l"Dk!Ag=h:k=l >k=t&Gl=o>|*I)Gr3o-~5*A2F:L@PCRHUO[Wa[c]e`gbidjhmnrswpsvx~億爇爇切㈆䍌后友午鏈쑈댇㇃{{y~ׂato9`2q(Lf!IWDVGYF\H^Ib!Jg#Kj%KfDd?n$Fj@f9f9s%FTpAW7IAS4J&?-G*J/Qv%G3Qe6j$5ʄۓш{֌|xnʀx҈ҋ̉Ȇ~ȈȋĆ~Ç~ÇÇÇu5ha"RVD_Kg%Q`H\>`A`>f"Dn'Hl%F`[8^;e@g?k!Ck!Ah>ju&JSqAW8JAS4I&?.I,L.Os!A8Vb3h"3͇ܔԋ~ُ{qʀx·~ω̉ɉNJɌ†}†}†††a#[]SWK]Mf$Q`H[<`=a;h$Bq+In(Fa;Y5b@p(OaB`AcDfGdC^=^;b=e=h@i?h>k=o#An"@hSI\P_O[V`^gajbkgnlssxrvswy{~㋊卌厍琐琐卌劈댉鉄~svyq?Xa/b;o#P]E`!M^$N_#N_!K_Hb!Hj'Lq)PeBc?kCf>h?mDx)OSr@V8HBS4I(A3N1O2St"B?]b3g!2Έْԋ~؎~{q}wyȂ{ȅ}Ɔ}ŇĈ||~~~RO]!VZQXI\H[CZ;a?g An(Fu-Lr*Kd@\:eCt,ScD`AbCh IgF`?^<`=c=f>h@g?k?o"Cm Ai=j @t*Jj>i<0R1Qs=p2r.u,z+0#:/F6N;ODRLUT]XaYb\dcjiootptrvxyۀކ⊉㊋钔葓匍㈈切艆yxrwvjz>We4`:l"Ne N`%R_'U`%R`!M_Jd Jk&Ns+ReCb?gBc;i?q#D{-NSq>T8HCS6H+A8P7R7Ux&EEcf3j 2Ј֏Їzӈzwpvswszu~xĀzÁz{„~~HBKEPEUG]J`HaDb@eBy+Su*Ow,QW4_=b@t/TaB]@aBfGfG`A`>c@Y6_:gAjDk Ek!Cp#Ft'Ht&Dv(Fv%Et!Dx$G+O*L%Cz4y,z*/229#<'50:;EDNJTQ[\ccjhnlrrwvyz|~݁玑܃ۂރ||uvptu~dtR2J}*E5Pv%=6G׎֏ˀvspef_`iirrsrwt{zÀ~P#IP GT#Ja*SI 5YCdGbCn K1[}/W{-UZ6_r-R`A\?`AdEdE_@_=b@^;_q>p?vE(M-O+G!8!4'70A6J6M:XA[@OFRMYR]S^V_\ebjjpnttzy||~၄ᄆ܄ځځځxxsrjmpw^ix2CU(T/e)Fn5YZ(TY&X["Ta!Ui#Xp&Xl#RbGf#HaB^=b ;d6l!95LLdG]]IW?Yo+M^?\?_@bCbC_@_=a?b?`=a=eAl!Fo$Im"GlBn >o;l;i9p?|#H-O0L,A1C=KJXQbRhUp[sgtjtnxnxlvlsovrykrptw{}ဂ⁃₅茐玑菒鐑琏揎㎌ߍ䕕束ՏitDUm1D^&eAiCl!Fl!Fk!Cq%Bo"=j;g8j;uB*L2N7L@PNZZe^k]p]t_ucqgrjultjrjrltotkpptw{|~}}~~ۂޅ⎇攍癓穭ٟcrsASN!9L;U!@b'Jd%K_E^De!K]EZ>Z;_Q9O/H)E.G2E旡́ΆjbSQZ[[\TTRTY[]^Z[]``bbefhhi˜}f1VM9S:cGeDm"J}2Y8]n$F_8`9q*K|5V^?_B_B_BaBcDcBcBa>c@eBeBe?gAk En$Fo&Bn"?jh ?u)F6SB]I`;P?SAS1A1A=P9Q3L,H3L:Mꛥȁxf\[Xccdd[[UWY[\]XY[^[^]`]`\_sxÎYCV=[=aBn%K}2W<^iA^7]6q+Iy2S^?`C`C^A`AdEeDdC`=c@eBdAc=d>k Eq'Ik">i X>PLWY`^b\c[d[i[haibjdlgnipkqlrlphlnnrruuttssrrsryxzy{z}xׁyߋ瘋죓漢취跪鼲忹˥x||IV]"7P+X9e&J]DZAW<\;h"@x,J8UB]Jd7N:N?Q0C0C:P7O2K-I3LCV隤~~{rh^gdkkkkff`b_a_`]^\_[^Y]W[UYǘ}NqxHi]f)LM 1dDg Ev-Q9Z`9[2X/q+Iw0Q\=_C^B\?\?bEdEcBa?a?a>a>b=fAk"Fo'Hh!j=m=+I=V@QNXZ^Z^Y\Z`[d[d[c]d^eafdifjfjfhikmlpoqppoomomqnpnspuqzsցuۊ}ᕄ㝊䣎밙纤罪òȶ߻Ʒļ٨zJ]d'@O2U=R:P6S6baDcD`AdB`>]:^;d?j!Em$Hm%Fj#>i"=l#@l@g`>b=fAi Dl$Eo(Co(Ax/Li=`5k>s?3L@QMXQUQQWVVWTVZ^[`\`]a`ddgfifgfgiikkmknkmjmjmiokpmvq}uޅz~啅螊馍걕紖渘滚澞ġĤહWkZ'?B (L/Y4e<}/N?]Lj|/J5L2I{)>4I1I,E/K*Fv#\@bCf!Gh!FfDcAa?b=e@hCj"Ap'Aq(B{2Om Ac8l?s?3M@RNXRVQSWVWXTVY^\a]a]a^bcffiijjkjjllmkljlilinjqmsmxqv߆{䕅矊馍뮓鱓糔淖庘潚澛翜Ÿöܭpe3GN.T0k%C{.O{-LJiz,J2L1I{)@5L2K,H-K|&Bv#c?eAh ?s'Bt)A5Rt&Ggd@g Cj"At'@z*D9W},Nm@l>q>4P=SN\T[QUWYY]V[X_Y`\b_ebhekilmppsmpmmkkiihhkholtp{ux{~⏂㔄坊梌橐媑䮑屓法趖縗蹘繙뽝¢ıǷĸ–P`Y4Y3s)K@cq#Bz*F|+Ew$=1J1J,H|&Dl2v#[:|2Zt*Rd H`Fa Gb!H^DY?^@e"Gl)Mi&Je EbBa?cAi"En$Dx(B},D<[0SpDk?o>4S;SP_T^QWW[\aV^XaT[[cbjgoiojplqmrmpmokmhjggjionus}wz}㉀⎃㔆䛋䠌榑䩒䫓䮓氕貕鳖鵗븞ﻝ¤ɮǮѿÔ|DZW4g C:]k>u%Cw&@t!:.G.J*Fz$Bg-w$=ֈsqti͆{ƀzĀ|{}y|z{y{yzy{|yzvytwtv Gl!Fl!Fm CkAi=z.Lj;i9o!?v)D3O3Pz9<%A.G8L>OAMBKDJFHIJNMSPXU[X]\cecgeihljokpjohmbgejfkdi`e^c`ebg^d\bZ`[a_edjhnjrsznycptbp3A|!7c8cFYǏpȪ7wfGjҝ>fg= uV]c'ڦ7+)+1lW^j05"G+>Vu,PA$;d{WWSG4fvi<[C+O:RKc)|GdV Isd%=𫖷qg'([A{U=Rݬ[ 3: Oԗo5ƙC׏n94w&Z.,qרiXA~]-bʣ{&Im ?PׇⳊ-0DGϹ+t46Ms+w75֪KMoŨMa+n=E,GcO+Sվz2Ǡ=>MoP 4q]Fv7"mi[{IoN -Ĉ 8ۂBЂ9v }M8󏉚~Ċ" vKtŻ" \#R{b~6A~ι{2@koZgМZ\C^F8?k\dDcPyglW45!p֚P'֐Z(͟\ҳd}'?ekv?غ!x*O_ƽxr•Wے?\Vg3 ._̙TjGDT幙1崹Ώ'+k1m߁AɡcBԤYUVG9r\};1m~ZfW kx&IڽF,+ ,jb+FÎ9 *k RO5(d&6GG<ʺK e;W {ɰ5["KIթ=qIY3~s :$vfqSA?AymAн}Ǘ3ԁ}.2ѴIa0XEs^Q.":] z,lI+gw WwRuٷQ8XsJ=܌wCa&*0{c)K\^} ]@n\wcl$o|8ŷA](M"iJ;t~eO+8#xK~~+Kr+yL1hfБK^kC渿Zc-A]vLD;qs mf\z,m;^!dܴ\l8VϣZ&n[TFJkku=" /Ie韠?޷mvd׮Ru;2ܖU1AV4XYHLVmnx+GF(^!~ 7V+H֚L-FQ+Rc ե1^gSzB&64eOqTK5 +mqBvcLi _ʺ"My|\m:vckr>a0*׉lM NR1KC+PaGcPISrbN$5@˞sWvr9A.<?ֺ|;NK,m\\ zt>H#J$dj@z]!v{kU5m\z)\wc5}P^by.t {BG1\Ll sS]%JeG,XҤy#Mzp$l1!lNjm^xf]CS;Q$ZgQ^+rm+-9#CjOH\5i4FU%c}Fr9^J?֬A*I`֍8²~Ӑoym8ǬydH(tw0x􆵵B@be|wAZ9S VNMGRBIcAS F,}>آ!jŚ5 ~?'BJvUho3&lOEbʟ:`g?ovɩ&vegVъlnXFQ"R_iO%ylDއ|5Ū9JKy&ۋ䳙@#=9"9vkגf4ޖ z\T@Lɭ؛R~Vlt1 <5$a%nqcd3 AJͤ;(+2彭`ypКӆE+p =Tڹ[f(Ҁmd WUX'Uœ_dڊCIT]^#Ƶe>u+MZN9;k~"ZHk:z,$GI=+#{猹ZLaа5?j%~M֮T^y2;'v3tA)TV:vwzh:A&YM+Ki{WWSG4fvi<[C+O:RKc g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${OBJS} libtiff.a core a.out mkg3states g3states.h *~ tags: ${SRCS} ${CTAGS} ${SRCS} OBQGSIRMRPTUVWXYXZ[bebgdheigkhlhkhkilloproqmonptvz}恂熆臅愂~~|⁁x{s|wdt*>c&w*E_@WBT?XA\DaId Je Ho'Nc>h@h:g7a/k5Kb;xloadimage.4.1/tiff/Makefile.aix 664 221 144 15006 5461577442 11750 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.aix,v 1.13 92/03/18 12:11:22 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # # This Makefile is designed for IBM RS6000, AIX 3.x. # Check up the CONFIGURE: comments for AIX 2.2.1 and building shared library # # The library will be installed in $(DESTDIR)/lib and the included # files in $(DESTDIR)/include DESTDIR=/usr/local # AR= /bin/ar # # SHELL, CTAGS, RANLIB and INSTALL is not defined in standard make for AIX # # CONFIGURE: AIX2.2.1 "RANLIB=echo ranlib" # ( ranlib for AIX3.x is for compatibility only ) RANLIB=/usr/bin/ranlib SHELL=/bin/sh # CONFIGURE: AIX2.2.1 "CTAGS=ctags -w" CTAGS=ctags -tw # # NOTE: The AIX versions of install is execute by root only, or SYSV versions. # CONFIGURE: (The /bin/cp variant should work on both 2.2 and 3.x) # INSTALL=/usr/ucb/install -c -m 444 INSTALL=/bin/cp # NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # # CONFIGURE: CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} # # CONFIGURE: AIX 3.2 : add -DMMAP_SUPPORT (?) # AIX 2.1.1 : -DUSE_VARARGS=1 -DUSE_PROTOTYPES=0 -DUSE_CONST=0 CONF_LIBRARY=\ -DUSE_VARARGS=0 \ -DUSE_PROTOTYPES=1 \ -DUSE_CONST=1 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DJPEG_SUPPORT \ -DYCBCR_SUPPORT \ -DCMYK_SUPPORT \ ${NULL} CFLAGS= -O -Dunix ${SHLIB_FLAGS} ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} # CONFIGURE: Compile libtiff as a Shared Library # Remove the comment if you want to build libtiff as a shared library: # #SHLIB_FLAGS= -bM\:SRE # ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} @if [ -n "$(SHLIB_FLAGS)" ]; then \ echo "\n\tBuilding $@ as a shared libary, assumes that" ;\ echo "\t\tall .o files is compiled with $(SHLIB_FLAGS).\n" ;\ set -x ;\ rm -f $@~ ; \ $(AR) clq $@~ $(OBJS) ;\ dump -g $@~ | sed -n -e 's/^[ ]*[0-9][0-9]*[ ]*\([^ .][^ ]*\)$$/\1/p' > $@.syms ;\ $(LD) -o shr.o $@~ -H512 -T512 -bM\:SRE -bE\:$@.syms -lc -lm ;\ rm -f $@~ ;\ $(AR) clq $@~ shr.o ;\ rm -f $@.syms $@ shr.o ;\ mv $@~ $@ ;\ else \ echo "\t${AR} rc libtiff.a $?" ;\ ${AR} rc libtiff.a $? ;\ fi # ranlib for AIX is for compatibility only # ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h # CONFIGURE: Remove '-c' in AIX 2.1.1 g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states -c > g3states.h install: all installh -test -d ${DESTDIR}/lib || mkdir ${DESTDIR}/lib -@for i in ${ALL}; do \ if cmp -s $$i ${DESTDIR}/lib/$$i ; then \ echo "${DESTDIR}/lib/$$i is up to date" ; \ else \ rm -f ${DESTDIR}/lib/$$i ;\ echo " ${INSTALL} $$i ${DESTDIR}/lib/$$i" ; \ ${INSTALL} $$i ${DESTDIR}/lib/$$i; \ fi \ done # ranlib for AIX is for compatibility only # ${RANLIB} -t ${DESTDIR}/lib/libtiff.a installh: ${INCS} -test -d ${DESTDIR}/include || mkdir ${DESTDIR}/include -@for i in ${INCS}; do \ h=`basename $$i`; \ if cmp -s $$i ${DESTDIR}/include/$$h ; then \ echo "${DESTDIR}/include/$$h is up to date" ; \ else \ rm -f ${DESTDIR}/include/$$h ;\ echo " ${INSTALL} $$i ${DESTDIR}/include/$$h" ; \ ${INSTALL} $$i ${DESTDIR}/include/$$h; \ fi \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h err errs tags: ${SRCS} ${CTAGS} ${SRCS} # EOF 5ʄۓш{֌|xnʀx҈ҋ̉Ȇ~ȈȋĆ~Ç~ÇÇÇu5ha"RVD_Kg%Q`H\>`A`>f"Dn'Hl%F`[8^;e@g?k!Ck!Ah>ju&JSqAW8JAS4I&?.I,L.Os!A8Vb3h"3͇ܔԋ~ُ{qʀx·~ω̉ɉNJɌ†}†}†††a#[]SWK]Mf$Q`H[<`=a;h$Bq+In(Fa;Y5b@p(OaB`AcDfGdC^=^;b=e=h@ixloadimage.4.1/tiff/Makefile.apollo 664 221 144 11054 5461577442 12454 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.apollo,v 1.26 92/02/19 14:25:25 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # # the library will be installed in DESTDIR/lib and the included files in DESTDIR/include DESTDIR=/progs/bit2bit/tiff # AR= /bin/ar RANLIB= /usr/bin/ranlib INSTALL= /usr/bin/install NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -O -A nansi ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_flush.c \ tif_getimage.c \ tif_jpeg.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_flush.o \ tif_getimage.o \ tif_jpeg.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh @-mkdir $(DESTDIR)/lib -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} @-mkdir $(DESTDIR)/include -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} umpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} # CONFIGURE: Compile libtiff as a Shared Library # Remove the comment if you want to build libtiff as a shared library: # #SHLIB_FLAGS= -bM\:SRE # ALL= libtiff.a all: ${ALL} ${ALL}: $xloadimage.4.1/tiff/Makefile.hpux 664 221 144 10550 5461577442 12152 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.hpux,v 1.25 92/02/19 14:25:26 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /bin/ar ts NULL= IPATH= -I. -I/usr/include/bsd # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -O -Dhpux ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documxloadimage.4.1/tiff/Makefile.mips 664 221 144 10543 5461577442 12140 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.mips,v 1.25 92/02/19 14:25:27 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /bin/ar ts NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} echo "${DESTDIR}/lib/$$i is up to date" ; \ else \ rm -f ${DESTDIR}/lib/$$i ;\ echo " ${INSTALL} $$i ${DESTDIR}/lib/$$i" ; \ ${INxloadimage.4.1/tiff/Makefile.next 664 221 144 10633 5461577442 12146 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.next,v 1.25 92/02/19 14:25:28 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /bin/ranlib INSTALL= /usr/bin/install NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=0 \ -DUSE_PROTOTYPES=1 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -mkdirs ${DESTDIR}/lib -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -mkdirs ${DESTDIR}/include -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} =0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${Cxloadimage.4.1/tiff/Makefile.sgi 664 221 144 10544 5461577443 11754 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.sgi,v 1.44 92/02/19 14:25:29 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /usr/bin/ar NULL= IPATH= -I. -I/usr/include/bsd # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=0 \ -DUSE_PROTOTYPES=1 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DJPEG_SUPPORT \ -DYCBCR_SUPPORT \ -DCMYK_SUPPORT \ -DMMAP_SUPPORT \ ${NULL} CFLAGS= -O ${IPATH} ${CONF_LIBRARY} -ansi # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${OBJS}: tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states -c > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} NLIB} -t ${DESTDIR}/lib/libtiff.a installh: ${INCS} -test -d ${DESTDIR}/include || mkdir ${DESTDIR}/include -@for i in ${INCS}; do \ h=`basename $$ixloadimage.4.1/tiff/Makefile.sun 664 221 144 10546 5461577443 12001 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.sun,v 1.36 92/02/19 14:25:29 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /usr/bin/ranlib NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} do \ h=`basename $$i`; \ if cmp -s $$i ${DESTDIR}/include/$$h ; then \ echo "${DESTDIR}/include/$$h is up to date" ; \ else \ rm -f ${xloadimage.4.1/tiff/Makefile.svr4 664 221 144 10540 5461577443 12064 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.sun,v 1.36 92/02/19 14:25:29 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /bin/true NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=1 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add supportxloadimage.4.1/tiff/Makefile.tahoe 664 221 144 10573 5461577443 12274 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.tahoe,v 1.27 92/03/30 18:33:37 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= ar RANLIB= ranlib NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=0 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_machdep.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_machdep.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} de/$$h; \ fi \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h err errs tags: ${SRCS} ${CTAGS} ${SRCS} xloadimage.4.1/tiff/Makefile.vax 664 221 144 10607 5461577443 11770 # $Header: /usr/people/sam/tiff/libtiff/RCS/Makefile.vax,v 1.37 92/03/30 18:13:23 sam Exp $ # # Tag Image File Format Library # # Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler # Copyright (c) 1991, 1992 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # AR= /bin/ar RANLIB= /usr/bin/ranlib NULL= IPATH= -I. # # Library-wide configuration defines: # MMAP_SUPPORT add support for memory mapping read-only files # COLORIMETRY_SUPPORT add support for 6.0 colorimetry tags # JPEG_SUPPORT add support for 6.0 JPEG tags & JPEG algorithms # YCBCR_SUPPORT add support for 6.0 YCbCr tags # CMYK_SUPPORT add support for 6.0 CMYK tags # # Compression configuration defines: # CCITT_SUPPORT add support for CCITT Group 3 & 4 algorithms # PACKBITS_SUPPORT add support for Macintosh PackBits algorithm # LZW_SUPPORT add support for LZW algorithm # THUNDER_SUPPORT add support for ThunderScan 4-bit RLE algorithm # NEXT_SUPPORT add support for NeXT 2-bit RLE algorithm # JPEG_SUPPORT add support for JPEG DCT algorithm # # Note that if you change the library-wide configuration, you'll # need to manual force a full rebuild. Changing the configuration # of which compression algorithms are included in the library is # automatically handled (i.e. tif_compress.o has a dependency on # the Makefile). # CONF_COMPRESSION=\ -DPACKBITS_SUPPORT \ -DLZW_SUPPORT \ -DCCITT_SUPPORT \ -DTHUNDER_SUPPORT \ -DNEXT_SUPPORT \ ${NULL} CONF_LIBRARY=\ -DUSE_VARARGS=1 \ -DUSE_PROTOTYPES=0 \ -DHAVE_IEEEFP=0 \ -DCOLORIMETRY_SUPPORT \ -DYCBCR_SUPPORT \ ${NULL} CFLAGS= -g ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ tif_fax4.c \ tif_aux.c \ tif_ccittrle.c \ tif_close.c \ tif_compat.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_lzw.c \ tif_machdep.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_write.c \ ${NULL} OBJS= tif_fax3.o \ tif_fax4.o \ tif_aux.o \ tif_ccittrle.o \ tif_close.o \ tif_compat.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_lzw.o \ tif_machdep.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_print.o \ tif_read.o \ tif_strip.o \ tif_swab.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALL}: ${OBJS} ${AR} rc libtiff.a $? ${RANLIB} libtiff.a ${OBJS}: tiffio.h tiff.h tiffcompat.h tiffioP.h tif_compress.o: tif_compress.c Makefile ${CC} -c ${CFLAGS} ${CONF_COMPRESSION} tif_compress.c tif_fax3.o: tif_fax3.c g3states.h t4.h tif_fax3.h g3states.h: mkg3states.c t4.h ${CC} -o mkg3states ${CFLAGS} mkg3states.c ./mkg3states > g3states.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ ${RANLIB} ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} if_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_write.o \ ${NULL} ALL= libtiff.a all: ${ALL} ${ALxloadimage.4.1/tiff/README 664 221 144 17260 5461577443 10415 $Header: /usr/people/sam/tiff/libtiff/RCS/README,v 1.14 92/02/19 14:04:31 sam Exp $ Configuration Comments: ---------------------- Aside from the compression algorithm support, there are configuration-related defines that you can set in the Makefile: COLORIMETRY_SUPPORT if this is defined, support for the colorimetry tags will be compiled in. JPEG_SUPPORT if this is defined, support for the JPEG-related tags will be compiled in. Note that at the present time the JPEG compression support is not included. YCBCR_SUPPORT if this is defined, support for the YCbCr-related tags will be compiled in. Note that you'll want YCBCR support for JPEG compression+decompression. CMYK_SUPPORT if this is defined, support for the CMYK-related tags will be compiled in. MMAP_SUPPORT if this is set, and OS support exists for memory mapping files, then the library will try to map a file if it is opened for reading. If mmap does not exist on your system, or the mmap call fails on the file, then the normal read system calls are used. It is not clear how useful this facility is. By default, the above are not defined. Portability Comments: -------------------- I run this code on SGI machines (big-endian, MIPS CPU, 32-bit ints, IEEE floating point). Makefiles exist for other platforms that the code runs on -- this work has mostly been done by other people. I've also been told that the code runs on Macintosh and PC-based systems, although I don't know the particulars. In general, I promise only that the code runs on SGI machines. I will, however, gladly take back fixes to make it work on other systems -- when the changes are reasonable unobtrusive. I've tried to isolate as many of the UNIX-dependencies as possible in two files: tiffcompat.h and tif_compat.c. There are still some problems with the use of lseek(). I personally don't care to devote much effort to making the code work (untouched) on lots of non-UNIX platforms. Machine dependencies such as byte order are determined on the fly and do not need to be specified. Three general portability-related defines are: USE_VARARGS define as 0 or 1 to select between the use of varargs.h and stdarg.h; i.e. -DUSE_VARARGS=0 means use stdarg.h USE_PROTOTYPES define as 0 or 1 to select function declarations with parameter types USE_CONST if your compiler defines __STDC__ or __EXTENSIONS__, but does not support const, define this as 0, otherwise leave it alone BSDTYPES define this if your system does NOT define the usual 4BSD typedefs If you compile the code with prototypes (USE_PROTOTYPES=1), then you must have USE_VARARGS=0. Beware that if __STDC__ is defined and the USE_* symbols are NOT defined, then compat.h defines: USE_PROTOTYPES 1 USE_VARARGS 0 USE_CONST 1 General Comments: ---------------- The library is designed to hide as much of the details of TIFF as possible. In particular, TIFF directories are read in their entirety into an internal format. This means that only the tags known by the library are available to a user and that certain tag data may be maintained that a user doesn't care about (e.g. transfer function tables). To add support for a new directory tag the following changes will be needed: 1. Define the tag in tiff.h. 2. Add a field to the directory structure in tiffioP.h and define a FIELD_* bit. 3. Add an entry in the FieldInfo array defined at the top of tiff_dirinfo.c. 4. Add entries in TIFFSetField() and TIFFGetField1() for the new tag. 5. (optional) If the value associated with the tag is not a scalar value (e.g. the array for TransferFunction), then add the appropriate code to TIFFReadDirectory() and TIFFWriteDirectory(). You're best off finding a similar tag and cribbing code. 6. Add support to TIFFPrintDirectory() in tiff_print.c to print the tag's value. To add support for a compression algorithm: 1. Define the tag value in tiff.h. 2. Edit the file tiff_compress.c to add an entry to the CompressionSchemes[] array. 3. Create a file with the compression scheme code, by convention files are named tif_*.c (except perhaps on System V where the tif_ prefix pushes some filenames over 14 chars. 4. Edit the Makefile to include the new source file. A compression scheme, say foo, can have up to 10 entry points: TIFFfoo(tif) /* initialize scheme and setup entry points in tif */ fooPreDecode(tif) /* called once per strip, after data is read, but before the first row in a strip is decoded */ fooDecode*(tif, bp, cc, sample)/* decode cc bytes of data into the buffer */ fooDecodeRow(...) /* called to decode a single scanline */ fooDecodeStrip(...) /* called to decode an entire strip */ fooDecodeTile(...) /* called to decode an entire tile */ fooPreEncode(tif) /* called once per strip/tile, before the first row in a strip is encoded */ fooEncode*(tif, bp, cc, sample)/* encode cc bytes of user data (bp) */ fooEncodeRow(...) /* called to decode a single scanline */ fooEncodeStrip(...) /* called to decode an entire strip */ fooEncodeTile(...) /* called to decode an entire tile */ fooPostEncode(tif) /* called once per strip/tile, just before data is written */ fooSeek(tif, row) /* seek forwards row scanlines from the beginning of a strip (row will always be >0 and native.mant<<11)|\ ((dp)->native.mant2>>21)) >> (1022+16-(dp)->native.exp)) #define EXTRACTEXPONENT(dp, exponent) ((exponent) = (dp)->native.exp) #define NATIVE2IEEEFLOAT(fp) #define IEEEFLOAT2NATIVE(fp) #define IEEEDOUBLE2NATIVE(dp) #define TIFFSwabArrayOfFloat(fp,n) TIFFSwabArrayOfLong((unsigned long *)fp,n) #define TIFFSwabArrayOfDouble(dp,n) TIFFSwabArrayOfLong((unsigned long *)dp,2*n) #endif /* IEEEFP */ #ifdef tahoe #define BIGENDIAN 1 typedef struct { unsigned sign:1; unsigned exp:8; unsigned mant:23; unsigned mant2; } nativedouble; typedef struct { unsigned sign:1; unsigned exp:8; unsigned mant:23; } nativefloat; #define ISFRACTION(e) (128 - 4 <= (e) && (e) <= 128 + 15) #define EXTRACTFRACTION(dp, fract) \ ((fract) = ((1<<31)|((dp)->native.mant<<8)|((dp)->native.mant2>>15)) >> \ (128+16-(dp)->native.exp)) #define EXTRACTEXPONENT(dp, exponent) ((exponent) = (dp)->native.exp - 2) /* * Beware, over/under-flow in conversions will * result in garbage values -- handling it would * require a subroutine call or lots more code. */ #define NATIVE2IEEEFLOAT(fp) { \ if ((fp)->native.exp) \ (fp)->ieee.exp = (fp)->native.exp - 129 + 127; /* alter bias */\ } #define IEEEFLOAT2NATIVE(fp) { \ if ((fp)->ieee.exp) \ (fp)->native.exp = (fp)->ieee.exp - 127 + 129; /* alter bias */\ } #define IEEEDOUBLE2NATIVE(dp) { \ if ((dp)->native.exp = (dp)->ieee.exp) \ (dp)->native.exp += -1023 + 129; \ (dp)->native.mant = ((dp)->ieee.mant<<3)|((dp)->native.mant2>>29); \ (dp)->native.mant2 <<= 3; \ } /* the following is to work around a compiler bug... */ #define SIGNEXTEND(a,b) { char ch; ch = (a); (b) = ch; } #define TIFFSwabArrayOfFloat(fp,n) TIFFSwabArrayOfLong((unsigned long *)fp,n) #define TIFFSwabArrayOfDouble(dp,n) TIFFSwabArrayOfLong((unsigned long *)dp,2*n) #endif /* tahoe */ #ifdef vax #define BIGENDIAN 0 typedef struct { unsigned mant1:7; unsigned exp:8; unsigned sign:1; unsigned mant2:16; unsigned mant3; } nativedouble; typedef struct { unsigned mant1:7; unsigned exp:8; unsigned sign:1; unsigned mant2:16; } nativefloat; #define ISFRACTION(e) (128 - 4 <= (e) && (e) <= 128 + 15) #define EXTRACTFRACTION(dp, fract) \ ((fract) = ((1<<31)|((dp)->native.mant1<<16)|(dp)->native.mant2)) >> \ (128+16-(dp)->native.exp)) #define EXTRACTEXPONENT(dp, exponent) ((exponent) = (dp)->native.exp - 2) /* * Beware, these do not handle over/under-flow * during conversion from ieee to native format. */ #define NATIVE2IEEEFLOAT(fp) { \ float_t t; \ if (t.ieee.exp = (fp)->native.exp) \ t.ieee.exp += -129 + 127; \ t.ieee.sign = (fp)->native.sign; \ t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \ *(fp) = t; \ } #define IEEEFLOAT2NATIVE(fp) { \ float_t t; int v = (fp)->ieee.exp; \ if (v) v += -127 + 129; /* alter bias of exponent */\ t.native.exp = v; /* implicit truncation of exponent */\ t.native.sign = (fp)->ieee.sign; \ v = (fp)->ieee.mant; \ t.native.mant1 = v >> 16; \ t.native.mant2 = v;\ *(fp) = v; \ } #define IEEEDOUBLE2NATIVE(dp) { \ double_t t; int v = (dp)->ieee.exp; \ if (v) v += -1023 + 129; /* if can alter bias of exponent */\ t.native.exp = v; /* implicit truncation of exponent */\ v = (dp)->ieee.mant; \ t.native.sign = (dp)->ieee.sign; \ t.native.mant1 = v >> 16; \ t.native.mant2 = v;\ t.native.mant3 = (dp)->mant2; \ *(dp) = t; \ } #define TIFFSwabArrayOfFloat(fp,n) TIFFSwabArrayOfLong((unsigned long *)fp,n) #define TIFFSwabArrayOfDouble(dp,n) TIFFSwabArrayOfLong((unsigned long *)dp,2*n) #endif /* vax */ /* * These unions are used during floating point * conversions. The macros given above define * the conversion operations. */ typedef struct ieeedouble { #if BIGENDIAN == 1 #if !defined(_IBMR2) unsigned sign:1; unsigned exp:11; unsigned long mant:20; unsigned mant2; #else /* _IBMR2 */ unsigned sign:1; unsigned exp:11; unsigned mant:20; unsigned mant2; #endif /* _IBMR2 */ #else #if !defined(vax) #ifdef INT_16_BIT /* MSDOS C compilers */ unsigned long mant2; unsigned long mant:20; unsigned long exp:11; unsigned long sign:1; #else /* 32 bit ints */ unsigned mant2; unsigned long mant:20; unsigned exp:11; unsigned sign:1; #endif /* 32 bit ints */ #else unsigned long mant:20; unsigned exp:11; unsigned sign:1; unsigned mant2; #endif /* !vax */ #endif } ieeedouble; typedef struct ieeefloat { #if BIGENDIAN == 1 #if !defined(_IBMR2) unsigned sign:1; unsigned exp:8; unsigned long mant:23; #else /* _IBMR2 */ unsigned sign:1; unsigned exp:8; unsigned mant:23; #endif /* _IBMR2 */ #else #ifdef INT_16_BIT /* MSDOS C compilers */ unsigned long mant:23; unsigned long exp:8; unsigned long sign:1; #else /* 32 bit ints */ unsigned long mant:23; unsigned exp:8; unsigned sign:1; #endif /* 32 bit ints */ #endif } ieeefloat; typedef union { ieeedouble ieee; nativedouble native; char b[8]; double d; } double_t; typedef union { ieeefloat ieee; nativefloat native; char b[4]; float f; } float_t; #endif /* _MACHDEP_ */ \ done clean: rm -f ${ALL} ${OBJS} core a.out mkg3states g3states.h err errs tags: ${SRCS} ${CTAGS} ${SRCS} # EOF 5ʄۓш{֌|xnʀx҈ҋ̉Ȇ~ȈȋĆ~Ç~ÇÇÇu5ha"RVD_Kg%Q`H\>`A`>f"Dn'Hl%F`[8^;e@g?k!Ck!Ah>ju&JSqAW8JAS4I&?.I,L.Os!A8Vb3h"3͇xloadimage.4.1/tiff/mkg3states.c 664 221 144 60016 5461577443 11763 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/mkg3states.c,v 1.13 92/03/06 11:10:57 sam Exp $"; #endif /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * Program to construct Group 3 & Group 4 decoding tables. * * This code is derived from code by Michael P. Marking. In * particular, the algorithms to generate the null_mode and * horiz_mode state tables are his. See the comments below * for more information. * * BEGIN (from the original source) LEGAL * Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039, * Scottsdale, Arizona 85252-8039. All rights reserved. * * License is granted by the copyright holder to distribute and use this * code without payment of royalties or the necessity of notification as * long as this notice (all the text under "LEGAL") is included. * * Reference: $Id: mkg3states.c,v 1.13 92/03/06 11:10:57 sam Exp $ * * This program is offered without any warranty of any kind. It includes * no warranty of merchantability or fitness for any purpose. Testing and * suitability for any use are the sole responsibility of the user. * INFORMATION * Although there is no support offered with this program, the author will * endeavor to correct errors. Updates will also be made available from * time to time. * * Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona * 85252-8039 USA. Replies are not guaranteed to be swift. Beginning * July 1990, e-mail may be sent to uunet!ipel!marking. * * Also beginning in July 1990, this code will be archived at the * ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number * for 300/1200/2400 is (602)274-0462. When logging in, specify user * "public", system "bbs", and password "public". * * This code is also available from the C Users Group in volume 317. * * END (from the original source) */ #include #include "prototypes.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define WHITE 0 #define BLACK 1 /* * G3 2D and G4 decoding modes. Note that * the vertical modes are ordered so that * (mode - MODE_VERT_V0) gives the vertical * adjustment for the b1 parameter. */ #define MODE_NULL 0 #define MODE_PASS 1 #define MODE_HORIZ 2 #define MODE_VERT_VL3 3 #define MODE_VERT_VL2 4 #define MODE_VERT_VL1 5 #define MODE_VERT_V0 6 #define MODE_VERT_VR1 7 #define MODE_VERT_VR2 8 #define MODE_VERT_VR3 9 #define MODE_UNCOMP 10 #define MODE_ERROR 11 #define MODE_ERROR_1 12 unsigned long DECLARE1(append_0, unsigned long, prefix) { return (prefix + (1L<<16)); } unsigned long DECLARE1(append_1, unsigned long, prefix) { static unsigned short prefix_bit[16] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001 }; unsigned char len = (prefix >> 16) & 0xf; return (append_0(prefix) + prefix_bit[len]); } #define G3CODES #include "t4.h" short #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST DECLARE3(search_table, unsigned long, prefix, tableentry const*, tab, int, n) #else DECLARE3(search_table, unsigned long, prefix, tableentry*, tab, int, n) #endif { unsigned short len = (prefix >> 16) & 0xf; unsigned short code = (prefix & 0xffff) >> (16 - len); while (n-- > 0) { if (tab->length == len && tab->code == code) return ((short) tab->runlen); tab++; } return (G3CODE_INCOMP); } #define NCODES(a) (sizeof (a) / sizeof (a[0])) short DECLARE1(white_run_length, unsigned long, prefix) { return (search_table(prefix, TIFFFaxWhiteCodes, NCODES(TIFFFaxWhiteCodes))); } short DECLARE1(black_run_length, unsigned long, prefix) { return (search_table(prefix, TIFFFaxBlackCodes, NCODES(TIFFFaxBlackCodes))); } #undef NCODES #define MAX_NULLPREFIX 200 /* max # of null-mode prefixes */ typedef unsigned char NullModeTable[MAX_NULLPREFIX][256]; #define MAX_HORIZPREFIX 250 /* max # of incomplete 1-D prefixes */ typedef unsigned char HorizModeTable[MAX_HORIZPREFIX][256]; /* the bit string corresponding to this row of the decoding table */ long null_mode_prefix[MAX_NULLPREFIX]; NullModeTable null_mode; /* MODE_*, indexed by bit and byte */ NullModeTable null_mode_next_state; /* next row of decoding tables to use */ /* number of prefixes or rows in the G4 decoding tables */ short null_mode_prefix_count = 0; /* * 2D uncompressed mode codes. Note * that two groups of codes are arranged * so that the decoder can caluclate the * length of the run by subtracting the * code from a known base value. */ #define UNCOMP_INCOMP 0 /* runs of [0]*1 */ #define UNCOMP_RUN0 1 #define UNCOMP_RUN1 2 #define UNCOMP_RUN2 3 #define UNCOMP_RUN3 4 #define UNCOMP_RUN4 5 #define UNCOMP_RUN5 6 #define UNCOMP_RUN6 7 /* runs of [0]* w/ terminating color */ #define UNCOMP_TRUN0 8 #define UNCOMP_TRUN1 9 #define UNCOMP_TRUN2 10 #define UNCOMP_TRUN3 11 #define UNCOMP_TRUN4 12 /* special code for unexpected EOF */ #define UNCOMP_EOF 13 /* invalid code encountered */ #define UNCOMP_INVALID 14 long uncomp_mode_prefix[MAX_NULLPREFIX]; NullModeTable uncomp_mode; NullModeTable uncomp_mode_next_state; short uncomp_mode_prefix_count = 0; /* * Decoding action values for horiz_mode. */ #define ACT_INCOMP 0 /* incompletely decoded code */ #define ACT_INVALID 1 /* invalide code */ #define ACT_WRUNT 2 /* terminating white run code */ #define ACT_WRUN 65 /* non-terminating white run code */ #define ACT_BRUNT 106 /* terminating black run code */ #define ACT_BRUN 169 /* non-terminating black run code */ #define ACT_EOL 210 /* end-of-line code */ HorizModeTable horiz_mode; short DECLARE1(horiz_mode_code_black, short, runlen) { return (runlen < 64 ? runlen + ACT_BRUNT : (runlen / 64) + ACT_BRUN); } short DECLARE1(horiz_mode_code_white, short, runlen) { return (runlen < 64 ? runlen + ACT_WRUNT : (runlen / 64) + ACT_WRUN); } /* * If the corresponding horiz_mode entry is ACT_INCOMP * this entry is a row number for decoding the next byte; * otherwise, it is the bit number with which to continue * decoding the next codeword. */ HorizModeTable horiz_mode_next_state; /* prefixes corresponding to the rows of the decoding table */ long horiz_mode_prefix[MAX_HORIZPREFIX]; /* color of next run, BLACK or WHITE */ char horiz_mode_color[MAX_HORIZPREFIX]; short horiz_mode_prefix_count = 0; static unsigned char bit_mask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; #if USE_PROTOTYPES void build_null_mode_tables(void); short find_horiz_mode_prefix(long, char); short find_null_mode_prefix(long); short null_mode_type(long); void build_horiz_mode_tables(void); short horiz_mode_code_black(short); short horiz_mode_code_white(short); void build_uncomp_mode_tables(void); void write_tables(FILE*); #else void build_null_mode_tables(); short find_horiz_mode_prefix(); short find_null_mode_prefix(); short null_mode_type(); void build_horiz_mode_tables(); short horiz_mode_code_black(); short horiz_mode_code_white(); void build_uncomp_mode_tables(); void write_tables(); #endif int verbose = FALSE; char *storage_class = ""; void DECLARE2(main, int, argc, char**, argv) { while (argc > 1 && argv[1][0] == '-') { if (strcmp(argv[1], "-v") == 0) { verbose = TRUE; argc--, argv++; } else if (strcmp(argv[1], "-c") == 0) { storage_class = "const "; argc--, argv++; } } build_null_mode_tables(); /* null mode decoding tables */ if (verbose) { fprintf(stderr, "%d null mode prefixes defined\n", (int) null_mode_prefix_count); fprintf(stderr, "building uncompressed mode scripts...\n"); } build_uncomp_mode_tables(); /* uncompressed mode decoding tables */ if (verbose) { fprintf(stderr, "%d uncompressed mode prefixes defined\n", (int) uncomp_mode_prefix_count); fprintf(stderr, "building 1D scripts...\n"); } build_horiz_mode_tables(); /* 1D decoding tables */ if (verbose) fprintf(stderr, "%d incomplete prefixes defined\n", (int) horiz_mode_prefix_count); write_tables(stdout); exit(0); } void DECLARE3(write_null_mode_table, FILE*, fd, NullModeTable, table, char*, name) { int i, j; char* outersep; char* sep; fprintf(fd, "%su_char\t%s[%d][256] = {", storage_class, name, (int) null_mode_prefix_count); outersep = ""; for (i = 0; i < null_mode_prefix_count; i++) { fprintf(fd, "%s\n/* prefix %d */ {\n", outersep, i); sep = " "; for (j = 0; j < 256; j++) { fprintf(fd, "%s%2d", sep, (int) table[i][j]); if (((j+1) % 16) == 0) { fprintf(fd, ", /* %3d-%3d */\n", j-15, j); sep = " "; } else sep = ","; } fprintf(fd, "}"); outersep = ","; } fprintf(fd, "\n};\n"); } void DECLARE3(write_horiz_mode_table, FILE*, fd, HorizModeTable, table, char*, name) { int i, j; char* outersep; char* sep; fprintf(fd, "%s u_char\t%s[%d][256] = {", storage_class, name, (int) horiz_mode_prefix_count); outersep = ""; for (i = 0; i < horiz_mode_prefix_count; i++) { fprintf(fd, "%s\n/* prefix %d */ {\n", outersep, i); sep = " "; for (j = 0; j < 256; j++) { fprintf(fd, "%s%3d", sep, (int) table[i][j]); if (((j+1) % 14) == 0) { fprintf(fd, ", /* %3d-%3d */\n", j-13, j); sep = " "; } else sep = ","; } fprintf(fd, "\n}"); outersep = ","; } fprintf(fd, "\n};\n"); } void write_define(fd, name, value, comment) FILE *fd; char *name; int value; char *comment; { fprintf(fd, "#define\t%s\t%d", name, value); if (comment) fprintf(fd, "\t/* %s */", comment); fprintf(fd, "\n"); } void write_preamble(fd) FILE *fd; { fprintf(fd, "%s\n", "/* DO NOT EDIT THIS FILE, IT WAS AUTOMATICALLY CREATED BY mkg3state */"); write_define(fd, "ACT_INCOMP", ACT_INCOMP, "incompletely decoded code"); write_define(fd, "ACT_INVALID", ACT_INVALID, "invalide code"); write_define(fd, "ACT_WRUNT", ACT_WRUNT, "terminating white run code"); write_define(fd, "ACT_WRUN", ACT_WRUN, "non-terminating white run code"); write_define(fd, "ACT_BRUNT", ACT_BRUNT, "terminating black run code"); write_define(fd, "ACT_BRUN", ACT_BRUN, "non-terminating black run code"); write_define(fd, "ACT_EOL", ACT_EOL, "end-of-line code"); fprintf(fd, "\n"); fprintf(fd, "/* modes that the decoder can be in */\n"); write_define(fd, "MODE_NULL", MODE_NULL, NULL); write_define(fd, "MODE_PASS", MODE_PASS, NULL); write_define(fd, "MODE_HORIZ", MODE_HORIZ, NULL); write_define(fd, "MODE_VERT_V0", MODE_VERT_V0, NULL); write_define(fd, "MODE_VERT_VR1", MODE_VERT_VR1, NULL); write_define(fd, "MODE_VERT_VR2", MODE_VERT_VR2, NULL); write_define(fd, "MODE_VERT_VR3", MODE_VERT_VR3, NULL); write_define(fd, "MODE_VERT_VL1", MODE_VERT_VL1, NULL); write_define(fd, "MODE_VERT_VL2", MODE_VERT_VL2, NULL); write_define(fd, "MODE_VERT_VL3", MODE_VERT_VL3, NULL); write_define(fd, "MODE_UNCOMP", MODE_UNCOMP, NULL); write_define(fd, "MODE_ERROR", MODE_ERROR, NULL); write_define(fd, "MODE_ERROR_1", MODE_ERROR_1, NULL); fprintf(fd, "\n"); fprintf(fd, "#define\tRUNLENGTH(ix) (TIFFFaxWhiteCodes[ix].runlen)\n"); fprintf(fd, "\n"); write_define(fd, "UNCOMP_INCOMP", UNCOMP_INCOMP, NULL); fprintf(fd, "/* runs of [0]*1 */\n"); write_define(fd, "UNCOMP_RUN0", UNCOMP_RUN0, NULL); write_define(fd, "UNCOMP_RUN1", UNCOMP_RUN1, NULL); write_define(fd, "UNCOMP_RUN2", UNCOMP_RUN2, NULL); write_define(fd, "UNCOMP_RUN3", UNCOMP_RUN3, NULL); write_define(fd, "UNCOMP_RUN4", UNCOMP_RUN4, NULL); write_define(fd, "UNCOMP_RUN5", UNCOMP_RUN5, NULL); write_define(fd, "UNCOMP_RUN6", UNCOMP_RUN6, NULL); fprintf(fd, "/* runs of [0]* w/ terminating color */\n"); write_define(fd, "UNCOMP_TRUN0", UNCOMP_TRUN0, NULL); write_define(fd, "UNCOMP_TRUN1", UNCOMP_TRUN1, NULL); write_define(fd, "UNCOMP_TRUN2", UNCOMP_TRUN2, NULL); write_define(fd, "UNCOMP_TRUN3", UNCOMP_TRUN3, NULL); write_define(fd, "UNCOMP_TRUN4", UNCOMP_TRUN4, NULL); fprintf(fd, "/* special code for unexpected EOF */\n"); write_define(fd, "UNCOMP_EOF", UNCOMP_EOF, NULL); fprintf(fd, "/* invalid code encountered */\n"); write_define(fd, "UNCOMP_INVALID", UNCOMP_INVALID, NULL); fprintf(fd, "/* codes >= terminate uncompress mode */\n"); fprintf(fd, "#define\tUNCOMP_EXIT UNCOMP_TRUN0\n"); fprintf(fd, "\n"); } void extern_table(fd, name) FILE* fd; char* name; { fprintf(fd, "extern\t%su_char %s[][256];\n", storage_class, name); } void write_tables(fd) FILE* fd; { write_preamble(fd); fprintf(fd, "#ifdef G3STATES\n"); write_null_mode_table(fd, null_mode, "TIFFFax2DMode"); write_null_mode_table(fd, null_mode_next_state, "TIFFFax2DNextState"); write_null_mode_table(fd, uncomp_mode, "TIFFFaxUncompAction"); write_null_mode_table(fd, uncomp_mode_next_state, "TIFFFaxUncompNextState"); write_horiz_mode_table(fd, horiz_mode, "TIFFFax1DAction"); write_horiz_mode_table(fd, horiz_mode_next_state, "TIFFFax1DNextState"); fprintf(fd, "#else\n"); extern_table(fd, "TIFFFax2DMode"); extern_table(fd, "TIFFFax2DNextState"); extern_table(fd, "TIFFFaxUncompAction"); extern_table(fd, "TIFFFaxUncompNextState"); extern_table(fd, "TIFFFax1DAction"); extern_table(fd, "TIFFFax1DNextState"); fprintf(fd, "#endif\n"); } short DECLARE1(find_null_mode_prefix, long, prefix) { short j1; if (prefix == 0L) return (0); for (j1 = 8; j1 < null_mode_prefix_count; j1++) if (prefix == null_mode_prefix[j1]) return (j1); if (null_mode_prefix_count == MAX_NULLPREFIX) { fprintf(stderr, "ERROR: null mode prefix table overflow\n"); exit(1); } if (verbose) fprintf(stderr, "adding null mode prefix[%d] 0x%lx\n", (int) null_mode_prefix_count, prefix); null_mode_prefix[null_mode_prefix_count++] = prefix; return (null_mode_prefix_count-1); } short DECLARE2(find_horiz_mode_prefix, long, prefix, char, color) { short j1; for (j1 = 0; j1 < horiz_mode_prefix_count; j1++) if (prefix == horiz_mode_prefix[j1] && horiz_mode_color[j1] == color) return (j1); /* * It wasn't found, so add it to the tables, but first, is there room? */ if (horiz_mode_prefix_count == MAX_HORIZPREFIX) { fprintf(stderr, "ERROR: 1D prefix table overflow\n"); exit(1); } /* OK, there's room... */ if (verbose) fprintf(stderr, "\nhoriz mode prefix %d, color %c = 0x%lx ", (int) horiz_mode_prefix_count, "WB"[color], prefix); horiz_mode_prefix[horiz_mode_prefix_count] = prefix; horiz_mode_color[horiz_mode_prefix_count] = color; horiz_mode_prefix_count++; return (horiz_mode_prefix_count - 1); } short DECLARE1(find_uncomp_mode_prefix, long, prefix) { short j1; if (prefix == 0L) return (0); for (j1 = 8; j1 < uncomp_mode_prefix_count; j1++) if (prefix == uncomp_mode_prefix[j1]) return (j1); if (uncomp_mode_prefix_count == MAX_NULLPREFIX) { fprintf(stderr, "ERROR: uncomp mode prefix table overflow\n"); exit(1); } if (verbose) fprintf(stderr, "adding uncomp mode prefix[%d] 0x%lx\n", (int) uncomp_mode_prefix_count, prefix); uncomp_mode_prefix[uncomp_mode_prefix_count++] = prefix; return (uncomp_mode_prefix_count-1); } short DECLARE1(null_mode_type, long, prefix) { switch (prefix) { case 0x18000L: return (MODE_VERT_V0); /* 1 */ case 0x36000L: return (MODE_VERT_VR1); /* 011 */ case 0x34000L: return (MODE_VERT_VL1); /* 010 */ case 0x32000L: return (MODE_HORIZ); /* 001 */ case 0x41000L: return (MODE_PASS); /* 0001 */ case 0x60C00L: return (MODE_VERT_VR2); /* 0000 11 */ case 0x60800L: return (MODE_VERT_VL2); /* 0000 10 */ case 0x70600L: return (MODE_VERT_VR3); /* 0000 011 */ case 0x70400L: return (MODE_VERT_VL3); /* 0000 010 */ case 0x80200L: return (MODE_ERROR); /* 0000 0010 */ case 0x90300L: return (MODE_ERROR); /* 0000 0011 0 */ case 0xA0380L: return (MODE_ERROR); /* 0000 0011 10 */ case 0xA03C0L: return (MODE_UNCOMP); /* 0000 0011 11 */ /* * Under the assumption that there are no * errors in the file, then this bit string * can only be the beginning of an EOL code. */ case 0x70000L: return (MODE_ERROR_1); /* 0000 000 */ } return (-1); } short DECLARE1(uncomp_mode_type, long, prefix) { short code; short len; switch (prefix) { case 0x18000L: return (UNCOMP_RUN1); /* 1 */ case 0x24000L: return (UNCOMP_RUN2); /* 01 */ case 0x32000L: return (UNCOMP_RUN3); /* 001 */ case 0x41000L: return (UNCOMP_RUN4); /* 0001 */ case 0x50800L: return (UNCOMP_RUN5); /* 0000 1 */ case 0x60400L: return (UNCOMP_RUN6); /* 0000 01 */ case 0x70200L: return (UNCOMP_TRUN0); /* 0000 001 */ case 0x80100L: return (UNCOMP_TRUN1); /* 0000 0001 */ case 0x90080L: return (UNCOMP_TRUN2); /* 0000 0000 1 */ case 0xA0040L: return (UNCOMP_TRUN3); /* 0000 0000 01 */ case 0xB0020L: return (UNCOMP_TRUN4); /* 0000 0000 001 */ } code = prefix & 0xffffL; len = (prefix >> 16) & 0xf; return ((code || len > 10) ? UNCOMP_INVALID : -1); } #define BASESTATE(b) ((unsigned char) ((b) & 0x7)) void build_null_mode_tables() { short prefix; /* * Note: the first eight entries correspond to * a null prefix and starting bit numbers 0-7. */ null_mode_prefix_count = 8; for (prefix = 0; prefix < null_mode_prefix_count; prefix++) { short byte; for (byte = 0; byte < 256; byte++) { short firstbit; short bit; long curprefix; char found_code = FALSE; if (prefix < 8) { curprefix = 0L; firstbit = prefix; } else { curprefix = null_mode_prefix[prefix]; firstbit = 0; } for (bit = firstbit; bit < 8 && !found_code; bit++) { short mode; if (bit_mask[bit] & byte) curprefix = append_1(curprefix); else curprefix = append_0(curprefix); switch (mode = null_mode_type(curprefix)) { case MODE_PASS: case MODE_HORIZ: case MODE_VERT_V0: case MODE_VERT_VR1: case MODE_VERT_VR2: case MODE_VERT_VR3: case MODE_VERT_VL1: case MODE_VERT_VL2: case MODE_VERT_VL3: case MODE_UNCOMP: case MODE_ERROR: case MODE_ERROR_1: /* * NOTE: if the bit number is 8, then the table * entry will be zero, which indicates a new byte * is to be fetched during the decoding process */ found_code = TRUE; null_mode[prefix][byte] = (unsigned char) mode; null_mode_next_state[prefix][byte] = BASESTATE(bit+1); break; } } if (!found_code) { null_mode_next_state[prefix][byte] = (unsigned char) find_null_mode_prefix(curprefix); /* * This indicates to the decoder that * no valid code has yet been identified. */ null_mode[prefix][byte] = MODE_NULL; } } } } void build_horiz_mode_tables() { unsigned short byte; short prefix; /* * The first 8 are for white, * the second 8 are for black, * beginning with bits 0-7. */ horiz_mode_prefix_count = 16; for (prefix = 0; prefix < horiz_mode_prefix_count; prefix++) for (byte = 0; byte < 256; byte++) { short bits_digested = 0; short bit; short firstbit; char color; unsigned long curprefix; if (prefix < 8) { color = WHITE; curprefix = 0L; firstbit = prefix; } else if (prefix < 16) { color = BLACK; curprefix = 0L; firstbit = prefix - 8; } else { color = horiz_mode_color[prefix]; curprefix = horiz_mode_prefix[prefix]; firstbit = 0; } for (bit = firstbit; bit < 8 && !bits_digested; bit++) { if (bit_mask[bit] & byte) curprefix = append_1(curprefix); else curprefix = append_0(curprefix); /* * The following conversion allows for arbitrary strings of * zeroes to precede the end-of-line code 0000 0000 0001. * It assumes no errors in the data, and is based on * the assumption that the code replaced (12 consecutive * zeroes) can only be "legally" encountered before the * end-of-line code. This assumption is valid only for * a Group 3 image; the combination will never occur * in horizontal mode in a proper Group 4 image. */ if (curprefix == 0xC0000L) curprefix = 0xB0000L; if (color == WHITE) { short runlength = white_run_length(curprefix); if (runlength == G3CODE_INVALID) { horiz_mode[prefix][byte] = (unsigned char) ACT_INVALID; horiz_mode_next_state[prefix][byte] = (unsigned char) bit; bits_digested = bit + 1; } else if (runlength == G3CODE_EOL) { /* Group 3 only */ horiz_mode[prefix][byte] = (unsigned char) ACT_EOL; horiz_mode_next_state[prefix][byte] = BASESTATE(bit+1); bits_digested = bit + 1; } else if (runlength != G3CODE_INCOMP) { horiz_mode[prefix][byte] = (unsigned char) horiz_mode_code_white(runlength); horiz_mode_next_state[prefix][byte] = BASESTATE(bit+1); bits_digested = bit + 1; } } else { /* color == BLACK */ short runlength = black_run_length(curprefix); if (runlength == G3CODE_INVALID) { horiz_mode[prefix][byte] = (unsigned char) ACT_INVALID; horiz_mode_next_state[prefix][byte] = (unsigned char) (bit+8); bits_digested = bit + 1; } else if (runlength == G3CODE_EOL) { /* Group 3 only */ horiz_mode[prefix][byte] = (unsigned char) ACT_EOL; horiz_mode_next_state[prefix][byte] = BASESTATE(bit+1); bits_digested = bit + 1; } else if (runlength != G3CODE_INCOMP) { horiz_mode[prefix][byte] = (unsigned char) horiz_mode_code_black(runlength); horiz_mode_next_state[prefix][byte] = BASESTATE(bit+1); bits_digested = bit + 1; } } } if (!bits_digested) { /* no codewords after examining byte */ horiz_mode[prefix][byte] = (unsigned char) ACT_INCOMP; horiz_mode_next_state[prefix][byte] = (unsigned char) find_horiz_mode_prefix(curprefix, color); } } } void build_uncomp_mode_tables() { short prefix; /* * Note: the first eight entries correspond to * a null prefix and starting bit numbers 0-7. */ uncomp_mode_prefix_count = 8; for (prefix = 0; prefix < uncomp_mode_prefix_count; prefix++) { short byte; for (byte = 0; byte < 256; byte++) { short firstbit; short bit; long curprefix; char found_code = FALSE; if (prefix < 8) { curprefix = 0L; firstbit = prefix; } else { curprefix = uncomp_mode_prefix[prefix]; firstbit = 0; } for (bit = firstbit; bit < 8 && !found_code; bit++) { short mode; if (bit_mask[bit] & byte) curprefix = append_1(curprefix); else curprefix = append_0(curprefix); mode = uncomp_mode_type(curprefix); if (mode != -1) { /* * NOTE: if the bit number is 8, then the table * entry will be zero, which indicates a new byte * is to be fetched during the decoding process */ found_code = TRUE; uncomp_mode[prefix][byte] = (unsigned char) mode; uncomp_mode_next_state[prefix][byte] = BASESTATE(bit+1); break; } } if (!found_code) { uncomp_mode_next_state[prefix][byte] = (unsigned char) find_uncomp_mode_prefix(curprefix); /* * This indicates to the decoder that * no valid code has yet been identified. */ uncomp_mode[prefix][byte] = UNCOMP_INCOMP; } } } } mode_prefix[uncomp_mode_prefix_count++] = prefix; return (uncomp_mode_prefix_count-1); } short DECLARE1(null_mode_type, long, prefix) { switch (prefix) { case 0x18000L: return (MODE_VERT_V0); /* 1 */ case 0x36000L: return (MODE_VERT_VR1); /* 011 */ case 0x34000L: return (MODE_VERT_VL1); /* 010 */ case 0x32000L: return (MODE_HORIZ); /* 001 */ case 0x41000L: return (MODE_PASS); /* 0001 */ case 0x60C00L: return (MODE_VERT_VR2); /* 0000 11 */ case 0x60800L: rxloadimage.4.1/tiff/mkspans.c 664 221 144 2054 5461577443 11330 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/mkspans.c,v 1.4 90/10/08 17:17:29 sam Exp $"; #endif #include "tiffcompat.h" /* * Hack program to construct tables used to find * runs of zeros and ones in Group 3 Fax encoding. */ dumparray(name, runs) char *name; unsigned char runs[256]; { register int i; register char *sep; printf("static u_char %s[256] = {\n", name); sep = " "; for (i = 0; i < 256; i++) { printf("%s%d", sep, runs[i]); if (((i + 1) % 16) == 0) { printf(", /* 0x%02x - 0x%02x */\n", i-15, i); sep = " "; } else sep = ", "; } printf("\n};\n"); } main() { unsigned char runs[2][256]; bzero(runs[0], 256*sizeof (char)); bzero(runs[1], 256*sizeof (char)); { register int run, runlen, i; runlen = 1; for (run = 0x80; run != 0xff; run = (run>>1)|0x80) { for (i = run-1; i >= 0; i--) { runs[1][run|i] = runlen; runs[0][(~(run|i)) & 0xff] = runlen; } runlen++; } runs[1][0xff] = runs[0][0] = 8; } dumparray("bruns", runs[0]); dumparray("wruns", runs[1]); } firstbit = prefix - 8; } else { color = horiz_mode_color[prefix]; curprefix = horiz_mode_prefix[prefix]; firstbit = 0; } for (bit = firstbit; bit < 8 && !bits_digested; bit++) { if (bit_mask[bit] & byte) curprefix = append_1(curprefix); else curprefix = append_0(curprefix); /* * The following conversion allows for arbitrary strings of * zeroes to precede the end-of-line code 0000 0000 0001. * It assumes no errors inxloadimage.4.1/tiff/out 664 221 144 23675 5461577443 10276 # 1 "tif_machdep.c" static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_machdep.c,v 1.2 92/03/06 11:52:42 sam Exp $"; # 1 "./tiffioP.h" # 1 "./tiffcompat.h" # 1 "/usr/include/sys/types.h" # 1 "/usr/include/ansi_compat.h" # 125 "/usr/include/ansi_compat.h" # 80 "/usr/include/sys/types.h" typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned int uint; typedef unsigned long u_long; typedef unsigned short ushort; typedef volatile char v_char; typedef volatile short v_short; typedef volatile long v_long; typedef volatile unsigned char vu_char; typedef volatile unsigned short vu_short; typedef volatile unsigned long vu_long; typedef signed char s_char; typedef struct _physadr { int r[1]; } *physadr; typedef struct label_t { int val[12]; } label_t; typedef struct _quad { long val[2]; } quad; typedef long daddr_t; typedef char * caddr_t; typedef u_long gno_t; typedef short cnt_t; typedef long swblk_t; typedef long paddr_t; typedef long audit_ID_t; typedef short dev_t; typedef short gid_t; typedef unsigned long ino_t; typedef unsigned short mode_t; typedef short nlink_t; typedef int off_t; typedef int pid_t; typedef short uid_t; typedef int time_t; typedef unsigned int size_t; typedef int clock_t; typedef long key_t; typedef long fd_mask; typedef struct fd_set { fd_mask fds_bits[(((4096 )+(( (sizeof(fd_mask) * 8 ) )-1))/( (sizeof(fd_mask) * 8 ) ))]; } fd_set; # 58 "./tiffcompat.h" # 1 "/usr/include/fcntl.h" # 1 "/usr/include/sys/file.h" # 1 "/usr/include/ansi_compat.h" # 125 "/usr/include/ansi_compat.h" # 135 "/usr/include/sys/file.h" # 1 "/usr/include/sys/types.h" # 215 "/usr/include/sys/types.h" # 140 "/usr/include/sys/file.h" struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; int l_pid; }; int creat(), fcntl(), open(); # 42 "/usr/include/fcntl.h" # 64 "./tiffcompat.h" extern long TIFFGetFileSize(); extern long lseek(); extern char *malloc(); extern char *realloc(); typedef double dblparam_t; # 1 "/usr/include/varargs.h" # 1 "/usr/include/ansi_compat.h" # 125 "/usr/include/ansi_compat.h" # 3 "/usr/include/varargs.h" typedef char *va_list; # 1 "/usr/include/stamp.h" # 51 "/usr/include/varargs.h" # 210 "./tiffcompat.h" # 33 "./tiffioP.h" # 1 "./tiff.h" typedef struct { unsigned short tiff_magic; unsigned short tiff_version; unsigned long tiff_diroff; } TIFFHeader; typedef struct { unsigned short tdir_tag; unsigned short tdir_type; unsigned long tdir_count; unsigned long tdir_offset; } TIFFDirEntry; typedef enum { TIFF_NOTYPE = 0, TIFF_BYTE = 1, TIFF_ASCII = 2, TIFF_SHORT = 3, TIFF_LONG = 4, TIFF_RATIONAL = 5, TIFF_SBYTE = 6, TIFF_UNDEFINED = 7, TIFF_SSHORT = 8, TIFF_SLONG = 9, TIFF_SRATIONAL = 10, TIFF_FLOAT = 11, TIFF_DOUBLE = 12 } TIFFDataType; # 34 "./tiffioP.h" typedef struct { u_long td_fieldsset[2]; u_long td_imagewidth, td_imagelength, td_imagedepth; u_long td_tilewidth, td_tilelength, td_tiledepth; u_short td_subfiletype; u_short td_bitspersample; u_short td_sampleformat; u_short td_compression; u_short td_photometric; u_short td_threshholding; u_short td_fillorder; u_short td_orientation; u_short td_samplesperpixel; u_short td_predictor; u_long td_rowsperstrip; u_long td_minsamplevalue, td_maxsamplevalue; float td_xresolution, td_yresolution; u_short td_resolutionunit; u_short td_planarconfig; float td_xposition, td_yposition; u_long td_group3options; u_long td_group4options; u_short td_pagenumber[2]; u_short td_matteing; u_short td_cleanfaxdata; u_short td_badfaxrun; u_long td_badfaxlines; u_short *td_colormap[3]; u_short td_halftonehints[2]; char *td_documentname; char *td_artist; char *td_datetime; char *td_hostcomputer; char *td_imagedescription; char *td_make; char *td_model; char *td_software; char *td_pagename; u_long td_stripsperimage; u_long td_nstrips; u_long *td_stripoffset; u_long *td_stripbytecount; float *td_ycbcrcoeffs; u_short td_ycbcrsubsampling[2]; u_short td_ycbcrpositioning; float *td_whitepoint; float *td_primarychromas; float *td_refblackwhite; u_short *td_transferfunction[4]; } TIFFDirectory; typedef struct { u_short field_tag; short field_readcount; short field_writecount; TIFFDataType field_type; u_short field_bit; u_short field_oktochange; char *field_name; } TIFFFieldInfo; extern TIFFFieldInfo tiffFieldInfo[]; extern int tiffDataWidth[]; struct tiff { char *tif_name; short tif_fd; short tif_mode; char tif_fillorder; char tif_options; short tif_flags; long tif_diroff; long tif_nextdiroff; TIFFDirectory tif_dir; TIFFHeader tif_header; int *tif_typeshift; long *tif_typemask; long tif_row; int tif_curdir; int tif_curstrip; long tif_curoff; long tif_col; int tif_curtile; long tif_tilesize; int (*tif_predecode)(); int (*tif_preencode)(); int (*tif_postencode)(); int (*tif_decoderow)(); int (*tif_encoderow)(); int (*tif_decodestrip)(); int (*tif_encodestrip)(); int (*tif_decodetile)(); int (*tif_encodetile)(); int (*tif_close)(); int (*tif_seek)(); int (*tif_cleanup)(); char *tif_data; int tif_scanlinesize; int tif_scanlineskew; char *tif_rawdata; long tif_rawdatasize; char *tif_rawcp; long tif_rawcc; }; # 1 "./tiffio.h" # 1 "./tiff.h" # 253 "./tiff.h" # 34 "./tiffio.h" typedef struct tiff TIFF; extern char TIFFVersion[]; extern unsigned char TIFFBitRevTable[256]; extern unsigned char TIFFNoBitRevTable[256]; # 158 "./tiffio.h" typedef void (*TIFFErrorHandler)(); extern void TIFFClose(); extern TIFF *TIFFOpen(); extern TIFF *TIFFFdOpen(); extern char* TIFFFileName(); extern int TIFFFileno(); extern int TIFFGetMode(); extern int TIFFIsTiled(); extern unsigned int TIFFComputeTile(); extern long TIFFCurrentRow(); extern int TIFFCurrentDirectory(); extern int TIFFCurrentStrip(); extern int TIFFCurrentTile(); extern void TIFFError(); extern TIFFErrorHandler TIFFSetErrorHandler(); extern int TIFFFlush(); extern int TIFFFlushData(); extern int TIFFGetField(); extern int TIFFVGetField(); extern int TIFFGetFieldDefaulted(); extern int TIFFVGetFieldDefaulted(); extern unsigned int TIFFNumberOfTiles(); extern void TIFFPrintDirectory(); extern int TIFFReadDirectory(); extern int TIFFReadBufferSetup(); extern int TIFFReadScanline(); extern int TIFFReadTile(); extern unsigned int TIFFComputeStrip(); extern unsigned int TIFFNumberOfStrips(); extern int TIFFReadEncodedStrip(); extern int TIFFReadRawStrip(); extern int TIFFReadEncodedTile(); extern int TIFFReadRGBAImage(); extern int TIFFReadRawTile(); extern int TIFFScanlineSize(); extern unsigned long TIFFStripSize(); extern unsigned long TIFFVStripSize(); extern unsigned long TIFFTileRowSize(); extern unsigned long TIFFTileSize(); extern unsigned long TIFFVTileSize(); extern int TIFFSetDirectory(); extern int TIFFSetField(); extern int TIFFVSetField(); extern void TIFFWarning(); extern TIFFErrorHandler TIFFSetWarningHandler(); extern int TIFFWriteDirectory(); extern int TIFFWriteScanline(); extern int TIFFWriteEncodedStrip(); extern int TIFFWriteRawStrip(); extern int TIFFWriteEncodedTile(); extern int TIFFWriteRawTile(); extern int TIFFSwabShort(); extern int TIFFSwabLong(); extern int TIFFSwabArrayOfShort(); extern int TIFFSwabArrayOfLong(); extern int TIFFReverseBits(); extern int TIFFCheckTile(); # 297 "./tiffioP.h" extern TIFFFieldInfo *TIFFFindFieldInfo(); extern TIFFFieldInfo *TIFFFieldWithTag(); extern int _TIFFgetfield(); extern int TIFFNoRowEncode(); extern int TIFFNoStripEncode(); extern int TIFFNoTileEncode(); extern int TIFFNoRowDecode(); extern int TIFFNoStripDecode(); extern int TIFFNoTileDecode(); # 33 "tif_machdep.c" # 77 "tif_machdep.c" # 138 "tif_machdep.c" "Help, you've configured the library to not have IEEE floating point,but not defined how to convert between IEEE and native formats!" typedef union { ieeedouble ieee; nativedouble native; char b[8]; double d; } double_t; typedef union { ieeefloat ieee; nativefloat native; char b[4]; float f; } float_t; TIFFCvtIEEEFloatToNative(tif, n, f) TIFF *tif; u_int n; float *f; { float_t *fp = (float_t *)f; while (n-- > 0) { IEEEFLOAT2NATIVE(fp); fp++; } } TIFFCvtNativeToIEEEFloat(tif, n, f) TIFF *tif; u_int n; float *f; { float_t *fp = (float_t *)f; while (n-- > 0) { NATIVE2IEEEFLOAT(fp); fp++; } } xloadimage.4.1/tiff/prototypes.h 664 221 144 5275 5461577444 12122 /* $Header: /d/sam/tiff/libtiff/RCS/prototypes.h,v 1.8 92/02/18 18:20:08 sam Exp $ */ /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #if USE_PROTOTYPES #define DECLARE1(f,t1,a1) f(t1 a1) #define DECLARE2(f,t1,a1,t2,a2) f(t1 a1, t2 a2) #define DECLARE3(f,t1,a1,t2,a2,t3,a3) f(t1 a1, t2 a2, t3 a3) #define DECLARE4(f,t1,a1,t2,a2,t3,a3,t4,a4)\ f(t1 a1, t2 a2, t3 a3, t4 a4) #define DECLARE5(f,t1,a1,t2,a2,t3,a3,t4,a4,t5,a5)\ f(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) #define DECLARE6(f,t1,a1,t2,a2,t3,a3,t4,a4,t5,a5,t6,a6)\ f(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) #define DECLARE1V(f,t1,a1) f(t1 a1 ...) #define DECLARE2V(f,t1,a1,t2,a2) f(t1 a1, t2 a2, ...) #define DECLARE3V(f,t1,a1,t2,a2,t3,a3) f(t1 a1, t2 a2, t3 a3, ...) #else #define DECLARE1(f,t1,a1) f(a1) t1 a1; #define DECLARE2(f,t1,a1,t2,a2) f(a1,a2) t1 a1; t2 a2; #define DECLARE3(f,t1,a1,t2,a2,t3,a3) f(a1, a2, a3) t1 a1; t2 a2; t3 a3; #define DECLARE4(f,t1,a1,t2,a2,t3,a3,t4,a4) \ f(a1, a2, a3, a4) t1 a1; t2 a2; t3 a3; t4 a4; #define DECLARE5(f,t1,a1,t2,a2,t3,a3,t4,a4,t5,a5)\ f(a1, a2, a3, a4, a5) t1 a1; t2 a2; t3 a3; t4 a4; t5 a5; #define DECLARE6(f,t1,a1,t2,a2,t3,a3,t4,a4,t5,a5,t6,a6)\ f(a1, a2, a3, a4, a5, a6) t1 a1; t2 a2; t3 a3; t4 a4; t5 a5; t6 a6; #if USE_VARARGS #define DECLARE1V(f,t1,a1) \ f(a1, va_alist) t1 a1; va_dcl #define DECLARE2V(f,t1,a1,t2,a2) \ f(a1, a2, va_alist) t1 a1; t2 a2; va_dcl #define DECLARE3V(f,t1,a1,t2,a2,t3,a3) \ f(a1, a2, a3, va_alist) t1 a1; t2 a2; t3 a3; va_dcl #else "Help, I don't know how to handle this case: !USE_PROTOTYPES and !USE_VARARGS?" #endif #endif extern long lseek(); extern char *malloc(); extern char *realloc(); typedef double dblparam_t; # 1 "/usr/include/varargs.h" # 1 "/usr/include/ansi_compat.h" # 125 "/usr/include/ansi_compat.h" # 3 "/usr/inxloadimage.4.1/tiff/t4.h 664 221 144 26536 5461577444 10244 /* $Header: /usr/people/sam/tiff/libtiff/RCS/t4.h,v 1.9 92/02/10 19:06:22 sam Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _T4_ #define _T4_ /* * CCITT T.4 1D Huffman runlength codes and * related definitions. Given the small sizes * of these tables it might does not seem * worthwhile to make code & length 8 bits. */ typedef struct tableentry { unsigned short length; /* bit length of g3 code */ unsigned short code; /* g3 code */ short runlen; /* run length in bits */ } tableentry; #define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */ /* status values returned instead of a run length */ #define G3CODE_INVALID -1 #define G3CODE_INCOMP -2 #define G3CODE_EOL -3 #define G3CODE_EOF -4 /* * Note that these tables are ordered such that the * index into the table is known to be either the * run length, or (run length / 64) + a fixed offset. * * NB: The G3CODE_INVALID entries are only used * during state generation (see mkg3states.c). */ #ifdef G3CODES #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST const tableentry TIFFFaxWhiteCodes[] = { #else tableentry TIFFFaxWhiteCodes[] = { #endif { 8, 0x35, 0 }, /* 0011 0101 */ { 6, 0x7, 1 }, /* 0001 11 */ { 4, 0x7, 2 }, /* 0111 */ { 4, 0x8, 3 }, /* 1000 */ { 4, 0xB, 4 }, /* 1011 */ { 4, 0xC, 5 }, /* 1100 */ { 4, 0xE, 6 }, /* 1110 */ { 4, 0xF, 7 }, /* 1111 */ { 5, 0x13, 8 }, /* 1001 1 */ { 5, 0x14, 9 }, /* 1010 0 */ { 5, 0x7, 10 }, /* 0011 1 */ { 5, 0x8, 11 }, /* 0100 0 */ { 6, 0x8, 12 }, /* 0010 00 */ { 6, 0x3, 13 }, /* 0000 11 */ { 6, 0x34, 14 }, /* 1101 00 */ { 6, 0x35, 15 }, /* 1101 01 */ { 6, 0x2A, 16 }, /* 1010 10 */ { 6, 0x2B, 17 }, /* 1010 11 */ { 7, 0x27, 18 }, /* 0100 111 */ { 7, 0xC, 19 }, /* 0001 100 */ { 7, 0x8, 20 }, /* 0001 000 */ { 7, 0x17, 21 }, /* 0010 111 */ { 7, 0x3, 22 }, /* 0000 011 */ { 7, 0x4, 23 }, /* 0000 100 */ { 7, 0x28, 24 }, /* 0101 000 */ { 7, 0x2B, 25 }, /* 0101 011 */ { 7, 0x13, 26 }, /* 0010 011 */ { 7, 0x24, 27 }, /* 0100 100 */ { 7, 0x18, 28 }, /* 0011 000 */ { 8, 0x2, 29 }, /* 0000 0010 */ { 8, 0x3, 30 }, /* 0000 0011 */ { 8, 0x1A, 31 }, /* 0001 1010 */ { 8, 0x1B, 32 }, /* 0001 1011 */ { 8, 0x12, 33 }, /* 0001 0010 */ { 8, 0x13, 34 }, /* 0001 0011 */ { 8, 0x14, 35 }, /* 0001 0100 */ { 8, 0x15, 36 }, /* 0001 0101 */ { 8, 0x16, 37 }, /* 0001 0110 */ { 8, 0x17, 38 }, /* 0001 0111 */ { 8, 0x28, 39 }, /* 0010 1000 */ { 8, 0x29, 40 }, /* 0010 1001 */ { 8, 0x2A, 41 }, /* 0010 1010 */ { 8, 0x2B, 42 }, /* 0010 1011 */ { 8, 0x2C, 43 }, /* 0010 1100 */ { 8, 0x2D, 44 }, /* 0010 1101 */ { 8, 0x4, 45 }, /* 0000 0100 */ { 8, 0x5, 46 }, /* 0000 0101 */ { 8, 0xA, 47 }, /* 0000 1010 */ { 8, 0xB, 48 }, /* 0000 1011 */ { 8, 0x52, 49 }, /* 0101 0010 */ { 8, 0x53, 50 }, /* 0101 0011 */ { 8, 0x54, 51 }, /* 0101 0100 */ { 8, 0x55, 52 }, /* 0101 0101 */ { 8, 0x24, 53 }, /* 0010 0100 */ { 8, 0x25, 54 }, /* 0010 0101 */ { 8, 0x58, 55 }, /* 0101 1000 */ { 8, 0x59, 56 }, /* 0101 1001 */ { 8, 0x5A, 57 }, /* 0101 1010 */ { 8, 0x5B, 58 }, /* 0101 1011 */ { 8, 0x4A, 59 }, /* 0100 1010 */ { 8, 0x4B, 60 }, /* 0100 1011 */ { 8, 0x32, 61 }, /* 0011 0010 */ { 8, 0x33, 62 }, /* 0011 0011 */ { 8, 0x34, 63 }, /* 0011 0100 */ { 5, 0x1B, 64 }, /* 1101 1 */ { 5, 0x12, 128 }, /* 1001 0 */ { 6, 0x17, 192 }, /* 0101 11 */ { 7, 0x37, 256 }, /* 0110 111 */ { 8, 0x36, 320 }, /* 0011 0110 */ { 8, 0x37, 384 }, /* 0011 0111 */ { 8, 0x64, 448 }, /* 0110 0100 */ { 8, 0x65, 512 }, /* 0110 0101 */ { 8, 0x68, 576 }, /* 0110 1000 */ { 8, 0x67, 640 }, /* 0110 0111 */ { 9, 0xCC, 704 }, /* 0110 0110 0 */ { 9, 0xCD, 768 }, /* 0110 0110 1 */ { 9, 0xD2, 832 }, /* 0110 1001 0 */ { 9, 0xD3, 896 }, /* 0110 1001 1 */ { 9, 0xD4, 960 }, /* 0110 1010 0 */ { 9, 0xD5, 1024 }, /* 0110 1010 1 */ { 9, 0xD6, 1088 }, /* 0110 1011 0 */ { 9, 0xD7, 1152 }, /* 0110 1011 1 */ { 9, 0xD8, 1216 }, /* 0110 1100 0 */ { 9, 0xD9, 1280 }, /* 0110 1100 1 */ { 9, 0xDA, 1344 }, /* 0110 1101 0 */ { 9, 0xDB, 1408 }, /* 0110 1101 1 */ { 9, 0x98, 1472 }, /* 0100 1100 0 */ { 9, 0x99, 1536 }, /* 0100 1100 1 */ { 9, 0x9A, 1600 }, /* 0100 1101 0 */ { 6, 0x18, 1664 }, /* 0110 00 */ { 9, 0x9B, 1728 }, /* 0100 1101 1 */ { 11, 0x8, 1792 }, /* 0000 0001 000 */ { 11, 0xC, 1856 }, /* 0000 0001 100 */ { 11, 0xD, 1920 }, /* 0000 0001 101 */ { 12, 0x12, 1984 }, /* 0000 0001 0010 */ { 12, 0x13, 2048 }, /* 0000 0001 0011 */ { 12, 0x14, 2112 }, /* 0000 0001 0100 */ { 12, 0x15, 2176 }, /* 0000 0001 0101 */ { 12, 0x16, 2240 }, /* 0000 0001 0110 */ { 12, 0x17, 2304 }, /* 0000 0001 0111 */ { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ }; #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST const tableentry TIFFFaxBlackCodes[] = { #else tableentry TIFFFaxBlackCodes[] = { #endif { 10, 0x37, 0 }, /* 0000 1101 11 */ { 3, 0x2, 1 }, /* 010 */ { 2, 0x3, 2 }, /* 11 */ { 2, 0x2, 3 }, /* 10 */ { 3, 0x3, 4 }, /* 011 */ { 4, 0x3, 5 }, /* 0011 */ { 4, 0x2, 6 }, /* 0010 */ { 5, 0x3, 7 }, /* 0001 1 */ { 6, 0x5, 8 }, /* 0001 01 */ { 6, 0x4, 9 }, /* 0001 00 */ { 7, 0x4, 10 }, /* 0000 100 */ { 7, 0x5, 11 }, /* 0000 101 */ { 7, 0x7, 12 }, /* 0000 111 */ { 8, 0x4, 13 }, /* 0000 0100 */ { 8, 0x7, 14 }, /* 0000 0111 */ { 9, 0x18, 15 }, /* 0000 1100 0 */ { 10, 0x17, 16 }, /* 0000 0101 11 */ { 10, 0x18, 17 }, /* 0000 0110 00 */ { 10, 0x8, 18 }, /* 0000 0010 00 */ { 11, 0x67, 19 }, /* 0000 1100 111 */ { 11, 0x68, 20 }, /* 0000 1101 000 */ { 11, 0x6C, 21 }, /* 0000 1101 100 */ { 11, 0x37, 22 }, /* 0000 0110 111 */ { 11, 0x28, 23 }, /* 0000 0101 000 */ { 11, 0x17, 24 }, /* 0000 0010 111 */ { 11, 0x18, 25 }, /* 0000 0011 000 */ { 12, 0xCA, 26 }, /* 0000 1100 1010 */ { 12, 0xCB, 27 }, /* 0000 1100 1011 */ { 12, 0xCC, 28 }, /* 0000 1100 1100 */ { 12, 0xCD, 29 }, /* 0000 1100 1101 */ { 12, 0x68, 30 }, /* 0000 0110 1000 */ { 12, 0x69, 31 }, /* 0000 0110 1001 */ { 12, 0x6A, 32 }, /* 0000 0110 1010 */ { 12, 0x6B, 33 }, /* 0000 0110 1011 */ { 12, 0xD2, 34 }, /* 0000 1101 0010 */ { 12, 0xD3, 35 }, /* 0000 1101 0011 */ { 12, 0xD4, 36 }, /* 0000 1101 0100 */ { 12, 0xD5, 37 }, /* 0000 1101 0101 */ { 12, 0xD6, 38 }, /* 0000 1101 0110 */ { 12, 0xD7, 39 }, /* 0000 1101 0111 */ { 12, 0x6C, 40 }, /* 0000 0110 1100 */ { 12, 0x6D, 41 }, /* 0000 0110 1101 */ { 12, 0xDA, 42 }, /* 0000 1101 1010 */ { 12, 0xDB, 43 }, /* 0000 1101 1011 */ { 12, 0x54, 44 }, /* 0000 0101 0100 */ { 12, 0x55, 45 }, /* 0000 0101 0101 */ { 12, 0x56, 46 }, /* 0000 0101 0110 */ { 12, 0x57, 47 }, /* 0000 0101 0111 */ { 12, 0x64, 48 }, /* 0000 0110 0100 */ { 12, 0x65, 49 }, /* 0000 0110 0101 */ { 12, 0x52, 50 }, /* 0000 0101 0010 */ { 12, 0x53, 51 }, /* 0000 0101 0011 */ { 12, 0x24, 52 }, /* 0000 0010 0100 */ { 12, 0x37, 53 }, /* 0000 0011 0111 */ { 12, 0x38, 54 }, /* 0000 0011 1000 */ { 12, 0x27, 55 }, /* 0000 0010 0111 */ { 12, 0x28, 56 }, /* 0000 0010 1000 */ { 12, 0x58, 57 }, /* 0000 0101 1000 */ { 12, 0x59, 58 }, /* 0000 0101 1001 */ { 12, 0x2B, 59 }, /* 0000 0010 1011 */ { 12, 0x2C, 60 }, /* 0000 0010 1100 */ { 12, 0x5A, 61 }, /* 0000 0101 1010 */ { 12, 0x66, 62 }, /* 0000 0110 0110 */ { 12, 0x67, 63 }, /* 0000 0110 0111 */ { 10, 0xF, 64 }, /* 0000 0011 11 */ { 12, 0xC8, 128 }, /* 0000 1100 1000 */ { 12, 0xC9, 192 }, /* 0000 1100 1001 */ { 12, 0x5B, 256 }, /* 0000 0101 1011 */ { 12, 0x33, 320 }, /* 0000 0011 0011 */ { 12, 0x34, 384 }, /* 0000 0011 0100 */ { 12, 0x35, 448 }, /* 0000 0011 0101 */ { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ { 11, 0x8, 1792 }, /* 0000 0001 000 */ { 11, 0xC, 1856 }, /* 0000 0001 100 */ { 11, 0xD, 1920 }, /* 0000 0001 101 */ { 12, 0x12, 1984 }, /* 0000 0001 0010 */ { 12, 0x13, 2048 }, /* 0000 0001 0011 */ { 12, 0x14, 2112 }, /* 0000 0001 0100 */ { 12, 0x15, 2176 }, /* 0000 0001 0101 */ { 12, 0x16, 2240 }, /* 0000 0001 0110 */ { 12, 0x17, 2304 }, /* 0000 0001 0111 */ { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ }; #else #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST extern const tableentry TIFFFaxWhiteCodes[]; extern const tableentry TIFFFaxBlackCodes[]; #else extern tableentry TIFFFaxWhiteCodes[]; extern tableentry TIFFFaxBlackCodes[]; #endif /* !__STDC__ */ #endif #endif /* _T4_ */ }, /* 0001 1010 */ { 8, 0x1B, 32 }, /* 0001 1011 */ { 8, 0x12, 33 }, /* 0001 0010 */ { 8, 0x13, 34 }, /* 0001 0011 */ { 8, 0x14, 35 }, /* 0001 01xloadimage.4.1/tiff/tif_aux.c 664 221 144 12573 5461577444 11343 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_aux.c,v 1.8 92/03/27 14:53:02 sam Exp $"; #endif /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Auxiliary Support Routines. */ #include "tiffioP.h" #include "prototypes.h" /* * Like TIFFGetField, but return any default * value if the tag is not present in the directory. * * NB: We use the value in the directory, rather than * explcit values so that defaults exist only one * place in the library -- in TIFFDefaultDirectory. */ TIFFVGetFieldDefaulted(tif, tag, ap) TIFF *tif; int tag; va_list ap; { TIFFDirectory *td = &tif->tif_dir; int i; if (TIFFVGetField(tif, tag, ap)) return (1); switch (tag) { case TIFFTAG_SUBFILETYPE: *va_arg(ap, u_short *) = td->td_subfiletype; return (1); case TIFFTAG_BITSPERSAMPLE: *va_arg(ap, u_short *) = td->td_bitspersample; return (1); case TIFFTAG_THRESHHOLDING: *va_arg(ap, u_short *) = td->td_threshholding; return (1); case TIFFTAG_FILLORDER: *va_arg(ap, u_short *) = td->td_fillorder; return (1); case TIFFTAG_ORIENTATION: *va_arg(ap, u_short *) = td->td_orientation; return (1); case TIFFTAG_SAMPLESPERPIXEL: *va_arg(ap, u_short *) = td->td_samplesperpixel; return (1); case TIFFTAG_ROWSPERSTRIP: *va_arg(ap, u_long *) = td->td_rowsperstrip; return (1); case TIFFTAG_MINSAMPLEVALUE: *va_arg(ap, u_short *) = td->td_minsamplevalue; return (1); case TIFFTAG_MAXSAMPLEVALUE: *va_arg(ap, u_short *) = td->td_maxsamplevalue; return (1); case TIFFTAG_PLANARCONFIG: *va_arg(ap, u_short *) = td->td_planarconfig; return (1); case TIFFTAG_GROUP4OPTIONS: *va_arg(ap, u_long *) = td->td_group4options; return (1); case TIFFTAG_RESOLUTIONUNIT: *va_arg(ap, u_short *) = td->td_resolutionunit; return (1); case TIFFTAG_PREDICTOR: *va_arg(ap, u_short *) = td->td_predictor; return (1); #ifdef CMYK_SUPPORT case TIFFTAG_DOTRANGE: *va_arg(ap, u_short *) = 0; *va_arg(ap, u_short *) = (1<td_bitspersample)-1; return (1); case TIFFTAG_INKSET: *va_arg(ap, u_short *) = td->td_inkset; return (1); #endif case TIFFTAG_TILEDEPTH: *va_arg(ap, u_long *) = td->td_tiledepth; return (1); case TIFFTAG_DATATYPE: *va_arg(ap, u_short *) = td->td_sampleformat-1; return (1); case TIFFTAG_IMAGEDEPTH: *va_arg(ap, u_short *) = td->td_imagedepth; return (1); #ifdef YCBCR_SUPPORT case TIFFTAG_YCBCRCOEFFICIENTS: if (!td->td_ycbcrcoeffs) { td->td_ycbcrcoeffs = (float *)malloc(3*sizeof (float)); /* defaults are from CCIR Recommendation 601-1 */ td->td_ycbcrcoeffs[0] = .299; td->td_ycbcrcoeffs[1] = .587; td->td_ycbcrcoeffs[2] = .114; } *va_arg(ap, float **) = td->td_ycbcrcoeffs; return (1); case TIFFTAG_YCBCRSUBSAMPLING: *va_arg(ap, u_short *) = td->td_ycbcrsubsampling[0]; *va_arg(ap, u_short *) = td->td_ycbcrsubsampling[1]; return (1); case TIFFTAG_YCBCRPOSITIONING: *va_arg(ap, u_short *) = td->td_ycbcrpositioning; return (1); #endif #ifdef COLORIMETRY_SUPPORT case TIFFTAG_TRANSFERFUNCTION: if (!td->td_transferfunction[0]) { u_short **tf = td->td_transferfunction; int n = 1<td_bitspersample; tf[0] = (u_short *)malloc(n * sizeof (u_short)); tf[0][0] = 0; for (i = 1; i < n; i++) tf[0][i] = (u_short) floor(65535.*pow(i/(n-1.), 2.2) + .5); for (i = 1; i < td->td_samplesperpixel; i++) { tf[i] = (u_short *)malloc(n * sizeof (u_short)); bcopy(tf[0], tf[i], n * sizeof (u_short)); } } for (i = 0; i < td->td_samplesperpixel; i++) *va_arg(ap, u_short **) = td->td_transferfunction[i]; return (1); case TIFFTAG_REFERENCEBLACKWHITE: if (!td->td_refblackwhite) { td->td_refblackwhite = (float *) malloc(2*td->td_samplesperpixel * sizeof (float)); for (i = 0; i < td->td_samplesperpixel; i++) { td->td_refblackwhite[2*i+0] = 0; td->td_refblackwhite[2*i+1] = 1L<td_bitspersample; } } *va_arg(ap, float **) = td->td_refblackwhite; return (1); #endif } return (0); } /* * Like TIFFGetField, but return any default * value if the tag is not present in the directory. */ /*VARARGS2*/ DECLARE2V(TIFFGetFieldDefaulted, TIFF*, tif, int, tag) { int ok; va_list ap; VA_START(ap, tag); ok = TIFFVGetFieldDefaulted(tif, tag, ap); va_end(ap); return (ok); } 7 }, /* 0000 1100 1011 */ { 12, 0xCC, 28 }, /* 0000 1100 1100 */ { 12, 0xCD, 29 }, /* 0000 1100 1101 */ { 12, 0x68, 30 },xloadimage.4.1/tiff/tif_ccittrle.c 664 221 144 5102 5461577444 12325 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_ccittrle.c,v 1.14 92/02/10 19:06:10 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * CCITT Group 3 1-D Modified Huffman * Run Length Encoding Compression Support */ #include "tiffioP.h" #include "tif_fax3.h" TIFFInitCCITTRLE(tif) TIFF *tif; { TIFFInitCCITTFax3(tif); /* reuse G3 compression */ tif->tif_preencode = NULL; tif->tif_postencode = NULL; tif->tif_encoderow = TIFFNoRowEncode; tif->tif_encodestrip = TIFFNoStripEncode; tif->tif_encodetile = TIFFNoTileEncode; tif->tif_close = NULL; /* * This magic causes the regular G3 decompression * code to not skip to the EOL mark at the end of * a row, and to flush input data to a byte boundary * at the end of each row. */ tif->tif_options |= FAX3_NOEOL|FAX3_BYTEALIGN; return (1); } TIFFInitCCITTRLEW(tif) TIFF *tif; { TIFFInitCCITTFax3(tif); /* reuse G3 compression */ tif->tif_preencode = NULL; tif->tif_postencode = NULL; tif->tif_encoderow = TIFFNoRowEncode; tif->tif_encodestrip = TIFFNoStripEncode; tif->tif_encodetile = TIFFNoTileEncode; tif->tif_close = NULL; /* * This magic causes the regular G3 decompression * code to not skip to the EOL mark at the end of * a row, and to flush input data to a byte boundary * at the end of each row. */ tif->tif_options |= FAX3_NOEOL|FAX3_WORDALIGN; return (1); } g(ap, u_short *) = td->td_planarconfig; return (1); case TIFFTAG_GROUP4OPTIONS: *va_arg(ap, u_long *) = td->td_group4options; return (1); case TIFFTAG_RESOLUTIONUNIT: *va_arg(ap, u_short *) = td->td_resolutionunit; return (1); case TIFFTAG_PREDICTOR: *va_arg(ap, u_short *) = td->td_predictor; return (1); #ifdef CMYK_SUPPORT case TIFFTAG_DOTRANGE: *va_arg(ap, u_short *) = 0; *va_arg(ap, u_short *) = (1<td_bitspersampxloadimage.4.1/tiff/tif_close.c 664 221 144 3670 5461577444 11631 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_close.c,v 1.17 92/02/10 19:06:30 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. */ #include "tiffioP.h" #if USE_PROTOTYPES extern int TIFFFreeDirectory(TIFF*); #else extern int TIFFFreeDirectory(); #endif void TIFFClose(tif) TIFF *tif; { if (tif->tif_mode != O_RDONLY) /* * Flush buffered data and directory (if dirty). */ TIFFFlush(tif); if (tif->tif_cleanup) (*tif->tif_cleanup)(tif); TIFFFreeDirectory(tif); if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) free(tif->tif_rawdata); #ifdef MMAP_SUPPORT if (isMapped(tif)) TIFFUnmapFileContents(tif->tif_base, tif->tif_size); #endif (void) close(tif->tif_fd); free((char *)tif); } *tif; { TIFFInitCCITTFax3(tif); /* reuse G3 compression */ tif->tif_xloadimage.4.1/tiff/tif_compat.c 664 221 144 13505 5461577444 12025 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_compat.c,v 1.15 92/03/11 09:16:49 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library Compatibility Routines. */ #include "tiffioP.h" #if defined(unix) || defined(__unix) || defined(MSDOS) || defined(VMS) #include long TIFFGetFileSize(fd) int fd; { struct stat sb; return (fstat(fd, &sb) < 0 ? 0 : sb.st_size); } #endif #if (defined(unix) || defined(__unix)) && defined(MMAP_SUPPORT) #include int TIFFMapFileContents(fd, pbase, psize) int fd; char **pbase; long *psize; { long size = TIFFGetFileSize(fd); if (size != -1) { *pbase = (char *) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); if (*pbase != (char *)-1) { *psize = size; return (1); } } return (0); } void TIFFUnmapFileContents(base, size) char *base; long size; { (void) munmap(base, size); } #endif /* (defined(unix) || defined(__unix)) && defined(MMAP_SUPPORT) */ #if defined(VMS) && defined(MMAP_SUPPORT) #include #include /* * Table for storing information on current open sections. * (You may want to substitute a linked list...) */ #define MAX_MAPPED 100 static int no_mapped = 0; static struct { void *base; void *top; unsigned channel; } map_table[MAX_MAPPED]; /* * This routine maps a file into a private section. Note that this * method of accessing a file is by far the fastest under VMS. * The routine may fail (i.e. return 0) for several reasons, for * example: * - There is no more room for storing the info on sections. * - The process is out of open file quota, channels, ... * - fd does not describe an opened file. * - The file is already opened for write access by this process * or another process * - There is no free "hole" in virtual memory that fits the * size of the file */ int TIFFMapFileContents(fd, pbase, psize) int fd; char **pbase; long *psize; { char name[256]; struct FAB fab; unsigned short channel; void *inadr[2], *retadr[2]; unsigned long status; long size; if (no_mapped >= MAX_MAPPED) return(0); /* * We cannot use a file descriptor, we * must open the file once more. */ if (getname(fd, name, 1) == NULL) return(0); /* prepare the FAB for a user file open */ fab = cc$rms_fab; fab.fab$v_ufo = 1; fab.fab$b_fac = FAB$M_GET; fab.fab$b_shr = FAB$M_SHRGET; fab.fab$l_fna = name; fab.fab$b_fns = strlen(name); status = sys$open(&fab); /* open file & get channel number */ if ((status&1) == 0) return(0); channel = (unsigned short)fab.fab$l_stv; inadr[0] = inadr[1] = &channel; /* just an address in P0 space */ /* * Map the blocks of the file up to * the EOF block into virtual memory. */ size = TIFFGetFileSize(fd); status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel, howmany(size,512), 0,0,0); if ((status&1) == 0) return(0); *pbase = retadr[0]; /* starting virtual address */ /* * Use the size of the file up to the * EOF mark for UNIX compatibility. */ *psize = size; /* Record the section in the table */ map_table[no_mapped].base = retadr[0]; map_table[no_mapped].top = retadr[1]; map_table[no_mapped].channel = channel; no_mapped++; return(1); } /* * This routine unmaps a section from the virtual address space of * the process, but only if the base was the one returned from a * call to TIFFMapFileContents. */ void TIFFUnmapFileContents(base, size) char *base; long size; { void *inadr[2]; int i, j; /* Find the section in the table */ for (i = 0;i < no_mapped; i++) { if (map_table[i].base == base) { /* Unmap the section */ inadr[1] = base; inadr[0] = map_table[i].top; sys$deltva(inadr, 0, 0); sys$dassgn(map_table[i].channel); /* Remove this section from the list */ for (j = i+1; j < no_mapped; j++) map_table[j-1] = map_table[j]; no_mapped--; return; } } } #endif /* defined(VMS) && defined(MMAP_SUPPORT) */ #if defined(THINK_C) || defined(applec) long TIFFGetFileSize(int fd) { long pos, eof; pos = lseek(fd, 0, SEEK_CUR); eof = lseek(fd, 0, SEEK_END); lseek(fd, pos, SEEK_SET); return(eof); } #endif /* THINK_C || applec */ #if defined(applec) #include #include #undef lseek long mpw_lseek(int fd, long offset, int whence) { long filepos, filesize, newpos; short macfd; if ((filepos = lseek(fd, 0, SEEK_CUR)) < 0 || (filesize = lseek(fd, 0, SEEK_END)) < 0) return (EOF); newpos = offset + (whence == SEEK_SET ? 0 : whence == SEEK_CUR ? filepos : filesize); if (newpos > filesize) if (ioctl(fd, FIOREFNUM, &macfd) == -1 || SetEOF(macfd, newpos) != 0) return (EOF); return (lseek(fd, newpos, SEEK_SET)); } #endif /* applec */ = td->td_transferfunction; int n = 1<td_bitspersample; tf[0] = (u_short *)malloc(n * sizeof (u_short)); tf[0][0] = 0; for (i = 1; i < n; i++) tf[0][i] = (u_short) xloadimage.4.1/tiff/tif_compress.c 664 221 144 12744 5461577444 12401 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_compress.c,v 1.26 92/02/10 19:06:13 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library * * Compression Scheme Configuration Support. */ #include "tiffioP.h" #if USE_PROTOTYPES extern int TIFFInitDumpMode(TIFF*); #ifdef PACKBITS_SUPPORT extern int TIFFInitPackBits(TIFF*); #endif #ifdef CCITT_SUPPORT extern int TIFFInitCCITTRLE(TIFF*), TIFFInitCCITTRLEW(TIFF*); extern int TIFFInitCCITTFax3(TIFF*), TIFFInitCCITTFax4(TIFF*); #endif #ifdef THUNDER_SUPPORT extern int TIFFInitThunderScan(TIFF*); #endif #ifdef NEXT_SUPPORT extern int TIFFInitNeXT(TIFF*); #endif #ifdef LZW_SUPPORT extern int TIFFInitLZW(TIFF*); #endif #ifdef JPEG_SUPPORT extern int TIFFInitJPEG(TIFF*); #endif #else extern int TIFFInitDumpMode(); #ifdef PACKBITS_SUPPORT extern int TIFFInitPackBits(); #endif #ifdef CCITT_SUPPORT extern int TIFFInitCCITTRLE(), TIFFInitCCITTRLEW(); extern int TIFFInitCCITTFax3(), TIFFInitCCITTFax4(); #endif #ifdef THUNDER_SUPPORT extern int TIFFInitThunderScan(); #endif #ifdef NEXT_SUPPORT extern int TIFFInitNeXT(); #endif #ifdef LZW_SUPPORT extern int TIFFInitLZW(); #endif #ifdef JPEG_SUPPORT extern int TIFFInitJPEG(); #endif #endif struct cscheme { char* name; int scheme; int (*init)(); }; static const struct cscheme CompressionSchemes[] = { { "Null", COMPRESSION_NONE, TIFFInitDumpMode }, #ifdef LZW_SUPPORT { "LZW", COMPRESSION_LZW, TIFFInitLZW }, #endif #ifdef PACKBITS_SUPPORT { "PackBits", COMPRESSION_PACKBITS, TIFFInitPackBits }, #endif #ifdef THUNDER_SUPPORT { "ThunderScan", COMPRESSION_THUNDERSCAN,TIFFInitThunderScan }, #endif #ifdef NEXT_SUPPORT { "NeXT", COMPRESSION_NEXT, TIFFInitNeXT }, #endif #ifdef JPEG_SUPPORT { "JPEG", COMPRESSION_JPEG, TIFFInitJPEG }, #endif #ifdef CCITT_SUPPORT { "CCITT RLE", COMPRESSION_CCITTRLE, TIFFInitCCITTRLE }, { "CCITT RLE/W", COMPRESSION_CCITTRLEW, TIFFInitCCITTRLEW }, { "CCITT Group3", COMPRESSION_CCITTFAX3, TIFFInitCCITTFax3 }, { "CCITT Group4", COMPRESSION_CCITTFAX4, TIFFInitCCITTFax4 }, #endif }; #define NSCHEMES (sizeof (CompressionSchemes) / sizeof (CompressionSchemes[0])) static struct cscheme const * findScheme(scheme) int scheme; { register struct cscheme const *c; for (c = CompressionSchemes; c < &CompressionSchemes[NSCHEMES]; c++) if (c->scheme == scheme) return (c); return ((struct cscheme const *)0); } static int TIFFNoEncode(tif, method) TIFF *tif; char *method; { struct cscheme const *c = findScheme(tif->tif_dir.td_compression); TIFFError(tif->tif_name, "%s %s encoding is not implemented", c->name, method); return (-1); } int TIFFNoRowEncode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoEncode(tif, "scanline")); } int TIFFNoStripEncode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoEncode(tif, "strip")); } int TIFFNoTileEncode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoEncode(tif, "tile")); } int TIFFNoDecode(tif, method) TIFF *tif; char *method; { struct cscheme const *c = findScheme(tif->tif_dir.td_compression); TIFFError(tif->tif_name, "%s %s decoding is not implemented", c->name, method); return (-1); } int TIFFNoRowDecode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoDecode(tif, "scanline")); } int TIFFNoStripDecode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoDecode(tif, "strip")); } int TIFFNoTileDecode(tif, pp, cc, s) TIFF *tif; u_char *pp; int cc; u_int s; { return (TIFFNoDecode(tif, "tile")); } TIFFSetCompressionScheme(tif, scheme) TIFF *tif; int scheme; { struct cscheme const *c = findScheme(scheme); if (!c) { TIFFError(tif->tif_name, "Unknown data compression algorithm %u (0x%x)", scheme, scheme); return (0); } tif->tif_predecode = NULL; tif->tif_decoderow = TIFFNoRowDecode; tif->tif_decodestrip = TIFFNoStripDecode; tif->tif_decodetile = TIFFNoTileDecode; tif->tif_preencode = NULL; tif->tif_postencode = NULL; tif->tif_encoderow = TIFFNoRowEncode; tif->tif_encodestrip = TIFFNoStripEncode; tif->tif_encodetile = TIFFNoTileEncode; tif->tif_close = NULL; tif->tif_seek = NULL; tif->tif_cleanup = NULL; tif->tif_flags &= ~TIFF_NOBITREV; tif->tif_options = 0; return ((*c->init)(tif)); } ); #ifdef PACKBITS_SUPPORT exloadimage.4.1/tiff/tif_dir.c 664 221 144 61525 5461577444 11325 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_dir.c,v 1.110 92/03/06 11:59:49 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Directory Tag Get & Set Routines. * (and also some miscellaneous stuff) * * NB: Beware of the varargs declarations for routines in * this file. The names and types of variables has been * carefully chosen to make things work with compilers that * are busted in one way or another (e.g. SGI/MIPS). */ #include "tiffioP.h" #include "prototypes.h" static DECLARE2(setString, char**, cpp, char*, cp) { if (*cpp) free(*cpp), *cpp = 0; if (cp) { int len = strlen(cp)+1; if (*cpp = malloc(len)) bcopy(cp, *cpp, len); } } static DECLARE3(setShortArray, u_short**, wpp, u_short*, wp, long, n) { if (*wpp) free((char *)*wpp), *wpp = 0; n *= sizeof (u_short); if (wp && (*wpp = (u_short *)malloc(n))) bcopy(wp, *wpp, n); } static DECLARE3(setLongArray, u_long**, wpp, u_long*, wp, long, n) { if (*wpp) free((char *)*wpp), *wpp = 0; n *= sizeof (u_long); if (wp && (*wpp = (u_long *)malloc(n))) bcopy(wp, *wpp, n); } static DECLARE3(setFloatArray, float**, wpp, float*, wp, long, n) { if (*wpp) free((char *)*wpp), *wpp = 0; n *= sizeof (float); if (wp && (*wpp = (float *)malloc(n))) bcopy(wp, *wpp, n); } #ifdef JPEG_SUPPORT /* * Install a JPEG Quantization table. * Note that we reorder the elements * of the array in the zig-zag order * that is expected by the compression code * and that is to be stored in the file. */ static DECLARE3(setJPEGQTable, u_char***, wpp, u_char**, wp, int, nc) { static u_char zigzag[64] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; char *tab; int i, j; if (*wpp) free((char *)*wpp), *wpp = 0; *wpp = (u_char **) malloc(nc * (sizeof (u_char *) + 64*sizeof (u_char))); tab = (((char *)*wpp) + nc*sizeof (u_short *)); for (i = 0; i < nc; i++) { (*wpp)[i] = (u_char *)tab; for (j = 0; j < 64; j++) tab[zigzag[j]] = wp[i][j]; tab += 64*sizeof (u_char); } } /* * Install a JPEG Coefficient table. */ static DECLARE3(setJPEGCTable, u_char***, cpp, u_char**, cp, int, nc) { u_char *tab; int i, j, nw; if (*cpp) free(*cpp), *cpp = 0; /* * Calculate the size of the table by counting * the number of codes specified in the bits array. */ nw = 0; for (i = 0; i < nc; i++) { nw += 16; /* 16 bytes for bits array */ for (j = 0; j < 16; j++)/* sum up count of codes */ nw += cp[i][j]; } *cpp = (u_char **)malloc(nc*sizeof (u_char *) + nw); tab = ((u_char *)*cpp) + nc*sizeof (u_char *); /* * Setup internal array and copy user data. */ for (i = 0; i < nc; i++) { (*cpp)[i] = tab; for (nw = 16, j = 0; j < 16; j++) nw += cp[i][j]; bcopy(cp[i], tab, nw); tab += nw; } } #endif static TIFFSetField1(tif, tag, ap) TIFF *tif; int tag; va_list ap; { TIFFDirectory *td = &tif->tif_dir; int i, status = 1; long v; switch (tag) { case TIFFTAG_SUBFILETYPE: td->td_subfiletype = va_arg(ap, u_long); break; case TIFFTAG_IMAGEWIDTH: td->td_imagewidth = va_arg(ap, u_long); break; case TIFFTAG_IMAGELENGTH: td->td_imagelength = va_arg(ap, u_long); break; case TIFFTAG_BITSPERSAMPLE: td->td_bitspersample = va_arg(ap, int); break; case TIFFTAG_COMPRESSION: v = va_arg(ap, int) & 0xffff; /* * If we're changing the compression scheme, * the notify the previous module so that it * can cleanup any state it's setup. */ if (TIFFFieldSet(tif, FIELD_COMPRESSION)) { if (td->td_compression == v) break; if (tif->tif_cleanup) (*tif->tif_cleanup)(tif); } /* * Setup new compression routine state. */ if (status = TIFFSetCompressionScheme(tif, v)) td->td_compression = v; break; case TIFFTAG_PHOTOMETRIC: td->td_photometric = va_arg(ap, int); break; case TIFFTAG_THRESHHOLDING: td->td_threshholding = va_arg(ap, int); break; case TIFFTAG_FILLORDER: v = va_arg(ap, int); if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB) goto badvalue; td->td_fillorder = v; break; case TIFFTAG_DOCUMENTNAME: setString(&td->td_documentname, va_arg(ap, char *)); break; case TIFFTAG_ARTIST: setString(&td->td_artist, va_arg(ap, char *)); break; case TIFFTAG_DATETIME: setString(&td->td_datetime, va_arg(ap, char *)); break; case TIFFTAG_HOSTCOMPUTER: setString(&td->td_hostcomputer, va_arg(ap, char *)); break; case TIFFTAG_IMAGEDESCRIPTION: setString(&td->td_imagedescription, va_arg(ap, char *)); break; case TIFFTAG_MAKE: setString(&td->td_make, va_arg(ap, char *)); break; case TIFFTAG_MODEL: setString(&td->td_model, va_arg(ap, char *)); break; case TIFFTAG_SOFTWARE: setString(&td->td_software, va_arg(ap, char *)); break; case TIFFTAG_ORIENTATION: v = va_arg(ap, int); if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) { TIFFWarning(tif->tif_name, "Bad value %ld for \"%s\" tag ignored", v, TIFFFieldWithTag(tag)->field_name); } else td->td_orientation = v; break; case TIFFTAG_SAMPLESPERPIXEL: /* XXX should cross check -- e.g. if pallette, then 1 */ v = va_arg(ap, int); if (v == 0) goto badvalue; if (v > 4) { TIFFError(tif->tif_name, "Cannot handle %ld-channel data", v); status = 0; } else td->td_samplesperpixel = v; break; case TIFFTAG_ROWSPERSTRIP: v = va_arg(ap, u_long); if (v == 0) goto badvalue; td->td_rowsperstrip = v; if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { td->td_tilelength = v; td->td_tilewidth = td->td_imagewidth; } break; case TIFFTAG_MINSAMPLEVALUE: td->td_minsamplevalue = va_arg(ap, int) & 0xffff; break; case TIFFTAG_MAXSAMPLEVALUE: td->td_maxsamplevalue = va_arg(ap, int) & 0xffff; break; case TIFFTAG_XRESOLUTION: td->td_xresolution = va_arg(ap, dblparam_t); break; case TIFFTAG_YRESOLUTION: td->td_yresolution = va_arg(ap, dblparam_t); break; case TIFFTAG_PLANARCONFIG: v = va_arg(ap, int); if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE) goto badvalue; td->td_planarconfig = v; break; case TIFFTAG_PAGENAME: setString(&td->td_pagename, va_arg(ap, char *)); break; case TIFFTAG_XPOSITION: td->td_xposition = va_arg(ap, dblparam_t); break; case TIFFTAG_YPOSITION: td->td_yposition = va_arg(ap, dblparam_t); break; case TIFFTAG_GROUP3OPTIONS: td->td_group3options = va_arg(ap, u_long); break; case TIFFTAG_GROUP4OPTIONS: td->td_group4options = va_arg(ap, u_long); break; case TIFFTAG_RESOLUTIONUNIT: v = va_arg(ap, int); if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v) goto badvalue; td->td_resolutionunit = v; break; case TIFFTAG_PAGENUMBER: td->td_pagenumber[0] = va_arg(ap, int); td->td_pagenumber[1] = va_arg(ap, int); break; case TIFFTAG_HALFTONEHINTS: td->td_halftonehints[0] = va_arg(ap, int); td->td_halftonehints[1] = va_arg(ap, int); break; case TIFFTAG_COLORMAP: v = 1L<td_bitspersample; setShortArray(&td->td_colormap[0], va_arg(ap, u_short *), v); setShortArray(&td->td_colormap[1], va_arg(ap, u_short *), v); setShortArray(&td->td_colormap[2], va_arg(ap, u_short *), v); break; case TIFFTAG_PREDICTOR: td->td_predictor = va_arg(ap, int); break; case TIFFTAG_EXTRASAMPLES: v = va_arg(ap, int); if (v > td->td_samplesperpixel) goto badvalue; if (v != 1) /* XXX */ goto badvalue; /* XXX */ v = va_arg(ap, int); if (v != EXTRASAMPLE_ASSOCALPHA)/* XXX */ goto badvalue; /* XXX */ td->td_matteing = 1; break; case TIFFTAG_MATTEING: td->td_matteing = va_arg(ap, int); break; case TIFFTAG_BADFAXLINES: td->td_badfaxlines = va_arg(ap, u_long); break; case TIFFTAG_CLEANFAXDATA: td->td_cleanfaxdata = va_arg(ap, int); break; case TIFFTAG_CONSECUTIVEBADFAXLINES: td->td_badfaxrun = va_arg(ap, u_long); break; case TIFFTAG_TILEWIDTH: v = va_arg(ap, u_long); if (v % 8) goto badvalue; td->td_tilewidth = v; tif->tif_flags |= TIFF_ISTILED; break; case TIFFTAG_TILELENGTH: v = va_arg(ap, u_long); if (v % 8) goto badvalue; td->td_tilelength = v; tif->tif_flags |= TIFF_ISTILED; break; case TIFFTAG_TILEDEPTH: v = va_arg(ap, u_long); if (v == 0) goto badvalue; td->td_tiledepth = v; break; case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: v = va_arg(ap, int); if (tag == TIFFTAG_DATATYPE && v == 0) v = SAMPLEFORMAT_VOID; if (v < SAMPLEFORMAT_INT || SAMPLEFORMAT_VOID < v) goto badvalue; td->td_sampleformat = v; break; case TIFFTAG_IMAGEDEPTH: td->td_imagedepth = va_arg(ap, u_long); break; #ifdef YCBCR_SUPPORT case TIFFTAG_YCBCRCOEFFICIENTS: setFloatArray(&td->td_ycbcrcoeffs, va_arg(ap, float *), 3); break; case TIFFTAG_YCBCRPOSITIONING: td->td_ycbcrpositioning = va_arg(ap, int); break; case TIFFTAG_YCBCRSUBSAMPLING: td->td_ycbcrsubsampling[0] = va_arg(ap, int); td->td_ycbcrsubsampling[1] = va_arg(ap, int); break; #endif #ifdef JPEG_SUPPORT case TIFFTAG_JPEGPROC: td->td_jpegproc = va_arg(ap, int); break; case TIFFTAG_JPEGRESTARTINTERVAL: td->td_jpegrestartinterval = va_arg(ap, int); break; case TIFFTAG_JPEGQTABLES: setJPEGQTable(&td->td_qtab, va_arg(ap, u_char **), td->td_samplesperpixel); break; case TIFFTAG_JPEGDCTABLES: setJPEGCTable(&td->td_dctab, va_arg(ap, u_char **), td->td_samplesperpixel); break; case TIFFTAG_JPEGACTABLES: setJPEGCTable(&td->td_actab, va_arg(ap, u_char **), td->td_samplesperpixel); break; #endif #ifdef COLORIMETRY_SUPPORT case TIFFTAG_WHITEPOINT: setFloatArray(&td->td_whitepoint, va_arg(ap, float *), 2); break; case TIFFTAG_PRIMARYCHROMATICITIES: setFloatArray(&td->td_primarychromas, va_arg(ap, float *), 6); break; case TIFFTAG_TRANSFERFUNCTION: for (i = 0; i < td->td_samplesperpixel; i++) setShortArray(&td->td_transferfunction[i], va_arg(ap, u_short *), 1L<td_bitspersample); break; case TIFFTAG_REFERENCEBLACKWHITE: /* XXX should check for null range */ v = 2 * td->td_samplesperpixel; setFloatArray(&td->td_refblackwhite, va_arg(ap, float *), v); break; #endif #ifdef CMYK_SUPPORT case TIFFTAG_INKSET: td->td_inkset = va_arg(ap, int); break; case TIFFTAG_DOTRANGE: /* XXX should check for null range */ td->td_dotrange[0] = va_arg(ap, int); td->td_dotrange[1] = va_arg(ap, int); break; case TIFFTAG_INKNAMES: setString(&td->td_inknames, va_arg(ap, char *)); break; case TIFFTAG_TARGETPRINTER: setString(&td->td_targetprinter, va_arg(ap, char *)); break; #endif default: TIFFError(tif->tif_name, "Internal error, tag value botch, tag \"%s\"", TIFFFieldWithTag(tag)->field_name); status = 0; break; } if (status) { TIFFSetFieldBit(tif, TIFFFieldWithTag(tag)->field_bit); tif->tif_flags |= TIFF_DIRTYDIRECT; } va_end(ap); return (status); badvalue: TIFFError(tif->tif_name, "%ld: Bad value for \"%s\"", v, TIFFFieldWithTag(tag)->field_name); va_end(ap); return (0); } /* * Return 1/0 according to whether or not * it is permissible to set the tag's value. * Note that we allow ImageLength to be changed * so that we can append and extend to images. * Any other tag may not be altered once writing * has commenced, unless its value has no effect * on the format of the data that is written. */ static OkToChangeTag(tif, tag) TIFF *tif; int tag; { if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING)) { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); /* * Consult info table to see if tag can be changed * after we've started writing. We only allow changes * to those tags that don't/shouldn't affect the * compression and/or format of the data. */ if (fip && !fip->field_oktochange) return (0); } return (1); } /* * Record the value of a field in the * internal directory structure. The * field will be written to the file * when/if the directory structure is * updated. */ /*VARARGS2*/ DECLARE2V(TIFFSetField, TIFF*, tif, int, tag) { int status = 0; if (OkToChangeTag(tif, tag)) { va_list ap; VA_START(ap, tag); status = TIFFSetField1(tif, tag, ap); va_end(ap); } else { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) TIFFError("TIFFSetField", "%s: Cannot modify tag \"%s\" while writing", tif->tif_name, fip->field_name); } return (status); } /* * Like TIFFSetField, but taking a varargs * parameter list. This routine is useful * for building higher-level interfaces on * top of the library. */ TIFFVSetField(tif, tag, ap) TIFF *tif; int tag; va_list ap; { int status = 0; if (!OkToChangeTag(tif, tag)) { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) TIFFError("TIFFVSetField", "%s: Cannot modify tag \"%s\" while writing", tif->tif_name, fip->field_name); } else status = TIFFSetField1(tif, tag, ap); return (status); } static TIFFGetField1(td, tag, ap) TIFFDirectory *td; int tag; va_list ap; { switch (tag) { case TIFFTAG_SUBFILETYPE: *va_arg(ap, u_long *) = td->td_subfiletype; break; case TIFFTAG_IMAGEWIDTH: *va_arg(ap, u_long *) = td->td_imagewidth; break; case TIFFTAG_IMAGELENGTH: *va_arg(ap, u_long *) = td->td_imagelength; break; case TIFFTAG_BITSPERSAMPLE: *va_arg(ap, u_short *) = td->td_bitspersample; break; case TIFFTAG_COMPRESSION: *va_arg(ap, u_short *) = td->td_compression; break; case TIFFTAG_PHOTOMETRIC: *va_arg(ap, u_short *) = td->td_photometric; break; case TIFFTAG_THRESHHOLDING: *va_arg(ap, u_short *) = td->td_threshholding; break; case TIFFTAG_FILLORDER: *va_arg(ap, u_short *) = td->td_fillorder; break; case TIFFTAG_DOCUMENTNAME: *va_arg(ap, char **) = td->td_documentname; break; case TIFFTAG_ARTIST: *va_arg(ap, char **) = td->td_artist; break; case TIFFTAG_DATETIME: *va_arg(ap, char **) = td->td_datetime; break; case TIFFTAG_HOSTCOMPUTER: *va_arg(ap, char **) = td->td_hostcomputer; break; case TIFFTAG_IMAGEDESCRIPTION: *va_arg(ap, char **) = td->td_imagedescription; break; case TIFFTAG_MAKE: *va_arg(ap, char **) = td->td_make; break; case TIFFTAG_MODEL: *va_arg(ap, char **) = td->td_model; break; case TIFFTAG_SOFTWARE: *va_arg(ap, char **) = td->td_software; break; case TIFFTAG_ORIENTATION: *va_arg(ap, u_short *) = td->td_orientation; break; case TIFFTAG_SAMPLESPERPIXEL: *va_arg(ap, u_short *) = td->td_samplesperpixel; break; case TIFFTAG_ROWSPERSTRIP: *va_arg(ap, u_long *) = td->td_rowsperstrip; break; case TIFFTAG_MINSAMPLEVALUE: *va_arg(ap, u_short *) = td->td_minsamplevalue; break; case TIFFTAG_MAXSAMPLEVALUE: *va_arg(ap, u_short *) = td->td_maxsamplevalue; break; case TIFFTAG_XRESOLUTION: *va_arg(ap, float *) = td->td_xresolution; break; case TIFFTAG_YRESOLUTION: *va_arg(ap, float *) = td->td_yresolution; break; case TIFFTAG_PLANARCONFIG: *va_arg(ap, u_short *) = td->td_planarconfig; break; case TIFFTAG_XPOSITION: *va_arg(ap, float *) = td->td_xposition; break; case TIFFTAG_YPOSITION: *va_arg(ap, float *) = td->td_yposition; break; case TIFFTAG_PAGENAME: *va_arg(ap, char **) = td->td_pagename; break; case TIFFTAG_GROUP3OPTIONS: *va_arg(ap, u_long *) = td->td_group3options; break; case TIFFTAG_GROUP4OPTIONS: *va_arg(ap, u_long *) = td->td_group4options; break; case TIFFTAG_RESOLUTIONUNIT: *va_arg(ap, u_short *) = td->td_resolutionunit; break; case TIFFTAG_PAGENUMBER: *va_arg(ap, u_short *) = td->td_pagenumber[0]; *va_arg(ap, u_short *) = td->td_pagenumber[1]; break; case TIFFTAG_HALFTONEHINTS: *va_arg(ap, u_short *) = td->td_halftonehints[0]; *va_arg(ap, u_short *) = td->td_halftonehints[1]; break; case TIFFTAG_COLORMAP: *va_arg(ap, u_short **) = td->td_colormap[0]; *va_arg(ap, u_short **) = td->td_colormap[1]; *va_arg(ap, u_short **) = td->td_colormap[2]; break; case TIFFTAG_PREDICTOR: *va_arg(ap, u_short *) = td->td_predictor; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: *va_arg(ap, u_long **) = td->td_stripoffset; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: *va_arg(ap, u_long **) = td->td_stripbytecount; break; case TIFFTAG_MATTEING: *va_arg(ap, u_short *) = td->td_matteing; break; case TIFFTAG_EXTRASAMPLES: *va_arg(ap, u_short *) = td->td_matteing; *va_arg(ap, u_short **) = &td->td_matteing; break; case TIFFTAG_BADFAXLINES: *va_arg(ap, u_long *) = td->td_badfaxlines; break; case TIFFTAG_CLEANFAXDATA: *va_arg(ap, u_short *) = td->td_cleanfaxdata; break; case TIFFTAG_CONSECUTIVEBADFAXLINES: *va_arg(ap, u_long *) = td->td_badfaxrun; break; case TIFFTAG_TILEWIDTH: *va_arg(ap, u_long *) = td->td_tilewidth; break; case TIFFTAG_TILELENGTH: *va_arg(ap, u_long *) = td->td_tilelength; break; case TIFFTAG_TILEDEPTH: *va_arg(ap, u_long *) = td->td_tiledepth; break; case TIFFTAG_DATATYPE: *va_arg(ap, u_short *) = (td->td_sampleformat == SAMPLEFORMAT_VOID ? 0 : td->td_sampleformat); break; case TIFFTAG_SAMPLEFORMAT: *va_arg(ap, u_short *) = td->td_sampleformat; break; case TIFFTAG_IMAGEDEPTH: *va_arg(ap, u_long *) = td->td_imagedepth; break; #ifdef YCBCR_SUPPORT case TIFFTAG_YCBCRCOEFFICIENTS: *va_arg(ap, float **) = td->td_ycbcrcoeffs; break; case TIFFTAG_YCBCRPOSITIONING: *va_arg(ap, u_short *) = td->td_ycbcrpositioning; break; case TIFFTAG_YCBCRSUBSAMPLING: *va_arg(ap, u_short *) = td->td_ycbcrsubsampling[0]; *va_arg(ap, u_short *) = td->td_ycbcrsubsampling[1]; break; #endif #ifdef JPEG_SUPPORT case TIFFTAG_JPEGPROC: *va_arg(ap, u_short *) = td->td_jpegproc; break; case TIFFTAG_JPEGRESTARTINTERVAL: *va_arg(ap, u_short *) = td->td_jpegrestartinterval; break; case TIFFTAG_JPEGQTABLES: *va_arg(ap, u_char ***) = td->td_qtab; break; case TIFFTAG_JPEGDCTABLES: *va_arg(ap, u_char ***) = td->td_dctab; break; case TIFFTAG_JPEGACTABLES: *va_arg(ap, u_char ***) = td->td_actab; break; #endif #ifdef COLORIMETRY_SUPPORT case TIFFTAG_WHITEPOINT: *va_arg(ap, float **) = td->td_whitepoint; break; case TIFFTAG_PRIMARYCHROMATICITIES: *va_arg(ap, float **) = td->td_primarychromas; break; case TIFFTAG_TRANSFERFUNCTION: { int i; for (i = 0; i < td->td_samplesperpixel; i++) *va_arg(ap, u_short **) = td->td_transferfunction[i]; break; } case TIFFTAG_REFERENCEBLACKWHITE: *va_arg(ap, float **) = td->td_refblackwhite; break; #endif #ifdef CMYK_SUPPORT case TIFFTAG_INKSET: *va_arg(ap, u_short *) = td->td_inkset; break; case TIFFTAG_DOTRANGE: *va_arg(ap, u_short *) = td->td_dotrange[0]; *va_arg(ap, u_short *) = td->td_dotrange[1]; break; case TIFFTAG_INKNAMES: *va_arg(ap, char **) = td->td_inknames; break; case TIFFTAG_TARGETPRINTER: *va_arg(ap, char **) = td->td_targetprinter; break; #endif default: TIFFError("TIFFGetField1", "Internal error, no value returned for tag \"%s\"", TIFFFieldWithTag(tag)->field_name); break; } va_end(ap); } /* * Return the value of a field in the * internal directory structure. */ /*VARARGS2*/ DECLARE2V(TIFFGetField, TIFF*, tif, int, tag) { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) { u_short bit = fip->field_bit; if (bit != FIELD_IGNORE && TIFFFieldSet(tif, bit)) { va_list ap; VA_START(ap, tag); (void) TIFFGetField1(&tif->tif_dir, tag, ap); va_end(ap); return (1); } } else TIFFError("TIFFGetField", "Unknown field, tag 0x%x", tag); return (0); } /* * Like TIFFGetField, but taking a varargs * parameter list. This routine is useful * for building higher-level interfaces on * top of the library. */ TIFFVGetField(tif, tag, ap) TIFF *tif; int tag; va_list ap; { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) { u_short bit = fip->field_bit; if (bit != FIELD_IGNORE && TIFFFieldSet(tif, bit)) { (void) TIFFGetField1(&tif->tif_dir, tag, ap); return (1); } } else TIFFError("TIFFGetField", "Unknown field, tag 0x%x", tag); return (0); } /* * Internal interface to TIFFGetField... */ int /*VARARGS2*/ DECLARE2V(_TIFFgetfield, TIFFDirectory*, td, int, tag) { va_list ap; VA_START(ap, tag); (void) TIFFGetField1(td, tag, ap); va_end(ap); } #define CleanupField(member) { \ if (td->member) { \ free((char *)td->member); \ td->member = 0; \ } \ } /* * Release storage associated with a directory. */ TIFFFreeDirectory(tif) TIFF *tif; { register TIFFDirectory *td = &tif->tif_dir; CleanupField(td_colormap[0]); CleanupField(td_colormap[1]); CleanupField(td_colormap[2]); CleanupField(td_documentname); CleanupField(td_artist); CleanupField(td_datetime); CleanupField(td_hostcomputer); CleanupField(td_imagedescription); CleanupField(td_make); CleanupField(td_model); CleanupField(td_software); CleanupField(td_pagename); #ifdef YCBCR_SUPPORT CleanupField(td_ycbcrcoeffs); #endif #ifdef JPEG_SUPPORT CleanupField(td_qtab); CleanupField(td_dctab); CleanupField(td_actab); #endif #ifdef CMYK_SUPPORT CleanupField(td_inknames); CleanupField(td_targetprinter); #endif #ifdef COLORIMETRY_SUPPORT CleanupField(td_whitepoint); CleanupField(td_primarychromas); CleanupField(td_refblackwhite); CleanupField(td_transferfunction[0]); CleanupField(td_transferfunction[1]); CleanupField(td_transferfunction[2]); CleanupField(td_transferfunction[3]); #endif CleanupField(td_stripoffset); CleanupField(td_stripbytecount); } #undef CleanupField /* * Setup a default directory structure. */ TIFFDefaultDirectory(tif) TIFF *tif; { register TIFFDirectory *td = &tif->tif_dir; bzero((char *)td, sizeof (*td)); td->td_fillorder = FILLORDER_MSB2LSB; td->td_bitspersample = 1; td->td_threshholding = THRESHHOLD_BILEVEL; td->td_orientation = ORIENTATION_TOPLEFT; td->td_samplesperpixel = 1; td->td_predictor = 1; td->td_rowsperstrip = 0xffffffff; td->td_tilewidth = 0xffffffff; td->td_tilelength = 0xffffffff; td->td_tiledepth = 1; td->td_resolutionunit = RESUNIT_INCH; td->td_sampleformat = SAMPLEFORMAT_VOID; td->td_imagedepth = 1; #ifdef YCBCR_SUPPORT td->td_ycbcrsubsampling[0] = 2; td->td_ycbcrsubsampling[1] = 2; td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED; #endif #ifdef CMYK_SUPPORT td->td_inkset = INKSET_CMYK; #endif (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); /* * NB: The directory is marked dirty as a result of setting * up the default compression scheme. However, this really * isn't correct -- we want TIFF_DIRTYDIRECT to be set only * if the user does something. We could just do the setup * by hand, but it seems better to use the normal mechanism * (i.e. TIFFSetField). */ tif->tif_flags &= ~TIFF_DIRTYDIRECT; return (1); } /* * Set the n-th directory as the current directory. * NB: Directories are numbered starting at 0. */ TIFFSetDirectory(tif, dirn) register TIFF *tif; int dirn; { static char module[] = "TIFFSetDirectory"; u_short dircount; long nextdir; int n; nextdir = tif->tif_header.tiff_diroff; for (n = dirn; n > 0 && nextdir != 0; n--) { if (!SeekOK(tif->tif_fd, nextdir) || !ReadOK(tif->tif_fd, &dircount, sizeof (dircount))) { TIFFError(module, "%s: Error fetching directory count", tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); lseek(tif->tif_fd, dircount*sizeof (TIFFDirEntry), L_INCR); if (!ReadOK(tif->tif_fd, &nextdir, sizeof (nextdir))) { TIFFError(module, "%s: Error fetching directory link", tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong((u_long *)&nextdir); } tif->tif_nextdiroff = nextdir; /* * Set curdir to the actual directory index. The * -1 is because TIFFReadDirectory will increment * tif_curdir after successfully reading the directory. */ tif->tif_curdir = (dirn - n) - 1; return (TIFFReadDirectory(tif)); } _arg(ap, u_short **) = td->td_colormap[0]; *va_arg(ap, u_short **) = td->td_colormap[1]; *va_arg(ap, u_short **) = td->td_colormap[2]; break; case TIFFTAG_PREDICTORxloadimage.4.1/tiff/tif_dirinfo.c 664 221 144 27755 5461577444 12210 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_dirinfo.c,v 1.17 92/03/20 11:25:08 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Known Directory Tag Support. */ #include "tiffioP.h" #include "prototypes.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* * NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG. * Also, if a tag can have both LONG and SHORT types * then the LONG must be placed before the SHORT for * writing to work properly. */ const TIFFFieldInfo tiffFieldInfo[] = { { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, FIELD_SUBFILETYPE, TRUE, "SubfileType" }, /* XXX SHORT for compatibility w/ old versions of the library */ { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, TRUE, "SubfileType" }, { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, TRUE, "OldSubfileType" }, { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, FALSE, "ImageWidth" }, { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, FALSE, "ImageWidth" }, { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, TRUE, "ImageLength" }, { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, TRUE, "ImageLength" }, { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_SHORT, FIELD_BITSPERSAMPLE, FALSE, "BitsPerSample" }, { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, FIELD_COMPRESSION, FALSE, "Compression" }, { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, FIELD_PHOTOMETRIC, FALSE, "PhotometricInterpretation" }, { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, FIELD_THRESHHOLDING, TRUE, "Threshholding" }, { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, TRUE, "CellWidth" }, { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, TRUE, "CellLength" }, { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, FIELD_FILLORDER, FALSE, "FillOrder" }, { TIFFTAG_DOCUMENTNAME, -1,-1, TIFF_ASCII, FIELD_DOCUMENTNAME, TRUE, "DocumentName" }, { TIFFTAG_IMAGEDESCRIPTION, -1,-1, TIFF_ASCII, FIELD_IMAGEDESCRIPTION, TRUE, "ImageDescription" }, { TIFFTAG_MAKE, -1,-1, TIFF_ASCII, FIELD_MAKE, TRUE, "Make" }, { TIFFTAG_MODEL, -1,-1, TIFF_ASCII, FIELD_MODEL, TRUE, "Model" }, { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_LONG, FIELD_STRIPOFFSETS, FALSE, "StripOffsets" }, { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_SHORT, FIELD_STRIPOFFSETS, FALSE, "StripOffsets" }, { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, FIELD_ORIENTATION, FALSE, "Orientation" }, { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, FIELD_SAMPLESPERPIXEL, FALSE, "SamplesPerPixel" }, { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, FIELD_ROWSPERSTRIP, FALSE, "RowsPerStrip" }, { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_SHORT, FIELD_ROWSPERSTRIP, FALSE, "RowsPerStrip" }, { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, FALSE, "StripByteCounts" }, { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, FALSE, "StripByteCounts" }, { TIFFTAG_MINSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MINSAMPLEVALUE, TRUE, "MinSampleValue" }, { TIFFTAG_MAXSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MAXSAMPLEVALUE, TRUE, "MaxSampleValue" }, { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, FALSE, "XResolution" }, { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, FALSE, "YResolution" }, { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, FIELD_PLANARCONFIG, FALSE, "PlanarConfiguration" }, { TIFFTAG_PAGENAME, -1,-1, TIFF_ASCII, FIELD_PAGENAME, TRUE, "PageName" }, { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, TRUE, "XPosition" }, { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, TRUE, "YPosition" }, { TIFFTAG_FREEOFFSETS, -1,-1, TIFF_LONG, FIELD_IGNORE, FALSE, "FreeOffsets" }, { TIFFTAG_FREEBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_IGNORE, FALSE, "FreeByteCounts" }, { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, TRUE, "GrayResponseUnit" }, { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT, FIELD_IGNORE, TRUE, "GrayResponseCurve" }, { TIFFTAG_GROUP3OPTIONS, 1, 1, TIFF_LONG, FIELD_GROUP3OPTIONS, FALSE, "Group3Options" }, { TIFFTAG_GROUP4OPTIONS, 1, 1, TIFF_LONG, FIELD_GROUP4OPTIONS, FALSE, "Group4Options" }, { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_RESOLUTIONUNIT, FALSE, "ResolutionUnit" }, { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, FIELD_PAGENUMBER, TRUE, "PageNumber" }, { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, TRUE, "ColorResponseUnit" }, #ifdef COLORIMETRY_SUPPORT { TIFFTAG_TRANSFERFUNCTION, -1,-1, TIFF_SHORT, FIELD_TRANSFERFUNCTION, TRUE, "TransferFunction" }, #endif { TIFFTAG_SOFTWARE, -1,-1, TIFF_ASCII, FIELD_SOFTWARE, TRUE, "Software" }, { TIFFTAG_DATETIME, 20,20, TIFF_ASCII, FIELD_DATETIME, TRUE, "DateTime" }, { TIFFTAG_ARTIST, -1,-1, TIFF_ASCII, FIELD_ARTIST, TRUE, "Artist" }, { TIFFTAG_HOSTCOMPUTER, -1,-1, TIFF_ASCII, FIELD_HOSTCOMPUTER, TRUE, "HostComputer" }, { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, FIELD_PREDICTOR, FALSE, "Predictor" }, #ifdef COLORIMETRY_SUPPORT { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL,FIELD_WHITEPOINT, TRUE, "WhitePoint" }, { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL,FIELD_PRIMARYCHROMAS, TRUE, "PrimaryChromaticities" }, #endif { TIFFTAG_COLORMAP, -1,-1, TIFF_SHORT, FIELD_COLORMAP, TRUE, "ColorMap" }, { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, FIELD_HALFTONEHINTS, TRUE, "HalftoneHints" }, { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, FALSE, "TileWidth" }, { TIFFTAG_TILEWIDTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, FALSE, "TileWidth" }, { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, FALSE, "TileLength" }, { TIFFTAG_TILELENGTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, FALSE, "TileLength" }, { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG, FIELD_STRIPOFFSETS, FALSE, "TileOffsets" }, { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, FALSE, "TileByteCounts" }, { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, FALSE, "TileByteCounts" }, { TIFFTAG_BADFAXLINES, 1, 1, TIFF_LONG, FIELD_BADFAXLINES, TRUE, "BadFaxLines" }, { TIFFTAG_BADFAXLINES, 1, 1, TIFF_SHORT, FIELD_BADFAXLINES, TRUE, "BadFaxLines" }, { TIFFTAG_CLEANFAXDATA, 1, 1, TIFF_SHORT, FIELD_CLEANFAXDATA, TRUE, "CleanFaxData" }, { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG,FIELD_BADFAXRUN, TRUE, "ConsecutiveBadFaxLines" }, { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT,FIELD_BADFAXRUN, TRUE, "ConsecutiveBadFaxLines" }, #ifdef CMYK_SUPPORT /* 6.0 CMYK tags */ { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, FIELD_INKSET, FALSE, "InkSet" }, { TIFFTAG_INKNAMES, -1,-1, TIFF_ASCII, FIELD_INKNAMES, TRUE, "InkNames" }, { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, FIELD_DOTRANGE, FALSE, "DotRange" }, { TIFFTAG_DOTRANGE, 2, 2, TIFF_BYTE, FIELD_DOTRANGE, FALSE, "DotRange" }, { TIFFTAG_TARGETPRINTER, -1,-1, TIFF_ASCII, FIELD_TARGETPRINTER, TRUE, "TargetPrinter" }, #endif { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_SHORT, FIELD_MATTEING, FALSE, "ExtraSamples" }, { TIFFTAG_SAMPLEFORMAT, -1,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, FALSE, "SampleFormat" }, #ifdef notdef { TIFFTAG_SMINSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMINSAMPLEVALUE, TRUE, "SMinSampleValue" }, { TIFFTAG_SMAXSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMAXSAMPLEVALUE, TRUE, "SMaxSampleValue" }, #endif #ifdef JPEG_SUPPORT /* 6.0 JPEG tags */ { TIFFTAG_JPEGPROC, 1, 1, TIFF_SHORT, FIELD_JPEGPROC, FALSE, "JPEGProc" }, { TIFFTAG_JPEGIFOFFSET, 1, 1, TIFF_LONG, FIELD_IGNORE, FALSE, "JPEGInterchangeFormat" }, { TIFFTAG_JPEGIFBYTECOUNT, 1, 1, TIFF_LONG, FIELD_IGNORE, FALSE, "JPEGInterchangeFormatLength" }, { TIFFTAG_JPEGRESTARTINTERVAL,1,1, TIFF_SHORT,FIELD_JPEGRESTARTINTERVAL, FALSE, "JPEGRestartInterval" }, { TIFFTAG_JPEGQTABLES, -2,-1, TIFF_LONG, FIELD_JPEGQTABLES, FALSE, "JPEGQTables" }, { TIFFTAG_JPEGDCTABLES, -2,-1, TIFF_LONG, FIELD_JPEGDCTABLES, FALSE, "JPEGDCTables" }, { TIFFTAG_JPEGACTABLES, -2,-1, TIFF_LONG, FIELD_JPEGACTABLES, FALSE, "JPEGACTables" }, #endif #ifdef YCBCR_SUPPORT /* 6.0 YCbCr tags */ { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, FIELD_YCBCRCOEFFICIENTS, FALSE, "YCbCrCoefficients" }, { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, FIELD_YCBCRSUBSAMPLING, FALSE, "YCbCrSubsampling" }, { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, FIELD_YCBCRPOSITIONING, FALSE, "YCbCrPositioning" }, #endif #ifdef COLORIMETRY_SUPPORT { TIFFTAG_REFERENCEBLACKWHITE,-1,-1,TIFF_RATIONAL, FIELD_REFBLACKWHITE, FALSE, "ReferenceBlackWhite" }, /* XXX temporarily accept LONG for backwards compatibility */ { TIFFTAG_REFERENCEBLACKWHITE,-1,-1,TIFF_LONG, FIELD_REFBLACKWHITE, FALSE, "ReferenceBlackWhite" }, #endif /* begin SGI tags */ { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, FIELD_MATTEING, FALSE, "Matteing" }, { TIFFTAG_DATATYPE, -2,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, FALSE, "DataType" }, { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, FIELD_IMAGEDEPTH, FALSE, "ImageDepth" }, { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDEPTH, FALSE, "ImageDepth" }, { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, FIELD_TILEDEPTH, FALSE, "TileDepth" }, { TIFFTAG_TILEDEPTH, 1, 1, TIFF_SHORT, FIELD_TILEDEPTH, FALSE, "TileDepth" }, /* end SGI tags */ { 0 } }; const int tiffDataWidth[] = { 1, /* nothing */ 1, /* TIFF_BYTE */ 1, /* TIFF_ASCII */ 2, /* TIFF_SHORT */ 4, /* TIFF_LONG */ 8, /* TIFF_RATIONAL */ 1, /* TIFF_SBYTE */ 1, /* TIFF_UNDEFINED */ 2, /* TIFF_SSHORT */ 4, /* TIFF_SLONG */ 8, /* TIFF_SRATIONAL */ 4, /* TIFF_FLOAT */ 8, /* TIFF_DOUBLE */ }; TIFFFieldInfo const * DECLARE2(TIFFFindFieldInfo, u_short, tag, TIFFDataType, dt) { static TIFFFieldInfo const *last = NULL; register TIFFFieldInfo const *fip; if (last && last->field_tag == tag && (dt == TIFF_ANY || dt == last->field_type)) return (last); /* NB: if table gets big, use sorted search (e.g. binary search) */ for (fip = tiffFieldInfo; fip->field_tag; fip++) if (fip->field_tag == tag && (dt == TIFF_ANY || fip->field_type == dt)) return (last = fip); return ((TIFFFieldInfo *)0); } TIFFFieldInfo const * DECLARE1(TIFFFieldWithTag, u_short, tag) { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) return (fip); TIFFError("TIFFFieldWithTag", "Internal error, unknown tag 0x%x", tag); exit(-1); /*NOTREACHED*/ } xloadimage.4.1/tiff/tif_dirread.c 664 221 144 76256 5461577445 12171 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_dirread.c,v 1.20 92/03/25 09:58:09 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Directory Read Support Routines. * * NB: Beware of the varargs declarations for routines in * this file. The names and types of variables has been * carefully chosen to make things work with compilers that * are busted in one way or another (e.g. SGI/MIPS). */ #include "tiffioP.h" #define IGNORE 0 /* tag placeholder used below */ #if HAVE_IEEEFP #define TIFFCvtIEEEFloatToNative(tif, n, fp) #endif #include "prototypes.h" #if USE_PROTOTYPES static EstimateStripByteCounts(TIFF *, TIFFDirEntry *, u_int); static MissingRequired(TIFF *, char *); static CheckDirCount(TIFF *, TIFFDirEntry *, u_long); static TIFFFetchData(TIFF *, TIFFDirEntry *, char *); static TIFFFetchString(TIFF *, TIFFDirEntry *, char *); static float TIFFFetchRational(TIFF *, TIFFDirEntry *); static TIFFFetchNormalTag(TIFF *, TIFFDirEntry *); static TIFFFetchPerSampleShorts(TIFF *, TIFFDirEntry *, long *); static TIFFFetchShortArray(TIFF *, TIFFDirEntry *, u_short []); static TIFFFetchStripThing(TIFF *, TIFFDirEntry *, long, u_long **); static TIFFFetchRefBlackWhite(TIFF *, TIFFDirEntry *); static TIFFFetchJPEGQTables(TIFF *, TIFFDirEntry *); static TIFFFetchJPEGCTables(TIFF *, TIFFDirEntry *, u_char ***); static TIFFFetchExtraSamples(TIFF *, TIFFDirEntry *); static float TIFFFetchFloat(TIFF *, TIFFDirEntry *); static int TIFFFetchFloatArray(TIFF *, TIFFDirEntry *, float *); extern int TIFFSetCompressionScheme(TIFF *, int); extern int TIFFDefaultDirectory(TIFF*); extern int TIFFFreeDirectory(TIFF*); #else static EstimateStripByteCounts(); static MissingRequired(); static CheckDirCount(); static TIFFFetchData(); static TIFFFetchString(); static float TIFFFetchRational(); static TIFFFetchNormalTag(); static TIFFFetchPerSampleShorts(); static TIFFFetchShortArray(); static TIFFFetchStripThing(); static TIFFFetchRefBlackWhite(); static TIFFFetchJPEGQTables(); static TIFFFetchJPEGCTables(); static TIFFFetchExtraSamples(); static float TIFFFetchFloat(); static int TIFFFetchFloatArray(); extern int TIFFSetCompressionScheme(); extern int TIFFDefaultDirectory(); extern int TIFFFreeDirectory(); #endif static char * CheckMalloc(tif, n, what) TIFF *tif; int n; char *what; { char *cp = malloc(n); if (cp == NULL) TIFFError(tif->tif_name, "No space %s", what); return (cp); } /* * Read the next TIFF directory from a file * and convert it to the internal format. * We read directories sequentially. */ TIFFReadDirectory(tif) TIFF *tif; { register TIFFDirEntry *dp; register int n; register TIFFDirectory *td; TIFFDirEntry *dir; long v; TIFFFieldInfo *fip; u_short dircount; char *cp; int diroutoforderwarning = 0; tif->tif_diroff = tif->tif_nextdiroff; if (tif->tif_diroff == 0) /* no more directories */ return (0); tif->tif_curdir++; if (!isMapped(tif)) { if (!SeekOK(tif->tif_fd, tif->tif_diroff)) { TIFFError(tif->tif_name, "Seek error accessing TIFF directory"); return (0); } if (!ReadOK(tif->tif_fd, &dircount, sizeof (short))) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (!ReadOK(tif->tif_fd, dir, dircount*sizeof (TIFFDirEntry))) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } /* * Read offset to next directory for sequential scans. */ if (!ReadOK(tif->tif_fd, &tif->tif_nextdiroff, sizeof (long))) tif->tif_nextdiroff = 0; #ifdef MMAP_SUPPORT } else { off_t off = tif->tif_diroff; if (off + sizeof (short) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } else bcopy(tif->tif_base + off, &dircount, sizeof (short)); off += sizeof (short); if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } else bcopy(tif->tif_base + off, dir, dircount*sizeof (TIFFDirEntry)); off += dircount* sizeof (TIFFDirEntry); if (off + sizeof (long) < tif->tif_size) bcopy(tif->tif_base + off, &tif->tif_nextdiroff, sizeof (long)); else tif->tif_nextdiroff = 0; #endif } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong((u_long *)&tif->tif_nextdiroff); tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ /* * Setup default value and then make a pass over * the fields to check type and tag information, * and to extract info required to size data * structures. A second pass is made afterwards * to read in everthing not taken in the first pass. */ td = &tif->tif_dir; /* free any old stuff and reinit */ TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); /* * Electronic Arts writes gray-scale TIFF files * without a PlanarConfiguration directory entry. * Thus we setup a default value here, even though * the TIFF spec says there is no default value. */ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); for (fip = tiffFieldInfo, dp = dir, n = dircount; n > 0; n--, dp++) { if (tif->tif_flags & TIFF_SWAB) { TIFFSwabArrayOfShort(&dp->tdir_tag, 2); TIFFSwabArrayOfLong(&dp->tdir_count, 2); } /* * Find the field information entry for this tag. */ /* * Silicon Beach (at least) writes unordered * directory tags (violating the spec). Handle * it here, but be obnoxious (maybe they'll fix it?). */ if (dp->tdir_tag < fip->field_tag) { if (!diroutoforderwarning) { TIFFWarning(tif->tif_name, "invalid TIFF directory; tags are not sorted in ascending order"); diroutoforderwarning = 1; } fip = tiffFieldInfo; /* O(n^2) */ } while (fip->field_tag && fip->field_tag < dp->tdir_tag) fip++; if (!fip->field_tag || fip->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "unknown field with tag %d (0x%x) ignored", dp->tdir_tag, dp->tdir_tag); dp->tdir_tag = IGNORE; fip = tiffFieldInfo; /* restart search */ continue; } /* * Null out old tags that we ignore. */ if (fip->field_bit == FIELD_IGNORE) { ignore: dp->tdir_tag = IGNORE; continue; } /* * Check data type. */ while (dp->tdir_type != (u_short)fip->field_type) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; fip++; if (!fip->field_tag || fip->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "wrong data type %d for \"%s\"; tag ignored", dp->tdir_type, fip[-1].field_name); goto ignore; } } /* * Check count if known in advance. */ if (fip->field_readcount != TIFF_VARIABLE) { u_long expected = (fip->field_readcount == TIFF_SPP) ? (u_long) td->td_samplesperpixel : (u_long) fip->field_readcount; if (!CheckDirCount(tif, dp, expected)) goto ignore; } switch (dp->tdir_tag) { case TIFFTAG_STRIPOFFSETS: case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEOFFSETS: case TIFFTAG_TILEBYTECOUNTS: TIFFSetFieldBit(tif, fip->field_bit); break; case TIFFTAG_IMAGEWIDTH: case TIFFTAG_IMAGELENGTH: case TIFFTAG_IMAGEDEPTH: case TIFFTAG_TILELENGTH: case TIFFTAG_TILEWIDTH: case TIFFTAG_TILEDEPTH: case TIFFTAG_PLANARCONFIG: case TIFFTAG_SAMPLESPERPIXEL: case TIFFTAG_ROWSPERSTRIP: if (!TIFFFetchNormalTag(tif, dp)) goto bad; break; } } /* * Allocate directory structure and setup defaults. */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { MissingRequired(tif, "ImageLength"); goto bad; } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { MissingRequired(tif, "PlanarConfiguration"); goto bad; } /* * Setup appropriate structures (by strip or by tile) */ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { td->td_stripsperimage = (td->td_rowsperstrip == 0xffffffff ? (td->td_imagelength != 0 ? 1 : 0) : howmany(td->td_imagelength, td->td_rowsperstrip)); td->td_tilewidth = td->td_imagewidth; td->td_tilelength = td->td_rowsperstrip; td->td_tiledepth = td->td_imagedepth; tif->tif_flags &= ~TIFF_ISTILED; } else { td->td_stripsperimage = TIFFNumberOfTiles(tif); tif->tif_flags |= TIFF_ISTILED; } td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_nstrips *= td->td_samplesperpixel; if (td->td_nstrips > 0 && !TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets"); goto bad; } /* * Second pass: extract other information. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (dp->tdir_tag == IGNORE) continue; switch (dp->tdir_tag) { case TIFFTAG_COMPRESSION: case TIFFTAG_MINSAMPLEVALUE: case TIFFTAG_MAXSAMPLEVALUE: case TIFFTAG_BITSPERSAMPLE: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. * * The MinSampleValue, MaxSampleValue and * BitsPerSample tags are supposed to be written * as one value/sample, but some vendors incorrectly * write one value only -- so we accept that * as well (yech). */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; } /* fall thru... */ case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: if (!TIFFFetchPerSampleShorts(tif, dp, &v) || !TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripoffset)) goto bad; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripbytecount)) goto bad; break; case TIFFTAG_IMAGELENGTH: case TIFFTAG_ROWSPERSTRIP: case TIFFTAG_TILELENGTH: case TIFFTAG_TILEWIDTH: case TIFFTAG_TILEDEPTH: case TIFFTAG_SAMPLESPERPIXEL: case TIFFTAG_PLANARCONFIG: /* handled in first pass above */ break; case TIFFTAG_COLORMAP: if (!CheckDirCount(tif,dp,3*(1L<td_bitspersample))) break; /* fall thru... */ case TIFFTAG_TRANSFERFUNCTION: v = (1L<td_bitspersample) * sizeof (u_short); cp = CheckMalloc(tif, dp->tdir_count * sizeof (u_short), "to read \"TransferFunction\" tag"); if (cp != NULL) { if (TIFFFetchData(tif, dp, cp)) { /* * This deals with there being only * one array to apply to all samples. */ if (dp->tdir_count == 1L<td_bitspersample) v = 0; /* NB: we assume samples/pixel <= 4 */ TIFFSetField(tif, dp->tdir_tag, cp, cp+v, cp+2*v, cp+3*v); } free(cp); } break; case TIFFTAG_PAGENUMBER: if (TIFFFetchShortArray(tif, dp, td->td_pagenumber)) TIFFSetFieldBit(tif, FIELD_PAGENUMBER); break; case TIFFTAG_HALFTONEHINTS: if (TIFFFetchShortArray(tif, dp, td->td_halftonehints)) TIFFSetFieldBit(tif, FIELD_HALFTONEHINTS); break; #ifdef COLORIMETRY_SUPPORT case TIFFTAG_REFERENCEBLACKWHITE: (void) TIFFFetchRefBlackWhite(tif, dp); break; #endif #ifdef YCBCR_SUPPORT case TIFFTAG_YCBCRSUBSAMPLING: if (TIFFFetchShortArray(tif, dp, td->td_ycbcrsubsampling)) TIFFSetFieldBit(tif, FIELD_YCBCRSUBSAMPLING); break; #endif #ifdef CMYK_SUPPORT case TIFFTAG_DOTRANGE: if (TIFFFetchShortArray(tif, dp, td->td_dotrange)) TIFFSetFieldBit(tif, FIELD_DOTRANGE); break; #endif #ifdef JPEG_SUPPORT case TIFFTAG_JPEGQTABLES: if (TIFFFetchJPEGQTables(tif, dp)) TIFFSetFieldBit(tif, FIELD_JPEGQTABLES); break; case TIFFTAG_JPEGDCTABLES: if (TIFFFetchJPEGCTables(tif, dp, &td->td_dctab)) TIFFSetFieldBit(tif, FIELD_JPEGDCTABLES); break; case TIFFTAG_JPEGACTABLES: if (TIFFFetchJPEGCTables(tif, dp, &td->td_actab)) TIFFSetFieldBit(tif, FIELD_JPEGACTABLES); break; #endif case TIFFTAG_EXTRASAMPLES: (void) TIFFFetchExtraSamples(tif, dp); break; /* BEGIN REV 4.0 COMPATIBILITY */ case TIFFTAG_OSUBFILETYPE: v = 0; switch (TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)) { case OFILETYPE_REDUCEDIMAGE: v = FILETYPE_REDUCEDIMAGE; break; case OFILETYPE_PAGE: v = FILETYPE_PAGE; break; } if (v) (void) TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (int)v); break; /* END REV 4.0 COMPATIBILITY */ default: (void) TIFFFetchNormalTag(tif, dp); break; } } /* * Verify Palette image has a Colormap. */ if (td->td_photometric == PHOTOMETRIC_PALETTE && !TIFFFieldSet(tif, FIELD_COLORMAP)) { MissingRequired(tif, "Colormap"); goto bad; } /* * Attempt to deal with a missing StripByteCounts tag. */ if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { /* * Some manufacturers violate the spec by not giving * the size of the strips. In this case, assume there * is one uncompressed strip of data. */ if (td->td_nstrips > 1) { MissingRequired(tif, "StripByteCounts"); goto bad; } TIFFWarning(tif->tif_name, "TIFF directory is missing required \"%s\" field, calculating from imagelength", TIFFFieldWithTag(TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); } else if (td->td_nstrips == 1 && td->td_stripbytecount[0] == 0) { /* * Plexus (and others) sometimes give a value * of zero for a tag when they don't know what * the correct value is! Try and handle the * simple case of estimating the size of a one * strip image. */ TIFFWarning(tif->tif_name, "Bogus \"%s\" field, ignoring and calculating from imagelength", TIFFFieldWithTag(TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); } if (dir) free((char *)dir); if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) td->td_maxsamplevalue = (1L<td_bitspersample)-1; /* * Setup default compression scheme. */ if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); /* * Reinitialize i/o since we are starting on a new directory. */ tif->tif_row = -1; tif->tif_curstrip = -1; tif->tif_col = -1; tif->tif_curtile = -1; tif->tif_tilesize = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); return (1); bad: if (dir) free((char *)dir); return (0); } static EstimateStripByteCounts(tif, dir, dircount) TIFF *tif; TIFFDirEntry *dir; u_int dircount; { register TIFFDirEntry *dp; register TIFFDirectory *td = &tif->tif_dir; register int n; td->td_stripbytecount = (u_long *) CheckMalloc(tif, sizeof (u_long), "for \"StripByteCounts\" array"); if (td->td_compression != COMPRESSION_NONE) { u_long space = sizeof (TIFFHeader) + sizeof (short) + (dircount * sizeof (TIFFDirEntry)) + sizeof (long); long filesize = TIFFGetFileSize(tif->tif_fd); /* calculate amount of space used by indirect values */ for (dp = dir, n = dircount; n > 0; n--, dp++) { int cc = dp->tdir_count * tiffDataWidth[dp->tdir_type]; if (cc > sizeof (long)) space += cc; } td->td_stripbytecount[0] = filesize - space; /* * This gross hack handles the case were the offset to * the strip is past the place where we think the strip * should begin. Since a strip of data must be contiguous, * it's safe to assume that we've overestimated the amount * of data in the strip and trim this number back accordingly. */ if (td->td_stripoffset[0] + td->td_stripbytecount[0] > filesize) td->td_stripbytecount[0] = filesize - td->td_stripoffset[0]; } else { u_long rowbytes = howmany(td->td_bitspersample * td->td_samplesperpixel * td->td_imagewidth, 8); td->td_stripbytecount[0] = td->td_imagelength * rowbytes; } TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) td->td_rowsperstrip = td->td_imagelength; } static MissingRequired(tif, tagname) TIFF *tif; char *tagname; { TIFFError(tif->tif_name, "TIFF directory is missing required \"%s\" field", tagname); } /* * Check the count field of a directory * entry against a known value. The caller * is expected to skip/ignore the tag if * there is a mismatch. */ static CheckDirCount(tif, dir, count) TIFF *tif; TIFFDirEntry *dir; u_long count; { if (count != dir->tdir_count) { TIFFWarning(tif->tif_name, "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", TIFFFieldWithTag(dir->tdir_tag)->field_name, dir->tdir_count, count); return (0); } return (1); } /* * Fetch a contiguous directory item. */ static TIFFFetchData(tif, dir, cp) TIFF *tif; TIFFDirEntry *dir; char *cp; { int cc, w; w = tiffDataWidth[dir->tdir_type]; cc = dir->tdir_count * w; if (!isMapped(tif)) { if (!SeekOK(tif->tif_fd, dir->tdir_offset)) goto bad; if (!ReadOK(tif->tif_fd, cp, cc)) goto bad; #ifdef MMAP_SUPPORT } else { if (dir->tdir_offset + cc > tif->tif_size) goto bad; bcopy(tif->tif_base + dir->tdir_offset, cp, cc); #endif } if (tif->tif_flags & TIFF_SWAB) { switch (dir->tdir_type) { case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((u_short *)cp, dir->tdir_count); break; case TIFF_LONG: case TIFF_SLONG: case TIFF_FLOAT: TIFFSwabArrayOfLong((u_long *)cp, dir->tdir_count); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: TIFFSwabArrayOfLong((u_long *)cp, 2*dir->tdir_count); break; } } return (cc); bad: TIFFError(tif->tif_name, "Error fetching data for field \"%s\"", TIFFFieldWithTag(dir->tdir_tag)->field_name); return (0); } /* * Fetch an ASCII item from the file. */ static TIFFFetchString(tif, dir, cp) TIFF *tif; TIFFDirEntry *dir; char *cp; { if (dir->tdir_count <= 4) { u_long l = dir->tdir_offset; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&l); bcopy(&l, cp, dir->tdir_count); return (1); } return (TIFFFetchData(tif, dir, cp)); } /* * Convert numerator+denominator to float. */ static int cvtRational(tif, dir, num, denom, rv) TIFF *tif; TIFFDirEntry *dir; u_long num, denom; float *rv; { if (denom == 0) { TIFFError(tif->tif_name, "%s: Rational with zero denominator (num = %lu)", TIFFFieldWithTag(dir->tdir_tag)->field_name, num); return (0); } else { if (dir->tdir_type == TIFF_RATIONAL) *rv = ((float)num / (float)denom); else *rv = ((float)(long)num / (float)(long)denom); return (1); } } /* * Fetch a rational item from the file * at offset off and return the value * as a floating point number. */ static float TIFFFetchRational(tif, dir) TIFF *tif; TIFFDirEntry *dir; { u_long l[2]; float v; return (!TIFFFetchData(tif, dir, (char *)l) || !cvtRational(tif, dir, l[0], l[1], &v) ? 1. : v); } /* * Fetch a single floating point value * from the offset field and return it * as a native float. */ static float TIFFFetchFloat(tif, dir) TIFF *tif; TIFFDirEntry *dir; { float v = (float) TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); TIFFCvtIEEEFloatToNative(tif, 1, &v); return (v); } /* * Fetch an array of BYTE or SBYTE values. */ static TIFFFetchByteArray(tif, dir, v) TIFF *tif; TIFFDirEntry *dir; u_short v[]; { if (dir->tdir_count <= 4) { /* * Extract data from offset field. */ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset & 0xff; case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; case 1: v[0] = dir->tdir_offset >> 24; } } else { switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset >> 24; case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; case 1: v[0] = dir->tdir_offset & 0xff; } } return (1); } else return (TIFFFetchData(tif, dir, (char *)v)); /* XXX */ } /* * Fetch an array of SHORT or SSHORT values. */ static TIFFFetchShortArray(tif, dir, v) TIFF *tif; TIFFDirEntry *dir; u_short v[]; { if (dir->tdir_count <= 2) { if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { switch (dir->tdir_count) { case 2: v[1] = dir->tdir_offset & 0xffff; case 1: v[0] = dir->tdir_offset >> 16; } } else { switch (dir->tdir_count) { case 2: v[1] = dir->tdir_offset >> 16; case 1: v[0] = dir->tdir_offset & 0xffff; } } return (1); } else return (TIFFFetchData(tif, dir, (char *)v)); } /* * Fetch an array of LONG or SLONG values. */ static TIFFFetchLongArray(tif, dir, v) TIFF *tif; TIFFDirEntry *dir; u_long v[]; { if (dir->tdir_count == 1) { v[0] = dir->tdir_offset; return (1); } else return (TIFFFetchData(tif, dir, (char *)v)); } /* * Fetch an array of RATIONAL or SRATIONAL values. */ static TIFFFetchRationalArray(tif, dir, v) TIFF *tif; TIFFDirEntry *dir; float v[]; { int ok = 0; u_long *l; l = (u_long *)CheckMalloc(tif, dir->tdir_count*tiffDataWidth[dir->tdir_type], "to fetch array of rationals"); if (l) { if (TIFFFetchData(tif, dir, (char *)l)) { u_long i; for (i = 0; i < dir->tdir_count; i++) { ok = cvtRational(tif, dir, l[2*i+0], l[2*i+1], &v[i]); if (!ok) break; } } free((char *)l); } return (ok); } /* * Fetch an array of FLOAT values. */ static TIFFFetchFloatArray(tif, dir, v) TIFF *tif; TIFFDirEntry *dir; float v[]; { if (TIFFFetchData(tif, dir, (char *)v)) { TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); return (1); } else return (0); } /* * Fetch a tag that is not handled by special case code. * * NB: DOUBLE and UNDEFINED types are not handled. */ static TIFFFetchNormalTag(tif, dp) TIFF *tif; TIFFDirEntry *dp; { static char mesg[] = "to fetch tag value"; int ok = 0; if (dp->tdir_count > 1) { /* array of values */ char *cp = NULL; switch (dp->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: /* NB: always expand BYTE values to shorts */ cp = CheckMalloc(tif, dp->tdir_count * sizeof (u_short), mesg); ok = cp && TIFFFetchByteArray(tif, dp, (u_short *)cp); break; case TIFF_SHORT: case TIFF_SSHORT: cp = CheckMalloc(tif, dp->tdir_count * sizeof (u_short), mesg); ok = cp && TIFFFetchShortArray(tif, dp, (u_short *)cp); break; case TIFF_LONG: case TIFF_SLONG: cp = CheckMalloc(tif, dp->tdir_count * sizeof (u_long), mesg); ok = cp && TIFFFetchLongArray(tif, dp, (u_long *)cp); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: cp = CheckMalloc(tif, dp->tdir_count * sizeof (float), mesg); ok = cp && TIFFFetchRationalArray(tif, dp, (float *)cp); break; case TIFF_FLOAT: cp = CheckMalloc(tif, dp->tdir_count * sizeof (float), mesg); ok = cp && TIFFFetchFloatArray(tif, dp, (float *)cp); break; case TIFF_ASCII: /* * Some vendors write strings w/o the trailing * NULL byte, so always append one just in case. */ cp = CheckMalloc(tif, dp->tdir_count+1, mesg); if (ok = (cp && TIFFFetchString(tif, dp, cp))) cp[dp->tdir_count] = '\0'; /* XXX */ break; } if (ok) ok = TIFFSetField(tif, dp->tdir_tag, cp); if (cp != NULL) free(cp); } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ char c[2]; switch (dp->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: case TIFF_SHORT: case TIFF_SSHORT: ok = TIFFSetField(tif, dp->tdir_tag, (int) TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)); break; case TIFF_LONG: case TIFF_SLONG: ok = TIFFSetField(tif, dp->tdir_tag, (u_long) TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: ok = TIFFSetField(tif, dp->tdir_tag, TIFFFetchRational(tif, dp)); break; case TIFF_FLOAT: ok = TIFFSetField(tif, dp->tdir_tag, TIFFFetchFloat(tif, dp)); break; case TIFF_ASCII: if (ok = (TIFFFetchString(tif, dp, c))) { c[1] = '\0'; /* XXX paranoid */ ok = TIFFSetField(tif, dp->tdir_tag, c); } break; } } return (ok); } /* * Fetch samples/pixel short values for * the specified tag and verify that * all values are the same. */ static TIFFFetchPerSampleShorts(tif, dir, pl) TIFF *tif; TIFFDirEntry *dir; long *pl; { u_short v[4]; int samples = tif->tif_dir.td_samplesperpixel; if (CheckDirCount(tif, dir, (u_long)samples) && TIFFFetchShortArray(tif, dir, v)) { int i; for (i = 1; i < samples; i++) if (v[i] != v[0]) { TIFFError(tif->tif_name, "Cannot handle different per-sample values for field \"%s\"", TIFFFieldWithTag(dir->tdir_tag)->field_name); return (0); } *pl = v[0]; return (1); } return (0); } /* * Fetch a set of offsets or lengths. * While this routine says "strips", * in fact it's also used for tiles. */ static TIFFFetchStripThing(tif, dir, nstrips, lpp) TIFF *tif; TIFFDirEntry *dir; long nstrips; u_long **lpp; { register u_long *lp; int status; if (!CheckDirCount(tif, dir, nstrips)) return (0); /* * Allocate space for strip information. */ if (*lpp == NULL && (*lpp = (u_long *)CheckMalloc(tif, nstrips * sizeof (u_long), "for strip array")) == NULL) return (0); lp = *lpp; if (dir->tdir_type == (int)TIFF_SHORT) { /* * Handle short->long expansion. */ u_short *dp = (u_short *)CheckMalloc(tif, dir->tdir_count* sizeof (u_short), "to fetch strip tag"); if (dp == NULL) return (0); if (status = TIFFFetchShortArray(tif, dir, dp)) { register u_short *wp = dp; while (nstrips-- > 0) *lp++ = *wp++; } free((char *)dp); } else status = TIFFFetchLongArray(tif, dir, lp); return (status); } #ifdef COLORIMETRY_SUPPORT static TIFFFetchRefBlackWhite(tif, dir) TIFF *tif; TIFFDirEntry *dir; { static char mesg[] = "for \"ReferenceBlackWhite\" array"; char *cp; int ok; if (!CheckDirCount(tif, dir, 2*tif->tif_dir.td_samplesperpixel)) return (0); if (dir->tdir_type == TIFF_RATIONAL) return (TIFFFetchNormalTag(tif, dir)); /* * Handle LONG's for backward compatibility. */ cp = CheckMalloc(tif, dir->tdir_count * sizeof (u_long), mesg); if (ok = (cp && TIFFFetchLongArray(tif, dir, (u_long *)cp))) { float *fp = (float *) CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg); if (ok = (fp != NULL)) { int i; for (i = 0; i < dir->tdir_count; i++) fp[i] = (float)((u_long *)cp)[i]; ok = TIFFSetField(tif, dir->tdir_tag, fp); free((char *)fp); } } if (cp) free(cp); return (ok); } #endif #ifdef JPEG_SUPPORT /* * Fetch the JPEG Quantization tables * for the specified directory entry. * Storage for the td_qtab array is * allocated as a side effect. */ static TIFFFetchJPEGQTables(tif, dir) TIFF *tif; TIFFDirEntry *dir; { TIFFDirectory *td = &tif->tif_dir; long off[4]; int i, j; TIFFDirEntry tdir; char *qmat; if (dir->tdir_count > 1) { /* XXX verify count <= 4 */ if (!TIFFFetchData(tif, dir, (char *)off)) return (0); } else off[0] = dir->tdir_offset; /* * We don't share per-component q matrices because * (besides complicating this logic even more), it * would make it very painful if the user does a ``set''. */ td->td_qtab = (u_char **)CheckMalloc(tif, dir->tdir_count*(sizeof (u_char *) + 64*sizeof (u_char)), "for JPEG Q table"); if (td->td_qtab == NULL) return (0); tdir.tdir_type = TIFF_BYTE; tdir.tdir_count = 64; qmat = (((char *)td->td_qtab) + dir->tdir_count*sizeof (u_char *)); for (i = 0; i < dir->tdir_count; i++) { td->td_qtab[i] = (u_char *)qmat; tdir.tdir_offset = off[i]; if (!TIFFFetchData(tif, &tdir, qmat)) return (0); qmat += 64*sizeof (u_char); } return (1); } /* * Fetch JPEG Huffman code tables for the * specified directory entry. Storage for * the tables are allocated as a side effect. */ static TIFFFetchJPEGCTables(tif, dir, ptab) TIFF *tif; TIFFDirEntry *dir; u_char ***ptab; { long off[4]; int i, j, ncodes; TIFFDirEntry tdir; char *tab; if (dir->tdir_count > 1) { /* XXX verify count <= 4 */ if (!TIFFFetchData(tif, dir, (char *)off)) return (0); } else off[0] = dir->tdir_offset; /* * We don't share per-component tables because * (besides complicating this logic even more), it * would make it very painful if the user does a * ``set''. Note also that we don't try to optimize * storage of the tables -- we just allocate enough * space to hold the largest possible. All this * stuff is so complicated 'cuz the tag is defined * to be compatible with the JPEG table format, * rather than something that fits well into the * structure of TIFF -- argh! */ *ptab = (u_char **)CheckMalloc(tif, dir->tdir_count* (sizeof (u_char *) + (16+256)*sizeof (u_char)), "for JPEG Huffman table"); if (*ptab == NULL) return (0); tdir.tdir_type = TIFF_BYTE; tab = (((char *)*ptab) + dir->tdir_count*sizeof (u_char *)); for (i = 0; i < dir->tdir_count; i++) { (*ptab)[i] = (u_char *)tab; tdir.tdir_offset = off[i]; tdir.tdir_count = 16; /* * We must fetch the array that holds the * count of codes for each bit length first * and the count up the number of codes that * are in the variable length table. This * information is implicit in the JPEG format * 'cuz it's preceded by a length field. */ if (!TIFFFetchData(tif, &tdir, tab)) /* count array */ return (0); for (ncodes = 0, j = 0; j < 16; j++) ncodes += tab[j]; /* * Adjust offsets and fetch codes separately. */ tdir.tdir_offset += 16; tdir.tdir_count = ncodes; tab += 16; if (!TIFFFetchData(tif, &tdir, tab)) return (0); tab += ncodes; } return (1); } #endif /* * Accept matteing-only ExtraSamples tag. */ static TIFFFetchExtraSamples(tif, dp) TIFF *tif; TIFFDirEntry *dp; { int type; if (dp->tdir_count != 1) { TIFFError(tif->tif_name, "Can not handle more than 1 extra sample/pixel"); return (0); } type = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (type != EXTRASAMPLE_ASSOCALPHA) { TIFFError(tif->tif_name, "Can only handle associated-alpha extra samples"); return (0); } return (TIFFSetField(tif, TIFFTAG_MATTEING, 1)); } oc(tif, dp->tdir_count * sizeof (u_short), mesg); ok = cp && TIFFFetchByteArray(tif, dp, (u_short *)cp); break; case TIFF_SHORT: case TIFF_SSHORT: cp = CheckMalloc(tif, dp->tdir_count * sizeof (u_short), mesg); ok = cp && TIFFFetchShortArray(tif, dp, (u_short *)cp); break; case TIFF_LONG: case TIFF_Sxloadimage.4.1/tiff/tif_dirwrite.c 664 221 144 52744 5461577445 12404 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_dirwrite.c,v 1.16 92/03/18 09:36:15 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Directory Write Support Routines. * * NB: Beware of the varargs declarations for routines in * this file. The names and types of variables has been * carefully chosen to make things work with compilers that * are busted in one way or another (e.g. SGI/MIPS). */ #include "tiffioP.h" #include "prototypes.h" #if HAVE_IEEEFP #define TIFFCvtNativeToIEEEFloat(tif, n, fp) #endif #if USE_PROTOTYPES static TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, TIFFFieldInfo*); static TIFFSetupShortLong(TIFF *, u_short, TIFFDirEntry *, u_long); static TIFFSetupShortPair(TIFF *, u_short, TIFFDirEntry *); static TIFFWriteRational(TIFF *, TIFFDataType, u_short, TIFFDirEntry *, float); static TIFFWritePerSampleShorts(TIFF *, u_short, TIFFDirEntry *); static TIFFWriteShortTable(TIFF *, u_short, TIFFDirEntry *, int, u_short **); static TIFFWriteShortArray(TIFF *, TIFFDataType, u_short, TIFFDirEntry *, int, u_short *); static TIFFWriteLongArray(TIFF *, TIFFDataType, u_short, TIFFDirEntry *, int, u_long *); static TIFFWriteRationalArray(TIFF *, TIFFDataType, u_short, TIFFDirEntry *, int, float *); static TIFFWriteFloatArray(TIFF *, TIFFDataType, u_short, TIFFDirEntry *, int, float *); static TIFFWriteString(TIFF *, u_short, TIFFDirEntry *, char *); #ifdef JPEG_SUPPORT static TIFFWriteJPEGQTables(TIFF *, TIFFDirEntry *); static TIFFWriteJPEGCTables(TIFF *, u_short, TIFFDirEntry *, u_char **); #endif #ifdef COLORIMETRY_SUPPORT static TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); #endif static TIFFWriteData(TIFF *, TIFFDirEntry *, char *); static TIFFLinkDirectory(TIFF *); #else static TIFFWriteNormalTag(); static TIFFSetupShortLong(); static TIFFSetupShortPair(); static TIFFWriteRational(); static TIFFWritePerSampleShorts(); static TIFFWriteShortTable(); static TIFFWriteShortArray(); static TIFFWriteLongArray(); static TIFFWriteRationalArray(); static TIFFWriteFloatArray(); static TIFFWriteString(); #ifdef JPEG_SUPPORT static TIFFWriteJPEGQTables(); static TIFFWriteJPEGCTables(); #endif static TIFFWriteData(); static TIFFLinkDirectory(); #endif #define WriteRationalPair(type, tag1, v1, tag2, v2) { \ if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \ goto bad; \ if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \ goto bad; \ dir++; \ } static long dataoff; /* * Write the contents of the current directory * to the specified file. This routine doesn't * handle overwriting a directory with auxiliary * storage that's been changed. */ TIFFWriteDirectory(tif) TIFF *tif; { short dircount, tag; int nfields, dirsize; char *data; TIFFFieldInfo *fip; TIFFDirEntry *dir; TIFFDirectory *td; u_long b, fields[sizeof (td->td_fieldsset) / sizeof (u_long)]; if (tif->tif_mode == O_RDONLY) return (1); /* * Clear write state so that subsequent images with * different characteristics get the right buffers * setup for them. */ if (tif->tif_flags & TIFF_POSTENCODE) { tif->tif_flags &= ~TIFF_POSTENCODE; if (tif->tif_postencode && !(*tif->tif_postencode)(tif)) { TIFFError(tif->tif_name, "Error post-encoding before directory write"); return (0); } } if (tif->tif_close) (*tif->tif_close)(tif); if (tif->tif_cleanup) (*tif->tif_cleanup)(tif); /* * Flush any data that might have been written * by the compression close+cleanup routines. */ if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) { TIFFError(tif->tif_name, "Error flushing data before directory write"); return (0); } if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { free(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawcc = 0; } tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); td = &tif->tif_dir; /* * Size the directory so that we can calculate * offsets for the data items that aren't kept * in-place in each field. */ nfields = 0; for (b = 0; b <= FIELD_LAST; b++) if (TIFFFieldSet(tif, b)) nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); dirsize = nfields * sizeof (TIFFDirEntry); data = malloc(dirsize); if (data == NULL) { TIFFError(tif->tif_name, "Cannot write directory, out of space"); return (0); } /* * Directory hasn't been placed yet, put * it at the end of the file and link it * into the existing directory structure. */ if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) return (0); dataoff = tif->tif_diroff + sizeof (short) + dirsize + sizeof (long); if (dataoff & 1) dataoff++; (void) lseek(tif->tif_fd, dataoff, L_SET); tif->tif_curdir++; dir = (TIFFDirEntry *)data; /* * Setup external form of directory * entries and write data items. */ bcopy(td->td_fieldsset, fields, sizeof (fields)); /*BEGIN XXX*/ /* * Write out ExtraSamples tag only if Matteing would * be set to 1 (i.e. Associated Alpha data is present). */ if (FieldSet(fields, FIELD_MATTEING) && !td->td_matteing) { /*XXX*/ ResetFieldBit(fields, FIELD_MATTEING); /*XXX*/ nfields--; /*XXX*/ dirsize -= sizeof (TIFFDirEntry); /*XXX*/ } /*XXX*/ /*END XXX*/ for (fip = tiffFieldInfo; fip->field_tag; fip++) { if (fip->field_bit == FIELD_IGNORE || !FieldSet(fields, fip->field_bit)) continue; switch (fip->field_bit) { case FIELD_STRIPOFFSETS: /* * We use one field bit for both strip and tile * offsets, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = isTiled(tif) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; if (tag != fip->field_tag) continue; if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, (int) td->td_nstrips, td->td_stripoffset)) goto bad; break; case FIELD_STRIPBYTECOUNTS: /* * We use one field bit for both strip and tile * byte counts, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = isTiled(tif) ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; if (tag != fip->field_tag) continue; if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, (int) td->td_nstrips, td->td_stripbytecount)) goto bad; break; case FIELD_COLORMAP: if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, 3, td->td_colormap)) goto bad; break; case FIELD_IMAGEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, dir++, td->td_imagewidth); TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, dir, td->td_imagelength); break; case FIELD_TILEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, dir++, td->td_tilewidth); TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, dir, td->td_tilelength); break; case FIELD_POSITION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XPOSITION, td->td_xposition, TIFFTAG_YPOSITION, td->td_yposition); break; case FIELD_RESOLUTION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XRESOLUTION, td->td_xresolution, TIFFTAG_YRESOLUTION, td->td_yresolution); break; case FIELD_BITSPERSAMPLE: case FIELD_MINSAMPLEVALUE: case FIELD_MAXSAMPLEVALUE: case FIELD_SAMPLEFORMAT: if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) goto bad; break; case FIELD_PAGENUMBER: case FIELD_HALFTONEHINTS: #ifdef YCBCR_SUPPORT case FIELD_YCBCRSUBSAMPLING: #endif #ifdef CMYK_SUPPORT case FIELD_DOTRANGE: #endif TIFFSetupShortPair(tif, fip->field_tag, dir); break; #ifdef JPEG_SUPPORT case FIELD_JPEGQTABLES: if (!TIFFWriteJPEGQTables(tif, dir)) goto bad; break; case FIELD_JPEGDCTABLES: if (!TIFFWriteJPEGCTables(tif, TIFFTAG_JPEGDCTABLES, dir, td->td_dctab)) goto bad; break; case FIELD_JPEGACTABLES: if (!TIFFWriteJPEGCTables(tif, TIFFTAG_JPEGACTABLES, dir, td->td_actab)) goto bad; break; #endif #ifdef COLORIMETRY_SUPPORT case FIELD_REFBLACKWHITE: if (!TIFFWriteRationalArray(tif, TIFF_RATIONAL, TIFFTAG_REFERENCEBLACKWHITE, dir, 2*td->td_samplesperpixel, td->td_refblackwhite)) goto bad; break; case FIELD_TRANSFERFUNCTION: if (!TIFFWriteTransferFunction(tif, dir)) goto bad; break; #endif default: if (!TIFFWriteNormalTag(tif, dir, fip)) goto bad; break; } dir++; ResetFieldBit(fields, fip->field_bit); } /* * Write directory. */ (void) lseek(tif->tif_fd, tif->tif_diroff, L_SET); dircount = nfields; if (!WriteOK(tif->tif_fd, &dircount, sizeof (short))) { TIFFError(tif->tif_name, "Error writing directory count"); goto bad; } if (!WriteOK(tif->tif_fd, data, dirsize)) { TIFFError(tif->tif_name, "Error writing directory contents"); goto bad; } if (!WriteOK(tif->tif_fd, &tif->tif_nextdiroff, sizeof (long))) { TIFFError(tif->tif_name, "Error writing directory link"); goto bad; } TIFFFreeDirectory(tif); free(data); tif->tif_flags &= ~TIFF_DIRTYDIRECT; /* * Reset directory-related state for subsequent * directories. */ TIFFDefaultDirectory(tif); tif->tif_diroff = 0; tif->tif_curoff = 0; tif->tif_row = -1; tif->tif_curstrip = -1; return (1); bad: free(data); return (0); } #undef WriteRationalPair /* * Process tags that are not special cased. */ static DECLARE3(TIFFWriteNormalTag, TIFF*, tif, TIFFDirEntry*, dir, TIFFFieldInfo*, fip) { TIFFDirectory* td = &tif->tif_dir; u_short wc = (u_short) fip->field_writecount; dir->tdir_tag = fip->field_tag; dir->tdir_type = (u_short)fip->field_type; dir->tdir_count = wc; #define WRITE(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y) switch (fip->field_type) { case TIFF_SHORT: case TIFF_SSHORT: if (wc > 1) { u_short *wp; if (wc == (u_short) TIFF_VARIABLE) { _TIFFgetfield(td, fip->field_tag, &wc, &wp); dir->tdir_count = wc; } else _TIFFgetfield(td, fip->field_tag, &wp); if (!WRITE(TIFFWriteShortArray, wp)) return (0); } else { u_short sv; _TIFFgetfield(td, fip->field_tag, &sv); dir->tdir_offset = TIFFInsertData(tif, dir->tdir_type, sv); } break; case TIFF_LONG: case TIFF_SLONG: if (wc > 1) { u_long *lp; if (wc == (u_short) TIFF_VARIABLE) { _TIFFgetfield(td, fip->field_tag, &wc, &lp); dir->tdir_count = wc; } else _TIFFgetfield(td, fip->field_tag, &lp); if (!WRITE(TIFFWriteLongArray, lp)) return (0); } else { /* XXX handle LONG->SHORT conversion */ _TIFFgetfield(td, fip->field_tag, &dir->tdir_offset); } break; case TIFF_RATIONAL: case TIFF_SRATIONAL: if (wc > 1) { float *fp; if (wc == (u_short) TIFF_VARIABLE) { _TIFFgetfield(td, fip->field_tag, &wc, &fp); dir->tdir_count = wc; } else _TIFFgetfield(td, fip->field_tag, &fp); if (!WRITE(TIFFWriteRationalArray, fp)) return (0); } else { float fv; _TIFFgetfield(td, fip->field_tag, &fv); if (!TIFFWriteRational(tif, fip->field_type, fip->field_tag, dir, fv)) return (0); } break; case TIFF_FLOAT: if (wc > 1) { float *fp; if (wc == (u_short) TIFF_VARIABLE) { _TIFFgetfield(td, fip->field_tag, &wc, &fp); dir->tdir_count = wc; } else _TIFFgetfield(td, fip->field_tag, &fp); if (!WRITE(TIFFWriteFloatArray, fp)) return (0); } else { float fv; _TIFFgetfield(td, fip->field_tag, &fv); TIFFCvtNativeToIEEEFloat(tif, 1, &fv); /* XXX assumes sizeof (long) == sizeof (float) */ dir->tdir_offset = *(u_long *)&fv; /* XXX */ } break; case TIFF_ASCII: { char *cp; _TIFFgetfield(td, fip->field_tag, &cp); if (!TIFFWriteString(tif, fip->field_tag, dir, cp)) return (0); break; } } return (1); } #undef WRITE /* * Setup a directory entry with either a SHORT * or LONG type according to the value. */ static DECLARE4(TIFFSetupShortLong, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir, u_long, v) { dir->tdir_tag = tag; dir->tdir_count = 1; if (v > 0xffffL) { dir->tdir_type = (short)TIFF_LONG; dir->tdir_offset = v; } else { dir->tdir_type = (short)TIFF_SHORT; dir->tdir_offset = TIFFInsertData(tif, (int)TIFF_SHORT, v); } } #undef MakeShortDirent /* * Setup a RATIONAL directory entry and * write the associated indirect value. */ static DECLARE5(TIFFWriteRational, TIFF*, tif, TIFFDataType, type, u_short, tag, TIFFDirEntry*, dir, float, v) { u_long t[2]; dir->tdir_tag = tag; dir->tdir_type = (short)type; dir->tdir_count = 1; if (type == TIFF_RATIONAL && v < 0) TIFFWarning(tif->tif_name, "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", TIFFFieldWithTag(tag)->field_name, v); /* need algorithm to convert ... XXX */ t[0] = v*10000.0 + 0.5; t[1] = 10000; return (TIFFWriteData(tif, dir, (char *)t)); } /* * Setup a directory entry that references a * samples/pixel array of SHORT values and * (potentially) write the associated indirect * values. */ static DECLARE3(TIFFWritePerSampleShorts, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir) { u_short w[4], v; int i, samplesperpixel = tif->tif_dir.td_samplesperpixel; _TIFFgetfield(&tif->tif_dir, tag, &v); for (i = 0; i < samplesperpixel; i++) w[i] = v; return (TIFFWriteShortArray( tif, TIFF_SHORT, tag, dir, samplesperpixel, w)); } /* * Setup a pair of shorts that are returned by * value, rather than as a reference to an array. */ static DECLARE3(TIFFSetupShortPair, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir) { u_short v[2]; _TIFFgetfield(&tif->tif_dir, tag, &v[0], &v[1]); return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v)); } /* * Setup a directory entry for an NxM table of shorts, * where M is known to be 2**bitspersample, and write * the associated indirect data. */ static DECLARE5(TIFFWriteShortTable, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir, int, n, u_short**, table) { u_long off; int i; dir->tdir_tag = tag; dir->tdir_type = (short)TIFF_SHORT; /* XXX -- yech, fool TIFFWriteData */ dir->tdir_count = 1L<tif_dir.td_bitspersample; off = dataoff; for (i = 0; i < n; i++) if (!TIFFWriteData(tif, dir, (char *)table[i])) return (0); dir->tdir_count *= n; dir->tdir_offset = off; return (1); } /* * Setup a directory entry of an ASCII string * and write any associated indirect value. */ static DECLARE4(TIFFWriteString, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir, char*, cp) { dir->tdir_tag = tag; dir->tdir_type = (short)TIFF_ASCII; dir->tdir_count = strlen(cp) + 1; /* includes \0 byte */ if (dir->tdir_count > 4) { if (!TIFFWriteData(tif, dir, cp)) return (0); } else bcopy(cp, &dir->tdir_offset, dir->tdir_count); return (1); } /* * Setup a directory entry of an array of SHORT * or SSHORT and write the associated indirect values. */ static DECLARE6(TIFFWriteShortArray, TIFF*, tif, TIFFDataType, type, u_short, tag, TIFFDirEntry*, dir, int, n, u_short*, v) { dir->tdir_tag = tag; dir->tdir_type = (short)type; dir->tdir_count = n; if (n <= 2) { if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { dir->tdir_offset = (long)v[0] << 16; if (n == 2) dir->tdir_offset |= v[1] & 0xffff; } else { dir->tdir_offset = v[0] & 0xffff; if (n == 2) dir->tdir_offset |= (long)v[1] << 16; } return (1); } else return (TIFFWriteData(tif, dir, (char *)v)); } /* * Setup a directory entry of an array of LONG * or SLONG and write the associated indirect values. */ static DECLARE6(TIFFWriteLongArray, TIFF*, tif, TIFFDataType, type, u_short, tag, TIFFDirEntry*, dir, int, n, u_long*, v) { dir->tdir_tag = tag; dir->tdir_type = (short)type; dir->tdir_count = n; if (n == 1) { dir->tdir_offset = v[0]; return (1); } else return (TIFFWriteData(tif, dir, (char *)v)); } /* * Setup a directory entry of an array of RATIONAL * or SRATIONAL and write the associated indirect values. */ static DECLARE6(TIFFWriteRationalArray, TIFF*, tif, TIFFDataType, type, u_short, tag, TIFFDirEntry*, dir, int, n, float*, v) { int i, status; u_long *t; dir->tdir_tag = tag; dir->tdir_type = (short)type; dir->tdir_count = n; t = (u_long *)malloc(2*n * sizeof (long)); for (i = 0; i < n; i++) { /* need algorithm to convert ... XXX */ t[2*i+0] = v[i]*10000.0 + 0.5; t[2*i+1] = 10000; } status = TIFFWriteData(tif, dir, (char *)t); free((char *)t); return (status); } static DECLARE6(TIFFWriteFloatArray, TIFF *, tif, TIFFDataType, type, u_short, tag, TIFFDirEntry *, dir, int, n, float *, v) { dir->tdir_tag = tag; dir->tdir_type = (short)type; dir->tdir_count = n; TIFFCvtNativeToIEEEFloat(tif, n, v); if (n == 1) { dir->tdir_offset = *(u_long *)&v[0]; return (1); } else return (TIFFWriteData(tif, dir, (char *)v)); } #ifdef JPEG_SUPPORT /* * Setup a directory entry for JPEG Quantization * tables and write the associated indirect values. */ static DECLARE2(TIFFWriteJPEGQTables, TIFF*, tif, TIFFDirEntry*, dir) { TIFFDirectory *td = &tif->tif_dir; TIFFDirEntry tdir; u_long off[4]; int i; tdir.tdir_tag = TIFFTAG_JPEGQTABLES; /* for diagnostics */ tdir.tdir_type = (short)TIFF_BYTE; tdir.tdir_count = 64; for (i = 0; i < td->td_samplesperpixel; i++) { if (!TIFFWriteData(tif, &tdir, (char *)td->td_qtab[i])) return (0); off[i] = tdir.tdir_offset; } return (TIFFWriteLongArray(tif, TIFF_LONG, TIFFTAG_JPEGQTABLES, dir, td->td_samplesperpixel, off)); } /* * Setup a directory entry for JPEG Coefficient * tables and write the associated indirect values. */ static DECLARE4(TIFFWriteJPEGCTables, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir, u_char **, tab) { TIFFDirectory *td = &tif->tif_dir; TIFFDirEntry tdir; u_long off[4]; int i, j, ncodes; tdir.tdir_tag = tag; /* for diagnostics */ tdir.tdir_type = (short)TIFF_BYTE; for (i = 0; i < td->td_samplesperpixel; i++) { for (ncodes = 0, j = 0; j < 16; j++) ncodes += tab[i][j]; tdir.tdir_count = 16+ncodes; if (!TIFFWriteData(tif, &tdir, (char *)tab[i])) return (0); off[i] = tdir.tdir_offset; } return (TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, td->td_samplesperpixel, off)); } #endif #ifdef COLORIMETRY_SUPPORT static DECLARE2(TIFFWriteTransferFunction, TIFF*, tif, TIFFDirEntry*, dir) { TIFFDirectory *td = &tif->tif_dir; int j, ncols; u_long n; u_short **tf = td->td_transferfunction; /* * Check if the table can be written as a single column. */ n = (1L<td_bitspersample) * sizeof (u_short); ncols = 1; /* assume only one column is needed */ for (j = 1; j < td->td_samplesperpixel; j++) if (bcmp(tf[0], tf[j], n)) { ncols = td->td_samplesperpixel; break; } return (TIFFWriteShortTable(tif, TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); } #endif /* * Write a contiguous directory item. */ static TIFFWriteData(tif, dir, cp) TIFF *tif; TIFFDirEntry *dir; char *cp; { int cc; dir->tdir_offset = dataoff; cc = dir->tdir_count * tiffDataWidth[dir->tdir_type]; if (SeekOK(tif->tif_fd, dir->tdir_offset) && WriteOK(tif->tif_fd, cp, cc)) { dataoff += (cc + 1) & ~1; return (1); } TIFFError(tif->tif_name, "Error writing data for field \"%s\"", TIFFFieldWithTag(dir->tdir_tag)->field_name); return (0); } /* * Link the current directory into the * directory chain for the file. */ static TIFFLinkDirectory(tif) register TIFF *tif; { static char module[] = "TIFFLinkDirectory"; u_short dircount; long nextdir; tif->tif_diroff = (lseek(tif->tif_fd, 0L, L_XTND)+1) &~ 1L; if (tif->tif_header.tiff_diroff == 0) { /* * First directory, overwrite header. */ tif->tif_header.tiff_diroff = tif->tif_diroff; (void) lseek(tif->tif_fd, 0L, L_SET); if (!WriteOK(tif->tif_fd, &tif->tif_header, sizeof (tif->tif_header))) { TIFFError(tif->tif_name, "Error writing TIFF header"); return (0); } return (1); } /* * Not the first directory, search to the last and append. */ nextdir = tif->tif_header.tiff_diroff; do { if (!SeekOK(tif->tif_fd, nextdir) || !ReadOK(tif->tif_fd, &dircount, sizeof (dircount))) { TIFFError(module, "Error fetching directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); lseek(tif->tif_fd, dircount * sizeof (TIFFDirEntry), L_INCR); if (!ReadOK(tif->tif_fd, &nextdir, sizeof (nextdir))) { TIFFError(module, "Error fetching directory link"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong((u_long *)&nextdir); } while (nextdir != 0); (void) lseek(tif->tif_fd, -sizeof (nextdir), L_INCR); if (!WriteOK(tif->tif_fd, &tif->tif_diroff, sizeof (tif->tif_diroff))) { TIFFError(module, "Error writing directory link"); return (0); } return (1); } & v < 0) TIFFWarning(tif->xloadimage.4.1/tiff/tif_dumpmode.c 664 221 144 10015 5461577445 12346 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_dumpmode.c,v 1.23 92/02/10 19:06:35 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * "Null" Compression Algorithm Support. */ #include "tiffioP.h" #include #include #if USE_PROTOTYPES static int DumpModeEncode(TIFF *, u_char *, int, u_int); static int DumpModeDecode(TIFF *, u_char *, int, u_int); static int DumpModeSeek(TIFF *, int); #else static int DumpModeEncode(), DumpModeDecode(), DumpModeSeek(); #endif /* * Initialize dump mode. */ TIFFInitDumpMode(tif) register TIFF *tif; { tif->tif_decoderow = DumpModeDecode; tif->tif_decodestrip = DumpModeDecode; tif->tif_decodetile = DumpModeDecode; tif->tif_encoderow = DumpModeEncode; tif->tif_encodestrip = DumpModeEncode; tif->tif_encodetile = DumpModeEncode; tif->tif_seek = DumpModeSeek; return (1); } /* * Encode a hunk of pixels. */ static int DumpModeEncode(tif, pp, cc, s) register TIFF *tif; u_char *pp; int cc; u_int s; { /* * This may be overzealous, but avoids having to * worry about byte alignment for the (potential) * byte-swapping work below. */ if (tif->tif_rawcc + cc > tif->tif_rawdatasize) if (!TIFFFlushData1(tif)) return (-1); while (cc > 0) { int n; if ((n = cc) > tif->tif_rawdatasize) n = tif->tif_rawdatasize; bcopy(pp, tif->tif_rawcp, n); if (tif->tif_flags & TIFF_SWAB) { switch (tif->tif_dir.td_bitspersample) { case 16: assert((n & 3) == 0); TIFFSwabArrayOfShort((u_short *)tif->tif_rawcp, n/2); break; case 32: assert((n & 15) == 0); TIFFSwabArrayOfLong((u_long *)tif->tif_rawcp, n/4); break; } } tif->tif_rawcp += n; tif->tif_rawcc += n; pp += n; cc -= n; if (tif->tif_rawcc >= tif->tif_rawdatasize && !TIFFFlushData1(tif)) return (-1); } return (1); } /* * Decode a hunk of pixels. */ static int DumpModeDecode(tif, buf, cc, s) register TIFF *tif; u_char *buf; int cc; u_int s; { if (tif->tif_rawcc < cc) { TIFFError(tif->tif_name, "DumpModeDecode: Not enough data for scanline %d", tif->tif_row); return (0); } /* * Avoid copy if client has setup raw * data buffer to avoid extra copy. */ if (tif->tif_rawcp != (char*) buf) bcopy(tif->tif_rawcp, buf, cc); if (tif->tif_flags & TIFF_SWAB) { switch (tif->tif_dir.td_bitspersample) { case 16: assert((cc & 3) == 0); TIFFSwabArrayOfShort((u_short *)buf, cc/2); break; case 32: assert((cc & 15) == 0); TIFFSwabArrayOfLong((u_long *)buf, cc/4); break; } } tif->tif_rawcp += cc; tif->tif_rawcc -= cc; return (1); } /* * Seek forwards nrows in the current strip. */ static int DumpModeSeek(tif, nrows) register TIFF *tif; int nrows; { tif->tif_rawcp += nrows * tif->tif_scanlinesize; tif->tif_rawcc -= nrows * tif->tif_scanlinesize; return (1); } .tdir_offset; } return (TIFFWriteLongArray(tif, TIFF_LONG, TIFFTAG_JPEGQTABLES, dir, td->td_samplesperpixel, off)); } /* * Setup a directory entry for JPEG Coefficient * tables and write the associated indirect values. */ static DECLARE4(TIFFWriteJPEGCTables, TIFF*, tif, u_short, tag, TIFFDirEntry*, dir, u_char **, tab) { TIFFDirectory *td = &tif->tif_dir; TIFFDirEntry tdir; u_long off[4]; int i, j, ncodes; tdir.tdir_tag = tag; /* for diagnostics */ tdir.tdir_type = (shorxloadimage.4.1/tiff/tif_error.c 664 221 144 4136 5461577445 11654 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_error.c,v 1.13 92/02/10 19:06:34 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. */ #include #include "tiffioP.h" #include "prototypes.h" static void DECLARE3(defaultHandler, char*, module, char*, fmt, va_list, ap) { if (module != NULL) fprintf(stderr, "%s: ", module); vfprintf(stderr, fmt, ap); fprintf(stderr, ".\n"); } static TIFFErrorHandler _errorHandler = defaultHandler; TIFFErrorHandler DECLARE1(TIFFSetErrorHandler, TIFFErrorHandler, handler) { TIFFErrorHandler prev = _errorHandler; _errorHandler = handler; return (prev); } void #if USE_PROTOTYPES TIFFError(char *module, char *fmt, ...) #else /*VARARGS2*/ TIFFError(module, fmt, va_alist) char *module; char *fmt; va_dcl #endif { if (_errorHandler) { va_list ap; VA_START(ap, fmt); (*_errorHandler)(module, fmt, ap); va_end(ap); } } } tif->tif_rawcp += cc; tif->tif_rawcc -= cc; return (1); } /* * Seek forwards nrows in the current strip. */ static int DumpModeSeek(tif, nrows) register TIFF *tif; int nrows; { tif->tif_rawcp += nrows * tif->tif_scanlinesize; tif->tif_rawcc -= nrows * tif->tif_scanlinesize; return (1); } .tdir_offset; } return (TIFFWriteLongArray(tif, TIFF_LONG, TIFFTAG_JPEGQTABLES, dir, td->td_samplesperpixel,xloadimage.4.1/tiff/tif_fax3.c 664 221 144 71035 5461577446 11407 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_fax3.c,v 1.60 92/02/10 19:06:36 sam Exp $"; #endif /* * Copyright (c) 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * CCITT Group 3 and Group 4 Compression Support. */ #include "tiffioP.h" #include #include #include "tif_fax3.h" #define G3CODES #include "t4.h" #define G3STATES #include "g3states.h" typedef struct { Fax3BaseState b; } Fax3DecodeState; typedef struct { Fax3BaseState b; u_char *wruns; u_char *bruns; short k; /* #rows left that can be 2d encoded */ short maxk; /* max #rows that can be 2d encoded */ } Fax3EncodeState; #if USE_PROTOTYPES static Fax3PreDecode(TIFF *); static Fax3Decode(TIFF*, u_char *, int, u_int); static int Fax3Decode1DRow(TIFF*, u_char *, int); static Fax3PreEncode(TIFF *); static Fax3PostEncode(TIFF *); static Fax3Encode(TIFF*, u_char *, int, u_int); static int Fax3Encode1DRow(TIFF *, u_char *, int); static Fax3Close(TIFF *); static Fax3Cleanup(TIFF *); static void *Fax3SetupState(TIFF *, int); static void fillspan(char *, int, int); static int findspan(u_char **, int, int, u_char const *); static int finddiff(u_char *, int, int, int); static void skiptoeol(TIFF *, int); static void putbits(TIFF *, u_int, u_int); static void putcode(TIFF *, tableentry const *); static void putspan(TIFF *, int, tableentry const *); extern int TIFFFlushData1(TIFF *); #else static int Fax3PreEncode(), Fax3Encode(), Fax3PostEncode(); static int Fax3Encode1DRow(); static int Fax3Decode(), Fax3PreDecode(); static int Fax3Decode1DRow(); static int Fax3Close(), Fax3Cleanup(); static void *Fax3SetupState(); static void fillspan(); static int findspan(); static int finddiff(); static void skiptoeol(); static void putbits(); static void putcode(); static void putspan(); extern int TIFFFlushData1(); #endif TIFFInitCCITTFax3(tif) TIFF *tif; { tif->tif_predecode = Fax3PreDecode; tif->tif_decoderow = Fax3Decode; tif->tif_decodestrip = Fax3Decode; tif->tif_decodetile = Fax3Decode; tif->tif_preencode = Fax3PreEncode; tif->tif_postencode = Fax3PostEncode; tif->tif_encoderow = Fax3Encode; tif->tif_encodestrip = Fax3Encode; tif->tif_encodetile = Fax3Encode; tif->tif_close = Fax3Close; tif->tif_cleanup = Fax3Cleanup; tif->tif_options |= FAX3_CLASSF; /* default */ tif->tif_flags |= TIFF_NOBITREV; /* we handle bit reversal */ return (1); } TIFFModeCCITTFax3(tif, isClassF) TIFF *tif; int isClassF; { if (isClassF) tif->tif_options |= FAX3_CLASSF; else tif->tif_options &= ~FAX3_CLASSF; } static u_char bitMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; #define isBitSet(sp) ((sp)->b.data & bitMask[(sp)->b.bit]) #define is2DEncoding(tif) \ (tif->tif_dir.td_group3options & GROUP3OPT_2DENCODING) #define fetchByte(tif, sp) \ ((tif)->tif_rawcc--, (sp)->b.bitmap[*(u_char *)(tif)->tif_rawcp++]) #define BITCASE(b) \ case b: \ code <<= 1; \ if (data & (1<<(7-b))) code |= 1;\ len++; \ if (code > 0) { bit = b+1; break; } /* * Skip over input until an EOL code is found. The * value of len is passed as 0 except during error * recovery when decoding 2D data. Note also that * we don't use the optimized state tables to locate * an EOL because we can't assume much of anything * about our state (e.g. bit position). */ static void skiptoeol(tif, len) TIFF *tif; int len; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; register int bit = sp->b.bit; register int data = sp->b.data; int code = 0; /* * Our handling of ``bit'' is painful because * the rest of the code does not maintain it as * exactly the bit offset in the current data * byte (bit == 0 means refill the data byte). * Thus we have to be careful on entry and * exit to insure that we maintain a value that's * understandable elsewhere in the decoding logic. */ if (bit == 0) /* force refill */ bit = 8; for (;;) { switch (bit) { again: BITCASE(0); BITCASE(1); BITCASE(2); BITCASE(3); BITCASE(4); BITCASE(5); BITCASE(6); BITCASE(7); default: if (tif->tif_rawcc <= 0) return; data = fetchByte(tif, sp); goto again; } if (len >= 12 && code == EOL) break; code = len = 0; } sp->b.bit = bit > 7 ? 0 : bit; /* force refill */ sp->b.data = data; } /* * Return the next bit in the input stream. This is * used to extract 2D tag values and the color tag * at the end of a terminating uncompressed data code. */ static int nextbit(tif) TIFF *tif; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; int bit; if (sp->b.bit == 0 && tif->tif_rawcc > 0) sp->b.data = fetchByte(tif, sp); bit = isBitSet(sp); if (++(sp->b.bit) > 7) sp->b.bit = 0; return (bit); } static void bset(cp, n, v) register unsigned char *cp; register int n; register int v; { while (n-- > 0) *cp++ = v; } /* * Setup G3-related compression/decompression * state before data is processed. This routine * is called once per image -- it sets up different * state based on whether or not 2D encoding is used. */ static void * Fax3SetupState(tif, space) TIFF *tif; int space; { TIFFDirectory *td = &tif->tif_dir; Fax3BaseState *sp; int cc = space; long rowbytes, rowpixels; if (td->td_bitspersample != 1) { TIFFError(tif->tif_name, "Bits/sample must be 1 for Group 3/4 encoding/decoding"); return (0); } /* * Calculate the scanline/tile widths. */ if (isTiled(tif)) { rowbytes = TIFFTileRowSize(tif); rowpixels = tif->tif_dir.td_tilewidth; } else { rowbytes = TIFFScanlineSize(tif); rowpixels = tif->tif_dir.td_imagewidth; } if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4) cc += rowbytes+1; tif->tif_data = malloc(cc); if (tif->tif_data == NULL) { TIFFError("Fax3SetupState", "%s: No space for Fax3 state block", tif->tif_name); return (0); } sp = (Fax3BaseState *)tif->tif_data; sp->rowbytes = rowbytes; sp->rowpixels = rowpixels; sp->bitmap = (tif->tif_fillorder != td->td_fillorder ? TIFFBitRevTable : TIFFNoBitRevTable); sp->white = (td->td_photometric == PHOTOMETRIC_MINISBLACK); if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4) { /* * 2d encoding/decoding requires a scanline * buffer for the ``reference line''; the * scanline against which delta encoding * is referenced. The reference line must * be initialized to be ``white'' (done elsewhere). */ sp->refline = (u_char *)tif->tif_data + space + 1; /* * Initialize pixel just to the left of the * reference line to white. This extra pixel * simplifies the edge-condition logic. */ sp->refline[-1] = sp->white ? 0xff : 0x00; } else sp->refline = 0; return (sp); } /* * Setup state for decoding a strip. */ static Fax3PreDecode(tif) TIFF *tif; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; if (sp == NULL) { sp = (Fax3DecodeState *)Fax3SetupState(tif, sizeof (*sp)); if (!sp) return (0); } sp->b.bit = 0; /* force initial read */ sp->b.data = 0; sp->b.tag = G3_1D; if (sp->b.refline) bset(sp->b.refline, sp->b.rowbytes, sp->b.white ? 0xff : 0x00); /* * If image has EOL codes, they precede each line * of data. We skip over the first one here so that * when we decode rows, we can use an EOL to signal * that less than the expected number of pixels are * present for the scanline. */ if ((tif->tif_options & FAX3_NOEOL) == 0) { skiptoeol(tif, 0); if (is2DEncoding(tif)) /* tag should always be 1D! */ sp->b.tag = nextbit(tif) ? G3_1D : G3_2D; } return (1); } /* * Fill a span with ones. */ static void fillspan(cp, x, count) register char *cp; register int x, count; { static const unsigned char masks[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; if (count <= 0) return; cp += x>>3; if (x &= 7) { /* align to byte boundary */ if (count < 8 - x) { *cp++ |= masks[count] >> x; return; } *cp++ |= 0xff >> x; count -= 8 - x; } while (count >= 8) { *cp++ = 0xff; count -= 8; } *cp |= masks[count]; } /* * Decode the requested amount of data. */ static Fax3Decode(tif, buf, occ, s) TIFF *tif; u_char *buf; int occ; u_int s; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; bzero(buf, occ); /* decoding only sets non-zero bits */ while (occ > 0) { if (sp->b.tag == G3_1D) { if (!Fax3Decode1DRow(tif, buf, sp->b.rowpixels)) return (0); } else { if (!Fax3Decode2DRow(tif, buf, sp->b.rowpixels)) return (0); } if (is2DEncoding(tif)) { /* * Fetch the tag bit that indicates * whether the next row is 1d or 2d * encoded. If 2d-encoded, then setup * the reference line from the decoded * scanline just completed. */ sp->b.tag = nextbit(tif) ? G3_1D : G3_2D; if (sp->b.tag == G3_2D) bcopy(buf, sp->b.refline, sp->b.rowbytes); } buf += sp->b.rowbytes; occ -= sp->b.rowbytes; } return (1); } /* * Decode a run of white. */ static int decode_white_run(tif) TIFF *tif; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; short state = sp->b.bit; short action; int runlen = 0; for (;;) { if (sp->b.bit == 0) { nextbyte: if (tif->tif_rawcc <= 0) return (G3CODE_EOF); sp->b.data = fetchByte(tif, sp); } action = TIFFFax1DAction[state][sp->b.data]; state = TIFFFax1DNextState[state][sp->b.data]; if (action == ACT_INCOMP) goto nextbyte; if (action == ACT_INVALID) return (G3CODE_INVALID); if (action == ACT_EOL) return (G3CODE_EOL); sp->b.bit = state; action = RUNLENGTH(action - ACT_WRUNT); runlen += action; if (action < 64) return (runlen); } /*NOTREACHED*/ } /* * Decode a run of black. */ static int decode_black_run(tif) TIFF *tif; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; short state = sp->b.bit + 8; short action; int runlen = 0; for (;;) { if (sp->b.bit == 0) { nextbyte: if (tif->tif_rawcc <= 0) return (G3CODE_EOF); sp->b.data = fetchByte(tif, sp); } action = TIFFFax1DAction[state][sp->b.data]; state = TIFFFax1DNextState[state][sp->b.data]; if (action == ACT_INCOMP) goto nextbyte; if (action == ACT_INVALID) return (G3CODE_INVALID); if (action == ACT_EOL) return (G3CODE_EOL); sp->b.bit = state; action = RUNLENGTH(action - ACT_BRUNT); runlen += action; if (action < 64) return (runlen); state += 8; } /*NOTREACHED*/ } /* * Process one row of 1d Huffman-encoded data. */ static int Fax3Decode1DRow(tif, buf, npels) TIFF *tif; u_char *buf; int npels; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; int x = 0; int runlen; short action; short color = sp->b.white; static char module[] = "Fax3Decode1D"; for (;;) { if (color == sp->b.white) runlen = decode_white_run(tif); else runlen = decode_black_run(tif); switch (runlen) { case G3CODE_EOF: TIFFError(module, "%s: Premature EOF at scanline %d (x %d)", tif->tif_name, tif->tif_row, x); return (0); case G3CODE_INVALID: /* invalid code */ /* * An invalid code was encountered. * Flush the remainder of the line * and allow the caller to decide whether * or not to continue. Note that this * only works if we have a G3 image * with EOL markers. */ TIFFError(module, "%s: Bad code word at scanline %d (x %d)", tif->tif_name, tif->tif_row, x); goto done; case G3CODE_EOL: /* premature end-of-line code */ TIFFWarning(module, "%s: Premature EOL at scanline %d (x %d)", tif->tif_name, tif->tif_row, x); return (1); /* try to resynchronize... */ } if (x+runlen > npels) runlen = npels-x; if (runlen > 0) { if (color) fillspan((char *)buf, x, runlen); x += runlen; if (x >= npels) break; } color = !color; } done: /* * Cleanup at the end of the row. This convoluted * logic is merely so that we can reuse the code with * two other related compression algorithms (2 & 32771). * * Note also that our handling of word alignment assumes * that the buffer is at least word aligned. This is * the case for most all versions of malloc (typically * the buffer is returned longword aligned). */ if ((tif->tif_options & FAX3_NOEOL) == 0) skiptoeol(tif, 0); if (tif->tif_options & FAX3_BYTEALIGN) sp->b.bit = 0; if ((tif->tif_options & FAX3_WORDALIGN) && ((long)tif->tif_rawcp & 1)) (void) fetchByte(tif, sp); return (x == npels); } /* * Group 3 2d Decoding support. */ /* * Return the next uncompressed mode code word. */ static int decode_uncomp_code(tif) TIFF *tif; { Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; short code; do { if (sp->b.bit == 0 || sp->b.bit > 7) { if (tif->tif_rawcc <= 0) return (UNCOMP_EOF); sp->b.data = fetchByte(tif, sp); } code = TIFFFaxUncompAction[sp->b.bit][sp->b.data]; sp->b.bit = TIFFFaxUncompNextState[sp->b.bit][sp->b.data]; } while (code == ACT_INCOMP); return (code); } /* * Process one row of 2d encoded data. */ int Fax3Decode2DRow(tif, buf, npels) TIFF *tif; u_char *buf; int npels; { #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; int a0 = -1; int b1, b2; int run1, run2; /* for horizontal mode */ short mode; short color = sp->b.white; static char module[] = "Fax3Decode2D"; do { if (sp->b.bit == 0 || sp->b.bit > 7) { if (tif->tif_rawcc <= 0) { TIFFError(module, "%s: Premature EOF at scanline %d", tif->tif_name, tif->tif_row); return (0); } sp->b.data = fetchByte(tif, sp); } mode = TIFFFax2DMode[sp->b.bit][sp->b.data]; sp->b.bit = TIFFFax2DNextState[sp->b.bit][sp->b.data]; switch (mode) { case MODE_NULL: break; case MODE_PASS: b2 = finddiff(sp->b.refline, a0, npels, !color); b1 = finddiff(sp->b.refline, b2, npels, color); b2 = finddiff(sp->b.refline, b1, npels, !color); if (color) { if (a0 < 0) a0 = 0; fillspan((char *)buf, a0, b2 - a0); } a0 = b2; break; case MODE_HORIZ: if (color == sp->b.white) { run1 = decode_white_run(tif); run2 = decode_black_run(tif); } else { run1 = decode_black_run(tif); run2 = decode_white_run(tif); } /* * Do the appropriate fill. Note that we exit * this logic with the same color that we enter * with since we do 2 fills. This explains the * somewhat obscure logic below. */ if (a0 < 0) a0 = 0; if (a0 + run1 > npels) run1 = npels - a0; if (color) fillspan((char *)buf, a0, run1); a0 += run1; if (a0 + run2 > npels) run2 = npels - a0; if (!color) fillspan((char *)buf, a0, run2); a0 += run2; break; case MODE_VERT_V0: case MODE_VERT_VR1: case MODE_VERT_VR2: case MODE_VERT_VR3: case MODE_VERT_VL1: case MODE_VERT_VL2: case MODE_VERT_VL3: b2 = finddiff(sp->b.refline, a0, npels, !color); b1 = finddiff(sp->b.refline, b2, npels, color); b1 += mode - MODE_VERT_V0; if (color) { if (a0 < 0) a0 = 0; fillspan((char *)buf, a0, b1 - a0); } color = !color; a0 = b1; break; case MODE_UNCOMP: /* * Uncompressed mode: select from the * special set of code words. */ if (a0 < 0) a0 = 0; do { mode = decode_uncomp_code(tif); switch (mode) { case UNCOMP_RUN1: case UNCOMP_RUN2: case UNCOMP_RUN3: case UNCOMP_RUN4: case UNCOMP_RUN5: run1 = mode - UNCOMP_RUN0; fillspan((char *)buf, a0+run1-1, 1); a0 += run1; break; case UNCOMP_RUN6: a0 += 5; break; case UNCOMP_TRUN0: case UNCOMP_TRUN1: case UNCOMP_TRUN2: case UNCOMP_TRUN3: case UNCOMP_TRUN4: run1 = mode - UNCOMP_TRUN0; a0 += run1; color = nextbit(tif) ? !sp->b.white : sp->b.white; break; case UNCOMP_INVALID: TIFFError(module, "%s: Bad uncompressed code word at scanline %d", tif->tif_name, tif->tif_row); goto bad; case UNCOMP_EOF: TIFFError(module, "%s: Premature EOF at scanline %d", tif->tif_name, tif->tif_row); return (0); } } while (mode < UNCOMP_EXIT); break; case MODE_ERROR_1: if ((tif->tif_options & FAX3_NOEOL) == 0) { TIFFWarning(module, "%s: Premature EOL at scanline %d (x %d)", tif->tif_name, tif->tif_row, a0); skiptoeol(tif, 7); /* seen 7 0's already */ return (1); /* try to synchronize */ } /* fall thru... */ case MODE_ERROR: TIFFError(module, "%s: Bad 2D code word at scanline %d", tif->tif_name, tif->tif_row); goto bad; default: TIFFError(module, "%s: Panic, bad decoding state at scanline %d", tif->tif_name, tif->tif_row); return (0); } } while (a0 < npels); bad: /* * Cleanup at the end of row. We check for * EOL separately so that this code can be * reused by the Group 4 decoding routine. */ if ((tif->tif_options & FAX3_NOEOL) == 0) skiptoeol(tif, 0); return (a0 >= npels); #undef PIXEL } /* * CCITT Group 3 FAX Encoding. */ /* * Write a variable-length bit-value to * the output stream. Values are * assumed to be at most 16 bits. */ static void putbits(tif, bits, length) TIFF *tif; u_int bits, length; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; static const int mask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; while (length > sp->bit) { sp->data |= bits >> (length - sp->bit); length -= sp->bit; Fax3FlushBits(tif, sp); } sp->data |= (bits & mask[length]) << (sp->bit - length); sp->bit -= length; if (sp->bit == 0) Fax3FlushBits(tif, sp); } /* * Write a code to the output stream. */ static void putcode(tif, te) TIFF *tif; tableentry const *te; { putbits(tif, te->code, te->length); } /* * Write the sequence of codes that describes * the specified span of zero's or one's. The * appropriate table that holds the make-up and * terminating codes is supplied. */ static void putspan(tif, span, tab) TIFF *tif; int span; tableentry const *tab; { while (span >= 2624) { tableentry const *te = &tab[63 + (2560>>6)]; putcode(tif, te); span -= te->runlen; } if (span >= 64) { tableentry const *te = &tab[63 + (span>>6)]; assert(te->runlen == 64*(span>>6)); putcode(tif, te); span -= te->runlen; } putcode(tif, &tab[span]); } /* * Write an EOL code to the output stream. The zero-fill * logic for byte-aligning encoded scanlines is handled * here. We also handle writing the tag bit for the next * scanline when doing 2d encoding. */ void Fax3PutEOL(tif) TIFF *tif; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; if (tif->tif_dir.td_group3options & GROUP3OPT_FILLBITS) { /* * Force bit alignment so EOL will terminate on * a byte boundary. That is, force the bit alignment * to 16-12 = 4 before putting out the EOL code. */ int align = 8 - 4; if (align != sp->bit) { if (align > sp->bit) align = sp->bit + (8 - align); else align = sp->bit - align; putbits(tif, 0, align); } } putbits(tif, EOL, 12); if (is2DEncoding(tif)) putbits(tif, sp->tag == G3_1D, 1); } static const u_char zeroruns[256] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ }; static const u_char oneruns[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */ }; /* * Reset encoding state at the start of a strip. */ static Fax3PreEncode(tif) TIFF *tif; { Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; if (sp == NULL) { sp = (Fax3EncodeState *)Fax3SetupState(tif, sizeof (*sp)); if (!sp) return (0); if (sp->b.white == 0) { sp->wruns = zeroruns; sp->bruns = oneruns; } else { sp->wruns = oneruns; sp->bruns = zeroruns; } } sp->b.bit = 8; sp->b.data = 0; sp->b.tag = G3_1D; /* * This is necessary for Group 4; otherwise it isn't * needed because the first scanline of each strip ends * up being copied into the refline. */ if (sp->b.refline) bset(sp->b.refline, sp->b.rowbytes, sp->b.white ? 0xff : 0x00); if (is2DEncoding(tif)) { float res = tif->tif_dir.td_yresolution; /* * The CCITT spec says that when doing 2d encoding, you * should only do it on K consecutive scanlines, where K * depends on the resolution of the image being encoded * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory * code initializes td_yresolution to 0, this code will * select a K of 2 unless the YResolution tag is set * appropriately. (Note also that we fudge a little here * and use 150 lpi to avoid problems with units conversion.) */ if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) res = (res * .3937) / 2.54; /* convert to inches */ sp->maxk = (res > 150 ? 4 : 2); sp->k = sp->maxk-1; } else sp->k = sp->maxk = 0; return (1); } /* * 1d-encode a row of pixels. The encoding is * a sequence of all-white or all-black spans * of pixels encoded with Huffman codes. */ static int Fax3Encode1DRow(tif, bp, bits) TIFF *tif; u_char *bp; int bits; { Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; int bs = 0, span; for (;;) { span = findspan(&bp, bs, bits, sp->wruns); /* white span */ putspan(tif, span, TIFFFaxWhiteCodes); bs += span; if (bs >= bits) break; span = findspan(&bp, bs, bits, sp->bruns); /* black span */ putspan(tif, span, TIFFFaxBlackCodes); bs += span; if (bs >= bits) break; } return (1); } static const tableentry horizcode = { 3, 0x1 }; /* 001 */ static const tableentry passcode = { 4, 0x1 }; /* 0001 */ static const tableentry vcodes[7] = { { 7, 0x03 }, /* 0000 011 */ { 6, 0x03 }, /* 0000 11 */ { 3, 0x03 }, /* 011 */ { 1, 0x1 }, /* 1 */ { 3, 0x2 }, /* 010 */ { 6, 0x02 }, /* 0000 10 */ { 7, 0x02 } /* 0000 010 */ }; /* * 2d-encode a row of pixels. Consult the CCITT * documentation for the algorithm. */ int Fax3Encode2DRow(tif, bp, rp, bits) TIFF *tif; u_char *bp, *rp; int bits; { #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) short white = ((Fax3BaseState *)tif->tif_data)->white; int a0 = 0; int a1 = (PIXEL(bp, 0) != white ? 0 : finddiff(bp, 0, bits, white)); int b1 = (PIXEL(rp, 0) != white ? 0 : finddiff(rp, 0, bits, white)); int a2, b2; for (;;) { b2 = finddiff(rp, b1, bits, PIXEL(rp,b1)); if (b2 >= a1) { int d = b1 - a1; if (!(-3 <= d && d <= 3)) { /* horizontal mode */ a2 = finddiff(bp, a1, bits, PIXEL(bp,a1)); putcode(tif, &horizcode); if (a0+a1 == 0 || PIXEL(bp, a0) == white) { putspan(tif, a1-a0, TIFFFaxWhiteCodes); putspan(tif, a2-a1, TIFFFaxBlackCodes); } else { putspan(tif, a1-a0, TIFFFaxBlackCodes); putspan(tif, a2-a1, TIFFFaxWhiteCodes); } a0 = a2; } else { /* vertical mode */ putcode(tif, &vcodes[d+3]); a0 = a1; } } else { /* pass mode */ putcode(tif, &passcode); a0 = b2; } if (a0 >= bits) break; a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); } return (1); #undef PIXEL } /* * Encode a buffer of pixels. */ static int Fax3Encode(tif, bp, cc, s) TIFF *tif; u_char *bp; int cc; u_int s; { Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; while (cc > 0) { Fax3PutEOL(tif); if (is2DEncoding(tif)) { if (sp->b.tag == G3_1D) { if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) return (0); sp->b.tag = G3_2D; } else { if (!Fax3Encode2DRow(tif, bp, sp->b.refline, sp->b.rowpixels)) return (0); sp->k--; } if (sp->k == 0) { sp->b.tag = G3_1D; sp->k = sp->maxk-1; } else bcopy(bp, sp->b.refline, sp->b.rowbytes); } else { if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) return (0); } bp += sp->b.rowbytes; cc -= sp->b.rowbytes; } return (1); } static int Fax3PostEncode(tif) TIFF *tif; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; if (sp->bit != 8) Fax3FlushBits(tif, sp); return (1); } static Fax3Close(tif) TIFF *tif; { if ((tif->tif_options & FAX3_CLASSF) == 0) { /* append RTC */ int i; for (i = 0; i < 6; i++) Fax3PutEOL(tif); (void) Fax3PostEncode(tif); } } static Fax3Cleanup(tif) TIFF *tif; { if (tif->tif_data) { free(tif->tif_data); tif->tif_data = NULL; } } /* * Bit handling utilities. */ /* * Find a span of ones or zeros using the supplied * table. The byte-aligned start of the bit string * is supplied along with the start+end bit indices. * The table gives the number of consecutive ones or * zeros starting from the msb and is indexed by byte * value. */ static int findspan(bpp, bs, be, tab) u_char **bpp; int bs, be; register u_char const *tab; { register u_char *bp = *bpp; register int bits = be - bs; register int n, span; /* * Check partial byte on lhs. */ if (bits > 0 && (n = (bs & 7))) { span = tab[(*bp << n) & 0xff]; if (span > 8-n) /* table value too generous */ span = 8-n; if (span > bits) /* constrain span to bit range */ span = bits; if (n+span < 8) /* doesn't extend to edge of byte */ goto done; bits -= span; bp++; } else span = 0; /* * Scan full bytes for all 1's or all 0's. */ while (bits >= 8) { n = tab[*bp]; span += n; bits -= n; if (n < 8) /* end of run */ goto done; bp++; } /* * Check partial byte on rhs. */ if (bits > 0) { n = tab[*bp]; span += (n > bits ? bits : n); } done: *bpp = bp; return (span); } /* * Return the offset of the next bit in the range * [bs..be] that is different from the specified * color. The end, be, is returned if no such bit * exists. */ static int finddiff(cp, bs, be, color) u_char *cp; int bs, be, color; { cp += bs >> 3; /* adjust byte offset */ return (bs + findspan(&cp, bs, be, color ? oneruns : zeroruns)); } 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ 0, 0, 0, 0, 0, 0, 0,xloadimage.4.1/tiff/tif_fax3.h 664 221 144 5744 5461577446 11400 /* $Header: /usr/people/sam/tiff/libtiff/RCS/tif_fax3.h,v 1.8 92/02/10 19:06:37 sam Exp $ */ /* * Copyright (c) 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _FAX3_ #define _FAX3_ /* * CCITT Group 3 compression/decompression definitions. */ #define FAX3_CLASSF TIFF_OPT0 /* use Class F protocol */ /* the following are for use by Compression=2, 32771, and 4 (T.6) algorithms */ #define FAX3_NOEOL TIFF_OPT1 /* no EOL code at end of row */ #define FAX3_BYTEALIGN TIFF_OPT2 /* force byte alignment at end of row */ #define FAX3_WORDALIGN TIFF_OPT3 /* force word alignment at end of row */ /* * Compression+decompression state blocks are * derived from this ``base state'' block. */ typedef struct { short data; /* current i/o byte */ short bit; /* current i/o bit in byte */ short white; /* value of the color ``white'' */ u_long rowbytes; /* XXX maybe should be a long? */ u_long rowpixels; /* XXX maybe should be a long? */ enum { /* decoding/encoding mode */ G3_1D, /* basic 1-d mode */ G3_2D /* optional 2-d mode */ } tag; #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST u_char const *bitmap; /* bit reversal table */ #else u_char *bitmap; /* bit reversal table */ #endif u_char *refline; /* reference line for 2d decoding */ } Fax3BaseState; /* these routines are used for Group 4 (T.6) */ #if USE_PROTOTYPES extern int Fax3Decode2DRow(TIFF*, u_char *, int); extern int Fax3Encode2DRow(TIFF*, u_char *, u_char *, int); extern void Fax3PutEOL(TIFF*); #else extern int Fax3Decode2DRow(); extern int Fax3Encode2DRow(); extern void Fax3PutEOL(); #endif #define Fax3FlushBits(tif, sp) { \ if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ (void) TIFFFlushData1(tif); \ *(tif)->tif_rawcp++ = (sp)->bitmap[(sp)->data]; \ (tif)->tif_rawcc++; \ (sp)->data = 0; \ (sp)->bit = 8; \ } #endif /* _FAX3_ */ , 0, 0, 0, 0, 0, 0, /* 0x90 xloadimage.4.1/tiff/tif_fax4.c 664 221 144 6511 5461577446 11365 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_fax4.c,v 1.14 92/03/11 15:45:17 sam Exp $"; #endif /* * Copyright (c) 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * CCITT Group 4 Facsimile-compatible * Compression Scheme Support. */ #include "tiffioP.h" #include "tif_fax3.h" #if USE_PROTOTYPES static int Fax4Decode(TIFF*, u_char *, int, u_int); static int Fax4Encode(TIFF*, u_char *, int, u_int); static int Fax4PostEncode(TIFF*); #else static int Fax4Decode(); static int Fax4Encode(); static int Fax4PostEncode(); #endif TIFFInitCCITTFax4(tif) TIFF *tif; { TIFFInitCCITTFax3(tif); /* reuse G3 compression */ tif->tif_decoderow = Fax4Decode; tif->tif_decodestrip = Fax4Decode; tif->tif_decodetile = Fax4Decode; tif->tif_encoderow = Fax4Encode; tif->tif_encodestrip = Fax4Encode; tif->tif_encodetile = Fax4Encode; tif->tif_postencode = Fax4PostEncode; /* * FAX3_NOEOL causes the regular G3 decompression * code to not skip to the EOL mark at the end of * a row (during normal decoding). FAX3_CLASSF * suppresses RTC generation at the end of an image. */ tif->tif_options = FAX3_NOEOL|FAX3_CLASSF; return (1); } /* * Decode the requested amount of data. */ static int Fax4Decode(tif, buf, occ, s) TIFF *tif; u_char *buf; int occ; u_int s; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; bzero(buf, occ); /* decoding only sets non-zero bits */ while (occ > 0) { if (!Fax3Decode2DRow(tif, buf, sp->rowpixels)) return (0); bcopy(buf, sp->refline, sp->rowbytes); buf += sp->rowbytes; occ -= sp->rowbytes; } return (1); } /* * Encode the requested amount of data. */ static int Fax4Encode(tif, bp, cc, s) TIFF *tif; u_char *bp; int cc; u_int s; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; while (cc > 0) { if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->rowpixels)) return (0); bcopy(bp, sp->refline, sp->rowbytes); bp += sp->rowbytes; cc -= sp->rowbytes; } return (1); } static Fax4PostEncode(tif) TIFF *tif; { Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; /* terminate strip w/ EOFB */ Fax3PutEOL(tif); Fax3PutEOL(tif); if (sp->bit != 8) Fax3FlushBits(tif, sp); return (1); } \ } #endif /* _FAX3_ */ , 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,xloadimage.4.1/tiff/tif_flush.c 664 221 144 3650 5461577446 11645 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_flush.c,v 1.14 92/02/10 19:06:39 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. */ #include "tiffioP.h" TIFFFlush(tif) TIFF *tif; { if (tif->tif_mode != O_RDONLY) { if (!TIFFFlushData(tif)) return (0); if ((tif->tif_flags & TIFF_DIRTYDIRECT) && !TIFFWriteDirectory(tif)) return (0); } return (1); } /* * Flush buffered data to the file. */ TIFFFlushData(tif) TIFF *tif; { if ((tif->tif_flags & TIFF_BEENWRITING) == 0) return (0); if (tif->tif_flags & TIFF_POSTENCODE) { tif->tif_flags &= ~TIFF_POSTENCODE; if (tif->tif_postencode && !(*tif->tif_postencode)(tif)) return (0); } return (TIFFFlushData1(tif)); } bits */ while (occ > 0) { if (!Fax3Decode2DRow(tif, buf, sp->rowpixels)) return (0xloadimage.4.1/tiff/tif_getimage.c 664 221 144 64042 5461577447 12331 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_getimage.c,v 1.8 92/03/11 09:19:10 sam Exp $"; #endif /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library * * Read and return a packed RGBA image. */ #include "tiffio.h" #include "tiffcompat.h" #include "prototypes.h" typedef u_char RGBvalue; static u_long width, height; /* image width & height */ static u_short bitspersample; static u_short samplesperpixel; static u_short photometric; static u_short orientation; /* colormap for pallete images */ static u_short *redcmap, *greencmap, *bluecmap; static int stoponerr; /* stop on read error */ static char *filename; /* YCbCr support */ static u_short YCbCrHorizSampling; static u_short YCbCrVertSampling; static float *YCbCrCoeffs; static float *refBlackWhite; static u_long **BWmap; static u_long **PALmap; static int gt(); TIFFReadRGBAImage(tif, rwidth, rheight, raster, stop) TIFF *tif; u_long rwidth, rheight; u_long *raster; int stop; { int ok; u_long width, height; TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); switch (bitspersample) { case 1: case 2: case 4: case 8: case 16: break; default: TIFFError(TIFFFileName(tif), "Sorry, can not handle %d-bit pictures", bitspersample); return (0); } TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); switch (samplesperpixel) { case 1: case 3: case 4: break; default: TIFFError(TIFFFileName(tif), "Sorry, can not handle %d-channel images", samplesperpixel); return (0); } if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { switch (samplesperpixel) { case 1: photometric = PHOTOMETRIC_MINISBLACK; break; case 3: case 4: photometric = PHOTOMETRIC_RGB; break; default: TIFFError(TIFFFileName(tif), "Missing needed \"PhotometricInterpretation\" tag"); return (0); } TIFFError(TIFFFileName(tif), "No \"PhotometricInterpretation\" tag, assuming %s\n", photometric == PHOTOMETRIC_RGB ? "RGB" : "min-is-black"); } /* XXX maybe should check photometric? */ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); /* XXX verify rwidth and rheight against width and height */ stoponerr = stop; BWmap = NULL; PALmap = NULL; ok = gt(tif, rwidth, height, raster + (rheight-height)*rwidth); if (BWmap) free((char *)BWmap); if (PALmap) free((char *)PALmap); return (ok); } static int checkcmap(n, r, g, b) int n; u_short *r, *g, *b; { while (n-- > 0) if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) return (16); TIFFWarning(filename, "Assuming 8-bit colormap"); return (8); } static gtTileContig(); static gtTileSeparate(); static gtStripContig(); static gtStripSeparate(); static void initYCbCrConversion(); static gt(tif, w, h, raster) TIFF *tif; int w, h; u_long *raster; { u_short minsamplevalue, maxsamplevalue, planarconfig; RGBvalue *Map; int e; TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue); TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue); Map = NULL; switch (photometric) { case PHOTOMETRIC_YCBCR: TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &YCbCrCoeffs); TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &YCbCrHorizSampling, &YCbCrVertSampling); TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE, &refBlackWhite); initYCbCrConversion(); /* fall thru... */ case PHOTOMETRIC_RGB: if (minsamplevalue == 0 && maxsamplevalue == 255) break; /* fall thru... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: { register int x, range; range = maxsamplevalue - minsamplevalue; Map = (RGBvalue *)malloc((range + 1) * sizeof (RGBvalue)); if (Map == NULL) { TIFFError(filename, "No space for photometric conversion table"); return (0); } if (photometric == PHOTOMETRIC_MINISWHITE) { for (x = 0; x <= range; x++) Map[x] = ((range - x) * 255) / range; } else { for (x = 0; x <= range; x++) Map[x] = (x * 255) / range; } if (photometric != PHOTOMETRIC_RGB && bitspersample <= 8) { /* * Use photometric mapping table to construct * unpacking tables for samples <= 8 bits. */ if (!makebwmap(Map)) return (0); /* no longer need Map, free it */ free((char *)Map); Map = NULL; } break; } case PHOTOMETRIC_PALETTE: if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &redcmap, &greencmap, &bluecmap)) { TIFFError(filename, "Missing required \"Colormap\" tag"); return (0); } /* * Convert 16-bit colormap to 8-bit (unless it looks * like an old-style 8-bit colormap). */ if (checkcmap(1< 0; i--) { #define CVT(x) (((x) * 255) / ((1L<<16)-1)) redcmap[i] = CVT(redcmap[i]); greencmap[i] = CVT(greencmap[i]); bluecmap[i] = CVT(bluecmap[i]); } } if (bitspersample <= 8) { /* * Use mapping table and colormap to construct * unpacking tables for samples < 8 bits. */ if (!makecmap(redcmap, greencmap, bluecmap)) return (0); } break; } TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig); if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel > 1) { e = TIFFIsTiled(tif) ? gtTileSeparate(tif, raster, Map, h, w) : gtStripSeparate(tif, raster, Map, h, w); } else { e = TIFFIsTiled(tif) ? gtTileContig(tif, raster, Map, h, w) : gtStripContig(tif, raster, Map, h, w); } if (Map) free((char *)Map); return (e); } u_long setorientation(tif, h) TIFF *tif; u_long h; { u_long y; TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); switch (orientation) { case ORIENTATION_BOTRIGHT: case ORIENTATION_RIGHTBOT: /* XXX */ case ORIENTATION_LEFTBOT: /* XXX */ TIFFWarning(filename, "using bottom-left orientation"); orientation = ORIENTATION_BOTLEFT; /* fall thru... */ case ORIENTATION_BOTLEFT: y = 0; break; case ORIENTATION_TOPRIGHT: case ORIENTATION_RIGHTTOP: /* XXX */ case ORIENTATION_LEFTTOP: /* XXX */ default: TIFFWarning(filename, "using top-left orientation"); orientation = ORIENTATION_TOPLEFT; /* fall thru... */ case ORIENTATION_TOPLEFT: y = h-1; break; } return (y); } #if USE_PROTOTYPES typedef void (*tileContigRoutine) (u_long*, u_char*, RGBvalue*, u_long, u_long, int, int); static tileContigRoutine pickTileContigCase(RGBvalue*); #else typedef void (*tileContigRoutine)(); static tileContigRoutine pickTileContigCase(); #endif /* * Get an tile-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ static gtTileContig(tif, raster, Map, h, w) TIFF *tif; u_long *raster; RGBvalue *Map; u_long h, w; { u_long col, row, y; u_long tw, th; u_char *buf; int fromskew, toskew; u_int nrow; tileContigRoutine put; put = pickTileContigCase(Map); if (put == 0) return (0); buf = (u_char *)malloc(TIFFTileSize(tif)); if (buf == 0) { TIFFError(filename, "No space for tile buffer"); return (0); } TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); y = setorientation(tif, h); toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w); for (row = 0; row < h; row += th) { nrow = (row + th > h ? h - row : th); for (col = 0; col < w; col += tw) { if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 && stoponerr) break; if (col + tw > w) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ u_long npix = w - col; fromskew = tw - npix; (*put)(raster + y*w + col, buf, Map, npix, nrow, fromskew, toskew + fromskew); } else (*put)(raster + y*w + col, buf, Map, tw, nrow, 0, toskew); } y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow); } free(buf); return (1); } #if USE_PROTOTYPES typedef void (*tileSeparateRoutine) (u_long*, u_char*, u_char*, u_char*, RGBvalue*, u_long, u_long, int, int); static tileSeparateRoutine pickTileSeparateCase(RGBvalue*); #else typedef void (*tileSeparateRoutine)(); static tileSeparateRoutine pickTileSeparateCase(); #endif /* * Get an tile-organized image that has * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ static gtTileSeparate(tif, raster, Map, h, w) TIFF *tif; u_long *raster; RGBvalue *Map; u_long h, w; { u_long col, row, y; u_long tw, th; u_char *buf; u_char *r, *g, *b; int tilesize; int fromskew, toskew; u_int nrow; tileSeparateRoutine put; put = pickTileSeparateCase(Map); if (put == 0) return (0); tilesize = TIFFTileSize(tif); buf = (u_char *)malloc(3*tilesize); if (buf == 0) { TIFFError(filename, "No space for tile buffer"); return (0); } r = buf; g = r + tilesize; b = g + tilesize; TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); y = setorientation(tif, h); toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w); for (row = 0; row < h; row += th) { nrow = (row + th > h ? h - row : th); for (col = 0; col < w; col += tw) { if (TIFFReadTile(tif, r, col, row,0,0) < 0 && stoponerr) break; if (TIFFReadTile(tif, g, col, row,0,1) < 0 && stoponerr) break; if (TIFFReadTile(tif, b, col, row,0,2) < 0 && stoponerr) break; if (col + tw > w) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ u_long npix = w - col; fromskew = tw - npix; (*put)(raster + y*w + col, r, g, b, Map, npix, nrow, fromskew, toskew + fromskew); } else (*put)(raster + y*w + col, r, g, b, Map, tw, nrow, 0, toskew); } y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow); } free(buf); return (1); } /* * Get a strip-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ static gtStripContig(tif, raster, Map, h, w) TIFF *tif; u_long *raster; RGBvalue *Map; u_long h, w; { u_long row, y, nrow; u_char *buf; tileContigRoutine put; u_long rowsperstrip; u_long imagewidth; int scanline; int fromskew, toskew; put = pickTileContigCase(Map); if (put == 0) return (0); buf = (u_char *)malloc(TIFFStripSize(tif)); if (buf == 0) { TIFFError(filename, "No space for strip buffer"); return (0); } y = setorientation(tif, h); toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w); TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += rowsperstrip) { nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf, nrow*scanline) < 0 && stoponerr) break; (*put)(raster + y*w, buf, Map, w, nrow, fromskew, toskew); y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow); } free(buf); return (1); } /* * Get a strip-organized image with * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ static gtStripSeparate(tif, raster, Map, h, w) TIFF *tif; u_long *raster; register RGBvalue *Map; u_long h, w; { u_char *buf; u_char *r, *g, *b; u_long row, y, nrow; int scanline; tileSeparateRoutine put; u_long rowsperstrip; u_long imagewidth; u_int stripsize; int fromskew, toskew; stripsize = TIFFStripSize(tif); r = buf = (u_char *)malloc(3*stripsize); if (buf == 0) return (0); g = r + stripsize; b = g + stripsize; put = pickTileSeparateCase(Map); if (put == 0) { TIFFError(filename, "Can not handle format"); return (0); } y = setorientation(tif, h); toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w); TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += rowsperstrip) { nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), r, nrow*scanline) < 0 && stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1), g, nrow*scanline) < 0 && stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2), b, nrow*scanline) < 0 && stoponerr) break; (*put)(raster + y*w, r, g, b, Map, w, nrow, fromskew, toskew); y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow); } free(buf); return (1); } #define PACK(r,g,b) ((u_long)(r)|((u_long)(g)<<8)|((u_long)(b)<<16)) /* * Greyscale images with less than 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*bwtile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */ makebwmap(Map) RGBvalue *Map; { register int i; int nsamples = 8 / bitspersample; register u_long *p; BWmap = (u_long **)malloc( 256*sizeof (u_long *)+(256*nsamples*sizeof(u_long))); if (BWmap == NULL) { TIFFError(filename, "No space for B&W mapping table"); return (0); } p = (u_long *)(BWmap + 256); for (i = 0; i < 256; i++) { BWmap[i] = p; switch (bitspersample) { register RGBvalue c; #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); case 1: GREY(i>>7); GREY((i>>6)&1); GREY((i>>5)&1); GREY((i>>4)&1); GREY((i>>3)&1); GREY((i>>2)&1); GREY((i>>1)&1); GREY(i&1); break; case 2: GREY(i>>6); GREY((i>>4)&3); GREY((i>>2)&3); GREY(i&3); break; case 4: GREY(i>>4); GREY(i&0xf); break; case 8: GREY(i); break; } #undef GREY } return (1); } /* * Palette images with <= 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*cmaptile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */ makecmap(rmap, gmap, bmap) u_short *rmap, *gmap, *bmap; { register int i; int nsamples = 8 / bitspersample; register u_long *p; PALmap = (u_long **)malloc( 256*sizeof (u_long *)+(256*nsamples*sizeof(u_long))); if (PALmap == NULL) { TIFFError(filename, "No space for Palette mapping table"); return (0); } p = (u_long *)(PALmap + 256); for (i = 0; i < 256; i++) { PALmap[i] = p; #define CMAP(x) \ c = x; *p++ = PACK(rmap[c]&0xff, gmap[c]&0xff, bmap[c]&0xff); switch (bitspersample) { register RGBvalue c; case 1: CMAP(i>>7); CMAP((i>>6)&1); CMAP((i>>5)&1); CMAP((i>>4)&1); CMAP((i>>3)&1); CMAP((i>>2)&1); CMAP((i>>1)&1); CMAP(i&1); break; case 2: CMAP(i>>6); CMAP((i>>4)&3); CMAP((i>>2)&3); CMAP(i&3); break; case 4: CMAP(i>>4); CMAP(i&0xf); break; case 8: CMAP(i); break; } #undef CMAP } return (1); } /* * The following routines move decoded data returned * from the TIFF library into rasters filled with packed * ABGR pixels (i.e. suitable for passing to lrecwrite.) * * The routines have been created according to the most * important cases and optimized. pickTileContigCase and * pickTileSeparateCase analyze the parameters and select * the appropriate "put" routine to use. */ #define REPEAT8(op) REPEAT4(op); REPEAT4(op) #define REPEAT4(op) REPEAT2(op); REPEAT2(op) #define REPEAT2(op) op; op #define CASE8(x,op) \ switch (x) { \ case 7: op; case 6: op; case 5: op; \ case 4: op; case 3: op; case 2: op; \ case 1: op; \ } #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } #define UNROLL8(w, op1, op2) { \ register u_long x; \ for (x = w; x >= 8; x -= 8) { \ op1; \ REPEAT8(op2); \ } \ if (x > 0) { \ op1; \ CASE8(x,op2); \ } \ } #define UNROLL4(w, op1, op2) { \ register u_long x; \ for (x = w; x >= 4; x -= 4) { \ op1; \ REPEAT4(op2); \ } \ if (x > 0) { \ op1; \ CASE4(x,op2); \ } \ } #define UNROLL2(w, op1, op2) { \ register u_long x; \ for (x = w; x >= 2; x -= 2) { \ op1; \ REPEAT2(op2); \ } \ if (x) { \ op1; \ op2; \ } \ } #define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; } /* * 8-bit palette => colormap/RGB */ static void put8bitcmaptile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; RGBvalue *Map; u_long w, h; int fromskew, toskew; { while (h-- > 0) { UNROLL8(w,, *cp++ = PALmap[*pp++][0]); cp += toskew; pp += fromskew; } } /* * 4-bit palette => colormap/RGB */ static void put4bitcmaptile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 2; while (h-- > 0) { UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 2-bit palette => colormap/RGB */ static void put2bitcmaptile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 4; while (h-- > 0) { UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 1-bit palette => colormap/RGB */ static void put1bitcmaptile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 8; while (h-- > 0) { UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 8-bit greyscale => colormap/RGB */ static void putgreytile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; RGBvalue *Map; u_long w, h; int fromskew, toskew; { while (h-- > 0) { register u_long x; for (x = w; x-- > 0;) *cp++ = BWmap[*pp++][0]; cp += toskew; pp += fromskew; } } /* * 1-bit bilevel => colormap/RGB */ static void put1bitbwtile(cp, pp, Map, w, h, fromskew, toskew) u_long *cp; u_char *pp; RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 8; while (h-- > 0) { UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 2-bit greyscale => colormap/RGB */ static void put2bitbwtile(cp, pp, Map, w, h, fromskew, toskew) u_long *cp; u_char *pp; RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 4; while (h-- > 0) { UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 4-bit greyscale => colormap/RGB */ static void put4bitbwtile(cp, pp, Map, w, h, fromskew, toskew) u_long *cp; u_char *pp; RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 2; while (h-- > 0) { UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 8-bit packed samples => RGB */ static void putRGBcontig8bittile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { fromskew *= samplesperpixel; if (Map) { while (h-- > 0) { register u_long x; for (x = w; x-- > 0;) { *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]); pp += samplesperpixel; } pp += fromskew; cp += toskew; } } else { while (h-- > 0) { UNROLL8(w,, *cp++ = PACK(pp[0], pp[1], pp[2]); pp += samplesperpixel); cp += toskew; pp += fromskew; } } } /* * 16-bit packed samples => RGB */ static void putRGBcontig16bittile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_short *wp = (u_short *)pp; register u_int x; fromskew *= samplesperpixel; if (Map) { while (h-- > 0) { for (x = w; x-- > 0;) { *cp++ = PACK(Map[wp[0]], Map[wp[1]], Map[wp[2]]); wp += samplesperpixel; } cp += toskew; wp += fromskew; } } else { while (h-- > 0) { for (x = w; x-- > 0;) { *cp++ = PACK(wp[0], wp[1], wp[2]); wp += samplesperpixel; } cp += toskew; wp += fromskew; } } } /* * 8-bit unpacked samples => RGB */ static void putRGBseparate8bittile(cp, r, g, b, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *r, *g, *b; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { if (Map) { while (h-- > 0) { register u_long x; for (x = w; x > 0; x--) *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]); SKEW(r, g, b, fromskew); cp += toskew; } } else { while (h-- > 0) { UNROLL8(w,, *cp++ = PACK(*r++, *g++, *b++)); SKEW(r, g, b, fromskew); cp += toskew; } } } /* * 16-bit unpacked samples => RGB */ static void putRGBseparate16bittile(cp, br, bg, bb, Map, w, h, fromskew, toskew) register u_long *cp; u_char *br, *bg, *bb; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_short *r = (u_short *)br; register u_short *g = (u_short *)bg; register u_short *b = (u_short *)bb; register u_long x; if (Map) { while (h-- > 0) { for (x = w; x > 0; x--) *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]); SKEW(r, g, b, fromskew); cp += toskew; } } else { while (h-- > 0) { for (x = 0; x < w; x++) *cp++ = PACK(*r++, *g++, *b++); SKEW(r, g, b, fromskew); cp += toskew; } } } #define Code2V(c, RB, RW, CR) ((((c)-RB)*(float)CR)/(float)(RW-RB)) #define CLAMP(f,min,max) \ (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5) #define LumaRed YCbCrCoeffs[0] #define LumaGreen YCbCrCoeffs[1] #define LumaBlue YCbCrCoeffs[2] static float D1, D2; static float D3, D4; static void initYCbCrConversion() { D1 = 2 - 2*LumaRed; D2 = D1*LumaRed / LumaGreen; D3 = 2 - 2*LumaBlue; D4 = D2*LumaBlue / LumaGreen; } static void putRGBContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew) register u_long *cp; register u_char *pp; int cw, ch; u_long w; int n, fromskew, toskew; { float Cb, Cr; int j, k; Cb = Code2V(pp[n], refBlackWhite[2], refBlackWhite[3], 127); Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127); for (j = 0; j < ch; j++) { for (k = 0; k < cw; k++) { float Y, R, G, B; Y = Code2V(*pp++, refBlackWhite[0], refBlackWhite[1], 255); R = Y + Cr*D1; B = Y + Cb*D3; G = Y - Cb*D4 - Cr*D2; cp[k] = PACK(CLAMP(R,0,255), CLAMP(G,0,255), CLAMP(B,0,255)); } cp += w+toskew; pp += fromskew; } } #undef LumaBlue #undef LumaGreen #undef LumaRed #undef CLAMP #undef Code2V /* * 8-bit packed YCbCr samples => RGB */ static void putcontig8bitYCbCrtile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { u_int Coff = YCbCrVertSampling * YCbCrHorizSampling; u_long *tp; u_long x; /* XXX adjust fromskew */ while (h >= YCbCrVertSampling) { tp = cp; for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) { putRGBContigYCbCrClump(tp, pp, YCbCrHorizSampling, YCbCrVertSampling, w, Coff, 0, toskew); tp += YCbCrHorizSampling; pp += Coff+2; } if (x > 0) { putRGBContigYCbCrClump(tp, pp, x, YCbCrVertSampling, w, Coff, YCbCrHorizSampling - x, toskew); pp += Coff+2; } cp += YCbCrVertSampling*(w + toskew); pp += fromskew; h -= YCbCrVertSampling; } if (h > 0) { tp = cp; for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) { putRGBContigYCbCrClump(tp, pp, YCbCrHorizSampling, h, w, Coff, 0, toskew); tp += YCbCrHorizSampling; pp += Coff+2; } if (x > 0) putRGBContigYCbCrClump(tp, pp, x, h, w, Coff, YCbCrHorizSampling - x, toskew); } } /* * Select the appropriate conversion routine for packed data. */ static tileContigRoutine DECLARE1(pickTileContigCase, RGBvalue*, Map) { tileContigRoutine put = 0; switch (photometric) { case PHOTOMETRIC_RGB: put = (bitspersample == 8 ? putRGBcontig8bittile : putRGBcontig16bittile); break; case PHOTOMETRIC_PALETTE: switch (bitspersample) { case 8: put = put8bitcmaptile; break; case 4: put = put4bitcmaptile; break; case 2: put = put2bitcmaptile; break; case 1: put = put1bitcmaptile; break; } break; case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: switch (bitspersample) { case 8: put = putgreytile; break; case 4: put = put4bitbwtile; break; case 2: put = put2bitbwtile; break; case 1: put = put1bitbwtile; break; } break; case PHOTOMETRIC_YCBCR: switch (bitspersample) { case 8: put = putcontig8bitYCbCrtile; break; } break; } if (put == 0) TIFFError(filename, "Can not handle format"); return (put); } /* * Select the appropriate conversion routine for unpacked data. * * NB: we assume that unpacked single channel data is directed * to the "packed routines. */ static tileSeparateRoutine DECLARE1(pickTileSeparateCase, RGBvalue*, Map) { tileSeparateRoutine put = 0; switch (photometric) { case PHOTOMETRIC_RGB: put = (bitspersample == 8 ? putRGBseparate8bittile : putRGBseparate16bittile); break; } if (put == 0) TIFFError(filename, "Can not handle format"); return (put); } int fromskew, toskew; { register u_long *bw; fromskew /= 4; while (h-- > 0) { UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); cp += toskew; pp += fromskew; } } /* * 1-bit palette => colormap/RGB */ static void put1bitcmaptile(cp, pp, Map, w, h, fromskew, toskew) register u_long *cp; register u_char *pp; register RGBvalue *Map; u_long w, h; int fromskew, toskew; { register u_long *bw; fromskew /= 8; while (h-- > 0) { UNROLL8(w, bw = PALmap[*pp++], *xloadimage.4.1/tiff/tif_jpeg.c 664 221 144 2746 5461577447 11457 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_jpeg.c,v 1.4 92/02/10 19:06:04 sam Exp $"; #endif /* * Copyright (c) 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Baseline JPEG Compression Algorithm Support. */ #include "tiffioP.h" TIFFInitJPEG(tif) register TIFF *tif; { return (1); } Map, w, h, fromskew, toskxloadimage.4.1/tiff/tif_lzw.c 664 221 144 57520 5461577447 11366 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_lzw.c,v 1.37 92/02/12 11:27:28 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * Rev 5.0 Lempel-Ziv & Welch Compression Support * * This code is derived from the compress program whose code is * derived from software contributed to Berkeley by James A. Woods, * derived from original work by Spencer Thomas and Joseph Orost. * * The original Berkeley copyright notice appears below in its entirety. */ #include "tiffioP.h" #include #include #include "prototypes.h" #define MAXCODE(n) ((1 << (n)) - 1) /* * The TIFF spec specifies that encoded bit strings range * from 9 to 12 bits. This is somewhat unfortunate in that * experience indicates full color RGB pictures often need * ~14 bits for reasonable compression. */ #define BITS_MIN 9 /* start with 9 bits */ #define BITS_MAX 12 /* max of 12 bit strings */ /* predefined codes */ #define CODE_CLEAR 256 /* code to clear string table */ #define CODE_EOI 257 /* end-of-information code */ #define CODE_FIRST 258 /* first free code entry */ #define CODE_MAX MAXCODE(BITS_MAX) #ifdef notdef #define HSIZE 9001 /* 91% occupancy */ #define HSHIFT (8-(16-13)) #else #define HSIZE 5003 /* 80% occupancy */ #define HSHIFT (8-(16-12)) #endif /* * NB: The 5.0 spec describes a different algorithm than Aldus * implements. Specifically, Aldus does code length transitions * one code earlier than should be done (for real LZW). * Earlier versions of this library implemented the correct * LZW algorithm, but emitted codes in a bit order opposite * to the TIFF spec. Thus, to maintain compatibility w/ Aldus * we interpret MSB-LSB ordered codes to be images written w/ * old versions of this library, but otherwise adhere to the * Aldus "off by one" algorithm. * * Future revisions to the TIFF spec are expected to "clarify this issue". */ #define SetMaxCode(sp, v) { \ (sp)->lzw_maxcode = (v)-1; \ if ((sp)->lzw_flags & LZW_COMPAT) \ (sp)->lzw_maxcode++; \ } /* * Decoding-specific state. */ struct decode { short prefixtab[HSIZE]; /* prefix(code) */ u_char suffixtab[CODE_MAX+1]; /* suffix(code) */ u_char stack[HSIZE-(CODE_MAX+1)]; u_char *stackp; /* stack pointer */ int firstchar; /* of string associated w/ last code */ }; /* * Encoding-specific state. */ struct encode { long checkpoint; /* point at which to clear table */ #define CHECK_GAP 10000 /* enc_ratio check interval */ long ratio; /* current compression ratio */ long incount; /* (input) data bytes encoded */ long outcount; /* encoded (output) bytes */ long htab[HSIZE]; /* hash table */ short codetab[HSIZE]; /* code table */ }; #if USE_PROTOTYPES typedef void (*predictorFunc)(char* data, int nbytes, int stride); #else typedef void (*predictorFunc)(); #endif /* * State block for each open TIFF * file using LZW compression/decompression. */ typedef struct { int lzw_oldcode; /* last code encountered */ u_short lzw_flags; #define LZW_RESTART 0x01 /* restart interrupted decode */ #define LZW_COMPAT 0x02 /* read old bit-reversed codes */ u_short lzw_nbits; /* number of bits/code */ u_short lzw_stride; /* horizontal diferencing stride */ u_short lzw_rowsize; /* XXX maybe should be a long? */ predictorFunc lzw_hordiff; int lzw_maxcode; /* maximum code for lzw_nbits */ long lzw_bitoff; /* bit offset into data */ long lzw_bitsize; /* size of strip in bits */ int lzw_free_ent; /* next free entry in hash table */ union { struct decode dec; struct encode enc; } u; } LZWState; #define dec_prefix u.dec.prefixtab #define dec_suffix u.dec.suffixtab #define dec_stack u.dec.stack #define dec_stackp u.dec.stackp #define dec_firstchar u.dec.firstchar #define enc_checkpoint u.enc.checkpoint #define enc_ratio u.enc.ratio #define enc_incount u.enc.incount #define enc_outcount u.enc.outcount #define enc_htab u.enc.htab #define enc_codetab u.enc.codetab /* masks for extracting/inserting variable length bit codes */ static const u_char rmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; static const u_char lmask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; #if USE_PROTOTYPES static int LZWPreEncode(TIFF*); static int LZWEncode(TIFF*, u_char*, int, u_int); static int LZWEncodePredRow(TIFF*, u_char*, int, u_int); static int LZWEncodePredTile(TIFF*, u_char*, int, u_int); static int LZWPostEncode(TIFF*); static int LZWDecode(TIFF*, u_char*, int, u_int); static int LZWDecodePredRow(TIFF*, u_char*, int, u_int); static int LZWDecodePredTile(TIFF*, u_char*, int, u_int); static int LZWPreDecode(TIFF*); static int LZWCleanup(TIFF*); static int GetNextCode(TIFF*); static void PutNextCode(TIFF*, int); static void cl_block(TIFF*); static void cl_hash(LZWState*); extern int TIFFFlushData1(TIFF *); #else static int LZWPreEncode(), LZWEncode(), LZWPostEncode(); static int LZWEncodePredRow(), LZWEncodePredTile(); static int LZWPreDecode(), LZWDecode(); static int LZWDecodePredRow(), LZWDecodePredTile(); static int LZWCleanup(); static int GetNextCode(); static void PutNextCode(); static void cl_block(); static void cl_hash(); extern int TIFFFlushData1(); #endif TIFFInitLZW(tif) TIFF *tif; { tif->tif_predecode = LZWPreDecode; tif->tif_decoderow = LZWDecode; tif->tif_decodestrip = LZWDecode; tif->tif_decodetile = LZWDecode; tif->tif_preencode = LZWPreEncode; tif->tif_postencode = LZWPostEncode; tif->tif_encoderow = LZWEncode; tif->tif_encodestrip = LZWEncode; tif->tif_encodetile = LZWEncode; tif->tif_cleanup = LZWCleanup; return (1); } static DECLARE4(LZWCheckPredictor, TIFF*, tif, LZWState*, sp, predictorFunc, pred8bit, predictorFunc, pred16bit ) { TIFFDirectory *td = &tif->tif_dir; switch (td->td_predictor) { case 1: break; case 2: sp->lzw_stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel : 1); switch (td->td_bitspersample) { case 8: sp->lzw_hordiff = pred8bit; break; case 16: sp->lzw_hordiff = pred16bit; break; default: TIFFError(tif->tif_name, "Horizontal differencing \"Predictor\" not supported with %d-bit samples", td->td_bitspersample); return (0); } break; default: TIFFError(tif->tif_name, "\"Predictor\" value %d not supported", td->td_predictor); return (0); } if (sp->lzw_hordiff) { /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) sp->lzw_rowsize = TIFFTileRowSize(tif); else sp->lzw_rowsize = TIFFScanlineSize(tif); } return (1); } /* * LZW Decoder. */ #define REPEAT4(n, op) \ switch (n) { \ default: { int i; for (i = n-4; i > 0; i--) { op; } } \ case 4: op; \ case 3: op; \ case 2: op; \ case 1: op; \ case 0: ; \ } static void DECLARE3(horizontalAccumulate8, register char*, cp, register int, cc, register int, stride ) { if (cc > stride) { cc -= stride; do { REPEAT4(stride, cp[stride] += cp[0]; cp++) cc -= stride; } while (cc > 0); } } static void DECLARE3(horizontalAccumulate16, char*, cp, int, cc, register int, stride ) { register short* wp = (short *)cp; register int wc = cc / 2; if (wc > stride) { wc -= stride; do { REPEAT4(stride, wp[stride] += wp[0]; wp++) wc -= stride; } while (wc > 0); } } /* * Setup state for decoding a strip. */ static LZWPreDecode(tif) TIFF *tif; { register LZWState *sp = (LZWState *)tif->tif_data; register int code; if (sp == NULL) { tif->tif_data = malloc(sizeof (LZWState)); if (tif->tif_data == NULL) { TIFFError("LZWPreDecode", "No space for LZW state block"); return (0); } sp = (LZWState *)tif->tif_data; sp->lzw_flags = 0; sp->lzw_hordiff = 0; sp->lzw_rowsize = 0; if (!LZWCheckPredictor(tif, sp, horizontalAccumulate8, horizontalAccumulate16)) return (0); if (sp->lzw_hordiff) { /* * Override default decoding method with * one that does the predictor stuff. */ tif->tif_decoderow = LZWDecodePredRow; tif->tif_decodestrip = LZWDecodePredTile; tif->tif_decodetile = LZWDecodePredTile; } } else sp->lzw_flags &= ~LZW_RESTART; sp->lzw_nbits = BITS_MIN; /* * Pre-load the table. */ for (code = 255; code >= 0; code--) sp->dec_suffix[code] = (u_char)code; sp->lzw_free_ent = CODE_FIRST; sp->lzw_bitoff = 0; /* calculate data size in bits */ sp->lzw_bitsize = tif->tif_rawdatasize; sp->lzw_bitsize = (sp->lzw_bitsize << 3) - (BITS_MAX-1); sp->dec_stackp = sp->dec_stack; sp->lzw_oldcode = -1; sp->dec_firstchar = -1; /* * Check for old bit-reversed codes. All the flag * manipulations are to insure only one warning is * given for a file. */ if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { if ((sp->lzw_flags & LZW_COMPAT) == 0) TIFFWarning(tif->tif_name, "Old-style LZW codes, convert file"); sp->lzw_flags |= LZW_COMPAT; } else sp->lzw_flags &= ~LZW_COMPAT; SetMaxCode(sp, MAXCODE(BITS_MIN)); return (1); } /* * Decode a "hunk of data". */ static LZWDecode(tif, op0, occ0, s) TIFF *tif; u_char *op0; u_int s; { register char *op = (char *)op0; register int occ = occ0; register LZWState *sp = (LZWState *)tif->tif_data; register int code; register u_char *stackp; int firstchar, oldcode, incode; stackp = sp->dec_stackp; /* * Restart interrupted unstacking operations. */ if (sp->lzw_flags & LZW_RESTART) { do { if (--occ < 0) { /* end of scanline */ sp->dec_stackp = stackp; return (1); } *op++ = *--stackp; } while (stackp > sp->dec_stack); sp->lzw_flags &= ~LZW_RESTART; } oldcode = sp->lzw_oldcode; firstchar = sp->dec_firstchar; while (occ > 0 && (code = GetNextCode(tif)) != CODE_EOI) { if (code == CODE_CLEAR) { bzero(sp->dec_prefix, sizeof (sp->dec_prefix)); sp->lzw_free_ent = CODE_FIRST; sp->lzw_nbits = BITS_MIN; SetMaxCode(sp, MAXCODE(BITS_MIN)); if ((code = GetNextCode(tif)) == CODE_EOI) break; *op++ = code, occ--; oldcode = firstchar = code; continue; } incode = code; /* * When a code is not in the table we use (as spec'd): * StringFromCode(oldcode) + * FirstChar(StringFromCode(oldcode)) */ if (code >= sp->lzw_free_ent) { /* code not in table */ *stackp++ = firstchar; code = oldcode; } /* * Generate output string (first in reverse). */ for (; code >= 256; code = sp->dec_prefix[code]) *stackp++ = sp->dec_suffix[code]; *stackp++ = firstchar = sp->dec_suffix[code]; do { if (--occ < 0) { /* end of scanline */ sp->lzw_flags |= LZW_RESTART; break; } *op++ = *--stackp; } while (stackp > sp->dec_stack); /* * Add the new entry to the code table. */ if ((code = sp->lzw_free_ent) < CODE_MAX) { sp->dec_prefix[code] = (u_short)oldcode; sp->dec_suffix[code] = firstchar; sp->lzw_free_ent++; /* * If the next entry is too big for the * current code size, then increase the * size up to the maximum possible. */ if (sp->lzw_free_ent > sp->lzw_maxcode) { sp->lzw_nbits++; if (sp->lzw_nbits > BITS_MAX) sp->lzw_nbits = BITS_MAX; SetMaxCode(sp, MAXCODE(sp->lzw_nbits)); } } oldcode = incode; } sp->dec_stackp = stackp; sp->lzw_oldcode = oldcode; sp->dec_firstchar = firstchar; if (occ > 0) { TIFFError(tif->tif_name, "LZWDecode: Not enough data at scanline %d (short %d bytes)", tif->tif_row, occ); return (0); } return (1); } /* * Decode a scanline and apply the predictor routine. */ static LZWDecodePredRow(tif, op0, occ0, s) TIFF *tif; u_char *op0; u_int s; { LZWState *sp = (LZWState *)tif->tif_data; if (LZWDecode(tif, op0, occ0, s)) { (*sp->lzw_hordiff)((char *)op0, occ0, sp->lzw_stride); return (1); } else return (0); } /* * Decode a tile/strip and apply the predictor routine. * Note that horizontal differencing must be done on a * row-by-row basis. The width of a "row" has already * been calculated at pre-decode time according to the * strip/tile dimensions. */ static LZWDecodePredTile(tif, op0, occ0, s) TIFF *tif; u_char *op0; u_int s; { LZWState *sp = (LZWState *)tif->tif_data; if (!LZWDecode(tif, op0, occ0, s)) return (0); while (occ0 > 0) { (*sp->lzw_hordiff)((char *)op0, sp->lzw_rowsize, sp->lzw_stride); occ0 -= sp->lzw_rowsize; op0 += sp->lzw_rowsize; } return (1); } /* * Get the next code from the raw data buffer. */ static GetNextCode(tif) TIFF *tif; { register LZWState *sp = (LZWState *)tif->tif_data; register int code, bits; register long r_off; register u_char *bp; /* * This check shouldn't be necessary because each * strip is suppose to be terminated with CODE_EOI. * At worst it's a substitute for the CODE_EOI that's * supposed to be there (see calculation of lzw_bitsize * in LZWPreDecode()). */ if (sp->lzw_bitoff > sp->lzw_bitsize) { TIFFWarning(tif->tif_name, "LZWDecode: Strip %d not terminated with EOI code", tif->tif_curstrip); return (CODE_EOI); } r_off = sp->lzw_bitoff; bits = sp->lzw_nbits; /* * Get to the first byte. */ bp = (u_char *)tif->tif_rawdata + (r_off >> 3); r_off &= 7; if (sp->lzw_flags & LZW_COMPAT) { /* Get first part (low order bits) */ code = (*bp++ >> r_off); r_off = 8 - r_off; /* now, offset into code word */ bits -= r_off; /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if (bits >= 8) { code |= *bp++ << r_off; r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off; } else { r_off = 8 - r_off; /* convert offset to count */ code = *bp++ & rmask[r_off]; /* high order bits */ bits -= r_off; if (bits >= 8) { code = (code<<8) | *bp++; bits -= 8; } /* low order bits */ code = (code << bits) | (((unsigned)(*bp & lmask[bits])) >> (8 - bits)); } sp->lzw_bitoff += sp->lzw_nbits; return (code); } /* * LZW Encoding. */ static void DECLARE3(horizontalDifference8, register char*, cp, register int, cc, register int, stride ) { if (cc > stride) { cc -= stride; cp += cc - 1; do { REPEAT4(stride, cp[stride] -= cp[0]; cp--) cc -= stride; } while (cc > 0); } } static void DECLARE3(horizontalDifference16, char*, cp, int, cc, register int, stride ) { register short *wp = (short *)cp; register int wc = cc/2; if (wc > stride) { wc -= stride; wp += wc - 1; do { REPEAT4(stride, wp[stride] -= wp[0]; wp--) wc -= stride; } while (wc > 0); } } /* * Reset encoding state at the start of a strip. */ static LZWPreEncode(tif) TIFF *tif; { register LZWState *sp = (LZWState *)tif->tif_data; if (sp == NULL) { tif->tif_data = malloc(sizeof (LZWState)); if (tif->tif_data == NULL) { TIFFError("LZWPreEncode", "No space for LZW state block"); return (0); } sp = (LZWState *)tif->tif_data; sp->lzw_flags = 0; sp->lzw_hordiff = 0; if (!LZWCheckPredictor(tif, sp, horizontalDifference8, horizontalDifference16)) return (0); if (sp->lzw_hordiff) { tif->tif_encoderow = LZWEncodePredRow; tif->tif_encodestrip = LZWEncodePredTile; tif->tif_encodetile = LZWEncodePredTile; } } sp->enc_checkpoint = CHECK_GAP; SetMaxCode(sp, MAXCODE(sp->lzw_nbits = BITS_MIN)+1); cl_hash(sp); /* clear hash table */ sp->lzw_bitoff = 0; sp->lzw_bitsize = (tif->tif_rawdatasize << 3) - (BITS_MAX-1); sp->lzw_oldcode = -1; /* generates CODE_CLEAR in LZWEncode */ return (1); } /* * Encode a scanline of pixels. * * Uses an open addressing double hashing (no chaining) on the * prefix code/next character combination. We do a variant of * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's * relatively-prime secondary probe. Here, the modular division * first probe is gives way to a faster exclusive-or manipulation. * Also do block compression with an adaptive reset, whereby the * code table is cleared when the compression ratio decreases, * but after the table fills. The variable-length output codes * are re-sized at this point, and a CODE_CLEAR is generated * for the decoder. */ static LZWEncode(tif, bp, cc, s) TIFF *tif; u_char *bp; int cc; u_int s; { static char module[] = "LZWEncode"; register LZWState *sp; register long fcode; register int h, c, ent, disp; if ((sp = (LZWState *)tif->tif_data) == NULL) return (0); ent = sp->lzw_oldcode; if (ent == -1 && cc > 0) { PutNextCode(tif, CODE_CLEAR); ent = *bp++; cc--; sp->enc_incount++; } while (cc > 0) { c = *bp++; cc--; sp->enc_incount++; fcode = ((long)c << BITS_MAX) + ent; h = (c << HSHIFT) ^ ent; /* xor hashing */ if (sp->enc_htab[h] == fcode) { ent = sp->enc_codetab[h]; continue; } if (sp->enc_htab[h] >= 0) { /* * Primary hash failed, check secondary hash. */ disp = HSIZE - h; if (h == 0) disp = 1; do { if ((h -= disp) < 0) h += HSIZE; if (sp->enc_htab[h] == fcode) { ent = sp->enc_codetab[h]; goto hit; } } while (sp->enc_htab[h] >= 0); } /* * New entry, emit code and add to table. */ PutNextCode(tif, ent); ent = c; sp->enc_codetab[h] = sp->lzw_free_ent++; sp->enc_htab[h] = fcode; if (sp->lzw_free_ent == CODE_MAX-1) { /* table is full, emit clear code and reset */ cl_hash(sp); PutNextCode(tif, CODE_CLEAR); SetMaxCode(sp, MAXCODE(sp->lzw_nbits = BITS_MIN)+1); } else { /* * If the next entry is going to be too big for * the code size, then increase it, if possible. */ if (sp->lzw_free_ent > sp->lzw_maxcode) { sp->lzw_nbits++; assert(sp->lzw_nbits <= BITS_MAX); SetMaxCode(sp, MAXCODE(sp->lzw_nbits)+1); } else if (sp->enc_incount >= sp->enc_checkpoint) cl_block(tif); } hit: ; } sp->lzw_oldcode = ent; return (1); } static LZWEncodePredRow(tif, bp, cc, s) TIFF *tif; u_char *bp; int cc; u_int s; { LZWState *sp = (LZWState *)tif->tif_data; /* XXX horizontal differencing alters user's data XXX */ (*sp->lzw_hordiff)((char *)bp, cc, sp->lzw_stride); return (LZWEncode(tif, bp, cc, s)); } static LZWEncodePredTile(tif, bp0, cc0, s) TIFF *tif; u_char *bp0; int cc0; u_int s; { LZWState *sp = (LZWState *)tif->tif_data; int cc = cc0; u_char *bp = bp0; while (cc > 0) { (*sp->lzw_hordiff)((char *)bp, sp->lzw_rowsize, sp->lzw_stride); cc -= sp->lzw_rowsize; bp += sp->lzw_rowsize; } return (LZWEncode(tif, bp0, cc0, s)); } /* * Finish off an encoded strip by flushing the last * string and tacking on an End Of Information code. */ static LZWPostEncode(tif) TIFF *tif; { LZWState *sp = (LZWState *)tif->tif_data; if (sp->lzw_oldcode != -1) { PutNextCode(tif, sp->lzw_oldcode); sp->lzw_oldcode = -1; } PutNextCode(tif, CODE_EOI); return (1); } static void PutNextCode(tif, c) TIFF *tif; int c; { register LZWState *sp = (LZWState *)tif->tif_data; register long r_off; register int bits, code = c; register char *bp; r_off = sp->lzw_bitoff; bits = sp->lzw_nbits; /* * Flush buffer if code doesn't fit. */ if (r_off + bits > sp->lzw_bitsize) { /* * Calculate the number of full bytes that can be * written and save anything else for the next write. */ if (r_off & 7) { tif->tif_rawcc = r_off >> 3; bp = tif->tif_rawdata + tif->tif_rawcc; (void) TIFFFlushData1(tif); tif->tif_rawdata[0] = *bp; } else { /* * Otherwise, on a byte boundary (in * which tiff_rawcc is already correct). */ (void) TIFFFlushData1(tif); } bp = tif->tif_rawdata; sp->lzw_bitoff = (r_off &= 7); } else { /* * Get to the first byte. */ bp = tif->tif_rawdata + (r_off >> 3); r_off &= 7; } /* * Note that lzw_bitoff is maintained as the bit offset * into the buffer w/ a right-to-left orientation (i.e. * lsb-to-msb). The bits, however, go in the file in * an msb-to-lsb order. */ bits -= (8 - r_off); *bp = (*bp & lmask[r_off]) | (code >> bits); bp++; if (bits >= 8) { bits -= 8; *bp++ = code >> bits; } if (bits) *bp = (code & rmask[bits]) << (8 - bits); /* * enc_outcount is used by the compression analysis machinery * which resets the compression tables when the compression * ratio goes up. lzw_bitoff is used here (in PutNextCode) for * inserting codes into the output buffer. tif_rawcc must * be updated for the mainline write code in TIFFWriteScanline() * so that data is flushed when the end of a strip is reached. * Note that the latter is rounded up to ensure that a non-zero * byte count is present. */ sp->enc_outcount += sp->lzw_nbits; sp->lzw_bitoff += sp->lzw_nbits; tif->tif_rawcc = (sp->lzw_bitoff + 7) >> 3; } /* * Check compression ratio and, if things seem to * be slipping, clear the hash table and reset state. */ static void cl_block(tif) TIFF *tif; { register LZWState *sp = (LZWState *)tif->tif_data; register long rat; sp->enc_checkpoint = sp->enc_incount + CHECK_GAP; if (sp->enc_incount > 0x007fffff) { /* shift will overflow */ rat = sp->enc_outcount >> 8; rat = (rat == 0 ? 0x7fffffff : sp->enc_incount / rat); } else rat = (sp->enc_incount<<8)/sp->enc_outcount; /* 8 fract bits */ if (rat <= sp->enc_ratio) { cl_hash(sp); PutNextCode(tif, CODE_CLEAR); SetMaxCode(sp, MAXCODE(sp->lzw_nbits = BITS_MIN)+1); } else sp->enc_ratio = rat; } /* * Reset code table and related statistics. */ static void cl_hash(sp) LZWState *sp; { register long *htab_p = sp->enc_htab+HSIZE; register long i, m1 = -1; i = HSIZE - 16; do { *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for (i += 16; i > 0; i--) *--htab_p = m1; sp->enc_ratio = 0; sp->enc_incount = 0; sp->enc_outcount = 0; sp->lzw_free_ent = CODE_FIRST; } static LZWCleanup(tif) TIFF *tif; { if (tif->tif_data) { free(tif->tif_data); tif->tif_data = NULL; } } /* * Copyright (c) 1985, 1986 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * James A. Woods, derived from original work by Spencer Thomas * and Joseph Orost. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ (!LZWCheckPredictor(tif, sp, horizontalDifference8, horizontalDifference16)) return (0); if (sp->lzw_hordiff) { tif->tif_encoderow = LZWEncodePredRow; tif->tixloadimage.4.1/tiff/tif_machdep.c 664 221 144 11235 5461577447 12144 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_machdep.c,v 1.2 92/03/06 11:52:42 sam Exp $"; #endif /* * Copyright (c) 1992 Sam Leffler * Copyright (c) 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library Machine Dependent Routines. */ #include "tiffioP.h" #ifdef tahoe typedef struct ieeedouble { u_long sign : 1, exp : 11, mant : 20; u_long mant2; } ieeedouble; typedef struct ieeefloat { u_long sign : 1, exp : 8, mant : 23; } ieeefloat; typedef struct { u_long sign : 1, exp : 8, mant : 23; u_long mant2; } nativedouble; typedef struct { u_long sign : 1, exp : 8, mant : 23; } nativefloat; /* * Beware, over/under-flow in conversions will * result in garbage values -- handling it would * require a subroutine call or lots more code. */ #define NATIVE2IEEEFLOAT(fp) { \ if ((fp)->native.exp) \ (fp)->ieee.exp = (fp)->native.exp - 129 + 127; /* alter bias */\ } #define IEEEFLOAT2NATIVE(fp) { \ if ((fp)->ieee.exp) \ (fp)->native.exp = (fp)->ieee.exp - 127 + 129; /* alter bias */\ } #define IEEEDOUBLE2NATIVE(dp) { \ if ((dp)->native.exp = (dp)->ieee.exp) \ (dp)->native.exp += -1023 + 129; \ (dp)->native.mant = ((dp)->ieee.mant<<3)|((dp)->native.mant2>>29); \ (dp)->native.mant2 <<= 3; \ } #endif /* tahoe */ #ifdef vax typedef struct ieeedouble { u_long mant : 20, exp : 11, sign : 1; u_long mant2; } ieeedouble; typedef struct ieeefloat { u_long mant : 23, exp : 8, sign : 1; } ieeefloat; typedef struct { u_long mant1 : 7, exp : 8, sign : 1, mant2 : 16; u_long mant3; } nativedouble; typedef struct { u_long mant1 : 7, exp : 8, sign : 1, mant2 : 16; } nativefloat; /* * Beware, these do not handle over/under-flow * during conversion from ieee to native format. */ #define NATIVE2IEEEFLOAT(fp) { \ float_t t; \ if (t.ieee.exp = (fp)->native.exp) \ t.ieee.exp += -129 + 127; \ t.ieee.sign = (fp)->native.sign; \ t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \ *(fp) = t; \ } #define IEEEFLOAT2NATIVE(fp) { \ float_t t; int v = (fp)->ieee.exp; \ if (v) v += -127 + 129; /* alter bias of exponent */\ t.native.exp = v; /* implicit truncation of exponent */\ t.native.sign = (fp)->ieee.sign; \ v = (fp)->ieee.mant; \ t.native.mant1 = v >> 16; \ t.native.mant2 = v;\ *(fp) = t; \ } #define IEEEDOUBLE2NATIVE(dp) { \ double_t t; int v = (dp)->ieee.exp; \ if (v) v += -1023 + 129; /* if can alter bias of exponent */\ t.native.exp = v; /* implicit truncation of exponent */\ v = (dp)->ieee.mant; \ t.native.sign = (dp)->ieee.sign; \ t.native.mant1 = v >> 16; \ t.native.mant2 = v;\ t.native.mant3 = (dp)->mant2; \ *(dp) = t; \ } #endif /* vax */ #if !HAVE_IEEEFP #if !defined(IEEEFLOAT2NATIVE) || !defined(NATIVE2IEEEFLOAT) "Help, you've configured the library to not have IEEE floating point,\ but not defined how to convert between IEEE and native formats!" #endif /* * These unions are used during floating point * conversions. The above macros define the * conversion operations. */ typedef union { ieeedouble ieee; nativedouble native; char b[8]; double d; } double_t; typedef union { ieeefloat ieee; nativefloat native; char b[4]; float f; } float_t; TIFFCvtIEEEFloatToNative(tif, n, f) TIFF *tif; u_int n; float *f; { float_t *fp = (float_t *)f; while (n-- > 0) { IEEEFLOAT2NATIVE(fp); fp++; } } TIFFCvtNativeToIEEEFloat(tif, n, f) TIFF *tif; u_int n; float *f; { float_t *fp = (float_t *)f; while (n-- > 0) { NATIVE2IEEEFLOAT(fp); fp++; } } #endif 992 Sam Leffler * Copyright (c) 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and xloadimage.4.1/tiff/tif_next.c 664 221 144 7316 5461577447 11506 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_next.c,v 1.14 92/02/10 19:06:45 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * NeXT 2-bit Grey Scale Compression Algorithm Support */ #include "tiffioP.h" #if USE_PROTOTYPES static int NeXTDecode(TIFF *, u_char *, int, u_int); #else static int NeXTDecode(); #endif TIFFInitNeXT(tif) TIFF *tif; { tif->tif_decoderow = NeXTDecode; tif->tif_decodestrip = NeXTDecode; tif->tif_decodetile = NeXTDecode; return (1); } #define SETPIXEL(op, v) { \ switch (npixels++ & 3) { \ case 0: op[0] = (v) << 6; break; \ case 1: op[0] |= (v) << 4; break; \ case 2: op[0] |= (v) << 2; break; \ case 3: *op++ |= (v); break; \ } \ } #define LITERALROW 0x00 #define LITERALSPAN 0x40 #define WHITE ((1<<2)-1) static int NeXTDecode(tif, buf, occ, s) TIFF *tif; u_char *buf; int occ; u_int s; { register u_char *bp, *op; register int cc, n; u_char *row; int scanline; /* * Each scanline is assumed to start off as all * white (we assume a PhotometricInterpretation * of ``min-is-black''). */ for (op = buf, cc = occ; cc-- > 0;) *op++ = 0xff; bp = (u_char *)tif->tif_rawcp; cc = tif->tif_rawcc; scanline = tif->tif_scanlinesize; for (row = buf; occ > 0; occ -= scanline, row += scanline) { n = *bp++, cc--; switch (n) { case LITERALROW: /* * The entire scanline is given as literal values. */ if (cc < scanline) goto bad; bcopy(bp, row, scanline); bp += scanline; cc -= scanline; break; case LITERALSPAN: { int off; /* * The scanline has a literal span * that begins at some offset. */ off = (bp[0] * 256) + bp[1]; n = (bp[2] * 256) + bp[3]; if (cc < 4+n) goto bad; bcopy(bp+4, row+off, n); bp += 4+n; cc -= 4+n; break; } default: { register int npixels = 0, grey; int imagewidth = tif->tif_dir.td_imagewidth; /* * The scanline is composed of a sequence * of constant color ``runs''. We shift * into ``run mode'' and interpret bytes * as codes of the form * until we've filled the scanline. */ op = row; for (;;) { grey = (n>>6) & 0x3; n &= 0x3f; while (n-- > 0) SETPIXEL(op, grey); if (npixels >= imagewidth) break; if (cc == 0) goto bad; n = *bp++, cc--; } break; } } } tif->tif_rawcp = (char *)bp; tif->tif_rawcc = cc; return (1); bad: TIFFError(tif->tif_name, "NeXTDecode: Not enough data for scanline %d", tif->tif_row); return (0); } AVE_IEEEFP #if !defined(IEEEFLOAT2NATIVE) || !defined(NATIVE2IEEEFLOAT) "Help, you've configured the library to not have IEEE floating point,\ but not defined how to convert between IEEE and native formats!" #endif /* * These unions are used during floating point * conversions. The above macros definexloadimage.4.1/tiff/tif_open.c 664 221 144 21134 5461577447 11503 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_open.c,v 1.33 92/02/14 13:40:51 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. */ #include "tiffioP.h" #include "prototypes.h" #if USE_PROTOTYPES extern int TIFFDefaultDirectory(TIFF*); #else extern int TIFFDefaultDirectory(); #endif static const long typemask[13] = { 0, /* TIFF_NOTYPE */ 0x000000ff, /* TIFF_BYTE */ 0xffffffff, /* TIFF_ASCII */ 0x0000ffff, /* TIFF_SHORT */ 0xffffffff, /* TIFF_LONG */ 0xffffffff, /* TIFF_RATIONAL */ 0x000000ff, /* TIFF_SBYTE */ 0x000000ff, /* TIFF_UNDEFINED */ 0x0000ffff, /* TIFF_SSHORT */ 0xffffffff, /* TIFF_SLONG */ 0xffffffff, /* TIFF_SRATIONAL */ 0xffffffff, /* TIFF_FLOAT */ 0xffffffff, /* TIFF_DOUBLE */ }; static const int bigTypeshift[13] = { 0, /* TIFF_NOTYPE */ 24, /* TIFF_BYTE */ 0, /* TIFF_ASCII */ 16, /* TIFF_SHORT */ 0, /* TIFF_LONG */ 0, /* TIFF_RATIONAL */ 16, /* TIFF_SBYTE */ 16, /* TIFF_UNDEFINED */ 24, /* TIFF_SSHORT */ 0, /* TIFF_SLONG */ 0, /* TIFF_SRATIONAL */ 0, /* TIFF_FLOAT */ 0, /* TIFF_DOUBLE */ }; static const int litTypeshift[13] = { 0, /* TIFF_NOTYPE */ 0, /* TIFF_BYTE */ 0, /* TIFF_ASCII */ 0, /* TIFF_SHORT */ 0, /* TIFF_LONG */ 0, /* TIFF_RATIONAL */ 0, /* TIFF_SBYTE */ 0, /* TIFF_UNDEFINED */ 0, /* TIFF_SSHORT */ 0, /* TIFF_SLONG */ 0, /* TIFF_SRATIONAL */ 0, /* TIFF_FLOAT */ 0, /* TIFF_DOUBLE */ }; /* * Initialize the bit fill order, the * shift & mask tables, and the byte * swapping state according to the file * contents and the machine architecture. */ static DECLARE3(TIFFInitOrder, register TIFF*, tif, int, magic, int, bigendian) { /* XXX how can we deduce this dynamically? */ tif->tif_fillorder = FILLORDER_MSB2LSB; tif->tif_typemask = typemask; if (magic == TIFF_BIGENDIAN) { tif->tif_typeshift = bigTypeshift; if (!bigendian) tif->tif_flags |= TIFF_SWAB; } else { tif->tif_typeshift = litTypeshift; if (bigendian) tif->tif_flags |= TIFF_SWAB; } } static int DECLARE2(getMode, char*, mode, char*, module) { int m = -1; switch (mode[0]) { case 'r': m = O_RDONLY; if (mode[1] == '+') m = O_RDWR; break; case 'w': case 'a': m = O_RDWR|O_CREAT; if (mode[0] == 'w') m |= O_TRUNC; break; default: TIFFError(module, "\"%s\": Bad mode", mode); break; } return (m); } /* * Open a TIFF file for read/writing. */ TIFF * TIFFOpen(name, mode) char *name, *mode; { static char module[] = "TIFFOpen"; int m, fd; m = getMode(mode, module); if (m == -1) return ((TIFF *)0); fd = TIFFOpenFile(name, m, 0666); if (fd < 0) { TIFFError(module, "%s: Cannot open", name); return ((TIFF *)0); } return (TIFFFdOpen(fd, name, mode)); } /* * Open a TIFF file descriptor for read/writing. */ TIFF * TIFFFdOpen(fd, name, mode) int fd; char *name, *mode; { static char module[] = "TIFFFdOpen"; TIFF *tif; int m, bigendian; m = getMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)malloc(sizeof (TIFF) + strlen(name) + 1); if (tif == NULL) { TIFFError(module, "%s: Out of memory (TIFF structure)", name); goto bad2; } bzero((char *)tif, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_fd = fd; tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = -1; /* invalid strip */ tif->tif_row = -1; /* read/write pre-increment */ { int one = 1; bigendian = (*(char *)&one == 0); } /* * Read in TIFF header. */ if (!ReadOK(fd, &tif->tif_header, sizeof (TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { TIFFError(name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ tif->tif_header.tiff_magic = bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; tif->tif_header.tiff_version = TIFF_VERSION; tif->tif_header.tiff_diroff = 0; /* filled in later */ if (!WriteOK(fd, &tif->tif_header, sizeof (TIFFHeader))) { TIFFError(name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)", tif->tif_header.tiff_magic, tif->tif_header.tiff_magic); goto bad; } TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Swap header if required. */ if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.tiff_version); TIFFSwabLong(&tif->tif_header.tiff_diroff); } /* * Now check version (if needed, it's been byte-swapped). * Note that this isn't actually a version number, it's a * magic number that doesn't change (stupid). */ if (tif->tif_header.tiff_version != TIFF_VERSION) { TIFFError(name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.tiff_version, tif->tif_header.tiff_version); goto bad; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; /* * Setup initial directory. */ switch (mode[0]) { case 'r': tif->tif_nextdiroff = tif->tif_header.tiff_diroff; #ifdef MMAP_SUPPORT if (TIFFMapFileContents(fd, &tif->tif_base, &tif->tif_size)) tif->tif_flags |= TIFF_MAPPED; #endif if (TIFFReadDirectory(tif)) { tif->tif_rawcc = -1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * Don't append to file that has information * byte swapped -- we will write data that is * in the opposite order. */ if (tif->tif_flags & TIFF_SWAB) { TIFFError(name, "Cannot append to file that has opposite byte ordering"); goto bad; } /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFClose(tif); return ((TIFF *)0); bad2: (void) close(fd); return ((TIFF *)0); } TIFFScanlineSize(tif) TIFF *tif; { TIFFDirectory *td = &tif->tif_dir; long scanline; scanline = td->td_bitspersample * td->td_imagewidth; if (td->td_planarconfig == PLANARCONFIG_CONTIG) scanline *= td->td_samplesperpixel; return (howmany(scanline, 8)); } /* * Query functions to access private data. */ /* * Return open file's name. */ char * TIFFFileName(tif) TIFF *tif; { return (tif->tif_name); } /* * Return open file's I/O descriptor. */ int TIFFFileno(tif) TIFF *tif; { return (tif->tif_fd); } /* * Return read/write mode. */ int TIFFGetMode(tif) TIFF *tif; { return (tif->tif_mode); } /* * Return nonzero if file is organized in * tiles; zero if organized as strips. */ int TIFFIsTiled(tif) TIFF *tif; { return (isTiled(tif)); } /* * Return current row being read/written. */ long TIFFCurrentRow(tif) TIFF *tif; { return (tif->tif_row); } /* * Return index of the current directory. */ int TIFFCurrentDirectory(tif) TIFF *tif; { return (tif->tif_curdir); } /* * Return current strip. */ int TIFFCurrentStrip(tif) TIFF *tif; { return (tif->tif_curstrip); } /* * Return current tile. */ int TIFFCurrentTile(tif) TIFF *tif; { return (tif->tif_curtile); } 1) { PutNextCode(tif, sp->lzw_oldcode); sp->lzw_oldcode = -1; } PutNextCode(tif, CODE_EOI); return (1); } static void PutNextCode(tif, c) TIFF *tif; int c; { register LZWState *sp = (LZWState *)tif->tif_data; register long r_off; register int bits, code = c; register char *bp; r_off = sp->lzw_bitoff; bits = sp->lzw_nbits; /* * Flush buffer if code doesn't fit. */ if (r_off + bits > sp->lzw_bitsxloadimage.4.1/tiff/tif_packbits.c 664 221 144 14634 5461577447 12351 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_packbits.c,v 1.23 92/03/30 18:29:40 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * PackBits Compression Algorithm Support */ #include "tiffioP.h" #include #include #if USE_PROTOTYPES static int PackBitsPreEncode(TIFF *); static int PackBitsEncode(TIFF *, u_char *, int, u_int); static int PackBitsEncodeChunk(TIFF *, u_char *, int, u_int); static int PackBitsDecode(TIFF *, u_char *, int, u_int); #else static int PackBitsPreEncode(); static int PackBitsEncode(), PackBitsEncodeChunk(); static int PackBitsDecode(); #endif TIFFInitPackBits(tif) TIFF *tif; { tif->tif_decoderow = PackBitsDecode; tif->tif_decodestrip = PackBitsDecode; tif->tif_decodetile = PackBitsDecode; tif->tif_preencode = PackBitsPreEncode; tif->tif_encoderow = PackBitsEncode; tif->tif_encodestrip = PackBitsEncodeChunk; tif->tif_encodetile = PackBitsEncodeChunk; return (1); } static int PackBitsPreEncode(tif) TIFF *tif; { /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) tif->tif_data = (char *) TIFFTileRowSize(tif); else tif->tif_data = (char *) TIFFScanlineSize(tif); return (1); } /* * Encode a rectangular chunk of pixels. We break it up * into row-sized pieces to insure that encoded runs do * not span rows. Otherwise, there can be problems with * the decoder if data is read, for example, by scanlines * when it was encoded by strips. */ static int PackBitsEncodeChunk(tif, bp, cc, s) TIFF *tif; u_char *bp; int cc; u_int s; { int rowsize = (int) tif->tif_data; assert(rowsize > 0); while (cc > 0) { if (PackBitsEncode(tif, bp, rowsize, s) < 0) return (-1); bp += rowsize; cc -= rowsize; } return (1); } /* * Encode a run of pixels. */ static int PackBitsEncode(tif, bp, cc, s) TIFF *tif; u_char *bp; register int cc; u_int s; { register char *op, *lastliteral; register int n, b; enum { BASE, LITERAL, RUN, LITERAL_RUN } state; char *ep; int slop; op = tif->tif_rawcp; ep = tif->tif_rawdata + tif->tif_rawdatasize; state = BASE; lastliteral = 0; while (cc > 0) { /* * Find the longest string of identical bytes. */ b = *bp++, cc--, n = 1; for (; cc > 0 && b == *bp; cc--, bp++) n++; again: if (op + 2 >= ep) { /* insure space for new data */ /* * Be careful about writing the last * literal. Must write up to that point * and then copy the remainder to the * front of the buffer. */ if (state == LITERAL || state == LITERAL_RUN) { slop = op - lastliteral; tif->tif_rawcc += lastliteral - tif->tif_rawcp; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; for (; slop-- > 0; *op++ = *lastliteral++) ; lastliteral = tif->tif_rawcp; } else { tif->tif_rawcc += op - tif->tif_rawcp; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; } } switch (state) { case BASE: /* initial state, set run/literal */ if (n > 1) { state = RUN; if (n > 128) { *op++ = -127; *op++ = b; n -= 128; goto again; } *op++ = -(n-1); *op++ = b; } else { lastliteral = op; *op++ = 0; *op++ = b; state = LITERAL; } break; case LITERAL: /* last object was literal string */ if (n > 1) { state = LITERAL_RUN; if (n > 128) { *op++ = -127; *op++ = b; n -= 128; goto again; } *op++ = -(n-1); /* encode run */ *op++ = b; } else { /* extend literal */ if (++(*lastliteral) == 127) state = BASE; *op++ = b; } break; case RUN: /* last object was run */ if (n > 1) { if (n > 128) { *op++ = -127; *op++ = b; n -= 128; goto again; } *op++ = -(n-1); *op++ = b; } else { lastliteral = op; *op++ = 0; *op++ = b; state = LITERAL; } break; case LITERAL_RUN: /* literal followed by a run */ /* * Check to see if previous run should * be converted to a literal, in which * case we convert literal-run-literal * to a single literal. */ if (n == 1 && op[-2] == (char)-1 && *lastliteral < 126) { state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL); op[-2] = op[-1]; /* replicate */ } else state = RUN; goto again; } } tif->tif_rawcc += op - tif->tif_rawcp; tif->tif_rawcp = op; return (1); } static int PackBitsDecode(tif, op, occ, s) TIFF *tif; register u_char *op; register int occ; u_int s; { register char *bp; register int n, b; register int cc; bp = tif->tif_rawcp; cc = tif->tif_rawcc; while (cc > 0 && occ > 0) { n = (int) *bp++; /* * Watch out for compilers that * don't sign extend chars... */ if (n >= 128) n -= 256; if (n < 0) { /* replicate next byte -n+1 times */ cc--; if (n == -128) /* nop */ continue; n = -n + 1; occ -= n; for (b = *bp++; n-- > 0;) *op++ = b; } else { /* copy next n+1 bytes literally */ bcopy(bp, op, ++n); op += n; occ -= n; bp += n; cc -= n; } } tif->tif_rawcp = bp; tif->tif_rawcc = cc; if (occ > 0) { TIFFError(tif->tif_name, "PackBitsDecode: Not enough data for scanline %d", tif->tif_row); return (0); } /* check for buffer overruns? */ return (1); } zero if file is organized in * tiles; zero if organized as strips. */ int TIFFIsTiled(tif) TIFF *xloadimage.4.1/tiff/tif_print.c 664 221 144 41402 5461577447 11676 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_print.c,v 1.43 92/03/17 11:08:58 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Directory Printing Support */ #include #include #include "tiffioP.h" #ifdef JPEG_SUPPORT static JPEGPrintQTable(fd, tab) FILE *fd; u_char tab[64]; { int i, j; char *sep; fputc('\n', fd); for (i = 0; i < 8; i++) { sep = " "; for (j = 0; j < 8; j++) { fprintf(fd, "%s%2u", sep, tab[8*i+j]); sep = ", "; } fputc('\n', fd); } } static JPEGPrintCTable(fd, tab) FILE *fd; u_char *tab; { int i, n, count; char *sep; fprintf(fd, "\n Bits:"); count = 0; for (i = 0; i < 16; i++) { fprintf(fd, " %u", tab[i]); count += tab[i]; } n = 0; for (; count > 0; count--) { if ((n % 8) == 0) { fputc('\n', fd); sep = " "; } fprintf(fd, "%s0x%02x", sep, tab[i++]); sep = ", "; n++; } if (n % 8) fputc('\n', fd); } #endif static const char *photoNames[] = { "min-is-white", /* PHOTOMETRIC_MINISWHITE */ "min-is-black", /* PHOTOMETRIC_MINISBLACK */ "RGB color", /* PHOTOMETRIC_RGB */ "palette color (RGB from colormap)", /* PHOTOMETRIC_PALETTE */ "transparency mask", /* PHOTOMETRIC_MASK */ "separated", /* PHOTOMETRIC_SEPARATED */ "YCbCr", /* PHOTOMETRIC_YCBCR */ "7 (0x7)", "CIE L*a*b*", /* PHOTOMETRIC_CIELAB */ }; #define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0])) static const char *orientNames[] = { "0 (0x0)", "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */ "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */ "row 0 bottom, col 0 rhs", /* ORIENTATION_BOTRIGHT */ "row 0 bottom, col 0 lhs", /* ORIENTATION_BOTLEFT */ "row 0 lhs, col 0 top", /* ORIENTATION_LEFTTOP */ "row 0 rhs, col 0 top", /* ORIENTATION_RIGHTTOP */ "row 0 rhs, col 0 bottom", /* ORIENTATION_RIGHTBOT */ "row 0 lhs, col 0 bottom", /* ORIENTATION_LEFTBOT */ }; #define NORIENTNAMES (sizeof (orientNames) / sizeof (orientNames[0])) /* * Print the contents of the current directory * to the specified stdio file stream. */ void TIFFPrintDirectory(tif, fd, flags) TIFF *tif; FILE *fd; long flags; { register TIFFDirectory *td; char *sep; int i, j; long n; fprintf(fd, "TIFF Directory at offset 0x%x\n", tif->tif_diroff); td = &tif->tif_dir; if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { fprintf(fd, " Subfile Type:"); sep = " "; if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { fprintf(fd, "%sreduced-resolution image", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_PAGE) { fprintf(fd, "%smulti-page document", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_MASK) fprintf(fd, "%stransparency mask", sep); fprintf(fd, " (%u = 0x%x)\n", td->td_subfiletype, td->td_subfiletype); } if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { fprintf(fd, " Image Width: %lu Image Length: %lu", td->td_imagewidth, td->td_imagelength); if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) fprintf(fd, " Image Depth: %lu", td->td_imagedepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { fprintf(fd, " Tile Width: %lu Tile Length: %lu", td->td_tilewidth, td->td_tilelength); if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) fprintf(fd, " Tile Depth: %lu", td->td_tiledepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { fprintf(fd, " Resolution: %g, %g", td->td_xresolution, td->td_yresolution); if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { switch (td->td_resolutionunit) { case RESUNIT_NONE: fprintf(fd, " (unitless)"); break; case RESUNIT_INCH: fprintf(fd, " pixels/inch"); break; case RESUNIT_CENTIMETER: fprintf(fd, " pixels/cm"); break; default: fprintf(fd, " (unit %u = 0x%x)", td->td_resolutionunit, td->td_resolutionunit); break; } } fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_POSITION)) fprintf(fd, " Position: %g, %g\n", td->td_xposition, td->td_yposition); if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { fprintf(fd, " Sample Format: "); switch (td->td_sampleformat) { case SAMPLEFORMAT_VOID: fprintf(fd, "void\n"); break; case SAMPLEFORMAT_INT: fprintf(fd, "signed integer\n"); break; case SAMPLEFORMAT_UINT: fprintf(fd, "unsigned integer\n"); break; case SAMPLEFORMAT_IEEEFP: fprintf(fd, "IEEE floating point\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_sampleformat, td->td_sampleformat); break; } } if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { fprintf(fd, " Compression Scheme: "); switch (td->td_compression) { case COMPRESSION_NONE: fprintf(fd, "none\n"); break; case COMPRESSION_CCITTRLE: fprintf(fd, "CCITT modified Huffman encoding\n"); break; case COMPRESSION_CCITTFAX3: fprintf(fd, "CCITT Group 3 facsimile encoding\n"); break; case COMPRESSION_CCITTFAX4: fprintf(fd, "CCITT Group 4 facsimile encoding\n"); break; case COMPRESSION_CCITTRLEW: fprintf(fd, "CCITT modified Huffman encoding %s\n", "w/ word alignment"); break; case COMPRESSION_PACKBITS: fprintf(fd, "Macintosh PackBits encoding\n"); break; case COMPRESSION_THUNDERSCAN: fprintf(fd, "ThunderScan 4-bit encoding\n"); break; case COMPRESSION_LZW: fprintf(fd, "Lempel-Ziv & Welch encoding\n"); break; case COMPRESSION_NEXT: fprintf(fd, "NeXT 2-bit encoding\n"); break; case COMPRESSION_JPEG: fprintf(fd, "JPEG encoding\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_compression, td->td_compression); break; } } if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { fprintf(fd, " Photometric Interpretation: "); if (td->td_photometric < NPHOTONAMES) fprintf(fd, "%s\n", photoNames[td->td_photometric]); else fprintf(fd, "%u (0x%x)\n", td->td_photometric, td->td_photometric); } if (TIFFFieldSet(tif,FIELD_MATTEING)) fprintf(fd, " Matteing: %s\n", td->td_matteing ? "pre-multiplied with alpha channel" : "none"); #ifdef CMYK_SUPPORT if (TIFFFieldSet(tif,FIELD_INKSET)) { fprintf(fd, " Ink Set: "); switch (td->td_inkset) { case INKSET_CMYK: fprintf(fd, "CMYK\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_inkset, td->td_inkset); break; } } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { char *cp; fprintf(fd, " Ink Names: "); i = td->td_samplesperpixel; sep = ""; for (cp = td->td_inknames; i > 0; cp = strchr(cp, '\0')) { fprintf(fd, "%s%s", sep, cp); sep = ", "; } } if (TIFFFieldSet(tif,FIELD_DOTRANGE)) fprintf(fd, " Dot Range: %u-%u\n", td->td_dotrange[0], td->td_dotrange[1]); if (TIFFFieldSet(tif,FIELD_TARGETPRINTER)) fprintf(fd, " Target Printer: %s\n", td->td_targetprinter); #endif if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { fprintf(fd, " Thresholding: "); switch (td->td_threshholding) { case THRESHHOLD_BILEVEL: fprintf(fd, "bilevel art scan\n"); break; case THRESHHOLD_HALFTONE: fprintf(fd, "halftone or dithered scan\n"); break; case THRESHHOLD_ERRORDIFFUSE: fprintf(fd, "error diffused\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_threshholding, td->td_threshholding); break; } } if (TIFFFieldSet(tif,FIELD_FILLORDER)) { fprintf(fd, " FillOrder: "); switch (td->td_fillorder) { case FILLORDER_MSB2LSB: fprintf(fd, "msb-to-lsb\n"); break; case FILLORDER_LSB2MSB: fprintf(fd, "lsb-to-msb\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_fillorder, td->td_fillorder); break; } } if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { fprintf(fd, " Predictor: "); switch (td->td_predictor) { case 1: fprintf(fd, "none\n"); break; case 2: fprintf(fd, "horizontal differencing\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_predictor, td->td_predictor); break; } } #ifdef YCBCR_SUPPORT if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) fprintf(fd, " YCbCr Subsampling: %u, %u\n", td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1]); if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { fprintf(fd, " YCbCr Positioning: "); switch (td->td_ycbcrpositioning) { case YCBCRPOSITION_CENTERED: fprintf(fd, "centered\n"); break; case YCBCRPOSITION_COSITED: fprintf(fd, "cosited\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_ycbcrpositioning, td->td_ycbcrpositioning); break; } } if (TIFFFieldSet(tif,FIELD_YCBCRCOEFFICIENTS)) fprintf(fd, " YCbCr Coefficients: %g, %g, %g\n", td->td_ycbcrcoeffs[0], td->td_ycbcrcoeffs[1], td->td_ycbcrcoeffs[2]); #endif #ifdef JPEG_SUPPORT if (TIFFFieldSet(tif,FIELD_JPEGPROC)) { fprintf(fd, " JPEG Processing Mode: "); switch (td->td_jpegproc) { case JPEGPROC_BASELINE: fprintf(fd, "baseline sequential algorithm\n"); break; case JPEGPROC_LOSSLESS: fprintf(fd, "lossless algorithm with Huffman coding\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_jpegproc, td->td_jpegproc); break; } } if (TIFFFieldSet(tif,FIELD_JPEGRESTARTINTERVAL)) { fprintf(fd, " JPEG Restart Interval: "); if (td->td_jpegrestartinterval) fprintf(fd, "%u\n", td->td_jpegrestartinterval); else fprintf(fd, "(no restart markers)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGQTABLES)) { fprintf(fd, " JPEG Quantization Tables: "); if (flags & TIFFPRINT_JPEGQTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintQTable(fd, td->td_qtab[i]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGDCTABLES)) { fprintf(fd, " JPEG DC Tables: "); if (flags & TIFFPRINT_JPEGDCTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintCTable(fd, td->td_dctab[i]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGACTABLES)) { fprintf(fd, " JPEG AC Tables: "); if (flags & TIFFPRINT_JPEGACTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintCTable(fd, td->td_actab[i]); } else fprintf(fd, "(present)\n"); } #endif if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) fprintf(fd, " Halftone Hints: light %u dark %u\n", td->td_halftonehints[0], td->td_halftonehints[1]); if (TIFFFieldSet(tif,FIELD_ARTIST)) fprintf(fd, " Artist: \"%s\"\n", td->td_artist); if (TIFFFieldSet(tif,FIELD_DATETIME)) fprintf(fd, " Date & Time: \"%s\"\n", td->td_datetime); if (TIFFFieldSet(tif,FIELD_HOSTCOMPUTER)) fprintf(fd, " Host Computer: \"%s\"\n", td->td_hostcomputer); if (TIFFFieldSet(tif,FIELD_SOFTWARE)) fprintf(fd, " Software: \"%s\"\n", td->td_software); if (TIFFFieldSet(tif,FIELD_DOCUMENTNAME)) fprintf(fd, " Document Name: \"%s\"\n", td->td_documentname); if (TIFFFieldSet(tif,FIELD_IMAGEDESCRIPTION)) fprintf(fd, " Image Description: \"%s\"\n", td->td_imagedescription); if (TIFFFieldSet(tif,FIELD_MAKE)) fprintf(fd, " Make: \"%s\"\n", td->td_make); if (TIFFFieldSet(tif,FIELD_MODEL)) fprintf(fd, " Model: \"%s\"\n", td->td_model); if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { fprintf(fd, " Orientation: "); if (td->td_orientation < NORIENTNAMES) fprintf(fd, "%s\n", orientNames[td->td_orientation]); else fprintf(fd, "%u (0x%x)\n", td->td_orientation, td->td_orientation); } if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { fprintf(fd, " Rows/Strip: "); if (td->td_rowsperstrip == 0xffffffffL) fprintf(fd, "(infinite)\n"); else fprintf(fd, "%u\n", td->td_rowsperstrip); } if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { fprintf(fd, " Planar Configuration: "); switch (td->td_planarconfig) { case PLANARCONFIG_CONTIG: fprintf(fd, "single image plane\n"); break; case PLANARCONFIG_SEPARATE: fprintf(fd, "separate image planes\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_planarconfig, td->td_planarconfig); break; } } if (TIFFFieldSet(tif,FIELD_PAGENAME)) fprintf(fd, " Page Name: \"%s\"\n", td->td_pagename); if (TIFFFieldSet(tif,FIELD_GROUP3OPTIONS)) { fprintf(fd, " Group 3 Options:"); sep = " "; if (td->td_group3options & GROUP3OPT_2DENCODING) fprintf(fd, "%s2-d encoding", sep), sep = "+"; if (td->td_group3options & GROUP3OPT_FILLBITS) fprintf(fd, "%sEOL padding", sep), sep = "+"; if (td->td_group3options & GROUP3OPT_UNCOMPRESSED) fprintf(fd, "%suncompressed data", sep); fprintf(fd, " (%u = 0x%x)\n", td->td_group3options, td->td_group3options); } if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { fprintf(fd, " Fax Data: "); switch (td->td_cleanfaxdata) { case CLEANFAXDATA_CLEAN: fprintf(fd, "clean\n"); break; case CLEANFAXDATA_REGENERATED: fprintf(fd, "receiver regenerated\n"); break; case CLEANFAXDATA_UNCLEAN: fprintf(fd, "uncorrected errors\n"); break; default: fprintf(fd, "(%u = 0x%x)\n", td->td_cleanfaxdata, td->td_cleanfaxdata); break; } } if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) fprintf(fd, " Bad Fax Lines: %u\n", td->td_badfaxlines); if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) fprintf(fd, " Consecutive Bad Fax Lines: %u\n", td->td_badfaxrun); if (TIFFFieldSet(tif,FIELD_GROUP4OPTIONS)) { fprintf(fd, " Group 4 Options:"); if (td->td_group4options & GROUP4OPT_UNCOMPRESSED) fprintf(fd, "uncompressed data"); fprintf(fd, " (%u = 0x%x)\n", td->td_group4options, td->td_group4options); } if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) fprintf(fd, " Page Number: %u-%u\n", td->td_pagenumber[0], td->td_pagenumber[1]); if (TIFFFieldSet(tif,FIELD_COLORMAP)) { fprintf(fd, " Color Map: "); if (flags & TIFFPRINT_COLORMAP) { fprintf(fd, "\n"); n = 1L<td_bitspersample; for (i = 0; i < n; i++) fprintf(fd, " %5d: %5u %5u %5u\n", i, td->td_colormap[0][i], td->td_colormap[1][i], td->td_colormap[2][i]); } else fprintf(fd, "(present)\n"); } #ifdef COLORIMETRY_SUPPORT if (TIFFFieldSet(tif,FIELD_WHITEPOINT)) fprintf(fd, " White Point: %g-%g\n", td->td_whitepoint[0], td->td_whitepoint[1]); if (TIFFFieldSet(tif,FIELD_PRIMARYCHROMAS)) fprintf(fd, " Primary Chromaticities: %g,%g %g,%g %g,%g\n", td->td_primarychromas[0], td->td_primarychromas[1], td->td_primarychromas[2], td->td_primarychromas[3], td->td_primarychromas[4], td->td_primarychromas[5]); if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { fprintf(fd, " Reference Black/White:\n"); for (i = 0; i < td->td_samplesperpixel; i++) fprintf(fd, " %2d: %5g %5g\n", i, td->td_refblackwhite[2*i+0], td->td_refblackwhite[2*i+1]); } if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { fprintf(fd, " Transfer Function: "); if (flags & TIFFPRINT_CURVES) { fprintf(fd, "\n"); n = 1L<td_bitspersample; for (i = 0; i < n; i++) { fprintf(fd, " %2d: %5u", i, td->td_transferfunction[0][i]); for (j = 1; j < td->td_samplesperpixel; j++) fprintf(fd, " %5u", td->td_transferfunction[j][i]); putc('\n', fd); } } else fprintf(fd, "(present)\n"); } #endif if ((flags & TIFFPRINT_STRIPS) && TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { fprintf(fd, " %u %s:\n", td->td_nstrips, isTiled(tif) ? "Tiles" : "Strips"); for (i = 0; i < td->td_nstrips; i++) fprintf(fd, " %3d: [%8u, %8u]\n", i, td->td_stripoffset[i], td->td_stripbytecount[i]); } } d_fillorder, td->td_fillorder); break; } } if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { fprintf(fd, " Predictor: "); switch (td->td_predictor) { case 1: fprintf(fd, "none\n"); break; case 2: fprintf(fd, "horizontal differencing\n"); xloadimage.4.1/tiff/tif_read.c 664 221 144 37165 5461577447 11470 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_read.c,v 1.43 92/02/10 19:06:41 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * Scanline-oriented Read Support */ #include "tiffioP.h" #if USE_PROTOTYPES static TIFFSeek(TIFF *, u_int, u_int); static int TIFFReadRawStrip1(TIFF *, u_int, u_char *, u_int, char []); static int TIFFReadRawTile1(TIFF *, u_int, u_char *, u_int, char []); static TIFFFillStrip(TIFF *, u_int); static TIFFFillTile(TIFF *, u_int); static TIFFStartStrip(TIFF *, u_int); static TIFFStartTile(TIFF *, u_int); static TIFFCheckRead(TIFF *, int); #else static TIFFSeek(); static int TIFFReadRawStrip1(); static int TIFFReadRawTile1(); static TIFFFillStrip(); static TIFFFillTile(); static TIFFStartStrip(); static TIFFStartTile(); static TIFFCheckRead(); #endif /*VARARGS3*/ TIFFReadScanline(tif, buf, row, sample) register TIFF *tif; u_char *buf; u_int row, sample; { int e; if (!TIFFCheckRead(tif, 0)) return (-1); if (e = TIFFSeek(tif, row, sample)) { /* * Decompress desired row into user buffer. */ e = (*tif->tif_decoderow)(tif, buf, tif->tif_scanlinesize, sample); tif->tif_row++; } return (e ? 1 : -1); } /* * Seek to a random row+sample in a file. */ static /*VARARGS2*/ TIFFSeek(tif, row, sample) register TIFF *tif; u_int row, sample; { register TIFFDirectory *td = &tif->tif_dir; int strip; if (row >= td->td_imagelength) { /* out of range */ TIFFError(tif->tif_name, "%d: Row out of range, max %d", row, td->td_imagelength); return (0); } if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFError(tif->tif_name, "%d: Sample out of range, max %d", sample, td->td_samplesperpixel); return (0); } strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; if (strip != tif->tif_curstrip) { /* different strip, refill */ if (!TIFFFillStrip(tif, strip)) return (0); } else if (row < tif->tif_row) { /* * Moving backwards within the same strip: backup * to the start and then decode forward (below). * * NB: If you're planning on lots of random access within a * strip, it's better to just read and decode the entire * strip, and then access the decoded data in a random fashion. */ if (!TIFFStartStrip(tif, strip)) return (0); } if (row != tif->tif_row) { if (tif->tif_seek) { /* * Seek forward to the desired row. */ if (!(*tif->tif_seek)(tif, row - tif->tif_row)) return (0); tif->tif_row = row; } else { TIFFError(tif->tif_name, "Compression algorithm does not support random access"); return (0); } } return (1); } /* * Read a strip of data and decompress the specified * amount into the user-supplied buffer. */ TIFFReadEncodedStrip(tif, strip, buf, size) TIFF *tif; u_int strip; u_char *buf; u_int size; { TIFFDirectory *td = &tif->tif_dir; u_int stripsize = TIFFStripSize(tif); if (!TIFFCheckRead(tif, 0)) return (-1); if (strip >= td->td_nstrips) { TIFFError(tif->tif_name, "%d: Strip out of range, max %d", strip, td->td_nstrips); return (-1); } /* * Calculate the strip size according to the number of * rows in the strip (check for truncated last strip). */ if (size == (u_int)-1) size = stripsize; else if (size > stripsize) size = stripsize; return (TIFFFillStrip(tif, strip) && (*tif->tif_decodestrip)(tif, buf, size, strip / td->td_stripsperimage) ? size : -1); } /* * Read a strip of data from the file. */ TIFFReadRawStrip(tif, strip, buf, size) TIFF *tif; u_int strip; u_char *buf; u_int size; { static char module[] = "TIFFReadRawStrip"; TIFFDirectory *td = &tif->tif_dir; u_long bytecount; if (!TIFFCheckRead(tif, 0)) return (-1); if (strip >= td->td_nstrips) { TIFFError(tif->tif_name, "%d: Strip out of range, max %d", strip, td->td_nstrips); return (-1); } bytecount = td->td_stripbytecount[strip]; if (size != (u_int)-1 && size < bytecount) bytecount = size; return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module)); } static int TIFFReadRawStrip1(tif, strip, buf, size, module) TIFF *tif; u_int strip; u_char *buf; u_int size; char module[]; { TIFFDirectory *td = &tif->tif_dir; if (!isMapped(tif)) { if (!SeekOK(tif->tif_fd, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %d, strip %d", tif->tif_name, tif->tif_row, strip); return (-1); } if (!ReadOK(tif->tif_fd, buf, size)) { TIFFError(module, "%s: Read error at scanline %d", tif->tif_name, tif->tif_row); return (-1); } #ifdef MMAP_SUPPORT } else { if (td->td_stripoffset[strip] + size > tif->tif_size) { TIFFError(module, "%s: Seek error at scanline %d, strip %d", tif->tif_name, tif->tif_row, strip); return (-1); } bcopy(tif->tif_base + td->td_stripoffset[strip], buf, size); #endif } return (size); } /* * Read the specified strip and setup for decoding. * The data buffer is expanded, as necessary, to * hold the strip's data. */ static TIFFFillStrip(tif, strip) TIFF *tif; u_int strip; { static char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; u_long bytecount; bytecount = td->td_stripbytecount[strip]; #ifdef MMAP_SUPPORT if (isMapped(tif) && (td->td_fillorder == tif->tif_fillorder || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is going * to handle this operation itself. In this case, avoid * copying the raw data and instead just reference the * data from the memory mapped file image. This assumes * that the decompression routines do not modify the * contents of the raw data buffer (if they try to, * the application will get a fault since the file is * mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) free(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; if (td->td_stripoffset[strip] + bytecount > tif->tif_size) { /* * This error message might seem strange, but it's * what would happen if a read were done instead. */ TIFFError(module, "%s: Read error on strip %d", tif->tif_name, strip); tif->tif_curstrip = -1; /* unknown state */ return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; } else { #endif /* * Expand raw data buffer, if needed, to * hold data strip coming from file * (perhaps should set upper bound on * the size of a buffer we'll use?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curstrip = -1; /* unknown state */ if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFError(module, "%s: Data buffer too small to hold strip %d", tif->tif_name, strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, roundup(bytecount, 1024))) return (0); } if (TIFFReadRawStrip1(tif, strip, (u_char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (td->td_fillorder != tif->tif_fillorder && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_char *)tif->tif_rawdata, bytecount); #ifdef MMAP_SUPPORT } #endif return (TIFFStartStrip(tif, strip)); } /* * Tile-oriented Read Support * Contributed by Nancy Cam (Silicon Graphics). */ /* * Read and decompress a tile of data. The * tile is selected by the (x,y,z,s) coordinates. */ TIFFReadTile(tif, buf, x, y, z, s) TIFF *tif; u_char *buf; u_long x, y, z; u_int s; { u_int tile; if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) return (-1); tile = TIFFComputeTile(tif, x, y, z, s); if (tile >= tif->tif_dir.td_nstrips) { TIFFError(tif->tif_name, "%d: Tile out of range, max %d", tile, tif->tif_dir.td_nstrips); return (-1); } return (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, buf, tif->tif_tilesize, s) ? tif->tif_tilesize : -1); } /* * Read a tile of data and decompress the specified * amount into the user-supplied buffer. */ TIFFReadEncodedTile(tif, tile, buf, size) TIFF *tif; u_int tile; u_char *buf; u_int size; { TIFFDirectory *td = &tif->tif_dir; int tilesize = tif->tif_tilesize; if (!TIFFCheckRead(tif, 1)) return (-1); if (tile >= td->td_nstrips) { TIFFError(tif->tif_name, "%d: Tile out of range, max %d", tile, td->td_nstrips); return (-1); } if (size == (u_int)-1) size = tilesize; else if (size > tilesize ) size = tilesize; return (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, buf, size, tile/td->td_stripsperimage) ? size : -1); } /* * Read a tile of data from the file. */ TIFFReadRawTile(tif, tile, buf, size) TIFF *tif; u_int tile; u_char *buf; u_int size; { static char module[] = "TIFFReadRawTile"; TIFFDirectory *td = &tif->tif_dir; u_long bytecount; if (!TIFFCheckRead(tif, 1)) return (-1); if (tile >= td->td_nstrips) { TIFFError(tif->tif_name, "%d: Tile out of range, max %d", tile, td->td_nstrips); return (-1); } bytecount = td->td_stripbytecount[tile]; if (size != (u_int)-1 && size < bytecount) bytecount = size; return (TIFFReadRawTile1(tif, tile, buf, bytecount, module)); } static int TIFFReadRawTile1(tif, tile, buf, size, module) TIFF *tif; u_int tile; u_char *buf; u_int size; char module[]; { TIFFDirectory *td = &tif->tif_dir; if (!isMapped(tif)) { if (!SeekOK(tif->tif_fd, td->td_stripoffset[tile])) { TIFFError(module, "%s: Seek error at row %d, col %d, tile %d", tif->tif_name, tif->tif_row, tif->tif_col, tile); return (-1); } if (!ReadOK(tif->tif_fd, buf, size)) { TIFFError(module, "%s: Read error at row %d, col %d", tif->tif_name, tif->tif_row, tif->tif_col); return (-1); } #ifdef MMAP_SUPPORT } else { if (td->td_stripoffset[tile] + size > tif->tif_size) { TIFFError(module, "%s: Seek error at row %d, col %d, tile %d", tif->tif_name, tif->tif_row, tif->tif_col, tile); return (-1); } bcopy(tif->tif_base + td->td_stripoffset[tile], buf, size); #endif } return (size); } /* * Read the specified tile and setup for decoding. * The data buffer is expanded, as necessary, to * hold the tile's data. */ static TIFFFillTile(tif, tile) TIFF *tif; u_int tile; { static char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; u_long bytecount; bytecount = td->td_stripbytecount[tile]; #ifdef MMAP_SUPPORT if (isMapped(tif) && (td->td_fillorder == tif->tif_fillorder || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is going * to handle this operation itself. In this case, avoid * copying the raw data and instead just reference the * data from the memory mapped file image. This assumes * that the decompression routines do not modify the * contents of the raw data buffer (if they try to, * the application will get a fault since the file is * mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) free(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; if (td->td_stripoffset[tile] + bytecount > tif->tif_size) { tif->tif_curtile = -1; /* unknown state */ return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile]; } else { #endif /* * Expand raw data buffer, if needed, to * hold data tile coming from file * (perhaps should set upper bound on * the size of a buffer we'll use?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curtile = -1; /* unknown state */ if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFError(module, "%s: Data buffer too small to hold tile %d", tif->tif_name, tile); return (0); } if (!TIFFReadBufferSetup(tif, 0, roundup(bytecount, 1024))) return (0); } if (TIFFReadRawTile1(tif, tile, (u_char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (td->td_fillorder != tif->tif_fillorder && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_char *)tif->tif_rawdata, bytecount); #ifdef MMAP_SUPPORT } #endif return (TIFFStartTile(tif, tile)); } /* * Setup the raw data buffer in preparation for * reading a strip of raw data. If the buffer * is specified as zero, then a buffer of appropriate * size is allocated by the library. Otherwise, * the client must guarantee that the buffer is * large enough to hold any individual strip of * raw data. */ int TIFFReadBufferSetup(tif, bp, size) TIFF *tif; char *bp; u_int size; { static char module[] = "TIFFReadBufferSetup"; if (tif->tif_rawdata) { if (tif->tif_flags & TIFF_MYBUFFER) free(tif->tif_rawdata); tif->tif_rawdata = NULL; } if (bp) { tif->tif_rawdatasize = size; tif->tif_rawdata = bp; tif->tif_flags &= ~TIFF_MYBUFFER; } else { tif->tif_rawdatasize = roundup(size, 1024); tif->tif_rawdata = malloc(tif->tif_rawdatasize); tif->tif_flags |= TIFF_MYBUFFER; } if (tif->tif_rawdata == NULL) { TIFFError(module, "%s: No space for data buffer at scanline %d", tif->tif_name, tif->tif_row); tif->tif_rawdatasize = 0; return (0); } return (1); } /* * Set state to appear as if a * strip has just been read in. */ static TIFFStartStrip(tif, strip) register TIFF *tif; u_int strip; { TIFFDirectory *td = &tif->tif_dir; tif->tif_curstrip = strip; tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_rawcp = tif->tif_rawdata; tif->tif_rawcc = td->td_stripbytecount[strip]; return (tif->tif_predecode == NULL || (*tif->tif_predecode)(tif)); } /* * Set state to appear as if a * tile has just been read in. */ static TIFFStartTile(tif, tile) register TIFF *tif; u_int tile; { TIFFDirectory *td = &tif->tif_dir; tif->tif_curtile = tile; tif->tif_row = (tile % howmany(td->td_imagewidth, td->td_tilewidth)) * td->td_tilelength; tif->tif_col = (tile % howmany(td->td_imagelength, td->td_tilelength)) * td->td_tilewidth; tif->tif_rawcp = tif->tif_rawdata; tif->tif_rawcc = td->td_stripbytecount[tile]; return (tif->tif_predecode == NULL || (*tif->tif_predecode)(tif)); } static TIFFCheckRead(tif, tiles) TIFF *tif; int tiles; { if (tif->tif_mode == O_WRONLY) { TIFFError(tif->tif_name, "File not open for reading"); return (0); } if (tiles ^ isTiled(tif)) { TIFFError(tif->tif_name, tiles ? "Can not read tiles from a stripped image" : "Can not read scanlines from a tiled image"); return (0); } return (1); } old data strip coming from file * (perhaps should set upper bound on * the size of a buffer we'll use?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curstrip = -1; /* unknown state */ if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFError(module, "%s: Data buffer too small to hold strip %d", tif->tif_name, strip); return (0); } if (!TIFFReaxloadimage.4.1/tiff/tif_strip.c 664 221 144 6666 5461577450 11672 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_strip.c,v 1.7 92/02/10 19:06:42 sam Exp $"; #endif /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Strip-organized Image Support Routines. */ #include "tiffioP.h" /* * Compute which strip a (row,sample) value is in. */ u_int TIFFComputeStrip(tif, row, sample) TIFF *tif; u_long row; u_int sample; { TIFFDirectory *td = &tif->tif_dir; u_int strip; strip = row / td->td_rowsperstrip; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFError(tif->tif_name, "%d: Sample out of range, max %d", sample, td->td_samplesperpixel); return (0); } strip += sample*td->td_stripsperimage; } return (strip); } /* * Compute how many strips are in an image. */ u_int TIFFNumberOfStrips(tif) TIFF *tif; { TIFFDirectory *td = &tif->tif_dir; return (td->td_rowsperstrip == 0xffffffff ? (td->td_imagelength != 0 ? 1 : 0) : howmany(td->td_imagelength, td->td_rowsperstrip)); } /* * Compute the # bytes in a variable height, row-aligned strip. */ u_long TIFFVStripSize(tif, nrows) TIFF *tif; u_long nrows; { TIFFDirectory *td = &tif->tif_dir; if (nrows == (u_long)-1) nrows = td->td_imagelength; #ifdef YCBCR_SUPPORT if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ u_long w = roundup(td->td_imagewidth, td->td_ycbcrsubsampling[0]); u_long scanline = howmany(w*td->td_bitspersample, 8); u_long samplingarea = td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; nrows = roundup(nrows, td->td_ycbcrsubsampling[1]); /* NB: don't need howmany here 'cuz everything is rounded */ return (nrows*scanline + 2*(nrows*scanline / samplingarea)); } else #endif return (nrows * TIFFScanlineSize(tif)); } /* * Compute the # bytes in a (row-aligned) strip. */ u_long TIFFStripSize(tif) TIFF *tif; { return (TIFFVStripSize(tif, tif->tif_dir.td_rowsperstrip)); } ill get a fault since the file is * mapped read-only). */ if ((tifxloadimage.4.1/tiff/tif_swab.c 664 221 144 15457 5461577450 11503 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_swab.c,v 1.12 92/02/10 19:06:03 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library Bit & Byte Swapping Support. * * XXX We assume short = 16-bits and long = 32-bits XXX */ #include "tiffio.h" #ifndef TIFFSwabShort TIFFSwabShort(wp) unsigned short *wp; { register unsigned char *cp = (unsigned char *)wp; int t; t = cp[1]; cp[1] = cp[0]; cp[0] = t; } #endif #ifndef TIFFSwabLong TIFFSwabLong(lp) unsigned long *lp; { register unsigned char *cp = (unsigned char *)lp; int t; t = cp[3]; cp[3] = cp[0]; cp[0] = t; t = cp[2]; cp[2] = cp[1]; cp[1] = t; } #endif #ifndef TIFFSwabArrayOfShort TIFFSwabArrayOfShort(wp, n) unsigned short *wp; register int n; { register unsigned char *cp; register int t; /* XXX unroll loop some */ while (n-- > 0) { cp = (unsigned char *)wp; t = cp[1]; cp[1] = cp[0]; cp[0] = t; wp++; } } #endif #ifndef TIFFSwabArrayOfLong TIFFSwabArrayOfLong(lp, n) register unsigned long *lp; register int n; { register unsigned char *cp; register int t; /* XXX unroll loop some */ while (n-- > 0) { cp = (unsigned char *)lp; t = cp[3]; cp[3] = cp[0]; cp[0] = t; t = cp[2]; cp[2] = cp[1]; cp[1] = t; lp++; } } #endif /* * Bit reversal tables. TIFFBitRevTable[] gives * the bit reversed value of . Used in various * places in the library when the FillOrder requires * bit reversal of byte values (e.g. CCITT Fax 3 * encoding/decoding). TIFFNoBitRevTable is provided * for algorithms that want an equivalent table that * do not reverse bit values. */ #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST const unsigned char TIFFBitRevTable[256] = { #else unsigned char TIFFBitRevTable[256] = { #endif 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST const unsigned char TIFFNoBitRevTable[256] = { #else unsigned char TIFFNoBitRevTable[256] = { #endif 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }; TIFFReverseBits(cp, n) register unsigned char *cp; register int n; { for (; n > 8; n -= 8) { cp[0] = TIFFBitRevTable[cp[0]]; cp[1] = TIFFBitRevTable[cp[1]]; cp[2] = TIFFBitRevTable[cp[2]]; cp[3] = TIFFBitRevTable[cp[3]]; cp[4] = TIFFBitRevTable[cp[4]]; cp[5] = TIFFBitRevTable[cp[5]]; cp[6] = TIFFBitRevTable[cp[6]]; cp[7] = TIFFBitRevTable[cp[7]]; cp += 8; } while (n-- > 0) *cp = TIFFBitRevTable[*cp], cp++; } defined(__EXTENDED__) || USE_CONST const unsigned char TIFFBitRevTable[256] = { #else unsigned char TIFFBitRevTable[256] = { #endif 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xdxloadimage.4.1/tiff/tif_thunder.c 664 221 144 11251 5461577450 12204 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_thunder.c,v 1.19 92/02/10 19:06:46 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * ThunderScan 4-bit Compression Algorithm Support */ #include "tiffioP.h" /* * ThunderScan uses an encoding scheme designed for * 4-bit pixel values. Data is encoded in bytes, with * each byte split into a 2-bit code word and a 6-bit * data value. The encoding gives raw data, runs of * pixels, or pixel values encoded as a delta from the * previous pixel value. For the latter, either 2-bit * or 3-bit delta values are used, with the deltas packed * into a single byte. */ #define THUNDER_DATA 0x3f /* mask for 6-bit data */ #define THUNDER_CODE 0xc0 /* mask for 2-bit code word */ /* code values */ #define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */ #define THUNDER_2BITDELTAS 0x40 /* 3 pixels w/ encoded 2-bit deltas */ #define DELTA2_SKIP 2 /* skip code for 2-bit deltas */ #define THUNDER_3BITDELTAS 0x80 /* 2 pixels w/ encoded 3-bit deltas */ #define DELTA3_SKIP 4 /* skip code for 3-bit deltas */ #define THUNDER_RAW 0xc0 /* raw data encoded */ static const int twobitdeltas[4] = { 0, 1, 0, -1 }; static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; #define SETPIXEL(op, v) { \ lastpixel = (v) & 0xf; \ if (npixels++ & 1) \ *op++ |= lastpixel; \ else \ op[0] = lastpixel << 4; \ } static int ThunderDecode(tif, op, maxpixels) TIFF *tif; register u_char *op; int maxpixels; { register u_char *bp; register int n, cc, lastpixel, npixels, delta; bp = (u_char *)tif->tif_rawcp; cc = tif->tif_rawcc; lastpixel = npixels = 0; while (cc > 0 && npixels < maxpixels) { n = *bp++, cc--; switch (n & THUNDER_CODE) { case THUNDER_RUN: /* pixel run */ /* * Replicate the last pixel n times, * where n is the lower-order 6 bits. */ if (npixels & 1) { op[0] |= lastpixel; lastpixel = *op++; npixels++; n--; } else lastpixel |= lastpixel << 4; npixels += n; for (; n > 0; n -= 2) *op++ = lastpixel; if (n == -1) *--op &= 0xf0; lastpixel &= 0xf; break; case THUNDER_2BITDELTAS: /* 2-bit deltas */ if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) SETPIXEL(op, lastpixel + twobitdeltas[delta]); if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) SETPIXEL(op, lastpixel + twobitdeltas[delta]); if ((delta = (n & 3)) != DELTA2_SKIP) SETPIXEL(op, lastpixel + twobitdeltas[delta]); break; case THUNDER_3BITDELTAS: /* 3-bit deltas */ if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) SETPIXEL(op, lastpixel + threebitdeltas[delta]); if ((delta = (n & 7)) != DELTA3_SKIP) SETPIXEL(op, lastpixel + threebitdeltas[delta]); break; case THUNDER_RAW: /* raw data */ SETPIXEL(op, n); break; } } tif->tif_rawcp = (char *)bp; tif->tif_rawcc = cc; if (npixels != maxpixels) { TIFFError(tif->tif_name, "ThunderDecode: %s data at scanline %d (%d != %d)", npixels < maxpixels ? "Not enough" : "Too much", tif->tif_row, npixels, maxpixels); return (0); } return (1); } static int ThunderDecodeRow(tif, buf, occ, s) TIFF *tif; u_char *buf; int occ; u_int s; { u_char *row = buf; while (occ > 0) { if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) return (0); occ -= tif->tif_scanlinesize; row += tif->tif_scanlinesize; } return (1); } TIFFInitThunderScan(tif) TIFF *tif; { tif->tif_decoderow = ThunderDecodeRow; tif->tif_decodestrip = ThunderDecodeRow; return (1); } 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software xloadimage.4.1/tiff/tiff.h 664 221 144 31334 5461577450 10632 /* $Header: /usr/people/sam/tiff/libtiff/RCS/tiff.h,v 1.36 92/02/19 09:52:30 sam Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _TIFF_ #define _TIFF_ /* * Tag Image File Format (TIFF) * * Based on Rev 6.0 from: * Developer's Desk * Aldus Corporation * 411 First Ave. South * Suite 200 * Seattle, WA 98104 * 206-622-5500 */ #define TIFF_VERSION 42 #define TIFF_BIGENDIAN 0x4d4d #define TIFF_LITTLEENDIAN 0x4949 typedef struct { unsigned short tiff_magic; /* magic number (defines byte order) */ unsigned short tiff_version; /* TIFF version number */ unsigned long tiff_diroff; /* byte offset to first directory */ } TIFFHeader; /* * TIFF Image File Directories are comprised of * a table of field descriptors of the form shown * below. The table is sorted in ascending order * by tag. The values associated with each entry * are disjoint and may appear anywhere in the file * (so long as they are placed on a word boundary). * * If the value is 4 bytes or less, then it is placed * in the offset field to save space. If the value * is less than 4 bytes, it is left-justified in the * offset field. */ typedef struct { unsigned short tdir_tag; /* see below */ unsigned short tdir_type; /* data type; see below */ unsigned long tdir_count; /* number of items; length in spec */ unsigned long tdir_offset; /* byte offset to field data */ } TIFFDirEntry; /* * NB: In the comments below, * - items marked with a + are obsoleted by revision 5.0, * - items marked with a ! are introduced in revision 6.0. * - items marked with a $ are obsoleted by revision 6.0. */ /* * Tag data type information. * * Note: RATIONALs are the ratio of two 32-bit integer values. */ typedef enum { TIFF_NOTYPE = 0, /* placeholder */ TIFF_BYTE = 1, /* 8-bit unsigned integer */ TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ TIFF_SHORT = 3, /* 16-bit unsigned integer */ TIFF_LONG = 4, /* 32-bit unsigned integer */ TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ TIFF_SBYTE = 6, /* !8-bit signed integer */ TIFF_UNDEFINED = 7, /* !8-bit untyped data */ TIFF_SSHORT = 8, /* !16-bit signed integer */ TIFF_SLONG = 9, /* !32-bit signed integer */ TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ TIFF_DOUBLE = 12 /* !64-bit IEEE floating point */ } TIFFDataType; /* * TIFF Tag Definitions. */ #define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ #define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ #define FILETYPE_PAGE 0x2 /* one page of many */ #define FILETYPE_MASK 0x4 /* transparency mask */ #define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ #define OFILETYPE_IMAGE 1 /* full resolution image data */ #define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ #define OFILETYPE_PAGE 3 /* one page of many */ #define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ #define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ #define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ #define TIFFTAG_COMPRESSION 259 /* data compression technique */ #define COMPRESSION_NONE 1 /* dump mode */ #define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ #define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ #define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ #define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ #define COMPRESSION_JPEG 6 /* !JPEG compression */ #define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ #define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ #define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ #define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ #define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ #define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ #define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ #define PHOTOMETRIC_RGB 2 /* RGB color model */ #define PHOTOMETRIC_PALETTE 3 /* color map indexed */ #define PHOTOMETRIC_MASK 4 /* $holdout mask */ #define PHOTOMETRIC_SEPARATED 5 /* !color separations */ #define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ #define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ #define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ #define THRESHHOLD_BILEVEL 1 /* b&w art scan */ #define THRESHHOLD_HALFTONE 2 /* or dithered scan */ #define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ #define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ #define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ #define TIFFTAG_FILLORDER 266 /* data order within a byte */ #define FILLORDER_MSB2LSB 1 /* most significant -> least */ #define FILLORDER_LSB2MSB 2 /* least significant -> most */ #define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ #define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ #define TIFFTAG_MAKE 271 /* scanner manufacturer name */ #define TIFFTAG_MODEL 272 /* scanner model name/number */ #define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ #define TIFFTAG_ORIENTATION 274 /* +image orientation */ #define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ #define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ #define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ #define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ #define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ #define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ #define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ #define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ #define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ #define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ #define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ #define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ #define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ #define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ #define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ #define TIFFTAG_PLANARCONFIG 284 /* storage organization */ #define PLANARCONFIG_CONTIG 1 /* single image plane */ #define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ #define TIFFTAG_PAGENAME 285 /* page name image is from */ #define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ #define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ #define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ #define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ #define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ #define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ #define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ #define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ #define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ #define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ #define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ #define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ #define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ #define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ #define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ #define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ #define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ #define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ #define RESUNIT_NONE 1 /* no meaningful units */ #define RESUNIT_INCH 2 /* english */ #define RESUNIT_CENTIMETER 3 /* metric */ #define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ #define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ #define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ #define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ #define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ #define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ #define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ #define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ #define TIFFTAG_SOFTWARE 305 /* name & release */ #define TIFFTAG_DATETIME 306 /* creation date and time */ #define TIFFTAG_ARTIST 315 /* creator of image */ #define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ #define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ #define TIFFTAG_WHITEPOINT 318 /* image white point */ #define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ #define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ #define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ #define TIFFTAG_TILEWIDTH 322 /* !rows/data tile */ #define TIFFTAG_TILELENGTH 323 /* !cols/data tile */ #define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ #define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ #define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ #define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ #define CLEANFAXDATA_CLEAN 0 /* no errors detected */ #define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ #define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ #define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ #define TIFFTAG_INKSET 332 /* !inks in separated image */ #define INKSET_CMYK 1 /* !cyan-magenta-yellow-black */ #define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ #define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ #define TIFFTAG_TARGETPRINTER 337 /* !separation target */ #define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ #define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ #define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ #define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ #define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ #define SAMPLEFORMAT_INT 1 /* !signed integer data */ #define SAMPLEFORMAT_UINT 2 /* !unsigned integer data */ #define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ #define SAMPLEFORMAT_VOID 4 /* !untyped data */ #define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ #define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ #define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ #define JPEGPROC_BASELINE 1 /* !baseline sequential */ #define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ #define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ #define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ #define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ #define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ #define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ #define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ #define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ #define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ #define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ #define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ #define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ #define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ #define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ #define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ /* tags 32995-32999 are private tags registered to SGI */ #define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ #define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ #define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ #define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ #endif /* _TIFF_ */ g matrix height */ #define TIFFTAG_FILLORDER 266 /* data order within a byte */ #define FILLORDER_MSB2LSB 1 /* most significant -> least */ #define FILLORDER_LSB2MSB 2 /* least significant -> most */ #define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ #define TIFFTAxloadimage.4.1/tiff/tif_tile.c 664 221 144 12474 5461577450 11500 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_tile.c,v 1.9 92/02/10 19:06:47 sam Exp $"; #endif /* * Copyright (c) 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Tiled Image Support Routines. */ #include "tiffioP.h" /* * Compute which tile an (x,y,z,s) value is in. */ u_int TIFFComputeTile(tif, x, y, s, z) TIFF *tif; u_long x, y, z; u_int s; { TIFFDirectory *td = &tif->tif_dir; u_long dx = td->td_tilewidth; u_long dy = td->td_tilelength; u_long dz = td->td_tiledepth; u_int tile = 1; if (td->td_imagedepth == 1) z = 0; if (dx == (u_long) -1) dx = td->td_imagewidth; if (dy == (u_long) -1) dy = td->td_imagelength; if (dz == (u_long) -1) dz = td->td_imagedepth; if (dx != 0 && dy != 0 && dz != 0) { u_int xpt = howmany(td->td_imagewidth, dx); u_int ypt = howmany(td->td_imagelength, dy); u_int zpt = howmany(td->td_imagedepth, dz); if (td->td_planarconfig == PLANARCONFIG_SEPARATE) tile = (xpt*ypt*zpt)*s + (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx; else tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx + s; } return (tile); } /* * Check an (x,y,z,s) coordinate * against the image bounds. */ TIFFCheckTile(tif, x, y, z, s) TIFF *tif; u_long x, y, z; u_int s; { TIFFDirectory *td = &tif->tif_dir; if (x >= td->td_imagewidth) { TIFFError(tif->tif_name, "Col %d out of range, max %d", x, td->td_imagewidth); return (0); } if (y >= td->td_imagelength) { TIFFError(tif->tif_name, "Row %d out of range, max %d", y, td->td_imagelength); return (0); } if (z >= td->td_imagedepth) { TIFFError(tif->tif_name, "Depth %d out of range, max %d", z, td->td_imagedepth); return (0); } if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s >= td->td_samplesperpixel) { TIFFError(tif->tif_name, "Sample %d out of range, max %d", s, td->td_samplesperpixel); return (0); } return (1); } /* * Compute how many tiles are in an image. */ u_int TIFFNumberOfTiles(tif) TIFF *tif; { TIFFDirectory *td = &tif->tif_dir; u_long dx = td->td_tilewidth; u_long dy = td->td_tilelength; u_long dz = td->td_tiledepth; u_int ntiles; if (dx == (u_long) -1) dx = td->td_imagewidth; if (dy == (u_long) -1) dy = td->td_imagelength; if (dz == (u_long) -1) dz = td->td_imagedepth; ntiles = (dx != 0 && dy != 0 && dz != 0) ? (howmany(td->td_imagewidth, dx) * howmany(td->td_imagelength, dy) * howmany(td->td_imagedepth, dz)) : 0; return (ntiles); } /* * Compute the # bytes in each row of a tile. */ u_long TIFFTileRowSize(tif) TIFF *tif; { TIFFDirectory *td = &tif->tif_dir; u_long rowsize; if (td->td_tilelength == 0 || td->td_tilewidth == 0) return (0); rowsize = td->td_bitspersample * td->td_tilewidth; if (td->td_planarconfig == PLANARCONFIG_CONTIG) rowsize *= td->td_samplesperpixel; return (howmany(rowsize, 8)); } /* * Compute the # bytes in a variable length, row-aligned tile. */ u_long TIFFVTileSize(tif, nrows) TIFF *tif; u_long nrows; { TIFFDirectory *td = &tif->tif_dir; u_long tilesize; if (td->td_tilelength == 0 || td->td_tilewidth == 0 || td->td_tiledepth == 0) return (0); #ifdef YCBCR_SUPPORT if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ u_long w = roundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]); u_long rowsize = howmany(w*td->td_bitspersample, 8); u_long samplingarea = td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; nrows = roundup(nrows, td->td_ycbcrsubsampling[1]); /* NB: don't need howmany here 'cuz everything is rounded */ tilesize = nrows*rowsize + 2*(nrows*rowsize / samplingarea); } else #endif tilesize = nrows * TIFFTileRowSize(tif); return (tilesize * td->td_tiledepth); } /* * Compute the # bytes in a row-aligned tile. */ u_long TIFFTileSize(tif) TIFF *tif; { return (TIFFVTileSize(tif, tif->tif_dir.td_tilelength)); } RMAT 339 /* !data sample format */ #define SAMPLEFORMAT_INT 1 /* !signed integer data */ #define SAMPLEFORMAT_UINT 2 /* !unsigned integer data */ #define SAMPLEFORMAT_IEEEFP 3 /* !xloadimage.4.1/tiff/tif_version.c 664 221 144 2567 5461577450 12212 /* * Copyright (c) 1992 Sam Leffler * Copyright (c) 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "tiffcompat.h" const char TIFFVersion[] = "\ LIBTIFF, Version 3.0 BETA\n\ Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler\n\ Copyright (c) 1991, 1992 Silicon Graphics, Inc.\ "; samplesperpixel); return (0); } return (1); } /* * Compute how many tiles are in an image. */ u_int TIFFNumberOfTiles(tif) TIFF *xloadimage.4.1/tiff/tif_warning.c 664 221 144 4217 5461577450 12164 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_warning.c,v 1.13 92/02/10 19:06:44 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. */ #include #include "tiffioP.h" #include "prototypes.h" static void DECLARE3(defaultHandler, char*, module, char*, fmt, va_list, ap) { if (module != NULL) fprintf(stderr, "%s: ", module); fprintf(stderr, "Warning, "); vfprintf(stderr, fmt, ap); fprintf(stderr, ".\n"); } static TIFFErrorHandler _warningHandler = defaultHandler; TIFFErrorHandler DECLARE1(TIFFSetWarningHandler, TIFFErrorHandler, handler) { TIFFErrorHandler prev = _warningHandler; _warningHandler = handler; return (prev); } void #if USE_PROTOTYPES TIFFWarning(char *module, char *fmt, ...) #else /*VARARGS2*/ TIFFWarning(module, fmt, va_alist) char *module; char *fmt; va_dcl #endif { if (_warningHandler) { va_list ap; VA_START(ap, fmt); (*_warningHandler)(module, fmt, ap); va_end(ap); } } g to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRxloadimage.4.1/tiff/tif_write.c 664 221 144 41335 5461577450 11673 #ifndef lint static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_write.c,v 1.41 92/02/10 19:06:47 sam Exp $"; #endif /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Scanline-oriented Write Support */ #include "tiffioP.h" #include #include #define STRIPINCR 20 /* expansion factor on strip array */ #if USE_PROTOTYPES static TIFFWriteCheck(TIFF *, int, char []); static TIFFBufferSetup(TIFF *, char []); static TIFFGrowStrips(TIFF *, int, char []); static TIFFAppendToStrip(TIFF *, u_int, u_char *, u_int); #else static TIFFWriteCheck(); static TIFFBufferSetup(); static TIFFGrowStrips(); static TIFFAppendToStrip(); #endif /*VARARGS3*/ TIFFWriteScanline(tif, buf, row, sample) register TIFF *tif; u_char *buf; u_int row, sample; { static char module[] = "TIFFWriteScanline"; register TIFFDirectory *td; int strip, status, imagegrew = 0; if (!TIFFWriteCheck(tif, 0, module)) return (-1); /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) { if (!TIFFBufferSetup(tif, module)) return (-1); tif->tif_flags |= TIFF_BUFFERSETUP; } td = &tif->tif_dir; /* * Extend image length if needed * (but only for PlanarConfig=1). */ if (row >= td->td_imagelength) { /* extend image */ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { TIFFError(tif->tif_name, "Can not change \"ImageLength\" when using separate planes"); return (-1); } td->td_imagelength = row+1; imagegrew = 1; } /* * Calculate strip and check for crossings. */ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFError(tif->tif_name, "%d: Sample out of range, max %d", sample, td->td_samplesperpixel); return (-1); } strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; if (strip != tif->tif_curstrip) { /* * Changing strips -- flush any data present. */ if (tif->tif_rawcc > 0 && !TIFFFlushData(tif)) return (-1); tif->tif_curstrip = strip; /* * Watch out for a growing image. The value of * strips/image will initially be 1 (since it * can't be deduced until the imagelength is known). */ if (strip >= td->td_stripsperimage && imagegrew) td->td_stripsperimage = howmany(td->td_imagelength, td->td_rowsperstrip); tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if (tif->tif_preencode && !(*tif->tif_preencode)(tif)) return (-1); tif->tif_flags |= TIFF_POSTENCODE; } /* * Check strip array to make sure there's space. * We don't support dynamically growing files that * have data organized in separate bitplanes because * it's too painful. In that case we require that * the imagelength be set properly before the first * write (so that the strips array will be fully * allocated above). */ if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) return (-1); /* * Ensure the write is either sequential or at the * beginning of a strip (or that we can randomly * access the data -- i.e. no encoding). */ if (row != tif->tif_row) { if (tif->tif_seek) { if (row < tif->tif_row) { /* * Moving backwards within the same strip: * backup to the start and then decode * forward (below). */ tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_rawcp = tif->tif_rawdata; } /* * Seek forward to the desired row. */ if (!(*tif->tif_seek)(tif, row - tif->tif_row)) return (-1); tif->tif_row = row; } else { TIFFError(tif->tif_name, "Compression algorithm does not support random access"); return (-1); } } status = (*tif->tif_encoderow)(tif, buf, tif->tif_scanlinesize, sample); tif->tif_row++; return (status); } /* * Encode the supplied data and write it to the * specified strip. There must be space for the * data; we don't check if strips overlap! * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ TIFFWriteEncodedStrip(tif, strip, data, cc) TIFF *tif; u_int strip; u_char *data; u_int cc; { static char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; if (!TIFFWriteCheck(tif, 0, module)) return (-1); if (strip >= td->td_nstrips) { TIFFError(module, "%s: Strip %d out of range, max %d", tif->tif_name, strip, td->td_nstrips); return (-1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized according to the directory * info. */ if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) { if (!TIFFBufferSetup(tif, module)) return (-1); tif->tif_flags |= TIFF_BUFFERSETUP; } tif->tif_curstrip = strip; tif->tif_flags &= ~TIFF_POSTENCODE; if (tif->tif_preencode && !(*tif->tif_preencode)(tif)) return (-1); if (!(*tif->tif_encodestrip)(tif, data, cc, strip / td->td_stripsperimage)) return (0); if (tif->tif_postencode && !(*tif->tif_postencode)(tif)) return (-1); if (td->td_fillorder != tif->tif_fillorder && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, strip, (u_char *)tif->tif_rawdata, tif->tif_rawcc)) return (-1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); } /* * Write the supplied data to the specified strip. * There must be space for the data; we don't check * if strips overlap! * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ TIFFWriteRawStrip(tif, strip, data, cc) TIFF *tif; u_int strip; u_char *data; u_int cc; { static char module[] = "TIFFWriteRawStrip"; if (!TIFFWriteCheck(tif, 0, module)) return (-1); if (strip >= tif->tif_dir.td_nstrips) { TIFFError(module, "%s: Strip %d out of range, max %d", tif->tif_name, strip, tif->tif_dir.td_nstrips); return (-1); } return (TIFFAppendToStrip(tif, strip, data, cc) ? cc : -1); } /* * Write and compress a tile of data. The * tile is selected by the (x,y,z,s) coordinates. */ TIFFWriteTile(tif, buf, x, y, z, s) TIFF *tif; u_char *buf; u_long x, y, z; u_int s; { if (!TIFFCheckTile(tif, x, y, z, s)) return (-1); /* * NB: A tile size of -1 is used instead of tif_tilesize knowing * that TIFFWriteEncodedTile will clamp this to the tile size. * This is done because the tile size may not be defined until * after the output buffer is setup in TIFFBufferSetup. */ return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf, (u_int)-1)); } /* * Encode the supplied data and write it to the * specified tile. There must be space for the * data. The function clamps individual writes * to a tile to the tile size, but does not (and * can not) check that multiple writes to the same * tile do not write more than tile size data. * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ TIFFWriteEncodedTile(tif, tile, data, cc) TIFF *tif; u_int tile; u_char *data; u_int cc; { static char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; if (!TIFFWriteCheck(tif, 1, module)) return (-1); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFError(module, "%s: Tile %d out of range, max %d", tif->tif_name, tile, td->td_nstrips); return (-1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) { if (!TIFFBufferSetup(tif, module)) return (-1); tif->tif_flags |= TIFF_BUFFERSETUP; } tif->tif_curtile = tile; /* * Compute tiles per row & per column to compute * current row and column */ tif->tif_row = (tile % howmany(td->td_imagelength, td->td_tilelength)) * td->td_tilelength; tif->tif_col = (tile % howmany(td->td_imagewidth, td->td_tilewidth)) * td->td_tilewidth; tif->tif_flags &= ~TIFF_POSTENCODE; if (tif->tif_preencode && !(*tif->tif_preencode)(tif)) return (-1); /* * Clamp write amount to the tile size. This is mostly * done so that callers can pass in some large number * (e.g. -1) and have the tile size used instead. */ if (cc > tif->tif_tilesize) cc = tif->tif_tilesize; if (!(*tif->tif_encodetile)(tif, data, cc, tile/td->td_stripsperimage)) return (0); if (tif->tif_postencode && !(*tif->tif_postencode)(tif)) return (-1); if (td->td_fillorder != tif->tif_fillorder && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, (u_char *)tif->tif_rawdata, tif->tif_rawcc)) return (-1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); } /* * Write the supplied data to the specified strip. * There must be space for the data; we don't check * if strips overlap! * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ TIFFWriteRawTile(tif, tile, data, cc) TIFF *tif; u_int tile; u_char *data; u_int cc; { static char module[] = "TIFFWriteRawTile"; if (!TIFFWriteCheck(tif, 1, module)) return (-1); if (tile >= tif->tif_dir.td_nstrips) { TIFFError(module, "%s: Tile %d out of range, max %d", tif->tif_name, tile, tif->tif_dir.td_nstrips); return (-1); } return (TIFFAppendToStrip(tif, tile, data, cc) ? cc : -1); } static TIFFSetupStrips(tif) TIFF *tif; { #define isUnspecified(td, v) \ (td->v == 0xffffffff || (td)->td_imagelength == 0) register TIFFDirectory *td = &tif->tif_dir; if (!isTiled(tif)) td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ? 1 : howmany(td->td_imagelength, td->td_rowsperstrip); else td->td_stripsperimage = isUnspecified(td, td_tilelength) ? 1 : TIFFNumberOfTiles(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_nstrips *= td->td_samplesperpixel; td->td_stripoffset = (u_long *) malloc(td->td_nstrips * sizeof (u_long)); td->td_stripbytecount = (u_long *) malloc(td->td_nstrips * sizeof (u_long)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ bzero((char *)td->td_stripoffset, td->td_nstrips * sizeof (u_long)); bzero((char *)td->td_stripbytecount, td->td_nstrips * sizeof (u_long)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); #undef isUnspecified } /* * Verify file is writable and that the directory * information is setup properly. In doing the latter * we also "freeze" the state of the directory so * that important information is not changed. */ static TIFFWriteCheck(tif, tiles, module) register TIFF *tif; int tiles; char module[]; { if (tif->tif_mode == O_RDONLY) { TIFFError(module, "%s: File not open for writing", tif->tif_name); return (0); } if (tiles ^ isTiled(tif)) { TIFFError(tif->tif_name, tiles ? "Can not write tiles to a stripped image" : "Can not write scanlines to a tiled image"); return (0); } /* * On the first write verify all the required information * has been setup and initialize any data structures that * had to wait until directory information was set. * Note that a lot of our work is assumed to remain valid * because we disallow any of the important parameters * from changing after we start writing (i.e. once * TIFF_BEENWRITING is set, TIFFSetField will only allow * the image's length to be changed). */ if ((tif->tif_flags & TIFF_BEENWRITING) == 0) { if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { TIFFError(module, "%s: Must set \"ImageWidth\" before writing data", tif->tif_name); return (0); } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { TIFFError(module, "%s: Must set \"PlanarConfiguration\" before writing data", tif->tif_name); return (0); } if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFError(module, "%s: No space for %s arrays", tif->tif_name, isTiled(tif) ? "tile" : "strip"); return (0); } tif->tif_flags |= TIFF_BEENWRITING; } return (1); } /* * Setup the raw data buffer used for encoding. */ static TIFFBufferSetup(tif, module) register TIFF *tif; char module[]; { int size; if (isTiled(tif)) tif->tif_tilesize = size = TIFFTileSize(tif); else tif->tif_scanlinesize = size = TIFFScanlineSize(tif); /* * Make raw data buffer at least 8K */ if (size < 8*1024) size = 8*1024; tif->tif_rawdata = malloc(size); if (tif->tif_rawdata == NULL) { TIFFError(module, "%s: No space for output buffer", tif->tif_name); return (0); } tif->tif_rawdatasize = size; tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (1); } /* * Grow the strip data structures by delta strips. */ static TIFFGrowStrips(tif, delta, module) TIFF *tif; int delta; char module[]; { TIFFDirectory *td = &tif->tif_dir; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); td->td_stripoffset = (u_long *)realloc(td->td_stripoffset, (td->td_nstrips + delta) * sizeof (u_long)); td->td_stripbytecount = (u_long *)realloc(td->td_stripbytecount, (td->td_nstrips + delta) * sizeof (u_long)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) { td->td_nstrips = 0; TIFFError(module, "%s: No space to expand strip arrays", tif->tif_name); return (0); } bzero(td->td_stripoffset+td->td_nstrips, delta*sizeof (u_long)); bzero(td->td_stripbytecount+td->td_nstrips, delta*sizeof (u_long)); td->td_nstrips += delta; return (1); } /* * Append the data to the specified strip. * * NB: We don't check that there's space in the * file (i.e. that strips do not overlap). */ static TIFFAppendToStrip(tif, strip, data, cc) TIFF *tif; u_int strip; u_char *data; u_int cc; { TIFFDirectory *td = &tif->tif_dir; static char module[] = "TIFFAppendToStrip"; if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { /* * No current offset, set the current strip. */ if (td->td_stripoffset[strip] != 0) { if (!SeekOK(tif->tif_fd, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %d", tif->tif_name, tif->tif_row); return (0); } } else td->td_stripoffset[strip] = lseek(tif->tif_fd, 0L, L_XTND); tif->tif_curoff = td->td_stripoffset[strip]; } if (!WriteOK(tif->tif_fd, data, cc)) { TIFFError(module, "%s: Write error at scanline %d", tif->tif_name, tif->tif_row); return (0); } tif->tif_curoff += cc; td->td_stripbytecount[strip] += cc; return (1); } /* * Internal version of TIFFFlushData that can be * called by ``encodestrip routines'' w/o concern * for infinite recursion. */ TIFFFlushData1(tif) register TIFF *tif; { if (tif->tif_rawcc > 0) { if (tif->tif_dir.td_fillorder != tif->tif_fillorder && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc); if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, (u_char *)tif->tif_rawdata, tif->tif_rawcc)) return (0); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } return (1); } range, max %d", tif->tif_name, tile, td->td_nstrips); return (-1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) { if (!TIFFBufferSetupxloadimage.4.1/tiff/tiffcompat.h 664 221 144 13130 5465550674 12033 /* $Header: /usr/people/sam/tiff/libtiff/RCS/tiffcompat.h,v 1.21 92/03/30 18:31:03 sam Exp $ */ /* * Copyright (c) 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _COMPAT_ #define _COMPAT_ /* * This file contains a hodgepodge of definitions and * declarations that are needed to provide compatibility * between the native system and the base UNIX implementation * that the library assumes (~4BSD). In particular, you * can override the standard i/o interface (read/write/lseek) * by redefining the ReadOK/WriteOK/SeekOK macros to your * liking. * * NB: This file is a mess. */ #if (defined(__STDC__) || defined(__EXTENDED__)) && !defined(USE_PROTOTYPES) #define USE_PROTOTYPES 1 #define USE_CONST 1 #endif #if !USE_CONST && !defined(const) #define const #endif #ifdef THINK_C #include #include #endif #if USE_PROTOTYPES #include #endif #ifndef THINK_C #include #endif #ifdef VMS #include #include #else #include #endif #if defined(THINK_C) || defined(applec) #include #endif /* * Workarounds for BSD lseek definitions. */ #if defined(SYSV) || defined(VMS) #if defined(SYSV) #include #endif #define L_SET SEEK_SET #define L_INCR SEEK_CUR #define L_XTND SEEK_END #endif #ifndef L_SET #define L_SET 0 #define L_INCR 1 #define L_XTND 2 #endif /* * SVID workarounds for BSD bit * string manipulation routines. */ #if defined(__STDC__) || defined(SYSV) || defined(THINK_C) || defined(applec) || defined(VMS) #define bzero(dst,len) memset((char *)dst, 0, len) #define bcopy(src,dst,len) memcpy((char *)dst, (char *)src, len) #define bcmp(src, dst, len) memcmp((char *)dst, (char *)src, len) #endif /* * These expand the BSD typedefs. This is done rather than typedef'ing * them so that we don't care whether or not defines them * (something that's hard to tell without trying to compile). */ #define u_char unsigned char #define u_short unsigned short #define u_int unsigned int #define u_long unsigned long /* * Return an open file descriptor or -1. */ #if defined(applec) || defined(THINK_C) #define TIFFOpenFile(name, mode, prot) open(name, mode) #else #if defined(MSDOS) #define TIFFOpenFile(name, mode, prot) open(name, mode|O_BINARY, prot) #else #define TIFFOpenFile(name, mode, prot) open(name, mode, prot) #endif #endif /* * Return the size in bytes of the file * associated with the supplied file descriptor. */ #if USE_PROTOTYPES extern long TIFFGetFileSize(int fd); #else extern long TIFFGetFileSize(); #endif #ifdef MMAP_SUPPORT /* * Mapped file support. * * TIFFMapFileContents must map the entire file into * memory and return the address of the mapped * region and the size of the mapped region. * TIFFUnmapFileContents does the inverse operation. */ #if USE_PROTOTYPES extern int TIFFMapFileContents(int fd, char **paddr, long *psize); extern void TIFFUnmapFileContents(char *addr, long size); #else extern int TIFFMapFileContents(); extern void TIFFUnmapFileContents(); #endif #endif /* * Mac workaround to handle the file * extension semantics of lseek. */ #ifdef applec #define lseek mpw_lseek extern long mpw_lseek(int, long, int); #else extern long lseek(); #endif /* * Default Read/Seek/Write definitions. */ #ifndef ReadOK #define ReadOK(fd, buf, size) (read(fd, (char *)buf, size) == size) #endif #ifndef SeekOK #define SeekOK(fd, off) (lseek(fd, (long)off, L_SET) == (long)off) #endif #ifndef WriteOK #define WriteOK(fd, buf, size) (write(fd, (char *)buf, size) == size) #endif #if defined(__MACH__) || defined(THINK_C) extern void *malloc(size_t size); extern void *realloc(void *ptr, size_t size); #else /* !__MACH__ && !THINK_C */ #if defined(MSDOS) #include #else /* !MSDOS */ #if defined(_IBMR2) #include #else /* !_IBMR2 */ extern char *malloc(); extern char *realloc(); #endif /* _IBMR2 */ #endif /* !MSDOS */ #endif /* !__MACH__ */ /* * dblparam_t is the type that a double precision * floating point value will have on the parameter * stack (when coerced by the compiler). */ #ifdef applec typedef extended dblparam_t; #else typedef double dblparam_t; #endif /* * Varargs parameter list handling...YECH!!!! */ #if defined(__STDC__) && !defined(USE_VARARGS) #define USE_VARARGS 0 #endif #if defined(USE_VARARGS) #if USE_VARARGS #include #define VA_START(ap, parmN) va_start(ap) #else #include #define VA_START(ap, parmN) va_start(ap, parmN) #endif #endif /* defined(USE_VARARGS) */ #endif /* _COMPAT_ */ ting to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDxloadimage.4.1/tiff/tiffio.h 664 221 144 20622 5461577451 11161 /* $Header: /usr/people/sam/tiff/libtiff/RCS/tiffio.h,v 1.53 92/02/19 14:24:20 sam Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _TIFFIO_ #define _TIFFIO_ /* * TIFF I/O Library Definitions. */ #include "tiff.h" /* * TIFF is defined as an incomplete type to hide the * library's internal data structures from clients. */ typedef struct tiff TIFF; #ifndef NULL #define NULL 0 #endif /* * Flags to pass to TIFFPrintDirectory to control * printing of data structures that are potentially * very large. Bit-or these flags to enable printing * multiple items. */ #define TIFFPRINT_NONE 0x0 /* no extra info */ #define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ #define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ #define TIFFPRINT_COLORMAP 0x4 /* colormap */ #define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ #define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ #define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ #if defined(__STDC__) || defined(__EXTENDED__) || USE_CONST extern const char TIFFVersion[]; extern const unsigned char TIFFBitRevTable[256]; extern const unsigned char TIFFNoBitRevTable[256]; #else extern char TIFFVersion[]; extern unsigned char TIFFBitRevTable[256]; extern unsigned char TIFFNoBitRevTable[256]; #endif /* * Macros for extracting components from the * packed ABGR form returned by TIFFReadRGBAImage. */ #define TIFFGetR(abgr) ((abgr) & 0xff) #define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) #define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) #define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) #if defined(c_plusplus) || defined(__cplusplus) || defined(__STDC__) || defined(__EXTENDED__) || USE_PROTOTYPES #include #include typedef void (*TIFFErrorHandler)(char* module, char* fmt, va_list ap); #if defined(__cplusplus) extern "C" { #endif extern void TIFFClose(TIFF*); extern int TIFFFlush(TIFF*); extern int TIFFFlushData(TIFF*); extern int TIFFGetField(TIFF*, int, ...); extern int TIFFVGetField(TIFF*, int, va_list); extern int TIFFGetFieldDefaulted(TIFF*, int, ...); extern int TIFFVGetFieldDefaulted(TIFF*, int, va_list); extern int TIFFReadDirectory(TIFF*); extern int TIFFScanlineSize(TIFF*); extern unsigned long TIFFStripSize(TIFF*); extern unsigned long TIFFVStripSize(TIFF*, unsigned long); extern unsigned long TIFFTileRowSize(TIFF*); extern unsigned long TIFFTileSize(TIFF*); extern unsigned long TIFFVTileSize(TIFF*, unsigned long); extern int TIFFFileno(TIFF*); extern int TIFFGetMode(TIFF*); extern int TIFFIsTiled(TIFF*); extern long TIFFCurrentRow(TIFF*); extern int TIFFCurrentDirectory(TIFF*); extern int TIFFCurrentStrip(TIFF*); extern int TIFFCurrentTile(TIFF*); extern int TIFFReadBufferSetup(TIFF*, char*, unsigned); extern int TIFFSetDirectory(TIFF*, int); extern int TIFFSetField(TIFF*, int, ...); extern int TIFFVSetField(TIFF*, int, va_list); extern int TIFFWriteDirectory(TIFF *); #if defined(c_plusplus) || defined(__cplusplus) extern TIFF* TIFFOpen(const char*, const char*); extern TIFF* TIFFFdOpen(const int, const char*, const char*); extern const char* TIFFFileName(TIFF*); extern void TIFFError(const char*, const char*, ...); extern void TIFFWarning(const char*, const char*, ...); extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); extern int TIFFReadScanline(TIFF*, unsigned char*, unsigned, unsigned = 0); extern int TIFFWriteScanline(TIFF*, unsigned char*, unsigned, unsigned = 0); extern int TIFFReadRGBAImage(TIFF*, unsigned long, unsigned long, unsigned long*, int stop = 0); #else extern TIFF* TIFFOpen(char*, char*); extern TIFF* TIFFFdOpen(int, char*, char*); extern char* TIFFFileName(TIFF*); extern void TIFFError(char*, char*, ...); extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler handler); extern void TIFFWarning(char*, char*, ...); extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler handler); extern void TIFFPrintDirectory(TIFF*, FILE*, long); extern int TIFFReadScanline(TIFF*, unsigned char*, unsigned, unsigned); extern int TIFFWriteScanline(TIFF*, unsigned char*, unsigned, unsigned); extern int TIFFReadRGBAImage(TIFF*, unsigned long, unsigned long, unsigned long*, int stop); #endif extern unsigned int TIFFComputeTile(TIFF*, unsigned long, unsigned long, unsigned int, unsigned long); extern int TIFFCheckTile(TIFF*, unsigned long, unsigned long, unsigned long, unsigned); extern unsigned int TIFFNumberOfTiles(TIFF*); extern int TIFFReadTile(TIFF*, unsigned char*, unsigned long, unsigned long, unsigned long, unsigned); extern unsigned int TIFFComputeStrip(TIFF*, unsigned long, unsigned int); extern unsigned int TIFFNumberOfStrips(TIFF*); extern int TIFFReadEncodedStrip(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFReadRawStrip(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFReadEncodedTile(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFReadRawTile(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFWriteEncodedStrip(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFWriteRawStrip(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFWriteEncodedTile(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFWriteRawTile(TIFF*, unsigned, unsigned char*, unsigned); extern int TIFFSwabShort(unsigned short *); extern int TIFFSwabLong(unsigned long *); extern int TIFFSwabArrayOfShort(unsigned short *, int); extern int TIFFSwabArrayOfLong(unsigned long *, int); extern int TIFFReverseBits(unsigned char *, int); #if defined(__cplusplus) } #endif #else typedef void (*TIFFErrorHandler)(); extern void TIFFClose(); extern TIFF *TIFFOpen(); extern TIFF *TIFFFdOpen(); extern char* TIFFFileName(); extern int TIFFFileno(); extern int TIFFGetMode(); extern int TIFFIsTiled(); extern unsigned int TIFFComputeTile(); extern long TIFFCurrentRow(); extern int TIFFCurrentDirectory(); extern int TIFFCurrentStrip(); extern int TIFFCurrentTile(); extern void TIFFError(); extern TIFFErrorHandler TIFFSetErrorHandler(); extern int TIFFFlush(); extern int TIFFFlushData(); extern int TIFFGetField(); extern int TIFFVGetField(); extern int TIFFGetFieldDefaulted(); extern int TIFFVGetFieldDefaulted(); extern unsigned int TIFFNumberOfTiles(); extern void TIFFPrintDirectory(); extern int TIFFReadDirectory(); extern int TIFFReadBufferSetup(); extern int TIFFReadScanline(); extern int TIFFReadTile(); extern unsigned int TIFFComputeStrip(); extern unsigned int TIFFNumberOfStrips(); extern int TIFFReadEncodedStrip(); extern int TIFFReadRawStrip(); extern int TIFFReadEncodedTile(); extern int TIFFReadRGBAImage(); extern int TIFFReadRawTile(); extern int TIFFScanlineSize(); extern unsigned long TIFFStripSize(); extern unsigned long TIFFVStripSize(); extern unsigned long TIFFTileRowSize(); extern unsigned long TIFFTileSize(); extern unsigned long TIFFVTileSize(); extern int TIFFSetDirectory(); extern int TIFFSetField(); extern int TIFFVSetField(); extern void TIFFWarning(); extern TIFFErrorHandler TIFFSetWarningHandler(); extern int TIFFWriteDirectory(); extern int TIFFWriteScanline(); extern int TIFFWriteEncodedStrip(); extern int TIFFWriteRawStrip(); extern int TIFFWriteEncodedTile(); extern int TIFFWriteRawTile(); extern int TIFFSwabShort(); extern int TIFFSwabLong(); extern int TIFFSwabArrayOfShort(); extern int TIFFSwabArrayOfLong(); extern int TIFFReverseBits(); extern int TIFFCheckTile(); #endif #endif /* _TIFFIO_ */ urves */ #define TIFFPRINT_COLORMAP 0x4 /* colormap */ #define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matricexloadimage.4.1/tiff/tiffioP.h 664 221 144 26731 5461577451 11310 /* $Header: /usr/people/sam/tiff/libtiff/RCS/tiffioP.h,v 1.28 92/03/06 11:59:52 sam Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _TIFFIOP_ #define _TIFFIOP_ /* * ``Library-private'' definitions. */ #include "tiffcompat.h" #include "tiff.h" /* * Internal format of a TIFF directory entry. */ typedef struct { u_long td_fieldsset[2]; /* bit vector of fields that are set */ u_long td_imagewidth, td_imagelength, td_imagedepth; u_long td_tilewidth, td_tilelength, td_tiledepth; u_short td_subfiletype; u_short td_bitspersample; u_short td_sampleformat; u_short td_compression; u_short td_photometric; u_short td_threshholding; u_short td_fillorder; u_short td_orientation; u_short td_samplesperpixel; u_short td_predictor; u_long td_rowsperstrip; u_long td_minsamplevalue, td_maxsamplevalue; /* XXX */ float td_xresolution, td_yresolution; u_short td_resolutionunit; u_short td_planarconfig; float td_xposition, td_yposition; u_long td_group3options; u_long td_group4options; u_short td_pagenumber[2]; u_short td_matteing; u_short td_cleanfaxdata; u_short td_badfaxrun; u_long td_badfaxlines; u_short *td_colormap[3]; u_short td_halftonehints[2]; char *td_documentname; char *td_artist; char *td_datetime; char *td_hostcomputer; char *td_imagedescription; char *td_make; char *td_model; char *td_software; char *td_pagename; u_long td_stripsperimage; u_long td_nstrips; /* size of offset & bytecount arrays */ u_long *td_stripoffset; u_long *td_stripbytecount; #ifdef YCBCR_SUPPORT float *td_ycbcrcoeffs; u_short td_ycbcrsubsampling[2]; u_short td_ycbcrpositioning; #endif #ifdef JPEG_SUPPORT u_short td_jpegproc; u_short td_jpegrestartinterval; u_char **td_qtab; u_char **td_dctab; u_char **td_actab; #endif #ifdef COLORIMETRY_SUPPORT float *td_whitepoint; float *td_primarychromas; float *td_refblackwhite; u_short *td_transferfunction[4]; #endif #ifdef CMYK_SUPPORT u_short td_inkset; u_short td_dotrange[2]; char *td_inknames; char *td_targetprinter; #endif } TIFFDirectory; /* * Field flags used to indicate fields that have * been set in a directory, and to reference fields * when manipulating a directory. */ /* multi-entry fields */ #define FIELD_IMAGEDIMENSIONS 0 #define FIELD_TILEDIMENSIONS 1 #define FIELD_CELLDIMENSIONS 2 /* XXX */ #define FIELD_RESOLUTION 3 #define FIELD_POSITION 4 /* single-entry fields */ #define FIELD_SUBFILETYPE 5 #define FIELD_BITSPERSAMPLE 6 #define FIELD_COMPRESSION 7 #define FIELD_PHOTOMETRIC 8 #define FIELD_THRESHHOLDING 9 #define FIELD_FILLORDER 10 #define FIELD_DOCUMENTNAME 11 #define FIELD_IMAGEDESCRIPTION 12 #define FIELD_MAKE 13 #define FIELD_MODEL 14 #define FIELD_ORIENTATION 15 #define FIELD_SAMPLESPERPIXEL 16 #define FIELD_ROWSPERSTRIP 17 #define FIELD_MINSAMPLEVALUE 18 #define FIELD_MAXSAMPLEVALUE 19 #define FIELD_PLANARCONFIG 20 #define FIELD_PAGENAME 21 #define FIELD_GROUP3OPTIONS 22 #define FIELD_GROUP4OPTIONS 23 #define FIELD_RESOLUTIONUNIT 24 #define FIELD_PAGENUMBER 25 #define FIELD_STRIPBYTECOUNTS 26 #define FIELD_STRIPOFFSETS 27 #define FIELD_COLORMAP 28 #define FIELD_PREDICTOR 29 #define FIELD_ARTIST 30 #define FIELD_DATETIME 31 #define FIELD_HOSTCOMPUTER 32 #define FIELD_SOFTWARE 33 #define FIELD_MATTEING 34 #define FIELD_BADFAXLINES 35 #define FIELD_CLEANFAXDATA 36 #define FIELD_BADFAXRUN 37 #define FIELD_SAMPLEFORMAT 38 #define FIELD_SMINSAMPLEVALUE 39 #define FIELD_SMAXSAMPLEVALUE 40 #define FIELD_IMAGEDEPTH 41 #define FIELD_TILEDEPTH 42 #define FIELD_HALFTONEHINTS 43 #ifdef YCBCR_SUPPORT #define FIELD_YCBCRCOEFFICIENTS 44 #define FIELD_YCBCRSUBSAMPLING 45 #define FIELD_YCBCRPOSITIONING 46 #endif #ifdef JPEG_SUPPORT #define FIELD_JPEGPROC 47 #define FIELD_JPEGRESTARTINTERVAL 48 #define FIELD_JPEGQTABLES 49 #define FIELD_JPEGDCTABLES 50 #define FIELD_JPEGACTABLES 51 #endif #ifdef COLORIMETRY_SUPPORT #define FIELD_REFBLACKWHITE 52 #define FIELD_WHITEPOINT 53 #define FIELD_PRIMARYCHROMAS 54 #define FIELD_TRANSFERFUNCTION 55 #endif #ifdef CMYK_SUPPORT #define FIELD_INKSET 56 #define FIELD_INKNAMES 57 #define FIELD_DOTRANGE 58 #define FIELD_TARGETPRINTER 59 #endif #define FIELD_LAST 59 #define TIFFExtractData(tif, type, v) \ ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ (v) & (tif)->tif_typemask[type]) #define TIFFInsertData(tif, type, v) \ ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \ (v) & (tif)->tif_typemask[type]) typedef struct { u_short field_tag; /* field's tag */ short field_readcount; /* read count (-1 for unknown) */ short field_writecount; /* write count (-1 for unknown) */ TIFFDataType field_type; /* type of associated data */ u_short field_bit; /* bit in fieldsset bit vector */ u_short field_oktochange; /* if true, can change while writing */ char *field_name; /* ASCII name */ } TIFFFieldInfo; #define FIELD_IGNORE ((u_short)-1) /* tags processed but ignored */ #define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ #define TIFF_VARIABLE -1 /* marker for variable length tags */ #define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ extern const TIFFFieldInfo tiffFieldInfo[];/* table of field descriptors */ extern const int tiffDataWidth[]; /* table of tag datatype widths */ #define BITn(n) (((unsigned)1L)<<((n)&0x1f)) #define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32]) #define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) #define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) #define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field)) #define FieldSet(fields, f) (fields[(f)/32] & BITn(f)) #define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) struct tiff { char *tif_name; /* name of open file */ short tif_fd; /* open file descriptor */ short tif_mode; /* open mode (O_*) */ char tif_fillorder; /* natural bit fill order for machine */ char tif_options; /* compression-specific options */ short tif_flags; #define TIFF_DIRTYHEADER 0x1 /* header must be written on close */ #define TIFF_DIRTYDIRECT 0x2 /* current directory must be written */ #define TIFF_BUFFERSETUP 0x4 /* data buffers setup */ #define TIFF_BEENWRITING 0x8 /* written 1+ scanlines to file */ #define TIFF_SWAB 0x10 /* byte swap file information */ #define TIFF_NOBITREV 0x20 /* inhibit bit reversal logic */ #define TIFF_MYBUFFER 0x40 /* my raw data buffer; free on close */ #define TIFF_ISTILED 0x80 /* file is tile, not strip- based */ #define TIFF_MAPPED 0x100 /* file is mapped into memory */ #define TIFF_POSTENCODE 0x200 /* need call to postencode routine */ long tif_diroff; /* file offset of current directory */ long tif_nextdiroff; /* file offset of following directory */ TIFFDirectory tif_dir; /* internal rep of current directory */ TIFFHeader tif_header; /* file's header block */ int const *tif_typeshift; /* data type shift counts */ long const *tif_typemask; /* data type masks */ long tif_row; /* current scanline */ int tif_curdir; /* current directory (index) */ int tif_curstrip; /* current strip for read/write */ long tif_curoff; /* current offset for read/write */ /* tiling support */ long tif_col; /* current column (offset by row too) */ int tif_curtile; /* current tile for read/write */ long tif_tilesize; /* # of bytes in a tile */ /* compression scheme hooks */ int (*tif_predecode)(); /* pre row/strip/tile decoding */ int (*tif_preencode)(); /* pre row/strip/tile encoding */ int (*tif_postencode)(); /* post row/strip/tile encoding */ int (*tif_decoderow)(); /* scanline decoding routine */ int (*tif_encoderow)(); /* scanline encoding routine */ int (*tif_decodestrip)(); /* strip decoding routine */ int (*tif_encodestrip)(); /* strip encoding routine */ int (*tif_decodetile)(); /* tile decoding routine */ int (*tif_encodetile)(); /* tile encoding routine */ int (*tif_close)(); /* cleanup-on-close routine */ int (*tif_seek)(); /* position within a strip routine */ int (*tif_cleanup)(); /* routine called to cleanup state */ char *tif_data; /* compression scheme private data */ /* input/output buffering */ int tif_scanlinesize; /* # of bytes in a scanline */ int tif_scanlineskew; /* scanline skew for reading strips */ char *tif_rawdata; /* raw data buffer */ long tif_rawdatasize; /* # of bytes in raw data buffer */ char *tif_rawcp; /* current spot in raw buffer */ long tif_rawcc; /* bytes unread from raw buffer */ #ifdef MMAP_SUPPORT char* tif_base; /* base of mapped file */ long tif_size; /* size of mapped file region (bytes) */ #endif }; #define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0) #ifdef MMAP_SUPPORT #define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0) #else #define isMapped(tif) 0 /* force dead code */ #endif /* generic option bit names */ #define TIFF_OPT0 0x1 #define TIFF_OPT1 0x2 #define TIFF_OPT2 0x4 #define TIFF_OPT3 0x8 #define TIFF_OPT4 0x10 #define TIFF_OPT5 0x20 #define TIFF_OPT6 0x40 #define TIFF_OPT7 0x80 #include "tiffio.h" /* NB: the u_int casts are to silence certain ANSI-C compilers */ #ifdef howmany #undef howmany #endif #define howmany(x, y) ((((u_int)(x))+(((u_int)(y))-1))/((u_int)(y))) #ifdef roundup #undef roundup #endif #define roundup(x, y) (howmany(x,y)*((u_int)(y))) #if defined(c_plusplus) || defined(__cplusplus) || defined(__STDC__) || USE_PROTOTYPES #if defined(__cplusplus) extern "C" { #endif extern TIFFFieldInfo const *TIFFFindFieldInfo(u_short, TIFFDataType); extern TIFFFieldInfo const *TIFFFieldWithTag(u_short); extern int _TIFFgetfield(TIFFDirectory*, int, ...); extern int TIFFNoRowEncode(TIFF*, u_char*, int, u_int); extern int TIFFNoStripEncode(TIFF*, u_char*, int, u_int); extern int TIFFNoTileEncode(TIFF*, u_char*, int, u_int); extern int TIFFNoRowDecode(TIFF*, u_char*, int, u_int); extern int TIFFNoStripDecode(TIFF*, u_char*, int, u_int); extern int TIFFNoTileDecode(TIFF*, u_char*, int, u_int); #if defined(__cplusplus) } #endif #else extern TIFFFieldInfo const *TIFFFindFieldInfo(); extern TIFFFieldInfo const *TIFFFieldWithTag(); extern int _TIFFgetfield(); extern int TIFFNoRowEncode(); extern int TIFFNoStripEncode(); extern int TIFFNoTileEncode(); extern int TIFFNoRowDecode(); extern int TIFFNoStripDecode(); extern int TIFFNoTileDecode(); #endif #endif /* _TIFFIOP_ */ awStrip(TIFF*, unsigned, unsigned char*ELD_SAMPLEFORMAT 38 #define FIELD_SMINSAMPLEVALUE 39 #define FIELD_SMAXSAMPLEVALUE 40 #define FIELD_IMAGEDEPTH 41 #define FIELD_TILEDEPTH 42 #define FIELD_HALFTONEHINTS 43 #ifdef YCBCR_SUPPORT #define FIELD_YCBCRCOEFFICIENTS 44 #define FIELD_YCBCRSUBSAMPLING 45 #define FIELD_YCBCRPOSITIONING 46 #endif #ifdef JPEG_SUPPORT #define FIELD_JPEGPROC 47 #define FIELD_JPEGRESTARTINTERVAL 48 #define FIELD_JPEGQTABLES 49 #define FIELD_JPEGDCTABLES 50 #define FIELD_JPEGACTABLES 51 #endif #ifdef COLORIMETRY_SUPPORT #define FIELD_REFBLACKWHITE 52 #define FIELD_WHITEPOINT 53 #define FIELD_PRIMARYCHROMAS 54 #define FIELD_TRANSFERFUNCTION 55 #endif #ifdef CMYK_SUPPORT #define FIELD_INKSET 56 #define FIELD_INKNAMES 57 #define FIELD_DOTRANGE 58 #define FIELD_TARGETPRINTER 59 #endif #define FIELD_LAST 59 #define TIFFExtractData(tif, type, v) \ ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ (v) & (tif)->tif_typemask