Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

gifwrite.c File Reference

#include "gif.h"
#include <stdarg.h>
#include <string.h>

Go to the source code of this file.


Data Structures

struct  Gif_Context
struct  Gif_Node
struct  Gif_Writer

Defines

#define inline
#define WRITE_BUFFER_SIZE   255
#define NODES_SIZE   GIF_MAX_CODE
#define LINKS_SIZE   GIF_MAX_CODE
#define TABLE_TYPE   0
#define LINKS_TYPE   1
#define MAX_LINKS_TYPE   5
#define gifputbyte(b, grr)   ((*grr->byte_putter)(b, grr))
#define gifputblock(b, l, grr)   ((*grr->block_putter)(b, l, grr))
#define CUR_BUMP_CODE   (1 << cur_code_bits)

Typedefs

typedef Gif_Node Gif_Node
typedef Gif_Context Gif_Context
typedef Gif_Writer Gif_Writer

Functions

void gifputunsigned (u_int16_t uns, Gif_Writer *grr)
void file_byte_putter (byte b, Gif_Writer *grr)
void file_block_putter (byte *block, u_int16_t size, Gif_Writer *grr)
void memory_byte_putter (byte b, Gif_Writer *grr)
void memory_block_putter (byte *data, u_int16_t len, Gif_Writer *grr)
void change_node_to_table (Gif_Context *gfc, Gif_Node *work_node, Gif_Node *next_node, Gif_Code clear_code)
void write_compressed_data (byte **img, u_int16_t width, u_int16_t height, byte min_code_bits, Gif_Context *gfc, Gif_Writer *grr)
int calculate_min_code_bits (Gif_Stream *gfs, Gif_Image *gfi, Gif_Writer *grr)
int write_image_data (Gif_Image *gfi, byte min_code_bits, Gif_Context *gfc, Gif_Writer *grr)
int get_color_table_size (Gif_Stream *, Gif_Image *, Gif_Writer *)
int Gif_FullCompressImage (Gif_Stream *gfs, Gif_Image *gfi, int flags)
void write_color_table (Gif_Colormap *gfcm, int totalcol, Gif_Writer *grr)
int write_image (Gif_Stream *gfs, Gif_Image *gfi, Gif_Context *gfc, Gif_Writer *grr)
void write_logical_screen_descriptor (Gif_Stream *gfs, Gif_Writer *grr)
void write_graphic_control_extension (Gif_Image *gfi, Gif_Writer *grr)
void blast_data (byte *data, int len, Gif_Writer *grr)
void write_name_extension (char *id, Gif_Writer *grr)
void write_comment_extensions (Gif_Comment *gfcom, Gif_Writer *grr)
void write_netscape_loop_extension (u_int16_t value, Gif_Writer *grr)
void write_generic_extension (Gif_Extension *gfex, Gif_Writer *grr)
int write_gif (Gif_Stream *gfs, Gif_Writer *grr)
int Gif_FullWriteFile (Gif_Stream *gfs, int flags, FILE *f)
int Gif_CompressImage (Gif_Stream *gfs, Gif_Image *gfi)
int Gif_WriteFile (Gif_Stream *gfs, FILE *f)

Define Documentation

#define CUR_BUMP_CODE   (1 << cur_code_bits)
 

#define gifputblock b,
l,
grr       ((*grr->block_putter)(b, l, grr))
 

Definition at line 95 of file gifwrite.c.

Referenced by blast_data(), real_write_image_data(), write_compressed_data(), write_generic_extension(), write_gif(), write_image(), and write_netscape_loop_extension().

#define gifputbyte b,
grr       ((*grr->byte_putter)(b, grr))
 

Definition at line 94 of file gifwrite.c.

Referenced by blast_data(), gifputunsigned(), real_write_image_data(), write_color_table(), write_comment_extensions(), write_compressed_data(), write_generic_extension(), write_gif(), write_graphic_control_extension(), write_image(), write_logical_screen_descriptor(), write_name_extension(), and write_netscape_loop_extension().

#define inline
 

Definition at line 20 of file gifwrite.c.

#define LINKS_SIZE   GIF_MAX_CODE
 

Definition at line 31 of file gifwrite.c.

Referenced by Gif_FullCompressImage(), write_compressed_data(), and write_gif().

#define LINKS_TYPE   1
 

Definition at line 53 of file gifwrite.c.

Referenced by write_compressed_data().

#define MAX_LINKS_TYPE   5
 

Definition at line 54 of file gifwrite.c.

Referenced by write_compressed_data().

