1 /*
2  * xvxpm.c - load routine for X11 XPM v3 format pictures
3  *
4  * LoadXPM(fname,pinfo)
5  * WriteXPM(fp,pic,ptype,w,h,rp,gp,bp,nc,col,name)
6  */
7 
8 /*
9  * Written by Chris P. Ross (cross@eng.umd.edu) to support XPM v3
10  * format images.
11  *
12  * Thanks go to Sam Yates (syates@spam.maths.adelaide.edu.au) for
13  * providing inspiration.
14  */
15 
16 #define VALUES_LEN	80	/* Max length of values line */
17 #define TOKEN_LEN	8	/* Max length of color token */
18 
19 #include "xv.h"
20 
21 
22 /*
23  * File format:
24  *  (A file format def should go here)
25  *
26  */
27 
28 typedef struct hent {
29   char        token[TOKEN_LEN];
30   union {
31     byte      index;
32     byte      rgb[3];
33   } color_val;
34   struct hent *next;
35 } hentry;
36 
37 #define cv_index	color_val.index
38 #define cv_rgb		color_val.rgb
39 
40 
41 
42 /* Local (Global) Variables */
43 static byte	hex[256];
44 static hentry **hashtab;        /* Hash table */
45 static int      hash_len;       /* number of hash buckets */
46 static int	bufchar;	/* Buffered character from XpmGetc */
47 static short	in_quote;	/* Is the current point in the file in */
48                                 /*  a quoted string? */
49 
50 /* Local Functions */
51 static int     XpmLoadError  PARM((const char *, const char *));
52 static int     XpmGetc	     PARM((FILE *));
53 static int     hash          PARM((char *));
54 static int     hash_init     PARM((int));
55 static int     hash_insert   PARM((hentry *));
56 static hentry *hash_search   PARM((char *));
57 static void    hash_destroy  PARM((void));
58 
59 
60 /**************************************/
LoadXPM(fname,pinfo)61 int LoadXPM(fname, pinfo)
62      char *fname;
63      PICINFO *pinfo;
64 {
65   /* returns '1' on success */
66 
67   FILE    *fp;
68   hentry   item;
69   int      c;
70   const char *bname;
71   char     values[VALUES_LEN];
72   byte    *pic;
73   byte    *i_sptr;		/* image search pointer */
74   long     filesize;
75   int      w, h, nc, cpp, line_pos;
76   int      npixels;
77   short    i, j, k;		/* for() loop indexes */
78   hentry  *clmp;		/* colormap hash-table */
79   hentry  *c_sptr;		/* cmap hash-table search pointer*/
80   XColor   col;
81 
82   bname = BaseName(fname);
83   fp = fopen(fname, "r");
84   if (!fp)
85     return (XpmLoadError(bname, "couldn't open file"));
86 
87   if (DEBUG)
88     printf("LoadXPM(): Loading xpm from %s\n", fname);
89 
90   fseek(fp, 0L, 2);
91   filesize = ftell(fp);
92   fseek(fp, 0L, 0);
93 
94   bufchar = -2;
95   in_quote = FALSE;
96 
97   /* Read in the values line.  It is the first string in the
98    * xpm, and contains four numbers.  w, h, num_colors, and
99    * chars_per_pixel. */
100 
101   /* First, get to the first string */
102   while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
103   line_pos = 0;
104 
105   /* Now, read in the string */
106   while (((c = XpmGetc(fp))!=EOF) && (line_pos < VALUES_LEN) && (c != '"')) {
107     values[line_pos++] = c;
108   }
109   if (c != '"')
110     return (XpmLoadError(bname, "error parsing values line"));
111 
112   values[line_pos] = '\0';
113   sscanf(values, "%d%d%d%d", &w, &h, &nc, &cpp);
114   if (nc <= 0 || cpp <= 0)
115     return (XpmLoadError(bname, "No colours in Xpm?"));
116 
117   npixels = w * h;
118   if (w <= 0 || h <= 0 || npixels/w != h)
119     return (XpmLoadError(bname, "Image dimensions out of range"));
120 
121   if (nc > 256)
122     pinfo->type = PIC24;
123   else
124     pinfo->type = PIC8;
125 
126   if (DEBUG)
127     printf("LoadXPM(): reading a %dx%d image (%d colors)\n", w, h, nc);
128 
129   /* We got this far... */
130   WaitCursor();
131 
132   if (!hash_init(nc))
133     return (XpmLoadError(bname, "Not enough memory to hash colormap"));
134 
135   clmp = (hentry *) malloc(nc * sizeof(hentry)); /* Holds the colormap */
136   if (pinfo->type == PIC8)
137     pic = (byte *) malloc((size_t) npixels);
138   else {
139     int bufsize = 3*npixels;
140     if (bufsize/3 != npixels)
141       return (XpmLoadError(bname, "Image dimensions out of range"));
142     pic = (byte *) malloc((size_t) bufsize);
143   }
144 
145   if (!clmp || !pic)
146     return (XpmLoadError(bname, "Not enough memory to load pixmap"));
147 
148   c_sptr = clmp;
149   i_sptr = pic;
150 
151   /* initialize the 'hex' array for zippy ASCII-hex -> int conversion */
152 
153   for (i = 0 ; i < 256 ; i++)   hex[i] = 0;
154   for (i = '0'; i <= '9' ; i++) hex[i] = i - '0';
155   for (i = 'a'; i <= 'f' ; i++) hex[i] = i - 'a' + 10;
156   for (i = 'A'; i <= 'F' ; i++) hex[i] = i - 'A' + 10;
157 
158   /* Again, we've made progress. */
159   WaitCursor();
160 
161   /* Now, we need to read the colormap. */
162   pinfo->colType = F_BWDITHER;
163   for (i = 0 ; i < nc ; i++) {
164     while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
165     if (c != '"')
166       return (XpmLoadError(bname, "Error reading colormap"));
167 
168     for (j = 0 ; j < cpp ; j++)
169       c_sptr->token[j] = XpmGetc(fp);
170     c_sptr->token[j] = '\0';
171 
172     while (((c = XpmGetc(fp))!=EOF) && ((c == ' ') || (c == '\t'))) ;
173     if (c == EOF)		/* The failure condition of getc() */
174       return (XpmLoadError(bname, "Error parsing colormap line"));
175 
176     do {
177       char  key[3];
178       char  color[80];	/* Need to figure a good size for this... */
179 
180 /*
181  *  Problem with spaces in color names
182  *
183  *    X s Color Name m Other Name c Last Name
184  *
185  *  ... this parser doesn't find `Any Name'
186  */
187 
188       for (j=0; j<2 && (c != ' ') && (c != '\t') && (c != EOF); j++) {
189 	key[j] = c;
190 	c = XpmGetc(fp);
191       }
192       key[j] = '\0';
193 
194       while (((c = XpmGetc(fp))!=EOF) && ((c == ' ') || (c == '\t'))) ;
195       if (c == EOF)	/* The failure condition of getc() */
196 	return (XpmLoadError(bname, "Error parsing colormap line"));
197 
198       for (j=0; j<79 && (c!=' ') && (c!='\t') && (c!='"') && c!=EOF; j++) {
199 	color[j] = c;
200 	c = XpmGetc(fp);
201       }
202       color[j]='\0';
203 
204       while ((c == ' ') || (c == '\t'))
205 	c = XpmGetc(fp);
206 
207       if (DEBUG > 1)
208 	printf("LoadXPM(): Got color key '%s', color '%s'\n",
209 	       key, color);
210 
211       if (key[0] == 's')	/* Don't find a color for a symbolic name */
212 	continue;
213 
214       if (XParseColor(theDisp,theCmap,color,&col)) {
215 	if (pinfo->type == PIC8) {
216 	  pinfo->r[i] = col.red >> 8;
217 	  pinfo->g[i] = col.green >> 8;
218 	  pinfo->b[i] = col.blue >> 8;
219 	  c_sptr->cv_index = i;
220 
221 	  /* Is there a better way to do this? */
222 	  if (pinfo->colType != F_FULLCOLOR) {
223 	    if (pinfo->colType == F_GREYSCALE) {
224 	      if (pinfo->r[i] == pinfo->g[i] &&
225 		  pinfo->g[i] == pinfo->b[i])
226 		/* Still greyscale... */
227 		;
228 	      else
229 		/* It's color */
230 		pinfo->colType = F_FULLCOLOR;
231 	    } else {
232 	      if (pinfo->r[i] == pinfo->g[i] &&
233 		  pinfo->g[i] == pinfo->b[i]) {
234 		if ((pinfo->r[i] == 0 || pinfo->r[i] == 0xff) &&
235 		    (pinfo->g[i] == 0 || pinfo->g[i] == 0xff) &&
236 		    (pinfo->b[i] == 0 || pinfo->b[i] == 0xff))
237 		  /* It's B/W */
238 		  ;
239 		else
240 		  /* It's greyscale */
241 		  pinfo->colType = F_GREYSCALE;
242 	      } else
243 		/* It's color */
244 		pinfo->colType = F_FULLCOLOR;
245 	    }
246 	  }
247 
248 	}
249 	else {   /* PIC24 */
250 	  c_sptr->cv_rgb[0] = col.red >> 8;
251 	  c_sptr->cv_rgb[1] = col.green >> 8;
252 	  c_sptr->cv_rgb[2] = col.blue >> 8;
253 	}
254       }
255 
256       else {      /* 'None' or unrecognized color spec */
257 	int rgb;
258 
259 	if (strcasecmp(color, "None") == 0) rgb = 0xb2c0dc;  /* infobg */
260 	else {
261 	  SetISTR(ISTR_INFO, "%s:  unknown color spec '%s'", bname, color);
262 	  Timer(1000);
263 	  rgb = 0x808080;
264 	}
265 
266 	if (pinfo->type == PIC8) {
267 	  pinfo->r[i] = (rgb>>16) & 0xff;
268 	  pinfo->g[i] = (rgb>> 8) & 0xff;
269 	  pinfo->b[i] = (rgb>> 0) & 0xff;
270 	  c_sptr->cv_index = i;
271 	}
272 	else {
273 	  c_sptr->cv_rgb[0] = (rgb>>16) & 0xff;
274 	  c_sptr->cv_rgb[1] = (rgb>> 8) & 0xff;
275 	  c_sptr->cv_rgb[2] = (rgb>> 0) & 0xff;
276 	}
277       }
278 
279 
280       xvbcopy((char *) c_sptr, (char *) &item, sizeof(item));
281       hash_insert(&item);
282 
283       if (DEBUG > 1)
284 	printf("LoadXPM():  Cmap entry %d, 0x%02x 0x%02x 0x%02x, token '%s'\n",
285 	       i, pinfo->r[i], pinfo->g[i], pinfo->b[i], c_sptr->token);
286 
287       if (*key == 'c') {	/* This is the color entry, keep it. */
288 	while (c!='"' && c!=EOF) c = XpmGetc(fp);
289 	break;
290       }
291 
292     } while (c != '"');
293     c_sptr++;
294 
295     if (!(i%13)) WaitCursor();
296   } /* for */
297 
298 
299   if (DEBUG)
300     printf("LoadXPM(): Read and stored colormap.\n");
301 
302   /* Now, read the pixmap. */
303   for (i = 0 ; i < h ; i++) {
304     while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
305     if (c != '"')
306       return (XpmLoadError(bname, "Error reading colormap"));
307 
308     for (j = 0 ; j < w ; j++) {
309       char pixel[TOKEN_LEN];
310       hentry *mapentry;
311 
312       for (k = 0 ; k < cpp ; k++)
313 	pixel[k] = XpmGetc(fp);
314       pixel[k] = '\0';
315 
316       if (!(mapentry = (hentry *) hash_search(pixel))) {
317 	/* No colormap entry found.  What do we do?  Bail for now */
318 	if (DEBUG)
319 	  printf("LoadXPM(): Found token '%s', can't find entry in colormap\n",
320 		 pixel);
321 	return (XpmLoadError(bname, "Can't map resolve into colormap"));
322       }
323 
324       if (pinfo->type == PIC8)
325 	*i_sptr++ = mapentry->cv_index;
326       else {
327 	*i_sptr++ = mapentry->cv_rgb[0];
328 	*i_sptr++ = mapentry->cv_rgb[1];
329 	*i_sptr++ = mapentry->cv_rgb[2];
330       }
331     }  /* for ( j < w ) */
332     while (((c = XpmGetc(fp))!=EOF) &&		/* Throw away the close " and */
333 	(c != '"'));				/* erase all remaining pixels */
334 
335     if (!(i%7)) WaitCursor();
336   }  /* for ( i < h ) */
337 
338   pinfo->pic = pic;
339   pinfo->normw = pinfo->w = w;
340   pinfo->normh = pinfo->h = h;
341   pinfo->frmType = F_XPM;
342 
343   if (DEBUG) printf("LoadXPM(): pinfo->colType is %d\n", pinfo->colType);
344 
345   sprintf(pinfo->fullInfo, "Xpm v3 Pixmap (%ld bytes)", filesize);
346   sprintf(pinfo->shrtInfo, "%dx%d Xpm.", w, h);
347   pinfo->comment = (char *)NULL;
348 
349   hash_destroy();
350   free(clmp);
351 
352   if (fp != stdin)
353     fclose(fp);
354 
355   return(1);
356 }
357 
358 
359 /***************************************/
XpmLoadError(fname,st)360 static int XpmLoadError(fname, st)
361      const char *fname, *st;
362 {
363   SetISTR(ISTR_WARNING, "%s:  %s", fname, st);
364   return 0;
365 }
366 
367 
368 /***************************************/
XpmGetc(f)369 static int XpmGetc(f)
370      FILE *f;
371 {
372   int	c, d, lastc;
373 
374   if (bufchar != -2) {
375     /* The last invocation of this routine read the character... */
376     c = bufchar;
377     bufchar = -2;
378     return(c);
379   }
380 
381   if ((c = getc(f)) == EOF)
382     return(EOF);
383 
384   if (c == '"')
385     in_quote = !in_quote;
386   else if (!in_quote && c == '/') {	/* might be a C-style comment */
387     if ((d = getc(f)) == EOF)
388       return(EOF);
389     if (d == '*') {				/* yup, it *is* a comment */
390       if ((lastc = getc(f)) == EOF)
391 	return(EOF);
392       do {				/* skip through to the end */
393 	if ((c = getc(f)) == EOF)
394 	  return(EOF);
395 	if (lastc != '*' || c != '/')	/* end of comment */
396 	  lastc = c;
397       } while (lastc != '*' || c != '/');
398       if ((c = getc(f)) == EOF)
399 	return(EOF);
400     } else					/* nope, not a comment */
401       bufchar = d;
402   }
403   return(c);
404 }
405 
406 
407 /***************************************/
408 /*         hashing functions           */
409 /***************************************/
410 
411 
412 /***************************************/
hash(token)413 static int hash(token)
414      char *token;
415 {
416   int i, sum;
417 
418   for (i=sum=0; token[i] != '\0'; i++)
419     sum += token[i];
420 
421   sum = sum % hash_len;
422   return (sum);
423 }
424 
425 
426 /***************************************/
hash_init(hsize)427 static int hash_init(hsize)
428      int hsize;
429 {
430   /*
431    * hash_init() - This function takes an arg, but doesn't do anything with
432    * it.  It could easily be expanded to figure out the "optimal" number of
433    * buckets.  But, for now, a hard-coded 257 will do.  (Until I finish the
434    * 24-bit image writing code.  :-)
435    */
436 
437   int i;
438 
439   hash_len = 257;
440 
441   hashtab = (hentry **) malloc(sizeof(hentry *) * hash_len);
442   if (!hashtab) {
443     SetISTR(ISTR_WARNING, "Couldn't malloc hashtable in LoadXPM()!\n");
444     return 0;
445   }
446 
447   for (i = 0 ; i < hash_len ; i++)
448     hashtab[i] = NULL;
449 
450   return 1;
451 }
452 
453 
454 /***************************************/
hash_insert(entry)455 static int hash_insert(entry)
456      hentry *entry;
457 {
458   int     key;
459   hentry *tmp;
460 
461   key = hash(entry->token);
462 
463   tmp = (hentry *) malloc(sizeof(hentry));
464   if (!tmp) {
465     SetISTR(ISTR_WARNING, "Couldn't malloc hash entry in LoadXPM()!\n");
466     return 0;
467   }
468 
469   xvbcopy((char *)entry, (char *)tmp, sizeof(hentry));
470 
471   if (hashtab[key]) tmp->next = hashtab[key];
472                else tmp->next = NULL;
473 
474   hashtab[key] = tmp;
475 
476   return 1;
477 }
478 
479 
480 /***************************************/
hash_search(token)481 static hentry *hash_search(token)
482      char *token;
483 {
484   int     key;
485   hentry *tmp;
486 
487   key = hash(token);
488 
489   tmp = hashtab[key];
490   while (tmp && strcmp(token, tmp->token)) {
491     tmp = tmp->next;
492   }
493 
494   return tmp;
495 }
496 
497 
498 /***************************************/
hash_destroy()499 static void hash_destroy()
500 {
501   int     i;
502   hentry *tmp;
503 
504   for (i=0; i<hash_len; i++) {
505     while (hashtab[i]) {
506       tmp = hashtab[i]->next;
507       free(hashtab[i]);
508       hashtab[i] = tmp;
509     }
510   }
511 
512   free(hashtab);
513   return;
514 }
515 
516 
517 
518 /**************************************************************************/
WriteXPM(fp,pic,ptype,w,h,rp,gp,bp,nc,col,name,comments)519 int WriteXPM(fp, pic, ptype, w, h, rp, gp, bp, nc, col, name, comments)
520      FILE *fp;			/* File to write to */
521      byte *pic;			/* Image data */
522      int ptype;			/* PIC8 or PIC24 */
523      int w, h;			/* width, & height */
524      byte *rp, *gp, *bp;	/* Colormap pointers */
525      int nc, col;		/* number of colors, & colorstyle */
526      char *name;		/* name of file (/image) */
527      char *comments;		/* image comments (not currently used */
528 {
529   /* Note here, that tokenchars is assumed to contain 64 valid token */
530   /* characters.  It's hardcoded to assume this for benefit of generating */
531   /* tokens, when there are more than 64^2 colors. */
532 
533   short	i, imax, j;	/* for() loop indices */
534   short	cpp = 0;
535   const char *tokenchars =
536             ".#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
537   char	*tokens;
538   char	image_name[256], *foo;
539   byte	grey;
540 
541 #ifndef USE_UNFINISHED_24BIT_WRITING_CODE
542   byte	*pic8, *sptr;
543   byte	rtemp[256], gtemp[256], btemp[256], hist[256], trans[256];
544   long	li;		/* for() loop index */
545   int	numcol;
546 #endif
547 
548   if (DEBUG) {
549     if (ptype == PIC8)
550       printf("WriteXPM(): Write a %d color, colortype %d, PIC8 image.\n",
551 	     nc, col);
552     else
553       printf("WriteXPM(): Write a colortype %d, PIC24 image.\n", col);
554   }
555 
556   strcpy(image_name, BaseName(name));
557   foo = (char *)strchr(image_name, '.');
558   if (foo)
559     *foo = '\0';		/* Truncate name at first '.' */
560 
561 #ifdef USE_UNFINISHED_24BIT_WRITING_CODE
562   if (ptype == PIC24)
563     return -1;
564 #else
565   /* XXX - The colormap returned from Conv24to8 is not a specific  */
566   /* size (and Conv24to8 doesn't tell me how many entries there    */
567   /* are, or not in this rev of code at least) and not necessarily */
568   /* 'packed'.  Code in here to do that should be removed if       */
569   /* Conv24to8 is "fixed" to do this...                            */
570   /*    Chris P. Ross (cross@eng.umd.edu)  28-Sept-94              */
571 
572   numcol = 0;
573 
574   if (ptype == PIC24) {
575     /* Reduce to an 8-bit image.  Would be nice to actually write */
576     /* the 24-bit image.  I'll have to code that someday...       */
577     pic8 = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp);
578     if (!pic8) {
579       SetISTR(ISTR_WARNING,
580 	      "%s:  Unable to convert to 8-bit image in WriteXPM()",
581 	      image_name);
582       return 1;
583     }
584     if (DEBUG) printf("WriteXPM(): Converted 24bit image.\n");
585 
586     /* This will count the number of colors in use, and build an */
587     /* index array into the colormap (which may not be 'packed') */
588     /* Thanks to John Bradley for this code..                    */
589 
590     xvbzero((char *) hist, sizeof(hist));
591     numcol = 0;
592 
593     if (DEBUG)
594       printf("WriteXPM(): Counting colors (width: %d, height: %d)...\n", w, h);
595 
596     for (li = 0, sptr = pic8 ; li < (w*h) ; li++, sptr++) {
597       hist[*sptr] = 1;
598     }
599 
600     if (DEBUG)
601       printf("WriteXPM(): building translation table...\n");
602     for (i = 0 ; i < 256 ; i++) {
603       trans[i] = numcol;
604       rtemp[numcol] = rtemp[i];
605       gtemp[numcol] = gtemp[i];
606       btemp[numcol] = btemp[i];
607       numcol += hist[i];
608     }
609     rp=rtemp; gp=gtemp; bp=btemp;
610     if (DEBUG)
611       printf("WriteXPM(): Converted 24bit image now has %d colors.\n", numcol);
612   } else {
613     pic8 = pic;
614     numcol = nc;
615   }
616 #endif
617 
618 
619 #ifdef USE_UNFINISHED_24BIT_WRITING_CODE
620   if (ptype == PIC24) cpp = 4;
621   else if (numcol > 64) cpp = 2;
622   else cpp = 1;
623 #else
624   if (numcol > 64) cpp = 2;
625   else cpp = 1;
626 #endif
627 
628   fprintf(fp, "/* XPM */\n");
629   fprintf(fp, "static char *%s[] = {\n", image_name);
630   fprintf(fp, "/* width height num_colors chars_per_pixel */\n");
631   fprintf(fp, "\"   %3d   %3d   %6d            %1d\",\n", w, h, numcol, cpp);
632   fprintf(fp, "/* colors */\n");
633 
634   switch (cpp) {
635 
636   case 1:			/* <= 64 colors; index into tokenchars */
637     if (col == F_GREYSCALE)
638       for (i = 0 ; i < numcol ; i ++) {
639 	grey = MONO(rp[i], gp[i], bp[i]);
640 	fprintf(fp, "\"%c c #%02x%02x%02x\",\n", tokenchars[i],
641 		grey, grey, grey);
642       }
643     else
644       for (i = 0 ; i < numcol ; i ++)
645 	fprintf(fp, "\"%c c #%02x%02x%02x\",\n", tokenchars[i],
646 		rp[i], gp[i], bp[i]);
647     fprintf(fp, "/* pixels */\n");
648     for (i = 0 ; i < h ; i ++) {
649       fprintf(fp, "\"");
650       if (!(i%20))
651 	WaitCursor();
652       for (j = 0 ; j < w ; j++) {
653 	if (rp == rtemp)
654 	  fprintf(fp, "%c", tokenchars[trans[*pic8++]]);
655 	else
656 	  fprintf(fp, "%c", tokenchars[*pic8++]);
657       }
658       if (i < h-1)
659 	fprintf(fp, "\",\n");
660     }
661     break;
662 
663   case 2:			/* 64 < colors < 64^2; build new token list */
664     tokens = (char *) malloc((size_t) ((2*numcol) + 1) );
665     if (numcol & 0x3f)
666       imax = (numcol >> 6) + 1;
667     else
668       imax = (numcol >> 6);
669     for (i = 0 ; i < imax ; i++)
670       for (j =  0 ; j < 64 && ((i<<6)+j) < numcol ; j++) {
671 	*(tokens+((i<<6)+j)*2) = tokenchars[i];
672 	*(tokens+((i<<6)+j)*2+1) = tokenchars[j];
673       }
674     if (col == F_GREYSCALE)
675       for (i = 0 ; i < numcol ; i++) {
676 	grey = MONO(rp[i], gp[i], bp[i]);
677 	fprintf(fp, "\"%c%c c #%02x%02x%02x\",\n", tokens[i*2],
678 		tokens[i*2+1], grey, grey, grey);
679       }
680     else
681       for (i = 0 ; i < numcol ; i++)
682 	fprintf(fp, "\"%c%c c #%02x%02x%02x\",\n", tokens[i*2],
683 		tokens[i*2+1], rp[i], gp[i], bp[i]);
684     fprintf(fp, "/* pixels */\n");
685     for (i = 0 ; i < h ; i++) {
686       fprintf(fp, "\"");
687       if (!(i%13))
688 	WaitCursor();
689       for (j = 0 ; j < w ; j++) {
690 	if (rp == rtemp)
691 	  fprintf(fp, "%c%c", tokens[trans[*pic8]*2],
692 		  tokens[(trans[*pic8]*2)+1]);
693 	else
694 	  fprintf(fp, "%c%c", tokens[(*pic8*2)],
695 		  tokens[(*pic8*2)+1]);
696 	pic8++;
697       }
698       if (i < h-1)
699 	fprintf(fp, "\",\n");
700     }
701     break;
702 
703   case 4:
704     /* Generate a colormap */
705 
706     break;
707   default:
708     break;
709   }
710 
711   if (fprintf(fp, "\"\n};\n") == EOF) {
712     return 1;
713   } else
714     return 0;
715 }
716 
717 
718 
719 
720