?? gif.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 + -