#define NODES_SIZE   GIF_MAX_CODE
 

Definition at line 30 of file gifwrite.c.

Referenced by Gif_FullCompressImage(), and write_gif().

#define TABLE_TYPE   0
 

Definition at line 52 of file gifwrite.c.

Referenced by change_node_to_table(), and write_compressed_data().

#define WRITE_BUFFER_SIZE   255
 

Definition at line 29 of file gifwrite.c.

Referenced by write_compressed_data().


Typedef Documentation

typedef struct Gif_Context Gif_Context
 

typedef struct Gif_Node Gif_Node
 

typedef struct Gif_Writer Gif_Writer
 


Function Documentation

void blast_data byte   data,
int    len,
Gif_Writer   grr
[static]
 

Definition at line 615 of file gifwrite.c.

References gifputblock, and gifputbyte.

00616 {
00617   while (len > 0) {
00618     int s = len > 255 ? 255 : len;
00619     gifputbyte(s, grr);
00620     gifputblock(data, s, grr);
00621     data += s;
00622     len -= s;
00623   }
00624   gifputbyte(0, grr);
00625 }

int calculate_min_code_bits Gif_Stream   gfs,
Gif_Image   gfi,
Gif_Writer   grr
[static]
 

Definition at line 339 of file gifwrite.c.

References Gif_Image::compressed, Gif_Writer::flags, Gif_FullCompressImage(), Gif_UncompressImage, GIF_WRITE_CAREFUL_MIN_CODE_SIZE, Gif_Writer::global_size, Gif_Image::height, i, Gif_Image::img, Gif_Writer::local_size, and Gif_Image::width.

00340 {
00341   int colors_used = -1, min_code_bits, i;
00342 
00343   if (grr->flags & GIF_WRITE_CAREFUL_MIN_CODE_SIZE) {
00344     /* calculate m_c_b based on colormap */
00345     if (grr->local_size > 0)
00346       colors_used = grr->local_size;
00347     else if (grr->global_size > 0)
00348       colors_used = grr->global_size;
00349     
00350   } else if (gfi->compressed) {
00351     /* take m_c_b from compressed image */
00352     colors_used = 1 << gfi->compressed[0];
00353   
00354   } else if (gfi->img) {
00355     /* calculate m_c_b from uncompressed data */
00356     int x, y, width = gfi->width, height = gfi->height;
00357     colors_used = 0;
00358     for (y = 0; y < height && colors_used < 128; y++) {
00359       byte *data = gfi->img[y];
00360       for (x = width; x > 0; x--, data++)
00361         if (*data > colors_used)
00362           colors_used = *data;
00363     }
00364     colors_used++;
00365     
00366   } else {
00367     /* should never happen */
00368     colors_used = 256;
00369   }
00370   
00371   min_code_bits = 2;            /* min_code_bits of 1 isn't allowed */
00372   i = 4;
00373   while (i < colors_used) {
00374     min_code_bits++;
00375     i *= 2;
00376   }
00377 
00378   if ((grr->flags & GIF_WRITE_CAREFUL_MIN_CODE_SIZE)
00379       && gfi->compressed && gfi->compressed[0] != min_code_bits) {
00380     /* if compressed image disagrees with careful min_code_bits, recompress */
00381     if (Gif_UncompressImage(gfi))      
00382       Gif_FullCompressImage(gfs, gfi, grr->flags);
00383   }
00384   
00385   return min_code_bits;
00386 }

void change_node_to_table Gif_Context   gfc,
Gif_Node   work_node,
Gif_Node   next_node,
Gif_Code    clear_code
[static]
 

Definition at line 146 of file gifwrite.c.

References c, Gif_Node::child, Gif_Code, Gif_Context::links, Gif_Context::links_pos, Gif_Node::sibling, Gif_Node::suffix, TABLE_TYPE, and Gif_Node::type.

Referenced by write_compressed_data().

00148 {
00149   /* change links node to table node */
00150   Gif_Code c;
00151   Gif_Node **table = &gfc->links[gfc->links_pos];
00152   Gif_Node *n;
00153   gfc->links_pos += clear_code;
00154   
00155   for (c = 0; c < clear_code; c++)
00156     table[c] = 0;
00157   table[next_node->suffix] = next_node;
00158   for (n = work_node->child.s; n; n = n->sibling)
00159     table[n->suffix] = n;
00160   
00161   work_node->type = TABLE_TYPE;
00162   work_node->child.m = table;
00163 }

