1 // -*- c-basic-offset: 4 -*-
2 /** @file nona/RemappedPanoImage.h
3  *
4  *  Contains functions to transform whole images.
5  *  Can use PTools::Transform or PanoCommand::SpaceTransform for the calculations
6  *
7  *  @author Pablo d'Angelo <pablo.dangelo@web.de>
8  *
9  *  $Id$
10  *
11  *  This is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU General Public
13  *  License as published by the Free Software Foundation; either
14  *  version 2 of the License, or (at your option) any later version.
15  *
16  *  This software is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  Lesser General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public
22  *  License along with this software. If not, see
23  *  <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef _NONA_IMAGEREMAPPER_H
28 #define _NONA_IMAGEREMAPPER_H
29 
30 
31 #include <panodata/PanoramaData.h>
32 #include <nona/RemappedPanoImage.h>
33 #include <vigra_ext/impexalpha.hxx>
34 
35 namespace HuginBase {
36 namespace Nona {
37 
38 
39     /** functor to create a remapped image */
40     template <typename ImageType, typename AlphaType>
41     class SingleImageRemapper
42     {
43 
44         public:
SingleImageRemapper()45             SingleImageRemapper() : m_advancedOptions()
46             {};
47 
48             /** create a remapped pano image.
49              *
50              *  The image ownership is transferred to the caller.
51              */
52             virtual RemappedPanoImage<ImageType,AlphaType>* getRemapped(const PanoramaData & pano,
53                                                                         const PanoramaOptions & opts,
54                                                                         unsigned int imgNr,
55                                                                         vigra::Rect2D outputROI,
56                                                                         AppBase::ProgressDisplay* progress) = 0;
57 
~SingleImageRemapper()58             virtual ~SingleImageRemapper() {};
59 
setAdvancedOptions(const HuginBase::Nona::AdvancedOptions advancedOptions)60             void setAdvancedOptions(const HuginBase::Nona::AdvancedOptions advancedOptions)
61             {
62                 m_advancedOptions = advancedOptions;
63             }
64 
65             ///
66             virtual	void release(RemappedPanoImage<ImageType,AlphaType>* d) = 0;
67         protected:
68             HuginBase::Nona::AdvancedOptions m_advancedOptions;
69 
70     };
71 
72 
73     /** functor to create a remapped image, loads image from disk */
74     template <typename ImageType, typename AlphaType>
75     class FileRemapper : public SingleImageRemapper<ImageType, AlphaType>
76     {
77 
78     public:
FileRemapper()79         FileRemapper() : SingleImageRemapper<ImageType, AlphaType>()
80         {
81             m_remapped = 0;
82         }
83 
~FileRemapper()84         virtual ~FileRemapper() {};
85 
86     typedef std::vector<float> LUT;
87 
88 
89     public:
90         ///
loadImage(const PanoramaOptions & opts,vigra::ImageImportInfo & info,ImageType & srcImg,AlphaType & srcAlpha)91         void loadImage(const PanoramaOptions & opts,
92                      vigra::ImageImportInfo & info, ImageType & srcImg,
93                      AlphaType & srcAlpha)
94             {}
95 
96         ///
97         virtual RemappedPanoImage<ImageType, AlphaType>*
98         getRemapped(const PanoramaData & pano, const PanoramaOptions & opts,
99                     unsigned int imgNr, vigra::Rect2D outputROI,
100                     AppBase::ProgressDisplay* progress);
101 
102         ///
release(RemappedPanoImage<ImageType,AlphaType> * d)103         virtual void release(RemappedPanoImage<ImageType,AlphaType>* d)
104             { delete d; }
105 
106 
107     protected:
108         RemappedPanoImage<ImageType,AlphaType> * m_remapped;
109 
110     };
111 
112 
113 
114     /// load a flatfield image and apply the correction
115     template <class FFType, class SrcIter, class SrcAccessor, class DestIter, class DestAccessor>
116     void applyFlatfield(vigra::triple<SrcIter, SrcIter, SrcAccessor> srcImg,
117                         vigra::pair<DestIter, DestAccessor> destImg,
118                         vigra::ImageImportInfo & ffInfo,
119                         double gamma,
120                         double gammaMaxVal,
121                         bool division,
122                         typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote a,
123                         typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote b,
124                         bool dither);
125 
126 
127 
128 }; // namespace
129 }; // namespace
130 
131 
132 
133 
134 //==============================================================================
135 // templated implementations
136 
137 
138 #include <vigra/functorexpression.hxx>
139 #include <vigra_ext/VignettingCorrection.h>
140 
141 
142 namespace HuginBase {
143 namespace Nona {
144 
145 
146 template <typename ImageType, typename AlphaType>
147 RemappedPanoImage<ImageType, AlphaType>*
getRemapped(const PanoramaData & pano,const PanoramaOptions & opts,unsigned int imgNr,vigra::Rect2D outputROI,AppBase::ProgressDisplay * progress)148     FileRemapper<ImageType,AlphaType>::getRemapped(const PanoramaData & pano, const PanoramaOptions & opts,
149                               unsigned int imgNr, vigra::Rect2D outputROI,
150                               AppBase::ProgressDisplay* progress)
151 {
152     typedef typename ImageType::value_type PixelType;
153 
154     //typedef typename vigra::NumericTraits<PixelType>::RealPromote RPixelType;
155     //        typedef typename vigra::BasicImage<RPixelType> RImportImageType;
156     typedef typename vigra::BasicImage<float> FlatImgType;
157 
158     FlatImgType ffImg;
159     AlphaType srcAlpha;
160 
161     // choose image type...
162     const SrcPanoImage & img = pano.getImage(imgNr);
163 
164     vigra::Size2D destSize(opts.getWidth(), opts.getHeight());
165 
166     m_remapped = new RemappedPanoImage<ImageType, AlphaType>;
167 
168     // load image
169 
170     vigra::ImageImportInfo info(img.getFilename().c_str());
171 
172     int width = info.width();
173     int height = info.height();
174 
175     if (opts.remapUsingGPU) {
176         // Extend image width to multiple of 8 for fast GPU transfers.
177         const int r = width % 8;
178         if (r != 0) width += 8 - r;
179     }
180 
181     ImageType srcImg(width, height);
182     m_remapped->m_ICCProfile = info.getICCProfile();
183 
184     if (info.numExtraBands() > 0) {
185         srcAlpha.resize(width, height);
186     }
187     //int nb = info.numBands() - info.numExtraBands();
188     bool alpha = info.numExtraBands() > 0;
189     std::string type = info.getPixelType();
190 
191     SrcPanoImage src = pano.getSrcImage(imgNr);
192 
193     // import the image
194     progress->setMessage("loading", hugin_utils::stripPath(img.getFilename()));
195 
196     if (alpha) {
197         vigra::importImageAlpha(info, vigra::destImage(srcImg),
198                                 vigra::destImage(srcAlpha));
199     } else {
200         vigra::importImage(info, vigra::destImage(srcImg));
201     }
202     // check if the image needs to be scaled to 0 .. 1,
203     // this only works for int -> float, since the image
204     // has already been loaded into the output container
205     double maxv = vigra_ext::getMaxValForPixelType(info.getPixelType());
206     if (maxv != vigra_ext::LUTTraits<PixelType>::max()) {
207         double scale = ((double)vigra_ext::LUTTraits<PixelType>::max()) /  maxv;
208         //std::cout << "Scaling input image (pixel type: " << info.getPixelType() << " with: " << scale << std::endl;
209         transformImage(vigra::srcImageRange(srcImg), destImage(srcImg),
210                        vigra::functor::Arg1()*vigra::functor::Param(scale));
211     }
212 
213     // load flatfield, if needed.
214     if (img.getVigCorrMode() & SrcPanoImage::VIGCORR_FLATFIELD) {
215         // load flatfield image.
216         vigra::ImageImportInfo ffInfo(img.getFlatfieldFilename().c_str());
217         progress->setMessage("flatfield vignetting correction", hugin_utils::stripPath(img.getFilename()));
218         vigra_precondition(( ffInfo.numBands() == 1),
219                            "flatfield vignetting correction: "
220                            "Only single channel flatfield images are supported\n");
221         ffImg.resize(ffInfo.width(), ffInfo.height());
222         vigra::importImage(ffInfo, vigra::destImage(ffImg));
223     }
224     m_remapped->setAdvancedOptions(SingleImageRemapper<ImageType, AlphaType>::m_advancedOptions);
225     // remap the image
226 
227     remapImage(srcImg, srcAlpha, ffImg,
228                pano.getSrcImage(imgNr), opts,
229                outputROI,
230                *m_remapped,
231                progress);
232     return m_remapped;
233 }
234 
235 
236 /// load a flatfield image and apply the correction
237 template <class FFType, class SrcIter, class SrcAccessor, class DestIter, class DestAccessor>
applyFlatfield(vigra::triple<SrcIter,SrcIter,SrcAccessor> srcImg,vigra::pair<DestIter,DestAccessor> destImg,vigra::ImageImportInfo & ffInfo,double gamma,double gammaMaxVal,bool division,typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote a,typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote b,bool dither)238 void applyFlatfield(vigra::triple<SrcIter, SrcIter, SrcAccessor> srcImg,
239                     vigra::pair<DestIter, DestAccessor> destImg,
240                     vigra::ImageImportInfo & ffInfo,
241                     double gamma,
242                     double gammaMaxVal,
243                     bool division,
244                     typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote a,
245                     typename vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote b,
246                     bool dither)
247 {
248     FFType ffImg(ffInfo.width(), ffInfo.height());
249     vigra::importImage(ffInfo, vigra::destImage(ffImg));
250     vigra_ext::flatfieldVigCorrection(srcImg, vigra::srcImage(ffImg),
251                                       destImg, gamma, gammaMaxVal, division, a, b, dither);
252 }
253 
254 
255 }; // namespace
256 }; // namespace
257 
258 #endif // _H
259