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.size() > 0) {
00121         TIFFSetField(tiff, TIFFTAG_ICCPROFILE, icc.size(), icc.front());
00122     }
00123 
00124 }
00125 
00126 
00128 template <class ImageIterator, class ImageAccessor,
00129           class AlphaIterator, class AlphaAccessor>
00130 static void
00131 createScalarATiffImage(ImageIterator upperleft, ImageIterator lowerright,
00132                        ImageAccessor a,
00133                        AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00134                        vigra::TiffImage * tiff, int sampleformat)
00135 {
00136     typedef typename ImageAccessor::value_type PixelType;
00137 
00138     int w = lowerright.x - upperleft.x;
00139     int h = lowerright.y - upperleft.y;
00140 
00141     TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
00142     TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
00143     TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(PixelType) * 8);
00144     TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 2);
00145     TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00146     TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, sampleformat);
00147     TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
00148     TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
00149 
00150     // for alpha stuff, do not uses premultilied data
00151     // We do not want to throw away data by premultiplying
00152     uint16 nextra_samples = 1;
00153     uint16 extra_samples = EXTRASAMPLE_UNASSALPHA;
00154     TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, nextra_samples, &extra_samples);
00155 
00156     int bufsize = TIFFScanlineSize(tiff);
00157     tdata_t * buf = new tdata_t[bufsize];
00158 
00159     ImageIterator ys(upperleft);
00160     AlphaIterator ya(alphaUpperleft);
00161 
00162     try
00163     {
00164         for(int y=0; y<h; ++y, ++ys.y, ++ya.y)
00165         {
00166             PixelType * pg = (PixelType *)buf;
00167             PixelType * alpha = pg+1;
00168 
00169             ImageIterator xs(ys);
00170             AlphaIterator xa(ya);
00171 
00172             for(int x=0; x<w; ++x, ++xs.x, pg+=2, alpha+=2, ++xa.x)
00173             {
00174                 *pg = a(xs);
00175                 *alpha = alphaA(xa);
00176             }
00177             TIFFWriteScanline(tiff, buf, y);
00178         }
00179     }
00180     catch(...)
00181     {
00182         delete[] buf;
00183         throw;
00184     }
00185     delete[] buf;
00186 }
00187 
00189 template <class ImageIterator, class ImageAccessor,
00190           class AlphaIterator, class AlphaAccessor>
00191 void
00192 createRGBATiffImage(ImageIterator upperleft, ImageIterator lowerright,
00193                     ImageAccessor a,
00194                     AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00195                     vigra::TiffImage * tiff, int sampleformat)
00196 {
00197     typedef typename ImageAccessor::value_type PType;
00198     typedef typename PType::value_type PixelType;
00199 //    typedef typename ImageAccessor::value_type PixelType;
00200     int w = lowerright.x - upperleft.x;
00201     int h = lowerright.y - upperleft.y;
00202 
00203     TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
00204     TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
00205     TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(PixelType) * 8);
00206     TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
00207     TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00208     TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, sampleformat);
00209     TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
00210     TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
00211                 
00212     // for alpha stuff, do not uses premultilied data
00213     // We do not want to throw away data & accuracy by premultiplying
00214     uint16 nextra_samples = 1;
00215     uint16 extra_samples = EXTRASAMPLE_UNASSALPHA;
00216     TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, nextra_samples, &extra_samples);
00217 
00218     int bufsize = TIFFScanlineSize(tiff);
00219     tdata_t * buf = new tdata_t[bufsize];
00220 
00221     ImageIterator ys(upperleft);
00222     AlphaIterator ya(alphaUpperleft);
00223 
00224     try
00225     {
00226         for(int y=0; y<h; ++y, ++ys.y, ++ya.y)
00227         {
00228             PixelType * pr = (PixelType *)buf;
00229             PixelType * pg = pr+1;
00230             PixelType * pb = pg+1;
00231             PixelType * alpha = pb+1;
00232 
00233             ImageIterator xs(ys);
00234             AlphaIterator xa(ya);
00235 
00236             for(int x=0; x<w; ++x, ++xs.x, pr+=4, pg+=4, pb+=4, alpha+=4, ++xa.x)
00237             {
00238                 *pr = a.red(xs);
00239                 *pg = a.green(xs);
00240                 *pb = a.blue(xs);
00241                 *alpha = alphaA(xa);
00242             }
00243             TIFFWriteScanline(tiff, buf, y);
00244         }
00245     }
00246     catch(...)
00247     {
00248         delete[] buf;
00249         throw;
00250     }
00251     delete[] buf;
00252 }
00253 
00254 // try to add stuff the vigra way
00255 // This are constructor classes, to do a kind of compile time switch
00256 // for the different image types.
00257 template <class T>
00258 struct CreateAlphaTiffImage;
00259 
00260 // 8 bit images
00261 template <>
00262 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned char> >
00263 {
00264     template <class ImageIterator, class ImageAccessor,
00265               class AlphaIterator, class AlphaAccessor>
00266     static void exec(ImageIterator iUL, ImageIterator iLR,
00267                      ImageAccessor iA,
00268                      AlphaIterator aUL,
00269                      AlphaAccessor aA,
00270                      vigra::TiffImage * tiff)
00271     {
00272         createRGBATiffImage(iUL, iLR, iA, aUL, aA, tiff, SAMPLEFORMAT_UINT);
00273     }
00274 };
00275 
00276 // 16 bit
00277 template <>
00278 struct CreateAlphaTiffImage<vigra::RGBValue<short> >
00279 {
00280     template <class ImageIterator, class ImageAccessor,
00281               class AlphaIterator, class AlphaAccessor>
00282     static void exec(ImageIterator iUL, ImageIterator iLR,
00283                      ImageAccessor iA,
00284                      AlphaIterator aUL,
00285                      AlphaAccessor aA,
00286                      vigra::TiffImage * tiff)
00287     {
00288         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<short>,
00289                                        AlphaAccessor>
00290             mA(vigra::ScalarIntensityTransform<short>(128), aA);
00291         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00292                             tiff,  SAMPLEFORMAT_INT);
00293     }
00294 };
00295 
00296 template <>
00297 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned short> >
00298 {
00299     template <class ImageIterator, class ImageAccessor,
00300               class AlphaIterator, class AlphaAccessor>
00301     static void exec(ImageIterator iUL, ImageIterator iLR,
00302                      ImageAccessor iA,
00303                      AlphaIterator aUL,
00304                      AlphaAccessor aA,
00305                      vigra::TiffImage * tiff)
00306     {
00307         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned short>, AlphaAccessor>
00308             mA(vigra::ScalarIntensityTransform<unsigned short>(256), aA);
00309         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00310                             tiff,  SAMPLEFORMAT_UINT);
00311     }
00312 };
00313 
00314 
00315 // 32 bit
00316 template <>
00317 struct CreateAlphaTiffImage<vigra::RGBValue<int> >
00318 {
00319     template <class ImageIterator, class ImageAccessor,
00320               class AlphaIterator, class AlphaAccessor>
00321     static void exec(ImageIterator iUL, ImageIterator iLR,
00322                      ImageAccessor iA,
00323                      AlphaIterator aUL,
00324                      AlphaAccessor aA,
00325                      vigra::TiffImage * tiff)
00326     {
00327         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<int>, AlphaAccessor>
00328             mA(vigra::ScalarIntensityTransform<int>(8388608), aA);
00329         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00330                             tiff,  SAMPLEFORMAT_INT);
00331     }
00332 };
00333 
00334 template <>
00335 struct CreateAlphaTiffImage<vigra::RGBValue<unsigned int> >
00336 {
00337     template <class ImageIterator, class ImageAccessor,
00338               class AlphaIterator, class AlphaAccessor>
00339     static void exec(ImageIterator iUL, ImageIterator iLR,
00340                      ImageAccessor iA,
00341                      AlphaIterator aUL,
00342                      AlphaAccessor aA,
00343                      vigra::TiffImage * tiff)
00344     {
00345         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned int>, AlphaAccessor>
00346             mA(vigra::ScalarIntensityTransform<unsigned int>(16777216), aA);
00347         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00348                             tiff,  SAMPLEFORMAT_UINT);
00349     }
00350 };
00351 
00352 // float
00353 template <>
00354 struct CreateAlphaTiffImage<vigra::RGBValue<float> >
00355 {
00356     template <class ImageIterator, class ImageAccessor,
00357               class AlphaIterator, class AlphaAccessor>
00358     static void exec(ImageIterator iUL, ImageIterator iLR,
00359                      ImageAccessor iA,
00360                      AlphaIterator aUL,
00361                      AlphaAccessor aA,
00362                      vigra::TiffImage * tiff)
00363     {
00364         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<float>, AlphaAccessor>
00365             mA(vigra::ScalarIntensityTransform<float>(1.0f/255), aA);
00366         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00367                             tiff,  SAMPLEFORMAT_IEEEFP);
00368     }
00369 };
00370 
00371 // double
00372 template <>
00373 struct CreateAlphaTiffImage<vigra::RGBValue<double> >
00374 {
00375     template <class ImageIterator, class ImageAccessor,
00376               class AlphaIterator, class AlphaAccessor>
00377     static void exec(ImageIterator iUL, ImageIterator iLR,
00378                      ImageAccessor iA,
00379                      AlphaIterator aUL,
00380                      AlphaAccessor aA,
00381                      vigra::TiffImage * tiff)
00382     {
00383         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<double>, AlphaAccessor>
00384             mA(vigra::ScalarIntensityTransform<double>(1.0f/255),aA);
00385         createRGBATiffImage(iUL, iLR, iA, aUL, mA,
00386                             tiff,  SAMPLEFORMAT_IEEEFP);
00387     }
00388 };
00389 
00390 // ================================================================
00391 // for scalar images
00392 // ================================================================
00393 
00394 // 8 bit images
00395 template <>
00396 struct CreateAlphaTiffImage<unsigned char>
00397 {
00398     template <class ImageIterator, class ImageAccessor,
00399               class AlphaIterator, class AlphaAccessor>
00400     static void exec(ImageIterator iUL, ImageIterator iLR,
00401                      ImageAccessor iA,
00402                      AlphaIterator aUL,
00403                      AlphaAccessor aA,
00404                      vigra::TiffImage * tiff)
00405     {
00406         createScalarATiffImage(iUL, iLR, iA, aUL, aA, tiff,  SAMPLEFORMAT_UINT);
00407     }
00408 };
00409 
00410 // 16 bit
00411 template <>
00412 struct CreateAlphaTiffImage<short>
00413 {
00414     template <class ImageIterator, class ImageAccessor,
00415               class AlphaIterator, class AlphaAccessor>
00416     static void exec(ImageIterator iUL, ImageIterator iLR,
00417                      ImageAccessor iA,
00418                      AlphaIterator aUL,
00419                      AlphaAccessor aA,
00420                      vigra::TiffImage * tiff)
00421     {
00422         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<short>, AlphaAccessor>
00423             mA(vigra::ScalarIntensityTransform<short>(128), aA);
00424         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_INT);
00425     }
00426 };
00427 template <>
00428 struct CreateAlphaTiffImage<unsigned short>
00429 {
00430     template <class ImageIterator, class ImageAccessor,
00431               class AlphaIterator, class AlphaAccessor>
00432     static void exec(ImageIterator iUL, ImageIterator iLR,
00433                      ImageAccessor iA,
00434                      AlphaIterator aUL,
00435                      AlphaAccessor aA,
00436                      vigra::TiffImage * tiff)
00437     {
00438         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned short>, AlphaAccessor>
00439             mA(vigra::ScalarIntensityTransform<unsigned short>(256), aA);
00440         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_UINT);
00441     }
00442 };
00443 
00444 // 32 bit
00445 template <>
00446 struct CreateAlphaTiffImage<int>
00447 {
00448     template <class ImageIterator, class ImageAccessor,
00449               class AlphaIterator, class AlphaAccessor>
00450     static void exec(ImageIterator iUL, ImageIterator iLR,
00451                      ImageAccessor iA,
00452                      AlphaIterator aUL,
00453                      AlphaAccessor aA,
00454                      vigra::TiffImage * tiff)
00455     {
00456         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<int>, AlphaAccessor>
00457             mA(vigra::ScalarIntensityTransform<int>(8388608), aA);
00458         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_INT);
00459     }
00460 };
00461 
00462 template <>
00463 struct CreateAlphaTiffImage<unsigned int>
00464 {
00465     template <class ImageIterator, class ImageAccessor,
00466               class AlphaIterator, class AlphaAccessor>
00467     static void exec(ImageIterator iUL, ImageIterator iLR,
00468                      ImageAccessor iA,
00469                      AlphaIterator aUL,
00470                      AlphaAccessor aA,
00471                      vigra::TiffImage * tiff)
00472     {
00473         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<unsigned int>, AlphaAccessor>
00474             mA(vigra::ScalarIntensityTransform<unsigned int>(16777216), aA);
00475         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_UINT);
00476     }
00477 };
00478 
00479 // float
00480 template <>
00481 struct CreateAlphaTiffImage<float>
00482 {
00483     template <class ImageIterator, class ImageAccessor,
00484               class AlphaIterator, class AlphaAccessor>
00485     static void exec(ImageIterator iUL, ImageIterator iLR,
00486                      ImageAccessor iA,
00487                      AlphaIterator aUL,
00488                      AlphaAccessor aA,
00489                      vigra::TiffImage * tiff)
00490     {
00491         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<float>, AlphaAccessor>
00492             mA(vigra::ScalarIntensityTransform<float>(1.0f/255), aA);
00493         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_IEEEFP);
00494     }
00495 };
00496 
00497 // double
00498 template <>
00499 struct CreateAlphaTiffImage<double>
00500 {
00501     template <class ImageIterator, class ImageAccessor,
00502               class AlphaIterator, class AlphaAccessor>
00503     static void exec(ImageIterator iUL, ImageIterator iLR,
00504                      ImageAccessor iA,
00505                      AlphaIterator aUL,
00506                      AlphaAccessor aA,
00507                      vigra::TiffImage * tiff)
00508     {
00509         vigra_ext::ReadFunctorAccessor<vigra::ScalarIntensityTransform<double>, AlphaAccessor>
00510             mA(vigra::ScalarIntensityTransform<double>(1.0f/255), aA);
00511         createScalarATiffImage(iUL, iLR, iA, aUL, mA, tiff,  SAMPLEFORMAT_IEEEFP);
00512     }
00513 };
00514 
00515 // ============================================================
00516 // ============================================================
00517 
00518 template <class ImageIterator, class ImageAccessor,
00519           class AlphaIterator, class AlphaAccessor>
00520 inline void
00521 createAlphaTiffImage(ImageIterator upperleft, ImageIterator lowerright,
00522                      ImageAccessor a,
00523                      AlphaIterator alphaUpperleft, AlphaAccessor alphaA,
00524                      vigra::TiffImage * tiff)
00525 {
00526     // call right constructor class for this image type
00527     CreateAlphaTiffImage<typename ImageAccessor::value_type>::
00528         exec(upperleft, lowerright, a,
00529              alphaUpperleft, alphaA, tiff);
00530 }
00531 
00541 template <class ImageIterator, class ImageAccessor,
00542           class AlphaIterator, class BImageAccessor>
00543 
00544 void
00545 createAlphaTiffImage(vigra::triple<ImageIterator, ImageIterator, ImageAccessor> src,
00546                      vigra::pair<AlphaIterator, BImageAccessor> alpha,
00547                      vigra::TiffImage * tiff)
00548 {
00549     createAlphaTiffImage(src.first, src.second, src.third,
00550                          alpha.first, alpha.second, tiff);
00551 }
00552 
00553 
00554 
00555 //***************************************************************************
00556 //
00557 //  functions to read tiff files with a single alpha channel,
00558 //  multiple layers and offsets.
00559 //
00560 //***************************************************************************
00561 
00562 
00563 }
00564 
00565 #endif // _TIFFUTILS_H

Generated on 30 Jul 2015 for Hugintrunk by  doxygen 1.4.7