Panda3D
|
00001 // Filename: pnmFileTypeTGA.cxx 00002 // Created by: drose (27Apr01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 // Much code in this file is borrowed from Netpbm, specifically tgatoppm.c 00017 // and ppmtotga.c. 00018 00019 /* tgatoppm.c - read a TrueVision Targa file and write a portable pixmap 00020 ** 00021 ** Partially based on tga2rast, version 1.0, by Ian MacPhedran. 00022 ** 00023 ** Copyright (C) 1989 by Jef Poskanzer. 00024 ** 00025 ** Permission to use, copy, modify, and distribute this software and its 00026 ** documentation for any purpose and without fee is hereby granted, provided 00027 ** that the above copyright notice appear in all copies and that both that 00028 ** copyright notice and this permission notice appear in supporting 00029 ** documentation. This software is provided "as is" without express or 00030 ** implied warranty. 00031 */ 00032 00033 /* ppmtotga.c - read a portable pixmap and produce a TrueVision Targa file 00034 ** 00035 ** Copyright (C) 1989, 1991 by Mark Shand and Jef Poskanzer 00036 ** 00037 ** Permission to use, copy, modify, and distribute this software and its 00038 ** documentation for any purpose and without fee is hereby granted, provided 00039 ** that the above copyright notice appear in all copies and that both that 00040 ** copyright notice and this permission notice appear in supporting 00041 ** documentation. This software is provided "as is" without express or 00042 ** implied warranty. 00043 */ 00044 00045 #include "pnmFileTypeTGA.h" 00046 00047 #ifdef HAVE_TGA 00048 00049 #include "config_pnmimagetypes.h" 00050 00051 #include "pnmFileTypeRegistry.h" 00052 #include "bamReader.h" 00053 #include "pnmimage_base.h" 00054 00055 #include <string.h> 00056 00057 static const char * const extensions_tga[] = { 00058 "tga" 00059 }; 00060 static const int num_extensions_tga = sizeof(extensions_tga) / sizeof(const char *); 00061 00062 TypeHandle PNMFileTypeTGA::_type_handle; 00063 00064 00065 /* Header definition. */ 00066 struct ImageHeader { 00067 unsigned char IDLength; /* length of Identifier String */ 00068 unsigned char CoMapType; /* 0 = no map */ 00069 unsigned char ImgType; /* image type (see below for values) */ 00070 unsigned char Index_lo, Index_hi; /* index of first color map entry */ 00071 unsigned char Length_lo, Length_hi; /* number of entries in color map */ 00072 unsigned char CoSize; /* size of color map entry (15,16,24,32) */ 00073 unsigned char X_org_lo, X_org_hi; /* x origin of image */ 00074 unsigned char Y_org_lo, Y_org_hi; /* y origin of image */ 00075 unsigned char Width_lo, Width_hi; /* width of image */ 00076 unsigned char Height_lo, Height_hi; /* height of image */ 00077 unsigned char PixelSize; /* pixel size (8,16,24,32) */ 00078 unsigned char AttBits; /* 4 bits, number of attribute bits per pixel */ 00079 unsigned char Rsrvd; /* 1 bit, reserved */ 00080 unsigned char OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */ 00081 unsigned char IntrLve; /* 2 bits, interleaving flag */ 00082 }; 00083 00084 typedef char ImageIDField[256]; 00085 00086 /* Max number of colors allowed for colormapped output. */ 00087 #define TGA_MAXCOLORS 257 00088 00089 /* Definitions for image types. */ 00090 #define TGA_Null 0 00091 #define TGA_Map 1 00092 #define TGA_RGB 2 00093 #define TGA_Mono 3 00094 #define TGA_RLEMap 9 00095 #define TGA_RLERGB 10 00096 #define TGA_RLEMono 11 00097 #define TGA_CompMap 32 00098 #define TGA_CompMap4 33 00099 00100 /* Definitions for interleave flag. */ 00101 #define TGA_IL_None 0 00102 #define TGA_IL_Two 1 00103 #define TGA_IL_Four 2 00104 00105 //////////////////////////////////////////////////////////////////// 00106 // Function: PNMFileTypeTGA::Constructor 00107 // Access: Public 00108 // Description: 00109 //////////////////////////////////////////////////////////////////// 00110 PNMFileTypeTGA:: 00111 PNMFileTypeTGA() { 00112 } 00113 00114 //////////////////////////////////////////////////////////////////// 00115 // Function: PNMFileTypeTGA::get_name 00116 // Access: Public, Virtual 00117 // Description: Returns a few words describing the file type. 00118 //////////////////////////////////////////////////////////////////// 00119 string PNMFileTypeTGA:: 00120 get_name() const { 00121 return "Targa"; 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: PNMFileTypeTGA::get_num_extensions 00126 // Access: Public, Virtual 00127 // Description: Returns the number of different possible filename 00128 // extensions_tga associated with this particular file type. 00129 //////////////////////////////////////////////////////////////////// 00130 int PNMFileTypeTGA:: 00131 get_num_extensions() const { 00132 return num_extensions_tga; 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: PNMFileTypeTGA::get_extension 00137 // Access: Public, Virtual 00138 // Description: Returns the nth possible filename extension 00139 // associated with this particular file type, without a 00140 // leading dot. 00141 //////////////////////////////////////////////////////////////////// 00142 string PNMFileTypeTGA:: 00143 get_extension(int n) const { 00144 nassertr(n >= 0 && n < num_extensions_tga, string()); 00145 return extensions_tga[n]; 00146 } 00147 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: PNMFileTypeTGA::get_suggested_extension 00150 // Access: Public, Virtual 00151 // Description: Returns a suitable filename extension (without a 00152 // leading dot) to suggest for files of this type, or 00153 // empty string if no suggestions are available. 00154 //////////////////////////////////////////////////////////////////// 00155 string PNMFileTypeTGA:: 00156 get_suggested_extension() const { 00157 return "tga"; 00158 } 00159 00160 //////////////////////////////////////////////////////////////////// 00161 // Function: PNMFileTypeTGA::make_reader 00162 // Access: Public, Virtual 00163 // Description: Allocates and returns a new PNMReader suitable for 00164 // reading from this file type, if possible. If reading 00165 // from this file type is not supported, returns NULL. 00166 //////////////////////////////////////////////////////////////////// 00167 PNMReader *PNMFileTypeTGA:: 00168 make_reader(istream *file, bool owns_file, const string &magic_number) { 00169 init_pnm(); 00170 return new Reader(this, file, owns_file, magic_number); 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: PNMFileTypeTGA::make_writer 00175 // Access: Public, Virtual 00176 // Description: Allocates and returns a new PNMWriter suitable for 00177 // reading from this file type, if possible. If writing 00178 // files of this type is not supported, returns NULL. 00179 //////////////////////////////////////////////////////////////////// 00180 PNMWriter *PNMFileTypeTGA:: 00181 make_writer(ostream *file, bool owns_file) { 00182 init_pnm(); 00183 return new Writer(this, file, owns_file); 00184 } 00185 00186 00187 //////////////////////////////////////////////////////////////////// 00188 // Function: PNMFileTypeTGA::Reader::Constructor 00189 // Access: Public 00190 // Description: 00191 //////////////////////////////////////////////////////////////////// 00192 PNMFileTypeTGA::Reader:: 00193 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : 00194 PNMReader(type, file, owns_file) 00195 { 00196 tga_head = new ImageHeader; 00197 RLE_count = 0; 00198 RLE_flag = 0; 00199 ColorMap = NULL; 00200 AlphaMap = NULL; 00201 00202 /* Read the Targa file header. */ 00203 readtga( file, tga_head, magic_number ); 00204 /* 00205 { 00206 pm_message( "IDLength = %d", (int) tga_head->IDLength ); 00207 pm_message( "CoMapType = %d", (int) tga_head->CoMapType ); 00208 pm_message( "ImgType = %d", (int) tga_head->ImgType ); 00209 pm_message( "Index_lo = %d", (int) tga_head->Index_lo ); 00210 pm_message( "Index_hi = %d", (int) tga_head->Index_hi ); 00211 pm_message( "Length_lo = %d", (int) tga_head->Length_lo ); 00212 pm_message( "Length_hi = %d", (int) tga_head->Length_hi ); 00213 pm_message( "CoSize = %d", (int) tga_head->CoSize ); 00214 pm_message( "X_org_lo = %d", (int) tga_head->X_org_lo ); 00215 pm_message( "X_org_hi = %d", (int) tga_head->X_org_hi ); 00216 pm_message( "Y_org_lo = %d", (int) tga_head->Y_org_lo ); 00217 pm_message( "Y_org_hi = %d", (int) tga_head->Y_org_hi ); 00218 pm_message( "Width_lo = %d", (int) tga_head->Width_lo ); 00219 pm_message( "Width_hi = %d", (int) tga_head->Width_hi ); 00220 pm_message( "Height_lo = %d", (int) tga_head->Height_lo ); 00221 pm_message( "Height_hi = %d", (int) tga_head->Height_hi ); 00222 pm_message( "PixelSize = %d", (int) tga_head->PixelSize ); 00223 pm_message( "AttBits = %d", (int) tga_head->AttBits ); 00224 pm_message( "Rsrvd = %d", (int) tga_head->Rsrvd ); 00225 pm_message( "OrgBit = %d", (int) tga_head->OrgBit ); 00226 pm_message( "IntrLve = %d", (int) tga_head->IntrLve ); 00227 } 00228 */ 00229 rows = ( (int) tga_head->Height_lo ) + ( (int) tga_head->Height_hi ) * 256; 00230 cols = ( (int) tga_head->Width_lo ) + ( (int) tga_head->Width_hi ) * 256; 00231 00232 switch ( tga_head->ImgType ) 00233 { 00234 case TGA_Map: 00235 case TGA_RGB: 00236 case TGA_Mono: 00237 case TGA_RLEMap: 00238 case TGA_RLERGB: 00239 case TGA_RLEMono: 00240 break; 00241 00242 default: 00243 pm_error( "unknown Targa image type %d", tga_head->ImgType ); 00244 } 00245 00246 int size; 00247 00248 if ( tga_head->ImgType == TGA_Map || 00249 tga_head->ImgType == TGA_RLEMap || 00250 tga_head->ImgType == TGA_CompMap || 00251 tga_head->ImgType == TGA_CompMap4 ) 00252 { /* Color-mapped image */ 00253 if ( tga_head->CoMapType != 1 ) 00254 pm_error( 00255 "mapped image (type %d) with color map type != 1", 00256 tga_head->ImgType ); 00257 mapped = 1; 00258 /* Figure maxval from CoSize. */ 00259 size = tga_head->CoSize; 00260 } 00261 else 00262 { /* Not colormap, so figure maxval from PixelSize. */ 00263 mapped = 0; 00264 size = tga_head->PixelSize; 00265 } 00266 00267 switch ( size ) { 00268 case 8: 00269 _num_channels = 1; 00270 _maxval = 255; 00271 break; 00272 00273 case 24: 00274 _num_channels = 3; 00275 _maxval = 255; 00276 break; 00277 00278 case 32: 00279 _num_channels = 4; 00280 _maxval = 255; 00281 break; 00282 00283 case 15: 00284 case 16: 00285 _num_channels = 3; 00286 _maxval = 31; 00287 break; 00288 00289 default: 00290 pm_error("unknown pixel size - %d", size ); 00291 } 00292 00293 /* If required, read the color map information. */ 00294 if ( tga_head->CoMapType != 0 ) 00295 { 00296 unsigned int temp1, temp2; 00297 temp1 = tga_head->Index_lo + tga_head->Index_hi * 256; 00298 temp2 = tga_head->Length_lo + tga_head->Length_hi * 256; 00299 int num_colors = temp1 + temp2 + 1; 00300 nassertv(ColorMap == NULL && AlphaMap == NULL); 00301 ColorMap = (pixel *)PANDA_MALLOC_ARRAY(num_colors * sizeof(pixel)); 00302 AlphaMap = (gray *)PANDA_MALLOC_ARRAY(num_colors * sizeof(gray)); 00303 for ( unsigned int i = temp1; i < ( temp1 + temp2 ); ++i ) 00304 get_map_entry( file, &ColorMap[i], (int) tga_head->CoSize, 00305 &AlphaMap[i]); 00306 } 00307 00308 /* Check run-length encoding. */ 00309 if ( tga_head->ImgType == TGA_RLEMap || 00310 tga_head->ImgType == TGA_RLERGB || 00311 tga_head->ImgType == TGA_RLEMono ) 00312 rlencoded = 1; 00313 else 00314 rlencoded = 0; 00315 00316 _x_size = cols; 00317 _y_size = rows; 00318 //_num_channels = 3; 00319 00320 } 00321 00322 //////////////////////////////////////////////////////////////////// 00323 // Function: PNMFileTypeTGA::Reader::Destructor 00324 // Access: Public, Virtual 00325 // Description: 00326 //////////////////////////////////////////////////////////////////// 00327 PNMFileTypeTGA::Reader:: 00328 ~Reader() { 00329 delete tga_head; 00330 if (ColorMap != NULL) { 00331 PANDA_FREE_ARRAY(ColorMap); 00332 } 00333 if (AlphaMap != NULL) { 00334 PANDA_FREE_ARRAY(AlphaMap); 00335 } 00336 } 00337 00338 //////////////////////////////////////////////////////////////////// 00339 // Function: PNMFileTypeTGA::Reader::read_data 00340 // Access: Public, Virtual 00341 // Description: Reads in an entire image all at once, storing it in 00342 // the pre-allocated _x_size * _y_size array and alpha 00343 // pointers. (If the image type has no alpha channel, 00344 // alpha is ignored.) Returns the number of rows 00345 // correctly read. 00346 // 00347 // Derived classes need not override this if they 00348 // instead provide supports_read_row() and read_row(), 00349 // below. 00350 //////////////////////////////////////////////////////////////////// 00351 int PNMFileTypeTGA::Reader:: 00352 read_data(xel *array, xelval *alpha) { 00353 int truerow = 0; 00354 int baserow = 0; 00355 for ( int row = 0; row < rows; ++row ) 00356 { 00357 int realrow = truerow; 00358 if ( tga_head->OrgBit == 0 ) 00359 realrow = rows - realrow - 1; 00360 00361 for ( int col = 0; col < cols; ++col ) 00362 get_pixel( _file, &(array[realrow * cols + col]), 00363 (int) tga_head->PixelSize, 00364 &(alpha[realrow * cols + col]) ); 00365 if ( tga_head->IntrLve == TGA_IL_Four ) 00366 truerow += 4; 00367 else if ( tga_head->IntrLve == TGA_IL_Two ) 00368 truerow += 2; 00369 else 00370 ++truerow; 00371 if ( truerow >= rows ) 00372 truerow = ++baserow; 00373 } 00374 00375 return rows; 00376 } 00377 00378 //////////////////////////////////////////////////////////////////// 00379 // Function: PNMFileTypeTGA::Writer::Constructor 00380 // Access: Public 00381 // Description: 00382 //////////////////////////////////////////////////////////////////// 00383 PNMFileTypeTGA::Writer:: 00384 Writer(PNMFileType *type, ostream *file, bool owns_file) : 00385 PNMWriter(type, file, owns_file) 00386 { 00387 tgaHeader = new ImageHeader; 00388 chv = (colorhist_vector)0; 00389 cht = (colorhash_table)0; 00390 runlength = (int*)0; 00391 } 00392 00393 //////////////////////////////////////////////////////////////////// 00394 // Function: PNMFileTypeTGA::Writer::Destructor 00395 // Access: Public 00396 // Description: 00397 //////////////////////////////////////////////////////////////////// 00398 PNMFileTypeTGA::Writer:: 00399 ~Writer() { 00400 delete tgaHeader; 00401 00402 if (chv != (colorhist_vector)0) { 00403 ppm_freecolorhist(chv); 00404 } 00405 if (cht != (colorhash_table)0) { 00406 ppm_freecolorhash(cht); 00407 } 00408 if (runlength != (int *)0) { 00409 pm_freerow((char *)runlength); 00410 } 00411 } 00412 00413 //////////////////////////////////////////////////////////////////// 00414 // Function: PNMFileTypeBMP::Writer::write_data 00415 // Access: Public, Virtual 00416 // Description: Writes out an entire image all at once, including the 00417 // header, based on the image data stored in the given 00418 // _x_size * _y_size array and alpha pointers. (If the 00419 // image type has no alpha channel, alpha is ignored.) 00420 // Returns the number of rows correctly written. 00421 // 00422 // It is the user's responsibility to fill in the header 00423 // data via calls to set_x_size(), set_num_channels(), 00424 // etc., or copy_header_from(), before calling 00425 // write_data(). 00426 // 00427 // It is important to delete the PNMWriter class after 00428 // successfully writing the data. Failing to do this 00429 // may result in some data not getting flushed! 00430 // 00431 // Derived classes need not override this if they 00432 // instead provide supports_streaming() and write_row(), 00433 // below. 00434 //////////////////////////////////////////////////////////////////// 00435 int PNMFileTypeTGA::Writer:: 00436 write_data(xel *array, xelval *) { 00437 // We don't presently support writing 4-channel tga files (since 00438 // ppmtotga doesn't support this). 00439 rle_flag = tga_rle; 00440 00441 int row, col; 00442 int i; 00443 pixel* pP; 00444 00445 cols = _x_size; 00446 rows = _y_size; 00447 00448 if (is_grayscale() && tga_grayscale) { 00449 // We allow grayscale TGA files, and this is a grayscale image, so... 00450 tgaHeader->ImgType = TGA_Mono; 00451 00452 // There's no real point in colormapping a grayscale image. 00453 pnmimage_tga_cat.info() 00454 << "writing grayscale.\n"; 00455 00456 } else { 00457 // This will be an RGB image. 00458 tgaHeader->ImgType = TGA_RGB; 00459 00460 if (tga_colormap) { 00461 // It may even be colormapped if there are few enough colors. 00462 pnmimage_tga_cat.info() 00463 << "computing colormap...\n"; 00464 chv = ppm_computecolorhist(&array, cols * rows, 1, TGA_MAXCOLORS, &ncolors ); 00465 if ( chv == (colorhist_vector) 0 ) { 00466 pnmimage_tga_cat.info() 00467 << "too many colors, writing RGB.\n"; 00468 } else { 00469 pnmimage_tga_cat.info() 00470 << ncolors << " colors found.\n"; 00471 tgaHeader->ImgType = TGA_Map; 00472 } 00473 } 00474 } 00475 00476 if ( rle_flag ) 00477 { 00478 switch ( tgaHeader->ImgType ) 00479 { 00480 case TGA_Mono: 00481 tgaHeader->ImgType = TGA_RLEMono; 00482 break; 00483 case TGA_Map: 00484 tgaHeader->ImgType = TGA_RLEMap; 00485 break; 00486 case TGA_RGB: 00487 tgaHeader->ImgType = TGA_RLERGB; 00488 break; 00489 default: 00490 pm_error( "can't happen" ); 00491 } 00492 runlength = (int*) pm_allocrow( cols, sizeof(int) ); 00493 } 00494 00495 tgaHeader->IDLength = 0; 00496 tgaHeader->Index_lo = 0; 00497 tgaHeader->Index_hi = 0; 00498 if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap ) 00499 { 00500 /* Make a hash table for fast color lookup. */ 00501 cht = ppm_colorhisttocolorhash( chv, ncolors ); 00502 00503 tgaHeader->CoMapType = 1; 00504 tgaHeader->Length_lo = ncolors % 256; 00505 tgaHeader->Length_hi = ncolors / 256; 00506 tgaHeader->CoSize = 24; 00507 } 00508 else 00509 { 00510 tgaHeader->CoMapType = 0; 00511 tgaHeader->Length_lo = 0; 00512 tgaHeader->Length_hi = 0; 00513 tgaHeader->CoSize = 0; 00514 } 00515 if ( tgaHeader->ImgType == TGA_RGB || tgaHeader->ImgType == TGA_RLERGB ) 00516 tgaHeader->PixelSize = 24; 00517 else 00518 tgaHeader->PixelSize = 8; 00519 tgaHeader->X_org_lo = tgaHeader->X_org_hi = 0; 00520 tgaHeader->Y_org_lo = tgaHeader->Y_org_hi = 0; 00521 tgaHeader->Width_lo = cols % 256; 00522 tgaHeader->Width_hi = cols / 256; 00523 tgaHeader->Height_lo = rows % 256; 00524 tgaHeader->Height_hi = rows / 256; 00525 tgaHeader->AttBits = 0; 00526 tgaHeader->Rsrvd = 0; 00527 tgaHeader->IntrLve = 0; 00528 tgaHeader->OrgBit = 0; 00529 00530 /* Write out the Targa header. */ 00531 writetga( tgaHeader, (char*) 0 ); 00532 00533 if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap ) 00534 { 00535 /* Write out the Targa colormap. */ 00536 for ( i = 0; i < ncolors; ++i ) 00537 put_map_entry( &chv[i].color, tgaHeader->CoSize, _maxval ); 00538 } 00539 00540 /* Write out the pixels */ 00541 for ( row = 0; row < rows; ++row ) 00542 { 00543 int realrow = row; 00544 if ( tgaHeader->OrgBit == 0 ) 00545 realrow = rows - realrow - 1; 00546 if ( rle_flag ) 00547 { 00548 compute_runlengths( cols, &array[realrow * cols], runlength ); 00549 for ( col = 0; col < cols; ) 00550 { 00551 if ( runlength[col] > 0 ) 00552 { 00553 _file->put( 0x80 + runlength[col] - 1 ); 00554 put_pixel(&(array[realrow * cols + col]), 00555 tgaHeader->ImgType, _maxval, cht ); 00556 col += runlength[col]; 00557 } 00558 else if ( runlength[col] < 0 ) 00559 { 00560 _file->put( -runlength[col] - 1 ); 00561 for ( i = 0; i < -runlength[col]; ++i ) 00562 put_pixel(&(array[realrow * cols + (col + i)]), 00563 tgaHeader->ImgType, _maxval, cht ); 00564 col += -runlength[col]; 00565 } 00566 else 00567 pm_error( "can't happen" ); 00568 } 00569 } 00570 else 00571 { 00572 for ( col = 0, pP = &array[realrow * cols]; col < cols; ++col, ++pP ) 00573 put_pixel( pP, tgaHeader->ImgType, _maxval, cht ); 00574 } 00575 } 00576 00577 return rows; 00578 } 00579 00580 00581 00582 //////////////////////////////////////////////////////////////////// 00583 // Function: PNMFileTypeTGA::register_with_read_factory 00584 // Access: Public, Static 00585 // Description: Registers the current object as something that can be 00586 // read from a Bam file. 00587 //////////////////////////////////////////////////////////////////// 00588 void PNMFileTypeTGA:: 00589 register_with_read_factory() { 00590 BamReader::get_factory()-> 00591 register_factory(get_class_type(), make_PNMFileTypeTGA); 00592 } 00593 00594 //////////////////////////////////////////////////////////////////// 00595 // Function: PNMFileTypeTGA::make_PNMFileTypeTGA 00596 // Access: Protected, Static 00597 // Description: This method is called by the BamReader when an object 00598 // of this type is encountered in a Bam file; it should 00599 // allocate and return a new object with all the data 00600 // read. 00601 // 00602 // In the case of the PNMFileType objects, since these 00603 // objects are all shared, we just pull the object from 00604 // the registry. 00605 //////////////////////////////////////////////////////////////////// 00606 TypedWritable *PNMFileTypeTGA:: 00607 make_PNMFileTypeTGA(const FactoryParams ¶ms) { 00608 return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); 00609 } 00610 00611 void PNMFileTypeTGA::Reader:: 00612 readtga( istream *ifp, struct ImageHeader *tgaP, const string &magic_number ) { 00613 unsigned char flags; 00614 ImageIDField junk; 00615 00616 if (magic_number.length() > 0) { 00617 tgaP->IDLength = (unsigned char)magic_number[0]; 00618 } else { 00619 tgaP->IDLength = getbyte( ifp ); 00620 } 00621 if (magic_number.length() > 1) { 00622 tgaP->CoMapType = (unsigned char)magic_number[1]; 00623 } else { 00624 tgaP->CoMapType = getbyte( ifp ); 00625 } 00626 if (magic_number.length() > 2) { 00627 tgaP->ImgType = (unsigned char)magic_number[2]; 00628 } else { 00629 tgaP->ImgType = getbyte( ifp ); 00630 } 00631 if (magic_number.length() > 3) { 00632 tgaP->Index_lo = (unsigned char)magic_number[3]; 00633 } else { 00634 tgaP->Index_lo = getbyte( ifp ); 00635 } 00636 tgaP->Index_hi = getbyte( ifp ); 00637 tgaP->Length_lo = getbyte( ifp ); 00638 tgaP->Length_hi = getbyte( ifp ); 00639 tgaP->CoSize = getbyte( ifp ); 00640 tgaP->X_org_lo = getbyte( ifp ); 00641 tgaP->X_org_hi = getbyte( ifp ); 00642 tgaP->Y_org_lo = getbyte( ifp ); 00643 tgaP->Y_org_hi = getbyte( ifp ); 00644 tgaP->Width_lo = getbyte( ifp ); 00645 tgaP->Width_hi = getbyte( ifp ); 00646 tgaP->Height_lo = getbyte( ifp ); 00647 tgaP->Height_hi = getbyte( ifp ); 00648 tgaP->PixelSize = getbyte( ifp ); 00649 flags = getbyte( ifp ); 00650 tgaP->AttBits = flags & 0xf; 00651 tgaP->Rsrvd = ( flags & 0x10 ) >> 4; 00652 tgaP->OrgBit = ( flags & 0x20 ) >> 5; 00653 tgaP->IntrLve = ( flags & 0xc0 ) >> 6; 00654 00655 if ( tgaP->IDLength != 0 ) 00656 ifp->read(junk, (int) tgaP->IDLength); 00657 } 00658 00659 void PNMFileTypeTGA::Reader:: 00660 get_map_entry( istream *ifp, pixel *Value, int Size, gray *Alpha ) { 00661 unsigned char j, k; 00662 unsigned char r = 0, g = 0, b = 0, a = 0; 00663 00664 /* Read appropriate number of bytes, break into rgb & put in map. */ 00665 switch ( Size ) 00666 { 00667 case 8: /* Grey scale, read and triplicate. */ 00668 r = g = b = getbyte( ifp ); 00669 a = 0; 00670 break; 00671 00672 case 16: /* 5 bits each of red green and blue. */ 00673 case 15: /* Watch for byte order. */ 00674 j = getbyte( ifp ); 00675 k = getbyte( ifp ); 00676 r = ( k & 0x7C ) >> 2; 00677 g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 ); 00678 b = j & 0x1F; 00679 a = 0; 00680 break; 00681 00682 case 32: /* 8 bits each of blue, green, red, and alpha */ 00683 case 24: /* 8 bits each of blue green and red. */ 00684 b = getbyte( ifp ); 00685 g = getbyte( ifp ); 00686 r = getbyte( ifp ); 00687 if ( Size == 32 ) 00688 a = getbyte( ifp ); 00689 else 00690 a = 0; 00691 break; 00692 00693 default: 00694 pm_error( "unknown colormap pixel size (#2) - %d", Size ); 00695 } 00696 PPM_ASSIGN( *Value, r, g, b ); 00697 *Alpha = a; 00698 } 00699 00700 00701 00702 void PNMFileTypeTGA::Reader:: 00703 get_pixel( istream *ifp, pixel *dest, int Size, gray *alpha_p) { 00704 static pixval Red, Grn, Blu; 00705 static pixval Alpha; 00706 unsigned char j, k; 00707 static unsigned int l; 00708 00709 /* Check if run length encoded. */ 00710 if ( rlencoded ) 00711 { 00712 if ( RLE_count == 0 ) 00713 { /* Have to restart run. */ 00714 unsigned char i; 00715 i = getbyte( ifp ); 00716 RLE_flag = ( i & 0x80 ); 00717 if ( RLE_flag == 0 ) 00718 /* Stream of unencoded pixels. */ 00719 RLE_count = i + 1; 00720 else 00721 /* Single pixel replicated. */ 00722 RLE_count = i - 127; 00723 /* Decrement count & get pixel. */ 00724 --RLE_count; 00725 } 00726 else 00727 { /* Have already read count & (at least) first pixel. */ 00728 --RLE_count; 00729 if ( RLE_flag != 0 ) 00730 /* Replicated pixels. */ 00731 goto PixEncode; 00732 } 00733 } 00734 /* Read appropriate number of bytes, break into RGB. */ 00735 switch ( Size ) 00736 { 00737 case 8: /* Grey scale, read and triplicate. */ 00738 Red = Grn = Blu = l = getbyte( ifp ); 00739 Alpha = 0; 00740 break; 00741 00742 case 16: /* 5 bits each of red green and blue. */ 00743 case 15: /* Watch byte order. */ 00744 j = getbyte( ifp ); 00745 k = getbyte( ifp ); 00746 l = ( (unsigned int) k << 8 ) + j; 00747 Red = ( k & 0x7C ) >> 2; 00748 Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 ); 00749 Blu = j & 0x1F; 00750 Alpha = 0; 00751 break; 00752 00753 case 32: /* 8 bits each of blue, green, red, and alpha */ 00754 case 24: /* 8 bits each of blue, green, and red. */ 00755 Blu = getbyte( ifp ); 00756 Grn = getbyte( ifp ); 00757 Red = getbyte( ifp ); 00758 if ( Size == 32 ) 00759 Alpha = getbyte( ifp ); 00760 else 00761 Alpha = 0; 00762 l = 0; 00763 break; 00764 00765 default: 00766 pm_error( "unknown pixel size (#2) - %d", Size ); 00767 } 00768 00769 PixEncode: 00770 if ( mapped ) { 00771 *dest = ColorMap[l]; 00772 if (has_alpha()) { 00773 *alpha_p = AlphaMap[l]; 00774 } 00775 } else { 00776 PPM_ASSIGN( *dest, Red, Grn, Blu ); 00777 if (has_alpha()) { 00778 *alpha_p = Alpha; 00779 } 00780 } 00781 } 00782 00783 00784 unsigned char PNMFileTypeTGA::Reader:: 00785 getbyte( istream *ifp ) { 00786 unsigned char c; 00787 00788 c = ifp->get(); 00789 if (ifp->fail() || ifp->eof()) 00790 pm_error( "EOF / read error" ); 00791 00792 return c; 00793 } 00794 00795 void PNMFileTypeTGA::Writer:: 00796 writetga( struct ImageHeader *tgaP, char *id ) 00797 { 00798 unsigned char flags; 00799 00800 _file->put( tgaP->IDLength ); 00801 _file->put( tgaP->CoMapType ); 00802 _file->put( tgaP->ImgType ); 00803 _file->put( tgaP->Index_lo ); 00804 _file->put( tgaP->Index_hi ); 00805 _file->put( tgaP->Length_lo ); 00806 _file->put( tgaP->Length_hi ); 00807 _file->put( tgaP->CoSize ); 00808 _file->put( tgaP->X_org_lo ); 00809 _file->put( tgaP->X_org_hi ); 00810 _file->put( tgaP->Y_org_lo ); 00811 _file->put( tgaP->Y_org_hi ); 00812 _file->put( tgaP->Width_lo ); 00813 _file->put( tgaP->Width_hi ); 00814 _file->put( tgaP->Height_lo ); 00815 _file->put( tgaP->Height_hi ); 00816 _file->put( tgaP->PixelSize ); 00817 flags = ( tgaP->AttBits & 0xf ) | ( ( tgaP->Rsrvd & 0x1 ) << 4 ) | 00818 ( ( tgaP->OrgBit & 0x1 ) << 5 ) | ( ( tgaP->OrgBit & 0x3 ) << 6 ); 00819 _file->put( flags ); 00820 if ( tgaP->IDLength ) 00821 _file->write( id, (int) tgaP->IDLength ); 00822 } 00823 00824 void PNMFileTypeTGA::Writer:: 00825 put_map_entry( pixel* valueP, int size, pixval maxval ) 00826 { 00827 int j; 00828 pixel p; 00829 00830 switch ( size ) 00831 { 00832 case 8: /* Grey scale. */ 00833 put_mono( valueP, maxval ); 00834 break; 00835 00836 case 16: /* 5 bits each of red green and blue. */ 00837 case 15: /* Watch for byte order. */ 00838 PPM_DEPTH( p, *valueP, maxval, 31 ); 00839 j = (int) PPM_GETB( p ) | ( (int) PPM_GETG( p ) << 5 ) | 00840 ( (int) PPM_GETR( p ) << 10 ); 00841 _file->put( j % 256 ); 00842 _file->put( j / 256 ); 00843 break; 00844 00845 case 32: 00846 case 24: /* 8 bits each of blue green and red. */ 00847 put_rgb( valueP, maxval ); 00848 break; 00849 00850 default: 00851 pm_error( "unknown colormap pixel size (#2) - %d", size ); 00852 } 00853 } 00854 00855 void PNMFileTypeTGA::Writer:: 00856 compute_runlengths( int cols, pixel *pixelrow, int *runlength ) 00857 { 00858 int col, start; 00859 00860 /* Initialize all run lengths to 0. (This is just an error check.) */ 00861 for ( col = 0; col < cols; ++col ) 00862 runlength[col] = 0; 00863 00864 /* Find runs of identical pixels. */ 00865 for ( col = 0; col < cols; ) 00866 { 00867 start = col; 00868 do { 00869 ++col; 00870 } 00871 while ( col < cols && 00872 col - start < 128 && 00873 PPM_EQUAL( pixelrow[col], pixelrow[start] ) ); 00874 runlength[start] = col - start; 00875 } 00876 00877 /* Now look for runs of length-1 runs, and turn them into negative runs. */ 00878 for ( col = 0; col < cols; ) 00879 { 00880 if ( runlength[col] == 1 ) 00881 { 00882 start = col; 00883 while ( col < cols && 00884 col - start < 128 && 00885 runlength[col] == 1 ) 00886 { 00887 runlength[col] = 0; 00888 ++col; 00889 } 00890 runlength[start] = - ( col - start ); 00891 } 00892 else 00893 col += runlength[col]; 00894 } 00895 } 00896 00897 void PNMFileTypeTGA::Writer:: 00898 put_pixel( pixel* pP, int imgtype, pixval maxval, colorhash_table cht ) 00899 { 00900 switch ( imgtype ) 00901 { 00902 case TGA_Mono: 00903 case TGA_RLEMono: 00904 put_mono( pP, maxval ); 00905 break; 00906 case TGA_Map: 00907 case TGA_RLEMap: 00908 put_map( pP, cht ); 00909 break; 00910 case TGA_RGB: 00911 case TGA_RLERGB: 00912 put_rgb( pP, maxval ); 00913 break; 00914 default: 00915 pm_error( "can't happen" ); 00916 } 00917 } 00918 00919 void PNMFileTypeTGA::Writer:: 00920 put_mono( pixel* pP, pixval maxval ) 00921 { 00922 pixel p; 00923 PPM_DEPTH( p, *pP, maxval, (pixval) 255 ); 00924 _file->put( PPM_GETB( p ) ); 00925 } 00926 00927 void PNMFileTypeTGA::Writer:: 00928 put_map( pixel *pP, colorhash_table cht ) 00929 { 00930 _file->put( ppm_lookupcolor( cht, pP ) ); 00931 } 00932 00933 void PNMFileTypeTGA::Writer:: 00934 put_rgb( pixel* pP, pixval maxval ) { 00935 pixel p; 00936 PPM_DEPTH( p, *pP, maxval, (pixval) 255 ); 00937 _file->put( PPM_GETB( p ) ); 00938 if (is_grayscale()) { 00939 _file->put( PPM_GETB( p ) ); 00940 _file->put( PPM_GETB( p ) ); 00941 } else { 00942 _file->put( PPM_GETG( p ) ); 00943 _file->put( PPM_GETR( p ) ); 00944 } 00945 } 00946 00947 #endif // HAVE_TGA