gif2apng-1.7.orig/0000755000000000000000000000000011727053104012513 5ustar rootrootgif2apng-1.7.orig/gif2apng.c0000644000000000000000000010275011720017614014360 0ustar rootroot/* gif2apng version 1.7 * * This program converts GIF animations into APNG format. * * http://gif2apng.sourceforge.net/ * * Copyright (c) 2009-2012 Max Stepin * maxst at users.sourceforge.net * * zlib license * ------------ * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * */ #define PNG_ZBUF_SIZE 32768 #include #include #include #include "zlib.h" #if defined(_MSC_VER) && _MSC_VER >= 1300 #define swap16(data) _byteswap_ushort(data) #define swap32(data) _byteswap_ulong(data) #elif defined(__linux__) #include #define swap16(data) bswap_16(data) #define swap32(data) bswap_32(data) #elif defined(__FreeBSD__) #include #define swap16(data) bswap16(data) #define swap32(data) bswap32(data) #elif defined(__APPLE__) #include #define swap16(data) OSSwapInt16(data) #define swap32(data) OSSwapInt32(data) #else unsigned short swap16(unsigned short data) {return((data & 0xFF) << 8) | ((data >> 8) & 0xFF);} unsigned int swap32(unsigned int data) {return((data & 0xFF) << 24) | ((data & 0xFF00) << 8) | ((data >> 8) & 0xFF00) | ((data >> 24) & 0xFF);} #endif typedef struct { z_stream zstream; unsigned char * zbuf; int x, y, w, h, valid; } OP; typedef struct { unsigned char r, g, b, a; unsigned int num; } STATS; OP op[6]; STATS stats[256]; unsigned int next_seq_num; unsigned char png_sign[8] = {137, 80, 78, 71, 13, 10, 26, 10}; unsigned char png_Software[24] = { 83, 111, 102, 116, 119, 97, 114, 101, '\0', 103, 105, 102, 50, 97, 112, 110, 103, 46, 115, 102, 46, 110, 101, 116}; int cmp_stats( const void *arg1, const void *arg2 ) { if ( ((STATS*)arg2)->a == ((STATS*)arg1)->a ) return ((STATS*)arg2)->num - ((STATS*)arg1)->num; else return ((STATS*)arg1)->a - ((STATS*)arg2)->a; } void DecodeLZW(unsigned char * img, FILE * f1) { int i, bits, codesize, codemask, clearcode, nextcode, lastcode; unsigned int j; unsigned int size = 0; unsigned int accum = 0; unsigned short prefix[4097]; unsigned char suffix[4097]; unsigned char str[4097]; unsigned char data[1024]; unsigned char firstchar = 0; unsigned char *pstr = str; unsigned char *pout = img; unsigned char mincodesize; if (fread(&mincodesize, 1, 1, f1) != 1) return; bits = 0; codesize = mincodesize + 1; codemask = (1 << codesize) - 1; clearcode = 1 << mincodesize; nextcode = clearcode + 2; lastcode = -1; for (i=0; i= codesize) { int incode; int code = accum & codemask; accum >>= codesize; bits -= codesize; if (code == clearcode + 1) break; if (code == clearcode) { codesize = mincodesize + 1; codemask = (1 << codesize) - 1; nextcode = clearcode + 2; lastcode = -1; continue; } if (lastcode == -1) { *pout++ = suffix[code]; firstchar = lastcode = code; continue; } incode = code; if (code >= nextcode) { *pstr++ = firstchar; code = lastcode; } while (code >= clearcode) { *pstr++ = suffix[code]; code = prefix[code]; } *pstr++ = firstchar = suffix[code]; if (nextcode < 4096) { prefix[nextcode] = lastcode; suffix[nextcode] = firstchar; nextcode++; if (((nextcode & codemask) == 0) && (nextcode < 4096)) { codesize++; codemask += nextcode; } } lastcode = incode; do { *pout++ = *--pstr; } while (pstr > str); } } if (fread(&size, 1, 1, f1) != 1) return; } } void write_chunk(FILE * f, const char * name, unsigned char * data, unsigned int length) { unsigned int crc = crc32(0, Z_NULL, 0); unsigned int len = swap32(length); fwrite(&len, 1, 4, f); fwrite(name, 1, 4, f); crc = crc32(crc, (const Bytef *)name, 4); if (memcmp(name, "fdAT", 4) == 0) { unsigned int seq = swap32(next_seq_num++); fwrite(&seq, 1, 4, f); crc = crc32(crc, (const Bytef *)(&seq), 4); length -= 4; } if (data != NULL && length > 0) { fwrite(data, 1, length, f); crc = crc32(crc, data, length); } crc = swap32(crc); fwrite(&crc, 1, 4, f); } void write_IDATs(FILE * f, int frame, unsigned char * data, unsigned int length, unsigned int idat_size) { unsigned int z_cmf = data[0]; if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) { if (length >= 2) { unsigned int z_cinfo = z_cmf >> 4; unsigned int half_z_window_size = 1 << (z_cinfo + 7); while (idat_size <= half_z_window_size && half_z_window_size >= 256) { z_cinfo--; half_z_window_size >>= 1; } z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); if (data[0] != (unsigned char)z_cmf) { data[0] = (unsigned char)z_cmf; data[1] &= 0xe0; data[1] += (unsigned char)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); } } } while (length > 0) { unsigned int ds = length; if (ds > PNG_ZBUF_SIZE) ds = PNG_ZBUF_SIZE; if (frame == 0) write_chunk(f, "IDAT", data, ds); else write_chunk(f, "fdAT", data, ds+4); data += ds; length -= ds; } } int get_rect(int w, int h, unsigned char *pimg1, unsigned char *pimg2, unsigned char *ptemp, int *px, int *py, int *pw, int *ph, int bpp, int has_tcolor, int tcolor) { int i, j; int x_min = w-1; int y_min = h-1; int x_max = 0; int y_max = 0; int diffnum = 0; int over_is_possible = 1; if (!has_tcolor) over_is_possible = 0; if (bpp == 1) { unsigned char *pa = pimg1; unsigned char *pb = pimg2; unsigned char *pc = ptemp; for (j=0; jx_max) x_max = i; if (jy_max) y_max = j; } else c = tcolor; *pc++ = c; } } else if (bpp == 3) { unsigned char *pa = pimg1; unsigned char *pb = pimg2; unsigned char *pc = ptemp; for (j=0; jx_max) x_max = i; if (jy_max) y_max = j; } else c2 = tcolor; memcpy(pc, &c2, 3); pa += 3; pb += 3; pc += 3; } } if (diffnum == 0) { *px = *py = 0; *pw = *ph = 1; } else { *px = x_min; *py = y_min; *pw = x_max-x_min+1; *ph = y_max-y_min+1; } return over_is_possible; } void deflate_rect(unsigned char *p, int x, int y, int w, int h, int bpp, int stride, unsigned char * row_buf, int zbuf_size, int n) { int j; unsigned char * row = p + y*stride + x*bpp; op[n].valid = 1; op[n].zstream.next_out = op[n].zbuf; op[n].zstream.avail_out = zbuf_size; for (j=0; j>4)] = 1; if (pal_l[i][0] == pal_l[i][1] && pal_l[i][1] == pal_l[i][2]) gray[pal_l[i][0]] = 1; else grayscale = 0; } if (frames == 0) { for (i=0; i<256; i++) { stats[i].r = pal_l[i][0]; stats[i].g = pal_l[i][1]; stats[i].b = pal_l[i][2]; stats[i].num = num[i]; } ssize = (palsize_g > palsize_l) ? palsize_g : palsize_l; } else { for (i=0; i<256; i++) if (num[i] > 0) { int found = 0; for (j=0; j>4)&0xF0; tg = i&0xF0; tb = (i<<4)&0xF0; unused = 1; break; } } if (coltype == 3) { if (keep_palette == 1) { for (i=0; i plte_size) plte_size = trns_size; } } else { if (grayscale) { int gray_count = 0; for (i=0; i<256; i++) gray_count += gray[i]; if (gray_count <= 192) grayscale = 0; } if (grayscale) { coltype = 0; plte_size = 0; if (has_tcolor) { tcolor = stats[tcolor].r; if (gray[tcolor] == 1) has_tcolor = 0; } if (!has_tcolor) for (i=0; i<256; i++) if (gray[i] == 0) { has_tcolor = 1; tcolor = i; break; } if (has_tcolor) { trns[0] = 0; trns[1] = tcolor; trns_size = 2; } } else { if (!has_tcolor) for (i=0; i<256; i++) if (stats[i].num == 0) { has_tcolor = 1; tcolor = i; break; } if (has_tcolor) stats[tcolor].a = 0; qsort(&stats[0], 256, sizeof(STATS), cmp_stats); for (i=0; i<256; i++) { plte[i][0] = stats[i].r; plte[i][1] = stats[i].g; plte[i][2] = stats[i].b; trns[i] = stats[i].a; if (stats[i].num != 0 || stats[i].a != 255) plte_size = i+1; if (trns[i] != 255) trns_size = i+1; if (trns[i] == 0) tcolor = i; } } } } else /* coltype == 2 */ { if (has_tcolor || unused) { trns[0] = 0; trns[1] = tr; trns[2] = 0; trns[3] = tg; trns[4] = 0; trns[5] = tb; trns_size = 6; has_tcolor = 1; tcolor = (tb<<16) + (tg<<8) + tr; } } /* Optimizations and making plte[] and trns[] - end */ delays = (unsigned short *)malloc(frames*2); if (delays == NULL) return 1; for (i=0; i 1) write_chunk(f2, "acTL", (unsigned char *)(&actl), 8); if (plte_size > 0 && coltype == 3) write_chunk(f2, "PLTE", (unsigned char *)(&plte), plte_size*3); if (trns_size > 0) write_chunk(f2, "tRNS", trns, trns_size); idat_size = (rowbytes + 1) * h; zbuf_size = idat_size + ((idat_size + 7) >> 3) + ((idat_size + 63) >> 6) + 11; for (i=0; i<6; i++) { op[i].zstream.data_type = Z_BINARY; op[i].zstream.zalloc = Z_NULL; op[i].zstream.zfree = Z_NULL; op[i].zstream.opaque = Z_NULL; deflateInit2(&op[i].zstream, Z_BEST_COMPRESSION, 8, 15, 8, Z_DEFAULT_STRATEGY); op[i].zbuf = (unsigned char *)malloc(zbuf_size); if (op[i].zbuf == NULL) return 1; } zbuf = (unsigned char *)malloc(zbuf_size); if (zbuf == NULL) return 1; row_buf = (unsigned char *)malloc(rowbytes + 1); if (row_buf == NULL) return 1; row_buf[0] = 0; x1 = 0; y1 = 0; w1 = w; h1 = h; bop = 0; fseek( f1, start, SEEK_SET ); dispose_op = 0; has_t = 0; n = 0; while ( !feof(f1) ) { if (fread(&id, 1, 1, f1) != 1) return 1; if (id == 0x21) { if (fread(&val, 1, 1, f1) != 1) return 1; if (val == 0xF9) { if (fread(&size, 1, 1, f1) != 1) return 1; if (fread(&flags, 1, 1, f1) != 1) return 1; if (fread(&delay, 2, 1, f1) != 1) return 1; if (fread(&t, 1, 1, f1) != 1) return 1; if (fread(&end, 1, 1, f1) != 1) return 1; has_t = flags & 1; dispose_op = (flags >> 2) & 7; if (dispose_op > 3) dispose_op = 3; if (dispose_op == 3 && n == 0) dispose_op = 2; if (delay > 1) delays[n] = delay; } else { if (fread(&size, 1, 1, f1) != 1) return 1; while (size != 0) { if (fread(&data[0], 1, size, f1) != size) return 1; if (fread(&size, 1, 1, f1) != 1) return 1; } } } else if (id == 0x2C) { /* decode GIF frame - start */ unsigned char * src; unsigned char * dst; unsigned int sh[256]; unsigned int shuffle = 0; x0 = y0 = w0 = h0 = 0; if (fread(&x0, 2, 1, f1) != 1) return 1; if (fread(&y0, 2, 1, f1) != 1) return 1; if (fread(&w0, 2, 1, f1) != 1) return 1; if (fread(&h0, 2, 1, f1) != 1) return 1; if (fread(&flags, 1, 1, f1) != 1) return 1; interlaced = flags & 0x40; memcpy(&pal_l, &pal_g, 256*3); if (flags & 0x80) { palsize_l = 1 << ((flags & 7) + 1); if (fread(&pal_l, 3, palsize_l, f1) != palsize_l) return 1; } if (coltype == 3) { for (c=0; c<256; c++) { sh[c] = c; if (has_t && c==t) sh[c] = tcolor; else { for (i=0; ih2) ? (j-h2)*2-1 : (j>h2/2) ? (j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8; src = buffer + j*w0; dst = frame0 + ((k+y0)*w + x0)*3; for (i=0; ih2) ? (j-h2)*2-1 : (j>h2/2) ? (j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8; src = buffer + j*w0; dst = frame0 + (k+y0)*w + x0; if (shuffle) { for (i=0; i 1) { try_over = get_rect(w, h, frame2, frame0, temp, &x2, &y2, &w2, &h2, bpp, has_tcolor, tcolor); deflate_rect(frame0, x2, y2, w2, h2, bpp, rowbytes, row_buf, zbuf_size, 4); if (try_over) deflate_rect(temp, x2, y2, w2, h2, bpp, rowbytes, row_buf, zbuf_size, 5); } op_min = op[0].zstream.total_out; op_best = 0; for (j=1; j<6; j++) { if (op[j].valid) { if (op[j].zstream.total_out < op_min) { op_min = op[j].zstream.total_out; op_best = j; } } } dop = op_best >> 1; fctl.mSeq = swap32(next_seq_num++); fctl.mWidth = swap32(w1); fctl.mHeight = swap32(h1); fctl.mXOffset = swap32(x1); fctl.mYOffset = swap32(y1); fctl.mDelayNum = swap16(delays[n-1]); fctl.mDelayDen = swap16((unsigned short)100); fctl.mDisposeOp = dop; fctl.mBlendOp = bop; write_chunk(f2, "fcTL", (unsigned char *)(&fctl), 26); write_IDATs(f2, n-1, zbuf, zsize, idat_size); /* process apng dispose - begin */ if (dop == 1) { if (coltype == 2) { for (j=0; j 1) { fctl.mSeq = swap32(next_seq_num++); fctl.mWidth = swap32(w1); fctl.mHeight = swap32(h1); fctl.mXOffset = swap32(x1); fctl.mYOffset = swap32(y1); fctl.mDelayNum = swap16(delays[frames-1]); fctl.mDelayDen = swap16((unsigned short)100); fctl.mDisposeOp = 0; fctl.mBlendOp = bop; write_chunk(f2, "fcTL", (unsigned char *)(&fctl), 26); } write_IDATs(f2, frames-1, zbuf, zsize, idat_size); free(row_buf); free(zbuf); for (j=0; j<6; j++) { deflateEnd(&op[j].zstream); free(op[j].zbuf); } write_chunk(f2, "tEXt", png_Software, 24); write_chunk(f2, "IEND", 0, 0); fclose(f2); printf("%d frames.\n", n); } else printf("Error: can't open the file '%s'\n", szOut); /* APNG encoding - end */ free(frame0); free(frame1); free(frame2); free(rest); free(temp); free(delays); free(buffer); fclose(f1); } else { printf("Error: can't open the file '%s'\n", szIn); return 1; } return 0; } gif2apng-1.7.orig/readme.txt0000644000000000000000000000100611720017574014512 0ustar rootroot gif2apng version 1.7 This program converts GIF animations into APNG format. http://gif2apng.sourceforge.net/ Copyright (c) 2009-2012 Max Stepin maxst@users.sourceforge.net License: zlib license -------------------------------- Changes in version 1.7: - Fixed a transparency bug with some true-color apng files. -------------------------------- Usage: gif2apng anim.gif [anim.png] [/kp] Options: /kp keep the palette from GIF as is, do not optimize it. gif2apng-1.7.orig/Makefile0000644000000000000000000000005111720017552014147 0ustar rootrootall: gcc -O2 -o gif2apng gif2apng.c -lz