Subversion Repositories Kolibri OS

Rev

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
#include 
27
#include "SDL_anim.h"
28
 
29
/* deal with MSVC++ crappiness */
30
#ifdef WIN32UNDEFINED
31
	#define strcasecmp _strcmpi
32
	#endif
33
 
34
void Anim_Free( SDL_Animation *anim ) {
35
	SDL_FreeSurface( anim->surface );
36
	free( anim );
37
	}
38
 
39
int Anim_GetFrameNum( SDL_Animation *anim, Uint32 start, Uint32 now ) {
40
	int mspf, ms, frame;
41
	if( now < start ) return 0;
42
 
43
	mspf = anim->duration / anim->frames;
44
	ms = now - start;
45
	if( mspf == 0 ) frame = 0;
46
	else frame = ms / mspf;
47
 
48
	return frame;
49
	}
50
 
51
void Anim_GetFrameRect( SDL_Animation *anim, int frame, SDL_Rect *rect ) {
52
	rect->x = anim->w * (frame % anim->frames);
53
	rect->y = 0;
54
	rect->w = anim->w;
55
	rect->h = anim->h;
56
	}
57
 
58
int Anim_BlitFrame( SDL_Animation *anim, Uint32 start, Uint32 now, SDL_Surface *dest, SDL_Rect *dr ) {
59
	int frame;
60
	frame = Anim_GetFrameNum( anim, start, now );
61
	return Anim_BlitFrameNum( anim, frame, dest, dr );
62
	}
63
 
64
int Anim_BlitFrameNum( SDL_Animation *anim, int frame, SDL_Surface *dest, SDL_Rect *dr ) {
65
	SDL_Rect rect;
66
	Anim_GetFrameRect( anim, frame, &rect );
67
	return SDL_BlitSurface( anim->surface, &rect, dest, dr );
68
	}
69
 
70
int Anim_DisplayFormat( SDL_Animation *anim ) {
71
	struct SDL_Surface *newsurface;
72
	if( SDL_WasInit( SDL_INIT_VIDEO ) == 0 ) return 0;/*"Video is not initialized.\n"*/
73
	newsurface = SDL_DisplayFormatAlpha( anim->surface );
74
	if( !newsurface ) return 0;
75
	anim->surface = newsurface;
76
	return 1;
77
	}
78
 
79
int DoAnimFormat( char *text, int *duration, int *framewidth, int *numframes ) {
80
	char *tok;
81
	SDL_printf( "file is \"%s\"\n", text );
82
 
83
	/* SDL_anim */
84
	tok = strtok( text, " " );
85
	if( !tok ) return 0;
86
	if( strcasecmp( tok, "SDL_anim" ) != 0 ) {
87
		SDL_printf( "no SDL_anim\n" );
88
		return 0;
89
		}
90
 
91
	/* duration */
92
	tok = strtok( NULL, " " );
93
	if( !tok ) return 0;
94
	*duration = atoi( tok );
95
	if( *duration < 1 ) {
96
		SDL_printf( "no duration\n" );
97
		return 0;
98
		}
99
 
100
	/* framewidth */
101
	tok = strtok( NULL, " " );
102
	if( !tok ) return 0;
103
	*framewidth = atoi( tok );
104
	if( *framewidth < 1 ) {
105
		SDL_printf( "no framewidth\n" );
106
		return 0;
107
		}
108
 
109
	/* numframes */
110
	tok = strtok( NULL, " " );
111
	if( !tok ) return 0;
112
	*numframes = atoi( tok );
113
	if( *numframes < 1 ) {
114
		SDL_printf( "no numframes\n" );
115
		return 0;
116
		}
117
 
118
	return 1;
119
	}
120
 
