RemappedPanoImage.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00027 #ifndef _NONA_REMAPPEDPANOIMAGE_H
00028 #define _NONA_REMAPPEDPANOIMAGE_H
00029 
00030 #include <vigra/impex.hxx>
00031 #include <vigra/flatmorphology.hxx>
00032 #include <vigra_ext/ROIImage.h>
00033 
00034 #include <appbase/ProgressDisplayOld.h>
00035 
00036 #include <panodata/SrcPanoImage.h>
00037 #include <panodata/Mask.h>
00038 #include <panodata/PanoramaOptions.h>
00039 #include <panotools/PanoToolsInterface.h>
00040 
00041 
00042 namespace HuginBase {
00043 namespace Nona {
00044 
00045 
00052 template <class TRANSFORM>
00053 void estimateImageRect(const SrcPanoImage & src,
00054                        const PanoramaOptions & dest,
00055                        TRANSFORM & transf,
00056                        vigra::Rect2D & imgRect);
00057 
00059 template <class TRANSFORM>
00060 void estimateImageAlpha(const SrcPanoImage & src,
00061                         const PanoramaOptions & dest,
00062                         TRANSFORM & transf,
00063                         vigra::Rect2D & imgRect,
00064                          vigra::BImage & alpha,
00065                          double & scale);
00066 
00067 
00071 template <class RemapImage, class AlphaImage>
00072 class RemappedPanoImage : public vigra_ext::ROIImage<RemapImage, AlphaImage>
00073 {
00074 
00075         typedef vigra_ext::ROIImage<RemapImage, AlphaImage> Base;
00076 
00077     public:
00078     // typedefs for the children types
00079         typedef typename RemapImage::value_type      image_value_type;
00080         typedef typename RemapImage::traverser       image_traverser;
00081         typedef typename RemapImage::const_traverser const_image_traverser;
00082         typedef typename RemapImage::Accessor        ImageAccessor;
00083         typedef typename RemapImage::ConstAccessor   ConstImageAccessor;
00084 
00085         typedef typename AlphaImage::value_type       mask_value_type;
00086         typedef typename AlphaImage::traverser        mask_traverser;
00087         typedef typename AlphaImage::const_traverser  const_mask_traverser;
00088         typedef typename AlphaImage::Accessor         MaskAccessor;
00089         typedef typename AlphaImage::ConstAccessor    ConstMaskAccessor;
00090 
00091         typedef typename vigra_ext::ValueTypeTraits<image_value_type>::value_type component_type;
00092 
00093         
00094     public:
00099         RemappedPanoImage()
00100         {};
00101 
00102         
00103     public:
00105         void setPanoImage(const SrcPanoImage & src,
00106                           const PanoramaOptions & dest,
00107                           vigra::Rect2D roi);
00108 
00109     //    /** set a new image or panorama options
00110     //     *
00111     //     *  This is needed before any of the remap functions can be used.
00112     //     *
00113     //     *  calculates bounding box, and outline
00114     //     */
00115     //    void setPanoImage(const vigra::Size2D & srcSize,
00116     //                      const PT::VariableMap & srcVars,
00117     //                      PT::Lens::LensProjectionFormat srcProj,
00118     //                      const PT::PanoImage & img,
00119     //                      const vigra::Diff2D &destSize,
00120     //                      PT::PanoramaOptions::ProjectionFormat destProj,
00121     //                      double destHFOV);
00122     //    
00123     //    ///
00124     //    void setPanoImage(const PT::Panorama & pano, unsigned int imgNr,
00125     //                      vigra::Size2D srcSize, const PT::PanoramaOptions & opts);
00126         
00127 
00128     public:
00133         template<class DistImgType>
00134             void calcSrcCoordImgs(DistImgType & imgX, DistImgType & imgY);
00135 
00144         void calcAlpha();
00145 
00147         template <class ImgIter, class ImgAccessor>
00148         void remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
00149                         vigra_ext::Interpolator interpol,
00150                         AppBase::MultiProgressDisplay & progress);
00151 
00152 
00154         template <class ImgIter, class ImgAccessor,
00155                   class AlphaIter, class AlphaAccessor>
00156         void remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
00157                         std::pair<AlphaIter, AlphaAccessor> alphaImg,
00158                         vigra_ext::Interpolator interp,
00159                         AppBase::MultiProgressDisplay & progress);
00160         
00161         
00162     public:
00164         vigra::ImageImportInfo::ICCProfile m_ICCProfile;
00165 
00166     protected:
00167         SrcPanoImage m_srcImg;
00168         PanoramaOptions m_destImg;
00169         PTools::Transform m_transf;
00170 
00171 };
00172 
00173 
00174 
00177 template <class SrcImgType, class FlatImgType, class DestImgType, class MaskImgType>
00178 void remapImage(SrcImgType & srcImg,
00179                 const MaskImgType & srcAlpha,
00180                 const FlatImgType & srcFlat,
00181                 const SrcPanoImage & src,
00182                 const PanoramaOptions & dest,
00183                 vigra::Rect2D outputRect,
00184                 RemappedPanoImage<DestImgType, MaskImgType> & remapped,
00185                 AppBase::MultiProgressDisplay & progress);
00186 
00187 
00188 } // namespace
00189 } // namespace
00190 
00191 
00192 
00193 //==============================================================================
00194 // templated implementations
00195 
00196 
00197 #include <photometric/ResponseTransform.h>
00198 #include <vigra_ext/ImageTransforms.h>
00199 #include <vigra_ext/ImageTransformsGPU.h>
00200 
00201 #ifdef DEBUG
00202 #define DEBUG_REMAP 1
00203 #endif
00204 
00205 #ifdef DEBUG_REMAP
00206 #ifdef WIN32
00207 #define DEBUG_FILE_PREFIX "C:/temp/"
00208 #else
00209 #define DEBUG_FILE_PREFIX "/tmp/"
00210 #endif
00211 #endif
00212 
00213 
00214 namespace HuginBase {
00215 namespace Nona {
00216 
00217 
00218 template <class RemapImage, class AlphaImage>
00219 void RemappedPanoImage<RemapImage,AlphaImage>::setPanoImage(const SrcPanoImage & src,
00220                   const PanoramaOptions & dest, vigra::Rect2D roi)
00221 {
00222     // restrict to panorama size
00223     m_srcImg = src;
00224     m_destImg = dest;
00225 
00226     if (m_destImg.remapUsingGPU) {
00227         // Make width multiple of 8 for fast GPU transfers.
00228         const int r = roi.width() % 8;
00229         if (r != 0) roi.addSize(vigra::Size2D(8 - r, 0));
00230     }
00231 
00232     Base::resize(roi);
00233     m_transf.createTransform(src, dest);
00234 
00235     DEBUG_DEBUG("after resize: " << Base::m_region);
00236     DEBUG_DEBUG("m_srcImg size: " << m_srcImg.getSize());
00237 }
00238 
00239 
00240 #if 0
00241 
00247 template <class RemapImage, class AlphaImage>
00248 void RemappedPanoImage<RemapImage,AlphaImage>::setPanoImage(const vigra::Size2D & srcSize,
00249                   const PT::VariableMap & srcVars,
00250                   PT::Lens::LensProjectionFormat srcProj,
00251                   const PT::PanoImage & img,
00252                   const vigra::Diff2D &destSize,
00253                   PT::PanoramaOptions::ProjectionFormat destProj,
00254                   double destHFOV)
00255 {
00256     m_srcSize = srcSize;
00257     m_srcOrigSize.x = img.getWidth();
00258     m_srcOrigSize.y = img.getHeight();
00259     m_srcProj = m_srcProj;
00260 
00261 
00262     m_srcPanoImg = img;
00263     m_destProj = destProj;
00264     m_destHFOV = destHFOV;
00265     // create transforms
00266     //    SpaceTransform t;
00267     //    SpaceTransform invT;
00268     /*
00269     m_invTransf.createInvTransform(srcSize, srcVars, srcProj,
00270                                    destSize, destProj, destHFOV,
00271                                    m_srcOrigSize);
00272     */
00273     // calculate ROI for this image.
00274     m_transf.createTransform(srcSize, srcVars, srcProj,
00275                              destSize, destProj, destHFOV,
00276                              m_srcOrigSize);
00277 
00278     ImageOptions imgOpts = img.getOptions();
00279 
00280     // todo: resize crop!
00281     bool circCrop = srcProj == Lens::CIRCULAR_FISHEYE;
00282     estimateImageRect(destSize, m_srcOrigSize,
00283                       imgOpts.docrop, imgOpts.cropRect, circCrop,
00284                       m_transf,
00285                       imageRect);
00286 
00287     m_warparound = (destProj == PanoramaOptions::EQUIRECTANGULAR && m_destHFOV == 360);
00288 
00289 
00290 }
00291 
00292 template <class RemapImage, class AlphaImage>
00293 void RemappedPanoImage<RemapImage,AlphaImage>::setPanoImage(const PT::Panorama & pano, unsigned int imgNr,
00294                   vigra::Size2D srcSize, const PT::PanoramaOptions & opts)
00295 {
00296     const PT::PanoImage & img = pano.getImage(imgNr);
00297 
00298     m_srcSize = srcSize;
00299     m_srcOrigSize.x = img.getWidth();
00300     m_srcOrigSize.y = img.getHeight();
00301     m_srcProj = pano.getLens(pano.getImage(imgNr).getLensNr()).getProjection();
00302 
00303     m_destProj = opts.getProjection();
00304     m_destHFOV = opts.getHFOV();
00305     m_warparound = (opts.getProjection() == PanoramaOptions::EQUIRECTANGULAR && opts.getHFOV() == 360);
00306 
00307     // create transforms
00308     //    SpaceTransform t;
00309     //    SpaceTransform invT;
00310 
00311 //        m_invTransf.createInvTransform(pano, imgNr, opts, m_srcSize);
00312     m_transf.createTransform(pano, imgNr, opts, m_srcSize);
00313 
00314     // calculate ROI for this image.
00315     m_srcPanoImg = pano.getImage(imgNr);
00316     ImageOptions imgOpts = pano.getImage(imgNr).getOptions();
00317     vigra::Rect2D imageRect;
00318     // todo: resize crop!
00319     bool circCrop = pano.getLens(pano.getImage(imgNr).getLensNr()).getProjection() == Lens::CIRCULAR_FISHEYE;
00320     estimateImageRect(vigra::Size2D(opts.getWidth(), opts.getHeight()), srcSize,
00321                       imgOpts.docrop, imgOpts.cropRect, circCrop,  
00322                       m_transf,
00323                       imageRect);
00324 
00325 
00326     // restrict to panorama size
00327     Base::resize(imageRect);
00328     DEBUG_DEBUG("after resize: " << Base::m_region);
00329 }
00330 #endif
00331 
00332 
00337 template<class RemapImage, class AlphaImage>
00338 template<class DistImgType>
00339 void RemappedPanoImage<RemapImage,AlphaImage>::calcSrcCoordImgs(DistImgType & imgX, DistImgType & imgY)
00340 {
00341     if (Base::boundingBox().isEmpty()) return;
00342     imgX.resize(Base::boundingBox().size());
00343     imgY.resize(Base::boundingBox().size());
00344     // calculate the alpha channel,
00345     int xstart = Base::boundingBox().left();
00346     int xend   = Base::boundingBox().right();
00347     int ystart = Base::boundingBox().top();
00348     int yend   = Base::boundingBox().bottom();
00349 
00350     // create dist y iterator
00351     typename DistImgType::Iterator yImgX(imgX.upperLeft());
00352     typename DistImgType::Iterator yImgY(imgY.upperLeft());
00353     typename DistImgType::Accessor accX = imgX.accessor();
00354     typename DistImgType::Accessor accY = imgY.accessor();
00355     // loop over the image and transform
00356     for(int y=ystart; y < yend; ++y, ++yImgX.y, ++yImgY.y)
00357     {
00358         // create x iterators
00359         typename DistImgType::Iterator xImgX(yImgX);
00360         typename DistImgType::Iterator xImgY(yImgY);
00361         for(int x=xstart; x < xend; ++x, ++xImgY.x, ++xImgX.x)
00362         {
00363             double sx,sy;
00364             m_transf.transformImgCoord(sx,sy,x,y);
00365             accX.set(sx, xImgX);
00366             accY.set(sy, xImgY);
00367         }
00368     }
00369 }
00370 
00379 template<class RemapImage, class AlphaImage>
00380 void RemappedPanoImage<RemapImage,AlphaImage>::calcAlpha()
00381 {
00382     if (Base::boundingBox().isEmpty())
00383         return;
00384 
00385     Base::m_mask.resize(Base::boundingBox().size());
00386     // calculate the alpha channel,
00387     int xstart = Base::boundingBox().left();
00388     int xend   = Base::boundingBox().right();
00389     int ystart = Base::boundingBox().top();
00390     int yend   = Base::boundingBox().bottom();
00391 
00392 // DGSW FIXME - Unreferenced
00393 //              int interpolHalfWidth=0;
00394     // create dist y iterator
00395     typename AlphaImage::Iterator yalpha(Base::m_mask.upperLeft());
00396     // loop over the image and transform
00397     for(int y=ystart; y < yend; ++y, ++yalpha.y)
00398     {
00399         // create x iterators
00400         typename AlphaImage::Iterator xalpha(yalpha);
00401         for(int x=xstart; x < xend; ++x, ++xalpha.x)
00402         {
00403             double sx,sy;
00404             if(m_transf.transformImgCoord(sx,sy,x,y))
00405             {
00406                 if (m_srcImg.isInside(vigra::Point2D(hugin_utils::roundi(sx),hugin_utils::roundi(sy))))
00407                 {
00408                     *xalpha = 255;
00409                 }
00410                 else
00411                 {
00412                     *xalpha = 0;
00413                 };
00414             }
00415             else
00416             {
00417                 *xalpha = 0;
00418             };
00419         }
00420     }
00421 }
00422 
00424 template<class RemapImage, class AlphaImage>
00425 template<class ImgIter, class ImgAccessor>
00426 void RemappedPanoImage<RemapImage,AlphaImage>::remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
00427                                                           vigra_ext::Interpolator interpol,
00428                                                           AppBase::MultiProgressDisplay & progress)
00429 {
00430 
00431     //        std::ostringstream msg;
00432     //        msg <<"remapping image "  << imgNr;
00433     //        progress.setMessage(msg.str().c_str());
00434 
00435     const bool useGPU = m_destImg.remapUsingGPU;
00436 
00437     if (Base::boundingBox().isEmpty())
00438         return;
00439 
00440     vigra::Diff2D srcImgSize = srcImg.second - srcImg.first;
00441 
00442     vigra::Size2D expectedSize = m_srcImg.getSize();
00443     if (useGPU) {
00444         const int r = expectedSize.width() % 8;
00445         if (r != 0) expectedSize += vigra::Diff2D(8 - r, 0);
00446     }
00447 
00448     DEBUG_DEBUG("srcImgSize: " << srcImgSize << " m_srcImgSize: " << m_srcImg.getSize());
00449     vigra_precondition(srcImgSize == expectedSize, 
00450                        "RemappedPanoImage<RemapImage,AlphaImage>::remapImage(): image sizes not consistent");
00451 
00452     typedef typename ImgAccessor::value_type input_value_type;
00453     typedef typename vigra_ext::ValueTypeTraits<input_value_type>::value_type input_component_type;
00454 
00455     // setup photometric transform for this image type
00456     // this corrects for response curve, white balance, exposure and 
00457     // radial vignetting
00458     Photometric::InvResponseTransform<input_component_type, double> invResponse(m_srcImg);
00459     invResponse.enforceMonotonicity();
00460     if (m_destImg.outputMode == PanoramaOptions::OUTPUT_LDR) {
00461         // select exposure and response curve for LDR output
00462         std::vector<double> outLut;
00463         vigra_ext::EMoR::createEMoRLUT(m_destImg.outputEMoRParams, outLut);
00464         double maxVal = vigra_ext::LUTTraits<input_value_type>::max();
00465         if (m_destImg.outputPixelType.size() > 0) {
00466             maxVal = vigra_ext::getMaxValForPixelType(m_destImg.outputPixelType);
00467         }
00468 
00469         invResponse.setOutput(1.0/pow(2.0,m_destImg.outputExposureValue), outLut,
00470                               maxVal);
00471     } else {
00472         invResponse.setHDROutput(true,1.0/pow(2.0,m_destImg.outputExposureValue));
00473     }
00474 
00475 
00476     if ((m_srcImg.hasActiveMasks()) || (m_srcImg.getCropMode() != SrcPanoImage::NO_CROP))
00477     {
00478         // need to create and additional alpha image for the crop mask...
00479         // not very efficient during the remapping phase, but works.
00480         vigra::BImage alpha(srcImgSize.x, srcImgSize.y);
00481 
00482         switch (m_srcImg.getCropMode()) {
00483         case SrcPanoImage::NO_CROP:
00484             {
00485                 if (useGPU) {
00486                     if (srcImgSize != m_srcImg.getSize()) {
00487                         // src image with was increased for alignment reasons.
00488                         // Need to make an alpha image to mask off the extended region.
00489                         initImage(vigra::destImageRange(alpha),0);
00490                         initImage(alpha.upperLeft(), 
00491                             alpha.upperLeft()+m_srcImg.getSize(),
00492                             alpha.accessor(),255);
00493                     }
00494                     else
00495                         initImage(vigra::destImageRange(alpha),255);
00496                 }
00497                 else
00498                     initImage(vigra::destImageRange(alpha),255);
00499                 break;
00500             }
00501         case SrcPanoImage::CROP_CIRCLE:
00502             {
00503                 vigra::Rect2D cR = m_srcImg.getCropRect();
00504                 hugin_utils::FDiff2D m( (cR.left() + cR.width()/2.0),
00505                         (cR.top() + cR.height()/2.0) );
00506 
00507                 double radius = std::min(cR.width(), cR.height())/2.0;
00508                 // Default the entire alpha channel to opaque..
00509                 initImage(vigra::destImageRange(alpha),255);
00510                 //..crop everything outside the circle
00511                 vigra_ext::circularCrop(vigra::destImageRange(alpha), m, radius);
00512                 break;
00513             }
00514         case SrcPanoImage::CROP_RECTANGLE:
00515             {
00516                 vigra::Rect2D cR = m_srcImg.getCropRect();
00517                 // Default the entire alpha channel to transparent..
00518                 initImage(vigra::destImageRange(alpha),0);
00519                 // Make sure crop is inside the image..
00520                 cR &= vigra::Rect2D(0,0, srcImgSize.x, srcImgSize.y);
00521                 // Opaque only the area within the crop rectangle..
00522                 initImage(alpha.upperLeft()+cR.upperLeft(), 
00523                           alpha.upperLeft()+cR.lowerRight(),
00524                           alpha.accessor(),255);
00525                 break;
00526             }
00527         default:
00528             break;
00529         }
00530         if(m_srcImg.hasActiveMasks())
00531             vigra_ext::applyMask(vigra::destImageRange(alpha), m_srcImg.getActiveMasks());
00532         if (useGPU) {
00533             transformImageAlphaGPU(srcImg,
00534                                    vigra::srcImage(alpha),
00535                                    destImageRange(Base::m_image),
00536                                    destImage(Base::m_mask),
00537                                    Base::boundingBox().upperLeft(),
00538                                    m_transf,
00539                                    invResponse,
00540                                    m_srcImg.horizontalWarpNeeded(),
00541                                    interpol,
00542                                    progress);
00543         } else {
00544             transformImageAlpha(srcImg,
00545                                 vigra::srcImage(alpha),
00546                                 destImageRange(Base::m_image),
00547                                 destImage(Base::m_mask),
00548                                 Base::boundingBox().upperLeft(),
00549                                 m_transf,
00550                                 invResponse,
00551                                 m_srcImg.horizontalWarpNeeded(),
00552                                 interpol,
00553                                 progress);
00554         }
00555     } else {
00556         if (useGPU) {
00557             if (srcImgSize != m_srcImg.getSize()) {
00558                 // src image with was increased for alignment reasons.
00559                 // Need to make an alpha image to mask off the extended region.
00560                 vigra::BImage alpha(srcImgSize.x, srcImgSize.y, vigra::UInt8(0));
00561                 initImage(alpha.upperLeft(), 
00562                           alpha.upperLeft()+m_srcImg.getSize(),
00563                           alpha.accessor(),255);
00564                 transformImageAlphaGPU(srcImg,
00565                                        vigra::srcImage(alpha),
00566                                        destImageRange(Base::m_image),
00567                                        destImage(Base::m_mask),
00568                                        Base::boundingBox().upperLeft(),
00569                                        m_transf,
00570                                        invResponse,
00571                                        m_srcImg.horizontalWarpNeeded(),
00572                                        interpol,
00573                                        progress);
00574 
00575             }
00576             else {
00577                 transformImageGPU(srcImg,
00578                                   destImageRange(Base::m_image),
00579                                   destImage(Base::m_mask),
00580                                   Base::boundingBox().upperLeft(),
00581                                   m_transf,
00582                                   invResponse,
00583                                   m_srcImg.horizontalWarpNeeded(),
00584                                   interpol,
00585                                   progress);
00586             }
00587         } else {
00588             transformImage(srcImg,
00589                            destImageRange(Base::m_image),
00590                            destImage(Base::m_mask),
00591                            Base::boundingBox().upperLeft(),
00592                            m_transf,
00593                            invResponse,
00594                            m_srcImg.horizontalWarpNeeded(),
00595                            interpol,
00596                            progress);
00597         }
00598     }
00599 }
00600 
00601 
00602 
00604 template<class RemapImage, class AlphaImage>
00605 template<class ImgIter, class ImgAccessor,
00606          class AlphaIter, class AlphaAccessor>
00607 void RemappedPanoImage<RemapImage,AlphaImage>::remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
00608                                                           std::pair<AlphaIter, AlphaAccessor> alphaImg,
00609                                                           vigra_ext::Interpolator interp,
00610                                                           AppBase::MultiProgressDisplay & progress)
00611 {
00612     const bool useGPU = m_destImg.remapUsingGPU;
00613 
00614     if (Base::boundingBox().isEmpty())
00615         return;
00616 
00617     vigra::Diff2D srcImgSize = srcImg.second - srcImg.first;
00618 
00619     vigra::Size2D expectedSize = m_srcImg.getSize();
00620     if (useGPU) {
00621         const int r = expectedSize.width() % 8;
00622         if (r != 0) expectedSize += vigra::Diff2D(8 - r, 0);
00623     }
00624 
00625     vigra_precondition(srcImgSize == expectedSize, 
00626                        "RemappedPanoImage<RemapImage,AlphaImage>::remapImage(): image sizes not consistent");
00627 
00628     typedef typename ImgAccessor::value_type input_value_type;
00629     typedef typename vigra_ext::ValueTypeTraits<input_value_type>::value_type input_component_type;
00630 
00631     // setup photometric transform for this image type
00632     // this corrects for response curve, white balance, exposure and 
00633     // radial vignetting
00634     Photometric::InvResponseTransform<input_component_type, double> invResponse(m_srcImg);
00635     if (m_destImg.outputMode == PanoramaOptions::OUTPUT_LDR) {
00636         // select exposure and response curve for LDR output
00637         std::vector<double> outLut;
00638         // scale up to desired output format
00639         double maxVal = vigra_ext::LUTTraits<input_value_type>::max();
00640         if (m_destImg.outputPixelType.size() > 0) {
00641             maxVal = vigra_ext::getMaxValForPixelType(m_destImg.outputPixelType);
00642         }
00643         vigra_ext::EMoR::createEMoRLUT(m_destImg.outputEMoRParams, outLut);
00644                 vigra_ext::enforceMonotonicity(outLut);
00645         invResponse.setOutput(1.0/pow(2.0,m_destImg.outputExposureValue), outLut,
00646                               maxVal);
00647     } else {
00648         invResponse.setHDROutput(true,1.0/pow(2.0,m_destImg.outputExposureValue));
00649     }
00650 
00651     if (((m_srcImg.hasActiveMasks()) || (m_srcImg.getCropMode() != SrcPanoImage::NO_CROP))) {
00652         vigra::BImage alpha(srcImgSize);
00653         vigra::Rect2D cR = m_srcImg.getCropRect();
00654         switch (m_srcImg.getCropMode()) {
00655             case SrcPanoImage::NO_CROP:
00656             {
00657                 // Just copy the source alpha channel and crop it down.
00658                 vigra::copyImage(vigra::make_triple(alphaImg.first,
00659                         alphaImg.first + srcImgSize, alphaImg.second),
00660                         vigra::destImage(alpha));
00661                 break;
00662             }
00663             case SrcPanoImage::CROP_CIRCLE:
00664             {
00665                 // Just copy the source alpha channel and crop it down.
00666                 vigra::copyImage(vigra::make_triple(alphaImg.first,
00667                         alphaImg.first + srcImgSize, alphaImg.second),
00668                         vigra::destImage(alpha));
00669                 hugin_utils::FDiff2D m( (cR.left() + cR.width()/2.0),
00670                             (cR.top() + cR.height()/2.0) );
00671                 double radius = std::min(cR.width(), cR.height())/2.0;
00672                 vigra_ext::circularCrop(vigra::destImageRange(alpha), m, radius);
00673                 break;
00674             }
00675             case SrcPanoImage::CROP_RECTANGLE:
00676             {
00677                 // Intersect the cropping rectangle with the one from the base
00678                 // image to ensure it fits inside.
00679                 cR &= vigra::Rect2D(0,0, srcImgSize.x, srcImgSize.y);
00680 
00681                 // Start with a blank alpha channel for the destination
00682                 initImage(vigra::destImageRange(alpha),0);
00683 
00684                 // Copy in only the area inside the rectangle
00685                 vigra::copyImage(alphaImg.first + cR.upperLeft(),
00686                         alphaImg.first + cR.lowerRight(),
00687                         alphaImg.second,
00688                         alpha.upperLeft() + cR.upperLeft(),alpha.accessor());
00689                 break;
00690             }
00691             default:
00692                 break;
00693         }
00694         if(m_srcImg.hasActiveMasks())
00695             vigra_ext::applyMask(vigra::destImageRange(alpha), m_srcImg.getActiveMasks());
00696 
00697         if (useGPU) {
00698             vigra_ext::transformImageAlphaGPU(srcImg,
00699                                               vigra::srcImage(alpha),
00700                                               destImageRange(Base::m_image),
00701                                               destImage(Base::m_mask),
00702                                               Base::boundingBox().upperLeft(),
00703                                               m_transf,
00704                                               invResponse,
00705                                               m_srcImg.horizontalWarpNeeded(),
00706                                               interp,
00707                                               progress);
00708         } else {
00709             vigra_ext::transformImageAlpha(srcImg,
00710                                            vigra::srcImage(alpha),
00711                                            destImageRange(Base::m_image),
00712                                            destImage(Base::m_mask),
00713                                            Base::boundingBox().upperLeft(),
00714                                            m_transf,
00715                                            invResponse,
00716                                            m_srcImg.horizontalWarpNeeded(),
00717                                            interp,
00718                                            progress);
00719         }
00720     } else {
00721         if (useGPU) {
00722             // extended region (if any) should already be cleared since ImportImageAlpha shouldn't have touched it.
00723             vigra_ext::transformImageAlphaGPU(srcImg,
00724                                               alphaImg,
00725                                               destImageRange(Base::m_image),
00726                                               destImage(Base::m_mask),
00727                                               Base::boundingBox().upperLeft(),
00728                                               m_transf,
00729                                               invResponse,
00730                                               m_srcImg.horizontalWarpNeeded(),
00731                                               interp,
00732                                               progress);
00733         } else {
00734             vigra_ext::transformImageAlpha(srcImg,
00735                                            alphaImg,
00736                                            destImageRange(Base::m_image),
00737                                            destImage(Base::m_mask),
00738                                            Base::boundingBox().upperLeft(),
00739                                            m_transf,
00740                                            invResponse,
00741                                            m_srcImg.horizontalWarpNeeded(),
00742                                            interp,
00743                                            progress);
00744         }
00745     }
00746 }
00747 
00748 
00749 
00750 
00751 
00752 
00755 template <class SrcImgType, class FlatImgType, class DestImgType, class MaskImgType>
00756 void remapImage(SrcImgType & srcImg,
00757                 const MaskImgType & srcAlpha,
00758                 const FlatImgType & srcFlat,
00759                 const SrcPanoImage & src,
00760                 const PanoramaOptions & dest,
00761                 vigra::Rect2D outputROI,
00762 //                vigra_ext::Interpolator interpolator,
00763                 RemappedPanoImage<DestImgType, MaskImgType> & remapped,
00764                 AppBase::MultiProgressDisplay & progress)
00765 {
00766     typedef typename SrcImgType::value_type SrcPixelType;
00767     typedef typename DestImgType::value_type DestPixelType;
00768 
00769     typedef typename vigra::NumericTraits<SrcPixelType>::RealPromote RSrcPixelType;
00770 
00771 #ifdef DEBUG_REMAP
00772     {
00773         vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin03_BeforeRemap.tif");
00774                 vigra::exportImage(vigra::srcImageRange(srcImg), exi);
00775     }
00776     {
00777         if (srcAlpha.width() > 0) {
00778             vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_BeforeRemapAlpha.tif");
00779                     vigra::exportImage(vigra::srcImageRange(srcAlpha), exi);
00780         }
00781     }
00782 #endif
00783 
00784     progress.setMessage(std::string("remapping ") + hugin_utils::stripPath(src.getFilename()));
00785     // set pano image
00786     DEBUG_DEBUG("setting src image with size: " << src.getSize());
00787     remapped.setPanoImage(src, dest, outputROI);
00788     // TODO: add provide support for flatfield images.
00789     if (srcAlpha.size().x > 0) {
00790         remapped.remapImage(vigra::srcImageRange(srcImg),
00791                             vigra::srcImage(srcAlpha), dest.interpolator,
00792                             progress);
00793     } else {
00794         remapped.remapImage(vigra::srcImageRange(srcImg), dest.interpolator, progress);
00795     }
00796 
00797 #ifdef DEBUG_REMAP
00798     {
00799         vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_AfterRemap.tif"); 
00800                 vigra::exportImage(vigra::srcImageRange(remapped.m_image), exi); 
00801     }
00802     {
00803         vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_AfterRemapAlpha.tif");
00804                 vigra::exportImage(vigra::srcImageRange(remapped.m_mask), exi);
00805     }
00806 #endif
00807 }
00808 
00809 
00810 } //namespace
00811 } //namespace
00812 
00813 #endif // _H

Generated on 22 Oct 2014 for Hugintrunk by  doxygen 1.4.7