00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "vil1_tiff.h"
00016
00017 #include <vcl_cassert.h>
00018 #if 0 // commented out
00019 #include <vcl_cstdio.h>
00020 #endif
00021 #include <vcl_cstring.h>
00022 #include <vcl_iostream.h>
00023
00024 #include <vil1/vil1_stream.h>
00025 #include <vil1/vil1_image_impl.h>
00026 #include <vil1/vil1_image.h>
00027 #include <vil1/vil1_property.h>
00028
00029 #include <tiffio.h>
00030
00031
00032 char const* vil1_tiff_format_tag = "tiff";
00033
00034
00035 static bool xxproblem(char const* linefile, char const* msg)
00036 {
00037 vcl_cerr << linefile << "[PROBLEM " <<msg << ']';
00038 return false;
00039 }
00040 #define xproblem(x, l) xxproblem(__FILE__ ":" #l ":", x)
00041 #define yxproblem(x, l) xproblem(x, l)
00042 #define problem(x) yxproblem(x, __LINE__)
00043
00044 #define trace if (true) { } else vcl_cerr
00045
00046 bool vil1_tiff_file_format_probe(vil1_stream* is)
00047 {
00048
00049
00050 #if 0
00051 short int hdr[2];
00052 int read = is->read(hdr, sizeof hdr);
00053 if (read < 2)
00054 return 0;
00055
00056 if (hdr[0]!=0x4D4D && hdr[0]!=0x4949)
00057 return 0;
00058
00059 if (hdr[1]!=0x002A && hdr[1]!=0x2A00)
00060 return 0;
00061 #else
00062 char hdr[4];
00063 unsigned int read = is->read(hdr, sizeof hdr);
00064 if (read < sizeof hdr)
00065 return false;
00066
00067
00068
00069
00070
00071
00072
00073
00074 if (hdr[0]==0x4D && hdr[1]==0x4D &&
00075 hdr[2]==0x00 && hdr[3]==0x2A)
00076 return true;
00077
00078 else if (hdr[0]==0x49 && hdr[1]==0x49 &&
00079 hdr[2]==0x2A && hdr[3]==0x00)
00080 return true;
00081
00082 else if ( ((hdr[0]==0x4D && hdr[1]==0x4D) || (hdr[1]==0x49 && hdr[1]==0x49)) &&
00083 ((hdr[2]==0x00 && hdr[3]==0x2A) || (hdr[2]==0x2A && hdr[3]==0x00)) ) {
00084 vcl_cerr << __FILE__ ": suspicious TIFF header\n";
00085 return true;
00086 }
00087
00088 else
00089 return false;
00090 #endif
00091 }
00092
00093 vil1_image_impl* vil1_tiff_file_format::make_input_image(vil1_stream* is)
00094 {
00095 if (!vil1_tiff_file_format_probe(is))
00096 return 0;
00097
00098 return new vil1_tiff_generic_image(is);
00099 }
00100
00101 vil1_image_impl* vil1_tiff_file_format::make_output_image(vil1_stream* is, int planes,
00102 int width,
00103 int height,
00104 int components,
00105 int bits_per_component,
00106 vil1_component_format format)
00107 {
00108 return new vil1_tiff_generic_image(is, planes, width, height, components, bits_per_component, format);
00109 }
00110
00111 char const* vil1_tiff_file_format::tag() const
00112 {
00113 return vil1_tiff_format_tag;
00114 }
00115
00116
00117
00118 struct vil1_tiff_structures {
00119 vil1_tiff_structures(vil1_stream *vs_):
00120 vs(vs_),
00121 filesize(0),
00122 buf(0)
00123 { if (vs) vs->ref(); }
00124 ~vil1_tiff_structures() {
00125 delete [] buf;
00126 if (vs) vs->unref();
00127 }
00128
00129 TIFF* tif;
00130 vil1_stream* vs;
00131 int filesize;
00132
00133 unsigned long tilewidth;
00134 unsigned long tileheight;
00135 unsigned short compression;
00136 unsigned long rows_per_strip;
00137 unsigned short planar_config;
00138 unsigned short photometric;
00139
00140 unsigned long stripsize;
00141 unsigned long scanlinesize;
00142 unsigned long numberofstrips;
00143
00144 bool tiled;
00145 bool compressed;
00146 bool jumbo_strips;
00147
00148 unsigned char* buf;
00149 };
00150
00151 #if 0 // commented out
00152 typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t);
00153 typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int);
00154 typedef int (*TIFFCloseProc)(thandle_t);
00155 typedef toff_t (*TIFFSizeProc)(thandle_t);
00156 typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*);
00157 typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t);
00158
00159 TIFF* TIFFClientOpen(const char* filename, const char* mode, thandle_t clientdata,
00160 TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc,
00161 TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc,
00162 TIFFUnmapFileProc unmapproc)
00163 #endif
00164
00165 static tsize_t vil1_tiff_readproc(thandle_t h, tdata_t buf, tsize_t n)
00166 {
00167 vil1_tiff_structures* p = (vil1_tiff_structures*)h;
00168 if (n > p->filesize) p->filesize= n;
00169 tsize_t ret = p->vs->read(buf, n);
00170 trace << "readproc, n = " << n << ", ret = " << ret << '\n';
00171 return ret;
00172 }
00173
00174 static tsize_t vil1_tiff_writeproc(thandle_t h, tdata_t buf, tsize_t n)
00175 {
00176 vil1_tiff_structures* p = (vil1_tiff_structures*)h;
00177 tsize_t ret = p->vs->write(buf, n);
00178 vil1_streampos s = p->vs->tell();
00179 if (s > p->filesize)
00180 p->filesize = s;
00181 trace << "writeproc: ret=" << ret << '/' << n << " , filesize = " << p->filesize << " " << s << vcl_endl;
00182 return ret;
00183 }
00184
00185 static toff_t vil1_tiff_seekproc(thandle_t h, toff_t offset, int whence)
00186 {
00187 trace << "seek " << offset << " w = " << whence << vcl_endl;
00188 vil1_tiff_structures* p = (vil1_tiff_structures*)h;
00189 if (whence == SEEK_SET) {
00190 p->vs->seek(offset);
00191 } else if (whence == SEEK_CUR) {
00192 p->vs->seek(p->vs->tell() + offset);
00193 } else if (whence == SEEK_END) {
00194 p->vs->seek(p->filesize + offset);
00195 }
00196 vil1_streampos s = p->vs->tell();
00197 if (s > p->filesize)
00198 p->filesize = s;
00199 return s;
00200 }
00201
00202 static int vil1_tiff_closeproc(thandle_t h)
00203 {
00204 trace << "vil1_tiff_closeproc\n";
00205 vil1_tiff_structures* p = (vil1_tiff_structures*)h;
00206
00207 if (p->vs) {
00208 p->vs->unref();
00209 p->vs = 0;
00210 }
00211 return 0;
00212 }
00213
00214 static toff_t vil1_tiff_sizeproc(thandle_t)
00215 {
00216 trace << "vil1_tiff_sizeproc\n";
00217
00218 return (toff_t)(-1);
00219 }
00220
00221 static int vil1_tiff_mapfileproc(thandle_t, tdata_t*, toff_t*)
00222 {
00223
00224 return 0;
00225 }
00226
00227 static void vil1_tiff_unmapfileproc(thandle_t, tdata_t, toff_t)
00228 {
00229 }
00230
00231
00232
00233 vil1_tiff_generic_image::vil1_tiff_generic_image(vil1_stream* is):
00234 p(new vil1_tiff_structures(is))
00235 {
00236 read_header();
00237 }
00238
00239 bool vil1_tiff_generic_image::get_property(char const *tag, void *prop) const
00240 {
00241 unsigned short orientation;
00242 int orientation_val_ok = TIFFGetField(p->tif, TIFFTAG_ORIENTATION, &orientation);
00243 if (orientation_val_ok != 1)
00244 {
00245
00246
00247 orientation = 1;
00248 }
00249
00250 bool topdown = (orientation==ORIENTATION_TOPLEFT ||
00251 orientation==ORIENTATION_TOPRIGHT ||
00252 orientation==ORIENTATION_LEFTTOP ||
00253 orientation==ORIENTATION_RIGHTTOP);
00254 bool leftright=(orientation==ORIENTATION_TOPLEFT ||
00255 orientation==ORIENTATION_BOTLEFT ||
00256 orientation==ORIENTATION_LEFTTOP ||
00257 orientation==ORIENTATION_LEFTBOT);
00258
00259 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00260 return prop ? (*(bool*)prop) = topdown, true : true;
00261
00262 if (0==vcl_strcmp(tag, vil1_property_left_first))
00263 return prop ? (*(bool*)prop) = leftright, true : true;
00264
00265 return false;
00266 }
00267
00268 bool vil1_tiff_generic_image::set_property(char const *tag, const void *prop) const
00269 {
00270 bool topdown; get_property(vil1_property_top_row_first, &topdown);
00271 bool leftright; get_property(vil1_property_left_first, &leftright);
00272 const bool newprop = prop ? (*(const bool*)prop) : true;
00273
00274 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00275 {
00276 if (topdown == newprop)
00277 return true;
00278 unsigned short orientation =
00279 ( topdown && leftright) ? ORIENTATION_TOPLEFT :
00280 (!topdown && leftright) ? ORIENTATION_BOTLEFT :
00281 ( topdown && !leftright) ? ORIENTATION_TOPRIGHT :
00282 ORIENTATION_BOTRIGHT;
00283 TIFFSetField(p->tif, TIFFTAG_ORIENTATION, orientation);
00284 return true;
00285 }
00286
00287 else if (0==vcl_strcmp(tag, vil1_property_left_first))
00288 {
00289 if (leftright == newprop)
00290 return true;
00291 unsigned short orientation =
00292 ( topdown && leftright) ? ORIENTATION_TOPLEFT :
00293 (!topdown && leftright) ? ORIENTATION_BOTLEFT :
00294 ( topdown && !leftright) ? ORIENTATION_TOPRIGHT :
00295 ORIENTATION_BOTRIGHT;
00296 TIFFSetField(p->tif, TIFFTAG_ORIENTATION, orientation);
00297 return true;
00298 }
00299
00300 else
00301 return false;
00302 }
00303
00304 vil1_tiff_generic_image::vil1_tiff_generic_image(vil1_stream* is, int ,
00305 int width,
00306 int height,
00307 int components,
00308 int bits_per_component,
00309 vil1_component_format ):
00310 p(new vil1_tiff_structures(is))
00311 {
00312 width_ = width;
00313 height_ = height;
00314 components_ = components;
00315 bits_per_component_ = bits_per_component;
00316
00317 write_header();
00318 }
00319
00320 vil1_tiff_generic_image::~vil1_tiff_generic_image()
00321 {
00322 if (p->tif)
00323 TIFFClose(p->tif);
00324 delete p;
00325 }
00326
00327 char const* vil1_tiff_generic_image::file_format() const
00328 {
00329 return vil1_tiff_format_tag;
00330 }
00331
00332 bool vil1_tiff_generic_image::read_header()
00333 {
00334 p->vs->seek(0L);
00335 p->tif = TIFFClientOpen("unknown filename",
00336 "rC",
00337 (thandle_t)p,
00338 vil1_tiff_readproc, vil1_tiff_writeproc,
00339 vil1_tiff_seekproc, vil1_tiff_closeproc,
00340 vil1_tiff_sizeproc,
00341 vil1_tiff_mapfileproc, vil1_tiff_unmapfileproc);
00342
00343 if (!p->tif) {
00344 return problem("TIFFClientOpen");
00345 }
00346
00347 #if defined(RIH_DEBUG)
00348 TIFFPrintDirectory(p->tif, stderr);
00349 #endif
00350
00351 unsigned short bitspersample;
00352 TIFFGetField(p->tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
00353
00354 unsigned short samplesperpixel;
00355
00356 if (!TIFFGetField(p->tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel))
00357 samplesperpixel = 1;
00358
00359 switch (samplesperpixel) {
00360 case 1:
00361 case 3:
00362 this->components_ = samplesperpixel;
00363 this->bits_per_component_ = bitspersample;
00364 break;
00365 case 16256:
00366 this->components_ = 1;
00367 this->bits_per_component_ = bitspersample;
00368 break;
00369 default:
00370 #ifdef DEBUG
00371 vcl_cerr << "vil1_tiff: Saw " << samplesperpixel << " samples @ " << bitspersample << '\n';
00372 #endif
00373 TIFFError("TIFFImageRH: ", "Can only handle 1-channel gray scale or 3-channel color");
00374 return false;
00375 }
00376
00377 unsigned long width;
00378 TIFFGetField(p->tif, TIFFTAG_IMAGEWIDTH, &width);
00379 this->width_ = width;
00380
00381 unsigned long height;
00382 TIFFGetField(p->tif, TIFFTAG_IMAGELENGTH, &height);
00383 this->height_ = height;
00384
00385 if (TIFFIsTiled(p->tif)){
00386 p->tiled = true;
00387 TIFFGetField(p->tif, TIFFTAG_TILEWIDTH, &p->tilewidth);
00388 TIFFGetField(p->tif, TIFFTAG_TILELENGTH, &p->tileheight);
00389 }
00390 else {
00391 p->tiled = false;
00392 p->tilewidth = 0;
00393 p->tileheight = 0;
00394 }
00395
00396
00397
00398 TIFFGetField(p->tif, TIFFTAG_PHOTOMETRIC, &p->photometric);
00399 switch (p->photometric)
00400 {
00401 case PHOTOMETRIC_RGB:
00402 if (!TIFFIsTiled(p->tif)) {
00403
00404 #ifdef RIH_DEBUG
00405 vcl_cerr << "vil1_tiff: Treating Tiff image as uncompressed ForeignImage\n";
00406 #endif
00407 }
00408 break;
00409 case PHOTOMETRIC_MINISBLACK:
00410 if (!TIFFIsTiled(p->tif))
00411 {
00412
00413 #ifdef RIH_DEBUG
00414 vcl_cerr << "Treating Tiff image as uncompressed ForeignImage\n";
00415 #endif
00416 }
00417
00418 #if 0 // commented out
00419 SetColorNum(0);
00420 SetBandOrder("IMAGE", 0);
00421 SetBandOrder("RED", 0);
00422 SetBandOrder("GREEN", 0);
00423 SetBandOrder("BLUE", 0);
00424 #endif
00425 break;
00426 case PHOTOMETRIC_MINISWHITE:
00427 #if 0 // commented out
00428
00429 int** cm = new int*[3];
00430 cm[0] = new int[ncolors];
00431 cm[1] = new int[ncolors];
00432 cm[2] = new int[ncolors];
00433
00434 for (int i=0; i < ncolors; i++) {
00435 cm[0][i] = (ncolors-1)-i;
00436 cm[1][i] = (ncolors-1)-i;
00437 cm[2][i] = (ncolors-1)-i;
00438 }
00439 SetColorMap(cm);
00440 SetColorNum(ncolors);
00441
00442 SetBandOrder("IMAGE", 0);
00443 SetBandOrder("RED", 0);
00444 SetBandOrder("GREEN", 0);
00445 SetBandOrder("BLUE", 0);
00446 #endif
00447 break;
00448 case PHOTOMETRIC_PALETTE:
00449 #if 0 // commented out
00450 int** cm = new int*[3];
00451 cm[0] = new int[ncolors];
00452 cm[1] = new int[ncolors];
00453 cm[2] = new int[ncolors];
00454
00455 unsigned short *redcolormap,*bluecolormap,*greencolormap;
00456 TIFFGetField(p->tif, TIFFTAG_COLORMAP,
00457 &redcolormap, &greencolormap, &bluecolormap);
00458
00459 for (int i=0; i < ncolors; i++) {
00460 cm[0][i] = (int) CVT(redcolormap[i]);
00461 cm[1][i] = (int) CVT(greencolormap[i]);
00462 cm[2][i] = (int) CVT(bluecolormap[i]);
00463 }
00464
00465 SetColorNum(ncolors);
00466 SetColorMap(cm);
00467
00468
00469 SetBandOrder("IMAGE", 0);
00470
00471 ColorList* cl = GetColorList();
00472 ArrayMapping* map = cl->GenerateRedMapping();
00473 SetBandOrder("RED", 0, map);
00474
00475 cl->GenerateGreenMapping(map);
00476 SetBandOrder("GREEN", 0, map);
00477
00478 cl->GenerateBlueMapping(map);
00479 SetBandOrder("BLUE", 0, map);
00480 delete map;
00481 #endif
00482 break;
00483 default:
00484 TIFFError("TIFFImageRH: ",
00485 "Can not handle image with PhotometricInterpretation=%d",
00486 p->photometric);
00487 return false;
00488 }
00489
00490 TIFFGetField(p->tif, TIFFTAG_ROWSPERSTRIP, &p->rows_per_strip);
00491 TIFFGetField(p->tif, TIFFTAG_COMPRESSION, &p->compression);
00492 TIFFGetField(p->tif, TIFFTAG_PLANARCONFIG, &p->planar_config);
00493
00494 p->compressed = (p->compression != COMPRESSION_NONE);
00495
00496 p->stripsize = TIFFStripSize(p->tif);
00497 p->scanlinesize = TIFFScanlineSize(p->tif);
00498 p->numberofstrips = TIFFNumberOfStrips(p->tif);
00499
00500
00501 #if defined(RIH_DEBUG)
00502 vcl_printf("vil1_tiff: size %dx%d, components %d of %d bits, tiled %d, compressed %d,"
00503 " rows per strip %ld, photometric code %d, stripsize %ld, scanlinesize %ld\n",
00504 this->width(), this->height(), this->components(), this->bits_per_component(),
00505 p->tiled, p->compressed, p->rows_per_strip, p->photometric, p->stripsize, p->scanlinesize);
00506 #endif
00507
00508 static const int MB = 1024 * 1024;
00509 p->jumbo_strips = (!p->compressed && p->stripsize > 2 * MB);
00510
00511
00512 delete [] p->buf;
00513 if (p->jumbo_strips)
00514
00515 p->buf = new unsigned char[width_ * components_ * bits_per_component_ / 8];
00516 else
00517 p->buf = new unsigned char[p->stripsize];
00518
00519 return true;
00520 }
00521
00522 bool vil1_tiff_generic_image::write_header()
00523 {
00524 p->vs->seek(0L);
00525 p->filesize = 0;
00526
00527
00528 if (bits_per_component_>8 && components_ == 1){
00529 TIFFError("TIFFImageWH: ", "TIFF6.0 does not support greater than 8-bit grayscale");
00530 return false;
00531 }
00532
00533 #if 0 // commented out
00534
00535 if (GetArea()*GetBytesPixel() > MIN_AREA_FOR_TILING &&
00536 !(GetBlockSizeX() % 8) && !(GetBlockSizeY() % 8)) {
00537
00538 TIFFSetField(p->tif, TIFFTAG_TILEWIDTH, GetBlockSizeX());
00539 TIFFSetField(p->tif, TIFFTAG_TILELENGTH, GetBlockSizeY());
00540 } else {
00541
00542
00543 TIFFSetField(p->tif, TIFFTAG_ROWSPERSTRIP, GetSizeY());
00544 }
00545 vcl_cerr << "Warning I no longer know how to create a tiled TIFF Image\n"
00546 << "but thats ok because I could never do it right anyway...\n";
00547 #endif
00548
00549
00550 p->tif = TIFFClientOpen("file_formats/vil1_tiff.cxx:374:unknown_filename",
00551 "w",
00552 (thandle_t)p,
00553 vil1_tiff_readproc, vil1_tiff_writeproc,
00554 vil1_tiff_seekproc, vil1_tiff_closeproc,
00555 vil1_tiff_sizeproc,
00556 vil1_tiff_mapfileproc, vil1_tiff_unmapfileproc);
00557
00558 TIFFSetField(p->tif, TIFFTAG_IMAGEWIDTH, width_);
00559 TIFFSetField(p->tif, TIFFTAG_IMAGELENGTH, height_);
00560 TIFFSetField(p->tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
00561
00562
00563
00564 p->rows_per_strip = 1;
00565 TIFFSetField(p->tif, TIFFTAG_ROWSPERSTRIP, p->rows_per_strip);
00566
00567 int samplesperpixel = components_;
00568 TIFFSetField(p->tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
00569
00570 int bitspersample = bits_per_component_;
00571 TIFFSetField(p->tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
00572
00573 p->planar_config = PLANARCONFIG_CONTIG;
00574 TIFFSetField(p->tif, TIFFTAG_PLANARCONFIG, p->planar_config);
00575
00576 #if 0 // commented out
00577 int ncolors = GetColorNum();
00578 if (ncolors && samplesperpixel==1)
00579 {
00580 int mapsize = 1<<bitspersample;
00581
00582 unsigned short *cmap = new unsigned short[mapsize*3];
00583 int** cm = GetColorMap();
00584 for (int i=0; i<3; i++)
00585 {
00586 register int j = 0;
00587 for (; j<ncolors; j++) *cmap++ = (unsigned short)SCALE(cm[i][j]);
00588 for (; j<mapsize; j++) *cmap++ = 0;
00589 }
00590 cmap -= mapsize*3;
00591 TIFFSetField(p->tif, TIFFTAG_COLORMAP, cmap, cmap+mapsize, cmap+2*mapsize);
00592 delete cmap;
00593
00594 TIFFSetField(p->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
00595 }
00596 else
00597 #endif
00598 {
00599 if (components_ == 3)
00600 p->photometric = PHOTOMETRIC_RGB;
00601 else
00602 p->photometric = PHOTOMETRIC_MINISBLACK;
00603 }
00604 TIFFSetField(p->tif, TIFFTAG_PHOTOMETRIC, p->photometric);
00605
00606
00607
00608 p->compression = COMPRESSION_NONE;
00609 TIFFSetField(p->tif, TIFFTAG_COMPRESSION, p->compression);
00610 p->compressed = (p->compression != COMPRESSION_NONE);
00611
00612
00613 TIFFSetField(p->tif, TIFFTAG_SOFTWARE, "VXL core/vil1/file_formats/vil1_tiff.cxx");
00614
00615 p->numberofstrips = TIFFNumberOfStrips(p->tif);
00616 p->scanlinesize = width_ * bitspersample * samplesperpixel / 8;
00617 p->scanlinesize = TIFFScanlineSize(p->tif);
00618 p->stripsize = p->rows_per_strip * p->scanlinesize;
00619 p->tiled = false;
00620
00621
00622 #if 0 // commented out
00623 vcl_time_t clock;
00624 struct tm *t_m;
00625 clock = time(NULL);
00626 t_m = localtime(&clock);
00627 char tmp[20];
00628 char datetime[20];
00629 strftime(tmp,sizeof(datetime),"%c",t_m);
00630 vcl_sprintf(datetime,"%19s",tmp);
00631 TIFFSetField(p->tif, TIFFTAG_DATETIME, datetime);
00632 #endif
00633
00634
00635 delete [] p->buf;
00636 p->buf = new unsigned char[p->stripsize];
00637
00638 #ifdef RIH_DEBUG
00639 vcl_printf("vil1_tiff: size %dx%d, components %d of %d bits, tiled %d, compressed %d,"
00640 " rows per strip %ld, photometric code %d, stripsize %ld, scanlinesize %ld\n",
00641 this->width(), this->height(), this->components(), this->bits_per_component(),
00642 p->tiled, p->compressed, p->rows_per_strip, p->photometric, p->stripsize, p->scanlinesize);
00643 #endif
00644
00645 return true;
00646 }
00647
00648 void vil1_tiff_generic_image::get_resolution(float& x_res, float& y_res, unsigned short& units) const
00649 {
00650 TIFFGetField(p->tif, TIFFTAG_XRESOLUTION, &x_res);
00651 TIFFGetField(p->tif, TIFFTAG_YRESOLUTION, &y_res);
00652 TIFFGetField(p->tif, TIFFTAG_RESOLUTIONUNIT, &units);
00653 }
00654
00655 void vil1_tiff_generic_image::set_resolution(float x_res, float y_res, unsigned short units)
00656 {
00657 TIFFSetField(p->tif, TIFFTAG_XRESOLUTION, x_res);
00658 TIFFSetField(p->tif, TIFFTAG_YRESOLUTION, y_res);
00659 TIFFSetField(p->tif, TIFFTAG_RESOLUTIONUNIT, units);
00660 }
00661
00662 bool vil1_tiff_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00663 {
00664 if (!p->jumbo_strips) {
00665 if (p->tiled)
00666 vcl_cerr << "vil1_tiff_generic_image: TILED TIFF: may be wrongly read?\n";
00667
00668
00669
00670 int y1 = (y0 + ys - 1);
00671 unsigned strip_min = y0 / p->rows_per_strip;
00672 unsigned strip_max = y1 / p->rows_per_strip;
00673 assert(strip_max <= p->numberofstrips);
00674
00675 int pixel_bit_size = components_ * bits_per_component_;
00676 {
00677 for (unsigned long strip_id = strip_min; strip_id <= strip_max; ++strip_id) {
00678 TIFFReadEncodedStrip(p->tif, strip_id, p->buf, (tsize_t) -1);
00679
00680 unsigned long strip_min_row = strip_id * p->rows_per_strip;
00681 unsigned long strip_max_row = strip_min_row + p->rows_per_strip - 1;
00682
00683 long ymin = (long)strip_min_row;
00684 if (ymin < y0) ymin = y0;
00685 long ymax = (long)strip_max_row;
00686 if (ymax > y1) ymax = y1;
00687
00688
00689 for (long y = ymin; y <= ymax; ++y) {
00690 unsigned char* in_row = p->buf + (y - strip_min_row) * p->scanlinesize;
00691 unsigned char* out_row = (unsigned char*)buf + ((y - y0) * xs * pixel_bit_size + 7) / 8;
00692 vcl_memcpy(out_row, in_row + (x0 * pixel_bit_size + 7) / 8, (xs * pixel_bit_size + 7) / 8);
00693 }
00694 }
00695 }
00696 return true;
00697 } else {
00698
00699 return problem("Jumbo strips, and strip chopping appears to be disabled...");
00700 }
00701 }
00702
00703 bool vil1_tiff_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00704 {
00705
00706
00707 int y1 = (y0 + ys - 1);
00708 unsigned strip_min = y0 / p->rows_per_strip;
00709 unsigned strip_max = y1 / p->rows_per_strip;
00710 assert(strip_max <= p->numberofstrips);
00711
00712 int pixel_byte_size = components_ * bits_per_component_ / 8;
00713 for (unsigned long strip_id = strip_min; strip_id <= strip_max; ++strip_id) {
00714
00715 unsigned long strip_min_row = strip_id * p->rows_per_strip;
00716 unsigned long strip_max_row = strip_min_row + p->rows_per_strip - 1;
00717
00718 long ymin = (long)strip_min_row;
00719 if (ymin < y0) ymin = y0;
00720 long ymax = (long)strip_max_row;
00721 if (ymax > y1) ymax = y1;
00722
00723
00724 for (long y = ymin; y <= ymax; ++y) {
00725 unsigned char* file_row = p->buf + (y - strip_min_row) * p->scanlinesize;
00726 const unsigned char* mem_row = (const unsigned char*)buf + (y - y0) * xs * pixel_byte_size;
00727 vcl_memcpy(file_row + x0 * pixel_byte_size, mem_row, xs * pixel_byte_size);
00728 }
00729
00730 TIFFWriteEncodedStrip(p->tif, strip_id, p->buf, (long)(ymax - ymin + 1) * p->scanlinesize);
00731 }
00732 return true;
00733 }
00734
00735 vil1_image vil1_tiff_generic_image::get_plane(unsigned int plane) const
00736 {
00737 assert(plane == 0);
00738 return const_cast<vil1_tiff_generic_image*>(this);
00739 }