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

Generated on Wed Sep 17 01:25:39 2014 for Hugintrunk by  doxygen 1.3.9.1