#include #include #include void giftrans(FILE *fin, FILE *fout, int index) { char header[14]; unsigned char color_table[1000]; int flags; int has_global_colormap; int bits_per_pixel; int colormap_entries; int color_tbl_size; int bits_color_byte; int rgb_byte_mask; int i; unsigned char nextblock[8]; /* The header looks like: byte 0 - 5: "GIF89a" or "GIF87a" byte 6, 7: width (low order first) byte 8, 9: height (low order first) byte 10: various flags byte 11: background color index byte 12: aspect ratio */ fread(header, 13, 1, fin); if (memcmp(header, "GIF", 3)) { printf("Not a GIF\n"); return; } if (!memcmp(header, "GIF87a", 6)) memcpy(header, "GIF89a", 6); printf("width = %d, height = %d\n", header[6] + header[7] * 256, header[8] + header[9] * 256); if (fout) fwrite(header, 13, 1, fout); /* Look at flags (8 bits): hi[MCCCSPPP]low M = global colormap present? CCC = bits/color/colormapentry - 1 S = color map sorted by importance? PPP = bits/pixel - 1 therefore Bits/pixel = PPP+1 Number of possible colors (entries in colormap): 2 ** (PPP+1) : 1 << (PPP+1) Size (bytes) of colormap: 3 * Number of possible colors : 3 * (1 << (PPP+1)) */ flags = header[10]; has_global_colormap = flags & 0x80; /* Copy over the colormap if need be. */ if (!has_global_colormap) { printf("Does not have color map"); return; } bits_per_pixel = 1 + (flags & 0x07); colormap_entries = 1 << bits_per_pixel; color_tbl_size = 3 * colormap_entries; printf("bits per pixel = %d, colormap_entries = %d, size = %d\n", bits_per_pixel, colormap_entries, color_tbl_size); fread(color_table, color_tbl_size, 1, fin); if (fout) fwrite(color_table, color_tbl_size, 1, fout); /* For each byte of each colormap's RGB triplit, we'll have to mask off bits that aren't used when looking at the color values. */ bits_color_byte = 1 + ((flags >> 4) & 0x07); rgb_byte_mask = (1 << bits_color_byte) - 1; printf(" r g b\n"); for (i = 0; i < colormap_entries; i++) { printf("%3d : %3d %3d %3d\n", i, color_table[i*3], color_table[i*3+1], color_table[i*3+2]); } /* The next 8 bytes will either be an already-there graphic-extension block, or something else that we'll not care about. In the latter case, we'll add a graphic-extension block saying "color such-and- such is transparent". If there's already one there, we'll just ensure that it says that. */ fread(nextblock, 8, 1, fin); /* If extension is 0x21 and label is 0xf9, that's the magic tha means there's already a graphic extension there. */ if (nextblock[0] == 0x21 && nextblock[1] == 0xf9) { nextblock[3] |= 1; nextblock[6] = index; } else { char newblock[8]; newblock[0] = 0x21; newblock[1] = 0xf9; newblock[2] = 4; newblock[3] = 1; newblock[4] = 0; newblock[5] = 0; newblock[6] = index; newblock[7] = 0; if (fout) fwrite(newblock, 8, 1, fout); } if (fout) fwrite(nextblock, 8, 1, fout); if (fout == NULL) return; /* copy the rest */ { char ch = (char)fgetc(fin); while (!feof(fin)) { fputc(ch, fout); ch = (char)fgetc(fin); } } } void main(int argc, char *argv[]) { FILE *fin = NULL, *fout = NULL; int index; if (argc == 1) { printf("transgif [ ]\n"); return; } fin = fopen(argv[1], "rb"); if (fin == NULL) { printf("no file %s\n", argv[1]); return; } if (argc == 4) { index = atoi(argv[2]); fout = fopen(argv[3], "wb"); if (fout == NULL) printf("Cannot open %s\n"); } giftrans(fin, fout, index); fclose(fin); if (fout) fclose(fout); }