32 #include <vigra/imageinfo.hxx> 
   41 #include <hugin_config.h> 
   42 #include <mach-o/dyld.h>     
   47 static void usage(
const char* name)
 
   49     std::cout << name << 
": generate project file from images" << std::endl
 
   52         << 
"Usage:  " << name << 
" [options] image1 [...]" << std::endl
 
   54         << 
"  Options:" << std::endl
 
   55         << 
"     -o, --output=file.pto  Output Hugin PTO file." << std::endl
 
   56         << 
"     -p, --projection=INT   Projection type (default: read from database)" << std::endl
 
   57         << 
"     -f, --fov=FLOAT        Horizontal field of view of images" << std::endl
 
   58         << 
"                            default: read from database" << std::endl
 
   59         << 
"     --ignore-fov-rectilinear  Don't read fov for rectilinear images from" <<std::endl
 
   60         << 
"                            the database, instead use only the values" << std::endl
 
   61         << 
"                            from EXIF data" << std::endl
 
   62         << 
"     -c, --crop=left,right,top,bottom        Sets the crop of input" << std::endl
 
   63         << 
"                            images (especially for fisheye lenses)" << std::endl
 
   64         << 
"     -s, --stacklength=INT  Number of images in stack" << std::endl
 
   65         << 
"                            (default: automatic detection)" << std::endl
 
   66         << 
"     -l, --linkstacks       Link image positions in stacks" << std::endl
 
   67         << 
"     --distortion           Try to load distortion information from" << std::endl
 
   68         << 
"                            lens database" << std::endl
 
   69         << 
"     --vignetting           Try to load vignetting information from" << std::endl
 
   70         << 
"                            lens database" << std::endl
 
   71         << 
"     --sort                 Sort the files by name alphanumeric" << std::endl
 
   72         << 
"                            otherwise the images are processed in the order" << std::endl
 
   73         << 
"                            given at the command line" << std::endl
 
   74         << 
"     -h, --help             Shows this help" << std::endl
 
   78 int main(
int argc, 
char* argv[])
 
   81     const char* optstring = 
"o:p:f:c:s:lh";
 
   84         SWITCH_IGNORE_FOV_RECTILINEAR = 1000,
 
   89     static struct option longOptions[] =
 
   91         {
"output", required_argument, NULL, 
'o' },
 
   92         {
"projection", required_argument, NULL, 
'p' },
 
   93         {
"fov", required_argument, NULL, 
'f' },
 
   94         {
"ignore-fov-rectilinear", no_argument, NULL, SWITCH_IGNORE_FOV_RECTILINEAR},
 
   95         {
"crop", required_argument, NULL, 
'c' },
 
   96         {
"stacklength", required_argument, NULL, 
's' },
 
   97         {
"linkstacks", no_argument, NULL, 
'l' },
 
   98         {
"distortion", no_argument, NULL, SWITCH_DISTORTION },
 
   99         {
"vignetting", no_argument, NULL, SWITCH_VIGNETTING },
 
  100         {
"sort", no_argument, NULL, SWITCH_SORT_FILENAME },
 
  101         {
"help", no_argument, NULL, 
'h' },
 
  111     bool linkStacks=
false;
 
  112     vigra::Rect2D cropRect(0,0,0,0);
 
  113     bool ignoreFovRectilinear = 
false;
 
  114     bool loadDistortion=
false;
 
  115     bool loadVignetting=
false;
 
  116     bool sortByFilename = 
false;
 
  117     while ((c = getopt_long (argc, argv, optstring, longOptions,
nullptr)) != -1)
 
  129                     projection=atoi(optarg);
 
  130                     if((projection==0) && (strcmp(optarg,
"0")!=0))
 
  156                     int left, right, top, bottom;
 
  157                     int n=sscanf(optarg, 
"%d,%d,%d,%d", &left, &right, &top, &bottom);
 
  160                         if(right>left && bottom>top)
 
  162                             cropRect.setUpperLeft(vigra::Point2D(left,top));
 
  163                             cropRect.setLowerRight(vigra::Point2D(right,bottom));
 
  179                 stackLength=atoi(optarg);
 
  180                 if ((stackLength == 0) && (strcmp(optarg, 
"0") != 0))
 
  189             case SWITCH_DISTORTION:
 
  192             case SWITCH_VIGNETTING:
 
  195             case SWITCH_IGNORE_FOV_RECTILINEAR:
 
  196                 ignoreFovRectilinear = 
true;
 
  198             case SWITCH_SORT_FILENAME:
 
  199                 sortByFilename = 
true;
 
  212     if (argc - optind < 1)
 
  218     std::cout << 
