home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / fbm / part07 / flgifr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-08  |  13.4 KB  |  553 lines

  1. /*****************************************************************
  2.  * flgifr.c: FBM Library 0.91 (Beta test) 26-Apr-89  Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  5.  * use this file in whole or in part provided that you do not sell it
  6.  * for profit and that this copyright notice is retained unchanged.
  7.  *
  8.  * Derived from 'giftorle', written by David Koblas
  9.  *
  10.  * +------------------------------------------------------------------+ 
  11.  * | Copyright 1989, David Koblas.                                    | 
  12.  * |   You may copy this file in whole or in part as long as you      | 
  13.  * |   don't try to make money off it, or pretend that you wrote it.  | 
  14.  * +------------------------------------------------------------------+ 
  15.  *
  16.  * flgifr.c:
  17.  *
  18.  * CONTENTS
  19.  *    read_gif (image, stream, mstr, mlen)
  20.  *
  21.  * HISTORY
  22.  * 26-Apr-89  Michael Mauldin (mlm) at Carnegie Mellon University
  23.  *    Beta release (version 0.91) mlm@cs.cmu.edu
  24.  *
  25.  * 19-Feb-89  Michael Mauldin (mlm) at Carnegie Mellon University
  26.  *    Changed name to flgifr from flgif (since there is now an flgifw)
  27.  *
  28.  * 13-Feb-89  Michael Mauldin (mlm) at Carnegie Mellon University
  29.  *    Modified from gif2rle program Copyright 1989 by David Koblas.
  30.  *    Converted to produce FBM image format in memory.
  31.  *
  32.  *
  33.  *****************************************************************/
  34.  
  35. # include <stdio.h>
  36. # include "fbm.h"
  37.  
  38. #define MAXCOLORMAPSIZE         256
  39.  
  40. #define TRUE    1
  41. #define FALSE   0
  42. #define BAD     0
  43. #define OK      1
  44.  
  45. #define MAX_LWZ_BITS            12
  46.  
  47. #define ReadOK(file,buffer,len) (fread(buffer,len,1,file)!=0)
  48. #define EasyFail(str,status)    while(1){fprintf(stderr,str);return(status);}
  49. #define HardFail(str,status)    while(1){fprintf(stderr,str);exit  (status);}
  50.  
  51. #define LM_to_uint(a,b)                 (((b)<<8)|(a))
  52.  
  53. #ifndef lint
  54. static char *fbmid =
  55.     "$FBM flgifr.c <0.91> 26-Apr-89  (C) 1989 by Michael Mauldin$";
  56. #endif
  57.  
  58. read_gif (image, fd, mstr, mlen)
  59. FBM *image;
  60. FILE *fd;
  61. char *mstr;
  62. int mlen;
  63. {
  64.   unsigned char   buf[16];
  65.   unsigned char   c;
  66.   int             use_global_colormap;
  67.   int             bit_pixel;
  68.   int             count = 0;
  69.   int             rows, cols, rowlen, depth, colors;
  70.  
  71.   /* Read magic number 'GIF87a' */
  72.   buf[0] = NEXTMCH (fd, mstr, mlen) & 0xff;
  73.   buf[1] = NEXTMCH (fd, mstr, mlen) & 0xff;
  74.   buf[2] = NEXTMCH (fd, mstr, mlen) & 0xff;
  75.   buf[3] = NEXTMCH (fd, mstr, mlen) & 0xff;
  76.   buf[4] = NEXTMCH (fd, mstr, mlen) & 0xff;
  77.   buf[5] = NEXTMCH (fd, mstr, mlen) & 0xff;
  78.   buf[6] = 0;
  79.  
  80.   if (strcmp (buf, GIF_MAGIC) != 0)
  81.     EasyFail("bad magic number (version mismatch?)\n", BAD);
  82.  
  83.   if (!ReadOK (fd, buf, 7))
  84.     EasyFail("error reading screen descriptor\n", BAD);
  85.  
  86.   /* Read image data */
  87.   image->hdr.cols = cols = LM_to_uint(buf[0], buf[1]);
  88.   image->hdr.rows = rows = LM_to_uint(buf[2], buf[3]);
  89.   image->hdr.planes = 1;
  90.   image->hdr.bits = depth = (buf[4] & 0x07) + 1;
  91.   image->hdr.physbits = 8;
  92.  
  93.   /* Pad to even byte */
  94.   if (depth == 1)
  95.   { image->hdr.rowlen = rowlen = 16 * ((cols + 15) / 16); }
  96.   else
  97.   { image->hdr.rowlen = rowlen = 2 * ((cols + 1) / 2); }
  98.  
  99.   image->hdr.plnlen = rowlen * rows;
  100.   colors = 1 << depth;
  101.   image->hdr.clrlen = 3 * colors;
  102.   image->hdr.title[0] = '\0';
  103.   image->hdr.credits[0] = '\0';
  104.   
  105.   /* Try to guess aspect ratio */
  106.   if (cols == 320 && rows == 200)    { image->hdr.aspect = 1.2; }
  107.   else if (cols == 320 && rows == 175)    { image->hdr.aspect = 1.2; }
  108.   else if (cols == 320 && rows == 400)    { image->hdr.aspect = 0.6; }
  109.   else if (cols == 320 && rows == 350)    { image->hdr.aspect = 0.6; }
  110.   else if (cols == 640 && rows == 200)    { image->hdr.aspect = 2.4; }
  111.   else if (cols == 640 && rows == 175)    { image->hdr.aspect = 2.4; }
  112.   else if (cols == 640 && rows == 400)    { image->hdr.aspect = 1.2; }
  113.   else if (cols == 640 && rows == 350)    { image->hdr.aspect = 1.2; }
  114.   else                    { image->hdr.aspect = 1.0; }
  115.   
  116. # ifdef DEBUG
  117.   fprintf (stderr, "\nImage file header:\n\n");
  118.   fprintf (stderr, "cols       %d\n", image->hdr.cols);
  119.   fprintf (stderr, "rows       %d\n", image->hdr.rows);
  120.   fprintf (stderr, "planes     %d\n", image->hdr.planes);
  121.   fprintf (stderr, "bits       %d\n", image->hdr.bits);
  122.   fprintf (stderr, "physbits   %d\n", image->hdr.physbits);
  123.   fprintf (stderr, "rowlen     %d\n", image->hdr.rowlen);
  124.   fprintf (stderr, "plnlen     %d\n", image->hdr.plnlen);
  125.   fprintf (stderr, "clrlen     %d\n", image->hdr.clrlen);
  126.   fprintf (stderr, "aspect     %1.3lf\n", image->hdr.aspect);
  127.   fprintf (stderr, "title      '%s'\n", image->hdr.title);
  128.   fprintf (stderr, "credits    '%s'\n", image->hdr.credits);
  129. # endif
  130.   
  131.   /* Allocate image */
  132.   alloc_fbm (image);
  133.  
  134.   /* Read colormap if given */
  135.   if ((buf[4] & 0x80) == 0x80)
  136.   { if (ReadColorMap (fd, colors, image->cm) == BAD)
  137.       return (BAD);
  138.   }
  139.  
  140.   while (1)
  141.   { if (!ReadOK (fd, &c, 1))
  142.       EasyFail("No image data -- EOF\n", BAD);
  143.  
  144.     if (c == ';')
  145.       return OK;
  146.  
  147.     if (c == '!')
  148.     { if (!ReadOK (fd, &c, 1))
  149.         EasyFail("No extention function code -- EOF\n", BAD);
  150.       if (IgnoreExtention(fd) == BAD)
  151.         return (BAD);
  152.     }
  153.  
  154.     if (c != ',')
  155.     { fprintf(stderr, "Bogus character ignoring '%c'\n", c);
  156.       continue;
  157.     }
  158.  
  159.     if (count == 1)
  160.       HardFail("This file contains more than one image! FAILING\n", 1);
  161.     count++;
  162.  
  163.     if (!ReadOK (fd, buf, 9))
  164.       EasyFail("Couldn't read left/top/width/height\n", TRUE);
  165.  
  166. # ifdef DEBUG
  167.     fprintf (stderr, "Image description: ");
  168.     for (i=0; i<9; i++) fprintf (stderr, "%02x", buf[i]);
  169.     fprintf (stderr, "\n");
  170. # endif
  171.  
  172.     if ((buf[8] & 0x80) == 0x80)
  173.       use_global_colormap = FALSE;
  174.     else
  175.       use_global_colormap = TRUE;
  176.  
  177.     bit_pixel = 2 << (buf[8] & 0x07);
  178.     
  179.     if (!use_global_colormap && bit_pixel > colors)
  180.     { HardFail ("Local colormap has more colors than global!\n", BAD); }
  181.  
  182.     if (!use_global_colormap)
  183.     { fprintf (stderr,
  184.                "Overriding global colormap (%d) with local (%d)\n",
  185.                colors, bit_pixel);
  186.  
  187.       colors = bit_pixel;
  188.       image->hdr.clrlen = 3 * colors;
  189.       
  190.       if (ReadColorMap(fd, colors, image->cm) == BAD)
  191.         return BAD;
  192.     }
  193.  
  194.     fprintf (stderr, "Reading GIF image [%dx%d], %d bits",
  195.          image->hdr.cols, image->hdr.rows, image->hdr.bits);
  196.     if (image->hdr.clrlen > 0)
  197.     { fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); }
  198.     else if (image->hdr.bits > 1)
  199.     { fprintf (stderr, ", grayscale"); }
  200.  
  201.     if ((buf[8] & 0x40) == 0x40)
  202.     { fprintf (stderr, ", interlaced"); }
  203.     fprintf (stderr, "\n");
  204.  
  205.  
  206.     if ((buf[8] & 0x40) == 0x40)
  207.     { 
  208.       if (ReadInterlaced(fd,
  209.              LM_to_uint(buf[4],buf[5]),
  210.              LM_to_uint(buf[6],buf[7]),
  211.              image->bm,
  212.              rowlen) == BAD)
  213.     return BAD;
  214.     }
  215.     else
  216.     { if (ReadRaster(fd,
  217.                      LM_to_uint(buf[4], buf[5]),
  218.                      LM_to_uint(buf[6], buf[7]),
  219.                      image->bm,
  220.                      rowlen) == BAD)
  221.         return BAD;
  222.       else
  223.         return OK;
  224.     }
  225.   }
  226. }
  227.  
  228. ReadColorMap (fd, number, buffer)
  229.   FILE           *fd;
  230.   int             number;
  231.   unsigned char   *buffer;
  232. {
  233.   int             i;
  234.   unsigned char   rgb[3], *red, *grn, *blu;
  235.  
  236.   red = buffer;
  237.   grn = buffer + number;
  238.   blu = grn + number;
  239.  
  240.   for (i = 0; i < number; i++)
  241.   { if (!ReadOK (fd, rgb, sizeof(rgb)))
  242.       EasyFail("Bogus colormap\n", BAD);
  243.  
  244.     red[i] = rgb[0];
  245.     grn[i] = rgb[1];
  246.     blu[i] = rgb[2];
  247.   }
  248.  
  249.   return OK;
  250. }
  251.  
  252. IgnoreExtention(fd)
  253.   FILE           *fd;
  254. {
  255.   static char     buf[256];
  256.   unsigned char   c;
  257.  
  258.   while (1)
  259.   {
  260.     if (!ReadOK (fd, &c, 1))
  261.       EasyFail("EOF in extention\n", BAD);
  262.  
  263.     if (c == 0)
  264.       return OK;
  265.  
  266.     if (read(fd, buf, (int) c) != (int) c)
  267.       EasyFail("EOF in extention\n", BAD);
  268.   }
  269. }
  270.  
  271. GetCode(fd, code_size, flag)
  272.   FILE           *fd;
  273.   int             code_size;
  274.   int             flag;
  275. {
  276.   static unsigned char buf[280];
  277.   static int      curbit, lastbit, done, last_byte;
  278.   int             i, j, ret;
  279.   unsigned char   count;
  280.  
  281.   if (flag)
  282.   {
  283.     curbit = 0;
  284.     lastbit = 0;
  285.     done = FALSE;
  286.     return 0;
  287.   }
  288.  
  289.   if ((curbit + code_size) >= lastbit)
  290.   { if (done)
  291.     { if (curbit >= lastbit)
  292.         EasyFail("Ran off the end of my bits\n", -1);
  293.     }
  294.     buf[0] = buf[last_byte - 2];
  295.     buf[1] = buf[last_byte - 1];
  296.  
  297.     if (!ReadOK (fd, &count, 1))
  298.     { EasyFail("Error in getting buffer size\n", -1); }
  299.  
  300.     if (count == 0)
  301.     { done = TRUE; } 
  302.  
  303.     else if (!ReadOK (fd, &buf[2], count))
  304.       EasyFail("Error in getting buffer\n", -1);
  305.  
  306.     last_byte = 2 + count;
  307.     curbit = (curbit - lastbit) + 16;
  308.     lastbit = (2 + count) * 8;
  309.   }
  310.  
  311.   ret = 0;
  312.  
  313.   for (i = curbit, j = 0; j < code_size; i++, j++)
  314.     ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
  315.  
  316.   curbit += code_size;
  317.  
  318.   return ret;
  319. }
  320.  
  321. LWZReadByte(fd, flag, input_code_size)
  322.   FILE           *fd;
  323.   int             flag;
  324.   int             input_code_size;
  325. {
  326.   static int      fresh = FALSE;
  327.   int             code, incode;
  328.   static int      code_size, set_code_size;
  329.   static int      max_code, max_code_size;
  330.   static int      firstcode, oldcode;
  331.   static int      clear_code, end_code;
  332.   static int      table[2][(1 << MAX_LWZ_BITS)];
  333.   static int      stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
  334.   register int    i;
  335.  
  336.   if (flag)
  337.   {
  338.     set_code_size = input_code_size;
  339.     code_size = set_code_size + 1;
  340.     clear_code = 1 << set_code_size;
  341.     end_code = clear_code + 1;
  342.     max_code_size = 2 * clear_code;
  343.     max_code = clear_code + 2;
  344.  
  345.     GetCode(fd, NULL, NULL);
  346.  
  347.     fresh = TRUE;
  348.  
  349.     for (i = 0; i < clear_code; i++)
  350.     {
  351.       table[0][i] = 0;
  352.       table[1][i] = i;
  353.     }
  354.  
  355.     for (; i < (1 << MAX_LWZ_BITS); i++)
  356.       table[0][i] = table[1][0] = 0;
  357.  
  358.     sp = stack;
  359.     return 0;
  360.   }
  361.   else if (fresh)
  362.   { fresh = FALSE;
  363.     do
  364.     { firstcode = oldcode =
  365.         GetCode(fd, code_size, FALSE);
  366.     } while (firstcode == clear_code);
  367.  
  368.     return firstcode;
  369.   }
  370.  
  371.   if (sp > stack)
  372.     return *--sp;
  373.  
  374.   while ((code = GetCode(fd, code_size, FALSE)) >= 0)
  375.   { if (code == clear_code)
  376.     { for (i = 0; i < clear_code; i++)
  377.       {table[0][i] = 0;
  378.         table[1][i] = i;
  379.       }
  380.  
  381.       for (; i < (1 << MAX_LWZ_BITS); i++)
  382.         table[0][i] = table[1][i] = 0;
  383.  
  384.       code_size = set_code_size + 1;
  385.       max_code_size = 2 * clear_code;
  386.       max_code = clear_code + 2;
  387.       sp = stack;
  388.       firstcode = oldcode =
  389.         GetCode(fd, code_size, FALSE);
  390.       return firstcode;
  391.     }
  392.     else if (code == end_code)
  393.     { unsigned char   count;
  394.       unsigned char   junk;
  395.  
  396.       while (ReadOK (fd, &count, 1) && (count != 0))
  397.         while (count-- != 0 && ReadOK (fd, &junk, 1));
  398.  
  399.       if (count != 0)
  400.         EasyFail("missing EOD in data stream (common occurance)\n", -3);
  401.  
  402.       return -2;
  403.     }
  404.  
  405.     incode = code;
  406.  
  407.     if (code >= max_code)
  408.     { *sp++ = firstcode;
  409.       code = oldcode;
  410.     }
  411.  
  412.     while (code >= clear_code)
  413.     {
  414.       *sp++ = table[1][code];
  415.       if (code == table[0][code])
  416.         EasyFail("Circular table entry BIG ERROR\n", -1);
  417.       code = table[0][code];
  418.     }
  419.  
  420.     *sp++ = firstcode = table[1][code];
  421.  
  422.     if ((code = max_code) < (1 << MAX_LWZ_BITS))
  423.     {
  424.       table[0][code] = oldcode;
  425.       table[1][code] = firstcode;
  426.       max_code++;
  427.  
  428.       if ((max_code >= max_code_size) &&
  429.           (max_code_size < (1 << MAX_LWZ_BITS)))
  430.       {
  431.         max_code_size *= 2;
  432.         code_size++;
  433.       }
  434.     }
  435.     oldcode = incode;
  436.  
  437.     if (sp > stack)
  438.       return *--sp;
  439.   }
  440.  
  441.   return code;
  442. }
  443.  
  444. ReadInterlaced(fd, len, height, buffer, rowlen)
  445.   FILE           *fd;
  446.   int             len, height;
  447.   unsigned char     *buffer;
  448.   int          rowlen;
  449. {
  450.   unsigned char   c;
  451.   register unsigned char *bmp;
  452.   register int    v;
  453.   register int    xpos = 0;
  454.   register int    ypos = 0, pass = 0;
  455.   register int    maxypos = 0;
  456.  
  457.  
  458.   if (!ReadOK(fd, &c, 1))
  459.     EasyFail("Bogus image data -- EOF\n", BAD);
  460.   if (LWZReadByte(fd, TRUE, c) < 0)
  461.     return BAD;
  462.  
  463.   while ((v = LWZReadByte(fd, FALSE, c)) >= 0)
  464.   {
  465.     if (xpos == 0)
  466.     { bmp = &(buffer[ypos * rowlen]);
  467.       if (ypos > height)
  468.       { fprintf (stderr, "Wanring Too much data, started to read line %d\n",
  469.          ypos);
  470.         return (OK);
  471.       }
  472.     }
  473.     
  474.     *bmp++ = v;
  475.  
  476.     if (++xpos == len)
  477.     {
  478.       xpos = 0;
  479.       switch (pass)
  480.       {
  481.        case 0: case 1:        ypos += 8; break;
  482.        case 2:            ypos += 4; break;
  483.        case 3:            ypos += 2; break;
  484.       }
  485.       
  486.       if (ypos > maxypos)    maxypos = ypos;
  487.  
  488.       if (ypos >= height)
  489.       {
  490.     switch (++pass)
  491.     {
  492.      case 1:        ypos = 4; break;
  493.      case 2:        ypos = 2; break;
  494.      case 3:        ypos = 1; break;
  495.     }
  496.       }
  497.     }
  498.   }
  499.  
  500.   if (maxypos >= height) return OK;
  501.  
  502.   if (v == (-2))
  503.     return OK;
  504.   return BAD;
  505. }
  506.  
  507. ReadRaster (fd, len, height, buffer, rowlen)
  508.   FILE           *fd;
  509.   int             len, height;
  510.   unsigned char  *buffer;
  511.   int             rowlen;
  512. {
  513.   unsigned char   c;
  514.   register unsigned char  *bmp;
  515.   register int    v;
  516.   register int    xpos = 0;
  517.   register int    ypos = 0;
  518.  
  519.   if (!ReadOK (fd, &c, 1))
  520.     EasyFail("Bogus image data -- EOF\n", TRUE);
  521.  
  522.   if (LWZReadByte(fd, TRUE, c) < 0)
  523.     return BAD;
  524.  
  525.   /* Read the raster data and dump it into the FBM bitmap */
  526.   while ((v = LWZReadByte(fd, FALSE, c)) >= 0)
  527.   {
  528.     if (xpos == 0)
  529.     { bmp = &(buffer[ypos++ * rowlen]);
  530.       if (ypos > height)
  531.       { fprintf (stderr, "Warning: too much data, started to read line %d\n",
  532.          ypos);
  533.         return (OK);
  534.       }
  535.     }
  536.     
  537.     *bmp++ = v;
  538.     
  539.     if (++xpos == len)
  540.  
  541.     if (xpos == len) xpos = 0;
  542.   }
  543.  
  544.   fprintf (stderr, "Done storing bitmap, xpos %d, ypos %d [%dx%d]\n",
  545.            xpos, ypos, len, height);
  546.  
  547.   if (ypos >= height) return OK;
  548.  
  549.   if (v == (-2))
  550.     return OK;
  551.   return BAD;
  552. }
  553.