void file_block_putter byte   block,
u_int16_t    size,
Gif_Writer   grr
[static]
 

Definition at line 112 of file gifwrite.c.

References Gif_Writer::f, and u_int16_t.

Referenced by Gif_FullWriteFile().

00113 {
00114   fwrite(block, size, 1, grr->f);
00115 }

void file_byte_putter byte    b,
Gif_Writer   grr
[static]
 

Definition at line 106 of file gifwrite.c.

References Gif_Writer::f.

Referenced by Gif_FullWriteFile().

00107 {
00108   fputc(b, grr->f);
00109 }

int get_color_table_size Gif_Stream  ,
Gif_Image  ,
Gif_Writer  
[static]
 

Definition at line 462 of file gifwrite.c.

References Gif_Writer::flags, GIF_WRITE_CAREFUL_MIN_CODE_SIZE, Gif_Stream::global, i, Gif_Stream::images, Gif_Image::local, Gif_Colormap::ncol, ncol, Gif_Stream::nimages, and Gif_Image::transparent.

Referenced by Gif_FullCompressImage(), write_image(), and write_logical_screen_descriptor().

00463 {
00464   Gif_Colormap *gfcm = (gfi ? gfi->local : gfs->global);
00465   int ncol, totalcol, i;
00466 
00467   if (!gfcm || gfcm->ncol <= 0)
00468     return 0;
00469 
00470   /* Make sure ncol is reasonable */
00471   ncol = gfcm->ncol;
00472 
00473   /* Possibly bump up 'ncol' based on 'transparent' values, if
00474      careful_min_code_bits */
00475   if (grr->flags & GIF_WRITE_CAREFUL_MIN_CODE_SIZE) {
00476     if (gfi && gfi->transparent >= ncol)
00477       ncol = gfi->transparent + 1;
00478     else if (!gfi)
00479       for (i = 0; i < gfs->nimages; i++)
00480         if (gfs->images[i]->transparent >= ncol)
00481           ncol = gfs->images[i]->transparent + 1;
00482   }
00483 
00484   /* Make sure the colormap is a power of two entries! */
00485   /* GIF format doesn't allow a colormap with only 1 entry. */
00486   if (ncol > 256)
00487     ncol = 256;
00488   for (totalcol = 2; totalcol < ncol; totalcol *= 2)
00489     /* nada */;
00490   
00491   return totalcol;
00492 }

int Gif_CompressImage Gif_Stream   gfs,
Gif_Image   gfi
 

Definition at line 771 of file gifwrite.c.

References Gif_FullCompressImage().

00772 {
00773   return Gif_FullCompressImage(gfs, gfi, 0);
00774 }

int Gif_FullCompressImage Gif_Stream   gfs,
Gif_Image   gfi,
int    flags
 

Definition at line 417 of file gifwrite.c.

References Gif_Writer::block_putter, Gif_Writer::byte_putter, calculate_min_code_bits(), Gif_Writer::cap, Gif_Image::compressed, Gif_Image::compressed_len, Gif_Writer::flags, flags, Gif_Image::free_compressed, get_color_table_size(), Gif_DeleteArray, Gif_DeleteArrayFunc, Gif_NewArray, Gif_Writer::global_size, Gif_Context::links, LINKS_SIZE, Gif_Writer::local_size, memory_block_putter(), memory_byte_putter(), Gif_Context::nodes, NODES_SIZE, Gif_Writer::pos, Gif_Writer::v, and write_image_data().

00418 {
00419   int ok = 0;
00420   byte min_code_bits;
00421   Gif_Writer grr;
00422   Gif_Context gfc;
00423   
00424   if (gfi->compressed && gfi->free_compressed) {
00425     (*gfi->free_compressed)((void *)gfi->compressed);
00426     gfi->compressed = 0;
00427   }
00428   
00429   gfc.nodes = Gif_NewArray(Gif_Node, NODES_SIZE);
00430   gfc.links = Gif_NewArray(Gif_Node *, LINKS_SIZE);
00431   
00432   grr.v = Gif_NewArray(byte, 1024);
00433   grr.pos = 0;
00434   grr.cap = 1024;
00435   grr.byte_putter = memory_byte_putter;
00436   grr.block_putter = memory_block_putter;
00437   grr.flags = flags;
00438   grr.global_size = get_color_table_size(gfs, 0, &grr);
00439   grr.local_size = get_color_table_size(gfs, gfi, &grr);
00440   
00441   if (!gfc.nodes || !gfc.links || !grr.v)
00442     goto done;
00443 
00444   min_code_bits = calculate_min_code_bits(gfs, gfi, &grr);
00445   ok = write_image_data(gfi, min_code_bits, &gfc, &grr);
00446   
00447  done:
00448   if (!ok) {
00449     Gif_DeleteArray(grr.v);
00450     grr.v = 0;
00451   }
00452   gfi->compressed = grr.v;
00453   gfi->compressed_len = grr.pos;
00454   gfi->free_compressed = Gif_DeleteArrayFunc;
00455   Gif_DeleteArray(gfc.nodes);
00456   Gif_DeleteArray(gfc.links);
00457   return grr.v != 0;
00458 }

