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