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