Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PanoramaOptions.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
51 #include <hugin_config.h>
52 
53 #include "PanoramaOptions.h"
54 
55 #include <hugin_utils/utils.h>
56 #include <hugin_math/hugin_math.h>
58 
59 
60 namespace HuginBase {
61 
63 {
64  assert((int)f <= (int)FILEFORMAT_NULL);
65  return fileformatNames[(int) f];
66 }
67 
68 const std::string & PanoramaOptions::getOutputExtension() const
69 {
70  assert((int)outputFormat < (int)FILEFORMAT_NULL);
71  return fileformatExt[(int) outputFormat];
72 }
73 
75 {
76  int max = (int) FILEFORMAT_NULL;
77  int i;
78  for (i=0; i<max; i++) {
79  if (name == fileformatNames[i]) {
80  break;
81  }
82  }
83  if (i+1 == max) {
84  DEBUG_ERROR("could not parse format " << name );
85  return TIFF_m;
86  }
87  return (FileFormat) i;
88 }
89 
90 
91 void PanoramaOptions::printScriptLine(std::ostream & o, bool forPTOptimizer) const
92 {
93  o << "p f" << m_projectionFormat << " w" << getWidth()<< " h" << getHeight()
94  << " v" << getHFOV() << " ";
95 
96  if (! forPTOptimizer) {
97  // anchor for photometric optimizer
98  o << " k" << colorReferenceImage;
99  // the new exposure options
100  o << " E" << outputExposureValue;
101  o << " R" << outputMode;
102  if (!outputPixelType.empty()) {
103  o << " T" << outputPixelType;
104  }
105  if (m_roi != vigra::Rect2D(m_size)) {
106  o << " S" << m_roi.left() << "," << m_roi.right() << "," << m_roi.top() << "," << m_roi.bottom();
107  }
108  }
109 
110  if (!m_projectionParams.empty()) {
111  o << " P\"";
112  for (int i=0; i < (int) m_projectionParams.size(); i++) {
113  o << m_projectionParams[i];
114  if (i+1 < (int)m_projectionParams.size())
115  o << " ";
116  }
117  o << "\"";
118  }
119  o << " n\"" << getFormatName(outputFormat);
120  if ( outputFormat == JPEG || outputFormat == JPEG_m) {
121  o << " q" << quality;
122  } else if ( outputFormat == TIFF ||
123  outputFormat == TIFF_m ||
124  outputFormat == TIFF_mask ||
127  {
128  o << " c:" << tiffCompression;
129  if (tiff_saveROI) {
130  o << " r:CROP";
131  }
132  }
133  o << "\"";
134  o << std::endl;
135 
136  // misc options
137  o << "m i" << interpolator;
138 
139  o << std::endl;
140 }
141 
143 {
144  // post new projection type
145  if ((int) f >= panoProjectionFormatCount()) {
146  // reset to equirect if this projection is not known
147  f = EQUIRECTANGULAR;
148  }
149  m_projectionFormat = f;
150 
151  /* Load constant features of the new projection */
152  panoProjectionFeaturesQuery(f, &m_projFeatures);
153  /* post default projection parameters and corresponding FOV limits */
154  m_projectionParams.resize(m_projFeatures.numberOfParameters);
155  // reset projection parameters to default, determine also new fov limits, clip current fovs...
157 }
158 
159 
160 void PanoramaOptions::setProjectionParameters(const std::vector<double> & params)
161 {
162  assert(m_projFeatures.numberOfParameters == (int) params.size());
163  // check if the parameters are good.
164  if (m_projFeatures.numberOfParameters == (int) params.size()) {
165  m_projectionParams = params;
166  // enforce limits.
167  for (size_t i=0; i < params.size(); i++) {
168  if (m_projectionParams[i] > m_projFeatures.parm[i].maxValue) {
169  m_projectionParams[i] = m_projFeatures.parm[i].maxValue;
170  }
171  if (m_projectionParams[i] < m_projFeatures.parm[i].minValue) {
172  m_projectionParams[i] = m_projFeatures.parm[i].minValue;
173  }
174  }
175  }
176  /* get dynamic FOV limits corresponding to the new parameters,
177  clip current fovs to those limits, and post the results
178  */
179  double parms[PANO_PROJECTION_MAX_PARMS];
180  double fovs[2];
181  int i;
182  for( i = 0; i < m_projFeatures.numberOfParameters; i++){
183  parms[i] = m_projectionParams[i];
184  }
185  if( queryFOVLimits((int)m_projectionFormat, parms, fovs )){
186  m_projFeatures.maxHFOV = fovs[0];
187  m_projFeatures.maxVFOV = fovs[1];
188  }
189  setHFOV( m_hfov, false );
190  setVFOV( getVFOV() );
191 }
192 
194 {
195  std::vector<double> defParam(m_projFeatures.numberOfParameters);
196  for(int i = 0; i < m_projFeatures.numberOfParameters; i++)
197  {
198  defParam[i] = m_projFeatures.parm[i].defValue;
199  };
200  setProjectionParameters(defParam);
201 };
202 
204 {
205  /* Ideally this attribute should come from libpano */
206  return ( f == RECTILINEAR
207  || f == CYLINDRICAL
208  || f == EQUIRECTANGULAR
209  || f == MERCATOR
210  || f == SINUSOIDAL
211  || f == MILLER_CYLINDRICAL
212  || f == PANINI
213  || f == ARCHITECTURAL
214  || f == EQUI_PANINI
215  || f == BIPLANE
216  || f == TRIPLANE
217  || f == GENERAL_PANINI
218  );
219 }
220 
221 
222 void PanoramaOptions::setWidth(unsigned int w, bool keepView)
223 {
225  if (w%2 == 1) {
226  w = w+1;
227  }
228  }
229  bool nocrop = (m_roi == vigra::Rect2D(m_size));
230  double scale = w / (double) m_size.x;
231  m_size.x = w;
232  if (nocrop) {
233  m_roi = vigra::Rect2D(m_size);
234  } else {
235  // for now, do a simple proportional scaling
236  m_roi.setUpperLeft(vigra::Point2D(hugin_utils::roundi(scale*m_roi.left()), m_roi.top()));
237  m_roi.setLowerRight(vigra::Point2D(hugin_utils::roundi(scale*m_roi.right()), m_roi.bottom()));
238  // ensure ROI is inside the panorama
239  m_roi &= vigra::Rect2D(m_size);
240  }
241 
242  if (keepView) {
243  m_size.y = hugin_utils::roundi(m_size.y*scale);
244  if (nocrop) {
245  m_roi = vigra::Rect2D(m_size);
246  } else {
247  m_roi.setUpperLeft(vigra::Point2D(m_roi.left(), hugin_utils::roundi(scale*m_roi.top())));
248  m_roi.setLowerRight(vigra::Point2D(m_roi.right(), hugin_utils::roundi(scale*m_roi.bottom())));
249  // ensure ROI is inside the panorama
250  m_roi &= vigra::Rect2D(m_size);
251  }
253  if (getVFOV() > getMaxVFOV()) {
254  setVFOV(getMaxVFOV());
255  }
256  }
257  }
258 
259  DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << " => vfov: " << getVFOV());
260 }
261 
262 void PanoramaOptions::setHeight(unsigned int h)
263 {
264  bool nocrop = (m_roi == vigra::Rect2D(m_size));
265 
266  if (h == 0) {
267  h = 1;
268  }
269  int dh = h - m_size.y;
270  m_size.y = h;
271  if (nocrop) {
272  m_roi = vigra::Rect2D(m_size);
273  } else {
274  // move ROI
275  m_roi.moveBy(0,dh/2);
276  m_roi &= vigra::Rect2D(m_size);
277  }
278 
279  DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi:" << m_roi << " => vfov: " << getVFOV() );
280 }
281 
282 void PanoramaOptions::setHFOV(double h, bool keepView)
283 {
284  if (keepView && !fovCalcSupported(m_projectionFormat)) {
285  DEBUG_NOTICE("Ignoring keepView");
286  keepView = false;
287  }
288 
289  if (h <= 0) {
290  h = 1;
291  }
292  double vfov;
293  if (keepView) {
294  vfov = getVFOV();
295  }
296  m_hfov = std::min(h, getMaxHFOV());
297  if (keepView) {
298  setVFOV(std::min(vfov, getMaxVFOV()));
299  }
300 }
301 
302 void PanoramaOptions::setVFOV(double VFOV)
303 {
304  VFOV = std::min(VFOV, getMaxVFOV());
305 
307  return;
308  }
309 
310  bool nocrop = (m_roi == vigra::Rect2D(m_size));
311 
312  if (VFOV <= 0) {
313  VFOV = 1;
314  }
315  // TODO: create transform from equirect to target projection and
316  // set additional
317  PTools::Transform transf;
318  SrcPanoImage src;
319  src.setProjection(SrcPanoImage::EQUIRECTANGULAR);
320  src.setHFOV(360);
321  src.setSize(vigra::Size2D(360,180));
322  transf.createInvTransform(src, *this);
323 
324  hugin_utils::FDiff2D pmiddle;
325 
326  if (VFOV>180 && getMaxVFOV() > 180) {
327  // we have crossed the pole
328  transf.transform(pmiddle, hugin_utils::FDiff2D(180, 180 - VFOV / 2 - 0.01));
329  } else {
330  transf.transform(pmiddle, hugin_utils::FDiff2D(0, VFOV / 2));
331  }
332  // try to keep the same ROI
333  vigra::Size2D oldSize = m_size;
334  m_size.y = abs(hugin_utils::roundi(2*pmiddle.y));
335 
336  if (nocrop) {
337  m_roi = vigra::Rect2D(m_size);
338  } else {
339  // adjust ROI to stay in previous position
340  int dh = m_size.y - oldSize.y;
341  m_roi.moveBy(0, dh/2);
342  // ensure ROI is visible
343  m_roi &= vigra::Rect2D(m_size);
344  }
345 
346  DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << " => vfov: " << VFOV);
347 
348 }
349 
351 {
352  // calcuale VFOV based on current panorama
353  PTools::Transform transf;
354  SrcPanoImage src;
355  src.setProjection(SrcPanoImage::EQUIRECTANGULAR);
356  src.setHFOV(360);
357  src.setSize(vigra::Size2D(360,180));
358  transf.createTransform(src, *this);
359 
360  hugin_utils::FDiff2D pmiddle;
361  if (transf.transform(pmiddle, hugin_utils::FDiff2D(0, m_size.y / 2.0)))
362  {
363  double VFOV;
364  if (pmiddle.x > 90 || pmiddle.y < -90)
365  {
366  // the pole has been crossed
367  VFOV = 2 * (180 - pmiddle.y);
368  }
369  else
370  {
371  VFOV = 2 * pmiddle.y;
372  }
373  DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << " => vfov: " << VFOV);
374  return VFOV;
375  }
376  else
377  {
378  DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << " => vfov: " << getMaxVFOV() << " (setting to max)");
379  return getMaxVFOV();
380  }
381 }
382 
383 const std::string PanoramaOptions::fileformatNames[] =
384 {
385  "JPEG",
386  "JPEG_m",
387  "PNG",
388  "PNG_m",
389  "TIFF",
390  "TIFF_m",
391  "TIFF_mask",
392  "TIFF_multilayer",
393  "TIFF_multilayer_mask",
394  "PICT",
395  "PSD",
396  "PSD_m",
397  "PSD_mask",
398  "PAN",
399  "IVR",
400  "IVR_java",
401  "VRML",
402  "QTVR",
403  "HDR",
404  "HDR_m",
405  "EXR",
406  "EXR_m"
407 };
408 
409 
410 const std::string PanoramaOptions::fileformatExt[] =
411 {
412  "jpg",
413  "jpg",
414  "png",
415  "png",
416  "tif",
417  "tif",
418  "tif",
419  "tif",
420  "tif",
421  "pict",
422  "psd",
423  "psd",
424  "psd",
425  "pan",
426  "ivr",
427  "IVR_java",
428  "wrl",
429  "mov",
430  "hdr",
431  "hdr",
432  "exr",
433  "exr"
434 };
435 
436 
437 
438 
439 
440 } //namespace
void setHeight(unsigned int h)
set panorama height
pano_projection_features m_projFeatures
int roundi(T x)
Definition: hugin_math.h:73
#define DEBUG_NOTICE(msg)
Definition: utils.h:70
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
misc math function &amp; classes used by other parts of the program
unsigned int getHeight() const
get panorama height
double getMaxHFOV() const
get maximum possible hfov with current projection
void setProjectionParameters(const std::vector< double > &params)
set the optional parameters (they need to be of the correct size)
bool transform(double &x_dest, double &y_dest, double x_src, double y_src) const
excecute transform
static FileFormat getFormatFromName(const std::string &name)
returns the FileFormat corrosponding to name.
std::vector< double > m_projectionParams
static const std::string & getFormatName(FileFormat f)
return string name of output file format
void resetProjectionParameters()
sets the optional parameters to their default values
void createInvTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
create image-&gt;pano transformation
vigra_ext::Interpolator interpolator
double getMaxVFOV() const
get maximum possible vfov with current projection
IMPEX double h[25][1024]
Definition: emor.cpp:169
void printScriptLine(std::ostream &o, bool forPTOptimizer=false) const
#define DEBUG_ERROR(msg)
Definition: utils.h:76
const std::string & getOutputExtension() const
return the extension used by the current output format
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
unsigned int getWidth() const
static T max(T x, T y)
Definition: svm.cpp:65
Holds transformations for Image -&gt; Pano and the other way.
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
void setSize(vigra::Size2D val)
Set the image size in pixels.
ProjectionFormat m_projectionFormat
ProjectionFormat
Projection of final panorama.
static const std::string fileformatExt[]
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
static T min(T x, T y)
Definition: svm.cpp:62
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
static const std::string fileformatNames[]