int Gif_FullWriteFile Gif_Stream   gfs,
int    flags,
FILE *    f
 

Definition at line 756 of file gifwrite.c.

References Gif_Writer::block_putter, Gif_Writer::byte_putter, Gif_Writer::f, file_block_putter(), file_byte_putter(), Gif_Writer::flags, flags, and write_gif().

00757 {
00758   Gif_Writer grr;
00759   grr.f = f;
00760   grr.byte_putter = file_byte_putter;
00761   grr.block_putter = file_block_putter;
00762   grr.flags = flags;
00763   return write_gif(gfs, &grr);
00764 }

int Gif_WriteFile Gif_Stream   gfs,
FILE *    f
 

Definition at line 777 of file gifwrite.c.

References Gif_FullWriteFile().

00778 {
00779   return Gif_FullWriteFile(gfs, 0, f);
00780 }

void gifputunsigned u_int16_t    uns,
Gif_Writer   grr
[inline, static]
 

Definition at line 98 of file gifwrite.c.

References gifputbyte, and u_int16_t.

00099 {
00100   gifputbyte(uns & 0xFF, grr);
00101   gifputbyte(uns >> 8, grr);
00102 }

void memory_block_putter byte   data,
u_int16_t    len,
Gif_Writer   grr
[static]
 

Definition at line 132 of file gifwrite.c.

References Gif_Writer::cap, Gif_ReArray, Gif_Writer::pos, u_int16_t, and Gif_Writer::v.

Referenced by Gif_FullCompressImage().

00133 {
00134   if (grr->pos + len >= grr->cap) {
00135     grr->cap *= 2;
00136     Gif_ReArray(grr->v, byte, grr->cap);
00137   }
00138   if (grr->v) {
00139     memcpy(grr->v + grr->pos, data, len);
00140     grr->pos += len;
00141   }
00142 }

void memory_byte_putter byte    b,
Gif_Writer   grr
[static]
 

Definition at line 119 of file gifwrite.c.

References Gif_Writer::cap, Gif_ReArray, Gif_Writer::pos, and Gif_Writer::v.

Referenced by Gif_FullCompressImage().

00120 {
00121   if (grr->pos >= grr->cap) {
00122     grr->cap *= 2;
00123     Gif_ReArray(grr->v, byte, grr->cap);
00124   }
00125   if (grr->v) {
00126     grr->v[grr->pos] = b;
00127     grr->pos++;
00128   }
00129 }

void write_color_table Gif_Colormap   gfcm,
int    totalcol,
Gif_Writer   grr
[static]
 

Definition at line 495 of file gifwrite.c.

References Gif_Color::blue, c, Gif_Colormap::col, gifputbyte, Gif_Color::green, i, Gif_Colormap::ncol, ncol, and Gif_Color::red.

00496 {
00497   Gif_Color *c = gfcm->col;
00498   int i, ncol = gfcm->ncol;
00499   
00500   for (i = 0; i < ncol && i < totalcol; i++, c++) {
00501     gifputbyte(c->red, grr);
00502     gifputbyte(c->green, grr);
00503     gifputbyte(c->blue, grr);
00504   }
00505   
00506   /* Pad out colormap with black. */
00507   for (; i < totalcol; i++) {
00508     gifputbyte(0, grr);
00509     gifputbyte(0, grr);
00510     gifputbyte(0, grr);
00511   }
00512 }

void write_comment_extensions Gif_Comment   gfcom,
Gif_Writer   grr
[static]
 

Definition at line 638 of file gifwrite.c.

References blast_data(), Gif_Comment::count, gifputbyte, i, Gif_Comment::len, and Gif_Comment::str.

00639 {
00640   int i;
00641   for (i = 0; i < gfcom->count; i++) {
00642     gifputbyte('!', grr);
00643     gifputbyte(0xFE, grr);
00644     blast_data((byte *)gfcom->str[i], gfcom->len[i], grr);
00645   }
00646 }

