00001
00025
00026
00027 #ifndef __SYNFIG_TRGT_GIF_H
00028 #define __SYNFIG_TRGT_GIF_H
00029
00030
00031
00032 #include <synfig/target_scanline.h>
00033 #include <synfig/string.h>
00034 #include <synfig/smartfile.h>
00035 #include <cstdio>
00036 #include <synfig/surface.h>
00037 #include <synfig/palette.h>
00038
00039
00040
00041
00042
00043
00044
00045 class gif : public synfig::Target_Scanline
00046 {
00047 SYNFIG_TARGET_MODULE_EXT
00048 private:
00049
00050
00051 struct bitstream
00052 {
00053 synfig::SmartFILE file;
00054 unsigned char pool;
00055 char curr_bit;
00056 bitstream():pool(0),curr_bit(0),curr_pos(0) {}
00057 bitstream(synfig::SmartFILE file):file(file),pool(0),curr_bit(0),curr_pos(0) {}
00058 unsigned char buffer[256];
00059 int curr_pos;
00060
00061
00062 void push_bit(bool bit)
00063 {
00064 if(bit)
00065 pool|=(1<<(curr_bit));
00066 curr_bit++;
00067 if(curr_bit==8)
00068 empty();
00069 }
00070
00071
00072
00073
00074 void empty()
00075 {
00076 buffer[curr_pos++]=pool;
00077 curr_bit=0;
00078 pool=0;
00079 if(curr_pos==255)dump();
00080 }
00081
00082
00083
00084
00085
00086 void dump()
00087 {
00088 if(curr_bit)
00089 empty();
00090 if(curr_pos || curr_bit)
00091 {
00092 fputc(curr_pos,file.get());
00093 fwrite(buffer,curr_pos,1,file.get());
00094 curr_pos=0;
00095 }
00096 }
00097
00098
00099
00100 void push_value(int value, int size)
00101 {
00102 int i;
00103 for(i=0;i<size;i++)
00104 push_bit((value>>(i))&1);
00105 }
00106 };
00107
00108
00109 struct lzwcode
00110 {
00111 int value;
00112 int code;
00113 struct lzwcode* kids;
00114 struct lzwcode* next;
00115
00116 lzwcode():value(0),code(0),kids(0),next(0) { }
00117
00118 lzwcode *FindCode(int value)
00119 {
00120 lzwcode *node=this;
00121
00122
00123 for (node = node->kids; node != 0; node = node->next)
00124 if (node->value == value)
00125 return(node);
00126 return(0);
00127 }
00128
00129 void AddNode(unsigned short code, unsigned short value)
00130 {
00131 lzwcode *n = new lzwcode;
00132
00133
00134 n->value = value;
00135 n->code = code;
00136 n->kids = 0;
00137 n->next = this->kids;
00138 this->kids = n;
00139 }
00140
00141 static lzwcode * NewTable(int values)
00142 {
00143 int i;
00144 lzwcode * table = new lzwcode;
00145
00146 table->kids = 0;
00147 for (i = 0; i < values; i++)
00148 table->AddNode( i, i);
00149
00150 return(table);
00151 }
00152
00153
00154
00155 ~lzwcode()
00156 {
00157 if(kids)
00158 delete kids;
00159 if(next)
00160 delete next;
00161 }
00162 };
00163
00164 private:
00165 bitstream bs;
00166 synfig::String filename;
00167 synfig::SmartFILE file;
00168 int
00169 i,
00170 codesize,
00171 rootsize,
00172 nextcode;
00173 lzwcode *table,*next,*node;
00174
00175 synfig::Surface curr_surface;
00176 etl::surface<unsigned char> curr_frame;
00177 etl::surface<unsigned char> prev_frame;
00178
00179 int imagecount;
00180 int cur_scanline;
00181
00182
00183
00184 bool lossy;
00185 bool multi_image;
00186 bool dithering;
00187 int color_bits;
00188 int iframe_density;
00189 int loop_count;
00190 bool local_palette;
00191
00192 synfig::Palette curr_palette;
00193
00194 void output_curr_palette();
00195
00196 public:
00197 gif(const char *filename);
00198
00199 virtual bool set_rend_desc(synfig::RendDesc *desc);
00200 virtual bool init();
00201 virtual bool start_frame(synfig::ProgressCallback *cb);
00202 virtual void end_frame();
00203
00204 virtual ~gif();
00205
00206 virtual synfig::Color * start_scanline(int scanline);
00207 virtual bool end_scanline(void);
00208
00209 };
00210
00211
00212
00213 #endif