"Generating pto file..." << std::endl;
 
  221     std::vector<std::string> filelist;
 
  228         char drive[_MAX_DRIVE];
 
  230         _splitpath(input.c_str(), drive, dir, NULL, NULL);
 
  232         struct _finddata_t finddata;
 
  233         intptr_t findhandle = _findfirst(input.c_str(), &finddata);
 
  234         if (findhandle != -1)
 
  239                 if((finddata.attrib & _A_SUBDIR)==0)
 
  241                     char fname[_MAX_FNAME];
 
  243                     char newFile[_MAX_PATH];
 
  244                     _splitpath(finddata.name, NULL, NULL, fname, ext);
 
  245                     _makepath(newFile, drive, dir, fname, ext);
 
  247                     if(vigra::isImage(newFile))
 
  249                         filelist.push_back(std::string(newFile));
 
  253             while (_findnext(findhandle, &finddata) == 0);
 
  254             _findclose(findhandle);
 
  260             if(vigra::isImage(input.c_str()))
 
  282     double redBalanceAnchor = 1.0;
 
  283     double blueBalanceAnchor = 1.0;
 
  284     for(
size_t i=0; i<filelist.size(); i++)
 
  290             std::cerr << 
"Ignoring raw file " << filelist[i] << 
"." << std::endl;
 
  294         std::cout << 
"Reading " << filelist[i] << 
"..." << std::endl;
 
  295         srcImage.setFilename(filelist[i]);
 
  298             vigra::ImageImportInfo 
info(filelist[i].c_str());
 
  299             if(info.width()==0 || info.height()==0)
 
  301                 std::cerr << 
"ERROR: Could not decode image " << filelist[i] << std::endl
 
  302                      << 
"Skipping this image." << std::endl << std::endl;
 
  307             const std::string pixelType=info.getPixelType();
 
  308             if (pixelType == 
"BILEVEL")
 
  310                 std::cerr << 
"ERROR: Image " << filelist[i] << 
" is a black/white images." << std::endl
 
  311                     << 
"       This is not supported. Convert to grayscale image and try again." << std::endl
 
  312                     << 
"       Skipping this image." << std::endl;
 
  315             if((pixelType==
"UINT8") || (pixelType==
"UINT16") || (pixelType==
"INT16"))
 
  331         catch(std::exception& e)
 
  333             std::cerr << 
"ERROR: caught exception: " << e.what() << std::endl;
 
  334             std::cerr << 
"Could not read image information for file " << filelist[i] << std::endl;
 
  335             std::cerr << 
"Skipping this image." << std::endl << std::endl;
 
  351             srcImage.setHFOV(fov);
 
  352             if(srcImage.getCropFactor()==0)
 
  354                 srcImage.setCropFactor(1.0);
 
  362                 std::cout << 
"\tNo value for field of view found in EXIF data. " << std::endl
 
  363                      << 
"\tAssuming a HFOV of 50 degrees. " << std::endl;
 
  364                 srcImage.setHFOV(50);
 
  365                 srcImage.setCropFactor(1.0);
 
  368         if(cropRect.width()>0 && cropRect.height()>0)
 
  378             srcImage.setAutoCenterCrop(
false);
 
  379             srcImage.setCropRect(cropRect);
 
  385                 std::cout << 
"\tRead distortion data from lens database." << std::endl;
 
  389                 std::cout << 
"\tNo valid distortion data found in lens database." << std::endl;
 
  396                 std::cout << 
"\tRead vignetting data from lens database." << std::endl;
 
  400                 std::cout << 
"\tNo valid vignetting data found in lens database." << std::endl;
 
  405             redBalanceAnchor = srcImage.getExifRedBalance();
 
  406             blueBalanceAnchor = srcImage.getExifBlueBalance();
 
  407             if (fabs(redBalanceAnchor)<1e-2)
 
  409                 redBalanceAnchor = 1;
 
  411             if (fabs(blueBalanceAnchor)<1e-2)
 
  413                 blueBalanceAnchor = 1;
 
  418             srcImage.setWhiteBalanceRed(srcImage.getExifRedBalance() / redBalanceAnchor);
 
  419             srcImage.setWhiteBalanceBlue(srcImage.getExifBlueBalance() / blueBalanceAnchor);
 
  426         std::cerr << 
"Adding images to project files failed." << std::endl;
 
  441             for(
size_t j=0; j<i; j++)
 
  444                 if(srcImg.getHFOV()==compareImg.getHFOV() &&
 
  445                         srcImg.getProjection()==compareImg.getProjection() &&
 
  446                         srcImg.getExifModel()==compareImg.getExifModel() &&
 
  447                         srcImg.getExifMake()==compareImg.getExifMake() &&
 
  448                         srcImg.getSize()==compareImg.getSize())
 
  459         std::cout << std::endl << 
"Assigned " << lenses.
getNumberOfParts() << 
" lenses." << std::endl;
 
  462             std::cout << 
"Project contains more than one lens, but you requested to assign" << std::endl
 
  463                  << 
