?? gif.c
字號(hào):
#include <assert.h>#include <stdio.h>#include <stdlib.h>#ifndef __ECOS# include <memory.h>#endif#include <string.h>#include "gif.h"const int v_incr[4]={8,8,4,2};const int v_start[4]={0,4,2,1};int unpack_gif(gif_info_t* ginfo){ int bpp; int palette_size; assert(ginfo->gif_surface==NULL); assert(ginfo->gif_buffer!=NULL); ginfo->gif_cur_buffer=ginfo->gif_buffer; memcpy(&(ginfo->gif_global), ginfo->gif_cur_buffer, sizeof(gif_global_t)); ginfo->gif_x=0; ginfo->gif_y=0; ginfo->gif_surface=malloc(ginfo->gif_global.width*ginfo->gif_global.height*3); ginfo->gif_cur_buffer+=GIF_GLOBAL_SIZE; bpp=(ginfo->gif_global.flag&0x07)+1; palette_size=(1<<bpp)*3; memcpy(&(ginfo->gif_global_palette), ginfo->gif_cur_buffer, palette_size); if (strncmp(ginfo->gif_global.magic_word,"GIF",3)!=0) { return -1; } ginfo->gif_cur_buffer+=palette_size; while(1) { char block_type=*(ginfo->gif_cur_buffer); ginfo->gif_cur_buffer++; switch(block_type) { case ',': // unpack local image block return unpack_local_image(ginfo); break; case '!': { // char sub_block_type=*(ginfo->gif_cur_buffer++); unsigned char sub_block_size=*(ginfo->gif_cur_buffer++); ginfo->gif_cur_buffer+=sub_block_size; // skip subblock ginfo->gif_cur_buffer++; // skip '0x00' } break; default: // unknown block , return false . return -1; } } return 0;}int unpack_local_image(gif_info_t* ginfo){ memcpy(&(ginfo->gif_local), ginfo->gif_cur_buffer, sizeof(gif_local_t)); ginfo->gif_cur_buffer+=GIF_LOCAL_SIZE; ginfo->b_interlaced=ginfo->gif_local.flag&0x40; ginfo->b_local_palette=ginfo->gif_local.flag&0x08; if (ginfo->b_local_palette!=0) { // load local palette ... int bpp; int palette_size; bpp=(ginfo->gif_local.flag&0x07)+1; palette_size=(1<<bpp)*3; memcpy(&(ginfo->gif_local_palette), ginfo->gif_cur_buffer, palette_size); ginfo->gif_cur_buffer+=palette_size; } return unpack_image_data(ginfo);}int unpack_image_data(gif_info_t* ginfo){ ginfo->first_ch=*(ginfo->gif_cur_buffer); assert(ginfo->first_ch==1|| ginfo->first_ch==2|| ginfo->first_ch==4|| ginfo->first_ch==8); ginfo->gif_cur_buffer++; ginfo->gif_x=0; ginfo->gif_y=0; ginfo->CLEAR=1<<ginfo->first_ch; ginfo->EOI=ginfo->CLEAR+1; ginfo->request_bits=ginfo->first_ch+1; while((ginfo->code=get_code(ginfo))!=ginfo->EOI) { if (ginfo->code==ginfo->CLEAR) { clear_code_table(ginfo,ginfo->CLEAR); } else { if (ginfo->code_table[ginfo->code].prefix==-2) { insert_code_table(ginfo,ginfo->prefix,ginfo->prefix); } else { if (ginfo->prefix!=-1) { insert_code_table(ginfo,ginfo->code,ginfo->prefix); } } // output code ... output_code(ginfo,ginfo->code); ginfo->prefix=ginfo->code; } } return 0;}void clear_code_table(gif_info_t* ginfo,int clear){ int i; ginfo->free_code=clear+2; ginfo->prefix=-1; for(i=0;i<clear;i++) { ginfo->code_table[i].first=i; // first char ginfo->code_table[i].last=i; // last char ginfo->code_table[i].prefix=-1; // prefix index } for(i=clear;i<4096;i++) { ginfo->code_table[i].prefix=-2; } ginfo->request_bits=ginfo->first_ch+1; ginfo->code_limit=1<<ginfo->request_bits;}void insert_code_table(gif_info_t* ginfo,int code,int prefix){ ginfo->code_table[ginfo->free_code].prefix=ginfo->prefix; ginfo->code_table[ginfo->free_code].last=ginfo->code_table[code].first; ginfo->code_table[ginfo->free_code].first=ginfo->code_table[prefix].first; ginfo->free_code++; if (ginfo->free_code==ginfo->code_limit) { if (ginfo->request_bits<12) { ginfo->request_bits++; ginfo->code_limit=1<<ginfo->request_bits; } }}void output_code(gif_info_t* ginfo,int code){ int i=0; while(code!=-1) { ginfo->code_string[i++]=ginfo->code_table[code].last; code=ginfo->code_table[code].prefix; } for(i--;i>=0;i--) { output_pixel(ginfo,ginfo->code_string[i]); }}void output_pixel(gif_info_t* ginfo,unsigned char pixel) { unsigned char r,g,b; if (ginfo->b_local_palette!=0) { r=ginfo->gif_local_palette.palette[pixel*3]; g=ginfo->gif_local_palette.palette[pixel*3+1]; b=ginfo->gif_local_palette.palette[pixel*3+2]; } else { r=ginfo->gif_global_palette.palette[pixel*3]; g=ginfo->gif_global_palette.palette[pixel*3+1]; b=ginfo->gif_global_palette.palette[pixel*3+2]; } draw_pixel(ginfo,r,g,b); ginfo->gif_x++; if (ginfo->gif_x>=ginfo->gif_local.width) { ginfo->gif_x=0; if (ginfo->b_interlaced==0) { ginfo->gif_y++; } else { ginfo->gif_y+=v_incr[ginfo->pass]; if (ginfo->gif_y>=ginfo->gif_local.height) { ginfo->pass++; ginfo->gif_y=v_start[ginfo->pass]; } } }}/* * get request_bits from buffer */int get_code(gif_info_t* ginfo){ int request_bits=ginfo->request_bits; int value=0; int mask; int position=0,use_bits=0; while(request_bits>0) { if (ginfo->remain_bits==0) { if (ginfo->remain_bytes==0) { ginfo->remain_bytes=*ginfo->gif_cur_buffer++; } ginfo->remain_bytes--; ginfo->remain_bits=8; ginfo->data=*ginfo->gif_cur_buffer++; } if (request_bits>=ginfo->remain_bits) { use_bits=ginfo->remain_bits; } else { use_bits=request_bits; } ginfo->remain_bits-=use_bits; mask=0xff>>(8-use_bits); mask&=ginfo->data; // store remain useful bits to low bits of data ginfo->data>>=use_bits; mask<<=position; // new position that bits should be placed next time position+=use_bits; // insert these bits to the value value|=mask; request_bits-=use_bits; } return value;}void draw_pixel(gif_info_t* ginfo,int r,int g,int b){ int x,y; int offset; unsigned char* mem; x=ginfo->gif_x; y=ginfo->gif_y; offset=ginfo->gif_local.width*y+x; mem=(unsigned char*)(ginfo->gif_surface); mem+=offset*3; if (r>=0) { *mem=(char)r; } mem++; if (g>=0) { *mem=(char)g; } mem++; if (b>=0) { *mem=(char)b; } mem++;}void destroy_gif(gif_info_t* ginfo) { if (ginfo->gif_surface!=NULL) { free(ginfo->gif_surface); }}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -