tiffUtils.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00026 #ifndef _TIFFUTILS_H
00027 #define _TIFFUTILS_H
00028 
00029 #include <vigra/tiff.hxx>
00030 #include <vigra/imageinfo.hxx>
00031 #include <vigra/transformimage.hxx>
00032 #include <vigra/functorexpression.hxx>
00033 
00034 #include <vigra_ext/FunctorAccessor.h>
00035 #include <hugin_utils/utils.h>
00036 
00037 #include <tiffio.h>
00038 
00039 // add this to the vigra_ext namespace
00040 namespace vigra_ext {
00041 
00042 
00043 //***************************************************************************
00044 //
00045 //  functions to write tiff files with a single alpha channel.
00046 //
00047 //***************************************************************************
00048 
00058 inline void createTiffDirectory(vigra::TiffImage * tiff, const std::string & pagename,
00059                                 const std::string & documentname,
00060                                 const std::string comp,
00061                                 uint16 page, uint16 nImg,
00062                                 vigra::Diff2D offset,
00063                                 vigra::Size2D fullSize,
00064                                 const vigra::ImageExportInfo::ICCProfile & icc)
00065 {
00066     const float dpi = 150;
00067     // create a new directory for our image
00068     // hopefully I didn't forget too much stuff..
00069     // TIFF tag reference at http://www.awaresystems.be/imaging/tiff/tifftags.html
00070 
00071     // set page
00072     // FIXME: Also only needed for multilayer images
00073     if (nImg > 1) {
00074         // create tiff directory for the new layers
00075         // TIFFOpen already created the first one.
00076         if (page > 1) {
00077             TIFFCreateDirectory (tiff);
00078         }
00079         TIFFSetField (tiff, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
00080         TIFFSetField (tiff, TIFFTAG_PAGENUMBER, (unsigned short)page, (unsigned short)nImg);
00081     }
00082     TIFFSetField (tiff, TIFFTAG_XRESOLUTION, (float) dpi);
00083     TIFFSetField (tiff, TIFFTAG_YRESOLUTION, (float) dpi);
00084     // offsets must allways be positive so correct them
00085     DEBUG_ASSERT(offset.x >= 0);
00086     DEBUG_ASSERT(offset.y >= 0);
00087     TIFFSetField (tiff, TIFFTAG_XPOSITION, (float)(offset.x / dpi));
00088     TIFFSetField (tiff, TIFFTAG_YPOSITION, (float)(offset.y / dpi));
00089 
00090     // TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH
00091     // are set when an image has been cropped out of a larger image.  
00092     // They reflect the size of the original uncropped image.
00093     // The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used
00094     // to determine the position of the smaller image in the larger one.
00095     TIFFSetField(tiff, TIFFTAG_PIXAR_IMAGEFULLWIDTH, fullSize.x);
00096     TIFFSetField(tiff, TIFFTAG_PIXAR_IMAGEFULLLENGTH, fullSize.y);
00097 
00098     // save input name.
00099     TIFFSetField (tiff, TIFFTAG_DOCUMENTNAME, documentname.c_str());
00100     TIFFSetField (tiff, TIFFTAG_PAGENAME, pagename.c_str() );
00101     //
00102     TIFFSetField (tiff, TIFFTAG_IMAGEDESCRIPTION, "stitched with hugin");
00103 
00104     // set compression
00105     unsigned short tiffcomp;
00106     if ( comp == "JPEG" )
00107         tiffcomp = COMPRESSION_OJPEG;
00108     else if ( comp == "LZW" )
00109         tiffcomp = COMPRESSION_LZW;
00110     else if ( comp == "DEFLATE" )
00111         tiffcomp = COMPRESSION_DEFLATE;
00112     else if ( comp == "PACKBITS" )
00113         tiffcomp = COMPRESSION_PACKBITS;
00114     else
00115         tiffcomp = COMPRESSION_NONE;
00116 
00117     TIFFSetField(tiff, TIFFTAG_COMPRESSION, tiffcomp);
00118 
00119     // Set ICC profile, if available.
00120     if (!icc.empty())
00121     {
00122         TIFFSetField(tiff, TIFFTAG_ICCPROFILE, icc.size(), icc.begin());
00123     }
00124 
00125 }
00126 
00127 
00129 template <class ImageIterator, class ImageAccessor,
00130           class AlphaIterator, class AlphaAccessor>
00131 static void
00132 createScalarATiffImage(ImageIterator upperleft, ImageIterator lowerright,
00133                        ImageAccessor a,
00134                        AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00135                        vigra::TiffImage * tiff, int sampleformat)
00136 {
00137     typedef typename ImageAccessor::value_type PixelType;
00138 
00139     int w = lowerright.x - upperleft.x;
00140     int h = lowerright.y - upperleft.y;
00141 
00142     TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
00143     TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
00144     TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(PixelType) * 8);
00145     TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 2);
00146     TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00147     TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, sampleformat);
00148     TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
00149     TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
00150 
00151     // for alpha stuff, do not uses premultilied data
00152     // We do not want to throw away data by premultiplying
00153     uint16 nextra_samples = 1;
00154     uint16 extra_samples = EXTRASAMPLE_UNASSALPHA;
00155     TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, nextra_samples, &extra_samples);
00156 
00157     int bufsize = TIFFScanlineSize(tiff);
00158     tdata_t * buf = new tdata_t[bufsize];
00159 
00160     ImageIterator ys(upperleft);
00161     AlphaIterator ya(alphaUpperleft);
00162 
00163     try
00164     {
00165         for(int y=0; y<h; ++y, ++ys.y, ++ya.y)
00166         {
00167             PixelType * pg = (PixelType *)buf;
00168             PixelType * alpha = pg+1;
00169 
00170             ImageIterator xs(ys);
00171             AlphaIterator xa(ya);
00172 
00173             for(int x=0; x<w; ++x, ++xs.x, pg+=2, alpha+=2, ++xa.x)
00174             {
00175                 *pg = a(xs);
00176                 *alpha = alphaA(xa);
00177             }
00178             TIFFWriteScanline(tiff, buf, y);
00179         }
00180     }
00181     catch(...)
00182     {
00183         delete[] buf;
00184         throw;
00185     }
00186     delete[] buf;
00187 }
00188 
00190 template <class ImageIterator, class ImageAccessor,
00191           class AlphaIterator, class AlphaAccessor>
00192 void
00193 createRGBATiffImage(ImageIterator upperleft, ImageIterator lowerright,
00194                     ImageAccessor a,
00195                     AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00196                     vigra::TiffImage * tiff, int sampleformat)
00197 {
00198     typedef typename ImageAccessor::value_type PType;
00199     typedef typename PType::value_type PixelType;
00200 //    typedef typename ImageAccessor::value_type PixelType;
00201     int w = lowerright.x - upperleft.x;
00202     int h = lowerright.y - upperleft.y;
00203 
00204     TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
00205     TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
00206     TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(PixelType) * 8);
00207     TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
00208     TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00209     TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, sampleformat);
00210     TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
00211     TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
00212                 
00213     // for alpha stuff, do not uses premultilied data
00214     // We do not want to throw away data & accuracy by premultiplying
00215     uint16 nextra_samples = 1;
00216     uint16 extra_samples = EXTRASAMPLE_UNASSALPHA;
00217     TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, nextra_samples, &extra_samples);
00218 
00219     int bufsize = TIFFScanlineSize(tiff);
00220     tdata_t * buf = new tdata_t[bufsize];
00221 
00222     ImageIterator ys(upperleft);
00223     AlphaIterator ya(alphaUpperleft);
00224 
00225     try
00226     {
00227         for(int y=0; y<h; ++y, ++ys.y, ++ya.y)
00228         {
00229             PixelType * pr = (PixelType *)buf;
00230             PixelType * pg = pr+1;
00231             PixelType * pb = pg+1;
00232             PixelType * alpha = pb+1;
00233 
00234             ImageIterator xs(ys);
00235             AlphaIterator xa(ya);
00236 
00237             for(int x=0; x<w; ++x, ++xs.x, pr+=4, pg+=4, pb+=4, alpha+=4, ++xa.x)
00238             {
00239                 *pr = a.red(xs);
00240                 *pg = a.green(xs);
00241                 *pb = a.blue(xs);
00242                 *alpha = alphaA(xa);
00243             }
00244             TIFFWriteScanline(tiff, buf, y);
00245         }
00246     }
00247     catch(...)
00248     {
00249         delete[] buf;
00250         throw;
00251     }
00252     delete[] buf;
00253 }
00254 
00255 // try to add stuff the vigra way
00256 // This are constructor classes, to do a kind of compile time switch
00257 // for the different image types.
00258 template <class T>
00259 struct CreateAlphaTiffImage;
00260 
00261 // 8 bit images
00262 template <>
00263 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned char> >
00264 {
00265     template <class ImageIterator, class ImageAccessor,
00266               class AlphaIterator, class AlphaAccessor>
00267     static void exec(ImageIterator iUL, ImageIterator iLR,
00268                      ImageAccessor iA,
00269                      AlphaIterator aUL,
00270                      AlphaAccessor aA,
00271                      vigra::TiffImage * tiff)
00272     {
00273         createRGBATiffImage(iUL, iLR, iA, aUL, aA, tiff, SAMPLEFORMAT_UINT);
00274     }
00275 };
00276 
00277 // 16 bit
00278 template <>
00279 struct CreateAlphaTiffImage<vigra::RGBValue<short> >
00280 {
00281     template <class ImageIterator, class ImageAccessor,
00282               class AlphaIterator, class AlphaAccessor>
00283     static void exec(ImageIterator iUL, ImageIterator iLR,
00284                      ImageAccessor iA,
00285                      AlphaIterator aUL,
00286                      AlphaAccessor aA,
00287                      vigra::TiffImage * tiff)
00288     {
00289         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<short>,
00290                                        AlphaAccessor>
00291             mA(vigra::ScalarIntensityTransform<short>(128), aA);
00292         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00293                             tiff,  SAMPLEFORMAT_INT);
00294     }
00295 };
00296 
00297 template <>
00298 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned short> >
00299 {
00300     template <class ImageIterator, class ImageAccessor,
00301               class AlphaIterator, class AlphaAccessor>
00302     static void exec(ImageIterator iUL, ImageIterator iLR,
00303                      ImageAccessor iA,
00304                      AlphaIterator aUL,
00305                      AlphaAccessor aA,
00306                      vigra::TiffImage * tiff)
00307     {
00308         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned short>, AlphaAccessor>
00309             mA(vigra::ScalarIntensityTransform<unsigned short>(256), aA);
00310         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00311                             tiff,  SAMPLEFORMAT_UINT);
00312     }
00313 };
00314 
00315 
00316 // 32 bit
00317 template <>
00318 struct CreateAlphaTiffImage<vigra::RGBValue<int> >
00319 {
00320     template <class ImageIterator, class ImageAccessor,
00321               class AlphaIterator, class AlphaAccessor>
00322     static void exec(ImageIterator iUL, ImageIterator iLR,
00323                      ImageAccessor iA,
00324                      AlphaIterator aUL,
00325                      AlphaAccessor aA,
00326                      vigra::TiffImage * tiff)
00327     {
00328         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<int>, AlphaAccessor>
00329             mA(vigra::ScalarIntensityTransform<int>(8388608), aA);
00330         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00331                             tiff,  SAMPLEFORMAT_INT);
00332     }
00333 };
00334 
00335 template <>
00336 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned int> >
00337 {
00338     template <class ImageIterator, class ImageAccessor,
00339               class AlphaIterator, class AlphaAccessor>
00340     static void exec(ImageIterator iUL, ImageIterator iLR,
00341                      ImageAccessor iA,
00342                      AlphaIterator aUL,
00343                      AlphaAccessor aA,
00344                      vigra::TiffImage * tiff)
00345     {
00346         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned int>, AlphaAccessor>
00347             mA(vigra::ScalarIntensityTransform<unsigned int>(16777216), aA);
00348         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00349                             tiff,  SAMPLEFORMAT_UINT);
00350     }
00351 };
00352 
00353 // float
00354 template <>
00355 struct CreateAlphaTiffImage<vigra::RGBValue<float> >
00356 {
00357     template <class ImageIterator, class ImageAccessor,
00358               class AlphaIterator, class AlphaAccessor>
00359     static void exec(ImageIterator iUL, ImageIterator iLR,
00360                      ImageAccessor iA,
00361                      AlphaIterator aUL,
00362                      AlphaAccessor aA,
00363                      vigra::TiffImage * tiff)
00364     {
00365         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<float>, AlphaAccessor>
00366             mA(vigra::ScalarIntensityTransform<float>(1.0f/255), aA);
00367         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00368                             tiff,  SAMPLEFORMAT_IEEEFP);
00369     }
00370 };
00371 
00372 // double
00373 template <>
00374 struct CreateAlphaTiffImage<vigra::RGBValue<double> >
00375 {
00376     template <class ImageIterator, class ImageAccessor,
00377               class AlphaIterator, class AlphaAccessor>
00378     static void exec(ImageIterator iUL, ImageIterator iLR,
00379                      ImageAccessor iA,
00380                      AlphaIterator aUL,
00381                      AlphaAccessor aA,
00382                      vigra::TiffImage * tiff)
00383     {
00384         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<double>, AlphaAccessor>
00385             mA(vigra::ScalarIntensityTransform<double>(1.0f/255),aA);
00386         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00387                             tiff,  SAMPLEFORMAT_IEEEFP);
00388     }
00389 };
00390 
00391 // ================================================================
00392 // for scalar images
00393 // ================================================================
00394 
00395 // 8 bit images
00396 template <>
00397 struct CreateAlphaTiffImage<unsigned char>
00398 {
00399     template <class ImageIterator, class ImageAccessor,
00400               class AlphaIterator, class AlphaAccessor>
00401     static void exec(ImageIterator iUL, ImageIterator iLR,
00402                      ImageAccessor iA,
00403                      AlphaIterator aUL,
00404                      AlphaAccessor aA,
00405                      vigra::TiffImage * tiff)
00406     {
00407         createScalarATiffImage(iUL, iLR, iA, aUL, aA, tiff,  SAMPLEFORMAT_UINT);
00408     }
00409 };
00410 
00411 // 16 bit
00412 template <>
00413 struct CreateAlphaTiffImage<short>
00414 {
00415     template <class ImageIterator, class ImageAccessor,
00416               class AlphaIterator, class AlphaAccessor>
00417     static void exec(ImageIterator iUL, ImageIterator iLR,
00418                      ImageAccessor iA,
00419                      AlphaIterator aUL,
00420                      AlphaAccessor aA,
00421                      vigra::TiffImage * tiff)
00422     {
00423         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<short>, AlphaAccessor>
00424             mA(vigra::ScalarIntensityTransform<short>(128), aA);
00425         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_INT);
00426     }
00427 };
00428 template <>
00429 struct CreateAlphaTiffImage<unsigned short>
00430 {
00431     template <class ImageIterator, class ImageAccessor,
00432               class AlphaIterator, class AlphaAccessor>
00433     static void exec(ImageIterator iUL, ImageIterator iLR,
00434                      ImageAccessor iA,
00435                      AlphaIterator aUL,
00436                      AlphaAccessor aA,
00437                      vigra::TiffImage * tiff)
00438     {
00439         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned short>, AlphaAccessor>
00440             mA(vigra::ScalarIntensityTransform<unsigned short>(256), aA);
00441         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_UINT);
00442     }
00443 };
00444 
00445 // 32 bit
00446 template <>
00447 struct CreateAlphaTiffImage<int>
00448 {
00449     template <class ImageIterator, class ImageAccessor,
00450               class AlphaIterator, class AlphaAccessor>
00451     static void exec(ImageIterator iUL, ImageIterator iLR,
00452                      ImageAccessor iA,
00453                      AlphaIterator aUL,
00454                      AlphaAccessor aA,
00455                      vigra::TiffImage * tiff)
00456     {
00457         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<int>, AlphaAccessor>
00458             mA(vigra::ScalarIntensityTransform<int>(8388608), aA);
00459         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_INT);
00460     }
00461 };
00462 
00463 template <>
00464 struct CreateAlphaTiffImage<unsigned int>
00465 {
00466     template <class ImageIterator, class ImageAccessor,
00467               class AlphaIterator, class AlphaAccessor>
00468     static void exec(ImageIterator iUL, ImageIterator iLR,
00469                      ImageAccessor iA,
00470                      AlphaIterator aUL,
00471                      AlphaAccessor aA,
00472                      vigra::TiffImage * tiff)
00473     {
00474         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned int>, AlphaAccessor>
00475             mA(vigra::ScalarIntensityTransform<unsigned int>(16777216), aA);
00476         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_UINT);
00477     }
00478 };
00479 
00480 // float
00481 template <>
00482 struct CreateAlphaTiffImage<float>
00483 {
00484     template <class ImageIterator, class ImageAccessor,
00485               class AlphaIterator, class AlphaAccessor>
00486     static void exec(ImageIterator iUL, ImageIterator iLR,
00487                      ImageAccessor iA,
00488                      AlphaIterator aUL,
00489                      AlphaAccessor aA,
00490                      vigra::TiffImage * tiff)
00491     {
00492         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<float>, AlphaAccessor>
00493             mA(vigra::ScalarIntensityTransform<float>(1.0f/255), aA);
00494         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_IEEEFP);
00495     }
00496 };
00497 
00498 // double
00499 template <>
00500 struct CreateAlphaTiffImage<double>
00501 {
00502     template <class ImageIterator, class ImageAccessor,
00503               class AlphaIterator, class AlphaAccessor>
00504     static void exec(ImageIterator iUL, ImageIterator iLR,
00505                      ImageAccessor iA,
00506                      AlphaIterator aUL,
00507                      AlphaAccessor aA,
00508                      vigra::TiffImage * tiff)
00509     {
00510         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<double>, AlphaAccessor>
00511             mA(vigra::ScalarIntensityTransform<double>(1.0f/255), aA);
00512         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_IEEEFP);
00513     }
00514 };
00515 
00516 // ============================================================
00517 // ============================================================
00518 
00519 template <class ImageIterator, class ImageAccessor,
00520           class AlphaIterator, class AlphaAccessor>
00521 inline void
00522 createAlphaTiffImage(ImageIterator upperleft, ImageIterator lowerright,
00523                      ImageAccessor a,
00524                      AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00525                      vigra::TiffImage * tiff)
00526 {
00527     // call right constructor class for this image type
00528     CreateAlphaTiffImage<typename ImageAccessor::value_type>::
00529         exec(upperleft, lowerright, a,
00530              alphaUpperleft, alphaA, tiff);
00531 }
00532 
00542 template <class ImageIterator, class ImageAccessor,
00543           class AlphaIterator, class BImageAccessor>
00544 
00545 void
00546 createAlphaTiffImage(vigra::triple<ImageIterator, ImageIterator, ImageAccessor> src,
00547                      vigra::pair<AlphaIterator, BImageAccessor> alpha,
00548                      vigra::TiffImage * tiff)
00549 {
00550     createAlphaTiffImage(src.first, src.second, src.third,
00551                          alpha.first, alpha.second, tiff);
00552 }
00553 
00554 
00555 
00556 //***************************************************************************
00557 //
00558 //  functions to read tiff files with a single alpha channel,
00559 //  multiple layers and offsets.
00560 //
00561 //***************************************************************************
00562 
00563 
00564 }
00565 
00566 #endif // _TIFFUTILS_H

Generated on 20 Apr 2018 for Hugintrunk by  doxygen 1.4.7