Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pnmimagetypes/pnmFileTypeTGA.cxx

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

Generated on Fri May 2 00:43:23 2003 for Panda by doxygen1.3