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.