void write_compressed_data byte **    img,
u_int16_t    width,
u_int16_t    height,
byte    min_code_bits,
Gif_Context   gfc,
Gif_Writer   grr
[static]
 

Definition at line 167 of file gifwrite.c.

References c, change_node_to_table(), Gif_Node::child, Gif_Node::code, Gif_Code, GIF_DEBUG, GIF_MAX_CODE_BITS, gifputblock, gifputbyte, Gif_Context::links_pos, LINKS_SIZE, LINKS_TYPE, MAX_LINKS_TYPE, Gif_Context::nodes, Gif_Context::nodes_pos, Gif_Node::sibling, Gif_Node::suffix, TABLE_TYPE, Gif_Node::type, u_int16_t, u_int32_t, and WRITE_BUFFER_SIZE.

Referenced by write_image_data().

00169 {
00170   byte buffer[WRITE_BUFFER_SIZE];
00171   byte *buf;
00172   
00173   u_int16_t xleft;
00174   byte *imageline;
00175   
00176   u_int32_t leftover;
00177   byte bits_left_over;
00178   
00179   Gif_Node *work_node;
00180   Gif_Node *next_node;
00181   Gif_Code next_code;
00182   Gif_Code output_code;
00183   Gif_Code clear_code;
00184   Gif_Code eoi_code;
00185 #define CUR_BUMP_CODE (1 << cur_code_bits)
00186   byte suffix;
00187   
00188   byte cur_code_bits;
00189   
00190   /* Here we go! */
00191   gifputbyte(min_code_bits, grr);
00192   clear_code = 1 << min_code_bits;
00193   eoi_code = clear_code + 1;
00194   
00195   cur_code_bits = min_code_bits + 1;
00196   /* next_code set by first runthrough of output clear_code */
00197   GIF_DEBUG(("clear(%d) eoi(%d) bits(%d)",clear_code,eoi_code,cur_code_bits));
00198   
00199   work_node = 0;
00200   output_code = clear_code;
00201   /* Because output_code is clear_code, we'll initialize next_code, et al.
00202      below. */
00203   
00204   bits_left_over = 0;
00205   leftover = 0;
00206   buf = buffer;
00207   xleft = width;
00208   imageline = img[0];
00209   
00210   while (1) {
00211     
00212     /*****
00213      * Output `output_code' to the data stream. */
00214 
00215     leftover |= output_code << bits_left_over;
00216     bits_left_over += cur_code_bits;
00217     while (bits_left_over >= 8) {
00218       *buf++ = leftover & 0xFF;
00219       leftover = (leftover >> 8) & 0x00FFFFFF;
00220       bits_left_over -= 8;
00221       if (buf == buffer + WRITE_BUFFER_SIZE) {
00222         gifputbyte(WRITE_BUFFER_SIZE, grr);
00223         gifputblock(buffer, WRITE_BUFFER_SIZE, grr);
00224         buf = buffer;
00225       }
00226     }
00227     
00228     if (output_code == clear_code) {
00229       /* Clear data and prepare gfc */
00230       Gif_Code c;
00231       
00232       cur_code_bits = min_code_bits + 1;
00233       next_code = eoi_code + 1;
00234       
00235       /* The first clear_code nodes are reserved for single-pixel codes */
00236       gfc->nodes_pos = clear_code;
00237       gfc->links_pos = 0;
00238       for (c = 0; c < clear_code; c++) {
00239         gfc->nodes[c].code = c;
00240         gfc->nodes[c].type = LINKS_TYPE;
00241         gfc->nodes[c].suffix = c;
00242         gfc->nodes[c].child.s = 0;
00243       }
00244       
00245     } else if (next_code > CUR_BUMP_CODE) {
00246       /* bump up compression size */
00247       if (cur_code_bits == GIF_MAX_CODE_BITS) {
00248         output_code = clear_code;
00249         continue;
00250       } else
00251         cur_code_bits++;
00252       
00253     } else if (output_code == eoi_code)
00254       break;
00255     
00256     
00257     /*****
00258      * Find the next code to output. */
00259     
00260     /* If height is 0 -- no more pixels to write -- we output work_node next
00261        time around. */
00262     while (height != 0) {
00263       suffix = *imageline;
00264       if (suffix >= clear_code)
00265         /* should not happen unless GIF_WRITE_CAREFUL_MIN_CODE_BITS */
00266         suffix = 0;
00267       if (!work_node)
00268         next_node = &gfc->nodes[suffix];
00269       else if (work_node->type == TABLE_TYPE)
00270         next_node = work_node->child.m[suffix];
00271       else
00272         for (next_node = work_node->child.s; next_node;
00273              next_node = next_node->sibling)
00274           if (next_node->suffix == suffix)
00275             break;
00276       
00277       imageline++;
00278       xleft--;
00279       if (xleft == 0) {
00280         xleft = width;
00281         height--;
00282         img++;
00283         imageline = img[0];
00284       }
00285       
00286       if (!next_node) {
00287         /* We need to output the current code and add a new one to our
00288            dictionary. First reserve a node for the added code. It's
00289            LINKS_TYPE at first. */
00290         next_node = &gfc->nodes[gfc->nodes_pos];
00291         gfc->nodes_pos++;
00292         next_node->code = next_code;
00293         next_code++;
00294         next_node->type = LINKS_TYPE;
00295         next_node->suffix = suffix;
00296         next_node->child.s = 0;
00297         
00298         /* link next_node into work_node's set of children */
00299         if (work_node->type == TABLE_TYPE)
00300           work_node->child.m[suffix] = next_node;
00301         else if (work_node->type < MAX_LINKS_TYPE
00302                  || gfc->links_pos + clear_code > LINKS_SIZE) {
00303           next_node->sibling = work_node->child.s;
00304           work_node->child.s = next_node;
00305           work_node->type++;
00306         } else
00307           change_node_to_table(gfc, work_node, next_node, clear_code);
00308         
00309         /* Output the current code. */
00310         output_code = work_node->code;
00311         work_node = &gfc->nodes[suffix];
00312         goto found_output_code;
00313       }
00314       
00315       work_node = next_node;
00316     }
00317     
00318     /* Ran out of data if we get here. */
00319     output_code = (work_node ? work_node->code : eoi_code);
00320     work_node = 0;
00321     
00322    found_output_code: ;
00323   }
00324   
00325   if (bits_left_over > 0)
00326     *buf++ = leftover;
00327   
00328   if (buf != buffer) {
00329     GIF_DEBUG(("imageblock(%d)", buf - buffer));
00330     gifputbyte(buf - buffer, grr);
00331     gifputblock(buffer, buf - buffer, grr);
00332   }
00333   
00334   gifputbyte(0, grr);
00335 }

