home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / gif_sun / gif2ras.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-09  |  12.1 KB  |  541 lines

  1. /*********************************************
  2.  *             GIF to SUN rasterfile         *
  3.  *                                           *
  4.  *      March 23 1989 By Marcel J.E. Mol     *
  5.  *                                           *
  6.  * I hereby place this program               *
  7.  * in the public domain, i.e. there are no   *
  8.  * copying restrictions of any kind.         *
  9.  *********************************************/
  10.  
  11. /* 
  12.  * Usage:
  13.  *        gif2ras <gif-file>
  14.  * 
  15.  * Compile:
  16.  *          cc gif2ras.c -o gif2ras -lpixrect
  17.  * 
  18.  */ 
  19.  
  20.  
  21. #include <stdio.h>
  22. #include    <rasterfile.h>
  23.  
  24. char *malloc();
  25. int strncmp();
  26.  
  27. #define FALSE 0
  28. #define TRUE 1
  29. #define COLSIZE 256
  30. #define PICSIZE 2;
  31. #define SHOWCOUNT 10;
  32.  
  33.  
  34. /*
  35.  * Rasterfile variables 
  36.  */
  37. struct rasterfile    header;
  38.  
  39. /*
  40.  * LZW structures and variables
  41.  */
  42. typedef int bool;
  43. unsigned char *stackp;
  44. unsigned int prefix[4096];
  45. unsigned char suffix[4096];
  46. unsigned char stack[4096];
  47. int datasize,codesize,codemask;     /* Decoder working variables */
  48. int clear,eoi;                      /* Special code values */
  49. int avail;
  50. int oldcode;
  51.  
  52. /*
  53.  * GIF variables
  54.  */
  55. FILE *infile;
  56. unsigned int screenwidth;           /* The dimensions of the screen */
  57. unsigned int screenheight;          /*   (not those of the image)   */
  58. unsigned int rscreenwidth;          /* The dimensions of the raster */
  59. bool global;                        /* Is there a global color map? */
  60. int globalbits;                     /* Number of bits of global colors */
  61. unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
  62. char bgcolor;                       /* background color */
  63. unsigned char *raster;              /* Decoded image data */
  64. unsigned left,top,width,height,rwidth;
  65.  
  66. char *progname;
  67. char *filename;
  68.  
  69. void convert();
  70. int  checksignature();
  71. void readscreen();
  72. int  readimage();
  73. void readextension();
  74. int  readraster();
  75. int  process();
  76. void outcode();
  77. void initraster();
  78. void initcolors();
  79. int  rasterize();
  80. void usage();
  81.  
  82.  
  83.  
  84.  
  85. main(argc,argv)
  86. int argc;
  87. char *argv[];
  88. {
  89.     extern int optind;
  90.     extern char *optarg;
  91.     int flag;
  92.  
  93.     progname = *argv;
  94.  
  95.     while ((flag = getopt(argc, argv, "")) != EOF) {
  96.         switch (flag) {
  97.             default  : fprintf(stderr, "ignoring unknown flag %c\n", flag);
  98.                        usage();
  99.         }
  100.     }
  101.  
  102.     if (optind >= argc) {
  103.         filename = "stdin";
  104.         convert();
  105.     }
  106.     else {
  107.         filename = argv[1];
  108.         if ((infile = fopen(filename,"r")) == NULL) {
  109.             perror(filename);
  110.             exit(1);
  111.         }
  112.         convert();
  113.         fclose(infile);
  114.     }
  115.         
  116. #if defined(ARGS)
  117.    else
  118.         while (optind < argc) {
  119.             filename = argv[optind];
  120.             optind++;
  121.             if ((infile = fopen(filename,"r")) == NULL) {
  122.                 perror(filename);
  123.                 continue;
  124.             }
  125.             convert();
  126.             fclose(infile);
  127.         }
  128. #endif
  129.  
  130. } /* main */
  131.  
  132.  
  133.  
  134. void convert()
  135. {
  136.     char ch;
  137.  
  138. /*    fprintf(stderr, "%s:\n", filename); */
  139.     if (checksignature())
  140.         return;
  141.     readscreen();
  142.     while ((ch = getc(infile)) != ';' && ch != EOF) {
  143.         switch (ch) {
  144.             case '\0':  break;  /* this kludge for non-standard files */
  145.             case ',':   if (readimage())
  146.                            return;
  147.                         break;
  148.             case '!':   readextension();
  149.                         break;
  150.             default:    fprintf(stderr, "illegal GIF block type\n");
  151.                         return;
  152.                         break;
  153.         }
  154.     }
  155.  
  156. } /* convert */
  157.  
  158.  
  159.  
  160. checksignature()
  161. {
  162.     char buf[6];
  163.  
  164.     fread(buf,1,6,infile);
  165.     if (strncmp(buf,"GIF",3)) {
  166.         fprintf(stderr, "file is not a GIF file\n");
  167.         return 1;
  168.     }
  169.     if (strncmp(&buf[3],"87a",3)) {
  170.         fprintf(stderr, "unknown GIF version number\n");
  171.         return 1;
  172.     }
  173.     return 0;
  174.  
  175. } /* checksignature */
  176.  
  177.  
  178.  
  179. /*
  180.  * Get information which is global to all the images stored in the file
  181.  */
  182.  
  183. void readscreen()
  184. {
  185.     unsigned char buf[7];
  186.  
  187.     fread(buf,1,7,infile);
  188.     screenwidth = buf[0] + (buf[1] << 8);
  189.     rscreenwidth = screenwidth + screenwidth%2; /* compensate odd widths */
  190.     screenheight = buf[2] + (buf[3] << 8);
  191.     global = buf[4] & 0x80;
  192.     if (global) {
  193.         globalbits = (buf[4] & 0x07) + 1;
  194.         fread(globalmap,3,1<<globalbits,infile);
  195.     }
  196.     bgcolor = buf[5];
  197. /*
  198.     fprintf(stderr, "    global screen: %dx%dx%d, backgroundcolor: %d\n",
  199.                 screenwidth, screenheight, 1<<globalbits, bgcolor);
  200. */
  201.  
  202. } /* readscreen */
  203.  
  204.  
  205.  
  206.  
  207. readimage()
  208. {
  209.     unsigned char buf[9];
  210.     bool local, interleaved;
  211.     char localmap[256][3];
  212.     int localbits;
  213.     register row;
  214.     register i;
  215.  
  216.     if (fread(buf, 1, 9, infile) == 0) {
  217.         perror(filename);
  218.         exit(1);
  219.     }
  220.     left = buf[0] + (buf[1] << 8);
  221.     top = buf[2] + (buf[3] << 8);
  222.     width = buf[4] + (buf[5] << 8);
  223.     rwidth = width + width%2; /* compensate odd widths */
  224.     height = buf[6] + (buf[7] << 8);
  225.     local = buf[8] & 0x80;
  226.     interleaved = buf[8] & 0x40;
  227. /*
  228.     fprintf(stderr, "    image: %dx%d %s  org: %d,%d\n", width, height,
  229.               interleaved ? "interleaved" : "", left, top);
  230. */
  231.     if (local == 0 && global == 0) {
  232.         fprintf(stderr, "no colormap present for image\n");
  233.         return 1;
  234.     }
  235.     if ((raster = (unsigned char*) malloc(rwidth*height)) == NULL) {
  236.         fprintf(stderr, "not enough memory for image\n");
  237.         return 1;
  238.     }
  239.     if (readraster(width, height))
  240.         return 1;
  241.  
  242.     if (local) {
  243.         localbits = (buf[8] & 0x7) + 1;
  244. /*
  245.         fprintf(stderr, "   local colors: %d\n", 1<<localbits);
  246. */
  247.         fread(localmap, 3, 1<<localbits, infile);
  248.         initraster(1<<localbits);
  249.         initcolors(localmap, 1<<localbits, bgcolor);
  250.     } else if (global) {
  251.         initraster(1<<globalbits);
  252.         initcolors(globalmap, 1<<globalbits, bgcolor);
  253.     }
  254.  
  255.     rasterize(interleaved, raster);
  256.     free(raster);
  257.  
  258.     return 0;
  259.  
  260. } /* readimage */
  261.  
  262.  
  263.  
  264. /*
  265.  * Read a GIF extension block (and do nothing with it).
  266.  */
  267.  
  268. void readextension()
  269. {
  270.     unsigned char code;
  271.     int count;
  272.     char buf[255];
  273.  
  274.     code = getc(infile);
  275.     while (count = getc(infile))
  276.         fread(buf, 1, count, infile);
  277.  
  278. } /* readextension */
  279.  
  280.  
  281.  
  282. /*
  283.  * Decode a raster image
  284.  */
  285.  
  286. readraster(width, height)
  287. unsigned width,height;
  288. {
  289.         unsigned char *fill = raster;
  290.         unsigned char buf[255];
  291.         register bits=0;
  292.         register unsigned datum=0;
  293.         register unsigned char *ch;
  294.         register int count, code;
  295.  
  296.         datasize = getc(infile);
  297.         clear = 1 << datasize;
  298.         eoi = clear + 1;
  299.         avail = clear + 2;
  300.         oldcode = -1;
  301.         codesize = datasize + 1;
  302.         codemask = (1 << codesize) - 1;
  303.         for (code = 0; code < clear; code++) {
  304.             prefix[code] = 0;
  305.             suffix[code] = code;
  306.         }
  307.         stackp = stack;
  308.         for (count = getc(infile); count > 0; count = getc(infile)) {
  309.             fread(buf,1,count,infile);
  310.             for (ch=buf; count-- > 0; ch++) {
  311.                 datum += *ch << bits;
  312.                 bits += 8;
  313.                 while (bits >= codesize) {
  314.                     code = datum & codemask;
  315.                     datum >>= codesize;
  316.                     bits -= codesize;
  317.                     if (code == eoi) {               /* This kludge put in */
  318. /*
  319.                         fprintf(stderr, "found eoi code\n");
  320. */
  321.                         goto exitloop;               /* because some GIF files*/
  322.                     }                                /* aren't standard */
  323.                     if (process(code, &fill)) {
  324.                         goto exitloop;
  325.                     }
  326.                 }
  327.             }
  328.             if (fill >= raster + width*height) {
  329.                 fprintf(stderr, "raster full before eoi code\n");
  330.                 goto exitloop;
  331.             }
  332.         }
  333. exitloop:
  334.         if (fill != raster + width*height)  {
  335.             fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
  336.                       (long) (fill-raster));
  337.             fprintf(stderr, "         instead of %ld bytes\n",
  338.                       (long) width*height);
  339.             return 0; /* can still draw a picture ... */
  340.         }
  341.  
  342.         return 0;
  343.  
  344. } /* readraster */
  345.  
  346.  
  347.  
  348.  
  349. /*
  350.  * Process a compression code.  "clear" resets the code table.  Otherwise
  351.  * make a new code table entry, and output the bytes associated with the
  352.  * code.
  353.  */
  354.  
  355. process(code, fill)
  356. register code;
  357. unsigned char **fill;
  358. {
  359.         int incode;
  360.         static unsigned char firstchar;
  361.  
  362.         if (code == clear) {
  363.             codesize = datasize + 1;
  364.             codemask = (1 << codesize) - 1;
  365.             avail = clear + 2;
  366.             oldcode = -1;
  367.             return 0;
  368.         }
  369.  
  370.         if (oldcode == -1) {
  371.             *(*fill)++ = suffix[code];
  372.             firstchar = oldcode = code;
  373.             return 0;
  374.         }
  375.  
  376.         if (code > avail) {
  377.             fprintf(stderr, "code % d to large for %d\n", code, avail);
  378.             return 1; 
  379.         }
  380.  
  381.         incode = code;
  382.         if (code == avail) {      /* the first code is always < avail */
  383.             *stackp++ = firstchar;
  384.             code = oldcode;
  385.         }
  386.         while (code > clear) {
  387.             *stackp++ = suffix[code];
  388.             code = prefix[code];
  389.         }
  390.  
  391.         *stackp++ = firstchar = suffix[code];
  392.         prefix[avail] = oldcode;
  393.         suffix[avail] = firstchar;
  394.         avail++;
  395.  
  396.         if (((avail & codemask) == 0) && (avail < 4096)) {
  397.             codesize++;
  398.             codemask += avail;
  399.         }
  400.  
  401.         oldcode = incode;
  402.         do {
  403.             *(*fill)++ = *--stackp;
  404.         } while (stackp > stack);
  405.  
  406.         return 0;
  407.  
  408. } /* process */
  409.  
  410.  
  411.  
  412. void initraster(numcols)
  413. int numcols;
  414. {
  415.  
  416.   header.ras_magic= 0x59a66a95;
  417.   header.ras_width= rwidth;
  418.   header.ras_height= height;
  419.   header.ras_depth= 8;
  420.   header.ras_length= rwidth * height;
  421.   header.ras_type= RT_STANDARD;
  422.   header.ras_maptype= RMT_EQUAL_RGB;
  423.   header.ras_maplength= 3*numcols;
  424.  
  425.   if (fwrite(&header, sizeof(header), 1, stdout) == 0) {
  426.     perror(progname);
  427.     exit(1);
  428.   }
  429.  
  430.  
  431. } /* initraster */
  432.  
  433.  
  434.  
  435. /*
  436.  * Convert a color map (local or global) to arrays with R, G and B
  437.  * values. Pass colors to SUNVIEW and set the background color.
  438.  */
  439.  
  440. void initcolors(colormap, ncolors, bgcolor)
  441. unsigned char colormap[COLSIZE][3];
  442. int ncolors;
  443. int bgcolor;
  444. {
  445.     register i;
  446.     unsigned char red[COLSIZE];
  447.     unsigned char green[COLSIZE];
  448.     unsigned char blue[COLSIZE];
  449.  
  450. /*
  451. fprintf(stderr, "            ");
  452. */
  453.     for (i = 0; i < ncolors; i++) {
  454.         red[i]   = colormap[i][0];
  455.         green[i] = colormap[i][1];
  456.         blue[i]  = colormap[i][2];
  457. /*
  458. fprintf(stderr, "   %3u: %3u, %3u, %3u", i, red[i], green[i], blue[i]);
  459. if (i%3 == 2) fprintf(stderr, "\n            ");
  460. */
  461.     }
  462.  
  463. /*
  464. fprintf(stderr, "\n      Background: %3u: %3u, %3u, %3u\n", bgcolor,
  465.                           red[bgcolor], green[bgcolor], blue[bgcolor]);
  466. */
  467.  
  468.   if (fwrite(red, 1, ncolors, stdout) == 0) {
  469.     perror(progname);
  470.     exit(1);
  471.   }
  472.   if (fwrite(green, 1, ncolors, stdout) == 0) {
  473.     perror(progname);
  474.     exit(1);
  475.   }
  476.   if (fwrite(blue, 1, ncolors, stdout) == 0) {
  477.     perror(progname);
  478.     exit(1);
  479.   }
  480.   
  481. } /* initcolors */
  482.  
  483.  
  484.  
  485. /*
  486.  * Read a row out of the raster image and write it to the screen
  487.  */
  488.  
  489. rasterize(interleaved, raster)
  490. int interleaved;
  491. register unsigned char *raster;
  492. {
  493.     register row, col;
  494.     register unsigned char *rr;
  495.     unsigned char * newras;
  496.     
  497.    
  498.     
  499. #define DRAWSEGMENT(offset, step)                       \
  500.         for (row = offset; row < height; row += step) { \
  501.             rr = newras + row*rwidth;                   \
  502.             bcopy(raster, rr, width);                   \
  503.             raster += width;                            \
  504.         }
  505.  
  506.  
  507.     if ((newras = (unsigned char*) malloc(rwidth*height)) == NULL) {
  508.         fprintf(stderr, "not enough memory for image\n");
  509.         return 1;
  510.     }
  511.     rr = newras;
  512.     if (interleaved) {
  513.         DRAWSEGMENT(0, 8);
  514.         DRAWSEGMENT(4, 8);
  515.         DRAWSEGMENT(2, 4);
  516.         DRAWSEGMENT(1, 2);
  517.     }
  518.     else 
  519.         DRAWSEGMENT(0, 1);
  520.  
  521.     if (!fwrite(newras, 1, rwidth*height, stdout)) {
  522.         perror(progname);
  523.         exit(1);
  524.     }
  525.  
  526.     free(newras);
  527.  
  528.  
  529. } /* rasterize */
  530.  
  531.  
  532.  
  533. void usage()
  534. {
  535.  
  536.         fprintf(stderr, "usage: %s [-l<num] [-s<num>] [-b] gif-files\n",
  537.                         progname);
  538.  
  539. } /* usage */
  540.  
  541.