62 #ifndef __INCLUDE_MIST_GIF__
63 #define __INCLUDE_MIST_GIF__
66 #ifndef __INCLUDE_MIST_H__
71 #ifndef __INCLUDE_MIST_COLOR_H__
72 #include "../config/color.h"
75 #ifndef __INCLUDE_MIST_LIMITS__
76 #include "../limits.h"
88 namespace __gif_controller__
91 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
92 #pragma pack( push, gif_align, 1 )
98 unsigned char signature[ 3 ];
99 unsigned char version[ 3 ];
101 unsigned short image_width;
102 unsigned short image_height;
103 unsigned char image_flags;
104 unsigned char background_color_index;
105 unsigned char pixel_aspect_ratio;
109 struct _image_descriptor_
116 unsigned short image_width;
117 unsigned short image_height;
118 unsigned char image_flags;
122 struct _graphic_control_extension_
128 unsigned char block_size;
130 unsigned short delay_time;
131 unsigned char transparent_color_index;
135 struct _comment_extension_
144 struct _plain_text_extension_
150 unsigned char block_size;
153 unsigned short grid_width;
154 unsigned short grid_height;
155 unsigned char cell_width;
156 unsigned char cell_height;
157 unsigned char text_foreground_color_index;
158 unsigned char text_background_color_index;
162 struct _application_extension_
168 unsigned char block_size;
169 unsigned char application_identifier[ 8 ];
170 unsigned char authentication_code[ 3 ];
176 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
177 #pragma pack( pop, gif_align )
181 template <
class T,
class Allocator >
182 struct gif_controller
184 typedef typename array2< T, Allocator >::size_type size_type;
185 typedef typename array2< T, Allocator >::difference_type difference_type;
186 typedef _pixel_converter_< T > pixel_converter;
187 typedef typename pixel_converter::color_type color_type;
190 static difference_type decode_LZW(
const unsigned char *buff,
unsigned char * &out, size_type num_bytes )
192 difference_type initial_code_size = buff[ 0 ];
193 difference_type clear_code = 1 << initial_code_size;
194 difference_type end_code = clear_code + 1;
196 difference_type code_size = initial_code_size + 1;
197 difference_type code_mask = ( 1 << code_size ) - 1;
198 difference_type bits = 0, data = 0, available = 0;
200 if( code_size < 3 || 12 < code_size )
206 out =
new unsigned char[ num_bytes ];
207 memset( out, 0,
sizeof(
unsigned char ) * num_bytes );
209 static difference_type prefix[ 4096 ];
210 static difference_type suffix[ 4096 ];
211 std::stack< difference_type > stack;
213 const unsigned char *pointer = buff + 1;
215 for( difference_type i = 0 ; i < clear_code ; i++ )
218 suffix[ i ] =
static_cast< unsigned char >( i );
221 difference_type count = 0, code = 0, old_code = -1, first_character = 0;
222 while( pointer < buff + num_bytes )
224 difference_type num = pointer[ 0 ];
227 for( difference_type i = 0 ; i < num ; i++ )
229 difference_type ch = pointer[ i ];
233 while( bits >= code_size )
235 code = data & code_mask;
239 if( code == end_code )
242 return( pointer - buff + i );
245 if( code == clear_code )
248 code_size = initial_code_size + 1;
249 code_mask = ( 1 << code_size ) - 1;
250 available = clear_code + 2;
253 else if ( old_code == -1 )
255 out[ count++ ] =
static_cast< unsigned char >( suffix[ code ] );
256 first_character = old_code = code;
258 else if( code > available )
266 difference_type incode = code;
267 if( code == available )
269 stack.push( first_character );
272 while( code > clear_code )
274 stack.push( suffix[ code ] );
275 code = prefix[ code ];
278 stack.push( first_character = suffix[ code ] );
279 prefix[ available ] = old_code;
280 suffix[ available ] = first_character;
283 if( ( ( available & code_mask ) == 0) && ( available < 4096 ) )
286 code_mask += available;
290 while( !stack.empty( ) )
292 out[ count++ ] =
static_cast< unsigned char >( stack.top( ) );
306 static bool convert_from_gif_data(
unsigned char *gif, size_type num_bytes, array2< T, Allocator > &image )
308 static difference_type _2[ ] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
311 _gif_header_ *pheader = reinterpret_cast < _gif_header_ * >( gif );
312 _gif_header_ &header = *pheader;
314 if( !( header.signature[ 0 ] ==
'G' && header.signature[ 1 ] ==
'I' && header.signature[ 2 ] ==
'F' ) )
320 bool global_color_table_flag = ( header.image_flags & 0x80 ) != 0;
323 difference_type size_of_global_color_table = ( header.image_flags & 0x07 );
325 if( size_of_global_color_table < 0 || size_of_global_color_table > 11 )
331 difference_type global_color_table_bytes = 3 * _2[ size_of_global_color_table + 1 ];
333 difference_type width = header.image_width;
334 difference_type height = header.image_height;
336 unsigned char *global_color_map_data = gif + _gif_header_::bytes;
337 unsigned char *pointer = global_color_map_data + ( global_color_table_flag ? global_color_table_bytes : 0 );
341 image.resize( width, height );
343 bool decode_finished =
false;
344 while( pointer < gif + num_bytes && !decode_finished )
346 switch( pointer[ 0 ] )
351 _image_descriptor_ *pimage_header = reinterpret_cast < _image_descriptor_ * >( pointer );
352 _image_descriptor_ &image_header = *pimage_header;
354 bool local_color_table_flag = ( image_header.image_flags & 0x80 ) != 0;
355 bool interlace_flag = ( image_header.image_flags & 0x40 ) != 0;
358 difference_type size_of_local_color_table = ( image_header.image_flags & 0x07 );
359 difference_type local_color_table_bytes = 3 * _2[ size_of_local_color_table + 1 ];
361 difference_type x = image_header.left;
362 difference_type y = image_header.top;
363 difference_type w = image_header.image_width;
364 difference_type h = image_header.image_height;
366 if( x + w > width || y + h > height )
369 std::cerr <<
"Error!!" << std::endl;
373 unsigned char *local_color_map_data = pointer + _image_descriptor_::bytes;
374 unsigned char *image_data = local_color_map_data + ( local_color_table_flag ? local_color_table_bytes : 0 );
376 unsigned char *color_map = local_color_table_flag ? local_color_map_data : global_color_map_data;
378 unsigned char *buff = NULL;
379 difference_type num_bytes = decode_LZW( image_data, buff, w * h );
380 unsigned char *p = buff;
387 static difference_type interlace_offset[] = { 0, 4, 2, 1 };
388 static difference_type interlace_jump[] = { 8, 8, 4, 2 };
389 for( difference_type k = 0 ; k < 4 ; k++ )
391 for( difference_type j = y + interlace_offset[ k ] ; j < y + h ; j += interlace_jump[ k ] )
393 for( difference_type i = x ; i < x + w ; i++ )
395 difference_type index = *p++;
396 image( i, j ) = pixel_converter::convert_to( color_map[ index * 3 + 0 ], color_map[ index * 3 + 1 ], color_map[ index * 3 + 2 ] );
403 for( difference_type j = y ; j < y + h ; j++ )
405 for( difference_type i = x ; i < x + w ; i++ )
407 difference_type index = *p++;
408 image( i, j ) = pixel_converter::convert_to( color_map[ index * 3 + 0 ], color_map[ index * 3 + 1 ], color_map[ index * 3 + 2 ] );
415 std::cerr <<
"LZW Decode failure." << std::endl;
420 pointer += num_bytes;
422 if( x == 0 && y == 0 && w == width && h == height )
425 decode_finished =
true;
433 switch( pointer[ 1 ] )
436 pointer += _graphic_control_extension_::bytes;
440 pointer += _comment_extension_::bytes;
444 pointer += _plain_text_extension_::bytes;
448 pointer += _application_extension_::bytes;
458 while( *pointer != 0x00 )
468 pointer += pointer[ 0 ] + 1;
476 static bool read( array2< T, Allocator > &image,
const std::string &filename )
478 typedef typename array2< T, Allocator >::size_type size_type;
482 if( ( fp = fopen( filename.c_str( ),
"rb" ) ) == NULL )
return(
false );
485 fseek( fp, 0, SEEK_END );
486 filesize = ftell( fp );
487 fseek( fp, 0, SEEK_SET );
489 unsigned char *buff =
new unsigned char[ filesize + 1 ];
490 unsigned char *pointer = buff;
491 size_type read_size = 0;
492 while( feof( fp ) == 0 )
494 read_size = fread( pointer,
sizeof(
unsigned char ), 1024, fp );
495 if( read_size < 1024 )
499 pointer += read_size;
503 bool ret = convert_from_gif_data( buff, filesize, image );
535 template <
class T,
class Allocator >
538 return( __gif_controller__::gif_controller< T, Allocator >::read( image, filename ) );
553 template <
class T,
class Allocator >
571 #endif // __INCLUDE_MIST_GIF__