void write_generic_extension Gif_Extension   gfex,
Gif_Writer   grr
[static]
 

Definition at line 659 of file gifwrite.c.

References Gif_Extension::application, Gif_Extension::data, gifputblock, gifputbyte, Gif_Extension::kind, Gif_Extension::length, and u_int32_t.

00660 {
00661   u_int32_t pos = 0;
00662   if (gfex->kind < 0) return;   /* ignore our private extensions */
00663   
00664   gifputbyte('!', grr);
00665   gifputbyte(gfex->kind, grr);
00666   if (gfex->kind == 255) {      /* an application extension */
00667     int len = gfex->application ? strlen(gfex->application) : 0;
00668     if (len) {
00669       gifputbyte(len, grr);
00670       gifputblock((byte *)gfex->application, len, grr);
00671     }
00672   }
00673   while (pos + 255 < gfex->length) {
00674     gifputbyte(255, grr);
00675     gifputblock(gfex->data + pos, 255, grr);
00676     pos += 255;
00677   }
00678   if (pos < gfex->length) {
00679     u_int32_t len = gfex->length - pos;
00680     gifputbyte(len, grr); 
00681     gifputblock(gfex->data + pos, len, grr);
00682   }
00683   gifputbyte(0, grr);
00684 }

int write_gif Gif_Stream   gfs,
Gif_Writer   grr
[static]
 

Definition at line 688 of file gifwrite.c.

References Gif_Image::comment, Gif_Stream::comment, Gif_Image::delay, Gif_Image::disposal, Gif_Stream::extensions, Gif_DeleteArray, Gif_NewArray, gifputblock, gifputbyte, i, Gif_Image::identifier, Gif_Stream::images, Gif_Context::links, LINKS_SIZE, Gif_Stream::loopcount, Gif_Extension::next, Gif_Stream::nimages, Gif_Context::nodes, NODES_SIZE, Gif_Extension::position, Gif_Image::transparent, write_comment_extensions(), write_generic_extension(), write_graphic_control_extension(), write_image(), write_logical_screen_descriptor(), write_name_extension(), and write_netscape_loop_extension().

