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 ) );