26 #include <hugin_config.h>
34 #include <vigra/error.hxx>
48 static void usage(
const char* name)
50 std::cout << name <<
": stitch a panorama image" << std::endl
54 <<
" It uses the transform function from PanoTools, the stitching itself" << std::endl
55 <<
" is quite simple, no seam feathering is done." << std::endl
56 <<
" only the non-antialiasing interpolators of panotools are supported" << std::endl
58 <<
" The following output formats (n option of panotools p script line)" << std::endl
59 <<
" are supported:"<< std::endl
61 <<
" JPEG, TIFF, PNG : Single image formats with internal blender"<< std::endl
62 <<
" JPEG_m, TIFF_m, PNG_m : multiple image files"<< std::endl
63 <<
" TIFF_multilayer : Multilayer tiff files, readable by The Gimp 2.0" << std::endl
65 <<
"Usage: " << name <<
" [options] -o output project_file (image files)" << std::endl
66 <<
" Options: " << std::endl
67 <<
" -c create coordinate images (only TIFF_m output)" << std::endl
68 <<
" -v|--verbose verbose output" << std::endl
69 <<
" -d|--debug print detailed output for gpu processing" << std::endl
70 <<
" -g|--gpu perform image remapping on the GPU" << std::endl
72 <<
" The following options can be used to override settings in the project file:" << std::endl
73 <<
" -i num remap only image with number num" << std::endl
74 <<
" (can be specified multiple times)" << std::endl
75 <<
" -m str set output file format (TIFF, TIFF_m, TIFF_multilayer," << std::endl
76 <<
" EXR, EXR_m, JPEG, JPEG_m, PNG, PNG_m)" << std::endl
77 <<
" -r ldr/hdr set output mode." << std::endl
78 <<
" ldr keep original bit depth and response" << std::endl
79 <<
" hdr merge to hdr" << std::endl
80 <<
" -e exposure set exposure for ldr mode" << std::endl
81 <<
" -p TYPE pixel type of the output. Can be one of:" << std::endl
82 <<
" UINT8 8 bit unsigned integer" << std::endl
83 <<
" UINT16 16 bit unsigned integer" << std::endl
84 <<
" INT16 16 bit signed integer" << std::endl
85 <<
" UINT32 32 bit unsigned integer" << std::endl
86 <<
" INT32 32 bit signed integer" << std::endl
87 <<
" FLOAT 32 bit floating point" << std::endl
88 <<
" -z|--compression set compression type." << std::endl
89 <<
" Possible options for tiff output:" << std::endl
90 <<
" NONE no compression" << std::endl
91 <<
" PACKBITS packbits compression" << std::endl
92 <<
" LZW lzw compression" << std::endl
93 <<
" DEFLATE deflate compression" << std::endl
94 <<
" For jpeg output set quality number" << std::endl
95 <<
" --bigtiff Use BigTIFF format for TIFF images" << std::endl
96 <<
" --ignore-exposure don't correct exposure" << std::endl
97 <<
" (this does not work with -e switch together)" << std::endl
98 <<
" --output-range-compression=value set range compression" << std::endl
99 <<
" value should be a real in range 0..20" << std::endl
100 <<
" --save-intermediate-images saves also the intermediate" << std::endl
101 <<
" images (only when output is TIFF, PNG or JPEG)" << std::endl
102 <<
" --intermediate-suffix=SUFFIX suffix for intermediate images" << std::endl
103 <<
" --final-suffix=SUFFIX suffix for the final image" << std::endl
104 <<
" --create-exposure-layers create all exposure layers" << std::endl
105 <<
" (this will always use TIFF)" << std::endl
106 <<
" --clip-exposure[=lower cutoff:upper cutoff]" << std::endl
107 <<
" mask automatically all dark and bright pixels" << std::endl
108 <<
" optionally you can specify the limits for the" << std::endl
109 <<
" lower and upper cutoff (specify in range 0...1," << std::endl
110 <<
" relative the full range)" << std::endl
111 <<
" --seam=hard|blend select the blend mode for the seam" << std::endl
115 int main(
int argc,
char* argv[])
119 const char* optstring =
"z:cho:i:t:m:p:r:e:vgd";
122 bool doCoord =
false;
124 std::string basename;
125 std::string outputFormat;
126 bool overrideOutputMode =
false;
127 std::string compression;
129 bool overrideExposure =
false;
131 double rangeCompression = -1;
135 std::string outputPixelType;
136 bool createExposureLayers =
false;
141 SAVEINTERMEDIATEIMAGES,
150 static struct option longOptions[] =
152 {
"ignore-exposure", no_argument, NULL, IGNOREEXPOSURE },
153 {
"save-intermediate-images", no_argument, NULL, SAVEINTERMEDIATEIMAGES },
154 {
"intermediate-suffix", required_argument, NULL, INTERMEDIATESUFFIX },
155 {
"final-suffix", required_argument, NULL, FINALSUFFIX },
156 {
"compression", required_argument, NULL,
'z' },
157 {
"create-exposure-layers", no_argument, NULL, EXPOSURELAYERS },
158 {
"clip-exposure", optional_argument, NULL, MASKCLIPEXPOSURE },
159 {
"seam", required_argument, NULL, SEAMMODE},
160 {
"gpu", no_argument, NULL,
'g'},
161 {
"bigtiff", no_argument, NULL, USE_BIGTIFF },
162 {
"output-range-compression", required_argument, NULL, RANGECOMPRESSION },
163 {
"help", no_argument, NULL,
'h'},
164 {
"debug", no_argument, NULL,
'd'},
165 {
"verbose", no_argument, NULL,
'v'},
166 {
"output", required_argument, NULL,
'o'},
170 while ((c = getopt_long(argc, argv, optstring, longOptions,
nullptr)) != -1)
181 outputImages.insert(atoi(optarg));
184 outputFormat = optarg;
187 outputPixelType = optarg;
190 if (std::string(optarg) ==
"ldr")
192 overrideOutputMode =
true;
195 else if (std::string(optarg) ==
"hdr")
197 overrideOutputMode =
true;
202 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": \"" << optarg <<
"\" is not a valid parameter for output mode (-r)." << std::endl;
207 overrideExposure =
true;
208 exposure = atof(optarg);
213 case SAVEINTERMEDIATEIMAGES:
216 case INTERMEDIATESUFFIX:
223 createExposureLayers =
true;
225 case MASKCLIPEXPOSURE:
227 if (optarg != NULL && *optarg != 0)
231 if (tokens.size() == 2)
237 if (lowerCutoff < 0 || lowerCutoff>1)
239 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Argument \"" << tokens[0] <<
"\" is not a valid number for lower cutoff." << std::endl;
242 if (upperCutoff < 0 || upperCutoff>1)
244 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Argument \"" << tokens[1] <<
"\" is not a valid number for upper cutoff." << std::endl;
247 if (lowerCutoff >= upperCutoff)
249 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Lower cutoff \"" << tokens[0] <<
"\" is higher than upper cutoff" << std::endl
250 <<
" \"" << tokens[1] <<
"\". This is no valid input." << std::endl;
258 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Argument \"" << optarg <<
"\" is not valid number for --clip-exposure" << std::endl
259 <<
" Expected --clip-exposure=lower cutoff:upper cutoff" << std::endl
260 <<
" Both should be numbers between 0 and 1." << std::endl;
266 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Argument \"" << optarg <<
"\" is not valid for --clip-exposure" << std::endl
267 <<
" Expected --clip-exposure=lower cutoff:upper cutoff" << std::endl;
274 std::string text(optarg);
288 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": String \"" << text <<
"\" is not a recognized seam blend mode." << std::endl;
298 std::cout <<
"WARNING: Switch -t is deprecated. Set environment variable OMP_NUM_THREADS instead" << std::endl;
304 compression = optarg;
316 case RANGECOMPRESSION:
319 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Could not parse output range compression (" << optarg <<
")." << std::endl;
322 if (rangeCompression < 0.0 || rangeCompression > 20.0)
324 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": range compression must be a real between 0 and 20." << std::endl;
339 if (basename.empty())
344 if(argc - optind < 1)
349 unsigned nCmdLineImgs = argc -optind -1;
351 const char* scriptFile = argv[optind];
354 TIFFSetWarningHandler(0);
362 if ( nCmdLineImgs > 0)
366 std::cerr <<
"Incorrect number of images specified on command line\nProject required " << pano.
getNrOfImages() <<
" but " << nCmdLineImgs <<
" where given" << std::endl;
379 if (createExposureLayers)
381 if (!outputFormat.empty())
383 std::cout <<
"Warning: Ignoring output format " << outputFormat << std::endl
384 <<
" Switch --create-exposure-layers will enforce TIFF_m output." << std::endl;
386 outputFormat =
"TIFF";
387 if (!outputImages.empty())
389 std::cout <<
"Warning: Ignoring specified output images." << std::endl
390 <<
" Switch --create-exposure-layers will always work on all active images." << std::endl;
391 outputImages.clear();
394 if (outputFormat ==
"TIFF_m")
399 else if (outputFormat ==
"JPEG_m")
405 else if (outputFormat ==
"JPEG")
411 else if (outputFormat ==
"PNG_m")
417 else if (outputFormat ==
"PNG")
423 else if (outputFormat ==
"TIFF")
428 else if (outputFormat ==
"TIFF_multilayer")
433 else if (outputFormat ==
"EXR_m")
438 else if (outputFormat ==
"EXR")
443 else if (outputFormat !=
"")
445 std::cerr <<
"Error: unknown output format: " << outputFormat << endl;
449 if (!compression.empty())
459 int q = atoi(compression.c_str());
460 if (q > 0 && q <= 100)
466 std::cerr <<
"WARNING: \"" << compression <<
"\" is not valid compression value for jpeg images." << std::endl
467 <<
" Using value " << opts.
quality <<
" found in pto file." << std::endl;
473 if (!outputPixelType.empty())
478 if (overrideOutputMode)
483 if (overrideExposure)
489 std::cout <<
"WARNING: Switches --ignore-exposure and -e can't to used together." << std::endl
490 <<
" Ignore switch --ignore-exposure." << std::endl;
493 if (rangeCompression >= 0.0)
497 std::cout <<
"WARNING: Switch --ignore-exposure disables range compression." << std::endl
498 <<
" --output-range-compression is therefore ignored." << std::endl;
506 if (outputImages.empty())
513 for (HuginBase::UIntSet::const_iterator it = outputImages.begin(); it != outputImages.end(); ++it)
517 std::cerr <<
"The project file does not contains an image with number " << *it << std::endl;
522 if(outputImages.empty())
524 std::cout <<
"Project does not contain active images." << std::endl
525 <<
"Nothing to do for nona." << std::endl;
539 std::cout <<
"Nona-GPU does not support this projection. Switch to CPU calculation."<<std::endl;
566 std::cout <<
"Could not initialize GPU. Switching back to CPU calculation." << std::endl;
572 if (createExposureLayers)
575 if (exposureLayers.empty())
577 std::cerr <<
"ERROR: Could not determine exposure layers. Cancel execution." << std::endl;
584 for (
size_t i = 0; i < exposureLayers.size(); ++i)
591 std::ostringstream filename;
592 filename << basename << std::setfill(
'0') << std::setw(4) << i;
605 std::cout << std::endl;
619 catch (std::exception& e)
621 std::cerr <<
"caught exception: " << e.what() << std::endl;
bool wrapupGPU()
cleanup GPU settings
PanoramaOptions::ProjectionFormat getProjection() const
Dummy progress display, without output.
declaration of functions to handle stacks and layers
bool GetAdvancedOption(const AdvancedOptions &opts, const std::string &name, const bool defaultValue)
check if given option is saved and return its boolean value, otherwise return defaultValue ...
double outputRangeCompression
std::vector< UIntSet > UIntSetVector
std::vector< UIntSet > getExposureLayers(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output exposure layers
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
bool set_contains(const _Container &c, const typename _Container::key_type &key)
This class will use the stitchPanorama function of nona.
virtual void run()
runs the algorithm.
std::string toupper(const std::string &s)
std::set< unsigned int > UIntSet
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
void SetGPUDebugMessages(const bool doPrint)
std::size_t getNrOfImages() const
number of images.
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Helper class for storing different options.
void setImageFilename(unsigned int img, const std::string &fname)
set a new image filename
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
bool initGPU(int *argcp, char **argv)
Try to initalise GLUT and GLEW, and create an OpenGL context for GPU stitching.
UIntSet getActiveImages() const
get active images
std::string tiffCompression
const PanoramaOptions & getOptions() const
returns the options for this panorama
std::string outputImageType
std::string GetHuginVersion()
return a string with version numbers
std::map< std::string, std::string > AdvancedOptions
std::string outputPixelType
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...
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
a progress display to print progress reports to a stream
std::string tolower(const std::string &s)
convert a string to lowercase
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
void SetAdvancedOption(AdvancedOptions &opts, const std::string &name, const bool value)
store the option with name in AdvancedOptions
double outputExposureValue
int main(int argc, char *argv[])