xli-2006-11-10/0000755000031400000060000000000010525262417012425 5ustar smarryconsolexli-2006-11-10/ABOUTGAMMA0000644000031400000060000001756406461630120013774 0ustar smarryconsole########################################################################### # "ident @(#)x11:contrib/clients/xloadimage/ABOUTGAMMA 1.1 93/07/28 Labtam" "A note on gamma correction and images" Author: Graeme W. Gill graeme@labtam.oz.au Date: 93/5/16 "What is all this gamma stuff anyway ?" -------------------------------------- Although it would be nice to think that "an image is an image", there are a lot of complications. Not only are there a whole bunch of different image formats (gif, jpeg, tiff etc etc), there is a whole lot of other technical stuff that makes dealing with images a bit complicated. Gamma is one of those things. If you've ever downloaded images from BBS or the net, you've probably noticed (with most image viewing programs) that some images look ok, some look too dark, and some look too light. "Why is this ?" you may ask. This, is gamma correction (or the lack of it). Why do we need gamma correction at all ? -------------------------------------- Gamma correction is needed because of the nature of CRTs (cathode ray tubes - the monitors usually used for viewing images). If you have some sort of real live scene and turn it into a computer image by measuring the amount of light coming from each point of the scene, then you have created a "linear" or un-gamma-corrected image. This is a good thing in many ways because you can manipulate the image as if the values in the image file were light (ie. adding and multiplying will work just like real light in the real world). Now if you take the image file and turn each pixel value into a voltage and feed it into a CRT, you find that the CRT _doesn't_ give you an amount of light proportional to the voltage. The amount of light coming from the phosphor in the screen depends on the the voltage something like this: Light_out = voltage ^ crt_gamma So if you just dump your nice linear image out to a CRT, the image will look much too dark. To fix this up you have to "gamma correct" the image first. You need to do the opposite of what the CRT will do to the image, so that things cancel out, and you get what you want. So you have to do this to your image: gamma_corrected_image = image ^ (1/crt_gamma) For most CRTs, the crt_gamma is somewhere between 1.0 and 3.0. If that is all it is, why does it seem so complicated ? ----------------------------------------------------- The problem is that not all display programs do gamma correction. Also not all sources of images give you linear images (Video cameras or video signals in general). Because of this, a lot of images already have some gamma correction done to them, and you are rarely sure how much. If you try and display one of those images with a program that does gamma correction for you, the image gets corrected twice and looks way to light. If you display one of those images with a program that doesn't do gamma correction, then it will look vaguely right, but not perfect, because the gamma correction is not exactly right for you particular CRT. Whose fault is all this ? ----------------------- It is really three things. One is all those display programs out there that don't do gamma correction properly. Another is that most image formats don't specify a standard gamma, or don't have some way or recording what their gamma correction is. The third thing is that not many people understand what gamma correction is all about, and create a lot of images with varying gamma's. At least two file formats do the right thing. The Utah Raster Toolkit .rle format has a semi-standard way of recording the gamma of an image. The JFIF file standard (that uses JPEG compression) specifies that the image to be encoded must have a gamma of 1.0 (ie. a linear image - but not everyone obeys the rules). Some image loaders (for instance xli - an X11 image utility) allow you to specify not only the gamma of the monitor you are using, but the individual gamma values of image you are trying to view. Other image viewers (eg. xv another X11 image program) and utilities (eg. the pbm toolkit) provide ways of changing the gamma of an image, but you have to figure out the overall gamma correction yourself, allowing for undoing any gamma correction the image has, and then the gamma correction you need to suite your CRT monitor. [ Note that xv 2.21 doesn't provide an easy way of modifying the gamma of an image. You need to adjust the R, G and B curves to the appropriate gamma in the ColEdit controls. Altering the Intensity in the HSV controls doesn't do the right thing, as it fails to take account of the effect gamma has on H and S. This tends to give a tint to the image. ] How can I figure out what my viewer does, or what gamma my screen has ? --------------------------------------------------------------------- The simplest way to do that is to try loading the file chkgamma.jpg (provided with xli distribution), which is a JFIF jpeg format file containing two grayscale ramps. The ramps are chosen to look linear to the human eye, one using continuous tones, and the other using dithering. If your viewer does the right thing and gamma corrects images, then the two ramps should look symmetrical, and the point at which they look equally bright should be almost exactly half way from the top to the bottom. (To find this point it helps if you move away a little from the screen, and de-focus your eyes a bit.) If your viewer doesn't do gamma correction, then left hand ramp will have a long dark part and a short white part, and the point of equal brightness will be above the center. If your viewer does have a way of setting the right amount of gamma correction for a display, then if the equal brightness point is above center increase the gamma, and decrease it if it is below the center. The value will usually be around 2.2 [with xli for instance, you can adjust the display gamma with the -dispgamma flag, and once you've got it right, you can set the DISPLAY_GAMMA environment variable in your .profile] How do I figure out what the gamma of an image is ? ------------------------------------------------- This is the most tricky bit. As a general rule it seems that a lot of true color (ie. 24 bit, .ppm .jpg) images have a gamma of 1.0 (linear), although there are many about that have some gamma correction. It seems that the majority of pseudo color images (ie. 8 bit images with color maps - .gif etc.) are gamma corrected to some degree or other. If your viewer does gamma correction then linear images will look good, and gamma corrected images will look too light. If your viewer doesn't do gamma correction, then linear images will look too dark, and gamma corrected images will ok. Why Linear images are sometimes not such a good thing ----------------------------------------------------- One of the reason that many high quality formats (such as Video) use gamma correction is that it actually makes better use of the storage medium. This is because the human eye has a logarithmic response to light, and gamma correction has a similar compression characteristic. This means images could make better use of 8 bits per color (for instance), if they used gamma correction. The implication though, is that every time you want to do any image processing you should convert the 8 bit image to 12 or so linear bits to retain the same accuracy. Since little popular software does this, and none of the popular image formats can agree on a standard gamma correction factor, it is difficult to justify gamma corrected images at the popular level. If some image formats can standardize on a particular gamma, and if image manipulation software takes care to use extra precision when dealing with linearized internal data, then gamma corrected distribution of images would be a good thing. (I am told that the Kodak PhotoCD format for instance, has a standard gamma correction factor that enables it to get the highest quality out of the bits used to hold the image). ########################################################################### xli-2006-11-10/CHANGES0000644000031400000060000000214510525262416013421 0ustar smarryconsoleFri Nov 10 21:50:45 PST 2006 Fix crashes for PGM/PPM images with maxval > 255. Fix various uninitialized variable warnings. Sun Sep 4 21:59:17 PDT 2005 Finally fix the unsigned arithmetic problem that was resulting in blank screens when using -fillscreen with -onroot. Also fix some problems turned up with -Wmissing-prototypes. Sun Feb 27 15:16:08 PST 2005 Fix a security problem in the faces loader, a security problem when opening compressed files, and check for integer overflows in image data size calculations. Add support for bzip2-compressed files. #include in png.c, not "assert.h" -- no idea why I did that. Sat Mar 29 16:56:37 PST 2003 Use integer arithmetic in zoom calculuations instead of floating point. Remove unused varargs.h #include from rlelib.c Fix bug when merging more than two images. Mon May 21 09:43:49 PDT 2001 Don't abort loading GIF87a images if the screen descriptor is non-null. Emit a warning message and continue. Sun Jul 30 00:11:34 PDT 2000 skip past failed loads when going backwards Thu Feb 17 06:33:10 PST 2000 fix problem where -geometry +0+0 gets ignored xli-2006-11-10/Makefile.std0000644000031400000060000001047610525262416014665 0ustar smarryconsole# Makefile for xli. # Use this to make default BSD or SYSV xli builds # miscellaneous defines. # -DHAVE_GUNZIP if you want to use gunzip rather than uncompress on .Z files # -DHAVE_BUNZIP2 if you have bzip2 and want to handle .bz2 files # -DNO_UNCOMPRESS if you system doesn't have uncompress MISC_DEFINES= SYSPATHFILE=/usr/lib/X11/Xli INSTALLDIR=/usr/bin/X11 SHELL= /bin/sh MAKE= make STD_CC= cc GCC= gcc CP= cp LN= ln -s RM= rm -f MV= mv -f LIBS= -lX11 -lm CFLAGS= -O -DSYSPATHFILE=\"$(SYSPATHFILE)\" $(OPTIONALFLAGS) $(EXTRAFLAGS) GCCFLAGS= -fstrength-reduce -finline-functions MISC= Makefile.std Imakefile README ABOUTGAMMA \ README.orig xli.man xli.txt xlito.man xlito.txt xliguide.man \ patchlevel release BINMISC= chkgamma.jpg INCS= cmuwmrast.h copyright.h fbm.h g3.h gif.h image.h imagetypes.h \ img.h kljcpyrght.h mac.h mcidas.h mrmcpyrght.h options.h \ pbm.h rle.h sunraster.h tgncpyrght.h xli.h xwd.h mit.cpyrght rgbtab.h \ tga.h bmp.h pcd.h ddxli.h SRCS1= bright.c clip.c cmuwmrast.c compress.c dither.c faces.c fbm.c \ fill.c g3.c gif.c halftone.c imagetypes.c img.c mac.c mcidas.c \ mc_tables.c merge.c misc.c new.c options.c path.c pbm.c pcx.c \ reduce.c jpeg.c rle.c rlelib.c root.c rotate.c send.c smooth.c \ sunraster.c $(OPTIONALSFILES) value.c window.c xbitmap.c xli.c \ xpixmap.c xwd.c zio.c zoom.c ddxli.c tga.c bmp.c pcd.c png.c OBJS1= bright.o clip.o cmuwmrast.o compress.o dither.o faces.o fbm.o \ fill.o g3.o gif.o halftone.o imagetypes.o img.o mac.o mcidas.o \ mc_tables.o merge.o misc.o new.o options.o path.o pbm.o pcx.o \ reduce.o jpeg.o rle.o rlelib.o root.o rotate.o send.o smooth.o \ sunraster.o $(OPTIONALOFILES) value.o window.o xbitmap.o xli.o \ xpixmap.o xwd.o zio.o zoom.o ddxli.o tga.o bmp.o pcd.o png.o SRCS2= xlito.c OBJS2= xlito.o ALLTXT= $(MISC) $(INCS) $(SRCS1) $(SRCS2) ALL= $(ALLTXT) $(BINMISC) # standard target. this is for BSD-like environments, generally, although # it will also work in many System-V environments. std: @echo "Building standard distribution. If this fails, consider trying" @echo "'make sysv'." $(MAKE) all CC=$(STD_CC) # system-v target. use this if you have a system-v compliant system. sysv: @echo "Building standard distribution for System-V." $(MAKE) all CC=$(STD_CC) EXTRAFLAGS=-DSYSV # gcc target. use this if you have a gcc that is not version 1.37. you # should add -DSYSV between the quotes in EXTRAFLAGS if your system is # system-v compliant as well. gcc: @echo "Building distribution with GNU cc." $(MAKE) all CC=$(GCC) EXTRAFLAGS="$(GCCFLAGS)" sysv-gcc: @echo "Building System-V distribution with GNU cc." $(MAKE) all CC=$(GCC) EXTRAFLAGS="-DSYSV $(GCCFLAGS)" install:: $(SYSPATHFILE) $(RM) $(INSTALLDIR)/xli $(RM) $(INSTALLDIR)/xsetbg $(RM) $(INSTALLDIR)/xview $(CP) xli $(INSTALLDIR)/xli $(LN) $(INSTALLDIR)/xli $(INSTALLDIR)/xsetbg $(LN) $(INSTALLDIR)/xli $(INSTALLDIR)/xview xli: $(OBJS1) $(CC) $(CFLAGS) -o xli $(OBJS1) $(LIBS) xlito: $(OBJS2) $(CC) $(CFLAGS) -o xlito $(OBJS2) all:: xli xlito .c.o: xli.h $(CC) -c $(CFLAGS) $*.c clean:: rm -f *.o *~ xli xlito buildshar doshar shar.* *.tar *.tar.gz $(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 xli manual page for" @echo "*** details on the contents of this file." cp /dev/null $(SYSPATHFILE) echo "path= /usr/local/images" \ >> $(SYSPATHFILE) echo "extension=.gif .jpg .rle .csun .msun .sun .face .xbm .bm" \ >>$(SYSPATHFILE) # target for making man and text manual entries xli.1: xli.man $(RM) xli.1 nroff -T37 -man xli.man > xli.1 xli.txt: xli.man $(RM) xli.txt nroff -man -Tlp xli.man | col -b > xli.txt xlito.1: xlito.man $(RM) xlito.1 nroff -T37 -man xlito.man > xlito.1 xlito.txt: xlito.man $(RM) xlito.txt nroff -man -Tlp xlito.man | col -b > xlito.txt # target for building debuggable versions debug: @echo Building a debugging version of xli. make xli CC=$(STD_CC) CFLAGS="-g -DDEBUG -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\"" debug-sysv: @echo Building a debugging version of xli for System-V. make xli CC=$(STD_CC) CFLAGS="-g -DDEBUG -DSYSPATHFILE=\\\"$(SYSPATHFILE)\\\" -DSYSV" xli-2006-11-10/README0000644000031400000060000001031210525262416013301 0ustar smarryconsoleXLI - X11 Image Loading Utility WHAT IS IT? xli is an image display program for X, created by Graeme Gill from Jim Frost's xloadimage, and currently maintained by smar@reptiles.org. xli will view several types of images under X11, or load images onto the X11 root window. The current version (1.17) supports: CMU Window Manager raster files Faces Project images Fuzzy Bitmap (.fbm) images GEM bit images GIF images (Including GIF89a compatibility) G3 FAX images JFIF style JPEG images McIDAS areafiles MacPaint images Windows, OS/2 BMP Image Monochrome PC Paintbrush (.pcx) images Photograph on CD Image Portable Bitmap (.pbm, .pgm, .ppm) images Portable Network Graphics (PNG) images Sun monochrome rasterfiles Sun color RGB rasterfiles Targa (.tga) files Utah Raster Toolkit (.rle) files X pixmap (.xpm) files (Version 1, 2C and 3) X10 bitmap files X11 bitmap files X Window Dump (except TrueColor and DirectColor) 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, input gamma correction, 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). A utility (xlito) is provided that allows these viewing options to be appended to the image files. CHANGES FROM XLI 1.16 Converted source code to ANSI C prototypes. Removed MSDOS support (Sorry! Anyone want to add Win32 support?) Added PNG file format loader. Added support for MIT shared memory extension. Rewrote JPEG file format loader to use the IJG library, to take advantage of performance improvements and support progressive scan JPEGs. Added the -delete, -iscale, -focus, and -cache options. Added interactive image fast scaling with the '<', '>' and '=' keys. Added TODO file. Feel free to do anything on the list, or offer your own fixes and enhancements. HOW IS XLI RELATED TO XLOADIMAGE ? xloadimage is maintained by Jim Frost - jimf@saber.com xli version 1.00 was based on xloadimage version 3.01. xli was maintained by Graeme Gill - graeme@labtam.oz.au, up to version 1.16. xli is currently maintained by smar@reptiles.org Please read README.xloadimage, which is the original xloadimage README file for xloadimage info and credits. WHERE CAN I GET IT ? http://pantransit.reptiles.org/prog/#xli COMPILING There are a variety of ways to compile xli, depending on what environment you have. The easiest way of compiling it is to use the Imakefile. Simply run 'xmkmf' (which should be in your systems /usr/bin/X11 or somewhere equivalent), which should make a Makefile suitable for your system. Type 'make' to then build xli. It can be installed in the standard place (along with its aliases xview and xsetbg) by typing 'make install'. The manual entry can be installed using 'make install.man'. The JPEG reader assumes that you have the IJG JPEG library somewhere. You can get it from ftp://ftp.uu.net/graphics/jpeg/. The PNG reader assumes you have the PNG group's library and zlib. They're at http://www.cdrom.com/pub/png/pngcode.html, along with a lot of other PNG stuff. You'll need libpng-1.0.5 or later. If using the Imakefile is not possible, then you can try using Makefile.std. Choose your target from std BSD environment sysv SYSV environment gcc BSD using gcc sysv-gcc SYSV using older gcc and use something like: make -f Makefile.std target There are a few compilation flags that you may need/want to change. This can be done in the Makefile.std file. The defines are: -DHAVE_GUNZIP if you want to use gunzip rather than uncompress on .Z files -DNO_UNCOMPRESS if you system doesn't have uncompress or gunzip. SUGGESTIONS AND BUG REPORTS xli has been developed in a fairly limited hardware environment, and not all combinations of displays and/or image formats and options have been tested. xli is useful to me, and maybe it will be useful to you. Suggestions and bug reports should go to: smar@reptiles.org xli-2006-11-10/README.xloadimage0000640000031400000060000003664110525262416015423 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/README.orig 1.1 91/12/18 Labtam" */ XLOADIMAGE - X11 Image Loading Utility WHAT IS IT? This utility will view several types of images under X11, or load images onto the root window. The current version supports: CMU Window Manager raster files Faces Project images Fuzzy Bitmap (FBM) images GEM bit images GIF images G3 FAX images McIDAS areafiles MacPaint images PC Paintbrush (PCX) images Portable Bitmap (PBM, PGM, PPM) images Sun monochrome rasterfiles Sun color RGB rasterfiles Utah Raster Toolkit (RLE) files X pixmap files X10 bitmap files X11 bitmap files X Window Dump (except TrueColor and DirectColor) 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). COMPILING There are a variety of ways to compile xloadimage, depending on what environment you have. The building techniques have changed somewhat from versions earlier than 2.0. If you use gcc you should read this whole section before compiling. If you are compiling under the X11R4 distribution, the apropriate Imakefile is included. I recommend using the standard Makefile as it contains a number of different build targets depending on your environment. If you're compiling on a BSD system or a system that's mostly BSDish, use "make std" or just "make". If you're compiling on a System-V system, use "make sysv". If you have gcc you may want to use that (read on for caveats) and should use "make sysv-gcc" or "make sysv-gcc-1-37" as appropriate. If you have gcc on your system, and it's not gcc 1.37, compile via "make gcc". Gcc should be used if it works because the strength-reduction and inline-functions directives dramatically improve performance of some operations. Please note that use of gcc on some systems, particularly Sun-4, may cause problems. If you have gcc 1.37 on your system, compile via "make gcc-1-37". Gcc 1.37 has an optimizer bug which causes (at least) GIF image loading to fail. This make target adds some extra compilation flags which should correct this problem. If you run into problems with code compiled with gcc, I suggest trying the same thing using the standard or System-V target (whichever is appropriate) before reporting a bug. Bug fixes are always appreciated. PLEASE INCLUDE THE VERSION NUMBER REPORTED BY xloadimage -version IN ANY BUG REPORT. WORKAROUNDS FOR BROKEN SERVERS Some servers which use odd-depth displays (eg not 1 or a multiple of 8 bits) do not correctly handle a plane mask with GXcopy. If your server displays color images in only two colors although it supports more colors, add a -DSERVER_HAS_BROKEN_PLANEMASK to CFLAGS in the Makefile. Some Visual X-19 Turbo displays have this problem; you should request an updated ROM if you have one of these. Xloadimage version 3.0 and later should not exhibit this problem. Xloadimage version 3.0 and later supports all visual types and will attempt to pick the best visual for a given image. Sometimes it may pick a bad visual or you pick one that the server says it knows how to do but really can't handle. In either case the -visual option can be used to force a particular visual. 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 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. Free code can be good code. All contributions have similar notices. Commercial sites are welcome to use the code even without asking me, although I'm very happy to hear of this stuff going toward real products so I appreciate it if anyone who uses some or all of the code drops me a line. 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. PRAISE, SUGGESTIONS AND BUG REPORTS Praise, suggestions, and bug reports should go to: Jim Frost Saber Software 185 Alewife Brook Parkway Cambridge, MA 02138 (617) 924-1985 jimf@saber.com ..!uunet!saber!jimf 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, 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. xli-2006-11-10/TODO0000644000031400000060000000156410525262416013122 0ustar smarryconsolefix 16-bit PGM crash bug fix PNG loading bug for interlaced depth 1 grayscale images with a background colour, and improve handling of grayscale and paletted PNG images with transparency fix crash on interactive zoom with -clip set fix bug where -fillscreen only applies to first image make MIT-SHM conditional for systems that don't have it document -delete, -iscale, -focus, -cache, '>', '<', and '=' and NEVER MIND tweaking send.c for performance. I mean, really, WHO ON EARTH CARES? Except me, I mean. add vicar reader, copyright Noel Gorelick, gorelick@asu.edu, description: 'VICAR: a general purpose multi-dimensional image processing package developed by NASA/JPL.' make fast image scaling a subfeature of -zoom, eliminate -iscale and add -zoom auto add a TIFF reader? add configurable external filters, action programs (making -delete redundant) and maybe readers xli-2006-11-10/bmp.c0000644000031400000060000002764307004736433013365 0ustar smarryconsole/* * Read a Microsoft/IBM BMP file. * * Created for xli by Graeme Gill, * * Based on tga.c, and guided by the Microsoft file format * description, and bmptoppm.c by David W. Sanderson. * */ #include "xli.h" #include "imagetypes.h" #include "bmp.h" #define GULONG4(bp) ((unsigned long)(bp)[0] + 256 * (unsigned long)(bp)[1] \ + 65536 * (unsigned long)(bp)[2] + 16777216 * (unsigned long)(bp)[3]) #define GULONG2(bp) ((unsigned long)(bp)[0] + 256 * (unsigned long)(bp)[1]) #define GUINT2(bp) ((unsigned int)(bp)[0] + 256 * (unsigned int)(bp)[1]) /* Read the header of the file, and */ /* Return TRUE if this looks like a bmp file */ static boolean read_bmpHeader(ZFILE * zf, bmpHeader * hp, char *name) { unsigned char buf[WIN_INFOHEADER_LEN]; /* largest we'll need */ if (zread(zf, buf, BMP_FILEHEADER_LEN) != BMP_FILEHEADER_LEN) return FALSE; if (buf[0] != 'B' || buf[1] != 'M') return FALSE; /* bad magic number */ hp->bfSize = GULONG4(&buf[2]); hp->bfxHotSpot = GUINT2(&buf[6]); hp->bfyHotSpot = GUINT2(&buf[8]); hp->bfOffBits = GULONG4(&buf[10]); /* Read enough of the file info to figure the type out */ if (zread(zf, buf, 4) != 4) return FALSE; hp->biSize = GULONG4(&buf[0]); if (hp->biSize == WIN_INFOHEADER_LEN) hp->class = C_WIN; else if (hp->biSize == OS2_INFOHEADER_LEN) hp->class = C_OS2; else return FALSE; if (hp->class == C_WIN) { /* read in the rest of the info header */ if (zread(zf, buf + 4, WIN_INFOHEADER_LEN - 4) != WIN_INFOHEADER_LEN - 4) return FALSE; hp->biWidth = GULONG4(&buf[4]); hp->biHeight = GULONG4(&buf[8]); hp->biPlanes = GUINT2(&buf[12]);; hp->biBitCount = GUINT2(&buf[14]);; hp->biCompression = GULONG4(&buf[16]);; hp->biSizeImage = GULONG4(&buf[20]);; hp->biXPelsPerMeter = GULONG4(&buf[24]);; hp->biYPelsPerMeter = GULONG4(&buf[28]);; hp->biClrUsed = GULONG4(&buf[32]); hp->biClrImportant = GULONG4(&buf[36]); } else { /* C_OS2 */ /* read in the rest of the info header */ if (zread(zf, buf + 4, OS2_INFOHEADER_LEN - 4) != OS2_INFOHEADER_LEN - 4) return FALSE; hp->biWidth = GULONG2(&buf[4]); hp->biHeight = GULONG2(&buf[6]); hp->biPlanes = GUINT2(&buf[8]);; hp->biBitCount = GUINT2(&buf[10]);; hp->biCompression = BI_RGB; hp->biSizeImage = 0; hp->biXPelsPerMeter = 0; hp->biYPelsPerMeter = 0; hp->biClrUsed = 0; hp->biClrImportant = 0; } /* Check for file corruption */ if (hp->biBitCount != 1 && hp->biBitCount != 4 && hp->biBitCount != 8 && hp->biBitCount != 24) { fprintf(stderr, "bmpLoad: %s - Illegal image BitCount\n", hp->name); return FALSE; } if ((hp->biCompression != BI_RGB && hp->biCompression != BI_RLE8 && hp->biCompression != BI_RLE4) || (hp->biCompression == BI_RLE8 && hp->biBitCount != 8) || (hp->biCompression == BI_RLE4 && hp->biBitCount != 4)) { fprintf(stderr, "bmpLoad: %s - Illegal image compression type\n", hp->name); return FALSE; } if (hp->biPlanes != 1) { fprintf(stderr, "bmpLoad: %s - Illegal image Planes value\n", hp->name); return FALSE; } /* Fix up a few things */ if (hp->biBitCount < 24) { if (hp->biClrUsed == 0 || hp->biClrUsed > (1 << hp->biBitCount)) hp->biClrUsed = (1 << hp->biBitCount); } else hp->biClrUsed = 0; hp->name = name; return TRUE; } /* Print a brief description of the image */ static void tell_about_bmp(bmpHeader * hp) { printf("%s is a %lux%lu %d bit deep, %s%s BMP image\n", hp->name, hp->biWidth, hp->biHeight, hp->biBitCount, hp->biCompression == BI_RGB ? "" : "Run length compressed, ", hp->class == C_WIN ? "Windows" : "OS/2"); } int bmpIdent(char *fullname, char *name) { ZFILE *zf; bmpHeader hdr; if (!(zf = zopen(fullname))) { perror("bmpIdent"); return (0); } if (!read_bmpHeader(zf, &hdr, name)) { zclose(zf); return 0; /* Nope, not a BMP file */ } tell_about_bmp(&hdr); zclose(zf); return 1; } Image *bmpLoad(char *fullname, ImageOptions * image_ops, boolean verbose) { ZFILE *zf; bmpHeader hdr; Image *image; boolean data_bounds = FALSE; int skip; if (!(zf = zopen(fullname))) { perror("bmpIdent"); return (0); } if (!read_bmpHeader(zf, &hdr, image_ops->name)) { zclose(zf); return NULL; /* Nope, not a BMP file */ } if (verbose) tell_about_bmp(&hdr); znocache(zf); /* Create the appropriate image and colormap */ if (hdr.biBitCount < 24) { /* must be 1, 4 or 8 bit mapped type */ int i, n = 3; byte buf[4]; /* maximum number of colors */ int used = (1 << hdr.biBitCount); if (hdr.biBitCount == 1) /* bitmap */ image = newBitImage(hdr.biWidth, hdr.biHeight); else image = newRGBImage(hdr.biWidth, hdr.biHeight, hdr.biBitCount); image->title = dupString(hdr.name); if (hdr.class == C_WIN) n++; for (i = 0; i < hdr.biClrUsed; i++) { if (zread(zf, buf, n) != n) { fprintf(stderr, "bmpLoad: %s - Short read within Colormap\n", hdr.name); freeImage(image); zclose(zf); return NULL; } image->rgb.red[i] = buf[2] << 8; image->rgb.green[i] = buf[1] << 8; image->rgb.blue[i] = buf[0] << 8; } /* init rest of colormap (if any) */ for (; i < used; i++) { image->rgb.red[i] = image->rgb.green[i] = image->rgb.blue[i] = 0; } /* Don't know how many colors are actually used. */ /* (believing the header caould cause a fault) */ /* compress() will figure it out. */ image->rgb.used = used; /* so use max possible */ } else { /* else must be a true color image */ image = newTrueImage(hdr.biWidth, hdr.biHeight); image->title = dupString(hdr.name); } /* Skip to offset specified in file header for image data */ if (hdr.class == C_WIN) skip = hdr.bfOffBits - (BMP_FILEHEADER_LEN + WIN_INFOHEADER_LEN + 4 * hdr.biClrUsed); else skip = hdr.bfOffBits - (BMP_FILEHEADER_LEN + OS2_INFOHEADER_LEN + 3 * hdr.biClrUsed); while (skip > 0) { if (zgetc(zf) == EOF) goto data_short; skip--; } /* Read the pixel data */ if (hdr.biBitCount == 1) { byte *data, pad[4]; int illen, padlen, y; /* round bits up to byte */ illen = (image->width + 7) / 8; /* extra bytes to word boundary */ padlen = (((image->width + 31) / 32) * 4) - illen; /* start at bottom */ data = image->data + (image->height - 1) * illen; for (y = image->height; y > 0; y--, data -= illen) { /* BMP files are left bit == ms bit, * so read straight in. */ if (zread(zf, data, illen) != illen || zread(zf, pad, padlen) != padlen) goto data_short; } } else if (hdr.biBitCount == 4) { byte *data; int illen, x, y; illen = image->width; /* start at bottom */ data = image->data + (image->height - 1) * illen; if (hdr.biCompression == BI_RLE4) { int d, e; bzero((char *) image->data, image->width * image->height); for (x = y = 0;;) { int i, f; if ((d = zgetc(zf)) == EOF) goto data_short; if (d != 0) { /* run of pixels */ x += d; if (x > image->width || y > image->height) { /* don't run off buffer */ data_bounds = TRUE; /* ignore this run */ x -= d; if ((e = zgetc(zf)) == EOF) goto data_short; continue; } if ((e = zgetc(zf)) == EOF) goto data_short; f = e & 0xf; e >>= 4; for (i = d / 2; i > 0; i--) { *(data++) = e; *(data++) = f; } if (d & 1) *(data++) = e; continue; } /* else code */ if ((d = zgetc(zf)) == EOF) goto data_short; if (d == 0) { /* end of line */ data -= (x + illen); x = 0; y++; continue; } /* else */ if (d == 1) /* end of bitmap */ break; /* else */ if (d == 2) { /* delta */ if ((d = zgetc(zf)) == EOF || (e = zgetc(zf)) == EOF) goto data_short; x += d; data += d; y += e; data -= (e * illen); continue; } /* else run of literals */ x += d; if (x > image->width || y > image->height) { int btr; /* don't run off buffer */ data_bounds = TRUE; x -= d; /* ignore this run */ btr = d / 2 + (d & 1) + (((d + 1) & 2) >> 1); for (; btr > 0; btr--) { if ((e = zgetc(zf)) == EOF) goto data_short; } continue; } for (i = d / 2; i > 0; i--) { if ((e = zgetc(zf)) == EOF) goto data_short; *(data++) = e >> 4; *(data++) = e & 0xf; } if (d & 1) { if ((e = zgetc(zf)) == EOF) goto data_short; *(data++) = e >> 4; } if ((d + 1) & 2) /* read pad byte */ if (zgetc(zf) == EOF) goto data_short; } } else { /* No 4 bit rle compression */ int d, s, p; int i, e; d = image->width / 2; /* double pixel count */ s = image->width & 1; /* single pixel */ p = (4 - (d + s)) & 0x3; /* byte pad */ for (y = image->height; y > 0; y--, data -= (2 * illen)) { for (i = d; i > 0; i--) { if ((e = zgetc(zf)) == EOF) goto data_short; *(data++) = e >> 4; *(data++) = e & 0xf; } if (s) { if ((e = zgetc(zf)) == EOF) goto data_short; *(data++) = e >> 4; } for (i = p; i > 0; i--) if (zgetc(zf) == EOF) goto data_short; } } } else if (hdr.biBitCount == 8) { byte *data; int illen, x, y; illen = image->width; /* start at bottom */ data = image->data + (image->height - 1) * illen; if (hdr.biCompression == BI_RLE8) { int d, e; bzero((char *) image->data, image->width * image->height); for (x = y = 0;;) { if ((d = zgetc(zf)) == EOF) goto data_short; if (d != 0) { /* run of pixels */ x += d; if (x > image->width || y > image->height) { /* don't run off buffer */ data_bounds = TRUE; /* ignore this run */ x -= d; if ((e = zgetc(zf)) == EOF) goto data_short; continue; } if ((e = zgetc(zf)) == EOF) goto data_short; bfill(data, d, e); data += d; continue; } /* else code */ if ((d = zgetc(zf)) == EOF) goto data_short; if (d == 0) { /* end of line */ data -= (x + illen); x = 0; y++; continue; } /* else */ if (d == 1) /* end of bitmap */ break; /* else */ if (d == 2) { /* delta */ if ((d = zgetc(zf)) == EOF || (e = zgetc(zf)) == EOF) goto data_short; x += d; data += d; y += e; data -= (e * illen); continue; } /* else run of literals */ x += d; if (x > image->width || y > image->height) { int btr; /* don't run off buffer */ data_bounds = TRUE; /* ignore this run */ x -= d; btr = d + (d & 1); for (; btr > 0; btr--) { if ((e = zgetc(zf)) == EOF) goto data_short; } continue; } if (zread(zf, data, d) != d) goto data_short; data += d; if (d & 1) /* read pad byte */ if (zgetc(zf) == EOF) goto data_short; } } else { /* No 8 bit rle compression */ byte pad[4]; int padlen; /* extra bytes to word boundary */ padlen = ((image->width + 3) & ~3) - illen; for (y = image->height; y > 0; y--, data -= illen) { if (zread(zf, data, illen) != illen || zread(zf, pad, padlen) != padlen) goto data_short; } } } else { /* hdr.biBitCount == 24 */ byte *data, pad[4]; int illen, padlen, y; illen = image->width * image->pixlen; /* extra bytes to word boundary */ padlen = (((image->width * 3) + 3) & ~3) - illen; /* start at bottom */ data = image->data + (image->height - 1) * illen; for (y = image->height; y > 0; y--, data -= illen) { int i; /* BMP files are RGB, so read straight in. */ if (zread(zf, data, illen) != illen || zread(zf, pad, padlen) != padlen) goto data_short; /* Oh, no they're not */ for (i = 3 * image->width - 1; i > 0; i -= 3) { int t = data[i]; data[i] = data[i - 2]; data[i - 2] = t; } } } if (data_bounds) fprintf(stderr, "bmpLoad: %s - Data outside image area\n", hdr.name); zclose(zf); return image; data_short: fprintf(stderr, "bmpLoad: %s - Short read within Data\n", hdr.name); zclose(zf); return image; } xli-2006-11-10/bmp.h0000644000031400000060000000254606461630121013356 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/bmp.h 1.2 94/07/29 Labtam" */ /* */ /* * bmp.h - header file for Targa files */ #define C_WIN 1 /* Image class */ #define C_OS2 2 #define BI_RGB 0 /* Compression type */ #define BI_RLE8 1 #define BI_RLE4 2 #define BMP_FILEHEADER_LEN 14 #define WIN_INFOHEADER_LEN 40 #define OS2_INFOHEADER_LEN 12 /* Header structure definition. */ typedef struct { char *name; /* stash pointer to name here too */ int class; /* Windows or OS/2 */ unsigned long bfSize; /* Size of file in bytes */ unsigned int bfxHotSpot; /* Not used */ unsigned int bfyHotSpot; /* Not used */ unsigned long bfOffBits; /* Offset of image bits from start of header */ unsigned long biSize; /* Size of info header in bytes */ unsigned long biWidth; /* Image width in pixels */ unsigned long biHeight; /* Image height in pixels */ unsigned int biPlanes; /* Planes. Must == 1 */ unsigned int biBitCount; /* Bits per pixels. Must be 1, 4, 8 or 24 */ unsigned long biCompression; /* Compression type */ unsigned long biSizeImage; /* Size of image in bytes */ unsigned long biXPelsPerMeter; /* X pixels per meter */ unsigned long biYPelsPerMeter; /* Y pixels per meter */ unsigned long biClrUsed; /* Number of colormap entries (0 == max) */ unsigned long biClrImportant; /* Number of important colors */ } bmpHeader; xli-2006-11-10/bright.c0000644000031400000060000001607507004736433014063 0ustar smarryconsole/* 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 "xli.h" /* alter an image's brightness by a given percentage */ void brighten(Image *image, unsigned int percent, unsigned int verbose) { int a; unsigned int newrgb; float fperc; unsigned int size; byte *destptr; if (BITMAPP(image)) return; if(GAMMA_NOT_EQUAL(image->gamma, 1.0)) gammacorrect(image, 1.0, verbose); 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 *image, float target_gam, unsigned int verbose) { int a; int gammamap[256]; unsigned int size; byte *destptr; if (BITMAPP(image)) { /* bitmap gamma looks ok on any screen */ image->gamma = target_gam; return; } if (verbose) { printf(" Adjusting image gamma from %4.2f to %4.2f for image processing...",image->gamma,target_gam); fflush(stdout); } make_gamma(target_gam/image->gamma,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; } image->gamma = target_gam; if (verbose) printf("done\n"); } /* * Apply default gamma values to an image */ void defaultgamma(Image *image) { if (BITMAPP(image)) { /* We can't change the gamma of a bitmap */ image->gamma = globals.display_gamma; if (globals.verbose) { printf(" Default gamma is arbitrary for bitmap\n"); fflush(stdout); } return; } if (RGBP(image)) { /* Assume 8 bit mapped images are gamma corrected */ image->gamma = DEFAULT_IRGB_GAMMA; if (globals.verbose) { printf(" Default gamma for IRGB image is %4.2f\n",image->gamma); fflush(stdout); } return; } if (TRUEP(image)) { /* Assume a 24 bit image is linear */ image->gamma = 1.0; if (globals.verbose) { printf(" Default gamma for ITRUE image is %4.2f\n",image->gamma); fflush(stdout); } } } /* this initializes a lookup table for doing normalization */ static void setupNormalizationArray(unsigned int min, unsigned int 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 *image, unsigned int verbose) { unsigned int a, x, y; unsigned int min, max; Pixel pixval; Image *newimage; byte *srcptr, *destptr; byte array[256]; if (BITMAPP(image)) return(image); if(GAMMA_NOT_EQUAL(image->gamma, 1.0)) gammacorrect(image, 1.0, verbose); 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); 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++ = array[image->rgb.green[pixval] >> 8]; *destptr++ = array[image->rgb.blue[pixval] >> 8]; srcptr += image->pixlen; } } newimage->title= dupString(image->title); newimage->gamma= image->gamma; 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; break; default: newimage= image; break; } if (verbose) printf("done\n"); return(newimage); } /* convert to grayscale */ void gray(Image *image, int verbose) { int a; unsigned int size; Intensity intensity, red, green, blue; byte *destptr; if (BITMAPP(image)) return; if(GAMMA_NOT_EQUAL(image->gamma, 1.0)) gammacorrect(image, 1.0, verbose); 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= ((Intensity)colorIntensity(red, green, blue)) >> 8; *(destptr++)= intensity; /* red */ *(destptr++)= intensity; /* green */ *(destptr++)= intensity; /* blue */ } break; } if (verbose) printf("done\n"); } xli-2006-11-10/buildshar.c0000644000031400000060000000543007004736434014553 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/buildshar.c 1.5 93/07/23 Labtam" */ /* 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(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); } xli-2006-11-10/chkgamma.jpg0000644000031400000060000003341106461630123014676 0ustar smarryconsoleÿØÿàJFIFÿÛC     ÿÛC   ÿÀ,d"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý=þÕ÷£ûWÞ¹í?ö¨þÓÿj€:ÿí_z?µ}ëþÓÿjí?ö¨¯þÕ÷£ûWÞ¹í?ö¨þÓÿj€??à§³yÿ·'ħõþÌÿÓe¥|Ë«i“hº­æŸpöò\ZLðHö—1ÜÂ̬T”–6d‘r8tb¬0A ƒ_GÁI¥ó¿mOˆ¯×?Ùßúmµ¯œl¬¡º¶¿–[û{7¶„K3,…®˜È‰åDZ í&\¢í°ÅŠ«”6)öúŠ40Êf¶Y«ßï@ö‡½ÚõÎ}¿Þ·ûÐå¯í×'›ûTøÝ½~Ãÿ¤6õáñEbt«‰$¸¸]If‰`·XÂñ“Ìv“x*Ê ªƒrY6þãûbjÙ~Ö^&½¸±·Õ`‚m>Y,nÚE†åVÒÜ˜ÜÆèáX ¤£«`œ2œáÑYC&•qv×öñÜE4Q%ƒ,žtÊË!i„( *°g ™Sj°PÔⱊåO¸¸º·0ÂÍ%Ì Lje@ªî ¬…Õ[ ²ª±T,QmÇâ;‹zÃSÖþ?²}š6¶Õg™’x TŽ;wduD""J Jà`ºû_…¯5½!ÿ³æ‘·X\ÉÙï“ä™X´®õh†&…¾d,‘ƒº½½Í戚ŧÚt­?l2Á§lî'ƒÎi]Lâ&̧ÌuYeY ‹‚ˆ¨*E{ zUÅ£X[Éq,ÑJ—ìÒyЪ¬£P!W.¬Å¶bM¬ ¸sSÓ&ÒnR ÞÝÝá†pm®cvÉÈ ´lÀ0WÈÁ‘‚²²‚)lF•q–÷ ©4Ñ4 :ˆR ²yˆÑì%™˜ÄUƒ¨PŽ ¾ðRÞ›7ööV·ky§Ü_ÃzÌ4ë›O´y~W–é$ÑË‚Xœ³(B_>TÐ)]àTQE~Ò}»Þ·{ÖÛ}ÿZ>ÛïúÐÿÛ½èûw½`}·ßõ£í¾ÿ­oý»Þ·{ÖÛ}ÿZ>ÛïúÐçoío¨CiûMxÊyìmõ$xaˆCrÒV}>$Y–êwFÌ$PIRÈ¡•×rŸ–+¥[ÉÅÃjM4«=»@¢ˆ,~[¬›Éff2†RŠ"ϼ„ö/Ú§V›Mý¤<_s[Èï 0umÂí’Â8Ø…‘X 䫹+)VUaã±^ÕqhÖò\K4R¥û4žt*« hÔUË«1d-˜“k(.ZÊÚúÛÄ7þÑ5ëyíõ9†”÷Þ5•Ž¡Ú£iãÊ ’8¥ÌáìVp…x©ÿËÏ ÿÌB é×¿íµ­ÕÊß ,©iìζÝÄ|•¶‡ö¯Ø5Bç˽Xôÿ´Ø$?hµýæe›?“(Ä8‰|Å>dŸ¼˜M¤[Ý}²]*ïí–VP\ÎÚ†ÒRíå$©fV3mšRa.Ñ¡”¢á-é÷7Ój£]ÑttM[»ˆâ³kÛH„m >}Äsù¨VYš=ë'î‹Ï°*«,b¦›¢È*ÿWP°ðÝÝëZ>«meç«òÚqg%–4š61ù‹þ²<²‡oíz¯™â¯ìôþÒ½¸Ì6_gƒdƒc¾-"ÛäEûå „XÎS>[·c6«qyšÃø&ÛSŠÎ}utµ3E!Œ´>w–³¼PÊë ŸÆàHB—ýQ@­?l÷£ížõ‹ö³ëGÚÏ­m}³Þ¶{Ö/ÚÏ­k>´µöÏz>ÙïX¿k>´}¬úÐÃÿ´@Õ.?hÿ"ÃûNïìD¼?a[Ͱ 1Lòìe`<¸D’y˜Ì[<ÀÊP0ó +Ý[ÅW7ñKaqâIôÁSL×Ïcoi?™Ç,VÖÍ4il*ìVNûö•µ†÷ãg&–þÞÑíá´–(fY ]7“lž\{€`®ÒeÊ.ØÛæ,U[ñ-ÄÂçR³×'¸Õ|Cg4jê±ÝÛ%½¼m”¬ÄÊ-Ö)#—ËXâ!C«©@B½šmWG—L°Ñí/´˜dºi/š6†ñ¡inKÏÛ´26À"… (Ž4¼Ž|Êšm¾—ký•©Mý¡h׬—šE”Íox O-‹ ^‰<Àî¨ÃÌ*Ñ1xñ³~¬±nþɸյoøI¼7£ýŽÕ­lõO³Ï3ù—RZÛ-ÂM®×*ò$2B“1oœJ†L¯´iv:vÈaþÒ»¼²Ù;ÞÂÑgÎ.7·1͉s h¥¥\>UåZ!·Òì>Ç5äßÚ±ÜÙNím§ÌÐKi?ïc…ei!*ØeŠfX÷ #rÞ]Kجc¶°kK‹‰îבÍÆ°Ëæ8 c"ùb6ÜBÌË´…ý×Z¦â«Ëïí½?Cñ‡È¿¹ó·*ŸÕ¢±‡U¼L¸¸¼ÓRg[[‹¸ ¥ˆ1Øï»„b¸%C¸±“V­jÒØÍªÞI¦[ÜYé¯3µ­½Üë<ÑDXìG‘Q°\Á ¹À«@¦ßi÷£í>õ•öŸz>Óï@¿i÷£í>õ•öŸz>Óï@¿i÷£í>õ•öŸz>Óï@~Ñ3ØŒ~2û]½Ä÷Cj¶rCp±¬2ùV伊QŒ‹å‰h(w2¶â£ó— }áËiÿ³5KHòonôKûÍ5¬/µ»K‰ŒÈ²B$,­s‰æhW˺ErîË'}ñKQÕÆO[éÓj2[ý[ƒGƒO]BÎî{;ts%ݼ‡Ë1Cl×’xåw«(I—Í´K .ÏRŽ5‹Oñ-ÜgÔÁ¹ÔÏN’íÞâêÎeq ¯);b)P–ŽD‹Í2Äà}6ÒÇ^I¼Ò¿áS²°AyâF¸s§ù«o+_¨‚5c‹¹ÑLSb þQ+„–‰¦×N¼»»¼ÿ„rÛTÑ X`KG³‹\µ†â(4XbˉmŒŒòaZKI¦1o§\iÞ›Q²Õõ 6ÃS²’Òñnm¦‚ßRž+¸ìa’2é?–gtÞo”Œ`²Âe·ih·ª^X¦¥j^ ™£Ót’ö³é¶¶· so(–k»‡6›U„æXöG$€/?³ììÂÿÈWÂË{©G¦ÊŸc±Õ$“ɈE-Ê/*DÙßÊfhÎ.dŸ„ÿ´>ÌšVâ {ûgÊÓtYáµò<ÝT}•®-Ö5ý§oœcTGGo:ÞBw’Öô+XÉ£Ã¦éšÆ®êšd–z)Ñ-.o5ÅÔ¶²)&PJ¼osmû…esˆÆYå’‹éÜé——~Ö&† Ø´ÞD]GL¶ŽeÔ/#¹”Êc`Ö’38ŠH•¾ÐqÀ" ¦§-Œ·(Ú}½Å­¸†hîgY˜Ê#Q+†T@¤ʸ%U•K9RíV­^ÙCkma,Wö÷s –XaYZ°‘ÓË“z(,UL¡uÛ"åƒU«@¡Ÿi÷£í>õ—öz>Ñï@Ÿi÷£í>õ—öz>Ñï@Ÿi÷£í>õ—öz>Ñï@:|XÓ-î¾(ê²jvŸ{aq{òʺÜ6W륊Ks~c²Eç$«±äËɤ;ØIyä3Z]iÖv—wž“~:Ã;Ú\E.Ÿ"\K:Æí Kç\˰Ư'Žî5gËûâÆ™çø·Å×±\}švYj7š†‘çYÛÿ¢EsgW*²ÒwÔ¤¸X•Ìò%ÞŸ˜f•LP¤ó$ŒøTiÀ2´ËÝ'[¹x……½µÞ§6©¨h–íod¶öVñ´‹ ž£vóJ¬É%Ìb& ¹£¶È¹¢¥Ht->ãN³E´ÅýÞ=Üs¿ˆlÖ%š+‰YÝã( y·ã[Wq4’äFe–8[«³ñÛo ô‡ˆ5 +Ý7WºIûm4M:Òil­ã¿µž­ï%Ž9mR&,l›É ÊE“ÿå½®ýƒ­·ö-ÝïØo›V‚ ômJk’ãD–öòÚ;{3¹UÈšR‚عå|S7Û5ë«Ãy§ÞÉ{¶öWÒ­>Ëo’¨‘âHDQ¬~[;FV4‚„FY6±Ê®ƒÇ’ß]xš{ÝNßXƒRÔ!·Ô.¤×§iî™îšFD,³´†d$²TËÉþ±¹úû›Ï£Ï¬ï´{ÑözÑóèóë;íô}£Þ€4|ú<úÎûG½h÷ ñÔ1|LÔïíg·Ó5ÝciuiªÉ¦êRH4ï6Ry@«m-ª8|»‰ZàGvd0órXÃáí=µ9ôÍËM¿Ó-ͦ§oi%̲´š}Ü ¶¾•<Å{˜åK‹¨ãu¶¸ƒu»."I}Å—Ú…ç‹a’Îçû.; Õ³²Ô,î/!:>³,pÜZ_¼òÜCgk-ÇÙ–ÛÍYK+B^‘ùK+%u«ýJÚ{xtÛ˜@±}U·°Ô”H·šdÒ‘n‘´–WE%ËYËö»›r‘,¾lÅ€$›Jñ6¿U·Õ5x&þÄŠöëYF¤Ë•¥Æ™wq¤ ) {ˆb»•fˆ²î Ÿ³Uðý·ü$–z-…®£öˆí¬¯-,oõ íµ¡†]A'³Y§k[U¸Ôn£º†ÜÈÏæÈ8?fè"Óï­µ["ì[Á©^êq^jº%ÆžÚp[PÒK¬Á¨Ùiq4ñÚZÜi±¿’e…áŠ!4V£Î- M*Óþ.-¯.µ nÁì¬'Õt™õïµÊÙiks Ö’Z™ ”[Á¨[5¤éÑÌ‘ÌÁ‰xÀ2§¸°¾‹Â÷š´:}…Ýí´öZoˆ¡ÕÖÊÃO7Ú‡“Å4¯.š¯“3ä\ù¥–-̳Hõ4ZÇIÒ¬ïEåºé¶ð¥¨žÒUÒµË¸Š…Ô´ôû9˜m•u)”]^FÂH­B!ÔôCý‰g«_ë¨XéÚ‡ö\šÂXi™²[­J›ˆîâÓ岆Øy6\Å ^dM濟k1„š¶šäÚôIuâ û½^öêÞKYõ繸Ԯn•a¼¸ÒnmL†ò]Jk û—ì³Û ’–Y‹,ˆÅY|:еû›ñªxûÀþ¼Óæké³6«|³´1¢=ÔsÚ[]Äë+‡mË.ÒÅŠ*Æcoþß„è»|?ÿÀÿòª¹OÿhIÿäú‡ú_›£[}ŸVÿL?o…7F¿5Î3ö}†Ë÷*°±mMÛLÊÐØÞuuQó¨ó¨÷GT|ê<ê½çQçU::€8?iV77—ÓëvóA<Ú§Ø.%‰`XåƒFäY&aŒ’Y4Q­Û˜™$ͬÆé#›aï5ËKZ¸Õîu õë{(Ú}?T¸{‹Å’ÖßQ½¿‚öÊK‹×1ZÈÝO Å£Fí¶YNŽeÝ$mieâ=6êóû>Î;íjãM{»ï´[á‘4x®m㸋쑶ëiîD¸ÔÓäZ¼‘Ë¡ž;©õMÎáî[¢†t¸+=è)©ü5е;”²Ô> ø_Àé¥C ­¤æªùúŒÜ A^ÛIËÁpÓ´™À™ahåQÕÿ…7áú.ßÿðÄ?üª¯UŸáü&:ξÿ𦾠|CþÏÖµ?áì?Ùpi›o&o±]Çÿúî¹]þfí‘í†kxü¨|¯&3þÇþ­cö€ÿÁ§ÿxhó¨óªŸG@<ê<ê§çQçPÏ::©ùÔyÔÐè’éz ìÚšêÙ>göQ¼¸7Ï;QûA¼® ó[N†êIág’9¤†=2óíäe[øfîÏÃSxoS²þÉŽâÊKÉ,î4«xÞkM6 6êæxŒ)q4VÒ\j2JÃO¸šÓnµÃ;_^'OàIn'ŽÖF¿Ô.®ìu« ^×A¾šmLi¿¾{+dŠÕžàDux‘¾Îa™îìÙæ&îÚæÅþþÏÐ%ÒµØÿv¶×·:ÅáÒ¾Æð³i¶3›ù-âÓ6A$°ßê2[ùL×IfmåK"Þ$»”* ß^Ÿ@¿ƒKûM¥Åîö$Ñaºó¬æÕ!ŽÎØÉsý¦òîµ·‚aµ{©mÿ²uY,eêy2­ô‰~M¢ Óï´É,¤Ó½Íä×6âÔAö­Bosz&ûÃêwm§“8RûPI¬nf¶  >Ò¡¶»†âÿPÓ|?×®æK¨g®™umö‰!xµ(ÔiâØ,w6v±@Îö²@ÃV{W—ŸðŠ}§_Ò®¶¡Ñ¼Û»Û7N…4ßµ-¨3­ÁOôt½N"[·¾¶i´É´ÛÛ˜¦†6çîõ gU{è÷vré‹$ s¨-ÕÍŽ— [+Û\‹9WQŠÓ®ïŒÑ¤úƒ-”‰jÛ¤Ó$žÚÜöw~Ôu÷Ò­µ k˜,µB1ö{{=>é`·šs7ÙìíþËw)[Ã'ÙÑ5S¥kžYžmÚæº­?H¸Òµ+ÂïíòYÞèšU‚Bf²µ6öíu¦y1ÛË3[yŠÓÞËwhïq¨\\Ü[éEÒ[›©p,¼)câ­>ÿD³ŠÝô¿L4ØãC[’îïOMKN½žÒÝ# Ë$—ëo(³mºò,åÖmâ’Ø€dêw°øZå--ü}ðßE¶Ha¶†÷Ç>“ÄêÑÛF¶‰skpúUøHm…»E ÜÖëqkrmÛÈhª¯ü&_õW¿gÿü5_þ Ö¯‰¾:x[áþ¥ Æ»àíûßÙZk‘ÅähOýlöñÅmkÿ îeÛ>m-ÿyþ‹l–¦ %Êÿ†¹ø}ÿD—ÿ%ù#ŠxçŠçY±IíÄÑ\j0DU$¸ÑõI/ ¿Ô/oãñ5ü¶×o}47¦ûLÖ®/ òí5V»K=©5Ü×77O–‘HdÊÃ[<7¡\-æ¤5ö¡¨\ÙYZèPÉg§M!¶–Öilõd•/-åò<ï³iVR[M×’Á¨ié"+êè–ŸØú–‘¤Gu¨\ÙÙ^øEŒÚëÛ%žÛìö÷ÖF3’e–òm1 i.4ÑÆ™%í²CÕM3C›P¶Óô«½RßB¸–7M¶¾³†;;*ö)-µ;ÝbÁ"¸ˆy+¯]ݴзðÅ5¬¿Ùs^[Û€sþÔ¿µ—š®©ªé÷zîÏß©_-äµÝè]°i.ësi—/{,"Egd[»MBgþγ·¡ØÝÙXÚý›L¸°Ôlá°²ŸL³´Ô-Λ©KO{=&),%’æ-&¸3\ÅÍ+Ë,-q2êw¶©aÐC¦ÿÂY£=‹éZ…·‡¼aeg¦öÉôÛg³°u„¿—$i½ˆðýœdE=ÅÌÚÞÙïìà°¶4øá#Õ<1=힟¯G>-î¡§ÚÝÿn‹¹"Ö®/£ˆ3Ê%¿¶—TþÒµ ÒËÜÿbµb®Ö:ÄàkâUt ;o|7ð¾›47i޼k­MvR¼Žk«G´°Ôm­í$¸Žsµ»Ãd8XåÏÛ.ùÿøL¿ê¯~Ïÿøj¿ü¯UÆzG¬ìYøÃâ]ëVÚ„·~ñþ£¦¦»t°¥µýô«a£ßA4¢þÞöÛí"DiÒÎ9XJ\Ý\Ÿð¼<#ÿG/ñÿ·ˆù• Ÿ¼Ê<Ê­æQæPŸ22«y”y”g̣̪Þee}ðêòúÛáŠj÷’\Cm™}b§SFžÞÖÖïšÞâ;XíÛíIs«^K.õ•þˡ둃<ÜZ/m§ÄÞצŸqqcy Íke—ä]OwVš´6ÒâßrÒ°Õ&ðõ¼7—AÃÓZí(ì€ÔyÏ‚M×íÒÊÞâàM·lK3y· ½Â…ÅÁÝ,ia Çå’êÖñ5«‹„´ñq§ÙM$af¿¸× Ì6±o¸Xç7 öX`’O‘'µÔ—R\È?Ò–Iu™DkuüPø˜•°Ó4+O´ÑËÜM A¦>“­­Í½”²ÇŸ¥Øê/nŒËlêÚf¿©jßhyå·ŽâK™csl·7Z‘ªXäéúý߈t˳3û?Tm2ÒH7Áa§Úyîmâ–) Í/öí¼ª[;«a/ØàIHß›ÃÿÛÚ5æ›}©jÄ:­”RJ“íž}Öq[Ë*Kn%s-ÓÝÉr̆ãtÚÄžH¹Šþ(¼K­ÿ!-gûA¿âaöíkûfê×ý|‡Ÿyö©í6´âÚçûAáòà2âSe¹¸ûlgÄ৉´Û¹o:þÁðý„Ñx·ûÂÿFðü¶ÅYexž–HŠèeì5~ߪMuÿ ”º‡‹u«Ÿøèú¨Ó×ûO_œèm´‘,¤2*EtÚV¥uùS§Aˆ,ƒJ–ÆÐ•Ñ?Òlü<ÑÅewqe¦I4W_"kRC¤™"/.IŠökˆË2«ñõëÍuÞÖŸe œuû}LXÍkËëë%¸ÔÕn¡‚æK­èæ’=;T¹»e¢‹Ä^$ ²Ë¦ê0Ϭ­cá{idMRÝ<9£Í¥ØÚøƒDÓUí¾Ë§É÷Ú ’@î-2ÄßG¸L÷1èúTs˜c¶›[µ¤x{þýgMµ×4ÿìØt?²ÚÜiê¿eû …æ™gy-ÓÅ?›kö[=RÎånGcý“¦Mö‰bÓ!¾ÔÀ9_øH|=á¿ôè¿õËÆû³üEÒ4}JølýÔ»dÕ5}.aºhæ’l@Ûîå¼–_³\ËscfÂÁø}ÿBgìÿÿ„„?ù¯¢Â#£h ÿ 'ü#ŸoÑ´ëíÉâìX5Öp¯Ûmàÿ„‡DÿF—fa_"o*¿›‘ýŸbÂÜÿª‘ÿ™ÿÆ|¾õú7ÐûèßPo£}O¾õú7Ðݳ–‹w'ÁÝÃNí²_Ù,ð[ÝY[Íeþ¤|I¥,Ò¤¯»J#´H!;–æ[Ô´‚5œ¶‘{:–Ÿ%ƽ¢j0ë3i:mµì—sßY\é÷Ú”:aÝm(k½El4E’d}ð£%ìFk©_WóÿÙ¯I][özÑ,-ìî5¼šcsa V¶PË|ðëPi±ºŠ×“7ÙdÔ ìtÓÊý±SØR´‡^W¿Õ|?z`½°½þÒ¾[ˆ­ï­­–Ý´»µº’G¸k™4û›‹ÜÍp†ÒÆIMî™d&˜&}"âòñ´e»ó¦¹ó®,fЌדgÏ6˜..ô÷–Y‹Ëqo§ÍâI 772ÞAt¾cKcv·µm"±Ó$ÒoÆ¡¥ÄÚN§uqg;NŠ;¥ò%²ŽgW—O7º¿I¢Ch°N’ˆÇL"Õ†‰ýŸ£K¢[G§êeµ’_^.³e¾í[[;ÝìwVv®M¼SjjöŸg´óžxaK+g¾±wƒMèLØÉ˜eyÿå•Äw?ðê~²ûMÇÚ&ðúˆu˜m"縉'—JºÑ^ÃZµ£j—w4Zã[êÃám/HÖ_I»µÿ„LÑïlåÕ-,¤håðì·–eÎ&˜¬ó[Gaa¢N—"XÌ1ÌڬɣJˆ[ðÞ§ Ö‹á-fd¸o 3DŽâÖ[i.Õ4ÍZööí¬í4Í»#´šÉ¢²kViâvû%½¬×7šLQÝT:EÁð½­–¥wþ•¦ý¶c%¹˜:êŸÛö:n Ð<’ý¢î(n­&¸Š+FûUÓÜZÉ1·Õ>É{rÊøƒÄ><Ñÿ³oÆ‹ñCÄWúÍ”wzž«àÝ#[Ô`ºÔcÍ­ãÌtý_Lò›‹iqkq“ÛÃäDÍ¢XÙåÂÁøƒÿBgíÿ„‹ÿù¯¯UŸÇ_ü-©^?Å_‡Þñ毭yý†«¨ Ú£^ÛÅs"DšŽ¢ˆbRݲµ‹OnÛ‹5Ä÷FîF?ár~ÉÿôB~ÿàw€¿ùk@”ÛèßPï÷£½M¾õÿz7ûÐÛèßPï÷£½~‰þÉ:M¯ìÿ¡&»go}£Ï©Ùk×vKÝ ¬ZúûL™ZZyÚAÛü³ÝDmJ(ßI‹Øm4-RöóìW·ßi¼¹ÿ„‚ßQH´åÔ£3yÖPkB-­Ùg‹ìÍ0 -.µKÆûUµÊAh|÷öMðÏÛ¾|<´ŠËO†bÊâgÔô¯µØÜê·:ÅŬÍ$.¥m2 ã”5ŤR©ŸJˆ´÷^›c.©[i—Úå½¾µ¤]ÍÖ­£j3Ï{!]A`¸Õµø¦¸í³iQê÷ÒΗ—×wo t¹žÊk ;Ô…Ì#ȵ‹M¸´¹Q`rtýÒM(i²Co¨Û¶™k§i³Û>æh#ºXcŠÚÞyám>kK¸Î­ýŸ<–ÂÝΩq§£iELë[è–:Þ‹¤76ö–:¼Ö^º@¿[­*ÃOÔ/Lö¶±·—ök˜"†^Ò;«¦-nT6)Í®—8Ò¯ˆ­¢½ŠÞÞê]ZmRâãCŠ{U–Ò-RI,o-fûJ%´L÷°"Ú[ÜÆ‚öâFKÛº·¸¾€W¯·Q¿ø™ñßÁz†¡4SiOiñ6ûG‡VÓ’Ö"»M·6ó^®øe€_܉$»Âduà†.ƒûoöbÿ¢÷ÿ™¿Tÿåt 4Ÿˆ·×>2o x«Âú-Ô~ ¸‹[YðÕ΢ׂÇkˆXjóÑy BFHXfšÌZ9íáøßÿEáÿþwßü¹ çǽýê-Þôn÷  wûѿޢÝïFïz—½ýê-Þôn÷ ÓØóM›LøàImžÞÇR½‡ÄsÂÖ÷1ÙÜÜ­Þ4ûp’+iÏ+Ø-á(/¥d’]?xO:Òm;è;¿ Ãâ‰Âß`¸Ót+¨V;8¤‚K[Ô±¸º¶ƒìv¶²Ø3gÃg.‘%ŪÚCmÖÑAw5ÚÍ|Ñy‡ì–ú7ìûàI´Ù?²îîotë«Û›]b> òë:­©’î7Äþt1¥š!³,ŸfT˜˜R[Zð&o«^x8iúNŸp’Yiz‚ÛGo ÃP0Mcu&¢Ò=ê=Ö×Öï¦..5Hxâ¸YÚ˜®@*iQø›XÕu[˜Öàxšö–â[+ÝNÎïIŽñ­nôˆÿ}ln碌76—èƒQ,Ö‘$ÚYÊÒïá6Úh÷vìšl>n‘¥[Å$1X\G%ݵ¶ûKF1¦4šˆk[{aw“[ÞϦÏl‹dòÛêé^]gCÕl¬´[{­>ÚÒ­a¹ÑmH‚Yô›[vžÞWì³Ímq§–7zT¦Ê(õ(˜I ­S¨6£m£ýŒÜ‹ N3¥Câ}BèÏ.¨dƒû>ÔÀ%¹Ômg:L,÷»Ä« ü·6“‰ná€*w†ëPðV³iuq©é£Ä,ˆn^IÚ{!¨kÛ¨Ieló+C4h®o›Í[…¼ûO—¬sö²hú…Ÿ„l&¿Óïì5[ÝL“N{í5íÚÆâi¯,í­-ZD´ÓJ\hpynXæ1ÛåoeM_ ’çI»¹eaqÌÓ[¨–imàñ7‘wvöÖ‘Ü_êÍsg<¶÷ºL)ÊúãIˆ'¿•ìúÞx³ÃwŠ“Üêêqù–÷2[\_É¥êâi.m>Ûqj–þeÕΛpC{"ÍöË‹˜¸·ífYÖïÂZÝÒê6ú“ßêiªÊö†ÕaIolm/dTŽÖîæ(Ô½Ë0 Ê\8‘ÃH×—^Á^ðzD[?YÃý­m§kRéðß­õõØ•!†‚»gýì[<‰ŒRH<3Hå&’x£ô þd·Qº£ÝFê“uª=Ôn  7Qº£ÝFêývýƒ¤›[ýŸþAf×_YC}ÐÙGm2Æž#´žúA<—0O<)-AÅ­ÔÇ:\-Ô†jõ»àum?S¾]bÝôÕ†}}üDóhï?‘&Ÿ“k­Ý\ZÍhöÐI ê7bKgóžb©sm´XŸ8ýˆ4›íCö*ð¡·²¸‘%Ó.!´yâk˜[TþÜ»:|Ð..RÕ­¦ýì³½ŒŠ–Òeµtù7Úîvk?Ú!¶O^eéößg¼ºÓd´ûyºòndûLb[©RâÐùÓÚG½Äp/ÙfŒ¬ WþÔ4‰â}FþË¿Ñ÷Ãgfmo-ìã…µK(´ë[sh'6öÒ[éˆ&û<é JËqw`ë)Š:¶“Ãàûä×4»;+FÓ¡e²¸Õôé4]6 m6æîÖÒòHímžÎÆ¥$jgŠòÚÓö°ŽúB ¯øGKÑ4mBÛUƒO·ŽøwYñ%åƒ$WFk;vÔ¯®g½³»ÌQYXÛ”–âæh'‘EµËŠ6î´•ñ5ÍõõÕÂj ©ØI©Xé±ZÛµÕärÙ²I5º½‡PƒM½´ónXЬ6ÍÐ@÷@2¼-©XøÄ:F“mâ+{­?JšÂÜišv²³@¡..t%,‘¥­‹;5£L¼O5¥äv¶ž| ;äèº,Þ¹ÐíbÐííu[Hlì¬áÑ´ÈôÉï§‚8Úî×Ε4ár̾DÖ¯/ Å»OeöHc‘û_íùÚ„j 4v_Û-yo¤ë&—²§Óäž'H•íî£}´MæMi3¥fz5-"ãÁ~#ÕnÖïû:ÓJ²V‹Ä:¹šx¬lâÓ¤KIõ Ç–ÔÝ[A2êm%¬²ÝËæ^Cpe· о \èÖRø'ÆÞE{+/øškšUî½°âÎöÛ)¿¶‹GlêÜ—2$Ò³Êeó_[þÏÿôPþÿá}ÿËš©§ëÚïÃxÄgÂ_kÖú”6·­.>”.íØZÃn`Ô..õ@÷—h ®e)å y eÚßü.OÑ øÿÞÿå­;û¨ÝQîn&ê7T{……IºÕáFá@³ŸðOÏhz¿ìÁðÂËWÓôý[ûrËR·}>5HçšÖÝU'kàÓ¯ÛlGÛãˆAåH±Mtƒæ‹ßt[è|S&›Ö§£ø‚ûX‡FÕ‘ÒîM~Ò%7WwÑ”‚( † xíu& Ò¼P™Ék/ÿÁ<¦˜~Ç­ÿá$·Ð­ï&Ô¡Žk¾¸MR{ O!+´Áov$AHQ‹£Äb,~‰kÝvÒÚ)E‡Š/^ÒmRý¡ ¥½Xä‘-ìΠ,‹*IŒÝ>Ó*1u‰°ÑmõÛ8´ýÇìWðh×SišUÄ:HÒô™á[k-9ÜZǨiÑ\›t¹ýÔEážÊTóJÁo­©KyºÄº®É.,­n µÔ×Tðõ½ÄÒß3èÖæW‘– Kos…æ˜Ë’$C»ôú4Ö÷0i_fñDº=´ÖVí&§XÖÚ3r·­qç}®U’O.ÚU•ݤhÆèŒO,²J¶•%ž¯{¥ëu´ ŠÚ}JëP»Šêþè5Ä7Ñb ùfY$HQ¦T0À„¸)¬xrÇí0ÚOá»}`6™5™ðÞ¥¨)Öµ}>Ê;Ûv2É%槦öØ$7Œ‹¼i¦JÊ‹o[ð¤V:”—³ÜÿbnÖ®µýHipJn¯mÒÞÒþÐýšO2æ2-6›Ëg¤ ŒEæÚ·ðêÇáè<5w¤ÜKbÙ%ïƒôÛ+Y4Xlg·6/a³[B“ZDRK‡@DøUDrGnúÖÞÔn5]y㻸Òî'†ãO}~[&Ô®›Ï³{y“( ´7Wq$w033 Í‘¹î5|c4ZTºî™o¥êú¼ÇP½†+Hà˜3*¤IqåË*ÉÓ²´é¡þÊÓô}÷·sý›LmÑ?™q$žs-?{.ÿ6A´âIn“ÛZ€?˜=Ôn¦n£u?u©›¨Ý@ÝFêfê7Pî¯üL‡[ýƒ¼ §Ü=Äv÷pê°Hö—2[LªÚÚ’’ÆÊñ¶Œ¬§@5ô¦¥á›MWûWΛPOí;%°ŸìÚ•Ä#f.Eò%ýóæh¶ÈqXùi·ç_ø&aÏìCðßþâ_úrº¯¨('Rðͦ«ý«çM¨'ö’ØOömJâ ‘3 —"ùþùó4[d8,|´Ûn-2µ[A^àÜO P:5ÌXÚFR±ØŒL­¹ÕC0ˆÝ“ká›K;=Õ&Ô=oÙš]JâG“l-óݤ-sò¹'Î/— !˪°!ð¶—ØÌ–¿m’Êö}BÒmBFº–Úy|ÐïÊY£ùgš5 @HÜÆ¡S ZÔPM'I±Ð4«=3L³·Ó´Û(RÚÖÎÒ%Š"E ‘¢(UT ·EÿÙxli-2006-11-10/clip.c0000644000031400000060000001513107004736434013524 0ustar smarryconsole/* 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 "xli.h" #define ABS(x) ((x) < 0 ? -(x) : (x)) Image *clip(Image *iimage, int clipx, int clipy, unsigned int clipw, unsigned int cliph, ImageOptions *imgopp) { Image *simage = iimage, *dimage; int dclipx, dclipy; unsigned int dclipw, dcliph; unsigned int x, y; unsigned int slinelen, dlinelen; unsigned int start, dstart; byte startmask, smask; byte dstartmask, dmask; byte *sp, *sline, *dp, *dline; boolean border_shows = FALSE; Pixel border_pv = 0; if (globals.verbose) { printf(" Clipping image..."); fflush(stdout); } /* sane-ify clip area with respect to dimage */ dclipx = 0; dclipy = 0; dclipw = clipw; dcliph = cliph; if (clipx < 0) { dclipx = -clipx; clipx = 0; border_shows = TRUE; } if (clipy < 0) { dclipy = -clipy; clipy = 0; border_shows = TRUE; } if (clipx + dclipw > simage->width) { if (clipx > simage->width) dclipw = 0; else dclipw = simage->width - clipx; border_shows = TRUE; } if (dclipx + dclipw > clipw) { if (dclipx > clipw) dclipw = 0; else dclipw = clipw - dclipx; } if (clipy + dcliph > simage->height) { if (clipy > simage->height) dcliph = 0; else dcliph = simage->height - clipy; border_shows = TRUE; } if (dclipy + dcliph > cliph) { if (dclipy > cliph) dcliph = 0; else dcliph = cliph - dclipy; } if (globals.verbose) { if (border_shows) printf("(Adding border)"); printf("..."); fflush(stdout); } /* If the background is going to show after clipping * (ie. we are clipping the image to to make it larger * rather than smaller), then look up a suitable pixel * value to use as the background value. If we can't find * a close match, allocate a new color, or as a last * resort, convert the image to a true color image */ if (border_shows) { Intensity red,green,blue; if (imgopp->border) { red = imgopp->bordercol.red; green = imgopp->bordercol.green; blue = imgopp->bordercol.blue; } else { red = green = blue = 65535; /* default is white */ } /* Gamma correct the background colour to suit image */ red = (int)(0.5 + 65535 * pow( (double)red / 65535.0, 1.0/simage->gamma )); green = (int)(0.5 + 65535 * pow( (double)green / 65535.0, 1.0/simage->gamma )); blue = (int)(0.5 + 65535 * pow( (double)blue / 65535.0, 1.0/simage->gamma )); switch (simage->type) { case IBITMAP: case IRGB: for (border_pv= 0; border_pv < simage->rgb.used; border_pv++) { if (*(simage->rgb.red + border_pv) == red && *(simage->rgb.green + border_pv) == green && *(simage->rgb.blue + border_pv) == blue) break; } if (border_pv >= simage->rgb.used) { /* Failed to find exact color */ border_pv = simage->rgb.used; if (border_pv >= simage->rgb.size) { /* can't fit another */ compress_cmap(simage, FALSE); /* try compressing image */ border_pv = simage->rgb.used; } if (border_pv < simage->rgb.size) { /* can fit another */ *(simage->rgb.red + border_pv) = red; *(simage->rgb.green + border_pv) = green; *(simage->rgb.blue + border_pv) = blue; simage->rgb.used++; } else { /* else need more color space */ Image *tmp; if (simage->depth >= 16) { /* don't create irgb with depth > 16 */ tmp = expandtotrue(simage); border_pv = RGB_TO_TRUE(red,green,blue); } else { /* add more depth (copes with bitmap) */ tmp = expandirgbdepth(simage,simage->depth+1); *(tmp->rgb.red + border_pv) = red; *(tmp->rgb.green + border_pv) = green; *(tmp->rgb.blue + border_pv) = blue; tmp->rgb.used++; } /* free intemediate image, but preserve input */ if (simage != tmp && simage != iimage) freeImage(simage); simage = tmp; } } break; case ITRUE: border_pv = RGB_TO_TRUE(red,green,blue); break; default: printf("clip: Unsupported image type\n"); exit(1); } } switch (simage->type) { case IBITMAP: /* this could be sped up; i don't care */ dimage= newBitImage(clipw, cliph); for (x= 0; x < simage->rgb.used; x++) { *(dimage->rgb.red + x)= *(simage->rgb.red + x); *(dimage->rgb.green + x)= *(simage->rgb.green + x); *(dimage->rgb.blue + x)= *(simage->rgb.blue + x); } if (border_shows) fill(dimage, 0, 0, clipw, cliph, border_pv); slinelen= (simage->width / 8) + (simage->width % 8 ? 1 : 0); start= clipx / 8; startmask= 0x80 >> (clipx % 8); sline= simage->data + (slinelen * clipy); dlinelen= (clipw / 8) + (clipw % 8 ? 1 : 0); dstart= dclipx / 8; dstartmask= 0x80 >> (dclipx % 8); dline= dimage->data + (dlinelen * dclipy); for (y= 0; y < dcliph; y++) { sp= sline + start; dp= dline + dstart; smask= startmask; dmask= dstartmask; for (x= 0; x < dclipw; x++) { if (*sp & smask) *dp |= dmask; else *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)) { dimage= newRGBImage(clipw, cliph, simage->depth); for (x= 0; x < simage->rgb.used; x++) { *(dimage->rgb.red + x)= *(simage->rgb.red + x); *(dimage->rgb.green + x)= *(simage->rgb.green + x); *(dimage->rgb.blue + x)= *(simage->rgb.blue + x); } dimage->rgb.used= simage->rgb.used; } else dimage= newTrueImage(clipw, cliph); if (border_shows) fill(dimage, 0, 0, clipw, cliph, border_pv); slinelen= simage->width * simage->pixlen; start= clipx * simage->pixlen; sline= simage->data + (clipy * slinelen); dlinelen = simage->pixlen * clipw; dstart= dclipx * simage->pixlen; dline= dimage->data + (dclipy * dlinelen); for (y= 0; y < dcliph; y++) { sp= sline + start; dp= dline + dstart; bcopy(sp,dp,simage->pixlen * dclipw); sline += slinelen; dline += dlinelen; } break; default: printf("clip: Unsupported image type\n"); exit(1); } dimage->title= dupString(simage->title); dimage->gamma= simage->gamma; if (simage != iimage) /* free intemediate image, but preserver input */ freeImage(simage); if (globals.verbose) printf("done\n"); return(dimage); } xli-2006-11-10/cmuwmrast.c0000644000031400000060000000500410525262416014611 0ustar smarryconsole/* * 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 "xli.h" #include "cmuwmrast.h" #include "imagetypes.h" /* SUPPRESS 558 */ static void babble(char *name, struct cmuwm_header *headerp) { printf("%s is a %ldx%ld %ld plane CMU WM raster\n", name, memToVal(headerp->width, sizeof(long)), memToVal(headerp->height, sizeof(long)), memToVal(headerp->depth, sizeof(short))); } int cmuwmIdent(char *fullname, char *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 sizeof(struct cmuwm_header): if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC) { r = 0; break; } babble(name, &header); r = 1; break; case -1: perror("cmuwmIdent"); default: r = 0; break; } zclose(zf); return r; } Image *cmuwmLoad(char *fullname, ImageOptions * image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; struct cmuwm_header header; Image *image; int height, width, row, linelen, r; long depth; byte *lineptr; if (!(zf = zopen(fullname))) { perror("cmuwmLoad"); return (Image *) 0; } switch (zread(zf, (byte *) & header, sizeof(struct cmuwm_header))) { case sizeof(struct cmuwm_header): if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC) { zclose(zf); return (Image *) 0; } if (verbose) babble(name, &header); break; default: zclose(zf); return (Image *) 0; } depth = memToVal(header.depth, sizeof(short)); if (depth != 1) { fprintf(stderr, "cmuwmLoad: %s - raster is of depth %ld, must be 1\n", name, depth); return (Image *) 0; } image = newBitImage(width = memToVal(header.width, sizeof(long)), height = memToVal(header.height, sizeof(long))); image->title = dupString(name); linelen = (width / 8) + (width % 8 ? 1 : 0); lineptr = image->data; znocache(zf); for (row = 0; row < height; row++) { r = zread(zf, lineptr, linelen); if (r != linelen) { printf("cmuwmLoad: %s - short raster\n", name); zclose(zf); return image; } for (r = 0; r < linelen; r++) { lineptr[r] ^= 0xff; } lineptr += linelen; } read_trail_opt(image_ops, zf, image, verbose); zclose(zf); return image; } xli-2006-11-10/cmuwmrast.h0000644000031400000060000000061206461630121014612 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/cmuwmrast.h 1.4 93/07/23 Labtam" */ /* cmuwmrast.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 xli-2006-11-10/compress.c0000644000031400000060000001100310525262416014416 0ustar smarryconsole/* compress.c: * * compress an index colormap by removing unused or duplicate RGB * colors. This implementation uses two passes through the image, 1 to * figure out which index values are unused, and another to map the * pixel values to the new map. * * Graeme Gill 93/7/14 */ #include "xli.h" void compress_cmap(Image * image, unsigned int verbose) { unsigned char *used, fast[32][32][32]; unsigned int dmask; /* Depth mask protection */ Pixel *map; unsigned int next_index; Intensity *red = image->rgb.red, *green = image->rgb.green, *blue = image->rgb.blue; Intensity r, g, b; unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0; CURRFUNC("compress"); if (!RGBP(image) || image->rgb.compressed) return; if (verbose) { printf(" Compressing colormap..."); fflush(stdout); } used = (unsigned char *) lcalloc(sizeof(unsigned char) * depthToColors(image->depth)); dmask = (1 << image->depth) - 1; /* Mask any illegal bits for that depth */ map = (Pixel *) lcalloc(sizeof(Pixel) * depthToColors(image->depth)); /* init fast duplicate check table */ for (r = 0; r < 32; r++) for (g = 0; g < 32; g++) for (b = 0; b < 32; b++) fast[r][g][b] = 0; /* do pass 1 through the image to check index usage */ if (image->pixlen == 1) { /* most usual */ unsigned char *pixptr = image->data, *pixend; pixend = pixptr + (image->height * image->width); for (; pixptr < pixend; pixptr++) used[(*pixptr) & dmask] = 1; } else if (image->pixlen == 2) { unsigned char *pixptr = image->data, *pixend; pixend = pixptr + (2 * image->height * image->width); for (; pixptr < pixend; pixptr += 2) { register unsigned long temp; temp = (*pixptr << 8) | *(pixptr + 1); used[temp & dmask] = 1; } } else { /* general case */ byte *pixptr = image->data; for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { used[memToVal(pixptr, image->pixlen) & dmask] = 1; pixptr += image->pixlen; } } /* count the bad pixels */ for (x = image->rgb.used; x < depthToColors(image->depth); x++) if (used[x]) badcount++; /* figure out duplicates and unuseds, and create the new mapping */ next_index = 0; for (x = 0; x < image->rgb.used; x++) { if (!used[x]) { unusedcount++; continue; /* delete this index */ } /* check for duplicate */ r = red[x]; g = green[x]; b = blue[x]; if (fast[r >> 11][g >> 11][b >> 11]) { /* if matches fast check */ /* then do a linear search */ for (y = x + 1; y < image->rgb.used; y++) { if (r == red[y] && g == green[y] && b == blue[y]) break; } if (y < image->rgb.used) { /* found match */ map[x] = y; dupcount++; continue; /* delete this index */ } fast[r >> 11][g >> 11][b >> 11] = 1; } /* will map to this index */ map[x] = next_index; next_index++; } /* change the image pixels */ if (image->pixlen == 1) { /* most usual */ unsigned char *pixptr = image->data, *pixend; pixend = pixptr + (image->height * image->width); for (; pixptr < pixend; pixptr++) *pixptr = map[(*pixptr) & dmask]; } else if (image->pixlen == 2) { unsigned char *pixptr = image->data, *pixend; pixend = pixptr + (2 * image->height * image->width); for (; pixptr < pixend; pixptr += 2) { register unsigned long temp; temp = (*pixptr << 8) | *(pixptr + 1); temp = map[temp & dmask]; *pixptr = temp >> 8; *(pixptr + 1) = temp; } } else { /* general case */ byte *pixptr = image->data; for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { register unsigned long temp; temp = memToVal(pixptr, image->pixlen) & dmask; temp = map[temp]; valToMem(temp, pixptr, image->pixlen); pixptr += image->pixlen; } } /* change the colormap */ for (x = 0; x < image->rgb.used; x++) { if (!used[x]) continue; red[map[x]] = red[x]; green[map[x]] = green[x]; blue[map[x]] = blue[x]; } image->rgb.used = next_index; /* clean up */ lfree((byte *) map); lfree(used); 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 (!unusedcount && !dupcount) printf("no improvment\n"); else { if (dupcount) printf("%d duplicate%s and %d unused color%s removed...", dupcount, (dupcount == 1 ? "" : "s"), unusedcount, (unusedcount == 1 ? "" : "s")); printf("%d unique color%s\n", next_index, (next_index == 1 ? "" : "s")); } } image->rgb.compressed = TRUE; /* don't do it again */ } xli-2006-11-10/copyright.h0000644000031400000060000000227706461630121014611 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/copyright.h 6.7 93/07/23 Labtam" */ #ifndef _JIM_COPYRIGHT_ /* * Copyright 1989, 1990, 1991 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, 1990, 1991 Jim Frost"; #endif #define _JIM_COPYRIGHT_ #endif xli-2006-11-10/ddxli.c0000644000031400000060000001202507004736435013701 0ustar smarryconsole/* * General Device dependent code for xli. * * Author; Graeme W. Gill */ #include "xli.h" #include static int saParseXColor(DisplayInfo *dinfo, char *spec, XColor *xcolor); /* Initialise a display info structure to default values */ void xliDefaultDispinfo(DisplayInfo *dinfo) { dinfo->width = 0; dinfo->height = 0; dinfo->disp = NULL; dinfo->scrn = 0; dinfo->colormap = 0; } /* open up a display and screen, and stick the info away */ /* Return FALSE on failure */ boolean xliOpenDisplay(DisplayInfo *dinfo, char *name) { Display *disp; int scrn; if (!(disp = XOpenDisplay(globals.dname))) return FALSE; /* failed */ scrn = DefaultScreen(disp); dinfo->disp = disp; dinfo->scrn = scrn; dinfo->colormap = DefaultColormap(disp, scrn); dinfo->width = DisplayWidth(disp, scrn); dinfo->height = DisplayHeight(disp, scrn); XSetErrorHandler(errorHandler); return TRUE; } /* report display name when connection fails */ char *xliDisplayName(char *name) { return XDisplayName(name); } void xliCloseDisplay(DisplayInfo *dinfo) { XCloseDisplay(dinfo->disp); } /* simple X11 error handler. this provides us with some kind of error recovery. */ int errorHandler(Display * disp, XErrorEvent * error) { char errortext[BUFSIZ]; XGetErrorText(disp, error->error_code, errortext, BUFSIZ); fprintf(stderr, "xli: X Error: %s on 0x%lx\n", errortext, error->resourceid); if (globals._Xdebug) abort(); else return (0); } /* Return the default visual class */ int xliDefaultVisual(void) { return (DefaultVisual(globals.dinfo.disp, globals.dinfo.scrn)->class); } /* return the default depth of the default visual */ int xliDefaultDepth(void) { return DefaultDepth(globals.dinfo.disp, globals.dinfo.scrn); } /* Print some information about the display */ void tellAboutDisplay(DisplayInfo * dinfo) { Screen *screen; int a, b; if (dinfo->disp) { screen = ScreenOfDisplay(dinfo->disp, dinfo->scrn); printf("Server: %s Version %d\n", ServerVendor(dinfo->disp), VendorRelease(dinfo->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"); } } /* A standalone color name to RGB lookup routine */ typedef struct { char *name; unsigned char red; unsigned char green; unsigned char blue; } xliXColorTableEntry; #include "rgbtab.h" /* Equivalent of an X color table */ /* parse an X like color. */ int xliParseXColor(DisplayInfo *dinfo, char *spec, XColor *xcolor) { int stat; if (dinfo->disp) { stat = XParseColor(globals.dinfo.disp, globals.dinfo.colormap, spec, xcolor); } else { stat = saParseXColor(dinfo, spec, xcolor); } return stat; } static int saParseXColor(DisplayInfo *dinfo, char *spec, XColor *xcolor) { int i, n, r, g, b; xliXColorTableEntry *tp; xcolor->red = 0; xcolor->green = 0; xcolor->blue = 0; n = strlen(spec); if (n > 0) { for (i = 0; i < n; i++) { if (isupper(spec[i])) spec[i] = tolower(spec[i]); } if (spec[0] == '#') { switch (n - 1) { case 3: r = hstoi(spec + 1, 1); g = hstoi(spec + 2, 1); b = hstoi(spec + 3, 1); if (r >= 0 && g >= 0 && b >= 0) { xcolor->red = r * 0x1111; xcolor->green = g * 0x1111; xcolor->blue = b * 0x1111; return 1; } break; case 6: r = hstoi(spec + 1, 2); g = hstoi(spec + 3, 2); b = hstoi(spec + 5, 2); if (r >= 0 && g >= 0 && b >= 0) { xcolor->red = r * 0x101; xcolor->green = g * 0x101; xcolor->blue = b * 0x101; return 1; } break; case 9: r = hstoi(spec + 1, 3); g = hstoi(spec + 4, 3); b = hstoi(spec + 7, 3); if (r >= 0 && g >= 0 && b >= 0) { xcolor->red = (r * 65535) / 4095; xcolor->green = (g * 65535) / 4095; xcolor->blue = (b * 65535) / 4095; return 1; } break; case 12: r = hstoi(spec + 1, 4); g = hstoi(spec + 5, 4); b = hstoi(spec + 9, 4); if (r >= 0 && g >= 0 && b >= 0) { xcolor->red = r; xcolor->green = g; xcolor->blue = b; return 1; } break; } } else { /* else its a color name. Do a linear search for it (binary search would be better) */ for (n = 0, tp = &xliXColorTable[0]; tp->name[0]; tp++) { if (strcmp(spec, tp->name) == 0) { xcolor->red = tp->red * 0x101; xcolor->green = tp->green * 0x101; xcolor->blue = tp->blue * 0x101; return 1; } } } } /* default - return black */ xcolor->red = 0; xcolor->green = 0; xcolor->blue = 0; return 0; } /* gamma correct an XColor */ void xliGammaCorrectXColor(XColor * xlicolor, double gamma) { xlicolor->red = (int) (0.5 + 65535.0 * pow((double) xlicolor->red / 65535.0, gamma)); xlicolor->green = (int) (0.5 + 65535.0 * pow((double) xlicolor->green / 65535.0, gamma)); xlicolor->blue = (int) (0.5 + 65535.0 * pow((double) xlicolor->blue / 65535.0, gamma)); } xli-2006-11-10/ddxli.h0000644000031400000060000000521607004736435013712 0ustar smarryconsole/* * General Device dependent code for xli. * * Author; Graeme W. Gill */ /* OS dependent stuff */ #include #include #include #include #include #include #include #include #if defined(SYSV) || defined(VMS) #include #ifndef index /* some SysV's do this for you */ #define index strchr #endif #ifndef rindex #define rindex strrchr #endif #ifndef HAS_MEMCPY #define HAS_MEMCPY #endif #else /* !SYSV && !VMS */ #include #endif /* !SYSV && !VMS */ #ifdef VMS #define R_OK 4 #define NO_UNCOMPRESS #endif /* equate bcopy with memcpy and bzero with memset where appropriate. */ #ifdef HAS_MEMCPY #ifndef bcopy #define bcopy(S,D,N) memcpy((char *)(D),(char *)(S),(N)) #endif #ifndef bzero #define bzero(P,N) memset((P),'\0',(N)) #endif #ifndef bfill #define bfill(P,N,C) memset((P),(C),(N)) #endif #else /* !HAS_MEMCPY */ void bfill(char *s, int n, int c); #endif /* !HAS_MEMCPY */ /* xli specific data types */ /* If signed char is a legal declaration * else assume char is signed by default */ #define HAS_SIGNED_CHAR 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; /* unsigned byte type */ /* signed byte type */ #ifdef HAS_SIGNED_CHAR typedef signed char sbyte; #else typedef char sbyte; #endif #ifndef HAVE_BOOLEAN #define HAVE_BOOLEAN typedef int boolean; #endif #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif /* Display device dependent Information structure */ typedef struct { int width; int height; Display *disp; int scrn; Colormap colormap; } DisplayInfo; /* 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 *index; /* array of pixel values allocated */ int no; /* number of pixels in the array */ boolean rootimage; /* True if is a root image - eg, retain colors */ 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 */ XShmSegmentInfo shm; /* valid if shm.shmid >= 0 */ } XImageInfo; /* ddxli.c */ char *xliDisplayName(char *name); int xliParseXColor(DisplayInfo *dinfo, char *spec, XColor *xlicolor); int xliDefaultVisual(void); void xliGammaCorrectXColor(XColor *xlicolor, double gamma); xli-2006-11-10/dither.c0000644000031400000060000001471307004736436014063 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/dither.c 6.13 94/07/29 Labtam" */ /* dither.c * * completely reworked dithering module for xli * 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 * Graeme Gill 16/10/92 - remove tone_scale_adjust() stuff - * gamma adjustment is better. Clean up values so * that dithering mono images doesn't change them! * * 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 "xli.h" #define MaxGrey 65280 /* limits on the grey levels used */ #define Threshold (MaxGrey/2) /* in the dithering process */ #define MinGrey 0 static void LeftToRight(int *curr, int *next, int width); static void RightToLeft(int *curr, int *next, int width); /* * simple floyd-steinberg dither with serpentine raster processing */ Image *dither(Image *cimage, unsigned int verbose) { Image *image; /* destination image */ 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 */ int level; /* grey level */ unsigned int i, j; /* loop counters */ CURRFUNC("dither"); /* * check the source image */ if (BITMAPP(cimage)) return(NULL); if(GAMMA_NOT_EQUAL(cimage->gamma, 1.0)) gammacorrect(cimage, 1.0, verbose); /* * 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); } image->gamma= cimage->gamma; /* * 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 = (int *)lmalloc(sizeof(int) * cimage->rgb.used); for (i=0; irgb.used; i++) grey[i]= ((int)colorIntensity(cimage->rgb.red[i], cimage->rgb.green[i], cimage->rgb.blue[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; bzero ((char *)curr, cimage->width * sizeof(*curr)); bzero ((char *)next, cimage->width * sizeof(*next)); /* * 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 = (int)colorIntensity(cimage->rgb.red[color], cimage->rgb.green[color], cimage->rgb.blue[color]); else level = (int)grey[color]; } else { level = (int)colorIntensity((TRUE_RED(color) << 8), (TRUE_GREEN(color) << 8), (TRUE_BLUE(color) << 8)); } 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; bzero ((char *)next, cimage->width * sizeof(*next)); } /* * clean up */ if (grey != NULL) lfree((byte *)grey); lfree((byte *)(curr-1)); lfree((byte *)(next-1)); if (verbose) printf("done\n"); return(image); } /* * dither a line from left to right */ static void LeftToRight(int *curr, int *next, int width) { int idx; int error; int output; if (0 < width) { output = (curr[0] > Threshold) ? MaxGrey : MinGrey; error = curr[0] - output; curr[0] = output; next[0] += error * 5 / 16; if (width > 1) { next[1] += error * 1 / 16; curr[1] += error * 7 / 16; } } for (idx=1; idx<(width-1); 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; } idx = width -1; if (idx > 0) { output = (curr[idx] > Threshold) ? MaxGrey : MinGrey; error = curr[idx] - output; curr[idx] = output; next[idx-1] += error * 3 / 16; next[idx] += error * 5 / 16; } } /* * dither a line from right to left */ static void RightToLeft(int *curr, int *next, int width) { int idx; int error; int output; idx = width -1; if (idx >= 0) { output = (curr[idx] > Threshold) ? MaxGrey : MinGrey; error = curr[idx] - output; curr[idx] = output; next[idx] += error * 5 / 16; if (idx > 0) { next[idx-1] += error * 1 / 16; curr[idx-1] += error * 7 / 16; } } for (idx=(width-2); idx>=1; 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; } if (0 < width) { output = (curr[0] > Threshold) ? MaxGrey : MinGrey; error = curr[0] - output; curr[0] = output; next[0] += error * 5 / 16; } } xli-2006-11-10/faces.c0000644000031400000060000001015610525262416013654 0ustar smarryconsole/* 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 "xli.h" #include "imagetypes.h" #include /* read a hex value and return its value */ static int nextInt(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= LEHexTable[c & 0xff]; switch(c) { case HEXDELIM_IGNORE: /* ignore */ break; case HEXBAD: /* bad */ case HEXSTART_BAD: case HEXDELIM_BAD: return(-1); default: value= (value << 4) + c; count++; } } } return(value); } static boolean isFaces(ZFILE *zf, char *name, char *fname, char *lname, unsigned int *wp, unsigned int *hp, unsigned int *dp) { char buf[BUFSIZ]; unsigned int w, h, d, iw, ih, id; 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) { fprintf(stderr,"facesLoad: %s - Bad image\n", name); return(FALSE); } } else if (!strncmp(buf, "PicData:", 8)) { if (sscanf(buf + 9, "%d%d%d", &w, &h, &d) != 3) { fprintf(stderr,"facesLoad: %s - Bad image\n", name); return(FALSE); } } } if (!w || !h || !d) return FALSE; *wp = w; *hp = h; *dp = d; return TRUE; } Image *facesLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; Image *image; char fname[BUFSIZ]; char lname[BUFSIZ]; unsigned int w, h, d; unsigned int x, y; int value; unsigned int linelen; byte *lineptr, *dataptr; int nn, nd; if (! (zf= zopen(fullname))) { perror("facesLoad"); return(NULL); } { unsigned int tw, th, td; if (!isFaces(zf, name, fname, lname, &tw, &th, &td)) { zclose(zf); return NULL; } w = tw; h = th; d = td; } if (verbose) printf("%s is a %dx%d %d-bit grayscale Faces Project image\n", name, w, h, d); initLEHexTable(); znocache(zf); image= newRGBImage(w, h, d); if ((!*fname && !*lname) || ('\n' == *fname && '\n' == *lname)) { image->title = dupString(name); } else { if (*fname) { fname[strlen(fname) - 1] = ' '; } if (*lname) { lname[strlen(lname) - 1] = '\0'; } strncat(fname, lname, sizeof(fname) - strlen(fname) - 1); fname[sizeof(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); nd = 8 - d; w = w / (8 / d); for (y= 0; y < h; y++) { lineptr -= linelen; dataptr= lineptr; for (x= 0; x < w; x++) { if ((value= nextInt(zf, image->pixlen)) < 0) { fprintf(stderr,"facesLoad: %s - Bad image data (returning partial image)\n", fullname); zclose(zf); return(image); } for (nn = 0; nn < 8; nn += d) *(dataptr++)= ((value>>(nd-nn)) & (0xff >> nd)); } } read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } int facesIdent(char *fullname, char *name) { ZFILE *zf; char fname[BUFSIZ]; char lname[BUFSIZ]; unsigned int w, h, d; if (! (zf= zopen(fullname))) { perror("facesIdent"); return(FALSE); } if (!isFaces(zf, name, fname, lname, &w, &h, &d)) { zclose(zf); return(FALSE); } printf("%s is a %dx%d %d-bit grayscale Faces Project image\n", name, w, h, d); zclose(zf); return(TRUE); } xli-2006-11-10/fbm.c0000644000031400000060000002464610525262416013350 0ustar smarryconsole/* * 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 "xli.h" # include # include #define FBM_C # include "fbm.h" # include "imagetypes.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; /* Depth (1 for B+W, 3 for RGB) */ static int fbmin_img_bits; /* Bits per pixel */ 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 double 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 int fbmin_image_test(void); static char * get_err_string(int errno) { int i; for (i=0;fbm_err_strings[i].err_no != 0;i++) { if (fbm_err_strings[i].err_no == errno) return fbm_err_strings[i].name; } return ""; } /* * open FBM image in the input stream; returns FBMIN_SUCCESS if * successful. (might also return various FBMIN_ERR codes.) */ static int fbmin_open_image(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_BAD_SIG; /* can't be FBM file */ 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 = atof(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(void) { /* 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; } static int fbmin_image_test(void) { 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_plnlen < (fbmin_img_height * fbmin_img_rowlen)) { fprintf (stderr, "Invalid plane length (%d) < (%d) * (%d) on input\n", fbmin_img_plnlen,fbmin_img_height,fbmin_img_rowlen); return FBMIN_ERR_BAD_SD; } if (fbmin_img_aspect < 0.01 || fbmin_img_aspect > 100.0) { fprintf (stderr, "Invalid aspect ratio %g on input\n", fbmin_img_aspect); return FBMIN_ERR_BAD_SD; } return FBMIN_SUCCESS; } /* * these are the routines added for interfacing to xli */ /* * tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(char *name) { printf("%s is a %dx%d FBM image, depth %d with %d colors\n", name, fbmin_img_width, fbmin_img_height, fbmin_img_bits * fbmin_img_depth, fbmin_img_clrlen / 3); } Image *fbmLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; Image *image; register int x, y, j, k, width, rowpad, plnpad; unsigned char *pixptr, *cm; unsigned char *r, *g, *b; int retv; CURRFUNC("fbmLoad"); if (! (zf= zopen(fullname))) return(NULL); if ((retv = fbmin_open_image(zf)) != FBMIN_SUCCESS) { /* read image header */ fbmin_close_file(); zclose(zf); if(retv != FBMIN_ERR_BAD_SIG) fprintf (stderr, "fbmLoad: %s - aborting, '%s'\n",name, get_err_string(retv)); return(NULL); } if (verbose) tellAboutImage(name); znocache(zf); if(fbmin_img_depth==1) if(fbmin_img_bits==1) image= newBitImage(fbmin_img_width, fbmin_img_height); else image = newRGBImage(fbmin_img_width, fbmin_img_height, fbmin_img_bits); else /* must be 3 */ image = newTrueImage(fbmin_img_width, fbmin_img_height); image->title= dupString(name); /* if image has a local colormap, override global colormap */ if (fbmin_img_depth==1 && fbmin_img_clrlen > 0) { cm = (unsigned char *) lmalloc(fbmin_img_clrlen); if (zread(ins, cm, fbmin_img_clrlen) != fbmin_img_clrlen) { fprintf (stderr, "fbmLoad: %s - can't read colormap (%d bytes)\n", name, fbmin_img_clrlen); fbmin_close_file(); lfree(cm); zclose(zf); freeImage(image); 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 cm = NULL; width = fbmin_img_width; rowpad = fbmin_img_rowlen - width; plnpad = fbmin_img_plnlen - (fbmin_img_height * fbmin_img_rowlen); if(fbmin_img_depth == 1) { if(fbmin_img_bits==1) { int xx,bb; byte *rb; rb = (byte *) lmalloc(width > rowpad ? width : rowpad); pixptr = image->data; for (j = 0; j < fbmin_img_height; j++, pixptr += ((width+7)/8)) { if (zread(ins, rb, width) != width) { fprintf(stderr, "fbmLoad: %s - Short read within image data\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } for (xx = 0,bb=0; xx < width; xx++) { bb = (bb << 1) | (rb[xx] ? 0 : 1); if ((xx & 7) == 7) { pixptr[xx/8] = bb; bb = 0; } } if (zread(ins, rb, rowpad) != rowpad) { fprintf(stderr, "fbmLoad: %s - Short read within row padding\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } } lfree(rb); } else { byte *rb; rb = (byte *) lmalloc(rowpad); pixptr = image->data; for (j = 0; j < fbmin_img_height; j++, pixptr += width) { if (zread(ins, pixptr, width) != width) { fprintf(stderr, "fbmLoad: %s - Short read within image data\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } if (zread(ins, rb, rowpad) != rowpad) { fprintf(stderr,"fbmLoad: %s - Short read within row padding\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } } lfree(rb); } } else { /* depth == 3 case */ int xx; byte *rb; rb = (byte *) lmalloc(width > rowpad ? (width > plnpad ? width : plnpad) :(rowpad > plnpad ? rowpad : plnpad)); for (k = 0; k < fbmin_img_depth; k++) { pixptr = image->data + k; for (j = 0; j < fbmin_img_height; j++) { if (zread(ins, rb, width) != width) { fprintf(stderr, "fbmLoad: %s - Short read within image data\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } for (xx = 0; xx < width; xx++,pixptr+=3) { *pixptr = rb[xx]; } if (zread(ins, rb, rowpad) != rowpad) { fprintf(stderr,"fbmLoad: %s - Short read within row padding\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } } if (zread(ins, rb, plnpad) != plnpad) { fprintf(stderr,"fbmLoad: %s - Short read within plane padding\n", name); if (cm != NULL) lfree(cm); lfree(rb); fbmin_close_file(); zclose(zf); return(image); } } lfree(rb); } if (cm != NULL) lfree(cm); fbmin_close_file(); read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } int fbmIdent(char *fullname, char *name) { ZFILE *zf; unsigned int ret; int retv; if (! (zf= zopen(fullname))) return(0); if ((retv = fbmin_open_image(zf)) == FBMIN_SUCCESS) { tellAboutImage(name); ret = 1; } else { if (retv != FBMIN_ERR_BAD_SIG) { fprintf (stderr, "FBM file error\n"); ret = 1; /* file was identified as FBM */ } else { ret = 0; } } fbmin_close_file(); zclose(zf); return(ret); } xli-2006-11-10/fbm.h0000644000031400000060000000572506461630121013346 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/fbm.h 1.6 94/07/29 Labtam" */ /***************************************************************** * This file is based on fbm.h by Michael Mauldin * The original file had the following copyright: * * Copyright (C) 1989,1990 by Michael Mauldin. Permission is granted * to use this file in whole or in part for any purpose, educational, * recreational or commercial, provided that this copyright notice * is retained unchanged. This software is available to all free of * charge by anonymous FTP and in the UUNET archives. * * 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 FBMIN_ERR_BAD_SD_STR "Bad screen descriptor" #define FBMIN_ERR_BAD_SIG_STR "Bad signature" #define FBMIN_ERR_EOD_STR "Unexpected end of raster data" #define FBMIN_ERR_EOF_STR "Unexpected end of input stream" #define FBMIN_ERR_FAO_STR "File already open" #define FBMIN_ERR_IAO_STR "Image already open" #define FBMIN_ERR_NFO_STR "No file open" #define FBMIN_ERR_NIO_STR "No image open" typedef struct { int err_no; char *name; } fbm_err_string; #ifdef FBM_C fbm_err_string fbm_err_strings[] = { {FBMIN_ERR_BAD_SD, FBMIN_ERR_BAD_SD_STR}, {FBMIN_ERR_BAD_SIG, FBMIN_ERR_BAD_SIG_STR}, {FBMIN_ERR_EOD, FBMIN_ERR_EOD_STR}, {FBMIN_ERR_EOF, FBMIN_ERR_EOF_STR}, {FBMIN_ERR_FAO, FBMIN_ERR_FAO_STR}, {FBMIN_ERR_IAO, FBMIN_ERR_IAO_STR}, {FBMIN_ERR_NFO, FBMIN_ERR_NFO_STR}, {FBMIN_ERR_NIO, FBMIN_ERR_NIO_STR}, {0} }; #endif # 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; xli-2006-11-10/fill.c0000644000031400000060000000315207004736437013526 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/fill.c 6.8 93/07/23 Labtam" */ /* 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 "xli.h" void fill(Image *image, unsigned int fx, unsigned int fy, unsigned int fw, unsigned int fh, Pixel pixval) { unsigned int x, y; unsigned int linelen, start; byte *lineptr, *pixptr; byte startmask, mask; 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); startmask= 0x80 >> (fx % 8); for (y= 0; y < fh; y++) { mask= startmask; pixptr= lineptr + start; if (pixval) for (x= 0; x < fw; x++) { *pixptr |= mask; mask >>= 1; if (mask == 0) { mask= 0x80; pixptr++; } } else for (x= 0; x < fw; x++) { *pixptr &= ~mask; mask >>= 1; if (mask == 0) { 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= 0; y < fh; y++) { pixptr= lineptr + start; for (x= 0; x < fw; x++) { valToMem(pixval, pixptr, image->pixlen); pixptr += image->pixlen; } lineptr += linelen; } break; default: printf("fill: Unsupported image type (ignored)\n"); return; } } xli-2006-11-10/g3.c0000644000031400000060000002505010525262416013103 0ustar smarryconsole/** g3.c - read a Group 3 FAX file and product a bitmap ** ** Adapted from Paul Haeberli's G3 to Portable Bitmap ** code. ** ** modified by jimf on 09.18.90 to fail on any load error. this was done ** to cut down on the false positives caused by a lack of any read ID ** string. the old errors are currently ifdef'ed out -- if you want 'em ** define ALLOW_G3_ERRORS. **/ /* Edit History 04/15/91 8 nazgul Sanity check line widths Doing a zclose on all failures 04/14/91 1 schulert add for SYSV systems 04/13/91 6 nazgul Handle reinvocation on the same file 04/13/91 5 nazgul Bug fix to retry with bitreversed, and do not double allocate on multiple calls 04/12/91 4 nazgul Spot faxes that do not have a 000 header Handle faxes that have the bytes in the wrong order 07/03/90 2 nazgul Added recovery for premature EOF */ #include "xli.h" #include #include #include "g3.h" #include "imagetypes.h" /**** ** ** Local defines ** ****/ #define BITS_TO_BYTES(bits) (((bits)+7)/8) /* Bytes to contain bits */ #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry)) #ifdef VMS #define cols vmscols #endif /**** ** ** Local variables ** ****/ static int g3_eof = 0; static int g3_eols; static int g3_rawzeros; static int g3_Xrawzeros; static int maxlinelen; static int rows, cols; static char *g3_error = NULL; static int g3_verb; static int curbit; static int firstTime = 1; #define MAX_ERRORS 20 /**** ** ** Local tables ** ****/ tableentry *whash[HASHSIZE]; tableentry *bhash[HASHSIZE]; static int g3_skiptoeol(ZFILE *fd); static int g3_rawgetbit(ZFILE *fd); static int g3_addtohash(tableentry **hash, tableentry *te, int n, int a, int b) { unsigned int pos; while (n--) { pos = ((te->length+a)*(te->code+b))%HASHSIZE; if (hash[pos] != 0) { g3_error = "G3: Hash collision during initialization."; return(-1); } hash[pos] = te; te++; } return 0; } static int g3_bitson(bit *b, int c, int n) { int i, col; bit *bP; static int bitmask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; bP = b; col = c; bP+=(c/8); i = (c - ((c/8)*8)); while(col <= (c+n)) { for(;col <= (c+n) && i < 8; i++) { *bP |= bitmask[i]; col++; } i = 0; bP++; } return(0); } static tableentry *g3_hashfind(tableentry **hash, int length, int code, int a, int b) { unsigned int pos; tableentry *te; pos = ((length+a)*(code+b))%HASHSIZE; if (pos >= HASHSIZE) { g3_error = "G3: Bad hash position"; return(NULL); } te = hash[pos]; return ((te && te->length == length && te->code == code) ? te : 0); } static int g3_getfaxrow(ZFILE *fd, byte *bitrow) { int col; int curlen, curcode, nextbit; int count, color; tableentry *te; /* First make the whole row white... */ bzero((char *) bitrow, maxlinelen); /* was memset -- jimf 09.11.90 */ col = 0; g3_rawzeros = 0; curlen = 0; curcode = 0; color = 1; count = 0; while (!g3_eof) { if (col >= MAXCOLS) { g3_error = "G3: Input row is too long, skipping to EOL"; g3_skiptoeol(fd); return (col); } do { if (g3_eof) return 0; if (g3_rawzeros >= 11) { nextbit = g3_rawgetbit(fd); if (nextbit==1) { if ( col == 0 ) /* 6 consecutive EOLs mean end of document */ g3_eof = (++g3_eols >= 5); else g3_eols = 0; return (col); } } else nextbit = g3_rawgetbit(fd); curcode = (curcode<<1) + nextbit; curlen++; } while (curcode <= 0); /* No codewords are greater than 13 bytes */ if (curlen > 13) { g3_error = "G3: Bad code word, skipping to EOL"; g3_skiptoeol(fd); return (col); } if (color) { /* White codewords are at least 4 bits long */ if (curlen < 4) continue; te = g3_hashfind(whash, curlen, curcode, WHASHA, WHASHB); } else { /* Black codewords are at least 2 bits long */ if (curlen < 2) continue; te = g3_hashfind(bhash, curlen, curcode, BHASHA, BHASHB); } if (!te) continue; switch (te->tabid) { case TWTABLE: case TBTABLE: count += te->count; if (col+count > MAXCOLS) count = MAXCOLS-col; if (count > 0) { if (color) { col += count; count = 0; } else g3_bitson(bitrow, col, count); } curcode = 0; curlen = 0; color = !color; break; case MWTABLE: case MBTABLE: count += te->count; curcode = 0; curlen = 0; break; case EXTABLE: count += te->count; curcode = 0; curlen = 0; break; default: g3_error = "G3: Bad table id from table entry"; return(-1); } } return (0); } static int g3_skiptoeol(ZFILE *fd) { int maxbits = 2 * MAXCOLS; while (g3_rawzeros<11 && !g3_eof && maxbits--) (void) g3_rawgetbit(fd); if(maxbits) { maxbits = MAXCOLS/2; while(!g3_rawgetbit(fd) && !g3_eof && maxbits--); } if (!maxbits) g3_error = "G3: unable to skip to eol"; return(0); } static int g3_rawgetbit(ZFILE *fd) { int b; static int shdata; if (curbit >= 8) { shdata = zgetc(fd); if (shdata == EOF) { g3_eols = 5; g3_eof = 1; g3_error = "G3: Premature EOF"; return(0); } curbit = 0; } if (shdata & bmask[curbit]) { g3_Xrawzeros = g3_rawzeros; g3_rawzeros = 0; b = 1; } else { g3_rawzeros++; b = 0; } curbit++; return b; } /* All G3 images begin with a G3 EOL codeword which is eleven binary 0's * followed by one binary 1. There could be up to 15 0' so that the image * starts on a char boundary. */ /* * They are all *supposed* to, but in fact some don't. In fact pbmtog3 doesn't seem * to generate them. So if that fails, we'll also try reading a line and seeing if * we get any errors. Note that this means we had to move the call to g3_ident * to after the hash table init. -nazgul */ /* Return TRUE if g3 image */ static boolean g3_ident(ZFILE *fd) { int ret = FALSE, col1, col2, col3, i; byte *tmpline = NULL; int reverse = 0; g3_verb = 0; col1 = col2 = col3 = 0; tmpline = (byte *) lmalloc(maxlinelen); /* In case this got reset by a previous pass through here */ for (i = 0; i < 8; ++i) { bmask[7-i] = 1 << i; } tryagain: if (!zrewind(fd)) { lfree(tmpline); return FALSE; } curbit = 8; g3_Xrawzeros = g3_rawzeros = 0; g3_error = NULL; g3_eof = g3_eols = rows = cols = 0; /* If we have the zeros we're off to a good start, otherwise, * skip some lines */ for (g3_rawzeros = 0; !g3_eof && !g3_rawgetbit(fd) && g3_rawzeros < 16;); if (g3_eof || g3_Xrawzeros < 11 || g3_Xrawzeros > 15) { if (g3_eof || !zrewind(fd)) { lfree(tmpline); return FALSE; } curbit = 8; g3_Xrawzeros = g3_rawzeros = 0; g3_error = NULL; g3_eof = g3_eols = rows = cols = 0; g3_skiptoeol(fd); if (!g3_error) g3_skiptoeol(fd); if (!g3_error) g3_skiptoeol(fd); if (!g3_error) g3_skiptoeol(fd); } /* Now get three lines and make sure they are the same length. If not * give up. Note that it is possible for this to give false positives * (value.o on a Sun IPC did) but it's unlikely enough that I think * we're okay. */ if (!g3_error) col1 = g3_getfaxrow(fd, tmpline); if (col1 > 0 && !g3_error) col2 = g3_getfaxrow(fd, tmpline); if (col1 > 0 && !g3_error) col3 = g3_getfaxrow(fd, tmpline); if (!g3_error && col1 > 0 && col1 == col2 && col2 == col3) ret = TRUE; else ret = FALSE; /* if (ret) printf("%d = %d\n", col1, col2); */ /* This bogus hack is to accomodate some fax modems which apparently * use a chip with a different byte order. We simply try again with * the table reversed. */ if (!ret && !reverse) { for (i = 0; i < 8; ++i) { bmask[i] = 1 << i; } reverse = 1; goto tryagain; } lfree(tmpline); /* Reset file so we don't loose lines */ if (!zrewind(fd)) { return FALSE; } curbit = 8; g3_Xrawzeros = g3_rawzeros = 0; g3_error = NULL; g3_eof = g3_eols = rows = cols = 0; return(ret); } Image *g3Load(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *fd; char *name = image_ops->name; Image *image; int i, col; byte *currline; if ((fd = zopen(fullname)) == NULL) { perror("g3Load"); return(NULL); } if (firstTime) { firstTime = 0; /* Initialize and load the hash tables */ for ( i = 0; i < HASHSIZE; ++i ) whash[i] = bhash[i] = (tableentry *) 0; g3_addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB); g3_addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB); g3_addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB); g3_addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB); g3_addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB); g3_addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB); } /* Calulate the number of bytes needed for maximum number of columns * (bits), create a temprary storage area for it. */ maxlinelen = BITS_TO_BYTES(MAXCOLS); if (!g3_ident(fd)) { zclose(fd); return(NULL); } g3_verb = verbose; znocache(fd); image = newBitImage(MAXCOLS, MAXROWS); currline = image->data; cols = 0; for (rows = 0; rows < MAXROWS; ++rows) { col = g3_getfaxrow(fd, currline); if (col < 0) { freeImage(image); zclose(fd); return(NULL); } if (g3_eof) break; if (col > cols) cols = col; currline += BITS_TO_BYTES(cols); } image->title= dupString(name); image->width = cols; image->height = rows; if (!image->width || !image->height) { /* sanity check */ zclose(fd); freeImage(image); return(NULL); } if(verbose) printf("%s is a %dx%d G3 FAX image.\n", name, image->width, image->height); read_trail_opt(image_ops,fd,image,verbose); zclose(fd); return(image); } boolean g3Ident(char *fullname, char *name) { ZFILE *fd; int i,retv; if ((fd = zopen(fullname)) == NULL) { perror("g3Ident"); return(0); } /* * Init hash table */ if (firstTime) { firstTime = 0; /* Initialize and load the hash tables */ for ( i = 0; i < HASHSIZE; ++i ) whash[i] = bhash[i] = (tableentry *) 0; g3_addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB); g3_addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB); g3_addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB); g3_addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB); g3_addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB); g3_addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB); } maxlinelen = BITS_TO_BYTES(MAXCOLS); if((retv = g3_ident(fd))) printf("%s is a G3 FAX image.\n", name); zclose(fd); return retv; } xli-2006-11-10/g3.h0000644000031400000060000001534106461630121013106 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/g3.h 6.7 93/07/23 Labtam" */ /* g3.h - header file for group 3 FAX compression filters */ #define MAXCOLS 2550 /* Maximum image size is 8.5"x11" @ 300dpi */ #define MAXROWS 3300 #define TWTABLE 23 #define MWTABLE 24 #define TBTABLE 25 #define MBTABLE 26 #define EXTABLE 27 #define VRTABLE 28 #define WHASHA 3510 #define WHASHB 1178 #define BHASHA 293 #define BHASHB 2695 #define HASHSIZE 1021 #ifndef _G3_H_ #define _G3_H_ typedef unsigned char bit; int bmask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; typedef struct tableentry { int tabid; int code; int length; int count; } tableentry; struct tableentry twtable[] = { { TWTABLE, 0x35, 8, 0 }, { TWTABLE, 0x7, 6, 1 }, { TWTABLE, 0x7, 4, 2 }, { TWTABLE, 0x8, 4, 3 }, { TWTABLE, 0xb, 4, 4 }, { TWTABLE, 0xc, 4, 5 }, { TWTABLE, 0xe, 4, 6 }, { TWTABLE, 0xf, 4, 7 }, { TWTABLE, 0x13, 5, 8 }, { TWTABLE, 0x14, 5, 9 }, { TWTABLE, 0x7, 5, 10 }, { TWTABLE, 0x8, 5, 11 }, { TWTABLE, 0x8, 6, 12 }, { TWTABLE, 0x3, 6, 13 }, { TWTABLE, 0x34, 6, 14 }, { TWTABLE, 0x35, 6, 15 }, { TWTABLE, 0x2a, 6, 16 }, { TWTABLE, 0x2b, 6, 17 }, { TWTABLE, 0x27, 7, 18 }, { TWTABLE, 0xc, 7, 19 }, { TWTABLE, 0x8, 7, 20 }, { TWTABLE, 0x17, 7, 21 }, { TWTABLE, 0x3, 7, 22 }, { TWTABLE, 0x4, 7, 23 }, { TWTABLE, 0x28, 7, 24 }, { TWTABLE, 0x2b, 7, 25 }, { TWTABLE, 0x13, 7, 26 }, { TWTABLE, 0x24, 7, 27 }, { TWTABLE, 0x18, 7, 28 }, { TWTABLE, 0x2, 8, 29 }, { TWTABLE, 0x3, 8, 30 }, { TWTABLE, 0x1a, 8, 31 }, { TWTABLE, 0x1b, 8, 32 }, { TWTABLE, 0x12, 8, 33 }, { TWTABLE, 0x13, 8, 34 }, { TWTABLE, 0x14, 8, 35 }, { TWTABLE, 0x15, 8, 36 }, { TWTABLE, 0x16, 8, 37 }, { TWTABLE, 0x17, 8, 38 }, { TWTABLE, 0x28, 8, 39 }, { TWTABLE, 0x29, 8, 40 }, { TWTABLE, 0x2a, 8, 41 }, { TWTABLE, 0x2b, 8, 42 }, { TWTABLE, 0x2c, 8, 43 }, { TWTABLE, 0x2d, 8, 44 }, { TWTABLE, 0x4, 8, 45 }, { TWTABLE, 0x5, 8, 46 }, { TWTABLE, 0xa, 8, 47 }, { TWTABLE, 0xb, 8, 48 }, { TWTABLE, 0x52, 8, 49 }, { TWTABLE, 0x53, 8, 50 }, { TWTABLE, 0x54, 8, 51 }, { TWTABLE, 0x55, 8, 52 }, { TWTABLE, 0x24, 8, 53 }, { TWTABLE, 0x25, 8, 54 }, { TWTABLE, 0x58, 8, 55 }, { TWTABLE, 0x59, 8, 56 }, { TWTABLE, 0x5a, 8, 57 }, { TWTABLE, 0x5b, 8, 58 }, { TWTABLE, 0x4a, 8, 59 }, { TWTABLE, 0x4b, 8, 60 }, { TWTABLE, 0x32, 8, 61 }, { TWTABLE, 0x33, 8, 62 }, { TWTABLE, 0x34, 8, 63 }, }; struct tableentry mwtable[] = { { MWTABLE, 0x1b, 5, 64 }, { MWTABLE, 0x12, 5, 128 }, { MWTABLE, 0x17, 6, 192 }, { MWTABLE, 0x37, 7, 256 }, { MWTABLE, 0x36, 8, 320 }, { MWTABLE, 0x37, 8, 384 }, { MWTABLE, 0x64, 8, 448 }, { MWTABLE, 0x65, 8, 512 }, { MWTABLE, 0x68, 8, 576 }, { MWTABLE, 0x67, 8, 640 }, { MWTABLE, 0xcc, 9, 704 }, { MWTABLE, 0xcd, 9, 768 }, { MWTABLE, 0xd2, 9, 832 }, { MWTABLE, 0xd3, 9, 896 }, { MWTABLE, 0xd4, 9, 960 }, { MWTABLE, 0xd5, 9, 1024 }, { MWTABLE, 0xd6, 9, 1088 }, { MWTABLE, 0xd7, 9, 1152 }, { MWTABLE, 0xd8, 9, 1216 }, { MWTABLE, 0xd9, 9, 1280 }, { MWTABLE, 0xda, 9, 1344 }, { MWTABLE, 0xdb, 9, 1408 }, { MWTABLE, 0x98, 9, 1472 }, { MWTABLE, 0x99, 9, 1536 }, { MWTABLE, 0x9a, 9, 1600 }, { MWTABLE, 0x18, 6, 1664 }, { MWTABLE, 0x9b, 9, 1728 }, }; struct tableentry tbtable[] = { { TBTABLE, 0x37, 10, 0 }, { TBTABLE, 0x2, 3, 1 }, { TBTABLE, 0x3, 2, 2 }, { TBTABLE, 0x2, 2, 3 }, { TBTABLE, 0x3, 3, 4 }, { TBTABLE, 0x3, 4, 5 }, { TBTABLE, 0x2, 4, 6 }, { TBTABLE, 0x3, 5, 7 }, { TBTABLE, 0x5, 6, 8 }, { TBTABLE, 0x4, 6, 9 }, { TBTABLE, 0x4, 7, 10 }, { TBTABLE, 0x5, 7, 11 }, { TBTABLE, 0x7, 7, 12 }, { TBTABLE, 0x4, 8, 13 }, { TBTABLE, 0x7, 8, 14 }, { TBTABLE, 0x18, 9, 15 }, { TBTABLE, 0x17, 10, 16 }, { TBTABLE, 0x18, 10, 17 }, { TBTABLE, 0x8, 10, 18 }, { TBTABLE, 0x67, 11, 19 }, { TBTABLE, 0x68, 11, 20 }, { TBTABLE, 0x6c, 11, 21 }, { TBTABLE, 0x37, 11, 22 }, { TBTABLE, 0x28, 11, 23 }, { TBTABLE, 0x17, 11, 24 }, { TBTABLE, 0x18, 11, 25 }, { TBTABLE, 0xca, 12, 26 }, { TBTABLE, 0xcb, 12, 27 }, { TBTABLE, 0xcc, 12, 28 }, { TBTABLE, 0xcd, 12, 29 }, { TBTABLE, 0x68, 12, 30 }, { TBTABLE, 0x69, 12, 31 }, { TBTABLE, 0x6a, 12, 32 }, { TBTABLE, 0x6b, 12, 33 }, { TBTABLE, 0xd2, 12, 34 }, { TBTABLE, 0xd3, 12, 35 }, { TBTABLE, 0xd4, 12, 36 }, { TBTABLE, 0xd5, 12, 37 }, { TBTABLE, 0xd6, 12, 38 }, { TBTABLE, 0xd7, 12, 39 }, { TBTABLE, 0x6c, 12, 40 }, { TBTABLE, 0x6d, 12, 41 }, { TBTABLE, 0xda, 12, 42 }, { TBTABLE, 0xdb, 12, 43 }, { TBTABLE, 0x54, 12, 44 }, { TBTABLE, 0x55, 12, 45 }, { TBTABLE, 0x56, 12, 46 }, { TBTABLE, 0x57, 12, 47 }, { TBTABLE, 0x64, 12, 48 }, { TBTABLE, 0x65, 12, 49 }, { TBTABLE, 0x52, 12, 50 }, { TBTABLE, 0x53, 12, 51 }, { TBTABLE, 0x24, 12, 52 }, { TBTABLE, 0x37, 12, 53 }, { TBTABLE, 0x38, 12, 54 }, { TBTABLE, 0x27, 12, 55 }, { TBTABLE, 0x28, 12, 56 }, { TBTABLE, 0x58, 12, 57 }, { TBTABLE, 0x59, 12, 58 }, { TBTABLE, 0x2b, 12, 59 }, { TBTABLE, 0x2c, 12, 60 }, { TBTABLE, 0x5a, 12, 61 }, { TBTABLE, 0x66, 12, 62 }, { TBTABLE, 0x67, 12, 63 }, }; struct tableentry mbtable[] = { { MBTABLE, 0xf, 10, 64 }, { MBTABLE, 0xc8, 12, 128 }, { MBTABLE, 0xc9, 12, 192 }, { MBTABLE, 0x5b, 12, 256 }, { MBTABLE, 0x33, 12, 320 }, { MBTABLE, 0x34, 12, 384 }, { MBTABLE, 0x35, 12, 448 }, { MBTABLE, 0x6c, 13, 512 }, { MBTABLE, 0x6d, 13, 576 }, { MBTABLE, 0x4a, 13, 640 }, { MBTABLE, 0x4b, 13, 704 }, { MBTABLE, 0x4c, 13, 768 }, { MBTABLE, 0x4d, 13, 832 }, { MBTABLE, 0x72, 13, 896 }, { MBTABLE, 0x73, 13, 960 }, { MBTABLE, 0x74, 13, 1024 }, { MBTABLE, 0x75, 13, 1088 }, { MBTABLE, 0x76, 13, 1152 }, { MBTABLE, 0x77, 13, 1216 }, { MBTABLE, 0x52, 13, 1280 }, { MBTABLE, 0x53, 13, 1344 }, { MBTABLE, 0x54, 13, 1408 }, { MBTABLE, 0x55, 13, 1472 }, { MBTABLE, 0x5a, 13, 1536 }, { MBTABLE, 0x5b, 13, 1600 }, { MBTABLE, 0x64, 13, 1664 }, { MBTABLE, 0x65, 13, 1728 }, }; struct tableentry extable[] = { { EXTABLE, 0x8, 11, 1792 }, { EXTABLE, 0xc, 11, 1856 }, { EXTABLE, 0xd, 11, 1920 }, { EXTABLE, 0x12, 12, 1984 }, { EXTABLE, 0x13, 12, 2048 }, { EXTABLE, 0x14, 12, 2112 }, { EXTABLE, 0x15, 12, 2176 }, { EXTABLE, 0x16, 12, 2240 }, { EXTABLE, 0x17, 12, 2304 }, { EXTABLE, 0x1c, 12, 2368 }, { EXTABLE, 0x1d, 12, 2432 }, { EXTABLE, 0x1e, 12, 2496 }, { EXTABLE, 0x1f, 12, 2560 }, }; #endif /*_G3_H_*/ xli-2006-11-10/gif.c0000644000031400000060000004174110525262416013344 0ustar smarryconsole/* 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) */ #define GIF_C #include "kljcpyrght.h" #include "xli.h" #include "gif.h" #include "imagetypes.h" /**** ** ** local #defines ** ****/ #define PUSH_PIXEL(p) \ { \ if (pstk_idx == PSTK_SIZE) \ return GIFIN_ERR_PSO; \ else \ pstk[pstk_idx++] = (p); \ } /* * push a string (denoted by a code) onto the pixel stack * (returns the code of the first pixel in the string in ps_rslt) */ int ps_rslt; /* return result */ #define GIFIN_PUSH_STRING(code) \ { \ int ps_code; \ ps_code = code; \ \ while (((unsigned int)ps_code) < STAB_SIZE && prefix[ps_code] != NULL_CODE) \ { \ PUSH_PIXEL(extnsn[ps_code]); \ ps_code = prefix[ps_code]; \ } \ \ if (((unsigned int)ps_code) >= STAB_SIZE) \ return GIFIN_ERR_TAO; \ PUSH_PIXEL(extnsn[ps_code]); \ ps_rslt = extnsn[ps_code]; \ if (((unsigned int)ps_rslt) >= STAB_SIZE) \ return GIFIN_ERR_TAO; \ } /* * Look up the ascii message coresponding to * the error number. */ static char * get_err_string(int errno) { int i; for (i=0;gif_err_strings[i].err_no != 0;i++) { if (gif_err_strings[i].err_no == errno) return gif_err_strings[i].name; } return ""; } /**** ** ** 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 BYTE gifin_g_cmap_sorted; /* global colormap sorted (GIF89a only) */ static int gifin_bg_color; /* background color index */ static int gifin_color_bits; /* bits of color resolution */ static double gifin_aspect; /* pixel aspect ratio (width/height) */ static int gifin_version; /* gif file version */ 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 */ /* * load a colormap from the input stream */ static int gifin_load_cmap(BYTE (*cmap)[256], int ncolors) { int i; for (i=0; i> 4) + 1; gifin_g_pixel_bits = (buf[4] & 0x07) + 1; gifin_bg_color = buf[5]; gifin_aspect = 1.0; if (gifin_version == GIF87a) { if (buf[4] & 0x08 || buf[6] != 0) { if (verbose) { fprintf(stderr, "gifLoad: ignoring non-null screen descriptor in Gif87a image\n"); } } } else { gifin_g_cmap_sorted = ((buf[4] & 0x08) != 0); if (buf[6] != 0) gifin_aspect = ((double)buf[6] + 15.0) / 64.0; } /* load global colormap */ if (gifin_g_cmap_flag) { gifin_g_ncolors = (1 << gifin_g_pixel_bits); if ((errno = gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors)) != GIFIN_SUCCESS) return errno; } else { gifin_g_ncolors = 0; } /* done! */ return GIFIN_SUCCESS; } /* * read a new data block from the input stream */ static int gifin_read_data_block(void) { /* 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; } /* * skip an extension block in the input stream */ static int gifin_skip_extension(void) { int errno; /* get the extension function byte */ zgetc(ins); /* skip any remaining raster data */ do { if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS) return errno; } while (buf_cnt > 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(void) { int i; int separator; int errno; /* 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 ((errno = gifin_skip_extension()) != GIFIN_SUCCESS) return errno; } } 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 ((errno = gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors)) != GIFIN_SUCCESS) return errno; } 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 STAB_SIZE) return GIFIN_ERR_TAO; return GIFIN_SUCCESS; } /* * try to read next pixel from the raster, return result in *pel */ static int gifin_get_pixel(int *pel) { int code; int first; int place; int errno; /* decode until there are some pixels on the pixel stack */ while (pstk_idx == 0) { /* load bytes until we have enough bits for another code */ while (work_bits < code_size) { if (buf_idx == buf_cnt) { /* read a new data block */ if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS) return errno; if (buf_cnt == 0) return GIFIN_ERR_EOD; } work_data |= ((long) buf[buf_idx++]) << work_bits; work_bits += 8; } /* get the next code */ code = work_data & code_mask; work_data >>= 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) { GIFIN_PUSH_STRING(code); first = ps_rslt; } else { place = pstk_idx; PUSH_PIXEL(NULL_CODE); GIFIN_PUSH_STRING(prev_code); first = ps_rslt; pstk[place] = first; } if((errno = gifin_add_string(prev_code, first)) != GIFIN_SUCCESS) return errno; prev_code = code; } } /* pop a pixel off the pixel stack */ *pel = (int) pstk[--pstk_idx]; /* done! */ return GIFIN_SUCCESS; } /* * close an open GIF file */ static int gifin_close_file(void) { /* 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; } /* these are the routines added for interfacing to xli */ /* tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(char *name) { printf("%s is a %dx%d %s%s image with %d colors\n", name, gifin_img_width, gifin_img_height, (gifin_interlace_flag ? "interlaced " : ""), gif_version_name[gifin_version], (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors)); } Image *gifLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; Image *image; int x, y, pixel, pass, scanlen; byte *pixptr, *pixline; int errno; if (! (zf= zopen(fullname))) { perror("gifLoad"); return(NULL); } if ((gifin_open_file(zf, verbose) != 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)); image->title= dupString(name); /* if image has a local colormap, override global colormap */ if (gifin_l_cmap_flag) { for (x= 0; x < gifin_l_ncolors; x++) { image->rgb.red[x]= gifin_l_cmap[GIF_RED][x] << 8; image->rgb.green[x]= gifin_l_cmap[GIF_GRN][x] << 8; image->rgb.blue[x]= gifin_l_cmap[GIF_BLU][x] << 8; } image->rgb.used= gifin_l_ncolors; } else { 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; } /* 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 ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) { fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", name, get_err_string(errno)); 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 { if(image->pixlen == 1) { /* the usual case */ pixptr= image->data; for (y= 0; y < gifin_img_height; y++) for (x= 0; x < gifin_img_width; x++) { if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) { fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", name, get_err_string(errno)); y = gifin_img_height; x = gifin_img_width; } valToMem(pixel, pixptr, 1); pixptr += 1; } } else { /* less ususal case */ pixptr= image->data; for (y= 0; y < gifin_img_height; y++) for (x= 0; x < gifin_img_width; x++) { if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) { fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", name, get_err_string(errno)); y = gifin_img_height; x = gifin_img_width; } valToMem(pixel, pixptr, image->pixlen); pixptr += image->pixlen; } } } gifin_close_file(); read_trail_opt(image_ops,zf,image,verbose); zclose(zf); if (gifin_aspect != 1.0) { /* correct for GIF89a aspect ratio */ Image *timage; printf(" Correcting for GIF89a pixel aspect ratio of %2.4f...",gifin_aspect); if (gifin_aspect < 1.0) /* tall pixels - image will look too short */ timage = zoom(image, 0, (int)(100.0/gifin_aspect + 0.5), FALSE, FALSE); else /* wide pixels - image will look too thin */ timage = zoom(image, (int)(100.0 * gifin_aspect + 0.5), 0, FALSE, FALSE); if (timage != image) freeImage(image); image = timage; printf("done\n"); } return(image); } int gifIdent(char *fullname, char *name) { ZFILE *zf; unsigned int ret; if (! (zf= zopen(fullname))) return(0); if ((gifin_open_file(zf, FALSE) == GIFIN_SUCCESS) && (gifin_open_image() == GIFIN_SUCCESS)) { tellAboutImage(name); ret= 1; } else ret= 0; gifin_close_file(); zclose(zf); return(ret); } xli-2006-11-10/gif.h0000644000031400000060000000643607004736440013354 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/gif.h 6.9 93/07/23 Labtam" */ /* 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 */ #define GIFIN_ERR_PSO -10 /* pixel stack overflow */ #define GIFIN_ERR_TAO -11 /* table overflow */ #define GIFIN_ERR_BAD_DES -12 /* bad image descriptor */ #define GIFIN_ERR_BAD_SD_STR "Bad screen descriptor" #define GIFIN_ERR_BAD_SEP_STR "Bad image separator" #define GIFIN_ERR_BAD_SIG_STR "Bad signature" #define GIFIN_ERR_EOD_STR "Unexpected end of raster data" #define GIFIN_ERR_EOF_STR "Unexpected end of input stream" #define GIFIN_ERR_FAO_STR "File already open" #define GIFIN_ERR_IAO_STR "Image already open" #define GIFIN_ERR_NFO_STR "No file open" #define GIFIN_ERR_NIO_STR "No image open" #define GIFIN_ERR_PSO_STR "Pixel stack overflow" #define GIFIN_ERR_TAO_STR "Table overflow" #define GIFIN_ERR_BAD_DES_STR "Bad image descriptor" typedef struct { int err_no; char *name; } gif_err_string; #ifdef GIF_C gif_err_string gif_err_strings[] = { {GIFIN_ERR_BAD_SD, GIFIN_ERR_BAD_SD_STR}, {GIFIN_ERR_BAD_SEP, GIFIN_ERR_BAD_SEP_STR}, {GIFIN_ERR_BAD_SIG, GIFIN_ERR_BAD_SIG_STR}, {GIFIN_ERR_EOD, GIFIN_ERR_EOD_STR}, {GIFIN_ERR_EOF, GIFIN_ERR_EOF_STR}, {GIFIN_ERR_FAO, GIFIN_ERR_FAO_STR}, {GIFIN_ERR_IAO, GIFIN_ERR_IAO_STR}, {GIFIN_ERR_NFO, GIFIN_ERR_NFO_STR}, {GIFIN_ERR_NIO, GIFIN_ERR_NIO_STR}, {GIFIN_ERR_PSO, GIFIN_ERR_PSO_STR}, {GIFIN_ERR_TAO, GIFIN_ERR_TAO_STR}, {GIFIN_ERR_BAD_DES, GIFIN_ERR_BAD_DES_STR}, {0} }; #endif /* * colormap indices */ #define GIF_RED 0 #define GIF_GRN 1 #define GIF_BLU 2 /* * typedef BYTE for convenience */ typedef unsigned char BYTE; /* #defines, typedefs, and such */ #define GIF_SIG "GIF87a" #define GIF_SIG_89 "GIF89a" #define GIF87a 0 /* Gif file version type */ #define GIF89a 1 /* Gif file version type */ #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 */ #ifdef GIF_C char *gif_version_name[] = { GIF_SIG, GIF_SIG_89 }; #endif xli-2006-11-10/halftone.c0000644000031400000060000002517610525262416014403 0ustar smarryconsole/* halftone.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 * * 16/10/92 - re do intensity tables to be rounded (so that they add up * properly !) - GWG * * Copyright 1989, 1990 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xli.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, 77, 154, 230, 307, 384, 461, 538, 614, 691, 768, 845, 922, 998, 1075, 1152, 1229, 1306, 1382, 1459, 1536, 1613, 1690, 1766, 1843, 1920, 1997, 2074, 2150, 2227, 2304, 2381, 2458, 2534, 2611, 2688, 2765, 2842, 2918, 2995, 3072, 3149, 3226, 3302, 3379, 3456, 3533, 3610, 3686, 3763, 3840, 3917, 3994, 4070, 4147, 4224, 4301, 4378, 4454, 4531, 4608, 4685, 4762, 4838, 4915, 4992, 5069, 5146, 5222, 5299, 5376, 5453, 5530, 5606, 5683, 5760, 5837, 5914, 5990, 6067, 6144, 6221, 6298, 6374, 6451, 6528, 6605, 6682, 6758, 6835, 6912, 6989, 7066, 7142, 7219, 7296, 7373, 7450, 7526, 7603, 7680, 7757, 7834, 7910, 7987, 8064, 8141, 8218, 8294, 8371, 8448, 8525, 8602, 8678, 8755, 8832, 8909, 8986, 9062, 9139, 9216, 9293, 9370, 9446, 9523, 9600, 9677, 9754, 9830, 9907, 9984, 10061, 10138, 10214, 10291, 10368, 10445, 10522, 10598, 10675, 10752, 10829, 10906, 10982, 11059, 11136, 11213, 11290, 11366, 11443, 11520, 11597, 11674, 11750, 11827, 11904, 11981, 12058, 12134, 12211, 12288, 12365, 12442, 12518, 12595, 12672, 12749, 12826, 12902, 12979, 13056, 13133, 13210, 13286, 13363, 13440, 13517, 13594, 13670, 13747, 13824, 13901, 13978, 14054, 14131, 14208, 14285, 14362, 14438, 14515, 14592, 14669, 14746, 14822, 14899, 14976, 15053, 15130, 15206, 15283, 15360, 15437, 15514, 15590, 15667, 15744, 15821, 15898, 15974, 16051, 16128, 16205, 16282, 16358, 16435, 16512, 16589, 16666, 16742, 16819, 16896, 16973, 17050, 17126, 17203, 17280, 17357, 17434, 17510, 17587, 17664, 17741, 17818, 17894, 17971, 18048, 18125, 18202, 18278, 18355, 18432, 18509, 18586, 18662, 18739, 18816, 18893, 18970, 19046, 19123, 19200, 19277, 19354, 19430, 19507, 19584 }; unsigned short GreenIntensity[256] = { 0, 151, 302, 453, 604, 755, 906, 1057, 1208, 1359, 1510, 1661, 1812, 1964, 2115, 2266, 2417, 2568, 2719, 2870, 3021, 3172, 3323, 3474, 3625, 3776, 3927, 4078, 4229, 4380, 4531, 4682, 4833, 4984, 5135, 5286, 5437, 5588, 5740, 5891, 6042, 6193, 6344, 6495, 6646, 6797, 6948, 7099, 7250, 7401, 7552, 7703, 7854, 8005, 8156, 8307, 8458, 8609, 8760, 8911, 9062, 9213, 9364, 9516, 9667, 9818, 9969, 10120, 10271, 10422, 10573, 10724, 10875, 11026, 11177, 11328, 11479, 11630, 11781, 11932, 12083, 12234, 12385, 12536, 12687, 12838, 12989, 13140, 13292, 13443, 13594, 13745, 13896, 14047, 14198, 14349, 14500, 14651, 14802, 14953, 15104, 15255, 15406, 15557, 15708, 15859, 16010, 16161, 16312, 16463, 16614, 16765, 16916, 17068, 17219, 17370, 17521, 17672, 17823, 17974, 18125, 18276, 18427, 18578, 18729, 18880, 19031, 19182, 19333, 19484, 19635, 19786, 19937, 20088, 20239, 20390, 20541, 20692, 20844, 20995, 21146, 21297, 21448, 21599, 21750, 21901, 22052, 22203, 22354, 22505, 22656, 22807, 22958, 23109, 23260, 23411, 23562, 23713, 23864, 24015, 24166, 24317, 24468, 24620, 24771, 24922, 25073, 25224, 25375, 25526, 25677, 25828, 25979, 26130, 26281, 26432, 26583, 26734, 26885, 27036, 27187, 27338, 27489, 27640, 27791, 27942, 28093, 28244, 28396, 28547, 28698, 28849, 29000, 29151, 29302, 29453, 29604, 29755, 29906, 30057, 30208, 30359, 30510, 30661, 30812, 30963, 31114, 31265, 31416, 31567, 31718, 31869, 32020, 32172, 32323, 32474, 32625, 32776, 32927, 33078, 33229, 33380, 33531, 33682, 33833, 33984, 34135, 34286, 34437, 34588, 34739, 34890, 35041, 35192, 35343, 35494, 35645, 35796, 35948, 36099, 36250, 36401, 36552, 36703, 36854, 37005, 37156, 37307, 37458, 37609, 37760, 37911, 38062, 38213, 38364, 38515 }; unsigned short BlueIntensity[256] = { 0, 28, 56, 84, 113, 141, 169, 197, 225, 253, 282, 310, 338, 366, 394, 422, 451, 479, 507, 535, 563, 591, 620, 648, 676, 704, 732, 760, 788, 817, 845, 873, 901, 929, 957, 986, 1014, 1042, 1070, 1098, 1126, 1155, 1183, 1211, 1239, 1267, 1295, 1324, 1352, 1380, 1408, 1436, 1464, 1492, 1521, 1549, 1577, 1605, 1633, 1661, 1690, 1718, 1746, 1774, 1802, 1830, 1859, 1887, 1915, 1943, 1971, 1999, 2028, 2056, 2084, 2112, 2140, 2168, 2196, 2225, 2253, 2281, 2309, 2337, 2365, 2394, 2422, 2450, 2478, 2506, 2534, 2563, 2591, 2619, 2647, 2675, 2703, 2732, 2760, 2788, 2816, 2844, 2872, 2900, 2929, 2957, 2985, 3013, 3041, 3069, 3098, 3126, 3154, 3182, 3210, 3238, 3267, 3295, 3323, 3351, 3379, 3407, 3436, 3464, 3492, 3520, 3548, 3576, 3604, 3633, 3661, 3689, 3717, 3745, 3773, 3802, 3830, 3858, 3886, 3914, 3942, 3971, 3999, 4027, 4055, 4083, 4111, 4140, 4168, 4196, 4224, 4252, 4280, 4308, 4337, 4365, 4393, 4421, 4449, 4477, 4506, 4534, 4562, 4590, 4618, 4646, 4675, 4703, 4731, 4759, 4787, 4815, 4844, 4872, 4900, 4928, 4956, 4984, 5012, 5041, 5069, 5097, 5125, 5153, 5181, 5210, 5238, 5266, 5294, 5322, 5350, 5379, 5407, 5435, 5463, 5491, 5519, 5548, 5576, 5604, 5632, 5660, 5688, 5716, 5745, 5773, 5801, 5829, 5857, 5885, 5914, 5942, 5970, 5998, 6026, 6054, 6083, 6111, 6139, 6167, 6195, 6223, 6252, 6280, 6308, 6336, 6364, 6392, 6420, 6449, 6477, 6505, 6533, 6561, 6589, 6618, 6646, 6674, 6702, 6730, 6758, 6787, 6815, 6843, 6871, 6899, 6927, 6956, 6984, 7012, 7040, 7068, 7096, 7124, 7153, 7181 }; /* 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(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 */ CURRFUNC("halftone"); if (BITMAPP(cimage)) return (NULL); /* set up */ if (GAMMA_NOT_EQUAL(cimage->gamma, 1.0)) gammacorrect(cimage, 1.0, verbose); 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); } image->gamma = cimage->gamma; 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 (RGBP(cimage) && (cimage->depth <= 16)) lfree((byte *) index); if (verbose) printf("done\n"); return (image); } xli-2006-11-10/image.h0000644000031400000060000001053507004736440013664 0ustar smarryconsole/* 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" typedef struct rgbmap { unsigned int size; /* size of RGB map */ unsigned int used; /* number of colors used in RGB map */ boolean 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 */ byte *data; /* data rounded to full byte for each row */ float gamma; /* gamma of display the image is adjusted for */ unsigned long flags; /* sundry flags */ } Image; #define IBITMAP 0 /* image is a bitmap */ #define IRGB 1 /* image is RGB */ #define ITRUE 2 /* 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) (((unsigned long)((PIXVAL) & 0xff0000)) >> 16) #define TRUE_GREEN(PIXVAL) (((unsigned long)((PIXVAL) & 0xff00)) >> 8) #define TRUE_BLUE(PIXVAL) ((unsigned long)((PIXVAL) & 0xff)) #define RGB_TO_TRUE(R,G,B) \ ((((unsigned long)((R) & 0xff00)) << 8) | ((G) & 0xff00) | (((unsigned short)(B)) >> 8)) #define FLAG_ISCALE 1 /* image scaled by decoder */ #define UNSET_GAMMA 0.0 #define depthToColors(n) DepthToColorsTable[((n) < 32 ? (n) : 32)] /* this returns the (approximate) intensity of an RGB triple */ #define colorIntensity(R,G,B) \ (RedIntensity[((unsigned short)(R)) >> 8] \ + GreenIntensity[((unsigned short)(G)) >> 8] \ + BlueIntensity[((unsigned short)(B)) >> 8]) extern unsigned short RedIntensity[]; extern unsigned short GreenIntensity[]; extern unsigned short BlueIntensity[]; /* Architecture independent memory to value conversions. * Note the "Normal" internal format is big endian. */ #define memToVal(PTR,LEN) (\ (LEN) == 1 ? (unsigned long)(*((byte *)(PTR))) : \ (LEN) == 2 ? (unsigned long)(((unsigned long)(*((byte *)(PTR))))<< 8) \ + (*(((byte *)(PTR))+1)) : \ (LEN) == 3 ? (unsigned long)(((unsigned long)(*((byte *)(PTR))))<<16) \ + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ + (*(((byte *)(PTR))+2)) : \ (unsigned long)(((unsigned long)(*((byte *)(PTR))))<<24) \ + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \ + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \ + (*(((byte *)(PTR))+3))) #define valToMem(VAL,PTR,LEN) ( \ (LEN) == 1 ? (*((byte *)(PTR)) = (VAL)) : \ (LEN) == 2 ? (*((byte *)(PTR)) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+1) = (VAL)) : \ (LEN) == 3 ? (*((byte *)(PTR)) = (((unsigned long)(VAL))>>16), \ *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+2) = (VAL)) : \ (*((byte *)(PTR)) = (((unsigned long)(VAL))>>24), \ *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \ *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+3) = (VAL))) #define memToValLSB(PTR,LEN) ( \ (LEN) == 1 ? (unsigned long)(*((byte *)(PTR))) : \ (LEN) == 2 ? (unsigned long)(*((byte *)(PTR))) \ + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) : \ (LEN) == 3 ? (unsigned long)(*((byte *)(PTR))) \ + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ + (((unsigned long)(*(((byte *)(PTR))+2)))<<16) : \ (unsigned long)(*((byte *)(PTR))) \ + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ + (((unsigned long)(*(((byte *)(PTR))+2)))<<16) \ + (((unsigned long)(*(((byte *)(PTR))+3)))<<24)) /* this is provided for orthagonality */ #define valToMemLSB(VAL,PTR,LEN) ( \ (LEN) == 1 ? (*((byte *)(PTR)) = (VAL)) : \ (LEN) == 2 ? (*((byte *)(PTR)) = (VAL), \ *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8)) : \ (LEN) == 3 ? (*((byte *)(PTR)) = (VAL), \ *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>>16)) : \ (*((byte *)(PTR)) = (VAL), \ *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>>16), \ *(((byte *)(PTR))+3) = (((unsigned long)(VAL))>>24))) xli-2006-11-10/imagetypes.c0000644000031400000060000000602510525262416014742 0ustar smarryconsole/* imagetypes.c: * * this contains the ImageTypes array * * jim frost 09.27.89 * * Copyright 1989, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xli.h" #include "imagetypes.h" #include extern int errno; /* some of these are order-dependent */ static struct { int (*identifier) (char *, char *); Image *(*loader) (char *, ImageOptions *, boolean); char *name; } ImageTypes[] = { {fbmIdent, fbmLoad, "FBM Image"}, {sunRasterIdent, sunRasterLoad, "Sun Rasterfile"}, {cmuwmIdent, cmuwmLoad, "CMU WM Raster"}, {pbmIdent, pbmLoad, "Portable Bit Map (PBM, PGM, PPM)"}, {facesIdent, facesLoad, "Faces Project"}, {pngIdent, pngLoad, "Portable Network Graphics (PNG)"}, {gifIdent, gifLoad, "GIF Image"}, {jpegIdent, jpegLoad, "JFIF style jpeg Image"}, {rleIdent, rleLoad, "Utah RLE Image"}, {bmpIdent, bmpLoad, "Windows, OS/2 RLE Image"}, {pcdIdent, pcdLoad, "Photograph on CD Image"}, {xwdIdent, xwdLoad, "X Window Dump"}, {tgaIdent, tgaLoad, "Targa Image"}, {mcidasIdent, mcidasLoad, "McIDAS areafile"}, {g3Ident, g3Load, "G3 FAX Image"}, {pcxIdent, pcxLoad, "PC Paintbrush Image"}, {imgIdent, imgLoad, "GEM Bit Image"}, {macIdent, macLoad, "MacPaint Image"}, {xpixmapIdent, xpixmapLoad, "X Pixmap"}, {xbitmapIdent, xbitmapLoad, "X Bitmap"}, {NULL, NULL, NULL} }; /* load a named image */ Image *loadImage(ImageOptions * image_ops, boolean verbose) { char fullname[BUFSIZ]; Image *image; int a; if (findImage(image_ops->name, fullname) < 0) { if (errno == ENOENT) printf("%s: image not found\n", image_ops->name); else if (errno == EISDIR) printf("%s: directory\n", image_ops->name); else perror(fullname); return (NULL); } image_ops->fullname = lmalloc(strlen(fullname) + 1); strcpy(image_ops->fullname, fullname); /* We've done this before !! */ if (image_ops->loader_idx != -1) { image = ImageTypes[image_ops->loader_idx].loader(fullname, image_ops, verbose); if (image) { zreset(NULL); return (image); } } else { for (a = 0; ImageTypes[a].loader; a++) { image = ImageTypes[a].loader(fullname, image_ops, verbose); if (image) { zreset(NULL); return (image); } } } printf("%s: unknown or unsupported image type\n", fullname); zreset(NULL); return (NULL); } /* identify what kind of image a named image is */ void identifyImage(char *name) { char fullname[BUFSIZ]; int a; if (findImage(name, fullname) < 0) { if (errno == ENOENT) printf("%s: image not found\n", name); else if (errno == EISDIR) printf("%s: directory\n", name); else perror(fullname); return; } for (a = 0; ImageTypes[a].identifier; a++) { if (ImageTypes[a].identifier(fullname, name)) { zreset(NULL); return; } } zreset(NULL); printf("%s: unknown or unsupported image type\n", fullname); } /* tell user what image types we support */ void supportedImageTypes(void) { int a; printf("Image types supported:\n"); for (a = 0; ImageTypes[a].name; a++) printf(" %s\n", ImageTypes[a].name); } xli-2006-11-10/imagetypes.h0000644000031400000060000000502707004736441014752 0ustar smarryconsole/* 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 *facesLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *pbmLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *sunRasterLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *gifLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *jpegLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *rleLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *bmpLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *pcdLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *xwdLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *xbitmapLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *xpixmapLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *g3Load(char *fullname, ImageOptions * image_ops, boolean verbose); Image *fbmLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *pcxLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *imgLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *macLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *cmuwmLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *mcidasLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *tgaLoad(char *fullname, ImageOptions * image_ops, boolean verbose); Image *pngLoad(char *fullname, ImageOptions * opt, boolean verbose); int facesIdent(char *fullname, char *name); int pbmIdent(char *fullname, char *name); int sunRasterIdent(char *fullname, char *name); int gifIdent(char *fullname, char *name); int jpegIdent(char *fullname, char *name); int rleIdent(char *fullname, char *name); int bmpIdent(char *fullname, char *name); int pcdIdent(char *fullname, char *name); int xwdIdent(char *fullname, char *name); int xbitmapIdent(char *fullname, char *name); int xpixmapIdent(char *fullname, char *name); int g3Ident(char *fullname, char *name); int fbmIdent(char *fullname, char *name); int pcxIdent(char *fullname, char *name); int imgIdent(char *fullname, char *name); int macIdent(char *fullname, char *name); int cmuwmIdent(char *fullname, char *name); int mcidasIdent(char *fullname, char *name); int tgaIdent(char *fullname, char *name); int pngIdent(char *fullname, char *name); xli-2006-11-10/img.c0000644000031400000060000001704507004736441013355 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/img.c 1.6 93/07/23 Labtam" */ /* ** img.c - load a GEM Bit Image file for use inside xli ** ** Tim Northrup ** ** Version 0.1 -- 4/25/91 -- Initial cut ** ** Copyright (C) 1991 Tim Northrup ** (see file "tgncpyrght.h" for complete copyright information) */ #include "tgncpyrght.h" #include "xli.h" #include "imagetypes.h" #include "img.h" static int Debug = 0; /* Set to 1 for info */ static unsigned char *BitRow; /* working row of bits */ static int RowRepeat; /* number of repititons */ static int RowCount; /* current row */ static int ColCount; /* current column */ static int IMG_ReadHeader(ZFILE *zf, IMG_Header *h); /* Read file header */ static void IMG_WriteByte(unsigned char c, register int cols, unsigned int bpl); /* Write output byte */ /* ** imgIdent ** ** Identify passed file as a GEM Bit Image or not ** ** Returns 1 if file is a GEM Image, 0 otherwise */ int imgIdent (char *fullname, char *name) { ZFILE *zf; /* Input file */ IMG_Header header; /* GEM Image header info */ int ret = 0; /* Return value */ if ( ! (zf = zopen(fullname))) return(0); if (IMG_ReadHeader(zf,&header) == 0) { printf("%s is a %dx%d GEM Bit Image\n", fullname, header.llen, header.lines); ret = 1; } zclose(zf); return(ret); } /* ** imgLoad ** ** Load GEM Image file into an Image structure. ** ** Returns pointer to allocated struct if successful, NULL otherwise */ Image *imgLoad (char *fullname, ImageOptions *image_ops, boolean verbose) { char *name = image_ops->name; register int i; /* Random index */ ZFILE *zf; /* Input file */ short creps; /* Repetition counter */ short ictr; /* Secondary index counter */ unsigned int bpl; /* Bytes per scanline */ Image *image; /* Allocated image struct */ IMG_Header header; /* GEM Image header */ unsigned char inbuf[MAX_LITERAL], ichr; /* Input buffer/char */ if ( ! (zf = zopen(fullname))) { perror("imgLoad"); return((Image *)NULL); } if ((i = IMG_ReadHeader(zf,&header)) != 0) { zclose(zf); switch (i) { case 1: /* short read in header */ case 2: /* not a GEM image */ break; case 3: fprintf(stderr,"imgLoad: %s - Color images are not supported (yet)\n",name); break; case 4: fprintf(stderr,"imgLoad: %s - image is too large\n",name); break; default: fprintf(stderr,"imgLoad: %s - Unsupported image pattern length\n",name); break; } return((Image *)NULL); } if (verbose) printf("%s is a %dx%d GEM Image\n",name,header.llen,header.lines); znocache(zf); image = newBitImage(header.llen,header.lines); image->title = dupString(name); BitRow = &(image->data[0]); bpl = header.llen / 8; /* bytes per line */ ColCount = 0; /* starting column */ RowCount = 0; /* starting row */ RowRepeat = 1; /* default repeat */ while (RowCount < header.lines) { /* While the last line has not been reached ... */ i = zgetc(zf); if (i == EOF) { fprintf(stderr,"imgLoad: %s - premature EOF\n",name); break; } if (i == BYTE_FLAG) { /* scanline */ i = zgetc(zf); if (i == EOF) { fprintf(stderr,"imgLoad: %s - premature EOF\n",name); break; } if (i == BYTE_SLREPEAT) { /* repeat scanline */ if (ColCount != 0) { printf("GEM Image Failure: corrupted\n"); fprintf(stderr,"imgLoad: %s - premature EOF\n",name); break; } i = zgetc(zf); /* SLFLAG byte (0xFF) */ if (i != BYTE_SLFLAG) { fprintf(stderr,"imgLoad: %s - corrupted\n",name); break; } RowRepeat = zgetc(zf); /* repeat count */ } else { /* repeat pattern_len */ creps = i; zread(zf,inbuf,header.patlen); for (i = 0 ; i < creps ; i++) for (ictr = 0 ; ictr < header.patlen ; ictr++) IMG_WriteByte(inbuf[ictr],header.llen,bpl); } } else if (i == BYTE_LITERAL) { /* literal follows */ creps = zgetc(zf); /* literal length */ zread(zf,inbuf,creps); /* literal */ for (ictr = 0 ; ictr < creps ; ictr++) IMG_WriteByte(inbuf[ictr],header.llen,bpl); } else { /* monochrome mode bits */ creps = RUN_LENGTH(i); ichr = (RUN_COLOR(i) == 1) ? BYTE_BLACK : BYTE_WHITE; for (i = 0 ; i < creps ; i++) IMG_WriteByte(ichr,header.llen,bpl); } } read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } /* ** IMG_ReadHeader ** ** Read in IMG file header information, skip extras. ** ** Returns 0 if successful ** 1 if not enough file for header record ** 2 if header data is nonsensical/invalid ** 3 if image is color (unsupported) ** 4 if image is too wide ( > 8K bits!!) ** 5 if pattern length is too big ( > 255) */ static int IMG_ReadHeader (ZFILE *zf, IMG_Header *h) { register int tlen; /* total to read in */ register int rlen; /* read lengths */ unsigned char junkbuffer[MAX_SCANLINE]; /* scrap buffer */ tlen = zread(zf,junkbuffer,(DEF_HLEN * 2)); if (tlen != (DEF_HLEN * 2)) return(1); /* not enough data */ /* convert from big-endian to machine specific */ h->vers = junkbuffer[1] + (256 * junkbuffer[0]); h->hlen = junkbuffer[3] + (256 * junkbuffer[2]); h->colors = junkbuffer[5] + (256 * junkbuffer[4]); h->patlen = junkbuffer[7] + (256 * junkbuffer[6]); h->pixw = junkbuffer[9] + (256 * junkbuffer[8]); h->pixh = junkbuffer[11] + (256 * junkbuffer[10]); h->llen = junkbuffer[13] + (256 * junkbuffer[12]); h->lines = junkbuffer[15] + (256 * junkbuffer[14]); /* sanity check; if fields don't look right, it's probably not a GEM * image. */ if ((h->vers != DEF_VERSION) || (h->hlen < DEF_HLEN) || (h->colors < 0) || (h->colors > 256) || (h->pixw < 1) || (h->pixh < 1) || (h->llen < 1) || (h->llen > (MAX_SCANLINE * 8)) || (h->lines < 1) || (h->lines > 8192) || (h->patlen < 0) || (h->patlen > MAX_LITERAL)) return(2); if (Debug) { fprintf(stderr,"Header Information:\n"); fprintf(stderr,"\tIMG Version: %d\n",h->vers); fprintf(stderr,"\t Header Len: %d\n",h->hlen); fprintf(stderr,"\t Colors: %d\n",h->colors); fprintf(stderr,"\tPattern Len: %d\n",h->patlen); fprintf(stderr,"\t Pixel Size: %d x %d (microns=1000th mm)\n", h->pixw,h->pixh); fprintf(stderr,"\t Image Size: %d x %d (pixels)\n", h->llen,h->lines); } /* validity check on particular fields */ if (h->colors != 1) return(3); if (h->llen > (MAX_SCANLINE * 8)) return(4); if (h->patlen > MAX_LITERAL) return(5); /* make life easier if not on an even boundary */ if (h->llen % 8) { h->llen += (8 - (h->llen % 8)); if (Debug) fprintf(stderr,"Image expanded to %d pixels wide\n", h->llen); } /* skip additional header information if present */ if (h->hlen > DEF_HLEN) { tlen = ((h->hlen - DEF_HLEN) * 2); if (Debug) fprintf(stderr,"imgLoad: %d bytes of extra header skipped",tlen); for ( ; tlen > 0 ; tlen -= rlen) { rlen = (tlen > MAX_SCANLINE) ? MAX_SCANLINE : tlen; zread(zf,junkbuffer,rlen); } } return(0); } /* ** IMG_WriteByte ** ** Add byte to image; if end of scanline, may need to replicate it ** ** Returns no value (void function) */ static void IMG_WriteByte (unsigned char c, register int cols, unsigned int bpl) { register int i; register unsigned char *ptr; register unsigned char *ptr2; BitRow[ColCount] = c; if (++ColCount >= bpl) { /* end of scanline */ ptr2 = BitRow + bpl; RowCount++; /* count one already out */ while (--RowRepeat > 0) { for (ptr = BitRow, i = 0 ; i < bpl ; i++, ptr++) *ptr2++ = *ptr; RowCount++; } BitRow = ptr2; ColCount = 0; RowRepeat = 1; } return; } xli-2006-11-10/img.h0000644000031400000060000000437506461630121013356 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/img.h 1.5 93/07/23 Labtam" */ /* ** 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 */ xli-2006-11-10/jpeg.c0000644000031400000060000002004710525262416013520 0ustar smarryconsole/* JPEG code for libjpeg v6 * derived from xli 1.16 jpeg.c and IJG code * any bugs are my fault -- smar@reptiles.org */ #include "xli.h" #include "imagetypes.h" #include #include #include #include #include /* JFIF defines the gamma of pictures to be 1.0. Unfortunately no-one * takes any notice (sigh), and the majority of images are like gifs - * they are adjusted to look ok on a "typical" monitor using a gamma naive * viewer/windowing system. We give in to the inevitable here and use 2.2 */ #define RETURN_GAMMA DEFAULT_IRGB_GAMMA #define INPUT_BUF_SIZE 4096 typedef struct { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; } xli_jpg_err; typedef struct { struct jpeg_source_mgr pub; ZFILE *zfp; JOCTET buf[INPUT_BUF_SIZE]; } xli_jpg_src; static void xli_jpg_error_exit(j_common_ptr cinfo) { xli_jpg_err *err = (xli_jpg_err *) cinfo->err; (*cinfo->err->output_message) (cinfo); longjmp(err->setjmp_buffer, 1); } static void xli_jpg_init_src(j_decompress_ptr cinfo) { } static boolean xli_jpg_fill_buf(j_decompress_ptr cinfo) { xli_jpg_src *src = (xli_jpg_src *) cinfo->src; size_t n; n = zread(src->zfp, src->buf, INPUT_BUF_SIZE); if (n <= 0) { WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buf[0] = (JOCTET) 0xFF; src->buf[1] = (JOCTET) JPEG_EOI; n = 2; } src->pub.next_input_byte = src->buf; src->pub.bytes_in_buffer = n; return TRUE; } static void xli_jpg_skip(j_decompress_ptr cinfo, long int n) { xli_jpg_src *src = (xli_jpg_src *) cinfo->src; if (n > 0) { while (n > (long) src->pub.bytes_in_buffer) { n -= (long) src->pub.bytes_in_buffer; xli_jpg_fill_buf(cinfo); } src->pub.next_input_byte += (size_t) n; src->pub.bytes_in_buffer -= (size_t) n; } } /* maybe in future we can exploit zio's rewind capability to provide a resync_to_restart function here? */ static void xli_jpg_term(j_decompress_ptr cinfo) { /* return unread input to the zstream */ xli_jpg_src *src = (xli_jpg_src *) cinfo->src; if (src->zfp && src->pub.bytes_in_buffer > 0) { zunread(src->zfp, (byte *) src->pub.next_input_byte, src->pub.bytes_in_buffer); } } static void xli_jpg_zio_src(j_decompress_ptr cinfo, ZFILE *zfp) { xli_jpg_src *src; if (!cinfo->src) { cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(xli_jpg_src)); } src = (xli_jpg_src *) cinfo->src; src->pub.init_source = xli_jpg_init_src; src->pub.fill_input_buffer = xli_jpg_fill_buf; src->pub.skip_input_data = xli_jpg_skip; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default */ src->pub.term_source = xli_jpg_term; src->zfp = zfp; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } static void describe_jpeg(j_decompress_ptr cinfo, char *filename) { printf("%s is a %dx%d JPEG image, color space ", filename, cinfo->image_width, cinfo->image_height); switch (cinfo->jpeg_color_space) { case JCS_UNKNOWN: printf("Unknown"); break; case JCS_GRAYSCALE: printf("Grayscale"); break; case JCS_RGB: printf("RGB"); break; case JCS_YCbCr: printf("YCbCr"); break; case JCS_CMYK: printf("CMYK"); break; case JCS_YCCK: printf("YCCK"); break; default: printf("Totally Weird"); break; } printf(", %d comp%s, %s\n", cinfo->num_components, cinfo->num_components ? "s." : ".", cinfo->arith_code ? "Arithmetic coding" : "Huffman coding"); } static unsigned int xli_jpg_getc(j_decompress_ptr cinfo) { struct jpeg_source_mgr *datasrc = cinfo->src; if (datasrc->bytes_in_buffer == 0) (*datasrc->fill_input_buffer) (cinfo); datasrc->bytes_in_buffer--; return GETJOCTET(*datasrc->next_input_byte++); } static boolean xli_jpg_com(j_decompress_ptr cinfo) { long length; unsigned int ch; unsigned int lastch = 0; length = xli_jpg_getc(cinfo) << 8; length += xli_jpg_getc(cinfo); length -= 2; /* discount the length word itself */ printf("Comment, length %ld:\n", (long) length); while (--length >= 0) { ch = xli_jpg_getc(cinfo); /* Emit the character in a readable form. * Nonprintables are converted to \nnn form, * while \ is converted to \\. * Newlines in CR, CR/LF, or LF form will be printed as one newline. */ if (ch == '\r') { printf("\n"); } else if (ch == '\n') { if (lastch != '\r') printf("\n"); } else { putc(ch, stdout); } lastch = ch; } printf("\n"); return TRUE; } Image *jpegLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zfp; struct jpeg_decompress_struct cinfo; xli_jpg_err jerr; Image *image = 0; byte **rows = 0; int i, rowbytes; CURRFUNC("jpegLoad"); zfp = zopen(fullname); if (!zfp) return (Image *) 0; /* Quick check to see if file starts with JPEG SOI marker */ if (zgetc(zfp) != 0xFF || zgetc(zfp) != 0xD8) { zclose(zfp); return (Image *) 0; } zrewind(zfp); /* set default error handlers and override error_exit */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = xli_jpg_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); zclose(zfp); if (rows) { lfree((byte *) rows); rows = 0; } return image; } jpeg_create_decompress(&cinfo); xli_jpg_zio_src(&cinfo, zfp); if (verbose) jpeg_set_marker_processor(&cinfo, JPEG_COM, xli_jpg_com); jpeg_read_header(&cinfo, TRUE); if (verbose) describe_jpeg(&cinfo, fullname); if (image_ops->iscale > 0 && image_ops->iscale < 4) { cinfo.scale_num = 1; cinfo.scale_denom = 1 << image_ops->iscale; } else if (image_ops->iscale_auto) { image_ops->iscale = 0; while (image_ops->iscale < 3 && (cinfo.image_width >> image_ops->iscale > globals.dinfo.width * .9 || cinfo.image_height >> image_ops->iscale > globals.dinfo.height * .9)) image_ops->iscale += 1; cinfo.scale_denom = 1 << image_ops->iscale; if (verbose) printf("auto-scaling to 1/%d\n", cinfo.scale_denom); } znocache(zfp); jpeg_start_decompress(&cinfo); if (JCS_GRAYSCALE == cinfo.out_color_space) { int i; image = newRGBImage(cinfo.output_width, cinfo.output_height, 8); image->title = dupString(image_ops->name); 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 (JCS_RGB == cinfo.out_color_space) { image = newTrueImage(cinfo.output_width, cinfo.output_height); image->title = dupString(image_ops->name); } else { fprintf(stderr, "jpegLoad: weird output color space\n"); jpeg_destroy_decompress(&cinfo); zclose(zfp); return (Image *) 0; } image->gamma = RETURN_GAMMA; if (cinfo.scale_denom > 1) image->flags |= FLAG_ISCALE; rowbytes = cinfo.output_width * cinfo.output_components; assert(image->pixlen * image->width == rowbytes); rows = (byte **) lmalloc(image->height * sizeof(byte *)); for (i = 0; i < image->height; ++i) rows[i] = image->data + i * rowbytes; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, rows + cinfo.output_scanline, cinfo.output_height - cinfo.output_scanline); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); read_trail_opt(image_ops, zfp, image, verbose); zclose(zfp); lfree((byte *) rows); rows = 0; return image; } int jpegIdent(char *fullname, char *name) { ZFILE *zfp; struct jpeg_decompress_struct cinfo; xli_jpg_err jerr; CURRFUNC("jpegIdent"); zfp = zopen(fullname); if (!zfp) return 0; /* Quick check to see if file starts with JPEG SOI marker */ if (zgetc(zfp) != 0xFF || zgetc(zfp) != 0xD8) { zclose(zfp); return 0; } zrewind(zfp); /* set default error handlers and override error_exit */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = xli_jpg_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); zclose(zfp); return 0; } jpeg_create_decompress(&cinfo); xli_jpg_zio_src(&cinfo, zfp); jpeg_read_header(&cinfo, TRUE); describe_jpeg(&cinfo, fullname); jpeg_destroy_decompress(&cinfo); zclose(zfp); return 1; } xli-2006-11-10/kljcpyrght.h0000644000031400000060000000226706461630121014761 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/kljcpyrght.h 6.7 93/07/23 Labtam" */ #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 xli-2006-11-10/mac.c0000644000031400000060000001162007004736442013333 0ustar smarryconsole/* * 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 "xli.h" #include "imagetypes.h" # include # 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(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(void) { /* 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; } /* * these are the routines added for interfacing to xli */ /* * tell someone what the image we're loading is. this could be a little more * descriptive but I don't care */ static void tellAboutImage(char *name) { printf("%s is a %dx%d MacPaint image\n", name, macin_img_width, macin_img_height); } Image *macLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; 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); image->title = dupString(name); if (verbose) tellAboutImage(name); 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) { printf("macLoad: Short read within image data, '%s'\n", fullname); macin_close_file(); zclose(zf); return (image); } macin_close_file(); read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return image; } int macIdent(char *fullname, char *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); } xli-2006-11-10/mac.h0000644000031400000060000000372207004736442013344 0ustar smarryconsole/**************************************************************** * 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 */ #define MACIN_ERR_BAD_SD_STR "Bad screen descriptor" #define MACIN_ERR_BAD_SIG_STR "Bad signature" #define MACIN_ERR_EOD_STR "Unexpected end of raster data" #define MACIN_ERR_EOF_STR "Unexpected end of input stream" #define MACIN_ERR_FAO_STR "File already open" #define MACIN_ERR_IAO_STR "Image already open" #define MACIN_ERR_NFO_STR "No file open" #define MACIN_ERR_NIO_STR "No image open" typedef struct { int err_no; char *name; } mac_err_string; #ifdef MAC_C mac_err_string mac_err_strings[] = { {MACIN_ERR_BAD_SD, MACIN_ERR_BAD_SD_STR}, {MACIN_ERR_BAD_SIG, MACIN_ERR_BAD_SIG_STR}, {MACIN_ERR_EOD, MACIN_ERR_EOD_STR}, {MACIN_ERR_EOF, MACIN_ERR_EOF_STR}, {MACIN_ERR_FAO, MACIN_ERR_FAO_STR}, {MACIN_ERR_IAO, MACIN_ERR_IAO_STR}, {MACIN_ERR_NFO, MACIN_ERR_NFO_STR}, {MACIN_ERR_NIO, MACIN_ERR_NIO_STR}, {0} }; #endif #define MAC_HDR_LEN 512 #define ADD_HDR_LEN 128 #define MAX_LINES 720 #define BYTES_LINE 72 xli-2006-11-10/mc_tables.c0000644000031400000060000000471307004736442014531 0ustar smarryconsole/* * 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. * */ #include "mcidas.h" char *mc_sensor(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 McIDAS format") ; } xli-2006-11-10/mcidas.c0000644000031400000060000000727507004736442014046 0ustar smarryconsole/* mcidas.c: * * McIDAS areafile support. contributed by Glenn P. Davis * (davis@unidata.ucar.edu). */ #include "xli.h" #include "imagetypes.h" #include "mcidas.h" char *mc_sensor(int sscode); /* * convert from little endian to big endian four byte object */ static unsigned long vhtonl(long unsigned int 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) ; } /* ARGSUSED */ int mcidasIdent(char *fullname, char *name) { ZFILE *zf; struct area_dir dir ; int r; int doswap = 0 ; if (! (zf= zopen(fullname))) { perror("mcidasIdent"); return(0); } switch (zread(zf, (byte *)&dir, sizeof(struct area_dir))) { case sizeof(struct area_dir): if (dir.type == 4) { r= 1; break; } else if (dir.type == 67108864) { r= 1; doswap = 1 ; } else { r= 0; break; } case -1: perror("mcidasIdent"); default: r= 0; break; } zclose(zf); if(r && doswap) { 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) ; } /* a simple sanity check */ if (dir.idate > 99999 || dir.itime > 999999) r = 0; if (r) { (void)printf("%s %ld %ld (%ld, %ld) (%ld, %ld)\n", mc_sensor(dir.satid), dir.idate, dir.itime, dir.lcor, dir.ecor, dir.lres, dir.eres) ; } return(r); } Image *mcidasLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; 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 sizeof(struct area_dir): if (dir.type != 4) { if(dir.type != 67108864) { zclose(zf); return(NULL) ; } else { doswap = 1 ; } } break; case -1: perror("mcidasLoad"); default: zclose(zf); return(NULL); } if(doswap) { 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) ; } /* a simple sanity check */ if (dir.idate > 99999 || dir.itime > 999999) { zclose(zf); return(NULL); } if (verbose) { printf("%s %ld %ld (%ld, %ld) (%ld, %ld)\n", mc_sensor(dir.satid), dir.idate, dir.itime, dir.lcor, dir.ecor, dir.lres, dir.eres); } 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, 8 * dir.bands); image->title= dupString(name); /* set up the colormap, linear grey scale */ for (y= 0; y < 255; y++) { *(image->rgb.red + y)= *(image->rgb.green + y)= *(image->rgb.blue + y)= y * 257 ; } image->rgb.used= 255 ; if (zread(zf, image->data, dir.esiz * dir.lsiz) != dir.esiz * dir.lsiz) { fprintf(stderr,"mcidasLoad: %s - Short read within image data\n",name); zclose(zf); return(image); } zclose(zf); read_trail_opt(image_ops,zf,image,verbose); return(image); } xli-2006-11-10/mcidas.h0000644000031400000060000000416107004736443014043 0ustar smarryconsole/* 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 */ } ; char *mc_sensor(int sscode); xli-2006-11-10/merge.c0000644000031400000060000001616407004736443013703 0ustar smarryconsole/* 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 "xli.h" /* if merging bitmaps they don't have to be converted to * 24-bit. this saves a lot of space. */ static Image *bitmapToBitmap(Image *src, Image *dst, unsigned int atx, unsigned int aty, unsigned int clipw, unsigned int cliph) { unsigned int dstlinelen, srclinelen; unsigned int dststart; unsigned int flip; unsigned int x, y; byte *dstline, *srcline; byte dststartmask; byte dstmask, srcmask; byte *dstpixel, *srcpixel; dstlinelen= (dst->width / 8) + (dst->width % 8 ? 1 : 0); srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0); dstline= dst->data + (aty * dstlinelen); srcline= src->data; dststart= atx / 8; dststartmask= 0x80 >> (atx % 8); flip= ((*dst->rgb.red == *(src->rgb.red + 1)) && (*dst->rgb.green == *(src->rgb.green + 1)) && (*dst->rgb.blue == *(src->rgb.blue + 1))); for (y= 0; y < cliph; y++) { dstpixel= dstline + dststart; srcpixel= srcline; dstmask= dststartmask; srcmask= 0x80; for (x= 0; x < clipw; x++) { if (flip) if (*srcpixel & srcmask) *dstpixel &= ~dstmask; else *dstpixel |= dstmask; else if (*srcpixel & srcmask) *dstpixel |= dstmask; else *dstpixel &= ~dstmask; dstmask >>= 1; srcmask >>= 1; if (dstmask == 0) { dstmask= 0x80; dstpixel++; } if (srcmask == 0) { srcmask= 0x80; srcpixel++; } } dstline += dstlinelen; srcline += srclinelen; } if (globals.verbose) printf("done\n"); return(dst); } #ifndef FABS #define FABS(x) ((x) < 0.0 ? -(x) : (x)) #endif /* merge any to true */ static Image *anyToTrue(Image *src, Image *dst, unsigned int atx, unsigned int aty, unsigned int clipw, unsigned int cliph) { Pixel fg, bg; unsigned int dstlinelen, srclinelen; unsigned int dststart; unsigned int x, y; byte *dstline, *srcline; byte *dstpixel, *srcpixel; byte srcmask; Pixel pixval; /* The gamma of our two images just need to be equal. */ /* Move towards our output gamma to minimize gamma changes */ if (GAMMA_NOT_EQUAL(src->gamma, dst->gamma)) { if (FABS(src->gamma-globals.display_gamma) > FABS(dst->gamma-globals.display_gamma)) gammacorrect(src, dst->gamma, globals.verbose); else gammacorrect(dst, src->gamma, globals.verbose); } 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]); dstlinelen= dst->width * dst->pixlen; srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0); dstline= dst->data + (aty * dstlinelen); srcline= src->data; dststart= atx * dst->pixlen; for (y= 0; y < cliph; y++) { dstpixel= dstline + dststart; srcpixel= srcline; srcmask= 0x80; if(dst->pixlen == 3) /* the ususal case */ for (x= 0; x < clipw; x++) { valToMem((*srcpixel & srcmask ? fg : bg), dstpixel, 3); dstpixel += 3; srcmask >>= 1; if (srcmask == 0) { srcpixel++; srcmask= 0x80; } } else /* less ususal case */ for (x= 0; x < clipw; x++) { valToMem((*srcpixel & srcmask ? fg : bg), dstpixel, dst->pixlen); dstpixel += dst->pixlen; srcmask >>= 1; if (srcmask == 0) { srcpixel++; srcmask= 0x80; } } dstline += dstlinelen; srcline += srclinelen; } break; case IRGB: dstlinelen= dst->width * dst->pixlen; srclinelen= src->width * src->pixlen; dststart= atx * dst->pixlen; dstline= dst->data + (aty * dstlinelen); srcline= src->data; if(src->pixlen == 1) /* the usual case */ for (y= 0; y < cliph; y++) { dstpixel= dstline + dststart; srcpixel= srcline; for (x= 0; x < clipw; x++) { pixval= memToVal(srcpixel, 1); *(dstpixel++)= src->rgb.red[pixval] >> 8; *(dstpixel++)= src->rgb.green[pixval] >> 8; *(dstpixel++)= src->rgb.blue[pixval] >> 8; srcpixel += 1; } dstline += dstlinelen; srcline += srclinelen; } else /* the less ususal */ for (y= 0; y < cliph; y++) { dstpixel= dstline + dststart; srcpixel= srcline; for (x= 0; x < clipw; x++) { pixval= memToVal(srcpixel, src->pixlen); *(dstpixel++)= src->rgb.red[pixval] >> 8; *(dstpixel++)= src->rgb.green[pixval] >> 8; *(dstpixel++)= src->rgb.blue[pixval] >> 8; srcpixel += src->pixlen; } dstline += dstlinelen; srcline += srclinelen; } break; case ITRUE: dstlinelen= dst->width * dst->pixlen; srclinelen= src->width * src->pixlen; dststart= atx * dst->pixlen; dstline= dst->data + (aty * dstlinelen); srcline= src->data; for (y= 0; y < cliph; y++) { dstpixel= dstline + dststart; srcpixel= srcline; for (x= 0; x < clipw; x++) { *(dstpixel++)= *(srcpixel++); *(dstpixel++)= *(srcpixel++); *(dstpixel++)= *(srcpixel++); } dstline += dstlinelen; srcline += srclinelen; } break; } if (globals.verbose) printf("done\n"); return(dst); } /* put src image on dst image */ Image *merge(Image *idst, Image *isrc, int atx, int aty, ImageOptions *imgopp) { int clipw, cliph; Image *src = isrc,*dst = idst,*outimage; if (globals.verbose) { printf(" Merging..."); fflush(stdout); } /* adjust clipping of src to fit within dst */ clipw= src->width; cliph= src->height; if ((atx + clipw < 0) || (aty + cliph < 0) || (atx >= (int)dst->width) || (aty >= (int)dst->height)) /* not on dst, ignore */ return dst; if (atx + clipw > dst->width) clipw = dst->width - atx; if (aty + cliph > dst->height) cliph = dst->height - aty; /* extra clipping required for negative offsets */ if ( atx < 0 || aty < 0 ) { int clipx, clipy; Image *tmp; if ( atx < 0 ) { clipx = -atx; clipw += atx; atx = 0; } else clipx = 0; if ( aty < 0 ) { clipy = -aty; cliph += aty; aty = 0; } else clipy = 0; tmp = clip(src, clipx, clipy, clipw, cliph, imgopp); if (src != tmp && src != isrc) /* free imtermediate, but preserve input */ freeImage(src); src = tmp; } if (BITMAPP(dst) && BITMAPP(src)) { outimage= bitmapToBitmap(src, dst, (unsigned int)atx, (unsigned int)aty, clipw, cliph); } else { if (!TRUEP(dst)) { /* convert to true */ Image *tmp; tmp = expandtotrue(dst); if (dst != tmp && dst != idst) freeImage(dst); dst = tmp; } outimage = anyToTrue(src, dst, (unsigned int)atx, (unsigned int)aty, clipw, cliph); } /* do the right thing */ if (dst != outimage && dst != idst) freeImage(dst); if (src != outimage && src != isrc) freeImage(src); return(outimage); } xli-2006-11-10/misc.c0000644000031400000060000002675410525262416013541 0ustar smarryconsole/* 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 "xli.h" #include "patchlevel" #include #include static char *signalName(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(void) { fprintf(stderr, "Memory has been exhausted; Last function was %s, operation cannot continue (sorry).\n", globals.lastfunc); if (globals._Xdebug) abort(); else exit(1); } void internalError(int sig) { static int handling_error = 0; switch (handling_error++) { case 0: printf("\ An internal error (%s) has occurred. Last function was %s.\n\ If you would like to file a bug report, please send email to %s\n\ with a description of how you triggered the bug, the output of xli\n\ before the failure, and the following information:\n\n", signalName(sig), globals.lastfunc, AUTHOR_EMAIL); printf("********************************************************************************\n"); printf("xli Version %s.%s\n", VERSION, PATCHLEVEL); tellAboutDisplay(&globals.dinfo); printf("********************************************************************************\n\n"); break; case 1: fprintf(stderr, "\ An internal error has occurred within the internal error handler. No more\n\ information about the error is available, sorry.\n"); break; } if (globals._Xdebug) /* dump core if -debug is on */ abort(); printf("If you run xli again with the -dumpcore flag, then it will core dump\n"); printf("so you can investigate the problem yourself.\n"); exit(1); } void version(void) { printf("xli version %s patchlevel %s.\n", VERSION, PATCHLEVEL); printf("based on xli version 1 patchlevel 16 by Graeme Gill.\n"); printf("based on xloadimage version 3 patchlevel 01 by Jim Frost.\n"); printf("Please send email to %s for bug reports.\n", AUTHOR_EMAIL); } void usage(char *name) { version(); printf("\nUsage: %s [global options] {[image options] image_name ...}\n\n", tail(name)); printf("\ Type `%s -help [option ...]' for information on a particular option, or\n\ `%s -help' to enter the interactive help facility.\n", tail(name), tail(name)); exit(1); } char *tail(char *path) { int s; char *t; t = path; for (s = 0; *(path + s) != '\0'; s++) if (*(path + s) == '/') t = path + s + 1; return (t); } Image *processImage(DisplayInfo *dinfo, Image *iimage, ImageOptions *options) { Image *image = iimage, *tmpimage; XColor xcolor; CURRFUNC("processImage"); /* Pre-processing */ /* clip the image if requested */ if ((options->clipx != 0) || (options->clipy != 0) || (options->clipw != 0) || (options->cliph != 0)) { tmpimage = clip(image, options->clipx, options->clipy, (options->clipw ? options->clipw : image->width), (options->cliph ? options->cliph : image->height), options); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } if (options->rotate) { tmpimage = rotate(image, options->rotate, globals.verbose); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } /* zoom image */ if (options->xzoom || options->yzoom) { /* if the image is to be blown up, compress before doing it */ if (!options->colors && RGBP(image) && ((!options->xzoom && (options->yzoom > 100)) || (!options->yzoom && (options->xzoom > 100)) || (options->xzoom + options->yzoom > 200))) { compress_cmap(image, globals.verbose); } tmpimage = zoom(image, options->xzoom, options->yzoom, globals.verbose, TRUE); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } /* set foreground and background colors of mono image */ xcolor.flags = DoRed | DoGreen | DoBlue; if (image->depth == 1 && (options->fg || options->bg)) { int backgmap = 0; /* figure out background map number - xwd can make it what it * likes */ if (*image->rgb.red == 0 && *image->rgb.green == 0 && *image->rgb.blue == 0) backgmap = 1; if (options->fg) { xliParseXColor(dinfo, options->fg, &xcolor); xliGammaCorrectXColor(&xcolor, DEFAULT_DISPLAY_GAMMA); *(image->rgb.red + (1 - backgmap)) = xcolor.red; *(image->rgb.green + (1 - backgmap)) = xcolor.green; *(image->rgb.blue + (1 - backgmap)) = xcolor.blue; } if (options->bg) { xliParseXColor(dinfo, options->bg, &xcolor); xliGammaCorrectXColor(&xcolor, DEFAULT_DISPLAY_GAMMA); *(image->rgb.red + backgmap) = xcolor.red; *(image->rgb.green + backgmap) = xcolor.green; *(image->rgb.blue + backgmap) = xcolor.blue; } } /* General image processing */ if (options->smooth > 0) { /* image is to be smoothed */ tmpimage = smooth(image, options->smooth, globals.verbose); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } /* Post-processing */ if (options->gray) /* convert image to grayscale */ gray(image, globals.verbose); if (options->normalize) { /* normalize image */ tmpimage = normalize(image, globals.verbose); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } if (options->bright) /* alter image brightness */ brighten(image, options->bright, globals.verbose); /* forcibly reduce colormap */ if (options->colors && (TRUEP(image) || (RGBP(image) && (options->colors < image->rgb.used)))) { tmpimage = reduce(image, options->colors, options->colordither, UNSET_GAMMA, globals.verbose); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } if (options->dither && (image->depth > 1)) { /* image is to be dithered */ if (options->dither == 1) tmpimage = dither(image, globals.verbose); else tmpimage = halftone(image, globals.verbose); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; /* Hmmm - if foreground or -background is used, */ /* make sure it applies here as well */ if (image->depth == 1 && (options->fg || options->bg)) { int backgmap = 0; /* figure out background map number - * xwd can make it what it likes */ if (*image->rgb.red == 0 && *image->rgb.green == 0 && *image->rgb.blue == 0) backgmap = 1; if (options->fg) { xliParseXColor(dinfo, options->fg, &xcolor); xliGammaCorrectXColor(&xcolor, DEFAULT_DISPLAY_GAMMA); image->rgb.red[1 - backgmap] = xcolor.red; image->rgb.green[1 - backgmap] = xcolor.green; image->rgb.blue[1 - backgmap] = xcolor.blue; } if (options->bg) { xliParseXColor(dinfo, options->bg, &xcolor); xliGammaCorrectXColor(&xcolor, DEFAULT_DISPLAY_GAMMA); image->rgb.red[backgmap] = xcolor.red; image->rgb.green[backgmap] = xcolor.green; image->rgb.blue[backgmap] = xcolor.blue; } } } if (options->expand && !TRUEP(image)) { /* expand image to truecolor */ if (globals.verbose) fprintf(stderr, " Expanding image to TRUE color\n"); tmpimage = expandtotrue(image); if (tmpimage != image && iimage != image) freeImage(image); image = tmpimage; } if (RGBP(image) && !image->rgb.compressed) { /* make sure colormap is minimized */ compress_cmap(image, globals.verbose); } return (image); } /* A dumb version that should work reliably * search for "s2" in "s1" */ char *xlistrstr(char *s1, char *s2) { int n; char *p; for (n = strlen(s2), p = s1;; p++) { if (!(p = index(p, *s2))) return (char *) 0; if (!strncmp(p, s2, n)) return p; } } #ifndef HAS_MEMCPY /* A block fill routine for BSD style systems */ void bfill(char *s, int n, int c) { #if defined(_CRAY) /* can't do arithmetic on cray pointers */ while (n >= 8) { *s++ = c; *s++ = c; *s++ = c; *s++ = c; *s++ = c; *s++ = c; *s++ = c; *s++ = c; n -= 8; } while (n-- > 0) *s++ = c; return; #else int b; /* bytes to next word */ b = (0 - (int) s) & (sizeof(unsigned long) - 1); if (n < b) b = n; while (n != 0) { n -= b; while (b-- > 0) *s++ = c; if (n == 0) return; /* words to fill */ b = n & ~(sizeof(unsigned long) - 1); if (b != 0) { unsigned long f; int i; f = c & (((unsigned long) -1) >> ((sizeof(unsigned long) - sizeof(char)) * 8)); for (i = sizeof(char); i < sizeof(unsigned long); i *= 2) f |= (f << (8 * i)); n -= b; /* remaining count */ while (b > 0) { *((unsigned long *) s) = f; s += sizeof(unsigned long); b -= sizeof(unsigned long); } } b = n; } #endif } #endif /* An ascii to hex table */ short BEHexTable[256]; /* Big endian conversion value */ static boolean BEHexTableInitialized = FALSE; short LEHexTable[256]; /* Little endian conversion value */ static boolean LEHexTableInitialized = FALSE; #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 /* build a hex digit value table. */ void initBEHexTable(void) { int a; if (BEHexTableInitialized) return; for (a = 0; a < 256; a++) BEHexTable[a] = HEXBAD; BEHexTable['0'] = b0000; BEHexTable['1'] = b1000; BEHexTable['2'] = b0100; BEHexTable['3'] = b1100; BEHexTable['4'] = b0010; BEHexTable['5'] = b1010; BEHexTable['6'] = b0110; BEHexTable['7'] = b1110; BEHexTable['8'] = b0001; BEHexTable['9'] = b1001; BEHexTable['A'] = b0101; BEHexTable['a'] = BEHexTable['A']; BEHexTable['B'] = b1101; BEHexTable['b'] = BEHexTable['B']; BEHexTable['C'] = b0011; BEHexTable['c'] = BEHexTable['C']; BEHexTable['D'] = b1011; BEHexTable['d'] = BEHexTable['D']; BEHexTable['E'] = b0111; BEHexTable['e'] = BEHexTable['E']; BEHexTable['F'] = b1111; BEHexTable['f'] = BEHexTable['F']; BEHexTable['x'] = HEXSTART_BAD; BEHexTable['\r'] = HEXDELIM_IGNORE; BEHexTable['\n'] = HEXDELIM_IGNORE; BEHexTable['\t'] = HEXDELIM_IGNORE; BEHexTable[' '] = HEXDELIM_IGNORE; BEHexTable[','] = HEXDELIM_BAD; BEHexTable['}'] = HEXDELIM_BAD; BEHexTableInitialized = TRUE; } void initLEHexTable(void) { int a; if (LEHexTableInitialized) return; for (a = 0; a < 256; a++) LEHexTable[a] = HEXBAD; LEHexTable['0'] = 0x0; LEHexTable['1'] = 0x1; LEHexTable['2'] = 0x2; LEHexTable['3'] = 0x3; LEHexTable['4'] = 0x4; LEHexTable['5'] = 0x5; LEHexTable['6'] = 0x6; LEHexTable['7'] = 0x7; LEHexTable['8'] = 0x8; LEHexTable['9'] = 0x9; LEHexTable['A'] = 0xa; LEHexTable['a'] = LEHexTable['A']; LEHexTable['B'] = 0xb; LEHexTable['b'] = LEHexTable['B']; LEHexTable['C'] = 0xc; LEHexTable['c'] = LEHexTable['C']; LEHexTable['D'] = 0xd; LEHexTable['d'] = LEHexTable['D']; LEHexTable['E'] = 0xe; LEHexTable['e'] = LEHexTable['E']; LEHexTable['F'] = 0xf; LEHexTable['f'] = LEHexTable['F']; LEHexTable['x'] = HEXSTART_BAD; LEHexTable['\r'] = HEXDELIM_IGNORE; LEHexTable['\n'] = HEXDELIM_IGNORE; LEHexTable['\t'] = HEXDELIM_IGNORE; LEHexTable[' '] = HEXDELIM_IGNORE; LEHexTable[','] = HEXDELIM_BAD; LEHexTable['}'] = HEXDELIM_BAD; LEHexTableInitialized = TRUE; } /* Hext number to integer */ /* return -1 if not legal hex */ int hstoi(unsigned char *s, int n) { int i, c; int value = 0; if (!LEHexTableInitialized) initLEHexTable(); for (i = 0; i < n; i++) { c = s[i]; c = LEHexTable[c & 0xff]; if (c < 0) /* bad hex */ return (-1); value = (value << 4) | c; } return value; } xli-2006-11-10/mit.cpyrght0000644000031400000060000000257106461630121014620 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/mit.cpyrght 6.5 91/12/20 Labtam" */ #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 xli-2006-11-10/mrmcpyrght.h0000644000031400000060000000224306461630121014766 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/mrmcpyrght.h 1.5 93/07/23 Labtam" */ #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 xli-2006-11-10/new.c0000644000031400000060000001210310525262416013356 0ustar smarryconsole/* 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 "xli.h" /* 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 */ 2147483648U, /* bigger than unsigned int; this is good enough */ /* 32 */ 2147483648U }; unsigned long colorsToDepth(long unsigned int ncolors) { unsigned long a; for (a = 0; (a < 32) && (DepthToColorsTable[a] < ncolors); a++) /* EMPTY */ ; return (a); } char *dupString(char *s) { char *d; if (!s) return (NULL); d = (char *) lmalloc(strlen(s) + 1); strcpy(d, s); return (d); } void newRGBMapData(RGBMap *rgb, unsigned int size) { CURRFUNC("newRGBMapData"); rgb->used = 0; rgb->size = size; rgb->compressed = FALSE; rgb->red = (Intensity *) lmalloc(sizeof(Intensity) * size); rgb->green = (Intensity *) lmalloc(sizeof(Intensity) * size); rgb->blue = (Intensity *) lmalloc(sizeof(Intensity) * size); } void resizeRGBMapData(RGBMap *rgb, unsigned int size) { CURRFUNC("resizeRGBMapData"); rgb->red = (Intensity *) lrealloc((byte *) rgb->red, sizeof(Intensity) * size); rgb->green = (Intensity *) lrealloc((byte *) rgb->green, sizeof(Intensity) * size); rgb->blue = (Intensity *) lrealloc((byte *) rgb->blue, sizeof(Intensity) * size); rgb->size = size; } void freeRGBMapData(RGBMap *rgb) { CURRFUNC("freeRGBMapData"); lfree((byte *) rgb->red); lfree((byte *) rgb->green); lfree((byte *) rgb->blue); } static unsigned int ovmul(unsigned int a, unsigned int b) { unsigned int r; r = a * b; if (r / a != b) { memoryExhausted(); } return r; } static Image *newImage(unsigned width, unsigned height) { Image *image; CURRFUNC("newImage"); image = (Image *) lmalloc(sizeof(Image)); image->title = 0; image->width = width; image->height = height; image->gamma = UNSET_GAMMA; image->flags = 0; return image; } Image *newBitImage(unsigned width, unsigned height) { Image *image; unsigned int linelen; CURRFUNC("newBitImage"); image = newImage(width, height); image->type = IBITMAP; 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->depth = 1; linelen = ((width + 7) / 8); image->data = (unsigned char *) lcalloc(ovmul(linelen, height)); return image; } Image *newRGBImage(unsigned int width, unsigned int height, unsigned int depth) { Image *image; unsigned int pixlen, numcolors; CURRFUNC("newRGBImage"); /* special case for `zero' depth image, which is sometimes * interpreted as `one color' */ if (depth == 0) depth = 1; pixlen = ((depth + 7) / 8); numcolors = depthToColors(depth); image = newImage(width, height); image->type = IRGB; newRGBMapData(&(image->rgb), numcolors); image->depth = depth; image->pixlen = pixlen; image->data = (unsigned char *) lmalloc(ovmul(ovmul(width, height), pixlen)); return image; } Image *newTrueImage(unsigned int width, unsigned int height) { Image *image; CURRFUNC("NewTrueImage"); image = newImage(width, height); image->type = ITRUE; image->rgb.used = image->rgb.size = 0; image->depth = 24; image->pixlen = 3; image->data = (unsigned char *) lmalloc(ovmul(ovmul(width, height), 3)); return image; } void freeImageData(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) { freeImageData(image); lfree((byte *) image); } byte *lmalloc(unsigned int size) { byte *area; if (size == 0) { size = 1; if (globals._Xdebug) fprintf(stderr, "lmalloc given zero size!\n"); } if (!(area = (byte *) malloc(size))) { memoryExhausted(); /* NOTREACHED */ } return (area); } byte *lcalloc(unsigned int size) { byte *area; if (size == 0) { size = 1; if (globals._Xdebug) fprintf(stderr, "lcalloc given zero size!\n"); } if (!(area = (byte *) calloc(1, size))) { memoryExhausted(); /* NOTREACHED */ } return (area); } byte *lrealloc(byte *old, unsigned int size) { byte *area; if (size == 0) { size = 1; if (globals._Xdebug) fprintf(stderr, "lrealloc given zero size!\n"); } if (!(area = (byte *) realloc(old, size))) { memoryExhausted(); /* NOTREACHED */ } return (area); } void lfree(byte *area) { free(area); } xli-2006-11-10/options.c0000644000031400000060000006142410525262416014272 0ustar smarryconsole/* 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 "xli.h" #include #include /* options array and definitions. If you add something to this you also * need to add its OptionId in options.h. */ static OptionArray Options[] = { /* general options */ {"debug", DBUG, NULL, "\ Turn on synchronous mode for debugging. Dump core on error",}, {"dumpcore", DUMPCORE, NULL, "\ Dump core immediately on error signal",}, {"default", DEFAULT, NULL, "\ Set the root background to the default pattern and colors.",}, {"delay", DELAY, "seconds", "\ Set the automatic advance delay for all images.",}, {"display", DISPLAY, NULL, "\ Indicate the X display you would like to use.",}, {"dispgamma", DISPLAYGAMMA, "value", "\ Specify the gamma of the display you are using. The default value is 2.2\n\ A value of between 1.6 and 2.8 is resonable.\n\ If images need brightening or darkening, use the -gamma option"}, {"fillscreen", FILLSCREEN, NULL, "\ Use the whole screen for displaying an image. The image will be zoomed\n\ so that it just fits the size of the screen. If -onroot is also specified,\n\ it will be zoomed to completely fill the screen.",}, {"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. The image will be surrounded by\n\ a border if it is smaller than the screen. If -onroot is also specified,\n\ the image will be zoomed so that it just fits the size of the screen.",}, {"geometry", GEOMETRY, "window_geometry", "\ Specify the size of the display window. Ignored if -fullscreen or -fillscreeni\n\ is given. If used in conjunction with -onroot, this defines the size of the base\n\ image.",}, {"goto", GOTO, "image_name", "\ When the end of the list of images is reached, go to the first image in the list\n\ with the target name.",}, {"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 `xli -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 just fit. If used with -fillscreen, the image will\n\ be zoomed to completely fill the screen. -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\ .xlirc file.",}, {"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.",}, {"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 xli.",}, {"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 xli\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.",}, {"cache", CACHE, NULL, "\ Force caching of entire input, useful for interactively twiddling images\n\ loaded from the standard input.",}, {"delete", DELETE, NULL, "\ Enable deleting images with the 'x' key.",}, {"focus", FOCUS, NULL, "\ Take keyboard focus when viewing in window.",}, /* 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.",}, {"background", BACKGROUND, "color", "\ Set the background pixel color for a monochrome image. See -foreground and\n\ -invert.",}, {"border", BORDER, "color", "\ Set the color used for the border around centered, placed or clipped images.",}, {"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.\n\ See also the -gamma option.",}, {"center", CENTER, NULL, "\ Center the image on the base image (if using -merge) or the root window (if\n\ using -onroot).",}, {"clip", CLIP, "X,Y,W,H", "\ Clip out the rectangle specified by X,Y,W,H and use that as the image.",}, {"colordither", COLORDITHER, NULL, "\ Dither the image if the number of colors is reduced. This will be slower,\n\ but will give a better looking result when 256 colors or less are used.",}, {"cdither", COLORDITHER, NULL, "\ See -colordither.",}, {"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.",}, {"dither", DITHER, NULL, "\ Dither the image into monochrome. This happens automatically if sent to\n\ a monochrome display.",}, {"expand", EXPAND, NULL, "\ Expand the image to TrueColor depth if it is not already of this depth.",}, {"foreground", FOREGROUND, "color", "\ Set the foreground pixel color for a monochrome image. See -background and\n\ -invert.",}, {"gamma", GAMMA, "value", "\ Specify the gamma of the display the image was intended to be displayed\n\ on. Images seem to come in two flavors: 1) linear color images, produced by\n\ ray tracers, scanners etc. These sort of images generally look too dark when\n\ displayed directly to a CRT display. 2) Images that have been processed to\n\ look right on a typical CRT display without any sort of processing. These\n\ images have been 'gamma corrected'. By default, xli assumes that\n\ images have been gamma corrected and need no other processing.\n\ If a linear image is displayed, it will look too dark and a gamma value of\n\ 1.0 should be specified, so that xli can correct the image for the\n\ CRT display device.\n\ Some formats (RLE) allow the image gamma to be embedded as a comment in the\n\ file itself, and the -gamma option allows overriding of the file comment.\n\ In general, values smaller than 2.2 will lighten the image, and values\n\ greater than 2.2 will darken the image.\n\ This often works better than the -brighten option.",}, {"gray", GRAY, NULL, "\ Convert a color image to grayscale. Also 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, "\ Set the automatic advance delay for this image. This overrides -delay\n\ temporarily.",}, {"invert", INVERT, NULL, "\ Invert a monochrome image. This is the same as specifying `-foreground black'\n\ and `-background white'.",}, {"iscale", ISCALE, "scale factor", "\ Scale the image using a fast, image-dependent method, if available.\n\ Positive values make the image smaller, negative values larger.\n\ Specifing `auto' will fast-scale the image to fit on the screen.",}, {"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, "\ Clear the options which propagate to all following images. This is useful\n\ for turning off image processing options which were specified for previous\n\ images.",}, {"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.",}, {"title", TITLE, "window_title", "\ Set the title of the window used to display the image.",}, {"xpm", XPM, "{ m | g4 | g | c }", "\ Select the prefered xpm colour mapping:\n\ (m = mono, g4 = 4 level gray, g = gray, c = color ).",}, {"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 int parse_args(char *as, int sl, char **argv); OptionId optionNumber(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 void listOptions(void) { 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(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: xli -%s %s\nDescription:\n%s\n\n", Options[a].name, 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(char *s) { printf("The quotes around %s are unnecessary. You don't have to be so\n\ literal-minded!\n", s); } void help(char *option) { char buf[BUFSIZ]; /* batch help facility */ if (option) { if (!helpOnOption(option)) listOptions(); printf("\ Type `xli -help [option ...]' to get help on a particular option or\n\ `xli -help' to enter the interactive help facility.\n\n"); return; } /* interactive help facility */ printf("\nxli 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) break; /* EOF */ while (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"); } } /* * Code to process options and set up options structures. */ /* Do general options and return no of argv's advanced */ int doGeneralOption(OptionId opid, char **argv, ImageOptions *persist_ops, ImageOptions *image_ops) { int a = 0; switch (opid) { case ONROOT: globals.onroot = 1; globals.fit = TRUE; /* assume -fit */ break; case DBUG: globals._Xdebug = TRUE; break; case DUMPCORE: globals._DumpCore = TRUE; break; case DEFAULT: globals.set_default = TRUE; break; case DELAY: if (!argv[++a]) break; persist_ops->delay = image_ops->delay = atoi(argv[a]); if (image_ops->delay < 0) { printf("Bad argument to -delay\n"); usage(globals.argv0); /* NOTREACHED */ break; } break; case DISPLAY: if (argv[++a]) globals.dname = argv[a]; break; case DISPLAYGAMMA: if (argv[++a]) globals.display_gamma = atof(argv[a]); break; case FILLSCREEN: globals.fillscreen = TRUE; break; case FIT: globals.fit = TRUE; break; case FORK: globals.do_fork = TRUE; /* background processes should be seen but not heard */ globals.verbose = FALSE; break; case FULLSCREEN: globals.fullscreen = TRUE; break; case GEOMETRY: if (argv[++a]) globals.user_geometry = argv[a]; break; case GOTO: if (argv[++a]) globals.go_to = argv[a]; break; case HELP: if (argv[++a]) do { help(argv[a++]); } while (argv[a]); else help(NULL); exit(0); case IDENTIFY: globals.identify = TRUE; break; case LIST: listImages(); exit(0); case INSTALL: globals.install = TRUE; break; case PATH: showPath(); break; case PIXMAP: globals.use_pixmap = TRUE; break; case PRIVATE: globals.private_cmap = TRUE; break; case QUIET: globals.verbose = FALSE; break; case SUPPORTED: supportedImageTypes(); break; case VERBOSE: globals.verbose = TRUE; break; case VER_NUM: version(); break; case VIEW: globals.onroot = FALSE; break; case VISUAL: if (argv[++a]) globals.visual_class = visualClassFromName(argv[a]); break; case WINDOWID: if (!argv[++a]) break; if (sscanf(argv[a], "0x%x", &globals.dest_window) != 1) { printf("Bad argument to -windowid\n"); usage(globals.argv0); /* NOTREACHED */ } globals.onroot = TRUE; /* this means "on special root" */ globals.fit = TRUE; /* assume -fit */ break; case CACHE: zforcecache(TRUE); break; case DELETE: globals.delete = TRUE; break; case FOCUS: globals.focus = TRUE; break; default: fprintf(stderr, "strange global option #%d\n", opid); exit(-1); break; } return a; } /* Do locals and return no of argv's advanced */ int doLocalOption(OptionId opid, char **argv, boolean setpersist, ImageOptions *persist_ops, ImageOptions *image_ops) { int a = 0; switch (opid) { case AT: if (!argv[++a]) break; if (sscanf(argv[a], "%d,%d", &image_ops->atx, &image_ops->aty) != 2) { printf("Bad argument to -at\n"); usage(globals.argv0); /* NOTREACHED */ } else image_ops->ats = TRUE; break; case BACKGROUND: if (argv[++a]) image_ops->bg = argv[a]; break; case BORDER: if (argv[++a]) image_ops->border = argv[a]; if (setpersist) persist_ops->border = image_ops->border; break; case BRIGHT: if (argv[++a]) { image_ops->bright = atoi(argv[a]); if (setpersist) persist_ops->bright = image_ops->bright; } break; case GAMMA: if (argv[++a]) { image_ops->gamma = atof(argv[a]); if (setpersist) persist_ops->gamma = image_ops->gamma; } break; case GRAY: image_ops->gray = 1; if (setpersist) persist_ops->gray = 1; break; case CENTER: image_ops->center = 1; break; case CLIP: if (!argv[++a]) break; if (sscanf(argv[a], "%d,%d,%d,%d", &image_ops->clipx, &image_ops->clipy, &image_ops->clipw, &image_ops->cliph) != 4) { printf("Bad argument to -clip\n"); usage(globals.argv0); /* NOTREACHED */ } break; case COLORDITHER: image_ops->colordither = 1; if (setpersist) persist_ops->colordither = 1; break; case COLORS: if (!argv[++a]) break; image_ops->colors = atoi(argv[a]); if (image_ops->colors < 2) { printf("Argument to -colors is too low (ignored)\n"); image_ops->colors = 0; } else if (image_ops->colors > 65536) { printf("Argument to -colors is too high (ignored)\n"); image_ops->colors = 0; } if (setpersist) persist_ops->colors = image_ops->colors; break; case DITHER: image_ops->dither = 1; if (setpersist) persist_ops->dither = 1; break; case EXPAND: image_ops->expand = 1; if (setpersist) persist_ops->expand = 1; break; case FOREGROUND: if (argv[++a]) image_ops->fg = argv[a]; break; case HALFTONE: image_ops->dither = 2; if (setpersist) persist_ops->dither = 2; break; case IDELAY: if (!argv[++a]) break; image_ops->delay = atoi(argv[a]); if (image_ops->delay < 0) { printf("Bad argument to -idelay\n"); usage(globals.argv0); /* NOTREACHED */ } break; case INVERT: image_ops->fg = "white"; image_ops->bg = "black"; break; case ISCALE: if (argv[++a]) { if (!strcmp(argv[a], "auto")) { image_ops->iscale_auto = TRUE; } else { image_ops->iscale = atoi(argv[a]); image_ops->iscale_auto = FALSE; } if (setpersist) { persist_ops->iscale_auto = image_ops->iscale_auto; } } break; case MERGE: image_ops->merge = 1; break; case NEWOPTIONS: if (setpersist) { persist_ops->bright = 0; persist_ops->colordither = 0; persist_ops->colors = 0; persist_ops->delay = -1; persist_ops->dither = 0; persist_ops->gray = 0; persist_ops->gamma = UNSET_GAMMA; persist_ops->normalize = 0; persist_ops->smooth = 0; persist_ops->xzoom = 0; persist_ops->yzoom = 0; } break; case NORMALIZE: image_ops->normalize = 1; if (setpersist) persist_ops->normalize = image_ops->normalize; break; case ROTATE: if (!argv[++a]) break; image_ops->rotate = atoi(argv[a]); if ((image_ops->rotate % 90) != 0) { printf("Argument to -rotate must be a multiple of 90 (ignored)\n"); image_ops->rotate = 0; } else while (image_ops->rotate < 0) image_ops->rotate += 360; break; case SMOOTH: image_ops->smooth = persist_ops->smooth + 1; if (setpersist) persist_ops->smooth = image_ops->smooth; break; case TITLE: if (argv[++a]) image_ops->title = argv[a]; break; case XPM: if (argv[++a]) { image_ops->xpmkeyc = xpmoption(argv[a]); if (image_ops->xpmkeyc != 0 && setpersist) persist_ops->xpmkeyc = image_ops->xpmkeyc; } break; case XZOOM: if (argv[++a]) { if (atoi(argv[a]) < 0) { printf("Zoom argument must be positive (ignored).\n"); break; } image_ops->xzoom = atoi(argv[a]); if (setpersist) persist_ops->xzoom = image_ops->xzoom; } break; case YZOOM: if (argv[++a]) { if (atoi(argv[a]) < 0) { printf("Zoom argument must be positive (ignored).\n"); break; } image_ops->yzoom = atoi(argv[a]); if (setpersist) persist_ops->yzoom = image_ops->yzoom; } break; case ZOOM: if (argv[++a]) { if (atoi(argv[a]) < 0) { printf("Zoom argument must be positive (ignored).\n"); break; } image_ops->xzoom = image_ops->yzoom = atoi(argv[a]); if (setpersist) persist_ops->xzoom = persist_ops->yzoom = image_ops->xzoom; } break; default: fprintf(stderr, "strange local option #%d\n", opid); exit(-1); break; } return a; } /* * Code to deal with xli trailing options */ #include "xlito.h" #include "ctype.h" void read_trail_opt(ImageOptions *image_ops, ZFILE *file, Image *image, boolean verbose) { CURRFUNC("read_trail_opt"); if (!image_ops->done_to) { /* then try and read trailing options */ char *pp, sc, buf[TOBUFSZ]; static char key[] = KEY; int nib, ti, klen, tlen; char *args; char **argv; int a; image_ops->done_to = TRUE; /* Tried to read image_ops */ klen = strlen(key); sc = key[0]; nib = zread(file, buf, TOBUFSZ); if (nib == 0) goto fail; for (pp = buf;; pp++) { for (; pp < &buf[nib] && *pp != sc; pp++); if (pp > &buf[nib - klen]) goto fail; if (strncmp(key, pp, klen) == 0) break; } /* found the first key string, so move the data down to the bottom */ nib = &buf[nib] - pp; bcopy(pp, buf, nib); /* try and fill the rest of the buffer up */ nib += zread(file, buf, TOBUFSZ - nib); /* read the length of the string */ if (!isdigit(buf[klen]) || !isdigit(buf[klen + 1]) || !isdigit(buf[klen + 2]) || !isdigit(buf[klen + 3]) || buf[klen + 4] != '"') goto fail; buf[klen + 4] = '\000'; tlen = atoi(&buf[klen]); if (nib < tlen + 2 * (klen + 5)) goto fail; /* not enough space to have read string */ /* check the second key string */ if (strncmp(key, &buf[tlen + klen + 10], klen) != 0) goto fail; ti = klen + 5 + tlen; if (buf[ti] != '"' || !isdigit(buf[ti + 1]) || !isdigit(buf[ti + 2]) || !isdigit(buf[ti + 3]) || !isdigit(buf[ti + 4])) goto fail; buf[ti + 5] = '\000'; if (tlen != atoi(&buf[ti + 1])) goto fail; args = (char *) lmalloc(tlen + 1); bcopy(&buf[klen + 5], args, tlen); args[tlen] = '\000'; /* Now we have to parse the argument string into individual arguments */ nib = parse_args(args, tlen, NULL); argv = (char **) lmalloc((nib + 2) * sizeof(char *)); argv[0] = globals.argv0; /* copy argv[0] */ argv[nib + 1] = NULL; /* mark last pointer null */ parse_args(args, tlen, argv + 1); /* parse for real now */ image_ops->to_argv = argv; /* stash this away */ /* Now parse the options */ for (a = 1; image_ops->to_argv[a] != NULL; a++) { OptionId opid; opid = optionNumber(image_ops->to_argv[a]); if (!isLocalOption(opid)) { printf("%s: Garbled or illegal trailing option ignored\n", file->filename); continue; } a += doLocalOption(opid, &image_ops->to_argv[a], FALSE, NULL, image_ops); } goto notfail; fail: /* all fails arrive here */ image_ops->to_argv = NULL; notfail:; } if (image_ops->to_argv && verbose) { /* remaind user that there are trailing options */ int a; { printf(" Found trailing options '"); for (a = 1; image_ops->to_argv[a] != NULL; a++) { printf("%s%s", a == 1 ? "" : " ", image_ops->to_argv[a]); } printf("'\n"); } } } /* Given a string "as" length "sl", parse the string into separate * NULL terminated arguments, with pointers to them placed in "argv" * If "argv" is null, parse the string and return the number of arguments */ static int parse_args(char *as, int sl, char **argv) { #define WSPACE 0 /* parser state */ #define ARG 1 #define QUOTE 2 char *sp; int no; int state = WSPACE; for (no = 0, sp = as; sp < as + sl; sp++) { switch (state) { case WSPACE: if (isspace(*sp)) break; state = ARG; no++; if (argv != NULL) *argv++ = sp; /* point to start of string */ break; case ARG: if (!isspace(*sp)) break; state = WSPACE; if (argv != NULL) *sp = '\000'; break; } } if (argv != NULL && state == ARG) /* Finish last string */ *sp = '\000'; return no; } /* * visual class to name table and back support */ 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, (char *) 0} }; int visualClassFromName(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(int class) { int a; for (a = 0; VisualClassName[a].name; a++) if (VisualClassName[a].class == class) return (VisualClassName[a].name); return ("[Unknown Visual Class]"); } xli-2006-11-10/options.h0000644000031400000060000000334007004736444014275 0ustar smarryconsole/* 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 { /* flags */ OPT_NOTOPT = 0, OPT_BADOPT, OPT_SHORTOPT, NAME, /* general options */ GENERAL_OPTIONS_START, /* marker */ DBUG, DUMPCORE, DEFAULT, DELAY, DISPLAY, DISPLAYGAMMA, FILLSCREEN, FIT, FORK, FULLSCREEN, GOTO, GEOMETRY, HELP, IDENTIFY, INSTALL, LIST, ONROOT, PATH, PIXMAP, PRIVATE, QUIET, SUPPORTED, VERBOSE, VER_NUM, VIEW, VISUAL, WINDOWID, CACHE, DELETE, FOCUS, GENERAL_OPTIONS_END, /* marker */ /* local options */ LOCAL_OPTIONS_START, /* marker */ AT, BACKGROUND, BORDER, BRIGHT, CENTER, CLIP, COLORDITHER, COLORS, DITHER, EXPAND, FOREGROUND, GAMMA, GRAY, HALFTONE, IDELAY, INVERT, MERGE, NEWOPTIONS, NORMALIZE, ROTATE, SMOOTH, TITLE, XPM, XZOOM, YZOOM, ZOOM, ISCALE, LOCAL_OPTIONS_END /* marker */ } OptionId; typedef struct option_array { char *name; /* name minus preceeding '-' */ OptionId option_id; char *args; /* arguments this option uses or NULL if none */ char *description; /* description of this option */ } OptionArray; OptionId optionNumber(char *arg); /* options.c */ #define isGeneralOption(opno) ((((int)(opno) > (int)GENERAL_OPTIONS_START) && \ ((int)(opno) < (int)GENERAL_OPTIONS_END)) \ ? TRUE : FALSE) #define isLocalOption(opno) ((((int)(opno) > (int)LOCAL_OPTIONS_START) && \ ((int)(opno) < (int)LOCAL_OPTIONS_END)) \ ? TRUE : FALSE) xli-2006-11-10/patchlevel0000644000031400000060000000024210525262416014474 0ustar smarryconsole/* this defines the version and patchlevel of this version of xli */ #define VERSION "1" #define PATCHLEVEL "17" #define AUTHOR_EMAIL "smar@reptiles.org" xli-2006-11-10/path.c0000644000031400000060000001426110525262416013530 0ustar smarryconsole/* path.c: * * functions that deal with the image path * * jim frost 10.03.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xli.h" #include #include #include #ifndef VMS #include #endif #include #include extern int errno; 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="; #define VOIDSECTION 0 #define PATHSECTION 1 #define EXTSECTION 2 static void readPathsAndExts(char *name) { FILE *f; char tokenbuf[BUFSIZ]; char buf[BUFSIZ]; char fmt[32]; unsigned int secnum, linenum, a, b, l; int c; if (!(f = fopen(name, "r"))) return; secnum = VOIDSECTION; linenum = 0; sprintf(fmt, "%%%ds", BUFSIZ - 1); while (fscanf(f, fmt, tokenbuf) > 0) { linenum++; l = strlen(tokenbuf); for (a = 0, b = 0; a < l; a++, b++) { if (tokenbuf[a] == '\\') { tokenbuf[b] = tokenbuf[++a]; } else if (b != a) { tokenbuf[b] = tokenbuf[a]; } if (tokenbuf[a] == '#') { tokenbuf[b] = '\0'; while (((c = fgetc(f)) != '\n') && (c != EOF)) ; break; } } if (!strncmp(tokenbuf, PathToken, strlen(PathToken))) { secnum = PATHSECTION; if (sscanf(tokenbuf + strlen(PathToken), "%s", buf) != 1) continue; } else if (!strncmp(tokenbuf, ExtToken, strlen(ExtToken))) { secnum = EXTSECTION; if (sscanf(tokenbuf + strlen(ExtToken), "%s", buf) != 1) continue; } else { strcpy(buf, tokenbuf); } if (buf[0] == '\0') continue; switch (secnum) { case VOIDSECTION: /* ala BASIC */ printf("%s: %d: Syntax error\n", name, linenum); fclose(f); return; case PATHSECTION: if (NumPaths < BUFSIZ - 1) Paths[NumPaths++] = expandPath(buf); else { printf("%s: %d: Path table overflow\n", name, linenum); fclose(f); return; } break; case EXTSECTION: if (NumExts < BUFSIZ - 1) Exts[NumExts++] = dupString(buf); else { printf("%s: %d: Extension table overflow\n", name, linenum); fclose(f); } break; } } } void loadPathsAndExts(void) { static int havepaths = 0; char buf[BUFSIZ]; #ifndef VMS struct passwd *pw; #endif char *homedir; if (havepaths) return; havepaths = 1; #ifdef VMS homedir = "/sys$scratch"; #else /* !VMS */ homedir = getenv("HOME"); if (!homedir || !*homedir) { if (!(pw = getpwuid(getuid()))) { printf("Cannot determine home directory."); homedir = 0; } else { homedir = pw->pw_dir; } } #endif /* !VMS */ if (homedir) { strncpy(buf, homedir, BUFSIZ); strncat(buf, "/.xlirc", BUFSIZ); buf[BUFSIZ - 1] = '\0'; if (!access(buf, R_OK)) { readPathsAndExts(buf); /* don't read system file if user has one */ return; } } #ifdef SYSPATHFILE readPathsAndExts(SYSPATHFILE); #endif } static int fileIsOk(char *fullname, struct stat *sbuf) { if ((sbuf->st_mode & S_IFMT) == S_IFDIR) { /* is a directory */ errno = EISDIR; return (-1); } /* we can read it */ return (access(fullname, R_OK)); } /* find an image with paths and extensions from defaults files. returns * -1 if access denied or not found, 0 if ok. */ int findImage(char *name, char *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++) { sprintf(fullname, "%s/%s", Paths[p], name); 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++) { sprintf(fullname, "%s/%s%s", Paths[p], 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 } } 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 } /* file not found */ errno = ENOENT; return (-1); } /* list images along our path */ void listImages(void) { 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); sprintf(buf, "ls %s", Paths[a]); if (system(buf) < 0) { perror("ls"); return; } } return; } void showPath(void) { int a; if (!NumPaths && !NumExts) { printf("No image paths or extensions\n"); return; } if (NumPaths) { printf("Image path:"); for (a = 0; a < NumPaths; a++) printf(" %s", Paths[a]); printf("\n"); } if (NumExts) { printf("Image extensions:"); for (a = 0; a < NumExts; a++) printf(" %s", Exts[a]); printf("\n"); } } char *expandPath(char *p) { char buf1[BUFSIZ], buf2[BUFSIZ]; int b1, b2, var; char *ptr; char *getenv(const char *); CURRFUNC("expandPath"); buf1[0] = '\0'; buf2[0] = '\0'; b1 = 0; b2 = 0; var = 0; while (*p) { if (isspace(*p)) break; if (*p == '$') var++; 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 (char *) 0; } } xli-2006-11-10/pbm.c0000644000031400000060000002643710525262416013362 0ustar smarryconsole/* 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 "xli.h" #include "imagetypes.h" #include "pbm.h" 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(void) { 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(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(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 pbmReadRawInt(ZFILE * zf, int depth) { int i, src, src2; src = 0; for (i = 0; i < depth; i += 8) { if ((src2 = zgetc(zf)) == EOF) return EOF; src = (src << 8) | src2; } return src; } static int isPBM(ZFILE * zf, char *name, unsigned int *width, unsigned int *height, unsigned int *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(char *fullname, char *name) { ZFILE *zf; unsigned 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(char *fullname, ImageOptions * image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; Image *image = 0; int pbm_type; unsigned int x, y; unsigned int width, height, maxval, fmaxval, depth, fdepth; unsigned int linelen; byte srcmask, destmask; byte *destptr = 0, *destline; int src = -1, size; unsigned int numbytes, numread; 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); image->title = dupString(name); 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, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } if (IntTable[src] == NOTINT) { fprintf(stderr, "pbmLoad: %s - Bad image data\n", name); 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, "pbmLoad: %s - Bad image data\n", name); zclose(zf); return (image); } } destline += linelen; } break; case PBMRAWBITS: image = newBitImage(width, height); image->title = dupString(name); destline = image->data; linelen = (width + 7) / 8; numbytes = linelen * height; srcmask = 0; /* force initial read */ numread = 0; for (y = 0; y < height; y++) { destptr = destline; destmask = 0x80; if (srcmask != 0x80) { srcmask = 0x80; if ((numread < numbytes) && ((src = zgetc(zf)) == EOF)) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } numread++; } for (x = 0; x < width; x++) { if (src & srcmask) *destptr |= destmask; if (!(destmask >>= 1)) { destmask = 0x80; destptr++; } if (!(srcmask >>= 1)) { srcmask = 0x80; if ((numread < numbytes) && ((src = zgetc(zf)) == EOF)) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } numread++; } } destline += linelen; } break; case PBMCOMPACT: image = newBitImage(width, height); image->title = dupString(name); destline = image->data; linelen = (width / 8) + (width % 8 ? 1 : 0); srcmask = 0x80; destmask = 0x80; if ((src = zgetc(zf)) == EOF) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } numread = 1; numbytes = width * height; numbytes = (numbytes / 8) + (numbytes % 8 ? 1 : 0); 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; if ((numread < numbytes) && ((src = zgetc(zf)) == EOF)) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } numread++; } } destline += linelen; } break; case PGMRAWBITS: fmaxval = maxval; if (maxval > 0xff) maxval = 0xff; depth = colorsToDepth(maxval + 1); image = newRGBImage(width, height, depth); /* use simple ramp for grey scale */ for (y = 0; y <= maxval; y++) { *(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; image->gamma = 1.0; /* overide xli IRGB guess */ image->title = dupString(name); size = height * width; if (fmaxval <= 0xff) { /* read in the image in a chunk */ if (zread(zf, image->data, size) != size) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } } else { destptr = image->data; fdepth = colorsToDepth(fmaxval + 1); for (y = 0; y < size; y++) { if ((src = pbmReadRawInt(zf, fdepth)) == EOF) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } *(destptr++) = PM_SCALE(src, fmaxval, 0xff); } } break; case PGMNORMAL: fmaxval = maxval; if (maxval > 0xff) maxval = 0xff; depth = colorsToDepth(maxval + 1); 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; image->gamma = 1.0; /* overide xli IRGB guess */ image->title = dupString(name); destptr = image->data; size = height * width; for (y = 0; y < size; y++) { if ((src = pbmReadInt(zf)) < 0) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } *(destptr++) = PM_SCALE(src, fmaxval, 0xff); } break; case PPMRAWBITS: /* this is nice because the bit format is exactly what we want * except for scaling. */ image = newTrueImage(width, height); image->title = dupString(name); size = height * width * 3; if (maxval <= 0xff) { if (zread(zf, image->data, size) != size) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } if (maxval != 0xff) { destptr = image->data; for (y = 0; y < size; y++) { *destptr = PM_SCALE(*destptr, maxval, 0xff); destptr++; } } } else { destptr = image->data; fdepth = colorsToDepth(maxval + 1); for (y = 0; y < size; y++) { if ((src = pbmReadRawInt(zf, fdepth)) == EOF) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } *(destptr++) = PM_SCALE(src, maxval, 0xff); } } break; case PPMNORMAL: image = newTrueImage(width, height); image->title = dupString(name); size = height * width * 3; destptr = image->data; for (y = 0; y < size; y++) { if ((src = pbmReadInt(zf)) == EOF) { fprintf(stderr, "pbmLoad: %s - Short image\n", name); zclose(zf); return (image); } *(destptr++) = PM_SCALE(src, maxval, 0xff); } break; } read_trail_opt(image_ops, zf, image, verbose); zclose(zf); return (image); } xli-2006-11-10/pbm.h0000644000031400000060000000041706461630121013351 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/pbm.h 6.7 93/07/23 Labtam" */ /* 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) xli-2006-11-10/pcd.c0000644000031400000060000006457610525262416013360 0ustar smarryconsole/* * Read a Photograph on CD format image. * * Created for xli by Graeme Gill, * * based on information (and some code) from xvphotocd by David Clunie, * * which was based on information from hpcdtoppm by Hadmut Danisch. * */ #include "xli.h" #include "imagetypes.h" #include "pcd.h" #undef TEST_DELTA static int read_baseband(pcdHeader *hp, int toff, int sf); static void upsample(pcdHeader *hp, byte *data, int sf); static void pcd_ycc_rgb_init(void); static void pcd_ycc_to_rgb(pcdHeader *hp, Image *image); static void rot_block(byte *Lp, byte *C1p, byte *C2p, int hii, int vii, byte *op, int voi, int w, int h); static huff *gethufftable(pcdHeader *hp, int *size); static int gethuffdata(pcdHeader * hp, int p, int tb, int db, int sf); /* Read a block into the buffer and update the off counter. */ /* If size is > PCDBLOCK, skip blocks and read size % PCDBLOCK */ /* return TRUE on error */ static boolean pcd_read(pcdHeader *hp, long unsigned int size) { /* Read in the header block */ while (size > PCDBLOCK) { if (zread(hp->zf, hp->buf, PCDBLOCK) != PCDBLOCK) return TRUE; size -= PCDBLOCK; hp->off += hp->nob; hp->nob = PCDBLOCK; } if (zread(hp->zf, hp->buf, size) != size) return TRUE; hp->off += hp->nob; hp->nob = size; /* Reset the bit read stuff */ hp->bp = hp->buf; hp->bytes_left = size; return FALSE; } /* Read a block into the specified buffer and update the off counter. */ /* return TRUE on error */ static boolean pcd_read_to_buf(pcdHeader *hp, byte *buf, long unsigned int size) { if (zread(hp->zf, buf, size) != size) return TRUE; hp->off += (hp->nob + size); hp->nob = 0; /* Reset the bit read stuff */ hp->bytes_left = 0; return FALSE; } /* Read data to align file with the given offset */ /* The next read will be data starting at that offset */ /* (Need to do this or pcd_skip_blocks() before using */ /* bit fetch macros) */ static boolean pcd_skip(pcdHeader * hp, long unsigned int toff) { if (toff < pcd_offset(hp)) { fprintf(stderr, "pcdLoad: internal error - tried to seek backwards\n"); return TRUE; } if (toff > pcd_offset(hp)) if (pcd_read(hp, toff - pcd_offset(hp))) return TRUE; /* Clear the byte/bit read stuff, */ /* so it will fetch from aligned address. */ hp->bits = 0; hp->bytes_left = 0; hp->bits_left = 0; return FALSE; } /* Skip to the end of the current block. */ static boolean pcd_skip_eob(pcdHeader * hp) { unsigned int toff; toff = ((pcd_offset(hp) + PCDBMASK) >> PCDSHIFT); return (pcd_skip(hp, toff * PCDBLOCK)); } /* Read the header of the file, and */ /* Return TRUE if this looks like a pcd file */ static boolean read_pcdHeader(pcdHeader * hp, char *name) { int i, w, h, sz; CURRFUNC("read_pcdHeader"); if (zread(hp->zf, hp->buf, 32) != 32) return FALSE; /* See if it is consistent with a pcd files */ for (i = 0; i < 32; i++) if (hp->buf[i] != 0xff) return FALSE; znocache(hp->zf); /* Read in the rest of the block */ if (zread(hp->zf, &hp->buf[32], PCDBLOCK - 32) != PCDBLOCK - 32) return FALSE; hp->off = 0; hp->nob = PCDBLOCK; /* Read in the header block */ if (pcd_read(hp, PCDBLOCK)) return FALSE; /* Image format ident string (?) */ bcopy(&hp->buf[0x0800 & PCDBMASK], hp->magic, 7); hp->magic[7] = '\000'; if (strcmp(hp->magic, "PCD_IPI") != 0) return FALSE; /* ? */ /* Source (?) */ bcopy(&hp->buf[0x0816 & PCDBMASK], hp->source, 88); hp->source[88] = '\000'; /* Owner (?) */ bcopy(&hp->buf[0x0870 & PCDBMASK], hp->owner, 20); hp->owner[20] = '\000'; /* Image orientation */ switch (hp->buf[0x0e02 & PCDBMASK] & 3) { case 0: hp->rotate = PCD_NO_ROTATE; break; case 1: hp->rotate = PCD_ACLOCK_ROTATE; break; case 3: hp->rotate = PCD_CLOCK_ROTATE; break; default: fprintf(stderr, "pcd: warning, unrecognized image orientation\n"); hp->rotate = PCD_NO_ROTATE; break; } /* Figure out the default size of the image (allowing for rotation) */ if (hp->rotate == PCD_NO_ROTATE) w = BASEW * 4, h = BASEH * 4; else w = BASEH * 4, h = BASEW * 4; for (sz = SZ_16B;; sz--, w /= 2, h /= 2) { if (sz == SZ_B16 || (w <= hp->width && h <= hp->height && ((w * 2) > hp->width || (h * 2) > hp->height))) { hp->size = sz; hp->width = w; hp->height = h; break; } } /* Re-compute for best quality zoom */ /* (should actually compute zoom up for speed, */ /* and zoom down when "quality" flag selected.) */ if ((hp->xzoom != 0 && hp->xzoom != 100) || (hp->yzoom != 0 && hp->yzoom != 100)) { int tw, th; if (hp->xzoom != 0 && hp->xzoom != 100) tw = (int) ((float) hp->width * (float) hp->xzoom / 100.0 + 0.5); else tw = hp->width; if (hp->yzoom != 0 && hp->yzoom != 100) th = (int) ((float) hp->height * (float) hp->yzoom / 100.0 + 0.5); else th = hp->height; /* Set for PCD size larger than requested size */ if (hp->rotate == PCD_NO_ROTATE) w = BASEW / 4, h = BASEH / 4; else w = BASEH / 4, h = BASEW / 4; for (sz = SZ_B16;; sz++, w *= 2, h *= 2) { if (sz == SZ_16B || (w >= tw && h >= th)) { hp->size = sz; hp->width = w; hp->height = h; hp->xzoom = (unsigned int) ((float) tw / (float) w * 100.0 + 0.5); hp->yzoom = (unsigned int) ((float) th / (float) h * 100.0 + 0.5); break; } } } /* Return un-rotated dimentions */ if (hp->rotate != PCD_NO_ROTATE) { int t; t = hp->width; hp->width = hp->height; hp->height = t; } hp->name = name; return TRUE; } /* Print a brief description of the image */ static void tell_about_pcd(pcdHeader * hp) { printf("%s is a %dx%d Photograph on CD Image%s\n", hp->name, hp->rotate == PCD_NO_ROTATE ? hp->width : hp->height, hp->rotate == PCD_NO_ROTATE ? hp->height : hp->width, hp->rotate == PCD_ACLOCK_ROTATE ? " (On right side)" : hp->rotate == PCD_CLOCK_ROTATE ? " (On left side)" : ""); } int pcdIdent(char *fullname, char *name) { pcdHeader hdr; CURRFUNC("pcdIdent"); if (!(hdr.zf = zopen(fullname))) { perror("pcdIdent"); return (0); } /* Set a target width and height to the display size */ hdr.width = globals.dinfo.width; hdr.height = globals.dinfo.height; if (!read_pcdHeader(&hdr, name)) { zclose(hdr.zf); return 0; /* Nope, not a PCD file */ } tell_about_pcd(&hdr); zclose(hdr.zf); return 1; } Image *pcdLoad(char *fullname, ImageOptions * image_ops, boolean verbose) { pcdHeader hdr; Image *image; unsigned long toff; int sf; /* target/current image size */ CURRFUNC("pcdLoad"); if (!(hdr.zf = zopen(fullname))) { perror("pcdIdent"); return (0); } /* Set a target width and height to the */ /* screen size. */ hdr.width = globals.dinfo.width * 1.0; hdr.height = globals.dinfo.height * 1.0; hdr.xzoom = image_ops->xzoom; hdr.yzoom = image_ops->yzoom; if (!read_pcdHeader(&hdr, image_ops->name)) { zclose(hdr.zf); return NULL; /* Nope, not a Photograph on CD file */ } if (verbose) tell_about_pcd(&hdr); znocache(hdr.zf); image = newTrueImage(hdr.width, hdr.height); image->title = dupString(hdr.name); image_ops->xzoom = hdr.xzoom; image_ops->yzoom = hdr.yzoom; hdr.Lp = image->data; hdr.C1p = hdr.Lp + (image->width * image->height); hdr.C2p = hdr.C1p + (image->width * image->height); toff = 0; switch (hdr.size) { case SZ_B16: toff = 4 * PCDBLOCK; sf = 1; break; case SZ_B4: toff = 23 * PCDBLOCK; sf = 1; break; case SZ_B: toff = 96 * PCDBLOCK; sf = 1; break; case SZ_4B: toff = 96 * PCDBLOCK; sf = 2; break; case SZ_16B: toff = 96 * PCDBLOCK; sf = 4; break; default: fprintf(stderr, "pcdLoad: unknown size %d\n", hdr.size); goto data_error; break; } /* Read the baseband image */ if (read_baseband(&hdr, toff, sf)) goto data_error; /* Need to up-sample C1 and C2 */ upsample(&hdr, hdr.C1p, sf); upsample(&hdr, hdr.C2p, sf); /* Up sample all components for greater than baseline sizes */ if (sf >= 2) { if (pcd_skip(&hdr, 384 * PCDBLOCK)) /* skip to start of greater than base stuff */ goto data_short; sf /= 2; upsample(&hdr, hdr.Lp, sf); /* upsample luma */ gethuffdata(&hdr, 1, 4, 5, sf); /* Add luma delta */ upsample(&hdr, hdr.C1p, sf); /* upsample chroma */ upsample(&hdr, hdr.C2p, sf); if (sf >= 2) { if (pcd_skip_eob(&hdr)) /* Round up to next block */ goto data_short; sf /= 2; upsample(&hdr, hdr.Lp, sf); /* upsample luma */ gethuffdata(&hdr, 3, 12, 14, sf); /* Add luma and chroma delta */ upsample(&hdr, hdr.C1p, sf); /* upsample chroma */ upsample(&hdr, hdr.C2p, sf); } } /* Need to convert LC1C2 to RGB */ pcd_ycc_to_rgb(&hdr, image); zclose(hdr.zf); image->gamma = 2.05; /* Approximate CCIR 709 */ return image; data_short: fprintf(stderr, "pcdLoad: %s - Short read within Data\n", hdr.name); data_error: zclose(hdr.zf); return image; } /* Read baseband image components in */ /* toff: File block offset to read components from */ /* sf: Scale factor down from image size */ int read_baseband(pcdHeader * hp, int toff, int sf) { int h, w, hw; byte *Lp, *C1p, *C2p; w = hp->width / sf; /* width */ hw = w / 2; /* Half width */ /* skip data to start of appropriate block */ if (pcd_skip(hp, toff)) goto data_short; /* Read in an image */ for (h = hp->height / (2 * sf), Lp = hp->Lp, C1p = hp->C1p, C2p = hp->C2p; h > 0; h--) { /* First row of luma */ if (pcd_read_to_buf(hp, Lp, w)) goto data_short; Lp += w; /* Second row of luma */ if (pcd_read_to_buf(hp, Lp, w)) goto data_short; Lp += w; /* C1 + C2 */ if (pcd_read_to_buf(hp, C1p, hw)) goto data_short; C1p += hw; if (pcd_read_to_buf(hp, C2p, hw)) goto data_short; C2p += hw; } return FALSE; data_short: fprintf(stderr, "pcd: Short data read in baseband data\n"); return TRUE; } /* xvphotocd upsample */ /* The input pixels are at the top left of each resulting four * pixels. Pixels directly between the input pixels are * the average of adjacent pixels. The remaing pixels * are the average of the four diagonal input pixels. */ void upsample(pcdHeader * hp, byte * data, int sf) /* start point */ /* Output target/curret size */ { int x, y; int w, hw, h, hh; /* Width, half width, height, half height */ int v1, v2; /* Upper input values */ int v3, v4; /* Lower input values */ byte *ui, *li; /* upper/lower input pointers */ byte *uo, *lo; /* upper/lower output pointers */ w = hp->width / sf; hw = w / 2; h = hp->height / sf; hh = h / 2; ui = li = uo = lo = 0; for (y = 0; y < h;) { if (y == 0) { ui = li = data + (hw * hh) - 1; /* last input pixel */ uo = lo = data + (w * h) - 1; /* last output pixel */ y++; } else if (y == (h - 1)) { uo = lo; ui = li; y++; } else y += 2; /* First pixel */ v2 = *li; li -= 1; v4 = *ui; ui -= 1; /* v2 = v2 */ v4 = v4 + v2; /* First pixel in line */ *lo = v2; lo -= 1; *uo = (v4 + 1) >> 1; uo -= 1; /* Do middle of double line two pixels at a time */ for (x = 3; x < w; x += 2) { v1 = v2; v2 = *li; li -= 1; v3 = v4; v4 = *ui; ui -= 1; /* v2 = v2 */ v4 = v4 + v2; *lo = v1; *(lo - 1) = (v1 + v2 + 1) >> 1; lo -= 2; *uo = (v3 + 1) >> 1; *(uo - 1) = (v3 + v4 + 2) >> 2; uo -= 2; } /* Last pixel in line */ *lo = v2; *uo = (v4 + 1) >> 1; /* Bump input and output pointer to the next double line */ /* ui = ui */ li = ui + hw; lo = uo - 1; uo -= (w + 1); } } /* * LC1C2 to RGB * * Currently just an approximation, since PCD * is (?) really CCIR 601-1 with CCIR 709 primaries, * and what is used below is just an approximation. * * The following code is based on IJPG code. */ #define SCALEBITS 16 #define ONE_HALF ((int) 1 << (SCALEBITS-1)) #define FIX(x) ((int) ((x) * (1< table for L to caley y conversion */ static int *pcdC2_r_tab; /* => table for C2 to R conversion */ static int *pcdC1_b_tab; /* => table for C1 to B conversion */ static int *pcdC2_g_tab; /* => table for C2 to G conversion */ static int *pcdC1_g_tab; /* => table for C1 to G conversion */ /* * Initialize for colorspace conversion. */ void pcd_ycc_rgb_init(void) { int i; CURRFUNC("pcd_ycc_rgb_init"); pcdlimit = 256 + (byte *) lmalloc(3 * 256 * sizeof(byte)); for (i = -256; i < 512; i++) { if (i < 0) pcdlimit[i] = 0; else if (i > 255) pcdlimit[i] = 255; else pcdlimit[i] = i; } pcdround = &roundtab[256]; pcdL_y_tab = (int *) lmalloc(256 * sizeof(int)); pcdC2_r_tab = (int *) lmalloc(256 * sizeof(int)); pcdC1_b_tab = (int *) lmalloc(256 * sizeof(int)); pcdC2_g_tab = (int *) lmalloc(256 * sizeof(int)); pcdC1_g_tab = (int *) lmalloc(256 * sizeof(int)); for (i = 0; i < 256; i++) { int C2, C1; /* PCD is supposed to be variation on CCIR 601-1 YCrCb * It seems that the L channel 100% (diffuse reflection) * is set at 182 (although images seem to exceed this value), * the C1 zero at 156, and the C2 zero at 137. * The Conversion to RGB is supposed to be: * R = L + C2 * G = L - 0.194 C1 - 0.509 C2 * B = L + C1 * * The primaries are supposed to be CCIR 709 [HDTV], which * are slightly different to the normal SMPTE-C RGB primaries. * The gamma is suposed to be CCIR 709 - that is linear below * 0.018, and exp 1/0.45 above, rather than the SMPTE-C exp 2.2. * * exp 2.05 is used as an approximation. * * The following conversion scales RGB by 255/182 to make sure * that maximum L gives 255,255,255. This probably causes some * clipping. No correction is currently made for CCIR 709 -> * SMPTE-C primaries. */ C1 = (i - 156); C2 = (i - 137); #define MAXL 182.0 pcdL_y_tab[i] = (int) (FIX(255.0 / MAXL) * i + ONE_HALF); pcdC2_r_tab[i] = (int) (FIX(255.0 / MAXL * 1.0) * C2); pcdC1_b_tab[i] = (int) (FIX(255.0 / MAXL * 1.0) * C1); pcdC2_g_tab[i] = (int) (-FIX(255.0 / MAXL * 0.509) * C2); pcdC1_g_tab[i] = (int) (-FIX(255.0 / MAXL * 0.194) * C1); } } /* * Convert some rows of samples to the output colorspace. * (do rotation at the same time if needed) */ void pcd_ycc_to_rgb(pcdHeader * hp, Image * image) { byte *Lp, *C1p, *C2p; unsigned char *odat; int x, y, w, h; CURRFUNC("pcd_ycc_to_rgb"); /* Allocate some output data area */ odat = (unsigned char *) lmalloc(image->width * image->height * 3); if (pcdlimit == NULL) pcd_ycc_rgb_init(); /* We do rotation in blocks to minimize */ /* virtual memory thrashing on big images. */ #define RBLOCK 128 /* rotate blocking */ Lp = hp->Lp; C1p = hp->C1p; C2p = hp->C2p; /* Image orientation */ switch (hp->rotate) { case PCD_NO_ROTATE: w = image->width; h = image->height; rot_block(Lp, C1p, C2p, 1, w, odat, w * 3, w, h); break; case PCD_ACLOCK_ROTATE: w = image->height; h = image->width; for (y = 0; y < h; y += RBLOCK) { int soff, ww, wh; wh = h - y; if (wh > RBLOCK) wh = RBLOCK; for (x = 0; x < w; x += RBLOCK) { ww = w - x; if (ww > RBLOCK) ww = RBLOCK; soff = h - 1 - y + (x * h); rot_block(Lp + soff, C1p + soff, C2p + soff, h, -1, odat + 3 * (x + (y * w)), w * 3, ww, wh); } } image->width = w; image->height = h; break; case PCD_CLOCK_ROTATE: w = image->height; h = image->width; for (y = 0; y < h; y += RBLOCK) { int soff, ww, wh; wh = h - y; if (wh > RBLOCK) wh = RBLOCK; for (x = 0; x < w; x += RBLOCK) { ww = w - x; if (ww > RBLOCK) ww = RBLOCK; soff = (w - 1 - x) * h + y; rot_block(Lp + soff, C1p + soff, C2p + soff, -h, 1, odat + 3 * (x + (y * w)), w * 3, ww, wh); } } image->width = w; image->height = h; break; } lfree(image->data); image->data = odat; } /* Rotate and convert a rectangular block */ void rot_block(byte * Lp, byte * C1p, byte * C2p, int hii, int vii, byte * op, int voi, int w, int h) /* Input start pointers */ /* Horizontal/virtical input increments */ /* Output pointer */ /* Virtical output increment */ { int x, y; voi -= w * 3; /* account for horizontal movement */ vii -= w * hii; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { int l, c1, c2; l = *Lp; c1 = *C1p; c2 = *C2p; l = pcdL_y_tab[l]; *op = pcdround[(l + pcdC2_r_tab[c2]) >> SCALEBITS]; *(op + 1) = pcdround[(l + pcdC1_g_tab[c1] + pcdC2_g_tab[c2]) >> SCALEBITS]; *(op + 2) = pcdround[(l + pcdC1_b_tab[c1]) >> SCALEBITS]; op += 3; Lp += hii; C1p += hii; C2p += hii; } op += voi; Lp += vii; C1p += vii; C2p += vii; } } /* Huffman encoded data functions. */ /* Read the huffman tables which consist of an unsigned byte giving the number of entries -1, followed by table entries, each of which is a series of 4 unsigned bytes - length, highseq, lowseq, and key. length is the number of bits of the huffman code -1. highseq and lowseq are the huffman code which is msb justified. key is the data value corresponding to that code. The huffman table is stored into an array huff structures. The huff structure holds the length in bits of the corresponding code, and the decoded data value. If the length of the code is less than the size of the array. then the array will contain aliases of that code for every combination of the unused bits. This way the huffman decoding becomes a straight table lookup. Note that the array must be the size of the longest code. */ #define get_byte(dest,hp) \ { \ if ((hp)->bytes_left <= 0) \ if (pcd_read((hp),PCDBLOCK)) \ goto data_short; \ --(hp)->bytes_left; \ dest = *((hp)->bp++); \ } #define EMPTYHUFF (-32768) /* nonsense value */ static huff * gethufftable(pcdHeader * hp, int *size) /* Table length return value */ { unsigned num, i; huff *hufftab = NULL; boolean lht = FALSE; /* Set if large (16 bit) huffman table */ get_byte(num, hp); num++; /* Allocate double space to allow for branch nodes */ hufftab = (huff *) lmalloc(sizeof(huff) * (1 << 12)); bfill(hufftab, sizeof(huff) * (1 << 12), 0xff); for (i = 0; i < num; i++) { unsigned int length, codeword, value; unsigned int j, k; get_byte(length, hp); length++; /* Bit length of code word */ get_byte(codeword, hp); /* ms byte of codeword */ get_byte(value, hp); /* ls byte of codeword */ codeword = (codeword << 8) | value; get_byte(value, hp); /* decoded value */ if (length > 12) { if (!lht) { int sz; /* Switch to large (16 bit) huffman table */ hufftab = (huff *) lrealloc((byte *)hufftab, sizeof(huff) * (1 << 16)); for (sz = sizeof(huff) * (1 << 12); sz < (sizeof(huff) * (1 << 16)); sz *= 2) bcopy((byte *) hufftab, ((byte *) hufftab) + sz, sz); lht = TRUE; } if (length > 16) { fprintf(stderr, "pcd: Huffman table corrupted\n"); goto data_error; } } j = codeword; k = codeword + (1 << (16 - length)); if (!lht) { j >>= (16 - 12); k >>= (16 - 12); } for (; j < k; j++) { hufftab[j].l = length; hufftab[j].v = value; } } *size = lht ? 16 : 12; return hufftab; data_short: fprintf(stderr, "pcd: Short data read in huffman table\n"); data_error: if (hufftab != NULL) lfree((byte *) hufftab); return NULL; } /* We keep the current bits left justified in hp->bits, */ /* and return bits right justified. */ #define BITS_PER_WORD (sizeof(unsigned int)*8) #define load_byte(hp) \ { \ if ((hp)->bytes_left <= 0) \ if (pcd_read((hp),PCDBLOCK)) \ goto data_short; \ --(hp)->bytes_left; \ (hp)->bits_left += 8; \ (hp)->bits |= ((unsigned int)(*((hp)->bp++))) << (BITS_PER_WORD - (hp)->bits_left); \ } /* Get (and consume) 1 bit */ #define get1bit(dest, hp) \ { \ if ((hp)->bits_left < 1) \ load_byte(hp); \ (dest) = (hp)->bits >> (BITS_PER_WORD - 1); \ (hp)->bits_left--; \ (hp)->bits <<= 1; \ } /* Get (and consume) nb bits */ #define getbits(dest, hp, nb) \ { \ while ((hp)->bits_left < nb) \ load_byte(hp); \ (dest) = (hp)->bits >> (BITS_PER_WORD - nb); \ (hp)->bits_left -= nb; \ (hp)->bits <<= nb; \ } /* Get nb bits without consuming them */ #define nextbits(dest, hp, nb) \ { \ while ((hp)->bits_left < nb) \ load_byte(hp); \ (dest) = (hp)->bits >> (BITS_PER_WORD - nb); \ } /* Consume nb bits */ #define skipbits(hp,nb) \ { \ while ((hp)->bits_left < nb) \ load_byte(hp); \ (hp)->bits_left -= nb; \ (hp)->bits <<= nb; \ } /* Consume nb bits (assuming previous nextbits( >= nb)) */ #define usedbits(hp,nb) \ { \ (hp)->bits_left -= nb; \ (hp)->bits <<= nb; \ } static int huff_sizes[3]; /* Sizes of huffman tables */ static huff *huffs[3]; /* Pointers to huffman tables */ static int gethuffdata(pcdHeader * hp, int p, int tb, int db, int sf) /* Number of planes expected */ /* Table and Data block offsets from where file is now */ /* scale factor from final size */ { byte *Lp, *C1p, *C2p; unsigned int bits; unsigned int soff; int w, h; /* width, height */ int i; Lp = hp->Lp; C1p = hp->C1p; C2p = hp->C2p; w = hp->width / sf; h = hp->height / sf; if (pcdlimit == NULL) pcd_ycc_rgb_init(); soff = pcd_offset(hp); /* where we are now */ if (pcd_skip(hp, soff + tb * PCDBLOCK)) /* skip to huffman table(s) */ goto data_short; huffs[0] = huffs[1] = huffs[2] = NULL; for (i = 0; i < p; i++) if ((huffs[i] = gethufftable(hp, &huff_sizes[i])) == NULL) goto data_error; if (pcd_skip(hp, soff + db * PCDBLOCK)) /* skip to huffman data */ goto data_short; for (;;) { /* skip until sync */ nextbits(bits, hp, 24); if (bits == 0xfffffe) break; usedbits(hp, 24); } for (;;) { /* Grab pixel data */ huff *hufft = 0; int huffsz = -1; byte *dp = 0; int wsf = 0; int col = 0; nextbits(bits, hp, 24); if (bits == 0xfffffe) { /* Found a sync marker */ int plane; static int pmap[4] = {0, 3, 1, 2}; int wvi; int row; usedbits(hp, 24); getbits(plane, hp, 2); /* New line/plane header */ plane = pmap[plane]; getbits(row, hp, 13); getbits(bits, hp, 1); if (plane > p) { fprintf(stderr, "pcd: Illegal plane number in huffman data\n"); goto data_error; } hufft = huffs[plane]; huffsz = huff_sizes[plane]; wsf = plane != 0 ? 2 : 1; wvi = w / wsf; if ((row * wsf) >= h) { if ((row * wsf) == h) break; fprintf(stderr, "pcd: Huffman data exceeds image size\n"); goto data_error; } dp = plane == 0 ? Lp : plane == 1 ? C1p : C2p; dp += row * wvi; col = 0; continue; } /* Not sync, must be another pixel delta */ if (col >= w) { fprintf(stderr, "pcd: Huffman data exceeds image size\n"); goto data_error; } if (huffsz == 12) { int sh, sum; bits >>= (24 - 12); sh = hufft[bits].l; sum = hufft[bits].v; if (sh > 12) { fprintf(stderr, "pcd: Unknown huffman data code\n"); goto data_error; } usedbits(hp, sh); sum += *dp; *dp = pcdlimit[sum]; dp += 1; col += wsf; } else { /* huffsz == 16 */ int sh, sum; bits >>= (24 - 16); sh = hufft[bits].l; sum = hufft[bits].v; if (sh > 16) { fprintf(stderr, "pcd: Unknown huffman data code\n"); goto data_error; } usedbits(hp, sh); sum += *dp; *dp = pcdlimit[sum]; dp += 1; col += wsf; } } for (i = 0; i < p; i++) if (huffs[i] != NULL) lfree((byte *) huffs[i]); return FALSE; data_short: fprintf(stderr, "pcd: Short data read in huffman data\n"); data_error: for (i = 0; i < p; i++) if (huffs[i]) if (huffs[i] != NULL) lfree((byte *) huffs[i]); return TRUE; } xli-2006-11-10/pcd.h0000644000031400000060000000270006461630121013336 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/pcd.h 1.2 94/07/29 Labtam" */ /* */ /* * pcd.h - header file for Photograph on CD image files. */ #define PCDSHIFT 11 #define PCDBLOCK (1 << PCDSHIFT) #define PCDBMASK (PCDBLOCK-1) #define BASEW 768 #define BASEH 512 #define SZ_B16 -2 #define SZ_B4 -1 #define SZ_B 0 #define SZ_4B 1 #define SZ_16B 2 #define PCD_NO_ROTATE 0 #define PCD_ACLOCK_ROTATE 1 #define PCD_CLOCK_ROTATE 2 /* PCD image information */ typedef struct { ZFILE *zf; unsigned long off; /* File byte offset of the start of the buffer */ int nob; /* Number of bytes currently in buffer */ byte buf[PCDBLOCK]; /* current block data */ byte *bp; /* Current byte pointer */ unsigned int bits; /* bits buffer */ int bytes_left; /* Bytes left from *bp */ int bits_left; /* Bits left in bits */ char *name; /* stash pointer to name here too */ char magic[8]; /* image format ident string (?) */ char source[89]; /* source (?) */ char owner[21]; /* owner (?) */ int rotate; /* rotation needed */ int size; /* Size code */ int width,height; /* Target width/height */ unsigned int xzoom,yzoom; /* User specified zoom percentages */ byte *Lp,*C1p,*C2p; /* Pointers to the color components */ } pcdHeader; /* Huffman entry (16 bit signed int) */ typedef struct { byte l; /* number of bits */ sbyte v; /* value */ } huff; /* The file offset of the next read */ #define pcd_offset(hp) ((hp)->off + (hp)->nob) xli-2006-11-10/pcx.c0000644000031400000060000001160707004736445013375 0ustar smarryconsole/* ** pcx.c - load a ZSoft PC Paintbrush (PCX) file for use inside xli ** ** 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 "tgncpyrght.h" #include "xli.h" #include "imagetypes.h" #define PCX_MAGIC 0x0a /* first byte in a PCX image file */ static boolean PCX_LoadImage(ZFILE *zf, int in_bpr, int img_bpr, Image *image, int rows); /* Routine to load a PCX file */ /* ** pcxIdent ** ** Identify passed file as a PC Paintbrush image or not ** ** Returns 1 if file is a PCX file, 0 otherwise */ int pcxIdent(char *fullname, char *name) { ZFILE *zf; int ret; int xmin; int xmax; int ymin; int ymax; unsigned char pcxhd[128]; ret = 0; if (! (zf = zopen(fullname))) { perror("pcxIdent"); return(0); } /* Read .pcx header. */ if (zread(zf,pcxhd,128) == 128) { if (pcxhd[0] == PCX_MAGIC) { /* Calculate raster header and swap bytes. */ xmin = pcxhd[4] + ( 256 * pcxhd[5] ); ymin = pcxhd[6] + ( 256 * pcxhd[7] ); xmax = pcxhd[8] + ( 256 * pcxhd[9] ); ymax = pcxhd[10] + ( 256 * pcxhd[11] ); xmax = xmax - xmin + 1; ymax = ymax - ymin + 1; printf("%s is a %dx%d PC Paintbrush image\n", name,xmax,ymax); ret = 1; } } zclose(zf); return(ret); } /* ** pcxLoad ** ** Load PCX Paintbrush file into an Image structure. ** ** Returns pointer to allocated struct if successful, NULL otherwise */ Image *pcxLoad (char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; unsigned char pcxhd[128]; int xmin; int xmax; int ymin; int ymax; int in_bpr; /* in input format bytes per row */ int img_bpr; /* xli image format bytes per row */ register Image *image; /* Open input file. */ if ( ! (zf = zopen(fullname))) { perror("pcxLoad"); return((Image *)NULL); } /* Read .pcx header. */ if (zread(zf,pcxhd,128) != 128) { zclose(zf); return((Image *)NULL); } if ((pcxhd[0] != PCX_MAGIC) || (pcxhd[1] > 5)) { zclose(zf); return((Image *)NULL); } /* Calculate raster header and swap bytes. */ xmin = pcxhd[4] + ( 256 * pcxhd[5] ); ymin = pcxhd[6] + ( 256 * pcxhd[7] ); xmax = pcxhd[8] + ( 256 * pcxhd[9] ); ymax = pcxhd[10] + ( 256 * pcxhd[11] ); xmax = xmax - xmin + 1; ymax = ymax - ymin + 1; in_bpr = pcxhd[66] + ( 256 * pcxhd[67] ); img_bpr = (xmax + 7)/8; /* assumes monochrome image */ /* double check image */ if (xmax < 0 || ymax < 0 || in_bpr < img_bpr) { zclose(zf); return((Image *)NULL); } if (verbose) printf("%s is a %dx%d PC Paintbrush image\n",name,xmax,ymax); if (pcxhd[65] > 1) { fprintf(stderr,"pcxLoad: %s - Unable to handle Color PCX image\n",name); zclose(zf); return((Image *)NULL); } znocache(zf); /* Allocate pbm array. */ image = newBitImage(xmax,ymax); image->title = dupString(name); /* Read compressed bitmap. */ if (!PCX_LoadImage( zf, in_bpr, img_bpr, image, ymax )) { fprintf(stderr,"pcxLoad: %s - Short read of PCX file\n",name); zclose(zf); return(image); } read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } /* ** PCX_LoadImage ** ** Load PC Paintbrush file into the passed Image structure. ** ** Returns FALSE if there was a short read. */ static boolean PCX_LoadImage (ZFILE *zf, int in_bpr, int img_bpr, Image *image, int rows) { /* Goes like this: Read a byte. If the two high bits are set, ** then the low 6 bits contain a repeat count, and the byte to ** repeat is the next byte in the file. If the two high bits are ** not set, then this is the byte to write. */ register unsigned char *ptr; int row = 0; int bytes_this_row = 0; int b, i, cnt; ptr = &(image->data[0]); while ((b = zgetc(zf)) != EOF) { if ((b & 0xC0) == 0xC0) { /* have a repetition count -- mask flag bits */ cnt = b & 0x3F; b = zgetc(zf); if (b == EOF) return FALSE; } else { cnt = 1; /* no repeating this one */ } for ( i = 0; i < cnt; i++ ) { if ( row >= rows ) { return TRUE; } if (bytes_this_row < img_bpr) *ptr++ = (unsigned char) (255 - b); if (++bytes_this_row == in_bpr) { /* start of a new line */ row++; bytes_this_row = 0; } } } return TRUE; } xli-2006-11-10/png.c0000644000031400000060000002216110525262416013356 0ustar smarryconsole/* * Based on example.c from libpng by Guy Eric Schalnat, Andreas Dilger, * Glenn Randers-Pehrson et al. Any bugs are my fault. -- smar@reptiles.org */ #include "xli.h" #include "imagetypes.h" #include "pbm.h" #include #include #define TITLE_KEYWORD "Title" /* check to see if a file is a png file using png_check_sig() */ static int check_png(char *file_name) { ZFILE *zfp; char buf[8]; int ret; zfp = zopen(file_name); if (!zfp) return 0; ret = zread(zfp, buf, 8); zclose(zfp); if (ret != 8) return 0; ret = png_check_sig(buf, 8); return (ret); } static void describe_png(char *name, png_struct *png, png_info *info) { int bd, ct; ct = png_get_color_type(png, info); bd = png_get_bit_depth(png, info); printf("%s is a%s %lux%lu %d bit deep %s PNG image", name, png_get_interlace_type(png, info) ? "n interlaced" : "", png_get_image_width(png, info), png_get_image_height(png, info), bd, (ct & PNG_COLOR_MASK_PALETTE) ? "paletted" : (ct & PNG_COLOR_MASK_COLOR) ? "RGB" : "grayscale"); if (ct & PNG_COLOR_MASK_ALPHA) printf(" with an alpha channel"); if (png_get_valid(png, info, PNG_INFO_tRNS)) printf(" with transparency"); if (png_get_valid(png, info, PNG_INFO_bKGD)) { png_color_16 *bg; int d; png_get_bKGD(png, info, &bg); d = (bd + 3) / 4; printf(", background = "); if (!(ct & PNG_COLOR_MASK_COLOR)) { printf("#%0*x", d, bg->gray); } else if (PNG_COLOR_TYPE_PALETTE == ct) { png_color *bp; int np; png_get_PLTE(png, info, &bp, &np); bp += bg->index; printf("index %d: #%02x%02x%02x", bg->index, bp->red, bp->green, bp->blue); } else { printf("#%0*x%0*x%0*x", d, bg->red, d, bg->green, d, bg->blue); } } if (png_get_valid(png, info, PNG_INFO_gAMA)) { double g; png_get_gAMA(png, info, &g); printf(", gamma = %g", g); } printf("\n"); } static void xli_png_read_data(png_struct *png, png_byte *data, png_size_t length) { ZFILE *zfp; zfp = (ZFILE *) png_get_io_ptr(png); if (zread(zfp, (byte *) data, (int) length) != length) png_error(png, "unexpected EOF in xli_png_read_data"); } static void xli_png_error(png_struct * png_ptr, png_const_charp error_msg) { fputs(error_msg, stderr); putc('\n', stderr); longjmp(*((jmp_buf *) png_get_error_ptr(png_ptr)), 1); } Image *pngLoad(char *fullname, ImageOptions * opt, boolean verbose) { ZFILE *zfp; png_struct *png; png_info *info; Image *image = (Image *) 0; int orig_depth = 0; byte **row = (byte **) 0; jmp_buf jmpbuf; int bit_depth, color_type; /* open the file */ if (!check_png(fullname)) return (Image *) 0; zfp = zopen(fullname); if (!zfp) { perror("pngLoad"); return (Image *) 0; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *) &jmpbuf, xli_png_error, (png_error_ptr) 0); if (!png) { zclose(zfp); return (Image *) 0; } info = png_create_info_struct(png); if (!info) { zclose(zfp); png_destroy_read_struct(&png, (png_infopp) 0, (png_infopp) 0); return (Image *) 0; } /* scary non-local transfer of control action */ if (setjmp(jmpbuf)) { png_destroy_read_struct(&png, &info, (png_infopp) 0); zclose(zfp); if (row) lfree((byte *) row); return image; } /* set up the input control */ png_set_read_fn(png, (void *) zfp, xli_png_read_data); /* read the file information */ png_read_info(png, info); if (verbose) describe_png(fullname, png, info); znocache(zfp); /* the rules: bit depth over 8 ITRUE rgb colour ITRUE 1 bit gray IBITMAP other gray IRGB palette colour IRGB */ bit_depth = png_get_bit_depth(png, info); color_type = png_get_color_type(png, info); if (bit_depth < 8 && (PNG_COLOR_TYPE_RGB == color_type || PNG_COLOR_TYPE_RGB_ALPHA == color_type)) png_set_expand(png); /* Set the background color to draw transparent and alpha images over */ if ((color_type & PNG_COLOR_MASK_ALPHA) || (png_get_valid(png, info, PNG_INFO_tRNS) && (opt->bg || png_get_valid(png, info, PNG_INFO_bKGD)))) { png_color_16 bg; int expand = 0; int gflag = PNG_BACKGROUND_GAMMA_SCREEN; double gval = 1.0; bg.red = bg.green = bg.blue = bg.gray = 0; if (PNG_COLOR_TYPE_PALETTE == color_type || opt->bg) png_set_expand(png); if (opt->bg) { XColor xc; int shift = ((color_type & PNG_COLOR_MASK_ALPHA) && 16 == bit_depth) ? 0 : 8; xc.flags = DoRed | DoGreen | DoBlue; xliParseXColor(&(globals.dinfo), opt->bg, &xc); bg.red = xc.red >> shift; bg.green = xc.green >> shift; bg.blue = xc.blue >> shift; bg.gray = (int) (xc.red * .299 + xc.green * .587 + xc.blue * .114 + .5) >> shift; } else if (png_get_valid(png, info, PNG_INFO_bKGD)) { png_color_16 *bgp; png_get_bKGD(png, info, &bgp); bg = *bgp; expand = 1; gflag = PNG_BACKGROUND_GAMMA_FILE; } png_set_background(png, &bg, gflag, expand, gval); } if (bit_depth < 8 && (bit_depth > 1 || PNG_COLOR_TYPE_GRAY != color_type)) { if (PNG_COLOR_TYPE_GRAY == color_type) orig_depth = bit_depth; png_set_packing(png); } /* tell libpng to strip 16 bit depth files down to 8 bits */ if (bit_depth > 8) png_set_strip_16(png); if (png_get_interlace_type(png, info)) png_set_interlace_handling(png); /* update palette with transformations, update the info structure */ png_read_update_info(png, info); bit_depth = png_get_bit_depth(png, info); color_type = png_get_color_type(png, info); /* allocate the memory to hold the image using the fields * of png_info. */ if (PNG_COLOR_TYPE_GRAY == color_type && 1 == bit_depth) { image = newBitImage(png_get_image_width(png, info), png_get_image_height(png, info)); png_set_invert_mono(png); } else if (PNG_COLOR_TYPE_PALETTE == color_type) { int i, np; png_color *pp; image = newRGBImage(png_get_image_width(png, info), png_get_image_height(png, info), bit_depth); png_get_PLTE(png, info, &pp, &np); for (i = 0; i < np; ++i) { image->rgb.red[i] = pp[i].red * 0x101; image->rgb.green[i] = pp[i].green * 0x101; image->rgb.blue[i] = pp[i].blue * 0x101; } image->rgb.used = np; } else if (PNG_COLOR_TYPE_GRAY == color_type) { int i; int depth = orig_depth ? orig_depth : bit_depth; int maxval = (1 << depth) - 1; image = newRGBImage(png_get_image_width(png, info), png_get_image_height(png, info), depth); for (i = 0; i <= maxval; i++) { image->rgb.red[i] = PM_SCALE(i, maxval, 0xffff); image->rgb.green[i] = PM_SCALE(i, maxval, 0xffff); image->rgb.blue[i] = PM_SCALE(i, maxval, 0xffff); } image->rgb.used = maxval + 1; } else { image = newTrueImage(png_get_image_width(png, info), png_get_image_height(png, info)); } if (png_get_valid(png, info, PNG_INFO_gAMA) && image->type != IBITMAP) { double g; png_get_gAMA(png, info, &g); image->gamma = 1.0 / g; } /* read the image */ if (IBITMAP == image->type) { assert((image->width + 7) / 8 == png_get_rowbytes(png, info)); } else { assert(image->width * image->pixlen == png_get_rowbytes(png, info)); } { int i; row = (byte **) lmalloc(image->height * sizeof(byte *)); for (i = 0; i < image->height; ++i) row[i] = image->data + i * png_get_rowbytes(png, info); } png_read_image(png, row); /* read the rest of the file, getting any additional chunks in info */ png_read_end(png, info); if (verbose && png_get_valid(png, info, PNG_INFO_tIME)) { png_time *tp; png_get_tIME(png, info, &tp); printf("Modification time: %d/%d/%d %02d:%02d:%02d", tp->year, tp->month, tp->day, tp->hour, tp->minute, tp->second); } { int i, num_text; char *title; png_text *text; title = opt->name; num_text = png_get_text(png, info, &text, (int *) 0); for (i = 0; i < num_text; ++i) { if (verbose) printf("\n%s: %s\n", text[i].key, text[i].text); if (!strcmp(text[i].key, TITLE_KEYWORD)) title = text[i].text; } image->title = dupString(title); } /* clean up after the read, and free any memory allocated */ png_destroy_read_struct(&png, &info, (png_infopp) 0); /* free the structures */ lfree((byte *) row); /* close the file */ zclose(zfp); /* that's it */ return image; } int pngIdent(char *fullname, char *name) { ZFILE *zfp; png_struct *png; png_info *info; jmp_buf jmpbuf; if (!check_png(fullname)) return 0; /* open the file */ zfp = zopen(fullname); if (!zfp) { perror("pngIdent"); return 0; } /* allocate the necessary structures */ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *) &jmpbuf, xli_png_error, (png_error_ptr) 0); if (!png) { zclose(zfp); return 0; } info = png_create_info_struct(png); if (!info) { zclose(zfp); png_destroy_read_struct(&png, (png_infopp) 0, (png_infopp) 0); return 0; } /* set error handling */ if (setjmp(jmpbuf)) { png_destroy_read_struct(&png, &info, (png_infopp) 0); zclose(zfp); return 0; } /* set up the input control */ png_set_read_fn(png, (void *) zfp, xli_png_read_data); /* read the file information */ png_read_info(png, info); describe_png(fullname, png, info); /* clean up after the read, and free any memory allocated */ png_destroy_read_struct(&png, &info, (png_infopp) 0); /* close the file */ zclose(zfp); /* that's it */ return 1; } xli-2006-11-10/reduce.c0000644000031400000060000012406307004736446014054 0ustar smarryconsole/* 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 function cannot reduce to any number of colors larger than 32768. * * Based on the file lib/colorquant.c in the Utah Raster Toolkit version 3.0 * * > Perform variance-based color quantization on a "full color" image. * > Author: Craig Kolb * > Department of Mathematics * > Yale University * > kolb@yale.edu * > Date: Tue Aug 22 1989 * > Copyright (C) 1989 Craig E. Kolb * * Adaption for xli, faster colour dithering * and other improvements by Graeme Gill. * */ #include "xli.h" #define MAXCOLORS 32768 #define INPUTQUANT 5 #define REDUCE_GAMMA 2.2 /* Work in gamma compressed space */ /* since this is closer to a linear */ /* perceptual space */ /* Ansi uses HUGE_VAL. */ #ifndef HUGE #define HUGE HUGE_VAL #endif typedef struct { float weightedvar, /* weighted variance */ /* (set to 0 if un-cutable) */ mean[3]; /* centroid */ unsigned long weight, /* # of pixels in box */ freq[3][256]; /* Projected frequencies */ int low[3], high[3]; /* Box extent - within low <= col < high */ } Box; static void QuantHistogram(Image *image, Box *box); static void BoxStats(Box *box); static void UpdateFrequencies(Box *box1, Box *box2); static void ComputeRGBMap(Box *boxes, int colors, short unsigned int *rgbmap, int ditherf); static void SetRGBmap(int boxnum, Box *box, short unsigned int *rgbmap); static boolean CutBoxes(Box *boxes, int colors); static int CutBox(Box *box, Box *newbox); static int GreatestVariance(Box *boxes, int n); static boolean FindCutpoint(Box *box, int color, Box *newbox1, Box *newbox2); static void CopyToNewImage(Image *inimage, Image *outimage, unsigned short *rgbmap, int ditherf, int colors, float gamma, int verbose); /* this converts a TLA-style pixel into a 15-bit true color pixel */ #define TLA_TO_15BIT(TABLE,PIXEL) \ ((((unsigned short)((TABLE).red[PIXEL] & 0xf800)) >> 1) | \ (((unsigned short)((TABLE).green[PIXEL] & 0xf800)) >> 6) | \ (((unsigned short)((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) \ ((((unsigned long)((PIXEL) & 0xf80000)) >> 9) | \ (((unsigned long)((PIXEL) & 0x00f800)) >> 6) | \ (((unsigned long)((PIXEL) & 0x0000f8)) >> 3)) /* these macros extract color intensities from a 15-bit true color pixel */ #define RED_INTENSITY(P) (((unsigned short)((P) & 0x7c00)) >> 10) #define GREEN_INTENSITY(P) (((unsigned short)((P) & 0x03e0)) >> 5) #define BLUE_INTENSITY(P) ((unsigned short)((P) & 0x001f)) /* * Value corrersponding to full intensity in colormap. The values placed * in the colormap are scaled to be between zero and this number. */ #define MAX(x,y) ((x) > (y) ? (x) : (y)) /* * Readability constants. */ #define REDI 0 #define GREENI 1 #define BLUEI 2 static unsigned long *Histogram, /* image histogram */ NPixels; /* total # of pixels */ #define Bits INPUTQUANT #define cBits (8-Bits) #define ColormaxI (1 << Bits) /* 2 ^ Bits */ #define Colormax (ColormaxI - 1) /* quantized full-intensity */ #define ColormaxcI (1 << cBits) /* 2 ^ (8-Bits) */ #define Colormaxc (ColormaxcI - 1) /* quantized bits lost */ /* * if "ditherf" is True, apply color disthering * if "Gamma" != 0.0, compensate for gamma post processing */ unsigned int verbose; Image *reduce(Image *image, unsigned colors, int ditherf, float gamma, int verbose) { unsigned short *rgbmap; Box *Boxes; /* Array of color boxes. */ int i; /* Counter */ int OutColors; /* # of entries computed */ int depth; Image *new_image; char buf[BUFSIZ]; CURRFUNC("reduce"); if (colors > MAXCOLORS) /* max # of colors we can handle */ colors = MAXCOLORS; if (BITMAPP(image) || (RGBP(image) && image->rgb.used <= colors)) return (image); if (TRUEP(image) && image->pixlen != 3) { fprintf(stderr, "reduce: true color image has strange pixel length?\n"); return (image); } /* do color reduction and dithering in linear color space */ if (GAMMA_NOT_EQUAL(image->gamma, REDUCE_GAMMA)) gammacorrect(image, REDUCE_GAMMA, verbose); NPixels = image->width * image->height; Histogram = (unsigned long *) lcalloc(ColormaxI * ColormaxI * ColormaxI * sizeof(long)); Boxes = (Box *) lmalloc(colors * sizeof(Box)); rgbmap = (unsigned short *) lmalloc(ColormaxI * ColormaxI * ColormaxI * sizeof(unsigned short)); switch (image->type) { case IRGB: if (verbose) { printf(" Reducing RGB image color usage to %d colors...", colors); fflush(stdout); } QuantHistogram(image, &Boxes[0]); break; case ITRUE: if (verbose) { printf(" Converting true color image to RGB image with %d colors...", colors); fflush(stdout); } QuantHistogram(image, &Boxes[0]); break; default: { lfree((char *) Histogram); lfree((char *) Boxes); lfree((char *) rgbmap); return (image); /* not something we can reduce, thank you anyway */ } } OutColors = CutBoxes(Boxes, colors); /* * We now know the set of representative colors. We now * must fill in the colormap. */ /* get destination image */ depth = colorsToDepth(OutColors); new_image = newRGBImage(image->width, image->height, depth); sprintf(buf, "%s (%d colors)", image->title, OutColors); new_image->title = dupString(buf); new_image->gamma = image->gamma; for (i = 0; i < OutColors; i++) { new_image->rgb.red[i] = (((unsigned short) (Boxes[i].mean[REDI] + 0.5)) << (cBits + 8)); new_image->rgb.green[i] = (((unsigned short) (Boxes[i].mean[GREENI] + 0.5)) << (cBits + 8)); new_image->rgb.blue[i] = (((unsigned short) (Boxes[i].mean[BLUEI] + 0.5)) << (cBits + 8)); } new_image->rgb.used = OutColors; new_image->rgb.compressed = TRUE; ComputeRGBMap(Boxes, OutColors, rgbmap, ditherf); lfree((char *) Histogram); lfree((char *) Boxes); /* copy old image into new image */ CopyToNewImage(image, new_image, rgbmap, ditherf, OutColors, gamma, verbose); lfree((char *) rgbmap); if (verbose) printf("done\n"); return (new_image); } /* * Compute the histogram of the image as well as the projected frequency * arrays for the first world-encompassing box. */ static void QuantHistogram(Image *image, Box *box) { register byte *pixel; register unsigned long *rf, *gf, *bf; int x, y; rf = box->freq[0]; gf = box->freq[1]; bf = box->freq[2]; /* * Zero-out the projected frequency arrays of the largest box. * We compute both the histogram and the proj. frequencies of * the first box at the same time to save a pass through the * entire image. */ bzero(rf, ColormaxI * sizeof(unsigned long)); bzero(gf, ColormaxI * sizeof(unsigned long)); bzero(bf, ColormaxI * sizeof(unsigned long)); if (image->type == IRGB) { Intensity *red = image->rgb.red, *green = image->rgb.green, *blue = image->rgb.blue; pixel = image->data; if (image->pixlen == 1) /* special case most common this for speed */ for (y = image->height; y > 0; y--) for (x = image->width; x > 0; x--) { register unsigned char r, g, b; r = red[memToVal(pixel, 1)] >> (8 + cBits); g = green[memToVal(pixel, 1)] >> (8 + cBits); b = blue[memToVal(pixel, 1)] >> (8 + cBits); rf[r]++; gf[g]++; bf[b]++; Histogram[(((r << Bits) | g) << Bits) | b]++; pixel += 1; } else for (y = image->height; y > 0; y--) for (x = image->width; x > 0; x--) { register unsigned char r, g, b; r = red[memToVal(pixel, image->pixlen)] >> (8 + cBits); g = green[memToVal(pixel, image->pixlen)] >> (8 + cBits); b = blue[memToVal(pixel, image->pixlen)] >> (8 + cBits); rf[r]++; gf[g]++; bf[b]++; Histogram[(((r << Bits) | g) << Bits) | b]++; pixel += image->pixlen; } } else { /* assume ITRUE */ pixel = image->data; if (image->pixlen == 3) /* most common */ for (y = image->height; y > 0; y--) for (x = image->width; x > 0; x--) { register unsigned long a, b; while (x > 4) { /* Unroll 4 times */ a = (*pixel++) >> cBits; /* Red */ rf[a]++; b = a << Bits; a = (*pixel++) >> cBits; /* Green */ gf[a]++; b = (b | a) << Bits; a = (*pixel++) >> cBits; /* Blue */ bf[a]++; b |= a; Histogram[b]++; a = (*pixel++) >> cBits; /* Red */ rf[a]++; b = a << Bits; a = (*pixel++) >> cBits; /* Green */ gf[a]++; b = (b | a) << Bits; a = (*pixel++) >> cBits; /* Blue */ bf[a]++; b |= a; Histogram[b]++; a = (*pixel++) >> cBits; /* Red */ rf[a]++; b = a << Bits; a = (*pixel++) >> cBits; /* Green */ gf[a]++; b = (b | a) << Bits; a = (*pixel++) >> cBits; /* Blue */ bf[a]++; b |= a; Histogram[b]++; a = (*pixel++) >> cBits; /* Red */ rf[a]++; b = a << Bits; a = (*pixel++) >> cBits; /* Green */ gf[a]++; b = (b | a) << Bits; a = (*pixel++) >> cBits; /* Blue */ bf[a]++; b |= a; Histogram[b]++; x -= 4; } a = (*pixel++) >> cBits; /* Red */ rf[a]++; b = a << Bits; a = (*pixel++) >> cBits; /* Green */ gf[a]++; b = (b | a) << Bits; a = (*pixel++) >> cBits; /* Blue */ bf[a]++; b |= a; Histogram[b]++; } else /* less common */ for (y = image->height; y > 0; y--) for (x = image->width; x > 0; x--) { register unsigned char r, g, b; r = TRUE_RED(memToVal(pixel, image->pixlen)) >> cBits; rf[r]++; g = TRUE_GREEN(memToVal(pixel, image->pixlen)) >> cBits; gf[g]++; b = TRUE_BLUE(memToVal(pixel, image->pixlen)) >> cBits; bf[b]++; Histogram[(((r << Bits) | g) << Bits) | b]++; pixel += image->pixlen; } } } /* * Interatively cut the boxes. */ static int CutBoxes(Box *boxes, int colors) { int curbox; boxes[0].low[REDI] = boxes[0].low[GREENI] = boxes[0].low[BLUEI] = 0; boxes[0].high[REDI] = boxes[0].high[GREENI] = boxes[0].high[BLUEI] = ColormaxI; boxes[0].weight = NPixels; BoxStats(&boxes[0]); for (curbox = 1; curbox < colors;) { int n; n = GreatestVariance(boxes, curbox); if (n == curbox) break; /* all are un-cutable */ if (CutBox(&boxes[n], &boxes[curbox])) curbox++; /* cut successfully */ } return curbox; } /* * Return the number of the box in 'boxes' with the greatest variance. * Restrict the search to those boxes with indices between 0 and n-1. * Return n if none of the boxes are cutable. */ static int GreatestVariance(Box *boxes, int n) { register int i, whichbox = n; float max = 0.0; for (i = 0; i < n; i++) { if (boxes[i].weightedvar > max) { max = boxes[i].weightedvar; whichbox = i; } } return whichbox; } /* Compute mean and weighted variance of the given box. */ static void BoxStats(Box *box) { register int i, color; unsigned long *freq; float mean, var; if (box->weight == 0) { box->weightedvar = 0.0; return; } box->weightedvar = 0.; for (color = 0; color < 3; color++) { var = mean = 0; i = box->low[color]; freq = &box->freq[color][i]; for (; i < box->high[color]; i++, freq++) { mean += i * *freq; var += i * i * *freq; } box->mean[color] = mean / (float) box->weight; box->weightedvar += var - box->mean[color] * box->mean[color] * (float) box->weight; } box->weightedvar /= NPixels; } /* * Cut the given box. Returns TRUE if the box could be cut, * FALSE (and weightedvar == 0.0) otherwise. */ static boolean CutBox(Box *box, Box *newbox) { int i; double totalvar[3]; Box newboxes[3][2]; if (box->weightedvar == 0.0 || box->weight == 0) { /* * Can't cut this box. */ box->weightedvar = 0.0; /* Don't try cutting it again */ return FALSE; } /* * Find 'optimal' cutpoint along each of the red, green and blue * axes. Sum the variances of the two boxes which would result * by making each cut and store the resultant boxes for * (possible) later use. */ for (i = 0; i < 3; i++) { if (FindCutpoint(box, i, &newboxes[i][0], &newboxes[i][1])) totalvar[i] = newboxes[i][0].weightedvar + newboxes[i][1].weightedvar; else totalvar[i] = HUGE; /* Not cutable on that axis */ } /* * Find which of the three cuts minimized the total variance * and make that the 'real' cut. */ if (totalvar[REDI] < HUGE && totalvar[REDI] <= totalvar[GREENI] && totalvar[REDI] <= totalvar[BLUEI]) { *box = newboxes[REDI][0]; *newbox = newboxes[REDI][1]; return TRUE; } else if (totalvar[GREENI] < HUGE && totalvar[GREENI] <= totalvar[REDI] && totalvar[GREENI] <= totalvar[BLUEI]) { *box = newboxes[GREENI][0]; *newbox = newboxes[GREENI][1]; return TRUE; } else if (totalvar[BLUEI] < HUGE) { *box = newboxes[BLUEI][0]; *newbox = newboxes[BLUEI][1]; return TRUE; } /* Unable to cut box on any axis - don't try again */ box->weightedvar = 0.0; return FALSE; } /* * Compute the 'optimal' cutpoint for the given box along the axis * indcated by 'color'. Store the boxes which result from the cut * in newbox1 and newbox2. * If it is not possible to */ static boolean FindCutpoint(Box *box, int color, Box *newbox1, Box *newbox2) { float u, v, max; int i, maxindex, minindex, cutpoint; unsigned long optweight, curweight; if (box->low[color] + 1 == box->high[color]) return FALSE; /* Cannot be cut. */ minindex = (int) (((float) box->low[color] + box->mean[color]) * 0.5); maxindex = (int) ((box->mean[color] + (float) box->high[color]) * 0.5); cutpoint = minindex; optweight = box->weight; curweight = 0; for (i = box->low[color]; i < minindex; i++) curweight += box->freq[color][i]; u = 0.0; max = -1.0; for (i = minindex; i <= maxindex; i++) { curweight += box->freq[color][i]; if (curweight == box->weight) break; u += (float) (i * box->freq[color][i]) / (float) box->weight; v = ((float) curweight / (float) (box->weight - curweight)) * (box->mean[color] - u) * (box->mean[color] - u); if (v > max) { max = v; cutpoint = i; optweight = curweight; } } cutpoint++; *newbox1 = *newbox2 = *box; newbox1->weight = optweight; newbox2->weight -= optweight; if (newbox1->weight == 0 || newbox2->weight == 0) return FALSE; /* Unable to cut on this axis */ newbox1->high[color] = cutpoint; newbox2->low[color] = cutpoint; UpdateFrequencies(newbox1, newbox2); BoxStats(newbox1); BoxStats(newbox2); return TRUE; /* Found cutpoint. */ } /* * Update projected frequency arrays for two boxes which used to be * a single box. Also shrink the box sizes to fit the points. */ static void UpdateFrequencies(Box *box1, Box *box2) { register unsigned long myfreq, *h; register int b, g, r; int roff; register unsigned long *b1f0, *b1f1, *b1f2, *b2f0, *b2f1, *b2f2; b1f0 = &box1->freq[0][0]; b1f1 = &box1->freq[1][0]; b1f2 = &box1->freq[2][0]; b2f0 = &box2->freq[0][0]; b2f1 = &box2->freq[1][0]; b2f2 = &box2->freq[2][0]; bzero(b1f0, ColormaxI * sizeof(unsigned long)); bzero(b1f1, ColormaxI * sizeof(unsigned long)); bzero(b1f2, ColormaxI * sizeof(unsigned long)); for (r = box1->low[0]; r < box1->high[0]; r++) { roff = r << Bits; for (g = box1->low[1]; g < box1->high[1]; g++) { b = box1->low[2]; h = Histogram + (((roff | g) << Bits) | b); for (; b < box1->high[2]; b++) { myfreq = *h++; if (myfreq == 0) continue; b1f0[r] += myfreq; b1f1[g] += myfreq; b1f2[b] += myfreq; b2f0[r] -= myfreq; b2f1[g] -= myfreq; b2f2[b] -= myfreq; } } } /* shrink the boxes to fit the new points */ for (r = 0; r < 3; r++) { register int l1, l2, h1, h2; l1 = l2 = ColormaxI; h1 = h2 = 0; for (g = 0; g < ColormaxI; g++) { if (box1->freq[r][g] != 0) { if (g < l1) l1 = g; if (g > h1) h1 = g; } if (box2->freq[r][g] != 0) { if (g < l2) l2 = g; if (g > h2) h2 = g; } } box1->low[r] = l1; box2->low[r] = l2; box1->high[r] = h1 + 1; box2->high[r] = h2 + 1; } } /* Compute RGB to colormap index map. */ static void ComputeRGBMap(Box *boxes, int colors, unsigned short *rgbmap, int ditherf) { register int i; if (!ditherf) { /* * The centroid of each box serves as the representative * for each color in the box. */ for (i = 0; i < colors; i++) SetRGBmap(i, &boxes[i], rgbmap); } else { /* Initialise the pixel value to illegal value. * Will fill in entry on demand. */ bfill((char *) rgbmap, ColormaxI * ColormaxI * ColormaxI * sizeof(*rgbmap), 0xff); /* speed things up by pre-filling boxes with input colors */ for (i = 0; i < colors; i++) SetRGBmap(i, &boxes[i], rgbmap); } } /* * Make the centroid of "boxnum" serve as the representative for * each color in the box. */ static void SetRGBmap(int boxnum, Box *box, unsigned short *rgbmap) { register int r, g, b; for (r = box->low[REDI]; r < box->high[REDI]; r++) { for (g = box->low[GREENI]; g < box->high[GREENI]; g++) { for (b = box->low[BLUEI]; b < box->high[BLUEI]; b++) { rgbmap[(((r << Bits) | g) << Bits) | b] = (unsigned short) boxnum; } } } } /* nearest neighbor structure */ typedef struct { int length; /* number of colors */ unsigned char *red, *green, *blue; unsigned short *pixel; } NN; #define NNBits 3 #define NNcBits (8-NNBits) #define NNmaxI (1 << NNBits) /* 2 ^ Bits */ #define NNmax (NNmaxI - 1) /* quantized full-intensity */ #define NNmaxcI (1 << NNcBits) /* 2 ^ (8 - Bits) */ #define NNmaxc (NNmaxcI - 1) /* quantized bits lost */ /* Initialise the appropriate nn cell */ static void find_nnearest(int rval, int gval, int bval, NN *nnp, Image *outimage) { long bdist, mdist; Intensity *red = outimage->rgb.red, *green = outimage->rgb.green, *blue = outimage->rgb.blue; long *ds, *de, dists[MAXCOLORS]; int *is, indexes[MAXCOLORS]; int i, length = 0; double tdouble; rval = ((rval & ~NNmaxc) << 1) + NNmaxc; /* closest color to center of cell */ gval = ((gval & ~NNmaxc) << 1) + NNmaxc; /* (2 * scaled values) */ bval = ((bval & ~NNmaxc) << 1) + NNmaxc; #define SQUARE(aa) ((aa) * ( aa)) #define QERR(r1,g1,b1,r2,g2,b2) /* sum of squares distance (in 2 * scale) */ \ (SQUARE(r1 - (r2 >>7)) + \ SQUARE(g1 - (g2 >>7)) + \ SQUARE(b1 - (b2 >>7))) /* Calculate the distances of all the colors in the colormap */ /* from the center of this nn cell. */ /* (unroll this loop 4 times) */ for (ds = dists, de = ds + outimage->rgb.used; ds < (de - 3);) { *ds = QERR(rval, gval, bval, *red, *green, *blue); ds++; red++; green++; blue++; *ds = QERR(rval, gval, bval, *red, *green, *blue); ds++; red++; green++; blue++; *ds = QERR(rval, gval, bval, *red, *green, *blue); ds++; red++; green++; blue++; *ds = QERR(rval, gval, bval, *red, *green, *blue); ds++; red++; green++; blue++; } /* finish off remaining */ while (ds < de) { *ds = QERR(rval, gval, bval, *red, *green, *blue); ds++; red++; green++; blue++; } /* find nearest colormap colour to the center */ /* (unroll this loop 8 times) */ for (bdist = 0x7fffffff, ds = dists; ds < (de - 7); ds++) { if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds < bdist) goto found_small; ds++; if (*ds >= bdist) continue; found_small: bdist = *ds; } /* finish off remaining */ while (ds < de) { if (*ds < bdist) bdist = *ds; ds++; } /* figure out the maximum distance from center */ tdouble = sqrt((double) bdist) + sqrt((double) (NNmaxc * NNmaxc * 12)); mdist = (int) ((tdouble * tdouble) + 0.5); /* back to square distance */ /* now select the neighborhood groups */ /* (unroll this loop 8 times) */ for (is = indexes, ds = dists; ds < (de - 7); ds++) { if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds <= mdist) goto found_neighbor; ds++; if (*ds > mdist) continue; found_neighbor: *is++ = ds - dists; } /* finish off remaining */ for (; ds < de; ds++) { if (*ds <= mdist) *is++ = ds - dists; } /* now make up the entries in the neighborhood structure entry */ length = is - indexes; nnp->length = length; nnp->red = (unsigned char *) lmalloc(length * 3); nnp->green = nnp->red + length; nnp->blue = nnp->green + length; nnp->pixel = (unsigned short *) lmalloc(length * sizeof(unsigned short)); red = outimage->rgb.red; green = outimage->rgb.green; blue = outimage->rgb.blue; for (i = 0, is = indexes; i < length; i++, is++) { nnp->red[i] = red[*is] >> 8; nnp->green[i] = green[*is] >> 8; nnp->blue[i] = blue[*is] >> 8; nnp->pixel[i] = *is; } #undef SQUARE #undef QERR } /* * Find the neareset chosen pixel value to the given color. * Uses nn accelerator. */ static unsigned short find_nearest(int rval, int gval, int bval, NN *nna, Image *outimage) { long bdist, ndist; int i, bindex = 0; int lastc; unsigned char *red, *green, *blue; int nnindex; NN *nnp; nnindex = ((((rval >> NNcBits) << NNBits) | (gval >> NNcBits)) << NNBits) | (bval >> NNcBits); nnp = nna + nnindex; if (nnp->length == 0) /* Create nearest neighbor color mapping on demand */ find_nnearest(rval, gval, bval, nnp, outimage); lastc = nnp->length - 1; red = &nnp->red[lastc], green = &nnp->green[lastc], blue = &nnp->blue[lastc]; rval = (rval & ~Colormaxc) + (ColormaxcI >> 1); /* closest color to center of 15 bit color */ gval = (gval & ~Colormaxc) + (ColormaxcI >> 1); bval = (bval & ~Colormaxc) + (ColormaxcI >> 1); #define SQUARE(aa) ((aa) * ( aa)) #define QERR(r1,g1,b1,r2,g2,b2) \ (SQUARE(r1 - r2) + \ SQUARE(g1 - g2) + \ SQUARE(b1 - b2)) /* now find the the nearest colour */ /* (try and unroll this loop 8 times) */ for (bdist = 0x7fffffff, i = lastc; i >= 7; i--, red--, green--, blue--) { if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) goto found_small; i--; red--; green--; blue--; if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) >= bdist) continue; found_small: bdist = ndist; bindex = i; } /* finish off remaining */ for (; i >= 0; i--, red--, green--, blue--) { if ((ndist = QERR(rval, gval, bval, *red, *green, *blue)) < bdist) { bdist = ndist; bindex = i; } } return nnp->pixel[bindex]; #undef SQUARE #undef QERR } /* "rgbmap" is pixel value lookup map */ static void CopyToNewImage(Image *inimage, Image *outimage, unsigned short *rgbmap, int ditherf, int colors, float gamma, int verbose) { byte *pixel, *dpixel; int x, y; pixel = inimage->data; dpixel = outimage->data; if (!ditherf) { switch (inimage->type) { case IRGB: if (outimage->pixlen == 1 && inimage->pixlen == 1) /* most common */ for (y = inimage->height; y > 0; y--) for (x = inimage->width; x > 0; x--) { register unsigned long temp; temp = TLA_TO_15BIT(inimage->rgb, *pixel); temp = rgbmap[temp]; valToMem(temp, dpixel, 1); pixel++; dpixel++; } else /* less common */ for (y = inimage->height; y > 0; y--) for (x = inimage->width; x > 0; x--) { register unsigned long temp; temp = memToVal(pixel, inimage->pixlen); temp = TLA_TO_15BIT(inimage->rgb, temp); temp = rgbmap[temp]; valToMem(temp, dpixel, outimage->pixlen); pixel += inimage->pixlen; dpixel += outimage->pixlen; } break; case ITRUE: if (inimage->pixlen == 3 && outimage->pixlen == 1) { /* common */ for (y = inimage->height; y > 0; y--) { register unsigned long temp; x = inimage->width; while (x >= 4) { /* Unroll 4 times */ temp = (((unsigned long) *pixel) & 0xf8) << (Bits + Bits - cBits); pixel++; temp |= (((unsigned long) *pixel) & 0xf8) << (Bits - cBits); pixel++; temp |= ((unsigned long) *pixel) >> cBits; *dpixel = rgbmap[temp]; pixel++; dpixel++; temp = (((unsigned long) *pixel) & 0xf8) << (Bits + Bits - cBits); pixel++; temp |= (((unsigned long) *pixel) & 0xf8) << (Bits - cBits); pixel++; temp |= ((unsigned long) *pixel) >> cBits; *dpixel = rgbmap[temp]; pixel++; dpixel++; temp = (((unsigned long) *pixel) & 0xf8) << (Bits + Bits - cBits); pixel++; temp |= (((unsigned long) *pixel) & 0xf8) << (Bits - cBits); pixel++; temp |= ((unsigned long) *pixel) >> cBits; *dpixel = rgbmap[temp]; pixel++; dpixel++; temp = (((unsigned long) *pixel) & 0xf8) << (Bits + Bits - cBits); pixel++; temp |= (((unsigned long) *pixel) & 0xf8) << (Bits - cBits); pixel++; temp |= ((unsigned long) *pixel) >> cBits; *dpixel = rgbmap[temp]; pixel++; dpixel++; x -= 4; } while (x >= 1) { /* Finish remaining */ temp = (((unsigned long) *pixel) & 0xf8) << (Bits + Bits - cBits); pixel++; temp |= (((unsigned long) *pixel) & 0xf8) << (Bits - cBits); pixel++; temp |= ((unsigned long) *pixel) >> cBits; *dpixel = rgbmap[temp]; pixel++; dpixel++; x--; } } } else /* less common */ for (y = inimage->height; y > 0; y--) for (x = inimage->width; x > 0; x--) { register unsigned long temp; temp = memToVal(pixel, inimage->pixlen); temp = TRUE_TO_15BIT(temp); temp = rgbmap[temp]; valToMem(temp, dpixel, outimage->pixlen); pixel += inimage->pixlen; dpixel += outimage->pixlen; } break; } } else { /* else use dithering */ NN *nna, *nnp; Intensity *ored, *ogreen, *oblue; int satary[3 * 256 + 20], *sat = &satary[256 + 10]; int *epixel, *ip, nextr, nextg, nextb; int err1ary[512], *err1 = &err1ary[256]; int err3ary[512], *err3 = &err3ary[256]; int err5ary[512], *err5 = &err5ary[256]; int err7ary[512], *err7 = &err7ary[256]; if (verbose) { printf("\n (Using color dithering to reduce the impact of restricted colors)..."); } nna = (NN *) lcalloc((NNmaxI * NNmaxI * NNmaxI) * sizeof(NN)); /* Init saturation table */ for (x = -256 - 10; x < (512 + 10); x++) { y = x; if (y < 0) y = 0; else if (y > 255) y = 255; sat[x] = y; } { int maxerr; /* Fudge factor */ maxerr = (int) (256.0 / pow(((double) colors), 0.45)); /* Init error lookup array */ for (x = -255; x < 256; x++) { int err, ro; err = x; if (err > maxerr) err = maxerr; else if (err < -maxerr) err = -maxerr; err7[x] = (err * 7) / 16; err5[x] = (err * 5) / 16; err3[x] = (err * 3) / 16; err1[x] = (err * 1) / 16; ro = err - err1[x] - err3[x] - err5[x] - err7[x]; switch (err & 3) { /* Distribute round off error */ case 0: err1[x] += ro; break; case 1: err5[x] += ro; break; case 2: err3[x] += ro; break; case 3: err7[x] += ro; break; } } } epixel = ((int *) lcalloc((inimage->width + 2) * 3 * sizeof(int))) + 3; /* set up index mapping tables */ ored = (Intensity *) lmalloc(sizeof(Intensity) * outimage->rgb.size); ogreen = (Intensity *) lmalloc(sizeof(Intensity) * outimage->rgb.size); oblue = (Intensity *) lmalloc(sizeof(Intensity) * outimage->rgb.size); if (UNSET_GAMMA == gamma || (gamma / inimage->gamma) == 1.0) for (x = 0; x < outimage->rgb.size; x++) { ored[x] = outimage->rgb.red[x] >> 8; ogreen[x] = outimage->rgb.green[x] >> 8; oblue[x] = outimage->rgb.blue[x] >> 8; } else /* Create map that accounts for quantizing effect of output */ /* gamma mapping applied to small values. */ for (x = 0; x < outimage->rgb.size; x++) { int val; val = outimage->rgb.red[x] >> 8; val = (int) (0.5 + 255 * pow(val / 255.0, inimage->gamma / gamma)); val = (int) (0.5 + 255 * pow(val / 255.0, gamma / inimage->gamma)); ored[x] = val; val = outimage->rgb.green[x] >> 8; val = (int) (0.5 + 255 * pow(val / 255.0, inimage->gamma / gamma)); val = (int) (0.5 + 255 * pow(val / 255.0, gamma / inimage->gamma)); ogreen[x] = val; val = outimage->rgb.blue[x] >> 8; val = (int) (0.5 + 255 * pow(val / 255.0, inimage->gamma / gamma)); val = (int) (0.5 + 255 * pow(val / 255.0, gamma / inimage->gamma)); oblue[x] = val; } switch (inimage->type) { case IRGB: { Intensity *red = inimage->rgb.red, *green = inimage->rgb.green, *blue = inimage->rgb.blue; if (outimage->pixlen == 1 && inimage->pixlen == 1) { /* most common */ for (x = inimage->width, ip = epixel; x > 0; x--, pixel++) { *ip++ = red[*pixel] >> 8;; *ip++ = green[*pixel] >> 8;; *ip++ = blue[*pixel] >> 8;; } for (y = inimage->height; y > 0; y--) { if (y == 1) /* protect last line */ pixel = inimage->data; for (x = inimage->width, ip = epixel, nextr = *ip, *ip++ = 0, nextg = *ip, *ip++ = 0, nextb = *ip, *ip++ = 0; x > 0; x--) { register unsigned long rgbindex; register int rval, gval, bval, color; rgbindex = ((rval = sat[nextr]) & 0xf8) << (Bits + Bits - cBits); rgbindex |= ((gval = sat[nextg]) & 0xf8) << (Bits - cBits); rgbindex |= (bval = sat[nextb]) >> cBits; *dpixel = color = rgbmap[rgbindex]; if (color == 0xffff) /* Create nearest color mapping on demand */ *dpixel = color = rgbmap[rgbindex] = find_nearest(rval, gval, bval, nna, outimage); dpixel++; rval -= ored[color]; nextr = *ip++ + err7[rval]; /* this line, next pixel */ ip[-1] = err1[rval]; /* next line, next pixel */ ip[-4] += (red[*pixel] >> 8) + err5[rval]; /* next line, this pixel */ ip[-7] += err3[rval]; /* next line, last pixel */ gval -= ogreen[color]; nextg = *ip++ + err7[gval]; /* this line, next pixel */ ip[-1] = err1[gval]; /* next line, next pixel */ ip[-4] += (green[*pixel] >> 8) + err5[gval]; /* next line, this pixel */ ip[-7] += err3[gval]; /* next line, last pixel */ bval -= oblue[color]; nextb = *ip++ + err7[bval]; /* this line, next pixel */ ip[-1] = err1[bval]; /* next line, next pixel */ ip[-4] += (blue[*pixel++] >> 8) + err5[bval]; /* next line, this pixel */ ip[-7] += err3[bval]; /* next line, last pixel */ } } } else { /* less common */ unsigned long temp; for (x = inimage->width, ip = epixel; x > 0; x--, pixel += inimage->pixlen) { temp = memToVal(pixel, inimage->pixlen); *ip++ = red[temp] >> 8;; *ip++ = green[temp] >> 8;; *ip++ = blue[temp] >> 8;; } for (y = inimage->height; y > 0; y--) { if (y == 1) /* protect last line */ pixel = inimage->data; for (x = inimage->width, ip = epixel, nextr = *ip, *ip++ = 0, nextg = *ip, *ip++ = 0, nextb = *ip, *ip++ = 0; x > 0; x--) { register unsigned long rgbindex; register int rval, gval, bval, color; rgbindex = ((rval = sat[nextr]) & 0xf8) << (Bits + Bits - cBits); rgbindex |= ((gval = sat[nextg]) & 0xf8) << (Bits - cBits); rgbindex |= (bval = sat[nextb]) >> cBits; color = rgbmap[rgbindex]; if (color == 0xffff) /* Create nearest color mapping on demand */ color = rgbmap[rgbindex] = find_nearest(rval, gval, bval, nna, outimage); valToMem(color, dpixel, outimage->pixlen); dpixel += outimage->pixlen; temp = memToVal(pixel, inimage->pixlen); pixel += inimage->pixlen; rval -= ored[color]; nextr = *ip++ + err7[rval]; /* this line, next pixel */ ip[-1] = err1[rval]; /* next line, next pixel */ ip[-4] += (red[temp] >> 8) + err5[rval]; /* next line, this pixel */ ip[-7] += err3[rval]; /* next line, last pixel */ gval -= ogreen[color]; nextg = *ip++ + err7[gval]; /* this line, next pixel */ ip[-1] = err1[gval]; /* next line, next pixel */ ip[-4] += (green[temp] >> 8) + err5[gval]; /* next line, this pixel */ ip[-7] += err3[gval]; /* next line, last pixel */ bval -= oblue[color]; nextb = *ip++ + err7[bval]; /* this line, next pixel */ ip[-1] = err1[bval]; /* next line, next pixel */ ip[-4] += (blue[temp] >> 8) + err5[bval]; /* next line, this pixel */ ip[-7] += err3[bval]; /* next line, last pixel */ } } } } break; case ITRUE: if (inimage->pixlen == 3 && outimage->pixlen == 1) { /* common */ for (x = inimage->width * 3, ip = epixel; x > 0; x--, ip++, pixel++) { *ip = *pixel; } for (y = inimage->height; y > 0; y--) { if (y == 1) /* protect last line */ pixel = inimage->data; for (x = inimage->width, ip = epixel, nextr = *ip, *ip++ = 0, nextg = *ip, *ip++ = 0, nextb = *ip, *ip++ = 0; x > 0; x--) { register unsigned long rgbindex; register int rval, gval, bval, color; rgbindex = ((rval = sat[nextr]) & 0xf8) << (Bits + Bits - cBits); rgbindex |= ((gval = sat[nextg]) & 0xf8) << (Bits - cBits); rgbindex |= (bval = sat[nextb]) >> cBits; *dpixel = color = rgbmap[rgbindex]; if (color == 0xffff) /* Create nearest color mapping on demand */ *dpixel = color = rgbmap[rgbindex] = find_nearest(rval, gval, bval, nna, outimage); dpixel++; rval -= ored[color]; nextr = *ip++ + err7[rval]; /* this line, next pixel */ ip[-1] = err1[rval]; /* next line, next pixel */ ip[-4] += *pixel++ + err5[rval]; /* next line, this pixel */ ip[-7] += err3[rval]; /* next line, last pixel */ gval -= ogreen[color]; nextg = *ip++ + err7[gval]; /* this line, next pixel */ ip[-1] = err1[gval]; /* next line, next pixel */ ip[-4] += *pixel++ + err5[gval]; /* next line, this pixel */ ip[-7] += err3[gval]; /* next line, last pixel */ bval -= oblue[color]; nextb = *ip++ + err7[bval]; /* this line, next pixel */ ip[-1] = err1[bval]; /* next line, next pixel */ ip[-4] += *pixel++ + err5[bval]; /* next line, this pixel */ ip[-7] += err3[bval]; /* next line, last pixel */ } } } else { /* less common */ unsigned long temp; for (x = inimage->width, ip = epixel; x > 0; x--, pixel += inimage->pixlen) { temp = memToVal(pixel, inimage->pixlen); *ip++ = TRUE_RED(temp); *ip++ = TRUE_GREEN(temp); *ip++ = TRUE_BLUE(temp); } for (y = inimage->height; y > 0; y--) { if (y == 1) /* protect last line */ pixel = inimage->data; for (x = inimage->width, ip = epixel, nextr = *ip, *ip++ = 0, nextg = *ip, *ip++ = 0, nextb = *ip, *ip++ = 0; x > 0; x--) { register unsigned long rgbindex; register int rval, gval, bval, color; rgbindex = ((rval = sat[nextr]) & 0xf8) << (Bits + Bits - cBits); rgbindex |= ((gval = sat[nextg]) & 0xf8) << (Bits - cBits); rgbindex |= (bval = sat[nextb]) >> cBits; color = rgbmap[rgbindex]; if (color == 0xffff) /* Create nearest color mapping on demand */ color = rgbmap[rgbindex] = find_nearest(rval, gval, bval, nna, outimage); valToMem(color, dpixel, outimage->pixlen); dpixel += outimage->pixlen; temp = memToVal(pixel, inimage->pixlen); pixel += inimage->pixlen; rval -= ored[color]; nextr = *ip++ + err7[rval]; /* this line, next pixel */ ip[-1] = err1[rval]; /* next line, next pixel */ ip[-4] += err5[rval] /* next line, this pixel */ +TRUE_RED(temp); ip[-7] += err3[rval]; /* next line, last pixel */ gval -= ogreen[color]; nextg = *ip++ + err7[gval]; /* this line, next pixel */ ip[-1] = err1[gval]; /* next line, next pixel */ ip[-4] += err5[gval] /* next line, this pixel */ +TRUE_GREEN(temp); ip[-7] += err3[gval]; /* next line, last pixel */ bval -= oblue[color]; nextb = *ip++ + err7[bval]; /* this line, next pixel */ ip[-1] = err1[bval]; /* next line, next pixel */ ip[-4] += err5[bval] /* next line, this pixel */ +TRUE_BLUE(temp); ip[-7] += err3[bval]; /* next line, last pixel */ } } } break; } lfree((byte *) ored); lfree((byte *) ogreen); lfree((byte *) oblue); lfree((byte *) (epixel - 3)); /* Clean up nn stuff */ for (x = NNmaxI * NNmaxI * NNmaxI, nnp = nna; x > 0; x--, nnp++) { if (nnp->length != 0) { /* free red, green and blue */ lfree((byte *) nnp->red); lfree((byte *) nnp->pixel); } } lfree((char *) nna); } } /* expand an image into a true color image */ Image *expandtotrue(Image *image) { Pixel fg, bg; Image *new_image; int x, y; byte *spixel, *dpixel, *line; unsigned int linelen; byte mask; CURRFUNC("expandtotrue"); if TRUEP (image) return (image); new_image = newTrueImage(image->width, image->height); new_image->title = dupString(image->title); new_image->gamma = image->gamma; switch (image->type) { case IBITMAP: fg = RGB_TO_TRUE(image->rgb.red[1], image->rgb.green[1], image->rgb.blue[1]); bg = RGB_TO_TRUE(image->rgb.red[0], image->rgb.green[0], image->rgb.blue[0]); 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; if (new_image->pixlen == 3) /* most common */ for (x = 0; x < image->width; x++) { valToMem((mask & *spixel ? fg : bg), dpixel, 3); mask >>= 1; if (!mask) { mask = 0x80; spixel++; } dpixel += 3; } else /* less common */ for (x = 0; x < image->width; x++) { valToMem((mask & *spixel ? fg : bg), dpixel, new_image->pixlen); mask >>= 1; if (!mask) { mask = 0x80; spixel++; } dpixel += new_image->pixlen; } line += linelen; } new_image->gamma = 1.0; /* will be linear now */ break; case IRGB: spixel = image->data; dpixel = new_image->data; if (image->pixlen == 1 && new_image->pixlen == 3) /* most common */ for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { register unsigned long temp; temp = memToVal(spixel, 1); temp = RGB_TO_TRUE(image->rgb.red[temp], image->rgb.green[temp], image->rgb.blue[temp]); valToMem(temp, dpixel, 3); spixel += 1; dpixel += 3; } else /* less common */ for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { register unsigned long temp; temp = memToVal(spixel, image->pixlen); temp = RGB_TO_TRUE(image->rgb.red[temp], image->rgb.green[temp], image->rgb.blue[temp]); valToMem(temp, dpixel, new_image->pixlen); spixel += image->pixlen; dpixel += new_image->pixlen; } break; } return (new_image); } /* expand a bitmap image into an indexed RGB pixmap */ Image *expandbittoirgb(Image *image, int depth) { Image *new_image; int x, y; byte *spixel, *dpixel, *line; unsigned int linelen; byte mask; CURRFUNC("expandbittoirgb"); if (!BITMAPP(image)) return (image); new_image = newRGBImage(image->width, image->height, depth); new_image->title = dupString(image->title); new_image->gamma = image->gamma; new_image->rgb.red[0] = image->rgb.red[0]; new_image->rgb.green[0] = image->rgb.green[0]; new_image->rgb.blue[0] = image->rgb.blue[0]; new_image->rgb.red[1] = image->rgb.red[1]; new_image->rgb.green[1] = image->rgb.green[1]; new_image->rgb.blue[1] = image->rgb.blue[1]; new_image->rgb.used = 2; 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; if (new_image->pixlen == 1) /* most common */ for (x = 0; x < image->width; x++) { valToMem((mask & *spixel ? 1 : 0), dpixel, 1); mask >>= 1; if (!mask) { mask = 0x80; spixel++; } dpixel += 1; } else /* less common */ for (x = 0; x < image->width; x++) { valToMem((mask & *spixel ? 1 : 0), dpixel, new_image->pixlen); mask >>= 1; if (!mask) { mask = 0x80; spixel++; } dpixel += new_image->pixlen; } line += linelen; } return (new_image); } /* expand an indexed RGB pixmaps depth */ Image *expandirgbdepth(Image *image, int depth) { Image *new_image; int i, x, y; byte *spixel, *dpixel; CURRFUNC("expandirgb"); if (TRUEP(image)) return (image); if (BITMAPP(image)) return expandbittoirgb(image, depth); if (((depth + 7) / 8) == image->pixlen) { /* no change in storage */ image->depth = depth; resizeRGBMapData(&(image->rgb), depthToColors(depth)); } /* change in storage size */ new_image = newRGBImage(image->width, image->height, depth); new_image->title = dupString(image->title); new_image->gamma = image->gamma; /* copy the color map */ for (i = 0; i < image->rgb.used; i++) { new_image->rgb.red[i] = image->rgb.red[i]; new_image->rgb.green[i] = image->rgb.green[i]; new_image->rgb.blue[i] = image->rgb.blue[i]; } new_image->rgb.used = image->rgb.used; spixel = image->data; dpixel = new_image->data; if (image->pixlen == 1 && new_image->pixlen == 2) /* most common */ for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { *dpixel = 0; /* sign extend bigendian 8bit to 16 bit */ *(dpixel + 1) = *spixel; spixel += 1; dpixel += 2; } else /* less common */ for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { register unsigned long temp; temp = memToVal(spixel, image->pixlen); valToMem(temp, dpixel, new_image->pixlen); spixel += image->pixlen; dpixel += new_image->pixlen; } return (new_image); } xli-2006-11-10/rgbtab.h0000644000031400000060000005467706461630121014055 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/rgbtab.h 1.1 93/07/28 Labtam" */ /* A default X11 colorname to RGB values table */ /* to allow X11 colors to be parsed when not running */ /* in an X11 environment. */ xliXColorTableEntry xliXColorTable[] = { { "snow", 255, 250, 250 }, { "ghost white", 248, 248, 255 }, { "ghostwhite", 248, 248, 255 }, { "white smoke", 245, 245, 245 }, { "whitesmoke", 245, 245, 245 }, { "gainsboro", 220, 220, 220 }, { "floral white", 255, 250, 240 }, { "floralwhite", 255, 250, 240 }, { "old lace", 253, 245, 230 }, { "oldlace", 253, 245, 230 }, { "linen", 250, 240, 230 }, { "antique white", 250, 235, 215 }, { "antiquewhite", 250, 235, 215 }, { "papaya whip", 255, 239, 213 }, { "papayawhip", 255, 239, 213 }, { "blanched almond", 255, 235, 205 }, { "blanchedalmond", 255, 235, 205 }, { "bisque", 255, 228, 196 }, { "peach puff", 255, 218, 185 }, { "peachpuff", 255, 218, 185 }, { "navajo white", 255, 222, 173 }, { "navajowhite", 255, 222, 173 }, { "moccasin", 255, 228, 181 }, { "cornsilk", 255, 248, 220 }, { "ivory", 255, 255, 240 }, { "lemon chiffon", 255, 250, 205 }, { "lemonchiffon", 255, 250, 205 }, { "seashell", 255, 245, 238 }, { "honeydew", 240, 255, 240 }, { "mint cream", 245, 255, 250 }, { "mintcream", 245, 255, 250 }, { "azure", 240, 255, 255 }, { "alice blue", 240, 248, 255 }, { "aliceblue", 240, 248, 255 }, { "lavender", 230, 230, 250 }, { "lavender blush", 255, 240, 245 }, { "lavenderblush", 255, 240, 245 }, { "misty rose", 255, 228, 225 }, { "mistyrose", 255, 228, 225 }, { "white", 255, 255, 255 }, { "black", 0, 0, 0 }, { "dark slate gray", 47, 79, 79 }, { "darkslategray", 47, 79, 79 }, { "dark slate grey", 47, 79, 79 }, { "darkslategrey", 47, 79, 79 }, { "dim gray", 105, 105, 105 }, { "dimgray", 105, 105, 105 }, { "dim grey", 105, 105, 105 }, { "dimgrey", 105, 105, 105 }, { "slate gray", 112, 128, 144 }, { "slategray", 112, 128, 144 }, { "slate grey", 112, 128, 144 }, { "slategrey", 112, 128, 144 }, { "light slate gray", 119, 136, 153 }, { "lightslategray", 119, 136, 153 }, { "light slate grey", 119, 136, 153 }, { "lightslategrey", 119, 136, 153 }, { "gray", 190, 190, 190 }, { "grey", 190, 190, 190 }, { "light grey", 211, 211, 211 }, { "lightgrey", 211, 211, 211 }, { "light gray", 211, 211, 211 }, { "lightgray", 211, 211, 211 }, { "midnight blue", 25, 25, 112 }, { "midnightblue", 25, 25, 112 }, { "navy", 0, 0, 128 }, { "navy blue", 0, 0, 128 }, { "navyblue", 0, 0, 128 }, { "cornflower blue", 100, 149, 237 }, { "cornflowerblue", 100, 149, 237 }, { "dark slate blue", 72, 61, 139 }, { "darkslateblue", 72, 61, 139 }, { "slate blue", 106, 90, 205 }, { "slateblue", 106, 90, 205 }, { "medium slate blue", 123, 104, 238 }, { "mediumslateblue", 123, 104, 238 }, { "light slate blue", 132, 112, 255 }, { "lightslateblue", 132, 112, 255 }, { "medium blue", 0, 0, 205 }, { "mediumblue", 0, 0, 205 }, { "royal blue", 65, 105, 225 }, { "royalblue", 65, 105, 225 }, { "blue", 0, 0, 255 }, { "dodger blue", 30, 144, 255 }, { "dodgerblue", 30, 144, 255 }, { "deep sky blue", 0, 191, 255 }, { "deepskyblue", 0, 191, 255 }, { "sky blue", 135, 206, 235 }, { "skyblue", 135, 206, 235 }, { "light sky blue", 135, 206, 250 }, { "lightskyblue", 135, 206, 250 }, { "steel blue", 70, 130, 180 }, { "steelblue", 70, 130, 180 }, { "light steel blue", 176, 196, 222 }, { "lightsteelblue", 176, 196, 222 }, { "light blue", 173, 216, 230 }, { "lightblue", 173, 216, 230 }, { "powder blue", 176, 224, 230 }, { "powderblue", 176, 224, 230 }, { "pale turquoise", 175, 238, 238 }, { "paleturquoise", 175, 238, 238 }, { "dark turquoise", 0, 206, 209 }, { "darkturquoise", 0, 206, 209 }, { "medium turquoise", 72, 209, 204 }, { "mediumturquoise", 72, 209, 204 }, { "turquoise", 64, 224, 208 }, { "cyan", 0, 255, 255 }, { "light cyan", 224, 255, 255 }, { "lightcyan", 224, 255, 255 }, { "cadet blue", 95, 158, 160 }, { "cadetblue", 95, 158, 160 }, { "medium aquamarine", 102, 205, 170 }, { "mediumaquamarine", 102, 205, 170 }, { "aquamarine", 127, 255, 212 }, { "dark green", 0, 100, 0 }, { "darkgreen", 0, 100, 0 }, { "dark olive green", 85, 107, 47 }, { "darkolivegreen", 85, 107, 47 }, { "dark sea green", 143, 188, 143 }, { "darkseagreen", 143, 188, 143 }, { "sea green", 46, 139, 87 }, { "seagreen", 46, 139, 87 }, { "medium sea green", 60, 179, 113 }, { "mediumseagreen", 60, 179, 113 }, { "light sea green", 32, 178, 170 }, { "lightseagreen", 32, 178, 170 }, { "pale green", 152, 251, 152 }, { "palegreen", 152, 251, 152 }, { "spring green", 0, 255, 127 }, { "springgreen", 0, 255, 127 }, { "lawn green", 124, 252, 0 }, { "lawngreen", 124, 252, 0 }, { "green", 0, 255, 0 }, { "chartreuse", 127, 255, 0 }, { "medium spring green", 0, 250, 154 }, { "mediumspringgreen", 0, 250, 154 }, { "green yellow", 173, 255, 47 }, { "greenyellow", 173, 255, 47 }, { "lime green", 50, 205, 50 }, { "limegreen", 50, 205, 50 }, { "yellow green", 154, 205, 50 }, { "yellowgreen", 154, 205, 50 }, { "forest green", 34, 139, 34 }, { "forestgreen", 34, 139, 34 }, { "olive drab", 107, 142, 35 }, { "olivedrab", 107, 142, 35 }, { "dark khaki", 189, 183, 107 }, { "darkkhaki", 189, 183, 107 }, { "khaki", 240, 230, 140 }, { "pale goldenrod", 238, 232, 170 }, { "palegoldenrod", 238, 232, 170 }, { "light goldenrod yellow", 250, 250, 210 }, { "lightgoldenrodyellow", 250, 250, 210 }, { "light yellow", 255, 255, 224 }, { "lightyellow", 255, 255, 224 }, { "yellow", 255, 255, 0 }, { "gold", 255, 215, 0 }, { "light goldenrod", 238, 221, 130 }, { "lightgoldenrod", 238, 221, 130 }, { "goldenrod", 218, 165, 32 }, { "dark goldenrod", 184, 134, 11 }, { "darkgoldenrod", 184, 134, 11 }, { "rosy brown", 188, 143, 143 }, { "rosybrown", 188, 143, 143 }, { "indian red", 205, 92, 92 }, { "indianred", 205, 92, 92 }, { "saddle brown", 139, 69, 19 }, { "saddlebrown", 139, 69, 19 }, { "sienna", 160, 82, 45 }, { "peru", 205, 133, 63 }, { "burlywood", 222, 184, 135 }, { "beige", 245, 245, 220 }, { "wheat", 245, 222, 179 }, { "sandy brown", 244, 164, 96 }, { "sandybrown", 244, 164, 96 }, { "tan", 210, 180, 140 }, { "chocolate", 210, 105, 30 }, { "firebrick", 178, 34, 34 }, { "brown", 165, 42, 42 }, { "dark salmon", 233, 150, 122 }, { "darksalmon", 233, 150, 122 }, { "salmon", 250, 128, 114 }, { "light salmon", 255, 160, 122 }, { "lightsalmon", 255, 160, 122 }, { "orange", 255, 165, 0 }, { "dark orange", 255, 140, 0 }, { "darkorange", 255, 140, 0 }, { "coral", 255, 127, 80 }, { "light coral", 240, 128, 128 }, { "lightcoral", 240, 128, 128 }, { "tomato", 255, 99, 71 }, { "orange red", 255, 69, 0 }, { "orangered", 255, 69, 0 }, { "red", 255, 0, 0 }, { "hot pink", 255, 105, 180 }, { "hotpink", 255, 105, 180 }, { "deep pink", 255, 20, 147 }, { "deeppink", 255, 20, 147 }, { "pink", 255, 192, 203 }, { "light pink", 255, 182, 193 }, { "lightpink", 255, 182, 193 }, { "pale violet red", 219, 112, 147 }, { "palevioletred", 219, 112, 147 }, { "maroon", 176, 48, 96 }, { "medium violet red", 199, 21, 133 }, { "mediumvioletred", 199, 21, 133 }, { "violet red", 208, 32, 144 }, { "violetred", 208, 32, 144 }, { "magenta", 255, 0, 255 }, { "violet", 238, 130, 238 }, { "plum", 221, 160, 221 }, { "orchid", 218, 112, 214 }, { "medium orchid", 186, 85, 211 }, { "mediumorchid", 186, 85, 211 }, { "dark orchid", 153, 50, 204 }, { "darkorchid", 153, 50, 204 }, { "dark violet", 148, 0, 211 }, { "darkviolet", 148, 0, 211 }, { "blue violet", 138, 43, 226 }, { "blueviolet", 138, 43, 226 }, { "purple", 160, 32, 240 }, { "medium purple", 147, 112, 219 }, { "mediumpurple", 147, 112, 219 }, { "thistle", 216, 191, 216 }, { "snow1", 255, 250, 250 }, { "snow2", 238, 233, 233 }, { "snow3", 205, 201, 201 }, { "snow4", 139, 137, 137 }, { "seashell1", 255, 245, 238 }, { "seashell2", 238, 229, 222 }, { "seashell3", 205, 197, 191 }, { "seashell4", 139, 134, 130 }, { "antiquewhite1", 255, 239, 219 }, { "antiquewhite2", 238, 223, 204 }, { "antiquewhite3", 205, 192, 176 }, { "antiquewhite4", 139, 131, 120 }, { "bisque1", 255, 228, 196 }, { "bisque2", 238, 213, 183 }, { "bisque3", 205, 183, 158 }, { "bisque4", 139, 125, 107 }, { "peachpuff1", 255, 218, 185 }, { "peachpuff2", 238, 203, 173 }, { "peachpuff3", 205, 175, 149 }, { "peachpuff4", 139, 119, 101 }, { "navajowhite1", 255, 222, 173 }, { "navajowhite2", 238, 207, 161 }, { "navajowhite3", 205, 179, 139 }, { "navajowhite4", 139, 121, 94 }, { "lemonchiffon1", 255, 250, 205 }, { "lemonchiffon2", 238, 233, 191 }, { "lemonchiffon3", 205, 201, 165 }, { "lemonchiffon4", 139, 137, 112 }, { "cornsilk1", 255, 248, 220 }, { "cornsilk2", 238, 232, 205 }, { "cornsilk3", 205, 200, 177 }, { "cornsilk4", 139, 136, 120 }, { "ivory1", 255, 255, 240 }, { "ivory2", 238, 238, 224 }, { "ivory3", 205, 205, 193 }, { "ivory4", 139, 139, 131 }, { "honeydew1", 240, 255, 240 }, { "honeydew2", 224, 238, 224 }, { "honeydew3", 193, 205, 193 }, { "honeydew4", 131, 139, 131 }, { "lavenderblush1", 255, 240, 245 }, { "lavenderblush2", 238, 224, 229 }, { "lavenderblush3", 205, 193, 197 }, { "lavenderblush4", 139, 131, 134 }, { "mistyrose1", 255, 228, 225 }, { "mistyrose2", 238, 213, 210 }, { "mistyrose3", 205, 183, 181 }, { "mistyrose4", 139, 125, 123 }, { "azure1", 240, 255, 255 }, { "azure2", 224, 238, 238 }, { "azure3", 193, 205, 205 }, { "azure4", 131, 139, 139 }, { "slateblue1", 131, 111, 255 }, { "slateblue2", 122, 103, 238 }, { "slateblue3", 105, 89, 205 }, { "slateblue4", 71, 60, 139 }, { "royalblue1", 72, 118, 255 }, { "royalblue2", 67, 110, 238 }, { "royalblue3", 58, 95, 205 }, { "royalblue4", 39, 64, 139 }, { "blue1", 0, 0, 255 }, { "blue2", 0, 0, 238 }, { "blue3", 0, 0, 205 }, { "blue4", 0, 0, 139 }, { "dodgerblue1", 30, 144, 255 }, { "dodgerblue2", 28, 134, 238 }, { "dodgerblue3", 24, 116, 205 }, { "dodgerblue4", 16, 78, 139 }, { "steelblue1", 99, 184, 255 }, { "steelblue2", 92, 172, 238 }, { "steelblue3", 79, 148, 205 }, { "steelblue4", 54, 100, 139 }, { "deepskyblue1", 0, 191, 255 }, { "deepskyblue2", 0, 178, 238 }, { "deepskyblue3", 0, 154, 205 }, { "deepskyblue4", 0, 104, 139 }, { "skyblue1", 135, 206, 255 }, { "skyblue2", 126, 192, 238 }, { "skyblue3", 108, 166, 205 }, { "skyblue4", 74, 112, 139 }, { "lightskyblue1", 176, 226, 255 }, { "lightskyblue2", 164, 211, 238 }, { "lightskyblue3", 141, 182, 205 }, { "lightskyblue4", 96, 123, 139 }, { "slategray1", 198, 226, 255 }, { "slategray2", 185, 211, 238 }, { "slategray3", 159, 182, 205 }, { "slategray4", 108, 123, 139 }, { "lightsteelblue1", 202, 225, 255 }, { "lightsteelblue2", 188, 210, 238 }, { "lightsteelblue3", 162, 181, 205 }, { "lightsteelblue4", 110, 123, 139 }, { "lightblue1", 191, 239, 255 }, { "lightblue2", 178, 223, 238 }, { "lightblue3", 154, 192, 205 }, { "lightblue4", 104, 131, 139 }, { "lightcyan1", 224, 255, 255 }, { "lightcyan2", 209, 238, 238 }, { "lightcyan3", 180, 205, 205 }, { "lightcyan4", 122, 139, 139 }, { "paleturquoise1", 187, 255, 255 }, { "paleturquoise2", 174, 238, 238 }, { "paleturquoise3", 150, 205, 205 }, { "paleturquoise4", 102, 139, 139 }, { "cadetblue1", 152, 245, 255 }, { "cadetblue2", 142, 229, 238 }, { "cadetblue3", 122, 197, 205 }, { "cadetblue4", 83, 134, 139 }, { "turquoise1", 0, 245, 255 }, { "turquoise2", 0, 229, 238 }, { "turquoise3", 0, 197, 205 }, { "turquoise4", 0, 134, 139 }, { "cyan1", 0, 255, 255 }, { "cyan2", 0, 238, 238 }, { "cyan3", 0, 205, 205 }, { "cyan4", 0, 139, 139 }, { "darkslategray1", 151, 255, 255 }, { "darkslategray2", 141, 238, 238 }, { "darkslategray3", 121, 205, 205 }, { "darkslategray4", 82, 139, 139 }, { "aquamarine1", 127, 255, 212 }, { "aquamarine2", 118, 238, 198 }, { "aquamarine3", 102, 205, 170 }, { "aquamarine4", 69, 139, 116 }, { "darkseagreen1", 193, 255, 193 }, { "darkseagreen2", 180, 238, 180 }, { "darkseagreen3", 155, 205, 155 }, { "darkseagreen4", 105, 139, 105 }, { "seagreen1", 84, 255, 159 }, { "seagreen2", 78, 238, 148 }, { "seagreen3", 67, 205, 128 }, { "seagreen4", 46, 139, 87 }, { "palegreen1", 154, 255, 154 }, { "palegreen2", 144, 238, 144 }, { "palegreen3", 124, 205, 124 }, { "palegreen4", 84, 139, 84 }, { "springgreen1", 0, 255, 127 }, { "springgreen2", 0, 238, 118 }, { "springgreen3", 0, 205, 102 }, { "springgreen4", 0, 139, 69 }, { "green1", 0, 255, 0 }, { "green2", 0, 238, 0 }, { "green3", 0, 205, 0 }, { "green4", 0, 139, 0 }, { "chartreuse1", 127, 255, 0 }, { "chartreuse2", 118, 238, 0 }, { "chartreuse3", 102, 205, 0 }, { "chartreuse4", 69, 139, 0 }, { "olivedrab1", 192, 255, 62 }, { "olivedrab2", 179, 238, 58 }, { "olivedrab3", 154, 205, 50 }, { "olivedrab4", 105, 139, 34 }, { "darkolivegreen1", 202, 255, 112 }, { "darkolivegreen2", 188, 238, 104 }, { "darkolivegreen3", 162, 205, 90 }, { "darkolivegreen4", 110, 139, 61 }, { "khaki1", 255, 246, 143 }, { "khaki2", 238, 230, 133 }, { "khaki3", 205, 198, 115 }, { "khaki4", 139, 134, 78 }, { "lightgoldenrod1", 255, 236, 139 }, { "lightgoldenrod2", 238, 220, 130 }, { "lightgoldenrod3", 205, 190, 112 }, { "lightgoldenrod4", 139, 129, 76 }, { "lightyellow1", 255, 255, 224 }, { "lightyellow2", 238, 238, 209 }, { "lightyellow3", 205, 205, 180 }, { "lightyellow4", 139, 139, 122 }, { "yellow1", 255, 255, 0 }, { "yellow2", 238, 238, 0 }, { "yellow3", 205, 205, 0 }, { "yellow4", 139, 139, 0 }, { "gold1", 255, 215, 0 }, { "gold2", 238, 201, 0 }, { "gold3", 205, 173, 0 }, { "gold4", 139, 117, 0 }, { "goldenrod1", 255, 193, 37 }, { "goldenrod2", 238, 180, 34 }, { "goldenrod3", 205, 155, 29 }, { "goldenrod4", 139, 105, 20 }, { "darkgoldenrod1", 255, 185, 15 }, { "darkgoldenrod2", 238, 173, 14 }, { "darkgoldenrod3", 205, 149, 12 }, { "darkgoldenrod4", 139, 101, 8 }, { "rosybrown1", 255, 193, 193 }, { "rosybrown2", 238, 180, 180 }, { "rosybrown3", 205, 155, 155 }, { "rosybrown4", 139, 105, 105 }, { "indianred1", 255, 106, 106 }, { "indianred2", 238, 99, 99 }, { "indianred3", 205, 85, 85 }, { "indianred4", 139, 58, 58 }, { "sienna1", 255, 130, 71 }, { "sienna2", 238, 121, 66 }, { "sienna3", 205, 104, 57 }, { "sienna4", 139, 71, 38 }, { "burlywood1", 255, 211, 155 }, { "burlywood2", 238, 197, 145 }, { "burlywood3", 205, 170, 125 }, { "burlywood4", 139, 115, 85 }, { "wheat1", 255, 231, 186 }, { "wheat2", 238, 216, 174 }, { "wheat3", 205, 186, 150 }, { "wheat4", 139, 126, 102 }, { "tan1", 255, 165, 79 }, { "tan2", 238, 154, 73 }, { "tan3", 205, 133, 63 }, { "tan4", 139, 90, 43 }, { "chocolate1", 255, 127, 36 }, { "chocolate2", 238, 118, 33 }, { "chocolate3", 205, 102, 29 }, { "chocolate4", 139, 69, 19 }, { "firebrick1", 255, 48, 48 }, { "firebrick2", 238, 44, 44 }, { "firebrick3", 205, 38, 38 }, { "firebrick4", 139, 26, 26 }, { "brown1", 255, 64, 64 }, { "brown2", 238, 59, 59 }, { "brown3", 205, 51, 51 }, { "brown4", 139, 35, 35 }, { "salmon1", 255, 140, 105 }, { "salmon2", 238, 130, 98 }, { "salmon3", 205, 112, 84 }, { "salmon4", 139, 76, 57 }, { "lightsalmon1", 255, 160, 122 }, { "lightsalmon2", 238, 149, 114 }, { "lightsalmon3", 205, 129, 98 }, { "lightsalmon4", 139, 87, 66 }, { "orange1", 255, 165, 0 }, { "orange2", 238, 154, 0 }, { "orange3", 205, 133, 0 }, { "orange4", 139, 90, 0 }, { "darkorange1", 255, 127, 0 }, { "darkorange2", 238, 118, 0 }, { "darkorange3", 205, 102, 0 }, { "darkorange4", 139, 69, 0 }, { "coral1", 255, 114, 86 }, { "coral2", 238, 106, 80 }, { "coral3", 205, 91, 69 }, { "coral4", 139, 62, 47 }, { "tomato1", 255, 99, 71 }, { "tomato2", 238, 92, 66 }, { "tomato3", 205, 79, 57 }, { "tomato4", 139, 54, 38 }, { "orangered1", 255, 69, 0 }, { "orangered2", 238, 64, 0 }, { "orangered3", 205, 55, 0 }, { "orangered4", 139, 37, 0 }, { "red1", 255, 0, 0 }, { "red2", 238, 0, 0 }, { "red3", 205, 0, 0 }, { "red4", 139, 0, 0 }, { "deeppink1", 255, 20, 147 }, { "deeppink2", 238, 18, 137 }, { "deeppink3", 205, 16, 118 }, { "deeppink4", 139, 10, 80 }, { "hotpink1", 255, 110, 180 }, { "hotpink2", 238, 106, 167 }, { "hotpink3", 205, 96, 144 }, { "hotpink4", 139, 58, 98 }, { "pink1", 255, 181, 197 }, { "pink2", 238, 169, 184 }, { "pink3", 205, 145, 158 }, { "pink4", 139, 99, 108 }, { "lightpink1", 255, 174, 185 }, { "lightpink2", 238, 162, 173 }, { "lightpink3", 205, 140, 149 }, { "lightpink4", 139, 95, 101 }, { "palevioletred1", 255, 130, 171 }, { "palevioletred2", 238, 121, 159 }, { "palevioletred3", 205, 104, 137 }, { "palevioletred4", 139, 71, 93 }, { "maroon1", 255, 52, 179 }, { "maroon2", 238, 48, 167 }, { "maroon3", 205, 41, 144 }, { "maroon4", 139, 28, 98 }, { "violetred1", 255, 62, 150 }, { "violetred2", 238, 58, 140 }, { "violetred3", 205, 50, 120 }, { "violetred4", 139, 34, 82 }, { "magenta1", 255, 0, 255 }, { "magenta2", 238, 0, 238 }, { "magenta3", 205, 0, 205 }, { "magenta4", 139, 0, 139 }, { "orchid1", 255, 131, 250 }, { "orchid2", 238, 122, 233 }, { "orchid3", 205, 105, 201 }, { "orchid4", 139, 71, 137 }, { "plum1", 255, 187, 255 }, { "plum2", 238, 174, 238 }, { "plum3", 205, 150, 205 }, { "plum4", 139, 102, 139 }, { "mediumorchid1", 224, 102, 255 }, { "mediumorchid2", 209, 95, 238 }, { "mediumorchid3", 180, 82, 205 }, { "mediumorchid4", 122, 55, 139 }, { "darkorchid1", 191, 62, 255 }, { "darkorchid2", 178, 58, 238 }, { "darkorchid3", 154, 50, 205 }, { "darkorchid4", 104, 34, 139 }, { "purple1", 155, 48, 255 }, { "purple2", 145, 44, 238 }, { "purple3", 125, 38, 205 }, { "purple4", 85, 26, 139 }, { "mediumpurple1", 171, 130, 255 }, { "mediumpurple2", 159, 121, 238 }, { "mediumpurple3", 137, 104, 205 }, { "mediumpurple4", 93, 71, 139 }, { "thistle1", 255, 225, 255 }, { "thistle2", 238, 210, 238 }, { "thistle3", 205, 181, 205 }, { "thistle4", 139, 123, 139 }, { "gray0", 0, 0, 0 }, { "grey0", 0, 0, 0 }, { "gray1", 3, 3, 3 }, { "grey1", 3, 3, 3 }, { "gray2", 5, 5, 5 }, { "grey2", 5, 5, 5 }, { "gray3", 8, 8, 8 }, { "grey3", 8, 8, 8 }, { "gray4", 10, 10, 10 }, { "grey4", 10, 10, 10 }, { "gray5", 13, 13, 13 }, { "grey5", 13, 13, 13 }, { "gray6", 15, 15, 15 }, { "grey6", 15, 15, 15 }, { "gray7", 18, 18, 18 }, { "grey7", 18, 18, 18 }, { "gray8", 20, 20, 20 }, { "grey8", 20, 20, 20 }, { "gray9", 23, 23, 23 }, { "grey9", 23, 23, 23 }, { "gray10", 26, 26, 26 }, { "grey10", 26, 26, 26 }, { "gray11", 28, 28, 28 }, { "grey11", 28, 28, 28 }, { "gray12", 31, 31, 31 }, { "grey12", 31, 31, 31 }, { "gray13", 33, 33, 33 }, { "grey13", 33, 33, 33 }, { "gray14", 36, 36, 36 }, { "grey14", 36, 36, 36 }, { "gray15", 38, 38, 38 }, { "grey15", 38, 38, 38 }, { "gray16", 41, 41, 41 }, { "grey16", 41, 41, 41 }, { "gray17", 43, 43, 43 }, { "grey17", 43, 43, 43 }, { "gray18", 46, 46, 46 }, { "grey18", 46, 46, 46 }, { "gray19", 48, 48, 48 }, { "grey19", 48, 48, 48 }, { "gray20", 51, 51, 51 }, { "grey20", 51, 51, 51 }, { "gray21", 54, 54, 54 }, { "grey21", 54, 54, 54 }, { "gray22", 56, 56, 56 }, { "grey22", 56, 56, 56 }, { "gray23", 59, 59, 59 }, { "grey23", 59, 59, 59 }, { "gray24", 61, 61, 61 }, { "grey24", 61, 61, 61 }, { "gray25", 64, 64, 64 }, { "grey25", 64, 64, 64 }, { "gray26", 66, 66, 66 }, { "grey26", 66, 66, 66 }, { "gray27", 69, 69, 69 }, { "grey27", 69, 69, 69 }, { "gray28", 71, 71, 71 }, { "grey28", 71, 71, 71 }, { "gray29", 74, 74, 74 }, { "grey29", 74, 74, 74 }, { "gray30", 77, 77, 77 }, { "grey30", 77, 77, 77 }, { "gray31", 79, 79, 79 }, { "grey31", 79, 79, 79 }, { "gray32", 82, 82, 82 }, { "grey32", 82, 82, 82 }, { "gray33", 84, 84, 84 }, { "grey33", 84, 84, 84 }, { "gray34", 87, 87, 87 }, { "grey34", 87, 87, 87 }, { "gray35", 89, 89, 89 }, { "grey35", 89, 89, 89 }, { "gray36", 92, 92, 92 }, { "grey36", 92, 92, 92 }, { "gray37", 94, 94, 94 }, { "grey37", 94, 94, 94 }, { "gray38", 97, 97, 97 }, { "grey38", 97, 97, 97 }, { "gray39", 99, 99, 99 }, { "grey39", 99, 99, 99 }, { "gray40", 102, 102, 102 }, { "grey40", 102, 102, 102 }, { "gray41", 105, 105, 105 }, { "grey41", 105, 105, 105 }, { "gray42", 107, 107, 107 }, { "grey42", 107, 107, 107 }, { "gray43", 110, 110, 110 }, { "grey43", 110, 110, 110 }, { "gray44", 112, 112, 112 }, { "grey44", 112, 112, 112 }, { "gray45", 115, 115, 115 }, { "grey45", 115, 115, 115 }, { "gray46", 117, 117, 117 }, { "grey46", 117, 117, 117 }, { "gray47", 120, 120, 120 }, { "grey47", 120, 120, 120 }, { "gray48", 122, 122, 122 }, { "grey48", 122, 122, 122 }, { "gray49", 125, 125, 125 }, { "grey49", 125, 125, 125 }, { "gray50", 127, 127, 127 }, { "grey50", 127, 127, 127 }, { "gray51", 130, 130, 130 }, { "grey51", 130, 130, 130 }, { "gray52", 133, 133, 133 }, { "grey52", 133, 133, 133 }, { "gray53", 135, 135, 135 }, { "grey53", 135, 135, 135 }, { "gray54", 138, 138, 138 }, { "grey54", 138, 138, 138 }, { "gray55", 140, 140, 140 }, { "grey55", 140, 140, 140 }, { "gray56", 143, 143, 143 }, { "grey56", 143, 143, 143 }, { "gray57", 145, 145, 145 }, { "grey57", 145, 145, 145 }, { "gray58", 148, 148, 148 }, { "grey58", 148, 148, 148 }, { "gray59", 150, 150, 150 }, { "grey59", 150, 150, 150 }, { "gray60", 153, 153, 153 }, { "grey60", 153, 153, 153 }, { "gray61", 156, 156, 156 }, { "grey61", 156, 156, 156 }, { "gray62", 158, 158, 158 }, { "grey62", 158, 158, 158 }, { "gray63", 161, 161, 161 }, { "grey63", 161, 161, 161 }, { "gray64", 163, 163, 163 }, { "grey64", 163, 163, 163 }, { "gray65", 166, 166, 166 }, { "grey65", 166, 166, 166 }, { "gray66", 168, 168, 168 }, { "grey66", 168, 168, 168 }, { "gray67", 171, 171, 171 }, { "grey67", 171, 171, 171 }, { "gray68", 173, 173, 173 }, { "grey68", 173, 173, 173 }, { "gray69", 176, 176, 176 }, { "grey69", 176, 176, 176 }, { "gray70", 179, 179, 179 }, { "grey70", 179, 179, 179 }, { "gray71", 181, 181, 181 }, { "grey71", 181, 181, 181 }, { "gray72", 184, 184, 184 }, { "grey72", 184, 184, 184 }, { "gray73", 186, 186, 186 }, { "grey73", 186, 186, 186 }, { "gray74", 189, 189, 189 }, { "grey74", 189, 189, 189 }, { "gray75", 191, 191, 191 }, { "grey75", 191, 191, 191 }, { "gray76", 194, 194, 194 }, { "grey76", 194, 194, 194 }, { "gray77", 196, 196, 196 }, { "grey77", 196, 196, 196 }, { "gray78", 199, 199, 199 }, { "grey78", 199, 199, 199 }, { "gray79", 201, 201, 201 }, { "grey79", 201, 201, 201 }, { "gray80", 204, 204, 204 }, { "grey80", 204, 204, 204 }, { "gray81", 207, 207, 207 }, { "grey81", 207, 207, 207 }, { "gray82", 209, 209, 209 }, { "grey82", 209, 209, 209 }, { "gray83", 212, 212, 212 }, { "grey83", 212, 212, 212 }, { "gray84", 214, 214, 214 }, { "grey84", 214, 214, 214 }, { "gray85", 217, 217, 217 }, { "grey85", 217, 217, 217 }, { "gray86", 219, 219, 219 }, { "grey86", 219, 219, 219 }, { "gray87", 222, 222, 222 }, { "grey87", 222, 222, 222 }, { "gray88", 224, 224, 224 }, { "grey88", 224, 224, 224 }, { "gray89", 227, 227, 227 }, { "grey89", 227, 227, 227 }, { "gray90", 229, 229, 229 }, { "grey90", 229, 229, 229 }, { "gray91", 232, 232, 232 }, { "grey91", 232, 232, 232 }, { "gray92", 235, 235, 235 }, { "grey92", 235, 235, 235 }, { "gray93", 237, 237, 237 }, { "grey93", 237, 237, 237 }, { "gray94", 240, 240, 240 }, { "grey94", 240, 240, 240 }, { "gray95", 242, 242, 242 }, { "grey95", 242, 242, 242 }, { "gray96", 245, 245, 245 }, { "grey96", 245, 245, 245 }, { "gray97", 247, 247, 247 }, { "grey97", 247, 247, 247 }, { "gray98", 250, 250, 250 }, { "grey98", 250, 250, 250 }, { "gray99", 252, 252, 252 }, { "grey99", 252, 252, 252 }, { "gray100", 255, 255, 255 }, { "grey100", 255, 255, 255 }, { "", 0, 0, 0 } }; xli-2006-11-10/rle.c0000644000031400000060000002173007004736446013364 0ustar smarryconsole/* * rle - read in a Utah RLE Toolkit type image. * * Author: Graeme Gill * Date: 30/5/90 * * Modified 24/5/91 to return 24 bit images if they are found rather * than dithering them down to 8 bits. * */ #define MIN(a,b) ( (a)<(b) ? (a) : (b)) #include "xli.h" #include "imagetypes.h" #include "rle.h" /* 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 color channel and color map */ #define C_NM 3 /* full color, no maps */ #define C_M 4 /* full color with color maps */ static rle_pixel **fmaps; /* file color 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 img_gam = UNSET_GAMMA; /* default image gamma (== don't know) */ static int background[3] = {0, 0, 0}; /* our background color */ int rleIdent(char *fullname, char *name) { ZFILE *rlefile; int x_len, y_len; int rv; rlefile = zopen(fullname); if (!rlefile) { perror("rleIdent"); return (0); } sv_globals.svfb_fd = rlefile; rv = rle_get_setup(&sv_globals); zclose(rlefile); rle_free_setup(&sv_globals); switch (rv) { case 0: /* now figure out the picture type */ 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_ncolors) { case 0: printf(" RLE image with an no color planes\n"); return 0; case 1: 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 color with decoding map */ printf(" 8 bit color RLE image with color map\n"); break; default: printf(" 8 bit RLE image with an illegal color map\n"); return 0; } break; case 3: 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 color map\n"); break; default: printf(" 24 bit color RLE image with an illegal color map\n"); return 0; } break; default: printf(" RLE image with an illegal number (%d)of color planes\n", sv_globals.sv_ncolors); return 0; } return 1; case -1: /* Not rle format */ default: /* Some sort of error */ return 0; } } Image *rleLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { char *name = image_ops->name; 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; CURRFUNC("rleLoad"); if (!(rlefile = zopen(fullname))) { perror("rleLoad"); return (NULL); } sv_globals.svfb_fd = rlefile; if (rle_get_setup(&sv_globals)) { zclose(rlefile); rle_free_setup(&sv_globals); return (NULL); } /* Check comments in file for gamma specification */ { char *v; if ((v = rle_getcom("image_gamma", &sv_globals)) != NULL) { img_gam = atof(v); /* Protect against bogus information */ if (img_gam == UNSET_GAMMA) 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 (UNSET_GAMMA == img_gam) 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 */ 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: fprintf(stderr, "rleLoad: %s - no color channels to display\n", name); zclose(rlefile); rle_free_setup(&sv_globals); 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 color with decoding map */ break; default: fprintf(stderr, "rleLoad: %s - Illegal number of maps for one color channel\n", name); zclose(rlefile); rle_free_setup(&sv_globals); return (NULL); } break; case 3: switch (sv_globals.sv_ncmap) { case 0: ptype = C_NM; /* color, no map */ break; case 3: ptype = C_M; /* color with maps */ break; default: fprintf(stderr, "rleLoad: %s - Illegal number of maps for color picture\n", name); zclose(rlefile); rle_free_setup(&sv_globals); return (NULL); } break; default: fprintf(stderr, "rleLoad: %s - too many of color channels (%d)\n", name, sv_globals.sv_ncolors); zclose(rlefile); rle_free_setup(&sv_globals); 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 color map"); break; case C_NM: printf(" 24 bit RLE image with no map"); break; case C_M: printf(" 24 bit RLE image with color map"); break; } if (img_gam != UNSET_GAMMA) printf(", with gamma of %4.2f\n", img_gam); else printf(", with unknown gamma\n"); } znocache(rlefile); /* get hold of the color maps */ fmaps = buildmap(&sv_globals, sv_globals.sv_ncolors, 1.0); /* now we had better sort out the picture data */ /* rle stufff */ /* Get space for a full color scan line */ if (ptype != SC_M && ptype != BW_NM) { scan = (unsigned char **) lmalloc(sv_globals.sv_ncolors * sizeof(unsigned char *)); for (i = 0; i < sv_globals.sv_ncolors; i++) scan[i] = (unsigned char *) lmalloc(x_len); } if (ptype == C_NM || ptype == C_M) { /* 24 bit color type result */ depth = 3; image = newTrueImage(x_len, y_len); image->title = dupString(name); } else { depth = 1; image = newRGBImage(x_len, y_len, 8 * depth); image->title = dupString(name); } buf = image->data; bufp = buf + (y_len - 1) * x_len * depth; switch (ptype) { case SC_M: case BW_NM: for (j = y_len; j > 0; j--, bufp -= (x_len * depth)) { register unsigned char **bufpp = &bufp; if (rle_getrow(&sv_globals, bufpp) < 0) break; } break; case BW_M: for (j = y_len; j > 0; j--, bufp -= (x_len * depth)) { register unsigned char *dp, *r; register int i; if (rle_getrow(&sv_globals, scan) < 0) break; for (i = x_len, r = &scan[0][0], dp = bufp; i > 0; i--, r++, dp++) *dp = fmaps[0][*r]; } break; case C_NM: for (j = y_len; j > 0; j--, bufp -= (x_len * depth)) { register unsigned char *dp; register unsigned char *r, *g, *b; register int i; if (rle_getrow(&sv_globals, scan) < 0) break; for (i = x_len, dp = bufp, r = &scan[0][0], g = &scan[1][0], b = &scan[2][0]; i > 0; i--, r++, g++, b++) { *(dp++) = *r; *(dp++) = *g; *(dp++) = *b; } } break; case C_M: for (j = y_len; j > 0; j--, bufp -= (x_len * depth)) { register unsigned char *dp; register unsigned char *r, *g, *b; register int i; if (rle_getrow(&sv_globals, scan) < 0) break; for (i = x_len, dp = bufp, r = &scan[0][0], g = &scan[1][0], b = &scan[2][0]; i > 0; i--, r++, g++, b++) { *(dp++) = fmaps[0][*r]; *(dp++) = fmaps[1][*g]; *(dp++) = fmaps[2][*b]; } } } if (ptype != SC_M && ptype != BW_NM) { /* Free line buffer */ for (i = 0; i < sv_globals.sv_ncolors; i++) lfree(scan[i]); lfree((byte *) scan); } /* Deal with color maps */ /* now load an appropriate color map */ if (ptype == SC_M) { /* use their maps */ ncol = 1 << sv_globals.sv_cmaplen; /* number of entries */ for (i = 0; i < ncol; i++) { *(image->rgb.red + i) = fmaps[0][i] << 8; *(image->rgb.green + i) = fmaps[1][i] << 8; *(image->rgb.blue + i) = fmaps[2][i] << 8; } image->rgb.used = ncol; } else if (ptype == BW_NM || ptype == BW_M) { ncol = 256; /* don't know whats been used */ for (i = 0; i < ncol; i++) { *(image->rgb.red + i) = *(image->rgb.green + i) = *(image->rgb.blue + i) = i << 8; } image->rgb.used = ncol; } /* record the image gamma in the image structure */ image->gamma = img_gam; read_trail_opt(image_ops, rlefile, image, verbose); zclose(rlefile); freemap(fmaps); rle_free_setup(&sv_globals); return (image); } xli-2006-11-10/rle.h0000644000031400000060000001117007004736447013367 0ustar smarryconsole/* * 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 /* **************************************************************** * 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(struct sv_globals *globals, int minmap, double gamma); /* * rle_getcom - get a specific comment from the image comments. */ extern char * rle_getcom(char *name, struct sv_globals *globals); /* other functions */ void freemap(rle_pixel **cmap); void rle_debug(int on_off); int rle_get_setup(struct sv_globals *globals); void rle_free_setup(struct sv_globals *globals); int rle_getrow(struct sv_globals *globals, rle_pixel **scanline); /* * 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 */ xli-2006-11-10/rlelib.c0000644000031400000060000007561510525262416014057 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/rlelib.c 6.15 93/07/23 Labtam" */ /* * 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 "xli.h" #include #include "rle.h" #undef DEBUG #ifdef DEBUG # define debug(xx) fprintf(stderr,xx) #else # define debug(xx) #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. */ /* * 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; }; /* "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 */ /* * 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 */ 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 */ }; /* * 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 */ /* * 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). * Record the size of cmap in cmap[-1] so that the memory can be freed * later. */ rle_pixel ** buildmap(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 **)lcalloc((nmap +1) * sizeof(rle_pixel *)); cmap[0] = (rle_pixel *)(nmap +1); cmap++; /* keep size in cmap[-1] */ 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 **)lcalloc((nmap+1) * sizeof(rle_pixel *)); cmap[0] = (rle_pixel *)(nmap+1); cmap++; /* keep size in cmap[-1] */ 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 **)lcalloc((nmap+1) * sizeof(rle_pixel *)); cmap[0] = (rle_pixel *)(nmap+1); cmap++; /* keep size in cmap[-1] */ 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 **)lcalloc((nmap+1) * sizeof(rle_pixel *)); cmap[0] = (rle_pixel *)(nmap+1); cmap++; /* keep size in cmap[-1] */ 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]]; lfree((char *) gammap); /* clean up */ } return cmap; } /* Free up the memory used in the cmap */ void freemap(rle_pixel **cmap) { int i,j; if(cmap != NULL) /* be carefull */ { j = (int)cmap[-1]-1; /* recover size of cmap */ for(i=j-1;i>=0;i--) if(cmap[i] != NULL && (i == 0 || cmap[i] != cmap[0])) lfree((char *)cmap[i]); /* free all its elements */ lfree((char *) (--cmap)); /* free it */ } } /* * 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(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(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 * */ struct inst { unsigned opcode:8, datum:8; }; /* read a byte from th input file */ #define BREAD1(var) (var = zgetc(infile)) /* read a little endian short from the input file */ #define BREAD2(var) (var = zgetc(infile), var |= (zgetc(infile) << 8)) #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 */ /***************************************************************** * 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. */ int rle_get_setup(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; globals->sv_bg_color = NULL; /* in case of error, nothing to free */ globals->sv_cmap = NULL; globals->sv_comments = NULL; BREAD2( magic ); if ( zeof( infile ) ) { debug("rlelib: EOF on reading magic\n"); return -3; } if ( magic != XtndRMAGIC ) { debug("rlelib: bad magic\n"); return -1; } BREAD2( setup.h_xpos ); /* assume VAX packing */ BREAD2( setup.h_ypos ); BREAD2( setup.h_xlen ); BREAD2( setup.h_ylen ); BREAD1( setup.h_flags ); BREAD1( setup.h_ncolors ); BREAD1( setup.h_pixelbits ); BREAD1( setup.h_ncmap ); BREAD1( setup.h_cmaplen ); if ( zeof( infile ) ) { debug("rlelib: EOF on reading header\n"); return -4; } /* 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; } for ( i = 0; i < maplen; i++ ) BREAD2( globals->sv_cmap[i] ); } /* Check for comments */ if ( setup.h_flags & H_COMMENT ) { short comlen, evenlen; register char * cp; BREAD2( comlen ); /* get comment length */ 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_free_setup ) * * Free any memory allocated by rle_get_setup * Inputs: * globals: Contains pointer to the input file. * Algorithm: * Assumes non-zero values mean there is something to free. */ void rle_free_setup(struct sv_globals *globals) { if(globals->sv_bg_color != NULL) lfree((char *)globals->sv_bg_color); if(globals->sv_cmap != NULL) lfree((char *)globals->sv_cmap); if(globals->sv_comments != NULL) { if(*globals->sv_comments != NULL) lfree((char *)*globals->sv_comments); lfree((char *)globals->sv_comments); } globals->sv_bg_color = NULL; globals->sv_cmap = NULL; globals->sv_comments = NULL; } /***************************************************************** * 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(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, or -1 if there was an error. * 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. */ int rle_getrow(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 ) { if (debug_f) fprintf(stderr, "Skipping a line\n"); return globals->sv_private.get.scan_y; } } /* If EOF has been encountered, return also */ if ( globals->sv_private.get.is_eof ) { if (debug_f) fprintf(stderr, "EOF was was encountered last read.\n"); 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 (;;) { BREAD1( inst.opcode ); BREAD1( inst.datum ); if ( zeof(infile) ) { if (debug_f) fprintf(stderr, "Got eof on read\n"); globals->sv_private.get.is_eof = 1; break; /* <--- one of the exits */ } switch( OPCODE(inst) ) { case RSkipLinesOp: if ( LONGP(inst) ) { BREAD2( 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) ) { BREAD2( 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) ) { BREAD2( 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) ) { BREAD2( long_data ); nc = long_data; } else nc = DATUM(inst); scan_x += nc + 1; BREAD2( 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: if (debug_f) fprintf(stderr, "Got eof op code\n"); globals->sv_private.get.is_eof = 1; break; default: fprintf( stderr, "rle_getrow: Unrecognized opcode: %d\n", inst.opcode ); return (-1); } if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp ) break; /* <--- the other loop exit */ } return globals->sv_private.get.scan_y; } /* * 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. * */ /***************************************************************** * TAG( make_gamma ) * * Makes a gamma compenstation map. * Inputs: * gamma: desired gamma * gammamap: gamma mapping array * Outputs: * Changes gamma array entries. */ void make_gamma(double gamma, int *gammamap) { 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 } } xli-2006-11-10/root.c0000644000031400000060000001322410525262416013555 0ustar smarryconsole/* 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 "xli.h" #include #define RETAIN_PROP_NAME "_XSETROOT_ID" static void updateProperty(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(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(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((caddr_t) pm); } else if (actual_type != None) { fprintf(stderr, "%s: warning: invalid format encountered for property %s\n", "xli", RETAIN_PROP_NAME); } } } /* this returns the root window for DECWindows servers. this is right * out of xsetroot with minor formatting changes. * (Later DEC OSF/1 releases don't need this stuff) */ static Window getWmRootWindow(Display * dpy, Window root) { Window parent, retv; Window *child; unsigned int nchildren; XWindowAttributes rootatt, childatt; retv = None; if (!XGetWindowAttributes(dpy, root, &rootatt)) { fprintf(stderr, "XGetWindowAttributes on root failed.\n"); exit(1); } if (XQueryTree(dpy, root, &root, &parent, &child, &nchildren)) { int i; for (i = 0; i < nchildren; i++) { if (!XGetWindowAttributes(dpy, child[i], &childatt)) { XFree((caddr_t) child); fprintf(stderr, "XGetWindowAttributes on child failed.\n"); exit(1); } if ((rootatt.width == childatt.width) && (rootatt.height == childatt.height)) retv = child[i]; } XFree((caddr_t) child); return retv; } else { fprintf(stderr, "XQueryTree failed (window doesn't exist).\n"); exit(1); } } static Window getDECRootWindow(Display * dpy, Window root) { Window temporary_rootW; temporary_rootW = getWmRootWindow(dpy, root); return (getWmRootWindow(dpy, temporary_rootW)); } void imageOnRoot(DisplayInfo * dinfo, Image * image, ImageOptions * options) { Display *disp = dinfo->disp; int scrn = dinfo->scrn; Pixmap pixmap; XImageInfo *ximageinfo; Atom __SWM_VROOT = None; Window root, rootReturn, parentReturn, *children; unsigned int numChildren; int i; char *s; if (globals.dest_window) root = globals.dest_window; else { root = RootWindow(disp, scrn); /* look for DECWindows servers because they do strange stuff with the * root window. they should be shot for that one. * (Later DEC OSF/1 releases don't need this stuff) */ for (s = ServerVendor(disp); *s; s++) if (!strncmp(s, "DECWINDOWS", 10) && !xlistrstr(s, "OSF/1")) root = getDECRootWindow(disp, root); /* 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; } } XFree((caddr_t) children); } freePrevious(disp, root); if (!(ximageinfo = imageToXImage(disp, scrn, DefaultVisual(disp, scrn), DefaultDepth(disp, scrn), image, FALSE, TRUE, options))) { 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); ximageinfo->rootimage = TRUE; /* make sure colors arn't freed */ freeXImage(image, ximageinfo); preserveResource(disp, root); } xli-2006-11-10/rotate.c0000644000031400000060000001142407004736450014072 0ustar smarryconsole/* rotate.c * * rotate an image * * Contributed by Tom Tatlow (tatlow@dash.enet.dec.com) */ #include "copyright.h" #include "xli.h" /* rotate_bitmap() * converts an old bitmap bit position into a new one */ static void rotate_bitmap(int num, int pos, int width, int height, int *new_num, int *new_pos) { 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(Image * iimage, int rotate, int verbose) { int rot; /* Actual rotation */ Image *simage; /* Source image */ Image *dimage; /* 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 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; CURRFUNC("rotate"); if (verbose) { printf(" Rotating image by %d degrees...", rotate); fflush(stdout); } simage = iimage; dimage = 0; for (rot = 0; rot < rotate; rot += 90) { switch (simage->type) { case IBITMAP: dimage = newBitImage(simage->height, simage->width); for (x = 0; x < simage->rgb.used; x++) { *(dimage->rgb.red + x) = *(simage->rgb.red + x); *(dimage->rgb.green + x) = *(simage->rgb.green + x); *(dimage->rgb.blue + x) = *(simage->rgb.blue + x); } slinelen = (simage->width / 8) + (simage->width % 8 ? 1 : 0); sp = simage->data; dp = dimage->data; for (i = 0; i < (slinelen * simage->height); i++) for (b = 0; b < 8; b++) if (sp[i] & bit[b]) { rotate_bitmap(i, b, simage->width, simage->height, &newi, &newb); dp[newi] |= bit[newb]; } break; case IRGB: dimage = newRGBImage(simage->height, simage->width, simage->depth); for (x = 0; x < simage->rgb.used; x++) { *(dimage->rgb.red + x) = *(simage->rgb.red + x); *(dimage->rgb.green + x) = *(simage->rgb.green + x); *(dimage->rgb.blue + x) = *(simage->rgb.blue + x); } dimage->rgb.used = simage->rgb.used; /* build array of y axis ptrs into destination image */ yptr = (byte **) lmalloc(simage->width * sizeof(char *)); dlinelen = simage->height * dimage->pixlen; for (y = 0; y < simage->width; y++) yptr[y] = dimage->data + (y * dlinelen); /* rotate */ sp = simage->data; if (simage->pixlen == 1 && dimage->pixlen == 1) /* most common */ for (y = 0; y < simage->height; y++) for (x = 0; x < simage->width; x++) { register unsigned long temp; temp = memToVal(sp, 1); valToMem(temp, yptr[x] + (simage->height - y - 1), 1); sp += 1; } else /* less common */ for (y = 0; y < simage->height; y++) for (x = 0; x < simage->width; x++) { register unsigned long temp; temp = memToVal(sp, simage->pixlen); valToMem(temp, yptr[x] + ((simage->height - y - 1) * dimage->pixlen), dimage->pixlen); sp += simage->pixlen; } lfree((byte *) yptr); break; case ITRUE: if (TRUEP(simage)) dimage = newTrueImage(simage->height, simage->width); /* build array of y axis ptrs into destination image */ yptr = (byte **) lmalloc(simage->width * sizeof(char *)); dlinelen = simage->height * dimage->pixlen; for (y = 0; y < simage->width; y++) yptr[y] = dimage->data + (y * dlinelen); /* rotate */ sp = simage->data; if (simage->pixlen == 3 && dimage->pixlen == 3) /* most common */ for (y = 0; y < simage->height; y++) for (x = 0; x < simage->width; x++) { register unsigned long temp; temp = memToVal(sp, 3); valToMem(temp, yptr[x] + ((simage->height - y - 1) * 3), 3); sp += 3; } else /* less common */ for (y = 0; y < simage->height; y++) for (x = 0; x < simage->width; x++) { register unsigned long temp; temp = memToVal(sp, simage->pixlen); valToMem(temp, yptr[x] + ((simage->height - y - 1) * dimage->pixlen), dimage->pixlen); sp += simage->pixlen; } lfree((byte *) yptr); break; default: printf("rotate: Unsupported image type\n"); exit(1); } if (simage != iimage) freeImage(simage); simage = dimage; } dimage->title = (char *) lmalloc(strlen(iimage->title) + 40); sprintf(dimage->title, "%s (rotated by %d degrees)", iimage->title, rot); dimage->gamma = iimage->gamma; if (verbose) printf("done\n"); return (dimage); } xli-2006-11-10/send.c0000644000031400000060000005426510525262416013535 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/send.c 6.21 94/07/29 Labtam" */ /* 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 "xli.h" #include /* extra colors to try allocating in private color maps to minimise flashing */ #define NOFLASH_COLORS 256 /* number of colors to allow in the default colormap */ #define DEFAULT_COLORS 16 static int GotError; static int pixmapErrorTrap(Display *disp, XErrorEvent *pErrorEvent) { #define MAXERRORLEN 100 char buf[MAXERRORLEN+1]; GotError = 1; XGetErrorText(disp, pErrorEvent->error_code, buf, MAXERRORLEN); printf("serial #%ld (request code %d) Got Error %s\n", pErrorEvent->serial, pErrorEvent->request_code, buf); return(0); } Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *xii) { int (*old_handler)(); Pixmap pixmap; GotError = 0; old_handler = XSetErrorHandler(pixmapErrorTrap); XSync(disp, False); pixmap= XCreatePixmap(disp, parent, xii->ximage->width, xii->ximage->height, xii->depth); (void)XSetErrorHandler(old_handler); if (GotError) return(None); xii->drawable= pixmap; sendXImage(xii, 0, 0, 0, 0, xii->ximage->width, xii->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(Display *disp, int scrn, unsigned int depth) { #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 4) /* the way things are */ XPixmapFormatValues *xf; int nxf, a; xf = XListPixmapFormats(disp, &nxf); for (a = 0; a < nxf; a++) if (xf[a].depth == depth) { int bpp; bpp = xf[a].bits_per_pixel; XFree(xf); return (unsigned int) bpp; } XFree(xf); #else /* the way things were (X11R3) */ 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); #endif /* this should never happen; if it does, we're in trouble */ fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); exit(1); } static int shmErrorTrap(Display *d, XErrorEvent *ev) { GotError = 1; if (ev->error_code != BadAccess) pixmapErrorTrap(d, ev); return 0; } static void createImage(XImageInfo *xii, Image *image, Visual *visual, int depth, int format) { if (XShmQueryExtension(xii->disp)) { xii->ximage = XShmCreateImage(xii->disp, visual, depth, format, NULL, &xii->shm, image->width, image->height); xii->shm.shmid = shmget(IPC_PRIVATE, xii->ximage->bytes_per_line * image->height, IPC_CREAT | 0777); if (xii->shm.shmid >= 0) { int ret; XErrorHandler old_handler; xii->ximage->data = xii->shm.shmaddr = shmat(xii->shm.shmid, 0, 0); xii->shm.readOnly = False; XSync(xii->disp, False); GotError = 0; old_handler = XSetErrorHandler(shmErrorTrap); ret = XShmAttach(xii->disp, &xii->shm); XSync(xii->disp, False); (void) XSetErrorHandler(old_handler); if (ret && !GotError) { shmctl(xii->shm.shmid, IPC_RMID, 0); return; } shmdt(xii->shm.shmaddr); shmctl(xii->shm.shmid, IPC_RMID, 0); xii->shm.shmid = -1; } XDestroyImage(xii->ximage); } xii->ximage = XCreateImage(xii->disp, visual, depth, format, 0, NULL, image->width, image->height, 8, 0); xii->ximage->data = lmalloc(image->height * xii->ximage->bytes_per_line); } XImageInfo *imageToXImage(Display *disp, int scrn, Visual *visual, unsigned int ddepth, Image *image, unsigned int private_cmap, unsigned int fit, ImageOptions *options) { float display_gamma = globals.display_gamma; unsigned int verbose = globals.verbose; Pixel *redvalue, *greenvalue, *bluevalue; unsigned int a, b, c=0, newmap, x, y, dpixlen, dbits; XColor xcolor; XImageInfo *xii; Image *orig_image; boolean dogamma=FALSE; int gammamap[256]; CURRFUNC("imageToXImage"); /* set up to adjust the image gamma for the display gamma we've got */ if(GAMMA_NOT_EQUAL(display_gamma,image->gamma) && !(BITMAPP(image))) { make_gamma(display_gamma/image->gamma,gammamap); dogamma = TRUE; } xcolor.flags= DoRed | DoGreen | DoBlue; redvalue= greenvalue= bluevalue= NULL; orig_image= image; xii= (XImageInfo *)lmalloc(sizeof(XImageInfo)); xii->disp= disp; xii->scrn= scrn; xii->depth= 0; xii->drawable= None; xii->index= NULL; xii->rootimage= FALSE; /* assume not */ xii->foreground= xii->background= 0; xii->gc= NULL; xii->ximage= NULL; xii->shm.shmid = -1; /* 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->map_entries > 2) { Image *dimage; int ncols = visual->map_entries; if(ncols >= 256) ncols -= DEFAULT_COLORS; /* allow for some default colors */ dimage = reduce(image, ncols, options->colordither, display_gamma, verbose); if(dimage != image && orig_image != image) freeImage(image); image = dimage; if(GAMMA_NOT_EQUAL(display_gamma,image->gamma)) { make_gamma(display_gamma/image->gamma,gammamap); dogamma = TRUE; } } else { /* it must be monochrome */ Image *dimage; dimage= dither(image, verbose); if(dimage != image && orig_image != image) freeImage(image); image = dimage; } } break; case IRGB: switch(visual->class) { case TrueColor: case DirectColor: /* no problem, we handle this just fine */ break; default: if (visual->map_entries <= 2) { /* monochrome */ Image *dimage; dimage= dither(image, verbose); if(dimage != image && orig_image != image) freeImage(image); image = dimage; } break; } case IBITMAP: /* no processing ever needs to be done for bitmaps */ break; } /* do color allocation */ switch (visual->class) { case TrueColor: case DirectColor: { 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)) xii->cmap= DefaultColormap(disp, scrn); else xii->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; redtop = greentop = bluetop = 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, xii->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))) { xii->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"); lfree((byte *) redvalue); lfree((byte *) greenvalue); lfree((byte *) bluevalue); lfree((byte *) xii); 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; default: /* Not TrueColor or DirectColor */ retry: /* this tag is used when retrying because we couldn't get a fit */ xii->index= (Pixel *)lmalloc(sizeof(Pixel) * (image->rgb.used+NOFLASH_COLORS)); /* 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)) { /* 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)) xii->cmap= DefaultColormap(disp, scrn); else xii->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); newmap= 0; /* allocate colors shareable (if we can) */ for (a= 0; a < image->rgb.used; a++) { if (dogamma) { xcolor.red= GAMMA16(*(image->rgb.red + a)); xcolor.green= GAMMA16(*(image->rgb.green + a)); xcolor.blue= GAMMA16(*(image->rgb.blue + a)); } else { xcolor.red= *(image->rgb.red + a); xcolor.green= *(image->rgb.green + a); xcolor.blue= *(image->rgb.blue + a); } if (! XAllocColor(disp, xii->cmap, &xcolor)) { if ((visual->class == StaticColor) || (visual->class == StaticGray)) { printf("imageToXImage: XAllocColor failed on a static visual\n"); xii->no = a; freeXImage(image, xii); 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, xii->cmap, xii->index, a, 0); xii->no = 0; newmap= 1; break; } } *(xii->index + a)= xcolor.pixel; } xii->no = a; /* number of pixels allocated in default visual */ } else { newmap= 1; fit= 0; } if (newmap) { if (fit) { /* fit the image into the map we have. Fitting the * colors is hard, we have to: * 1. count the available colors using XAllocColorCells. * 2. reduce the depth of the image to fit. * 3. grab the server so no one can goof with the colormap. * 4. free the colors we just allocated. * 5. allocate the colors again shareable. * 6. ungrab the server and continue on our way. */ if (verbose) printf(" Fitting image into default colormap\n"); for (a= 0; a < image->rgb.used; a++) /* count entries we got */ if (! XAllocColorCells(disp, xii->cmap, False, NULL, 0, xii->index + a, 1)) break; if (a <= 2) { Image *dimage; if (verbose) { printf(" Cannot fit into default colormap, dithering..."); fflush(stdout); } dimage= dither(image, 0); if(dimage != image && orig_image != image) freeImage(image); image = dimage; if (verbose) printf("done\n"); fit= 0; if(a > 0) XFreeColors(disp, xii->cmap, xii->index, a, 0); lfree((byte *) xii->index); xii->index = NULL; goto retry; } if (a < image->rgb.used) { /* if image has too many colors, reduce it */ Image *dimage; dimage= reduce(image, a, options->colordither, display_gamma, verbose); if(dimage != image && orig_image != image) freeImage(image); image = dimage; if(GAMMA_NOT_EQUAL(display_gamma,image->gamma)) { /* reduce may have changed it */ make_gamma(display_gamma/image->gamma,gammamap); dogamma = TRUE; } } XGrabServer(disp); /* stop someone else snarfing the colors */ XFreeColors(disp, xii->cmap, xii->index, a, 0); for (a= 0; a < image->rgb.used; a++) { if(dogamma) { xcolor.red= GAMMA16(*(image->rgb.red + a)); xcolor.green= GAMMA16(*(image->rgb.green + a)); xcolor.blue= GAMMA16(*(image->rgb.blue + a)); } else { 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, xii->cmap, &xcolor)) { printf("XAllocColor failed while fitting colormap!\n"); XUngrabServer(disp); xii->no = a; freeXImage(image, xii); return(NULL); } *(xii->index + a)= xcolor.pixel; } XUngrabServer(disp); xii->no = a; } else { /* not fit */ /* * we create a private cmap and allocate * the colors writable. */ if (verbose) printf(" Using private colormap\n"); /* create new colormap */ xii->cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); for (a= 0; a < image->rgb.used; a++) /* count entries we got */ if (! XAllocColorCells(disp, xii->cmap, False, NULL, 0, xii->index + a, 1)) break; if (a == 0) { fprintf(stderr, "imageToXImage: Color allocation failed!\n"); lfree((byte *) xii->index); xii->index = NULL; freeXImage(image, xii); return(NULL); } if (a < image->rgb.used) { /* if image has too many colors, reduce it */ Image *dimage; dimage= reduce(image, a, options->colordither, display_gamma, verbose); if(dimage != image && orig_image != image) freeImage(image); image = dimage; if(GAMMA_NOT_EQUAL(display_gamma,image->gamma)) { /* reduce may have changed it */ make_gamma(display_gamma/image->gamma,gammamap); dogamma = TRUE; } } /* See if we can allocate some more colors for a few */ /* entries from the default color map to reduce flashing.*/ for(c=0; c < NOFLASH_COLORS; c++) { if (! XAllocColorCells(disp, xii->cmap, False, NULL, 0, xii->index + a + c, 1)) break; } for(b=0; b < c; b++) { /* set default colors */ xcolor.pixel = *(xii->index + b); XQueryColor(disp, DefaultColormap(disp, scrn), &xcolor); XStoreColor(disp, xii->cmap, &xcolor); } if(dogamma) { for (b=0; b < a; b++) { xcolor.pixel= *(xii->index + c + b); xcolor.red= GAMMA16(*(image->rgb.red + b)); xcolor.green= GAMMA16(*(image->rgb.green + b)); xcolor.blue= GAMMA16(*(image->rgb.blue + b)); XStoreColor(disp, xii->cmap, &xcolor); } } else { for (b=0; b < a; b++) { xcolor.pixel= *(xii->index + c + b); xcolor.red= *(image->rgb.red + b); xcolor.green= *(image->rgb.green + b); xcolor.blue= *(image->rgb.blue + b); XStoreColor(disp, xii->cmap, &xcolor); } } xii->no = a + c; } } 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 *dst, *src; int rowbytes; createImage(xii, image, visual, 1, XYBitmap); dst = xii->ximage->data; src = image->data; rowbytes = (image->width + 7) / 8; assert(rowbytes <= xii->ximage->bytes_per_line); for (y = image->height; y--;) { memcpy(dst, src, rowbytes); if (LSBFirst == xii->ximage->bitmap_bit_order) flipBits(dst, rowbytes); dst += xii->ximage->bytes_per_line; src += rowbytes; } xii->depth= ddepth; if(visual->class == DirectColor || visual->class == TrueColor) { Pixel pixval; dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); dpixlen= (dbits + 7) / 8; pixval= redvalue[image->rgb.red[0] >> 8] | greenvalue[image->rgb.green[0] >> 8] | bluevalue[image->rgb.blue[0] >> 8]; xii->background = pixval; pixval= redvalue[image->rgb.red[1] >> 8] | greenvalue[image->rgb.green[1] >> 8] | bluevalue[image->rgb.blue[1] >> 8]; xii->foreground = pixval; } else { /* Not Direct or True Color */ xii->foreground= *((xii->index + c) + 1); xii->background= *(xii->index + c); } break; } case IRGB: case ITRUE: /* modify image data to match visual and colormap */ dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */ xii->depth= ddepth; dpixlen= (dbits + 7) / 8; /* bytes per pixel */ switch (visual->class) { case DirectColor: case TrueColor: { byte *data, *dst, *src; Pixel *pixels, *p; createImage(xii, image, visual, ddepth, ZPixmap); pixels = (Pixel *) lmalloc(image->width * sizeof(Pixel)); src = image->data; data = xii->ximage->data; for (y = image->height; y--;) { for (p = pixels, x = image->width; x--; src += image->pixlen, ++p) *p = memToVal(src, image->pixlen); if (IRGB == image->type) { for (p = pixels, x = image->width; x--; ++p) { *p = RGB_TO_TRUE(image->rgb.red[*p], image->rgb.green[*p], image->rgb.blue[*p]); } } if (dogamma) { for (p = pixels, x = image->width; x--; ++p) { *p = RGB_TO_TRUE(GAMMA8(TRUE_RED(*p)) << 8, GAMMA8(TRUE_GREEN(*p)) << 8, GAMMA8(TRUE_BLUE(*p)) << 8); } } for (p = pixels, x = image->width; x--; ++p) { *p = redvalue[TRUE_RED(*p)] | greenvalue[TRUE_GREEN(*p)] | bluevalue[TRUE_BLUE(*p)]; } dst = data; if (MSBFirst == xii->ximage->byte_order) { for (p = pixels, x = image->width; x--; ++p, dst += dpixlen) valToMem(*p, dst, dpixlen); } else { for (p = pixels, x = image->width; x--; ++p, dst += dpixlen) valToMemLSB(*p, dst, dpixlen); } data += xii->ximage->bytes_per_line; } lfree((byte *) pixels); break; } default: /* only IRGB images make it this far. */ createImage(xii, image, visual, ddepth, ZPixmap); /* if our XImage doesn't have modulus 8 bits per pixel, it's unclear * how to pack bits so we use XPutPixel. this is slower. */ if (dbits % 8) { byte *src; src = image->data; for (y = 0; y < image->height; ++x) { for (x = 0; x < image->width; ++x) { XPutPixel(xii->ximage, x, y, xii->index[c + memToVal(src, image->pixlen)]); src += image->pixlen; } } } else { byte *data, *src, *dst; data = xii->ximage->data; src = image->data; for (y = image->height; y--;) { dst = data; if (MSBFirst == xii->ximage->byte_order) { for (x = image->width; x--; src += image->pixlen, dst += dpixlen) { valToMem(xii->index[c + memToVal(src, image->pixlen)], dst, dpixlen); } } else { for (x = image->width; x--; src += image->pixlen, dst += dpixlen) { valToMemLSB(xii->index[c + memToVal(src, image->pixlen)], dst, dpixlen); } } data += xii->ximage->bytes_per_line; } } break; } } if (verbose) printf("done\n"); if (redvalue) { lfree((byte *)redvalue); lfree((byte *)greenvalue); lfree((byte *)bluevalue); } if (verbose && dogamma) printf(" Have adjusted image from %4.2f to display gamma of %4.2f\n",image->gamma,display_gamma); if (image != orig_image) freeImage(image); return(xii); } /* Given an XImage and a drawable, move a rectangle from the Ximage * to the drawable. */ void sendXImage(XImageInfo *xii, int src_x, int src_y, int dst_x, int dst_y, unsigned w, unsigned h) { XGCValues gcv; /* build and cache the GC */ if (!xii->gc) { gcv.function= GXcopy; if (xii->ximage->depth == 1) { gcv.foreground= xii->foreground; gcv.background= xii->background; xii->gc= XCreateGC(xii->disp, xii->drawable, GCFunction | GCForeground | GCBackground, &gcv); } else xii->gc= XCreateGC(xii->disp, xii->drawable, GCFunction, &gcv); } if (src_x < 0 || src_y < 0 || src_x + w > xii->ximage->width || src_y + h > xii->ximage->height) return; if (xii->shm.shmid >= 0) { XShmPutImage(xii->disp, xii->drawable, xii->gc, xii->ximage, src_x, src_y, dst_x, dst_y, w, h, False); XSync(xii->disp, False); } else { XPutImage(xii->disp, xii->drawable, xii->gc, xii->ximage, src_x, src_y, dst_x, dst_y, w, h); } } /* free up anything cached in the local Ximage structure. */ void freeXImage(Image *image, XImageInfo *xii) { if (xii->index != NULL) { /* if we allocated colors */ if (xii->no > 0 && !xii->rootimage) /* don't free root colors */ XFreeColors(xii->disp, xii->cmap, xii->index, xii->no, 0); lfree((byte *) xii->index); } if (xii->gc) XFreeGC(xii->disp, xii->gc); if (xii->shm.shmid >= 0) { XShmDetach(xii->disp, &xii->shm); shmdt(xii->shm.shmaddr); shmctl(xii->shm.shmid, IPC_RMID, 0); } else { lfree((byte *) xii->ximage->data); } xii->ximage->data= NULL; XDestroyImage(xii->ximage); lfree((byte *) xii); /* should we free private color map to ??? */ } xli-2006-11-10/smooth.c0000644000031400000060000000706407004736451014113 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/smooth.c 1.10 94/07/29 Labtam" */ /* 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 "xli.h" static Image *doSmooth(Image *isrc) { Image *src = isrc, *dest, *tmp; int x, y, x1, y1, linelen; int xindex[3]; byte *yindex[3]; byte *srcptr, *destptr; unsigned long avgred, avggreen, avgblue; /* build true color image from old image and allocate new image */ tmp= expandtotrue(src); if (src != tmp && src != isrc) freeImage(src); src = tmp; dest= newTrueImage(src->width, src->height); dest->title= (char *)lmalloc(strlen(src->title) + 12); sprintf(dest->title, "%s (smoothed)", src->title); dest->gamma= src->gamma; /* run through src and take a guess as to what the color should * actually be. */ destptr= dest->data; linelen= src->pixlen * src->width; if(dest->pixlen == 3 && src->pixlen == 3) { /* usual case */ for (y= 0; y < src->height; y++) { yindex[1]= src->data + (y * linelen); yindex[0]= yindex[1] - (y > 0 ? linelen : 0); yindex[2]= yindex[1] + (y < src->height - 1 ? linelen : 0); for (x= 0; x < src->width; x++) { avgred= avggreen= avgblue= 0; xindex[1]= x * 3; xindex[0]= xindex[1] - (x > 0 ? 3 : 0); xindex[2]= xindex[1] + (x < src->width - 1 ? 3 : 0); for (y1= 0; y1 < 3; y1++) { for (x1= 0; x1 < 3; x1++) { srcptr = yindex[y1] + xindex[x1]; avgred += *srcptr; avggreen += *(srcptr + 1); avgblue += *(srcptr + 2); } } /* average the pixel values */ *destptr++ = ((avgred + 8) / 9); *destptr++ = ((avggreen + 8) / 9); *destptr++ = ((avgblue + 8) / 9); } } } else { /* less usual */ Pixel pixval; for (y= 0; y < src->height; y++) { yindex[1]= src->data + (y * linelen); yindex[0]= yindex[1] - (y > 0 ? linelen : 0); yindex[2]= yindex[1] + (y < src->height - 1 ? linelen : 0); for (x= 0; x < src->width; x++) { avgred= avggreen= avgblue= 0; xindex[1]= x * src->pixlen; xindex[0]= xindex[1] - (x > 0 ? src->pixlen : 0); xindex[2]= xindex[1] + (x < src->width - 1 ? src->pixlen : 0); for (y1= 0; y1 < 3; y1++) { for (x1= 0; x1 < 3; x1++) { pixval= memToVal(yindex[y1] + xindex[x1], src->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, dest->pixlen); destptr += dest->pixlen; } } } if (src != isrc) /* Free possible intermediate image */ freeImage(src); return(dest); } Image *smooth(Image *isrc, int iterations, int verbose) { int a; Image *src=isrc,*tmp; if(GAMMA_NOT_EQUAL(src->gamma, 1.0)) gammacorrect(src, 1.0, verbose); if (verbose) { printf(" Smoothing..."); fflush(stdout); } for (a= 0; a < iterations; a++) { tmp= doSmooth(src); if(src != tmp && src != isrc) /* free imtermediate image */ freeImage(src); src= tmp; } if (verbose) printf("done\n"); return(src); } xli-2006-11-10/sunraster.c0000644000031400000060000002111107004736451014615 0ustar smarryconsole/* 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 "xli.h" #include "imagetypes.h" #include "sunraster.h" /* SUPPRESS 558 */ /* SUPPRESS 560 */ static void babble(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(" %ldx%ld", 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(char *fullname, char *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 sizeof(struct rheader): if (memToVal(header.magic, 4) != RMAGICNUMBER) { r= 0; break; } babble(name, &header); r= 1; break; case -1: perror("sunRasterIdent"); default: r= 0; break; } zclose(zf); return(r); } /* read either rl-encoded or normal image data * Return TRUE if read was ok */ static boolean sunread(ZFILE *zf, byte *buf, unsigned int len, unsigned int enc, char *name) /* 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) { fprintf(stderr,"sunRasterLoad: %s - Bad read on encoded image data\n",name); return FALSE; } if (repchar == RESC) { if (zread(zf, &remaining, 1) != 1) { fprintf(stderr,"sunRasterLoad: %s - Bad read on encoded image data\n",name); return FALSE; } if (remaining == 0) *(buf++)= RESC; else { if (zread(zf, &repchar, 1) != 1) { fprintf(stderr,"sunRasterLoad: %s - Bad read on encoded image data\n",name); return FALSE; } *(buf++)= repchar; } } else *(buf++)= repchar; } } /* normal read */ else { if (zread(zf, buf, len) < len) { fprintf(stderr,"sunRasterLoad: %s - Bad read on standard image data\n",name); return FALSE; } } return TRUE; } Image *sunRasterLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; 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; 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 sizeof(struct rheader): if (memToVal(header.magic, 4) != RMAGICNUMBER) { zclose(zf); return(NULL); } if (verbose) babble(name, &header); break; case -1: perror("sunRasterLoad"); 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)); linelen= image->width * image->pixlen; break; default: fprintf(stderr,"sunRasterLoad: %s - Bad depth %d (only 1, 8, 24 are valid)\n",name,depth); zclose(zf); return NULL; } image->title= dupString(name); /* * Handle color map... */ mapsize= memToVal(header.maplen, 4); if (mapsize) { map= lmalloc(mapsize); if (zread(zf, map, mapsize) < mapsize) { fprintf(stderr,"sunRasterLoad: %s - Bad read on colormap\n",name); lfree(map); freeImage(image); zclose(zf); return NULL; } mapsize /= 3; if (depth > 8) { fprintf(stderr,"sunRasterLoad: %s - Warning, true color image colormap being ignored\n",name); } else { /* can handle 8 bit indexed rgb */ if (mapsize > image->rgb.size) { fprintf(stderr,"sunRasterLoad: %s - Warning, colormap is too big for depth\n",name); mapsize = image->rgb.size; /* rgb.size is set from depth */ } mapred= map; mapgreen= mapred + mapsize; mapblue= mapgreen + 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); } image->rgb.used= mapsize; } lfree(map); } /* * Handle 8-bit greyscale via a simple ramp function... */ else if (depth == 8) { for (mapsize = 256, y= 0; y < mapsize; y++) { *(image->rgb.red + y)= (y << 8); *(image->rgb.green + y)= (y << 8); *(image->rgb.blue + y)= (y << 8); } image->rgb.used= mapsize; } /* 24-bit and 32-bit handle themselves. currently we don't support * a colormap for them. */ enc= (memToVal(header.type, 4) == RRLENCODED); 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; linelen= image->width * (depth == 24 ? 3 : 4); fill= (linelen % 2 ? 1 : 0); buf= lmalloc(linelen); for (y= 0; y < image->height; y++) { if (!sunread(zf, buf, linelen, enc, name)) { lfree(buf); zclose(zf); return(image); } bp= buf; if (memToVal(header.type, 4) != RRGB) { if (depth == 24) { for (x= 0; x < image->width; x++) { *(lineptr++)= *(bp + 2); /* red */ *(lineptr++)= *(bp + 1); /* green */ *(lineptr++)= *bp; /* blue */ bp += 3; } } else { for (x= 0; x < image->width; x++) { *(lineptr++)= *(bp + 3); /* red */ *(lineptr++)= *(bp + 2); /* green */ *(lineptr++)= *(bp + 1); /* blue */ bp += 4; } } } else { /* RGB */ if (depth == 24) { for (x= 0; x < image->width; x++) { *(lineptr++)= *bp; /* red */ *(lineptr++)= *(bp + 1); /* green */ *(lineptr++)= *(bp + 2); /* blue */ bp += 3; } } else { for (x= 0; x < image->width; x++) { *(lineptr++)= *bp; /* red */ *(lineptr++)= *(bp + 1); /* green */ *(lineptr++)= *(bp + 2); /* blue */ bp += 4; } } } if (fill) if (!sunread(zf, &fillchar, fill, enc, name)) { lfree(buf); zclose(zf); return(image); } } lfree(buf); } else { if (depth == 1) linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); else linelen= image->width * image->pixlen; fill= (linelen % 2 ? 1 : 0); for (y= 0; y < image->height; y++) { if (!sunread(zf, lineptr, linelen, enc, name)) { zclose(zf); return(image); } lineptr += linelen; if (fill) if (!sunread(zf, &fillchar, fill, enc, name)) { zclose(zf); return(image); } } } read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } xli-2006-11-10/sunraster.h0000644000031400000060000000355306461630121014625 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/sunraster.h 6.7 93/07/23 Labtam" */ /* 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 */ xli-2006-11-10/tga.c0000644000031400000060000002312707004736451013353 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/tga.c 1.2 93/07/28 Labtam" */ /* * Read a TrueVision Targa file. * * Created for xli by Graeme Gill, * * partially based on tgatoppm Copyright by Jef Poskanzer, * * which was partially based on tga2rast, version 1.0, by Ian MacPhedran. * */ #include "xli.h" #include "imagetypes.h" #include "tga.h" /* Read the header of the file, and */ /* Return TRUE if this looks like a tga file */ /* Note that since Targa files don't have a magic number, */ /* we have to be pickey about this. */ static boolean read_tgaHeader(ZFILE *zf, tgaHeader *hp, char *name) { unsigned char buf[18]; if(zread(zf, buf, TGA_HEADER_LEN) != TGA_HEADER_LEN) return FALSE; hp->IDLength = (unsigned int)buf[0]; hp->CoMapType = (unsigned int)buf[1]; hp->ImgType = (unsigned int)buf[2]; hp->Index = (unsigned int)buf[3] + 256 * (unsigned int)buf[4]; hp->Length = (unsigned int)buf[5] + 256 * (unsigned int)buf[6]; hp->CoSize = (unsigned int)buf[7]; hp->X_org = (int)buf[8] + 256 * (int)buf[9]; hp->Y_org = (int)buf[10] + 256 * (int)buf[11]; hp->Width = (unsigned int)buf[12] + 256 * (unsigned int)buf[13]; hp->Height = (unsigned int)buf[14] + 256 * (unsigned int)buf[15]; hp->PixelSize = (unsigned int)buf[16]; hp->AttBits = (unsigned int)buf[17] & 0xf; hp->Rsrvd = ( (unsigned int)buf[17] & 0x10 ) >> 4; hp->OrgBit = ( (unsigned int)buf[17] & 0x20 ) >> 5; hp->IntrLve = ( (unsigned int)buf[17] & 0xc0 ) >> 6; /* See if it is consistent with a tga files */ if( hp->CoMapType != 0 && hp->CoMapType != 1) return FALSE; if( hp->ImgType != 1 && hp->ImgType != 2 && hp->ImgType != 3 && hp->ImgType != 9 && hp->ImgType != 10 && hp->ImgType != 11) return FALSE; if( hp->CoSize != 0 && hp->CoSize != 15 && hp->CoSize != 16 && hp->CoSize != 24 && hp->CoSize != 32) return FALSE; if( hp->PixelSize != 8 && hp->PixelSize != 16 && hp->PixelSize != 24 && hp->PixelSize != 32) return FALSE; if( hp->IntrLve != 0 && hp->IntrLve != 1 && hp->IntrLve != 2) return FALSE; /* Do a few more consistency checks */ if(hp->ImgType == TGA_Map || hp->ImgType == TGA_RLEMap) { if(hp->CoMapType != 1 || hp->CoSize == 0) return FALSE; /* map types must have map */ } else { if(hp->CoMapType != 0 || hp->CoSize != 0) return FALSE; /* non-map types must not have map */ } /* can only handle 8 or 16 bit pseudo color images */ if(hp->CoMapType != 0 && hp->PixelSize > 16) return FALSE; /* other numbers mustn't be silly */ if( (hp->Index + hp->Length) > 65535 || (hp->X_org + hp->Width) > 65535 || (hp->Y_org + hp->Height) > 65535) return FALSE; /* setup run-length encoding flag */ if( hp->ImgType == TGA_RLEMap || hp->ImgType == TGA_RLERGB || hp->ImgType == TGA_RLEMono) hp->RLE = TRUE; else hp->RLE = FALSE; hp->name = name; return TRUE; } /* Print a brief description of the image */ static void tell_about_tga(tgaHeader *hp) { char colors[40]; if (hp->ImgType == TGA_Map || hp->ImgType == TGA_RLEMap) sprintf(colors," with %d colors",hp->Length); else colors[0] = '\000'; printf("%s is a %dx%d %sTarga %simage%s\n", hp->name, hp->Width, hp->Height, TGA_IL_TYPE(hp->IntrLve), TGA_IMAGE_TYPE(hp->ImgType), colors); } int tgaIdent(char *fullname, char *name) { ZFILE *zf; tgaHeader hdr; if(!(zf = zopen(fullname))) { perror("tgaIdent"); return(0); } if (!read_tgaHeader(zf,&hdr,name)) { zclose(zf); return 0; /* Nope, not a Targa file */ } tell_about_tga(&hdr); zclose(zf); return 1; } Image *tgaLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; tgaHeader hdr; Image *image; int span,hretrace,vretrace,nopix,x,y; byte *data,*eoi; unsigned int rd_count,wr_count; if(!(zf = zopen(fullname))) { perror("tgaIdent"); return(0); } if(!read_tgaHeader(zf,&hdr,image_ops->name)) { zclose(zf); return NULL; /* Nope, not a Targa file */ } if(verbose) tell_about_tga(&hdr); znocache(zf); /* Skip the identifier string */ if(hdr.IDLength) { byte buf[256]; if(zread(zf, buf, hdr.IDLength) != hdr.IDLength) { fprintf(stderr, "tgaLoad: %s - Short read within Identifier String\n",hdr.name); zclose(zf); return NULL; } } /* Create the appropriate image and colormap */ if(hdr.CoMapType != 0) /* must be 8 or 16 bit mapped type */ { int i,n=0; byte buf[4]; int used = (1 << hdr.PixelSize); /* maximum numnber of colors */ image= newRGBImage(hdr.Width, hdr.Height, hdr.PixelSize); image->title= dupString(hdr.name); for(i = 0; i < hdr.Index; i++) /* init bottom of colormap */ { image->rgb.red[i]= image->rgb.green[i]= image->rgb.blue[i]= 0; } switch (hdr.CoSize) { case 8: /* Gray scale color map */ for(; i < ( hdr.Index + hdr.Length ); i++) { if(zread(zf, buf, 1) != 1) { fprintf(stderr, "tgaLoad: %s - Short read within Colormap\n",hdr.name); freeImage(image); zclose(zf); return NULL; } image->rgb.red[i]= image->rgb.green[i]= image->rgb.blue[i]= buf[0] << 8; } break; case 16: /* 5 bits of RGB */ case 15: for(i = hdr.Index; i < ( hdr.Index + hdr.Length ); i++) { if(zread(zf, buf, 2) != 2) { fprintf(stderr, "tgaLoad: %s - Short read within Colormap\n",hdr.name); freeImage(image); zclose(zf); return NULL; } image->rgb.red[i]= (buf[1] & 0x7c) << 6; image->rgb.green[i]= ((buf[1] & 0x03)<< 11) + ((buf[0] & 0xe0)<< 3); image->rgb.blue[i]= (buf[0] & 0x1f)<< 8; } break; case 32: /* 8 bits of RGB */ n = 1; case 24: n += 3; for(i = hdr.Index; i < ( hdr.Index + hdr.Length ); i++) { if(zread(zf, buf, n) != n) { fprintf(stderr, "tgaLoad: %s - Short read within Colormap\n",hdr.name); freeImage(image); zclose(zf); return NULL; } image->rgb.red[i]= buf[2] << 8; image->rgb.green[i]= buf[1] << 8; image->rgb.blue[i]= buf[0] << 8; } break; } for(; i < used; i++) /* init rest of colormap */ { image->rgb.red[i]= image->rgb.green[i]= image->rgb.blue[i]= 0; } /* Don't know how many colors are actually used. */ /* (believing the header caould cause a fault) */ /* compress() will figure it out. */ image->rgb.used= used; /* so use max possible */ } else if(hdr.PixelSize == 8) /* Have to handle gray as pseudocolor */ { int i; image= newRGBImage(hdr.Width, hdr.Height, 8); image->title= dupString(hdr.name); 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 /* else must be a true color image */ { image= newTrueImage(hdr.Width, hdr.Height); image->title= dupString(hdr.name); } /* work out virtical advance and retrace */ if(hdr.OrgBit) /* if upper left */ span = hdr.Width; else span = -hdr.Width; if (hdr.IntrLve == TGA_IL_Four ) hretrace = 4 * span - hdr.Width; else if(hdr.IntrLve == TGA_IL_Two ) hretrace = 2 * span - hdr.Width; else hretrace = span - hdr.Width; vretrace = (hdr.Height-1) * -span; nopix = (hdr.Width * hdr.Height); /* total number of pixels */ hretrace *= image->pixlen; /* scale for byes per pixel */ vretrace *= image->pixlen; span *= image->pixlen; if(hdr.OrgBit) /* if upper left */ { data = image->data; eoi = image->data + (nopix * image->pixlen); } else { eoi = image->data + span; data = image->data + (nopix * image->pixlen) + span; } /* Now read in the image data */ rd_count = wr_count = 0; if (!hdr.RLE) /* If not rle, all are literal */ wr_count = rd_count = nopix; for(y = hdr.Height; y > 0; y--, data += hretrace) { byte buf[6]; /* 0, 1 for pseudo, 2, 3, 4 for BGR */ if (data == eoi) /* adjust for possible retrace */ { data += vretrace; eoi += span; } /* Do another line of pixels */ for(x = hdr.Width; x > 0; x--) { if(wr_count == 0) { /* Deal with run length encoded. */ if(zread(zf, buf, 1) != 1) goto data_short; if(buf[0] & 0x80) { /* repeat count */ wr_count = (unsigned int)buf[0] - 127; /* no. */ rd_count = 1; /* need to read pixel to repeat */ } else /* number of literal pixels */ { wr_count = rd_count = buf[0] + 1; } } if(rd_count != 0) { /* read a pixel and decode into RGB */ switch (hdr.PixelSize) { case 8: /* Pseudo or Gray */ if(zread(zf, buf, 1) != 1) goto data_short; break; case 16: /* 5 bits of RGB or 16 pseudo color */ case 15: if(zread(zf, buf, 2) != 2) goto data_short; buf[2] = buf[0] & 0x1F; /* B */ buf[3] = ((buf[1] & 0x03) << 3) + ((unsigned)(buf[0] & 0xE0) >> 5); /* G */ buf[4] = (unsigned)(buf[1] & 0x7C) >> 2; /* R */ break; case 24: /* 8 bits of B G R */ if(zread(zf, &buf[2], 3) != 3) goto data_short; break; case 32: /* 8 bits of B G R + alpha */ if(zread(zf, &buf[2], 4) != 4) goto data_short; break; } rd_count--; } switch (image->pixlen) { case 1: /* 8 bit pseudo or gray */ *data++ = buf[0]; break; case 2: /* 16 bit pseudo */ *data++ = buf[1]; /* tga is little endian, */ *data++ = buf[0]; /* xli is big endian */ break; case 3: /* True color */ *data++ = buf[4]; /* R */ *data++ = buf[3]; /* G */ *data++ = buf[2]; /* B */ break; } wr_count--; } } zclose(zf); return image; data_short: fprintf(stderr, "tgaLoad: %s - Short read within Data\n",hdr.name); zclose(zf); return image; } xli-2006-11-10/tga.h0000644000031400000060000000366406461630121013355 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/tga.h 1.1 93/07/28 Labtam" */ /* *tga.h - header file for Targa files */ #define TGA_HEADER_LEN 18 /* Header structure definition. */ typedef struct { char *name; /* stash pointer to name here too */ unsigned int IDLength; /* length of Identifier String */ unsigned int CoMapType; /* 0 = no map */ unsigned int ImgType; /* image type (see below for values) */ unsigned int Index; /* index of first color map entry */ unsigned int Length; /* number of entries in color map */ unsigned int CoSize; /* size of color map entry (15,16,24,32) */ int X_org; /* x origin of image */ int Y_org; /* y origin of image */ unsigned int Width; /* width of image */ unsigned int Height; /* height of image */ unsigned int PixelSize; /* pixel size (8,16,24,32) */ unsigned int AttBits; /* 4 bits, number of attribute bits per pixel */ unsigned int Rsrvd; /* 1 bit, reserved */ unsigned int OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */ unsigned int IntrLve; /* 2 bits, interleaving flag */ boolean RLE; /* Run length encoded */ } tgaHeader; /* Definitions for image types. */ #define TGA_Null 0 /* Not used */ #define TGA_Map 1 #define TGA_RGB 2 #define TGA_Mono 3 #define TGA_RLEMap 9 #define TGA_RLERGB 10 #define TGA_RLEMono 11 #define TGA_CompMap 32 /* Not used */ #define TGA_CompMap4 33 /* Not used */ #define TGA_IMAGE_TYPE(tt) \ tt == 1 ? "Pseudo color " : \ tt == 2 ? "True color " : \ tt == 3 ? "Gray scale " : \ tt == 9 ? "Run length encoded pseudo color " : \ tt == 10 ? "Run length encoded true color " : \ tt == 11 ? "Run length encoded gray scale " : \ "Unknown " /* Definitions for interleave flag. */ #define TGA_IL_None 0 #define TGA_IL_Two 1 #define TGA_IL_Four 2 #define TGA_IL_TYPE(tt) \ tt == 0 ? "" : \ tt == 1 ? "Two way interleaved " : \ tt == 2 ? "Four way interleaved " : \ "Unknown " xli-2006-11-10/tgncpyrght.h0000644000031400000060000000225106461630121014762 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/tgncpyrght.h 1.5 93/07/23 Labtam" */ #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 xli-2006-11-10/value.c0000644000031400000060000000151707004736452013714 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/value.c 6.9 93/07/23 Labtam" */ /* 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 "xli.h" /* this flips all the bits in a byte array at byte intervals */ void flipBits(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]]; } xli-2006-11-10/window.c0000644000031400000060000006240310525262416014104 0ustar smarryconsole/* * 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 "xli.h" #include #include #include #include #include #if defined(linux) #include #endif #if (defined(SYSV) || defined(SVR4)) && !defined(__hpux) && !defined(_CRAY) #include #include #endif #ifdef _AIX #include #endif static Window ImageWindow = 0; static Window ViewportWin = 0; static Colormap ImageColormap; static int AlarmWentOff = 0; static void delayAlarmHandler(int sig_no) { 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(Display *disp, XEvent *event) { #if (defined(SYSV) || defined(SVR4)) && !defined(__hpux) && !defined(_CRAY) struct pollfd pfd[1]; #else fd_set rmask; int nfound; #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); } #if (defined(SYSV) || defined(SVR4)) && !defined(__hpux) && !defined(_CRAY) pfd[0].fd = ConnectionNumber(disp); pfd[0].events = POLLIN; poll(pfd, 1, -1L); /* use very long timeout */ switch (pfd[0].revents) { #else FD_ZERO(&rmask); FD_SET(ConnectionNumber(disp), &rmask); nfound = select(ConnectionNumber(disp) + 1, &rmask, (fd_set *) 0, (fd_set *) 0, /*(struct timeval *) */ 0); switch (nfound) { #endif case -1: if (errno == EINTR) { continue; } else { perror("select"); continue; } } } /* end while ! AlarmWentOff */ return (0); } static void setCursor(Display *disp, Window window, unsigned int iw, unsigned int ih, unsigned int ww, unsigned int 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 - ie. constain it to be as * visible as possible in the window, then move it there. */ static void placeImage(Display *disp, int width, int height, int winwidth, int winheight, int *rx, int *ry) /* supplied and returned */ { int pixx, pixy; pixx = *rx; pixy = *ry; if (winwidth > width) /* If window bigger than image */ pixx = (winwidth - width) / 2; /* center it */ else { if ((pixx < 0) && (pixx + width < winwidth)) /* if too far left */ pixx = winwidth - width; /* constrain to right hand side */ if (pixx > 0) /* if too far right */ pixx = 0; /* constrain to left hand side */ } 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 *ximageinfo, unsigned int width, unsigned int height, int x, int y, int w, int 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(DisplayInfo *dinfo) { Display *disp = dinfo->disp; if (ImageWindow) XDestroyWindow(disp, ImageWindow); ImageWindow = 0; if (ViewportWin) XDestroyWindow(disp, ViewportWin); ViewportWin = 0; } /* clean up after displaying an image */ static void cleanUpImage(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. */ static void setViewportColormap(Display *disp, int scrn, Visual *visual) { XSetWindowAttributes swa; static int 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, PropModePrepend, (unsigned char *) cmap_windows, 2); } } /* this attempts to convert an image title into a reasonable icon name */ static char *iconName(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); } /* find the best visual of a particular class with a particular depth */ static Visual *bestVisualOfClassAndDepth(Display *disp, int scrn, int class, unsigned int depth) { Visual *best = 0; XVisualInfo template, *info; int nvisuals; template.screen = scrn; template.class = class; template.depth = depth; if (!(info = XGetVisualInfo(disp, VisualScreenMask | VisualClassMask | VisualDepthMask, &template, &nvisuals))) return (Visual *) 0; /* 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((caddr_t) info); return (best); } /* this tries to determine the best available visual to use for a particular * image */ static void bestVisual(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); visual = 0; 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 * (This is used when the user has specified a visual class) */ static void bestVisualOfClass(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 *) 0; 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(DisplayInfo *dinfo, Image *image, ImageOptions *options, int argc, char **argv) { Display *disp = dinfo->disp; int scrn = dinfo->scrn; unsigned int private_cmap = globals.private_cmap; Pixmap pixmap = None; XImageInfo *xii; Visual *visual; unsigned int depth; int delay = options->delay; 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; int winx, winy, winwidth, winheight; int user_geometry; oldimagewindow = None; oldcmap = None; lastx = lasty = -1; /* figure out the window size. unless specifically requested to do so, * we will not exceed 90% of display real estate. */ if (!globals.user_geometry) { winx = winy = winwidth = winheight = 0; user_geometry = 0; } else { user_geometry = XGeometry(disp, scrn, globals.user_geometry, "0x0+0+0", 0, 1, 1, 0, 0, &winx, &winy, &winwidth, &winheight); } if (globals.fullscreen || globals.fillscreen) { 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 (globals.fit) { visual = DefaultVisual(disp, scrn); depth = DefaultDepth(disp, scrn); } else { visual = (Visual *) 0; if (globals.visual_class == -1) { /* try to pick the best visual for the image. */ bestVisual(disp, scrn, image, &visual, &depth); if (globals.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, globals.visual_class, &visual, &depth); if (!visual) { bestVisual(disp, scrn, image, &visual, &depth); fprintf(stderr, "Server does not support %s visual, using %s\n", nameOfVisualClass(globals.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 (globals.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 or grey scale) so we don't get color erosion when * switching images. */ else if (!options->gray && !BITMAPP(image)) private_cmap = 1; } if (!(xii = imageToXImage(disp, scrn, visual, depth, image, private_cmap, globals.fit, options))) { 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 = "xli"; classhint.res_name = "xli"; 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, PropModePrepend, (unsigned char *) &delete_atom, 1); } if (globals.focus) { XSetTransientForHint(disp, ViewportWin, atoi(getenv("WINDOWID"))); } 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 = xii->cmap; swa_img.border_pixel = 0; swa_img.event_mask = KeyPressMask; /* (Some systems need this) */ ImageWindow = XCreateWindow(disp, ViewportWin, winx, winy, image->width, image->height, 0, xii->depth, InputOutput, visual, CWBitGravity | CWColormap | CWSaveUnder | CWBorderPixel | CWEventMask, &swa_img); ImageColormap = xii->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. */ xii->drawable = ImageWindow; if ((DoesBackingStore(ScreenOfDisplay(disp, scrn)) == NotUseful && xii->shm.shmid < 0) || globals.use_pixmap) { if (((pixmap = ximageToPixmap(disp, ImageWindow, xii)) == None) && globals.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; if (xii->shm.shmid < 0) { 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 &= ~ExposureMask; /* 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 (options->title) { /* Option overides title */ XStoreName(disp, ViewportWin, options->title); XSetIconName(disp, ViewportWin, iconName(options->title)); } else if (image->title) { XStoreName(disp, ViewportWin, image->title); XSetIconName(disp, ViewportWin, iconName(image->title)); } else { XStoreName(disp, ViewportWin, "Unnamed"); XSetIconName(disp, ViewportWin, iconName((char *) 0)); } sh.width = winwidth; sh.height = winheight; if (globals.fullscreen || globals.fillscreen) { 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 || globals.fullscreen || globals.fillscreen) sh.flags |= USSize; else sh.flags |= PSize; if (globals.fullscreen || globals.fillscreen) { sh.x = sh.y = 0; sh.flags |= USPosition; } else if (user_geometry & (XValue | YValue)) { 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 > 0) { /* reset alarm to -delay seconds after every event */ AlarmWentOff = 0; signal(SIGALRM, delayAlarmHandler); alarm(delay); } for (;;) { if (delay > 0) { 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, xii); return ('n'); } } else if (delay == 0 && !XPending(disp)) { Cursor cursor = swa_view.cursor; 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, xii); return ('n'); } else { 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 'l': case 'r': case 'n': case 'f': case 'b': case 'p': case '.': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': case '<': case '=': case '>': case 'x': if ('x' == ret && !globals.delete) break; if (delay > 0) 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, xii); return (ret); case '\003': /* ^C */ case 'q': if (delay > 0) alarm(0); cleanUpImage(disp, scrn, swa_view.cursor, pixmap, image, xii); 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, xii); return ('\0'); case Expose: blitImage(xii, image->width, image->height, event.expose.x, event.expose.y, event.expose.width, event.expose.height); break; case EnterNotify: if (globals.install) XInstallColormap(disp, xii->cmap); break; case LeaveNotify: if (globals.install) XUninstallColormap(disp, xii->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, xii); return ('q'); } break; } } } xli-2006-11-10/xbitmap.c0000644000031400000060000001146510525262416014243 0ustar smarryconsole/* 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 "xli.h" #include "imagetypes.h" #include #define MAX_SIZE 255 /* read a hex value and return its value */ static int nextInt(ZFILE *zf) { int c; int value= 0; int shift= 0; for (;;) { c= zgetc(zf); if (c == EOF) return(-1); else { c= BEHexTable[c & 0xff]; switch(c) { case HEXSTART_BAD: /* start */ shift= 0; /* reset shift counter */ break; case HEXDELIM_BAD: /* delim */ case HEXDELIM_IGNORE: if (shift) return(value); break; case HEXBAD: /* bad */ return(-1); default: value += (c << shift); shift += 4; } } } } /* * Return TRUE if the given file is an xbitmap file */ static boolean isXbitmap(ZFILE *zf, unsigned int *w, unsigned int *h, int *v10p, char **title) { char line[MAX_SIZE]; char name_and_type[MAX_SIZE]; char *type; int value; int maxlines=8; /* 8 lines to find #define etc. */ *title = NULL; *w = 0; *h = 0; /* get width/height values */ while (zgets((byte *)line, MAX_SIZE, zf) && maxlines-- > 0) { if (strlen(line) == MAX_SIZE-1) { return FALSE; } /* 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) { return FALSE; } /* get title of bitmap if any */ if ((type = rindex(name_and_type, '_')) && !strcmp("bits[]", type + 1)) { *type= '\0'; *title= dupString(name_and_type); } return TRUE; } Image *xbitmapLoad(char *fullname, ImageOptions *image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; Image *image; char *title; int value; int v10p; unsigned int linelen, dlinelen; unsigned int x, y; unsigned int w, h; byte *dataptr; if (! (zf= zopen(fullname))) { perror("xbitmapLoad"); return(NULL); } /* See if it's an x bitmap */ { unsigned int tw, th; int tv10p; if (!isXbitmap(zf, &tw, &th, &tv10p, &title)) { zclose(zf); return NULL; } w = tw; h = th; v10p = tv10p; } image= newBitImage(w, h); if (title != NULL) image->title= title; else image->title= dupString(name); if (verbose) { printf("%s is a %dx%d X%s bitmap file titled '%s'\n", name, image->width, image->height, v10p ? "10" : "11", image->title); } /* read bitmap data */ initBEHexTable(); znocache(zf); 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) { fprintf(stderr,"xbitmapLoad: %s - short read on X bitmap file\n", name); zclose(zf); return(image); } *(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) { fprintf(stderr,"xbitmapLoad: %s - short read on X bitmap file\n", name); zclose(zf); return(image); } *(dataptr++)= value; } } read_trail_opt(image_ops,zf,image,verbose); zclose(zf); return(image); } int xbitmapIdent(char *fullname, char *name) { ZFILE *zf; char *title; unsigned int w, h; int v10p; if (! (zf= zopen(fullname))) { perror("xbitmapIdent"); return(0); } /* See if it's an x bitmap */ if (!isXbitmap(zf, &w, &h, &v10p, &title)) { zclose(zf); return 0; } if (title == NULL) title= dupString(name); printf("%s is a %dx%d X%s bitmap file titled '%s'\n", name, w, h, v10p ? "10" : "11",title); lfree(title); zclose(zf); return 1; } xli-2006-11-10/xli.c0000644000031400000060000003076210525262416013374 0ustar smarryconsole/* * xli.c: * * generic image loader for X11 * * smar@reptiles.org 1998/09/30 * * Graeme Gill 93/2/24 * * Based on xloadimage by * jim frost 09.27.89 * * Copyright 1989, 1990, 1991 Jim Frost. * See included file "copyright.h" for complete copyright information. */ #include "copyright.h" #include "xli.h" #include "patchlevel" #include GlobalsRec globals; /* * used for the -default option. this is the root weave bitmap with * the bits in the order that xli likes. */ #define root_weave_width 4 #define root_weave_height 4 static byte root_weave_bits[] = { 0xe0, 0xb0, 0xd0, 0x70 }; #define INIT_IMAGE_OPTS(istr){ \ istr.name = (char *) 0; \ istr.fullname = (char *) 0; \ istr.loader_idx = -1; \ istr.atx = istr.aty = 0; \ istr.ats = FALSE; \ istr.border = (char *) 0; \ istr.bright = 0; \ istr.center = FALSE; \ istr.clipx = istr.clipy = 0;\ istr.clipw = istr.cliph = 0;\ istr.colordither = FALSE; \ istr.colors = 0; \ istr.delay = -1; \ istr.dither = 0; \ istr.gamma = UNSET_GAMMA; \ istr.gray = FALSE; \ istr.iscale = 0; \ istr.iscale_auto = FALSE; \ istr.merge = FALSE; \ istr.normalize = FALSE; \ istr.rotate = 0; \ istr.smooth = FALSE; \ istr.title = NULL; \ istr.xpmkeyc = 0; \ istr.xzoom = istr.yzoom = 0;\ istr.fg = (char *) 0; \ istr.bg = (char *) 0; \ istr.done_to = 0; \ istr.to_argv = 0; } /* deal with unsigned arithmetic problems */ static int scentre(unsigned tspan, unsigned sspan) { return ((int) tspan - (int) sspan) / 2; } int main(int argc, char *argv[]) { Image *idisp; ImageOptions *images; int maximages, nimages, i, first, dir; unsigned int winwidth, winheight; ImageOptions persist_ops; char switchval; CURRFUNC("main"); maximages = INIT_MAXIMAGES; images = (ImageOptions *) lmalloc(maximages * sizeof(ImageOptions)); persist_ops.border = (char *) 0; persist_ops.bright = 0; persist_ops.colordither = FALSE; persist_ops.colors = 0; /* remaining images */ persist_ops.delay = -1; persist_ops.dither = 0; persist_ops.gamma = UNSET_GAMMA; persist_ops.normalize = FALSE; persist_ops.smooth = FALSE; persist_ops.xpmkeyc = 0; /* none */ persist_ops.xzoom = 0; persist_ops.yzoom = 0; persist_ops.iscale = 0; persist_ops.iscale_auto = FALSE; /* 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 if (argc < 2) usage(argv[0]); /* * defaults and other initial settings. some of these depend on what * our name was when invoked. */ loadPathsAndExts(); xliDefaultDispinfo(&globals.dinfo); globals.argv0 = argv[0]; /* so we can get at this elsewhere */ globals._Xdebug = FALSE; globals._DumpCore = FALSE; globals.onroot = FALSE; globals.verbose = TRUE; if (!strcmp(tail(argv[0]), "xview")) { globals.onroot = FALSE; globals.verbose = TRUE; } else if (!strcmp(tail(argv[0]), "xsetbg")) { globals.onroot = TRUE; globals.verbose = FALSE; } /* Get display gamma from the environment if we can */ { char *gstr; globals.display_gamma = UNSET_GAMMA; if ((gstr = getenv("DISPLAY_GAMMA")) != NULL) { globals.display_gamma = atof(gstr); } /* Ignore silly values */ if (globals.display_gamma > 20.0 || globals.display_gamma < 0.05) globals.display_gamma = DEFAULT_DISPLAY_GAMMA; } globals.dname = NULL; globals.fit = FALSE; globals.fillscreen = FALSE; globals.fullscreen = FALSE; globals.go_to = NULL; globals.do_fork = FALSE; globals.identify = FALSE; globals.install = FALSE; globals.private_cmap = FALSE; globals.use_pixmap = FALSE; globals.set_default = FALSE; globals.user_geometry = NULL; globals.visual_class = -1; winwidth = winheight = 0; nimages = 0; INIT_IMAGE_OPTS(images[nimages]); for (i = 1; i < argc; i++) { OptionId opid; opid = optionNumber(argv[i]); if (opid == OPT_BADOPT) { printf("%s: Bad option\n", argv[i]); usage(argv[0]); } if (opid == OPT_SHORTOPT) { printf("%s: Not enough characters to identify option\n", argv[i]); usage(argv[0]); } if (opid == OPT_NOTOPT || opid == NAME) { if (opid == NAME && argv[++i] == NULL) continue; if (nimages + 1 >= maximages) { maximages *= 2; images = (ImageOptions *) lrealloc( (byte *) images, maximages * sizeof(ImageOptions)); } images[nimages].name = argv[i]; images[nimages].border = persist_ops.border; images[nimages].bright = persist_ops.bright; images[nimages].colordither = persist_ops.colordither; images[nimages].colors = persist_ops.colors; images[nimages].delay = persist_ops.delay; images[nimages].dither = persist_ops.dither; images[nimages].gamma = persist_ops.gamma; images[nimages].normalize = persist_ops.normalize; images[nimages].smooth = persist_ops.smooth; images[nimages].xpmkeyc = persist_ops.xpmkeyc; images[nimages].xzoom = persist_ops.xzoom; images[nimages].yzoom = persist_ops.yzoom; images[nimages].iscale_auto = persist_ops.iscale_auto; nimages++; INIT_IMAGE_OPTS(images[nimages]); } else if (isGeneralOption(opid)) { i += doGeneralOption(opid, &argv[i], &persist_ops, &images[nimages]); } else if (isLocalOption(opid)) { i += doLocalOption(opid, &argv[i], TRUE, &persist_ops, &images[nimages]); } else { printf("%s: Internal error parsing arguments\n", argv[0]); exit(1); } } if (globals._DumpCore) { signal(SIGSEGV, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGILL, SIG_DFL); } if (globals.fit && (globals.visual_class != -1)) { printf("-fit and -visual options are mutually exclusive (ignoring -visual)\n"); globals.visual_class = -1; } if (!nimages && !globals.set_default) exit(0); if (globals.identify) { /* identify the named image(s) */ for (i = 0; i < nimages; i++) identifyImage(images[i].name); exit(0); } /* start talking to the display */ if (!xliOpenDisplay(&globals.dinfo, globals.dname)) { fprintf(stderr, "%s: Cannot open display '%s'\n", globals.argv0, xliDisplayName(globals.dname)); exit(1); } if (globals.do_fork) { switch (fork()) { case -1: perror("fork"); /* FALLTHRU */ case 0: break; default: exit(0); } } /* -default: resets colormap and load default root weave */ if (globals.set_default) { byte *old_data; ImageOptions ioptions; boolean tempverb; INIT_IMAGE_OPTS(ioptions); idisp = newBitImage(root_weave_width, root_weave_height); idisp->gamma = globals.display_gamma; old_data = idisp->data; idisp->data = root_weave_bits; tempverb = globals.verbose; globals.verbose = FALSE; imageOnRoot(&globals.dinfo, idisp, &ioptions); globals.verbose = tempverb; idisp->data = old_data; freeImage(idisp); if (!nimages) { xliCloseDisplay(&globals.dinfo); exit(0); } } /* load in each named image */ idisp = 0; first = -1; dir = 1; for (i = 0; i < nimages; i += dir) { ImageOptions *io; Image *inew, *itmp; if (i < 0) { dir = 1; continue; } io = &images[i]; if (io->iscale) { io->xzoom = io->yzoom = io->iscale < 0 ? 100 << -io->iscale : 100 >> io->iscale; } if (!(inew = loadImage(io, globals.verbose))) continue; first = (first < 0); if (inew->flags & FLAG_ISCALE) io->xzoom = io->yzoom = 0; if (io->gamma != UNSET_GAMMA) inew->gamma = io->gamma; else if (UNSET_GAMMA == inew->gamma) defaultgamma(inew); /* Process any other options that need doing here */ if (io->border) { xliParseXColor(&globals.dinfo, io->border, &io->bordercol); xliGammaCorrectXColor(&io->bordercol, DEFAULT_DISPLAY_GAMMA); } /* * if first image and we're putting it on the root window * in fullscreen mode, set zoom factors to something reasonable */ if (first && ((globals.onroot && globals.fullscreen) || globals.fillscreen) && !io->xzoom && !io->yzoom && !io->center) { double wr, hr; wr = (double) globals.dinfo.width / inew->width; hr = (double) globals.dinfo.height / inew->height; io->xzoom = io->yzoom = (((wr < hr) ^ (globals.onroot && globals.fillscreen)) ? wr : hr) * 100 + 0.5; } itmp = processImage(&globals.dinfo, inew, io); if (itmp != inew) freeImage(inew); inew = itmp; if (idisp) { if (io->center) { io->atx = scentre(idisp->width, inew->width); io->aty = scentre(idisp->height, inew->height); } if (!idisp->title) { idisp->title = dupString(inew->title); idisp->gamma = inew->gamma; } itmp = merge(idisp, inew, io->atx, io->aty, io); if (idisp != itmp) { freeImage(idisp); idisp = itmp; } freeImage(inew); } /* * else if this is the first image on root * set its position and any border needed */ if (first && globals.onroot && (winwidth || winheight || io->center || io->ats || globals.fullscreen || globals.fillscreen)) { int atx = io->atx, aty = io->aty; if (!winwidth) winwidth = globals.dinfo.width; if (!winheight) winheight = globals.dinfo.height; if (!images[0].ats) { atx = scentre(winwidth, inew->width); aty = scentre(winheight, inew->height); } /* use clip to put border around image */ itmp = clip(inew, -atx, -aty, winwidth, winheight, io); if (itmp != inew) { freeImage(inew); inew = itmp; } idisp = inew; } else if (!idisp) { idisp = inew; } /* if next image is to be merged onto this one, * then go on to the next image. */ if (globals.onroot || ((i + 1 < nimages) && (images[i + 1].merge))) continue; dir = 1; switchval = imageInWindow(&globals.dinfo, idisp, io, argc, argv); switch (switchval) { /* window got nuked by someone */ case '\0': xliCloseDisplay(&globals.dinfo); exit(1); /* user quit */ case '\003': case 'q': cleanUpWindow(&globals.dinfo); xliCloseDisplay(&globals.dinfo); exit(0); /* delete current image */ case 'x': /* double-check delete-enable here */ if (globals.delete && io->fullname) { if (unlink(io->fullname) < 0) { perror(io->fullname); } else { fprintf(stderr, "Deleted %s\n", io->fullname); } } else { i--; } /* next image */ case ' ': case 'f': case 'n': if (i >= (nimages - 1) && globals.go_to != NULL) { int j; for (j = 0; j < nimages; j++) { if (!strcmp(images[j].name, globals.go_to)) { i = j - 1; break; } } if (j >= nimages) fprintf(stderr, "Target for -goto %s was not found\n", globals.go_to); } break; /* previous image */ case 'b': case 'p': dir = -1; break; case '.': /* re-load current image */ i--; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* change gamma same way as a command line option */ if (UNSET_GAMMA == io->gamma) io->gamma = idisp->gamma; switch (switchval) { int l; double jump; /* set gamma to default image gamma */ case '0': io->gamma = DEFAULT_DISPLAY_GAMMA; break; /* set gamma to 1.0 */ case '1': io->gamma = 1.0; break; default: l = (switchval - '6'); if (l >= 0) l++; if (l > 0) jump = 1.1; else jump = 0.909; if (l < 0) l = -l; for (l--; l > 0; l--) jump *= jump; io->gamma *= jump; break; } if (globals.verbose) printf("Image Gamma now %f\n", io->gamma); i--; break; /* rotations */ case 'l': case 'r': switch (switchval) { case 'l': io->rotate -= 90; break; case 'r': io->rotate += 90; break; } while (io->rotate >= 360) io->rotate -= 360; while (io->rotate < 0) io->rotate += 360; if (globals.verbose) printf("Image rotation is now %d\n", io->rotate); i--; break; case '<': case '=': case '>': switch (switchval) { case '<': io->iscale += 1; break; case '>': io->iscale -= 1; break; case '=': io->iscale = 0; break; } io->xzoom = io->yzoom = 0; io->iscale_auto = 0; if (globals.verbose) { printf("Image decoder scaling is now %d\n", io->iscale); } i--; break; } freeImage(idisp); idisp = 0; } if (idisp && globals.onroot) imageOnRoot(&globals.dinfo, idisp, &images[nimages - 1]); xliCloseDisplay(&globals.dinfo); exit(0); } xli-2006-11-10/xli.h0000644000031400000060000002625307004736453013406 0ustar smarryconsole/* xli.h: * jim frost 06.21.89 * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #if defined(SVR4) && !defined(SYSV) #define SYSV /* SYSV is out System V flag */ #endif #include "copyright.h" #include #include #include #ifndef VMS #include #endif #include "ddxli.h" #include "image.h" #include "options.h" #ifndef INIT_MAXIMAGES #define INIT_MAXIMAGES 1024 #endif /* image name and option structure used when processing arguments */ typedef struct { char *name; /* name of image */ char *fullname; /* full pathname for -delete */ int loader_idx; /* loader last used successfully with image */ int atx, aty; /* location to load image at */ boolean ats; /* TRUE if atx and aty have been set */ unsigned int bright; /* brightness multiplier */ boolean center; /* true if image is to be centered */ int clipx, clipy; /* Offset and area of image to be used */ unsigned int clipw, cliph; char *border; /* Border colour used in clipping */ XColor bordercol; /* X RGB of above */ boolean colordither; /* true if color reduction is to dither image */ unsigned int colors; /* max # of colors to use for this image */ int delay; /* # of seconds delay before auto pic advance */ unsigned int dither; /* true if image is to be dithered */ boolean expand; /* true if image should be forced to * TrueColor depth */ float gamma; /* display gamma */ boolean gray; /* true if image is to be grayed */ boolean merge; /* true if we should merge onto previous */ boolean normalize; /* true if image is to be normalized */ int rotate; /* # degrees to rotate image */ boolean smooth; /* true if image is to be smoothed */ char *title; /* Override title on image */ unsigned int xzoom, yzoom; /* zoom percentages */ char *fg, *bg; /* foreground/background colors if mono image */ boolean done_to; /* TRUE if we have already looked for trailing * options */ char **to_argv; /* If non-null, text of trailing options, * parsed as for argv */ int xpmkeyc; /* Overriding color context key value for xpm * pixmaps */ int iscale; /* image-dependent scaling factor */ boolean iscale_auto; /* automatically iscale to fit on screen */ } ImageOptions; /* globals and global options */ typedef struct { DisplayInfo dinfo; /* device dependent display information */ char *argv0; /* name of this programs */ char *lastfunc; /* name of last function called (used in error * reps) */ int _Xdebug; /* dump on X error flag */ int _DumpCore; /* dump on signal flag */ boolean verbose; float display_gamma; char *dname; boolean do_fork; boolean fillscreen; boolean fit; boolean fullscreen; char *go_to; /* label to goto */ boolean identify; boolean install; boolean onroot; boolean private_cmap; boolean set_default; boolean use_pixmap; char *user_geometry; /* -geometry passed by user */ int visual_class; /* user-defined visual class */ unsigned int dest_window; /* window id to put image onto */ boolean delete; /* enable deleting current image with 'x' */ boolean focus; /* take keyboard focus when viewing in window */ } GlobalsRec; /* Global declarations */ extern GlobalsRec globals; #define CURRFUNC(aa) (globals.lastfunc = (aa)) /* Gamma correction stuff */ /* the default target display gamma. This can be overridden on the * command line or by settin an environment variable. */ #define DEFAULT_DISPLAY_GAMMA 2.2 /* the default IRGB image gamma. This can be overridden on the * command line. */ #define DEFAULT_IRGB_GAMMA 2.2 /* Compare gammas for equality */ #define GAMMA_NOT_EQUAL(g1,g2) ((g1) > ((g2) + 0.00001) || (g1) < ((g2) - 0.00001)) /* Cached/uudecoded/uncompressed file I/O structures. */ struct cache { byte *end; byte buf[BUFSIZ]; struct cache *next; boolean eof; }; #define UULEN 128 /* uudecode buffer length */ #define UUBODY 1 /* uudecode state - reading body of file */ #define UUSKIP 2 /* uudecode state - skipping garbage */ #define UUEOF 3 /* uudecode stat - found eof */ typedef struct { unsigned int type; /* ZIO file type */ boolean 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 */ byte *bufptr; /* ptr within current cache block */ byte *endptr; /* ptr to end of current cache block */ byte *auxb; /* non NULL if auxiliary buffer in use */ byte *oldbufptr; /* save bufptr here when aux buffer is in use */ byte *oldendptr; /* save endptr here when aux buffer is in use */ boolean eof; /* TRUE if we are at encountered EOF */ byte buf[BUFSIZ]; /* getc buffer when un-cached */ boolean uudecode; /* TRUE if being uudecoded */ byte uubuf[UULEN]; /* uu decode buffer */ byte *uunext, *uuend; int uustate; /* state of uu decoder */ } ZFILE; #define ZSTANDARD 0 /* standard file */ #define ZPIPE 1 /* file is a pipe (ie uncompress) */ #define ZSTDIN 2 /* file is stdin */ /* C library functions that may not be decalared elsewehere */ int atoi(const char *); long atol(const char *); double atof(const char *); char *getenv(const char *); /* function declarations */ /* * Note on image processing functions :- * * The assumption is always that an image processing function that returns * an image may return a new image or one of the input images, and that * input images are preserved. * * This means that within an image processing function the following * technique of managinging intermediate images is recomended: * * Image *func(isrc) * Image *isrc; * { * Image *src = isrc, *dst, *tmp; * . * . * tmp = other_func(src); * if (src != tmp && src != isrc) * freeImage(src); * src = tmp; * . * . * dst = process(src); * . * . * if (src != isrc) * freeImage(src); * return (dst); * * This may seem redundant in places, but allows changes to be made * without looking at the overal image structure usage. * */ /* imagetypes.c */ void supportedImageTypes(void); /* misc.c */ char *tail(char *path); void memoryExhausted(void); void internalError(int sig); void version(void); void usage(char *name); Image *processImage(DisplayInfo *dinfo, Image *iimage, ImageOptions *options); int errorHandler(Display *disp, XErrorEvent *error); extern short LEHexTable[]; /* Little Endian conversion value */ extern short BEHexTable[]; /* Big Endian conversion value */ #define HEXSTART_BAD -1 /* bitmap_faces useage */ #define HEXDELIM_BAD -2 #define HEXDELIM_IGNORE -3 #define HEXBAD -4 void initLEHexTable(void); void initBEHexTable(void); /* ascii hex number to integer (string, length) */ int hstoi(unsigned char *s, int n); char *xlistrstr(char *s1, char *s2); /* path.c */ char *expandPath(char *p); int findImage(char *name, char *fullname); void listImages(void); void loadPathsAndExts(void); void showPath(void); /* root.c */ void imageOnRoot(DisplayInfo *dinfo, Image *image, ImageOptions *options); /* window.c */ void cleanUpWindow(DisplayInfo *dinfo); char imageInWindow(DisplayInfo *dinfo, Image *image, ImageOptions *options, int argc, char **argv); /* options.c */ int visualClassFromName(char *name); char *nameOfVisualClass(int class); /* clip.c */ Image *clip(Image *iimage, int clipx, int clipy, unsigned int clipw, unsigned int cliph, ImageOptions *imgopp); /* bright.c */ void brighten(Image *image, unsigned int percent, unsigned int verbose); void gray(Image *image, int verbose); Image *normalize(Image *image, unsigned int verbose); void gammacorrect(Image *image, float target_gam, unsigned int verbose); extern int gammamap[256]; #define GAMMA16(color16) (gammamap[(color16)>>8]<<8) #define GAMMA8(color8) (gammamap[(color8)]) #define GAMMA16to8(color16) (gammamap[(color16)>>8]) void defaultgamma(Image *image); /* compress.c */ void compress_cmap(Image *image, unsigned int verbose); /* dither.c */ Image *dither(Image *cimage, unsigned int verbose); /* fill.c */ void fill(Image *image, unsigned int fx, unsigned int fy, unsigned int fw, unsigned int fh, Pixel pixval); /* halftone.c */ Image *halftone(Image *cimage, unsigned int verbose); /* imagetypes.c */ Image *loadImage(ImageOptions *image_ops, boolean verbose); void identifyImage(char *name); /* merge.c */ Image *merge(Image *idst, Image *isrc, int atx, int aty, ImageOptions *imgopp); /* new.c */ extern unsigned long DepthToColorsTable[]; unsigned long colorsToDepth(long unsigned int ncolors); char *dupString(char *s); Image *newBitImage(unsigned int width, unsigned int height); Image *newRGBImage(unsigned int width, unsigned int height, unsigned int depth); Image *newTrueImage(unsigned int width, unsigned int height); void freeImage(Image *image); void freeImageData(Image *image); void newRGBMapData(RGBMap *rgb, unsigned int size); void resizeRGBMapData(RGBMap *rgb, unsigned int size); void freeRGBMapData(RGBMap *rgb); byte *lcalloc(unsigned int size); byte *lmalloc(unsigned int size); byte *lrealloc(byte *old, unsigned int size); void lfree(byte *area); /* options.c */ void help(char *option); int doGeneralOption(OptionId opid, char **argv, ImageOptions *persist_ops, ImageOptions *image_ops); int doLocalOption(OptionId opid, char **argv, boolean setpersist, ImageOptions *persist_ops, ImageOptions *image_ops); void read_trail_opt(ImageOptions *image_ops, ZFILE *file, Image *image, boolean verbose); /* rlelib.c */ void make_gamma(double gamma, int *gammamap); /* reduce.c */ Image *reduce(Image *image, unsigned colors, int ditherf, float gamma, int verbose); Image *expandtotrue(Image *image); Image *expandbittoirgb(Image *image, int depth); Image *expandirgbdepth(Image *image, int depth); /* rotate.c */ Image *rotate(Image *iimage, int rotate, int verbose); /* send.c */ void sendXImage(XImageInfo *xii, int src_x, int src_y, int dst_x, int dst_y, unsigned int w, unsigned int h); XImageInfo *imageToXImage(Display *disp, int scrn, Visual *visual, unsigned int ddepth, Image *image, unsigned int private_cmap, unsigned int fit, ImageOptions *options); Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *xii); void freeXImage(Image *image, XImageInfo *xii); /* smooth.c */ Image *smooth(Image *isrc, int iterations, int verbose); /* value.c */ void flipBits(byte *p, unsigned int len); /* xpixmap.c */ int xpmoption(char *s); /* zio.c */ ZFILE *zopen(char *name); int zread(ZFILE *zf, byte *buf, int len); int zeof(ZFILE *zf); void zunread(ZFILE *zf, byte const *buf, int len); char *zgets(char *buf, unsigned int size, ZFILE *zf); boolean zrewind(ZFILE *zf); void zclose(ZFILE *zf); void znocache(ZFILE *zf); void zforcecache(boolean); void zreset(char *filename); void zclearerr(ZFILE *zf); int _zgetc(ZFILE *zf); boolean _zopen(ZFILE *zf); void _zreset(ZFILE *zf); void _zclear(ZFILE *zf); boolean _zreopen(ZFILE *zf); #define zgetc(zf) (((zf)->bufptr < (zf)->endptr) ? *(zf)->bufptr++ : _zgetc(zf)) /* zoom.c */ Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom, boolean verbose, boolean changetitle); /* ddxli.c */ boolean xliOpenDisplay(DisplayInfo *dinfo, char *name); void xliCloseDisplay(DisplayInfo *dinfo); void xliDefaultDispinfo(DisplayInfo *dinfo); int xliDefaultDepth(void); void tellAboutDisplay(DisplayInfo * dinfo); xli-2006-11-10/xli.man0000644000031400000060000006463210525262416013730 0ustar smarryconsole.\" @(#)x11:contrib/clients/xloadimage/xli.man 1.13 94/07/29 Labtam .\" .TH XLI 1 "27 Jul 1994" .SH NAME xli, xsetbg, xview \- load images into an X11 window or onto the root window .SH SYNOPSIS \fIxli\fR [global_options] {[image_options] image ...} .br \fIxli\fR [global_options] [image_options] stdin < image .SH DESCRIPTION \fIxli\fR displays images in an X11 window or loads them onto the root window. See the \fIIMAGE TYPES\fR section below for supported image types. .PP If the filename \fIstdin\fR is given, xli will read the image from standard input. .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 or \fI-fillscreen\fR options. 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. .PP When the keyboard focus is in the window you can: .na .nf Type 'q' or '^C' to exit xli. Type space, 'n' or 'f' to move to the next image in the list. Type 'b' or 'p' to move to the previous image in the list. Type . to reload the image. Type l to rotate the image anti-clockwise. Type r to rotate the image clockwise. Type 0 to set the images assumed gamma to your display gamma (usually darkens images) Type 1 to set the images assumed gamma to 1.0 (usually lightens images) Type 5-2 to lighten the image (5 in small steps, up to 2 in large steps) Type 6-9 to darken the image (6 in small steps, up to 9 in large steps) .ad .fi .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 \fIXsetbg\fR is equivalent to \fIxli -onroot -quiet\fR and \fIxview\fR is equivalent to \fIxli -view -verbose\fR. .SH RESOURCE CLASS \fIxli\fR uses the resource class name \fI_XSETROOT_Id\FR for window managers which need this resource set. .SH GLOBAL OPTIONS The following options affect the global operation of \fIxli\fR. They may be specified anywhere on the command line. .TP -default Set the root background to the default root weave. This is the same as \fIxsetroot\fR with no arguments. .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 -dumpcore Signals will not be trapped, and instead a coredump will occur. .TP -display \fIdisplay_name\fR X11 display name to send the image(s) to. .TP -dispgamma \fIDisplay_gamma\fR Specify the gamma correction value appropriate for the display device. This overides the value read from the environment variable \fBDISPLAY_GAMMA\fR, or the default value of 2.2, which is approximately correct for many displays. A value of between 1.6 and 2.8 is reasonable. If individual images are too bright or dark, use the -gamma option. .PP There is an image provided with xli called 'chkgamma.jpg' that lets you set the display gamma reasonably accurately. This file contains two grayscale ramps. The ramps are chosen to look linear to the human eye, one using continuous tones, and the other using dithering. When the display gamma is correct, then the two ramps should look symmetrical, and the point at which they look equally bright should be almost exactly half way from the top to the bottom. (To find this point it helps if you move away a little from the screen, and de-focus your eyes a bit.) .PP If the equal brightness point is above center increase the gamma, and decrease it if it is below the center. The value will usually be around 2.2 Once you've got it right, you can set the DISPLAY_GAMMA environment variable in your .profile .TP -fillscreen Use the whole screen for displaying an image. The image will be zoomed so that it just fits the size of the screen. If -onroot is also specified, it will be zoomed to completely fill the screen. .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 xli. This causes xli to disassociate itself from the shell. This option automatically turns on -quiet. .TP -fullscreen Use the whole screen for displaying an image. The image will be surrounded by a border if it is smaller than the screen. If -onroot is also specified, the image will be zoomed so that it just fits the size of the screen. .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 set the size and position of the viewing window. If the size is not specified in the geometry, (or is set to 0), then the size will be chosen to be small enough to able to fit the window in the screen (as usual). .TP -goto image_name When the end of the list of images is reached, go to image \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 images 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. If used in conjunction with -fullscreen, the image will be zoomed to just fit. If used with -fillscreen, the image will be zoomed to completely fill the screen. -border, -at, and -center also affect the results. .TP -path Displays the image path and image suffixes which will be used when looking for images. These are loaded from ~/.xlirc and optionally from a system wide file (normally /usr/lib/xlirc). .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 \fIxli\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 -verbose Causes \fIxli\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 \fIxli\fR. .TP -version Print the version number and patchlevel of this version of \fIxli\fR. .TP -view View image(s) in a window. This is the opposite of \fI-onroot\fR and the default for \fIxview\fR and \fIxli\fR. .TP -visual \fIvisual_name\fR Force the use of a specific visual type to display an image. Normally \fIxli\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 preceded 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 PERSISTENT IMAGE OPTIONS The following options may precede each image. They take effect from the next image, and continue until overridden or canceled with \fI-newoptions.\fR .TP -border \fIcolor\fR This sets the background portion of the window or clipped image which is not covered by any images to be \fIcolor\fR. .TP -brighten \fIpercentage\fR Specify a percentage multiplier for a color images colormap. A value of more than 100 will brighten an image, one of less than 100 will darken it. .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 -cdither .TP -colordither Dither the image with a Floyd-Steinberg dither if the number of colors is reduced. This will be slow, but will give a better looking result with a restricted color set. \fI-cdither\fR and \fI-colordither\fR are equivalent. .TP -delay \fIsecs\fR Sets xli to automatically advance to the following image, \fIsecs\fR seconds after the next image file is displayed. .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 -gamma \fIImage_gamma\fR Specify the gamma of the display the image was intended to be displayed on. Images seem to come in two flavors: 1) linear color images, produced by ray tracers, scanners etc. These sort of images generally look too dark when displayed directly to a CRT display. 2) Images that have been processed to look right on a typical CRT display without any sort of processing. These images have been 'gamma corrected'. By default, xli assumes that 8 bit images have been gamma corrected and need no other processing. 24 bit images are assumed to be linear. If a linear image is displayed as if it is gamma corrected it will look too dark, and a gamma value of 1.0 should be specified, so that xli can correct the image for the CRT display device. If a gamma corrected image is displayed as if it were a linear image, then it will look too light, and a gamma value of (approximately) 2.2 should be specified for that image. Some formats (RLE) allow the image gamma to be embedded as a comment in the file itself, and the -gamma option allows overriding of the file comment. In general, values smaller than 2.2 will lighten the image, and values greater than 2.2 will darken the image. In general this will work better than the -brighten option. .TP -gray Convert an image to grayscale. This is very useful when displaying colorful images on servers with limited color capability. The optional spelling \fI-grey\fR may also be used. .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 -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 -title \fIwindow_title\fR Set the titlebar of the window used to display the image. This will overide any title that is read from the image file. The title will also be used for the icon name. .TP -xpm \fIcolor_context_key\fR Select the prefered xpm colour map. XPM files may contain more than one color mapping, each mapping being appropriate for a particular visual. Normally xli will select an apropriate color mapping from that supported by the XPM file by checking on the default X visual class and depth. This option allows the user to overide this choice. Legal values of \fIcolor_context_key\fR are: m, g4, g and c. m = mono, g4 = 4 level gray, g = gray, c = color ). .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. .TP -newoptions Reset options that propagate. The \fI-bright, -colors, -colordither, -delay, -dither, -gamma, -gray, -normalize, -smooth, -xzoom, -yzoom\fR, and \fI-zoom\fR options normally propagate to all following images. .SH LOCAL IMAGE OPTIONS The following options may precede each image. These options are local to the image they precede. .TP -at \fIX\fR,\fIY\fR Indicates coordinates to load the image at \fIX\fR,\fIY\fR 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 -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. Note that \fIX\fR and \fIY\fR may be negative, and that \fIW\fR and \fIH\fR may be larger than the image. This causes a border to be placed around the image. The border color may be set with the \fI-border\fR option. .TP -expand Forces the image (after all other optional processing) to be expanded into a True Color (24 bit) image. This is useful on systems which support 24 bit color, but where xli might choose to load a bitmap or 8 bit image into one of the other smaller depth visuals supported on your system. .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 -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 -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 preceded by \fI-merge\fR. If used in conjunction with \fI-at\fR and \fI-clip\fR, very complex images can be built up. Note that the final image will be the size of the first image, and that subsequent merged images overlay previous images. The final image size can be altered by using the \fI-clip\fR option on the base image to make it bigger or smaller. 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 -normalize Normalize a color image. .TP -rotate \fIdegrees\fR Rotate the image by \fIdegrees\fR clockwise. The number must be a multiple of 90. .SH EXAMPLES To load the rasterfile "my.image" onto the background and replicate it to fill the entire background: .sp .ti +5 xli -onroot 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 xli -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 xli -center -clip 10,10,100,0 my.image .PP To double the size of an image: .sp .ti +5 xli -zoom 200 my.image .PP To halve the size of an image: .sp .ti +5 xli -zoom 50 my.image .PP To brighten a dark image: .sp .ti +5 xli -brighten 150 my.image .PP To darken a bright image: .sp .ti +5 xli -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 noticeable 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 xli 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 XLITO \fIxlito\fR (XLoadImageTrailingOptions) is a separate utility that provides a file format independent way of marking image files with the appropriate options to display correctly. It does this by appending to file a string specified by the user, marked with some magic numbers so that this string can be extracted by a program that knows where to look. Since almost all image files have some sort of image size specifier, the programs that load or manipulate these files do not look beyond the point at which they have read the image, so trailing information can safely be appended to the file. If appending this information causes trouble with other utilities, it can simply be deleted. .PP \fIxli\fR will recognize these trailing options at the end of the image files, and will treat the embedded string as if it were a sequence of command line \fIIMAGE OPTIONS\fR. Any \fIGLOBAL OPTIONS\fR will be ignored, and the \fIIMAGE OPTIONS\fR are never propagated to other images. .PP Trailing options can be examined with: .sp .ti +5 xlito image_file ... .PP Changed or added with: .sp .ti +5 xlito -c "string of options" image_file .PP And deleted with: .sp .ti +5 xlito -d image_file ... .PP For example, if you have a gif file fred.gif which is too dark and is the wrong aspect ratio, then it may need to be viewed with: .sp .ti +5 xli -yzoom 130 -gamma 1.0 fred.gif .PP to get it to look OK. These options can then be appended to the file by: .sp .ti +5 xlito -c "-yzoom 130 -gamma 1.0" fred.gif .PP and from then on xli will get the appropriate options from the image file itself. See the \fIxlito\fR manual entry for more details about this utility. .SH PATHS AND EXTENSIONS The file ~/.xlirc (and optionally a system-wide file) defines the path and default extensions that \fIxli\fR will use when looking for images. This file can have two statements: "path=" and "extension=" (the equals signs must follow the word with no spaces between). Everything following the "path=" keyword will be prepended to the supplied image name if the supplied name does not specify an existing file. The paths will be searched in the order they are specified. Everything following the "extension=" keyword will be appended to the supplied image name if the supplied name does not specify an existing file. As with paths, these extensions will be searched in the order they are given. Comments are any portion of a line following a hash-mark (#). .PP The following is a sample ~/.xlirc file: .PP .nf # paths to look for images in path= /usr/local/images /home/usr1/guest/madd/images /usr/include/X11/bitmaps # default extensions for images; .Z is automatic; scanned in order extension= .csun .msun .sun .face .xbm .bm .fi .PP Versions of \fIxli\fR prior to version 01, patchlevel 03 would load the system-wide file (if any), followed by the user's file. This behavior made it difficult for the user to configure her environment if she didn't want the default. Newer versions will ignore the system-wide file if a personal configuration file exists. .SH IMAGE TYPES .PP \fIxli\fR currently supports the following image types: .sp .nf CMU Window Manager raster files Faces Project images Fuzzy Bitmap (.fbm) images GEM bit images GIF images (Including GIF89a compatibility) G3 FAX images JFIF style jpeg images McIDAS areafiles MacPaint images Windows, OS/2 RLE Image Monochrome PC Paintbrush (.pcx) images Photograph on CD Image Portable Bitmap (.pbm, .pgm, .ppm) images Sun monochrome rasterfiles Sun color RGB rasterfiles Targa (.tga) files Utah Raster Toolkit (.rle) files X pixmap (.xpm) files (Version 1, 2C and 3) X10 bitmap files X11 bitmap files X Window Dump (except TrueColor and DirectColor) .fi .PP Normal, compact, and raw PBM images are supported. Both standard and run-length encoded Sun rasterfiles are supported. Any image whose name ends in .Z is assumed to be a compressed image and will be filtered through "uncompress". If HAVE_GUNZIP is defined in the Makefile.std make file, then any image whose name ends in .gz or .Z will be filtered through gunzip. .PP Any file that looks like a uuencoded file will be decoded automatically. .SH AUTHORS The original Author is: .nf Jim Frost Saber Software jimf@saber.com .fi .PP Version 1.16 of xli is derived from xloadimage 3.01 has been brought to you by: .nf Graeme Gill graeme@labtam.oz.au .fi .PP Version 1.17 of xli is derived from xli 1.16 by .nf smar@reptiles.org .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 xli - the image loader and viewer xsetbg - pseudonym which quietly sets the background xview - pseudonym which views in a window xlito - the trailing options utility /usr/lib/X11/Xli - default system-wide configuration file ~/.xlirc - user's personal configuration file .in -5 .fi .SH COPYRIGHT Copyright (c) 1989, 1990, 1991, 1992, 1993 Jim Frost, Graeme Gill and others. .PP \fIXli\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. \fIXli\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. The solution to this is to use \fIxlito\fR to append the appropriate options to the image file. See \fIHINTS FOR GOOD IMAGE DISPLAYS\fR and \fIXLITO\fR for more information. .PP The GIF format allows more than one image to be stored in a single GIF file, but \fIxli\fR will only display the first. .PP One of the pseudonyms for \fIxli\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, \fIxli\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. .PP The order in which operations are performed on an image is independent of the order in which they were specified on the command line. Wherever possible I tried to order operations in such a way as to look the best possible (zooming before dithering, for instance) or to increase speed (zooming downward before compressing, for instance). .PP Display Gamma should setable in the ~/.xlirc file. .PP Embedded trailing options overide the command line \fIImage Options.\fR Command line options should really overide trailing options. xli-2006-11-10/xliguide.man0000644000031400000060000001657106461630120014740 0ustar smarryconsole.\" @(#)x11:contrib/clients/xloadimage/xliguide.man 1.2 93/07/23 Labtam .\" .de Sc \" start of code. no re-arrange, no fill, constant width etc. \f(CW .na .nf .. .de Ec \" end of code. no re-arrange, no fill, constant width etc. \fR .ad .fi .. .TH "XLI LOADER GUIDE" 5 .SH "Guide to writing image loaders for xli" This is a introduction on how an image load routine should be written, and what resources are available for use by the writer. .SH "Include files" The include file xli.h is generally sufficient to make all the xli resources available: ie: .sp .ti +5 #include "xli.h" .PP .SH "Identify function" The identification function is used to implement the \fI-identify\fR option of xli. It is generally of the form : .Sc int xyyzIdent(fullname, name) char \(**fullname, \(**name; { } .Ec .PP where this is an xyyz type image loader file. .PP fullname is the name including path, while name is the short name of the file that is used as a title, or to refer to the file in messages. .PP Return 0 if the image is NOT identified. .PP Return 1 if the image IS identified. .PP If the file is identified, use a message something like: .Sc printf("%s is a %dx%d xyyz image with %d colors\\n", name, width, height, ncolors); .Ec .PP Try and be quick about identifying the image - don't read the whole image just to identify it ! .PP Use printf even if something is wrong with the file. Use perror for a system error - ie. unable to open file. .SH "Loading the image" The load function is used to identify and load the file if it is recognized. It is of the form: .Sc Image xyyzLoad(fullname, image_ops, verbose) ImageOptions \(**image_ops; char \(**fullname; boolean verbose; { } .Ec .PP Identify the image as quickly as possible. .PP Return NULL if the image is not identified. .PP Otherwise Return a pointer to an image structure with the image in it. .PP If the image is properly identified, but there is something wrong with it before anything useful is read in, report the error - ie. .Sc fprintf(stderr,"xyyzLoad: %s - corrupted color map\\n",name); .Ec .PP clean up (ie. release the image structure and any allocated memory) and return NULL. .PP If the image is properly identified, and there is something wrong with it, but something useful has been read in (ie. color maps etc. have been loaded, and part of the image is loaded), report the error using fprintf (as above) and return what there is of the image. .PP Remember to release and temporary memory allocated on returning, whether the image is loaded ok, or if something goes wrong. .PP Remember to read any trailing options before returning a successfully loaded image, and before closing the file. Trailing options are read by calling the function: .Sc read_trail_opt(image_ops, zf, image, verbose) ImageOptions \(**image_ops; ZFILE \(**zf; Image \(**image; boolean verbose; .Ec .PP Remember to close the file before returning. .PP Remember to add any additional info to the image structure - ie. name, gamma if known etc. .PP NEVER EVER exit(). There may be other image loaders and other images to load. .PP Use printf to give verbose output on image details. .PP Use fprintf(stderr," ... "); to give error warning if the file is corrupted. .PP use perror for a system error - ie. unable to open file. .SH "Useful info in image_ops:" .Sc char \(**name; /\(** Short name of image \(**/ .Ec .SH "Useful things to set in the image structure:" .Sc char \(**title; /\(** name of image \(**/ RGBMap rgb; / RGB map of image if IRGB type \(**/ byte \(**data; /\(** data, rounded to full byte for each row \(**/ float gamma; /\(** gamma of display the image is adjusted \(**/ /\(** for, if know. \(**/ .Ec .SH "Creating and destroying Image structures:" The image structure is created by a call to one of three routines: .Sc /\(** For a monochrome bitmap \(**/ Image \(**newBitImage(width, height) unsigned int width, height; /\(** For a color image with a color map \(**/ Image \(**newRGBImage(width, height, depth) unsigned int width, height, depth; /\(** For a true color image \(**/ Image \(**newTrueImage(width, height) unsigned int width, height; .Ec .PP And the image can be freed with: .Sc void freeImageData(image) Image \(**image; .Ec .PP Examine another image loader (ie. gif.c) to see how to set up a color map. .SH "File input resources:" A set of file input functions are available that automatically handle compressed files, and also by default buffer the file in memory to speed up the detection of the image type. The following functions are available: .Sc /\(** Open a file by name and return a pointer to a file descriptor. \(**/ ZFILE \(**zopen(name) char \(**name; /\(** Read some data into a buffer \(**/ int zread(zf, buf, len) ZFILE \(**zf; byte \(**buf; int len; /\(** Macro that returns a character from the file. \(**/ zgetc(zf) ZFILE \(**zf; /\(** Function that reads a string into a buffer \(**/ char \(**zgets(buf, size, zf) char \(**buf; unsigned int size; ZFILE \(**zf; /\(** Return the files EOF status \(**/ int zeof(zf) ZFILE \(**zf; /\(** Clear any errors (ie. EOF) \(**/ void zclearerr(zf) ZFILE \(**zf; /\(** Turn off caching when an image has been identified and there is no need to re-open it. The cached part of the file is still kept, but any reads past this point are not cached. \(**/ void znocache(zf) ZFILE \(**zf; /\(** Rewind the cached file. This won't work if the file is stdin and we have read past the cached part of the file. Return TRUE on success. \(**/ boolean zrewind(zf) ZFILE \(**zf; /\(** Return a block of data back to the input stream. Useful for a load routine that does its own buffering and wants to return what is left after it has read an image. (This is needed to allow trailing options to be recognized.) Can also be used instead of ungetc(). \(**/ void zunread(zf, buf, len) ZFILE \(**zf; byte \(**buf; int len; /\(** Close a file. The file is not actually closed until zreset is called, in case another loader wants to re-open it. \(**/ void zclose(zf) ZFILE \(**zf; /\(** Really close a file. Not used by imageLoad functions. \(**/ void zreset(filename) char \(**filename; .Ec .PP Some macros are provided to facilitate reading and writing elements larger than a character from/to a data buffer according to the desired endianness: .PP Big endian: .Sc #define memToVal(PTR,LEN) #define valToMem(VAL,PTR,LEN) .Ec .PP Little Endian .Sc #define memToValLSB(PTR,LEN) #define valToMemLSB(VAL,PTR,LEN) .Ec .SH "Memory allocation:" The built in memory allocation routines are guaranteed not to fail. .Sc /\(** Duplicate a string. Good for making up the image title etc. \(**/ char \(**dupString(s) char \(**s; byte \(**lmalloc(size) unsigned int size; byte \(**lcalloc(size) unsigned int size; void lfree(area) byte \(**area; .Ec .PP Be careful not to call lfree with NULL. It may cause a fault. .SH "Other facilities:" Memory manipulation .Sc /\(** Copy a block of memory \(**/ bcopy(S,D,N) /\(** Zero a block of memory \(**/ bzero(P,N) /\(** Fill a block of memory with a value \(**/ bfill(P,N,C) .Ec .SH "If all else fails:" Read the source. xli.h and image.h are a good place to start. Look at one of the existing loaders ie. pcx.c Grep for anything else! xli-2006-11-10/xlito.c0000644000031400000060000001735310525262416013740 0ustar smarryconsole#include #include #include #include #include #include "ddxli.h" #include "xlito.h" #ifndef VMS #include #endif #include #define VERSION "1" #define PATCHLEVEL "02" #define PADSIZE 20 /* allow a little over-read on image load */ #if (defined(SYSV) || defined (VMS)) && !defined(SVR4) && !defined(__hpux) && !defined(_CRAY) #define NEED_FTRUNCATE /* define this if your system doesn't have ftruncate() */ #endif #define SHOW 0 #define XLI 1 #define CHANGE 2 #define DELETE 3 static char *find_text(int file, char *key, char **junk, int *jlen, int show, int delete); static void usage(char *pname); char *pname, *fname; #undef DEBUG #ifdef DEBUG # define debug(xx) fprintf(stderr,xx) #else # define debug(xx) #endif int main(int argc, char **argv) { int func = SHOW; char *text = 0; int a = 1; char *key = KEY; int klen; char *junk; int jlen; int file; int nameopt = 0; pname = argv[0]; klen = strlen(key); if (argc < 2) usage(pname); if (argv[a][0] == '-') { if (argv[a][1] == 'c') { if (argv[a][2] != '\000') text = &argv[a][2]; else if (argc >= 3) text = argv[++a]; else usage(pname); func = CHANGE; } else if (argv[a][1] == 'd') { if (argv[a][2] != '\000') usage(pname); func = DELETE; } else if (argv[a][1] == 'x') { if (argv[a][2] != '\000') usage(pname); func = XLI; } else usage(pname); a++; } for(;a < argc; a++) /* Do all the files */ { fname = argv[a]; if (func == XLI) { if (nameopt) { nameopt = 0; file = open(fname,O_RDONLY); if (file != -1) { if ((text = find_text(file,key,&junk,&jlen, 1, 0)) != NULL) printf(" %s -name %s",text,fname); else printf(" -name %s",fname); close(file); continue; } printf(" -name %s",fname); continue; } if (argv[a][0] != '-') { file = open(fname,O_RDONLY); if (file != -1) { if ((text = find_text(file,key,&junk,&jlen, 1, 0)) != NULL) printf(" %s %s",text,fname); else printf(" %s",fname); close(file); continue; } } else { if(strcmp("-name",fname)==0) { nameopt = 1; continue; } } printf(" %s",fname); continue; } else if (func == SHOW) { file = open(fname,O_RDONLY); if (file != -1) { if ((text = find_text(file,key,&junk,&jlen, 1, 0)) != NULL) { printf("%s: '%s'\n",fname, text); } else { printf("%s: none\n",fname); } if(close(file) != 0) { fprintf(stderr,"%s: Error closing %s, ",pname,fname); perror(""); exit(-1); } continue; } fprintf(stderr,"Unable to open file %s",fname); continue; } else if (func == DELETE) { file = open(fname,O_RDWR); if (file == -1) { fprintf(stderr,"%s: Unable to open file '%s' for deleting options, ",pname,fname); perror(""); exit(-1); } if ((text = find_text(file,key,&junk,&jlen, 0, 1)) != NULL) { long fsize; fsize = lseek(file, 0L,1); if(ftruncate(file, fsize) != 0) { fprintf(stderr,"%s: Error truncating %s, ",pname,fname); perror(""); exit(-1); } } if(close(file) != 0) { fprintf(stderr,"%s: Error closing %s, ",pname,fname); perror(""); exit(-1); } continue; } else if (func == CHANGE) { char padding[PADSIZE]; int i; char tt[6]; int tlen; long fsize; tlen = strlen(text); if (tlen > (TOBUFSZ - klen - 4)) { fprintf(stderr,"%s: text is too long\n",pname); exit(-1); } file = open(fname,O_RDWR); if (file == -1) { fprintf(stderr,"%s: Unable to open file '%s' for changing options, ",pname,fname); perror(""); exit(-1); } if (!find_text(file,key,&junk,&jlen,0, 0)) { /* No padding there already, so add some */ for(i=0; i < PADSIZE; i++) padding[i] = '0' + (i % 10); if (write(file, padding,PADSIZE) != PADSIZE) { fprintf(stderr,"%s: Error writing to file %s, ",pname,fname); perror(""); exit(-1); } } sprintf(tt+1,"%04d",tlen); tt[0] = tt[ 5] = '"'; if (write(file, key,klen) != klen || write(file, tt + 1,5) != 5 || write(file, text,tlen) != tlen || write(file, tt,5) != 5 || write(file, key,klen) != klen || write(file, junk,jlen) != jlen) { fprintf(stderr,"%s: Error writing to file %s, ",pname,fname); perror(""); exit(-1); } fsize = lseek(file, 0L,1); if(ftruncate(file, fsize) != 0) { fprintf(stderr,"%s: Error truncating %s, ",pname,fname); perror(""); exit(-1); } if(close(file) != 0) { fprintf(stderr,"%s: Error closing %s, ",pname,fname); perror(""); exit(-1); } } } return 0; } char buf1[TOBUFSZ]; char buf[TOBUFSZ]; /* show == Non zero if fail gracefully delete == Non zero to position at padding rather than at options */ static char *find_text(int file, char *key, char **junk, int *jlen, int show, int delete) { int klen; int count; int tlen; long foff, fsize, sk; char *pp, sc; klen = strlen(key); fsize = foff = lseek(file, 0L,2); /* Look for key backwards in file up to TOBUFSZ chars from end */ sk = TOBUFSZ < fsize ? TOBUFSZ : fsize; if (lseek(file, -sk, 2) == -1L) goto seekerr; if ((count = read(file, buf1, sk)) != sk) { debug("didn't read key\n"); goto fail; } sc = key[klen-1]; for(pp = &buf1[sk-1];;pp--) { for(;*pp != sc && pp >= buf1; pp--); if(pp < (buf1 + klen -1)) { debug("couldn't find key\n"); goto fail; } if (strncmp(key,pp - klen + 1,klen) ==0) break; } /* found the last key string, so read the text length */ *junk = pp + 1; *jlen = count + (buf1 - pp) - 1; sk = count + (buf1 - pp) - 1 + klen + 5; if ((foff = lseek(file, -(sk < fsize ? sk : fsize),2)) == -1L) goto seekerr; count = read(file, buf,5); if (count != 5) { debug("didn't read key\n"); goto fail; } foff += count; if (buf[0] != '"' || !isdigit(buf[1]) || !isdigit(buf[2]) || !isdigit(buf[3]) || !isdigit(buf[4])) { debug("length wasn't recognised\n"); goto fail; } buf[5] = '\000'; tlen = atoi(&buf[1]); if (tlen > (TOBUFSZ - klen - 5)) { debug("text was too long\n"); goto fail; } sk = tlen + klen + 10; if ((foff = lseek(file, -(sk < foff ? sk : foff),1)) == -1L) goto seekerr; count = read(file, buf,(tlen + klen + 5)); if (count != (tlen + klen + 5)) { debug("didn't read key + text\n"); goto fail; } foff += count; if (strncmp(key,buf,klen) !=0) { debug("first key wasn't recognised\n"); goto fail; } if (!isdigit(buf[klen]) || !isdigit(buf[klen+1]) || !isdigit(buf[klen+2]) || !isdigit(buf[klen+3]) || buf[klen+4] != '"') { debug("first length wasn't recognised\n"); goto fail; } buf[klen+4] = '\000'; if (tlen != atoi(&buf[klen])) { debug("first length didn't match\n"); goto fail; } sk = tlen + klen + 5; if (delete) sk += PADSIZE; if ((foff = lseek(file, -(sk < foff ? sk : foff),1)) == -1L) goto seekerr; buf[klen + 5 + tlen] = '\000'; return &buf[klen + 5]; fail: *jlen = 0; if(lseek(file,0L,2) != -1L) return NULL; seekerr: *jlen = 0; if (show) return NULL; fprintf(stderr,"%s: Error seeking on file %s, ",pname,fname); perror(""); exit(-1); } static void usage(char *name) { fprintf(stderr,"%s: Version %s.%s usage\n",name,VERSION,PATCHLEVEL); fprintf(stderr,"%s [-x]|[-c text]|[-d] files\n",name); fprintf(stderr," -x xli command line processing\n"); fprintf(stderr," -c text replace options with \"text\"\n"); fprintf(stderr," -d delete options\n"); exit(-1); } #ifdef NEED_FTRUNCATE #include #include ftruncate(fd, size) int fd; off_t size; { struct flock ff; ff.l_whence = SEEK_SET; ff.l_start = size; ff.l_len = 0; /* till end of file */ return(fcntl(fd, F_FREESP, (char *)&ff)); } #endif xli-2006-11-10/xlito.h0000644000031400000060000000020207004736453013733 0ustar smarryconsole/* xli trailing option header file */ #define TOBUFSZ 1024 /* Magic number */ #define KEY "XXX xloadimage trailing options XXX" xli-2006-11-10/xlito.man0000644000031400000060000001137610525262416014270 0ustar smarryconsole.\" @(#)x11:contrib/clients/xloadimage/xlito.man 1.3 93/07/29 Labtam .\" .TH XLITO 1 "7 Jul 1993" .SH NAME xlito (XLoadImageTrailingOptions) \- Append/Delete/Show a Trailing Option string in a file. .SH SYNOPSIS \fIxlito\fR [option] [string] files ... .SH DESCRIPTION \fIxlito\fR (XLoadImageTrailingOptions) is a utility that provides a file format independent way of marking image files with the appropriate options to display correctly. It does this by appending to a file, a string specified by the user. The string is marked with some magic numbers so that it can be extracted by a program that knows what to look for. Since almost all image files have some sort of image dimension information in the file, the programs that load or manipulate these files generally do not look beyond the point at which they have read the complete image, so trailing information is safely be hidden. If appending this information causes trouble with other utilities, it can simply be deleted. .PP Appropriate version of \fIxloadimage\fR (ie. \fIxli 1.00\fR) will recognise these trailing options at the end of the image files, and will treat the embedded string as if it were a sequence of command line \fIImage Options\fR. Any \fIGlobal Options\fR will be ignored, and unlike command line \fIimage Options,\fR \fITrailing Options\fR are never propagated to other images. .PP Old versions of \fIxloadimage\fR (3.01 or less) can be made forward compatible by using the \fI-x\fR option to pull the trailing options out of the image files, and put them on the command line where \fIxloadimage\fR can see them. .SH OPTIONS The default behavior is to display the trailing option strings (if any) of the files on the argument line. The following options change the behavior of \fIxlito:\fR .TP 8 -c \fIoption_string file_name ...\fR This adds or changes the embedded string to \fIoption_string\fR. The string will have to be quoted if it is composed of more than one word. .TP -d \fIfile_name ...\fR Delete any embedded trailing option strings in the given files. .TP -x \fIfile_name ...\fR Process the files and create a command line string suitable for use by \fIxloadimage.\fR Arguments starting with \fI-\fR are echoed, arguments not starting with \fI-\fR are treated as files and any trailing options strings are echoed followed by the file name. The \fIxloadimage\fR option \fI-name\fR is treated correctly. .SH EXAMPLES If fred.gif has the wrong aspect ratio, then it might need viewing with the \fIxloadimage\fR options: .sp .ti +5 xloadimage -yzoom 130 fred.gif .PP This option can then be appended to the file by: .sp .ti +5 xlito -c "-yzoom 130" fred.gif .PP and from then on some new versions of xloadimage will get the appropriate options from the image file itself. Old versions of \fIxloadimage\fR can be made to work by using: .sp .ti +5 xloadimage \(gaxlito -x fred.gif\(ga .PP This can be made transparent by using a script containing something like: .sp .ti +5 xloadimage \(gaxlito -x $\(**\(ga .PP The script could be called \fIxli\fR for instance. .PP The options can be deleted with: .sp .ti +5 xlito -d fred.gif .SH AUTHOR .nf Graeme Gill Labtam Australia graeme@labtam.oz.au .fi .SH MAINTAINER .nf smar@reptiles.org .fi .SH COMPATIBILITY WITH IMAGE FILES Some image files are actually ascii files that are used in other contexts. X Bitmap files are an example. They are formatted as 'C' style #defines and an initialised array of characters, so that they can be included in 'C' source code. Adding trailing options would therefore render the file unusable with a compiler, since it will get a syntax error on the railing option string and the magic numbers. The solution to this is that xlito will ignore a certain amount (a few hundred bytes) after the trailing options, and uses a padding of 20 bytes before the trailing options. These two areas will be maintained when changing an existing trailing option. In the case of an X bitmap then, the solution is to edit the file and place the embedded string in some 'C' comments: .PP eg: say the file starts as: .br #define tt_width 4 .br #define tt_height 4 .br static char tt_bits[] = { .br 0x08, 0x02, 0x04, 0x01}; .PP and you add a trailing options: .br #define tt_width 4 .br #define tt_height 4 .br static char tt_bits[] = { .br 0x08, 0x02, 0x04, 0x01}; .br 01234567890123456789XXX xloadimage trailing options XXX0007"-smooth"0007XXX .br xloadimage trailing options XXX .PP Then the trailing options can be commented out: .br #define tt_width 4 .br #define tt_height 4 .br static char tt_bits[] = { .br 0x08, 0x02, 0x04, 0x01}; .br /\(**234567890123456789XXX xloadimage trailing options XXX0007"-smooth"0007XXX .br xloadimage trailing options XXX \(**/ .SH BUGS xlito doesn't cope with compressed files. A files will need uncompressing, the options added, and then compressing again. xli-2006-11-10/xpixmap.c0000644000031400000060000003456710525262416014275 0ustar smarryconsole/* xpixmap.c: * * XPixMap format file read and identify routines. these can handle any * "format 1" XPixmap file with up to a memory limited number of chars * per pixel. It also handles XPM2 C and XPM3 format files. * It is 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. * * Modified 16/10/92 by GWG to add version 2C and 3 support. */ #include "copyright.h" #include "xli.h" #include "imagetypes.h" #include static void freeCtable(char **ctable, int ncolors) /* color table */ { int i; if (ctable == NULL) return; for (i = 0; i < ncolors; i++) if (ctable[i] != NULL) lfree(ctable[i]); lfree((byte *) ctable); } /* * put the next word from the string s into b, * and return a pointer beyond the word returned. * Return NULL if no word is found. */ static char *nword(char *s, char *b) { while (*s != '\0' && (*s == ' ' || *s == '\t')) s++; if (*s == '\0') return NULL; while (*s != '\0' && *s != ' ' && *s != '\t') *b++ = *s++; *b = '\0'; return s; } #define XPM_FORMAT1 1 #define XPM_FORMAT2C 2 #define XPM_FORMAT3 3 /* xpm colour map key */ #define XPMKEY_NONE 0 #define XPMKEY_S 1 /* Symbolic (not supported) */ #define XPMKEY_M 2 /* Mono */ #define XPMKEY_G4 3 /* 4-level greyscale */ #define XPMKEY_G 4 /* >4 level greyscale */ #define XPMKEY_C 5 /* color */ char *xpmkeys[6] = {"", "s", "m", "g4", "g", "c"}; /* * encapsulate option processing */ int xpmoption(char *s) { int i; for (i = XPMKEY_M; i <= XPMKEY_C; i++) { if (!strcmp(s, xpmkeys[i])) return i; } printf("Argument to -xpm must be a xpm color context m, g4, g or c. (ignored)\n"); return XPMKEY_NONE; } /* * Return TRUE if we think this is an XPM file */ static boolean isXpixmap(ZFILE * zf, unsigned int *w, unsigned int *h, unsigned int *cpp, unsigned int *ncolors, int *format, char **imagetitle) /* image dimensions */ /* chars per pixel */ /* number of colors */ /* XPM format type */ { char buf[BUFSIZ]; char what[BUFSIZ]; char *p; unsigned int value; int maxlines = 8; /* 8 lines to find #define etc. */ unsigned int b; int c; *imagetitle = NULL; /* read #defines until we have all that are necessary or until we * get an error */ *format = *w = *h = *ncolors = 0; for (; maxlines-- > 0;) { if (!zgets((byte *) buf, BUFSIZ - 1, zf)) { if (*imagetitle) lfree(*imagetitle); return (FALSE); } if (!strncmp(buf, "#define", 7)) { if (sscanf(buf, "#define %s %d", what, &value) != 2) { if (*imagetitle) lfree(*imagetitle); return (FALSE); } 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 + 1, "colors[]") || !strcmp(p + 1, "mono[]"))) { zunread(zf, buf, strlen(buf)); /* stuff it back so we can read it again */ break; } else if ((sscanf(buf, "/* %s C */", what) == 1) && !strcmp(what, "XPM2")) { *format = XPM_FORMAT2C; break; } else if ((sscanf(buf, "/* %s */", what) == 1) && !strcmp(what, "XPM")) { *format = XPM_FORMAT3; break; } } if (maxlines <= 0) { if (*imagetitle) lfree(*imagetitle); return FALSE; } if (*format == XPM_FORMAT2C || *format == XPM_FORMAT3) { for (; maxlines-- > 0;) { if (!zgets((byte *) buf, BUFSIZ - 1, zf)) { if (*imagetitle) lfree(*imagetitle); return FALSE; } if (sscanf(buf, "static char * %s", what) == 1) { if (strlen(what) >= (unsigned) 2 && what[strlen(what) - 2] == '[' && what[strlen(what) - 1] == ']') what[strlen(what) - 2] = '\000'; /* remove "[]" */ if (strlen(what) > (unsigned) 0) /* if not titleless */ *imagetitle = dupString(what); break; } } if (maxlines <= 0) { if (*imagetitle) lfree(*imagetitle); return FALSE; } /* get to the first string in the array */ while (((c = zgetc(zf)) != EOF) && (c != '"')); if (c == EOF) { if (*imagetitle) lfree(*imagetitle); return FALSE; } /* put the string in the buffer */ for (b = 0; ((c = zgetc(zf)) != EOF) && (c != '"') && b < (BUFSIZ - 1); b++) { if (c == '\\') c = zgetc(zf); if (c == EOF) { if (*imagetitle) lfree(*imagetitle); return FALSE; } buf[b] = (char) c; } buf[b] = '\0'; if (sscanf(buf, "%d %d %d %d", w, h, ncolors, cpp) != 4) { if (*imagetitle) lfree(*imagetitle); return FALSE; } } else if ((p = rindex(what, '_'))) { /* get the name in the image if there is one */ *p = '\0'; *imagetitle = dupString(what); } if (!*format || !*w || !*h || !*ncolors || !*cpp) { if (*imagetitle) lfree(*imagetitle); return FALSE; } return TRUE; } Image *xpixmapLoad(char *fullname, ImageOptions * image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; char buf[BUFSIZ]; char what[BUFSIZ]; char *p; char *imagetitle; unsigned int value; unsigned int w, h; /* image dimensions */ unsigned int cpp; /* chars per pixel */ unsigned int ncolors; /* number of colors */ unsigned int depth; /* depth of image */ int format; /* XPM format type */ char **ctable = NULL; /* temp color table */ int *clookup; /* working color table */ int cmin, cmax; /* min/max color string index numbers */ Image *image; XColor xcolor; unsigned int a, b, x, y; int c; byte *dptr; int colkey = image_ops->xpmkeyc; int gotkey = XPMKEY_NONE; int donecmap = 0; if (!(zf = zopen(fullname))) { perror("xpixmapLoad"); return (NULL); } { unsigned int tw, th; unsigned int tcpp; unsigned int tncolors; if (!isXpixmap(zf, &tw, &th, &tcpp, &tncolors, &format, &imagetitle)) { zclose(zf); return (NULL); } w = tw; h = th; cpp = tcpp; ncolors = tncolors; } for (depth = 1, value = 2; value < ncolors; value <<= 1, depth++); image = newRGBImage(w, h, depth); image->rgb.used = ncolors; if (imagetitle != NULL) image->title = imagetitle; else image->title = dupString(name); if (verbose) printf("%s is a %dx%d X Pixmap image (Version %d) with %d colors titled '%s'\n", name, w, h, format, ncolors, image->title); /* * decide which version of the xpm file to read in */ if (colkey == XPMKEY_NONE) { /* if the user hasn't specified it */ switch (xliDefaultVisual()) { case StaticGray: case GrayScale: switch (xliDefaultDepth()) { case 1: colkey = XPMKEY_M; break; case 2: colkey = XPMKEY_G4; break; default: colkey = XPMKEY_G; break; } break; default: colkey = XPMKEY_C; } } for (donecmap = 0; !donecmap;) { /* until we have read a colormap */ if (format == XPM_FORMAT1) { for (;;) { /* keep reading lines */ if (!zgets((byte *) buf, BUFSIZ - 1, zf)) { fprintf(stderr, "xpixmapLoad: %s - unable to find a colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } if ((sscanf(buf, "static char * %s", what) == 1) && (p = rindex(what, '_')) && (!strcmp(p + 1, "colors[]") || !strcmp(p + 1, "mono[]") || !strcmp(p + 1, "pixels[]"))) { if (!strcmp(p + 1, "pixels[]")) { if (gotkey == XPMKEY_NONE) { fprintf(stderr, "xpixmapLoad: %s - colormap is missing\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } donecmap = 1; break; } else if (!strcmp(p + 1, "colors[]")) { if (gotkey == XPMKEY_M && colkey == XPMKEY_M) { continue; /* good enough already - look for pixels */ } gotkey = XPMKEY_C; break; } else { /* must be m */ if (gotkey == XPMKEY_C && colkey != XPMKEY_M) { continue; /* good enough already - look for pixels */ } gotkey = XPMKEY_M; break; } } } } if (donecmap) break; /* read the colors array and build the image colormap */ znocache(zf); ctable = (char **) lmalloc(sizeof(char *) * ncolors); bzero(ctable, sizeof(char *) * ncolors); xcolor.flags = DoRed | DoGreen | DoBlue; for (a = 0; a < ncolors; a++) { /* read pixel value */ *(ctable + a) = (char *) lmalloc(sizeof(char *) * ncolors); /* Find the start of the next string */ while (((c = zgetc(zf)) != EOF) && (c != '"')); if (c == EOF) { fprintf(stderr, "xpixmapLoad: %s - file ended in the colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } /* Read cpp characters in as the color symbol */ for (b = 0; b < cpp; b++) { if ((c = zgetc(zf)) == '\\') c = zgetc(zf); if (c == EOF) { fprintf(stderr, "xpixmapLoad: %s - file ended in the colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } *(*(ctable + a) + b) = (char) c; } /* Locate the end of this string */ if (format == XPM_FORMAT1) { if (((c = zgetc(zf)) == EOF) || (c != '"')) { fprintf(stderr, "xpixmapLoad: %s - file ended in the colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } } /* read color definition and parse it */ /* Locate the start of the next string */ if (format == XPM_FORMAT1) { while (((c = zgetc(zf)) != EOF) && (c != '"')); if (c == EOF) { fprintf(stderr, "xpixmapLoad: %s - file ended in the colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } } /* load the rest of this string into the buffer */ for (b = 0; ((c = zgetc(zf)) != EOF) && (c != '"') && b < (BUFSIZ - 1); b++) { if (c == '\\') c = zgetc(zf); if (c == EOF) { fprintf(stderr, "xpixmapLoad: %s - file ended in the colormap\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } buf[b] = (char) c; } buf[b] = '\0'; /* locate the colour to use */ if (format != XPM_FORMAT1) { for (p = buf; p != NULL;) { if ((p = nword(p, what)) != NULL && !strcmp(what, xpmkeys[colkey])) { if (nword(p, what)) { p = what; break; /* found a color definition */ } } } if (p == NULL) { /* failed to find that color key type */ for (b = XPMKEY_C; b >= XPMKEY_M && p == NULL; b--) { /* try all the rest */ for (p = buf; p != NULL;) { if ((p = nword(p, what)) != NULL && !strcmp(what, xpmkeys[b])) { if (nword(p, what)) { p = what; fprintf(stderr, "xpixmapLoad: %s - couldn't find color key '%s', switching to '%s'\n", name, xpmkeys[colkey], xpmkeys[b]); colkey = b; break; /* found a color definition */ } } } } } if (p == NULL) { fprintf(stderr, "xpixmapLoad: %s - file is corrupted\n", name); freeCtable(ctable, ncolors); freeImage(image); zclose(zf); return NULL; } donecmap = 1; /* There is only 1 color map for new xpm files */ } else p = buf; if (!xliParseXColor(&globals.dinfo, p, &xcolor)) { fprintf(stderr, "xpixmapLoad: %s - Bad color name '%s'\n", name, p); xcolor.red = xcolor.green = xcolor.blue = 0; } *(image->rgb.red + a) = xcolor.red; *(image->rgb.green + a) = xcolor.green; *(image->rgb.blue + a) = xcolor.blue; } } /* convert the linear search color table into a lookup table * for better speed (but could use a lot of memory!). */ cmin = 1 << (sizeof(int) * 8 - 2); /* Hmm. should use maxint */ cmax = 0; for (a = 0; a < ncolors; a++) { int val; for (b = 0, val = 0; b < cpp; b++) val = val * 96 + ctable[a][b] - 32; if (val < cmin) cmin = val; if (val > cmax) cmax = val; } cmax++; /* point one past cmax */ clookup = (int *) lmalloc(sizeof(int) * cmax - cmin); bzero(clookup, sizeof(int) * cmax - cmin); for (a = 0; a < ncolors; a++) { int val; for (b = 0, val = 0; b < cpp; b++) val = val * 96 + ctable[a][b] - 32; clookup[val - cmin] = a; } freeCtable(ctable, ncolors); /* * Now look for the pixel array */ /* 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++) { int val; for (b = 0, val = 0; b < cpp; b++) { if ((c = zgetc(zf)) == '\\') c = zgetc(zf); if (c == EOF) { fprintf(stderr, "xpixmapLoad: %s - Short read of X Pixmap\n", name); zclose(zf); lfree((byte *) clookup); return (image); } val = val * 96 + (int) c - 32; } if (val < cmin || val >= cmax) { fprintf(stderr, "xpixmapLoad: %s - Pixel data doesn't match color data\n", name); a = 0; } a = clookup[val - cmin]; valToMem((unsigned long) a, dptr, image->pixlen); dptr += image->pixlen; } if ((c = zgetc(zf)) != '"') { fprintf(stderr, "xpixmapLoad: %s - Short read of X Pixmap\n", name); lfree((byte *) clookup); zclose(zf); return (image); } } lfree((byte *) clookup); read_trail_opt(image_ops, zf, image, verbose); zclose(zf); return (image); } int xpixmapIdent(char *fullname, char *name) { ZFILE *zf; char *imagetitle; unsigned int w, h; /* image dimensions */ unsigned int cpp; /* chars per pixel */ unsigned int ncolors; /* number of colors */ int format; /* XPM format type */ if (!(zf = zopen(fullname))) { perror("xpixmapIdent"); return (0); } if (!isXpixmap(zf, &w, &h, &cpp, &ncolors, &format, &imagetitle)) { zclose(zf); return 0; } if (imagetitle == NULL) imagetitle = dupString(name); printf("%s is a %dx%d X Pixmap image (Version %d) with %d colors titled '%s'\n", name, w, h, format, ncolors, imagetitle); lfree(imagetitle); zclose(zf); return (1); } xli-2006-11-10/xwd.c0000644000031400000060000004657310525262416013411 0ustar smarryconsole/* 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 "xli.h" #include "imagetypes.h" #include "xwd.h" /* this reads the header and does the magic to determine if it is indeed * an XWD file. */ static int isXWD(char *name, ZFILE * zf, XWDHeader * header, int verbose) { GenericXWDHeader gh; int a; int type = NOT_XWD; if (zread(zf, (byte *) & gh, sizeofGenericXWDHeader) != sizeofGenericXWDHeader) return (0); /* first try -- see if XWD version number matches in either MSB or LSB order */ if (memToVal(gh.file_version, 4) != XWD_VERSION) { if (memToValLSB(gh.file_version, 4) != XWD_VERSION) return (0); else type = XWD_LSB; } else type = XWD_MSB; /* convert fields to fill out header. things we don't care about * are commented out. */ if (type == XWD_MSB) { 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); */ } else { header->header_size = memToValLSB(gh.header_size, 4); header->file_version = memToValLSB(gh.file_version, 4); header->pixmap_format = memToValLSB(gh.pixmap_format, 4); header->pixmap_depth = memToValLSB(gh.pixmap_depth, 4); header->pixmap_width = memToValLSB(gh.pixmap_width, 4); header->pixmap_height = memToValLSB(gh.pixmap_height, 4); header->xoffset = memToValLSB(gh.xoffset, 4); header->byte_order = memToValLSB(gh.byte_order, 4); header->bitmap_unit = memToValLSB(gh.bitmap_unit, 4); header->bitmap_bit_order = memToValLSB(gh.bitmap_bit_order, 4); header->bitmap_pad = memToValLSB(gh.bitmap_pad, 4); header->bits_per_pixel = memToValLSB(gh.bits_per_pixel, 4); header->bytes_per_line = memToValLSB(gh.bytes_per_line, 4); header->visual_class = memToValLSB(gh.visual_class, 4); /*header->red_mask= memToValLSB(gh.red_mask, 4); */ /*header->green_mask= memToValLSB(gh.green_mask, 4); */ /*header->blue_mask= memToValLSB(gh.blue_mask, 4); */ /*header->bits_per_rgb= memToValLSB(gh.bits_per_rgb, 4); */ header->colormap_entries = memToValLSB(gh.colormap_entries, 4); header->ncolors = memToValLSB(gh.ncolors, 4); /*header->window_width= memToValLSB(gh.window_width, 4); */ /*header->window_height= memToValLSB(gh.window_height, 4); */ /*header->window_x= memToValLSB(gh.window_x, 4); */ /*header->window_y= memToValLSB(gh.window_y, 4); */ /*header->window_bdrwidth= memToValLSB(gh.window_bdrwidth, 4); */ } /* if header size isn't either 100 or 104 bytes, this isn't an XWD file */ if (header->header_size < sizeofGenericXWDHeader) return (0); for (a = header->header_size - sizeofGenericXWDHeader; 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; } if (type == XWD_LSB) printf(" LSB header, "); else printf(" MSB header, "); if (header->pixmap_format != ZPixmap || header->pixmap_depth == 1) { if (header->bitmap_bit_order == LSBFirst) { printf(" LSB bit, %d units,", header->bitmap_unit); } else { printf(" MSB bit, %d units,", header->bitmap_unit); } } if (header->byte_order == LSBFirst) printf(" LSB byte order"); else printf(" MSB byte order"); printf("\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. */ return (type); } int xwdIdent(char *fullname, char *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(char *name, ZFILE * zf, XWDHeader header, int type) { 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 */ 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; line = (byte *) lmalloc(dlinelen); for (y = 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *) line, dlinelen) != dlinelen) { fprintf(stderr, "xwdLoad: %s - Short read (returning partial image)\n", name); lfree(line); return (image); } dptr = line + xoffset; iptr = image->data + (y * ilinelen); if (header.bitmap_bit_order == LSBFirst) flipBits(line, dlinelen); /* The byte swap conditions are a little complex as three things cause a * need to swap. If the byte_order is wrong we need to swap. If the bit * order is wrong we need to swap the bits across bytes. If the whole * file is byte reversed we need to swap. These swaps may cancel out, * hence the xor expression below. */ if ((header.byte_order == MSBFirst) ^ (header.bitmap_bit_order == MSBFirst) ^ (type == XWD_MSB)) for (x = 0; x < xunits; x++) { /* Don't swap bytes */ register unsigned long temp; temp = memToVal(dptr, unit); valToMem(temp, iptr, unit); dptr += unit; iptr += unit; } else for (x = 0; x < xunits; x++) { /* swap bytes */ register unsigned long temp; temp = memToValLSB(dptr, unit); valToMem(temp, iptr, unit); dptr += unit; iptr += unit; } /* take care of last unit on this line */ if ((header.byte_order == MSBFirst) ^ (header.bitmap_bit_order == MSBFirst) ^ (type == XWD_MSB)) { register unsigned long temp; temp = memToVal(dptr, unit); valToMem(temp >> shift, iptr, trailer); } else { register unsigned long temp; temp = memToValLSB(dptr, unit); valToMem(temp >> 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(char *name, ZFILE * zf, XWDHeader header, int type) { 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; 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); line = (byte *) lmalloc(dlinelen); /* for each plane, load in the bitmap and or it into the image */ for (plane = header.pixmap_depth; plane > 0; plane--) { for (y = 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *) line, dlinelen) != dlinelen) { fprintf(stderr, "xwdLoad: %s - Short read (returning partial image)\n", name); lfree(line); return (image); } dptr = line + xoffset; iptr = image->data + (y * ilinelen); index = 0; if (header.bitmap_bit_order == LSBFirst) flipBits(line, dlinelen); if ((header.byte_order == MSBFirst) ^ (header.bitmap_bit_order == MSBFirst) ^ (type == XWD_MSB)) for (x = 0; x < xunits; x++) { register unsigned long temp; pixvals = memToVal(dptr, unit); mask = unitmask; for (x2 = 0; x2 < unitbits; x2++) { if (pixvals & mask) { temp = memToVal(iptr + index, image->pixlen); valToMem(temp | (1 << plane), iptr + index, image->pixlen); } index += image->pixlen; if (index > ilinelen) { x = xunits; break; } if (!(mask >>= 1)) mask = unitmask; } dptr += unit; } else for (x = 0; x < xunits; x++) { register unsigned long temp; pixvals = memToValLSB(dptr, unit); mask = unitmask; for (x2 = 0; x2 < unitbits; x2++) { if (pixvals & mask) { temp = memToVal(iptr + index, image->pixlen); valToMem(temp | (1 << plane), 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(char *name, ZFILE * zf, XWDHeader header, int type) { 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 */ 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 = ((unsigned long) 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; line = (byte *) lmalloc(dlinelen); for (y = 0; y < header.pixmap_height; y++) { if (zread(zf, (byte *) line, dlinelen) != dlinelen) { fprintf(stderr, "xwdLoad: %s - Short read (returning partial image)\n", name); lfree(line); return (image); } dptr = line; iptr = image->data + (y * ilinelen); switch (depth) { case 4: /* The protocol documents says we should take the order of */ /* 4 bit pixels within a byte from the byte_order field - GWG */ if (header.byte_order == LSBFirst) { /* nybbles are reversed */ for (x = 0; x < header.pixmap_width; x++) { pixel = memToVal(dptr, 1); valToMem(pixel & pixmask, iptr++, 1); if (++x < header.pixmap_width) valToMem((pixel >> 4) & pixmask, iptr++, 1); } } else { /* MSB first */ for (x = 0; x < header.pixmap_width; x++) { pixel = memToVal(dptr, 1); valToMem((pixel >> 4) & pixmask, iptr++, 1); if (++x < header.pixmap_width) valToMem(pixel & pixmask, iptr++, 1); } } break; case 8: for (x = 0; x < header.pixmap_width; x++) { pixel = ((unsigned long) *(dptr++)) & pixmask; /* loader isn't needed */ valToMem(pixel, iptr++, 1); } break; case 16: if ((header.byte_order == MSBFirst) ^ (type != XWD_MSB)) { for (x = 0; x < header.pixmap_width; x++) { pixel = memToVal(dptr, 2); valToMem(pixel & pixmask, iptr, 2); dptr += 2; iptr += 2; } } else { for (x = 0; x < header.pixmap_width; x++) { pixel = memToValLSB(dptr, 2); valToMem(pixel & pixmask, iptr, 2); dptr += 2; iptr += 2; } } break; case 24: if ((header.byte_order == MSBFirst) ^ (type != XWD_MSB)) { for (x = 0; x < header.pixmap_width; x++) { pixel = memToVal(dptr, 3); valToMem(pixel & pixmask, iptr, 3); dptr += 3; iptr += 3; } } else { for (x = 0; x < header.pixmap_width; x++) { pixel = memToValLSB(dptr, 3); valToMem(pixel & pixmask, iptr, 3); dptr += 3; iptr += 3; } } break; case 32: if ((header.byte_order == MSBFirst) ^ (type != XWD_MSB)) { for (x = 0; x < header.pixmap_width; x++) { pixel = memToVal(dptr, 4); valToMem(pixel & pixmask, iptr, 4); dptr += 4; iptr += 4; } } else { for (x = 0; x < header.pixmap_width; x++) { pixel = memToValLSB(dptr, 4); valToMem(pixel & pixmask, iptr, 4); dptr += 4; iptr += 4; } } break; default: fprintf(stderr, "xwdLoad: %s - ZPixmaps of depth %d are not supported (sorry).\n", name, header.pixmap_depth); lfree(line); freeImage(image); return (NULL); } } lfree(line); return (image); } Image *xwdLoad(char *fullname, ImageOptions * image_ops, boolean verbose) { ZFILE *zf; char *name = image_ops->name; XWDHeader header; int cmaplen; XWDColor *cmap; byte *cmapptr; /* Pointer into structure elements */ Image *image; int a; int type; if (!(zf = zopen(fullname))) { perror("xwdLoad"); return (NULL); } if (!(type = isXWD(name, zf, &header, verbose))) { zclose(zf); return (NULL); } znocache(zf); /* 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, "xwdLoad: %d - Unsupported visual type, sorry\n", header.visual_class); zclose(zf); return (NULL); } if ((header.pixmap_width == 0) || (header.pixmap_height == 0)) { fprintf(stderr, "Zero-size image -- header might be corrupted.\n"); zclose(zf); return (NULL); } /* read in colormap */ cmaplen = header.ncolors * sizeofXWDColor; cmap = (XWDColor *) lmalloc(cmaplen); if (zread(zf, (byte *) cmap, cmaplen) != cmaplen) { fprintf(stderr, "Short read in colormap!\n"); lfree((byte *) cmap); zclose(zf); return (NULL); } /* 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", name); lfree((byte *) cmap); zclose(zf); return (NULL); } /* load the colormap. */ if (header.pixmap_format == XYBitmap) { image = loadXYBitmap(name, zf, header, type); image->rgb.used = 2; if (type == XWD_MSB) for (a = 0, cmapptr = (byte *) cmap; a < 2; a++, cmapptr += sizeofXWDColor) { image->rgb.red[a] = memToVal(cmapptr + 4, 2); image->rgb.green[a] = memToVal(cmapptr + 6, 2); image->rgb.blue[a] = memToVal(cmapptr + 8, 2); } else for (a = 0, cmapptr = (byte *) cmap; a < 2; a++, cmapptr += sizeofXWDColor) { image->rgb.red[a] = memToValLSB(cmapptr + 4, 2); image->rgb.green[a] = memToValLSB(cmapptr + 6, 2); image->rgb.blue[a] = memToValLSB(cmapptr + 8, 2); } } else { /* color format */ if (header.pixmap_format == XYPixmap) image = loadXYPixmap(name, zf, header, type); else /* ZPixmap */ image = loadZPixmap(name, zf, header, type); if (image == NULL) { zclose(zf); return NULL; } image->rgb.used = header.ncolors; if (type == XWD_MSB) for (a = 0, cmapptr = (byte *) cmap; a < header.ncolors; a++, cmapptr += sizeofXWDColor) { int pixelval = memToVal(cmapptr, 4); image->rgb.red[pixelval] = memToVal(cmapptr + 4, 2); image->rgb.green[pixelval] = memToVal(cmapptr + 6, 2); image->rgb.blue[pixelval] = memToVal(cmapptr + 8, 2); } else for (a = 0, cmapptr = (byte *) cmap; a < header.ncolors; a++, cmapptr += sizeofXWDColor) { int pixelval = memToValLSB(cmapptr, 4); image->rgb.red[pixelval] = memToValLSB(cmapptr + 4, 2); image->rgb.green[pixelval] = memToValLSB(cmapptr + 6, 2); image->rgb.blue[pixelval] = memToValLSB(cmapptr + 8, 2); } } read_trail_opt(image_ops, zf, image, verbose); zclose(zf); image->title = dupString(name); lfree((byte *) cmap); return (image); } xli-2006-11-10/xwd.h0000644000031400000060000000720106461630121013373 0ustar smarryconsole/* #ident "@(#)x11:contrib/clients/xloadimage/xwd.h 1.6 94/07/29 Labtam" */ /* 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 */ #define sizeofGenericXWDHeader 100 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; #define sizeofXWDColor 12 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 */ xli-2006-11-10/zio.c0000644000031400000060000005114610525262416013400 0ustar smarryconsole/* 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. * * Re-worked by Graeme W. Gill on 91/12/04 to add zrewind, zunread and * better performance of per character reads. * * The uu decoder is loosely based on uuexplode-1.2.c * by Michael Bergman (ebcrmb@ebc.ericsson.se), * which is based on kiss 1.0 by Kevin Yang. * */ #include "copyright.h" #include "xli.h" #include #include #ifdef VMS #define NO_UNCOMPRESS /* VMS doesn't have uncompress */ #endif /* ANSI C doesn't declare popen in stdio.h ! */ FILE *popen(const char *, const char *); #define MAX_ZFILES 32 #define UUSTARTLEN 100 /* Lines to look though before assuming not uuencoded */ static int uuread(ZFILE *zf, byte *buf, int len); static int uugetline(ZFILE *zf, byte *obuf); static boolean uuCheck(byte *icp, int len); static int uuExplodeLine(byte *icp, byte *ocp); static int buflen(byte *buf, int len); static ZFILE ZFileTable[MAX_ZFILES]; static boolean ZForceCache = FALSE; int zread(ZFILE *zf, byte *buf, int len) { int lentoread = len; struct cache *dataptr = zf->dataptr; while (len > 0 && !zf->eof) { /* Read any data in cache buffers or aux buffer */ if (zf->bufptr < zf->endptr) { int readlen = zf->endptr - zf->bufptr; if (readlen > len) readlen = len; bcopy(zf->bufptr, buf, readlen); buf += readlen; len -= readlen; zf->bufptr += readlen; continue; } /* else we have run out of buffered data */ /* If we were reading from an aux buffer, */ /* retore the previous state */ if (zf->auxb != NULL) { /* restore previous buffer */ if (zf->auxb != zf->buf) /* if not getc buffer */ lfree(zf->auxb); /* was un-read buffer */ zf->auxb = NULL; zf->bufptr = zf->oldbufptr; zf->endptr = zf->oldendptr; continue; } /* If this is a newly opened file or we are */ /* no longer reading previously cached data */ if (dataptr == NULL) { if (zf->nocache) { /* If the cache is turned off, read directly */ if (len > 1) { /* more than a byte being read */ len -= uuread(zf, buf, len); if (len > 0) zf->eof = TRUE; continue; } /* else we are reading one byte directly - this is a little */ /* inefficient :-). Buffer it instead. */ zf->bufptr = zf->buf; zf->endptr = zf->bufptr + uuread(zf, zf->bufptr, BUFSIZ); if (zf->endptr == zf->bufptr) zf->eof = TRUE; continue; } /* else fall through to deal with first cached buffered read */ } else { /* we must move on to the next cache buffer */ if (zf->bufptr == NULL) { /* If this is a first re-read of the cache */ zf->bufptr = dataptr->buf; /* init the pointers */ zf->endptr = dataptr->end; continue; } /* If there are more buffers, then advance */ /* to the next one */ if (dataptr->next != NULL) { /* advance to the next buffer */ dataptr = zf->dataptr = dataptr->next; zf->bufptr = dataptr->buf; zf->endptr = dataptr->end; continue; } /* There are no more buffers */ if (dataptr->eof) { zf->eof = TRUE; /* we know that was the last one */ continue; } } /* We have come to the end of the cache buffers or */ /* we are doing the first cached read. */ /* If the cache is off, switch it fully */ /* out of the picture from now on */ if (zf->nocache) { /* read directly */ zf->dataptr = dataptr = NULL; zf->bufptr = NULL; zf->endptr = NULL; continue; } /* We are caching and have to read another buffer or maybe we have */ /* to read the very first buffer (zf->data and dataptr == NULL) */ zf->dataptr = (struct cache *) lmalloc(sizeof(struct cache)); zf->dataptr->next = NULL; zf->dataptr->eof = FALSE; if (zf->data == NULL) /* If very first read */ zf->data = zf->dataptr; /* set to first allocated buffer */ else /* link buffer into chain */ dataptr->next = zf->dataptr; dataptr = zf->dataptr; zf->bufptr = dataptr->buf; zf->endptr = dataptr->end = zf->bufptr + uuread(zf, zf->bufptr, BUFSIZ); dataptr->eof = ((zf->endptr - zf->bufptr) < BUFSIZ); } return (lentoread - len); } /* append the given buffer data to the files read cache */ /* (Allows reading blocks directly from input stream while */ /* maintaining cache data) */ static void _zaptocache(ZFILE *zf, char *cbuf, int blen) { struct cache *newdat, *dat; int len; while (blen > 0) { /* until we've stashed all of input */ len = blen; if (len > BUFSIZ) len = BUFSIZ; /* create new cache data block */ newdat = (struct cache *) lmalloc(sizeof(struct cache)); bcopy(cbuf, newdat->buf, len); newdat->end = newdat->buf + len; newdat->next = NULL; newdat->eof = FALSE; /* append it to cache buffers */ if (zf->data == NULL) { /* nothing read yet */ zf->data = newdat; zf->dataptr = zf->data; } else { for (dat = zf->data; dat->next != NULL; dat = dat->next); /* go to end of chain */ dat->next = newdat; dat->eof = FALSE; } cbuf += len; blen -= len; } } /* Return the files EOF status */ int zeof(ZFILE *zf) { return zf->eof; } void zclearerr(ZFILE *zf) { clearerr((zf)->stream); zf->eof = 0; } /* reset a read cache (reset means really close the file) */ void zreset(char *filename) { int a; ZFILE *zf; if (TRUE == ZForceCache) return; /* 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 (zf = ZFileTable; zf < (ZFileTable + MAX_ZFILES); zf++) if (zf->filename && !strcmp(filename, zf->filename)) break; if (zf == (ZFileTable + MAX_ZFILES)) /* no go joe */ return; _zreset(zf); } /* reset by file descriptor */ void _zreset(ZFILE *zf) { struct cache *old; if (zf->dataptr != zf->data) fprintf(stderr, "zreset: warning: ZFILE for %s was not closed properly\n", zf->filename); while (zf->data) { old = zf->data; zf->data = zf->data->next; lfree((byte *) old); } lfree((byte *) zf->filename); zf->filename = NULL; zf->data = NULL; zf->dataptr = NULL; zf->nocache = FALSE; if (zf->auxb != NULL && zf->auxb != zf->buf) lfree((byte *) zf->auxb); zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->eof = FALSE; switch (zf->type) { case ZSTANDARD: fclose(zf->stream); break; #ifndef NO_UNCOMPRESS case ZPIPE: pclose(zf->stream); break; #endif /* NO_UNCOMPRESS */ case ZSTDIN: break; default: fprintf(stderr, "zreset: bad ZFILE structure\n"); exit(1); } } /* discard all data that has been read. Return to state just after file was opened */ void _zclear(ZFILE *zf) { struct cache *old; if (zf->auxb != NULL && zf->auxb != zf->buf) lfree(zf->auxb); while (zf->data) { old = zf->data; zf->data = zf->data->next; free(old); } zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->eof = FALSE; zf->data = NULL; zf->dataptr = NULL; zf->nocache = FALSE; } ZFILE *zopen(char *name) { ZFILE *zf; /* look for filename in open file table */ for (zf = ZFileTable; zf < (ZFileTable + MAX_ZFILES); zf++) if (zf->filename && !strcmp(name, zf->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 (zf->nocache) { if (zf->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(zf->filename); /* remove entry and treat like new open */ break; } if (zf->dataptr != zf->data) fprintf(stderr, "zopen: warning: file doubly opened\n"); zf->dataptr = zf->data; /* re-start with cache if it exists */ if (zf->auxb != NULL && zf->auxb != zf->buf) lfree((byte *) zf->auxb); zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->eof = FALSE; return (zf); } /* find unused ZFileTable entry */ for (zf = ZFileTable; zf < (ZFileTable + MAX_ZFILES) && zf->filename; zf++) /* EMPTY */ ; if (zf >= (ZFileTable + MAX_ZFILES)) { fprintf(stderr, "zopen: no more files available\n"); exit(1); } zf->filename = dupString(name); if (!_zopen(zf)) { /* failed */ lfree(zf->filename); zf->filename = NULL; return (NULL); } return (zf); } /* Do an open given a file pointer */ /* Return TRUE if open suceeded */ boolean _zopen(ZFILE *zf) { char *name = zf->filename; char uuibuf[UULEN], uudest[UULEN], uudummy[UULEN]; int uumode, uutry = UUSTARTLEN; zf->data = NULL; zf->dataptr = NULL; zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->nocache = FALSE; zf->eof = FALSE; zf->uudecode = FALSE; /* file filename is `stdin' then use stdin */ if (!strcmp(name, "stdin")) { zf->type = ZSTDIN; zf->stream = stdin; } else { char const *cmd = 0; #ifndef NO_UNCOMPRESS /* if filename ends in `.Z' then open pipe to uncompress. if * your system doesn't have uncompress you can define * NO_UNCOMPRESS and it just won't check for this. */ #ifdef HAVE_GUNZIP if ( (strlen(name) > 3 && !strcasecmp(".gz", name + strlen(name) - 3)) || (strlen(name) > 2 && !strcasecmp(".Z", name + strlen(name) - 2)) ) { cmd = "gunzip -c "; } #else /* it's a unix compressed file, so use uncompress */ if ((strlen(name) > (unsigned) 2) && !strcmp(".Z", name + (strlen(name) - 2))) { cmd = "uncompress -c "; } #endif /* HAVE_GUNZIP */ #ifdef HAVE_BUNZIP2 if (strlen(name) > 4 && !strcasecmp(".bz2", name + strlen(name) - 4)) { cmd = "bunzip2 -c "; } #endif /* HAVE_BUNZIP2 */ #endif /* NO_UNCOMPRESS */ if (cmd) { char *buf, *s, *t; /* protect in single quotes, replacing single quotes * with '"'"', so worst-case expansion is 5x */ buf = (char *) lmalloc( strlen(cmd) + 1 + 5 * strlen(name) + 1 + 1); strcpy(buf, cmd); s = buf + strlen(buf); *s++ = '\''; for (t = name; *t; ++t) { if ('\'' == *t) { strcpy(s, "'\"'\"'"); s += strlen(s); } else { *s++ = *t; } } *s++ = '\''; *s = '\0'; zf->type = ZPIPE; zf->stream = popen(buf, "r"); lfree(buf); } else { /* default to normal stream */ zf->type = ZSTANDARD; #ifdef VMS zf->stream = fopen(name, "r", "ctx=bin", "ctx=stm", "rfm=stmlf"); #else zf->stream = fopen(name, "r"); #endif } } if (!zf->stream) { return (FALSE); } /* File is now open, so see if it is a uuencoded file */ while (uutry-- > 0) { if (fgets(uuibuf, UULEN, zf->stream) != NULL) { int blen; blen = buflen(uuibuf, UULEN); if (blen < 0) { /* doesn't look like reasonable junk */ _zaptocache(zf, uuibuf, -blen); break; } _zaptocache(zf, uuibuf, blen); /* keep zfile data cached */ if (!strncmp(uuibuf, "begin ", 6) && isdigit(uuibuf[6]) && isdigit(uuibuf[7]) && isdigit(uuibuf[8])) { /* Found a begin line */ /* Extract filename and file mode */ if ((sscanf(uuibuf, "begin %o%[ ]%s", &uumode, uudummy, uudest)) != 3) { continue; /* it's not right */ } /* Need access to verbose flag to print the following */ /* printf("uuencoded file '%s' being decoded\n",uudest); */ _zclear(zf); /* discard all data read */ zf->uudecode = TRUE; zf->uunext = zf->uuend = &zf->uubuf[0]; zf->uustate = UUBODY; return (TRUE); } } } /* Not uu encodede */ return (TRUE); } /* The function zgetc, rather than the macro */ int _zgetc(ZFILE *zf) { unsigned char c; if (zf->bufptr < zf->endptr) return *zf->bufptr++; if (zread(zf, &c, 1) > 0) return (c); else return (EOF); } char *zgets(char *buf, unsigned int size, ZFILE *zf) { if ((--size) <= 0) return NULL; { int ssize = zf->endptr - zf->bufptr; if (ssize > 0) { /* can do this fast */ register byte *bp = zf->bufptr, *be; be = zf->bufptr + (size < ssize ? size : ssize); while (bp < be) { if (*bp++ == '\n') break; } if (bp < be || size < ssize) { bcopy(zf->bufptr, buf, bp - zf->bufptr); buf[bp - zf->bufptr] = '\000'; zf->bufptr = bp; return ((char *) buf); } } } /* do this slower */ { register char *cp = buf; register int c; while (cp < (buf + size) && (c = zgetc(zf)) != EOF) { *cp++ = c; if (c == '\n') break; } if (cp > buf) { /* we read something */ *cp = '\000'; return ((char *) buf); } } return (NULL); } /* Return a block of data back to the input stream. * Usefull if a load routine does its own buffering * and wants to return what is left after it has read an image. */ void zunread(ZFILE *zf, byte const *buf, int len) { byte *new; int sizeaxb; /* size of aux buffer */ int noinaxb; /* number unread in aux buffer */ int nofraxb; /* number free in aux buffer */ if (len == 0) return; if (zf->auxb != NULL) { sizeaxb = zf->endptr - zf->auxb; /* size of aux buffer */ noinaxb = zf->endptr - zf->bufptr; /* number unread in aux buffer */ nofraxb = zf->bufptr - zf->auxb; /* number free in aux buffer */ } else { zf->oldbufptr = zf->bufptr; zf->oldendptr = zf->endptr; sizeaxb = noinaxb = nofraxb = 0; } if (len <= nofraxb) { /* no need to alloc more */ zf->bufptr -= len; bcopy(buf, zf->bufptr, len); } else { /* need some more space */ int extra = 0; if (len < 100) extra = 100; new = (byte *) lmalloc(extra + noinaxb + len); bcopy(buf, new + extra, len); /* copy new aux data */ if (noinaxb != 0) { /* copy old data */ bcopy(zf->bufptr, new + extra + len, noinaxb); if (zf->auxb != NULL && zf->auxb != zf->buf) lfree(zf->auxb); } zf->auxb = new; zf->bufptr = new + extra; zf->endptr = new + extra + noinaxb + len; } zf->eof = FALSE; } /* this turns off caching when an image has been identified and we will not * need to re-open it */ void znocache(ZFILE *zf) { if (FALSE == ZForceCache) zf->nocache = TRUE; } void zforcecache(boolean v) { ZForceCache = v; } /* reset cache pointers in a ZFILE. nothing is actually reset until a * zreset() is called with the filename. */ void zclose(ZFILE *zf) { zf->dataptr = zf->data; if (zf->auxb != NULL && zf->auxb != zf->buf) lfree(zf->auxb); zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->eof = FALSE; } /* close the file and then re-open it. */ /* Return TRUE on sucess. */ boolean _zreopen(ZFILE *zf) { char *tname; tname = dupString(zf->filename); _zreset(zf); zf->filename = tname; if (!_zopen(zf)) { /* failed */ lfree(zf->filename); zf->filename = NULL; return (FALSE); } return (TRUE); } /* Rewind the cached file. Warn the user if * this is not likely to work. * Return TRUE on sucess. */ boolean zrewind(ZFILE *zf) { if (zf->nocache) { if (zf->type == ZSTDIN) { fprintf(stderr, "zrewind: caching was disabled by previous caller; can't rewind\n"); return (FALSE); } fprintf(stderr, "zrewind: warning: caching was disabled by previous caller\n"); return !_zreopen(zf); } zf->dataptr = zf->data; if (zf->auxb != NULL && zf->auxb != zf->buf) lfree(zf->auxb); zf->auxb = NULL; zf->bufptr = NULL; zf->endptr = NULL; zf->eof = FALSE; return TRUE; } /* Read in a buffer from the possibly uuencoded input stream */ int uuread(ZFILE *zf, byte *buf, int len) { int cl, ld = 0; if (!zf->uudecode) { if (zf->type == ZSTANDARD) return fread(buf, 1, len, zf->stream); /* Work around for SVR4 fread() bug */ for (;;) { ld += cl = fread(buf, 1, len - ld, zf->stream); if (ld == len) break; buf += cl; if (feof(zf->stream)) break; } return ld; } for (;;) { if (zf->uunext >= zf->uuend) { /* if buffer empty */ zf->uunext = zf->uubuf; zf->uuend = zf->uubuf + uugetline(zf, zf->uubuf); if (zf->uunext >= zf->uuend) { /* nothing read */ return ld; } } /* Copy what we got into the buffer */ cl = zf->uuend - zf->uunext; /* copy length */ if (cl > (len - ld)) cl = (len - ld); bcopy(zf->uunext, buf, cl); zf->uunext += cl; ld += cl; /* bump length done */ buf += cl; if (ld >= len) { /* Finished */ return ld; } } } /* Get a line of uudecoded bytes from the input stream */ #define SHORTALOWANCE 6 /* alowance for truncation of ' 's at the end of lines */ int uugetline(ZFILE *zf, byte *obuf) { int ulen, len; /* number of uu encoding characters */ byte ibuf[UULEN]; /* raw line buffer */ int nib = 0; /* number in buffer */ for (;;) { /* until we return something */ if (zf->uustate == UUEOF) { /* there's nothing more to read */ return 0; } if (fgets((char *) ibuf, UULEN, zf->stream) == NULL) { fprintf(stderr, "uudecode: unexpected EOF\n"); zf->uustate = UUEOF; return 0; } len = strlen((char *) ibuf) - 2; ulen = ((int) (((*ibuf) - ' ') & 077) * 4 + 2) / 3; if (*ibuf == 'M' && (len + SHORTALOWANCE) >= ulen && uuCheck(ibuf + 1, ulen <= len ? ulen : len)) { if (len < ulen) { /* we have a slightly short line */ fprintf(stderr, "uudecode: warning, short line\n"); while (len < ulen) ibuf[++len] = ' '; } nib = uuExplodeLine(ibuf, obuf); zf->uustate = UUBODY; return nib; } /* Found a possibly dodgey line */ if (zf->uustate == UUSKIP) { continue; /* Skip any non 'M' lines */ } if ((*ibuf != ' ' && *ibuf != '`') || (len != 0 && len != 1)) { /* not a blank before end line */ /* Is zf->uustate == UUBODY and possible dodgy line */ if (*ibuf > 'L' || *ibuf <= ' ' || len < ulen || !uuCheck(ibuf + 1, ulen)) { /* not a possible short line */ zf->uustate = UUSKIP; continue; } nib = uuExplodeLine(ibuf, obuf); /* decode possible short line */ /* if this is a valid short line, then we expect a */ /* specific line followed by an end line */ if (fgets((char *) ibuf, UULEN, zf->stream) == NULL) { fprintf(stderr, "uudecode: unexpected EOF\n"); zf->uustate = UUEOF; return nib; } len = strlen((char *) ibuf) - 2; ulen = ((int) (((*ibuf) - ' ') & 077) * 4 + 2) / 3; if (*ibuf == 'M' && (len + SHORTALOWANCE) >= ulen && uuCheck(ibuf + 1, ulen <= len ? ulen : len)) { /* Found an 'M' line - previous line must be garbage */ if (len < ulen) { /* we have a slightly short line */ fprintf(stderr, "uudecode: warning, short line\n"); while (len < ulen) ibuf[++len] = ' '; } nib = uuExplodeLine(ibuf, obuf); zf->uustate = UUBODY; return nib; } if ((*ibuf != ' ' && *ibuf != '`') || (len != 0 && len != 1)) { /* Not found correct thing after short line. Assume garbage */ nib = 0; zf->uustate = UUSKIP; continue; } } /* Check for an end line */ if (fgets((char *) ibuf, UULEN, zf->stream) == NULL) { fprintf(stderr, "uudecode: unexpected EOF\n"); zf->uustate = UUEOF; return nib; } len = strlen((char *) ibuf) - 2; ulen = ((int) (((*ibuf) - ' ') & 077) * 4 + 2) / 3; if (*ibuf == 'M' && (len + SHORTALOWANCE) >= ulen && uuCheck(ibuf + 1, ulen <= len ? ulen : len)) { /* Found an 'M' line - previous lines must be garbage */ if (len < ulen) { /* we have a slightly short line */ fprintf(stderr, "uudecode: warning, short line\n"); while (len < ulen) ibuf[++len] = ' '; } nib = uuExplodeLine(ibuf, obuf); zf->uustate = UUBODY; return nib; } if (len != 2 || strncmp((char *) ibuf, "end", 3)) { /* Not found correct thing after short line. Assume garbage */ nib = 0; zf->uustate = UUSKIP; continue; } /* Found end line, assume short line was ok */ zf->uustate = UUEOF; return nib; } } #define DEC(C) ((unsigned)(((C) - ' ') & 077)) int uuExplodeLine(byte *icp, byte *ocp) { unsigned int x, y, z; int i, len; i = len = DEC(*icp); ++icp; while (i > 0) { if (i >= 3) { x = (DEC(*icp) << 2); icp++; x |= (DEC(*icp) >> 4); y = (DEC(*icp) << 4); icp++; y |= (DEC(*icp) >> 2); z = (DEC(*icp) << 6); icp++; z |= (DEC(*icp)); *ocp++ = x; *ocp++ = y; *ocp++ = z; } else if (i >= 2) { x = (DEC(*icp) << 2); icp++; x |= (DEC(*icp) >> 4); y = (DEC(*icp) << 4); icp++; y |= (DEC(*icp) >> 2); *ocp++ = x; *ocp++ = y; } else if (i >= 1) { x = (DEC(*icp) << 2); icp++; x |= (DEC(*icp) >> 4); *ocp++ = x; } icp++; i -= 3; } return len; } /* Check for valid uu encoding characters */ boolean uuCheck(byte *icp, int len) { for (; len > 0; len--, icp++) if (*icp >= 'a' || *icp < ' ') return FALSE; return TRUE; } /* Find the length of a gets buffer */ /* Return the negative length if it looks like binary */ /* junk */ static int buflen(byte *buf, int len) { int i, j = 0; len--; /* allow for '\000' at end */ for (i = 0; i < len && *buf != '\n'; i++, buf++) { if (*buf == '\000') j = 1; } if (i < len) i++; /* count '\n' */ if (j) return -i; return i; } xli-2006-11-10/zoom.c0000644000031400000060000001402710525262416013560 0ustar smarryconsole/* 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 "xli.h" static unsigned int *buildIndex(unsigned int width, unsigned int zoom, unsigned int *rwidth) { unsigned int *index; unsigned int a; if (!zoom) { zoom = 100; } *rwidth = width * zoom / 100; index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth); for (a = 0; a < *rwidth; a++) *(index + a) = a * (width - 1) / (*rwidth - 1); return(index); } Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom, boolean verbose, boolean changetitle) { char buf[BUFSIZ]; float gamma; 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; CURRFUNC("zoom"); image = 0; if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100)) return(oimage); if (!xzoom) { if (verbose) printf(" Zooming image Y axis by %d%%...", yzoom); if (changetitle) sprintf(buf, "%s (Y zoom %d%%)", oimage->title, yzoom); } else if (!yzoom) { if (verbose) printf(" Zooming image X axis by %d%%...", xzoom); if (changetitle) sprintf(buf, "%s (X zoom %d%%)", oimage->title, xzoom); } else if (xzoom == yzoom) { if (verbose) printf(" Zooming image by %d%%...", xzoom); if (changetitle) 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); if (changetitle) sprintf(buf, "%s (X zoom %d%% Y zoom %d%%)", oimage->title, xzoom, yzoom); } if (!changetitle) strcpy(buf,oimage->title); if (verbose) fflush(stdout); gamma= oimage->gamma; 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; 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, image->pixlen); if(pixlen == 1 && image->pixlen == 1) /* common */ for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) { if (xsrc != *(xindex + x)) { do { xsrc++; srcptr += 1; } while (xsrc != *(xindex + x)); value= memToVal(srcptr, 1); } valToMem(value, destptr, 1); destptr += 1; } else /* less common */ 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, image->pixlen); } valToMem(value, destptr, pixlen); destptr += pixlen; } } break; 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, image->pixlen); if(pixlen == 3 && image->pixlen == 3) /* common */ for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) { if (xsrc != *(xindex + x)) { do { xsrc++; srcptr += 3; } while (xsrc != *(xindex + x)); value= memToVal(srcptr, 3); } valToMem(value, destptr, 3); destptr += 3; } else /* less common */ 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, image->pixlen); } valToMem(value, destptr, pixlen); destptr += pixlen; } } break; } image->title = dupString(buf); image->gamma= gamma; lfree((byte *)xindex); lfree((byte *)yindex); if (verbose) printf("done\n"); return(image); } xli-2006-11-10/Imakefile0000644000031400000060000000442010525262416014235 0ustar smarryconsole# Imakefile for building within the X11 source tree. # # If you have problems building, read the README file and use Makefile.std. # # Put these in DEFINES below if needed: # # -DHAVE_GUNZIP use gunzip instead of uncompress # -DNO_UNCOMPRESS if you don't have uncompress # -DHAVE_BOOLEAN if your system declares 'boolean' somewhere # -DHAVE_BUNZIP2 if you have bzip2 and want to handle .bz2 files #ifdef HPArchitecture CCOPTIONS = -Aa -D_HPUX_SOURCE #endif JPEG_INCLUDES = JPEG_LDFLAGS = PNG_INCLUDES = PNG_LDFLAGS = SYSPATHFILE = $(XAPPLOADDIR)/Xli DEPLIBS = $(DEPXLIB) LOCAL_LIBRARIES = $(XLIB) $(JPEG_LDFLAGS) $(PNG_LDFLAGS) -ljpeg -lpng -lz SYS_LIBRARIES = -lm DEFINES = -DHAS_MEMCPY EXTRA_INCLUDES = $(JPEG_INCLUDES) $(PNG_INCLUDES) SRCS1 = bright.c clip.c cmuwmrast.c compress.c dither.c faces.c fbm.c fill.c g3.c gif.c halftone.c imagetypes.c img.c mac.c mcidas.c mc_tables.c merge.c misc.c new.c options.c path.c pbm.c pcx.c reduce.c jpeg.c rle.c rlelib.c root.c rotate.c send.c smooth.c sunraster.c value.c window.c xbitmap.c xli.c xpixmap.c xwd.c zio.c zoom.c ddxli.c tga.c bmp.c pcd.c png.c OBJS1 = bright.o clip.o cmuwmrast.o compress.o dither.o faces.o fbm.o fill.o g3.o gif.o halftone.o imagetypes.o img.o mac.o mcidas.o mc_tables.o merge.o misc.o new.o options.o path.o pbm.o pcx.o reduce.o jpeg.o rle.o rlelib.o root.o rotate.o send.o smooth.o sunraster.o value.o window.o xbitmap.o xli.o xpixmap.o xwd.o zio.o zoom.o ddxli.o tga.o bmp.o pcd.o png.o SRCS2 = xlito.c OBJS2 = xlito.o PROGRAMS = xli xlito ComplexProgramTarget_1(xli,$(DEFINES) $(LOCAL_LIBRARIES),) ComplexProgramTarget_2(xlito,,) install:: $(SYSPATHFILE) $(RM) $(BINDIR)/xview $(BINDIR)/xsetbg $(LN) $(BINDIR)/xli $(BINDIR)/xview $(LN) $(BINDIR)/xli $(BINDIR)/xsetbg $(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 /dev/null $(SYSPATHFILE) echo "path=$(INCDIR)/bitmaps $(INCDIR)/images" \ >> $(SYSPATHFILE) echo "extension=.gif .jpg .rle .csun .msun .sun .face .xbm .bm" \ >>$(SYSPATHFILE) chmod a+r $(SYSPATHFILE)