Panda3D

pnmFileTypeTGA.cxx

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 &params) {
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
 All Classes Functions Variables Enumerations