45 #include "pnmFileTypeTGA.h"
49 #include "config_pnmimagetypes.h"
51 #include "pnmFileTypeRegistry.h"
52 #include "bamReader.h"
53 #include "pnmimage_base.h"
57 static const char *
const extensions_tga[] = {
60 static const int num_extensions_tga =
sizeof(extensions_tga) /
sizeof(
const char *);
67 unsigned char IDLength;
68 unsigned char CoMapType;
69 unsigned char ImgType;
70 unsigned char Index_lo, Index_hi;
71 unsigned char Length_lo, Length_hi;
73 unsigned char X_org_lo, X_org_hi;
74 unsigned char Y_org_lo, Y_org_hi;
75 unsigned char Width_lo, Width_hi;
76 unsigned char Height_lo, Height_hi;
77 unsigned char PixelSize;
78 unsigned char AttBits;
81 unsigned char IntrLve;
84 typedef char ImageIDField[256];
87 #define TGA_MAXCOLORS 257
96 #define TGA_RLEMono 11
97 #define TGA_CompMap 32
98 #define TGA_CompMap4 33
101 #define TGA_IL_None 0
103 #define TGA_IL_Four 2
119 string PNMFileTypeTGA::
131 get_num_extensions()
const {
132 return num_extensions_tga;
142 string PNMFileTypeTGA::
143 get_extension(
int n)
const {
144 nassertr(n >= 0 && n < num_extensions_tga,
string());
145 return extensions_tga[n];
155 string PNMFileTypeTGA::
156 get_suggested_extension()
const {
168 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
170 return new Reader(
this, file, owns_file, magic_number);
181 make_writer(ostream *file,
bool owns_file) {
183 return new Writer(
this, file, owns_file);
192 PNMFileTypeTGA::Reader::
193 Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
196 tga_head =
new ImageHeader;
209 readtga( file, tga_head, magic_number );
235 rows = ( (int) tga_head->Height_lo ) + ( (int) tga_head->Height_hi ) * 256;
236 cols = ( (int) tga_head->Width_lo ) + ( (int) tga_head->Width_hi ) * 256;
238 switch ( tga_head->ImgType )
249 pm_error(
"unknown Targa image type %d", tga_head->ImgType );
254 if ( tga_head->ImgType == TGA_Map ||
255 tga_head->ImgType == TGA_RLEMap ||
256 tga_head->ImgType == TGA_CompMap ||
257 tga_head->ImgType == TGA_CompMap4 )
259 if ( tga_head->CoMapType != 1 )
261 "mapped image (type %d) with color map type != 1",
265 size = tga_head->CoSize;
270 size = tga_head->PixelSize;
296 pm_error(
"unknown pixel size - %d", size );
300 if ( tga_head->CoMapType != 0 )
302 unsigned int temp1, temp2;
303 temp1 = tga_head->Index_lo + tga_head->Index_hi * 256;
304 temp2 = tga_head->Length_lo + tga_head->Length_hi * 256;
305 int num_colors = temp1 + temp2 + 1;
306 nassertv(ColorMap == NULL && AlphaMap == NULL);
307 ColorMap = (
pixel *)PANDA_MALLOC_ARRAY(num_colors *
sizeof(
pixel));
308 AlphaMap = (gray *)PANDA_MALLOC_ARRAY(num_colors *
sizeof(gray));
309 for (
unsigned int i = temp1; i < ( temp1 + temp2 ); ++i )
310 get_map_entry( file, &ColorMap[i], (
int) tga_head->CoSize,
315 if ( tga_head->ImgType == TGA_RLEMap ||
316 tga_head->ImgType == TGA_RLERGB ||
317 tga_head->ImgType == TGA_RLEMono )
333 PNMFileTypeTGA::Reader::
336 if (ColorMap != NULL) {
337 PANDA_FREE_ARRAY(ColorMap);
339 if (AlphaMap != NULL) {
340 PANDA_FREE_ARRAY(AlphaMap);
357 int PNMFileTypeTGA::Reader::
358 read_data(
xel *array, xelval *alpha) {
361 for (
int row = 0; row < rows; ++row )
363 int realrow = truerow;
364 if ( tga_head->OrgBit == 0 )
365 realrow = rows - realrow - 1;
367 for (
int col = 0; col < cols; ++col )
368 get_pixel( _file, &(array[realrow * cols + col]),
369 (
int) tga_head->PixelSize,
370 &(alpha[realrow * cols + col]) );
371 if ( tga_head->IntrLve == TGA_IL_Four )
373 else if ( tga_head->IntrLve == TGA_IL_Two )
377 if ( truerow >= rows )
389 PNMFileTypeTGA::Writer::
390 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
393 tgaHeader =
new ImageHeader;
404 PNMFileTypeTGA::Writer::
409 ppm_freecolorhist(chv);
412 ppm_freecolorhash(cht);
414 if (runlength != (
int *)0) {
415 pm_freerow((
char *)runlength);
441 int PNMFileTypeTGA::Writer::
442 write_data(
xel *array, xelval *) {
454 if (is_grayscale() && tga_grayscale) {
456 tgaHeader->ImgType = TGA_Mono;
459 pnmimage_tga_cat.info()
460 <<
"writing grayscale.\n";
464 tgaHeader->ImgType = TGA_RGB;
468 pnmimage_tga_cat.info()
469 <<
"computing colormap...\n";
470 chv = ppm_computecolorhist(&array, cols * rows, 1, TGA_MAXCOLORS, &ncolors );
472 pnmimage_tga_cat.info()
473 <<
"too many colors, writing RGB.\n";
475 pnmimage_tga_cat.info()
476 << ncolors <<
" colors found.\n";
477 tgaHeader->ImgType = TGA_Map;
484 switch ( tgaHeader->ImgType )
487 tgaHeader->ImgType = TGA_RLEMono;
490 tgaHeader->ImgType = TGA_RLEMap;
493 tgaHeader->ImgType = TGA_RLERGB;
496 pm_error(
"can't happen" );
498 runlength = (
int*) pm_allocrow( cols,
sizeof(
int) );
501 tgaHeader->IDLength = 0;
502 tgaHeader->Index_lo = 0;
503 tgaHeader->Index_hi = 0;
504 if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
507 cht = ppm_colorhisttocolorhash( chv, ncolors );
509 tgaHeader->CoMapType = 1;
510 tgaHeader->Length_lo = ncolors % 256;
511 tgaHeader->Length_hi = ncolors / 256;
512 tgaHeader->CoSize = 24;
516 tgaHeader->CoMapType = 0;
517 tgaHeader->Length_lo = 0;
518 tgaHeader->Length_hi = 0;
519 tgaHeader->CoSize = 0;
521 if ( tgaHeader->ImgType == TGA_RGB || tgaHeader->ImgType == TGA_RLERGB )
522 tgaHeader->PixelSize = 24;
524 tgaHeader->PixelSize = 8;
525 tgaHeader->X_org_lo = tgaHeader->X_org_hi = 0;
526 tgaHeader->Y_org_lo = tgaHeader->Y_org_hi = 0;
527 tgaHeader->Width_lo = cols % 256;
528 tgaHeader->Width_hi = cols / 256;
529 tgaHeader->Height_lo = rows % 256;
530 tgaHeader->Height_hi = rows / 256;
531 tgaHeader->AttBits = 0;
532 tgaHeader->Rsrvd = 0;
533 tgaHeader->IntrLve = 0;
534 tgaHeader->OrgBit = 0;
537 writetga( tgaHeader, (
char*) 0 );
539 if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
542 for ( i = 0; i < ncolors; ++i )
543 put_map_entry( &chv[i].
color, tgaHeader->CoSize, _maxval );
547 for ( row = 0; row < rows; ++row )
550 if ( tgaHeader->OrgBit == 0 )
551 realrow = rows - realrow - 1;
554 compute_runlengths( cols, &array[realrow * cols], runlength );
555 for ( col = 0; col < cols; )
557 if ( runlength[col] > 0 )
559 _file->put( 0x80 + runlength[col] - 1 );
560 put_pixel(&(array[realrow * cols + col]),
561 tgaHeader->ImgType, _maxval, cht );
562 col += runlength[col];
564 else if ( runlength[col] < 0 )
566 _file->put( -runlength[col] - 1 );
567 for ( i = 0; i < -runlength[col]; ++i )
568 put_pixel(&(array[realrow * cols + (col + i)]),
569 tgaHeader->ImgType, _maxval, cht );
570 col += -runlength[col];
573 pm_error(
"can't happen" );
578 for ( col = 0, pP = &array[realrow * cols]; col < cols; ++col, ++pP )
579 put_pixel( pP, tgaHeader->ImgType, _maxval, cht );
594 void PNMFileTypeTGA::
595 register_with_read_factory() {
597 register_factory(get_class_type(), make_PNMFileTypeTGA);
617 void PNMFileTypeTGA::Reader::
618 readtga( istream *ifp,
struct ImageHeader *tgaP,
const string &magic_number ) {
622 if (magic_number.length() > 0) {
623 tgaP->IDLength = (
unsigned char)magic_number[0];
625 tgaP->IDLength = getbyte( ifp );
627 if (magic_number.length() > 1) {
628 tgaP->CoMapType = (
unsigned char)magic_number[1];
630 tgaP->CoMapType = getbyte( ifp );
632 if (magic_number.length() > 2) {
633 tgaP->ImgType = (
unsigned char)magic_number[2];
635 tgaP->ImgType = getbyte( ifp );
637 if (magic_number.length() > 3) {
638 tgaP->Index_lo = (
unsigned char)magic_number[3];
640 tgaP->Index_lo = getbyte( ifp );
642 tgaP->Index_hi = getbyte( ifp );
643 tgaP->Length_lo = getbyte( ifp );
644 tgaP->Length_hi = getbyte( ifp );
645 tgaP->CoSize = getbyte( ifp );
646 tgaP->X_org_lo = getbyte( ifp );
647 tgaP->X_org_hi = getbyte( ifp );
648 tgaP->Y_org_lo = getbyte( ifp );
649 tgaP->Y_org_hi = getbyte( ifp );
650 tgaP->Width_lo = getbyte( ifp );
651 tgaP->Width_hi = getbyte( ifp );
652 tgaP->Height_lo = getbyte( ifp );
653 tgaP->Height_hi = getbyte( ifp );
654 tgaP->PixelSize = getbyte( ifp );
655 flags = getbyte( ifp );
656 tgaP->AttBits = flags & 0xf;
657 tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
658 tgaP->OrgBit = ( flags & 0x20 ) >> 5;
659 tgaP->IntrLve = ( flags & 0xc0 ) >> 6;
661 if ( tgaP->IDLength != 0 )
662 ifp->read(junk, (
int) tgaP->IDLength);
665 void PNMFileTypeTGA::Reader::
666 get_map_entry( istream *ifp,
pixel *Value,
int Size, gray *Alpha ) {
668 unsigned char r = 0, g = 0, b = 0, a = 0;
674 r = g = b = getbyte( ifp );
682 r = ( k & 0x7C ) >> 2;
683 g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
700 pm_error(
"unknown colormap pixel size (#2) - %d", Size );
702 PPM_ASSIGN( *Value, r, g, b );
708 void PNMFileTypeTGA::Reader::
709 get_pixel( istream *ifp,
pixel *dest,
int Size, gray *alpha_p) {
715 if ( RLE_count == 0 )
719 RLE_flag = ( i & 0x80 );
741 Red = Grn = Blu = l = getbyte( ifp );
749 l = ( (
unsigned int) k << 8 ) + j;
750 Red = ( k & 0x7C ) >> 2;
751 Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
758 Blu = getbyte( ifp );
759 Grn = getbyte( ifp );
760 Red = getbyte( ifp );
762 Alpha = getbyte( ifp );
769 pm_error(
"unknown pixel size (#2) - %d", Size );
776 *alpha_p = AlphaMap[l];
779 PPM_ASSIGN( *dest, Red, Grn, Blu );
787 unsigned char PNMFileTypeTGA::Reader::
788 getbyte( istream *ifp ) {
792 if (ifp->fail() || ifp->eof())
793 pm_error(
"EOF / read error" );
798 void PNMFileTypeTGA::Writer::
799 writetga(
struct ImageHeader *tgaP,
char *
id )
803 _file->put( tgaP->IDLength );
804 _file->put( tgaP->CoMapType );
805 _file->put( tgaP->ImgType );
806 _file->put( tgaP->Index_lo );
807 _file->put( tgaP->Index_hi );
808 _file->put( tgaP->Length_lo );
809 _file->put( tgaP->Length_hi );
810 _file->put( tgaP->CoSize );
811 _file->put( tgaP->X_org_lo );
812 _file->put( tgaP->X_org_hi );
813 _file->put( tgaP->Y_org_lo );
814 _file->put( tgaP->Y_org_hi );
815 _file->put( tgaP->Width_lo );
816 _file->put( tgaP->Width_hi );
817 _file->put( tgaP->Height_lo );
818 _file->put( tgaP->Height_hi );
819 _file->put( tgaP->PixelSize );
820 flags = ( tgaP->AttBits & 0xf ) | ( ( tgaP->Rsrvd & 0x1 ) << 4 ) |
821 ( ( tgaP->OrgBit & 0x1 ) << 5 ) | ( ( tgaP->OrgBit & 0x3 ) << 6 );
823 if ( tgaP->IDLength )
824 _file->write(
id, (
int) tgaP->IDLength );
827 void PNMFileTypeTGA::Writer::
828 put_map_entry(
pixel* valueP,
int size, pixval maxval )
836 put_mono( valueP, maxval );
841 PPM_DEPTH( p, *valueP, maxval, 31 );
842 j = (int) PPM_GETB( p ) | ( (int) PPM_GETG( p ) << 5 ) |
843 ( (
int) PPM_GETR( p ) << 10 );
844 _file->put( j % 256 );
845 _file->put( j / 256 );
850 put_rgb( valueP, maxval );
854 pm_error(
"unknown colormap pixel size (#2) - %d", size );
858 void PNMFileTypeTGA::Writer::
859 compute_runlengths(
int cols,
pixel *pixelrow,
int *runlength )
864 for ( col = 0; col < cols; ++col )
868 for ( col = 0; col < cols; )
874 while ( col < cols &&
876 PPM_EQUAL( pixelrow[col], pixelrow[start] ) );
877 runlength[start] = col - start;
881 for ( col = 0; col < cols; )
883 if ( runlength[col] == 1 )
886 while ( col < cols &&
888 runlength[col] == 1 )
893 runlength[start] = - ( col - start );
896 col += runlength[col];
900 void PNMFileTypeTGA::Writer::
907 put_mono( pP, maxval );
915 put_rgb( pP, maxval );
918 pm_error(
"can't happen" );
922 void PNMFileTypeTGA::Writer::
923 put_mono(
pixel* pP, pixval maxval )
926 PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
927 _file->put( PPM_GETB( p ) );
930 void PNMFileTypeTGA::Writer::
933 _file->put( ppm_lookupcolor( cht, pP ) );
936 void PNMFileTypeTGA::Writer::
937 put_rgb(
pixel* pP, pixval maxval ) {
939 PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
940 _file->put( PPM_GETB( p ) );
941 if (is_grayscale()) {
942 _file->put( PPM_GETB( p ) );
943 _file->put( PPM_GETB( p ) );
945 _file->put( PPM_GETG( p ) );
946 _file->put( PPM_GETR( p ) );
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e...
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...
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
This is an abstract base class that defines the interface for reading image files of various types...
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.