00689 {
00690   int ok = 0;
00691   int i;
00692   Gif_Image *gfi;
00693   Gif_Extension *gfex = gfs->extensions;
00694   Gif_Context gfc;
00695   
00696   gfc.nodes = Gif_NewArray(Gif_Node, NODES_SIZE);
00697   gfc.links = Gif_NewArray(Gif_Node *, LINKS_SIZE);
00698   if (!gfc.nodes || !gfc.links)
00699     goto done;
00700   
00701   {
00702     byte isgif89a = 0;
00703     if (gfs->comment || gfs->loopcount > -1)
00704       isgif89a = 1;
00705     for (i = 0; i < gfs->nimages && !isgif89a; i++) {
00706       gfi = gfs->images[i];
00707       if (gfi->identifier || gfi->transparent != -1 || gfi->disposal ||
00708           gfi->delay || gfi->comment)
00709         isgif89a = 1;
00710     }
00711     if (isgif89a)
00712       gifputblock((byte *)"GIF89a", 6, grr);
00713     else
00714       gifputblock((byte *)"GIF87a", 6, grr);
00715   }
00716   
00717   write_logical_screen_descriptor(gfs, grr);
00718   
00719   if (gfs->loopcount > -1)
00720     write_netscape_loop_extension(gfs->loopcount, grr);
00721   
00722   for (i = 0; i < gfs->nimages; i++) {
00723     Gif_Image *gfi = gfs->images[i];
00724     while (gfex && gfex->position == i) {
00725       write_generic_extension(gfex, grr);
00726       gfex = gfex->next;
00727     }
00728     if (gfi->comment)
00729       write_comment_extensions(gfi->comment, grr);
00730     if (gfi->identifier)
00731       write_name_extension(gfi->identifier, grr);
00732     if (gfi->transparent != -1 || gfi->disposal || gfi->delay)
00733       write_graphic_control_extension(gfi, grr);
00734     if (!write_image(gfs, gfi, &gfc, grr))
00735       goto done;
00736   }
00737   
00738   while (gfex) {
00739     write_generic_extension(gfex, grr);
00740     gfex = gfex->next;
00741   }
00742   if (gfs->comment)
00743     write_comment_extensions(gfs->comment, grr);
00744   
00745   gifputbyte(';', grr);
00746   ok = 1;
00747   
00748  done:
00749   Gif_DeleteArray(gfc.nodes);
00750   Gif_DeleteArray(gfc.links);
00751   return ok;
00752 }

void write_graphic_control_extension Gif_Image   gfi,
Gif_Writer   grr
[static]
 

Definition at line 599 of file gifwrite.c.

References Gif_Image::delay, Gif_Image::disposal, gifputbyte, gifputunsigned(), packed, and Gif_Image::transparent.

00600 {
00601   byte packed = 0;
00602   gifputbyte('!', grr);
00603   gifputbyte(0xF9, grr);
00604   gifputbyte(4, grr);
00605   if (gfi->transparent >= 0) packed |= 0x01;
00606   packed |= (gfi->disposal & 0x07) << 2;
00607   gifputbyte(packed, grr);
00608   gifputunsigned(gfi->delay, grr);
00609   gifputbyte((byte)gfi->transparent, grr);
00610   gifputbyte(0, grr);
00611 }

int write_image Gif_Stream   gfs,
Gif_Image   gfi,
Gif_Context   gfc,
Gif_Writer   grr
[static]
 

Definition at line 516 of file gifwrite.c.

References calculate_min_code_bits(), Gif_Image::compressed, Gif_Image::compressed_len, get_color_table_size(), gifputblock, gifputbyte, gifputunsigned(), Gif_Image::height, Gif_Image::interlace, Gif_Image::left, Gif_Image::local, Gif_Writer::local_size, packed, Gif_Image::top, u_int16_t, u_int32_t, Gif_Image::width, write_color_table(), and write_image_data().

