26 #define int8 tiff_int8 27 #define uint8 tiff_uint8 28 #define int32 tiff_int32 29 #define uint32 tiff_uint32 41 static const char *
const extensions_tiff[] = {
44 static const int num_extensions_tiff =
sizeof(extensions_tiff) /
sizeof(
const char *);
51 unsigned short tiff_compression = COMPRESSION_NONE;
66 long tiff_g3options = 0;
74 unsigned short tiff_fillorder = FILLORDER_MSB2LSB;
80 short tiff_predictor = 0;
84 #ifndef PHOTOMETRIC_DEPTH 85 #define PHOTOMETRIC_DEPTH 32768 91 istream_read(thandle_t fd, tdata_t buf, tsize_t size) {
92 istream *in = (istream *)fd;
93 in->read((
char *)buf, size);
99 ostream_write(thandle_t fd, tdata_t buf, tsize_t size) {
100 ostream *out = (ostream *)fd;
101 out->write((
char *)buf, size);
103 return out->fail() ? (tsize_t)0 : size;
107 ostream_dont_read(thandle_t, tdata_t, tsize_t) {
114 istream_dont_write(thandle_t, tdata_t, tsize_t) {
121 istream_seek(thandle_t fd, toff_t off,
int whence) {
122 istream *in = (istream *)fd;
144 if (pnmimage_tiff_cat->is_spam()) {
145 pnmimage_tiff_cat->spam()
146 <<
"istream_seek(" << (
void *)in <<
", " << off <<
", " 147 << whence <<
"), result = " << in->tellg() <<
"\n";
153 ostream_seek(thandle_t fd, toff_t off,
int whence) {
154 ostream *out = (ostream *)fd;
174 out->seekp(off, dir);
176 if (pnmimage_tiff_cat->is_spam()) {
177 pnmimage_tiff_cat->spam()
178 <<
"ostream_seek(" << (
void *)out <<
", " << off <<
", " 179 << whence <<
"), result = " << out->tellp() <<
"\n";
185 iostream_dont_close(thandle_t) {
191 istream_size(thandle_t fd) {
192 istream *in = (istream *)fd;
193 in->seekg(0, ios::end);
198 ostream_size(thandle_t fd) {
199 ostream *out = (ostream *)fd;
200 out->seekp(0, ios::end);
205 iostream_map(thandle_t, tdata_t*, toff_t*) {
210 iostream_unmap(thandle_t, tdata_t, toff_t) {
213 bool PNMFileTypeTIFF::_installed_error_handlers =
false;
223 if (pnmimage_tiff_cat->is_debug()) {
224 pnmimage_tiff_cat->debug()
225 << TIFFGetVersion() <<
"\n";
232 string PNMFileTypeTIFF::
241 int PNMFileTypeTIFF::
242 get_num_extensions()
const {
243 return num_extensions_tiff;
250 string PNMFileTypeTIFF::
251 get_extension(
int n)
const {
252 nassertr(n >= 0 && n < num_extensions_tiff,
string());
253 return extensions_tiff[n];
260 string PNMFileTypeTIFF::
261 get_suggested_extension()
const {
269 bool PNMFileTypeTIFF::
270 has_magic_number()
const {
279 bool PNMFileTypeTIFF::
280 matches_magic_number(
const string &magic_number)
const {
281 nassertr(magic_number.size() >= 2,
false);
283 ((
unsigned char)magic_number[0] << 8) |
284 ((
unsigned char)magic_number[1]);
285 return (mn == TIFF_BIGENDIAN || mn == TIFF_LITTLEENDIAN);
294 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
296 install_error_handlers();
297 return new Reader(
this, file, owns_file, magic_number);
306 make_writer(ostream *file,
bool owns_file) {
308 install_error_handlers();
309 return new Writer(
this, file, owns_file);
315 PNMFileTypeTIFF::Reader::
316 Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
319 bool grayscale =
false;
322 unsigned short* redcolormap;
323 unsigned short* greencolormap;
324 unsigned short* bluecolormap;
327 for (string::reverse_iterator mi = magic_number.rbegin();
328 mi != magic_number.rend();
333 pnmimage_tiff_cat.error()
334 <<
"Unable to put back magic number.\n";
339 tif = TIFFClientOpen(
"TIFF file",
"r",
341 istream_read, istream_dont_write,
342 (TIFFSeekProc)istream_seek,
343 iostream_dont_close, istream_size,
344 iostream_map, iostream_unmap);
346 if ( tif ==
nullptr ) {
352 if ( ! TIFFGetField( tif, TIFFTAG_SAMPLEFORMAT, &sample_format ) )
353 sample_format = SAMPLEFORMAT_UINT;
354 if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) )
356 if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) )
359 if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) ) {
360 pnmimage_tiff_cat.error()
361 <<
"Error getting photometric from TIFF file.\n";
364 }
else if (sample_format == SAMPLEFORMAT_IEEEFP) {
367 pnmimage_tiff_cat.error()
368 <<
"Can only read 32-bit float TIFF files, not " << bps <<
"-bit.\n";
372 }
else if (sample_format != SAMPLEFORMAT_UINT) {
374 pnmimage_tiff_cat.error()
375 <<
"Can't understand sample format\n";
381 unsigned short num_extra_samples;
382 unsigned short *extra_samples =
nullptr;
384 if (!TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &num_extra_samples,
386 num_extra_samples = 0;
388 _num_channels = spp - num_extra_samples;
389 unassoc_alpha_sample = 0;
390 assoc_alpha_sample = 0;
392 if (_num_channels == 1 || _num_channels == 3) {
394 bool got_alpha =
false;
395 for (
unsigned short s = 0; s < num_extra_samples && !got_alpha; s++) {
396 if (extra_samples[s] == EXTRASAMPLE_UNASSALPHA) {
397 unassoc_alpha_sample = s + _num_channels;
401 }
else if (extra_samples[s] == EXTRASAMPLE_ASSOCALPHA) {
402 assoc_alpha_sample = s + _num_channels;
412 if (!got_alpha && num_extra_samples == 1 &&
413 extra_samples[0] == EXTRASAMPLE_UNSPECIFIED) {
414 unassoc_alpha_sample = _num_channels;
418 }
else if ((_num_channels == 2 || _num_channels == 4) && num_extra_samples == 0) {
422 unassoc_alpha_sample = _num_channels - 1;
423 if (pnmimage_tiff_cat.is_debug()) {
424 pnmimage_tiff_cat.debug()
425 <<
"Assuming last channel of " << spp
426 <<
"-color image is meant to represent alpha.\n";
430 pnmimage_tiff_cat.error()
431 <<
"Cannot handle " << spp <<
"-color image (with " 432 << num_extra_samples <<
" extra channels).\n";
438 (void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &_x_size );
439 (void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &_y_size );
441 if (pnmimage_tiff_cat.is_debug()) {
442 pnmimage_tiff_cat.debug()
443 <<
"Reading TIFF image: " << _x_size <<
" x " << _y_size <<
"\n" 444 << bps <<
" bits/sample, " << spp <<
" samples/pixel\n";
447 _maxval = ( 1 << bps ) - 1;
448 if ( _maxval == 1 && _num_channels == 1 ) {
449 if (pnmimage_tiff_cat.is_debug()) {
450 pnmimage_tiff_cat.debug(
false)
455 switch ( photomet ) {
456 case PHOTOMETRIC_MINISBLACK:
457 if (pnmimage_tiff_cat.is_debug()) {
458 pnmimage_tiff_cat.debug(
false)
459 << _maxval + 1 <<
" graylevels (min is black)\n";
464 case PHOTOMETRIC_MINISWHITE:
465 if (pnmimage_tiff_cat.is_debug()) {
466 pnmimage_tiff_cat.debug(
false)
467 << _maxval + 1 <<
" graylevels (min is white)\n";
472 case PHOTOMETRIC_PALETTE:
473 if (pnmimage_tiff_cat.is_debug()) {
474 pnmimage_tiff_cat.debug(
false)
477 if ( ! TIFFGetField( tif, TIFFTAG_COLORMAP, &redcolormap, &greencolormap, &bluecolormap ) ) {
478 pnmimage_tiff_cat.error()
479 <<
"Error getting colormap from TIFF file.\n";
482 numcolors = _maxval + 1;
483 if ( numcolors > TIFF_COLORMAP_MAXCOLORS ) {
484 pnmimage_tiff_cat.error()
485 <<
"Cannot read TIFF file with " << numcolors
486 <<
" in colormap; max supported is " << TIFF_COLORMAP_MAXCOLORS <<
"\n";
489 _maxval = PNM_MAXMAXVAL;
491 for ( i = 0; i < numcolors; ++i ) {
493 r = (xelval)(_maxval * (
double)(redcolormap[i] / 65535.0));
494 g = (xelval)(_maxval * (
double)(greencolormap[i] / 65535.0));
495 b = (xelval)(_maxval * (
double)(bluecolormap[i] / 65535.0));
496 PPM_ASSIGN( colormap[i], r, g, b );
502 case PHOTOMETRIC_RGB:
503 if (pnmimage_tiff_cat.is_debug()) {
504 pnmimage_tiff_cat.debug(
false)
510 case PHOTOMETRIC_MASK:
511 pnmimage_tiff_cat.error()
512 <<
"Don't know how to handle TIFF image with PHOTOMETRIC_MASK.\n";
516 case PHOTOMETRIC_DEPTH:
517 pnmimage_tiff_cat.error()
518 <<
"Don't know how to handle TIFF image with PHOTOMETRIC_DEPTH.\n";
523 pnmimage_tiff_cat.error()
524 <<
"Unknown photometric " << photomet <<
" in TIFF image.\n";
532 if ( _maxval > PNM_MAXMAXVAL ) {
533 pnmimage_tiff_cat.error()
534 <<
"Cannot read TIFF file with maxval of " << _maxval <<
"\n";
553 PNMFileTypeTIFF::Reader::
555 if (tif !=
nullptr) {
565 bool PNMFileTypeTIFF::Reader::
566 is_floating_point() {
567 return (sample_format == SAMPLEFORMAT_IEEEFP);
574 bool PNMFileTypeTIFF::Reader::
580 int x_size = get_x_size();
581 int y_size = get_y_size();
582 int num_channels = get_num_channels();
584 pfm.
clear(x_size, y_size, num_channels);
588 for (
int yi = 0; yi < y_size; ++yi) {
589 float *row = &table[(yi * x_size) * _num_channels];
591 if (TIFFReadScanline(tif, row, yi, 0 ) < 0 ) {
592 pnmimage_tiff_cat.error()
593 <<
"failed a scanline read on row " << yi <<
"\n";
609 bool PNMFileTypeTIFF::Reader::
610 supports_read_row()
const {
620 bool PNMFileTypeTIFF::Reader::
621 read_row(
xel *row_data, xelval *alpha_data,
int x_size,
int) {
626 size_t scanline_size = (size_t)TIFFScanlineSize(tif);
627 unsigned char *buf = (
unsigned char*) alloca(scanline_size);
633 if ( TIFFReadScanline( tif, buf, current_row, 0 ) < 0 ) {
634 pnmimage_tiff_cat.error()
635 <<
"Bad data read on line " << current_row <<
" of TIFF image.\n";
639 unsigned char *buf_ptr = buf;
646 xelval (PNMFileTypeTIFF::Reader::*next_sample)(
unsigned char *&buf_ptr,
int &bits_left)
const;
649 next_sample = &PNMFileTypeTIFF::Reader::next_sample_lt_8;
651 }
else if (bps == 8) {
652 next_sample = &PNMFileTypeTIFF::Reader::next_sample_8;
654 }
else if (bps == 16) {
655 next_sample = &PNMFileTypeTIFF::Reader::next_sample_16;
657 }
else if (bps == 32) {
660 next_sample = &PNMFileTypeTIFF::Reader::next_sample_32;
663 next_sample = &PNMFileTypeTIFF::Reader::next_sample_general;
666 switch ( photomet ) {
667 case PHOTOMETRIC_MINISBLACK:
668 for ( col = 0; col < x_size; ++col )
670 sample = (this->*next_sample)(buf_ptr, bits_left);
673 for (s = 1; s < spp; s++) {
674 sample = (this->*next_sample)(buf_ptr, bits_left);
675 if (s == unassoc_alpha_sample) {
676 alpha_data[col] = sample;
678 }
else if (s == assoc_alpha_sample) {
679 alpha_data[col] = sample;
681 gray = (xelval)((
float)gray * _maxval / (float)sample);
685 PPM_PUTB(row_data[col], gray);
689 case PHOTOMETRIC_MINISWHITE:
690 for ( col = 0; col < x_size; ++col )
692 sample = (this->*next_sample)(buf_ptr, bits_left);
693 gray = _maxval - sample;
694 for (s = 1; s < spp; s++) {
695 sample = (this->*next_sample)(buf_ptr, bits_left);
696 sample = _maxval - sample;
698 if (s == unassoc_alpha_sample) {
699 alpha_data[col] = sample;
701 }
else if (s == assoc_alpha_sample) {
702 alpha_data[col] = sample;
704 gray = (xelval)((
float)gray * _maxval / (float)sample);
709 PPM_PUTB(row_data[col], gray);
713 case PHOTOMETRIC_PALETTE:
714 for ( col = 0; col < x_size; ++col )
716 sample = (this->*next_sample)(buf_ptr, bits_left);
717 row_data[col] = colormap[sample];
719 for (s = 1; s < spp; s++) {
720 sample = (this->*next_sample)(buf_ptr, bits_left);
721 if (s == unassoc_alpha_sample) {
722 alpha_data[col] = sample;
724 }
else if (s == assoc_alpha_sample) {
725 alpha_data[col] = sample;
727 r = PPM_GETR(row_data[col]);
728 g = PPM_GETG(row_data[col]);
729 b = PPM_GETB(row_data[col]);
730 r = (xelval)((
float)r * _maxval / (float)sample);
731 g = (xelval)((
float)g * _maxval / (float)sample);
732 b = (xelval)((
float)b * _maxval / (float)sample);
733 PPM_ASSIGN(row_data[col], r, g, b);
740 case PHOTOMETRIC_RGB:
741 for ( col = 0; col < x_size; ++col ) {
742 sample = (this->*next_sample)(buf_ptr, bits_left);
744 sample = (this->*next_sample)(buf_ptr, bits_left);
746 sample = (this->*next_sample)(buf_ptr, bits_left);
749 for (s = 3; s < spp; s++) {
750 sample = (this->*next_sample)(buf_ptr, bits_left);
751 if (s == unassoc_alpha_sample) {
752 alpha_data[col] = sample;
754 }
else if (s == assoc_alpha_sample) {
755 alpha_data[col] = sample;
757 r = (xelval)((
float)r * _maxval / (float)sample);
758 g = (xelval)((
float)g * _maxval / (float)sample);
759 b = (xelval)((
float)b * _maxval / (float)sample);
764 PPM_ASSIGN(row_data[col], r, g, b);
769 pnmimage_tiff_cat.error()
770 <<
"Internal error: unsupported photometric " << photomet <<
"\n";
774 nassertr(buf_ptr <= buf + scanline_size,
false);
783 xelval PNMFileTypeTIFF::Reader::
784 next_sample_lt_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
785 if (bits_left == 0) {
791 return (*buf_ptr >> bits_left) & _maxval;
797 xelval PNMFileTypeTIFF::Reader::
798 next_sample_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
806 xelval PNMFileTypeTIFF::Reader::
807 next_sample_16(
unsigned char *&buf_ptr,
int &bits_left)
const {
810 unsigned short result = *(
unsigned short *)buf_ptr;
819 xelval PNMFileTypeTIFF::Reader::
820 next_sample_32(
unsigned char *&buf_ptr,
int &bits_left)
const {
823 unsigned long result = *(
unsigned long *)buf_ptr;
825 return (xelval)result;
832 xelval PNMFileTypeTIFF::Reader::
833 next_sample_general(
unsigned char *&buf_ptr,
int &bits_left)
const {
834 unsigned int result = 0;
835 int bits_needed = bps;
837 while (bits_needed > 0) {
838 nassertr(bits_left >= 0, 0);
839 if (bits_left == 0) {
844 if (bits_needed <= bits_left) {
845 bits_left -= bits_needed;
846 unsigned int mask = (1 << bits_needed) - 1;
847 result |= ((*buf_ptr) >> bits_left) & mask;
851 bits_needed -= bits_left;
852 unsigned int mask = (1 << bits_left) - 1;
853 result |= ((*buf_ptr) & mask) << bits_needed;
865 PNMFileTypeTIFF::Writer::
866 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
876 bool PNMFileTypeTIFF::Writer::
877 supports_floating_point() {
886 bool PNMFileTypeTIFF::Writer::
895 bool PNMFileTypeTIFF::Writer::
896 write_pfm(
const PfmFile &pfm) {
900 tif = TIFFClientOpen(
"TIFF file",
"w",
902 ostream_dont_read, ostream_write,
903 (TIFFSeekProc)ostream_seek,
904 iostream_dont_close, ostream_size,
905 iostream_map, iostream_unmap);
906 if (tif ==
nullptr) {
915 if (num_channels >= 3) {
916 photometric = PHOTOMETRIC_RGB;
920 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, x_size);
921 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, y_size);
922 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
923 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
924 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
925 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
926 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
927 TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION,
"Generated via pnmimage.\n" );
928 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, num_channels);
929 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
931 const vector_float &table = pfm.
get_table();
932 for (
int yi = 0; yi < y_size; ++yi) {
933 const float *row = &table[(yi * x_size) * _num_channels];
935 if (TIFFWriteScanline(tif, (tdata_t)row, yi, 0 ) < 0) {
936 pnmimage_tiff_cat.error()
937 <<
"failed a scanline write on row " << yi <<
"\n";
964 int PNMFileTypeTIFF::Writer::
965 write_data(
xel *array, xelval *alpha) {
969 red[TIFF_COLORMAP_MAXCOLORS],
970 grn[TIFF_COLORMAP_MAXCOLORS],
971 blu[TIFF_COLORMAP_MAXCOLORS];
974 int grayscale =
false;
976 short photometric = 0;
977 short samplesperpixel = 0;
978 unsigned short extra_samples[1] = { EXTRASAMPLE_UNASSALPHA };
979 short bitspersample = 0;
984 switch ( get_color_type() ) {
992 chv = ppm_computecolorhist( (
pixel **)&array, _x_size * _y_size, 1,
994 if ( chv ==
nullptr ) {
995 pnmimage_tiff_cat.debug()
996 << colors <<
" colors found; too many for a palette.\n" 997 <<
"Writing a 24-bit RGB file.\n";
1000 pnmimage_tiff_cat.debug()
1001 << colors <<
" colors found; writing an 8-bit palette file.\n";
1003 for ( i = 0; i < colors; ++i ) {
1006 r = PPM_GETR( chv[i].color );
1007 g = PPM_GETG( chv[i].color );
1008 b = PPM_GETB( chv[i].color );
1009 if ( r != g || g != b ) {
1017 case CT_two_channel:
1018 case CT_four_channel:
1033 tif = TIFFClientOpen(
"TIFF file",
"w",
1035 ostream_dont_read, ostream_write,
1036 (TIFFSeekProc)ostream_seek,
1037 iostream_dont_close, ostream_size,
1038 iostream_map, iostream_unmap);
1039 if ( tif ==
nullptr ) {
1044 switch ( get_color_type() ) {
1046 case CT_four_channel:
1047 if ( chv ==
nullptr ) {
1048 samplesperpixel = _num_channels;
1050 photometric = PHOTOMETRIC_RGB;
1051 bytesperrow = _x_size * samplesperpixel;
1052 }
else if ( grayscale ) {
1053 samplesperpixel = 1;
1055 photometric = PHOTOMETRIC_MINISBLACK;
1056 i = 8 / bitspersample;
1057 bytesperrow = ( _x_size + i - 1 ) / i;
1059 samplesperpixel = 1;
1061 photometric = PHOTOMETRIC_PALETTE;
1062 bytesperrow = _x_size;
1067 case CT_two_channel:
1068 samplesperpixel = _num_channels;
1070 photometric = PHOTOMETRIC_MINISBLACK;
1071 i = 8 / bitspersample;
1072 bytesperrow = ( _x_size + i - 1 ) / i;
1079 buf = (
unsigned char*) malloc( bytesperrow );
1080 if ( buf ==
nullptr ) {
1081 pnmimage_tiff_cat.error()
1082 <<
"Can't allocate memory for row buffer\n";
1087 TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, _x_size );
1088 TIFFSetField( tif, TIFFTAG_IMAGELENGTH, _y_size );
1089 TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT );
1090 TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample );
1091 TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
1092 TIFFSetField( tif, TIFFTAG_COMPRESSION, tiff_compression );
1093 if ( tiff_compression == COMPRESSION_CCITTFAX3 && tiff_g3options != 0 )
1094 TIFFSetField( tif, TIFFTAG_GROUP3OPTIONS, tiff_g3options );
1095 if ( tiff_compression == COMPRESSION_LZW && tiff_predictor != 0 )
1096 TIFFSetField( tif, TIFFTAG_PREDICTOR, tiff_predictor );
1097 TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
1098 TIFFSetField( tif, TIFFTAG_FILLORDER, tiff_fillorder );
1100 TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION,
1101 "Generated via pnmimage.\n" );
1102 TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel );
1104 TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
1106 TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
1108 if ( chv ==
nullptr ) {
1112 for ( i = 0; i < colors; ++i ) {
1113 red[i] = (
unsigned short) (PPM_GETR( chv[i].color ) * 65535L / _maxval);
1114 grn[i] = (
unsigned short) (PPM_GETG( chv[i].color ) * 65535L / _maxval);
1115 blu[i] = (
unsigned short) (PPM_GETB( chv[i].color ) * 65535L / _maxval);
1117 TIFFSetField( tif, TIFFTAG_COLORMAP, red, grn, blu );
1120 cht = ppm_colorhisttocolorhash( chv, colors );
1121 ppm_freecolorhist( chv );
1125 for ( row = 0; row < _y_size; ++row ) {
1126 xel *row_data = array + row*_x_size;
1127 xelval *alpha_data = alpha + row*_x_size;
1129 if ( !is_grayscale() && ! grayscale ) {
1130 if ( cht ==
nullptr ) {
1132 for ( col = 0; col < _x_size; ++col ) {
1133 *tP++ = (
unsigned char)(255 * PPM_GETR(row_data[col]) / _maxval);
1134 *tP++ = (
unsigned char)(255 * PPM_GETG(row_data[col]) / _maxval);
1135 *tP++ = (
unsigned char)(255 * PPM_GETB(row_data[col]) / _maxval);
1136 if (samplesperpixel==4) {
1137 *tP++ = (
unsigned char)(255 * alpha_data[col] / _maxval);
1142 for ( col = 0; col < _x_size; ++col ) {
1145 s = ppm_lookupcolor( cht, (
pixel *)(&row_data[col]) );
1147 pnmimage_tiff_cat.error()
1148 <<
"Internal error: color not found?!? row=" << row
1149 <<
" col=" << col <<
"\n";
1152 *tP++ = (
unsigned char) s;
1153 if (samplesperpixel==2) {
1154 *tP++ = (
unsigned char)(255 * alpha_data[col] / _maxval);
1159 xelval bigger_maxval;
1165 bitshift = 8 - bitspersample;
1168 for ( col = 0; col < _x_size; ++col ) {
1169 s = PPM_GETB(row_data[col]);
1170 if ( _maxval != bigger_maxval )
1171 s = (xelval)((
long) s * bigger_maxval / _maxval);
1172 byte |= s << bitshift;
1173 bitshift -= bitspersample;
1174 if ( bitshift < 0 ) {
1176 bitshift = 8 - bitspersample;
1180 if ( bitshift != 8 - bitspersample )
1184 if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 ) {
1185 pnmimage_tiff_cat.error()
1186 <<
"failed a scanline write on row " << row <<
"\n";
1190 TIFFFlushData( tif );
1201 void PNMFileTypeTIFF::
1202 install_error_handlers() {
1203 if (!_installed_error_handlers) {
1204 TIFFSetWarningHandler(tiff_warning);
1205 TIFFSetErrorHandler(tiff_error);
1206 _installed_error_handlers =
true;
1214 void PNMFileTypeTIFF::
1215 tiff_warning(
const char *,
const char *format, va_list ap) {
1216 static const int buffer_size = 1024;
1217 char buffer[buffer_size];
1218 #if defined(WIN32_VC) || defined(WIN64_VC) 1219 vsprintf(buffer, format, ap);
1221 vsnprintf(buffer, buffer_size, format, ap);
1225 pnmimage_tiff_cat.warning()
1233 void PNMFileTypeTIFF::
1234 tiff_error(
const char *module,
const char *format, va_list ap) {
1235 static const int buffer_size = 1024;
1236 char buffer[buffer_size];
1237 #if defined(WIN32_VC) || defined(WIN64_VC) 1238 vsprintf(buffer, format, ap);
1240 vsnprintf(buffer, buffer_size, format, ap);
1244 pnmimage_tiff_cat.error()
1252 void PNMFileTypeTIFF::
1253 register_with_read_factory() {
1255 register_factory(get_class_type(), make_PNMFileTypeTIFF);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int pm_maxvaltobits(int maxval)
Returns the number of bits sufficient to hold the indicated maxval value.
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...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
void swap_table(vector_float &table)
This is a very low-level function that completely exchanges the PfmFile's internal table of floating-...
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
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.
const vector_float & get_table() const
This is a very low-level function that returns a read-only reference to the internal table of floatin...
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
int pm_bitstomaxval(int bits)
Returns the highest maxval that can be represented in the indicated number of bits.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear()
Eliminates all data in the file.