"stacks. This is not supported. Therefore stacks will not be" << std::endl
 
  464                  << 
"assigned." << std::endl << std::endl;
 
  468         if (stackLength == 0)
 
  480                 stackLength = std::min<int>(stackLength, pano.
getNrOfImages());
 
  488                     for (
size_t stackNr = 0; stackNr < stackCount; stackNr++)
 
  490                         size_t firstImgStack = stackNr*stackLength;
 
  491                         for (
size_t i = 0; i < stackLength; i++)
 
  495                                 pano.linkImageVariableStack(firstImgStack, firstImgStack + i);
 
  498                                     pano.linkImageVariableYaw(firstImgStack, firstImgStack + i);
 
  499                                     pano.linkImageVariablePitch(firstImgStack, firstImgStack + i);
 
  500                                     pano.linkImageVariableRoll(firstImgStack, firstImgStack + i);
 
  501                                     pano.linkImageVariableX(firstImgStack, firstImgStack + i);
 
  502                                     pano.linkImageVariableY(firstImgStack, firstImgStack + i);
 
  503                                     pano.linkImageVariableZ(firstImgStack, firstImgStack + i);
 
  504                                     pano.linkImageVariableTranslationPlaneYaw(firstImgStack, firstImgStack + i);
 
  505                                     pano.linkImageVariableTranslationPlanePitch(firstImgStack, firstImgStack + i);
 
  518             std::cout << 
"Assigned " << stackCount << 
" stacks: " << std::endl
 
  519                 << 
"\t" << (linkStacks ? 
"Linking position of images in stacks" : 
"Use individual positions of images in stacks") << std::endl;
 
  541         output=output.append(
".pto");
 
  547         std::cout << std::endl << 
"Written output to " << output << std::endl;
 
void setCropMode(CropMode val)
Set the crop mode. 
bool FileExists(const std::string &filename)
checks if file exists 
void updateOptimizeVector()
updates the optimize vector according to master switches 
bool applyEXIFValues(bool applyEVValue=true)
apply values found in EXIF data to SrcPanoImage class, call readEXIF() before to initialize some valu...
unsigned int getPartNumber(unsigned int imageNr) const 
Get a part number from an image number. 
static double calcMeanExposure(const PanoramaData &pano)
bool IsLinearICCProfile(const vigra::ImageImportInfo::ICCProfile &iccProfile)
return true if icc profile is linear one, otherwise return false 
bool isCircularCrop() const 
returns true, if projection requires cicular crop 
ImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables. 
void setPhotometricOptimizerSwitch(const int newSwitch)
sets the photometric optimizer master switch 
Somewhere to specify what variables belong to what. 
Functor class to compare two objects with the "Alphanum Algorithm". 
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
void setOptimizerSwitch(const int newSwitch)
set optimizer master switch 
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program 
bool readProjectionFromDB(const bool ignoreFovRectilinear=true)
tries to read projection and crop area from lens database you need to call SrcPanoImage::readEXIF bef...
class to access Hugins camera and lens database 
void linkPossibleStacks(bool linkPosition)
create automatically stacks as indicated by metadata 
empirical model of response 
std::string getPathPrefix(const std::string &filename)
Get the path to a filename. 
std::string GetAbsoluteFilename(const std::string &filename)
returns the full absolute filename 
some definitions to work with optimizer master switches 
std::size_t getNrOfImages() const 
number of images. 
std::string getExtension(const std::string &basename2)
Get extension of a filename. 
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables. 
std::string stripExtension(const std::string &basename2)
remove extension of a filename 
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image 
Same as above, but use a non const panorama. 
bool readVignettingFromDB()
tries to read vignetting data from lens database you need to call SrcPanoImage::readEXIF before to fi...
const PanoramaOptions & getOptions() const 
returns the options for this panorama 
bool readDistortionFromDB()
tries to read distortion data from lens database you need to call SrcPanoImage::readEXIF before to fi...
bool readEXIF()
try to fill out information about the image, by examining the exif data 
void setSize(vigra::Size2D val)
Set the image size in pixels. 
std::string GetHuginVersion()
return a string with version numbers 
void update()
Update part numbers for each variable group. 
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file 
static void info(const char *fmt,...)
const SrcPanoImage & getImage(std::size_t nr) const 
get a panorama image, counting starts with 0 
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
bool IsRawExtension(const std::string testExt)
return true if extension belongs to a raw file 
std::size_t getNumberOfParts() const 
get the number of parts. 
All variables of a source image. 
void switchParts(unsigned int ImageNr, unsigned int partNr)
switch a given image to a different part number. 
const bool hasPossibleStacks() const 
return true, if the metadata indicates that the projects is a bracketet project 
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames) 
double outputExposureValue
int main(int argc, char *argv[])