Hugin trunk 0.1
Loading...
Searching...
No Matches
pano_modify.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
13/* This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This software is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public
24 * License along with this software. If not, see
25 * <http://www.gnu.org/licenses/>.
26 *
27 */
28
29#include <fstream>
30#include <sstream>
31#include <cmath>
32#include <getopt.h>
33#include <panodata/Panorama.h>
43#include "hugin_utils/utils.h"
44#include "PanoOptionsFromIni.h"
45
46static void usage(const char* name)
47{
48 std::cout << name << ": change output parameters of project file" << std::endl
49 << "pano_modify version " << hugin_utils::GetHuginVersion() << std::endl
50 << std::endl
51 << "Usage: " << name << " [options] input.pto" << std::endl
52 << std::endl
53 << " Options:" << std::endl
54 << " -o, --output=file.pto Output Hugin PTO file. Default: <filename>_mod.pto" << std::endl
55 << " -p, --projection=x Sets the output projection to number x" << std::endl
56 << " --projection-parameter=x Sets the parameter of the projection" << std::endl
57 << " (Several parameters are separated by"<<std::endl
58 << " space or comma)" << std::endl
59 << " --fov=AUTO|HFOV|HFOVxVFOV Sets field of view" << std::endl
60 << " AUTO: calculates optimal fov" << std::endl
61 << " HFOV|HFOVxVFOV: set to given fov" << std::endl
62 << " -s, --straighten Straightens the panorama" << std::endl
63 << " -c, --center Centers the panorama" << std::endl
64 << " --canvas=AUTO|num%|WIDTHxHEIGHT Sets the output canvas size" << std::endl
65 << " AUTO: calculate optimal canvas size" << std::endl
66 << " num%: scales the optimal size by given percent" << std::endl
67 << " WIDTHxHEIGHT: set to given size" << std::endl
68 << " --crop=AUTO|AUTOHDR|AUTOOUTSIDE|left,right,top,bottom|left,right,top,bottom%" << std::endl
69 << " Sets the crop rectangle" << std::endl
70 << " AUTO: autocrop panorama" << std::endl
71 << " AUTOHDR: autocrop HDR panorama" << std::endl
72 << " AUTOOUTSIDE: autocrop outside of all images" << std::endl
73 << " left,right,top,bottom: to given size" << std::endl
74 << " left,right,top,bottom%: to size relative to canvas" << std::endl
75 << " --output-exposure=AUTO|num Sets the output exposure value to mean" << std::endl
76 << " exposure (AUTO) or to given value" << std::endl
77 << " Prefix number with r for relativ change" << std::endl
78 << " --output-range-compression=num Set range compression" << std::endl
79 << " Value should be a real in range 0..20" << std::endl
80 << " --output-cropped-tiff Output cropped tiffs as intermediate images" << std::endl
81 << " --output-uncropped-tiff Output uncropped tiffs as intermediate images" << std::endl
82 << " --output-type=str Sets the type of output" << std::endl
83 << " Valid items are" << std::endl
84 << " NORMAL|N: normal panorama" << std::endl
85 << " STACKSFUSEDBLENDED|BF: LDR panorama with" << std::endl
86 << " blended stacks" << std::endl
87 << " EXPOSURELAYERSFUSED|FB: LDR panorama with" << std::endl
88 << " fused exposure layers (any arrangement)" << std::endl
89 << " HDR: HDR panorama" << std::endl
90 << " REMAP: remapped images with corrected exposure" << std::endl
91 << " REMAPORIG: remapped images with" << std::endl
92 << " uncorrected exposure" << std::endl
93 << " HDRREMAP: remapped images in linear color space" << std::endl
94 << " FUSEDSTACKS: exposure fused stacks" << std::endl
95 << " HDRSTACKS: HDR stacks" << std::endl
96 << " EXPOSURELAYERS: blended exposure layers" << std::endl
97 << " and separated by a comma." << std::endl
98 << " --ldr-file=JPG|TIF|PNG Sets the filetype for LDR panorama output" << std::endl
99 << " --ldr-compression=str Sets the compression for LDR panorama output" << std::endl
100 << " For TIF: NONE|PACKBITS|LZW|DEFLATE" << std::endl
101 << " For JPEG: quality as number" << std::endl
102 << " --hdr-file=EXR|TIF Sets the filetype for HDR panorama output" << std::endl
103 << " --hdr-compression=str Sets the compression for HDR panorama output" << std::endl
104 << " For TIF: NONE|PACKBITS|LZW|DEFLATE" << std::endl
105 << " --blender=ENBLEND|INTERNAL Sets the blender to be used at stitching" << std::endl
106 << " stage." << std::endl
107 << " --blender-args=str Sets the arguments for the blender" << std::endl
108 << " --fusion-args=str Sets the arguments for the fusion program" << std::endl
109 << " --hdrmerge-args=str Setst the arguments for hdrmerge" << std::endl
110 << " --rotate=yaw,pitch,roll Rotates the whole panorama with the given angles" << std::endl
111 << " --translate=x,y,z Translate the whole panorama with the given values" << std::endl
112 << " --interpolation=int Sets the interpolation method" << std::endl
113 << " --ini=FILE Read the settings from the given FILE and apply it" << std::endl
114 << " --template=TEMPLATE Read the panorama options from the given TEMPLATE" << std::endl
115 << " and apply it" << std::endl
116 << " -h, --help Shows this help" << std::endl
117 << std::endl;
118}
119
120int main(int argc, char* argv[])
121{
122 // parse arguments
123 const char* optstring = "o:p:sch";
124
125 enum
126 {
127 SWITCH_FOV=1000,
149 };
150 static struct option longOptions[] =
151 {
152 {"output", required_argument, NULL, 'o' },
153 {"projection", required_argument, NULL, 'p' },
154 {"projection-parameter", required_argument, NULL, SWITCH_PROJECTION_PARAMETER },
156 {"straighten", no_argument, NULL, 's' },
157 {"center", no_argument, NULL, 'c' },
158 {"canvas", required_argument, NULL, SWITCH_CANVAS },
160 {"output-cropped-tiff", no_argument, NULL, SWITCH_CROPPED_TIFF },
161 {"output-uncropped-tiff", no_argument, NULL, SWITCH_UNCROPPED_TIFF },
162 {"output-exposure", required_argument, NULL, SWITCH_EXPOSURE },
163 {"output-range-compression", required_argument, NULL, SWITCH_RANGE_COMPRESSION },
164 {"output-type", required_argument, NULL, SWITCH_OUTPUT_TYPE },
165 {"blender", required_argument, NULL, SWITCH_BLENDER },
166 {"blender-args", required_argument, NULL, SWITCH_BLENDER_ARGS },
167 {"fusion-args", required_argument, NULL, SWITCH_FUSION_ARGS },
168 {"hdrmerge-args", required_argument, NULL, SWITCH_HDRMERGE_ARGS },
170 {"ldr-compression", required_argument, NULL, SWITCH_LDRCOMPRESSION },
172 {"hdr-compression", required_argument, NULL, SWITCH_HDRCOMPRESSION },
173 {"rotate", required_argument, NULL, SWITCH_ROTATE },
174 {"translate", required_argument, NULL, SWITCH_TRANSLATE },
175 {"interpolation", required_argument, NULL, SWITCH_INTERPOLATION},
177 {"template", required_argument, NULL, SWITCH_TEMPLATE },
178 {"help", no_argument, NULL, 'h' },
179 0
180 };
181
182 int projection=-1;
183 std::vector<double> projParameter;
184 double newHFOV=-1;
185 double newVFOV=-1;
186 int scale=100;
187 int newWidth=-1;
188 int newHeight=-1;
189 int outputCroppedTiff=-1;
190 vigra::Rect2D newROI(0,0,0,0);
193 bool doFit=false;
194 bool doStraighten=false;
195 bool doCenter=false;
196 bool doOptimalSize=false;
197 enum AutoCropMode
198 { NONE, AUTO, AUTOHDR, AUTOOUTSIDE};
199 AutoCropMode doAutocrop=AutoCropMode::NONE;
200 int c;
201 double yaw = 0;
202 double pitch = 0;
203 double roll = 0;
204 double x = 0;
205 double y = 0;
206 double z = 0;
207 double outputExposure = -1000;
208 double outputRangeCompression = -1;
209 bool relativeExposure = false;
210 bool calcMeanExposure = false;
211 std::string outputType;
212 std::string ldrfiletype;
213 std::string ldrcompression;
214 std::string hdrfiletype;
215 std::string hdrcompression;
216 std::string output;
217 std::string param;
218 std::string blender;
219#define EMPTYARG "(empty)"
220 std::string blenderArgs(EMPTYARG);
221 std::string fusionArgs(EMPTYARG);
222 std::string hdrMergeArgs(EMPTYARG);
223 std::string iniFile;
224 std::string templateFile;
225 int interpolation = -1;
226 while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
227 {
228 switch (c)
229 {
230 case 'o':
231 output = optarg;
232 break;
233 case 'h':
235 return 0;
236 case 'p':
237 //projection
238 projection=atoi(optarg);
239 if((projection==0) && (strcmp(optarg,"0")!=0))
240 {
241 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse projection number." << std::endl;
242 return 1;
243 };
244 if(projection>=panoProjectionFormatCount())
245 {
246 std::cerr << hugin_utils::stripPath(argv[0]) << ": projection " << projection << " is an invalid projection number." << std::endl;
247 return 1;
248 };
249 break;
251 // projection parameters
252 {
253 // split at space or comma
254 std::vector<std::string> parameter = hugin_utils::SplitString(optarg, ", ");
255 for(const auto& p: parameter)
256 {
257 double d;
259 {
260 projParameter.push_back(d);
261 }
262 else
263 {
264 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse projection parameters \"" << optarg << "\"." << std::endl;
265 return 1;
266 };
267 };
268 }
269 break;
270 case SWITCH_FOV:
271 //field of view
272 param=optarg;
273 param=hugin_utils::toupper(param);
274 if(param=="AUTO")
275 {
276 doFit=true;
277 }
278 else
279 {
280 double hfov, vfov;
281 int n=sscanf(optarg, "%lfx%lf", &hfov, &vfov);
282 if(n==1)
283 {
284 if(hfov>0)
285 {
286 newHFOV=hfov;
287 }
288 else
289 {
290 std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid field of view" << std::endl;
291 return 1;
292 };
293 }
294 else
295 {
296 if (n==2)
297 {
298 if(hfov>0 && vfov>0)
299 {
300 newHFOV=hfov;
302 }
303 else
304 {
305 std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid field of view" << std::endl;
306 return 1;
307 };
308 }
309 else
310 {
311 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse field of view" << std::endl;
312 return 1;
313 };
314 };
315 };
316 break;
317 case 's':
318 doStraighten=true;
319 break;
320 case 'c':
321 doCenter=true;
322 break;
323 case SWITCH_CANVAS:
324 //canvas size
325 param=optarg;
326 param=hugin_utils::toupper(param);
327 if(param=="AUTO")
328 {
329 doOptimalSize=true;
330 }
331 else
332 {
333 int pos=param.find("%");
334 if(pos!=std::string::npos)
335 {
336 param=param.substr(0,pos);
337 scale=atoi(param.c_str());
338 if(scale==0)
339 {
340 std::cerr << hugin_utils::stripPath(argv[0]) << ": No valid scale factor given." << std::endl;
341 return 1;
342 };
343 doOptimalSize=true;
344 }
345 else
346 {
347 int width, height;
348 int n=sscanf(optarg, "%dx%d", &width, &height);
349 if (n==2)
350 {
351 if(width>0 && height>0)
352 {
353 newWidth=width;
354 newHeight=height;
355 }
356 else
357 {
358 std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid canvas size" << std::endl;
359 return 1;
360 };
361 }
362 else
363 {
364 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse canvas size" << std::endl;
365 return 1;
366 };
367 };
368 };
369 break;
370 case SWITCH_CROP:
371 //crop
372 param=optarg;
373 param=hugin_utils::toupper(param);
374 if (param == "AUTO")
375 {
376 doAutocrop = AutoCropMode::AUTO;
377 }
378 else
379 {
380 if (param == "AUTOHDR")
381 {
382 doAutocrop = AutoCropMode::AUTOHDR;
383 }
384 else
385 {
386 if (param == "AUTOOUTSIDE")
387 {
388 doAutocrop = AutoCropMode::AUTOOUTSIDE;
389 }
390 else
391 {
392 const int pos = param.find("%");
393 if (pos != std::string::npos)
394 {
395 // parse relative values
396 param = param.substr(0, pos);
397 double left, right, top, bottom;
398 const int n = sscanf(param.c_str(), "%lf,%lf,%lf,%lf", &left, &right, &top, &bottom);
399 if (n == 4)
400 {
401 if (right > left && bottom > top && left >= 0.0 && top >= 0.0 && right <= 100.0 && bottom <= 100.0)
402 {
403 // check values, 0..100 %
406 }
407 else
408 {
409 std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid crop area" << std::endl;
410 return 1;
411 };
412 }
413 else
414 {
415 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse crop values" << std::endl;
416 return 1;
417 };
418 }
419 else
420 {
421 int left, right, top, bottom;
422 int n = sscanf(optarg, "%d,%d,%d,%d", &left, &right, &top, &bottom);
423 if (n == 4)
424 {
425 if (right > left && bottom > top && left >= 0 && top >= 0)
426 {
427 newROI.setUpperLeft(vigra::Point2D(left, top));
428 newROI.setLowerRight(vigra::Point2D(right, bottom));
429 }
430 else
431 {
432 std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid crop area" << std::endl;
433 return 1;
434 };
435 }
436 else
437 {
438 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse crop values" << std::endl;
439 return 1;
440 };
441 };
442 };
443 };
444 };
445 break;
448 break;
451 break;
452 case SWITCH_EXPOSURE:
453 param = optarg;
454 param = hugin_utils::toupper(param);
455 if (param == "AUTO")
456 {
457 calcMeanExposure = true;
458 }
459 else
460 {
461 if (!param.empty())
462 {
463 // if first character is r assume relative exposure values
464 relativeExposure = (param[0] == 'R');
466 {
467 param.erase(0, 1);
468 };
469 int n = sscanf(param.c_str(), "%lf", &outputExposure);
470 if (n != 1)
471 {
472 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse output exposure value." << std::endl;
473 return 1;
474 };
475 }
476 else
477 {
478 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse output exposure value." << std::endl;
479 return 1;
480 };
481 };
482 break;
484 if(!hugin_utils::stringToDouble(std::string(optarg), outputRangeCompression))
485 {
486 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse output range compression (" << optarg << ")." << std::endl;
487 return 1;
488 };
490 {
491 std::cerr << hugin_utils::stripPath(argv[0]) << ": range compression must be a real between 0 and 20." << std::endl;
492 return 1;
493 };
494 break;
496 if (!outputType.empty())
497 {
498 outputType.append(",");
499 };
500 outputType.append(optarg);
501 break;
502 case SWITCH_BLENDER:
504 break;
507 break;
510 break;
513 break;
516 break;
519 break;
522 break;
525 break;
526 case SWITCH_ROTATE:
527 {
528 int n=sscanf(optarg, "%lf,%lf,%lf", &yaw, &pitch, &roll);
529 if(n!=3)
530 {
531 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse rotate angles values. Given: \"" << optarg << "\"" << std::endl;
532 return 1;
533 };
534 };
535 break;
536 case SWITCH_TRANSLATE:
537 {
538 int n=sscanf(optarg, "%lf,%lf,%lf", &x, &y, &z);
539 if(n!=3)
540 {
541 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse translation values. Given: \"" << optarg << "\"" << std::endl;
542 return 1;
543 };
544 };
545 break;
548 {
549 std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not parse interpolation value. Given: \"" << optarg << "\"" << std::endl;
550 return 1;
551 };
553 {
554 std::cerr << hugin_utils::stripPath(argv[0]) << ": Interpolator " << interpolation << " is not valid." << std::endl;
555 return 1;
556 }
557 break;
558 case SWITCH_INI_FILE:
559 iniFile = optarg;
561 {
562 std::cerr << hugin_utils::stripPath(argv[0]) << ": INI file " << iniFile << " not found." << std::endl;
563 return 1;
564 };
565 break;
566 case SWITCH_TEMPLATE:
569 {
570 std::cerr << hugin_utils::stripPath(argv[0]) << ": Template file " << templateFile << " not found." << std::endl;
571 return 1;
572 };
573 break;
574 case ':':
575 case '?':
576 // missing argument or invalid switch
577 return 1;
578 break;
579 default:
580 // this should not happen
581 abort();
582
583 }
584 }
585
586 if (argc - optind != 1)
587 {
588 if (argc - optind < 1)
589 {
590 std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
591 }
592 else
593 {
594 std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
595 };
596 return 1;
597 };
598
599 // set some options which depends on each other
600 if(doStraighten)
601 {
602 doCenter=false;
603 doFit=true;
604 };
605 if(doCenter)
606 {
607 doFit=true;
608 };
609
610 std::string input=argv[optind];
611 // read panorama
614 {
615 return 1;
616 };
617
618 // sets the projection
619 if(projection!=-1)
620 {
624 if (panoProjectionFeaturesQuery(projection, &proj))
625 {
626 std::cout << "Setting projection to " << proj.name << std::endl;
627 }
628 pano.setOptions(opt);
629 };
630 // set projection parameters
631 if (!projParameter.empty())
632 {
634 if (projParameter.size() > opt.m_projFeatures.numberOfParameters)
635 {
636 std::cout << "Warning: Given " << projParameter.size() << " projection parameters, but projection supports" << std::endl
637 << " only " << opt.m_projFeatures.numberOfParameters << ". Ignoring surplus parameters." << std::endl;
638 while (projParameter.size() > opt.m_projFeatures.numberOfParameters)
639 {
640 projParameter.pop_back();
641 }
642 }
643 if (!projParameter.empty())
644 {
645 std::vector<double> newProjParameters = opt.getProjectionParameters();
646 std::copy(projParameter.begin(), projParameter.end(), newProjParameters.begin());
647 opt.setProjectionParameters(newProjParameters);
648 // read back, new the limits have been applied
649 newProjParameters = opt.getProjectionParameters();
650 auto it = newProjParameters.begin();
651 std::cout << "Setting projection parameters to: " << *it;
652 ++it;
653 while (it != newProjParameters.end())
654 {
655 std::cout << ", " << *it;
656 ++it;
657 }
658 std::cout << std::endl;
659 pano.setOptions(opt);
660 }
661 else
662 {
663 std::cout << "Warning: Current projection does not support projection parameters." << std::endl;
664 }
665 }
666 // output exposure value
667 if (outputExposure > -1000 || calcMeanExposure)
668 {
670 if (calcMeanExposure)
671 {
673 }
674 else
675 {
677 {
678 opt.outputExposureValue += outputExposure;
679 }
680 else
681 {
682 opt.outputExposureValue = outputExposure;
683 };
684 };
685 std::cout << "Setting output exposure value to " << opt.outputExposureValue << std::endl;
686 pano.setOptions(opt);
687 };
688 // output range compression
689 if (outputRangeCompression >= 0.0)
690 {
692 opt.outputRangeCompression = outputRangeCompression;
693 std::cout << "Setting output range compression to " << opt.outputRangeCompression << std::endl;
694 pano.setOptions(opt);
695 };
696 // output type: normal, fused, hdr pano..
697 if (!outputType.empty())
698 {
700 // reset all output
701 // final pano
702 opt.outputLDRBlended = false;
703 opt.outputLDRExposureBlended = false;
704 opt.outputLDRExposureLayersFused = false;
705 opt.outputHDRBlended = false;
706 // remapped images
707 opt.outputLDRLayers = false;
708 opt.outputLDRExposureRemapped = false;
709 opt.outputHDRLayers = false;
710 // stacks
711 opt.outputLDRStacks = false;
712 opt.outputHDRStacks = false;
713 // exposure layers
714 opt.outputLDRExposureLayers = false;
715 // now parse string and set corresponding options
716 std::vector<std::string> tokens = hugin_utils::SplitString(outputType, ",");
717 size_t counter = 0;
718 for (size_t i = 0; i < tokens.size(); i++)
719 {
721 if (s == "NORMAL" || s=="N")
722 {
723 opt.outputLDRBlended = true;
724 std::cout << "Activate output of normal panorama." << std::endl;
725 counter++;
726 continue;
727 };
728 if (s == "STACKSFUSEDBLENDED" || s == "FB")
729 {
730 opt.outputLDRExposureBlended = true;
731 std::cout << "Activate output of LDR panorama: Exposure fused from stacks." << std::endl;
732 counter++;
733 continue;
734 };
735 if (s == "EXPOSURELAYERSFUSED" || s == "BF")
736 {
737 opt.outputLDRExposureLayersFused = true;
738 std::cout << "Activate output of LDR panorama: Exposure fused from any arrangement." << std::endl;
739 counter++;
740 continue;
741 };
742 if (s == "HDR")
743 {
744 opt.outputHDRBlended = true;
745 std::cout << "Activate output of hdr panorama." << std::endl;
746 counter++;
747 continue;
748 };
749 // single remapped images
750 if (s == "REMAP")
751 {
752 opt.outputLDRLayers = true;
753 std::cout << "Activate output of remapped, exposure corrected images." << std::endl;
754 counter++;
755 continue;
756 };
757 if (s == "REMAPORIG")
758 {
759 opt.outputLDRExposureRemapped = true;
760 std::cout << "Activate output of remapped images with unmodified exposure." << std::endl;
761 counter++;
762 continue;
763 };
764 if (s == "HDRREMAP")
765 {
766 opt.outputHDRLayers = true;
767 std::cout << "Activate output of remapped hdr images." << std::endl;
768 counter++;
769 continue;
770 };
771 //stacks
772 if (s == "FUSEDSTACKS")
773 {
774 opt.outputLDRStacks = true;
775 std::cout << "Activate output of exposure fused stacks." << std::endl;
776 counter++;
777 continue;
778 };
779 if (s == "HDRSTACKS")
780 {
781 opt.outputHDRStacks = true;
782 std::cout << "Activate output of HDR stacks." << std::endl;
783 counter++;
784 continue;
785 };
786 //exposure layers
787 if (s == "EXPOSURELAYERS")
788 {
789 opt.outputLDRExposureLayers = true;
790 std::cout << "Activate output of exposure layers." << std::endl;
791 counter++;
792 continue;
793 };
794 std::cout << "Unknown parameter \"" << s << "\" found in --output-type." << std::endl
795 << "Ignoring this parameter." << std::endl;
796 }
797 if (counter > 0)
798 {
799 pano.setOptions(opt);
800 }
801 else
802 {
803 std::cout << "No matching output type given. The whole output-type is ignored." << std::endl;
804 };
805 };
806 // cropped or uncropped tiff output
807 if (outputCroppedTiff != -1)
808 {
810 opts.tiff_saveROI = (outputCroppedTiff == 1);
811 std::cout << "Setting support for cropped images: " << ((outputCroppedTiff == 1) ? "yes" : "no") << std::endl;
812 pano.setOptions(opts);
813 }
814 // blender type
815 if (!blender.empty())
816 {
818 if (blender == "enblend")
819 {
821 std::cout << "Setting blender type to \"ENBLEND\"." << std::endl;
822 }
823 else
824 {
825 if (blender == "internal" || blender == "verdandi")
826 {
828 std::cout << "Setting blender type to \"INTERNAL\"." << std::endl;
829 }
830 else
831 {
832 std::cout << "Blender \"" << blender << "\" is not a valid blender ." << std::endl
833 << "Ignoring parameter." << std::endl;
834 };
835 };
836 pano.setOptions(opt);
837 }
838 if (blenderArgs != EMPTYARG)
839 {
841 switch (opt.blendMode)
842 {
845 std::cout << "Setting enblend arguments to " << blenderArgs << std::endl;
846 break;
848 opt.verdandiOptions = blenderArgs;
849 std::cout << "Setting verdandi arguments to " << blenderArgs << std::endl;
850 break;
851 default:
852 std::cout << "Unknown blender in pto file." << std::endl;
853 break;
854 };
855 pano.setOptions(opt);
856 };
857 if (fusionArgs != EMPTYARG)
858 {
861 std::cout << "Setting enfuse arguments to " << fusionArgs << std::endl;
862 pano.setOptions(opt);
863 };
864 if (hdrMergeArgs != EMPTYARG)
865 {
868 std::cout << "Setting hugin_hdrdmerge arguments to " << hdrMergeArgs << std::endl;
869 pano.setOptions(opt);
870 };
871 // ldr output file type
872 if (!ldrfiletype.empty())
873 {
875 if (ldrfiletype == "jpg" || ldrfiletype == "png" || ldrfiletype == "tif")
876 {
878 std::cout << "Setting ldr output to filetype \"" << ldrfiletype << "\"." << std::endl;
879 pano.setOptions(opt);
880 }
881 else
882 {
883 std::cout << "LDR file format \"" << ldrfiletype << "\" is not a valid LDR output filetype." << std::endl
884 << "Ignoring parameter." << std::endl;
885 };
886 };
887 // ldr compression
888 if (!ldrcompression.empty())
889 {
891 if (opt.outputImageType == "tif")
892 {
893 if (ldrcompression == "NONE" || ldrcompression == "PACKBITS" || ldrcompression == "LZW" || ldrcompression == "DEFLATE")
894 {
896 std::cout << "Setting TIF compression to \"" << ldrcompression << "\"." << std::endl;
897 opt.tiffCompression = ldrcompression;
898 }
899 else
900 {
901 std::cout << "LDR compression \"" << ldrcompression << "\" is not a valid compression value for TIF files." << std::endl
902 << "Ignoring compression." << std::endl;
903 }
904 }
905 else
906 {
907 if (opt.outputImageType == "jpg")
908 {
909 int quality = 0;
910 quality = atoi(ldrcompression.c_str());
911 if (quality != 0)
912 {
913 if (quality>0 && quality <=100)
914 {
915 opt.quality = quality;
916 std::cout << "Setting JPEG quality to " << quality << "." << std::endl;
917 }
918 else
919 {
920 std::cout << "Given value for JPEG quality is outside the valid range 1..100." << std::endl
921 << "Ignoring value." << std::endl;
922 };
923 }
924 else
925 {
926 std::cout << "Could not parse \"" << ldrcompression << "\" as a valid JPEG quality number." << std::endl
927 << "Ignoring value." << std::endl;
928 };
929 }
930 else
931 {
932 if (opt.outputImageType == "png")
933 {
934 std::cout << "Setting compression for PNG images is not supported." << std::endl;
935 }
936 else
937 {
938 // this should never happen
939 std::cout << "Unknown image format" << std::endl;
940 };
941 };
942 };
943 pano.setOptions(opt);
944 };
945 // hdr output file type
946 if (!hdrfiletype.empty())
947 {
949 if (hdrfiletype == "exr" || hdrfiletype == "tif")
950 {
952 std::cout << "Setting hdr output to filetype \"" << hdrfiletype << "\"." << std::endl;
953 pano.setOptions(opt);
954 }
955 else
956 {
957 std::cout << "HDR file format \"" << hdrfiletype << "\" is not a valid HDR output filetype." << std::endl
958 << "Ignoring parameter." << std::endl;
959 };
960 };
961 // hdr compression
962 if (!hdrcompression.empty())
963 {
965 if (opt.outputImageTypeHDR == "tif")
966 {
967 if (hdrcompression == "NONE" || hdrcompression == "PACKBITS" || hdrcompression == "LZW" || hdrcompression == "DEFLATE")
968 {
970 std::cout << "Setting HDR-TIF compression to \"" << hdrcompression << "\"." << std::endl;
971 }
972 else
973 {
974 std::cout << "HDR compression \"" << hdrcompression << "\" is not a valid compression value for TIF files." << std::endl
975 << "Ignoring compression." << std::endl;
976 }
977 }
978 else
979 {
980 if (opt.outputImageTypeHDR == "exr")
981 {
982 std::cout << "Setting compression for EXR images is not supported." << std::endl;
983 }
984 else
985 {
986 // this should never happen
987 std::cout << "Unknown HDR image format" << std::endl;
988 };
989 };
990 pano.setOptions(opt);
991 };
992 // rotate complete pano
993 if (std::abs(yaw) + std::abs(pitch) + std::abs(roll) > 0.0)
994 {
995 std::cout << "Rotate panorama (yaw=" << yaw << ", pitch= " << pitch << ", roll=" << roll << ")" << std::endl;
996 HuginBase::RotatePanorama(pano, yaw, pitch, roll).run();
997 };
998 // translate complete pano
999 if(std::abs(x) + std::abs(y) + std::abs(z) > 0.0)
1000 {
1001 std::cout << "Translate panorama (x=" << x << ", y=" << y << ", z=" << z << ")" << std::endl;
1002 HuginBase::TranslatePanorama(pano, x, y, z).run();
1003 };
1004 // straighten
1005 if(doStraighten)
1006 {
1007 std::cout << "Straighten panorama" << std::endl;
1010 };
1011 // center
1012 if(doCenter)
1013 {
1014 std::cout << "Center panorama" << std::endl;
1016 }
1017 //fit fov
1018 if(doFit)
1019 {
1020 std::cout << "Fit panorama field of view to best size" << std::endl;
1022 HuginBase::CalculateFitPanorama fitPano(pano);
1023 fitPano.run();
1024 opt.setHFOV(fitPano.getResultHorizontalFOV());
1025 opt.setHeight(hugin_utils::roundi(fitPano.getResultHeight()));
1026 std::cout << "Setting field of view to " << opt.getHFOV() << " x " << opt.getVFOV() << std::endl;
1027 pano.setOptions(opt);
1028 };
1029 //set field of view manually
1030 if(newHFOV>0)
1031 {
1034 if(opt.fovCalcSupported(opt.getProjection()) && newVFOV>0)
1035 {
1036 opt.setVFOV(newVFOV);
1037 }
1038 std::cout << "Setting field of view to " << opt.getHFOV() << " x " << opt.getVFOV() << std::endl;
1039 pano.setOptions(opt);
1040 };
1041 // calc optimal size
1042 if(doOptimalSize)
1043 {
1044 std::cout << "Calculate optimal size of panorama" << std::endl;
1047 opt.setWidth(hugin_utils::roundi(opt.getWidth()*s*scale/100), true);
1048 std::cout << "Setting canvas size to " << opt.getWidth() << " x " << opt.getHeight() << std::endl;
1049 pano.setOptions(opt);
1050 };
1051 // set canvas size
1052 if(newWidth>0 && newHeight>0)
1053 {
1056 opt.setHeight(newHeight);
1057 std::cout << "Setting canvas size to " << opt.getWidth() << " x " << opt.getHeight() << std::endl;
1058 pano.setOptions(opt);
1059 };
1060 // auto crop
1061 if (doAutocrop != AutoCropMode::NONE)
1062 {
1063 std::cout << "Searching for best crop rectangle" << std::endl;
1065 vigra::Rect2D roi;
1066 if (doAutocrop == AutoCropMode::AUTOOUTSIDE)
1067 {
1069 cropPano.run();
1070 roi = cropPano.getResultOptimalROI();
1071 }
1072 else
1073 {
1075 if (doAutocrop == AutoCropMode::AUTOHDR)
1076 {
1077 cropPano.setStacks(getHDRStacks(pano, pano.getActiveImages(), pano.getOptions()));
1078 }
1079 cropPano.run();
1080 roi = cropPano.getResultOptimalROI();
1081 };
1083 //set the ROI - fail if the right/bottom is zero, meaning all zero
1084 if(!roi.isEmpty())
1085 {
1086 opt.setROI(roi);
1087 std::cout << "Set crop size to " << roi.left() << "," << roi.top() << "," << roi.right() << "," << roi.bottom() << std::endl;
1088 pano.setOptions(opt);
1089 }
1090 else
1091 {
1092 std::cout << "Could not find best crop rectangle" << std::endl;
1093 }
1094 };
1095 //setting crop rectangle manually
1096 if(newROI.right() != 0 && newROI.bottom() != 0)
1097 {
1099 opt.setROI(newROI);
1100 std::cout << "Set crop size to " << opt.getROI().left() << "," << opt.getROI().right() << "," << opt.getROI().top() << "," << opt.getROI().bottom() << std::endl;
1101 pano.setOptions(opt);
1102 };
1104 {
1106 opt.setROI(vigra::Rect2D(
1107 opt.getWidth() * newRoiRelativeLeftTop.x / 100.0,
1108 opt.getHeight() * newRoiRelativeLeftTop.y / 100.0,
1109 opt.getWidth() * newRoiRelativeRightBottom.x / 100.0,
1110 opt.getHeight() * newRoiRelativeRightBottom.y / 100.0
1111 ));
1112 std::cout << "Set crop size to " << opt.getROI().left() << "," << opt.getROI().right() << "," << opt.getROI().top() << "," << opt.getROI().bottom() << std::endl;
1113 pano.setOptions(opt);
1114 }
1115 //setting interpolation method
1116 if (interpolation>=0)
1117 {
1120 std::cout << "Set interpolation method to " << interpolation << std::endl;
1121 pano.setOptions(opt);
1122 };
1123 // read settings from ini file and apply it
1124 if (!iniFile.empty())
1125 {
1126 std::cout << "Reading panorama options from " << iniFile << std::endl;
1128 pano.setOptions(options);
1129 };
1130 // read settings from other pto file and apply only PanoramaOptions
1131 if (!templateFile.empty())
1132 {
1133 // read template panorama
1136 {
1137 return 1;
1138 };
1139 std::cout << "Applying settings from " << templateFile << std::endl;
1140 pano.setOptions(templatePano.getOptions());
1141 };
1142 //write output
1143 // Set output .pto filename if not given
1146 {
1147 std::cout << std::endl << "Written output to " << output << std::endl;
1148 };
1149
1150 return 0;
1151}
declaration of functions to handle stacks and layers
static void usage()
Definition Main.cpp:32
HuginBase::PanoramaOptions ReadPanoramaOptionsFromIni(const std::string &iniFile, HuginBase::Panorama &pano)
read settings from given ini file and apply wished settings if they are applicable
read settings from ini file and apply only applicable values
Dummy progress display, without output.
virtual double getResultHorizontalFOV()
Definition FitPanorama.h:68
virtual double getResultHeight()
Definition FitPanorama.h:75
static double calcMeanExposure(const PanoramaData &pano)
static double calcOptimalScale(PanoramaData &panorama)
virtual void run()
runs the algorithm.
Panorama image options.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
vigra_ext::Interpolator interpolator
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
void setROI(const vigra::Rect2D &val)
bool outputLDRBlended
save blended panorama (LDR)
ProjectionFormat
Projection of final panorama.
std::string outputImageTypeHDRCompression
pano_projection_features m_projFeatures
Model for a panorama.
Definition Panorama.h:153
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition Panorama.h:481
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...
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 WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
UIntSet getActiveImages() const
get active images
TDiff2D< double > FDiff2D
Definition hugin_math.h:162
std::string toupper(const std::string &s)
Definition stl_utils.h:59
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
Definition utils.cpp:294
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
Definition utils.cpp:208
int roundi(T x)
Definition hugin_math.h:73
std::string tolower(const std::string &s)
convert a string to lowercase
Definition stl_utils.h:49
std::string GetHuginVersion()
return a string with version numbers
Definition utils.cpp:907
bool FileExists(const std::string &filename)
checks if file exists
Definition utils.cpp:362
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
Definition utils.h:114
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition utils.cpp:420
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition utils.cpp:160
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition utils.cpp:184
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
Definition utils.cpp:264
Interpolator
enum with all interpolation methods
int main(int argc, char *argv[])
#define EMPTYARG
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41