JNIEXPORT jint JNICALL Java_org_yoooo_GifUtil_Init(JNIEnv *ioEnv, jobject ioThis, jstring gifName, jint w, jint h, jint numColors, jint quality, jint frameDelay) { const char *str; str = ioEnv->GetStringUTFChars(gifName, NULL); if (str == NULL) { return -1; /* OutOfMemoryError already thrown */ } __android_log_write(ANDROID_LOG_VERBOSE, "gifflen",str); if ((pGif = fopen(str, "wb")) == NULL) { ioEnv->ReleaseStringUTFChars(gifName, str); return -2; } ioEnv->ReleaseStringUTFChars(gifName, str); optDelay = frameDelay; optCol = numColors; optQuality = quality; imgw = w; imgh = h; __android_log_write(ANDROID_LOG_VERBOSE, "gifflen","Allocating memory for input DIB"); data32bpp = new unsigned char[imgw * imgh * PIXEL_SIZE]; inDIB.bits = data32bpp; inDIB.width = imgw; inDIB.height = imgh; inDIB.bitCount = 32; inDIB.pitch = imgw * PIXEL_SIZE; inDIB.palette = NULL; __android_log_write(ANDROID_LOG_VERBOSE, "gifflen","Allocating memory for output DIB"); outDIB = new DIB(imgw, imgh, 8); outDIB->palette = new unsigned char[768]; neuQuant = new NeuQuant(); // Output the GIF header and Netscape extension fwrite("GIF89a", 1, 6, pGif); s[0] = w & 0xFF; s[1] = w / 0x100; s[2] = h & 0xFF; s[3] = h / 0x100; s[4] = 0x50 + max_bits(numColors) - 1; s[5] = s[6] = 0; s[7] = 0x21; s[8] = 0xFF; s[9] = 0x0B; fwrite(s, 1, 10, pGif); fwrite("NETSCAPE2.0", 1, 11, pGif); s[0] = 3; s[1] = 1; s[2] = s[3] = s[4] = 0; fwrite(s, 1, 5, pGif); return 0; }
/** Edit the trie so it maps a range of bit sequences to the same leaf. * * \param range_min * The first bit sequence in the range. Eight bits are packed in each byte. * The most significant bit of the whole sequence is in the * most significant bit of the first byte. * * \param range_max * The last bit sequence in the range. * * \param bit_count * The number of bits in both sequences. * * \param leaf * The leaf to which all the bit sequences in the range should be mapped. */ void binary_trie::set_range( const uint8_t range_min[], const uint8_t range_max[], std::size_t bit_count, edge_type leaf) { bits_vector min_bits(bit_count); bits_vector max_bits(bit_count); for (std::size_t i = 0; i < bit_count; ++i) { std::size_t byte_pos = i / 8; uint8_t mask = 1 << ((~i) % 8); min_bits[i] = ((range_min[byte_pos] & mask) != 0); max_bits[i] = ((range_max[byte_pos] & mask) != 0); } set_range_in_node(&min_bits, &max_bits, 0, 0, leaf); }
JNIEXPORT jint JNICALL Java_org_yoooo_GifUtil_AddFrame(JNIEnv *ioEnv, jobject ioThis, jintArray inArray) { ioEnv->GetIntArrayRegion(inArray, (jint)0, (jint)(inDIB.width * inDIB.height), (jint*)(inDIB.bits)); s[0] = '!'; s[1] = 0xF9; s[2] = 4; s[3] = 0; s[4] = optDelay & 0xFF; s[5] = optDelay / 0x100; s[6] = s[7] = 0; s[8] = ','; s[9] = s[10] = s[11] = s[12] = 0; s[13] = imgw & 0xFF; s[14] = imgw / 0x100; s[15] = imgh & 0xFF; s[16] = imgh / 0x100; s[17] = 0x80 + max_bits(optCol) - 1; fwrite(s, 1, 18, pGif); __android_log_write(ANDROID_LOG_VERBOSE, "gifflen","Quantising"); neuQuant->quantise(outDIB, &inDIB, optCol, optQuality, 0); fwrite(outDIB->palette, 1, optCol * 3, pGif); __android_log_write(ANDROID_LOG_VERBOSE, "gifflen","Doing GIF encoding"); GIF_LZW_compressor(outDIB, optCol, pGif, 0); return 0; }
int GIF_LZW_compressor(DIB *srcimg,unsigned int numColors,FILE *handle,int interlace) { int xdim,ydim,clear,EOI,code,bits,pre,suf,x,y,i,max,bits_color,done,rasterlen; static short int rasters[768]; stat_bits = 0; code_in_progress = 0; LZWpos = 1; for (i = 0; i < hash; i++) { hashtree[i][0] = hashtree[i][1] = hashtree[i][2] = -1; } if (handle==NULL) return 0; xdim = srcimg->width; ydim = srcimg->height; bits_color = max_bits(numColors)-1; clear = (1 << (bits_color+1)); //powers2[bits_color+2] EOI = clear+1; code = EOI+1; bits = bits_color+2; max = (1 << bits); //powers2[bits+1] if (code==max) { clear = 4; EOI = 5; code = 6; bits++; max *= 2; } fputc(bits-1, handle); write_code(handle, bits, clear); rasterlen = 0; if (interlace) { for (int e=1; e<=5; e+=4) { for (int f=e; f<=ydim; f+=8) { rasters[rasterlen++] = f; } } for (int e=3; e<=ydim; e+=4) { rasters[rasterlen++] = e; } for (int e=2; e<=ydim; e+=2) { rasters[rasterlen++] = e; } } else { for (int e=1; e<=ydim; e++) rasters[rasterlen++] = e - 1; } pre = srcimg->bits[rasters[0] * xdim]; x=1; y=0; done=0; if (x>=xdim) { y++; x=0; } while (1) { while (1) { if (!done) { suf = srcimg->bits[rasters[y] * xdim + x]; x++; if (x>=xdim) { y++; x=0; if (y>=ydim) done = 1; } i = find_hash(pre,suf); if (hashtree[i][0]==-1) break; else pre = hashtree[i][0]; } else { write_code(handle,bits,pre); write_code(handle,bits,EOI); if (stat_bits) write_code(handle,bits,0); LZW[0] = LZWpos - 1; fwrite(LZW, 1, LZWpos, handle); fputc(0, handle); return 1; } } write_code(handle,bits,pre); hashtree[i][0] = code; hashtree[i][1] = pre; hashtree[i][2] = suf; pre = suf; code++; if (code == max+1) { max *= 2; if (bits == 12) { write_code(handle,bits,clear); for (i = 0; i < hash; i++) { hashtree[i][0] = hashtree[i][1] = hashtree[i][2] = -1; } code = EOI+1; bits = bits_color+2; max = 1 << bits; if (bits == 2) { clear = 4; EOI = 5; code = 6; bits = 3; max *= 2; } } else bits++; } } return 0; }