59 static const char * 
const extensions_tga[] = {
    62 static const int num_extensions_tga = 
sizeof(extensions_tga) / 
sizeof(
const char *);
    69     unsigned char IDLength;             
    70     unsigned char CoMapType;            
    71     unsigned char ImgType;              
    72     unsigned char Index_lo, Index_hi;   
    73     unsigned char Length_lo, Length_hi; 
    75     unsigned char X_org_lo, X_org_hi;   
    76     unsigned char Y_org_lo, Y_org_hi;   
    77     unsigned char Width_lo, Width_hi;   
    78     unsigned char Height_lo, Height_hi; 
    79     unsigned char PixelSize;            
    80     unsigned char AttBits;              
    83     unsigned char IntrLve;              
    86 typedef char ImageIDField[256];
    89 #define TGA_MAXCOLORS 257    98 #define TGA_RLEMono 11    99 #define TGA_CompMap 32   100 #define TGA_CompMap4 33   103 #define TGA_IL_None 0   105 #define TGA_IL_Four 2   117 string PNMFileTypeTGA::
   127 get_num_extensions()
 const {
   128   return num_extensions_tga;
   135 string PNMFileTypeTGA::
   136 get_extension(
int n)
 const {
   137   nassertr(n >= 0 && n < num_extensions_tga, 
string());
   138   return extensions_tga[n];
   145 string PNMFileTypeTGA::
   146 get_suggested_extension()
 const {
   156 make_reader(istream *file, 
bool owns_file, 
const string &magic_number) {
   158   return new Reader(
this, file, owns_file, magic_number);
   167 make_writer(ostream *file, 
bool owns_file) {
   169   return new Writer(
this, file, owns_file);
   176 PNMFileTypeTGA::Reader::
   177 Reader(
PNMFileType *type, istream *file, 
bool owns_file, 
string magic_number) :
   180   tga_head = 
new ImageHeader;
   193     readtga( file, tga_head, magic_number );
   219     rows = ( (int) tga_head->Height_lo ) + ( (int) tga_head->Height_hi ) * 256;
   220     cols = ( (int) tga_head->Width_lo ) + ( (int) tga_head->Width_hi ) * 256;
   222     switch ( tga_head->ImgType )
   233         pm_error( 
"unknown Targa image type %d", tga_head->ImgType );
   238     if ( tga_head->ImgType == TGA_Map ||
   239          tga_head->ImgType == TGA_RLEMap ||
   240          tga_head->ImgType == TGA_CompMap ||
   241          tga_head->ImgType == TGA_CompMap4 )
   243         if ( tga_head->CoMapType != 1 )
   245                 "mapped image (type %d) with color map type != 1",
   249         size = tga_head->CoSize;
   254         size = tga_head->PixelSize;
   280       pm_error(
"unknown pixel size - %d", size );
   284     if ( tga_head->CoMapType != 0 )
   286         unsigned int temp1, temp2;
   287         temp1 = tga_head->Index_lo + tga_head->Index_hi * 256;
   288         temp2 = tga_head->Length_lo + tga_head->Length_hi * 256;
   289         int num_colors = temp1 + temp2 + 1;
   290         nassertv(ColorMap == 
nullptr && AlphaMap == 
nullptr);
   291         ColorMap = (
pixel *)PANDA_MALLOC_ARRAY(num_colors * 
sizeof(
pixel));
   292         AlphaMap = (gray *)PANDA_MALLOC_ARRAY(num_colors * 
sizeof(gray));
   293         for ( 
unsigned int i = temp1; i < ( temp1 + temp2 ); ++i )
   294             get_map_entry( file, &ColorMap[i], (
int) tga_head->CoSize,
   299     if ( tga_head->ImgType == TGA_RLEMap ||
   300          tga_head->ImgType == TGA_RLERGB ||
   301          tga_head->ImgType == TGA_RLEMono )
   315 PNMFileTypeTGA::Reader::
   318   if (ColorMap != 
nullptr) {
   319     PANDA_FREE_ARRAY(ColorMap);
   321   if (AlphaMap != 
nullptr) {
   322     PANDA_FREE_ARRAY(AlphaMap);
   335 int PNMFileTypeTGA::Reader::
   336 read_data(
xel *array, xelval *alpha) {
   339     for ( 
int row = 0; row < rows; ++row )
   341         int realrow = truerow;
   342         if ( tga_head->OrgBit == 0 )
   343             realrow = rows - realrow - 1;
   345         for ( 
int col = 0; col < cols; ++col )
   346             get_pixel( _file, &(array[realrow * cols + col]),
   347                        (
int) tga_head->PixelSize,
   348                        &(alpha[realrow * cols + col]) );
   349         if ( tga_head->IntrLve == TGA_IL_Four )
   351         else if ( tga_head->IntrLve == TGA_IL_Two )
   355         if ( truerow >= rows )
   365 PNMFileTypeTGA::Writer::
   366 Writer(
PNMFileType *type, ostream *file, 
bool owns_file) :
   369   tgaHeader = 
new ImageHeader;
   378 PNMFileTypeTGA::Writer::
   382   if (chv != 
nullptr) {
   383     ppm_freecolorhist(chv);
   385   if (cht != 
nullptr) {
   386     ppm_freecolorhash(cht);
   388   if (runlength != 
nullptr) {
   409 int PNMFileTypeTGA::Writer::
   410 write_data(
xel *array, xelval *) {
   422   if (is_grayscale() && tga_grayscale) {
   424     tgaHeader->ImgType = TGA_Mono;
   427     pnmimage_tga_cat.info()
   428       << 
"writing grayscale.\n";
   432     tgaHeader->ImgType = TGA_RGB;
   436       pnmimage_tga_cat.info()
   437         << 
"computing colormap...\n";
   438       chv = ppm_computecolorhist(&array, cols * rows, 1, TGA_MAXCOLORS, &ncolors );
   439       if ( chv == 
nullptr ) {
   440         pnmimage_tga_cat.info()
   441           << 
"too many colors, writing RGB.\n";
   443         pnmimage_tga_cat.info()
   444           << ncolors << 
" colors found.\n";
   445         tgaHeader->ImgType = TGA_Map;
   452       switch ( tgaHeader->ImgType )
   455           tgaHeader->ImgType = TGA_RLEMono;
   458           tgaHeader->ImgType = TGA_RLEMap;
   461           tgaHeader->ImgType = TGA_RLERGB;
   466       runlength = (
int*) 
pm_allocrow( cols, 
sizeof(
int) );
   469   tgaHeader->IDLength = 0;
   470   tgaHeader->Index_lo = 0;
   471   tgaHeader->Index_hi = 0;
   472   if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
   475       cht = ppm_colorhisttocolorhash( chv, ncolors );
   477       tgaHeader->CoMapType = 1;
   478       tgaHeader->Length_lo = ncolors % 256;
   479       tgaHeader->Length_hi = ncolors / 256;
   480       tgaHeader->CoSize = 24;
   484       tgaHeader->CoMapType = 0;
   485       tgaHeader->Length_lo = 0;
   486       tgaHeader->Length_hi = 0;
   487       tgaHeader->CoSize = 0;
   489   if ( tgaHeader->ImgType == TGA_RGB || tgaHeader->ImgType == TGA_RLERGB )
   490     tgaHeader->PixelSize = 24;
   492     tgaHeader->PixelSize = 8;
   493   tgaHeader->X_org_lo = tgaHeader->X_org_hi = 0;
   494   tgaHeader->Y_org_lo = tgaHeader->Y_org_hi = 0;
   495   tgaHeader->Width_lo = cols % 256;
   496   tgaHeader->Width_hi = cols / 256;
   497   tgaHeader->Height_lo = rows % 256;
   498   tgaHeader->Height_hi = rows / 256;
   499   tgaHeader->AttBits = 0;
   500   tgaHeader->Rsrvd = 0;
   501   tgaHeader->IntrLve = 0;
   502   tgaHeader->OrgBit = 0;
   505   writetga( tgaHeader, 
nullptr );
   507   if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
   510       for ( i = 0; i < ncolors; ++i )
   511         put_map_entry( &chv[i].color, tgaHeader->CoSize, _maxval );
   515   for ( row = 0; row < rows; ++row )
   518       if ( tgaHeader->OrgBit == 0 )
   519         realrow = rows - realrow - 1;
   522           compute_runlengths( cols, &array[realrow * cols], runlength );
   523           for ( col = 0; col < cols; )
   525               if ( runlength[col] > 0 )
   527                   _file->put( 0x80 + runlength[col] - 1 );
   528                   put_pixel(&(array[realrow * cols + col]),
   529                             tgaHeader->ImgType, _maxval, cht );
   530                   col += runlength[col];
   532               else if ( runlength[col] < 0 )
   534                   _file->put( -runlength[col] - 1 );
   535                   for ( i = 0; i < -runlength[col]; ++i )
   536                     put_pixel(&(array[realrow * cols + (col + i)]),
   537                               tgaHeader->ImgType, _maxval, cht );
   538                   col += -runlength[col];
   546           for ( col = 0, pP = &array[realrow * cols]; col < cols; ++col, ++pP )
   547             put_pixel( pP, tgaHeader->ImgType, _maxval, cht );
   559 void PNMFileTypeTGA::
   560 register_with_read_factory() {
   562     register_factory(get_class_type(), make_PNMFileTypeTGA);
   578 void PNMFileTypeTGA::Reader::
   579 readtga( istream *ifp, 
struct ImageHeader *tgaP, 
const string &magic_number ) {
   583     if (magic_number.length() > 0) {
   584       tgaP->IDLength = (
unsigned char)magic_number[0];
   586       tgaP->IDLength = getbyte( ifp );
   588     if (magic_number.length() > 1) {
   589       tgaP->CoMapType = (
unsigned char)magic_number[1];
   591       tgaP->CoMapType = getbyte( ifp );
   593     if (magic_number.length() > 2) {
   594       tgaP->ImgType = (
unsigned char)magic_number[2];
   596       tgaP->ImgType = getbyte( ifp );
   598     if (magic_number.length() > 3) {
   599       tgaP->Index_lo = (
unsigned char)magic_number[3];
   601       tgaP->Index_lo = getbyte( ifp );
   603     tgaP->Index_hi = getbyte( ifp );
   604     tgaP->Length_lo = getbyte( ifp );
   605     tgaP->Length_hi = getbyte( ifp );
   606     tgaP->CoSize = getbyte( ifp );
   607     tgaP->X_org_lo = getbyte( ifp );
   608     tgaP->X_org_hi = getbyte( ifp );
   609     tgaP->Y_org_lo = getbyte( ifp );
   610     tgaP->Y_org_hi = getbyte( ifp );
   611     tgaP->Width_lo = getbyte( ifp );
   612     tgaP->Width_hi = getbyte( ifp );
   613     tgaP->Height_lo = getbyte( ifp );
   614     tgaP->Height_hi = getbyte( ifp );
   615     tgaP->PixelSize = getbyte( ifp );
   616     flags = getbyte( ifp );
   617     tgaP->AttBits = flags & 0xf;
   618     tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
   619     tgaP->OrgBit = ( flags & 0x20 ) >> 5;
   620     tgaP->IntrLve = ( flags & 0xc0 ) >> 6;
   622     if ( tgaP->IDLength != 0 )
   623         ifp->read(junk, (
int) tgaP->IDLength);
   626 void PNMFileTypeTGA::Reader::
   627 get_map_entry( istream *ifp, 
pixel *Value, 
int Size, gray *Alpha ) {
   629     unsigned char r = 0, g = 0, b = 0, a = 0;
   635         r = g = b = getbyte( ifp );
   643         r = ( k & 0x7C ) >> 2;
   644         g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
   661         pm_error( 
"unknown colormap pixel size (#2) - %d", Size );
   663     PPM_ASSIGN( *Value, r, g, b );
   669 void PNMFileTypeTGA::Reader::
   670 get_pixel( istream *ifp, 
pixel *dest, 
int Size, gray *alpha_p) {
   676         if ( RLE_count == 0 )
   680             RLE_flag = ( i & 0x80 );
   702         Red = Grn = Blu = l = getbyte( ifp );
   710         l = ( (
unsigned int) k << 8 ) + j;
   711         Red = ( k & 0x7C ) >> 2;
   712         Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
   719         Blu = getbyte( ifp );
   720         Grn = getbyte( ifp );
   721         Red = getbyte( ifp );
   723             Alpha = getbyte( ifp );
   730         pm_error( 
"unknown pixel size (#2) - %d", Size );
   737           *alpha_p = AlphaMap[l];
   740         PPM_ASSIGN( *dest, Red, Grn, Blu );
   748 unsigned char PNMFileTypeTGA::Reader::
   749 getbyte( istream *ifp ) {
   753     if (ifp->fail() || ifp->eof())
   759 void PNMFileTypeTGA::Writer::
   760 writetga( 
struct ImageHeader *tgaP, 
char *
id )
   764     _file->put( tgaP->IDLength );
   765     _file->put( tgaP->CoMapType );
   766     _file->put( tgaP->ImgType );
   767     _file->put( tgaP->Index_lo );
   768     _file->put( tgaP->Index_hi );
   769     _file->put( tgaP->Length_lo );
   770     _file->put( tgaP->Length_hi );
   771     _file->put( tgaP->CoSize );
   772     _file->put( tgaP->X_org_lo );
   773     _file->put( tgaP->X_org_hi );
   774     _file->put( tgaP->Y_org_lo );
   775     _file->put( tgaP->Y_org_hi );
   776     _file->put( tgaP->Width_lo );
   777     _file->put( tgaP->Width_hi );
   778     _file->put( tgaP->Height_lo );
   779     _file->put( tgaP->Height_hi );
   780     _file->put( tgaP->PixelSize );
   781     flags = ( tgaP->AttBits & 0xf ) | ( ( tgaP->Rsrvd & 0x1 ) << 4 ) |
   782             ( ( tgaP->OrgBit & 0x1 ) << 5 ) | ( ( tgaP->OrgBit & 0x3 ) << 6 );
   784     if ( tgaP->IDLength )
   785         _file->write( 
id, (
int) tgaP->IDLength );
   788 void PNMFileTypeTGA::Writer::
   789 put_map_entry( 
pixel* valueP, 
int size, pixval maxval )
   797         put_mono( valueP, maxval );
   802         PPM_DEPTH( p, *valueP, maxval, 31 );
   803         j = (int) PPM_GETB( p ) | ( (int) PPM_GETG( p ) << 5 ) |
   804             ( (
int) PPM_GETR( p ) << 10 );
   805         _file->put( j % 256 );
   806         _file->put( j / 256 );
   811         put_rgb( valueP, maxval );
   815         pm_error( 
"unknown colormap pixel size (#2) - %d", size );
   819 void PNMFileTypeTGA::Writer::
   820 compute_runlengths( 
int cols, 
pixel *pixelrow, 
int *runlength )
   825     for ( col = 0; col < cols; ++col )
   829     for ( col = 0; col < cols; )
   835         while ( col < cols &&
   837                 PPM_EQUAL( pixelrow[col], pixelrow[start] ) );
   838         runlength[start] = col - start;
   842     for ( col = 0; col < cols; )
   844         if ( runlength[col] == 1 )
   847             while ( col < cols &&
   849                     runlength[col] == 1 )
   854             runlength[start] = - ( col - start );
   857             col += runlength[col];
   861 void PNMFileTypeTGA::Writer::
   868         put_mono( pP, maxval );
   876         put_rgb( pP, maxval );
   883 void PNMFileTypeTGA::Writer::
   884 put_mono( 
pixel* pP, pixval maxval )
   887     PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
   888     _file->put( PPM_GETB( p ) );
   891 void PNMFileTypeTGA::Writer::
   894     _file->put( ppm_lookupcolor( cht, pP ) );
   897 void PNMFileTypeTGA::Writer::
   898 put_rgb( 
pixel* pP, pixval maxval ) {
   900   PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
   901   _file->put( PPM_GETB( p ) );
   902   if (is_grayscale()) {
   903     _file->put( PPM_GETB( p ) );
   904     _file->put( PPM_GETB( p ) );
   906     _file->put( PPM_GETG( p ) );
   907     _file->put( PPM_GETR( p ) );
 PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
Base class for objects that can be written to and read from Bam files.
 
This is the base class of a family of classes that represent particular image file types that PNMImag...
 
void pm_freerow(char *itrow)
Frees the row previously allocated withm pm_allocrow().
 
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
 
void pm_error(const char *format,...)
Outputs the given printf-style message to the user and terminates messily.
 
An instance of this class is passed to the Factory when requesting it to do its business and construc...
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
This is an abstract base class that defines the interface for reading image files of various types.
 
char * pm_allocrow(int cols, int size)
Allocates a row of cols * size bytes.
 
This is an abstract base class that defines the interface for writing image files of various types.
 
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
 
TypeHandle is the identifier used to differentiate C++ class types.