⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gif.c

📁 LZW compression example with java
💻 C
字号:
/*The GIF loader, Included as a part of the compression tutorial
 *Written By Martin Zolnieryk (c) 2004
 *This code is freeware, however if you use this some credit
 *be nice.
 *This code is based upon the GifAllegS Library
*/

#include <stdio.h>
#include "allegro.h"
#include "lzw.h"
#include "gif.h"

//This grabs the code
int get_gif_lzw_code(FILE *fp,LZW *table, GIF *gif)
{
unsigned int code = 0;
//Gif specialized code
//Restart new buffer block?
//code = 0;		
while(table->buffer_bits <=((sizeof(int)-sizeof(char))*8))//Never go over than size - 8or we loose data
 {
//No point reading anymore, if the files done
if(feof(fp))
{
break;
}
   
   table->buffer |= ((unsigned char)fgetc(fp)) << table->buffer_bits; //We store all data in the buffer
   table->buffer_bits+= 8; 

   table->to_nbuffer--;
   if(table->to_nbuffer <= 0) //We reset the table data
   { 
    table->buffer_size = getc(fp);
    table->to_nbuffer = table->buffer_size;
    }
}


code = table->buffer << (sizeof(int) * 8 - table->bits); //extract code
code = code   >> (sizeof(int) * 8 - table->bits);
table->buffer >>= table->bits; //remove code from buffer
table->buffer_bits -= table->bits;

return code;
}

//This is where all the work is done
BITMAP *load_gif(const char *filename, RGB *pal)
{
GIF al_gif;
FILE *fp;
LZW table;
RGB *g_pal;
int looper;


///Everything here from Decompress LZW
short int first_code = -1;      //Check psuedo code, grabs next char
unsigned short int next_code;     
short int first_char = -1;   //Is for the if fix,make sure is 0 to escape potential bugs
short int code_number = -1;    //Holds code value for STRING_BUFFER
int counter=0;
unsigned char *string = NULL;

//Start Code
g_pal = pal;
if(!g_pal)
 {
 g_pal = malloc(sizeof(RGB) * 256);
 }

if(!(fp = fopen(filename, "rb")))
     return NULL; 

for(looper = 0;looper <6;looper++)
   al_gif.id[looper] = getc(fp);

//Test if valid header
if(al_gif.id[0] != 'G' || al_gif.id[1] !='I' || al_gif.id[2] !='F')
   return NULL;

//Two types of gif, 87a, 89a, we check the numero
if(al_gif.id[4] == '9') //89a
    NULL;
else                    //87a
    NULL;

//Load Withs
fread(&al_gif.s_width, 2, 1, fp); 
fread(&al_gif.s_height,2,1,fp);

//Get Important Info
al_gif.global_depth = getc(fp);
al_gif.bpp = 1 + (al_gif.global_depth & 7);

//Irrelevant Entries,
//We dont need to use these
fgetc(fp);
fgetc(fp);

//If the palette is global, we load it
if(al_gif.global_depth & 128);
{
  for(looper = 0; looper < (1 << al_gif.bpp); looper++)
  {
      g_pal[looper].r = (fgetc(fp) /4);
      g_pal[looper].g = (fgetc(fp) /4);
      g_pal[looper].b = (fgetc(fp) /4);
  }
}

//We keep reading until "," which begins the image header.
while(getc(fp) != ',')
{
//Some error checking
 if(feof(fp))
   return NULL;
}
//Read image header, the sizes
fread(&al_gif.ileft, 2, 1, fp); 
fread(&al_gif.itop, 2, 1, fp); 
fread(&al_gif.iwidth, 2, 1, fp); 
fread(&al_gif.iheight, 2, 1, fp); 
//Get local depth
al_gif.depth = getc(fp);

//Allocate Memory
if(!(al_gif.image = create_bitmap_ex(8,al_gif.s_width, al_gif.s_height)))
 return NULL;
create_lzw_table(&table,12);


//We don't support all gif's 
//For this little proggy
  if (al_gif.depth & 128) 
  {
    allegro_message("Local colour maps/Animated Images not supported");
    return NULL;
  }
  if (al_gif.depth & 64) 
  {
    allegro_message ("Interlaced images not supported\n");
    return NULL;
  }

//Last Minute Initalizing
al_gif.cc = getc(fp);
al_gif.code_size =al_gif.cc + 1;   //Starting Code Size
table.bits = al_gif.code_size;     //Bits used for table
table.buffer_size = getc(fp);      //al_gif.block_byte; //Buffer size
table.to_nbuffer = table.buffer_size;  //Countdown
table.codes_reserved = GIF_EOI;        //Set reserved code
al_gif.counter = 0;                    //restart drawing buffer




//We start the loop
while((next_code = get_gif_lzw_code(fp,&table,&al_gif))!= GIF_EOI && al_gif.counter <= (al_gif.image->w*al_gif.image->h))
  {
   if(next_code == GIF_CC) //If it's a clear code
    {
      clear_lzw_table(&table);   //We clear everthing and laod first code
      table.bits = al_gif.cc+1;
	  table.codes_used = 0;
	  al_gif.code_size = al_gif.cc +1;
      next_code = get_gif_lzw_code(fp,&table,&al_gif);
      first_code = next_code;
      first_char = first_code;
      draw_lzw_pixel(al_gif.image,al_gif.counter,next_code); //Draw first_code
      al_gif.counter++;
    }
//If its not a clear code, or an EOI
    else
    {
    //If not in table
      if (next_code > table.codes_used + table.codes_reserved)          
      {
        table.codes_used++;
        table.prefix[next_code]= first_code;
        table.character[next_code]=first_char;
        looper = lzw_get_string(&table,next_code);
      }
      //If the code was already in the table
      //See if we can add a new code to the table
      //Make sure we have not gone over the table size
      else if(table.codes_used + table.codes_reserved < table.lzw_size )                                   
      {                                       
          looper = lzw_get_string(&table,next_code);
          table.codes_used++;
          table.prefix[table.codes_used +table.codes_reserved]= first_code;
          table.character[table.codes_used +table.codes_reserved]=table.string[looper-1];
      }
      else //Characters that we output
        looper = lzw_get_string(&table,next_code);


    //We Draw the gif
      first_char = table.string[looper-1];    
      first_code = next_code;
      while(looper > 0)
       {
       draw_lzw_pixel(al_gif.image,al_gif.counter,table.string[looper-1]);
       al_gif.counter++;
 
       looper--;
       }
 
  //This is a check to see if the code_size must grow by a bit or not.
    if((1 << al_gif.code_size)-1 <= table.codes_used + table.codes_reserved && al_gif.code_size < 12)
    {
    table.bits++;
    al_gif.code_size++;
    }
   
   }//End else 
  } //End While

//Close and clean up
fclose(fp);
//Check to see if we allocated palette
if(g_pal != pal)
  free(g_pal);

return al_gif.image;
}


//This makes a calculation Based on width and height where the pixel should go
void draw_lzw_pixel(BITMAP *image, long counter,unsigned char color)
{
putpixel(image,counter % image->w,counter / image->w,color);
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -