00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pnmFileTypeTIFF.h"
00020 #include "config_pnmimagetypes.h"
00021
00022 #include "pnmFileTypeRegistry.h"
00023 #include "bamReader.h"
00024 #include "ppmcmap.h"
00025
00026
00027 #define int8 tiff_int8
00028 #define uint8 tiff_uint8
00029 #define int32 tiff_int32
00030 #define uint32 tiff_uint32
00031
00032 extern "C" {
00033 #include <tiff.h>
00034 #include <tiffio.h>
00035 }
00036
00037 static const char * const extensions_tiff[] = {
00038 "tiff", "tif"
00039 };
00040 static const int num_extensions_tiff = sizeof(extensions_tiff) / sizeof(const char *);
00041
00042
00043
00044
00045
00046
00047 #ifdef COMPRESSION_DEFLATE
00048 unsigned short tiff_compression = COMPRESSION_DEFLATE;
00049 #else
00050 unsigned short tiff_compression = COMPRESSION_NONE;
00051 #endif
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 long tiff_g3options = 0;
00066
00067
00068
00069
00070
00071
00072
00073 unsigned short tiff_fillorder = FILLORDER_MSB2LSB;
00074
00075
00076
00077
00078
00079 short tiff_predictor = 0;
00080
00081
00082
00083 long tiff_rowsperstrip = 0;
00084
00085
00086 #ifndef PHOTOMETRIC_DEPTH
00087 #define PHOTOMETRIC_DEPTH 32768
00088 #endif
00089
00090
00091
00092 static tsize_t
00093 istream_read(thandle_t fd, tdata_t buf, tsize_t size) {
00094 istream *in = (istream *)fd;
00095 in->read((char *)buf, size);
00096 return in->gcount();
00097 }
00098
00099 static tsize_t
00100 ostream_write(thandle_t fd, tdata_t buf, tsize_t size) {
00101 ostream *out = (ostream *)fd;
00102 out->write((char *)buf, size);
00103 return out->fail() ? (tsize_t)0 : size;
00104 }
00105
00106 static tsize_t
00107 ostream_dont_read(thandle_t, tdata_t, tsize_t) {
00108
00109
00110 return 0;
00111 }
00112
00113 static tsize_t
00114 istream_dont_write(thandle_t, tdata_t, tsize_t) {
00115
00116
00117 return 0;
00118 }
00119
00120 static toff_t
00121 istream_seek(thandle_t fd, off_t off, int whence) {
00122 istream *in = (istream *)fd;
00123
00124 ios_seekdir dir;
00125 switch (whence) {
00126 case SEEK_SET:
00127 dir = ios::beg;
00128 break;
00129
00130 case SEEK_END:
00131 dir = ios::end;
00132 break;
00133
00134 case SEEK_CUR:
00135 dir = ios::cur;
00136 break;
00137
00138 default:
00139 return in->tellg();
00140 }
00141
00142 in->seekg(off, dir);
00143 return in->tellg();
00144 }
00145
00146 static toff_t
00147 ostream_seek(thandle_t fd, off_t off, int whence) {
00148 ostream *out = (ostream *)fd;
00149
00150 ios_seekdir dir;
00151 switch (whence) {
00152 case SEEK_SET:
00153 dir = ios::beg;
00154 break;
00155
00156 case SEEK_END:
00157 dir = ios::end;
00158 break;
00159
00160 case SEEK_CUR:
00161 dir = ios::cur;
00162 break;
00163
00164 default:
00165 return out->tellp();
00166 }
00167
00168 out->seekp(off, dir);
00169 return out->tellp();
00170 }
00171
00172 static int
00173 iostream_dont_close(thandle_t) {
00174
00175 return true;
00176 }
00177
00178 static toff_t
00179 istream_size(thandle_t fd) {
00180 istream *in = (istream *)fd;
00181 in->seekg(0, ios::end);
00182 return in->tellg();
00183 }
00184
00185 static toff_t
00186 ostream_size(thandle_t fd) {
00187 ostream *out = (ostream *)fd;
00188 out->seekp(0, ios::end);
00189 return out->tellp();
00190 }
00191
00192 static int
00193 iostream_map(thandle_t, tdata_t*, toff_t*) {
00194 return (0);
00195 }
00196
00197 static void
00198 iostream_unmap(thandle_t, tdata_t, toff_t) {
00199 }
00200
00201 bool PNMFileTypeTIFF::_installed_error_handlers = false;
00202 TypeHandle PNMFileTypeTIFF::_type_handle;
00203
00204
00205
00206
00207
00208
00209 PNMFileTypeTIFF::
00210 PNMFileTypeTIFF() {
00211 }
00212
00213
00214
00215
00216
00217
00218 string PNMFileTypeTIFF::
00219 get_name() const {
00220 return "TIFF";
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 int PNMFileTypeTIFF::
00230 get_num_extensions() const {
00231 return num_extensions_tiff;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241 string PNMFileTypeTIFF::
00242 get_extension(int n) const {
00243 nassertr(n >= 0 && n < num_extensions_tiff, string());
00244 return extensions_tiff[n];
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254 string PNMFileTypeTIFF::
00255 get_suggested_extension() const {
00256 return "tiff";
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 bool PNMFileTypeTIFF::
00266 has_magic_number() const {
00267 return true;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 bool PNMFileTypeTIFF::
00278 matches_magic_number(const string &magic_number) const {
00279 nassertr(magic_number.size() >= 2, false);
00280 int mn =
00281 ((unsigned char)magic_number[0] << 8) |
00282 ((unsigned char)magic_number[1]);
00283 return (mn == TIFF_BIGENDIAN || mn == TIFF_LITTLEENDIAN);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293 PNMReader *PNMFileTypeTIFF::
00294 make_reader(istream *file, bool owns_file, const string &magic_number) {
00295 init_pnm();
00296 install_error_handlers();
00297 return new Reader(this, file, owns_file, magic_number);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 PNMWriter *PNMFileTypeTIFF::
00308 make_writer(ostream *file, bool owns_file) {
00309 init_pnm();
00310 install_error_handlers();
00311 return new Writer(this, file, owns_file);
00312 }
00313
00314
00315
00316
00317
00318
00319 PNMFileTypeTIFF::Reader::
00320 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
00321 PNMReader(type, file, owns_file)
00322 {
00323 bool grayscale = false;
00324 int numcolors;
00325 int i;
00326 unsigned short* redcolormap;
00327 unsigned short* greencolormap;
00328 unsigned short* bluecolormap;
00329
00330
00331 for (string::reverse_iterator mi = magic_number.rbegin();
00332 mi != magic_number.rend();
00333 mi++) {
00334 _file->putback(*mi);
00335 }
00336 if (_file->fail()) {
00337 pnmimage_tiff_cat.error()
00338 << "Unable to put back magic number.\n";
00339 _is_valid = false;
00340 }
00341
00342 if (_is_valid) {
00343 tif = TIFFClientOpen("TIFF file", "r",
00344 (thandle_t) _file,
00345 istream_read, istream_dont_write,
00346 (TIFFSeekProc)istream_seek,
00347 iostream_dont_close, istream_size,
00348 iostream_map, iostream_unmap);
00349
00350 if ( tif == NULL ) {
00351 _is_valid = false;
00352 }
00353 }
00354
00355 if (_is_valid) {
00356 if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) )
00357 bps = 1;
00358 if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) )
00359 spp = 1;
00360
00361 if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) ) {
00362 pnmimage_tiff_cat.error()
00363 << "Error getting photometric from TIFF file.\n";
00364 _is_valid = false;
00365 }
00366 }
00367
00368 if (_is_valid) {
00369 if (spp >= 1 && spp <= 4) {
00370 _num_channels = spp;
00371 } else {
00372 pnmimage_tiff_cat.error()
00373 << "Cannot handle " << spp << "-channel image.\n";
00374 _is_valid = false;
00375 }
00376 }
00377
00378 if (_is_valid) {
00379 (void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &_x_size );
00380 (void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &_y_size );
00381
00382 if (pnmimage_tiff_cat.is_debug()) {
00383 pnmimage_tiff_cat.debug()
00384 << "Reading TIFF image: " << _x_size << " x " << _y_size << "\n"
00385 << bps << " bits/sample, " << spp << " samples/pixel\n";
00386 }
00387
00388 _maxval = ( 1 << bps ) - 1;
00389 if ( _maxval == 1 && spp == 1 ) {
00390 if (pnmimage_tiff_cat.is_debug()) {
00391 pnmimage_tiff_cat.debug(false)
00392 << "monochrome\n";
00393 }
00394 grayscale = true;
00395 } else {
00396 switch ( photomet ) {
00397 case PHOTOMETRIC_MINISBLACK:
00398 if (pnmimage_tiff_cat.is_debug()) {
00399 pnmimage_tiff_cat.debug(false)
00400 << _maxval + 1 << " graylevels (min is black)\n";
00401 }
00402 grayscale = true;
00403 break;
00404
00405 case PHOTOMETRIC_MINISWHITE:
00406 if (pnmimage_tiff_cat.is_debug()) {
00407 pnmimage_tiff_cat.debug(false)
00408 << _maxval + 1 << " graylevels (min is white)\n";
00409 }
00410 grayscale = true;
00411 break;
00412
00413 case PHOTOMETRIC_PALETTE:
00414 if (pnmimage_tiff_cat.is_debug()) {
00415 pnmimage_tiff_cat.debug(false)
00416 << " colormapped\n";
00417 }
00418 if ( ! TIFFGetField( tif, TIFFTAG_COLORMAP, &redcolormap, &greencolormap, &bluecolormap ) ) {
00419 pnmimage_tiff_cat.error()
00420 << "Error getting colormap from TIFF file.\n";
00421 _is_valid = false;
00422 } else {
00423 numcolors = _maxval + 1;
00424 if ( numcolors > TIFF_COLORMAP_MAXCOLORS ) {
00425 pnmimage_tiff_cat.error()
00426 << "Cannot read TIFF file with " << numcolors
00427 << " in colormap; max supported is " << TIFF_COLORMAP_MAXCOLORS << "\n";
00428 _is_valid = false;
00429 } else {
00430 _maxval = PNM_MAXMAXVAL;
00431 grayscale = false;
00432 for ( i = 0; i < numcolors; ++i ) {
00433 xelval r, g, b;
00434 r = (xelval)(_maxval * (double)(redcolormap[i] / 65535.0));
00435 g = (xelval)(_maxval * (double)(greencolormap[i] / 65535.0));
00436 b = (xelval)(_maxval * (double)(bluecolormap[i] / 65535.0));
00437 PPM_ASSIGN( colormap[i], r, g, b );
00438 }
00439 }
00440 }
00441 break;
00442
00443 case PHOTOMETRIC_RGB:
00444 if (pnmimage_tiff_cat.is_debug()) {
00445 pnmimage_tiff_cat.debug(false)
00446 << "truecolor\n";
00447 }
00448 grayscale = false;
00449 break;
00450
00451 case PHOTOMETRIC_MASK:
00452 pnmimage_tiff_cat.error()
00453 << "Don't know how to handle TIFF image with PHOTOMETRIC_MASK.\n";
00454 _is_valid = false;
00455 break;
00456
00457 case PHOTOMETRIC_DEPTH:
00458 pnmimage_tiff_cat.error()
00459 << "Don't know how to handle TIFF image with PHOTOMETRIC_DEPTH.\n";
00460 _is_valid = false;
00461 break;
00462
00463 default:
00464 pnmimage_tiff_cat.error()
00465 << "Unknown photometric " << photomet << " in TIFF image.\n";
00466 _is_valid = false;
00467 break;
00468 }
00469 }
00470 }
00471
00472 if (_is_valid ) {
00473 if ( _maxval > PNM_MAXMAXVAL ) {
00474 pnmimage_tiff_cat.error()
00475 << "Cannot read TIFF file with maxval of " << _maxval << "\n";
00476 _is_valid = false;
00477 }
00478 }
00479
00480 if (_is_valid) {
00481 if (grayscale && !is_grayscale()) {
00482 _num_channels = (has_alpha()) ? 2 : 1;
00483 } else if (!grayscale && is_grayscale()) {
00484 _num_channels = (has_alpha()) ? 4 : 3;
00485 }
00486
00487 current_row = 0;
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496 PNMFileTypeTIFF::Reader::
00497 ~Reader() {
00498 TIFFClose( tif );
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 bool PNMFileTypeTIFF::Reader::
00512 supports_read_row() const {
00513 return true;
00514 }
00515
00516 #define NEXTSAMPLE \
00517 { \
00518 if ( bitsleft == 0 ) \
00519 { \
00520 ++inP; \
00521 bitsleft = 8; \
00522 } \
00523 bitsleft -= bps; \
00524 sample = ( *inP >> bitsleft ) & _maxval; \
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 bool PNMFileTypeTIFF::Reader::
00537 read_row(xel *row_data, xelval *alpha_data) {
00538 if (!is_valid()) {
00539 return false;
00540 }
00541
00542 unsigned char *buf = (unsigned char*) alloca((size_t)TIFFScanlineSize(tif));
00543 int col;
00544 unsigned char sample;
00545
00546 if ( TIFFReadScanline( tif, buf, current_row, 0 ) < 0 ) {
00547 pnmimage_tiff_cat.error()
00548 << "Bad data read on line " << current_row << " of TIFF image.\n";
00549 return false;
00550 }
00551
00552 unsigned char *inP = buf;
00553 int bitsleft = 8;
00554
00555 switch ( photomet ) {
00556 case PHOTOMETRIC_MINISBLACK:
00557 for ( col = 0; col < _x_size; ++col )
00558 {
00559 NEXTSAMPLE;
00560 PPM_PUTB(row_data[col], sample);
00561 if ( spp == 2 ) {
00562 NEXTSAMPLE;
00563 alpha_data[col] = sample;
00564 }
00565 }
00566 break;
00567
00568 case PHOTOMETRIC_MINISWHITE:
00569 for ( col = 0; col < _x_size; ++col )
00570 {
00571 NEXTSAMPLE;
00572 sample = _maxval - sample;
00573 PPM_PUTB(row_data[col], sample);
00574 if ( spp == 2 ) {
00575 NEXTSAMPLE;
00576 alpha_data[col] = sample;
00577 }
00578 }
00579 break;
00580
00581 case PHOTOMETRIC_PALETTE:
00582 for ( col = 0; col < _x_size; ++col )
00583 {
00584 NEXTSAMPLE;
00585 row_data[col] = colormap[sample];
00586 if ( spp == 2 ) {
00587 NEXTSAMPLE;
00588 alpha_data[col] = sample;
00589 }
00590 }
00591 break;
00592
00593 case PHOTOMETRIC_RGB:
00594 for ( col = 0; col < _x_size; ++col ) {
00595 xelval r, g, b;
00596
00597 NEXTSAMPLE;
00598 r = sample;
00599 NEXTSAMPLE;
00600 g = sample;
00601 NEXTSAMPLE;
00602 b = sample;
00603 PPM_ASSIGN(row_data[col], r, g, b);
00604 if ( spp == 4 ) {
00605 NEXTSAMPLE;
00606 alpha_data[col] = sample;
00607 }
00608 }
00609 break;
00610
00611 default:
00612 pnmimage_tiff_cat.error()
00613 << "Internal error: unsupported photometric " << photomet << "\n";
00614 return false;
00615 }
00616
00617 current_row++;
00618 return true;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627 PNMFileTypeTIFF::Writer::
00628 Writer(PNMFileType *type, ostream *file, bool owns_file) :
00629 PNMWriter(type, file, owns_file)
00630 {
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 int PNMFileTypeTIFF::Writer::
00656 write_data(xel *array, xelval *alpha) {
00657 colorhist_vector chv = (colorhist_vector) 0;
00658 colorhash_table cht;
00659 unsigned short
00660 red[TIFF_COLORMAP_MAXCOLORS],
00661 grn[TIFF_COLORMAP_MAXCOLORS],
00662 blu[TIFF_COLORMAP_MAXCOLORS];
00663 int row, colors, i;
00664 register int col;
00665 int grayscale = false;
00666 struct tiff * tif;
00667 short photometric = 0;
00668 short samplesperpixel = 0;
00669 short bitspersample = 0;
00670 int bytesperrow = 0;
00671 unsigned char* buf;
00672 unsigned char* tP;
00673
00674 switch ( get_color_type() ) {
00675 case CT_color:
00676
00677
00678
00679 chv = ppm_computecolorhist( (pixel **)&array, _x_size * _y_size, 1,
00680 TIFF_COLORMAP_MAXCOLORS, &colors );
00681 if ( chv == (colorhist_vector) 0 ) {
00682 pnmimage_tiff_cat.debug()
00683 << colors << " colors found; too many for a palette.\n"
00684 << "Writing a 24-bit RGB file.\n";
00685 grayscale = false;
00686 } else {
00687 pnmimage_tiff_cat.debug()
00688 << colors << " colors found; writing an 8-bit palette file.\n";
00689 grayscale = true;
00690 for ( i = 0; i < colors; ++i ) {
00691 register xelval r, g, b;
00692
00693 r = PPM_GETR( chv[i].color );
00694 g = PPM_GETG( chv[i].color );
00695 b = PPM_GETB( chv[i].color );
00696 if ( r != g || g != b ) {
00697 grayscale = false;
00698 break;
00699 }
00700 }
00701 }
00702 break;
00703
00704 case CT_two_channel:
00705 case CT_four_channel:
00706 chv = (colorhist_vector) 0;
00707 grayscale = false;
00708 break;
00709
00710 case CT_grayscale:
00711 chv = (colorhist_vector) 0;
00712 grayscale = true;
00713 break;
00714
00715 default:
00716 break;
00717 }
00718
00719
00720 tif = TIFFClientOpen("TIFF file", "w",
00721 (thandle_t) _file,
00722 ostream_dont_read, ostream_write,
00723 (TIFFSeekProc)ostream_seek,
00724 iostream_dont_close, ostream_size,
00725 iostream_map, iostream_unmap);
00726 if ( tif == NULL ) {
00727 return false;
00728 }
00729
00730
00731 switch ( get_color_type() ) {
00732 case CT_color:
00733 case CT_four_channel:
00734 if ( chv == (colorhist_vector) 0 ) {
00735 samplesperpixel = _num_channels;
00736 bitspersample = 8;
00737 photometric = PHOTOMETRIC_RGB;
00738 bytesperrow = _x_size * samplesperpixel;
00739 } else if ( grayscale ) {
00740 samplesperpixel = 1;
00741 bitspersample = pm_maxvaltobits( _maxval );
00742 photometric = PHOTOMETRIC_MINISBLACK;
00743 i = 8 / bitspersample;
00744 bytesperrow = ( _x_size + i - 1 ) / i;
00745 } else {
00746 samplesperpixel = 1;
00747 bitspersample = 8;
00748 photometric = PHOTOMETRIC_PALETTE;
00749 bytesperrow = _x_size;
00750 }
00751 break;
00752
00753 case CT_grayscale:
00754 case CT_two_channel:
00755 samplesperpixel = _num_channels;
00756 bitspersample = pm_maxvaltobits( _maxval );
00757 photometric = PHOTOMETRIC_MINISBLACK;
00758 i = 8 / bitspersample;
00759 bytesperrow = ( _x_size + i - 1 ) / i;
00760 break;
00761
00762 default:
00763 break;
00764 }
00765
00766 if ( tiff_rowsperstrip == 0 )
00767 tiff_rowsperstrip = ( 8 * 1024 ) / bytesperrow;
00768 buf = (unsigned char*) malloc( bytesperrow );
00769 if ( buf == (unsigned char*) 0 ) {
00770 pnmimage_tiff_cat.error()
00771 << "Can't allocate memory for row buffer\n";
00772 return 0;
00773 }
00774
00775
00776 TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, _x_size );
00777 TIFFSetField( tif, TIFFTAG_IMAGELENGTH, _y_size );
00778 TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample );
00779 TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
00780 TIFFSetField( tif, TIFFTAG_COMPRESSION, tiff_compression );
00781 if ( tiff_compression == COMPRESSION_CCITTFAX3 && tiff_g3options != 0 )
00782 TIFFSetField( tif, TIFFTAG_GROUP3OPTIONS, tiff_g3options );
00783 if ( tiff_compression == COMPRESSION_LZW && tiff_predictor != 0 )
00784 TIFFSetField( tif, TIFFTAG_PREDICTOR, tiff_predictor );
00785 TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
00786 TIFFSetField( tif, TIFFTAG_FILLORDER, tiff_fillorder );
00787
00788 TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION,
00789 "Generated via pnmimage.\n" );
00790 TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel );
00791 TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, tiff_rowsperstrip );
00792
00793 TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
00794
00795 if ( chv == (colorhist_vector) 0 ) {
00796 cht = (colorhash_table) 0;
00797 } else {
00798
00799 for ( i = 0; i < colors; ++i ) {
00800 red[i] = (unsigned short) (PPM_GETR( chv[i].color ) * 65535L / _maxval);
00801 grn[i] = (unsigned short) (PPM_GETG( chv[i].color ) * 65535L / _maxval);
00802 blu[i] = (unsigned short) (PPM_GETB( chv[i].color ) * 65535L / _maxval);
00803 }
00804 TIFFSetField( tif, TIFFTAG_COLORMAP, red, grn, blu );
00805
00806
00807 cht = ppm_colorhisttocolorhash( chv, colors );
00808 ppm_freecolorhist( chv );
00809 }
00810
00811
00812 for ( row = 0; row < _y_size; ++row ) {
00813 xel *row_data = array + row*_x_size;
00814 xelval *alpha_data = alpha + row*_x_size;
00815
00816 if ( !is_grayscale() && ! grayscale ) {
00817 if ( cht == (colorhash_table) 0 ) {
00818 tP = buf;
00819 for ( col = 0; col < _x_size; ++col ) {
00820 *tP++ = (unsigned char)(255 * PPM_GETR(row_data[col]) / _maxval);
00821 *tP++ = (unsigned char)(255 * PPM_GETG(row_data[col]) / _maxval);
00822 *tP++ = (unsigned char)(255 * PPM_GETB(row_data[col]) / _maxval);
00823 if (samplesperpixel==4) {
00824 *tP++ = (unsigned char)(255 * alpha_data[col] / _maxval);
00825 }
00826 }
00827 } else {
00828 tP = buf;
00829 for ( col = 0; col < _x_size; ++col ) {
00830 register int s;
00831
00832 s = ppm_lookupcolor( cht, (pixel *)(&row_data[col]) );
00833 if ( s == -1 ) {
00834 pnmimage_tiff_cat.error()
00835 << "Internal error: color not found?!? row=" << row
00836 << " col=" << col << "\n";
00837 return 0;
00838 }
00839 *tP++ = (unsigned char) s;
00840 if (samplesperpixel==2) {
00841 *tP++ = (unsigned char)(255 * alpha_data[col] / _maxval);
00842 }
00843 }
00844 }
00845 } else {
00846 register xelval bigger_maxval;
00847 register int bitshift;
00848 register unsigned char byte;
00849 register xelval s;
00850
00851 bigger_maxval = pm_bitstomaxval( bitspersample );
00852 bitshift = 8 - bitspersample;
00853 byte = 0;
00854 tP = buf;
00855 for ( col = 0; col < _x_size; ++col ) {
00856 s = PPM_GETB(row_data[col]);
00857 if ( _maxval != bigger_maxval )
00858 s = (xelval)((long) s * bigger_maxval / _maxval);
00859 byte |= s << bitshift;
00860 bitshift -= bitspersample;
00861 if ( bitshift < 0 ) {
00862 *tP++ = byte;
00863 bitshift = 8 - bitspersample;
00864 byte = 0;
00865 }
00866 }
00867 if ( bitshift != 8 - bitspersample )
00868 *tP++ = byte;
00869 }
00870
00871 if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 ) {
00872 pnmimage_tiff_cat.error()
00873 << "failed a scanline write on row " << row << "\n";
00874 return row;
00875 }
00876 }
00877 TIFFFlushData( tif );
00878 TIFFClose( tif );
00879
00880 return _y_size;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 void PNMFileTypeTIFF::
00893 install_error_handlers() {
00894 if (!_installed_error_handlers) {
00895 TIFFSetWarningHandler(tiff_warning);
00896 TIFFSetErrorHandler(tiff_error);
00897 _installed_error_handlers = true;
00898 }
00899 }
00900
00901
00902
00903
00904
00905
00906
00907 void PNMFileTypeTIFF::
00908 tiff_warning(const char *, const char *format, va_list ap) {
00909 static const int buffer_size = 1024;
00910 char buffer[buffer_size];
00911 #ifdef WIN32_VC
00912 vsprintf(buffer, format, ap);
00913 #else
00914 vsnprintf(buffer, buffer_size, format, ap);
00915 #endif
00916
00917
00918 pnmimage_tiff_cat.warning()
00919 << buffer << "\n";
00920 }
00921
00922
00923
00924
00925
00926
00927
00928 void PNMFileTypeTIFF::
00929 tiff_error(const char *module, const char *format, va_list ap) {
00930 static const int buffer_size = 1024;
00931 char buffer[buffer_size];
00932 #ifdef WIN32_VC
00933 vsprintf(buffer, format, ap);
00934 #else
00935 vsnprintf(buffer, buffer_size, format, ap);
00936 #endif
00937
00938
00939 pnmimage_tiff_cat.error()
00940 << buffer << "\n";
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950 void PNMFileTypeTIFF::
00951 register_with_read_factory() {
00952 BamReader::get_factory()->
00953 register_factory(get_class_type(), make_PNMFileTypeTIFF);
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 TypedWritable *PNMFileTypeTIFF::
00969 make_PNMFileTypeTIFF(const FactoryParams ¶ms) {
00970 return PNMFileTypeRegistry::get_ptr()->get_type_by_handle(get_class_type());
00971 }