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.