Initial Stable Commit
[synfig.git] / synfig-core / trunk / src / modules / mod_gif / trgt_gif.h
1 /*! ========================================================================
2 ** Sinfg
3 ** Template Header File
4 ** $Id: trgt_gif.h,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 **
8 ** This software and associated documentation
9 ** are CONFIDENTIAL and PROPRIETARY property of
10 ** the above-mentioned copyright holder.
11 **
12 ** You may not copy, print, publish, or in any
13 ** other way distribute this software without
14 ** a prior written agreement with
15 ** the copyright holder.
16 **
17 ** === N O T E S ===========================================================
18 **
19 ** ========================================================================= */
20
21 /* === S T A R T =========================================================== */
22
23 #ifndef __SINFG_TRGT_GIF_H
24 #define __SINFG_TRGT_GIF_H
25
26 /* === H E A D E R S ======================================================= */
27
28 #include <sinfg/target_scanline.h>
29 #include <sinfg/string.h>
30 #include <sinfg/smartfile.h>
31 #include <cstdio>
32 #include <sinfg/surface.h>
33 #include <sinfg/palette.h>
34
35 /* === M A C R O S ========================================================= */
36
37 /* === T Y P E D E F S ===================================================== */
38
39 /* === C L A S S E S & S T R U C T S ======================================= */
40
41 class gif : public sinfg::Target_Scanline
42 {
43         SINFG_TARGET_MODULE_EXT
44 private:
45         // Class for abstracting the
46         // output of the codes
47         struct bitstream
48         {
49                 sinfg::SmartFILE file;
50                 unsigned char pool;
51                 char curr_bit;
52                 bitstream():pool(0),curr_bit(0),curr_pos(0) {}
53                 bitstream(sinfg::SmartFILE file):file(file),pool(0),curr_bit(0),curr_pos(0) {}
54                 unsigned char buffer[256];
55                 int curr_pos;
56                 
57                 // Pushes a single bit onto the bit
58                 void push_bit(bool bit)
59                 {
60                         if(bit)
61                                 pool|=(1<<(curr_bit));
62                         curr_bit++;
63                         if(curr_bit==8)
64                                 empty();
65                 }
66                 
67                 // Emptys out the current pool into
68                 // the buffer. Calls 'dump()' if the
69                 // buffer is full.
70                 void empty()
71                 {
72                         buffer[curr_pos++]=pool;
73                         curr_bit=0;
74                         pool=0;
75                         if(curr_pos==255)dump();
76                 }
77                 
78                 // If there is anything in the
79                 // buffer or in the pool, it 
80                 // dumps it to the filestream.
81                 // Buffer and pool are cleared.
82                 void dump()
83                 {
84                         if(curr_bit)
85                                 empty();
86                         if(curr_pos || curr_bit)
87                         {
88                                 fputc(curr_pos,file.get());
89                                 fwrite(buffer,curr_pos,1,file.get());
90                                 curr_pos=0;
91                         }
92                 }
93                 
94                 // Pushes a symbol of the given size
95                 // onto the bitstream.
96                 void push_value(int value, int size)
97                 {
98                         int i;
99                         for(i=0;i<size;i++)
100                                 push_bit((value>>(i))&1);
101                 }
102         };
103
104         // Class for dealing with the LZW codes
105         struct lzwcode
106         {
107                 int value; // the data element or character
108                 int code; // lzwcode
109                 struct lzwcode* kids; // children of this node
110                 struct lzwcode* next; // siblings of this node
111                 
112                 lzwcode():value(0),code(0),kids(0),next(0) { }
113                 
114                 lzwcode *FindCode(int value)
115                 {
116                         lzwcode *node=this;
117                         
118                         // check the children (kids) of the node for the value
119                         for (node = node->kids; node != 0; node = node->next)
120                                 if (node->value == value)
121                                         return(node);
122                         return(0);
123                 }
124         
125                 void AddNode(unsigned short code, unsigned short value)
126                 {
127                         lzwcode *n = new lzwcode;
128                 
129                         // add a new child to node; the child will have code and value
130                         n->value = value;
131                         n->code = code;
132                         n->kids = 0;
133                         n->next = this->kids;
134                         this->kids = n;
135                 }
136                 
137                 static lzwcode * NewTable(int values)
138                 {
139                         int i;
140                         lzwcode * table = new lzwcode;
141                 
142                         table->kids = 0;
143                         for (i = 0; i < values; i++)
144                                 table->AddNode( i, i);
145                 
146                         return(table);
147                 }
148                 
149                 // Destructor just deletes any
150                 // children and sibblings.
151                 ~lzwcode()
152                 {
153                         if(kids)
154                                 delete kids;
155                         if(next)
156                                 delete next;
157                 }
158         };
159
160 private:
161         bitstream bs;
162         sinfg::String filename;
163         sinfg::SmartFILE file;
164         int 
165                 i,                      // General-purpose index
166                 codesize,       // Current code size
167                 rootsize,       // Size of pixel bits (will be recalculted)
168                 nextcode;       // Next code to use
169         lzwcode *table,*next,*node;
170         
171         sinfg::Surface curr_surface;
172         etl::surface<unsigned char> curr_frame;
173         etl::surface<unsigned char> prev_frame;
174
175         int imagecount;
176         int cur_scanline;
177
178
179         // GIF compression parameters
180         bool lossy;
181         bool multi_image;
182         bool dithering;
183         int color_bits;
184         int iframe_density;
185         int loop_count;
186         bool local_palette;
187         
188         sinfg::Palette curr_palette;
189         
190         void output_curr_palette();
191         
192 public:
193         gif(const char *filename);
194
195         virtual bool set_rend_desc(sinfg::RendDesc *desc);
196         virtual bool init();
197         virtual bool start_frame(sinfg::ProgressCallback *cb);
198         virtual void end_frame();
199
200         virtual ~gif();
201         
202         virtual sinfg::Color * start_scanline(int scanline);
203         virtual bool end_scanline(void);
204
205 };
206
207 /* === E N D =============================================================== */
208
209 #endif