home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Web / Utilities / wwwcount-2.3 / combine / readgif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-02  |  8.0 KB  |  441 lines

  1. /*
  2.  *    ReadGIFImage - reads a GIF Image
  3.  *
  4.  *    RCS:
  5.  *        $Revision: 2.3 $
  6.  *        $Date: 1996/05/03 02:21:34 $
  7.  *
  8.  *    Security:
  9.  *        Unclassified
  10.  *
  11.  *    Description:
  12.  *        Adapted mostly from ImageMagick 3.1
  13.  *
  14.  *    Input Parameters:
  15.  *        type    identifier    description
  16.  *
  17.  *        text
  18.  *
  19.  *    Output Parameters:
  20.  *        type    identifier    description
  21.  *
  22.  *        text
  23.  *
  24.  *    Return Values:
  25.  *        value    description
  26.  *
  27.  *    Side Effects:
  28.  *        text
  29.  *
  30.  *    Limitations and Comments:
  31.  *        text
  32.  *
  33.  *    Development History:
  34.  *        when    who        why
  35.  *    6/28/94        muquit    first cut
  36.  */
  37.  
  38. #include "combine.h"
  39. #include "defines.h"
  40. #include "errcds.h"
  41.  
  42.  
  43. int ReadGIFImage (image)
  44. Image
  45.     *image;
  46. {
  47.  
  48. #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
  49. #define LSBFirstOrder(x, y)    (((y) << 8) | (x))
  50.  
  51.     int
  52.         rc = 0;
  53.  
  54.     int
  55.         pass,
  56.         x, y;
  57.     
  58.     short int
  59.         transparency_index;
  60.  
  61.     register int
  62.         i;
  63.  
  64.     register Runlength
  65.         *q;
  66.     
  67.     register unsigned char
  68.         *p;
  69.     
  70.     unsigned char
  71.         c,
  72.         *global_colormap,
  73.         header[MaxTextLength],
  74.         type[12];
  75.  
  76.     unsigned int
  77.         global_colors,
  78.         image_count,
  79.         interlace,
  80.         local_colormap;
  81.  
  82.     FILE
  83.         *fp=(FILE *) NULL;
  84.     
  85.     Image
  86.         *next_image = (Image *) NULL;
  87.  
  88.     fp = fopen (image->filename, "rb");
  89.  
  90.     if (fp == (FILE *) NULL)
  91.     {
  92.         fprintf (stderr, "could not open file: %s\n",image->filename);
  93.         rc = OPEN_FAILED;
  94.         goto ExitProcessing;
  95.     }
  96.  
  97.     image->fp = fp;
  98.  
  99.     rc = Read_Data ((char *) type, 1, 6, fp);
  100.  
  101.     if ((rc == 1) || ((strncmp((char *) type, "GIF87", 5) != 0) &&
  102.         (strncmp ((char *) type, "GIF89", 5) != 0)))
  103.     {
  104.         fprintf (stderr, "Not a GIF Image: [%s]\n",image->filename);
  105.         rc = NOT_A_GIF_FILE;
  106.         goto ExitProcessing;
  107.     }
  108.  
  109. #ifdef DEBUG
  110.     fprintf (stderr, " File Type: %s\n",type);
  111. #endif
  112.     rc = Read_Data ((char *) header, 1, 7, fp);
  113.  
  114.     if (rc == 1)
  115.     {
  116.         rc = FAILED_TO_READ_SCREEND;
  117.         goto ExitProcessing;
  118.     }
  119.  
  120.     global_colors = 0;
  121.     global_colormap = (unsigned char *) NULL;
  122.  
  123.     if (BitSet(header[4], 0x80))
  124.     {
  125.         global_colors = 1 << ((header[4] & 0x07) + 1);
  126.  
  127.         global_colormap = (unsigned char *)
  128.             malloc (3*global_colors*sizeof(unsigned char));
  129.  
  130.         if (global_colormap == (unsigned char *) NULL)
  131.         {
  132.             rc = MALLOC_FAILED;
  133.             goto ExitProcessing;
  134.         }
  135.  
  136.         (void) Read_Data ((char *) global_colormap, 3, (int) global_colors,
  137.             fp);
  138.     }
  139.  
  140.     transparency_index = (-1);
  141.     image_count = 0;
  142.  
  143.     for ( ; ; )
  144.     {
  145.         rc = Read_Data ((char *) &c, 1, 1, fp);
  146.  
  147.         if (rc == 1)
  148.         {
  149.             rc = 0;
  150.             break;
  151.         }
  152.  
  153.         if (c == ';')    /* terminator */
  154.             break;
  155.         
  156.         if (c == '!')    /* EXTENSION ! */
  157.         {
  158.             rc = Read_Data ((char *) &c, 1, 1, fp);
  159.  
  160.             if (rc == 1)
  161.             {
  162.                 rc = READ_ERR_EXT_BLOCK;
  163.                 goto ExitProcessing;
  164.             }
  165.  
  166.             switch (c)
  167.             {
  168.                 case 0xf9:    /* Transperency */
  169.                 {
  170.                     while (ReadDataBlock ((char *) header, fp) !=0)
  171.                     if ((header[0] * 0x01) == 1)
  172.                     {
  173.                         transparency_index = header[3];
  174.                     }
  175.                     break;
  176.                 
  177.                 }
  178.                 case 0xfe:    /* comment extension */
  179.                 {
  180.                     int
  181.                         length;
  182.                     
  183.                     for ( ; ; )
  184.                     {
  185.                         length = ReadDataBlock ((char *) header, fp);
  186.                         if (length <= 0)
  187.                             break;
  188.  
  189.                     if (image->comments != (char *) NULL)
  190.                     {
  191.                         image->comments=(char *) realloc((char *) 
  192.                             image->comments,
  193.                             (strlen(image->comments)+length+1)*
  194.                             sizeof(char));
  195.                     }
  196.                     else
  197.                     {
  198.                         image->comments = (char *) malloc ((length + 1)*
  199.                             sizeof(char));
  200.                         if (image->comments != (char *) NULL)
  201.                         {
  202.                             *image->comments = '\0';
  203.                         }
  204.                     }
  205.  
  206.                     if (image->comments == (char *) NULL)
  207.                     {
  208.                         rc = MALLOC_FAILED;
  209.                         goto ExitProcessing;
  210.                     }
  211.                     header[length] = '\0';
  212.                     (void) strcat (image->comments, (char *) header);
  213. #ifdef DEBUG
  214.     fprintf (stderr, " GIF: comment: %s\n", image->comments);
  215. #endif
  216.                     }
  217.                     break;
  218.                 }    
  219.  
  220.                 default:
  221.                 {
  222.                     while (ReadDataBlock ((char *) header, fp) != 0);
  223.                     break;
  224.                 }
  225.             }
  226.         }
  227.  
  228.  
  229.         if (c != ',')
  230.             continue;
  231.  
  232.  
  233.         if (image_count != 0)
  234.         {
  235.             if (next_image != (Image *) NULL)
  236.                 DestroyAnyImageStruct(&next_image);
  237.  
  238.             next_image = AllocateImageStruct();
  239.             if (next_image == (Image *)NULL)
  240.             {
  241.                 (void) fprintf (stderr,"Unable to Display GIF!\n");
  242.                 rc=MALLOC_FAILED;
  243.                 goto ExitProcessing;
  244.             }
  245.             (void) strcpy(next_image->filename, image->filename);
  246.             next_image->fp = fp;
  247.  
  248.             if (image != (Image *) NULL)
  249.                 DestroyAnyImageStruct(&image);
  250.             image=next_image;
  251.         }
  252.         image_count++;
  253.         /*
  254.         ** can't handle multiple images in one file
  255.         */
  256.  
  257.         /*
  258.         ** read Header Now
  259.         */
  260.  
  261.         rc = Read_Data ((char *) header, 1, 9, fp);
  262.  
  263.         if (rc == 1)
  264.         {
  265.             rc = READ_ERR_WIDTH_HEIGHT;
  266.             goto ExitProcessing;
  267.         }
  268.  
  269.         interlace = BitSet (header[8], 0x40);
  270.         local_colormap = BitSet (header[8], 0x80);
  271.         image->columns = LSBFirstOrder (header[4], header[5]);
  272.         image->rows = LSBFirstOrder (header[6], header[7]);
  273.         image->packets = image->columns*image->rows;
  274.  
  275.         if (image->pixels != (Runlength *) NULL)
  276.         {
  277.             (void) free ((char *) image->pixels);
  278.         }
  279.  
  280.         image->pixels = (Runlength *)
  281.             malloc (image->packets*sizeof(Runlength));
  282.  
  283.         if (image->pixels == (Runlength *) NULL)
  284.         {
  285.             rc = MALLOC_FAILED;
  286.             goto ExitProcessing;
  287.         }
  288.         
  289.         image->class = PseudoClass;
  290.         image->colors = 
  291.             !local_colormap ? global_colors : 1 << ((header[8] & 0x07) + 1);
  292. #ifdef DEBUG
  293.     fprintf (stderr, " GIF: no of colors: %d\n", image->colors);
  294. #endif
  295.  
  296.         image->colormap = (RGB *) malloc (image->colors*sizeof(RGB));
  297.  
  298.         if (image->colormap == (RGB *) NULL)
  299.         {
  300.             rc = MALLOC_FAILED;
  301.             goto ExitProcessing;
  302.         }
  303.  
  304.         if (!local_colormap)
  305.         {
  306.             p = global_colormap;
  307.  
  308.             for (i=0; i < image->colors; i++)
  309.             {
  310.                 image->colormap[i].red = (*p++);
  311.                 image->colormap[i].green = (*p++);
  312.                 image->colormap[i].blue = (*p++);
  313.             }
  314.         }
  315.         else
  316.         {
  317.             unsigned char
  318.                 *colormap;
  319.  
  320.             colormap = (unsigned char *)
  321.                 malloc (3*image->colors*sizeof(unsigned char));
  322.  
  323.             if (colormap == (unsigned char *) NULL)
  324.             {
  325.                 rc = MALLOC_FAILED;
  326.                 goto ExitProcessing;
  327.             }
  328.  
  329.             (void) Read_Data ((char *) colormap, 3, (int) image->colors, 
  330.                 fp);
  331.             
  332.             p = colormap;
  333.  
  334.             for (i=0; i < image->colors; i++)
  335.             {
  336.                 image->colormap[i].red = (*p++);
  337.                 image->colormap[i].green = (*p++);
  338.                 image->colormap[i].blue = (*p++);
  339.             }
  340.             (void) free ((char *) colormap);
  341.         }
  342.         rc = LZWDecodeImage (image);
  343.         if (interlace)
  344.            { 
  345.             Image
  346.                   *interlaced_image;
  347.             register Runlength
  348.                    *p;
  349.  
  350.             static int
  351.             interlace_rate[4] = { 8, 8, 4, 2 },
  352.             interlace_start[4] = { 0, 4, 2, 1 };
  353.             
  354. #ifdef DEBUG
  355.     fprintf (stderr, " GIF: processing Interlaced image\n");
  356. #endif
  357.             interlaced_image = DuplicateImage (image, image->columns,
  358.                 image->rows, True);
  359.  
  360.             if (interlaced_image == (Image *) NULL)
  361.             {
  362.                 rc = MALLOC_FAILED;
  363.                 /* destroy interlaced_image */
  364.                 goto ExitProcessing;
  365.             } 
  366.             
  367.             p = interlaced_image->pixels;
  368.             q = image->pixels;
  369.  
  370.             for (pass=0; pass < 4; pass++)
  371.             {
  372.                 y = interlace_start[pass];
  373.                 
  374.                 while (y < image->rows)
  375.                 {
  376.                     q = image->pixels + (y*image->columns);
  377.                     for (x=0; x < image->columns; x++)
  378.                     {
  379.                         *q = (*p);
  380.                         p++;
  381.                         q++;
  382.                     }
  383.                     y+=interlace_rate[pass];
  384.                 }
  385.             }
  386.             DestroyAnyImageStruct (&interlaced_image);
  387.         }/*if interlace*/
  388.  
  389.             /*
  390.             ** handle transparency
  391.             */
  392.  
  393.             if (transparency_index >= 0)
  394.             {
  395.                 /*
  396.                 ** create alpha channel
  397.                 */
  398.                 q=image->pixels;
  399.                 for(i=0; i < image->packets; i++)
  400.                 {
  401.                     if (q->index != (unsigned short) transparency_index)
  402.                         q->index=Opaque;
  403.                     else
  404.                         q->index=Transparent;
  405.                     q++;
  406.                 }
  407.                 transparency_index=(-1);
  408.                 image->class=DirectClass;
  409.                 image->alpha=True;
  410.             }
  411.  
  412.             if (rc == 1)
  413.             {
  414.                 rc = 0;
  415.                 (void) fprintf (stderr," Error\n");
  416.                 break;
  417.             }
  418.  
  419.         break;
  420.     }/* for (;;) */
  421.  
  422.         if (global_colormap != (unsigned char *) NULL)
  423.         {
  424.             (void) free ((char *) global_colormap);
  425.         }
  426.  
  427.         if (image->pixels == (Runlength *) NULL)
  428.         {
  429.             rc = CORRUPT_GIF_IMAGE;
  430.             goto ExitProcessing;
  431.         }
  432.  
  433.         CompressColormap(image);
  434. ExitProcessing:
  435.     if (fp != (FILE *) NULL)
  436.         (void) fclose ((FILE *) fp);
  437.     return (rc);
  438.  
  439. }
  440.     
  441.