27#define uint8 tiff_uint8
28#define int32 tiff_int32
29#define uint32 tiff_uint32
41static const char *
const extensions_tiff[] = {
44static const int num_extensions_tiff =
sizeof(extensions_tiff) /
sizeof(
const char *);
51unsigned short tiff_compression = COMPRESSION_NONE;
66long tiff_g3options = 0;
74unsigned short tiff_fillorder = FILLORDER_MSB2LSB;
80short tiff_predictor = 0;
84#ifndef PHOTOMETRIC_DEPTH
85#define PHOTOMETRIC_DEPTH 32768
91istream_read(thandle_t fd, tdata_t buf, tsize_t size) {
92 istream *in = (istream *)fd;
93 in->read((
char *)buf, size);
99ostream_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;
107ostream_dont_read(thandle_t, tdata_t, tsize_t) {
114istream_dont_write(thandle_t, tdata_t, tsize_t) {
121istream_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";
153ostream_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";
185iostream_dont_close(thandle_t) {
191istream_size(thandle_t fd) {
192 istream *in = (istream *)fd;
193 in->seekg(0, ios::end);
198ostream_size(thandle_t fd) {
199 ostream *out = (ostream *)fd;
200 out->seekp(0, ios::end);
205iostream_map(thandle_t, tdata_t*, toff_t*) {
210iostream_unmap(thandle_t, tdata_t, toff_t) {
213bool PNMFileTypeTIFF::_installed_error_handlers =
false;
223 if (pnmimage_tiff_cat->is_debug()) {
224 pnmimage_tiff_cat->debug()
225 << TIFFGetVersion() <<
"\n";
232string PNMFileTypeTIFF::
242get_num_extensions()
const {
243 return num_extensions_tiff;
250string PNMFileTypeTIFF::
251get_extension(
int n)
const {
252 nassertr(n >= 0 && n < num_extensions_tiff,
string());
253 return extensions_tiff[n];
260string PNMFileTypeTIFF::
261get_suggested_extension()
const {
269bool PNMFileTypeTIFF::
270has_magic_number()
const {
279bool PNMFileTypeTIFF::
280matches_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);
294make_reader(istream *file,
bool owns_file,
const string &magic_number) {
296 install_error_handlers();
297 return new Reader(
this, file, owns_file, magic_number);
306make_writer(ostream *file,
bool owns_file) {
308 install_error_handlers();
309 return new Writer(
this, file, owns_file);
315PNMFileTypeTIFF::Reader::
316Reader(
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";
540 if (grayscale && !is_grayscale()) {
541 _num_channels = (has_alpha()) ? 2 : 1;
542 }
else if (!grayscale && is_grayscale()) {
543 _num_channels = (has_alpha()) ? 4 : 3;
553PNMFileTypeTIFF::Reader::
555 if (tif !=
nullptr) {
565bool PNMFileTypeTIFF::Reader::
567 return (sample_format == SAMPLEFORMAT_IEEEFP);
574bool 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";
609bool PNMFileTypeTIFF::Reader::
610supports_read_row()
const {
620bool PNMFileTypeTIFF::Reader::
621read_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);
783xelval PNMFileTypeTIFF::Reader::
784next_sample_lt_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
785 if (bits_left == 0) {
791 return (*buf_ptr >> bits_left) & _maxval;
797xelval PNMFileTypeTIFF::Reader::
798next_sample_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
806xelval PNMFileTypeTIFF::Reader::
807next_sample_16(
unsigned char *&buf_ptr,
int &bits_left)
const {
810 unsigned short result = *(
unsigned short *)buf_ptr;
819xelval PNMFileTypeTIFF::Reader::
820next_sample_32(
unsigned char *&buf_ptr,
int &bits_left)
const {
823 unsigned long result = *(
unsigned long *)buf_ptr;
825 return (xelval)result;
832xelval PNMFileTypeTIFF::Reader::
833next_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;
865PNMFileTypeTIFF::Writer::
866Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
876bool PNMFileTypeTIFF::Writer::
877supports_floating_point() {
886bool PNMFileTypeTIFF::Writer::
895bool PNMFileTypeTIFF::Writer::
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";
964int PNMFileTypeTIFF::Writer::
965write_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*) alloca( 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";
1150 if (cht !=
nullptr) {
1151 ppm_freecolorhash(cht);
1155 *tP++ = (
unsigned char) s;
1156 if (samplesperpixel==2) {
1157 *tP++ = (
unsigned char)(255 * alpha_data[col] / _maxval);
1162 xelval bigger_maxval;
1168 bitshift = 8 - bitspersample;
1171 for ( col = 0; col < _x_size; ++col ) {
1172 s = PPM_GETB(row_data[col]);
1173 if ( _maxval != bigger_maxval )
1174 s = (xelval)((
long) s * bigger_maxval / _maxval);
1175 byte |= s << bitshift;
1176 bitshift -= bitspersample;
1177 if ( bitshift < 0 ) {
1179 bitshift = 8 - bitspersample;
1183 if ( bitshift != 8 - bitspersample )
1187 if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 ) {
1188 pnmimage_tiff_cat.error()
1189 <<
"failed a scanline write on row " << row <<
"\n";
1193 TIFFFlushData( tif );
1196 if (cht !=
nullptr) {
1197 ppm_freecolorhash(cht);
1208void PNMFileTypeTIFF::
1209install_error_handlers() {
1210 if (!_installed_error_handlers) {
1211 TIFFSetWarningHandler(tiff_warning);
1212 TIFFSetErrorHandler(tiff_error);
1213 _installed_error_handlers =
true;
1221void PNMFileTypeTIFF::
1222tiff_warning(
const char *,
const char *format, va_list ap) {
1223 static const int buffer_size = 1024;
1224 char buffer[buffer_size];
1225#if defined(WIN32_VC) || defined(WIN64_VC)
1226 vsprintf(buffer, format, ap);
1228 vsnprintf(buffer, buffer_size, format, ap);
1232 pnmimage_tiff_cat.warning()
1240void PNMFileTypeTIFF::
1241tiff_error(
const char *module,
const char *format, va_list ap) {
1242 static const int buffer_size = 1024;
1243 char buffer[buffer_size];
1244#if defined(WIN32_VC) || defined(WIN64_VC)
1245 vsprintf(buffer, format, ap);
1247 vsnprintf(buffer, buffer_size, format, ap);
1251 pnmimage_tiff_cat.error()
1259void PNMFileTypeTIFF::
1260register_with_read_factory() {
1262 register_factory(get_class_type(), make_PNMFileTypeTIFF);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
This is the base class of a family of classes that represent particular image file types that PNMImag...
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.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
void swap_table(vector_float &table)
This is a very low-level function that completely exchanges the PfmFile's internal table of floating-...
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...
void clear()
Eliminates all data in the file.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
int pm_bitstomaxval(int bits)
Returns the highest maxval that can be represented in the indicated number of bits.