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

📄 save_gif.c

📁 gif编码和解码的程序。:)
💻 C
字号:
// GIF Saver
// by Paul Bartrum

#include <allegro.h>

typedef struct
{
	short base;
	unsigned char new;
} LZW_STRING;

typedef struct
{
	int pos;
	int bit_pos;
	unsigned char data[255];
} BUFFER;


void clear_speed_buffer(short *speed_buffer)
{
	// clear speed buffer to -1
	__asm__("csb_loop:\n"
					"movl %%ecx, (%%eax)\n"
					"addl %%edx, %%eax\n"
					"decl %%ebx\n"
					"jne csb_loop\n"
					:
					: "a" (speed_buffer), "b" (256 * 4096 / 2), "c" (-1), "d" (4)
					: "memory");
}

void dump_buffer(BUFFER *b, PACKFILE *f)
{
	int size;

	size = b->pos;
	if(b->bit_pos != 0)
		size ++;

	pack_putc(size, f);
	pack_fwrite(b->data, size, f);
}

void output(BUFFER *b, int bit_size, int code, PACKFILE *f)
{
	int shift;

	// pack the code into the buffer
	shift = b->bit_pos;
	do {
		if(shift >= 0) {
			if(b->bit_pos != 0)
				b->data[b->pos] = (unsigned char)((code << shift) | b->data[b->pos]);
			else
				b->data[b->pos] = (unsigned char)(code << shift);
		}
		else {
			if(b->bit_pos != 0)
				b->data[b->pos] = (unsigned char)((code >> -shift) | b->data[b->pos]);
			else
				b->data[b->pos] = (unsigned char)(code >> -shift);
		}
		if(bit_size + shift > 7) {
			b->bit_pos = 0;
			b->pos ++;
			shift -= 8;
			if(b->pos == 255) {
				dump_buffer(b, f);
				b->pos = 0;
				b->bit_pos = 0;
			}
			if(bit_size + shift <= 0)
				break;
		}
		else {
			b->bit_pos = bit_size + shift;
			break;
		}
	} while(TRUE);
}

int save_gif(char *filename, BITMAP *bmp, RGB *pal)
{
	PACKFILE *f;
	int i, bpp, bit_size;
	LZW_STRING string_table[4096];
	int prefix;
	int input_pos = 0;
	int c;												// current character
	int empty_string;
	BUFFER buffer;
	short *speed_buffer;

	f = pack_fopen(filename, F_WRITE);
	if (!f)
		return errno;

	pack_mputl(0x47494638, f);		// GIF8
	pack_mputw(0x3761, f);				// 7a
	pack_iputw(bmp->w, f);				// width
	pack_iputw(bmp->h, f);				// height
	pack_putc(215, f);						// packed fields
	pack_putc(0, f);							// background colour
	pack_putc(0, f);							// pixel aspect ratio

	// global colour table
	for(i = 0; i < 256; i ++) {
		pack_putc(pal[i].r << 2, f);
		pack_putc(pal[i].g << 2, f);
		pack_putc(pal[i].b << 2, f);
	}

	pack_putc(0x2c, f);						// image separator
	pack_iputw(0, f);							// x offset
	pack_iputw(0, f);							// y offset
	pack_iputw(bmp->w, f);				// width
	pack_iputw(bmp->h, f);				// height
	pack_putc(0, f);							// packed fields

	// Image data starts here
	bpp = 8;
	pack_putc(bpp, f);			// initial code size

	// initialize string table
	for(i = 0; i < 1 << bpp; i ++) {
		string_table[i].base = -1;
		string_table[i].new = i;
	}
	for(; i < (1 << bpp) + 2; i ++) {
		string_table[i].base = -1;
		string_table[i].new = -1;
	}
	empty_string = (1 << bpp) + 2;

	prefix = -1;

	bit_size = bpp + 1;

	buffer.pos = 0;
	buffer.bit_pos = 0;

	output(&buffer, bit_size, 1 << bpp, f);					// clear code

	speed_buffer = malloc(256 * 4096 * 2);
	clear_speed_buffer(speed_buffer);

	while(TRUE) {
		if((c = getpixel(bmp, input_pos % bmp->w, input_pos / bmp->w)) == EOF) {
			output(&buffer, bit_size, prefix, f);
			output(&buffer, bit_size, (1 << bpp) + 1, f);		// end of information
			dump_buffer(&buffer, f);
			pack_putc(0, f);		// no more data blocks
			break;
		}
		input_pos ++;

		//i = search_table(string_table, prefix, c, empty_string);
		//i = quick_search_table(string_table, prefix, c, empty_string, speed_buffer);
		if(prefix == -1)
			i = c;
		else
			i = speed_buffer[prefix * 256 + c];
		if(i != -1) {
			prefix = i;
		}
		else {
			// add prefix + c to string table
			string_table[empty_string].base = prefix;
			string_table[empty_string].new = c;

			//if(prefix < 512)
				speed_buffer[prefix * 256 + c] = empty_string;

			empty_string ++;

			// output code for prefix
			output(&buffer, bit_size, prefix, f);

			if(empty_string == (1 << bit_size) + 1)
				bit_size ++;

			// make sure string table doesn't overflow
			if(empty_string == 4095) {
				output(&buffer, bit_size, 1 << bpp, f); // clear code
				empty_string = (1 << bpp) + 2;
				bit_size = bpp + 1;

				clear_speed_buffer(speed_buffer);
			}

			// set prefix to c
			prefix = c;
		}
	}

	free(speed_buffer);

	pack_putc(0x3b, f);						// trailer (end of gif)
	pack_fclose(f);
	return errno;
}

⌨️ 快捷键说明

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