1 /* === S Y N F I G ========================================================= */
3 ** \brief MNG Target Module
8 ** Copyright 2007 Paul Wise
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 ** === N O T E S ===========================================================
23 ** FIXME: THIS DOES NOT ACTUALLY WORK YET
25 ** You will need to read the PNG and MNG specs to understand this code
27 ** ========================================================================= */
29 /* === H E A D E R S ======================================================= */
42 #include <ETL/stringf>
50 /* === M A C R O S ========================================================= */
52 using namespace synfig;
56 /* === G L O B A L S ======================================================= */
58 SYNFIG_TARGET_INIT(mng_trgt);
59 SYNFIG_TARGET_SET_NAME(mng_trgt,"mng");
60 SYNFIG_TARGET_SET_EXT(mng_trgt,"mng");
61 SYNFIG_TARGET_SET_VERSION(mng_trgt,"0.1");
62 SYNFIG_TARGET_SET_CVS_ID(mng_trgt,"$Id$");
64 /* === M E T H O D S ======================================================= */
66 static mng_ptr MNG_DECL
67 mng_alloc_proc(mng_size_t size)
69 return (mng_ptr)calloc(1,size);
73 mng_free_proc(mng_ptr ptr, mng_size_t size)
78 static mng_bool MNG_DECL
79 mng_null_proc(mng_handle mng)
81 synfig::error("mng_trgt: error: mng_null_proc");
85 static mng_bool MNG_DECL
86 mng_write_proc(mng_handle mng, mng_ptr buf, mng_uint32 size, mng_uint32* written)
88 synfig::error("mng_trgt: error: mng_write_proc");
89 FILE* file = (FILE*)mng_get_userdata (mng);
90 *written = fwrite(buf, 1, size, file);
94 static mng_bool MNG_DECL
95 mng_error_proc(mng_handle mng, mng_int32 error, mng_int8 severity, mng_chunkid chunkname,
96 mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar errortext)
99 (mng_trgt*)mng_get_userdata (mng);
100 fprintf(stderr,"mng_trgt: error: %s",errortext);
105 mng_trgt::mng_trgt(const char *Filename):
116 mng_trgt::~mng_trgt()
118 synfig::error("mng_trgt: error: ~mng_trgt");
121 mng_putchunk_mend(mng);
122 if (mng_write(mng) != 0 )
125 mng_chunkid chunkname;
130 mng_getlasterror(mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
131 synfig::error("mng_trgt: error: couldn't write mng: %s",errortext);
135 if (file != NULL ) fclose(file); file=NULL;
136 if (buffer != NULL ) { delete [] buffer; buffer = NULL; }
137 if (color_buffer != NULL ) { delete [] color_buffer; color_buffer = NULL; }
138 if (zbuffer != NULL ) { free(zbuffer); zbuffer = NULL; zbuffer_len = 0; }
142 mng_trgt::set_rend_desc(RendDesc *given_desc)
145 imagecount=desc.get_frame_start();
146 if(desc.get_frame_end()-desc.get_frame_start()>0)
157 time_t t = time (NULL);
158 struct tm* gmt = gmtime(&t);
159 w=desc.get_w(); h=desc.get_h();
160 //synfig::error("mng_trgt: init %d %d",w,h);
161 file = fopen(filename.c_str(), POPEN_BINARY_WRITE_TYPE);
162 if (file == NULL ) goto cleanup_on_error;
163 mng = mng_initialize((mng_ptr)file, mng_alloc_proc, mng_free_proc, MNG_NULL);
164 if(mng == MNG_NULL) goto cleanup_on_error;
165 if (mng_setcb_errorproc(mng, mng_error_proc) != 0 ) goto cleanup_on_error;
166 if (mng_setcb_writedata(mng, mng_write_proc) != 0 ) goto cleanup_on_error;
167 if (mng_setcb_openstream(mng, mng_null_proc) != 0 ) goto cleanup_on_error;
168 if (mng_setcb_closestream(mng, mng_null_proc) != 0 ) goto cleanup_on_error;
169 if (mng_create(mng) != 0 ) goto cleanup_on_error;
170 if (mng_putchunk_mhdr(mng, w, h, multi_image?1000:0, 1, desc.get_frame_end()-desc.get_frame_start(), 0, 0) != 0 ) goto cleanup_on_error;
171 if (mng_putchunk_term(mng, MNG_TERMACTION_REPEAT, MNG_ITERACTION_LASTFRAME, 0, 0x7fffffff) != 0 ) goto cleanup_on_error;
172 if (mng_putchunk_text(mng, sizeof(MNG_TEXT_TITLE), MNG_TEXT_TITLE, get_canvas()->get_name().length(), const_cast<char *>(get_canvas()->get_name().c_str()) ) != 0 ) goto cleanup_on_error;
173 if (mng_putchunk_text(mng, sizeof(MNG_TEXT_DESCRIPTION), MNG_TEXT_DESCRIPTION, get_canvas()->get_description().length(), const_cast<char *>(get_canvas()->get_description().c_str()) ) != 0 ) goto cleanup_on_error;
174 if (mng_putchunk_text(mng, sizeof(MNG_TEXT_SOFTWARE), MNG_TEXT_SOFTWARE, sizeof("SYNFIG"), "SYNFIG" ) != 0 ) goto cleanup_on_error;
175 /* FIXME: not sure if this is correct */
176 if (mng_putchunk_gama(mng, MNG_FALSE, (int)(1.0/gamma().get_gamma()*100000)) != 0 ) goto cleanup_on_error;
177 if (mng_putchunk_phyg(mng, MNG_FALSE,round_to_int(desc.get_x_res()),round_to_int(desc.get_y_res()),MNG_UNIT_METER) != 0 ) goto cleanup_on_error;
178 if (mng_putchunk_time(mng, gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec) != 0 ) goto cleanup_on_error;
179 buffer=new unsigned char[4*w];
180 if (buffer == NULL ) goto cleanup_on_error;
181 color_buffer=new Color[w];
182 if (color_buffer == NULL ) goto cleanup_on_error;
190 mng_chunkid chunkname;
195 mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
196 synfig::error("mng_trgt: libmng: %s",errortext);
199 if (file && file!=stdout ) fclose(file); file=NULL;
200 if (buffer != NULL ) { delete [] buffer; buffer = NULL; }
201 if (color_buffer != NULL ) { delete [] color_buffer; color_buffer = NULL; }
206 mng_trgt::end_frame()
208 //synfig::error("mng_trgt: endf %d %d",w,h);
209 //synfig::error("mng_trgt: error: endframe");
210 deflate(&zstream,Z_FINISH);
211 deflateEnd(&zstream);
212 if (mng != MNG_NULL )
214 // mng_int8 severity;
215 // mng_chunkid chunkname;
216 // mng_uint32 chunkseq;
219 // mng_pchar errortext;
220 mng_putchunk_idat(mng, zbuffer_len, zbuffer);
221 //mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
222 //synfig::error("mng_trgt: libmng: %s %d",errortext,zbuffer_len);
223 mng_putchunk_iend(mng);
224 //mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
225 //synfig::error("mng_trgt: libmng: %s %d",errortext);
232 mng_trgt::start_frame(synfig::ProgressCallback *callback)
234 //synfig::error("mng_trgt: startf %d %d",w,h);
235 //synfig::error("mng_trgt: error: startframe");
237 FIXME: figure out if we need this
238 mng_putchunk_fram(mng,
240 MNG_FRAMINGMODE_NOCHANGE,
245 MNG_CHANGECLIPPING_NO,
251 layer_offset_x + layer_cols,
253 layer_offset_y + layer_rows,
256 mng_getchunk_fram(mng_handle hHandle,
260 mng_uint32 *iNamesize,
262 mng_uint8 *iChangedelay,
263 mng_uint8 *iChangetimeout,
264 mng_uint8 *iChangeclipping,
265 mng_uint8 *iChangesyncid,
267 mng_uint32 *iTimeout,
268 mng_uint8 *iBoundarytype,
269 mng_int32 *iBoundaryl,
270 mng_int32 *iBoundaryr,
271 mng_int32 *iBoundaryt,
272 mng_int32 *iBoundaryb,
274 mng_uint32p *pSyncids);
276 if (mng == MNG_NULL ) return false;
277 if (mng_putchunk_defi(mng,0,MNG_DONOTSHOW_VISIBLE,MNG_ABSTRACT,MNG_FALSE,0,0,MNG_FALSE,0,0,0,0) != 0) return false;
278 if (mng_putchunk_ihdr(mng,w,h,MNG_BITDEPTH_8,MNG_COLORTYPE_RGBA,MNG_COMPRESSION_DEFLATE, 0/*MNG_FILTER_NO_DIFFERING*/,MNG_INTERLACE_NONE) != 0) return false;
279 zstream.zalloc = Z_NULL;
280 zstream.zfree = Z_NULL;
281 zstream.opaque = Z_NULL;
282 zstream.data_type = Z_BINARY;
283 if (deflateInit(&zstream, Z_DEFAULT_COMPRESSION) != Z_OK ) return false;
284 //zbuffer_len = deflateBound(&zstream,4*w*h);
288 zbuffer = (unsigned char*)realloc(zbuffer, zbuffer_len);
289 zstream.next_out = zbuffer;
290 zstream.avail_out = zbuffer_len;
297 mng_trgt::start_scanline(int scanline)
299 //synfig::error("mng_trgt: starts %d %d",w,h);
300 //synfig::error("mng_trgt: error: startscanline");
305 mng_trgt::end_scanline()
307 //synfig::error("mng_trgt: ends %d %d",w,h);
308 //synfig::error("mng_trgt: error: endscanline");
311 convert_color_format(buffer, color_buffer, desc.get_w(), PF_RGB|PF_A, gamma());
312 /* FIXME: Implement buffer management */
313 zstream.next_in = buffer;
314 zstream.avail_in = 4*w;
315 deflate(&zstream,Z_NO_FLUSH);