00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <stdio.h>
00050 #include <malloc.h>
00051
00052 #include "contrib/libtarga.h"
00053
00054
00055
00056
00057 #define TGA_IMG_NODATA (0)
00058 #define TGA_IMG_UNC_PALETTED (1)
00059 #define TGA_IMG_UNC_TRUECOLOR (2)
00060 #define TGA_IMG_UNC_GRAYSCALE (3)
00061 #define TGA_IMG_RLE_PALETTED (9)
00062 #define TGA_IMG_RLE_TRUECOLOR (10)
00063 #define TGA_IMG_RLE_GRAYSCALE (11)
00064
00065
00066 #define TGA_LOWER_LEFT (0)
00067 #define TGA_LOWER_RIGHT (1)
00068 #define TGA_UPPER_LEFT (2)
00069 #define TGA_UPPER_RIGHT (3)
00070
00071
00072 #define HDR_LENGTH (18)
00073 #define HDR_IDLEN (0)
00074 #define HDR_CMAP_TYPE (1)
00075 #define HDR_IMAGE_TYPE (2)
00076 #define HDR_CMAP_FIRST (3)
00077 #define HDR_CMAP_LENGTH (5)
00078 #define HDR_CMAP_ENTRY_SIZE (7)
00079 #define HDR_IMG_SPEC_XORIGIN (8)
00080 #define HDR_IMG_SPEC_YORIGIN (10)
00081 #define HDR_IMG_SPEC_WIDTH (12)
00082 #define HDR_IMG_SPEC_HEIGHT (14)
00083 #define HDR_IMG_SPEC_PIX_DEPTH (16)
00084 #define HDR_IMG_SPEC_IMG_DESC (17)
00085
00086
00087
00088 #define TGA_ERR_NONE (0)
00089 #define TGA_ERR_BAD_HEADER (1)
00090 #define TGA_ERR_OPEN_FAILS (2)
00091 #define TGA_ERR_BAD_FORMAT (3)
00092 #define TGA_ERR_UNEXPECTED_EOF (4)
00093 #define TGA_ERR_NODATA_IMAGE (5)
00094 #define TGA_ERR_COLORMAP_FOR_GRAY (6)
00095 #define TGA_ERR_BAD_COLORMAP_ENTRY_SIZE (7)
00096 #define TGA_ERR_BAD_COLORMAP (8)
00097 #define TGA_ERR_READ_FAILS (9)
00098 #define TGA_ERR_BAD_IMAGE_TYPE (10)
00099 #define TGA_ERR_BAD_DIMENSIONS (11)
00100
00101
00102
00103 static uint32 TargaError;
00104
00105
00106 static int16 ttohs( int16 val );
00107 static int16 htots( int16 val );
00108 static int32 ttohl( int32 val );
00109 static int32 htotl( int32 val );
00110
00111
00112 static uint32 tga_get_pixel( FILE * tga, ubyte bytes_per_pix,
00113 ubyte * colormap, ubyte cmap_bytes_entry );
00114 static uint32 tga_convert_color( uint32 pixel, uint32 bpp_in, ubyte alphabits, uint32 format_out );
00115 static void tga_write_pixel_to_mem( ubyte * dat, ubyte img_spec, uint32 number,
00116 uint32 w, uint32 h, uint32 pixel, uint32 format );
00117
00118
00119
00120
00121 int tga_get_last_error() {
00122 return( TargaError );
00123 }
00124
00125
00126
00127 const char * tga_error_string( int error_code ) {
00128
00129 switch( error_code ) {
00130
00131 case TGA_ERR_NONE:
00132 return( "no error" );
00133
00134 case TGA_ERR_BAD_HEADER:
00135 return( "bad image header" );
00136
00137 case TGA_ERR_OPEN_FAILS:
00138 return( "cannot open file" );
00139
00140 case TGA_ERR_BAD_FORMAT:
00141 return( "bad format argument" );
00142
00143 case TGA_ERR_UNEXPECTED_EOF:
00144 return( "unexpected end-of-file" );
00145
00146 case TGA_ERR_NODATA_IMAGE:
00147 return( "image contains no data" );
00148
00149 case TGA_ERR_COLORMAP_FOR_GRAY:
00150 return( "found colormap for a grayscale image" );
00151
00152 case TGA_ERR_BAD_COLORMAP_ENTRY_SIZE:
00153 return( "unsupported colormap entry size" );
00154
00155 case TGA_ERR_BAD_COLORMAP:
00156 return( "bad colormap" );
00157
00158 case TGA_ERR_READ_FAILS:
00159 return( "cannot read from file" );
00160
00161 case TGA_ERR_BAD_IMAGE_TYPE:
00162 return( "unknown image type" );
00163
00164 case TGA_ERR_BAD_DIMENSIONS:
00165 return( "image has size 0 width or height (or both)" );
00166
00167 default:
00168 return( "unknown error" );
00169
00170 }
00171
00172
00173 return( NULL );
00174
00175 }
00176
00177
00178
00179
00180 void * tga_create( int width, int height, unsigned int format ) {
00181
00182 switch( format ) {
00183
00184 case TGA_TRUECOLOR_32:
00185 return( (void *)malloc( width * height * 4 ) );
00186
00187 case TGA_TRUECOLOR_24:
00188 return( (void *)malloc( width * height * 3 ) );
00189
00190 default:
00191 TargaError = TGA_ERR_BAD_FORMAT;
00192 break;
00193
00194 }
00195
00196 return( NULL );
00197
00198 }
00199
00200
00201
00202
00203 void * tga_load( const char * filename,
00204 int * width, int * height, unsigned int format ) {
00205
00206 ubyte idlen;
00207 ubyte cmap_type;
00208 ubyte image_type;
00209 uint16 cmap_first;
00210 uint16 cmap_length;
00211 ubyte cmap_entry_size;
00212 uint16 img_spec_xorig;
00213 uint16 img_spec_yorig;
00214 uint16 img_spec_width;
00215 uint16 img_spec_height;
00216 ubyte img_spec_pix_depth;
00217 ubyte img_spec_img_desc;
00218
00219 FILE * targafile;
00220
00221 ubyte * tga_hdr = NULL;
00222
00223 ubyte * colormap = NULL;
00224
00225
00226
00227
00228
00229
00230
00231 ubyte cmap_bytes_entry = 0;
00232 uint32 cmap_bytes = 0;
00233
00234 uint32 tmp_col = 0;
00235 uint32 tmp_int32 = 0;
00236 ubyte tmp_byte = 0;
00237
00238 ubyte alphabits = 0;
00239
00240 uint32 num_pixels = 0;
00241
00242 uint32 i = 0;
00243 uint32 j = 0;
00244
00245 ubyte * image_data = 0;
00246 uint32 img_dat_len = 0;
00247
00248 ubyte bytes_per_pix = 0;
00249
00250 ubyte true_bits_per_pixel = 0;
00251
00252 uint32 bytes_total = 0;
00253
00254 ubyte packet_header = 0;
00255 ubyte repcount = 0;
00256
00257
00258 switch( format ) {
00259
00260 case TGA_TRUECOLOR_24:
00261 case TGA_TRUECOLOR_32:
00262 break;
00263
00264 default:
00265 TargaError = TGA_ERR_BAD_FORMAT;
00266 return( NULL );
00267
00268 }
00269
00270
00271
00272 targafile = fopen( filename, "rb" );
00273 if( targafile == NULL ) {
00274 TargaError = TGA_ERR_OPEN_FAILS;
00275 return( NULL );
00276 }
00277
00278
00279
00280 tga_hdr = (ubyte *)malloc( HDR_LENGTH );
00281
00282
00283 if( fread( (void *)tga_hdr, 1, HDR_LENGTH, targafile ) != HDR_LENGTH ) {
00284 free( tga_hdr );
00285 TargaError = TGA_ERR_BAD_HEADER;
00286 return( NULL );
00287 }
00288
00289
00290
00291 idlen = (ubyte)tga_hdr[HDR_IDLEN];
00292
00293 image_type = (ubyte)tga_hdr[HDR_IMAGE_TYPE];
00294
00295 cmap_type = (ubyte)tga_hdr[HDR_CMAP_TYPE];
00296 cmap_first = ttohs( *(uint16 *)(&tga_hdr[HDR_CMAP_FIRST]) );
00297 cmap_length = ttohs( *(uint16 *)(&tga_hdr[HDR_CMAP_LENGTH]) );
00298 cmap_entry_size = (ubyte)tga_hdr[HDR_CMAP_ENTRY_SIZE];
00299
00300 img_spec_xorig = ttohs( *(uint16 *)(&tga_hdr[HDR_IMG_SPEC_XORIGIN]) );
00301 img_spec_yorig = ttohs( *(uint16 *)(&tga_hdr[HDR_IMG_SPEC_YORIGIN]) );
00302 img_spec_width = ttohs( *(uint16 *)(&tga_hdr[HDR_IMG_SPEC_WIDTH]) );
00303 img_spec_height = ttohs( *(uint16 *)(&tga_hdr[HDR_IMG_SPEC_HEIGHT]) );
00304 img_spec_pix_depth = (ubyte)tga_hdr[HDR_IMG_SPEC_PIX_DEPTH];
00305 img_spec_img_desc = (ubyte)tga_hdr[HDR_IMG_SPEC_IMG_DESC];
00306
00307 free( tga_hdr );
00308
00309
00310 num_pixels = img_spec_width * img_spec_height;
00311
00312 if( num_pixels == 0 ) {
00313 TargaError = TGA_ERR_BAD_DIMENSIONS;
00314 return( NULL );
00315 }
00316
00317
00318 alphabits = img_spec_img_desc & 0x0F;
00319
00320
00321
00322 if( idlen ) {
00323 if( fseek( targafile, idlen, SEEK_CUR ) ) {
00324 TargaError = TGA_ERR_UNEXPECTED_EOF;
00325 return( NULL );
00326 }
00327 }
00328
00329
00330
00331 if( image_type == TGA_IMG_NODATA ) {
00332 TargaError = TGA_ERR_NODATA_IMAGE;
00333 return( NULL );
00334 }
00335
00336
00337
00338
00339
00340
00341 if( cmap_type ) {
00342
00343 switch( image_type ) {
00344
00345 case TGA_IMG_UNC_PALETTED:
00346 case TGA_IMG_RLE_PALETTED:
00347 break;
00348
00349 case TGA_IMG_UNC_TRUECOLOR:
00350 case TGA_IMG_RLE_TRUECOLOR:
00351
00352
00353
00354 break;
00355
00356 case TGA_IMG_UNC_GRAYSCALE:
00357 case TGA_IMG_RLE_GRAYSCALE:
00358 TargaError = TGA_ERR_COLORMAP_FOR_GRAY;
00359 return( NULL );
00360 }
00361
00362
00363 if( !(cmap_entry_size == 15 ||
00364 cmap_entry_size == 16 ||
00365 cmap_entry_size == 24 ||
00366 cmap_entry_size == 32) ) {
00367 TargaError = TGA_ERR_BAD_COLORMAP_ENTRY_SIZE;
00368 return( NULL );
00369 }
00370
00371
00372
00373 if( cmap_entry_size & 0x07 ) {
00374 cmap_bytes_entry = (((8 - (cmap_entry_size & 0x07)) + cmap_entry_size) >> 3);
00375 } else {
00376 cmap_bytes_entry = (cmap_entry_size >> 3);
00377 }
00378
00379 cmap_bytes = cmap_bytes_entry * cmap_length;
00380 colormap = (ubyte *)malloc( cmap_bytes );
00381
00382
00383 for( i = 0; i < cmap_length; i++ ) {
00384
00385
00386 if( cmap_first != 0 ) {
00387 fseek( targafile, cmap_first * cmap_bytes_entry, SEEK_CUR );
00388 }
00389
00390 tmp_int32 = 0;
00391 for( j = 0; j < cmap_bytes_entry; j++ ) {
00392 if( !fread( &tmp_byte, 1, 1, targafile ) ) {
00393 free( colormap );
00394 TargaError = TGA_ERR_BAD_COLORMAP;
00395 return( NULL );
00396 }
00397 tmp_int32 += tmp_byte << (j * 8);
00398 }
00399
00400
00401 tmp_int32 = ttohl( tmp_int32 );
00402
00403 for( j = 0; j < cmap_bytes_entry; j++ ) {
00404 colormap[i * cmap_bytes_entry + j] = (tmp_int32 >> (8 * j)) & 0xFF;
00405 }
00406
00407 }
00408
00409 }
00410
00411
00412
00413 if( img_spec_pix_depth & 0x07 ) {
00414 bytes_per_pix = (((8 - (img_spec_pix_depth & 0x07)) + img_spec_pix_depth) >> 3);
00415 } else {
00416 bytes_per_pix = (img_spec_pix_depth >> 3);
00417 }
00418
00419
00420
00421 if( bytes_per_pix == 0 ) {
00422 bytes_per_pix = 1;
00423 }
00424
00425
00426
00427 bytes_total = img_spec_width * img_spec_height * format;
00428
00429 image_data = (ubyte *)malloc( bytes_total );
00430
00431 img_dat_len = img_spec_width * img_spec_height * bytes_per_pix;
00432
00433
00434 true_bits_per_pixel = cmap_type ? cmap_entry_size : img_spec_pix_depth;
00435
00436 switch( image_type ) {
00437
00438 case TGA_IMG_UNC_TRUECOLOR:
00439 case TGA_IMG_UNC_GRAYSCALE:
00440 case TGA_IMG_UNC_PALETTED:
00441
00442
00443
00444 for( i = 0; i < num_pixels; i++ ) {
00445
00446
00447 tmp_col = tga_get_pixel( targafile, bytes_per_pix, colormap, cmap_bytes_entry );
00448 tmp_col = tga_convert_color( tmp_col, true_bits_per_pixel, alphabits, format );
00449
00450
00451 tga_write_pixel_to_mem( image_data, img_spec_img_desc,
00452 i, img_spec_width, img_spec_height, tmp_col, format );
00453
00454 }
00455
00456 break;
00457
00458
00459 case TGA_IMG_RLE_TRUECOLOR:
00460 case TGA_IMG_RLE_GRAYSCALE:
00461 case TGA_IMG_RLE_PALETTED:
00462
00463
00464
00465 for( i = 0; i < num_pixels; ) {
00466
00467
00468 if( fread( &packet_header, 1, 1, targafile ) < 1 ) {
00469
00470 packet_header = 1;
00471 }
00472
00473 if( packet_header & 0x80 ) {
00474
00475
00476 tmp_col = tga_get_pixel( targafile, bytes_per_pix, colormap, cmap_bytes_entry );
00477 tmp_col = tga_convert_color( tmp_col, true_bits_per_pixel, alphabits, format );
00478
00479 repcount = (packet_header & 0x7F) + 1;
00480
00481
00482 for( j = 0; j < repcount; j++ ) {
00483 tga_write_pixel_to_mem( image_data, img_spec_img_desc,
00484 i + j, img_spec_width, img_spec_height, tmp_col, format );
00485 }
00486
00487 i += repcount;
00488
00489 } else {
00490
00491
00492
00493 repcount = (packet_header & 0x7F) + 1;
00494
00495 for( j = 0; j < repcount; j++ ) {
00496
00497 tmp_col = tga_get_pixel( targafile, bytes_per_pix, colormap, cmap_bytes_entry );
00498 tmp_col = tga_convert_color( tmp_col, true_bits_per_pixel, alphabits, format );
00499
00500 tga_write_pixel_to_mem( image_data, img_spec_img_desc,
00501 i + j, img_spec_width, img_spec_height, tmp_col, format );
00502
00503 }
00504
00505 i += repcount;
00506
00507 }
00508
00509 }
00510
00511 break;
00512
00513
00514 default:
00515
00516 TargaError = TGA_ERR_BAD_IMAGE_TYPE;
00517 return( NULL );
00518
00519 }
00520
00521 fclose( targafile );
00522
00523 *width = img_spec_width;
00524 *height = img_spec_height;
00525
00526 return( (void *)image_data );
00527
00528 }
00529
00530
00531
00532
00533
00534 int tga_write_raw( const char * file, int width, int height, unsigned char * dat, unsigned int format ) {
00535
00536 FILE * tga;
00537
00538 uint32 i, j;
00539
00540 uint32 size = width * height;
00541
00542 float red, green, blue, alpha;
00543
00544 char id[] = "written with libtarga";
00545 ubyte idlen = 21;
00546 ubyte zeroes[5] = { 0, 0, 0, 0, 0 };
00547 uint32 pixbuf;
00548 ubyte one = 1;
00549 ubyte cmap_type = 0;
00550 ubyte img_type = 2;
00551 uint16 xorigin = 0;
00552 uint16 yorigin = 0;
00553 ubyte pixdepth = format * 8;
00554 ubyte img_desc;
00555
00556
00557 switch( format ) {
00558
00559 case TGA_TRUECOLOR_24:
00560 img_desc = 0;
00561 break;
00562
00563 case TGA_TRUECOLOR_32:
00564 img_desc = 8;
00565 break;
00566
00567 default:
00568 TargaError = TGA_ERR_BAD_FORMAT;
00569 return( 0 );
00570 break;
00571
00572 }
00573
00574 tga = fopen( file, "wb" );
00575
00576 if( tga == NULL ) {
00577 TargaError = TGA_ERR_OPEN_FAILS;
00578 return( 0 );
00579 }
00580
00581
00582 fwrite( &idlen, 1, 1, tga );
00583
00584
00585 fwrite( &cmap_type, 1, 1, tga );
00586
00587
00588 fwrite( &img_type, 1, 1, tga );
00589
00590
00591 fwrite( &zeroes, 5, 1, tga );
00592
00593
00594 fwrite( &xorigin, 2, 1, tga );
00595 fwrite( &yorigin, 2, 1, tga );
00596 fwrite( &width, 2, 1, tga );
00597 fwrite( &height, 2, 1, tga );
00598 fwrite( &pixdepth, 1, 1, tga );
00599 fwrite( &img_desc, 1, 1, tga );
00600
00601
00602
00603 fwrite( &id, idlen, 1, tga );
00604
00605
00606 for( i = 0; i < size; i++ ) {
00607
00608 pixbuf = 0;
00609 for( j = 0; j < format; j++ ) {
00610 pixbuf += dat[i*format+j] << (8 * j);
00611 }
00612
00613 switch( format ) {
00614
00615 case TGA_TRUECOLOR_24:
00616
00617 pixbuf = ((pixbuf & 0xFF) << 16) +
00618 (pixbuf & 0xFF00) +
00619 ((pixbuf & 0xFF0000) >> 16);
00620
00621 pixbuf = htotl( pixbuf );
00622
00623 fwrite( &pixbuf, 3, 1, tga );
00624
00625 break;
00626
00627 case TGA_TRUECOLOR_32:
00628
00629
00630
00631 red = (pixbuf & 0xFF) / 255.0f;
00632 green = ((pixbuf & 0xFF00) >> 8) / 255.0f;
00633 blue = ((pixbuf & 0xFF0000) >> 16) / 255.0f;
00634 alpha = ((pixbuf & 0xFF000000) >> 24) / 255.0f;
00635
00636 if( alpha > 0.0001 ) {
00637 red /= alpha;
00638 green /= alpha;
00639 blue /= alpha;
00640 }
00641
00642
00643
00644 red = red > 1.0f ? 255.0f : red * 255.0f;
00645 green = green > 1.0f ? 255.0f : green * 255.0f;
00646 blue = blue > 1.0f ? 255.0f : blue * 255.0f;
00647 alpha = alpha > 1.0f ? 255.0f : alpha * 255.0f;
00648
00649 pixbuf = (ubyte)blue + (((ubyte)green) << 8) +
00650 (((ubyte)red) << 16) + (((ubyte)alpha) << 24);
00651
00652 pixbuf = htotl( pixbuf );
00653
00654 fwrite( &pixbuf, 4, 1, tga );
00655
00656 break;
00657
00658 }
00659
00660 }
00661
00662 fclose( tga );
00663
00664 return( 1 );
00665
00666 }
00667
00668
00669
00670
00671
00672 int tga_write_rle( const char * file, int width, int height, unsigned char * dat, unsigned int format ) {
00673
00674 FILE * tga;
00675
00676 uint32 i, j;
00677 uint32 oc, nc;
00678
00679 enum RLE_STATE { INIT, NONE, RLP, RAWP };
00680
00681 int state = INIT;
00682
00683 uint32 size = width * height;
00684
00685 uint16 shortwidth = (uint16)width;
00686 uint16 shortheight = (uint16)height;
00687
00688 ubyte repcount;
00689
00690 float red, green, blue, alpha;
00691
00692 int idx, row, column;
00693
00694
00695 unsigned char * rawbuf = (unsigned char *)malloc( width * format );
00696
00697 char id[] = "written with libtarga";
00698 ubyte idlen = 21;
00699 ubyte zeroes[5] = { 0, 0, 0, 0, 0 };
00700 uint32 pixbuf;
00701 ubyte one = 1;
00702 ubyte cmap_type = 0;
00703 ubyte img_type = 10;
00704 uint16 xorigin = 0;
00705 uint16 yorigin = 0;
00706 ubyte pixdepth = format * 8;
00707 ubyte img_desc = format == TGA_TRUECOLOR_32 ? 8 : 0;
00708
00709
00710 switch( format ) {
00711 case TGA_TRUECOLOR_24:
00712 case TGA_TRUECOLOR_32:
00713 break;
00714
00715 default:
00716 TargaError = TGA_ERR_BAD_FORMAT;
00717 return( 0 );
00718 }
00719
00720
00721 tga = fopen( file, "wb" );
00722
00723 if( tga == NULL ) {
00724 TargaError = TGA_ERR_OPEN_FAILS;
00725 return( 0 );
00726 }
00727
00728
00729 fwrite( &idlen, 1, 1, tga );
00730
00731
00732 fwrite( &cmap_type, 1, 1, tga );
00733
00734
00735 fwrite( &img_type, 1, 1, tga );
00736
00737
00738 fwrite( &zeroes, 5, 1, tga );
00739
00740
00741 fwrite( &xorigin, 2, 1, tga );
00742 fwrite( &yorigin, 2, 1, tga );
00743 fwrite( &shortwidth, 2, 1, tga );
00744 fwrite( &shortheight, 2, 1, tga );
00745 fwrite( &pixdepth, 1, 1, tga );
00746 fwrite( &img_desc, 1, 1, tga );
00747
00748
00749
00750 fwrite( &id, idlen, 1, tga );
00751
00752
00753 nc = 0;
00754
00755
00756
00757 for( i = 0; i < size; i++ ) {
00758
00759 idx = i * format;
00760
00761 row = i / width;
00762 column = i % width;
00763
00764
00765 pixbuf = 0;
00766 for( j = 0; j < format; j++ ) {
00767 pixbuf += dat[idx+j] << (8 * j);
00768 }
00769
00770 switch( format ) {
00771
00772 case TGA_TRUECOLOR_24:
00773
00774 pixbuf = ((pixbuf & 0xFF) << 16) +
00775 (pixbuf & 0xFF00) +
00776 ((pixbuf & 0xFF0000) >> 16);
00777
00778 pixbuf = htotl( pixbuf );
00779 break;
00780
00781 case TGA_TRUECOLOR_32:
00782
00783
00784
00785 red = (pixbuf & 0xFF) / 255.0f;
00786 green = ((pixbuf & 0xFF00) >> 8) / 255.0f;
00787 blue = ((pixbuf & 0xFF0000) >> 16) / 255.0f;
00788 alpha = ((pixbuf & 0xFF000000) >> 24) / 255.0f;
00789
00790 if( alpha > 0.0001 ) {
00791 red /= alpha;
00792 green /= alpha;
00793 blue /= alpha;
00794 }
00795
00796
00797
00798 red = red > 1.0f ? 255.0f : red * 255.0f;
00799 green = green > 1.0f ? 255.0f : green * 255.0f;
00800 blue = blue > 1.0f ? 255.0f : blue * 255.0f;
00801 alpha = alpha > 1.0f ? 255.0f : alpha * 255.0f;
00802
00803 pixbuf = (ubyte)blue + (((ubyte)green) << 8) +
00804 (((ubyte)red) << 16) + (((ubyte)alpha) << 24);
00805
00806 pixbuf = htotl( pixbuf );
00807 break;
00808
00809 }
00810
00811
00812 oc = nc;
00813
00814 nc = pixbuf;
00815
00816
00817 switch( state ) {
00818
00819 case INIT:
00820
00821 state = NONE;
00822 break;
00823
00824
00825 case NONE:
00826
00827 if( column == 0 ) {
00828
00829 repcount = 0;
00830 fwrite( &repcount, 1, 1, tga );
00831 #ifdef WORDS_BIGENDIAN
00832 fwrite( (&oc)+4, format, 1, tga );
00833 #else
00834 fwrite( &oc, format, 1, tga );
00835 #endif
00836 state = NONE;
00837 break;
00838 }
00839
00840 if( nc == oc ) {
00841 repcount = 0;
00842 state = RLP;
00843 } else {
00844 repcount = 0;
00845 state = RAWP;
00846 for( j = 0; j < format; j++ ) {
00847 #ifdef WORDS_BIGENDIAN
00848 rawbuf[(repcount * format) + j] = (ubyte)(*((&oc)+format-j-1));
00849 #else
00850 rawbuf[(repcount * format) + j] = *(((ubyte *)(&oc)) + j);
00851 #endif
00852 }
00853 }
00854 break;
00855
00856
00857 case RLP:
00858 repcount++;
00859
00860 if( column == 0 ) {
00861
00862 repcount |= 0x80;
00863 fwrite( &repcount, 1, 1, tga );
00864 #ifdef WORDS_BIGENDIAN
00865 fwrite( (&oc)+4, format, 1, tga );
00866 #else
00867 fwrite( &oc, format, 1, tga );
00868 #endif
00869 state = NONE;
00870 break;
00871 }
00872
00873 if( repcount == 127 ) {
00874
00875 repcount |= 0x80;
00876 fwrite( &repcount, 1, 1, tga );
00877 #ifdef WORDS_BIGENDIAN
00878 fwrite( (&oc)+4, format, 1, tga );
00879 #else
00880 fwrite( &oc, format, 1, tga );
00881 #endif
00882 state = NONE;
00883 break;
00884 }
00885
00886 if( nc != oc ) {
00887
00888 repcount |= 0x80;
00889 fwrite( &repcount, 1, 1, tga );
00890 #ifdef WORDS_BIGENDIAN
00891 fwrite( (&oc)+4, format, 1, tga );
00892 #else
00893 fwrite( &oc, format, 1, tga );
00894 #endif
00895 state = NONE;
00896 }
00897 break;
00898
00899
00900 case RAWP:
00901 repcount++;
00902
00903 if( column == 0 ) {
00904
00905 for( j = 0; j < format; j++ ) {
00906 #ifdef WORDS_BIGENDIAN
00907 rawbuf[(repcount * format) + j] = (ubyte)(*((&oc)+format-j-1));
00908 #else
00909 rawbuf[(repcount * format) + j] = *(((ubyte *)(&oc)) + j);
00910 #endif
00911 }
00912 fwrite( &repcount, 1, 1, tga );
00913 fwrite( rawbuf, (repcount + 1) * format, 1, tga );
00914 state = NONE;
00915 break;
00916 }
00917
00918 if( repcount == 127 ) {
00919
00920 for( j = 0; j < format; j++ ) {
00921 #ifdef WORDS_BIGENDIAN
00922 rawbuf[(repcount * format) + j] = (ubyte)(*((&oc)+format-j-1));
00923 #else
00924 rawbuf[(repcount * format) + j] = *(((ubyte *)(&oc)) + j);
00925 #endif
00926 }
00927 fwrite( &repcount, 1, 1, tga );
00928 fwrite( rawbuf, (repcount + 1) * format, 1, tga );
00929 state = NONE;
00930 break;
00931 }
00932
00933 if( nc == oc ) {
00934
00935 repcount--;
00936 fwrite( &repcount, 1, 1, tga );
00937 fwrite( rawbuf, (repcount + 1) * format, 1, tga );
00938
00939
00940 repcount = 0;
00941 state = RLP;
00942 break;
00943 }
00944
00945
00946 for( j = 0; j < format; j++ ) {
00947 #ifdef WORDS_BIGENDIAN
00948 rawbuf[(repcount * format) + j] = (ubyte)(*((&oc)+format-j-1));
00949 #else
00950 rawbuf[(repcount * format) + j] = *(((ubyte *)(&oc)) + j);
00951 #endif
00952 }
00953
00954 break;
00955
00956 }
00957
00958
00959 }
00960
00961
00962
00963
00964 switch( state ) {
00965
00966 case INIT:
00967 break;
00968
00969 case NONE:
00970
00971 fwrite( &one, 1, 1, tga );
00972 #ifdef WORDS_BIGENDIAN
00973 fwrite( (&oc)+4, format, 1, tga );
00974 #else
00975 fwrite( &oc, format, 1, tga );
00976 #endif
00977 #ifdef WORDS_BIGENDIAN
00978 fwrite( (&nc)+4, format, 1, tga );
00979 #else
00980 fwrite( &nc, format, 1, tga );
00981 #endif
00982 break;
00983
00984 case RLP:
00985 repcount++;
00986 repcount |= 0x80;
00987 fwrite( &repcount, 1, 1, tga );
00988 #ifdef WORDS_BIGENDIAN
00989 fwrite( (&oc)+4, format, 1, tga );
00990 #else
00991 fwrite( &oc, format, 1, tga );
00992 #endif
00993 break;
00994
00995 case RAWP:
00996 repcount++;
00997 for( j = 0; j < format; j++ ) {
00998 #ifdef WORDS_BIGENDIAN
00999 rawbuf[(repcount * format) + j] = (ubyte)(*((&oc)+format-j-1));
01000 #else
01001 rawbuf[(repcount * format) + j] = *(((ubyte *)(&oc)) + j);
01002 #endif
01003 }
01004 fwrite( &repcount, 1, 1, tga );
01005 fwrite( rawbuf, (repcount + 1) * 3, 1, tga );
01006 break;
01007
01008 }
01009
01010
01011
01012 fclose( tga );
01013
01014 free( rawbuf );
01015
01016 return( 1 );
01017
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 static void tga_write_pixel_to_mem( ubyte * dat, ubyte img_spec, uint32 number,
01034 uint32 w, uint32 h, uint32 pixel, uint32 format ) {
01035
01036
01037
01038
01039 uint32 j;
01040 uint32 x, y;
01041 uint32 addy;
01042
01043 switch( (img_spec & 0x30) >> 4 ) {
01044
01045 case TGA_LOWER_RIGHT:
01046 x = w - 1 - (number % w);
01047 y = number / h;
01048 break;
01049
01050 case TGA_UPPER_LEFT:
01051 x = number % w;
01052 y = h - 1 - (number / w);
01053 break;
01054
01055 case TGA_UPPER_RIGHT:
01056 x = w - 1 - (number % w);
01057 y = h - 1 - (number / w);
01058 break;
01059
01060 case TGA_LOWER_LEFT:
01061 default:
01062 x = number % w;
01063 y = number / w;
01064 break;
01065
01066 }
01067
01068 addy = (y * w + x) * format;
01069 for( j = 0; j < format; j++ ) {
01070 dat[addy + j] = (ubyte)((pixel >> (j * 8)) & 0xFF);
01071 }
01072
01073 }
01074
01075
01076
01077
01078
01079 static uint32 tga_get_pixel( FILE * tga, ubyte bytes_per_pix,
01080 ubyte * colormap, ubyte cmap_bytes_entry ) {
01081
01082
01083
01084 uint32 tmp_col;
01085 uint32 tmp_int32;
01086 ubyte tmp_byte;
01087
01088 uint32 j;
01089
01090 tmp_int32 = 0;
01091 for( j = 0; j < bytes_per_pix; j++ ) {
01092 if( fread( &tmp_byte, 1, 1, tga ) < 1 ) {
01093 tmp_int32 = 0;
01094 } else {
01095 tmp_int32 += tmp_byte << (j * 8);
01096 }
01097 }
01098
01099
01100 switch( bytes_per_pix ) {
01101
01102 case 2:
01103 tmp_int32 = ttohs( (uint16)tmp_int32 );
01104 break;
01105
01106 case 3:
01107 case 4:
01108 tmp_int32 = ttohl( tmp_int32 );
01109 break;
01110
01111 }
01112
01113 if( colormap != NULL ) {
01114
01115 tmp_col = 0;
01116 for( j = 0; j < cmap_bytes_entry; j++ ) {
01117 tmp_col += colormap[cmap_bytes_entry * tmp_int32 + j] << (8 * j);
01118 }
01119 } else {
01120 tmp_col = tmp_int32;
01121 }
01122
01123 return( tmp_col );
01124
01125 }
01126
01127
01128
01129
01130
01131 static uint32 tga_convert_color( uint32 pixel, uint32 bpp_in, ubyte alphabits, uint32 format_out ) {
01132
01133
01134
01135
01136
01137
01138 ubyte r, g, b, a;
01139
01140 switch( bpp_in ) {
01141
01142 case 32:
01143 if( alphabits == 0 ) {
01144 goto is_24_bit_in_disguise;
01145 }
01146
01147 break;
01148
01149 case 24:
01150 is_24_bit_in_disguise:
01151
01152 pixel |= 0xFF000000;
01153 break;
01154
01155 case 15:
01156 is_15_bit_in_disguise:
01157 r = (ubyte)(((float)((pixel & 0x7C00) >> 10)) * 8.2258f);
01158 g = (ubyte)(((float)((pixel & 0x03E0) >> 5 )) * 8.2258f);
01159 b = (ubyte)(((float)(pixel & 0x001F)) * 8.2258f);
01160
01161 pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
01162 break;
01163
01164 case 16:
01165 if( alphabits == 1 ) {
01166 goto is_15_bit_in_disguise;
01167 }
01168
01169 r = (ubyte)(((float)((pixel & 0xF800) >> 11)) * 8.2258f);
01170 g = (ubyte)(((float)((pixel & 0x07E0) >> 5 )) * 4.0476f);
01171 b = (ubyte)(((float)(pixel & 0x001F)) * 8.2258f);
01172 pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
01173 break;
01174
01175 }
01176
01177
01178 pixel = (pixel & 0xFF00FF00) + ((pixel & 0xFF) << 16) + ((pixel & 0xFF0000) >> 16);
01179
01180 r = pixel & 0x000000FF;
01181 g = (pixel & 0x0000FF00) >> 8;
01182 b = (pixel & 0x00FF0000) >> 16;
01183 a = (pixel & 0xFF000000) >> 24;
01184
01185
01186 r = (ubyte)(((float)r / 255.0f) * ((float)a / 255.0f) * 255.0f);
01187 g = (ubyte)(((float)g / 255.0f) * ((float)a / 255.0f) * 255.0f);
01188 b = (ubyte)(((float)b / 255.0f) * ((float)a / 255.0f) * 255.0f);
01189
01190 pixel = r + (g << 8) + (b << 16) + (a << 24);
01191
01192
01193
01194 switch( format_out ) {
01195
01196 case TGA_TRUECOLOR_32:
01197
01198 break;
01199
01200 case TGA_TRUECOLOR_24:
01201
01202 pixel &= 0x00FFFFFF;
01203 break;
01204
01205 }
01206
01207 return( pixel );
01208
01209 }
01210
01211
01212
01213
01214 static int16 ttohs( int16 val ) {
01215
01216 #ifdef WORDS_BIGENDIAN
01217 return( ((val & 0xFF) << 8) + (val >> 8) );
01218 #else
01219 return( val );
01220 #endif
01221
01222 }
01223
01224
01225 static int16 htots( int16 val ) {
01226
01227 #ifdef WORDS_BIGENDIAN
01228 return( ((val & 0xFF) << 8) + (val >> 8) );
01229 #else
01230 return( val );
01231 #endif
01232
01233 }
01234
01235
01236 static int32 ttohl( int32 val ) {
01237
01238 #ifdef WORDS_BIGENDIAN
01239 return( ((val & 0x000000FF) << 24) +
01240 ((val & 0x0000FF00) << 8) +
01241 ((val & 0x00FF0000) >> 8) +
01242 ((val & 0xFF000000) >> 24) );
01243 #else
01244 return( val );
01245 #endif
01246
01247 }
01248
01249
01250 static int32 htotl( int32 val ) {
01251
01252 #ifdef WORDS_BIGENDIAN
01253 return( ((val & 0x000000FF) << 24) +
01254 ((val & 0x0000FF00) << 8) +
01255 ((val & 0x00FF0000) >> 8) +
01256 ((val & 0xFF000000) >> 24) );
01257 #else
01258 return( val );
01259 #endif
01260
01261 }