dal@midgard.Midgard.MN.ORG (Dale Schumacher) (01/18/89)
In article <10354@well.UUCP> Jef Poskanzer <jef@rtsg.ee.lbl.gov> writes: |I get a lot of mail about my portable bitmap toolkit. I mean a *lot* |of mail - I'm approaching 1000 messages. A certain percentage of the |mail has always asked how come the package barfs when fed a color |image. Now, I named the package specifically to avoid this class of |questions. I thought *everyone* knew that a bitmap is one bit deep. |Apparently not. [...rest of article deleted...] I took a good look at the PBM (Portable Bitmap) toolkit code that was posted recently in comp.source.misc (I think) by Mr. Poskanzer. There is quite a bit of useful code in that package. However, my first reaction was "This is great, and very portable, but it only handles 1-bit deep images (also know as bitmaps)". Being of the hacker mentality, I set out to rectify this situation, and in the process located several problems with portability in the original routines. At this point I have an entirely rewritten set of routines that handles an image file format that I'm calling PXM (Portable Pixmap), which is a superset of PBMs. PXM format stores images in one of 4 types, Monochrome Bitmaps (1 bpp), Greyscale Pixmaps (2-8 bpp), Colormapped Images (1-16 bpp, w/ 24-bit RGB colormap), or Full Color Images (24-bit RGB). Each of these image types can be stored using one of 3 storage methods, ASCII (an ASCII 1-bit image is the same as an ASCII PBM), Binary (8-bit data stream), or Binary Run-Length Encoded (8-bit data stream with RLE compression). I should mention that my RLE is *NOT* compatible with compressed PBMs. There are 4 classes of code that will be included in the PXM package. First, there is the library, a collection of C functions and a header file for routines which read/write/manage images in PXM format. The source for this part of the package is quite small (~25K) and could easily be posted to this newsgroup. Secondly, there are import/export programs which convert between PXM format and other image file formats. Third, there are system independent image processing utilities that work on PXM files, and finally, utilities (such as histograms and PXM display programs) which must be written specifically for each machine. Only the RLE code remains to be done for the library to be ready. Would it be appropriate to post it here? Only a few of the import/export programs are ready (the ones I needed, some of which were not in the PBM package), though it should be fairly easy to convert the PBM code to use the PXM library. Most of my effort is going into the generic image processing programs, many of which were not in the PBM package. There is Floyd-Steinberg dithering, generalized convolution, input/output function transformation (which can do gamma correction, positive/negative inversion, contrast enhancements, quantization, and more), and I'm hoping to have 2-d FFT processing soon. The system dependent programs are a bit of a problem. A good histogram display is needed to be able to use input/output transformation effectively, as well as an interactive graphical curve creation program, but such programs are difficult, or impossible, to write machine independently. Should machine dependent versions be posted as a basis for porting? At this point my plan is to post just the library routines here, and later to post the entire package to comp.sources.misc. Hopefully all you other graphics hackers will take the PXM routines and use them to implement your latest and greatest image processing algorithms so we can all see how well they work. PS. Jef, I tried to send you mail but it bounced, please try to reach me <dal@syntel.UUCP>, <bungia!midgard!syntel!dal> or <umn-cs!cctb!syntel!dal>
pokey@well.UUCP (Jef Poskanzer) (01/19/89)
In the referenced message, dal@syntel.UUCP (Dale Schumacher) wrote: } "This is great, and very portable, but it only handles 1-bit deep }images (also know as bitmaps)". Being of the hacker mentality, I set }out to rectify this situation, and in the process located several problems }with portability in the original routines. At this point I have an }entirely rewritten set of routines that handles an image file format }that I'm calling PXM (Portable Pixmap), which is a superset of PBMs. Actually, I mentioned a while back that I was considering doing this very thing. (Article <6377@well.UUCP> of 26 Jun 88, in this newsgroup, titled "Upgrade PBM to PGM or PPM: opinions wanted.") I got a few responses, mostly pointing out that the Utah and IM Raster Toolkits already did what I was proposing to do. This I already knew (but needed to be reminded of), and is the main reason that PBM restricts itself to black and white: the operations you typically perform on black and white images are somewhat different from those for grayscale or color images. There was a niche unfilled, and I filled it. So, my opinion then and now is that extending PBM to gray and color is not a particularly great idea. Even so, I must admit that I have done it too, because like Dale I am of the hacker mentality. I just couldn't resist. There was some color hacking I wanted to do, so rather than bringing up and learning Utah or IM I just rolled my own. It was only a few days work, and in the process I learned more about what I really wanted to do with the color images. I don't feel like releasing this new stuff (yet), but if Dale releases his I'm sure I'll steal code from it! And the portability enhancements mentioned are, of course, welcome. }PS. Jef, I tried to send you mail but it bounced, please try to reach me }<dal@syntel.UUCP>, <bungia!midgard!syntel!dal> or <umn-cs!cctb!syntel!dal> I have no idea how to get to any of those addresses, sorry. --- Jef Jef Poskanzer jef@rtsg.ee.lbl.gov ...well!pokey Yow! Are we interfacing yet?
dal@midgard.Midgard.MN.ORG (Dale Schumacher) (01/26/89)
Well, I had some last minute trouble with the compression code, but everything appears to be working now, so here (for your amusement :-) is the PXM library. Feedback to: <dal@syntel.UUCP> or <bungia.mn.org!midgard!syntel!dal> #----------------------------------cut here----------------------------------- #! /bin/sh # # This is a "shar" archive; to extract files from it, type the command # "sh sharfile" or "ksh sharfile". The "csh" shell will NOT work to extract # files. # # Wrapped by midgard!dal on Thu Jan 26 00:53:30 CST 1989. # # The contents of this archive are: # # -rw-r--r-- 1 dal users 1658 Jan 26 00:39 libpxm1.c # -rw-r--r-- 1 dal users 7391 Jan 26 00:41 libpxm2.c # -rw-r--r-- 1 dal users 7743 Jan 26 00:43 libpxm3.c # -rw-r--r-- 1 dal users 5280 Jan 26 00:45 libpxm6.c # -rw-r--r-- 1 dal users 12169 Jan 26 00:49 pxm.doc # -rw-r--r-- 1 dal users 3390 Jan 26 00:46 pxm.h # if test -f "pxm.doc"; then echo 'shar: will not overwrite "'pxm.doc'"' else echo 'shar: extracting "'pxm.doc'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "pxm.doc" X X Portable Pixmap (PXM) Image File Format X by Dale Schumacher X X X0. INTRODUCTION X In early December of 1988, Jef Poskanzer released the "Portable X Bitmap" source code to the comp.sources.misc newsgroup on Usenet. X This was a very useful format for exchange of images between X nearly any systems. Unfortunately, the format was limited to X 1-bit deep pixmaps (bitmaps) and thus only represented monochrome X on/off images. I've attempted to extend this concept to handle X greyscale images (up to 8-bits/pixel) and color images, both X colormapped and 24-bit RGB "true color". X X1. LIBRARY X The pxm library contains a core set of functions for manipulating X images in the pxm format. Use of these functions makes expression X of image manipulation algorithms much cleaner and simpler. The X storage mechanics are hidden in the library routines, which give X the image processing programs an idealized pixel-by-pixel, X scan-line-at-a-time or whole-image model for accessing images in X a variety of storage formats. The pbm library, from which the X pxm concepts are derived, had only to deal with images of different X dimensions, since all pbm's where simple bitmaps. The pxm library X handles 4 basic image types and 3 storage techniques in an X orthogonal way. As you will see, the original pbm is still handled X (though not the "compressed pbm") by the new pxm library, giving X a smooth upgrade path. X X 1.1 IMAGE TYPES. The 4 basic image types are monochrome (bitmaps), X greyscale, colormapped and truecolor. The monochrome type is a X simple bitmap, like the pbm format. One bit is allocated for each X pixel in the image. The greyscale format has the additional X dimension of "depth" in bits, with a maximum of 8. This allows X up to 256 greyscales, which is quite sufficient. The colormapped X format also has a "depth" dimension, allowing up to 16 bits per X pixel (which should be plenty), and the colormap gives 24-bit X RGB values for each of the colormap entries. The size of the X colormap is determined strictly by the depth of the image. The X final format, truecolor, has a fixed depth of 24 bits/pixel, since X each pixel in represented by a direct 24-bit RGB value. These X formats should cover any 2-d image with no loss of information. X X 1.2 STORAGE METHODS. The 3 storage methods are text, binary and X rle. The text method represents each pixel with an ascii printed X hexadecimal value. For all image types except monochrome, the X values MUST be whitespace separated, since they aren't known to X be exactly one digit. As with pbm's, the output is limited to X no more than 70 characters per line of text. The binary method X stores each pixel as a series of bytes (MSB to LSB). The bits X from consecutive pixels are not packed and the number of bytes X per pixel is strictly a function of the bits per pixel. The file X is read/written a byte at a time to avoid byte ordering problems X between machines. The rle method is also a binary method, ie. the X resulting file may contain non-printable characters. This method X first packs the bits of each pixel into consecutive bytes (msb to X lsb) and then encodes "runs" in the byte stream as a means of X compression. X X 1.3 THE PX_DEF STRUCTURE. Pictures attributes are stored in the X PX_DEF structure and passed to almost all pxm library functions. X This structure helps make the different picture types and storage X methods transparent to the application. The structure contains X a file pointer to the open file corresponding to the pixmap (unlike X the pbm functions, images are not always read entirely into memory X before processing), picture type/storage method, width, height, X depth, a colormap if needed, and various other precalculated values X and status variables. If you're curious, look at the actual X declaration in "pxm.h". X X 1.4 STORAGE ALLOCATION. In order to reduce the amount of memory X needed to process an image, the pxm routines don't load the image X into memory when it is opened. Various parts of the image structure X need to be allocated dynamically during processing. These functions X provide this allocation and include code to check for errors and X zero allocated storage (to simplify their use). X X 1.4.1 PX_BYTE *px_alloc(int size) X Allocate size byte of storage and zero fill. Like all X of the pxm allocation routines, if the allocation fails X the program is aborted with an error message, thus if X the function returns you are assured of having storage. X X 1.4.2 PX_BYTE *px_rowalloc(int width, int psize) X Allocate a row, width pixels wide, with psize bytes per X pixel. The bytes/pixel value is stored in the PX_DEF X structure px_psize field. X X 1.4.3 PX_BYTE **px_arrayalloc(int width, int height, int psize) X Allocate an image array of width by height pixels with X psize bytes per pixel. This can take a considerable X amount of memory and should only be used if the processing X algorithm requires more than a few scanlines at a time. X X 1.4.4 rgb *px_mapalloc(int colors) X Allocate a colormap with colors entries. The number of X colors is stored in the px_colors field of the PX_DEF. X X 1.5 IMAGE READING. Images may be process a single pixel at a time, X a few scanlines at a time, or all at once. The read functions X are used to open and incrementally read an image file. X X 1.5.1 PX_DEF *px_ropen(char *filename) X Open a picture file and load header information. This X function returns a pointer to a dynamically allocated X PX_DEF structure describing the image. Any errors X cause an appropriate error message and terminate the X program. X X 1.5.2 long px_rpixel(PX_DEF *px) X Read the next pixel from a picture. The pixel value is X always returned as a long value since it may be up to X 24 bits. The value range of the pixel is dependent on X the image type and number of bits per pixel. If you X need the raw pixel values (color index, for example) X rather than the ideal colors (explained in 1.7) you X should use this function. Otherwise the other functions X are much more efficient. X X 1.5.3 PX_BYTE *px_rrow(PX_DEF *px, PX_BYTE *rowbuf) X Read the next row of pixels from a picture into rowbuf. X The rowbuf is assumed to be the proper size (allocated by X px_rowalloc()). The rowbuf pointer is returned. X X 1.5.4 PX_BYTE **px_readpxm(PX_DEF *px) X Read an entire picture at once. This must be the first X (and only) read call after the picture is opened. The X pixel array is allocated automatically and becomes the X return value. X X 1.6 IMAGE WRITING. X X 1.6.1 PX_DEF *px_wopen(char *filename, int type, X int width, int height, int depth, rgb *colormap) X Open a picture file and write header information. This X function returns a pointer to a dynamically allocated X PX_DEF structure describing the image. The type value X is on of the picture type values PXT_BIT (monochrome X bitmap), PXT_PIX (greyscale pixmap), PXT_MAP (colormapped), X PXT_RGB (truecolor), logically ORed with one of the X storage methods PXT_TXT (ascii text), PXT_BIN (binary), X PXT_RLE (run-length encoded). The colormap value is X either NULL if there is no colormap, or a pointer to X an already allocated colormap. Any errors cause an X appropriate error message and terminate the program. X X 1.6.2 long px_wpixel(PX_DEF *px, long value) X Write the next pixel to a picture. The pixel value is X always a long, but only px_psize bytes will be stored X in the file. The value range of the pixel is dependent X on the image type and number of bits per pixel. If you X need to write raw pixel values (color index, for example) X rather than the ideal colors (explained in 1.7) you X should use this function. Otherwise the other functions X are much more efficient. X X 1.6.3 PX_BYTE *px_wrow(PX_DEF *px, PX_BYTE *rowbuf) X Write the next row of pixels to a picture from rowbuf. X The rowbuf is assumed to be the proper size (allocated by X px_rowalloc()). The rowbuf pointer is returned. X X 1.6.4 PX_BYTE **px_writepxm(PX_DEF *px, PX_BYTE **pixels) X Write an entire picture at once. This must be the first X (and only) write call after the picture is opened. The X pixel array must already exist and becomes the return value. X NOTE: The pixel array is NOT a simple rectangular array X of bytes. Please use px_arrayalloc() to allocate the array, X or use the array returned by px_readpxm(). X X 1.7 IDEAL PIXELS. In order to ease generalization of image X processing algorithms, the pxm library provides a set of routines X for dealing with "ideal" pixels. Regardless of which picture X type and storage method is used, these routines retrieve the X 8-bit greyscale or 24-bit color value of a pixel (depending on X which function you call). These routines are intended to be the X primary interface to the pixmap. They read/write pixels within X a row array, since there is nearly always enough memory for at X least one scanline of even a 24-bit color image. Conversion to X and from the ideal pixel form is handled internally by these X routines. Bitmaps return values of black (all zeros) or white X (all ones), note that to remain compatible with pbms, 'white' X is represented by '0' in the file, and 'black' by '1', but is X reversed when read as an ideal pixel. When writing bitmaps, any X non-zero pixel is 'white' and only all-zeros becomes 'black'. X For greyscale pixmaps, an 8-bit greyscale value is created, X either by scaling the given greyscale up to 8-bits, or by calc- X culating the luminence of the given color with the formula: X Luminence = 29.9% Red + 58.7% Green + 11.4% Blue. This is the X NTSC Y-component (luminence) of a Y-I-Q color value. Pixel X values for a colormapped image are looked up in the colormap X and then returned as RGB or computed greyscale. Truecolor is X handled similarly using the direct color. If RGB is requested X from a greyscale or monochrome image, the grey value is scaled X to 8-bits and assigned equally to each gun on the assumption X that equal portions of each gun gives a scale of neutral greys. X Several other pixel utility functions are also provided. X X 1.7.1 rgb px_rrgb(PX_DEF *px, PX_BYTE *rowbuf, int x) X Return the 24-bit RGB color value of the x'th pixel in X the rowbuf scanline. The PX_DEF px must be an open pixmap X descriptor. X X 1.7.2 rgb px_rgrey(PX_DEF *px, PX_BYTE *rowbuf, int x) X Return the 8-bit greyscale value of the x'th pixel in the X rowbuf scanline. The PX_DEF px must be an open pixmap X descriptor. X X 1.7.3 rgb px_wrgb(PX_DEF *px, PX_BYTE *rowbuf, int x, rgb value) X Return the 24-bit RGB color value of the x'th pixel in X the rowbuf scanline. The PX_DEF px must be an open pixmap X descriptor. X X 1.7.4 rgb px_wgrey(PX_DEF *px, PX_BYTE *rowbuf, int x, int value) X Return the 8-bit greyscale value of the x'th pixel in the X rowbuf scanline. The PX_DEF px must be an open pixmap X descriptor. NOTE: There is no transformation for greyscale X to colormapped output. The px_wrgb() function must be X used instead. X X 1.7.5 void px_close(PX_DEF *px) X Close the image and free dynamically allocated memory. The X pixel array, if any, is NOT free'd by this function since X there is no pointer to it in the PX_DEF structure. X X 1.7.6 int px_rgb2grey(rgb color) X Return the 8-bit greyscale luminence value of the given X 24-bit RGB color. X X 1.7.7 void px_splitrgb(rgb color, int *R, int *G, int *B) X Split a 24-bit RGB color int it's component parts. The X results are stored in the locations pointed to by R, G X and B. If a pointer in NULL, the corresponding component X is not stored. X X 1.7.8 rgb px_mergergb(rgb *color, int R, int G, int B) X Merge R, G and B components into a 24-bit RGB color. The X result is stored in the locations pointed to by color, if X the pointer is not NULL, and also becomes the return value. X X 1.7.9 int px_makeN(int value, int srcbits, int dstbits) X Normalize an int value with srcbits significant bits to X dstbits significant bits. This is accomplished by shifting X if the source has more than dstbits bits and replication X of the bit pattern (linear interpolation) if the source has X fewer than dstbits bits. X X[more sections will follow later explaining image processing programs, etc.] @FOOBIE@BLETCH@ if test `wc -l < "pxm.doc" | sed -e 's/^ *//'` != 248; then echo 'shar: "'pxm.doc'" unpacked with wrong size!' >&2 fi fi if test -f "pxm.h"; then echo 'shar: will not overwrite "'pxm.h'"' else echo 'shar: extracting "'pxm.h'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "pxm.h" X/* X * pxm.h - header file for libpxm portable pixmap library X * X * Copyright (C) 1988 by Dale Schumacher. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation. This software is provided "as is" without express or X * implied warranty. X * X */ X X#define PX_READMODE "rb" X#define PX_WRITEMODE "wb" X Xtypedef long rgb; /* 24-bit RGB triplet */ Xtypedef unsigned char PX_BYTE; /* 8-bit unsigned */ X X/* X * pixmap type values X */ X#define PXT_BIT 0x01 /* simple bitmap */ X#define PXT_PIX 0x02 /* monochrome pixmap */ X#define PXT_MAP 0x04 /* color-mapped pixmap */ X#define PXT_RGB 0x08 /* RGB true-color pixmap */ X#define PXT_TYP 0x0F /* mask to type info only */ X X#define PXT_TXT 0x10 /* text representation */ X#define PXT_BIN 0x20 /* binary representation */ X#define PXT_RLE 0x40 /* run-length encoded binary */ X#define PXT_STO 0x70 /* mask to storage info only */ X X#define PXT_WRT 0x80 /* pxm open in write mode */ X X/* X * pixmap definition structure X */ Xtypedef struct X { X FILE *px_file; /* file pointer */ X int px_type; /* type of pixmap (PXT_*) */ X int px_width; /* width of pixmap in pixels */ X int px_height; /* height of pixmap in pixels */ X int px_depth; /* bits per pixel */ X int px_colors; /* # of colors/grey levels */ X int px_psize; /* pixel size (in bytes) */ X rgb *px_map; /* colormap pointer */ X int px_state; /* state variable for context changes */ X int px_runlen; /* chars remaining in a run */ X PX_BYTE px_runval; /* char value for the run */ X char *px_data; /* rle compression data pointer */ X int px_nbits; /* bit buffer counter */ X PX_BYTE px_bitbuf; /* bit pack/unpack buffer */ X } X PX_DEF; X X/* X * pixmap ident values (magic numbers) X */ X#define PXm1TXT 'P' /* text representation */ X#define PXm1BIN 'B' /* binary representation */ X#define PXm1RLE 'C' /* run-length encoded binary */ X X#define PXm2BIT '1' /* simple bitmap */ X#define PXm2PIX 'm' /* monochrome pixmap */ X#define PXm2MAP 'x' /* color-mapped pixmap */ X#define PXm2RGB 't' /* RGB true-color pixmap */ X X/* X * Declarations of routines. X */ X X/* LIBPXM1 */ Xextern PX_BYTE *px_alloc(/* size */); Xextern PX_BYTE *px_rowalloc(/* width, psize */); Xextern PX_BYTE **px_arrayalloc(/* width, height, psize */); Xextern rgb *px_mapalloc(/* colors */); X X/* LIBPXM2 */ Xextern PX_DEF *px_ropen(/* filename */); Xextern long px_rpixel(/* px */); Xextern PX_BYTE *px_rrow(/* px, rowbuf */); Xextern PX_BYTE **px_readpxm(/* px */); X X/* LIBPXM3 */ Xextern void px_flush(/* px */); Xextern PX_DEF *px_wopen(/* filename, type, width, height, depth, colormap */); Xextern long px_wpixel(/* px, pixel */); Xextern PX_BYTE *px_wrow(/* px, rowbuf */); Xextern PX_BYTE **px_writepxm(/* px, pixels */); X X/* LIBPXM6 */ Xextern int px_makeN(/* value, srcbits, dstbits */); Xextern void px_splitrgb(/* color, &R, &G, &B */); Xextern rgb px_mergergb(/* &color, R, G, B */); Xextern int px_rgb2grey(/* color */); Xextern rgb px_rrgb(/* px, rowbuf, x */); Xextern int px_rgrey(/* px, rowbuf, x */); Xextern rgb px_wrgb(/* px, rowbuf, x, value */); Xextern int px_wgrey(/* px, rowbuf, x, value */); Xextern void px_close(/* px */); X X/* MACROS */ X#define NEW(t) ((t *) px_alloc(sizeof(t))) @FOOBIE@BLETCH@ if test `wc -l < "pxm.h" | sed -e 's/^ *//'` != 106; then echo 'shar: "'pxm.h'" unpacked with wrong size!' >&2 fi fi if test -f "libpxm1.c"; then echo 'shar: will not overwrite "'libpxm1.c'"' else echo 'shar: extracting "'libpxm1.c'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "libpxm1.c" X/* libpxm1.c - pxm utility library part 1 X** X** Copyright (C) 1988 by Jef Poskanzer. X** Copyright (C) 1988 by Dale Schumacher. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include "pxm.h" X X#define TRACE(x) if(0)/* x */ X#define DEBUG(x) if(0)/* x */ X X X#if 0 /* include this function if it's missing from your library */ Xbzero(p, n) X register PX_BYTE *p; X register int n; X { X while(n--) X *p++ = 0; X } X#endif X X/* X * allocate memory with error checking and zero storage X */ XPX_BYTE * Xpx_alloc(size) X int size; X { X register PX_BYTE *p; X char *malloc(); X X if((p = ((PX_BYTE *) malloc(size))) == NULL) X { X fprintf(stderr, "\nOut of memory!\n"); X exit(1); X } X bzero(p, size); X return(p); X } X X/* X * allocate space for a single row of pixels X */ XPX_BYTE * Xpx_rowalloc(width, psize) X int width, psize; X { X return(px_alloc(width * psize)); X } X X/* X * allocate an array of pointers pointing to rows of pixels storage X */ XPX_BYTE ** Xpx_arrayalloc(width, height, psize) X register int width, height, psize; X { X register PX_BYTE **p, **q; X X q = p = (PX_BYTE **) px_alloc(height * sizeof(PX_BYTE *)); X while(height--) X *q++ = px_alloc(width * psize); X return(p); X } X/* X * allocate storage for a colormap X */ Xrgb * Xpx_mapalloc(colors) X int colors; X { X return((rgb *) px_alloc(colors * sizeof(rgb))); X } @FOOBIE@BLETCH@ if test `wc -l < "libpxm1.c" | sed -e 's/^ *//'` != 82; then echo 'shar: "'libpxm1.c'" unpacked with wrong size!' >&2 fi fi if test -f "libpxm2.c"; then echo 'shar: will not overwrite "'libpxm2.c'"' else echo 'shar: extracting "'libpxm2.c'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "libpxm2.c" X/* libpxm2.c - pxm utility library part 2 X** X** Copyright (C) 1988 by Jef Poskanzer. X** Copyright (C) 1988 by Dale Schumacher. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <ctype.h> X#include <errno.h> X#include "pxm.h" X X#define TRACE(x) if(0)/* x */ X#define DEBUG(x) if(0)/* x */ X X Xstatic int X_getc(f) X FILE *f; X { X register int c; X X errno = 0; X c = getc(f); X if(c == EOF) X { X if(errno) X perror("Read error"); X else X fprintf(stderr, "Premature EOF\n"); X exit(1); X } X return(c); X } X Xstatic int X_nextln(f) X FILE *f; X { X register int c; X X while((c = getc(f)) != '\n') X if(c == EOF) X return(EOF); X return('\n'); X } X Xstatic int X_skipspace(f) X FILE *f; X { X register int c; X X for(;;) X { X c = getc(f); X if(isascii(c) && isspace(c)) X continue; X if(c == '#') /* eat comment */ X { X if(_nextln(f) == EOF) X return(EOF); X } X else X { X /* X * anything other than whitespace or comments causes X * an unget and ends the whitespace skipping loop X */ X ungetc(c, f); X break; X } X } X return(c); X } X Xstatic int X_getbit(f) X FILE *f; X { X register int c; X X _skipspace(f); X c = _getc(f); X if((c == '0') || (c == '1')) X { X return((c == '0') ? 1 : 0); /* '0'=white, '1'=black */ X } X else X { X fprintf(stderr, "Expected '0' or '1', got c=%02x\n", X (c & 0xFF)); X exit(1); X } X } X Xstatic int X_getint(f) X FILE *f; X { X register int c, i; X X c = _skipspace(f); X X if(!isascii(c) || !isdigit(c)) X { X fprintf(stderr, "Expected decimal data, got c=%02x\n", X (c & 0xFF)); X exit(1); X } X i = 0; X while(isdigit(c = _getc(f))) X { X i *= 10; X i += (c - '0'); X } X X ungetc(c, f); /* unget the delimiter */ X return(i); X } X Xstatic long X_getlhex(f) X FILE *f; X { X int c; X long x; X X c = _skipspace(f); X X if(!isascii(c) || !isxdigit(c)) X { X fprintf(stderr, "Expected hexidecimal data, got c=%02x\n", X (c & 0xFF)); X exit(1); X } X x = 0L; X while(isascii(c = getc(f)) && isxdigit(c)) X { X x <<= 4; X if(isdigit(c)) X x |= (c - '0'); X else X x |= (toupper(c) - 'A' + 10); X } X if(c != EOF) X ungetc(c, f); /* unget the delimiter */ X return(x); X } X X#define PXS_HDR 0 X#define PXS_RAW 1 X#define PXS_RUN 2 X#define PX_ISRUN 0x80 X#define PX_EXTND 0x80 X Xstatic PX_BYTE X_getbyte(px) /* run-length decoder */ X register PX_DEF *px; X { X register FILE *f; X register int i, j; X register PX_BYTE b; X X f = px->px_file; X if(px->px_state == PXS_HDR) X { X j = _getc(f); X if(j & PX_ISRUN) X { X px->px_state = PXS_RUN; X if(j == PX_EXTND) X { X i = _getc(f); X px->px_runlen = (i << 8) + _getc(f); X } X else X px->px_runlen = (j & ~PX_ISRUN) + 1; X px->px_runval = (PX_BYTE) _getc(f); X } X else X { X px->px_state = PXS_RAW; X px->px_runlen = j + 1; X } X } X if(px->px_state == PXS_RAW) X b = (PX_BYTE) _getc(f); X else /* PXS_RUN */ X b = px->px_runval; X if(--(px->px_runlen) <= 0) X px->px_state = PXS_HDR; XTRACE(printf("_getbyte: b=%02x state=%d len=%d val=%02x j=%02x\n", X ((int) b), px->px_state, px->px_runlen, ((int) px->px_runval), j)); X return(b); X } X Xstatic long X_getnext(px) /* bit un-packer */ X register PX_DEF *px; X { X register int i; X register long n; X X n = 0L; X i = px->px_depth; X while(i--) X { X n <<= 1; X if(--(px->px_nbits) <= 0) X { X px->px_bitbuf = _getbyte(px); X px->px_nbits = 8; X } X if(px->px_bitbuf & 0x80) X n |= 1; X px->px_bitbuf <<= 1; X } XTRACE(printf("getnext: n=%06lx nbits=%d bitbuf=%02x\n", X n, px->px_nbits, px->px_bitbuf)); X return(n); X } X X/* X * open a pxm file for reading X */ X XPX_DEF * Xpx_ropen(filename) X char *filename; X { X FILE *f; X register PX_DEF *px; X register rgb *cm; X register int m1, m2, t, i, n; X int rw; X X /* Open file */ X if((filename == NULL) /* use standard input */ X || (strcmp(filename, "") == 0) X || (strcmp(filename, "-") == 0)) X { X f = stdin; X#ifdef dLibs X f->_flag |= _IOBIN; /* force binary mode */ X#endif X } X else if((f = fopen(filename, PX_READMODE)) == NULL) X { X fprintf(stderr, "Can't open pxm file '%s'\n", filename); X exit(1); X } X X /* Allocate pixmap definition block */ X px = NEW(PX_DEF); X px->px_file = f; X px->px_state = px->px_runlen = 0; X px->px_runval = 0; X px->px_map = NULL; X px->px_data = NULL; X px->px_nbits = 0; X X /* Check for magic number. */ X m1 = getc(f); X m2 = getc(f); X DEBUG(printf("[px_ropen: magic1=%c magic2=%c]\n", m1, m2)); X t = 0; X if(m1 == PXm1TXT) X t |= PXT_TXT; X else if(m1 == PXm1RLE) X t |= PXT_RLE; X else if(m1 == PXm1BIN) X t |= PXT_BIN; X else X { X fprintf(stderr, "Bad magic number.\n"); X exit(1); X } X if(m2 == PXm2BIT) X t |= PXT_BIT; X else if(m2 == PXm2PIX) X t |= PXT_PIX; X else if(m2 == PXm2MAP) X t |= PXT_MAP; X else if(m2 == PXm2RGB) X t |= PXT_RGB; X else X { X fprintf(stderr, "Bad magic number.\n"); X exit(1); X } X px->px_type = t; X X /* read sizes */ X px->px_width = _getint(f); X px->px_height = _getint(f); X if(t & PXT_BIT) X { X _nextln(f); X px->px_depth = 1; X px->px_colors = 2; X px->px_psize = 1; X } X else if(t & PXT_PIX) X { X i = _getint(f); X _nextln(f); X px->px_depth = i; X px->px_colors = (1 << i); X px->px_psize = 1; X } X else if(t & PXT_MAP) X { X i = _getint(f); X _nextln(f); X px->px_depth = i; X n = (1 << i); X px->px_colors = n; X if(i <= 8) X px->px_psize = 1; X else if(i <= 16) X px->px_psize = 2; X /* allocate and read colormap */ X cm = px_mapalloc(n); X px->px_map = cm; X if(t & PXT_TXT) X { X while(n--) X *cm++ = (rgb) _getlhex(f); X } X else X { X if(fread(cm, sizeof(rgb), n, f) != n) X { X fprintf(stderr, "Error reading colormap\n"); X exit(1); X } X } X } X else if(t & PXT_RGB) X { X _nextln(f); X px->px_depth = 24; X px->px_colors = (1 << 24); X px->px_psize = 3; X } X X DEBUG(printf("[px_ropen: done, px=%p]\n", px)); X return(px); X } X Xlong Xpx_rpixel(px) X register PX_DEF *px; X { X register int i, size; X register long m, n = 0L; X register int t; X FILE *f; X X f = px->px_file; X t = px->px_type; X if(t & PXT_RLE) X n = _getnext(px); X else if(t & PXT_BIT) X n = (long) _getbit(f); X else if(t & PXT_TXT) X n = _getlhex(f); X else /* PXT_BIN */ X { X for(size = px->px_psize, i = 0; i < size; ++i) X n = (n << 8) | _getc(f); X } X return(n); X } X XPX_BYTE * Xpx_rrow(px, pbuf) X register PX_DEF *px; X register PX_BYTE *pbuf; X { X register PX_BYTE *p; X register int k, step, cols; X register long n, m; X X step = px->px_psize; X cols = px->px_width; X if(px->px_type & (PXT_BIT | PXT_TXT | PXT_RLE)) X { X TRACE(printf("[px_rrow: loop read]\n")); X m = (0x0000FFFFL >> (16 - px->px_depth)); X for(p = pbuf; cols--; p += step) X { X n = px_rpixel(px) & m; X for(k = step; (k--); n >>= 8) X p[k] = n & 0xFF; X } X } X else X { X TRACE(printf("[px_rrow: block read (%dx%d)]\n", X cols, step)); X if(fread(pbuf, step, cols, px->px_file) != cols) X { X fprintf(stderr, "Error reading image\n"); X exit(1); X } X } X return(pbuf); X } X XPX_BYTE ** Xpx_readpxm(px) X register PX_DEF *px; X { X register PX_BYTE **pixels; X register int n, m; X X /* Read image */ X pixels = px_arrayalloc(px->px_width, px->px_height, px->px_psize); X for(n = 0, m = px->px_height; n < m; ++n) X px_rrow(px, pixels[n]); X return(pixels); X } @FOOBIE@BLETCH@ if test `wc -l < "libpxm2.c" | sed -e 's/^ *//'` != 430; then echo 'shar: "'libpxm2.c'" unpacked with wrong size!' >&2 fi fi if test -f "libpxm3.c"; then echo 'shar: will not overwrite "'libpxm3.c'"' else echo 'shar: extracting "'libpxm3.c'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "libpxm3.c" X/* libpxm3.c - pxm utility library part 3 X** X** Copyright (C) 1988 by Jef Poskanzer. X** Copyright (C) 1988 by Dale Schumacher. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <errno.h> X#include "pxm.h" X X#define TRACE(x) if(0)/* x */ X#define DEBUG(x) if(0)/* x */ X X Xstatic void X_outerr() X { X perror("Write error"); X exit(1); X } X Xstatic int X_putbit(i, f) X int i; X FILE *f; X { X errno = 0; X putc((i ? '0' : '1'), f); /* '0'=white, '1'=black */ X if(errno) X _outerr(); X return(i); X } X Xstatic int X_putint(i, f) X int i; X FILE *f; X { X errno = 0; X fprintf(f, "%d ", i); X if(errno) X _outerr(); X return(i); X } X Xstatic long X_putlhex(x, f) X long x; X FILE *f; X { X errno = 0; X fprintf(f, "%lx ", x); X if(errno) X _outerr(); X return(x); X } X X#define PX_L0 3 /* minumum run */ X#define PX_L1 128 /* 2^7 */ X#define PX_L2 32767 /* 2^15 - 1 */ X#define PX_ISRUN 0x80 X#define PX_EXTND 0x80 X Xstatic PX_BYTE X_putbyte(b, px) /* byte-stream run-length encoder */ X PX_BYTE b; X PX_DEF *px; X { X /* X * px_state is used to keep track of the number of X * consecutive identical pixel values X */ X register FILE *f; X register int i, j; X register PX_BYTE *rledata; X X f = px->px_file; X i = px->px_runlen; X j = (px->px_runval == b); X rledata = px->px_data; XTRACE(printf("_putbyte: b=%02x state=%d len=%d val=%02x %c\n", X ((int) b), px->px_state, i, ((int) px->px_runval), (j ? '+' : '-'))); X if(px->px_state == PX_ISRUN) X { X if(!j || (i >= PX_L2)) X { X px_flush(px); X px->px_state = 1; X px->px_runval = b; X rledata[0] = b; X } X } X else X { X if(i >= PX_L1) X { X px_flush(px); X px->px_runval = b; X } X if(j) X { X if(++(px->px_state) >= PX_L0) X { X px->px_runlen = (i - (PX_L0 - 1)); X px_flush(px); X px->px_runlen = PX_L0; X px->px_state = PX_ISRUN; X return(b); X } X } X else X { X px->px_state = 1; X px->px_runval = b; X } X rledata[px->px_runlen] = b; X } X ++(px->px_runlen); X return(b); X } X Xstatic long X_putnext(n, px) /* bit packer */ X register long n; X register PX_DEF *px; X { X register int i; X register long m; X XTRACE(printf("putnext: n=%06lx nbits=%d bitbuf=%02x\n", X n, px->px_nbits, px->px_bitbuf)); X i = px->px_depth; X m = 1L << (i - 1); X while(i--) X { X px->px_bitbuf <<= 1; X if(m & n) X px->px_bitbuf |= 1; X if(++(px->px_nbits) >= 8) X { X px->px_nbits = 0; X _putbyte(px->px_bitbuf, px); X } X n <<= 1; X } X } X Xvoid Xpx_flush(px) X register PX_DEF *px; X { X register FILE *f; X register int i, j, t; X register PX_BYTE b; X X t = px->px_type; X if((t & PXT_WRT) && ((t & PXT_STO) == PXT_RLE)) X { X if(px->px_nbits > 0) X { X px->px_bitbuf <<= (8 - px->px_nbits); X px->px_nbits = 0; X _putbyte(px->px_bitbuf, px); X } X f = px->px_file; X i = px->px_runlen; X if(i <= 0) X return; X errno = 0; X if(px->px_state == PX_ISRUN) X { X if(i <= PX_L1) X putc((PX_ISRUN | ((char) (i - 1))), f); X else X { X putc(((char) PX_EXTND), f); X putc(((char) ((i >> 8) & 0x7F)), f); X putc(((char) (i & 0xFF)), f); X } XTRACE(printf("px_flush: run of %d (pixel=%02x)\n", i, ((int) px->px_runval))); X putc(((char) px->px_runval), f); X } X else X { X putc(((char) (i - 1)), f); XTRACE(printf("px_flush: %d unique\n", i)); X fwrite(px->px_data, 1, i, f); X } X if(errno) X _outerr(); X px->px_runlen = 0; X px->px_state = 0; X } X } X X/* X * open a pxm file for writing X */ XPX_DEF * Xpx_wopen(filename, t, w, h, d, cm) X char *filename; X char t; X int w, h, d; X register rgb *cm; X { X FILE *f; X register PX_DEF *px; X register int m1, m2, i, n; X X /* Open file */ X if((filename == NULL) /* use standard output */ X || (strcmp(filename, "") == 0) X || (strcmp(filename, "-") == 0)) X { X f = stdout; X#ifdef dLibs X if((t & PXT_TXT) == 0) X f->_flag |= _IOBIN; /* force binary mode */ X#endif X } X else if((f = fopen(filename, PX_WRITEMODE)) == NULL) X { X fprintf(stderr, "Can't open pxm file '%s'\n", filename); X exit(1); X } X X /* Allocate pixmap definition block */ X px = NEW(PX_DEF); X px->px_file = f; X px->px_state = px->px_runlen = 0; X px->px_runval = 0; X px->px_data = NULL; X px->px_nbits = 0; X X /* Write magic number. */ X switch(t & PXT_STO) X { X case PXT_TXT: m1 = PXm1TXT; break; X case PXT_RLE: m1 = PXm1RLE; break; X case PXT_BIN: m1 = PXm1BIN; break; X default: X fprintf(stderr, "Bad picture type %02x\n", t); X exit(1); X } X switch(t & PXT_TYP) X { X case PXT_BIT: m2 = PXm2BIT; break; X case PXT_PIX: m2 = PXm2PIX; break; X case PXT_MAP: m2 = PXm2MAP; break; X case PXT_RGB: m2 = PXm2RGB; break; X default: X fprintf(stderr, "Bad picture type %02x\n", t); X exit(1); X } X DEBUG(fprintf(stderr, "[px_wopen: magic1=%c magic2=%c]\n", m1, m2)); X putc(m1, f); X putc(m2, f); X px->px_type = (t | PXT_WRT); X fprintf(f, " # %s\n", filename); X X /* write sizes */ X px->px_width = _putint(w, f); X px->px_height = _putint(h, f); X if(t & PXT_BIT) X { X fprintf(f, " # width height\n"); X px->px_depth = 1; X px->px_colors = 2; X px->px_psize = 1; X } X else if(t & PXT_PIX) X { X i = _putint(d, f); X fprintf(f, " # width height depth\n"); X px->px_depth = i; X px->px_colors = (1 << i); X px->px_psize = 1; X } X else if(t & PXT_MAP) X { X i = _putint(d, f); X fprintf(f, " # width height depth\n"); X px->px_depth = i; X n = (1 << i); X px->px_colors = n; X if(i <= 8) X px->px_psize = 1; X else if(i <= 16) X px->px_psize = 2; X /* write colormap */ X px->px_map = cm; X if(t & PXT_TXT) X { X fprintf(f, "## colormap\n"); X while(n--) X _putlhex(((long) *cm++), f); X } X else X { X if(fwrite(cm, sizeof(rgb), n, f) != n) X _outerr(); X } X } X else if(t & PXT_RGB) X { X fprintf(f, " # width height\n"); X px->px_depth = 24; X px->px_colors = (1 << 24); X px->px_psize = 3; X } X X if(t & PXT_TXT) X fprintf(f, "## pixel data\n"); X X if(t & PXT_RLE) X px->px_data = px_alloc(PX_L1); X X DEBUG(fprintf(stderr, "[px_wopen: done]\n")); X return(px); X } X Xlong Xpx_wpixel(px, pixel) X register PX_DEF *px; X long pixel; X { X register int i, size; X register long n; X register int t; X FILE *f; X PX_BYTE pixdata[4]; X X for(n = pixel, i = px->px_psize; i--; n >>= 8) X pixdata[i] = n & 0xFF; X n = pixel; X f = px->px_file; X t = px->px_type; X if(t & PXT_RLE) X _putnext(n, px); X else if(t & PXT_BIT) X { X if(px->px_state >= 64) X { X putc('\n', px->px_file); X px->px_state = 0; X } X _putbit(((int) n), f); X ++px->px_state; X } X else if(t & PXT_TXT) X { X if(px->px_state > 60) X { X putc('\n', px->px_file); X px->px_state = 0; X } X _putlhex(n, f); X px->px_state += 7; X } X else /* PXT_BIN */ X { X for(size = px->px_psize, i = 0; i < size; ++i) X putc(pixdata[i], f); X } X return(n); X } X XPX_BYTE * Xpx_wrow(px, pbuf) X register PX_DEF *px; X register PX_BYTE *pbuf; X { X register PX_BYTE *p; X register int k, step, cols; X register long n; X X step = px->px_psize; X cols = px->px_width; X if(px->px_type & (PXT_BIT | PXT_TXT | PXT_RLE)) X { XTRACE(printf("px_wrow: (BIT | TXT | RLE) loop\n")); X for(p = pbuf; cols--; p += step) X { X for(k = step, n = 0L; (k--); ) X n = (n << 8) | p[k]; X px_wpixel(px, n); X } X if(px->px_type & PXT_TXT) X { X putc('\n', px->px_file); X px->px_state = 0; X } X } X else X { X if(fwrite(pbuf, step, cols, px->px_file) != cols) X _outerr(); X } X return(pbuf); X } X XPX_BYTE ** Xpx_writepxm(px, pixels) X register PX_DEF *px; X register PX_BYTE **pixels; X { X register int n, m; X X /* Write image */ X for(n = 0, m = px->px_height; n < m; ++n) X px_wrow(px, pixels[n]); X return(pixels); X } @FOOBIE@BLETCH@ if test `wc -l < "libpxm3.c" | sed -e 's/^ *//'` != 420; then echo 'shar: "'libpxm3.c'" unpacked with wrong size!' >&2 fi fi if test -f "libpxm6.c"; then echo 'shar: will not overwrite "'libpxm6.c'"' else echo 'shar: extracting "'libpxm6.c'"' sed -e 's/^X//' << \@FOOBIE@BLETCH@ > "libpxm6.c" X/* libpxm6.c - pxm utility library part X** X** Copyright (C) 1988 by Dale Schumacher. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <errno.h> X#include "pxm.h" X X#define TRACE(x) if(0)/* x */ X#define DEBUG(x) if(0)/* x */ X X X/* X * normalize a [1..31]-bit value to N-bits X */ Xint Xpx_makeN(value, srcbits, dstbits) X register int value, srcbits, dstbits; X { X register int n; X X if(srcbits != dstbits) X { X if(srcbits > dstbits) X value >>= srcbits - dstbits; X else X { X n = ((long) value); X while(srcbits < dstbits) X { X n |= n << srcbits; X srcbits <<= 1; X } X n >>= (srcbits - dstbits); X value = ((int) n); X } X } X return(value); X } X X/* X * split a 24-bit RGB triplet into 8-bit components X */ Xvoid Xpx_splitrgb(color, R, G, B) X register rgb color; X int *R, *G, *B; X { X TRACE(fprintf(stderr, "[px_splitrgb: color=%06lx]\n", color)); X if(B) X *B = (color & 0xFF); X color >>= 8; X if(G) X *G = (color & 0xFF); X color >>= 8; X if(R) X *R = (color & 0xFF); X } X X/* X * merge 8-bit components into a 24-bit RGB triplet X */ Xrgb Xpx_mergergb(color, R, G, B) X register rgb *color; X int R, G, B; X { X register rgb n; X X n = (R << 16) | (G << 8) | B; X if(color) X *color = n; X TRACE(fprintf(stderr, "[px_mergergb: color=%06lx]\n", n)); X return(n); X } X X/* X * return the 24-bit RGB color value for a given pixel X */ Xrgb Xpx_rrgb(px, row, x) X register PX_DEF *px; X register PX_BYTE *row; X int x; X { X register int i; X register rgb n = 0L; X X i = px->px_psize; X row += (x * i); X while(i--) X n = (n << 8) | (*row++); X switch(px->px_type & PXT_TYP) X { X case PXT_BIT: X n = (n ? 0xFFFFFF : 0x000000); X break; X case PXT_PIX: X n = (rgb) px_makeN((int) n, px->px_depth, 8); X n |= (n << 16) | (n << 8); X break; X case PXT_MAP: X n = px->px_map[n]; X break; X case PXT_RGB: X /* already HAVE rgb */ X break; X default: X fprintf(stderr, "px: bad picture type\n"); X exit(1); X } X return(n); X } X X/* X * convert 24-bit RGB color value to [0..255] grey-scale value X */ Xint Xpx_rgb2grey(color) X rgb color; X { X int R, G, B; X register int grey; X X px_splitrgb(color, &R, &G, &B); X /* X * The following formula gives the following color weighting X * Red 30.1%, Green 58.6%, Blue 11.3% X * The optimal values are: X * Red 29.9%, Green 58.7%, Blue 11.4% X */ X grey = (((77 * R) + (150 * G) + (29 * B)) / 256) & 0xFF; X return(grey); X } X X/* X * return the [0..255] grey-scale value for a given pixel X */ Xint Xpx_rgrey(px, row, x) X register PX_DEF *px; X register PX_BYTE *row; X int x; X { X register int g = 0, i; X register rgb n = 0L; X X i = px->px_psize; X row += (x * i); X while(i--) X n = (n << 8) | (*row++); X TRACE(printf("[px_rgrey: n=0x%06lx]\n", n)); X switch(px->px_type & PXT_TYP) X { X case PXT_BIT: X g = (n ? 0xFF : 0x00); X break; X case PXT_PIX: X g = px_makeN((int) n, px->px_depth, 8); X break; X case PXT_MAP: X n = px->px_map[n]; X /* got RGB now, fall thru... */ X case PXT_RGB: X g = px_rgb2grey(n); X break; X default: X fprintf(stderr, "px: bad picture type\n"); X exit(1); X } X return(g); X } X X/* X * store a 24-bit RGB color value in a given pixel X */ Xrgb Xpx_wrgb(px, row, x, value) X register PX_DEF *px; X register PX_BYTE *row; X int x; X rgb value; X { X register int i; X register rgb *cm; X register long n; X X n = value; X row += (x * px->px_psize); X switch(px->px_type & PXT_TYP) X { X case PXT_BIT: X n = (n ? 1L : 0L); X break; X case PXT_PIX: X n = (rgb) px_rgb2grey(n); X break; X case PXT_MAP: X cm = px->px_map; X i = px->px_colors; X while(i--) X if(cm[i] == n) X break; X if(n < 0) X { X fprintf(stderr, X "color %06lx not in colormap\n", X n); X exit(1); X } X n = px->px_map[n]; X break; X case PXT_RGB: X /* already HAVE rgb */ X break; X default: X fprintf(stderr, "px: bad picture type\n"); X exit(1); X } X for(i = px->px_psize; i--; n >>= 8) X row[i] = ((PX_BYTE) (n & 0xFF)); X return(value); X } X X/* X * store a [0..255] grey-scale value in a given pixel X */ Xint Xpx_wgrey(px, row, x, value) X register PX_DEF *px; X register PX_BYTE *row; X int x; X int value; X { X register int g; X register int i; X register rgb n = 0L; X X g = value; X row += (x * px->px_psize); X switch(px->px_type & PXT_TYP) X { X case PXT_BIT: X n = (g ? 1L : 0L); X break; X case PXT_PIX: X n = ((rgb) (g >>= (8 - px->px_depth))); X break; X case PXT_MAP: X fprintf(stderr, X "use px_wrgb() for colormapped output\n", n); X exit(1); X case PXT_RGB: X n = ((rgb) g); X n |= (n << 16) | (n << 8); X break; X default: X fprintf(stderr, "px: bad picture type\n"); X exit(1); X } X for(i = px->px_psize; i--; n >>= 8) X row[i] = ((PX_BYTE) (n & 0xFF)); X return(value); X } X X/* X * close the file associated with a given pixmap X */ Xvoid Xpx_close(px) X register PX_DEF *px; X { X px_flush(px); X errno = 0; X fclose(px->px_file); X if(errno) X { X perror("Error closing pixmap"); X exit(1); X } X if(px->px_map) X free(px->px_map); X if(px->px_data) X free(px->px_data); X free(px); X } @FOOBIE@BLETCH@ if test `wc -l < "libpxm6.c" | sed -e 's/^ *//'` != 294; then echo 'shar: "'libpxm6.c'" unpacked with wrong size!' >&2 fi fi # End of shell archive.
barad@bourbon.ee.tulane.edu (Herb Barad) (01/27/89)
In article <10403@well.UUCP> Jef Poskanzer <jef@rtsg.ee.lbl.gov> writes: >I don't feel like releasing this new stuff (yet), but if Dale releases >his I'm sure I'll steal code from it! And the portability enhancements >mentioned are, of course, welcome. Well, I hope that one of you releases it. I think that people would be very interested in this stuff. Please consider it. -- Herb Barad [Signal & Image Processing Laboratory] [Electrical Engineering Dept. - Tulane Univ.] INTERNET: barad@ee.tulane.edu USENET: barad@bourbon.uucp