1 // -*- c-basic-offset: 4 -*-
2 
3 /** @file SrcPanoImage.h
4  *
5  *  @brief
6  *
7  *  @author Pablo d'Angelo <pablo.dangelo@web.de>
8  *          James Legg
9  *
10  * !! from PanoImage.h 1970
11  *
12  *  $Id$
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public
16  *  License as published by the Free Software Foundation; either
17  *  version 2 of the License, or (at your option) any later version.
18  *
19  *  This software is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  *  General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public
25  *  License along with this software. If not, see
26  *  <http://www.gnu.org/licenses/>.
27  *
28  */
29 
30 #ifndef _PANODATA_SRCPANOIMAGE_H
31 #define _PANODATA_SRCPANOIMAGE_H
32 
33 // if this file is preprocessed for SWIG, we want to ignore
34 // all the header inclusions that follow:
35 
36 #ifndef _HSI_IGNORE_SECTION
37 
38 #include <hugin_shared.h>
39 #include <hugin_config.h>
40 #include <iostream>
41 #include <vector>
42 #include <vigra/diff2d.hxx>
43 
44 #include <hugin_utils/utils.h>
45 #include <hugin_math/hugin_math.h>
46 #include "PanoramaVariable.h"
47 #include "ImageVariable.h"
48 #include "Mask.h"
49 #include <map>
50 
51 #endif // _HSI_IGNORE_SECTION
52 
53 namespace HuginBase {
54 
55 class Panorama;
56 
57 /** typedef for general map for storing metadata in files */
58 typedef std::map<std::string, std::string> FileMetaData;
59 
60 /** Base class containing all the variables, but missing some of the other
61  * important functions and with some daft accessors.
62  *
63  * Used for lazy metaprogramming, we include image_variables.h several times
64  * with different defintions of image_variable to get all the repetitive bits
65  * out the way. This should reduce typos and cut and paste errors.
66  */
67 class IMPEX BaseSrcPanoImage
68 {
69 public:
70     ///
71     enum Projection {
72         RECTILINEAR = 0,
73         PANORAMIC = 1,
74         CIRCULAR_FISHEYE = 2,
75         FULL_FRAME_FISHEYE = 3,
76         EQUIRECTANGULAR = 4,
77         FISHEYE_ORTHOGRAPHIC = 8,
78         FISHEYE_STEREOGRAPHIC = 10,
79         FISHEYE_EQUISOLID = 21,
80         FISHEYE_THOBY = 20
81     };
82 
83     ///
84     enum CropMode {
85         NO_CROP=0,
86         CROP_RECTANGLE=1,
87         CROP_CIRCLE=2
88     };
89 
90     /// vignetting correction mode (bitflags, no real enum)
91     enum VignettingCorrMode {
92         VIGCORR_NONE = 0,      ///< no vignetting correction
93         VIGCORR_RADIAL = 1,    ///< radial vignetting correction
94         VIGCORR_FLATFIELD = 2, ///< flatfield correction
95         VIGCORR_DIV = 4        ///< correct by division.
96     };
97 
98     ///
99     enum ResponseType {
100         RESPONSE_EMOR=0,                 ///< empirical model of response
101         RESPONSE_LINEAR,                 ///< linear response
102         RESPONSE_GAMMA,                  ///< a simple gamma response curve
103         RESPONSE_FILE,                   ///< load response curve from file (not implemented yet)
104         RESPONSE_ICC                     ///< use ICC for transformation into linear data (not implemented yet)
105     };
106 
107     /// Check that the variables match.
108     bool operator==(const BaseSrcPanoImage & other) const;
109 
110 
111 public:
112     ///
BaseSrcPanoImage()113     BaseSrcPanoImage()
114     {};
115 
~BaseSrcPanoImage()116     virtual ~BaseSrcPanoImage() {};
117 
118     // property accessors
119 public:
120     // get[variable name] functions. Return the value stored in the ImageVariable.
121 #define image_variable( name, type, default_value ) \
122     type get##name() const { return m_##name.getData(); }
123 #include "image_variables.h"
124 #undef image_variable
125 
126     // get[variable name]IV functions. Return a const reference to the ImageVariable.
127 #define image_variable( name, type, default_value ) \
128     const ImageVariable<type > & get##name##IV() const { return m_##name; }
129 #include "image_variables.h"
130 #undef image_variable
131 
132     // set[variable name] functions
133 #define image_variable( name, type, default_value ) \
134     void set##name(type data) { m_##name.setData(data); }
135 #include "image_variables.h"
136 #undef image_variable
137 
138     /* The link[variable name] functions
139      * Pass a pointer to another SrcPanoImg and the respective image variable
140      * will be shared between the images. Afterwards, changing the variable with
141      * set[variable name] on either image also sets the other image.
142      */
143 #define image_variable( name, type, default_value ) \
144     void link##name (BaseSrcPanoImage * target) \
145     { m_##name.linkWith(&(target->m_##name)); }
146 #include "image_variables.h"
147 #undef image_variable
148 
149     /* The unlink[variable name] functions
150      * Unlinking a variable makes it unique to this image. Then changing it will
151      * not affect the other images.
152      */
153 #define image_variable( name, type, default_value ) \
154     void unlink##name () \
155     { m_##name.removeLinks(); }
156 #include "image_variables.h"
157 #undef image_variable
158 
159     /* The [variable name]isLinked functions
160      * Returns true if the variable has links, or false if it is independant.
161      */
162 #define image_variable( name, type, default_value ) \
163     bool name##isLinked () const \
164     { return m_##name.isLinked(); }
165 #include "image_variables.h"
166 #undef image_variable
167 
168     /* The [variable name]isLinkedWith functions
169      * Returns true if the variable is linked with the equivalent variable in
170      * the specified image, false otherwise.
171      */
172 #define image_variable( name, type, default_value ) \
173     bool name##isLinkedWith (const BaseSrcPanoImage & image) const \
174     { return m_##name.isLinkedWith(&(image.m_##name)); }
175 #include "image_variables.h"
176 #undef image_variable
177 
178 protected:
179     // the image variables m_[variable name]
180 #define image_variable( name, type, default_value ) \
181     ImageVariable<type> m_##name {ImageVariable<type>(default_value)};
182 #include "image_variables.h"
183 #undef image_variable
184 };
185 
186 
187 /** All variables of a source image.
188  *
189  *  In the long term, this simplified class will replace
190  *  PanoImage and Image options and the variables array.
191  *  All image variables are stored in this class, regardless of what the
192  *  variable is attached to (lens, sensor, position).
193  */
194 class IMPEX SrcPanoImage : public BaseSrcPanoImage
195 {
196 public:
197     ///
SrcPanoImage()198     SrcPanoImage() :BaseSrcPanoImage()
199     {};
200 
SrcPanoImage(const BaseSrcPanoImage::Projection projection,const double hfov,const vigra::Size2D size)201     SrcPanoImage(const BaseSrcPanoImage::Projection projection, const double hfov, const vigra::Size2D size) :BaseSrcPanoImage()
202     {
203         setProjection(projection);
204         setHFOV(hfov);
205         setSize(size);
206     };
207 
~SrcPanoImage()208     virtual ~SrcPanoImage() {};
209 public:
210     /** "resize" image,
211      *  adjusts all distortion coefficients for usage with a source image
212      *  of size @p size
213      */
214     void resize(const vigra::Size2D & size);
215 
216     /** check if a coordinate is inside the source image
217      */
218     bool isInside(vigra::Point2D p, bool ignoreMasks=false) const;
219 
220     ///
221     bool horizontalWarpNeeded();
222 
223     // Accessors
224     // These are either:
225     // #- extra ones that are derived from image varibles, or
226     // #- replacements where we need extra processing.
227 public:
228     bool getCorrectTCA() const;
229 
230     /** Set the crop mode.
231      *
232      * This sets the cropping region to the entire image when set to NO_CROP,
233      * unlike the lazy metaprogrammed equivalent in BaseSrcPanoImage.
234      */
235     void setCropMode(CropMode val);
236 
237     /** returns true, if projection requires cicular crop */
238     bool isCircularCrop() const;
239 
240     /** Set the image size in pixels
241      *
242      * If we aren't cropping the image, set the size to the entire image
243      */
244     void setSize(vigra::Size2D val);
245 
246     hugin_utils::FDiff2D getRadialDistortionCenter() const;
247 
248     hugin_utils::FDiff2D getRadialVigCorrCenter() const;
249 
250     // these are linked to ExposureValue, which is done with the above.
251     // exposure value  is log2 of inverse exposure factor.
252     double getExposure() const;
253     void setExposure(const double & val);
254 
255 
256     /** Get the width of the image in pixels.
257      *
258      * Should not be used, use getSize().width() instead.
259      * This is here for compatiblity with PnaoImage, but should be removed.
260      *
261      * @todo replace all calls to getWidth() with getSize().width().
262      */
getWidth()263     int getWidth() const
264     { return getSize().width(); }
265 
266     /** Get the height of the image in pixels.
267      *
268      * Should not be used, use getSize().height() instead.
269      * This is here for compatiblity with PnaoImage, but should be removed.
270      *
271      * @todo replace all calls to getHeight() with getSize().height().
272      */
getHeight()273     int getHeight() const
274     { return getSize().height(); }
275 
276     double getVar(const std::string & name) const;
277 
278     void setVar(const std::string & name, double val);
279 
280     /** Return all the image variables in a variable map
281      *
282      * Returns a map of all the variables for this image. It is adivisable to
283      * use the individual getX functions where apropriate instead.
284      *
285      * @todo remove this infavour of the individual get*() functions. This
286      * creates a map of all the variables, regardless of which ones are actually
287      * needed, every time it is called.
288      */
289     VariableMap getVariableMap() const;
290 
291     /** try to convert Exif date time string to struct tm
292      *  @return 0, if conversion was sucessfull */
293     const int getExifDateTime(struct tm* datetime) const;
294 
295     /** unlinking vignetting parameters should unlink the vignetting correction mode
296      */
unlinkRadialVigCorrCoeff()297     void unlinkRadialVigCorrCoeff ()
298     {
299         m_RadialVigCorrCoeff.removeLinks();
300         m_VigCorrMode.removeLinks();
301     }
302 
303     /** unlinking vignetting parameters should unlink the vignetting correction mode
304      */
unlinkRadialVigCorrCenterShift()305     void unlinkRadialVigCorrCenterShift ()
306     {
307         m_RadialVigCorrCenterShift.removeLinks();
308         m_VigCorrMode.removeLinks();
309     }
310 
311     /** unlinking the EMOR parameters should unlink the correction mode.
312      */
unlinkEMoRParams()313     void unlinkEMoRParams ()
314     {
315         m_EMoRParams.removeLinks();
316         m_ResponseType.removeLinks();
317     }
318 
319     /** linking vignetting parameters should link the vignetting correction mode
320      */
linkRadialVigCorrCoeff(SrcPanoImage * target)321     void linkRadialVigCorrCoeff (SrcPanoImage * target)
322     {
323         m_RadialVigCorrCoeff.linkWith(&(target->m_RadialVigCorrCoeff));
324         m_VigCorrMode.linkWith(&(target->m_VigCorrMode));
325     }
326 
327     /** linking vignetting parameters should link the vignetting correction mode
328      */
linkRadialVigCorrCenterShift(SrcPanoImage * target)329     void linkRadialVigCorrCenterShift (SrcPanoImage * target)
330     {
331         m_RadialVigCorrCenterShift.linkWith(&(target->m_RadialVigCorrCenterShift));
332         m_VigCorrMode.linkWith(&(target->m_VigCorrMode));
333     }
334 
335     /** linking the EMOR parameters should link the correction mode.
336      */
linkEMoRParams(SrcPanoImage * target)337     void linkEMoRParams (SrcPanoImage * target)
338     {
339         m_EMoRParams.linkWith(&(target->m_EMoRParams));
340         m_ResponseType.linkWith(&(target->m_ResponseType));
341     }
342 
linkStack(SrcPanoImage * target)343     void linkStack (SrcPanoImage * target)
344     { m_Stack.linkWith(&(target->m_Stack)); }
345 
346     /** check if the image size is known, if try to load the information from the file */
347     bool checkImageSizeKnown();
348     /** try to fill out information about the image, by examining the exif data
349     */
350     bool readEXIF();
351     /** apply values found in EXIF data to SrcPanoImage class, call readEXIF() before to initialize some values*/
352     bool applyEXIFValues(bool applyEVValue=true);
353 
354     /** calculate hfov of an image given focal length, image size and crop factor */
355     static double calcHFOV(SrcPanoImage::Projection proj, double fl, double crop, vigra::Size2D imageSize);
356 
357     /** calcualte focal length, given crop factor and hfov */
358     static double calcFocalLength(SrcPanoImage::Projection proj, double hfov, double crop, vigra::Size2D imageSize);
359 
360     /** calculate crop factor, given focal length and hfov */
361     static double calcCropFactor(SrcPanoImage::Projection proj, double hfov, double focalLength, vigra::Size2D imageSize);
362 
363     /** calculate exposure value */
364     double calcExifExposureValue();
365 
366     /** updates the focal length, changes the hfov to reflect thew newFocalLength */
367     void updateFocalLength(double newFocalLength);
368     /** updates the crop factor, the hfov is calculates so that focal length remains the same */
369     void updateCropFactor(double focalLength, double newCropFactor);
370 
371     /** tries to read cropfactor from lens database
372         you need to call SrcPanoImage::readEXIF before to fill some values
373         @return true, if information could be read from database */
374     bool readCropfactorFromDB();
375     /** tries to read projection and crop area from lens database
376         you need to call SrcPanoImage::readEXIF before to fill some values
377         @param ignoreFovRectilinear if this parameter is true, the fov of
378           rectilinear is not read from the database, otherwise the hfov
379           is populated with the value from the database
380         @return true, if information could be read from database */
381     bool readProjectionFromDB(const bool ignoreFovRectilinear=true);
382     /** tries to read distortion data from lens database
383         you need to call SrcPanoImage::readEXIF before to fill some values
384         @return true, if information could be read from database */
385     bool readDistortionFromDB();
386     /** tries to read vignetting data from lens database
387         you need to call SrcPanoImage::readEXIF before to fill some values
388         @return true, if information could be read from database */
389     bool readVignettingFromDB();
390     /** constructs the lens name for the database
391         it is the lensname if known, for compact cameras it is constructed from camera maker and camera model */
392     std::string getDBLensName() const;
393 
394     /** returns true, if image has masks associated */
395     bool hasMasks() const;
396     /** returns true, if image has positive masks */
397     bool hasPositiveMasks() const;
398     /** returns true, if image has active masks */
399     bool hasActiveMasks() const;
400     /** add newMask to list of masks */
401     void addMask(MaskPolygon newMask);
402     /** add newMask to list of active masks */
403     void addActiveMask(MaskPolygon newMask);
404     /** clears list of active masks */
405     void clearActiveMasks();
406     /** changes type of mask with index to given newType */
407     void changeMaskType(unsigned int index, HuginBase::MaskPolygon::MaskType newType);
408     /** delete mask at index */
409     void deleteMask(unsigned int index);
410     /** delete all masks */
411     void deleteAllMasks();
412     /** writes all mask lines to stream, using given image number */
413     void printMaskLines(std::ostream &o, unsigned int newImgNr) const;
414     /** returns true, if point p is inside of one mask polygon */
415     bool isInsideMasks(vigra::Point2D p) const;
416 
417 private:
418 
419     /** Check if Exiv orientation tag can be trusted */
420     bool trustExivOrientation();
421 };
422 
423 typedef std::vector<SrcPanoImage> ImageVector;
424 
425 } // namespace
426 
427 #endif // PANOIMAGE_H
428