121
struct SDL_Animation *Anim_Load( const char *file ) {
122
	int ckey = -1, i;
123
	char buf[8];
124
	static FILE *fp;  /* "static" prevents setjmp corruption */
125
	png_structp read_ptr;
126
	png_infop read_info_ptr, end_info_ptr;
127
	png_bytep *row_pointers;
128
	png_textp text_ptr;
129
	int num_text, t;
130
	int interlace_type, compression_type, filter_type, bit_depth, color_type;
131
	png_uint_32 width, height, row;
132
	int duration, framewidth, numframes;
133
 
134
	png_color_16p background;
135
	double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
136
	double gamma;
137
	int intent;
138
	png_uint_16p hist;
139
	png_uint_32 offset_x, offset_y;
140
	int unit_type;
141
	png_charp purpose, units;
142
	png_charpp params;
143
	png_int_32 X0, X1;
144
	int type, nparams;
145
	png_uint_32 res_x, res_y;
146
/*	png_colorp palette;
147
	int num_palette;
148
*/	png_color_8p sig_bit;
149
	png_bytep trans;
150
	int num_trans;
151
	png_color_16p trans_values;
152
 
153
	Uint32 Rmask;
154
	Uint32 Gmask;
155
	Uint32 Bmask;
156
	Uint32 Amask;
157
 
158
	SDL_Animation *anim;
159
	SDL_Surface *surface;
160
	SDL_Palette *palette;
161
 
162
	if( !file ) return NULL;
163
 
164
/*	printf( "opening file \"%s\"\n", file );
165
*/
166
	/* open the file handle */
167
	fp = fopen( file, "rb" );
168
	if( fp == NULL ) {
169
		SDL_printf( "fopen() failed\n" );
170
		return NULL;
171
		}
172
 
173
	/* check if it's PNG */
174
	if( fread( buf, 1, 8, fp ) != 8 ) {
175
		SDL_printf( "fread() failed\n" );
176
		return NULL;
177
		}
178
	if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) {
179
		SDL_printf( "not a PNG file\n" );
180
		return NULL;
181
		}
182
	fseek( fp, 0, SEEK_SET );
183
 
184
	/* allocate read structure */
185
	read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );
186
	if( read_ptr == NULL ) {
187
		SDL_printf( "png_create_read_struct() failed\n" );
188
		return NULL;
189
		}
190
 
191
	/* allocate read info structure */
192
	read_info_ptr = png_create_info_struct( read_ptr );
193
	if( read_info_ptr == NULL ) {
194
		SDL_printf( "png_create_info_struct() failed\n" );
195
		return NULL;
196
		}
197
	end_info_ptr = png_create_info_struct( read_ptr );
198
	if( end_info_ptr == NULL ) {
199
		SDL_printf( "png_create_info_struct() failed\n" );
200
		return NULL;
201
		}
202
 
203
	/* set error handler code */
204
	if( setjmp( read_ptr->jmpbuf ) ) {
205
		SDL_printf( "libpng read error\n" );
206
		return NULL;
207
		}
208
 
209
	/* initialize stream */
210
	png_init_io( read_ptr, fp );
211
	png_set_read_status_fn( read_ptr, NULL );
212
 
213
	/* read png info struct */
214
	png_read_info( read_ptr, read_info_ptr );
215
 
216
	/* get the info */
217
	if( !png_get_IHDR( read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type ) ) {
218
		SDL_printf( "png_get_IHDR() failed\n" );
219
		return NULL;
220
		}
221
 
222
	/* background color */
223
	png_get_bKGD( read_ptr, read_info_ptr, &background );
224
 
225
	png_get_cHRM( read_ptr, read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y );
226
 
227
	/* gamma */
228
	png_get_gAMA( read_ptr, read_info_ptr, &gamma );
229
 
230
	/* rendering intent */
231
	png_get_sRGB( read_ptr, read_info_ptr, &intent );
232
 
233
	/* Histogram */
234
	png_get_hIST( read_ptr, read_info_ptr, &hist );
235
 
236
	/* offsets */
237
	png_get_oFFs( read_ptr, read_info_ptr, &offset_x, &offset_y, &unit_type );
238
 
239
	png_get_pCAL( read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, ¶ms );
240
 
241
	/* pixel density */
242
	png_get_pHYs( read_ptr, read_info_ptr, &res_x, &res_y, &unit_type );
243
 
244
/* 	png_get_PLTE( read_ptr, read_info_ptr, &palette, &num_palette );
245
*/
246
	/* significant bits */
247
	png_get_sBIT( read_ptr, read_info_ptr, &sig_bit );
248
 
249
	/* transparency */
250
	if( png_get_tRNS( read_ptr, read_info_ptr, &trans, &num_trans, &trans_values ) ) {
251
		if( color_type == PNG_COLOR_TYPE_PALETTE ) {
252
			if( num_trans == 1 ) ckey = trans[0];
253
			else png_set_expand( read_ptr );
254
			}
255
		else ckey = 0; /* actual value will be set later */
256
		}
257
 
258
	/* text chunks */
259
	num_text = 0;
