jimf@saber.com (09/28/90)
Submitted-by: saber.com!jimf@saber.com Posting-number: Volume 9, Issue 52 Archive-name: xloadimage/part05 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 5 (of 9)." # Contents: misc.c path.c pbm.c reduce.c root.c rotate.c value.c # Wrapped by jimf@armory on Tue Sep 25 19:37:41 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'misc.c'\" else echo shar: Extracting \"'misc.c'\" \(6442 characters\) sed "s/^X//" >'misc.c' <<'END_OF_FILE' X/* misc.c: X * X * miscellaneous funcs X * X * jim frost 10.05.89 X * X * Copyright 1989, 1990 Jim Frost. See included file "copyright.h" for X * complete copyright information. X */ X X#include "copyright.h" X#include "xloadimage.h" X Xvoid usage(name) X char *name; X{ X printf("Usage: %s [global options] {[image options] image_name ...}\n", X tail(name)); X printf("Global options:\n"); X printf(" -onroot - load image onto root window\n"); X printf(" -border colorname - border image with this color\n"); X printf(" -display dispname - destination display\n"); X printf(" -fullscreen - use entire screen for display\n"); X printf(" -geometry WxH+X+Y - destination size and location\n"); X printf(" -help - print this help message\n"); X printf(" -identify - identify given images\n"); X printf(" -list - list images in path\n"); X printf(" -install - explicitly install colormap\n"); X printf(" -path - show image path for loading\n"); X printf(" -quiet - silence is golden\n"); X printf(" -slideshow - show images in slideshow style\n"); X printf(" -supported - show supported image types\n"); X printf(" -verbose - whistle while you work\n"); X printf(" -version - show version and patchlevel\n"); X printf(" -view - view image in a window\n"); X printf("Image_options:\n"); X printf(" -at X,Y - load image at location\n"); X printf(" -background colorname - background color for bitmap images\n"); X printf(" -gamma display_gamma - specify display gamma - default = 1.0\n"); X printf(" - typical display needs 2.0 - 2.5\n"); X printf(" -brighten percentage - specify brightness multiplier\n"); X printf(" -center - center image\n"); X printf(" -colors number - specify maximum number of RGB colors\n"); X printf(" -clip X,Y,W,H - use clipped portion of image\n"); X printf(" -dither - dither color image to bitmap image\n"); X printf(" -foreground colorname - foreground color for bitmap images\n"); X printf(" -halftone - halftone a color image to bitmap image\n"); X printf(" -name name - force next argument to be image name\n"); X printf(" -rotate degrees - rotate an image by a 90 degree angle\n"); X printf(" -smooth - smooth a color image\n"); X printf(" -xzoom percentage - zoom the X axis by a percentage\n"); X printf(" -yzoom percentage - zoom the Y axis by a percentage\n"); X printf(" -zoom percentage - zoom the image by a percentage\n"); X exit(1); X} X Xchar *tail(path) X char *path; X{ int s; X char *t; X X t= path; X for (s= 0; *(path + s) != '\0'; s++) X if (*(path + s) == '/') X t= path + s + 1; X return(t); X} X XImage *processImage(disp, scrn, image, options, verbose) X Display *disp; X int scrn; X Image *image; X ImageOptions *options; X unsigned int verbose; X{ Image *tmpimage; X XColor xcolor; X unsigned int compressed= 0; X XWindowAttributes windowAttrs; X X goodImage(image, "processImage"); X X /* clip the image if requested X */ X X if ((options->clipx != 0) || (options->clipy != 0) || X (options->clipw != 0) || (options->cliph != 0)) { X if (!options->clipw) X options->clipw= image->width; X if (!options->cliph) X options->cliph= image->height; X tmpimage= clip(image, options->clipx, options->clipy, X (options->clipw ? options->clipw : image->width), X (options->cliph ? options->cliph : image->height), X verbose); X freeImage(image); X image= tmpimage; X } X X if (options->rotate) X { tmpimage = rotate(image, options->rotate, verbose); X freeImage(image); X image = tmpimage; X } X X if (onroot && fullscreen) X { XGetWindowAttributes(disp, XRootWindow(disp, scrn), &windowAttrs); X options->xzoom = (((float) windowAttrs.width) / X ((float) image->width)) * 100; X options->yzoom = (((float) windowAttrs.height) / X ((float) image->height)) * 100; X } X X if (options->xzoom || options->yzoom) { /* zoom image */ X if (!options->colors && RGBP(image) && /* if the image is to */ X (!options->xzoom && (options->yzoom > 100)) || /* be blown up, */ X (!options->yzoom && (options->xzoom > 100)) || /* compress before */ X (options->xzoom + options->yzoom > 200)) { /* doing it */ X compress(image, verbose); X compressed= 1; X } X tmpimage= zoom(image, options->xzoom, options->yzoom, verbose); X freeImage(image); X image= tmpimage; X } X X if (options->bright) /* alter image brightness */ X brighten(image, options->bright, verbose); X X if (options->gamma != 1.0) /* do display gamma compensation */ X gammacorrect(image, options->gamma, verbose); X X /* forcibly reduce colormap X */ X X if (options->colors && RGBP(image) && (options->colors < image->rgb.used)) { X reduce(image, options->colors, verbose); X image->rgb.size= options->colors; /* lie */ X compressed= 1; X } X X if (options->dither && (image->depth > 1)) { /* image is to be dithered */ X if (options->dither == 1) X tmpimage= dither(image, verbose); X else X tmpimage= halftone(image, verbose); X freeImage(image); X image= tmpimage; X } X else if (!compressed) /* make sure colormap is minimized */ X compress(image, verbose); X X if (options->smooth > 0) { /* image is to be smoothed */ X tmpimage= smooth(image, options->smooth, verbose); X if (tmpimage != image) { X freeImage(image); X image= tmpimage; X } X } X X /* set foreground and background colors of mono image X */ X X xcolor.flags= DoRed | DoGreen | DoBlue; X if ((image->depth == 1) && options->fg) { X XParseColor(disp, DefaultColormap(disp, scrn), options->fg, &xcolor); X *(image->rgb.red + 1)= xcolor.red; X *(image->rgb.green + 1)= xcolor.green; X *(image->rgb.blue + 1)= xcolor.blue; X } X if ((image->depth == 1) && options->bg) { X XParseColor(disp, DefaultColormap(disp, scrn), options->bg, &xcolor); X *image->rgb.red= xcolor.red; X *image->rgb.green= xcolor.green; X *image->rgb.blue= xcolor.blue; X } X return(image); X} X X/* this gets called on an I/O error; it really assumes that a KillClient X * was issued. X */ X X/* ARGSUSED */ Xint ioErrorHandler(disp) X Display *disp; X{ X exit(0); X} END_OF_FILE if test 6442 -ne `wc -c <'misc.c'`; then echo shar: \"'misc.c'\" unpacked with wrong size! fi # end of 'misc.c' fi if test -f 'path.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'path.c'\" else echo shar: Extracting \"'path.c'\" \(5593 characters\) sed "s/^X//" >'path.c' <<'END_OF_FILE' X/* path.c: X * X * functions that deal with the image path X * X * jim frost 10.03.89 X * X * Copyright 1989, 1990 Jim Frost. See included file "copyright.h" for X * complete copyright information. X */ X X#include "copyright.h" X#include "xloadimage.h" X#include <X11/Xos.h> X#include <sys/stat.h> X#include <ctype.h> X#include <pwd.h> X#include <errno.h> X#ifdef SYSV X#include <unistd.h> X#endif X Xextern int errno; X Xstatic unsigned int NumPaths= 0; Xstatic unsigned int NumExts= 0; Xstatic char *Paths[BUFSIZ]; Xstatic char *Exts[BUFSIZ]; Xstatic char *PathToken= "path="; Xstatic char *ExtToken= "extension="; X X#define VOIDSECTION 0 X#define PATHSECTION 1 X#define EXTSECTION 2 X Xstatic void readPathsAndExts(name) X char *name; X{ FILE *f; X char tokenbuf[BUFSIZ]; X char buf[BUFSIZ]; X unsigned int secnum; X unsigned int linenum; X unsigned int a, b, l; X int c; X X if (! (f= fopen(name, "r"))) X return; X X secnum= VOIDSECTION; X linenum= 0; X while (fscanf(f, "%s", tokenbuf) > 0) { X linenum++; X l= strlen(tokenbuf); X for (a= 0, b= 0; a < l; a++, b++) { X if (tokenbuf[a] == '\\') X tokenbuf[b]= tokenbuf[++a]; X else if (b != a) X tokenbuf[b]= tokenbuf[a]; X if (tokenbuf[a] == '#') { X tokenbuf[b]= '\0'; X while (((c= fgetc(f)) != '\n') && (c != EOF)) X ; X break; X } X } X X if (!strncmp(tokenbuf, PathToken, strlen(PathToken))) { X secnum= PATHSECTION; X if (sscanf(tokenbuf + strlen(PathToken), "%s", buf) != 1) X continue; X } X else if (!strncmp(tokenbuf, ExtToken, strlen(ExtToken))) { X secnum= EXTSECTION; X if (sscanf(tokenbuf + strlen(ExtToken), "%s", buf) != 1) X continue; X } X else X strcpy(buf, tokenbuf); X if (buf[0] == '\0') X continue; X X switch (secnum) { X case VOIDSECTION: X printf("%s: %d: Syntax error\n", name, linenum); /* ala BASIC */ X fclose(f); X return; X case PATHSECTION: X if (NumPaths < BUFSIZ - 1) X Paths[NumPaths++]= expandPath(buf); X else { X printf("%s: %d: Path table overflow\n", name, linenum); X fclose(f); X return; X } X break; X case EXTSECTION: X if (NumExts < BUFSIZ - 1) X Exts[NumExts++]= dupString(buf); X else { X printf("%s: %d: Extension table overflow\n", name, linenum); X fclose(f); X } X break; X } X } X} X Xvoid loadPathsAndExts() X{ static int havepaths= 0; X struct passwd *pw; X char buf[BUFSIZ]; X X if (havepaths) X return; X havepaths= 1; X X if (pw= getpwuid(getuid())) { X sprintf(buf, "%s/.xloadimagerc", pw->pw_dir); X if (! access(buf, R_OK)) { X readPathsAndExts(buf); X return; /* don't read system file if user has one */ X } X } X else X printf("Can't find your password file entry?!?\n"); X#ifdef SYSPATHFILE X readPathsAndExts(SYSPATHFILE); X#endif X} X X/* find an image with paths and extensions from defaults files. returns X * -1 if access denied or not found, 0 if ok. X */ X Xint findImage(name, fullname) X char *name, *fullname; X{ unsigned int p, e; X struct stat sbuf; X X strcpy(fullname, name); X if (!strcmp(name, "stdin")) /* stdin is special name */ X return(0); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X strcat(fullname, ".Z"); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X for (p= 0; p < NumPaths; p++) { X sprintf(fullname, "%s/%s", Paths[p], name); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X strcat(fullname, ".Z"); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X for (e= 0; e < NumExts; e++) { X sprintf(fullname, "%s/%s%s", Paths[p], name, Exts[e]); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X strcat(fullname, ".Z"); X if (! stat(fullname, &sbuf)) X return(access(fullname, R_OK)); X } X } X errno= ENOENT; /* file not found */ X return(-1); X} X X/* list images along our path X */ X Xvoid listImages() X{ unsigned int a; X char buf[BUFSIZ]; X X if (!NumPaths) { X printf("No image path\n"); X return; X } X for (a= 0; a < NumPaths; a++) { X printf("%s:\n", Paths[a]); X fflush(stdout); X sprintf(buf, "ls %s", Paths[a]); X if (system(buf) < 0) { X perror("ls"); X return; X } X } X return; X} X Xvoid showPath() X{ int a; X X if (!NumPaths && !NumExts) { X printf("No image paths or extensions\n"); X return; X } X if (NumPaths) { X printf("Image path:"); X for (a= 0; a < NumPaths; a++) X printf(" %s", Paths[a]); X printf("\n"); X } X if (NumExts) { X printf("Image extensions:"); X for (a= 0; a < NumExts; a++) X printf(" %s", Exts[a]); X printf("\n"); X } X} X Xchar *expandPath(p) X char *p; X{ char buf1[BUFSIZ], buf2[BUFSIZ]; X int b1, b2, var; X char *ptr; X X char *getenv(); X X buf1[0] = '\0'; X buf2[0] = '\0'; X b1 = 0; X b2 = 0; X var = 0; X X while(*p) { X if(isspace(*p)) break; X if (*p == '$') var++; X else if(*p == '~') { X buf1[b1] = '\0'; X strcat(buf1, getenv("HOME")); X b1 = strlen(buf1); X var = 0; X } X else if(*p == '/' || *p == '}') { X if(var) { X buf1[b1] = '\0'; X buf2[b2] = '\0'; X strcat(buf1, getenv(buf2)); X b1 = strlen(buf1); X buf2[0] = '\0'; X b2 = 0; X var = 0; X } X if(*p == '/') { X buf1[b1] = *p; X b1++; X } X } X else if(var) { X if(*p != '{') { X buf2[b2] = *p; X b2++; X } X } X else { X buf1[b1] = *p; X b1++; X } X *p++; X } X X buf1[b1] = '\0'; X X if((b2 = strlen(buf1)) > 0) { X ptr = (char *)lmalloc((unsigned) b2+1); X strcpy(ptr, buf1); X return(ptr); X } X else X return(NULL); X X} END_OF_FILE if test 5593 -ne `wc -c <'path.c'`; then echo shar: \"'path.c'\" unpacked with wrong size! fi # end of 'path.c' fi if test -f 'pbm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pbm.c'\" else echo shar: Extracting \"'pbm.c'\" \(12015 characters\) sed "s/^X//" >'pbm.c' <<'END_OF_FILE' X/* pbm.c: X * X * portable bit map (pbm) format images X * X * jim frost 09.27.89 X * X * patched by W. David Higgins (wdh@mkt.csd.harris.com) to support X * raw-format PBM files. X * X * patched by Ian MacPhedran (macphed@dvinci.usask.ca) to support X * PGM and PPM files (03-July-1990) X */ X X#include "image.h" X#include "hash.h" X Xstatic int IntTable[256]; Xstatic unsigned int Initialized= 0; X X#define NOTINT -1 X#define COMMENT -2 X#define SPACE -3 X#define NEWLINE -4 X X#define BADREAD 0 /* read error */ X#define NOTPBM 1 /* not a pbm file */ X#define PBMNORMAL 2 /* pbm normal type file */ X#define PBMCOMPACT 3 /* pbm compacty type file */ X#define PBMRAWBITS 4 /* pbm raw bits type file */ X#define PGMNORMAL 5 /* pgm normal type file */ X#define PGMRAWBITS 6 /* pgm raw bytes type file */ X#define PPMNORMAL 7 /* ppm normal type file */ X#define PPMRAWBITS 8 /* ppm raw bytes type file */ X Xstatic void initializeTable() X{ unsigned int a; X X for (a= 0; a < 256; a++) X IntTable[a]= NOTINT; X IntTable['#']= COMMENT; X IntTable['\n']= NEWLINE; X IntTable['\r']= IntTable['\t']= IntTable[' ']= SPACE; X IntTable['0']= 0; X IntTable['1']= 1; X IntTable['2']= 2; X IntTable['3']= 3; X IntTable['4']= 4; X IntTable['5']= 5; X IntTable['6']= 6; X IntTable['7']= 7; X IntTable['8']= 8; X IntTable['9']= 9; X Initialized= 1; X} X Xstatic int pbmReadChar(zf) X ZFILE *zf; X{ int c; X X if ((c= zgetc(zf)) == EOF) { X zclose(zf); X return(-1); X } X if (IntTable[c] == COMMENT) X do { X if ((c= zgetc(zf)) == EOF) X return(-1); X } while (IntTable[c] != NEWLINE); X return(c); X} X Xstatic int pbmReadInt(zf) X ZFILE *zf; X{ int c, value; X X for (;;) { X c= pbmReadChar(zf); X if (c < 0) X return(-1); X if (IntTable[c] >= 0) X break; X }; X X value= IntTable[c]; X for (;;) { X c= pbmReadChar(zf); X if (c < 0) X return(-1); X if (IntTable[c] < 0) X return(value); X value= (value * 10) + IntTable[c]; X } X} X Xstatic int isPBM(zf, name, width, height, maxval, verbose) X ZFILE *zf; X char *name; X unsigned int *width, *height, *maxval; X unsigned int verbose; X{ unsigned char buf[4]; X X if (! Initialized) X initializeTable(); X X if (zread(zf, buf, 2) != 2) X return(NOTPBM); X if (memToVal(buf, 2) == memToVal("P1", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = 1; X if (verbose) X printf("%s is a %dx%d PBM image\n", name, *width, *height); X return(PBMNORMAL); X } X if (memToVal(buf, 2) == memToVal("P4", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = 1; X if (verbose) X printf("%s is a %dx%d RawBits PBM image\n", name, *width, *height); X return(PBMRAWBITS); X } X if (memToVal(buf, 2) == 0x2a17) { X if (zread(zf, buf, 4) != 4) X return(NOTPBM); X *width= memToVal(buf, 2); X *height= memToVal(buf + 2, 2); X *maxval = 1; X if (verbose) X printf("%s is a %dx%d Compact PBM image\n", name, *width, *height); X return(PBMCOMPACT); X } X if (memToVal(buf, 2) == memToVal("P2", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = pbmReadInt(zf); X if (verbose) X printf("%s is a %dx%d PGM image with %d levels\n", name, *width, X *height, (*maxval+1)); X return(PGMNORMAL); X } X if (memToVal(buf, 2) == memToVal("P5", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = pbmReadInt(zf); X if (verbose) X printf("%s is a %dx%d Raw PGM image with %d levels\n", name, *width, X *height, (*maxval+1)); X return(PGMRAWBITS); X } X if (memToVal(buf, 2) == memToVal("P3", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = pbmReadInt(zf); X if (verbose) X printf("%s is a %dx%d PPM image with %d levels\n", name, *width, X *height, (*maxval+1)); X return(PPMNORMAL); X } X if (memToVal(buf, 2) == memToVal("P6", 2)) { X if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0)) X return(NOTPBM); X *maxval = pbmReadInt(zf); X if (verbose) X printf("%s is a %dx%d Raw PPM image with %d levels\n", name, *width, X *height, (*maxval+1)); X return(PPMRAWBITS); X } X return(NOTPBM); X} X Xint pbmIdent(fullname, name) X char *fullname, *name; X{ ZFILE *zf; X unsigned int width, height, maxval, ret; X X if (! (zf= zopen(fullname, name))) X return(0); X X ret= isPBM(zf, name, &width, &height, &maxval, (unsigned int)1); X zclose(zf); X return(ret != NOTPBM); X} X XImage *pbmLoad(fullname, name, verbose) X char *fullname, *name; X unsigned int verbose; X{ ZFILE *zf; X Image *image; X unsigned int x, y; X unsigned int width, height, maxval, depth, curmax; X unsigned int linelen; X byte srcmask, destmask; X byte *destptr, *destline; X int src, size; X unsigned int numbytes, numread; X hash_list chl; X Intensity *red,*grn,*blu; X X if (! (zf= zopen(fullname))) X return(NULL); X X switch (isPBM(zf, name, &width, &height, &maxval, verbose)) { X case NOTPBM: X zclose(zf); X return(NULL); X X case PBMNORMAL: X image= newBitImage(width, height); X linelen= (width / 8) + (width % 8 ? 1 : 0); X destline= image->data; X for (y= 0; y < height; y++) { X destptr= destline; X destmask= 0x80; X for (x= 0; x < width; x++) { X do { X if ((src= pbmReadChar(zf)) < 0) { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X if (IntTable[src] == NOTINT) { X printf("%s: Bad image data\n", fullname); X zclose(zf); X exit(1); X } X } while (IntTable[src] < 0); X X switch (IntTable[src]) { X case 1: X *destptr |= destmask; X case 0: X if (! (destmask >>= 1)) { X destmask= 0x80; X destptr++; X } X break; X default: X printf("%s: Bad image data\n", fullname); X zclose(zf); X exit(1); X } X } X destline += linelen; X } X break; X X case PBMRAWBITS: X image= newBitImage(width, height); X destline= image->data; X linelen= (width + 7) / 8; X numbytes= linelen * height; X srcmask= 0; /* force initial read */ X numread= 0; X for (y= 0; y < height; y++) { X destptr= destline; X destmask= 0x80; X if (srcmask != 0x80) { X srcmask= 0x80; X if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X numread++; X } X for (x= 0; x < width; x++) { X if (src & srcmask) X *destptr |= destmask; X if (! (destmask >>= 1)) { X destmask= 0x80; X destptr++; X } X if (! (srcmask >>= 1)) { X srcmask= 0x80; X if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X numread++; X } X } X destline += linelen; X } X break; X X case PBMCOMPACT: X image= newBitImage(width, height); X destline= image->data; X linelen= (width / 8) + (width % 8 ? 1 : 0); X srcmask= 0x80; X destmask= 0x80; X if ((src= zgetc(zf)) == EOF) { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X numread= 1; X numbytes= width * height; X numbytes= (numbytes / 8) + (numbytes % 8 ? 1 : 0); X for (y= 0; y < height; y++) { X destptr= destline; X destmask= 0x80; X for (x= 0; x < width; x++) { X if (src & srcmask) X *destptr |= destmask; X if (! (destmask >>= 1)) { X destmask= 0x80; X destptr++; X } X if (! (srcmask >>= 1)) { X srcmask= 0x80; X if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X numread++; X } X } X destline += linelen; X } X break; X case PGMRAWBITS: X for (depth=0,curmax=1;maxval>curmax;depth++) curmax=curmax*2; X image = newRGBImage(width, height, depth); X for (y=0; y<=maxval; y++) X { /* As in sunraster.c, use simple ramp for grey scale */ X *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff); X *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff); X *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff); X } X image->rgb.used = maxval+1; X destline = image->data; X size = height*width; X for (y=0; y<size; y++) X { X if ((src = zgetc(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X { X valToMem(src,destline,image->pixlen); destline += image->pixlen; X } X } X break; X case PGMNORMAL: X for (depth=0,curmax=1;maxval>curmax;depth++) curmax=curmax*2; X image = newRGBImage(width, height, depth); X for (y=0; y<=maxval; y++) X { /* As in sunraster.c, use simple ramp for grey scale */ X *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff); X *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff); X *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff); X } X image->rgb.used = maxval+1; X destline = image->data; X size = height*width; X for (y=0; y<size; y++) X { X if ((src = pbmReadInt(zf)) < 0) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X { X valToMem(src,destline,image->pixlen); destline += image->pixlen; X } X } X break; X case PPMRAWBITS: X size = height*width; X red = (Intensity *)lmalloc(size * sizeof(Intensity)); X grn = (Intensity *)lmalloc(size * sizeof(Intensity)); X blu = (Intensity *)lmalloc(size * sizeof(Intensity)); X chl = init_hash(); X for (y=0; y<size; y++) X { X if ((src = zgetc(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X red[y] = src; X if ((src = zgetc(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X grn[y] = src; X if ((src = zgetc(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X blu[y] = src; X add_hash(chl, red[y], grn[y], blu[y]); X } X X y = count_hash(chl); /* Find number of colours in table */ X printf("%d colors found in image",y); X if (y > 256) X printf(". You may wish to run ppmquant 256 on it.\n"); X else X printf(".\n"); X X for (depth=0,curmax=1;y>curmax;depth++) curmax=curmax*2; X image = newRGBImage(width, height, depth); X image->rgb.used = y; X fill_map(chl,&(image->rgb),maxval); X destline = image->data; X for (x=0; x<size; x++) X { X y = find_hash( chl, red[x], grn[x], blu[x]); X valToMem(y,destline,image->pixlen); destline += image->pixlen; X } X X free_hash( chl ); X lfree( red ); lfree( grn ); lfree( blu ); X break; X case PPMNORMAL: X size = height*width; X red = (Intensity *)lmalloc(size * sizeof(Intensity)); X grn = (Intensity *)lmalloc(size * sizeof(Intensity)); X blu = (Intensity *)lmalloc(size * sizeof(Intensity)); X chl = init_hash(); X for (y=0; y<size; y++) X { X if ((src = pbmReadInt(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X red[y] = src; X if ((src = pbmReadInt(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X grn[y] = src; X if ((src = pbmReadInt(zf)) == EOF) X { X printf("%s: Short image\n", fullname); X zclose(zf); X exit(1); X } X else X blu[y] = src; X add_hash(chl, red[y], grn[y], blu[y]); X } X X y = count_hash(chl); /* Find number of colours in table */ X printf("%d colors found in image",y); X if (y > 256) X printf(". You may wish to run ppmquant 256 on it.\n"); X else X printf(".\n"); X X for (depth=0,curmax=1;y>curmax;depth++) curmax=curmax*2; X image = newRGBImage(width, height, depth); X image->rgb.used = y; X fill_map(chl,&(image->rgb),maxval); X destline = image->data; X for (x=0; x<size; x++) X { X y = find_hash( chl, red[x], grn[x], blu[x]); X valToMem(y,destline,image->pixlen); destline += image->pixlen; X } X X free_hash( chl ); X lfree( red ); lfree( grn ); lfree( blu ); X break; X } X image->title= dupString(name); X zclose(zf); X return(image); X} END_OF_FILE if test 12015 -ne `wc -c <'pbm.c'`; then echo shar: \"'pbm.c'\" unpacked with wrong size! fi # end of 'pbm.c' fi if test -f 'reduce.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'reduce.c'\" else echo shar: Extracting \"'reduce.c'\" \(5757 characters\) sed "s/^X//" >'reduce.c' <<'END_OF_FILE' X/* reduce.c: X * X * reduce an image's colormap usage to a set number of colors. X * X * jim frost 07.06.89 X * X * Copyright 1989, 1990 Jim Frost. See included file "copyright.h" for X * complete copyright information. X */ X X#include "copyright.h" X#include "image.h" X X#define DIST(A, B) ((A) < (B) ? (B) - (A) : (A) - (B)) X X/* find the distance between two colors. we loose some accuracy here because X * a triple squared short may not fit in a long. we use a table lookup X * to help speed this up; it's an O(exp(n,2)) algorithm. X */ X Xunsigned int squareInit= 0; Xunsigned long squareTable[32768]; X Xvoid initSquareTable() X{ unsigned long a; X X for (a= 0; a < 32768; a++) X squareTable[a]= a * a; X squareInit= 1; X} X Xunsigned long colorDistance(rgb, a, b) X RGBMap *rgb; X Pixel a, b; X{ X return(squareTable[DIST(*(rgb->red + a), *(rgb->red + b)) >> 1] + X squareTable[DIST(*(rgb->green + a), *(rgb->green + b)) >> 1] + X squareTable[DIST(*(rgb->blue + a), *(rgb->blue + b)) >> 1]); X} X Xstatic Pixel bestColor(rgb, color, rdist) X RGBMap *rgb; X Pixel color; X unsigned long *rdist; X{ Pixel qcolor, bcolor; X unsigned long qdist, bdist; X X bdist= 0xffffffff; X bcolor= 0; X for (qcolor= color + 1; qcolor < rgb->used; qcolor++) X if ((qdist= colorDistance(rgb, color, qcolor)) && (qdist < bdist)) { X bdist= qdist; X bcolor= qcolor; X } X *rdist= bdist; X return(bcolor); X} X Xvoid reduceRGBMap(rgb, n, verbose) X RGBMap *rgb; X unsigned int n; X unsigned int verbose; X{ unsigned int numcolors; X Pixel a, b; X Pixel lowextreme, highextreme; /* intensity extremes */ X unsigned long lowintensity, highintensity, myintensity; X Pixel bcolor1; /* closest colors */ X Pixel bcolor2; X unsigned long bdist; X Pixel *best; /* array holding best match for each color */ X unsigned long *dists; /* array holding distances of best matches */ X Pixel *same; /* array holding identical pixel lists */ X Intensity newred, newgreen, newblue; X X if (!squareInit) /* only do multiplies once */ X initSquareTable(); X X if (verbose) { X printf(" Reducing colormap to %d colors...", n); X fflush(stdout); X } X X best= (Pixel *)lmalloc(sizeof(Pixel) * rgb->used); X same= (Pixel *)lmalloc(sizeof(Pixel) * rgb->used); X dists= (unsigned long *)lmalloc(sizeof(unsigned long) * rgb->used); X X /* find out how many unique colors we have by subtracting identical ones X * and build table of identicals. find extreme intensities while we're X * at it. X */ X X lowextreme= highextreme= rgb->used - 1; X lowintensity= highintensity= *(rgb->red + lowextreme) + X *(rgb->green + lowextreme) + *(rgb->blue + lowextreme); X for (a= 0; a < rgb->used; a++) X *(same + a)= a; X for (numcolors= rgb->used, a= 0; a < rgb->used - 1; a++) { X if (*(same + a) == a) { X myintensity= *(rgb->red + a) + *(rgb->green + a) + *(rgb->blue + a); X if (myintensity < lowintensity) { X lowintensity= myintensity; X lowextreme= a; X } X if (myintensity > highintensity) { X highintensity= myintensity; X highextreme= a; X } X for (b= a + 1; b < rgb->used; b++) { X if ((*(rgb->red + a) == *(rgb->red + b)) && X (*(rgb->green + a) == *(rgb->green + b)) && X (*(rgb->blue + a) == *(rgb->blue + b))) { X numcolors--; X *(same + b)= a; X } X } X } X } X X for (a= 0; a < rgb->used - 1; a++) /* build table of "bests" */ X *(best + a)= bestColor(rgb, a, dists + a); X X /* find the two closest colors in the colormap and average them, thus X * reducing the size of the colormap by one. continue until we fit. X * this is simplistic but effective. X */ X X while (numcolors-- > n) { X bdist= 0xffffffff; /* a really big number */ X for (a= 0; a < rgb->used - 1; a++) X if ((*(same + a) == a) && (*(dists + a) < bdist)) { X bdist= *(dists + a); X bcolor1= a; X } X X bcolor2= *(same + *(best + bcolor1)); X X /* calculate new rgb values. we average the colors unless one of them X * is an extreme. X */ X X if ((bcolor1 == lowextreme) || (bcolor1 == highextreme)) { X newred= *(rgb->red + bcolor1); X newgreen= *(rgb->green + bcolor1); X newblue= *(rgb->blue + bcolor1); X } X else if ((bcolor2 == lowextreme) || (bcolor2 == highextreme)) { X newred= *(rgb->red + bcolor2); X newgreen= *(rgb->green + bcolor2); X newblue= *(rgb->blue + bcolor2); X } X else { X newred= ((unsigned int)(*(rgb->red + bcolor1)) + X (unsigned int)(*(rgb->red + bcolor2))) >> 1; X newgreen= ((unsigned int)(*(rgb->green + bcolor1)) + X (unsigned int)(*(rgb->green + bcolor2))) >> 1; X newblue= ((unsigned int)(*(rgb->blue + bcolor1)) + X (unsigned int)(*(rgb->blue + bcolor2))) >> 1; X } X X for (a= 0; a < rgb->used; a++) X if ((*(same + a) == bcolor1) || (*(same + a) == bcolor2)) { X *(same + a)= bcolor1; X *(rgb->red + a)= newred; X *(rgb->green + a)= newgreen; X *(rgb->blue + a)= newblue; X } X X for (a= 0; a < rgb->used - 1; a++) X if ((*(best + a) == bcolor1) || (*(same + a) == bcolor1) || X (*(same + *(best + a)) == bcolor1)) X *(best + a)= bestColor(rgb, a, dists + a); X } X X lfree((byte *)best); X lfree((byte *)dists); X lfree((byte *)same); X X if (verbose) X printf("done\n"); X} X Xvoid reduce(image, n, verbose) X Image *image; X unsigned int n, verbose; X{ char buf[BUFSIZ]; X X goodImage(image, "reduce"); X if (! RGBP(image)) /* we're AT&T */ X return; X compress(image, verbose); X reduceRGBMap(&(image->rgb), n, verbose); X compress(image, verbose); X sprintf(buf, "%s (%d colors)", image->title, image->rgb.used); X if (image->title) X lfree((byte *)image->title); X image->title= dupString(buf); X} END_OF_FILE if test 5757 -ne `wc -c <'reduce.c'`; then echo shar: \"'reduce.c'\" unpacked with wrong size! fi # end of 'reduce.c' fi if test -f 'root.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'root.c'\" else echo shar: Extracting \"'root.c'\" \(3987 characters\) sed "s/^X//" >'root.c' <<'END_OF_FILE' X/* root.c: X * X * this loads an image onto the root window. changes to allow proper X * freeing of previously allocated resources made by Deron Dann Johnson X * (dj@eng.sun.com). X * X * jim frost 10.03.89 X * X * Copyright 1989, 1990 Jim Frost. See included file "copyright.h" for X * complete copyright information. X */ X X#include "copyright.h" X#include "xloadimage.h" X#include <X11/Xatom.h> X X#define RETAIN_PROP_NAME "XA_XLOADIMAGE_COLORS_XID" X Xstatic void XupdateProperty(dpy, w, name, type, format, data, nelem) X Display *dpy; X Window w; X char *name; X Atom type; X int format; X int data; X int nelem; X{ X /* intern the property name */ X Atom atom = XInternAtom(dpy, name, 0); X X /* create or replace the property */ X XChangeProperty(dpy, w, atom, type, format, PropModeReplace, X (unsigned char *)&data, nelem); X} X X X/* Sets the close-down mode of the client to 'RetainPermanent' X * so all client resources will be preserved after the client X * exits. Puts a property on the default root window containing X * an XID of the client so that the resources can later be killed. X */ X Xvoid XpreserveResource(dpy, w) X Display *dpy; X Window w; X{ X /* create dummy resource */ X Pixmap pm= XCreatePixmap(dpy, w, 1, 1, 1); X X /* create/replace the property */ X updateProperty(dpy, w, RETAIN_PROP_NAME, XA_PIXMAP, 32, (int)pm, 1); X X /* retain all client resources until explicitly killed */ X XSetCloseDownMode(dpy, RetainPermanent); X} X X X/* Flushes any resources previously retained by the client, X * if any exist. X */ X Xstatic void XfreePrevious(dpy, w) X Display *dpy; X Window w; X{ X Pixmap *pm; X Atom actual_type; /* NOTUSED */ X int format; X int nitems; X int bytes_after; X X /* intern the property name */ X Atom atom = XInternAtom(dpy, RETAIN_PROP_NAME, 0); X X /* look for existing resource allocation */ X if ((XGetWindowProperty(dpy, w, atom, 0, 1, 1/*delete*/, X AnyPropertyType, &actual_type, &format, &nitems, X &bytes_after, &pm) == Success) && X nitems == 1) X if ((actual_type == XA_PIXMAP) && (format == 32) && X (nitems == 1) && (bytes_after == 0)) { X /* blast it away */ X XKillClient(dpy, (Pixmap *) *pm); X XFree(pm); X } X else if (actual_type != None) { X fprintf(stderr, X "%s: warning: invalid format encountered for property %s\n", X RETAIN_PROP_NAME, "xloadimage"); X } X} X Xvoid imageOnRoot(disp, scrn, image, verbose) X Display *disp; X int scrn; X Image *image; X unsigned int verbose; X{ Pixmap pixmap; X Colormap xcmap; X X /* Added for window managers like swm and tvtwm that follow solbourne's X * virtual root window concept X */ X X Atom __SWM_VROOT = None; X Window root, rootReturn, parentReturn, *children; X unsigned int numChildren; X int i; X X root = RootWindow(disp, scrn); X X /* see if there is a virtual root */ X __SWM_VROOT = XInternAtom(disp, "__SWM_VROOT", False); X XQueryTree(disp, root, &rootReturn, &parentReturn, &children, &numChildren); X for(i = 0; i < numChildren; i++) { X Atom actual_type; X int actual_format; X long nitems, bytesafter; X Window *newRoot = NULL; X X if (XGetWindowProperty (disp, children[i], __SWM_VROOT,0,1, X False, XA_WINDOW, &actual_type, &actual_format, X &nitems, &bytesafter, X (unsigned char **) &newRoot) == X Success && newRoot) { X root = *newRoot; X break; X } X } X X freePrevious(disp, RootWindow(disp, scrn)); X X if (! sendImageToX(disp, scrn, DefaultVisual(disp, scrn), image, X &pixmap, &xcmap, verbose)) X exit(1); X X /* changing the root colormap is A Bad Thing, so deny it. X */ X X if (xcmap != DefaultColormap(disp, scrn)) { X printf("Loading image onto root would change default colormap (sorry)\n"); X XFreePixmap(disp, pixmap); X exit(1); X } X X XSetWindowBackgroundPixmap(disp, root, pixmap); X XClearWindow(disp, root); X XFreePixmap(disp, pixmap); X preserveResource(disp, RootWindow(disp, scrn)); X} END_OF_FILE if test 3987 -ne `wc -c <'root.c'`; then echo shar: \"'root.c'\" unpacked with wrong size! fi # end of 'root.c' fi if test -f 'rotate.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rotate.c'\" else echo shar: Extracting \"'rotate.c'\" \(3668 characters\) sed "s/^X//" >'rotate.c' <<'END_OF_FILE' X/* rotate.c X * X * rotate an image X * X * Contributed by Tom Tatlow (tatlow@dash.enet.dec.com) X */ X X#include "copyright.h" X#include "image.h" X X/* rotate_bitmap() X * converts an old bitmap bit position into a new one X */ Xvoid rotate_bitmap(num, pos, width, height, new_num, new_pos) Xint num; /* Source byte number */ Xint pos; /* Source bit position */ Xint width; /* Width of source bitmap */ Xint height; /* Height of source bitmap */ Xint *new_num; /* Destination byte number */ Xint *new_pos; /* Destination bit position */ X{ X int slen; /* Length of source line */ X int dlen; /* Length of destination line */ X int sx, sy; X int dx, dy; X X slen = (width / 8) + (width % 8 ? 1 : 0); X dlen = (height / 8) + (height % 8 ? 1 : 0); X sy = num / slen; X sx = ((num - (sy * slen)) * 8) + pos; X dx = (height - sy) - 1; X dy = sx; X *new_num = (dx / 8) + (dy * dlen); X *new_pos = dx % 8; X} X X/* rotate() X * rotates an image X */ XImage *rotate(simage, rotate, verbose) XImage *simage; /* Image to rotate */ Xint rotate; /* Number of degrees to rotate */ X{ X char buf[BUFSIZ]; /* New title */ X Image *image1; /* Source image */ X Image *image2; /* Destination image */ X byte *sp; /* Pointer to source data */ X byte *dp; /* Pointer to destination data */ X int slinelen; /* Length of source line */ X int dlinelen; /* Length of destination line */ X int bit[8]; /* Array of hex values */ X int x, y; X int i, b; X int newx, newy; X int newi, newb; X X bit[0] = 128; X bit[1] = 64; X bit[2] = 32; X bit[3] = 16; X bit[4] = 8; X bit[5] = 4; X bit[6] = 2; X bit[7] = 1; X X goodImage(simage, "rotate"); X X if (verbose) X { printf(" Rotating image by %d degrees...", rotate); X fflush(stdout); X } X sprintf(buf, "%s (rotated by %d degrees)", simage->title, rotate); X X image1 = simage; X do { X rotate -= 90; X switch (image1->type) { X case IBITMAP: X image2= newBitImage(image1->height, image1->width); X for (x= 0; x < image1->rgb.used; x++) { X *(image2->rgb.red + x)= *(image1->rgb.red + x); X *(image2->rgb.green + x)= *(image1->rgb.green + x); X *(image2->rgb.blue + x)= *(image1->rgb.blue + x); X } X slinelen= (image1->width / 8) + (image1->width % 8 ? 1 : 0); X sp = image1->data; X dp = image2->data; X for (i = 0; i < (slinelen * image1->height); i++) X for (b = 0; b < 8; b++) X if (sp[i] & bit[b]) X { rotate_bitmap(i, b, image1->width, image1->height, &newi, &newb); X dp[newi] |= bit[newb]; X } X break; X X case IRGB: X image2= newRGBImage(image1->height, image1->width, image1->depth); X for (x= 0; x < image1->rgb.used; x++) { X *(image2->rgb.red + x)= *(image1->rgb.red + x); X *(image2->rgb.green + x)= *(image1->rgb.green + x); X *(image2->rgb.blue + x)= *(image1->rgb.blue + x); X } X image2->rgb.used= image1->rgb.used; X slinelen= image1->width * image1->pixlen; X dlinelen= image1->height * image1->pixlen; X sp = image1->data; X dp = image2->data; X for (y = 0; y < image1->height; y++) X for (x = 0; x < image1->width; x++) X { newx = ((image1->height - y) - 1); X newy = x; X for (i = 0; i < image1->pixlen; i++) X dp[((newy * dlinelen) + newx + i)] = X sp[((y * slinelen) + x + i)]; X } X break; X default: X printf("rotate: Unsupported image type\n"); X exit(1); X } X image1 = image2; X } while (rotate); X image1->title= dupString(buf); X if (verbose) X printf("done\n"); X return(image1); X} X END_OF_FILE if test 3668 -ne `wc -c <'rotate.c'`; then echo shar: \"'rotate.c'\" unpacked with wrong size! fi # end of 'rotate.c' fi if test -f 'value.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'value.c'\" else echo shar: Extracting \"'value.c'\" \(1574 characters\) sed "s/^X//" >'value.c' <<'END_OF_FILE' X/* value.c: X * X * routines for converting byte values to long values. these are pretty X * portable although they are not necessarily the fastest things in the X * world. X * X * jim frost 10.02.89 X * X * Copyright 1989 Jim Frost. See included file "copyright.h" for complete X * copyright information. X */ X X#include "copyright.h" X#include "image.h" X Xunsigned long memToVal(p, len) X byte *p; X unsigned int len; X{ unsigned int a; X unsigned long i; X X i= 0; X for (a= 0; a < len; a++) X i= (i << 8) + *(p++); X return(i); X} X Xvoid valToMem(val, p, len) X unsigned long val; X byte *p; X unsigned int len; X{ int a; X X for (a= len - 1; a >= 0; a--) { X *(p + a)= val & 0xff; X val >>= 8; X } X} X Xunsigned long memToValLSB(p, len) X byte *p; X unsigned int len; X{ int val, a; X X val= 0; X for (a= len - 1; a >= 0; a--) X val= (val << 8) + *(p + a); X return(val); X} X X/* this is provided for orthagonality X */ X Xvoid valToMemLSB(val, p, len) X byte *p; X unsigned long val; X unsigned int len; X{ X while (len--) { X *(p++)= val & 0xff; X val >>= 8; X } X} X X/* this flips all the bits in a byte array at byte intervals X */ X Xvoid flipBits(p, len) X byte *p; X unsigned int len; X{ static int init= 0; X static byte flipped[256]; X X if (!init) { X int a, b; X byte norm; X X for (a= 0; a < 256; a++) { X flipped[a]= 0; X norm= a; X for (b= 0; b < 8; b++) { X flipped[a]= (flipped[a] << 1) | (norm & 1); X norm >>= 1; X } X } X } X X while (len--) X p[len]= flipped[p[len]]; X} END_OF_FILE if test 1574 -ne `wc -c <'value.c'`; then echo shar: \"'value.c'\" unpacked with wrong size! fi # end of 'value.c' fi echo shar: End of archive 5 \(of 9\). cp /dev/null ark5isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.