core/vil1/file_formats/vil1_tiff.cxx

Go to the documentation of this file.
00001 // This is core/vil1/file_formats/vil1_tiff.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \brief See vil1_tiff.h for a description of this file.
00008 // \author  awf@robots.ox.ac.uk
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   09-NOV-2001  K.Y.McGaul  Use default value for orientation when it can't be read.
00013 // \endverbatim
00014 
00015 #include "vil1_tiff.h"
00016 
00017 #include <vcl_cassert.h>
00018 #if 0 // commented out
00019 #include <vcl_cstdio.h> // sprintf
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 // Constants
00032 char const* vil1_tiff_format_tag = "tiff";
00033 
00034 // Functions
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   // The byte ordering in a TIFF image (usually) depends on the byte-order
00049   // of the writing host. The header is always 4 bytes.
00050 #if 0
00051   short int hdr[2];
00052   int read = is->read(hdr, sizeof hdr);
00053   if (read < 2)
00054     return 0;
00055   // First word specifies the file byte-order (0x4D4D=big, 0x4949=little)
00056   if (hdr[0]!=0x4D4D && hdr[0]!=0x4949)
00057     return 0;
00058   // Second word specifies the TIFF version (we expect v42 for some reason?)
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   // First two bytes specify the file byte-order (0x4D4D=big, 0x4949=little).
00068   // Second two bytes specify the TIFF version (we expect 0x2A for some reason?).
00069   // So,
00070   //   0x4D 0x4D 0x2A 0x00
00071   // and
00072   //   0x49 0x49 0x00 0x2A
00073   // are invalid TIFF headers.
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; // allow it.
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   //delete p->vs;
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   // TODO
00218   return (toff_t)(-1); // could be unsigned - avoid compiler warning
00219 }
00220 
00221 static int vil1_tiff_mapfileproc(thandle_t, tdata_t*, toff_t*)
00222 {
00223   // TODO: Add mmap support to vil1_tiff_mapfileproc
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     // kym - apparently most products ignore this orientation tag and use the default
00246     // value of 1 (eg Adobe Photoshop) so its debatable whether its worth reading at all.
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; // default is to set the property
00273 
00274   if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00275   {
00276     if (topdown == newprop) // no change necessary
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) // no change necessary
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 /*planes*/,
00305                                                  int width,
00306                                                  int height,
00307                                                  int components,
00308                                                  int bits_per_component,
00309                                                  vil1_component_format /*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", // read, enable strip chopping
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   // assume one sample per pixel if not in tiff file
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   // int ncolors = (1 << bitspersample);
00397 
00398   TIFFGetField(p->tif, TIFFTAG_PHOTOMETRIC, &p->photometric);
00399   switch (p->photometric)
00400   {
00401    case PHOTOMETRIC_RGB:
00402     if (!TIFFIsTiled(p->tif)) {
00403       // section_tiff_image = new ForeignImage(GetDescription(), 'r', GetSizeX(), GetSizeY(), GetBitsPixel(), 8);
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       // section_tiff_image = new ForeignImage(GetDescription(), 'r', GetSizeX(), GetSizeY(), GetBitsPixel(), 8);
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      // invert colormap
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     // make sure ncolors is set first or set cm will fail!
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   // Allocate tmp buf
00512   delete [] p->buf;
00513   if (p->jumbo_strips)
00514     // only ever use a scan line
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   // TIFF does not support > 8-bit grayscale
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         // Strips or Tiles?
00535         if (GetArea()*GetBytesPixel() > MIN_AREA_FOR_TILING &&
00536             !(GetBlockSizeX() % 8) && !(GetBlockSizeY() % 8)) {
00537                 // Tiles
00538                 TIFFSetField(p->tif, TIFFTAG_TILEWIDTH, GetBlockSizeX());
00539                 TIFFSetField(p->tif, TIFFTAG_TILELENGTH, GetBlockSizeY());
00540         } else {
00541                 // Strips
00542                 // Think about setting the strip length
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   // hmmm.  single strip image.  good for compression?
00563   //  p->rows_per_strip = height_;
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   // TODO: Choice of compression
00607   //  p->compression = COMPRESSION_LZW;
00608   p->compression = COMPRESSION_NONE;
00609   TIFFSetField(p->tif, TIFFTAG_COMPRESSION, p->compression);
00610   p->compressed = (p->compression != COMPRESSION_NONE);
00611 
00612   // TIFFSetField(p->tif, TIFFTAG_IMAGEDESCRIPTION, GetDescription());
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   // TODO: fix date
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   // Allocate tmp buf
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     // Random access only to strips.
00669     // Get the nearby strips...
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     // Get each strip
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         // Strip contains some rows...
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         // printf("reading strip %d, y  = %d .. %d\n", strip_id, ymin, ymax);
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     // not compressed, and jumbo strips. dig it out manually in case ReadScanLine pulls in all the image
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   // Random access only to strips.
00706   // Put the nearby strips...
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   // Put each strip
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     // Strip contains some rows...
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     // printf("writing strip %d, y  = %d .. %d\n", strip_id, ymin, ymax);
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 }

Generated on Sat Nov 22 05:08:28 2008 for core/vil1 by  doxygen 1.5.1