Advertisement
xerpi

gif

Apr 27th, 2012
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 52.27 KB | None | 0 0
  1. /* gifread.c given a filename.gif, alpha, returns width, height, rgb pixels */
  2. /*     int width, height; int alpha=0 to 255, or -1 for just rgb            */
  3. /*     unsigned char pixels[4*width*height]; or 3*width*height for alpha=-1 */
  4. /* call:  status = gifread("your-filename", alpha, &width, &height, pixels);*/
  5. /* status==0 for OK                                                         */
  6.  
  7. #include "gif.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10.  
  11. static FILE *fpGif;        /* Pointer to the input FILE stream, global for decoder  */
  12. static int bad_code_count; /* set by decoder */
  13. static int gifReadHead(char gifFileName[], BYTE rgbpix[]);
  14. static short int gif_decode(short int linewidth, BYTE rgbpix[]);
  15. static int nrgbpix;
  16. static int debug = 0; /* set to 1 for full debug printout */
  17. static int line_num;
  18. static int ipass;
  19. static int rgba=0;
  20. static int alph;
  21.  
  22. static GIFHEAD           gifHead;           /* GIF Header structure            */
  23. static GIFIMAGEDESC      gifImageDesc;      /* Logical Image Descriptor struct */
  24.  
  25. #define OUT_OF_MEMORY -10
  26. #define BAD_CODE_SIZE -20
  27. #define READ_ERROR -1
  28. #define WRITE_ERROR -2
  29. #define OPEN_ERROR -3
  30. #define CREATE_ERROR -4
  31.  
  32. int gifread(char filename[], int alpha, int *width, int *height, BYTE rgbpix[])
  33. {
  34.   int status;
  35.  
  36.   line_num = 0; /* needed for multiple calls in one program */
  37.   nrgbpix = 0;
  38.   ipass = 1;    /* pass number of interlace */
  39.   rgba = 0;
  40.   if(alpha>=0 && alpha<=255) { rgba = 1; alph = alpha; } /* 4 bytes per pixel */
  41.  
  42.   status = gifReadHead(filename, rgbpix);
  43.   *width  = gifImageDesc.ImageWidth;
  44.   *height = gifImageDesc.ImageHeight;
  45.   return status;
  46. } /* end gifread */
  47.  
  48. static int gifReadHead(char gifFileName[], BYTE rgbpix[])
  49. {
  50.     WORD i, j;              /* Loop counter                                 */
  51.     WORD tableSize;         /* Number of entires in the global color table  */
  52.     WORD lineCount;         /* Count of the number of table lines displayed */
  53.     WORD imageCount;        /* Count of the number of images in the file    */
  54.     WORD blockCount;        /* Running count of the number of data blocks   */
  55.     BYTE Identifier;        /* Extension block identifier holder            */
  56.     BYTE Label;             /* Extension block label holder                 */
  57.     BYTE dataSize;          /* Size of data sub-block holder                */
  58.     int  blkSize;           /* Data block byte count, (int) of above        */
  59.     BYTE dataBlock[256];    /* Hold a data block                            */
  60.     BYTE *ptr;              /* Scratch pointer variable                     */
  61.     BYTE code_size;
  62.     short int err;
  63.  
  64.     GIFPLAINTEXT      gifPlainText;      /* Plain Text Extension structure  */
  65.     GIFAPPLICATION    gifApplication;    /* Application Extension structure */
  66.     GIFCOMMENT        gifComment;        /* Comment Extension structure     */
  67.     GIFGRAPHICCONTROL gifGraphicControl; /* Graphic Control Extension strct */
  68.  
  69.     if(debug)printf("gifhead - Display the header info within a GIF image file \n");
  70.  
  71.     /* Open the GIF image file */
  72.     if ((fpGif = fopen(gifFileName, "rb")) == (FILE *) NULL)
  73.     {
  74.         printf("gifhead: Cannot open file %s\n", gifFileName);
  75.         return -1;
  76.     }
  77.  
  78.     /* Read the GIF image file header information */
  79.     ReadGifHeader(&gifHead, fpGif);
  80.  
  81.     /* Check for FILE stream error */
  82.     if (ferror(fpGif))
  83.     {
  84.         printf("gifhead: Error reading header information!\n");
  85.         return -1;
  86.     }
  87.  
  88.     if(debug)printf("                       Signature: %.*s\n",
  89.       sizeof(gifHead.Signature), gifHead.Signature);
  90.  
  91.     if(debug)printf("                         Version: %.*s\n",
  92.       sizeof(gifHead.Version), gifHead.Version);
  93.  
  94.     if(debug)printf("                     ScreenWidth: %u\n", gifHead.ScreenWidth);
  95.     if(debug)printf("                    ScreenHeight: %u\n", gifHead.ScreenHeight);
  96.  
  97.     if(debug)printf("           Global Color Table is: %s\n",
  98.       gifHead.PackedField & 0x80 ? "Present" : "Not Present");
  99.    
  100.     if(debug)printf("             Original Resolution: %u (%u bits per primary color)\n",
  101.        (gifHead.PackedField & 0x70) >> 4,
  102.       ((gifHead.PackedField & 0x70) >> 4) + 1);
  103.    
  104.     if(debug)printf("           Global Color Table is: %s\n",
  105.       gifHead.PackedField & 0x08 ? "Sorted" : "Not Sorted");
  106.    
  107.     if(debug)printf("      Size of Global Color Table: %lu entries (%lu bytes)\n",
  108.       1L << ((gifHead.PackedField & 0x07) + 1),
  109.       3L * (1L << ((gifHead.PackedField & 0x07) + 1)));
  110.    
  111.     if(debug)printf("Size of Global Color Table Entry: %u bits per pixel\n",
  112.       (gifHead.PackedField & 0x07) + 1);
  113.    
  114.     if(debug)printf("          Background Color Index: %u\n", gifHead.ColorIndex);
  115.     if(debug)printf("              Pixel Aspect Ratio: %u\n", gifHead.AspectRatio);
  116.  
  117.     /*
  118.     ** Read and display the global color table if present.
  119.     */
  120.     if (gifHead.PackedField & 0x80)
  121.     {
  122.         lineCount = 0;  /* Count of the number of lines displayed */
  123.         tableSize = (WORD) (1L << ((gifHead.PackedField & 0x07) + 1));
  124.  
  125.         if(debug)puts("\n\n\t\t\t\tGlobal Color Table\n");
  126.         if(debug)printf("Color  Red Grn Blu  Color  Red Grn Blu  Color");
  127.         if(debug)printf(" Red Grn Blu  Color  Red Grn Blu\n");
  128.  
  129.         /* Display the palette values */
  130.         for (i = 0; i < tableSize; i++)
  131.         {
  132.             if(debug)printf(" %3d   %03u %03u %03u",
  133.               i,
  134.               gifHead.GlobalCT[i].Red,
  135.               gifHead.GlobalCT[i].Green,
  136.               gifHead.GlobalCT[i].Blue);
  137.  
  138.             /* Four entries per row */
  139.             if (i && i % 4 == 3)
  140.             {
  141.                 if(debug)putchar('\n');
  142.                 lineCount++;
  143.             }
  144.             else
  145.                 if(debug)fputs("  ", stdout);
  146.  
  147.             if (lineCount == 22)
  148.             {
  149.                 if(debug)printf("\n\nColor  Red Grn Blu  Color  Red Grn Blu");
  150.                 if(debug)printf("  Color  Red Grn Blu  Color  Red Grn Blu\n");
  151.                 lineCount = 0;
  152.             }
  153.         }
  154.     }
  155.  
  156.     /*
  157.     ** Identify, read, and display block information.
  158.     */
  159.     imageCount = 0;     /* Clear the image counter */
  160.  
  161.     for (;;)
  162.     {
  163.         Identifier = GetByte(fpGif);
  164.  
  165.         switch (Identifier)
  166.         {
  167.             case 0x3B:  /* Trailer */
  168.                 if(debug)printf("\n\nGIF Trailer found (end of GIF image file).\n\n");
  169.                 fclose(fpGif);
  170.                 return(0);
  171.             case 0x2C:  /* Image Descriptor */
  172.                 gifImageDesc.ImageSeparator = Identifier;
  173.                 if (ReadGifImageDesc(&gifImageDesc, fpGif) == -1)
  174.                     fputs("Error reading Image Descriptor information\n", stderr);
  175.                 imageCount++;
  176.  
  177.                 if(debug)printf("\n\nImage Descriptor for Image %d\n\n",
  178.                   imageCount);
  179.                 if(debug)printf("            Image Left Position: %u\n",
  180.                   gifImageDesc.ImageLeft);    
  181.                 if(debug)printf("             Image Top Position: %u\n",
  182.                   gifImageDesc.ImageTop);      
  183.                 if(debug)printf("                    Image Width: %u\n",
  184.                   gifImageDesc.ImageWidth);
  185.                 if(debug)printf("                   Image Height: %u\n",
  186.                   gifImageDesc.ImageHeight);
  187.                 if(debug)printf("           Local Color Table is: %s\n",
  188.                   gifImageDesc.PackedField & 0x80 ? "Present" : "Not Present");
  189.                 if(debug)printf("  Local Color Table Entries are: %s\n",
  190.                   gifImageDesc.PackedField & 0x20 ? "Sorted" : "Not Sorted");
  191.                 if(debug)printf("                       Image is: %sInterlaced\n",
  192.                   gifImageDesc.PackedField & 0x40 ? "" : "Not ");
  193.                 if(debug)printf("                       Reserved: %u\n",
  194.                   (gifImageDesc.PackedField & 0x18) >> 3);
  195.                 if(debug)printf("      Size of Local Color Table: %lu entries (%lu bytes)\n",
  196.                   1L << ((gifImageDesc.PackedField & 0x07) + 1),
  197.                   3L * (1L << ((gifImageDesc.PackedField & 0x07) + 1)));
  198.                 if(debug)printf("Size of Local Color Table Entry: %u bits per pixel\n",
  199.                   (gifImageDesc.PackedField & 0x07) + 1);
  200.  
  201.                 /*
  202.                 ** Read and display local color table, if present.
  203.                 */
  204.                 if (gifImageDesc.PackedField & 0x80)
  205.                 {
  206.                     lineCount = 0;  /* Count of the number of lines displayed */
  207.                     tableSize =
  208.                       (WORD) (1L << ((gifImageDesc.PackedField & 0x07) + 1));
  209.  
  210.                     if(debug)puts("\n\n\t\t\t\tLocal Color Table\n");
  211.                     if(debug)printf("Color  Red Grn Blu  Color  Red Grn Blu");
  212.                     if(debug)printf("  Color  Red Grn Blu  Color  Red Grn Blu\n");
  213.  
  214.                     /* Display the palette values */
  215.                     for (i = 0; i < tableSize; i++)
  216.                     {
  217.                         if(debug)printf(" %3d   %03u %03u %03u",
  218.                           i,
  219.                           gifImageDesc.LocalCT[i].Red,
  220.                           gifImageDesc.LocalCT[i].Green,
  221.                           gifImageDesc.LocalCT[i].Blue);
  222.  
  223.                         /* Four entries per row */
  224.                         if (i && i % 4 == 3)
  225.                         {
  226.                             if(debug)putchar('\n');
  227.                             lineCount++;
  228.                         }
  229.                         else
  230.                             if(debug)fputs("  ", stdout);
  231.  
  232.                         if (lineCount == 22)
  233.                         {
  234.                             if(debug)printf("\n\nColor  Red Grn Blu  Color  Red Grn Blu");
  235.                             if(debug)printf("  Color  Red Grn Blu  Color  Red Grn Blu\n");
  236.                             lineCount = 0;
  237.                         }
  238.                     }
  239.                     if(debug)puts("\n");
  240.                 }
  241.  
  242.                 /*
  243.                 ** Skip past the encoded image data.
  244.                 */
  245.                 if(debug)printf(" Image data: doing via gif_decode.c \n");
  246.                 err=gif_decode(gifImageDesc.ImageWidth, rgbpix);
  247.                 err=GetByte(fpGif); /* final zero block */
  248.  
  249.                 if(debug)printf("gif_decode returned err=%d, bad_code_count=%d\n",
  250.                        (int)err, (int)bad_code_count);
  251.                 break;
  252.             case 0x21:  /* Extension Block */  
  253.                 Label = GetByte(fpGif);
  254.                 switch (Label)
  255.                 {
  256.                     case 0x01:  /* Plain Text Extension */
  257.                         if(debug)puts("\n\nPlain Text Extension\n");
  258.                         gifPlainText.Introducer = Identifier;
  259.                         gifPlainText.Label = Label;
  260.                         if (ReadGifPlainText(&gifPlainText, fpGif))
  261.                             fprintf(stderr,
  262.                               "Error reading Plain Text Extension information.\n");
  263.  
  264.                         if(debug)printf("                  Block Size: %u\n",
  265.                           gifPlainText.BlockSize);
  266.                         if(debug)printf("     Text Grid Left Position: %u\n",
  267.                           gifPlainText.TextGridLeft);
  268.                         if(debug)printf("    Text Grid Right Position: %u\n",
  269.                           gifPlainText.TextGridTop);
  270.                         if(debug)printf("             Text Grid Width: %u\n",
  271.                           gifPlainText.TextGridWidth);
  272.                         if(debug)printf("            Text Grid Height: %u\n",
  273.                           gifPlainText.TextGridHeight);
  274.                         if(debug)printf("        Character Cell Width: %u\n",
  275.                           gifPlainText.CellWidth);
  276.                         if(debug)printf("       Character Cell Height: %u\n",
  277.                           gifPlainText.CellHeight);
  278.                         if(debug)printf(" Text Foreground Color Index: %u\n",
  279.                           gifPlainText.TextFgColorIndex);
  280.                         if(debug)printf(" Text Background Color Index: %u\n",
  281.                           gifPlainText.TextBgColorIndex);
  282.      
  283.                         /* Display Plain Text Data */
  284.                         ptr = gifPlainText.PlainTextData;
  285.                         while ((dataSize = *ptr++) != 0)
  286.                         {
  287.                             if(debug)printf("\nSize of Plain Text sub-block: %u\n",
  288.                               dataSize);
  289.                             if(debug)puts("\nText:");
  290.                             while (dataSize--)
  291.                                 if(debug)fputc(*ptr++, stdout);
  292.                             if(debug)putchar('\n');
  293.                         }
  294.                         break;
  295.                     case 0xFE:  /* Comment Extension */
  296.                         if(debug)puts("\n\nComment Extension");
  297.                         gifComment.Introducer = Identifier;
  298.                         gifComment.Label = Label;
  299.  
  300.                         if (ReadGifComment(&gifComment, fpGif))
  301.                             fprintf(stderr,
  302.                               "Error reading Comment Extension information\n");
  303.  
  304.                         /* Display Comment Data */
  305.                         ptr = gifComment.CommentData;
  306.                         while ((dataSize = *ptr++) != 0)
  307.                         {
  308.                             if(debug)printf("\nSize of Comment sub-block: %u\n", dataSize);
  309.                             if(debug)puts("\nComment:");
  310.                             while (dataSize--)
  311.                                 if(debug)fputc(*ptr++, stdout);
  312.                             if(debug)putchar('\n');
  313.                         }
  314.                         break;
  315.                     case 0xF9:  /* Graphic Control Extension */
  316.                         if(debug)puts("\n\nGraphics Control Extension\n");
  317.                         gifGraphicControl.Introducer = Identifier;
  318.                         gifGraphicControl.Label = Label;
  319.                         if (ReadGifGraphicControl(&gifGraphicControl, fpGif))
  320.                             fprintf(stderr,
  321.                               "Error reading Graphic Control Extension information\n");
  322.                         if(debug)printf("             Block Size: %u\n",
  323.                           gifGraphicControl.BlockSize);
  324.                         if(debug)printf("               Reserved: %u\n",
  325.                           (gifGraphicControl.PackedField & 0xE0) >> 5);
  326.                         if(debug)printf("        Disposal Method: %u ",
  327.                           (gifGraphicControl.PackedField & 0x1D) >> 2);
  328.                         switch((gifGraphicControl.PackedField & 0x1D) >> 2)
  329.                         {
  330.                             case 0x00:
  331.                                 if(debug)puts("(No Disposal Method Defined)");
  332.                                 break;
  333.                             case 0x01:
  334.                                 if(debug)puts("(Do Not Dispose)");
  335.                                 break;
  336.                             case 0x02:
  337.                                 if(debug)puts("(Restore to Background Color)");
  338.                                 break;
  339.                             case 0x03:
  340.                                 if(debug)puts("(Restore to Previous Graphic)");
  341.                                 break;
  342.                             default:
  343.                                 if(debug)puts("(To Be Defined)");
  344.                         }
  345.                         if(debug)printf("        User Input Flag: User Input is %sExpected\n",
  346.                           gifGraphicControl.PackedField & 0x02 ? "" : "Not ");
  347.                         if(debug)printf(" Transparent Color Flag: Color Index Is %sPresent\n",
  348.                           gifGraphicControl.PackedField & 0x01 ? "" : "Not ");
  349.  
  350.                         if(debug)printf("             Delay Time: %u\n",
  351.                           gifGraphicControl.DelayTime);
  352.                         if(debug)printf("Transparent Color Index: %u\n",
  353.                           gifGraphicControl.ColorIndex);
  354.  
  355.                         /* Display Graphic Control Information */
  356.                         while ((dataSize = GetByte(fpGif)) != 0)
  357.                         {
  358.                             if(debug)printf("\nSize of Graphic Control sub-block: %u\n",
  359.                               dataSize);
  360.                             if(debug)puts("Graphic Control Information:");
  361.                             for (i = 0; i < dataSize; i++)
  362.                                 if(debug)fputc(GetByte(fpGif), stdout);
  363.                             if(debug)putchar('\n');
  364.                         }
  365.                         break;
  366.                     case 0xFF:  /* Application Extension */
  367.                         if(debug)puts("\n\nApplication Extension\n");
  368.                         gifApplication.Introducer = Identifier;
  369.                         gifApplication.Label = Label;
  370.  
  371.                         if (ReadGifApplication(&gifApplication, fpGif))
  372.                             fprintf(stderr,
  373.                               "Error reading Application Extension information\n");
  374.  
  375.                         if(debug)printf("Block Size: %u\n", gifApplication.BlockSize);
  376.                         if(debug)printf("Application Identifier: %*u\n",
  377.                             sizeof(gifApplication.Identifier),
  378.                             gifApplication.Identifier);
  379.                         if(debug)printf("Authentication Code: %*u\n",
  380.                             sizeof(gifApplication.AuthentCode),
  381.                             gifApplication.AuthentCode);
  382.  
  383.                         /* Display Application Data */
  384.                         ptr = gifApplication.ApplicationData;
  385.                         while ((dataSize = *ptr++) != 0)
  386.                         {
  387.                             if(debug)printf("\nSize of Application sub-block: %u\n", dataSize);
  388.                             if(debug)puts("\nApplication Data:");
  389.                             while (dataSize--)
  390.                                 if(debug)fputc(*ptr++, stdout);
  391.                             if(debug)putchar('\n');
  392.                         }
  393.                         break;
  394.                     default:
  395.                         if(debug)printf("\n\nUnknown Extension Label: 0x%02x\n", Label);
  396.                         break;
  397.                 }
  398.                 break;
  399.             default:
  400.                 fprintf(stderr, "\n\nUnknown Block Separator Character: 0x%02x\n\n",
  401.                   Identifier);
  402.                 fclose(fpGif);
  403.                 return(-1);
  404.         }
  405.     }
  406. } /* end gifHead */
  407.  
  408. /* gif_decode.c - An LZW decoder for GIF    JSS mods                       */
  409. /* Copyright (C) 1987, by Steven A. Bennett                                */
  410. /* Permission is given by the author to freely redistribute and include    */
  411. /* this code in any program as long as this credit is given where due.     */
  412. /* In accordance with the above, I want to credit Steve Wilhite who wrote  */
  413. /* the code which this is heavily inspired by...                           */
  414. /*                                                                         */
  415. /* GIF and 'Graphics Interchange Format' are trademarks (tm) of            */
  416. /* Compuserve, Incorporated, an H&R Block Company.                         */
  417. /*                                                                         */
  418. /* Release Notes: This file contains a decoder routine for GIF images      */
  419. /* which is similar, structurally, to the original routine by Steve Wilhite*/
  420. /* It is, however, somewhat noticably faster in most cases.                */
  421.  
  422.  
  423. /*  Various error codes used by decode.c */
  424.  
  425. /* extern int get_byte(); replaced by  getc(fpGif)                  */
  426. /* This external (machine specific) function is expected to return  */
  427. /* either the next byte from the GIF file, or a negative number, as */
  428. /* defined in above errors                                          */
  429.  
  430.  
  431. /* extern int out_line(BYTE pixels[], int linelen, BYTE rgbpix[]); Now here. */
  432. /* This function takes a full line of pixels (one byte per pixel) and        */
  433. /* displays them (or does whatever your program wants with them...).  It     */
  434. /* should return zero, or negative if an error or some other event occurs    */
  435. /* which would require aborting the decode process...  Note that the length  */
  436. /* passed will almost always be equal to the line length passed to the       */
  437. /* decoder function, with the sole exception occurring when an ending code   */
  438. /* occurs in an odd place in the GIF file...  In any case, linelen will be   */
  439. /* equal to the number of pixels passed...                                   */
  440.  
  441. int out_line(BYTE pixels[], int linelen, BYTE rgbpix[]) /* JSS */
  442. {
  443.   int i, j;
  444.   BYTE r, g, b;
  445.   int enough=26;
  446.   int w, h, hw, x, y;
  447.  
  448.   w = gifImageDesc.ImageWidth;
  449.   h = gifImageDesc.ImageHeight;
  450.   if(rgba) { hw = 4*h*w; x = 4*w; }
  451.   else     { hw = 3*h*w; x = 3*w; }
  452.   line_num++; /* number, not subscript */
  453.  
  454.   for(i=0; i<linelen; i++)
  455.   {
  456.     if(i%enough==0) if(debug)printf("\n");
  457.     if(debug)printf("%d ", (int)pixels[i]);
  458.   }
  459.   if(debug)printf("\n");
  460.   y = hw-x*(2*(nrgbpix/x)+1);   /* invert image y */
  461.   if(debug)printf("out_line %d with length=%d, nrgbpix=%d, y=%d \n",
  462.          line_num, linelen, nrgbpix, y);
  463.   for(i=0; i<linelen; i++)
  464.   {
  465.     j = (int)pixels[i];
  466.     /* have index into color table, now get colors */
  467.     r = gifHead.GlobalCT[j].Red;
  468.     g = gifHead.GlobalCT[j].Green;
  469.     b = gifHead.GlobalCT[j].Blue;
  470.     if(debug)printf("r=%03u, g=%03u, b=%03u, row=%d, col=%d, inv=%d \n",
  471.            r, g, b, line_num, i, y+nrgbpix);
  472.     rgbpix[y+nrgbpix] = r;   /* invert y */
  473.     rgbpix[y+nrgbpix+1] = g;
  474.     rgbpix[y+nrgbpix+2] = b;
  475.     if(rgba) { rgbpix[y+nrgbpix+3] = alph; nrgbpix += 4; }
  476.     else     {                             nrgbpix += 3; }
  477.   }
  478.   if(gifImageDesc.PackedField & 0x40)
  479.   {
  480.     if(ipass==4)
  481.     {
  482.       nrgbpix = nrgbpix + x;       /* every other */
  483.     }
  484.     if(ipass==3)
  485.     {
  486.       nrgbpix = nrgbpix + (4-1)*x; /* every fourth */
  487.       if(nrgbpix>=hw)
  488.       {
  489.         ipass = 4;
  490.         nrgbpix = x;               /* start row 1 */
  491.       }
  492.     }
  493.     if(ipass==2)
  494.     {
  495.       nrgbpix = nrgbpix + (8-1)*x; /* every eighth */
  496.       if(nrgbpix>=hw)
  497.       {
  498.         ipass = 3;
  499.         nrgbpix = 2*x;             /* start row 2 */
  500.       }
  501.     }
  502.     if(ipass==1)
  503.     {
  504.       nrgbpix = nrgbpix + (8-1)*x; /* every eighth */
  505.       if(nrgbpix>=hw)
  506.       {
  507.         ipass = 2;
  508.         nrgbpix = 4*x;             /* start row 4 */
  509.       }
  510.     }
  511.   }
  512.   return 0;
  513. } /* end out_line */
  514.  
  515.  
  516. /* extern int bad_code_count;                                               */
  517. /* This value is the only other global required by the using program, and   */
  518. /* is incremented each time an out of range code is read by the decoder.    */
  519. /* When this value is non-zero after a decode, your GIF file is probably    */
  520. /* corrupt in some way...                                                   */
  521.  
  522. #define MAX_CODES 4095
  523.  
  524. /* Static variables */
  525. static WORD curr_size;                     /* The current code size */
  526. static WORD clear;                         /* Value for a clear code */
  527. static WORD ending;                        /* Value for a ending code */
  528. static WORD newcodes;                      /* First available code */
  529. static WORD top_slot;                      /* Highest code for current size */
  530. static WORD slot;                          /* Last read code */
  531.  
  532. /* The following static variables are used */
  533. /* for separating out codes */
  534. static WORD navail_bytes = 0;              /* # bytes left in block */
  535.  
  536. static WORD nbits_left = 0;                /* # bits left in current byte */
  537. static BYTE b1;                           /* Current byte */
  538. static BYTE byte_buff[257];               /* Current block */
  539. static BYTE *pbytes;                      /* Pointer to next byte in block */
  540.  
  541. static int code_mask[13] = {
  542.      0,
  543.      0x0001, 0x0003,
  544.      0x0007, 0x000F,
  545.      0x001F, 0x003F,
  546.      0x007F, 0x00FF,
  547.      0x01FF, 0x03FF,
  548.      0x07FF, 0x0FFF
  549.      };
  550.  
  551. /* This function initializes the decoder for reading a new image. */
  552. static WORD init_exp(WORD size)
  553. {
  554.   if(debug)printf("gif_decode.c init_exp size=%d\n", (int)size);
  555.   curr_size = size + 1;
  556.   top_slot = 1 << curr_size;
  557.   clear = 1 << size;
  558.   ending = clear + 1;
  559.   slot = newcodes = ending + 1;
  560.   navail_bytes = nbits_left = 0;
  561.   return(0);
  562. } /* end init_exp */
  563.  
  564. /* get_next_code() */
  565. /* - gets the next code from the GIF file.  Returns the code, or else */
  566. /* a negative number in case of file errors... */
  567. static WORD get_next_code()
  568. {
  569.   WORD i, x;
  570.   int ret;
  571.   if (nbits_left == 0)
  572.   {
  573.     if (navail_bytes <= 0)
  574.     {
  575.       /* Out of bytes in current block, so read next block */
  576.       pbytes = byte_buff;
  577.       if ((navail_bytes = getc(fpGif)) < 0)
  578.       {
  579.         printf("gif_decode.c get_next_code bad block size=%d\n",
  580.                (int)navail_bytes);
  581.         return navail_bytes;
  582.       }
  583.       else if (navail_bytes)
  584.       {
  585.         if(debug)printf("gif_decode.c get_next_code block size=%d\n",
  586.                (int)navail_bytes);
  587.         for (i = 0; i < navail_bytes; ++i)
  588.         {
  589.           if ((x = getc(fpGif)) < 0) return x;
  590.           byte_buff[i] = x;
  591.         }
  592.       }
  593.       else
  594.       {
  595.         printf("gif_decode.c get_next_code zero block size=%d\n",
  596.                (int)navail_bytes);
  597.       }
  598.     }
  599.     b1 = *pbytes++;
  600.     nbits_left = 8;
  601.     --navail_bytes;
  602.   }
  603.   ret = b1 >> (8 - nbits_left);
  604.   while (curr_size > nbits_left)
  605.   {
  606.     if (navail_bytes <= 0)
  607.     {
  608.       /* Out of bytes in current block, so read next block */
  609.       pbytes = byte_buff;
  610.       if ((navail_bytes = getc(fpGif)) < 0) return(navail_bytes);
  611.       else if (navail_bytes)
  612.       {
  613.         for (i = 0; i < navail_bytes; ++i)
  614.         {
  615.           if ((x = getc(fpGif)) < 0) return x;
  616.           byte_buff[i] = x;
  617.         }
  618.       }
  619.     }
  620.     b1 = *pbytes++;
  621.     ret |= b1 << nbits_left;
  622.     nbits_left += 8;
  623.     --navail_bytes;
  624.   }
  625.   nbits_left -= curr_size;
  626.   ret &= code_mask[curr_size];
  627.   /* printf("gif_decode.c get_next_code code=%d\n", (int)ret); */
  628.   return (WORD)ret;
  629. } /* end get_next_code */
  630.  
  631.  
  632. /* The reason we have these seperated like this instead of using         */
  633. /* a structure like the original Wilhite code did, is because this       */
  634. /* stuff generally produces significantly faster code when compiled...   */
  635. /* This code is full of similar speedups...  (For a good book on writing */
  636. /* C for speed or for space optomisation, see Efficient C by Tom Plum,   */
  637. /* published by Plum-Hall Associates...)                                 */
  638.  
  639. static BYTE stack[MAX_CODES + 1];            /* Stack for storing pixels */
  640. static BYTE suffix[MAX_CODES + 1];           /* Suffix table */
  641. static unsigned int prefix[MAX_CODES + 1];           /* Prefix linked list */
  642.  
  643.  
  644. /* - This function decodes an LZW image, according to the method used      */
  645. /* in the GIF spec.  Every *linewidth* "characters" (ie. pixels) decoded   */
  646. /* will generate a call to out_line(), which is a user specific function   */
  647. /* to display a line of pixels.  The function gets it's codes from         */
  648. /* get_next_code() which is responsible for reading blocks of data and     */
  649. /* seperating them into the proper size codes.  Finally, getc(fpGif) is*/
  650. /* the global routine to read the next byte from the GIF file.             */
  651.  
  652. /* It is generally a good idea to have linewidth correspond to the actual  */
  653. /* width of a line (as specified in the Image header) to make your own     */
  654. /* code a bit simpler, but it isn't absolutely necessary.                  */
  655. /* Returns: 0 if successful, else negative.  (See ERRS.H)                  */
  656.  
  657. static short int gif_decode(short int linewidth, BYTE rgbpix[])
  658.    /* call with width, LZW initial code size, return is error code */
  659. {
  660.   register BYTE *sp, *bufptr;
  661.   BYTE *buf;
  662.   register WORD code, fc, oc, bufcnt;
  663.   WORD c, size, ret;
  664.  
  665.   if(debug)printf("gif_decode.c linewidth=%d\n", (int)linewidth);
  666.   /* Initialize for decoding a new image... */
  667.   if ((size = getc(fpGif)) < 0) return size;
  668.   if (size < 2 || 9 < size) return BAD_CODE_SIZE;
  669.   init_exp(size);
  670.   /* Initialize in case they forgot to put in a clear code.         */
  671.   /* (This shouldn't happen, but we'll try and decode it anyway...) */
  672.   oc = fc = 0;
  673.  
  674.   /* Allocate space for the decode buffer */
  675.   if ((buf = (BYTE *)malloc(linewidth + 1)) == NULL) return OUT_OF_MEMORY;
  676.  
  677.   /* Set up the stack pointer and decode buffer pointer */
  678.   sp = stack;
  679.   bufptr = buf;
  680.   bufcnt = linewidth;
  681.  
  682.   /* This is the main loop.  For each code we get we pass through the       */
  683.   /* linked list of prefix codes, pushing the corresponding "character" for */
  684.   /* each code onto the stack.  When the list reaches a single "character"  */
  685.   /* we push that on the stack too, and then start unstacking each          */
  686.   /* character for output in the correct order.  Special handling is        */
  687.   /* included for the clear code, and the whole thing ends when we get      */
  688.   /* an ending code.                                                        */
  689.   while ((c = get_next_code()) != ending)
  690.   {
  691.     /* If we had a file error, return without completing the decode */
  692.     if (c < 0)
  693.     {
  694.       free(buf);
  695.       return 0;
  696.     }
  697.     /* If the code is a clear code, reinitialize all necessary items. */
  698.     if (c == clear)
  699.     {
  700.       curr_size = size + 1;
  701.       slot = newcodes;
  702.       top_slot = 1 << curr_size;
  703.  
  704.       /* Continue reading codes until we get a non-clear code  */
  705.       /* (Another unlikely, but possible case...)              */
  706.       while ((c = get_next_code()) == clear) ;
  707.       /* If we get an ending code immediately after a clear code  */
  708.       /* (Yet another unlikely case), then break out of the loop. */
  709.       if (c == ending) break;
  710.       /* Finally, if the code is beyond the range of already set codes,  */
  711.       /* (This one had better NOT happen...  I have no idea what will    */
  712.       /* result from this, but I doubt it will look good...) then set it */
  713.       /* to color zero.                                                  */
  714.       if (c >= slot) c = 0;
  715.       oc = fc = c;
  716.       /* And let us not forget to put the char into the buffer... And  */
  717.       /* if, on the off chance, we were exactly one pixel from the end */
  718.       /* of the line, we have to send the buffer to the out_line()     */
  719.       /* routine...                                                    */
  720.       *bufptr++ = c;
  721.       if (--bufcnt == 0)
  722.       {
  723.         if ((ret = out_line(buf, linewidth, rgbpix)) < 0)
  724.         {
  725.           free(buf);
  726.           return(ret);
  727.         }
  728.         bufptr = buf;
  729.         bufcnt = linewidth;
  730.      }
  731.   }
  732.   else
  733.   {
  734.     /* In this case, it's not a clear code or an ending code, so        */
  735.     /* it must be a code code...  So we can now decode the code into    */
  736.     /* a stack of character codes. (Clear as mud, right?)               */
  737.     code = c;
  738.     /* Here we go again with one of those off chances...  If, on the    */
  739.     /* off chance, the code we got is beyond the range of those already */
  740.     /* set up (Another thing which had better NOT happen...) we trick   */
  741.     /* the decoder into thinking it actually got the last code read.    */
  742.     /* (Hmmn... I'm not sure why this works...  But it does...)         */
  743.     if (code >= slot)
  744.     {
  745.       if (code > slot) ++bad_code_count;
  746.       code = oc;
  747.       *sp++ = fc;
  748.     }
  749.     /* Here we scan back along the linked list of prefixes, pushing     */
  750.     /* helpless characters (ie. suffixes) onto the stack as we do so.   */
  751.     while (code >= newcodes)
  752.     {
  753.       *sp++ = suffix[code];
  754.       code = prefix[code];
  755.     }
  756.     /* Push the last character on the stack, and set up the new       */
  757.     /* prefix and suffix, and if the required slot number is greater  */
  758.     /* than that allowed by the current bit size, increase the bit    */
  759.     /* size.  (NOTE - If we are all full, we *don't* save the new     */
  760.     /* suffix and prefix...  I'm not certain if this is correct...    */
  761.     /* it might be more proper to overwrite the last code...          */
  762.     *sp++ = code;
  763.     if (slot < top_slot)
  764.     {
  765.       suffix[slot] = fc = code;
  766.       prefix[slot++] = oc;
  767.       oc = c;
  768.     }
  769.     if (slot >= top_slot)
  770.       if (curr_size < 12)
  771.       {
  772.         top_slot <<= 1;
  773.         ++curr_size;
  774.       }
  775.  
  776.       /* Now that we've pushed the decoded string (in reverse order) */
  777.       /* onto the stack, lets pop it off and put it into our decode  */
  778.       /* buffer...  And when the decode buffer is full, write another*/
  779.       /* line... */
  780.       while (sp > stack)
  781.       {
  782.         *bufptr++ = *(--sp);
  783.         if (--bufcnt == 0)
  784.         {
  785.           if ((ret = out_line(buf, linewidth, rgbpix)) < 0)
  786.           {
  787.             free(buf);
  788.             return ret;
  789.           }
  790.           bufptr = buf;
  791.           bufcnt = linewidth;
  792.         }
  793.       }
  794.     }
  795.   }
  796.   ret = 0;
  797.   if (bufcnt != linewidth) ret = out_line(buf, (linewidth - bufcnt), rgbpix);
  798.   free(buf);
  799.   return(ret);
  800. } /* end gif_decode */
  801.  
  802. /* gif_io.c  implement low level I/O for Gif */
  803.  
  804. WORD GetWord(FILE *FpGif) /* little endian */
  805. {
  806.   int low, high; /* native machine */
  807.   WORD word;
  808.   low  = getc(FpGif);
  809.   high = getc(FpGif);
  810.   word = low;
  811.   word = word+ (high<<8);
  812.   return word;
  813. } /* end GetWord */
  814.  
  815. BYTE GetByte(FILE *FpGif)
  816. {
  817.   return getc(FpGif);
  818. } /* end GetByte */
  819.  
  820. DWORD GetDword(FILE *FpGif)
  821. {
  822.   int b1, b2, b3, b4; /* native machine */
  823.   WORD word;
  824.   b1   = getc(FpGif);
  825.   b2   = getc(FpGif);
  826.   b3   = getc(FpGif);
  827.   b4   = getc(FpGif);
  828.   word = b1;
  829.   word = word + (b2<<8) + (b3<<16) + (b4<24);
  830.   return word;
  831. } /* end GetDword */
  832.  
  833. void GetString(char * str, int len, FILE *FpGif)
  834. {
  835.   int i;
  836.   for(i=0; i<len; i++)
  837.   {
  838.     str[i] = (BYTE)getc(FpGif);
  839.   }
  840. } /* end GetString */
  841.  
  842. VOID  PutByte(BYTE x, FILE *FpGif)
  843. {
  844.   putc(x, FpGif);
  845. } /* end PutByte */
  846.  
  847. void PutWord(WORD x, FILE *FpGif)
  848. {
  849.   BYTE low, high;
  850.   low  = (BYTE)(x & 0xFF);
  851.   high = (BYTE)(x>>8);
  852.   putc(low, FpGif);
  853.   putc(high, FpGif);
  854. } /* end PutWord */
  855.  
  856. void PutDword(DWORD x, FILE *FpGif)
  857. {
  858.   BYTE b1, b2, b3, b4;
  859.   b1 = (BYTE)(x & 0xFF);
  860.   b2 = (BYTE)( (x>>8) & 0xFF);
  861.   b3 = (BYTE)( (x>>16) * 0xFF);
  862.   b4 = (BYTE)(x>>24);
  863.   putc(b1, FpGif);
  864.   putc(b2, FpGif);
  865.   putc(b3, FpGif);
  866.   putc(b4, FpGif);
  867. } /* end PutDword */
  868.  
  869. void PutString(char * str, int len, FILE *FpGif)
  870. {
  871.   int i;
  872.   for(i=0; i<len; i++)
  873.   {
  874.     putc(str[i],FpGif);
  875.   }
  876. } /* end PutString */
  877.  
  878.  
  879. /****************************************************************************\
  880. **  This module contains six functions which read various data structures   **
  881. **  stored in GIF 87a and 89a-format files.                                 **
  882. **                                                                          **
  883. **  This module contains the following functions:                           **
  884. **                                                                          **
  885. **      ReadGifHeader         - Read a GIF image file Header                **
  886. **      ReadGifImageDesc      - Read a GIF Local Image Descriptor           **
  887. **      ReadGifGraphicControl - Read a GIF Graphic Control Extension block  **
  888. **      ReadGifPlainText      - Read a GIF Plain Text Extension block       **
  889. **      ReadGifApplication    - Read a GIF Application Extension block      **
  890. **      ReadGifComment        - Read a GIF Comment Extension block          **
  891. **      ReadDataSubBlocks     - Read one or more GIF data sub-blocks        **
  892. **                                                                          **
  893. **  Copyright (C) 1991,92 by Graphics Software Labs.  All rights reserved.  **
  894. \****************************************************************************/
  895.  
  896. /* Local function prototype */
  897. BYTE *ReadDataSubBlocks(FILE *FpGif);
  898.  
  899. /*
  900. **  Read a GIF image file Header.
  901. **
  902. **  This function reads the Header, Logical Screen Descriptor, and
  903. **  Global Color Table (if any) from a GIF image file.  The information
  904. **  is stored in a GIFHEAD structure.
  905. **
  906. **  Returns: -1 if a FILE stream error occured during the read,
  907. **           otherwise 0 if no error occured.
  908. */
  909. int
  910. ReadGifHeader(GIFHEAD *GifHead,   /* Pointer to GIF header structure  */
  911.               FILE    *FpGif)     /* GIF image file input FILE stream */
  912. {
  913.     register WORD i;    /* Loop counter                                */
  914.     WORD tableSize;     /* Number of entires in the Global Color Table */
  915.  
  916.     /* GetWord = GetLittleWord;     Read using little-endian byte order */
  917.  
  918.     GetString(GifHead->Signature, sizeof(GifHead->Signature), FpGif);
  919.     GetString(GifHead->Version, sizeof(GifHead->Version), FpGif);
  920.  
  921.     GifHead->ScreenWidth    = GetWord(FpGif);
  922.     GifHead->ScreenHeight   = GetWord(FpGif);
  923.     GifHead->PackedField    = GetByte(FpGif);
  924.     GifHead->ColorIndex     = GetByte(FpGif);
  925.     GifHead->AspectRatio    = GetByte(FpGif);
  926.  
  927.     /* Check if a Global Color Table is present */
  928.     if (GifHead->PackedField & 0x80)
  929.     {
  930.         /* Read number of color table entries */
  931.         tableSize = (WORD) (1L << ((GifHead->PackedField & 0x07) + 1));
  932.  
  933.         /* Read the Global Color Table */
  934.         for (i = 0; i < tableSize; i++)
  935.         {
  936.             GifHead->GlobalCT[i].Red   = GetByte(FpGif);
  937.             GifHead->GlobalCT[i].Green = GetByte(FpGif);
  938.             GifHead->GlobalCT[i].Blue  = GetByte(FpGif);
  939.         }
  940.     }
  941.  
  942.     /* Check for a FILE stream error */
  943.     if (ferror(FpGif))
  944.         return -1;     /* FILE stream error occured during read */
  945.  
  946.     return 0;          /* No FILE stream error occured */
  947. }
  948.  
  949.  
  950. /*
  951. **  Read a GIF Local Image Descriptor.
  952. **
  953. **  This function reads the Local Image Descriptor, and Local Color
  954. **  Table (if any) from a GIF image file.  The information is stored
  955. **  in a GIFIMAGEDESC structure.
  956. **
  957. **  Note that the ImageSeparator field value in the GIFIMAGEDESC
  958. **  structure is assigned by the function calling ReadGifImageDesc().
  959. **
  960. **  Returns: -1 if a FILE stream error occured during the read,
  961. **           otherwise 0 if no error occured.
  962. */
  963. int
  964. ReadGifImageDesc(
  965.   GIFIMAGEDESC *GifImageDesc, /* Pointer to GIF image descriptor structure */
  966.   FILE         *FpGif)        /* GIF image file input FILE stream          */
  967. {
  968.     WORD i;                 /* Loop counter                               */
  969.     WORD tableSize;         /* Number of entries in the Local Color Table */
  970.  
  971.     /* GetWord = GetLittleWord;    Read using little-endian byte order    */
  972.  
  973.     GifImageDesc->ImageLeft   = GetWord(FpGif);
  974.     GifImageDesc->ImageTop    = GetWord(FpGif);
  975.     GifImageDesc->ImageWidth  = GetWord(FpGif);
  976.     GifImageDesc->ImageHeight = GetWord(FpGif);
  977.     GifImageDesc->PackedField = GetByte(FpGif);
  978.  
  979.     /* Check if a Local Color Table is present */
  980.     if (GifImageDesc->PackedField & 0x80)
  981.     {
  982.         /* Read number of color table entries */
  983.         tableSize = (WORD) (1L << ((GifImageDesc->PackedField & 0x07) + 1));
  984.  
  985.         /* Read the Local Color Table */
  986.         for (i = 0; i < tableSize; i++)
  987.         {
  988.             GifImageDesc->LocalCT[i].Red   = GetByte(FpGif);
  989.             GifImageDesc->LocalCT[i].Green = GetByte(FpGif);
  990.             GifImageDesc->LocalCT[i].Blue  = GetByte(FpGif);
  991.         }
  992.     }
  993.  
  994.     /* Check for a FILE stream error */
  995.     if (ferror(FpGif))
  996.         return -1;     /* FILE stream error occured during read */
  997.  
  998.     return 0;          /* No FILE stream error occured */
  999. }
  1000.  
  1001.  
  1002. /*
  1003. **  Read a GIF Graphic Control Extension block.
  1004. **
  1005. **  Note that the Introducer and Label field values in the GIFGRAPHICCONTROL
  1006. **  structure are assigned by the function calling ReadGifGraphicControl().
  1007. **
  1008. **  Returns: -1 if a FILE stream error occured during the read,
  1009. **           otherwise 0 if no error occured.
  1010. */
  1011. int
  1012. ReadGifGraphicControl(
  1013.   GIFGRAPHICCONTROL *GifGraphicControl, /* Pointer to GC Extension structure */
  1014.   FILE              *FpGif)             /* GIF image file input FILE stream  */
  1015. {
  1016.     /* GetWord = GetLittleWord;   Read using little-endian byte order     */
  1017.  
  1018.     GifGraphicControl->BlockSize   = GetByte(FpGif);
  1019.     GifGraphicControl->PackedField = GetByte(FpGif);
  1020.     GifGraphicControl->DelayTime   = GetWord(FpGif);
  1021.     GifGraphicControl->ColorIndex  = GetByte(FpGif);
  1022.  
  1023.     /* Check for a FILE stream error */
  1024.     if (ferror(FpGif))
  1025.         return -1;     /* FILE stream error occured during read */
  1026.  
  1027.     return 0;          /* No FILE stream error occured */
  1028. }
  1029.  
  1030.  
  1031. /*
  1032. **  Read a GIF Plain Text Extension block.
  1033. **
  1034. **  Note that the Introducer and Label field values in the GIFLPLAINTEXT
  1035. **  structure are assigned by the function calling ReadGifPlainText().
  1036. **
  1037. **  Returns: -1 if a FILE stream error occured during the read,
  1038. **           otherwise 0 if no error occured.
  1039. */
  1040. int
  1041. ReadGifPlainText(
  1042.   GIFPLAINTEXT *GifPlainText, /* Pointer to Plain Text Extension structure */
  1043.   FILE         *FpGif)        /* GIF image file input FILE stream          */
  1044. {
  1045.     /* GetWord = GetLittleWord;    Read using little-endian byte order   */
  1046.  
  1047.     GifPlainText->BlockSize        = GetByte(FpGif);
  1048.     GifPlainText->TextGridLeft     = GetWord(FpGif);
  1049.     GifPlainText->TextGridTop      = GetWord(FpGif);
  1050.     GifPlainText->TextGridWidth    = GetWord(FpGif);
  1051.     GifPlainText->TextGridHeight   = GetWord(FpGif);
  1052.     GifPlainText->CellWidth        = GetByte(FpGif);
  1053.     GifPlainText->CellHeight       = GetByte(FpGif);
  1054.     GifPlainText->TextFgColorIndex = GetByte(FpGif);
  1055.     GifPlainText->TextBgColorIndex = GetByte(FpGif);
  1056.  
  1057.     /* Read in the Plain Text data sub-blocks */
  1058.     if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(FpGif)))
  1059.         return 1;
  1060.  
  1061.     GifPlainText->Terminator       = 0;
  1062.  
  1063.     /* Check for a FILE stream error */
  1064.     if (ferror(FpGif))
  1065.         return -1;     /* FILE stream error occured during read */
  1066.  
  1067.     return 0;          /* No FILE stream error occured */
  1068. }
  1069.  
  1070.  
  1071. /*
  1072. **  Read a GIF Application Extension block.
  1073. **
  1074. **  Note that the Introducer and Label field values in the GIFAPPLICATION
  1075. **  structure are assigned by the function calling ReadGifApplication().
  1076. **
  1077. **  Returns: -1 if a FILE stream error occured during the read,
  1078. **           otherwise 0 if no error occured.
  1079. */
  1080. int
  1081. ReadGifApplication(
  1082.   GIFAPPLICATION *GifApplication, /* Pointer to Application Extension struct */
  1083.   FILE           *FpGif)          /* GIF image file input FILE stream        */
  1084. {
  1085.     GifApplication->BlockSize      = GetByte(FpGif);
  1086.  
  1087.     GifApplication->Identifier[0]  = GetByte(FpGif);
  1088.     GifApplication->Identifier[1]  = GetByte(FpGif);
  1089.     GifApplication->Identifier[2]  = GetByte(FpGif);
  1090.     GifApplication->Identifier[3]  = GetByte(FpGif);
  1091.     GifApplication->Identifier[4]  = GetByte(FpGif);
  1092.     GifApplication->Identifier[5]  = GetByte(FpGif);
  1093.     GifApplication->Identifier[6]  = GetByte(FpGif);
  1094.     GifApplication->Identifier[7]  = GetByte(FpGif);
  1095.  
  1096.     GifApplication->AuthentCode[0] = GetByte(FpGif);
  1097.     GifApplication->AuthentCode[1] = GetByte(FpGif);
  1098.     GifApplication->AuthentCode[2] = GetByte(FpGif);
  1099.  
  1100.     /* Read in the Plain Text data sub-blocks */
  1101.     if (!(GifApplication->ApplicationData = ReadDataSubBlocks(FpGif)))
  1102.         return(1);
  1103.  
  1104.     GifApplication->Terminator     = 0;
  1105.  
  1106.     /* Check for a FILE stream error */
  1107.     if (ferror(FpGif))
  1108.         return -1;     /* FILE stream error occured during read */
  1109.  
  1110.     return 0;          /* No FILE stream error occured */
  1111. }
  1112.  
  1113.  
  1114. /*
  1115. **  Read a GIF Comment Extension block.
  1116. **
  1117. **  Note that the Introducer and Label field values in the GIFCOMMENT
  1118. **  structure are assigned by the function calling ReadGifComment().
  1119. **
  1120. **  Returns: -1 if a FILE stream error occured during the read,
  1121. **           otherwise 0 if no error occured.
  1122. */
  1123. int
  1124. ReadGifComment(
  1125.   GIFCOMMENT *GifComment, /* Pointer to GIF Comment Extension structure */
  1126.   FILE       *FpGif)      /* GIF image file input FILE stream           */
  1127. {
  1128.     /* Read in the Plain Text data sub-blocks */
  1129.     if (!(GifComment->CommentData = ReadDataSubBlocks(FpGif)))
  1130.         return(1);
  1131.  
  1132.     GifComment->Terminator = 0;
  1133.    
  1134.     /* Check for a FILE stream error */
  1135.     if (ferror(FpGif))
  1136.         return -1;     /* FILE stream error occured during read */
  1137.  
  1138.     return 0 ;          /* No FILE stream error occured */
  1139. }
  1140.  
  1141.  
  1142. /*
  1143. **  Read one or more GIF data sub-blocks and write the information
  1144. **  to a buffer.
  1145. **
  1146. **  A GIF "sub-block" is a single count byte followed by 1 to 255
  1147. **  additional data bytes.
  1148. **
  1149. **  Returns: A NULL pointer if a memory allocation error occured,
  1150. **           otherwise a valid pointer if no error occured.
  1151. */
  1152. BYTE *
  1153. ReadDataSubBlocks(FILE *FpGif) /* GIF image file input FILE stream   */
  1154. {
  1155.     BYTE *ptr1;     /* Pointer used to "walk the heap"               */
  1156.     BYTE *ptr2;     /* Pointer used to mark the top of the heap      */
  1157.     BYTE dataSize;  /* Size of the current data sub-block being read */
  1158.     WORD bufSize;   /* Total size of the Plain Text data buffer      */
  1159.  
  1160.     bufSize = 0;    /* The output buffer is empty                    */
  1161.  
  1162.     dataSize = GetByte(FpGif);  /* Get the size of the first sub-block */
  1163.  
  1164.     /* Allocate initial data buffer */
  1165.     if (!(ptr1 = ptr2 = (BYTE *) malloc(dataSize + 1)))
  1166.         return((BYTE *) NULL);
  1167.  
  1168.     for (;;)
  1169.     {
  1170.         bufSize += (dataSize + 1);  /* Running total of the buffer size */
  1171.  
  1172.         *ptr1++ = dataSize; /* Write the data count */
  1173.         while (dataSize--)  /* Read/write the Plain Text data */
  1174.             *ptr1++ = GetByte(FpGif);
  1175.        
  1176.         /* Check if there is another data sub-block */
  1177.         if ((dataSize = GetByte(FpGif)) == 0)
  1178.             break;  /* Block Terminator encountered */
  1179.  
  1180.         /* Increase the buffer size to accomodate the next sub-block */
  1181.         if (!(ptr1 = ptr2 = (BYTE *) realloc(ptr2, dataSize + 1)))
  1182.             return((BYTE *) NULL);
  1183.  
  1184.         ptr1 += bufSize;    /* Move pointer to the end of the data */
  1185.     }
  1186.     *ptr1++ = (BYTE) NULL;  /* Add NULL to simulate Terminator value */
  1187.  
  1188.     return(ptr2);   /* Return a pointer to the sub-block data */
  1189. }
  1190.  
  1191.  
  1192.  
  1193.  
  1194. /* gifwrite.c */
  1195.  
  1196. /* These functions are the complement of the reader functions in GIFREAD.C.
  1197.  * They are used to write the header and data blocks found within the GIF
  1198.  *image file format.
  1199.  */
  1200.  
  1201. /****************************************************************************\
  1202. **  Title:       gifwrite.c                                                 **
  1203. **  Purpose:     Write GIF header information to a file.                    **
  1204. **  Version:     1.0                                                        **
  1205. **  Date:        May 1991                                                   **
  1206. **  Author:      James D. Murray, Anaheim, CA  USA                          **
  1207. **  C Compilers: Borland C++ v2.0, Microsoft C v6.00a                       **
  1208. **                                                                          **
  1209. **  Write the information contained within a GIFHEADER structure            **
  1210. **  to a file.  Used to construct GIF-format files.                         **
  1211. **                                                                          **
  1212. **  This module contains the following functions:                           **
  1213. **                                                                          **
  1214. **      WriteGifHeader - Write a GIF header to a file stream                **
  1215. **                                                                          **
  1216. **  Copyright (C) 1991 by Graphics Software Labs.  All rights reserved.     **
  1217. \****************************************************************************/
  1218. #include "gif.h"
  1219.  
  1220.  
  1221. VOID
  1222. WriteGifHeader(GIFHEAD *GifHead,   /* Pointer to GIF header structure  */
  1223.                FILE    *FpGif)     /* GIF image file output FILE stream */
  1224. {
  1225.     /* PutWord = PutLittleWord;  write using little-endian byte order */
  1226.  
  1227.     PutString(GifHead->Signature, sizeof(GifHead->Signature), FpGif);
  1228.     PutString(GifHead->Version, sizeof(GifHead->Version), FpGif);
  1229.     PutWord(GifHead->ScreenWidth,  FpGif);
  1230.     PutWord(GifHead->ScreenHeight, FpGif);
  1231.     PutByte(GifHead->PackedField,  FpGif);
  1232.     PutByte(GifHead->ColorIndex,   FpGif);
  1233.     PutByte(GifHead->AspectRatio,  FpGif);                              
  1234. }
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240. /* gifdecode.c  GIF LZW Decoder */
  1241.  
  1242. /****************************************************************************\
  1243. **  Title:       gifdecode.c                                                **
  1244. **  Purpose:     Decode a GIF image file scan line.                         **
  1245. **  Version:     1.0                                                        **
  1246. **  Date:        May 1991                                                   **
  1247. **  Author:      James D. Murray, Anaheim, CA  USA                          **
  1248. **  C Compilers: Borland C++ v2.0, Microsoft C v6.00a                       **
  1249. **                                                                          **
  1250. **  Decompress an image scan line using the Lez-Zempel Welch (LZW) encoding **
  1251. **  algorithm.  Decoded data is returned in a buffer.  Useful for           **
  1252. **  algorithms that need to work on images one scan line at a time.         **
  1253. **                                                                          **
  1254. **  This module contains the following functions:                           **
  1255. **                                                                          **
  1256. **      GifDecodeScanLine - Decode an LZW-encoded scan line                 **
  1257. **                                                                          **
  1258. **  Copyright (C) 1991 by Graphics Software Labs.  All rights reserved.     **
  1259. \****************************************************************************/
  1260. #include "gif.h"
  1261.  
  1262.  
  1263. /*
  1264. **  Decode (uncompress) a GIF image file scan line.
  1265. **
  1266. **  The LZW-encoded data stored in a GIF file is arranged as a series
  1267. **  of sub-blocks.  Each sub-lock consists of a single count byte followed
  1268. **  by 1 to 255 data bytes.  This function reads the sub-blocks, sends
  1269. **  the LZW data to the LZWDecode() function, and then returns a parameter
  1270. **  pointer to a buffer filled with the decoded image data.
  1271. */
  1272. SHORT
  1273. GIFDecodeScanLine(
  1274.     BYTE *DecodedBuffer,  /* Pointer to buffer to hold decoded data       */
  1275.     WORD  BufferSize,     /* Size of buffer to hold decoded data          */
  1276.     BYTE  MinCodeSize,    /*  */
  1277.     FILE *FpGif)          /* FILE pointer to the open input GIF image file*/
  1278. {
  1279. #if 0
  1280.     if (!(DecodedBuffer = LZWDecoder(buffer, bufferSize, MinCodeSize)))
  1281.         return -1;
  1282. #endif
  1283.     return 0;
  1284. }
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290. /* gifencode.c   GIF LZW Encoder */
  1291.  
  1292. /****************************************************************************\
  1293. **  Title:       GIFENCOD.C                                                 **
  1294. **  Purpose:     Encode a GIF image file scan line.                         **
  1295. **  Version:     1.0                                                        **
  1296. **  Date:        May 1991                                                   **
  1297. **  Author:      James D. Murray, Anaheim, CA  USA                          **
  1298. **  C Compilers: Borland C++ v2.0, Microsoft C v6.00a                       **
  1299. **                                                                          **
  1300. **  Compress an image scan line using the Lev-Zempel Welch (LZW) encoding   **
  1301. **  algorithm.  Useful for algorithms that need to work on images           **
  1302. **  one scan line at a time.                                                **
  1303. **                                                                          **
  1304. **  This module contains the following functions:                           **
  1305. **                                                                          **
  1306. **      GifEncodeScanLine - Encode a raw scan line using LZW.               **
  1307. **                                                                          **
  1308. **  Copyright (C) 1991 by Graphics Software Labs.  All rights reserved.     **
  1309. \****************************************************************************/
  1310. #include "gif.h"
  1311.  
  1312.  
  1313. WORD
  1314. GifEncodeScanLine(
  1315.   BYTE *DecodedBuffer,    /* Pointer to buffer holding unencoded data      */
  1316.   WORD  BufferSize,       /* Size of buffer holding unencoded data         */
  1317.   BYTE *EncodedBuffer)    /* Pointer to buffer to hold encodeded scan line */
  1318. {
  1319.   return 0;
  1320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement