void create_mgif_delta() { void *d; long siz; //conv_2_rgb(); init_palmap(); if (BZTRATA) create_color_state(); set_max_color_change(BZTRATA); create_low_quality(); if (delta_data_size+frame_delta_size>FRAME_LEN) { create_mgif_lzw(); return; } if (!frame_delta_size) return; reduce_palette(); filter_colors(frame_delta,frame_delta_size,color_map); d=join_two_blocks(delta_data,frame_delta,delta_data_size,frame_delta_size,&siz); init_lzw_compressor(8); memset(lzw_buffer,0,sizeof(lzw_buffer)); siz=lzw_encode(d,lzw_buffer,siz); done_lzw_compressor(); free(d); if (siz>FRAME_LEN) { create_mgif_lzw(); return; } write_chunk(MGIF_DELTA,siz,lzw_buffer); create_mgif_pal(); }
int main(void) { unsigned char outbuf[DICTSIZE]; unsigned char *outbuf_end = outbuf + DICTSIZE; struct lzw_state enc; struct lzw_state dec; for(unsigned n = 0; tests[n]; n++) { char *input = tests[n]; unsigned compressed[1024]; unsigned char output[1024]; printf(" input: %s\n", input); lzw_state_init(&enc); unsigned *comp_curs = &compressed[0]; unsigned complen = 0; for(unsigned i = 0; input[i]; i++) comp_curs += lzw_encode(&enc, input[i], comp_curs); comp_curs += lzw_encode_finish(&enc, comp_curs); complen = comp_curs - compressed; printf("compressed: "); for(unsigned i = 0; i < complen; i++) { printf("%u (", compressed[i]); print_dict_item(&enc, compressed[i]); printf(") "); } printf("\n"); memset(output, 0, sizeof(output)); lzw_state_init(&dec); unsigned char *dec_curs = &output[0]; for(unsigned i = 0; i < complen; i++) { unsigned char *outbuf_curs = lzw_decode(&dec, compressed[i], outbuf); memcpy(dec_curs, outbuf_curs, (outbuf_end - outbuf_curs)); dec_curs += (outbuf_end - outbuf_curs); } unsigned declen = dec_curs - output; printf("output: %*s (%u)\n\n", declen, output, declen); for(unsigned i = 0; input[i]; i++) assert(input[i] == output[i]); assert(declen == strlen(input)); } return 0; }
int main(int argc, char* argv[]){ int input_length = 100; uint8_t input[100] = {1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,0,0,0,0,2,2,2,1,1,1,0,0,0,0,2,2,2,2,2,2,0,0,0,0,1,1,1,2,2,2,0,0,0,0,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1}; int color_list_size = 4; LZWEncoderData ld; lzw_encode_initialize(&ld, color_list_size); lzw_encode(&ld, input, input_length); lzw_encode_free(&ld); for(int m=0; m<ld.output_active_length; m++) printf("%02x ", ld.output[m]); printf("\n"); free(ld.output); return 0; }
/* ======================================================================== */ int gif_wr_frame_s ( gif_t *gif, uint_8 *vid ) { uint_8 *enc_ptr = gif_enc_buf; int lzw_len; size_t wrote; assert(enc_ptr); /* -------------------------------------------------------------------- */ /* Output local header. */ /* -------------------------------------------------------------------- */ *enc_ptr++ = 0x2C; /* Local header signature. */ *enc_ptr++ = 0; /* X position of image = 0 LSB */ *enc_ptr++ = 0; /* X position of image = 0 MSB */ *enc_ptr++ = 0; /* Y position of image = 0 LSB */ *enc_ptr++ = 0; /* Y position of image = 0 MSB */ *enc_ptr++ = (gif->x_dim >> 0) & 0xFF; /* Width = X dimension LSB */ *enc_ptr++ = (gif->x_dim >> 8) & 0xFF; /* Width = X dimension MSB */ *enc_ptr++ = (gif->y_dim >> 0) & 0xFF; /* Height = Y dimension LSB */ *enc_ptr++ = (gif->y_dim >> 8) & 0xFF; /* Height = Y dimension MSB */ *enc_ptr++ = 0; /* No local colors */ /* -------------------------------------------------------------------- */ /* Now compress the image. */ /* -------------------------------------------------------------------- */ lzw_len = lzw_encode(vid, enc_ptr, gif->x_dim*gif->y_dim, gif_enc_buf_sz - (enc_ptr - gif_enc_buf)); if (lzw_len < 0) return -1; enc_ptr += lzw_len; assert(enc_ptr < gif_enc_buf + gif_enc_buf_sz); /* -------------------------------------------------------------------- */ /* Write the compressed image out. */ /* -------------------------------------------------------------------- */ wrote = fwrite(gif_enc_buf, 1, enc_ptr - gif_enc_buf, gif->f); if (wrote < (unsigned)(enc_ptr - gif_enc_buf)) return -1; return wrote; }
int lzw_benchmark(char *code) { char *alphabet = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI"; data *d = lzw_encode(alphabet, code); int result = data_size(d); /*char *dec = lzw_decode(alphabet, d); if (strncmp(dec, code, strlen(code)) != 0) { printf("[LZW ERROR]\n"); printf("Original: %s\n", code); printf("Decoded : %s\n", dec); } free(dec);*/ data_free(d); return result; }
void create_mgif_lzw() { int siz; //conv_2_rgb(); init_palmap(); create_mgif_pal(); filter_colors(frame_buffer,FRAME_LEN,color_map); create_last_frame(frame_buffer,last_frame,hipal,FRAME_LEN); init_lzw_compressor(8); memset(lzw_buffer,0,sizeof(lzw_buffer)); siz=lzw_encode(frame_buffer,lzw_buffer,FRAME_LEN); if (siz>FRAME_LEN) write_chunk(MGIF_COPY,FRAME_LEN,frame_buffer); else write_chunk(MGIF_LZW,siz,lzw_buffer); done_lzw_compressor(8); }
void assert_lzw(char *plain) { memset(enc_buf, 0, sizeof(enc_buf)); memset(res_buf, 0, sizeof(res_buf)); size_t esz = lzw_encode(plain, strlen(plain), enc_buf); lzw_decode(enc_buf, esz, res_buf); char *input = plain; char *output = res_buf; while (*input) { if (*input++ != *output++) { res_buf[4095] = 0; fprintf(stderr, "\x1b[41mTEST FAILED: %s == %s\x1b[0m\n", plain, res_buf); failed = true; return; } } fprintf(stderr, "\x1b[42mTEST PASSED: \"%s\" == \"%s\"\x1b[0m\n", plain, res_buf); }
int main(int argc, char **argv) { #if 1 bitstream_t bs = {}; bs.data = malloc(1000000); memset(bs.data, 0, 1000000); { write_bits(&bs, 1, 0b1); ASSERT_EQ(bs.data[0], 0b00000001); ASSERT_EQ(bs.bit, 1); ASSERT_EQ(bs.index, 0); fprintf(stderr, "\n"); write_bits(&bs, 4, 0b1010); ASSERT_EQ(bs.data[0], 0b00010101); ASSERT_EQ(bs.bit, 5); ASSERT_EQ(bs.index, 0); fprintf(stderr, "\n"); write_bits(&bs, 3, 0b101); ASSERT_EQ(bs.data[0], 0b10110101); ASSERT_EQ(bs.bit, 0); ASSERT_EQ(bs.index, 1); fprintf(stderr, "\n"); write_bits(&bs, 5, 0b11011); ASSERT_EQ(bs.data[0], 0b10110101); ASSERT_EQ(bs.data[1], 0b00011011); ASSERT_EQ(bs.bit, 5); ASSERT_EQ(bs.index, 1); fprintf(stderr, "\n"); write_bits(&bs, 5, 0b10110); ASSERT_EQ(bs.data[0], 0b10110101); ASSERT_EQ(bs.data[1], 0b11011011); ASSERT_EQ(bs.data[2], 0b00000010); ASSERT_EQ(bs.bit, 2); ASSERT_EQ(bs.index, 2); fprintf(stderr, "\n"); write_bits(&bs, 20, 0xABCDE); ASSERT_EQ(bs.data[0], 0b10110101); ASSERT_EQ(bs.data[1], 0b11011011); ASSERT_EQ(bs.data[2], 0b01111010); ASSERT_EQ(bs.data[3], 0b11110011); ASSERT_EQ(bs.data[4], 0b00101010); ASSERT_EQ(bs.bit, 6); ASSERT_EQ(bs.index, 4); fprintf(stderr, "\n"); write_bits(&bs, 1, 0); ASSERT_EQ(bs.data[0], 0b10110101); ASSERT_EQ(bs.data[1], 0b11011011); ASSERT_EQ(bs.data[2], 0b01111010); ASSERT_EQ(bs.data[3], 0b11110011); ASSERT_EQ(bs.data[4], 0b00101010); ASSERT_EQ(bs.bit, 7); ASSERT_EQ(bs.index, 4); fprintf(stderr, "\n"); } { ASSERT_EQ(extract_bits(0b11011011, 0, 8), 0b11011011); ASSERT_EQ(extract_bits(0b00000001, 0, 1), 0b1); ASSERT_EQ(extract_bits(0b11111110, 0, 1), 0b0); ASSERT_EQ(extract_bits(0b01111111, 7, 8), 0b0); ASSERT_EQ(extract_bits(0b10000000, 7, 8), 0b1); ASSERT_EQ(extract_bits(0b11011011, 2, 6), 0b0110); fprintf(stderr, "\n"); } bs.index = 0; bs.bit = 0; { ASSERT_EQ(read_bits(&bs, 1), 0b1); ASSERT_EQ(read_bits(&bs, 4), 0b1010); ASSERT_EQ(read_bits(&bs, 3), 0b101); ASSERT_EQ(read_bits(&bs, 5), 0b11011); ASSERT_EQ(read_bits(&bs, 5), 0b10110); ASSERT_EQ(read_bits(&bs, 20), 0xABCDE); ASSERT_EQ(read_bits(&bs, 1), 0); fprintf(stderr, "\n"); } assert_lzw("ababcbababaaaaaaa"); assert_lzw("A circular buffer, or ring buffer, is a FIFO container consisting of a fixed-size buffer and head & tail indices. The head index is incremented as items are added and the tail index when items are removed."); if (failed) { return 1; } #endif #if 1 // void *ibuff = malloc(10000000); // memset(ibuff, 0, 10000000); // void *obuff = malloc(10000000); // memset(obuff, 0, 10000000); // int *ebuff = malloc(10000000); // memset(ebuff, 0, 10000000); size_t rsz = read(STDIN_FILENO, ibuff, 10000000); size_t esz = lzw_encode(ibuff, rsz, ebuff); lzw_decode(ebuff, esz, obuff); write(STDOUT_FILENO, obuff, rsz); fprintf(stderr, "input size: %lu; compressed size: %lu; rate: %f\n", rsz, esz, (float)esz/(float)rsz); #endif }
/* ======================================================================== */ int gif_wr_frame_m ( gif_t *gif, uint_8 *vid, int delay, int mode ) { int trans = gif->trans >= 0; uint_8 *enc_ptr = gif_enc_buf; uint_8 *vid_ptr, *prv_ptr, *trn_ptr; uint_8 *best_img1, *best_img2, *best_lct; int x, y, xx, yy, min_x, min_y, max_x, max_y, width, height; int n_col_d, n_col_e = 0, n_col_f = 0, lct_sz_d, lct_sz_e, lct_sz_f; int enc_sz_a, enc_sz_b, enc_sz_c, enc_sz_d, enc_sz_e, enc_sz_f; int best_sz, best_lct_sz, trans_idx, do_trans = 0; int lzw_len; int cnt, num_trans = 0; char best = '*'; size_t wrote; assert(enc_ptr); /* -------------------------------------------------------------------- */ /* Allocate our image optimization scratch buffers, if necessary. */ /* -------------------------------------------------------------------- */ if (gif_img_sz < gif->x_dim * gif->y_dim) { if (gif_img_tr) free(gif_img_tr); gif_img_sz = gif->x_dim * gif->y_dim; gif_img_tr = CALLOC(uint_8, 7 * gif->x_dim * gif->y_dim + 3*256); if (!gif_img_tr) { fprintf(stderr, "gif_wr_frame_m: out of memory\n"); return -1; } gif_img_a = gif_img_tr + gif_img_sz * 2; gif_img_b = gif_img_a + gif_img_sz; gif_img_d = gif_img_b + gif_img_sz; gif_img_e = gif_img_d + gif_img_sz; gif_img_f = gif_img_e + gif_img_sz; gif_pal_d = gif_img_f + gif_img_sz; gif_pal_e = gif_pal_d + 256; gif_pal_f = gif_pal_e + 256; } /* -------------------------------------------------------------------- */ /* Optimize image: */ /* */ /* 1. Generate "transparency" image with trans pixels wherever this */ /* image is the same as the previous one. */ /* */ /* 2. Compute tighter bounding box on image--that is, smallest box */ /* that contains all the non-trans pixels. */ /* */ /* 3. Crop the incoming image based on the tighter bounding box. */ /* */ /* 4. Generate "minimal palette" images that renumber all the */ /* pixels into the smallest possible numbering space. */ /* */ /* 5. Compress the image multiple ways, and take the best: */ /* */ /* a. Cropped image, orig palette, no trans pixels */ /* b. Cropped image, orig palette, trans pixels */ /* c. Cropped image, orig palette, "wildcard" trans/no-trans */ /* d. Cropped image, new palette, no trans pixels */ /* e. Cropped image, new palette, trans pixels */ /* f. Cropped image, new palette, "wildcard" trans/no-trans */ /* */ /* When comparing new palette to orig palette, include cost */ /* of sending local palette. If the global palette has too */ /* many colors, we may not be able to try b or c. If the local */ /* palette has too many colors, we may not be able to try e or */ /* f. */ /* */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* 1. Generate "transparency" image... */ /* 2. Compute tighter bounding box on image... */ /* -------------------------------------------------------------------- */ min_x = gif->x_dim; min_y = gif->y_dim; max_x = 0; max_y = 0; vid_ptr = vid; prv_ptr = gif->vid; trn_ptr = gif_img_tr; for (y = 0; y < gif->y_dim; y++) for (x = 0; x < gif->x_dim; x++) { uint_8 curr = *vid_ptr++; uint_8 prev = *prv_ptr++; uint_8 tran = gif->trans; if (curr != prev) { tran = curr; if (x < min_x) min_x = x; if (y < min_y) min_y = y; if (x > max_x) max_x = x; if (y > max_y) max_y = y; } *trn_ptr++ = tran; } /* -------------------------------------------------------------------- */ /* Stop now if current image matches previous image. */ /* -------------------------------------------------------------------- */ if (min_x > max_x || min_y > max_y) return 0; if (mode != 0) { min_x = 0; min_y = 0; max_x = gif->x_dim - 1; max_y = gif->y_dim - 1; } width = max_x - min_x + 1; height = max_y - min_y + 1; cnt = width*height; /* -------------------------------------------------------------------- */ /* 3. Crop the incoming image based on the tighter bounding box. */ /* -------------------------------------------------------------------- */ for (y = min_y, yy = 0; y <= max_y; y++, yy++) for (x = min_x, xx = 0; x <= max_x; x++, xx++) { /* a. Cropped image, orig palette, no trans pixels */ /* b. Cropped image, orig palette, trans pixels */ gif_img_a[xx + yy*width] = vid [x + y*gif->x_dim]; gif_img_b[xx + yy*width] = gif_img_tr[x + y*gif->x_dim]; if (gif_img_tr[x + y*gif->x_dim] == gif->trans) num_trans++; } if (num_trans == 0) trans = 0; if (mode != 0) trans = 0; #if 0 { FILE *ff; ff = fopen("debug", "wb"); if (ff) { fwrite(gif_img_a, 1, cnt, ff); fclose(ff); } } #endif /* -------------------------------------------------------------------- */ /* 4. Generate "minimal palette" images... */ /* d. Cropped image, new palette, no trans pixels */ /* e. Cropped image, new palette, trans pixels */ /* f. Cropped image, new palette, "wildcard" trans/no-trans */ /* -------------------------------------------------------------------- */ n_col_d = gen_mpi(gif_img_a, NULL, gif_img_d, cnt, gif_pal_d); if(trans) n_col_e = gen_mpi(gif_img_b, NULL, gif_img_e, cnt, gif_pal_e); if(trans) n_col_f = gen_mpi(gif_img_b,gif_img_a,gif_img_f, cnt, gif_pal_f); for (lct_sz_d = 1; (2 << lct_sz_d) < n_col_d; lct_sz_d++); for (lct_sz_e = 1; (2 << lct_sz_e) < n_col_e; lct_sz_e++); for (lct_sz_f = 1; (2 << lct_sz_f) < n_col_f; lct_sz_f++); if (trans) { int i; for (i = 0; i < n_col_d; i++) assert(gif_pal_d[i] == gif_pal_f[i]); /*printf("n_col_d=%d, n_col_f=%d gif_pal_f[n_col_f-1]=%d gif->trans=%d\n", n_col_d, n_col_f, gif_pal_f[n_col_f-1], gif->trans);*/ assert(n_col_d < n_col_f); assert(gif_pal_f[n_col_f - 1] == gif->trans); } /* -------------------------------------------------------------------- */ /* 5. Compress the image multiple ways, and take the best... */ /* */ /* We reuse gif_img_tr as a compression buffer here, since we don't */ /* need that image any longer, but we do need a temp buffer for LZW. */ /* -------------------------------------------------------------------- */ enc_sz_a = lzw_encode(gif_img_a, gif_img_tr, cnt, gif_img_sz*2); enc_sz_b = -1; enc_sz_c = -1; enc_sz_d = lzw_encode(gif_img_d, gif_img_tr, cnt, gif_img_sz*2); enc_sz_e = -1; enc_sz_f = -1; if (trans) { enc_sz_b = lzw_encode(gif_img_b, gif_img_tr, cnt, gif_img_sz*2); enc_sz_e = lzw_encode(gif_img_e, gif_img_tr, cnt, gif_img_sz*2); #if 1 enc_sz_c = lzw_encode2(gif_img_b, gif_img_a, gif_img_tr, cnt, gif_img_sz); enc_sz_f = lzw_encode2(gif_img_f, gif_img_d, gif_img_tr, cnt, gif_img_sz); #endif } if (enc_sz_d > 0) enc_sz_d += 3 << (lct_sz_d + 1); if (enc_sz_e > 0) enc_sz_e += 3 << (lct_sz_e + 1); if (enc_sz_f > 0) enc_sz_f += 3 << (lct_sz_f + 1); if (enc_sz_a < 0) enc_sz_a = INT_MAX; if (enc_sz_b < 0) enc_sz_b = INT_MAX; if (enc_sz_c < 0) enc_sz_c = INT_MAX; if (enc_sz_d < 0) enc_sz_d = INT_MAX; if (enc_sz_e < 0) enc_sz_e = INT_MAX; if (enc_sz_f < 0) enc_sz_f = INT_MAX; /* Initially assume A's the best. */ best_img1 = gif_img_a; best_img2 = NULL; best_lct = NULL; best_lct_sz = 0; best_sz = enc_sz_a; trans_idx = 0; do_trans = 0; best = 'a'; #if 1 if (enc_sz_b < best_sz) { best_img1 = gif_img_b; best_img2 = NULL; best_lct = NULL; best_lct_sz = 0; best_sz = enc_sz_b; trans_idx = gif->trans; do_trans = 1; best = 'b'; } if (enc_sz_d < best_sz) { best_img1 = gif_img_d; best_img2 = NULL; best_lct = gif_pal_d; best_lct_sz = lct_sz_d; best_sz = enc_sz_d; trans_idx = 0; do_trans = 0; best = 'd'; } if (enc_sz_e < best_sz) { best_img1 = gif_img_e; best_img2 = NULL; best_lct = gif_pal_e; best_lct_sz = lct_sz_e; best_sz = enc_sz_e; trans_idx = n_col_e - 1; do_trans = 1; best = 'e'; } if (enc_sz_c < best_sz) { best_img1 = gif_img_b; best_img2 = gif_img_a; best_lct = NULL; best_lct_sz = 0; best_sz = enc_sz_c; trans_idx = gif->trans; do_trans = 1; best = 'c'; } if (enc_sz_f < best_sz) { best_img1 = gif_img_f; best_img2 = gif_img_d; best_lct = gif_pal_f; best_lct_sz = lct_sz_f; best_sz = enc_sz_f; trans_idx = n_col_f - 1; do_trans = 1; best = 'f'; } if (best_sz < 0 || best_sz == INT_MAX) { fprintf(stderr, "gif_wr_frame_m: Image overflowed compression " "buffer.\n"); return -1; } #endif gif_best_stat[best - 'a']++; /* -------------------------------------------------------------------- */ /* Output a Graphic Control Ext. */ /* -------------------------------------------------------------------- */ *enc_ptr++ = 0x21; /* Extension signature */ *enc_ptr++ = 0xF9; /* Graphic control extension */ *enc_ptr++ = 0x04; /* Length of block: Fixed at 4. */ *enc_ptr++ = 0x04 | do_trans; /* Disposal 01, No input, Trans */ *enc_ptr++ = (delay >> 0) & 0xFF; /* delay in 100ths of a second LSB */ *enc_ptr++ = (delay >> 8) & 0xFF; /* delay in 100ths of a second MSB */ *enc_ptr++ = trans_idx; /* Transparency index, if any. */ *enc_ptr++ = 0x00; /* GCE block terminator. */ /* -------------------------------------------------------------------- */ /* Output an Image Descriptor. */ /* -------------------------------------------------------------------- */ *enc_ptr++ = 0x2C; /* Image Separator */ *enc_ptr++ = (min_x >> 0) & 0xFF; /* Left edge, LSB */ *enc_ptr++ = (min_x >> 8) & 0xFF; /* Left edge, MSB */ *enc_ptr++ = (min_y >> 0) & 0xFF; /* Top edge, LSB */ *enc_ptr++ = (min_y >> 8) & 0xFF; /* Top edge, MSB */ *enc_ptr++ = (width >> 0) & 0xFF; /* Image width, LSB */ *enc_ptr++ = (width >> 8) & 0xFF; /* Image width, MSB */ *enc_ptr++ = (height >> 0) & 0xFF; /* Image height, LSB */ *enc_ptr++ = (height >> 8) & 0xFF; /* Image height, MSB */ *enc_ptr++ = best_lct_sz == 0 ? 0 /* no local color table? */ : best_lct_sz | 0x80; /* or yes local color table? */ /*printf("[%3d,%3d] [%3d,%3d] [%3d,%3d] delay=%-3d trans=%-3d%c lct=%d\n", min_x, min_y, width, height, min_x + width, min_y + height, delay, trans_idx, do_trans ? '*' : ' ', best_lct_sz);*/ /* -------------------------------------------------------------------- */ /* If we're sending a local color table, put it here. */ /* -------------------------------------------------------------------- */ if (best_lct_sz) { int i; for (i = 0; i < (2 << best_lct_sz); i++) { if (best_lct[i] < gif->n_cols) { *enc_ptr++ = gif->pal[3*best_lct[i] + 0]; *enc_ptr++ = gif->pal[3*best_lct[i] + 1]; *enc_ptr++ = gif->pal[3*best_lct[i] + 2]; } else { *enc_ptr++ = 0; *enc_ptr++ = 0; *enc_ptr++ = 0; } } } /* -------------------------------------------------------------------- */ /* Now, re-encode the winning image. */ /* -------------------------------------------------------------------- */ if (best_img2) { lzw_len = lzw_encode2(best_img1, best_img2, enc_ptr, cnt, gif_enc_buf_sz - (enc_ptr - gif_enc_buf) - 1); } else { lzw_len = lzw_encode(best_img1, enc_ptr, cnt, gif_enc_buf_sz - (enc_ptr - gif_enc_buf) - 1); } if (lzw_len < 0) { fprintf(stderr, "gif_wr_frame_m: Final encode failed?\n"); return -1; } enc_ptr += lzw_len; assert(enc_ptr < gif_enc_buf + gif_enc_buf_sz); /* -------------------------------------------------------------------- */ /* Write the compressed image out. */ /* -------------------------------------------------------------------- */ wrote = fwrite(gif_enc_buf, 1, enc_ptr - gif_enc_buf, gif->f); if (wrote < (unsigned)(enc_ptr - gif_enc_buf)) { fprintf(stderr, "gif_wr_frame_m: Short write? %ld vs %ld\n", (long)wrote, (long)(enc_ptr - gif_enc_buf)); return -1; } /* -------------------------------------------------------------------- */ /* Make the current image the new previous image. */ /* -------------------------------------------------------------------- */ memcpy(gif->vid, vid, gif->x_dim * gif->y_dim); return wrote; }