260
	if( !png_get_text( read_ptr, read_info_ptr, &text_ptr, &num_text ) ) {
261
		SDL_printf( "file has no text chunks\n" );
262
		return NULL;
263
		}
264
	for( t = 0; t < num_text; t++ ) {
265
		if( strcasecmp( text_ptr[t].key, "format" ) == 0 ) {
266
			if( DoAnimFormat( text_ptr[t].text, &duration, &framewidth, &numframes ) ) break;
267
			}
268
		}
269
	if( t == num_text ) {
270
		SDL_printf( "file is not an SDL_anim PNG\n" );
271
		return NULL;
272
		}
273
 
274
	png_set_strip_16( read_ptr );
275
	png_set_packing( read_ptr );
276
	if(color_type == PNG_COLOR_TYPE_GRAY)
277
		png_set_expand( read_ptr );
278
 
279
	/* Allocate the SDL surface to hold the image */
280
	Rmask = Gmask = Bmask = Amask = 0;
281
	if( color_type != PNG_COLOR_TYPE_PALETTE ) {
282
		if( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
283
			Rmask = 0x000000FF;
284
			Gmask = 0x0000FF00;
285
			Bmask = 0x00FF0000;
286
			Amask = (read_info_ptr->channels == 4)? 0xFF000000 : 0;
287
			}
288
		else {
289
			int s = (read_info_ptr->channels == 4) ? 0 : 8;
290
			Rmask = 0xFF000000 >> s;
291
			Gmask = 0x00FF0000 >> s;
292
			Bmask = 0x0000FF00 >> s;
293
			Amask = 0x000000FF >> s;
294
			}
295
		}
296
 
297
	surface = SDL_AllocSurface( SDL_SWSURFACE, width, height, bit_depth * read_info_ptr->channels, Rmask, Gmask, Bmask, Amask );
298
	if( surface == NULL ) {
299
		Anim_SetError("Out of memory");
300
		return NULL;
301
		}
302
 
303
	if(ckey != -1) {
304
		if( color_type != PNG_COLOR_TYPE_PALETTE ) ckey = SDL_MapRGB( surface->format, (Uint8)trans_values->red, (Uint8)trans_values->green, (Uint8)trans_values->blue );
305
		SDL_SetColorKey( surface, SDL_SRCCOLORKEY, ckey );
306
		}
307
 
308
	/* allocate row pointers */
309
	row_pointers = (png_bytep *)malloc( sizeof( png_bytep ) * height );
310
	if( row_pointers == NULL ) {
311
		SDL_printf( "malloc() failed\n" );
312
		return NULL;
313
		}
314
	for( row = 0; row < height; row++ ) {
315
		row_pointers[row] = (Uint8 *)surface->pixels + row * surface->pitch;
316
		}
317
 
318
	png_read_image( read_ptr, row_pointers );
319
 
320
	/* end io */
321
/*	printf( "done\n" );
322
*/	png_read_end( read_ptr, end_info_ptr );
323
 
324
	/* cleanup */
325
	png_destroy_read_struct( &read_ptr, &read_info_ptr, &end_info_ptr);
326
	fclose( fp );
327
 
328
	/* Load the palette, if any */
329
	palette = surface->format->palette;
330
	if( palette ) {
331
		if(color_type == PNG_COLOR_TYPE_GRAY) {
332
			palette->ncolors = 256;
333
			for( i = 0; i < 256; i++ ) {
334
				palette->colors[i].r = i;
335
				palette->colors[i].g = i;
336
				palette->colors[i].b = i;
337
				}
338
			}
339
		else if( read_info_ptr->num_palette > 0 ) {
340
			palette->ncolors = read_info_ptr->num_palette;
341
			for( i = 0; i < read_info_ptr->num_palette; ++i ) {
342
				palette->colors[i].b = read_info_ptr->palette[i].blue;
343
				palette->colors[i].g = read_info_ptr->palette[i].green;
344
				palette->colors[i].r = read_info_ptr->palette[i].red;
345
				}
346
			}
347
		}
348
 
349
	anim = (struct SDL_Animation *)malloc( sizeof( struct SDL_Animation ) );
350
	if( !anim ) {
351
		SDL_printf( "malloc() failed\n" );
352
		return NULL;
353
		}
354
 
355
	anim->surface = surface;
356
	anim->w = framewidth;
357
	anim->h = height;
358
	anim->frames = numframes;
359
	anim->duration = duration;
360
 
361
	return anim;
362
	}