home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / flgifr.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  15KB  |  575 lines

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