15 #include "pnmFileTypeTIFF.h" 19 #include "config_pnmimagetypes.h" 21 #include "pnmFileTypeRegistry.h" 22 #include "bamReader.h" 27 #define int8 tiff_int8 28 #define uint8 tiff_uint8 29 #define int32 tiff_int32 30 #define uint32 tiff_uint32 37 static const char *
const extensions_tiff[] = {
40 static const int num_extensions_tiff =
sizeof(extensions_tiff) /
sizeof(
const char *);
47 unsigned short tiff_compression = COMPRESSION_NONE;
62 long tiff_g3options = 0;
70 unsigned short tiff_fillorder = FILLORDER_MSB2LSB;
76 short tiff_predictor = 0;
80 #ifndef PHOTOMETRIC_DEPTH 81 #define PHOTOMETRIC_DEPTH 32768 87 istream_read(thandle_t fd, tdata_t buf, tsize_t size) {
88 istream *in = (istream *)fd;
89 in->read((
char *)buf, size);
95 ostream_write(thandle_t fd, tdata_t buf, tsize_t size) {
96 ostream *out = (ostream *)fd;
97 out->write((
char *)buf, size);
99 return out->fail() ? (tsize_t)0 : size;
103 ostream_dont_read(thandle_t, tdata_t, tsize_t) {
110 istream_dont_write(thandle_t, tdata_t, tsize_t) {
117 istream_seek(thandle_t fd, toff_t off,
int whence) {
118 istream *in = (istream *)fd;
140 if (pnmimage_tiff_cat->is_spam()) {
141 pnmimage_tiff_cat->spam()
142 <<
"istream_seek(" << (
void *)in <<
", " << off <<
", " 143 << whence <<
"), result = " << in->tellg() <<
"\n";
149 ostream_seek(thandle_t fd, toff_t off,
int whence) {
150 ostream *out = (ostream *)fd;
170 out->seekp(off, dir);
172 if (pnmimage_tiff_cat->is_spam()) {
173 pnmimage_tiff_cat->spam()
174 <<
"ostream_seek(" << (
void *)out <<
", " << off <<
", " 175 << whence <<
"), result = " << out->tellp() <<
"\n";
181 iostream_dont_close(thandle_t) {
187 istream_size(thandle_t fd) {
188 istream *in = (istream *)fd;
189 in->seekg(0, ios::end);
194 ostream_size(thandle_t fd) {
195 ostream *out = (ostream *)fd;
196 out->seekp(0, ios::end);
201 iostream_map(thandle_t, tdata_t*, toff_t*) {
206 iostream_unmap(thandle_t, tdata_t, toff_t) {
209 bool PNMFileTypeTIFF::_installed_error_handlers =
false;
221 if (pnmimage_tiff_cat->is_debug()) {
222 pnmimage_tiff_cat->debug()
223 << TIFFGetVersion() <<
"\n";
232 string PNMFileTypeTIFF::
243 int PNMFileTypeTIFF::
244 get_num_extensions()
const {
245 return num_extensions_tiff;
255 string PNMFileTypeTIFF::
256 get_extension(
int n)
const {
257 nassertr(n >= 0 && n < num_extensions_tiff,
string());
258 return extensions_tiff[n];
268 string PNMFileTypeTIFF::
269 get_suggested_extension()
const {
279 bool PNMFileTypeTIFF::
280 has_magic_number()
const {
291 bool PNMFileTypeTIFF::
292 matches_magic_number(
const string &magic_number)
const {
293 nassertr(magic_number.size() >= 2,
false);
295 ((
unsigned char)magic_number[0] << 8) |
296 ((
unsigned char)magic_number[1]);
297 return (mn == TIFF_BIGENDIAN || mn == TIFF_LITTLEENDIAN);
308 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
310 install_error_handlers();
311 return new Reader(
this, file, owns_file, magic_number);
322 make_writer(ostream *file,
bool owns_file) {
324 install_error_handlers();
325 return new Writer(
this, file, owns_file);
333 PNMFileTypeTIFF::Reader::
334 Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
337 bool grayscale =
false;
340 unsigned short* redcolormap;
341 unsigned short* greencolormap;
342 unsigned short* bluecolormap;
345 for (string::reverse_iterator mi = magic_number.rbegin();
346 mi != magic_number.rend();
351 pnmimage_tiff_cat.error()
352 <<
"Unable to put back magic number.\n";
357 tif = TIFFClientOpen(
"TIFF file",
"r",
359 istream_read, istream_dont_write,
360 (TIFFSeekProc)istream_seek,
361 iostream_dont_close, istream_size,
362 iostream_map, iostream_unmap);
370 if ( ! TIFFGetField( tif, TIFFTAG_SAMPLEFORMAT, &sample_format ) )
371 sample_format = SAMPLEFORMAT_UINT;
372 if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) )
374 if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) )
377 if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) ) {
378 pnmimage_tiff_cat.error()
379 <<
"Error getting photometric from TIFF file.\n";
382 }
else if (sample_format == SAMPLEFORMAT_IEEEFP) {
385 pnmimage_tiff_cat.error()
386 <<
"Can only read 32-bit float TIFF files, not " << bps <<
"-bit.\n";
390 }
else if (sample_format != SAMPLEFORMAT_UINT) {
392 pnmimage_tiff_cat.error()
393 <<
"Can't understand sample format\n";
399 unsigned short num_extra_samples;
400 unsigned short *extra_samples = NULL;
402 if (!TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &num_extra_samples,
404 num_extra_samples = 0;
406 _num_channels = spp - num_extra_samples;
407 unassoc_alpha_sample = 0;
408 assoc_alpha_sample = 0;
410 if (_num_channels == 1 || _num_channels == 3) {
413 bool got_alpha =
false;
414 for (
unsigned short s = 0; s < num_extra_samples && !got_alpha; s++) {
415 if (extra_samples[s] == EXTRASAMPLE_UNASSALPHA) {
416 unassoc_alpha_sample = s + _num_channels;
420 }
else if (extra_samples[s] == EXTRASAMPLE_ASSOCALPHA) {
421 assoc_alpha_sample = s + _num_channels;
431 if (!got_alpha && num_extra_samples == 1 &&
432 extra_samples[0] == EXTRASAMPLE_UNSPECIFIED) {
433 unassoc_alpha_sample = _num_channels;
437 }
else if ((_num_channels == 2 || _num_channels == 4) && num_extra_samples == 0) {
442 unassoc_alpha_sample = _num_channels - 1;
443 if (pnmimage_tiff_cat.is_debug()) {
444 pnmimage_tiff_cat.debug()
445 <<
"Assuming last channel of " << spp
446 <<
"-color image is meant to represent alpha.\n";
450 pnmimage_tiff_cat.error()
451 <<
"Cannot handle " << spp <<
"-color image (with " 452 << num_extra_samples <<
" extra channels).\n";
458 (void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &_x_size );
459 (void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &_y_size );
461 if (pnmimage_tiff_cat.is_debug()) {
462 pnmimage_tiff_cat.debug()
463 <<
"Reading TIFF image: " << _x_size <<
" x " << _y_size <<
"\n" 464 << bps <<
" bits/sample, " << spp <<
" samples/pixel\n";
467 _maxval = ( 1 << bps ) - 1;
468 if ( _maxval == 1 && _num_channels == 1 ) {
469 if (pnmimage_tiff_cat.is_debug()) {
470 pnmimage_tiff_cat.debug(
false)
475 switch ( photomet ) {
476 case PHOTOMETRIC_MINISBLACK:
477 if (pnmimage_tiff_cat.is_debug()) {
478 pnmimage_tiff_cat.debug(
false)
479 << _maxval + 1 <<
" graylevels (min is black)\n";
484 case PHOTOMETRIC_MINISWHITE:
485 if (pnmimage_tiff_cat.is_debug()) {
486 pnmimage_tiff_cat.debug(
false)
487 << _maxval + 1 <<
" graylevels (min is white)\n";
492 case PHOTOMETRIC_PALETTE:
493 if (pnmimage_tiff_cat.is_debug()) {
494 pnmimage_tiff_cat.debug(
false)
497 if ( ! TIFFGetField( tif, TIFFTAG_COLORMAP, &redcolormap, &greencolormap, &bluecolormap ) ) {
498 pnmimage_tiff_cat.error()
499 <<
"Error getting colormap from TIFF file.\n";
502 numcolors = _maxval + 1;
503 if ( numcolors > TIFF_COLORMAP_MAXCOLORS ) {
504 pnmimage_tiff_cat.error()
505 <<
"Cannot read TIFF file with " << numcolors
506 <<
" in colormap; max supported is " << TIFF_COLORMAP_MAXCOLORS <<
"\n";
509 _maxval = PNM_MAXMAXVAL;
511 for ( i = 0; i < numcolors; ++i ) {
513 r = (xelval)(_maxval * (
double)(redcolormap[i] / 65535.0));
514 g = (xelval)(_maxval * (
double)(greencolormap[i] / 65535.0));
515 b = (xelval)(_maxval * (
double)(bluecolormap[i] / 65535.0));
516 PPM_ASSIGN( colormap[i], r, g, b );
522 case PHOTOMETRIC_RGB:
523 if (pnmimage_tiff_cat.is_debug()) {
524 pnmimage_tiff_cat.debug(
false)
530 case PHOTOMETRIC_MASK:
531 pnmimage_tiff_cat.error()
532 <<
"Don't know how to handle TIFF image with PHOTOMETRIC_MASK.\n";
536 case PHOTOMETRIC_DEPTH:
537 pnmimage_tiff_cat.error()
538 <<
"Don't know how to handle TIFF image with PHOTOMETRIC_DEPTH.\n";
543 pnmimage_tiff_cat.error()
544 <<
"Unknown photometric " << photomet <<
" in TIFF image.\n";
552 if ( _maxval > PNM_MAXMAXVAL ) {
553 pnmimage_tiff_cat.error()
554 <<
"Cannot read TIFF file with maxval of " << _maxval <<
"\n";
575 PNMFileTypeTIFF::Reader::
577 if (tif != (
struct tiff *)NULL) {
590 bool PNMFileTypeTIFF::Reader::
591 is_floating_point() {
592 return (sample_format == SAMPLEFORMAT_IEEEFP);
601 bool PNMFileTypeTIFF::Reader::
611 pfm.
clear(x_size, y_size, num_channels);
613 pfm.swap_table(table);
615 for (
int yi = 0; yi < y_size; ++yi) {
616 float *row = &table[(yi * x_size) * _num_channels];
618 if (TIFFReadScanline(tif, row, yi, 0 ) < 0 ) {
619 pnmimage_tiff_cat.error()
620 <<
"failed a scanline read on row " << yi <<
"\n";
621 pfm.swap_table(table);
626 pfm.swap_table(table);
640 bool PNMFileTypeTIFF::Reader::
641 supports_read_row()
const {
654 bool PNMFileTypeTIFF::Reader::
655 read_row(
xel *row_data, xelval *alpha_data,
int x_size,
int) {
660 size_t scanline_size = (size_t)TIFFScanlineSize(tif);
661 unsigned char *buf = (
unsigned char*) alloca(scanline_size);
667 if ( TIFFReadScanline( tif, buf, current_row, 0 ) < 0 ) {
668 pnmimage_tiff_cat.error()
669 <<
"Bad data read on line " << current_row <<
" of TIFF image.\n";
673 unsigned char *buf_ptr = buf;
680 xelval (PNMFileTypeTIFF::Reader::*next_sample)(
unsigned char *&buf_ptr,
int &bits_left)
const;
683 next_sample = &PNMFileTypeTIFF::Reader::next_sample_lt_8;
685 }
else if (bps == 8) {
686 next_sample = &PNMFileTypeTIFF::Reader::next_sample_8;
688 }
else if (bps == 16) {
689 next_sample = &PNMFileTypeTIFF::Reader::next_sample_16;
691 }
else if (bps == 32) {
694 next_sample = &PNMFileTypeTIFF::Reader::next_sample_32;
697 next_sample = &PNMFileTypeTIFF::Reader::next_sample_general;
700 switch ( photomet ) {
701 case PHOTOMETRIC_MINISBLACK:
702 for ( col = 0; col < x_size; ++col )
704 sample = (this->*next_sample)(buf_ptr, bits_left);
707 for (s = 1; s < spp; s++) {
708 sample = (this->*next_sample)(buf_ptr, bits_left);
709 if (s == unassoc_alpha_sample) {
710 alpha_data[col] = sample;
712 }
else if (s == assoc_alpha_sample) {
713 alpha_data[col] = sample;
715 gray = (xelval)((
float)gray * _maxval / (float)sample);
719 PPM_PUTB(row_data[col], gray);
723 case PHOTOMETRIC_MINISWHITE:
724 for ( col = 0; col < x_size; ++col )
726 sample = (this->*next_sample)(buf_ptr, bits_left);
727 gray = _maxval - sample;
728 for (s = 1; s < spp; s++) {
729 sample = (this->*next_sample)(buf_ptr, bits_left);
730 sample = _maxval - sample;
732 if (s == unassoc_alpha_sample) {
733 alpha_data[col] = sample;
735 }
else if (s == assoc_alpha_sample) {
736 alpha_data[col] = sample;
738 gray = (xelval)((
float)gray * _maxval / (float)sample);
743 PPM_PUTB(row_data[col], gray);
747 case PHOTOMETRIC_PALETTE:
748 for ( col = 0; col < x_size; ++col )
750 sample = (this->*next_sample)(buf_ptr, bits_left);
751 row_data[col] = colormap[sample];
753 for (s = 1; s < spp; s++) {
754 sample = (this->*next_sample)(buf_ptr, bits_left);
755 if (s == unassoc_alpha_sample) {
756 alpha_data[col] = sample;
758 }
else if (s == assoc_alpha_sample) {
759 alpha_data[col] = sample;
761 r = PPM_GETR(row_data[col]);
762 g = PPM_GETG(row_data[col]);
763 b = PPM_GETB(row_data[col]);
764 r = (xelval)((
float)r * _maxval / (float)sample);
765 g = (xelval)((
float)g * _maxval / (float)sample);
766 b = (xelval)((
float)b * _maxval / (float)sample);
767 PPM_ASSIGN(row_data[col], r, g, b);
774 case PHOTOMETRIC_RGB:
775 for ( col = 0; col < x_size; ++col ) {
776 sample = (this->*next_sample)(buf_ptr, bits_left);
778 sample = (this->*next_sample)(buf_ptr, bits_left);
780 sample = (this->*next_sample)(buf_ptr, bits_left);
783 for (s = 3; s < spp; s++) {
784 sample = (this->*next_sample)(buf_ptr, bits_left);
785 if (s == unassoc_alpha_sample) {
786 alpha_data[col] = sample;
788 }
else if (s == assoc_alpha_sample) {
789 alpha_data[col] = sample;
791 r = (xelval)((
float)r * _maxval / (float)sample);
792 g = (xelval)((
float)g * _maxval / (float)sample);
793 b = (xelval)((
float)b * _maxval / (float)sample);
798 PPM_ASSIGN(row_data[col], r, g, b);
803 pnmimage_tiff_cat.error()
804 <<
"Internal error: unsupported photometric " << photomet <<
"\n";
808 nassertr(buf_ptr <= buf + scanline_size,
false);
820 xelval PNMFileTypeTIFF::Reader::
821 next_sample_lt_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
822 if (bits_left == 0) {
828 return (*buf_ptr >> bits_left) & _maxval;
837 xelval PNMFileTypeTIFF::Reader::
838 next_sample_8(
unsigned char *&buf_ptr,
int &bits_left)
const {
848 xelval PNMFileTypeTIFF::Reader::
849 next_sample_16(
unsigned char *&buf_ptr,
int &bits_left)
const {
852 unsigned short result = *(
unsigned short *)buf_ptr;
863 xelval PNMFileTypeTIFF::Reader::
864 next_sample_32(
unsigned char *&buf_ptr,
int &bits_left)
const {
867 unsigned long result = *(
unsigned long *)buf_ptr;
869 return (xelval)result;
879 xelval PNMFileTypeTIFF::Reader::
880 next_sample_general(
unsigned char *&buf_ptr,
int &bits_left)
const {
881 unsigned int result = 0;
882 int bits_needed = bps;
884 while (bits_needed > 0) {
885 nassertr(bits_left >= 0, 0);
886 if (bits_left == 0) {
891 if (bits_needed <= bits_left) {
892 bits_left -= bits_needed;
893 unsigned int mask = (1 << bits_needed) - 1;
894 result |= ((*buf_ptr) >> bits_left) & mask;
898 bits_needed -= bits_left;
899 unsigned int mask = (1 << bits_left) - 1;
900 result |= ((*buf_ptr) & mask) << bits_needed;
914 PNMFileTypeTIFF::Writer::
915 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
928 bool PNMFileTypeTIFF::Writer::
929 supports_floating_point() {
941 bool PNMFileTypeTIFF::Writer::
952 bool PNMFileTypeTIFF::Writer::
953 write_pfm(
const PfmFile &pfm) {
957 tif = TIFFClientOpen(
"TIFF file",
"w",
959 ostream_dont_read, ostream_write,
960 (TIFFSeekProc)ostream_seek,
961 iostream_dont_close, ostream_size,
962 iostream_map, iostream_unmap);
972 if (num_channels >= 3) {
973 photometric = PHOTOMETRIC_RGB;
977 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, x_size);
978 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, y_size);
979 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
980 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
981 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
982 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
983 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
984 TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION,
"Generated via pnmimage.\n" );
985 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, num_channels);
986 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
988 const vector_float &table = pfm.get_table();
989 for (
int yi = 0; yi < y_size; ++yi) {
990 const float *row = &table[(yi * x_size) * _num_channels];
992 if (TIFFWriteScanline(tif, (tdata_t)row, yi, 0 ) < 0) {
993 pnmimage_tiff_cat.error()
994 <<
"failed a scanline write on row " << yi <<
"\n";
1027 int PNMFileTypeTIFF::Writer::
1028 write_data(
xel *array, xelval *alpha) {
1032 red[TIFF_COLORMAP_MAXCOLORS],
1033 grn[TIFF_COLORMAP_MAXCOLORS],
1034 blu[TIFF_COLORMAP_MAXCOLORS];
1037 int grayscale =
false;
1039 short photometric = 0;
1040 short samplesperpixel = 0;
1041 unsigned short extra_samples[1] = { EXTRASAMPLE_UNASSALPHA };
1042 short bitspersample = 0;
1043 int bytesperrow = 0;
1055 chv = ppm_computecolorhist( (
pixel **)&array, _x_size * _y_size, 1,
1058 pnmimage_tiff_cat.debug()
1059 << colors <<
" colors found; too many for a palette.\n" 1060 <<
"Writing a 24-bit RGB file.\n";
1063 pnmimage_tiff_cat.debug()
1064 << colors <<
" colors found; writing an 8-bit palette file.\n";
1066 for ( i = 0; i < colors; ++i ) {
1069 r = PPM_GETR( chv[i].color );
1070 g = PPM_GETG( chv[i].color );
1071 b = PPM_GETB( chv[i].color );
1072 if ( r != g || g != b ) {
1080 case CT_two_channel:
1081 case CT_four_channel:
1096 tif = TIFFClientOpen(
"TIFF file",
"w",
1098 ostream_dont_read, ostream_write,
1099 (TIFFSeekProc)ostream_seek,
1100 iostream_dont_close, ostream_size,
1101 iostream_map, iostream_unmap);
1102 if ( tif == NULL ) {
1109 case CT_four_channel:
1111 samplesperpixel = _num_channels;
1113 photometric = PHOTOMETRIC_RGB;
1114 bytesperrow = _x_size * samplesperpixel;
1115 }
else if ( grayscale ) {
1116 samplesperpixel = 1;
1117 bitspersample = min(8, pm_maxvaltobits(_maxval));
1118 photometric = PHOTOMETRIC_MINISBLACK;
1119 i = 8 / bitspersample;
1120 bytesperrow = ( _x_size + i - 1 ) / i;
1122 samplesperpixel = 1;
1123 bitspersample = min(8, pm_maxvaltobits(_maxval));
1124 photometric = PHOTOMETRIC_PALETTE;
1125 bytesperrow = _x_size;
1130 case CT_two_channel:
1131 samplesperpixel = _num_channels;
1132 bitspersample = pm_maxvaltobits( _maxval );
1133 photometric = PHOTOMETRIC_MINISBLACK;
1134 i = 8 / bitspersample;
1135 bytesperrow = ( _x_size + i - 1 ) / i;
1142 buf = (
unsigned char*) malloc( bytesperrow );
1143 if ( buf == (
unsigned char*) 0 ) {
1144 pnmimage_tiff_cat.error()
1145 <<
"Can't allocate memory for row buffer\n";
1150 TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, _x_size );
1151 TIFFSetField( tif, TIFFTAG_IMAGELENGTH, _y_size );
1152 TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT );
1153 TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample );
1154 TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
1155 TIFFSetField( tif, TIFFTAG_COMPRESSION, tiff_compression );
1156 if ( tiff_compression == COMPRESSION_CCITTFAX3 && tiff_g3options != 0 )
1157 TIFFSetField( tif, TIFFTAG_GROUP3OPTIONS, tiff_g3options );
1158 if ( tiff_compression == COMPRESSION_LZW && tiff_predictor != 0 )
1159 TIFFSetField( tif, TIFFTAG_PREDICTOR, tiff_predictor );
1160 TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
1161 TIFFSetField( tif, TIFFTAG_FILLORDER, tiff_fillorder );
1163 TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION,
1164 "Generated via pnmimage.\n" );
1165 TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel );
1167 TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
1169 TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
1175 for ( i = 0; i < colors; ++i ) {
1176 red[i] = (
unsigned short) (PPM_GETR( chv[i].color ) * 65535L / _maxval);
1177 grn[i] = (
unsigned short) (PPM_GETG( chv[i].color ) * 65535L / _maxval);
1178 blu[i] = (
unsigned short) (PPM_GETB( chv[i].color ) * 65535L / _maxval);
1180 TIFFSetField( tif, TIFFTAG_COLORMAP, red, grn, blu );
1183 cht = ppm_colorhisttocolorhash( chv, colors );
1184 ppm_freecolorhist( chv );
1188 for ( row = 0; row < _y_size; ++row ) {
1189 xel *row_data = array + row*_x_size;
1190 xelval *alpha_data = alpha + row*_x_size;
1195 for ( col = 0; col < _x_size; ++col ) {
1196 *tP++ = (
unsigned char)(255 * PPM_GETR(row_data[col]) / _maxval);
1197 *tP++ = (
unsigned char)(255 * PPM_GETG(row_data[col]) / _maxval);
1198 *tP++ = (
unsigned char)(255 * PPM_GETB(row_data[col]) / _maxval);
1199 if (samplesperpixel==4) {
1200 *tP++ = (
unsigned char)(255 * alpha_data[col] / _maxval);
1205 for ( col = 0; col < _x_size; ++col ) {
1208 s = ppm_lookupcolor( cht, (
pixel *)(&row_data[col]) );
1210 pnmimage_tiff_cat.error()
1211 <<
"Internal error: color not found?!? row=" << row
1212 <<
" col=" << col <<
"\n";
1215 *tP++ = (
unsigned char) s;
1216 if (samplesperpixel==2) {
1217 *tP++ = (
unsigned char)(255 * alpha_data[col] / _maxval);
1222 xelval bigger_maxval;
1227 bigger_maxval = pm_bitstomaxval( bitspersample );
1228 bitshift = 8 - bitspersample;
1231 for ( col = 0; col < _x_size; ++col ) {
1232 s = PPM_GETB(row_data[col]);
1233 if ( _maxval != bigger_maxval )
1234 s = (xelval)((
long) s * bigger_maxval / _maxval);
1235 byte |= s << bitshift;
1236 bitshift -= bitspersample;
1237 if ( bitshift < 0 ) {
1239 bitshift = 8 - bitspersample;
1243 if ( bitshift != 8 - bitspersample )
1247 if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 ) {
1248 pnmimage_tiff_cat.error()
1249 <<
"failed a scanline write on row " << row <<
"\n";
1253 TIFFFlushData( tif );
1268 void PNMFileTypeTIFF::
1269 install_error_handlers() {
1270 if (!_installed_error_handlers) {
1271 TIFFSetWarningHandler(tiff_warning);
1272 TIFFSetErrorHandler(tiff_error);
1273 _installed_error_handlers =
true;
1283 void PNMFileTypeTIFF::
1284 tiff_warning(
const char *,
const char *format, va_list ap) {
1285 static const int buffer_size = 1024;
1286 char buffer[buffer_size];
1287 #if defined(WIN32_VC) || defined(WIN64_VC) 1288 vsprintf(buffer, format, ap);
1290 vsnprintf(buffer, buffer_size, format, ap);
1294 pnmimage_tiff_cat.warning()
1304 void PNMFileTypeTIFF::
1305 tiff_error(
const char *module,
const char *format, va_list ap) {
1306 static const int buffer_size = 1024;
1307 char buffer[buffer_size];
1308 #if defined(WIN32_VC) || defined(WIN64_VC) 1309 vsprintf(buffer, format, ap);
1311 vsnprintf(buffer, buffer_size, format, ap);
1315 pnmimage_tiff_cat.error()
1326 void PNMFileTypeTIFF::
1327 register_with_read_factory() {
1329 register_factory(get_class_type(), make_PNMFileTypeTIFF);
bool is_valid() const
Returns true if the PNMWriter can be used to write data, false if something is wrong.
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.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component, or with a special extension, 2- or 4-component.
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...
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.
void clear()
Eliminates all data in the file.