Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | SDL_anim: an animation library for SDL |
||
3 | Copyright (C) 2001, 2002 Michael Leonhard |
||
4 | |||
5 | This library is free software; you can redistribute it and/or |
||
6 | modify it under the terms of the GNU Library General Public |
||
7 | License as published by the Free Software Foundation; either |
||
8 | version 2 of the License, or (at your option) any later version. |
||
9 | |||
10 | This library is distributed in the hope that it will be useful, |
||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
13 | Library General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU Library General Public |
||
16 | License along with this library; if not, write to the Free |
||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
18 | |||
19 | Michael Leonhard |
||
20 | mike@tamale.net |
||
21 | */ |
||
22 | |||
23 | #include |
||
24 | #include |
||
25 | #include |
||
26 | |||
27 | /* deal with MSVC++ crappiness */ |
||
28 | #ifdef WIN32UNDEFINED |
||
29 | #define snprintf _snprintf |
||
30 | #endif |
||
31 | |||
32 | typedef struct inputstruct { |
||
33 | FILE *file; |
||
34 | char *name; |
||
35 | png_structp read_ptr; |
||
36 | png_infop read_info_ptr; |
||
37 | }; |
||
38 | |||
39 | int numfiles; |
||
40 | struct inputstruct *input; |
||
41 | |||
42 | int main( int argc, char *argv[] ) { |
||
43 | int f, rowbytes; |
||
44 | char buf[256]; |
||
45 | static FILE *fpout; /* "static" prevents setjmp corruption */ |
||
46 | png_structp write_ptr; |
||
47 | png_infop write_info_ptr, end_info_ptr; |
||
48 | png_bytep row_buf, here; |
||
49 | png_uint_32 y; |
||
50 | png_textp text_ptr, new_text_ptr; |
||
51 | int num_text; |
||
52 | |||
53 | int interlace_type, compression_type, filter_type, bit_depth, color_type; |
||
54 | int it, ct, ft, bd, clrt; |
||
55 | png_uint_32 width, height, w, h; |
||
56 | |||
57 | int duration; |
||
58 | |||
59 | if( argc < 4 ) { |
||
60 | printf( "makeanim v0.2\nusage: makeanim |
||
61 | printf( "example: makeanim 1500 a00.png a01.png a02.png a03.png a04.png a.anim\n" ); |
||
62 | return 1; |
||
63 | } |
||
64 | |||
65 | duration = atoi( argv[1] ); |
||
66 | if( duration < 1 ) { |
||
67 | printf( "duration is incorrect\n" ); |
||
68 | return 1; |
||
69 | } |
||
70 | |||
71 | numfiles = argc - 3; |
||
72 | input = (struct inputstruct *)malloc( sizeof( struct inputstruct ) * numfiles ); |
||
73 | if( !input ) return 1; |
||
74 | |||
75 | for( f = 0; f < numfiles; f++ ) { |
||
76 | input[f].name = argv[f + 2]; |
||
77 | printf( "opening file %d, \"%s\"\n", f, input[f].name ); |
||
78 | |||
79 | /* open the file handle */ |
||
80 | input[f].file = fopen( input[f].name, "rb" ); |
||
81 | if( input[f].file == NULL ) { |
||
82 | printf( "fopen() failed\n" ); |
||
83 | return 1; |
||
84 | } |
||
85 | |||
86 | /* check if it's PNG */ |
||
87 | if( fread( buf, 1, 8, input[f].file ) != 8 ) { |
||
88 | printf( "fread() failed for file \"%s\"\n", input[f].name ); |
||
89 | return 1; |
||
90 | } |
||
91 | if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) { |
||
92 | printf( "not a PNG file\n" ); |
||
93 | return 1; |
||
94 | } |
||
95 | fseek( input[f].file, 0, SEEK_SET ); |
||
96 | |||
97 | /* allocate read structure */ |
||
98 | input[f].read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); |
||
99 | if( input[f].read_ptr == NULL ) { |
||
100 | printf( "png_create_read_struct() failed\n" ); |
||
101 | return 1; |
||
102 | } |
||
103 | |||
104 | /* allocate read info structure */ |
||
105 | input[f].read_info_ptr = png_create_info_struct( input[f].read_ptr ); |
||
106 | if( input[f].read_info_ptr == NULL ) { |
||
107 | printf( "png_create_info_struct() failed\n" ); |
||
108 | return 1; |
||
109 | } |
||
110 | |||
111 | |||
112 | /* set error handler code */ |
||
113 | if( setjmp( input[f].read_ptr->jmpbuf ) ) { |
||
114 | printf( "libpng read error\n" ); |
||
115 | return 1; |
||
116 | } |
||
117 | |||
118 | /* initialize stream */ |
||
119 | png_init_io( input[f].read_ptr, input[f].file ); |
||
120 | png_set_read_status_fn( input[f].read_ptr, NULL ); |
||
121 | |||
122 | /* read png info struct */ |
||
123 | png_read_info( input[f].read_ptr, input[f].read_info_ptr ); |
||
124 | |||
125 | /* get the info */ |
||
126 | if( !png_get_IHDR( input[f].read_ptr, input[f].read_info_ptr, &w, &h, &bd, &clrt, &it, &ct, &ft ) ) { |
||
127 | printf( "png_get_IHDR() failed\n" ); |
||
128 | return 1; |
||
129 | } |
||
130 | |||
131 | /* save the info of the first frame */ |
||
132 | if( f == 0 ) { |
||
133 | width = w; |
||
134 | height = h; |
||
135 | bit_depth = bd; |
||
136 | color_type = clrt; |
||
137 | interlace_type = it; |
||
138 | compression_type = ct; |
||
139 | filter_type = ft; |
||
140 | } |
||
141 | /* compare all other frames to first frame */ |
||
142 | else if( (w != width) || |
||
143 | (h != height) || |
||
144 | (bd != bit_depth) || |
||
145 | (clrt != color_type) || |
||
146 | (it != interlace_type) || |
||
147 | (ct != compression_type) || |
||
148 | (ft != filter_type) ) { |
||
149 | if( w != width ) printf( "width is different\n" ); |
||
150 | if( h != height ) printf( "height is different\n" ); |
||
151 | if( bd != bit_depth ) printf( "bit depth is different\n" ); |
||
152 | if( clrt != color_type ) printf( "color type is different\n" ); |
||
153 | if( it != interlace_type ) printf( "interlace type is different\n" ); |
||
154 | if( ct != compression_type ) printf( "compression type is different\n" ); |
||
155 | if( ft != filter_type ) printf( "filter type is different\n" ); |
||
156 | return 1; |
||
157 | } |
||
158 | } |
||
159 | |||
160 | row_buf = (png_bytep)NULL; |
||
161 | |||
162 | /* open output file */ |
||
163 | printf( "opening file \"%s\"\n", argv[numfiles + 2] ); |
||
164 | fpout = fopen( argv[numfiles + 2], "wb" ); |
||
165 | if( fpout == NULL ) { |
||
166 | printf( "fopen() failed\n" ); |
||
167 | return 1; |
||
168 | } |
||
169 | |||
170 | /* allocate write structure */ |
||
171 | write_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); |
||
172 | |||
173 | /* allocate info structures */ |
||
174 | write_info_ptr = png_create_info_struct( write_ptr ); |
||
175 | end_info_ptr = png_create_info_struct( write_ptr ); |
||
176 | |||
177 | /* error handling */ |
||
178 | if( setjmp( write_ptr->jmpbuf ) ) { |
||
179 | printf( "libpng write error\n" ); |
||
180 | return 1; |
||
181 | } |
||
182 | |||
183 | /* initialize output stream */ |
||
184 | png_init_io( write_ptr, fpout ); |
||
185 | png_set_write_status_fn( write_ptr, NULL ); |
||
186 | |||
187 | /* set info */ |
||
188 | png_set_IHDR( write_ptr, write_info_ptr, width * numfiles, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type); |
||
189 | |||
190 | /* image characteristics */ |
||
191 | { |
||
192 | png_color_16p background; |
||
193 | double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; |
||
194 | double gamma; |
||
195 | int intent; |
||
196 | png_uint_16p hist; |
||
197 | png_uint_32 offset_x, offset_y; |
||
198 | int unit_type; |
||
199 | png_charp purpose, units; |
||
200 | png_charpp params; |
||
201 | png_int_32 X0, X1; |
||
202 | int type, nparams; |
||
203 | png_uint_32 res_x, res_y; |
||
204 | png_colorp palette; |
||
205 | int num_palette; |
||
206 | png_color_8p sig_bit; |
||
207 | png_bytep trans; |
||
208 | int num_trans; |
||
209 | png_color_16p trans_values; |
||
210 | |||
211 | /* background color */ |
||
212 | if( png_get_bKGD( input[0].read_ptr, input[0].read_info_ptr, &background ) ) { |
||
213 | png_set_bKGD( write_ptr, write_info_ptr, background ); |
||
214 | } |
||
215 | |||
216 | if( png_get_cHRM( input[0].read_ptr, input[0].read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y ) ) { |
||
217 | png_set_cHRM( write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y ); |
||
218 | } |
||
219 | |||
220 | /* gamma */ |
||
221 | if( png_get_gAMA( input[0].read_ptr, input[0].read_info_ptr, &gamma ) ) { |
||
222 | png_set_gAMA( write_ptr, write_info_ptr, gamma ); |
||
223 | } |
||
224 | |||
225 | /* rendering intent */ |
||
226 | if( png_get_sRGB( input[0].read_ptr, input[0].read_info_ptr, &intent ) ) { |
||
227 | png_set_sRGB( write_ptr, write_info_ptr, intent ); |
||
228 | } |
||
229 | |||
230 | /* Histogram */ |
||
231 | if( png_get_hIST( input[0].read_ptr, input[0].read_info_ptr, &hist ) ) { |
||
232 | png_set_hIST( write_ptr, write_info_ptr, hist ); |
||
233 | } |
||
234 | |||
235 | /* offsets */ |
||
236 | if( png_get_oFFs( input[0].read_ptr, input[0].read_info_ptr, &offset_x, &offset_y, &unit_type ) ) { |
||
237 | png_set_oFFs( write_ptr, write_info_ptr, offset_x, offset_y, unit_type ); |
||
238 | } |
||
239 | |||
240 | if( png_get_pCAL( input[0].read_ptr, input[0].read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, ¶ms ) ) { |
||
241 | png_set_pCAL( write_ptr, write_info_ptr, purpose, X0, X1, type, nparams, units, params ); |
||
242 | } |
||
243 | |||
244 | /* pixel density */ |
||
245 | if( png_get_pHYs( input[0].read_ptr, input[0].read_info_ptr, &res_x, &res_y, &unit_type ) ) { |
||
246 | png_set_pHYs( write_ptr, write_info_ptr, res_x, res_y, unit_type ); |
||
247 | } |
||
248 | |||
249 | /* text chunks */ |
||
250 | /* if( png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) > 0 ) { |
||
251 | printf( "Handling %d tEXt/zTXt chunks\n", num_text ); |
||
252 | png_set_text( write_ptr, write_info_ptr, text_ptr, num_text ); |
||
253 | } |
||
254 | */ |
||
255 | /* palette */ |
||
256 | if( png_get_PLTE( input[0].read_ptr, input[0].read_info_ptr, &palette, &num_palette ) ) { |
||
257 | png_set_PLTE( write_ptr, write_info_ptr, palette, num_palette ); |
||
258 | } |
||
259 | |||
260 | /* significant bits */ |
||
261 | if( png_get_sBIT( input[0].read_ptr, input[0].read_info_ptr, &sig_bit ) ) { |
||
262 | png_set_sBIT( write_ptr, write_info_ptr, sig_bit ); |
||
263 | } |
||
264 | |||
265 | /* transparency */ |
||
266 | if( png_get_tRNS( input[0].read_ptr, input[0].read_info_ptr, &trans, &num_trans, &trans_values ) ) { |
||
267 | png_set_tRNS( write_ptr, write_info_ptr, trans, num_trans, trans_values ); |
||
268 | } |
||
269 | } |
||
270 | |||
271 | /* text chunks */ |
||
272 | num_text = 0; |
||
273 | if( !png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) ) num_text = 0; |
||
274 | new_text_ptr = (struct png_text_struct *)malloc( sizeof( struct png_text_struct ) * num_text + 1 ); |
||
275 | if( !new_text_ptr ) { |
||
276 | printf( "malloc() failed\n" ); |
||
277 | return 1; |
||
278 | } |
||
279 | |||
280 | memcpy( new_text_ptr, text_ptr, sizeof( struct png_text_struct ) * num_text ); |
||
281 | |||
282 | snprintf( buf, 255, "SDL_anim %d %d %d", duration, width, numfiles ); |
||
283 | buf[255] = 0; |
||
284 | new_text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE; |
||
285 | new_text_ptr[num_text].key = "format"; |
||
286 | new_text_ptr[num_text].text = buf; |
||
287 | new_text_ptr[num_text].text_length = strlen( buf ); |
||
288 | num_text++; |
||
289 | png_set_text( write_ptr, write_info_ptr, new_text_ptr, num_text ); |
||
290 | |||
291 | /* write info */ |
||
292 | png_write_info( write_ptr, write_info_ptr ); |
||
293 | |||
294 | /* allocate buffer */ |
||
295 | rowbytes = png_get_rowbytes( input[0].read_ptr, input[0].read_info_ptr ); |
||
296 | row_buf = (png_bytep)png_malloc( write_ptr, rowbytes * numfiles ); |
||
297 | if( row_buf == NULL ) { |
||
298 | printf( "png_malloc() failed\n" ); |
||
299 | return 1; |
||
300 | } |
||
301 | |||
302 | /* copy raw data */ |
||
303 | for( y = 0; y < height; y++ ) { |
||
304 | /* grab a scanline from each file */ |
||
305 | here = row_buf; |
||
306 | for( f = 0; f < numfiles; f++ ) { |
||
307 | png_read_rows( input[f].read_ptr, (png_bytepp)&here, (png_bytepp)NULL, 1 ); |
||
308 | here += rowbytes; |
||
309 | } |
||
310 | /* write the long scanline */ |
||
311 | png_write_rows( write_ptr, (png_bytepp)&row_buf, 1 ); |
||
312 | } |
||
313 | |||
314 | /* end io */ |
||
315 | for( f = 0; f < numfiles; f++ ) png_read_end( input[f].read_ptr, end_info_ptr ); |
||
316 | png_write_end( write_ptr, end_info_ptr ); |
||
317 | |||
318 | /* cleanup */ |
||
319 | png_free( write_ptr, row_buf ); |
||
320 | for( f = 0; f < numfiles; f++ ) { |
||
321 | png_destroy_read_struct( &input[f].read_ptr, &input[f].read_info_ptr, &end_info_ptr); |
||
322 | fclose( input[f].file ); |
||
323 | } |
||
324 | png_destroy_write_struct( &write_ptr, &write_info_ptr ); |
||
325 | fclose( fpout ); |
||
326 | |||
327 | return 0; |
||
328 | }>>>>>>> |