jimf@saber.com (09/28/90)
Submitted-by: saber.com!jimf@saber.com Posting-number: Volume 9, Issue 53 Archive-name: xloadimage/part06 #! /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 6 (of 9)." # Contents: rle.c send.c smooth.c sunraster.c xbitmap.c zio.c # Wrapped by jimf@armory on Tue Sep 25 19:37:41 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'rle.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rle.c'\" else echo shar: Extracting \"'rle.c'\" \(11071 characters\) sed "s/^X//" >'rle.c' <<'END_OF_FILE' X/* X * rle - read in a Utah RLE Toolkit type image. X * X * Author: Graeme Gill X * Date: 30/5/90 X * X * Bugs - doesn't free up memory used by rle functions. X * X */ X X#undef DEBUG X X#ifdef DEBUG X# define debug(xx) fprintf(stderr,xx) X#else X# define debug(xx) X#endif X X X#define MIN(a,b) ( (a)<(b) ? (a) : (b)) X X#include <math.h> X#include <stdio.h> X#include "image.h" X#include "rle.h" X X/* input file stuff */ Xstatic int ptype; /* picture type : */ X#define BW_NM 0 /* black and white, no map */ X#define BW_M 1 /* black and white, and a map */ X#define SC_M 2 /* single colour channel and colour map */ X#define C_NM 3 /* full colour, no maps */ X#define C_M 4 /* full colour with colour maps */ Xstatic rle_pixel **fmaps; /* file colour maps from buildmap() */ Xstatic unsigned char **scan; /* buffer for input data */ Xstatic int x_min; /* copy of picture x_min */ Xstatic int y_min; /* copy of picture y_min */ X X/* option stuff (Not functional) */ Xstatic float disp_gam = 2.0; /* default display gamma correction factor */ Xstatic int gflag = 0; /* if user supplies display gamma */ Xstatic int iflag=0; /* user suplied image gamma */ Xstatic int lflag=0; /* user supplied levels */ Xstatic float img_gam = 1.0; /* image gamma */ Xstatic int bwflag = 0; /* black and white flag */ Xstatic int gammamap[256]; Xstatic int background[3] = {0,0,0}; /* our background colour */ X X/* stuff for dithering colour pictures */ Xint colmap[216][3]; /* for dither map */ Xint magic[16][16]; Xint modN[256]; Xint divN[256]; X Xint rleIdent(fullname,name) Xchar *fullname, *name; X { X ZFILE *rlefile; X int x_len,y_len; X int rv; X X debug("rleIdent called\n"); X rlefile = zopen(fullname); X if(!rlefile) X { X perror("rleIdent: Unable to open file"); X return(0); X } X debug("rleIdent: Opened file ok\n"); X sv_globals.svfb_fd = rlefile; X rv = rle_get_setup(&sv_globals); X debug("rleIdent: got setup ok\n"); X zclose(rlefile); X debug("rleIdent: closed file ok\n"); X switch(rv) X { X case -1: X return 0; /* Not rle format */ X case 0: X /* now figure out the picture type */ X switch(sv_globals.sv_ncolors) X { X case 0: X perror("rleIdent: no colour channels to display"); X return(0); X case 1: X x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; X y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; X printf("%s is a %dx%d,",name,x_len,y_len); X switch(sv_globals.sv_ncmap) X { X case 0: X /* black and white, no map */ X printf(" 8 bit grey scale image with no map"); X break; X case 1: X /* black and white with a map */ X printf(" 8 bit grey scale image with map"); X break; X case 3: X /* single channel encoded colour with decoding map */ X printf(" 8 bit colour image with colour map"); X break; X default: X perror(" 8 bit image with an illegal colour map"); X return 0; X } X break; X case 3: X switch(sv_globals.sv_ncmap) X { X case 0: X printf(" 24 bit colour image with no map"); X break; X case 3: X printf(" 24 bit colour image with colour map"); X break; X default: X perror(" 24 bit colour image with an illegal colour map"); X return 0; X } X break; X default: X perror(" image with an illegal number of colour planes"); X return 0; X } X return 1; X default: /* Some sort of error */ X/* perror("rleIdent");*/ X return 0; X } X } X X XImage *rleLoad(fullname,name,verbose) Xchar *fullname,*name; Xunsigned int verbose; X { X int x_len, y_len; X int i,j; X ZFILE *rlefile; X int ncol; /* number of colors */ X int depth; X unsigned char *bufp; X char *v; X Image *image; X unsigned char *buf; X X dith_levels = 256; /* aim for 128 levels of each colour */ X X debug("rleLoad called\n"); X rlefile = zopen(fullname); X if(!rlefile) X { X perror("rleLoad: Cannot open input file"); X return(NULL); X } X sv_globals.svfb_fd = rlefile; X debug("rleLoad: About to call get_setup\n"); X if(rle_get_setup( &sv_globals )) { X zclose(rlefile); X return(NULL); X } X X debug("rleLoad: get_setup called ok\n"); X if(iflag == 1) /* -i flag */ X img_gam = 1.0/img_gam; /* convert to display gamma */ X X /* If no image gamma on command line, check comments in file */ X if (!iflag) X { X char * v; X if ( (v = rle_getcom( "image_gamma", &sv_globals )) != NULL ) X { X img_gam = atof( v ); X /* Protect against bogus information */ X if ( img_gam == 0.0 ) X img_gam = 1.0; X else X img_gam = 1.0 / img_gam; /* convert to display gamma */ X } X else if ( (v = rle_getcom( "display_gamma", &sv_globals )) != NULL ) X { X img_gam = atof( v ); X /* Protect */ X if ( img_gam == 0.0 ) X img_gam = 1.0; X } X } X X x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1; X y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1; X X x_min = sv_globals.sv_xmin; X y_min = sv_globals.sv_ymin; X X /* fix this so that we don't waste space */ X sv_globals.sv_xmax -= sv_globals.sv_xmin; X sv_globals.sv_xmin = 0; X X /* turn off the alpha channel (don't waste time and space)*/ X sv_globals.sv_alpha = 0; X SV_CLR_BIT(sv_globals,SV_ALPHA); X X /* for now, force background clear */ X if(sv_globals.sv_background ==1) /* danger setting */ X { X debug("Forcing clear of background\n"); X sv_globals.sv_background = 2; X if(sv_globals.sv_bg_color==0) /* if none allocated */ X sv_globals.sv_bg_color = background; /* use this one */ X } X X /* now figure out the picture type */ X switch(sv_globals.sv_ncolors) X { X case 0: X perror("rleLoad: no colour channels to display"); X zclose(rlefile); X return(NULL); X case 1: X switch(sv_globals.sv_ncmap) X { X case 0: X ptype = BW_NM; /* black and white, no map */ X break; X case 1: X ptype = BW_M; /* black and white with a map */ X break; X case 3: X ptype = SC_M; /* single channel encoded colour with decoding map */ X break; X default: X zclose(rlefile); X perror("rleLoad: Illegal number of maps for one colour channel"); X return(NULL); X } X break; X case 3: X switch(sv_globals.sv_ncmap) X { X case 0: X ptype = C_NM; /* colour, no map */ X break; X case 3: X ptype = C_M; /* colour with maps */ X break; X default: X perror("rleLoad: Illegal number of maps for colour picture"); X zclose(rlefile); X return(NULL); X } X break; X default: X perror("rleLoad: Illegal number of colour channels"); X zclose(rlefile); X return(NULL); X break; X } X X if(verbose) X { X printf("rleLoad: %s is a %dx%d,",name,x_len,y_len); X switch(ptype) X { X case BW_NM: X printf(" 8 bit grey scale image with no map"); X break; X case BW_M: X printf(" 8 bit grey scale image with map"); X break; X case SC_M: X printf(" 8 bit colour image with colour map"); X break; X case C_NM: X printf(" 24 bit colour image with no map (will dither to 8 bits)"); X break; X case C_M: X printf(" 24 bit colour image with colour map (will dither to 8 bits)"); X break; X } X printf(", and has an image gama of %4.2f\n",img_gam); X } X X if(ptype==SC_M) X { /* don't mess with the image, but change their colour map a bit if needed */ X disp_gam /= img_gam; /* amount to change their map */ X img_gam = 1.0; /* not to the image coming in */ X } X X /* get hold of the colour maps, and set to undo their images gamma */ X fmaps = buildmap(&sv_globals,sv_globals.sv_ncolors,img_gam); X X /* now we had better sort out the picture data */ X debug("done colour map\n"); X X /* rle stufff */ X /* Get space for a full colour scan line */ X scan = (unsigned char **) lmalloc( (sv_globals.sv_ncolors + X sv_globals.sv_alpha) * X sizeof( unsigned char * ) ); X for ( i = 0; i < sv_globals.sv_ncolors + sv_globals.sv_alpha; i++ ) X scan[i] = (unsigned char *)lmalloc(x_len); X if ( sv_globals.sv_alpha ) X scan++; X debug("got space for get_row\n"); X X depth = 8; /* We always supply 8bit images */ X image = newRGBImage(x_len,y_len,depth); X image->title = dupString(name); X debug("got image structure\n"); X X buf = image->data; X X /* If we are going to dither - then create the dither matrix. */ X if(!bwflag && ptype!=SC_M && ptype != BW_NM && ptype != BW_M) X { X dith_np2 = 1; /* allow non-power of 2 dither map size */ X dithermap( 6, disp_gam, colmap, divN, modN, magic ); X } X X debug("About to read image in\n"); X bufp = buf + (y_len-1) * x_len; X for(j=y_len;j>0;j--,bufp -= x_len) X { X rle_getrow(&sv_globals,scan); X switch(ptype) X { X case SC_M: X memcpy(bufp,&scan[0][0],x_len); X break; X case BW_NM: X case BW_M: X bw_m_line(bufp,x_len); X break; X case C_NM: X case C_M: X c_m_line(bufp,x_len,j); X break; X } X } X debug("Image Read in\n"); X X /* Deal with colour maps */ X /* set up our gamma correction */ X make_gamma(disp_gam,gammamap); /* we'll need it */ X X debug("Creating color map\n"); X /* now load an appropriate colour map */ X if(!bwflag && ptype==SC_M) X { X /* use their maps & correct their gamma */ X ncol = 1<<sv_globals.sv_cmaplen; /* number of entries */ X for(i=0;i<ncol;i++) X { X *(image->rgb.red + i) = gammamap[fmaps[0][i]]<<8; X *(image->rgb.green + i) = gammamap[fmaps[1][i]]<<8; X *(image->rgb.blue + i) = gammamap[fmaps[2][i]]<<8; X } X } X else if(bwflag || ptype == BW_NM || ptype == BW_M) X { X /* load a black and white map (gamma corrected for this display)*/ X ncol = 256; /* don't know whats been used */ X for(i=0;i<ncol;i++) X { X *(image->rgb.red + i) = X *(image->rgb.green + i) = X *(image->rgb.blue + i) = gammamap[i]<<8; X } X } X else X { X /* must be colour, so use dither map (gamma corrected for this display)*/ X ncol = 6*6*6; X /* Dither map has already been created above */ X for(i = 0; i < ncol; i++) X { X *(image->rgb.red + i) = colmap[i][0]<<8; X *(image->rgb.green + i) = colmap[i][1]<<8; X *(image->rgb.blue + i) = colmap[i][2]<<8; X } X } X image->rgb.used = ncol; X X zclose(rlefile); X debug("finished\n"); X return(image); X } X X#define DMAP(v,x,y) (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v]) X X /* run the black and white through its map */ X bw_m_line(dp,number) X int number; X register unsigned char *dp; X { X register unsigned char *r; X register int i; X X for(i=number,r= &scan[0][0];i>0;i--,r++,dp++) X { X *dp = fmaps[0][*r]; X } X } X X /* convert a colour line with map to 8 bits per pixel */ X c_m_line(dp,number,line) X int number,line; X register unsigned char *dp; X { X register unsigned char *r, *g, *b; X register int i, col, row; X X if(!bwflag) X { X for ( row = line % dith_size, col = x_min % dith_size, i = number, r = &scan[0][0] X ,g= &scan[1][0], b= &scan[2][0]; X i > 0; i--, r++, g++, b++, dp++, col = ((col + 1) % dith_size) ) X { X *dp = DMAP(fmaps[0][*r], col, row) + X DMAP(fmaps[1][*g], col, row) * 6 + X DMAP(fmaps[2][*b], col, row) * 36; X } X } X else X { X int red,green,blue; X for (i = number, r= &scan[0][0], g= &scan[1][0] X ,b= &scan[2][0]; i>0;i--,r++,g++,b++,dp++) X { X red = fmaps[0][*r];green=fmaps[1][*g];blue = fmaps[2][*b]; X *dp = 0.35* red + 0.55* green + 0.1* blue; X } X } X } X END_OF_FILE if test 11071 -ne `wc -c <'rle.c'`; then echo shar: \"'rle.c'\" unpacked with wrong size! fi # end of 'rle.c' fi if test -f 'send.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'send.c'\" else echo shar: Extracting \"'send.c'\" \(6580 characters\) sed "s/^X//" >'send.c' <<'END_OF_FILE' X/* send.c: X * X * send an Image to an X pixmap X * X * jim frost 10.02.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 Xunsigned int sendImageToX(disp, scrn, visual, image, pixmap, cmap, verbose) X Display *disp; X int scrn; X Visual *visual; X Image *image; X Pixmap *pixmap; X Colormap *cmap; X unsigned int verbose; X{ Pixel *index; X unsigned int a, b, newmap, x, y, linelen, ddepth, dpixlen; X unsigned long plane; X byte *pixptr, *destline, *destptr, *bitplane, destmask; X byte *modimageptr; X XColor xcolor; X XGCValues gcv; X GC gc; X XImage *ximage; X X goodImage(image, "sendImageToX"); X X switch(visual->class) { X case PseudoColor: X case GrayScale: X case StaticColor: X case StaticGray: X break; X default: X printf("sendImageToX: unsupported display visual\n"); X exit(1); X } X X index= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used); X xcolor.flags= DoRed | DoGreen | DoBlue; X X /* get the colormap to use X */ X X if (visual == DefaultVisual(disp, scrn)) { X *cmap= DefaultColormap(disp, scrn); X newmap= 0; X X /* allocate colors shareable (if we can) X */ X X for (a= 0; a < image->rgb.used; a++) { X xcolor.red= *(image->rgb.red + a); X xcolor.green= *(image->rgb.green + a); X xcolor.blue= *(image->rgb.blue + a); X if (! XAllocColor(disp, *cmap, &xcolor)) X if ((visual->class == StaticColor) || (visual->class == StaticGray)) { X printf("sendImageToX: XAllocColor failed on a static visual\n"); X return(0); X } X else { X X /* we can't allocate the colors shareable so free all the colors X * we had allocated and create a private colormap X */ X X for (b= 0; b < a; b++) X XFreeColors(disp, *cmap, index + b, 1, 0); X *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, X AllocNone); X newmap= 1; X break; X } X *(index + a)= xcolor.pixel; X } X } X else { X if ((visual->class == PseudoColor) || (visual->class == GrayScale)) { X *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone); X } X else X *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocAll); X newmap= 1; X } X X if (newmap) { X for (a= 0; a < image->rgb.used; a++) /* count entries we got */ X if (! XAllocColorCells(disp, *cmap, False, NULL, 0, index + a, 1)) X break; X X if (a < image->rgb.used) /* can't get enough colors, so reduce */ X reduce(image, a, verbose); /* the colormap to fit what we have */ X X for (b= 0; b < a; b++) { X xcolor.pixel= *(index + b); X xcolor.red= *(image->rgb.red + b); X xcolor.green= *(image->rgb.green + b); X xcolor.blue= *(image->rgb.blue + b); X XStoreColor(disp, *cmap, &xcolor); X } X } X X ddepth= DefaultDepth(disp, scrn); X *pixmap= XCreatePixmap(disp, RootWindow(disp, scrn), image->width, X image->height, ddepth); X X /* blast the image across X */ X X switch (image->type) { X case IBITMAP: X gcv.function= GXcopy; X gcv.foreground= *(index + 1); X gcv.background= *index; X gc= XCreateGC(disp, *pixmap, GCFunction | GCForeground | GCBackground, X &gcv); X ximage= XCreateImage(disp, visual, image->depth, XYBitmap, 0, image->data, X image->width, image->height, 8, 0); X ximage->bitmap_bit_order= MSBFirst; X ximage->byte_order= MSBFirst; X XPutImage(disp, *pixmap, gc, ximage, 0, 0, 0, 0, X image->width, image->height); X XFreeGC(disp, gc); X break; X X case IRGB: X X /* modify image data to match colormap and pack pixels if necessary X */ X X if (verbose) { X printf(" Building XImage..."); X fflush(stdout); X } X pixptr= image->data; X modimageptr = image->data; X dpixlen = ddepth / 8; X if(image->pixlen != dpixlen) { /* Need to convert depth */ X modimageptr = (byte *)lmalloc(image->height * image->width * dpixlen); X } X destptr = modimageptr; X X for (y= 0; y < image->height; y++) X for (x= 0; x < image->width; x++) { X valToMem(*(index + memToVal(pixptr, image->pixlen)), X destptr, dpixlen); X pixptr += image->pixlen; X destptr += dpixlen; X } X X if (verbose) X printf("done\n"); X X /* if the destination depth is not a multiple of 8, then we send each X * plane as a bitmap because otherwise we would have to pack the pixel X * data and the XImage format is pretty vague about how that should X * be done. this is not as fast as it would be if it were packed but X * it should be a lot more portable and only slightly slower. X */ X X if (ddepth % 8) { X#ifndef SERVER_HAS_BROKEN_PLANEMASK /* see README */ X gcv.function= GXcopy; X#else X gcv.function= GXor; X#endif X gcv.background= 0; X gc= XCreateGC(disp, *pixmap, GCFunction | GCBackground, &gcv); X linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); X bitplane= lmalloc(image->height * linelen); X ximage= XCreateImage(disp, visual, 1, XYBitmap, 0, bitplane, X image->width, image->height, 8, 0); X ximage->bitmap_bit_order= MSBFirst; X ximage->byte_order= MSBFirst; X X for (plane= 1 << (ddepth - 1); plane; plane >>= 1) { X pixptr= image->data; X destline= bitplane; X for (y= 0; y < image->height; y++) { X destmask= 0x80; X destptr= destline; X for (x= 0; x < image->width; x++) { X if (*pixptr & plane) X *destptr |= destmask; X else X *destptr &= ~destmask; X if (!(destmask >>= 1)) { X destmask= 0x80; X destptr++; X } X pixptr += image->pixlen; X } X destline += linelen; X } X XSetForeground(disp, gc, plane); X XSetPlaneMask(disp, gc, plane); X XPutImage(disp, *pixmap, gc, ximage, 0, 0, 0, 0, X image->width, image->height); X } X X ximage->data= NULL; X XDestroyImage(ximage); X lfree(bitplane); X break; X } X X /* send image across in one whack X */ X X gcv.function= GXcopy; X gc= XCreateGC(disp, *pixmap, GCFunction, &gcv); X ximage= XCreateImage(disp, visual, ddepth, ZPixmap, 0, modimageptr, X image->width, image->height, 8, 0); X ximage->byte_order= MSBFirst; /* trust me, i know what i'm talking about */ X X XPutImage(disp, *pixmap, gc, ximage, 0, 0, X 0, 0, image->width, image->height); X if(image->data == modimageptr) X ximage->data= NULL; X XDestroyImage(ximage); /* waste not want not */ X XFreeGC(disp, gc); X break; X X default: X printf("sendImageToX: bad image type\n"); X return(0); X } X lfree((byte *)index); X return(1); X} END_OF_FILE if test 6580 -ne `wc -c <'send.c'`; then echo shar: \"'send.c'\" unpacked with wrong size! fi # end of 'send.c' fi if test -f 'smooth.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'smooth.c'\" else echo shar: Extracting \"'smooth.c'\" \(6012 characters\) sed "s/^X//" >'smooth.c' <<'END_OF_FILE' X/* smooth.c: X * X * this performs a smoothing convolution using a 3x3 area. X * X * jim frost 09.20.90 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 X/* this stuff is all used to pick the best possible color out of the X * image's colormap. it creates a table sorted by the sum of the rgb X * values. we then do a binary search to find the colors which are X * closest to our sum. we then search those colors to find the best X * possible color. this will have a complexity between log n base 2 and X * n depending on the distribution of colormap sums. usually it's pretty X * good. X */ X Xextern unsigned int squareInit; Xextern unsigned long squareTable[]; X Xstruct colorarray { X Pixel pixel; /* pixel value */ X unsigned long sum; /* sum of rgb values */ X}; X Xstatic int colorPredicate(c1, c2) X struct colorarray *c1, *c2; X{ X return(c1->sum < c2->sum ? -1 : 1); X} X Xstatic struct colorarray *createColorArray(rgb) X RGBMap *rgb; X{ struct colorarray *carray; X Pixel a; X X carray= (struct colorarray *)lmalloc(rgb->used * sizeof(struct colorarray)); X for (a= 0; a < rgb->used; a++) { X carray[a].pixel= a; X carray[a].sum= rgb->red[a] + rgb->green[a] + rgb->blue[a]; X } X qsort(carray, rgb->used, sizeof(struct colorarray), colorPredicate); X return(carray); X} X X#define DIST(A, B) ((A) < (B) ? (B) - (A) : (A) - (B)) X Xstatic Pixel bestColorByRGB(rgb, carray, red, green, blue) X RGBMap *rgb; X struct colorarray *carray; X unsigned long red, green, blue; X{ unsigned long bdist, qdist, sum, sum2; X Pixel pick, bpick, qpick; X unsigned int areasize; X X sum= red + green + blue; X X /* binary search to find colors which are close to us X */ X X pick= areasize= rgb->used / 2; X while ((pick > 0) && (pick < rgb->used - 1)) { X areasize= (areasize + 1) >> 1; X pick += (carray[pick].sum > sum ? -areasize : areasize); X if ((carray[pick].sum <= sum) && (sum < carray[pick + 1].sum)) X break; X } X X /* look at colors that are a little darker than we are X */ X X bdist= X squareTable[DIST(rgb->red[carray[pick].pixel], red) >> 1] + X squareTable[DIST(rgb->green[carray[pick].pixel], green) >> 1] + X squareTable[DIST(rgb->blue[carray[pick].pixel], blue) >> 1]; X bpick= pick; X X if (pick > 0) { X qpick= pick - 1; X sum2= carray[qpick].sum; X while (carray[qpick].sum == sum2) { X qdist= X squareTable[DIST(rgb->red[carray[qpick].pixel], red) >> 1] + X squareTable[DIST(rgb->green[carray[qpick].pixel], green) >> 1] + X squareTable[DIST(rgb->blue[carray[qpick].pixel], blue) >> 1]; X if (qdist < bdist) { X bpick= qpick; X bdist= qdist; X if (!bdist) X return(carray[bpick].pixel); X } X if (qpick == 0) X break; X qpick--; X } X } X X if (pick == rgb->used - 1) /* nothing following */ X return(carray[bpick].pixel); X X /* look at colors which are a little lighter than we are X */ X X qpick= pick + 1; X sum2= carray[qpick].sum; X do { X qdist= X squareTable[DIST(rgb->red[carray[qpick].pixel], red) >> 1] + X squareTable[DIST(rgb->green[carray[qpick].pixel], green) >> 1] + X squareTable[DIST(rgb->blue[carray[qpick].pixel], blue) >> 1]; X if (qdist < bdist) { X bpick= qpick; X bdist= qdist; X if (!bdist) X return(carray[bpick].pixel); X } X qpick++; X } while ((qpick < rgb->used) && (carray[qpick].sum == sum2)); X X return(carray[bpick].pixel); X} X Xstatic Image *doSmooth(image) X Image *image; X{ Image *new; X int x, y, x1, y1, linelen, reductions; X int xindex[3]; X byte *yindex[3]; X byte *srcptr, *destptr; X Pixel pixval; X unsigned long avgred, avggreen, avgblue; X struct colorarray *carray; X X /* create new image and copy colormap X */ X X new= newRGBImage(image->width, image->height, image->depth); X new->title= (char *)lmalloc(strlen(image->title) + 12); X sprintf(new->title, "%s (smoothed)", image->title); X bcopy(image->rgb.red, new->rgb.red, image->rgb.used * sizeof(Intensity)); X bcopy(image->rgb.green, new->rgb.green, image->rgb.used * sizeof(Intensity)); X bcopy(image->rgb.blue, new->rgb.blue, image->rgb.used * sizeof(Intensity)); X new->rgb.used= image->rgb.used; X X carray= createColorArray(&(new->rgb)); X X /* run through image and take a guess as to what the color should X * actually be. X */ X X for (y= 0; y < image->height; y++) { X linelen= image->pixlen * image->width; X destptr= new->data + (y * linelen); X yindex[1]= image->data + (y * linelen); X yindex[0]= yindex[1] - (y > 0 ? linelen : 0); X yindex[2]= yindex[1] + (y < image->height - 1 ? linelen : 0); X for (x= 0; x < image->width; x++) { X avgred= avggreen= avgblue= 0; X xindex[1]= x * image->pixlen; X xindex[0]= xindex[1] - (x > 0 ? image->pixlen : 0); X xindex[2]= xindex[1] + (x < image->width - 1 ? image->pixlen : 0); X for (y1= 0; y1 < 3; y1++) { X for (x1= 0; x1 < 3; x1++) { X pixval= memToVal(yindex[y1] + xindex[x1], image->pixlen); X avgred += *(image->rgb.red + pixval); X avggreen += *(image->rgb.green + pixval); X avgblue += *(image->rgb.blue + pixval); X } X } X X /* pick the pixel that's closest to this average and put in image X */ X X avgred= ((avgred + 8) / 9); X avggreen= ((avggreen + 8) / 9); X avgblue= ((avgblue + 8) / 9); X pixval= bestColorByRGB(&(new->rgb), carray, avgred, avggreen, avgblue); X valToMem(pixval, destptr, new->pixlen); X destptr += new->pixlen; X } X } X X lfree(carray); X return(new); X} X XImage *smooth(image, iterations, verbose) X Image *image; X int verbose; X{ int a; X Image *new; X X if (!squareInit) X initSquareTable(); X X if (!RGBP(image)) /* no effect unless color image (yet) */ X return(image); X X if (verbose) { X printf(" Smoothing..."); X fflush(stdout); X } X X for (a= 0; a < iterations; a++) { X new= doSmooth(image); X freeImage(image); X image= new; X } X X if (verbose) X printf("done\n"); X X return(image); X} END_OF_FILE if test 6012 -ne `wc -c <'smooth.c'`; then echo shar: \"'smooth.c'\" unpacked with wrong size! fi # end of 'smooth.c' fi if test -f 'sunraster.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sunraster.c'\" else echo shar: Extracting \"'sunraster.c'\" \(5487 characters\) sed "s/^X//" >'sunraster.c' <<'END_OF_FILE' X/* sunraster.c: X * X * sun rasterfile image type X * X * jim frost 09.27.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#include "sunraster.h" X Xstatic void babble(name, header) X char *name; X struct rheader *header; X{ X printf("%s is a", name); X switch (memToVal(header->type, 4)) { X case ROLD: X printf("n old-style"); X break; X case RSTANDARD: X printf(" standard"); X break; X case RRLENCODED: X printf(" run-length encoded"); X break; X default: X printf(" unknown-type"); X } X printf(" %dx%d ", memToVal(header->width, 4), memToVal(header->height, 4)); X if (memToVal(header->depth, 4) > 1) X printf("%d plane %s", X memToVal(header->depth, 4), X (memToVal(header->maplen, 4) > 0 ? "color" : "greyscale") X ); X else X printf("monochrome"); X printf(" Sun rasterfile\n"); X} X Xint sunRasterIdent(fullname, name) X char *fullname, *name; X{ ZFILE *zf; X struct rheader header; X int r; X X if (! (zf= zopen(fullname))) { X perror("sunRasterIdent"); X return(0); X } X switch (zread(zf, &header, sizeof(struct rheader))) { X case -1: X perror("sunRasterIdent"); X r= 0; X break; X X case sizeof(struct rheader): X if (memToVal(header.magic, 4) != RMAGICNUMBER) { X r= 0; X break; X } X babble(name, &header); X r= 1; X break; X X default: X r= 0; X break; X } X zclose(zf); X return(r); X} X X/* read either rl-encoded or normal image data X */ X Xstatic void sunread(zf, buf, len, enc) X ZFILE *zf; X byte *buf; X unsigned int len; X unsigned int enc; /* true if encoded file */ X{ static byte repchar, remaining= 0; X X /* rl-encoded read X */ X X if (enc) { X while (len--) X if (remaining) { X remaining--; X *(buf++)= repchar; X } X else { X if (zread(zf, &repchar, 1) != 1) { X printf("sunRasterLoad: Bad read on image data\n"); X exit(1); X } X if (repchar == RESC) { X if (zread(zf, &remaining, 1) != 1) { X printf("sunRasterLoad: Bad read on image data\n"); X exit(1); X } X if (remaining == 0) X *(buf++)= RESC; X else { X if (zread(zf, &repchar, 1) != 1) { X printf("sunRasterLoad: Bad read on image data\n"); X exit(1); X } X *(buf++)= repchar; X } X } X else X *(buf++)= repchar; X } X } X X /* normal read X */ X X else { X if (zread(zf, buf, len) < len) { X printf("sunRasterLoad: Bad read on image data\n"); X exit(1); X } X } X} X XImage *sunRasterLoad(fullname, name, verbose) X char *fullname, *name; X unsigned int verbose; X{ ZFILE *zf; X struct rheader header; X unsigned int mapsize; X byte *map; X byte *mapred, *mapgreen, *mapblue; X unsigned int depth; X unsigned int linelen; /* length of raster line in bytes */ X unsigned int fill; /* # of fill bytes per raster line */ X unsigned int enc; X byte fillchar; X Image *image; X byte *lineptr; X unsigned int y; X X if (! (zf= zopen(fullname))) { X perror("sunRasterLoad"); X return(NULL); X } X switch (zread(zf, &header, sizeof(struct rheader))) { X case -1: X perror("sunRasterLoad"); X zclose(zf); X exit(1); X X case sizeof(struct rheader): X if (memToVal(header.magic, 4) != RMAGICNUMBER) { X zclose(zf); X return(NULL); X } X if (verbose) X babble(name, &header); X break; X X default: X zclose(zf); X return(NULL); X } X X /* get an image to put the data in X */ X X depth= memToVal(header.depth, 4); X if (depth == 1) X image= newBitImage(memToVal(header.width, 4), X memToVal(header.height, 4)); X else X image= newRGBImage(memToVal(header.width, 4), X memToVal(header.height, 4), X memToVal(header.depth, 4)); X X /* set up the colormap X */ X X if (depth == 1) X linelen= (image->width / 8) + (image->width % 8 ? 1 : 0); X else X linelen= image->width * image->pixlen; X fill= (linelen % 2 ? 1 : 0); X /* X * Handle color... X */ X if (mapsize= memToVal(header.maplen, 4)) { X map= lmalloc(mapsize); X if (zread(zf, map, mapsize) < mapsize) { X printf("sunRasterLoad: Bad read on colormap\n"); X exit(1); X } X mapsize /= 3; X mapred= map; X mapgreen= mapred + mapsize; X mapblue= mapgreen + mapsize; X for (y= 0; y < mapsize; y++) { X *(image->rgb.red + y)= (*(mapred++) << 8); X *(image->rgb.green + y)= (*(mapgreen++) << 8); X *(image->rgb.blue + y)= (*(mapblue++) << 8); X } X lfree(map); X image->rgb.used= mapsize; X } X X /* X * Handle 8-bit greyscale via a simple ramp function... X */ X else if (depth > 1) { X mapsize = 256*3; X map= lmalloc(mapsize); X for (y = 0; y < 256; y += 1) { X map[y] = map[256+y] = map[2*256+y] = y; X } X mapsize /= 3; X mapred= map; X mapgreen= mapred + mapsize; X mapblue= mapgreen + mapsize; X for (y= 0; y < mapsize; y++) { X *(image->rgb.red + y)= (*(mapred++) << 8); X *(image->rgb.green + y)= (*(mapgreen++) << 8); X *(image->rgb.blue + y)= (*(mapblue++) << 8); X } X lfree(map); X image->rgb.used= mapsize; X } X X X enc= (memToVal(header.type, 4) == RRLENCODED); X lineptr= image->data; X for (y= 0; y < image->height; y++) { X sunread(zf, lineptr, linelen, enc); X lineptr += linelen; X if (fill) X sunread(zf, &fillchar, fill, enc); X } X zclose(zf); X image->title= dupString(name); X return(image); X} END_OF_FILE if test 5487 -ne `wc -c <'sunraster.c'`; then echo shar: \"'sunraster.c'\" unpacked with wrong size! fi # end of 'sunraster.c' fi if test -f 'xbitmap.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbitmap.c'\" else echo shar: Extracting \"'xbitmap.c'\" \(5417 characters\) sed "s/^X//" >'xbitmap.c' <<'END_OF_FILE' X/* xbitmap.c: X * X * at one time this was XRdBitF.c. it bears very little resemblence to it X * now. that was ugly code. this is cleaner, faster, and more reliable X * in most cases. X * X * jim frost 10.06.89 X * X * Copyright, 1987, Massachusetts Institute of Technology X * X * Copyright 1989 Jim Frost. See included file "copyright.h" for complete X * copyright information. X */ X X#include "mit.cpyrght" X#include "copyright.h" X#include "image.h" X#include <ctype.h> X X#ifdef SYSV X#include <string.h> X#define rindex strrchr X#else Xchar *rindex(); X#endif X X#define MAX_SIZE 255 X Xstatic short HexTable[256]; /* conversion value */ Xstatic unsigned int Initialized= 0; /* easier to fill in at run time */ X X#define b0000 0 /* things make more sense if you see them by bit */ X#define b0001 1 X#define b0010 2 X#define b0011 3 X#define b0100 4 X#define b0101 5 X#define b0110 6 X#define b0111 7 X#define b1000 8 X#define b1001 9 X#define b1010 10 X#define b1011 11 X#define b1100 12 X#define b1101 13 X#define b1110 14 X#define b1111 15 X X#define HEXSTART -1 X#define HEXDELIM -2 X#define HEXBAD -3 X X/* build a hex digit value table with the bits inverted X */ X Xstatic void initHexTable() X{ int a; X X for (a= 0; a < 256; a++) X HexTable[a]= HEXBAD; X X HexTable['0']= b0000; X HexTable['1']= b1000; X HexTable['2']= b0100; X HexTable['3']= b1100; X HexTable['4']= b0010; X HexTable['5']= b1010; X HexTable['6']= b0110; X HexTable['7']= b1110; X HexTable['8']= b0001; X HexTable['9']= b1001; X HexTable['A']= b0101; HexTable['a']= HexTable['A']; X HexTable['B']= b1101; HexTable['b']= HexTable['B']; X HexTable['C']= b0011; HexTable['c']= HexTable['C']; X HexTable['D']= b1011; HexTable['d']= HexTable['D']; X HexTable['E']= b0111; HexTable['e']= HexTable['E']; X HexTable['F']= b1111; HexTable['f']= HexTable['F']; X HexTable['x']= HEXSTART; X HexTable['\r']= HEXDELIM; X HexTable['\n']= HEXDELIM; X HexTable['\t']= HEXDELIM; X HexTable[' ']= HEXDELIM; X HexTable[',']= HEXDELIM; X HexTable['}']= HEXDELIM; X X Initialized = 1; X} X X/* read a hex value and return its value X */ X Xstatic int nextInt(zf) X ZFILE *zf; X{ int c; X int value= 0; X int shift= 0; X X for (;;) { X c= zgetc(zf); X if (c == EOF) X return(-1); X else { X c= HexTable[c & 0xff]; X switch(c) { X case HEXSTART: X shift= 0; /* reset shift counter */ X break; X case HEXDELIM: X if (shift) X return(value); X break; X case HEXBAD: X return(-1); X default: X value += (c << shift); X shift += 4; X } X } X } X} X Xstatic void badFile(name) X char *name; X{ X printf("%s: bad X bitmap file\n", name); X exit(1); X} X XImage *xbitmapLoad(fullname, name, verbose) X char *fullname, *name; X unsigned int verbose; X{ ZFILE *zf; X Image *image; X char line[MAX_SIZE]; X char name_and_type[MAX_SIZE]; X char *type; X int value; X int v10p; X unsigned int linelen, dlinelen; X unsigned int x, y; X unsigned int w = 0, h = 0; X byte *dataptr; X X if (!Initialized) X initHexTable(); X X if (! (zf= zopen(fullname))) X return(NULL); X X /* get width/height values */ X X while (zgets(line, MAX_SIZE, zf)) { X if (strlen(line) == MAX_SIZE-1) { X zclose(zf); X return(NULL); X } X X /* width/height/hot_x/hot_y scanning X */ X X if (sscanf(line,"#define %s %d", name_and_type, &value) == 2) { X if (!(type = rindex(name_and_type, '_'))) X type = name_and_type; X else X type++; X X if (!strcmp("width", type)) X w= (unsigned int)value; X if (!strcmp("height", type)) X h= (unsigned int)value; X } X X /* if start of data, determine if it's X10 or X11 data and break X */ X X if (sscanf(line, "static short %s = {", name_and_type) == 1) { X v10p = 1; X break; X } X if ((sscanf(line,"static unsigned char %s = {", name_and_type) == 1) || X (sscanf(line, "static char %s = {", name_and_type) == 1)) { X v10p = 0; X break; X } X } X X if (!w || !h) { X zclose(zf); X return(NULL); X } X image= newBitImage(w, h); X X /* get title of bitmap if any X */ X X if ((type = rindex(name_and_type, '_')) && !strcmp("bits[]", type + 1)) { X *type= '\0'; X image->title= dupString(name_and_type); X } X X /* read bitmap data X */ X X linelen= (w / 8) + (w % 8 ? 1 : 0); /* internal line length */ X if (v10p) { X dlinelen= (w / 8) + (w % 16 ? 2 : 0); X dataptr= image->data; X for (y= 0; y < h; y++) { X for (x= 0; x < dlinelen; x++) { X if ((value= nextInt(zf)) < 0) { X freeImage(image); X zclose(zf); X return(NULL); X } X *(dataptr++)= value >> 8; X if (++x < linelen) X *(dataptr++)= value & 0xff; X } X } X } X else { X dataptr= image->data; X for (y= 0; y < h; y++) X for (x= 0; x < linelen; x++) { X if ((value= nextInt(zf)) < 0) X badFile(name); X *(dataptr++)= value; X } X } X X if (verbose) { X printf("%s is a %dx%d X", name, image->width, image->height); X if (v10p) X printf("10"); X else X printf("11"); X if (image->title) X printf(" bitmap file titled '%s'", image->title); X printf("\n"); X } X zclose(zf); X return(image); X} X X/* this is the easiest way to do this. it's not likely we'll have mondo X * x bitmaps anyway given their size X */ X Xint xbitmapIdent(fullname, name) X char *fullname, *name; X{ Image *image; X X if (image= xbitmapLoad(fullname, name, (unsigned int)1)) { X freeImage(image); X return(1); X } X return(0); X} END_OF_FILE if test 5417 -ne `wc -c <'xbitmap.c'`; then echo shar: \"'xbitmap.c'\" unpacked with wrong size! fi # end of 'xbitmap.c' fi if test -f 'zio.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'zio.c'\" else echo shar: Extracting \"'zio.c'\" \(4983 characters\) sed "s/^X//" >'zio.c' <<'END_OF_FILE' X/* zio.c: X * X * this properly opens and reads from an image file, compressed or otherwise. X * X * jim frost 10.03.89 X * X * this was hacked on 09.12.90 to cache reads and to use stdin. 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 X#define MAX_ZFILES 32 X Xstatic ZFILE ZFileTable[MAX_ZFILES]; X X/* read some info through the read cache X */ X Xstatic int doRead(zf, buf, len) X ZFILE *zf; X byte *buf; X int len; X{ int bread, readlen; X X /* loop through the read X */ X X for (bread= 0; bread < len; bread += readlen, zf->bufptr += readlen) { X X /* read new or move to next data block if necessary X */ X X if (!zf->dataptr || (zf->bufptr == zf->dataptr->len)) { X if (zf->dataptr && zf->dataptr->next) X zf->dataptr= zf->dataptr->next; X else { X if (!zf->dataptr) X zf->data= zf->dataptr= (struct cache *)lmalloc(sizeof(struct cache)); X else { X zf->dataptr->next= (struct cache *)lmalloc(sizeof(struct cache)); X zf->dataptr= zf->dataptr->next; X } X zf->dataptr->next= NULL; X zf->dataptr->len= fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream); X if (zf->dataptr->len < 0) { X perror("fread"); X exit(1); X } X } X zf->bufptr= 0; X } X X /* calculate length we can get out of read buffer X */ X X readlen= (len - bread > zf->dataptr->len - zf->bufptr ? X zf->dataptr->len - zf->bufptr : len - bread); X if (!readlen) /* we're at EOF */ X return(bread); X bcopy(zf->dataptr->buf + zf->bufptr, buf + bread, readlen); X } X return(bread); X} X X/* reset a read cache X */ X Xvoid zreset(filename) X char *filename; X{ int a; X struct cache *old; X X /* if NULL filename, reset the entire table X */ X X if (!filename) { X for (a= 0; a < MAX_ZFILES; a++) X if (ZFileTable[a].filename) X zreset(ZFileTable[a].filename); X return; X } X X for (a= 0; a < MAX_ZFILES; a++) X if (ZFileTable[a].filename && !strcmp(filename, ZFileTable[a].filename)) X break; X X if (a == MAX_ZFILES) /* no go joe */ X return; X X if (ZFileTable[a].dataptr != ZFileTable[a].data) X printf("zreset: warning: ZFILE for %s was not closed properly\n", X ZFileTable[a].filename); X while (ZFileTable[a].data) { X old= ZFileTable[a].data; X ZFileTable[a].data= ZFileTable[a].data->next; X free(old); X } X lfree(ZFileTable[a].filename); X ZFileTable[a].filename= NULL; X ZFileTable[a].dataptr= NULL; X ZFileTable[a].bufptr= 0; X X switch(ZFileTable[a].type) { X case ZSTANDARD: X fclose(ZFileTable[a].stream); X break; X case ZPIPE: X pclose(ZFileTable[a].stream); X break; X case ZSTDIN: X break; X default: X printf("zreset: bad ZFILE structure\n"); X exit(1); X } X} X XZFILE *zopen(name) X char *name; X{ int a; X ZFILE *zf; X char buf[BUFSIZ]; X X /* look for filename in open file table X */ X X for (a= 0; a < MAX_ZFILES; a++) X if (ZFileTable[a].filename && !strcmp(name, ZFileTable[a].filename)) { X if (ZFileTable[a].dataptr != ZFileTable[a].data) X printf("zopen: warning: file doubly opened\n"); X ZFileTable[a].dataptr= ZFileTable[a].data; X ZFileTable[a].bufptr= 0; X return(ZFileTable + a); X } X X /* find open ZFileTable entry X */ X X for (a= 0; (a < MAX_ZFILES) && ZFileTable[a].filename; a++) X /* EMPTY */ X ; X X if (a == MAX_ZFILES) { X printf("zopen: no more files available\n"); X exit(1); X } X zf= ZFileTable + a; X X zf->filename= dupString(name); X zf->dataptr= NULL; X zf->bufptr= 0; X X /* file filename is `stdin' then use stdin X */ X X if (!strcmp(name, "stdin")) { X zf->type= ZSTDIN; X zf->stream= stdin; X return(zf); X } X X /* if filename ends in `.Z' then open pipe to uncompress. if your X * system doesn't have uncompress you can define NO_UNCOMPRESS and X * it just won't check for this. X */ X X#ifndef NO_UNCOMPRESS X if ((strlen(name) > 2) && !strcmp(".Z", name + (strlen(name) - 2))) { X zf->type= ZPIPE; X sprintf(buf, "uncompress -c %s", name); X if (! (zf->stream= popen(buf, "r"))) { X return(NULL); X } X return(zf); X } X#endif X X /* default to normal stream X */ X X zf->type= ZSTANDARD; X if (! (zf->stream= fopen(name, "r"))) { X return(NULL); X } X return(zf); X} X Xint zread(zf, buf, len) X ZFILE *zf; X byte *buf; X unsigned int len; X{ X return(doRead(zf, buf, len)); X} X Xint zgetc(zf) X ZFILE *zf; X{ unsigned char c; X X if (doRead(zf, &c, 1) > 0) X return(c); X else X return(EOF); X} X Xchar *zgets(buf, size, zf) X byte *buf; X unsigned int size; X ZFILE *zf; X{ int p= 0; X X while (doRead(zf, buf + p, 1) > 0) { X if (p == size) X return((char *)buf); X if (*(buf + p) == '\n') { X *(buf + p + 1)= '\0'; X return((char *)buf); X } X p++; X } X return(NULL); X} X X/* reset cache pointers in a ZFILE. nothing is actually reset until a X * zreset() is called with the filename. X */ X Xvoid zclose(zf) X ZFILE *zf; X{ X zf->dataptr= zf->data; X zf->bufptr= 0; X} END_OF_FILE if test 4983 -ne `wc -c <'zio.c'`; then echo shar: \"'zio.c'\" unpacked with wrong size! fi # end of 'zio.c' fi echo shar: End of archive 6 \(of 9\). cp /dev/null ark6isdone 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.