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

Generated on 31 Aug 2015 for Hugintrunk by  doxygen 1.4.7