PanoramaOptions.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00051 #include <hugin_config.h>
00052 
00053 #include "PanoramaOptions.h"
00054 
00055 #include <hugin_utils/utils.h>
00056 #include <hugin_math/hugin_math.h>
00057 #include <panotools/PanoToolsInterface.h>
00058 
00059 
00060 namespace HuginBase {
00061 
00062 const std::string & PanoramaOptions::getFormatName(FileFormat f)
00063 {
00064     assert((int)f <= (int)FILEFORMAT_NULL);
00065     return fileformatNames[(int) f];
00066 }
00067 
00068 const std::string & PanoramaOptions::getOutputExtension() const
00069 {
00070     assert((int)outputFormat < (int)FILEFORMAT_NULL);
00071     return fileformatExt[(int) outputFormat];
00072 }
00073 
00074 PanoramaOptions::FileFormat PanoramaOptions::getFormatFromName(const std::string & name)
00075 {
00076     int max = (int) FILEFORMAT_NULL;
00077     int i;
00078     for (i=0; i<max; i++) {
00079         if (name == fileformatNames[i]) {
00080             break;
00081         }
00082     }
00083     if (i+1 == max) {
00084         DEBUG_ERROR("could not parse format " << name );
00085         return TIFF_m;
00086     }
00087     return (FileFormat) i;
00088 }
00089 
00090 
00091 void PanoramaOptions::printScriptLine(std::ostream & o, bool forPTOptimizer) const
00092 {
00093     o << "p f" << m_projectionFormat << " w" << getWidth()<< " h" << getHeight()
00094             << " v" << getHFOV() << " ";
00095 
00096     if (! forPTOptimizer) {
00097         switch (colorCorrection) {
00098         case NONE:
00099             break;
00100         case BRIGHTNESS_COLOR:
00101             o << " k" << colorReferenceImage;
00102             break;
00103         case BRIGHTNESS:
00104             o << " b" << colorReferenceImage;
00105             break;
00106         case COLOR:
00107             o << " d" << colorReferenceImage;
00108             break;
00109         }
00110 
00111         // the new exposure options
00112         o << " E" << outputExposureValue;
00113         o << " R" << outputMode;
00114         if (!outputPixelType.empty()) {
00115             o << " T" << outputPixelType;
00116         }
00117         if (m_roi != vigra::Rect2D(m_size)) {
00118             o << " S" << m_roi.left() << "," << m_roi.right() << "," << m_roi.top() << "," << m_roi.bottom();
00119         }
00120     }
00121 
00122     if (!m_projectionParams.empty()) {
00123         o << " P\"";
00124         for (int i=0; i < (int) m_projectionParams.size(); i++) {
00125             o << m_projectionParams[i];
00126             if (i+1 < (int)m_projectionParams.size())
00127                 o << " ";
00128         }
00129         o << "\"";
00130     }
00131     o << " n\"" << getFormatName(outputFormat);
00132     if ( outputFormat == JPEG || outputFormat == JPEG_m) {
00133         o << " q" << quality;
00134     } else if ( outputFormat == TIFF ||
00135                 outputFormat == TIFF_m ||
00136                 outputFormat == TIFF_mask ||
00137                 outputFormat == TIFF_multilayer ||
00138                 outputFormat == TIFF_multilayer_mask)
00139     {
00140         o << " c:" << tiffCompression;
00141         if (tiff_saveROI) {
00142             o << " r:CROP";
00143         }
00144     }
00145     o << "\"";
00146     o << std::endl;
00147 
00148     // misc options
00149     o << "m i" << interpolator;
00150     o << " m" << huberSigma;
00151 
00152     // options for photometric estimation.
00153     o << " p" << photometricHuberSigma;
00154 
00155     o << std::endl;
00156 }
00157 
00158 void PanoramaOptions::setProjection(ProjectionFormat f)
00159 {
00160   // post new projection type
00161    if ((int) f >= panoProjectionFormatCount()) {
00162         // reset to equirect if this projection is not known
00163         f = EQUIRECTANGULAR;
00164     }
00165         m_projectionFormat = f;
00166 
00167         /* Load constant features of the new projection */
00168         panoProjectionFeaturesQuery(f, &m_projFeatures);
00169         /* post default projection parameters and corresponding FOV limits */
00170     m_projectionParams.resize(m_projFeatures.numberOfParameters);
00171     // reset projection parameters to default, determine also new fov limits, clip current fovs...
00172     resetProjectionParameters();
00173 }
00174 
00175 
00176 void PanoramaOptions::setProjectionParameters(const std::vector<double> & params)
00177 {
00178     assert(m_projFeatures.numberOfParameters == (int) params.size());
00179     // check if the parameters are good.
00180     if (m_projFeatures.numberOfParameters == (int) params.size()) {
00181         m_projectionParams = params;
00182         // enforce limits.
00183         for (size_t i=0; i < params.size(); i++) {
00184             if (m_projectionParams[i] > m_projFeatures.parm[i].maxValue) {
00185                 m_projectionParams[i] = m_projFeatures.parm[i].maxValue;
00186             }
00187             if (m_projectionParams[i] < m_projFeatures.parm[i].minValue) {
00188                 m_projectionParams[i] = m_projFeatures.parm[i].minValue;
00189             }
00190         }
00191     }
00192         /* get dynamic FOV limits corresponding to the new parameters,
00193            clip current fovs to those limits, and post the results
00194         */
00195     double parms[PANO_PROJECTION_MAX_PARMS];
00196         double fovs[2];
00197         int i;
00198         for( i = 0; i < m_projFeatures.numberOfParameters; i++){
00199                 parms[i] = m_projectionParams[i];
00200         }
00201         if( queryFOVLimits((int)m_projectionFormat, parms, fovs )){
00202                 m_projFeatures.maxHFOV = fovs[0];
00203                 m_projFeatures.maxVFOV = fovs[1];
00204         }
00205         setHFOV( m_hfov, false );
00206         setVFOV( getVFOV() );
00207 }
00208 
00209 void PanoramaOptions::resetProjectionParameters()
00210 {
00211     std::vector<double> defParam(m_projFeatures.numberOfParameters);
00212     for(int i = 0; i < m_projFeatures.numberOfParameters; i++)
00213     {
00214         defParam[i] = m_projFeatures.parm[i].defValue;
00215     };
00216     setProjectionParameters(defParam);
00217 };
00218 
00219 bool PanoramaOptions::fovCalcSupported(ProjectionFormat f) const
00220 {
00221     /* Ideally this attribute should come from libpano */
00222     return ( f == RECTILINEAR
00223              || f == CYLINDRICAL
00224              || f == EQUIRECTANGULAR
00225              || f == MERCATOR
00226              || f == SINUSOIDAL 
00227              || f == MILLER_CYLINDRICAL
00228              || f == PANINI
00229              || f == ARCHITECTURAL
00230              || f == EQUI_PANINI
00231                          || f == BIPLANE
00232                          || f == TRIPLANE
00233              || f == GENERAL_PANINI
00234                          );
00235 }
00236 
00237 
00238 void PanoramaOptions::setWidth(unsigned int w, bool keepView)
00239 {
00240     if (m_projectionFormat == EQUIRECTANGULAR || m_projectionFormat == SINUSOIDAL) {
00241         if (w%2 == 1) {
00242             w = w+1;
00243         }
00244     }
00245     bool nocrop =  (m_roi == vigra::Rect2D(m_size));
00246     double scale = w / (double) m_size.x;
00247     m_size.x = w;
00248     if (nocrop) {
00249         m_roi = vigra::Rect2D(m_size);
00250     } else {
00251         // for now, do a simple proportional scaling
00252         m_roi.setUpperLeft(vigra::Point2D(hugin_utils::roundi(scale*m_roi.left()), m_roi.top()));
00253         m_roi.setLowerRight(vigra::Point2D(hugin_utils::roundi(scale*m_roi.right()), m_roi.bottom()));
00254         // ensure ROI is inside the panorama
00255         m_roi &= vigra::Rect2D(m_size);
00256     }
00257 
00258     if (keepView) {
00259         m_size.y = hugin_utils::roundi(m_size.y*scale);
00260         if (nocrop) {
00261             m_roi = vigra::Rect2D(m_size);
00262         } else {
00263             m_roi.setUpperLeft(vigra::Point2D(m_roi.left(), hugin_utils::roundi(scale*m_roi.top())));
00264             m_roi.setLowerRight(vigra::Point2D(m_roi.right(), hugin_utils::roundi(scale*m_roi.bottom())));
00265             // ensure ROI is inside the panorama
00266             m_roi &= vigra::Rect2D(m_size);
00267         }
00268         if (fovCalcSupported(m_projectionFormat)) {
00269             if (getVFOV() > getMaxVFOV()) {
00270                 setVFOV(getMaxVFOV());
00271             }
00272         }
00273     }
00274 
00275     DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << "  => vfov: " << getVFOV());
00276 }
00277 
00278 void PanoramaOptions::setHeight(unsigned int h) 
00279 {
00280     bool nocrop =  (m_roi == vigra::Rect2D(m_size));
00281 
00282     if (h == 0) {
00283         h = 1;
00284     }
00285     int dh = h - m_size.y;
00286     m_size.y = h;
00287     if (nocrop) {
00288         m_roi = vigra::Rect2D(m_size);
00289     } else {
00290         // move ROI
00291         m_roi.moveBy(0,dh/2);
00292         m_roi &= vigra::Rect2D(m_size);
00293     }
00294 
00295     DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi:" << m_roi << "  => vfov: " << getVFOV() );
00296 }
00297 
00298 void PanoramaOptions::setHFOV(double h, bool keepView)
00299 {
00300     if (keepView && !fovCalcSupported(m_projectionFormat)) {
00301         DEBUG_NOTICE("Ignoring keepView");
00302         keepView = false;
00303     }
00304 
00305     if (h <= 0) {
00306         h = 1;
00307     }
00308     double vfov;
00309     if (keepView) {
00310         vfov = getVFOV();
00311     }
00312     m_hfov = std::min(h, getMaxHFOV());
00313     if (keepView) {
00314         setVFOV(std::min(vfov, getMaxVFOV()));
00315     }
00316 }
00317 
00318 void PanoramaOptions::setVFOV(double VFOV)
00319 {
00320     VFOV = std::min(VFOV, getMaxVFOV());
00321 
00322     if (! fovCalcSupported(m_projectionFormat)) {
00323         return;
00324     }
00325 
00326     bool nocrop =  (m_roi == vigra::Rect2D(m_size));
00327 
00328     if (VFOV <= 0) {
00329         VFOV = 1;
00330     }
00331     // TODO: create transform from equirect to target projection and
00332     // set additional
00333     PTools::Transform transf;
00334     SrcPanoImage src;
00335     src.setProjection(SrcPanoImage::EQUIRECTANGULAR);
00336     src.setHFOV(360);
00337     src.setSize(vigra::Size2D(360,180));
00338     transf.createInvTransform(src, *this);
00339 
00340     hugin_utils::FDiff2D pmiddle;
00341 
00342     if (VFOV>180 && getMaxVFOV() > 180) {
00343         // we have crossed the pole
00344         transf.transform(pmiddle, hugin_utils::FDiff2D(180, 180 - VFOV / 2 - 0.01));
00345     } else {
00346         transf.transform(pmiddle, hugin_utils::FDiff2D(0, VFOV / 2));
00347     }
00348     // try to keep the same ROI
00349     vigra::Size2D oldSize = m_size;
00350     m_size.y = abs(hugin_utils::roundi(2*pmiddle.y));
00351 
00352     if (nocrop) {
00353         m_roi = vigra::Rect2D(m_size);
00354     } else {
00355         // adjust ROI to stay in previous position
00356         int dh = m_size.y - oldSize.y;
00357         m_roi.moveBy(0, dh/2);
00358         // ensure ROI is visible
00359         m_roi &= vigra::Rect2D(m_size);
00360     }
00361 
00362     DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << "  => vfov: " << VFOV);
00363 
00364 }
00365 
00366 double PanoramaOptions::getVFOV() const
00367 {
00368     // calcuale VFOV based on current panorama
00369     PTools::Transform transf;
00370     SrcPanoImage src;
00371     src.setProjection(SrcPanoImage::EQUIRECTANGULAR);
00372     src.setHFOV(360);
00373     src.setSize(vigra::Size2D(360,180));
00374     transf.createTransform(src, *this);
00375 
00376     hugin_utils::FDiff2D pmiddle;
00377     if (transf.transform(pmiddle, hugin_utils::FDiff2D(0, m_size.y / 2.0)))
00378     {
00379         double VFOV;
00380         if (pmiddle.x > 90 || pmiddle.y < -90)
00381         {
00382             // the pole has been crossed
00383             VFOV = 2 * (180 - pmiddle.y);
00384         }
00385         else
00386         {
00387             VFOV = 2 * pmiddle.y;
00388         }
00389         DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << "  => vfov: " << VFOV);
00390         return VFOV;
00391     }
00392     else
00393     {
00394         DEBUG_DEBUG(" HFOV: " << m_hfov << " size: " << m_size << " roi: " << m_roi << "  => vfov: " << getMaxVFOV() << " (setting to max)");
00395         return getMaxVFOV();
00396     }
00397 }
00398 
00399 const std::string PanoramaOptions::fileformatNames[] =
00400 {
00401     "JPEG",
00402     "JPEG_m",
00403     "PNG",
00404     "PNG_m",
00405     "TIFF",
00406     "TIFF_m",
00407     "TIFF_mask",
00408     "TIFF_multilayer",
00409     "TIFF_multilayer_mask",
00410     "PICT",
00411     "PSD",
00412     "PSD_m",
00413     "PSD_mask",
00414     "PAN",
00415     "IVR",
00416     "IVR_java",
00417     "VRML",
00418     "QTVR",
00419     "HDR",
00420     "HDR_m",
00421     "EXR",
00422     "EXR_m"
00423 };
00424 
00425 
00426 const std::string PanoramaOptions::fileformatExt[] =
00427 {
00428     "jpg",
00429     "jpg",
00430     "png",
00431     "png",
00432     "tif",
00433     "tif",
00434     "tif",
00435     "tif",
00436     "tif",
00437     "pict",
00438     "psd",
00439     "psd",
00440     "psd",
00441     "pan",
00442     "ivr",
00443     "IVR_java",
00444     "wrl",
00445     "mov",
00446     "hdr",
00447     "hdr",
00448     "exr",
00449     "exr"
00450 };
00451 
00452 
00453 
00454 
00455 
00456 } //namespace

Generated on 26 May 2018 for Hugintrunk by  doxygen 1.4.7