00517 {
00518   byte min_code_bits, packed = 0;
00519   grr->local_size = get_color_table_size(gfs, gfi, grr);
00520   
00521   gifputbyte(',', grr);
00522   gifputunsigned(gfi->left, grr);
00523   gifputunsigned(gfi->top, grr);
00524   gifputunsigned(gfi->width, grr);
00525   gifputunsigned(gfi->height, grr);
00526   
00527   if (grr->local_size > 0) {
00528     int size = 2;
00529     packed |= 0x80;
00530     while (size < grr->local_size)
00531       size *= 2, packed++;
00532   }
00533   
00534   if (gfi->interlace) packed |= 0x40;
00535   gifputbyte(packed, grr);
00536   
00537   if (grr->local_size > 0)
00538     write_color_table(gfi->local, grr->local_size, grr);
00539 
00540   /* calculate min_code_bits here (because calculation may involve
00541      recompression, if GIF_WRITE_CAREFUL_MIN_CODE_BITS is true) */
00542   min_code_bits = calculate_min_code_bits(gfs, gfi, grr);
00543   
00544   /* use existing compressed data if it exists. This will tend to whip
00545      people's asses who uncompress an image, keep the compressed data around,
00546      but modify the uncompressed data anyway. That sucks. */
00547   if (gfi->compressed) {
00548     byte *compressed = gfi->compressed;
00549     u_int32_t compressed_len = gfi->compressed_len;
00550     while (compressed_len > 0) {
00551       u_int16_t amt = (compressed_len > 0x7000 ? 0x7000 : compressed_len);
00552       gifputblock(compressed, amt, grr);
00553       compressed += amt;
00554       compressed_len -= amt;
00555     }
00556     
00557   } else
00558     write_image_data(gfi, min_code_bits, gfc, grr);
00559   
00560   return 1;
00561 }

int write_image_data Gif_Image   gfi,
byte    min_code_bits,
Gif_Context   gfc,
Gif_Writer   grr
[static]
 

Definition at line 389 of file gifwrite.c.

References Gif_DeleteArray, Gif_InterlaceLine(), Gif_NewArray, Gif_Image::height, Gif_Image::img, Gif_Image::interlace, u_int16_t, Gif_Image::width, and write_compressed_data().

00391 {
00392   byte **img = gfi->img;
00393   u_int16_t width = gfi->width, height = gfi->height;
00394     
00395   if (gfi->interlace) {
00396     u_int16_t y;
00397     byte **nimg = Gif_NewArray(byte *, height + 1);
00398     if (!nimg) return 0;
00399     
00400     for (y = 0; y < height; y++)
00401       nimg[y] = img[Gif_InterlaceLine(y, height)];
00402     nimg[height] = 0;
00403     
00404     write_compressed_data(nimg, width, height, min_code_bits, gfc, grr);
00405     
00406     Gif_DeleteArray(nimg);
00407   } else
00408     write_compressed_data(img, width, height, min_code_bits, gfc, grr);
00409   
00410   return 1;
00411 }

void write_logical_screen_descriptor Gif_Stream   gfs,
Gif_Writer   grr
[static]
 

Definition at line 565 of file gifwrite.c.

References Gif_Stream::background, get_color_table_size(), Gif_CalculateScreenSize(), gifputbyte, gifputunsigned(), Gif_Stream::global, Gif_Writer::global_size, packed, Gif_Stream::screen_height, Gif_Stream::screen_width, u_int16_t, and write_color_table().

00566 {
00567   byte packed = 0x70;           /* high resolution colors */
00568   grr->global_size = get_color_table_size(gfs, 0, grr);
00569 
00570   Gif_CalculateScreenSize(gfs, 0);
00571   gifputunsigned(gfs->screen_width, grr);
00572   gifputunsigned(gfs->screen_height, grr);
00573   
00574   if (grr->global_size > 0) {
00575     u_int16_t size = 2;
00576     packed |= 0x80;
00577     while (size < grr->global_size && size < 256)
00578       size *= 2, packed++;
00579   }
00580   
00581   gifputbyte(packed, grr);
00582   gifputbyte(gfs->background, grr);
00583   gifputbyte(0, grr);           /* no aspect ratio information */
00584   
00585   if (grr->global_size > 0)
00586     write_color_table(gfs->global, grr->global_size, grr);
00587 }

void write_name_extension char *    id,
Gif_Writer   grr
[static]
 

Definition at line 629 of file gifwrite.c.

References blast_data(), and gifputbyte.

00630 {
00631   gifputbyte('!', grr);
00632   gifputbyte(0xCE, grr);
00633   blast_data((byte *)id, strlen(id), grr);
00634 }

void write_netscape_loop_extension u_int16_t    value,
Gif_Writer   grr
[static]
 

Definition at line 650 of file gifwrite.c.

References gifputblock, gifputbyte, gifputunsigned(), and u_int16_t.

00651 {
00652   gifputblock((byte *)"!\xFF\x0BNETSCAPE2.0\x03\x01", 16, grr);
00653   gifputunsigned(value, grr);
00654   gifputbyte(0, grr);
00655 }
 

Powered by Plone

This site conforms to the following standards: