34 #ifndef __INCLUDE_MIST_TGA__
35 #define __INCLUDE_MIST_TGA__
38 #ifndef __INCLUDE_MIST_H__
43 #ifndef __INCLUDE_MIST_COLOR_H__
44 #include "../config/color.h"
47 #ifndef __INCLUDE_MIST_ENDIAN__
48 #include "../config/endian.h"
51 #ifndef __INCLUDE_MIST_LIMITS__
52 #include "../limits.h"
68 namespace __tga_controller__
71 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
72 #pragma pack( push, tga_align, 1 )
79 unsigned char id_length;
82 unsigned char color_map_type;
85 unsigned char image_type;
88 unsigned short first_entry_index;
89 unsigned short color_map_length;
90 unsigned char color_map_entry_size;
93 unsigned short x_origin;
94 unsigned short y_origin;
95 unsigned short image_width;
96 unsigned short image_height;
97 unsigned char pixel_depth;
98 unsigned char image_descriptor;
102 #if defined(__MIST_MSVC__) || defined(__INTEL_COMPILER)
103 #pragma pack( pop, tga_align )
108 template <
class T,
class Allocator >
109 struct tga_controller
111 typedef typename array2< T, Allocator >::size_type size_type;
112 typedef typename array2< T, Allocator >::difference_type difference_type;
113 typedef _pixel_converter_< T > pixel_converter;
114 typedef typename pixel_converter::color_type color_type;
116 static bool is_supported( size_type tga_bits )
133 static bool decode_RLE(
const unsigned char *pixel,
unsigned char * &buff, size_type snum_bytes, size_type num_bytes, size_type pixel_bytes )
135 buff =
new unsigned char[ num_bytes ];
136 memset( buff, 0,
sizeof(
unsigned char ) * num_bytes );
138 size_type i = 0, j = 0;
139 for( ; i < snum_bytes && j < num_bytes ; )
141 unsigned char byte = pixel[ i++ ];
142 if( ( byte & 0x80 ) != 0 )
148 size_type num = ( byte & 0x7f ) + 1;
151 if( i + pixel_bytes > snum_bytes || j + num * pixel_bytes > num_bytes )
156 for( size_type l = 0 ; l < num ; l++ )
158 for( size_type m = 0 ; m < pixel_bytes ; m++ )
160 buff[ j + l * pixel_bytes + m ] = pixel[ i + m ];
165 j += num * pixel_bytes;
172 size_type num = byte + 1;
175 if( i + num * pixel_bytes > snum_bytes || j + num * pixel_bytes > num_bytes )
180 memcpy( buff + j, pixel + i,
sizeof(
unsigned char ) * num * pixel_bytes );
182 i += num * pixel_bytes;
183 j += num * pixel_bytes;
198 inline static bool is_equal(
const unsigned char *pix1,
const unsigned char *pix2, size_type pixel_bytes )
200 for( size_type i = 0 ; i < pixel_bytes ; i++ )
202 if( pix1[ i ] != pix2[ i ] )
210 inline static size_type count_run_length(
const unsigned char *pixel, size_type num_bytes, size_type pixel_bytes )
218 for( i = 0 ; i < num_bytes ; i++ )
220 for( l = 0 ; l < pixel_bytes ; l++ )
222 if( pixel[ l ] != pixel[ i * pixel_bytes + l ] )
228 if( l != pixel_bytes )
236 static size_type encode_RLE(
unsigned char *pixel, size_type num_bytes, size_type pixel_bytes )
238 unsigned char *buff =
new unsigned char[ num_bytes * 2 ];
239 unsigned char temp[ 20 ];
242 size_type num = num_bytes / pixel_bytes, count = 0, k;
243 unsigned char *pbuff = buff;
244 const unsigned char *pix = pixel;
245 const unsigned char *epix = pixel + num_bytes;
246 for( size_type i = 0 ; i < num ; i++ )
248 size_type len = count_run_length( pix, epix - pix, pixel_bytes );
252 size_type nrun = len / 128;
253 size_type rest = len % 128;
257 for( k = 0 ; k < pixel_bytes ; k++ )
259 temp[ k + 1 ] = pix[ k ];
262 for( k = 0 ; k < nrun ; k++ )
264 for( size_type l = 0 ; l <= pixel_bytes ; l++ )
266 pbuff[ l ] = temp[ l ];
268 pbuff += pixel_bytes + 1;
271 pix += 128 * nrun * pixel_bytes;
275 temp[ 0 ] = 0x80 +
static_cast< unsigned char >( rest - 1 );
276 for( size_type l = 0 ; l <= pixel_bytes ; l++ )
278 pbuff[ l ] = temp[ l ];
280 pbuff += pixel_bytes + 1;
281 pix += pixel_bytes * rest;
287 pbuff[ 0 ] =
static_cast< unsigned char >( rest - 1 );
289 for( k = 0 ; k < pixel_bytes * rest ; k++ )
291 pbuff[ k + 1 ] = pix[ k ];
293 pbuff += pixel_bytes * rest + 1;
294 pix += pixel_bytes * rest;
303 size_type total = count + len;
304 size_type nnum, rest;
317 pbuff[ 0 ] =
static_cast< unsigned char >( nnum - 1 );
319 for( k = 0 ; k < pixel_bytes * nnum ; k++ )
321 pbuff[ k + 1 ] = pix[ k ];
323 pbuff += pixel_bytes * nnum + 1;
324 pix += pixel_bytes * nnum;
328 pbuff[ 0 ] =
static_cast< unsigned char >( rest - 1 );
330 for( k = 0 ; k < pixel_bytes * rest ; k++ )
332 pbuff[ k + 1 ] = pix[ k ];
334 pbuff += pixel_bytes * rest + 1;
335 pix += pixel_bytes * rest;
342 pbuff[ 0 ] =
static_cast< unsigned char >( len - 1 );
344 for( k = 0 ; k < pixel_bytes * len ; k++ )
346 pbuff[ k + 1 ] = pix[ k ];
348 pbuff += pixel_bytes * len + 1;
349 pix += pixel_bytes * len;
356 if( num_bytes <= static_cast< size_type >( pbuff - buff ) )
364 num_bytes = pbuff - buff;
365 memcpy( pixel, buff, num_bytes );
372 static bool convert_from_tga_data(
unsigned char *tga, size_type num_bytes, array2< T, Allocator > &image )
375 _tga_header_ *pheader = reinterpret_cast < _tga_header_ * >( tga );
376 _tga_header_ &header = *pheader;
378 difference_type width = header.image_width;
379 difference_type height = header.image_height;
380 difference_type pixel_bytes = header.pixel_depth / 8;
382 unsigned char *color_map_data = tga + _tga_header_::bytes;
383 unsigned char *image_data = color_map_data + ( header.color_map_type == 0 ? 0 : header.color_map_length * header.color_map_entry_size / 8 );
387 bool is_RLE = ( header.image_type & 0x08 ) != 0;
388 bool is_Huffman = ( header.image_type & 0x20 ) != 0;
389 bool from_top = ( header.image_descriptor & 0x20 ) != 0;
390 bool from_left = ( header.image_descriptor & 0x10 ) == 0;
392 if( is_Huffman || header.image_type > 11 )
398 unsigned char *buff = NULL, *pixels = NULL;
402 if( !
decode_RLE( image_data, buff, tga + num_bytes - image_data, width * height * pixel_bytes, pixel_bytes ) )
406 pixels = buff + ( from_top ? 0 : width * ( height - 1 ) * pixel_bytes );
410 pixels = image_data + ( from_top ? 0 : width * ( height - 1 ) * pixel_bytes );
413 difference_type line_skip = from_top ? width * pixel_bytes : - width * pixel_bytes;
414 difference_type pixel_skip = from_left ? pixel_bytes : - pixel_bytes;
416 image.resize( width, height );
420 difference_type i, j, k;
421 switch( header.image_type & 0x07 )
424 for( j = 0 ; j < height ; j++ )
426 unsigned char *pixel = pixels + line_skip * j + ( from_left ? 0 : pixel_bytes ) * ( width - 1 );
428 for( i = 0 ; i < width ; i++ )
430 difference_type tmp = 0;
431 unsigned char *pix = pixel + pixel_skip * i;
433 for( k = pixel_bytes - 1 ; k >= 0 ; k-- )
435 tmp = ( tmp << 8 ) + pix[ k ];
438 difference_type index = tmp - header.first_entry_index;
440 switch( header.color_map_entry_size )
444 unsigned short v =
reinterpret_cast< unsigned short *
>( color_map_data + index * 2 )[ 0 ];
445 unsigned char a = ( v & 0x8000 ) >> 15;
446 unsigned char r = ( ( v & 0x7c00 ) >> 10 ) * 8;
447 unsigned char g = ( ( v & 0x03e0 ) >> 5 ) * 8;
448 unsigned char b = ( v & 0x001f ) * 8;
449 image( i, j ) = pixel_converter::convert_to( r, g, b, static_cast< unsigned char >( a * 255 ) );
455 unsigned char r = color_map_data[ index * 3 + 2 ];
456 unsigned char g = color_map_data[ index * 3 + 1 ];
457 unsigned char b = color_map_data[ index * 3 + 0 ];
458 image( i, j ) = pixel_converter::convert_to( r, g, b );
464 unsigned char a = color_map_data[ index * 4 + 3 ];
465 unsigned char r = color_map_data[ index * 4 + 2 ];
466 unsigned char g = color_map_data[ index * 4 + 1 ];
467 unsigned char b = color_map_data[ index * 4 + 0 ];
468 image( i, j ) = pixel_converter::convert_to( r, g, b, a );
480 for( j = 0 ; j < height ; j++ )
482 unsigned char *pixel = pixels + line_skip * j + ( from_left ? 0 : pixel_bytes ) * ( width - 1 );
484 switch( header.pixel_depth )
487 for( i = 0 ; i < width ; i++ )
489 unsigned short pix =
reinterpret_cast< unsigned short *
>( pixel + pixel_skip * i )[ 0 ];
490 unsigned char a = ( pix & 0x8000 ) >> 15;
491 unsigned char r = ( ( pix & 0x7c00 ) >> 10 ) * 8;
492 unsigned char g = ( ( pix & 0x03e0 ) >> 5 ) * 8;
493 unsigned char b = ( pix & 0x001f ) * 8;
494 image( i, j ) = pixel_converter::convert_to( r, g, b, static_cast< unsigned char >( a * 255 ) );
499 for( i = 0 ; i < width ; i++ )
501 unsigned char *pix = pixel + pixel_skip * i;
502 image( i, j ) = pixel_converter::convert_to( pix[ 2 ], pix[ 1 ], pix[ 0 ] );
507 for( i = 0 ; i < width ; i++ )
509 unsigned char *pix = pixel + pixel_skip * i;
510 image( i, j ) = pixel_converter::convert_to( pix[ 2 ], pix[ 1 ], pix[ 0 ], pix[ 3 ] );
521 if( header.pixel_depth != 8 )
527 for( j = 0 ; j < height ; j++ )
529 unsigned char *pixel = pixels + line_skip * j + ( from_left ? 0 : pixel_bytes ) * ( width - 1 );
531 for( i = 0 ; i < width ; i++ )
533 unsigned char *pix = pixel + pixel_skip * i;
534 image( i, j ) = pixel_converter::convert_to( pix[ 0 ], pix[ 0 ], pix[ 0 ] );
546 static difference_type convert_to_tga_data(
const array2< T, Allocator > &image,
unsigned char * &tga, size_type tga_bits,
bool is_encode_RLE,
bool from_top,
bool from_left )
553 difference_type pixel_bytes = tga_bits / 8;
554 difference_type width = image.width( );
555 difference_type height = image.height( );
557 tga =
new unsigned char[ _tga_header_::bytes + width * height * pixel_bytes ];
560 _tga_header_ *pheader = reinterpret_cast < _tga_header_ * >( tga );
561 _tga_header_ &header = *pheader;
564 header.id_length = 0;
567 header.color_map_type = 0;
570 header.image_type = 2 + ( is_encode_RLE ? 8 : 0 );
573 header.first_entry_index = 0;
574 header.color_map_length = 0;
575 header.color_map_entry_size = 0;
580 header.image_width =
static_cast< unsigned short >( width );
581 header.image_height =
static_cast< unsigned short >( height );
582 header.pixel_depth =
static_cast< unsigned char >( tga_bits );
583 header.image_descriptor = ( is_encode_RLE ? 0x08 : 0 ) | ( from_top ? 0x20 : 0 ) | ( from_left ? 0 : 0x10 );
585 unsigned char *image_data = tga + _tga_header_::bytes;
587 unsigned char *pixels = image_data + ( from_top ? 0 : width * ( height - 1 ) * pixel_bytes );
589 difference_type line_skip = from_top ? width * pixel_bytes : - width * pixel_bytes;
590 difference_type pixel_skip = from_left ? pixel_bytes : - pixel_bytes;
592 difference_type i, j;
593 for( j = 0 ; j < height ; j++ )
595 unsigned char *pixel = pixels + line_skip * j + ( from_left ? 0 : pixel_bytes ) * ( width - 1 );
597 switch( header.pixel_depth )
600 for( i = 0 ; i < width ; i++ )
602 color_type c =
limits_0_255( pixel_converter::convert_from( image( i, j ) ) );
603 unsigned short &pix =
reinterpret_cast< unsigned short *
>( pixel + pixel_skip * i )[ 0 ];
604 unsigned short a = ( ( c.a == 0 ? 0 : 1 ) << 15 ) & 0x8000;
605 unsigned short r = (
static_cast< unsigned char >( c.r / 8 ) << 10 ) & 0x7c00;
606 unsigned short g = (
static_cast< unsigned char >( c.g / 8 ) << 5 ) & 0x03e0;
607 unsigned short b =
static_cast< unsigned char >( c.b / 8 ) & 0x001f;
613 for( i = 0 ; i < width ; i++ )
615 color_type c =
limits_0_255( pixel_converter::convert_from( image( i, j ) ) );
616 unsigned char *pix = pixel + pixel_skip * i;
617 pix[ 0 ] =
static_cast< unsigned char >( c.b );
618 pix[ 1 ] =
static_cast< unsigned char >( c.g );
619 pix[ 2 ] =
static_cast< unsigned char >( c.r );
624 for( i = 0 ; i < width ; i++ )
626 color_type c =
limits_0_255( pixel_converter::convert_from( image( i, j ) ) );
627 unsigned char *pix = pixel + pixel_skip * i;
628 pix[ 0 ] =
static_cast< unsigned char >( c.b );
629 pix[ 1 ] =
static_cast< unsigned char >( c.g );
630 pix[ 2 ] =
static_cast< unsigned char >( c.r );
631 pix[ 3 ] =
static_cast< unsigned char >( c.a );
644 difference_type nbytes = encode_RLE( image_data, width * height * pixel_bytes, pixel_bytes );
646 if( nbytes == width * height * pixel_bytes )
648 header.image_type = 2;
649 header.image_descriptor = ( from_top ? 0x20 : 0 ) | ( from_left ? 0 : 0x10 );
652 return( _tga_header_::bytes + nbytes );
656 return( _tga_header_::bytes + width * height * pixel_bytes );
660 static bool read( array2< T, Allocator > &image,
const std::string &filename )
662 typedef typename array2< T, Allocator >::size_type size_type;
666 if( ( fp = fopen( filename.c_str( ),
"rb" ) ) == NULL )
return(
false );
669 fseek( fp, 0, SEEK_END );
670 filesize = ftell( fp );
671 fseek( fp, 0, SEEK_SET );
673 unsigned char *buff =
new unsigned char[ filesize + 1 ];
674 unsigned char *pointer = buff;
675 size_type read_size = 0;
676 while( feof( fp ) == 0 )
678 read_size = fread( pointer,
sizeof(
unsigned char ), 1024, fp );
679 if( read_size < 1024 )
683 pointer += read_size;
687 bool ret = convert_from_tga_data( buff, filesize, image );
692 static bool write(
const array2< T, Allocator > &image,
const std::string &filename, size_type tga_bits,
bool is_encode_RLE )
694 typedef typename array2< T, Allocator >::size_type size_type;
696 if( image.width( ) == 0 )
698 std::cerr <<
"Image width is zero!" << std::endl;
701 else if( image.height( ) == 0 )
703 std::cerr <<
"Image height is zero!" << std::endl;
706 else if( !is_supported( tga_bits ) )
708 std::cerr <<
"This format is not supported currently!" << std::endl;
712 unsigned char *buff = NULL;
713 difference_type size = convert_to_tga_data( image, buff, tga_bits, is_encode_RLE,
true,
true );
722 if( ( fp = fopen( filename.c_str( ),
"wb" ) ) == NULL )
730 unsigned char *pointer = buff;
731 size_type write_size = 0, writed_size = 0;
734 write_size = size < 1024 ? size : 1024;
736 writed_size = fwrite( pointer,
sizeof(
unsigned char ), write_size, fp );
737 pointer += writed_size;
739 if( write_size != writed_size )
781 template <
class T,
class Allocator >
784 return( __tga_controller__::tga_controller< T, Allocator >::read( image, filename ) );
798 template <
class T,
class Allocator >
819 template <
class T,
class Allocator >
822 return( __tga_controller__::tga_controller< T, Allocator >::write( image, filename, tga_bits, is_encode_RLE ) );
840 template <
class T,
class Allocator >
857 #endif // __INCLUDE_MIST_TGA__