27 #include <wx/config.h> 
   28 #include <wx/translation.h> 
   29 #include <wx/arrstr.h> 
   30 #include <wx/filefn.h> 
   31 #include <wx/txtstrm.h> 
   32 #include <wx/wfstream.h> 
   49             wxArrayString filenames;
 
   50             for (HuginBase::UIntSet::const_iterator it = img.begin(); it != img.end(); ++it)
 
   52                 filenames.Add(wxString::Format(
"%s%04u%s", prefix.c_str(), *it, postfix.c_str()));
 
   58         void AddToArray(
const wxArrayString& input, wxArrayString& output)
 
   60             for (
size_t i = 0; i < input.size(); ++i)
 
   71             wxString argfileInput = config->Read(
"/output/FinalArgfile", wxEmptyString);
 
   72             const bool generateGPanoTags = (config->Read(
"/output/writeGPano", 
HUGIN_EXIFTOOL_CREATE_GPANO) == 1l) && (exifToolVersion >= 9.09);
 
   73             pano_projection_features proj;
 
   75             const bool readProjectionName = panoProjectionFeaturesQuery(opts.
getProjection(), &proj) != 0;
 
   81                 Placeholder(
const wxString& holder, 
const wxString& newValue)
 
   87             std::list<Placeholder> placeholders;
 
   89             const wxString linebreak(
"
");
 
   91             const wxString linebreak(
"
");
 
   93             if (readProjectionName)
 
   96                 placeholders.push_back(Placeholder(
"%projectionNumber", wxString::Format(
"%d", opts.
getProjection())));
 
   97                 placeholders.push_back(Placeholder(
"%projection", wxString(proj.name, wxConvLocal)));
 
  100             placeholders.push_back(Placeholder(
"%hfov", wxString::Format(
"%.0f", opts.
getHFOV())));
 
  101             placeholders.push_back(Placeholder(
"%vfov", wxString::Format(
"%.0f", opts.
getVFOV())));
 
  102             placeholders.push_back(Placeholder(
"%ev", wxString::Format(
"%.2f", opts.
outputExposureValue)));
 
  103             placeholders.push_back(Placeholder(
"%nrImages", wxString::Format(
"%lu", (
unsigned long)images.size())));
 
  104             placeholders.push_back(Placeholder(
"%nrAllImages", wxString::Format(
"%lu", (
unsigned long)pano.
getNrOfImages())));
 
  105             placeholders.push_back(Placeholder(
"%fullwidth", wxString::Format(
"%u", opts.
getWidth())));
 
  106             placeholders.push_back(Placeholder(
"%fullheight", wxString::Format(
"%u", opts.
getHeight())));
 
  107             placeholders.push_back(Placeholder(
"%width", wxString::Format(
"%d", opts.
getROI().width())));
 
  108             placeholders.push_back(Placeholder(
"%height", wxString::Format(
"%d", opts.
getROI().height())));
 
  109             wxFileName projectFilename(projectName);
 
  110             placeholders.push_back(Placeholder(
"%projectname", projectFilename.GetFullName()));
 
  112             wxFileName tempArgfileFinal(wxFileName::CreateTempFileName(
GetConfigTempDir(config) + 
"he"));
 
  113             wxFFileOutputStream outputStream(tempArgfileFinal.GetFullPath());
 
  114             wxTextOutputStream outputFile(outputStream);
 
  117             outputFile << 
"-E" << endl;
 
  118             outputFile << 
"-UserComment<${UserComment}" << linebreak;
 
  119             if (readProjectionName)
 
  121                 outputFile << 
"Projection: " << wxString(proj.name, wxConvLocal) << 
" (" << opts.
getProjection() << 
")" << linebreak;
 
  123             outputFile << 
"FOV: " << wxString::Format(
"%.0f", opts.
getHFOV()) << 
" x " << wxString::Format(
"%.0f", opts.
getVFOV()) << linebreak;
 
  125             outputFile << 
"-f" << endl;
 
  126             if (exifToolVersion >= 11.53)
 
  130                 outputFile << 
"-CompositeImage=General Composite Image" << endl;
 
  131                 outputFile << wxString::Format(
"-CompositeImageCount=%lu %lu", (
unsigned long)pano.
getNrOfImages(), (
unsigned long)pano.
getActiveImages().size()) << endl;
 
  133             if (generateGPanoTags)
 
  139                     const vigra::Rect2D roi = opts.
getROI();
 
  140                     int left = roi.left();
 
  142                     int width = roi.width();
 
  143                     int height = roi.height();
 
  148                         fullWidth = 
static_cast<int>(opts.
getWidth() * 360.0 / opts.
getHFOV());
 
  149                         left += (fullWidth - opts.
getWidth()) / 2;
 
  152                     if (!isCylindrical && opts.
getVFOV()<180)
 
  155                         top += (fullHeight - opts.
getHeight()) / 2;
 
  160                         top =  height/2 - top;
 
  162                     outputFile << 
"-UsePanoramaViewer=True" << endl;
 
  163                     outputFile << 
"-StitchingSoftware=Hugin" << endl;
 
  166                         outputFile << 
"-ProjectionType=cylindrical" << endl;
 
  170                         outputFile << 
"-ProjectionType=equirectangular" << endl;
 
  172                     outputFile << 
"-CroppedAreaLeftPixels=" << left << endl;
 
  173                     outputFile << 
"-CroppedAreaTopPixels=" << top << endl;
 
  174                     outputFile << 
"-CroppedAreaImageWidthPixels=" << width << endl;
 
  175                     outputFile << 
"-CroppedAreaImageHeightPixels=" << height << endl;
 
  176                     outputFile << 
"-FullPanoWidthPixels=" << fullWidth << endl;
 
  180                         outputFile << 
"-FullPanoHeightPixels=" << fullHeight << endl;
 
  182                     outputFile << 
"-SourcePhotosCount=" << 
static_cast<wxUint32
>(pano.
getNrOfImages()) << endl;
 
  186             if (!argfileInput.IsEmpty())
 
  188                 if (wxFileExists(argfileInput))
 
  190                     wxFileInputStream inputFileStream(argfileInput);
 
  191                     wxTextInputStream input(inputFileStream);
 
  192                     while (inputFileStream.IsOk() && !inputFileStream.Eof())
 
  194                         wxString 
line = input.ReadLine();
 
  196                         for (
auto variable : placeholders)
 
  198                             line.Replace(variable.placeholder, variable.value, 
true);
 
  201                         outputFile << line << endl;
 
  205             return tempArgfileFinal.GetFullPath();
 
  211             const wxString wxEndl(
"\n");
 
  213                 << 
"============================================" << wxEndl
 
  214                 << _(
"Stitching panorama...") << wxEndl
 
  215                 << 
"============================================" << wxEndl
 
  217                 << _(
"Platform:") << 
" " << wxGetOsDescription() << wxEndl
 
  219                 << _(
"Working directory:") << 
" " << wxFileName::GetCwd() << wxEndl
 
  220                 << _(
"Output prefix:") << 
" " << prefix << wxEndl
 
  229                             wxArrayString version;
 
  232                                 output << _(
"Blender:") << 
" " << version[0] << wxEndl;
 
  236                                 output << _(
"Blender:") << 
" " << _(
"Unknown blender (enblend --version failed)") << wxEndl;
 
  242                         output << _(
"Blender:") << 
" " << _(
"internal") << wxEndl;
 
  248                 wxArrayString version;
 
  251                     output << _(
"Exposure fusion:") << 
" " << version[0] << wxEndl;
 
  255                     output << _(
"Exposure fusion:") << 
" " << _(
"Unknown exposure fusion (enfuse --version failed)") << wxEndl;
 
  260                 wxArrayString version;
 
  263                     output << _(
"ExifTool version:") << 
" " << version[0] << wxEndl;
 
  264                     version[0].ToCDouble(&exiftoolVersion);
 
  268                     output << _(
"ExifTool:") << 
" " << _(
"FAILED") << wxEndl;
 
  274                 << _(
"Number of active images:") << 
" " << allActiveImages.size() << wxEndl
 
  276                 << wxString::Format(_(
"Canvas size: %dx%d"), opts.
getSize().width(), opts.
getSize().height()) << wxEndl
 
  277                 << wxString::Format(_(
"ROI: (%d, %d) - (%d, %d)"), opts.
getROI().left(), opts.
getROI().top(), opts.
getROI().right(), opts.
getROI().bottom()) << 
" " << wxEndl
 
  278                 << wxString::Format(_(
"FOV: %.0fx%.0f"), opts.
getHFOV(), opts.
getVFOV()) << wxEndl;
 
  279             pano_projection_features proj;
 
  280             const bool readProjectionName = panoProjectionFeaturesQuery(opts.
getProjection(), &proj) != 0;
 
  281             if (readProjectionName)
 
  284                     << _(
"Projection:") << 
" " << wxGetTranslation(wxString(proj.name, wxConvLocal))
 
  290                     << _(
"Projection:") << 
" " << opts.
getProjection() << wxEndl;
 
  293                 << _(
"Using GPU for remapping:") << 
" " << (opts.
remapUsingGPU ? _(
"true") : _(
"false")) << wxEndl
 
  297                 output << _(
"Panorama Outputs:") << wxEndl;
 
  300                     output << 
"* " << _(
"Exposure corrected, low dynamic range") << wxEndl;
 
  304                     output << 
"* " << _(
"Exposure fused from stacks") << wxEndl;
 
  308                     output << 
"* " << _(
"Exposure fused from any arrangement") << wxEndl;
 
  312                     output << 
"* " << _(
"High dynamic range") << wxEndl;
 
  318                 output << _(
"Remapped Images:") << wxEndl;
 
  321                     output << 
"* " << _(
"Exposure corrected, low dynamic range") << wxEndl;
 
  325                     output << 
"* " << _(
"No exposure correction, low dynamic range") << wxEndl;
 
  329                     output << 
"* " << _(
"High dynamic range") << wxEndl;
 
  335                 output << _(
"Combined stacks:") << wxEndl;
 
  338                     output << 
"* " << _(
"Exposure fused stacks") << wxEndl;
 
  342                     output << 
"* " << _(
"High dynamic range") << wxEndl;
 
  348                 output << _(
"Layers:") << wxEndl
 
  349                     << 
"* " << _(
"Blended layers of similar exposure, without exposure correction") << wxEndl
 
  353             output << _(
"First input image") << wxEndl
 
  354                 << _(
"Number:") << 
" " << *allActiveImages.begin() << wxEndl
 
  355                 << _(
"Filename:") << 
" " << img.getFilename() << wxEndl
 
  359                 << wxString::Format(_(
"HFOV: %.0f"), img.getHFOV()) << wxEndl
 
  360                 << wxString::Format(_(
"Exposure value: %.1f"), img.getExposureValue()) << wxEndl
 
  377             for (
size_t i = 0; i < stacks.size(); ++i)
 
  383                 stackImgs.insert(*(stacks[i].begin()));
 
  388             fill_set(subpanoImgs, 0, stackImgs.size() - 1);
 
  394             for (
size_t i = 0; i < blendOrder.size();++i)
 
  409                     _(
"Filling edges...")));
 
  419         if (allActiveImages.empty())
 
  421             errStream << 
"ERROR: No active images in ROI. Nothing to do." << std::endl;
 
  424         std::vector<HuginBase::UIntSet> stacks;
 
  428         wxConfigBase* config = wxConfigBase::Get();
 
  432             errStream << 
"ERROR: Only nona remappper is supported by hugin_executor." << std::endl;
 
  437             errStream << 
"ERROR: Only enblend and internal remappper are currently supported by hugin_executor." << std::endl;
 
  442             errStream << 
"ERROR: Only hdr merger HDRMERGE_AVERAGE is currently supported by hugin_executor." << std::endl;
 
  445         double exiftoolVersion;
 
  450         wxString nonaArgs(
"-v ");
 
  451         wxString enLayersCompressionArgs;
 
  461                 nonaArgs.Append(
"-z LZW ");
 
  466             nonaArgs.Append(
"-g ");
 
  469         wxString enblendArgs;
 
  475                 enblendArgs.Append(
" -w");
 
  477             const vigra::Rect2D roi (opts.
getROI());
 
  478             if (roi.top() != 0 || roi.left() != 0)
 
  480                 enblendArgs << 
" -f" << roi.width() << 
"x" << roi.height() << 
"+" << roi.left() << 
"+" << roi.top();
 
  484                 enblendArgs << 
" -f" << roi.width() << 
"x" << roi.height();
 
  486             enblendArgs.Append(
" ");
 
  489         wxString verdandiArgs;
 
  495                 verdandiArgs.Append(
" -w");
 
  499         wxString finalCompressionArgs;
 
  508                 finalCompressionArgs << 
" --compression=" << opts.
quality;
 
  511         finalCompressionArgs.Append(
" ");
 
  516             enfuseArgs.Append(
" -w");
 
  518         const vigra::Rect2D roi (opts.
getROI());
 
  519         if (roi.top() != 0 || roi.left() != 0)
 
  521             enfuseArgs << 
" -f" << roi.width() << 
"x" << roi.height() << 
"+" << roi.left() << 
"+" << roi.top();
 
  525             enfuseArgs << 
" -f" << roi.width() << 
"x" << roi.height();
 
  527         enfuseArgs.Append(
" ");
 
  530         const bool copyMetadata = config->Read(
"/output/useExiftool", 
HUGIN_USE_EXIFTOOL) == 1l;
 
  531         wxString exiftoolArgs;
 
  532         wxString exiftoolArgsFinal;
 
  535             exiftoolArgs = 
"-overwrite_original -TagsFromFile ";
 
  538             exiftoolArgs.Append(
" -WhitePoint -ColorSpace");
 
  539             wxString exiftoolArgfile = config->Read(
"/output/CopyArgfile", wxEmptyString);
 
  540             if (exiftoolArgfile.IsEmpty())
 
  544             wxFileName argfile(exiftoolArgfile);
 
  545             argfile.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
 
  546             exiftoolArgs.Append(
" -@ " + 
wxEscapeFilename(argfile.GetFullPath()) + 
" ");
 
  548             if (!finalArgfile.IsEmpty())
 
  551                 tempFilesDelete.Add(finalArgfile);
 
  554         wxArrayString filesForFullExiftool;
 
  555         wxArrayString filesForCopyTagsExiftool;
 
  566                 wxString finalNonaArgs(
"-v -r ldr ");
 
  569                     finalNonaArgs.Append(
"-g ");
 
  574                     finalNonaArgs.Append(
" ");
 
  576                 wxString edgeInputFile;
 
  579                     finalNonaArgs.Append(
"-m TIFF -z " + opts.
tiffCompression + 
" --final-suffix=_nofill ");
 
  580                     edgeInputFile = prefix + 
"_nofill.tif";
 
  581                     outputFiles.Add(edgeInputFile);
 
  586                             filesForFullExiftool.Add(edgeInputFile);
 
  591                         tempFilesDelete.Add(edgeInputFile);
 
  598                         finalNonaArgs.Append(
"-m TIFF ");
 
  608                             finalNonaArgs.Append(
"-m JPEG -z ");
 
  609                             finalNonaArgs << opts.
quality << 
" ";
 
  615                                 finalNonaArgs.Append(
"-m PNG ");
 
  619                                 errStream << 
"ERROR: Invalid output image type found." << std::endl;
 
  627                     finalNonaArgs.Append(
"--save-intermediate-images ");
 
  630                 finalNonaArgs.Append(
"-o " + 
wxEscapeFilename(prefix) + 
" " + quotedProject);
 
  632                     finalNonaArgs, _(
"Remapping and blending LDR images...")));
 
  633                 outputFiles.Add(finalFilename);
 
  640                     filesForFullExiftool.Add(finalFilename);
 
  646                     nonaArgs + 
"-r ldr -m TIFF_m -o " + 
wxEscapeFilename(prefix) + 
" " + quotedProject,
 
  647                     _(
"Remapping LDR images...")));
 
  653                         wxString finalEnblendArgs(enblendArgs);
 
  654                         wxString edgeFillInput;
 
  657                             edgeFillInput = prefix + 
"_nofill.tif";
 
  662                             finalEnblendArgs.Append(finalCompressionArgs + 
" -o " + 
wxEscapeFilename(finalFilename) + 
" -- ");
 
  667                             _(
"Blending images..."))
 
  672                             outputFiles.Add(edgeFillInput);
 
  675                                 tempFilesDelete.Add(edgeFillInput);
 
  678                         outputFiles.Add(finalFilename);
 
  683                                 filesForFullExiftool.Add(edgeFillInput);
 
  685                             filesForFullExiftool.Add(finalFilename);
 
  700             std::vector<HuginBase::UIntSet> exposureLayers;
 
  701             wxArrayString exposureLayersFiles;
 
  710                 wxString finalNonaArgs(nonaArgs);
 
  714                     finalNonaArgs.Append(
" ");
 
  716                 finalNonaArgs.append(
"-r ldr --create-exposure-layers --ignore-exposure -o " + 
wxEscapeFilename(prefix + 
"_exposure_"));
 
  719                     finalNonaArgs.append(
" --save-intermediate-images --intermediate-suffix=layers_");
 
  726                 finalNonaArgs.append(
" ");
 
  727                 finalNonaArgs.append(quotedProject);
 
  729                     finalNonaArgs, _(
"Remapping LDR images and blending exposure layers...")));
 
  731                 fill_set(exposureLayersNumber, 0, exposureLayers.size() - 1);
 
  746                     nonaArgs + 
"-r ldr -m TIFF_m --ignore-exposure -o " + 
wxEscapeFilename(prefix + 
"_exposure_layers_") + 
" " + quotedProject,
 
  747                     _(
"Remapping LDR images without exposure correction...")));
 
  757                     for (
unsigned exposureLayer = 0; exposureLayer < exposureLayers.size(); ++exposureLayer)
 
  759                         const wxArrayString exposureLayersImgs = 
detail::GetNumberedFilename(prefix + 
"_exposure_layers_", 
".tif", exposureLayers[exposureLayer]);
 
  760                         const wxString exposureLayerImgName = wxString::Format(
"%s_exposure_%04u%s", prefix.c_str(), exposureLayer, 
".tif");
 
  761                         exposureLayersFiles.Add(exposureLayerImgName);
 
  762                         outputFiles.Add(exposureLayerImgName);
 
  767                             wxString::Format(_(
"Blending exposure layer %u..."), exposureLayer))
 
  771                             filesForCopyTagsExiftool.Add(exposureLayerImgName);
 
  775                             tempFilesDelete.Add(exposureLayerImgName);
 
  782                 const wxString fusedExposureLayersFilename(prefix + 
"_blended_fused." + opts.
outputImageType);
 
  783                 wxString finalEnfuseArgs(enfuseArgs);
 
  784                 wxString edgeFillInput;
 
  787                     edgeFillInput = prefix + 
"_blended_fused_nofill.tif";
 
  792                     finalEnfuseArgs.Append(finalCompressionArgs + 
" -o " + 
wxEscapeFilename(fusedExposureLayersFilename) + 
" -- ");
 
  797                     _(
"Fusing all exposure layers..."))
 
  799                 outputFiles.Add(fusedExposureLayersFilename);
 
  803                     outputFiles.Add(edgeFillInput);
 
  806                         tempFilesDelete.Add(edgeFillInput);
 
  813                         filesForFullExiftool.Add(edgeFillInput);
 
  815                     filesForFullExiftool.Add(fusedExposureLayersFilename);
 
  822                 wxArrayString stackedImages;
 
  824                 for (
unsigned stackNr = 0; stackNr < stacks.size(); ++stackNr)
 
  827                     const wxString stackImgName = wxString::Format(
"%s_stack_ldr_%04u%s", prefix.c_str(), stackNr, 
".tif");
 
  828                     outputFiles.Add(stackImgName);
 
  829                     stackedImages.Add(stackImgName);
 
  833                         wxString::Format(_(
"Fusing stack number %u..."), stackNr))
 
  837                         filesForCopyTagsExiftool.Add(stackImgName);
 
  841                         tempFilesDelete.Add(stackImgName);
 
  846                     const wxString fusedStacksFilename(prefix + 
"_fused." + opts.
outputImageType);
 
  847                     wxString edgeFillInput;
 
  850                         edgeFillInput = prefix + 
"_fused_nofill.tif";
 
  856                             wxString finalEnblendArgs(enblendArgs);
 
  863                                 finalEnblendArgs.Append(finalCompressionArgs + 
" -o " + 
wxEscapeFilename(fusedStacksFilename) + 
" -- ");
 
  868                                 _(
"Blending all stacks..."))
 
  875                             wxString finalVerdandiArgs(verdandiArgs); 
 
  882                                 finalVerdandiArgs.Append(finalCompressionArgs + 
" -o " + 
wxEscapeFilename(fusedStacksFilename));
 
  886                                 finalVerdandiArgs, _(
"Blending all stacks...")));
 
  890                     outputFiles.Add(fusedStacksFilename);
 
  894                         outputFiles.Add(edgeFillInput);
 
  897                             tempFilesDelete.Add(edgeFillInput);
 
  904                             filesForFullExiftool.Add(edgeFillInput);
 
  906                         filesForFullExiftool.Add(fusedStacksFilename);
 
  915                 nonaArgs + 
"-r hdr -m EXR_m  -o " + 
wxEscapeFilename(prefix + 
"_hdr_") + 
" " + quotedProject,
 
  916                 _(
"Remapping HDR images...")));
 
  928                 wxArrayString stackedImages;
 
  930                 for (
unsigned stackNr = 0; stackNr < stacks.size(); ++stackNr)
 
  933                     const wxString stackImgName = wxString::Format(
"%s_stack_hdr_%04u%s", prefix.c_str(), stackNr, 
".exr");
 
  934                     stackedImages.Add(stackImgName);
 
  935                     outputFiles.Add(stackImgName);
 
  938                         wxString::Format(_(
"Merging HDR stack number %u..."), stackNr)));
 
  941                         tempFilesDelete.Add(stackImgName);
 
  947                     wxString finalBlendArgs;
 
  948                     wxString edgeFillInput;
 
  951                         edgeFillInput = prefix + 
"_hdr_nofill.exr";
 
  956                         finalBlendArgs.Append(
" -o " + 
wxEscapeFilename(mergedStacksFilename) + 
" -- ");
 
  964                                     _(
"Blending HDR stacks..."))
 
  971                                 _(
"Blending HDR stacks...")));
 
  974                     outputFiles.Add(mergedStacksFilename);
 
  978                         outputFiles.Add(edgeFillInput);
 
  981                             tempFilesDelete.Add(edgeFillInput);
 
  988                             filesForFullExiftool.Add(edgeFillInput);
 
  990                         filesForFullExiftool.Add(mergedStacksFilename);
 
 1001         if (!filesForCopyTagsExiftool.IsEmpty())
 
 1005                 _(
"Updating metadata...")));
 
 1007         if (!filesForFullExiftool.IsEmpty())
 
 1011                 _(
"Updating metadata...")));
 
 1024             const int& stepNr, 
const wxString& arguments, 
const wxString& description, std::ostream& errStream)
 
 1028                 errStream << 
"ERROR: Step " << stepNr << 
" has no program name specified." << std::endl;
 
 1035             if (prog.CmpNoCase(
"verdandi") == 0)
 
 1041                 if (prog.CmpNoCase(
"hugin_hdrmerge") == 0)
 
 1051             queue->push_back(
new NormalCommand(program, arguments, description));
 
 1060             int prefixPos = args.Find(
"%prefix");
 
 1061             while (prefixPos != wxNOT_FOUND)
 
 1063                 const wxString nextChar = args.Mid(prefixPos + 7, 1);
 
 1064                 if (nextChar == 
"%")
 
 1070                     if (nextChar == 
",")
 
 1072                         const int closingPercent = args.Mid(prefixPos + 8).Find(
"%");
 
 1073                         if (closingPercent < 2)
 
 1077                         wxString postfix = args.Mid(prefixPos + 8, closingPercent);
 
 1078                         args.Replace(
"%prefix," + postfix + 
"%", 
wxEscapeFilename(prefix + postfix), 
true);
 
 1085                 prefixPos = args.Find(
"%prefix");
 
 1093             int pos = args.Find(
"%" + name);
 
 1094             while (pos != wxNOT_FOUND)
 
 1096                 const wxString nextChar = args.Mid(pos + 1 + name.Len(), 1);
 
 1097                 if (nextChar == 
"%")
 
 1099                     args.Replace(
"%" + name + 
"%", wxString::Format(
"%d", value), 
true);
 
 1103                     if (nextChar == 
"*")
 
 1105                         const int closingPercent = args.Mid(pos + 2 + name.Len()).Find(
"%");
 
 1106                         if (closingPercent < 2)
 
 1110                         wxString factorString = args.Mid(pos + 2 + name.Len(), closingPercent);
 
 1112                         if (!factorString.ToCDouble(&factor))
 
 1116                         args.Replace(
"%" + name + 
"*" + factorString + 
"%", wxString::Format(
"%d", 
hugin_utils::roundi(factor*value)), 
true);
 
 1123                 pos = args.Find(
"%" + name);
 
 1134         if (allActiveImages.empty())
 
 1136             errStream << 
"ERROR: No active images in ROI. Nothing to do." << std::endl;
 
 1139         wxFileInputStream input(outputSettings);
 
 1142             errStream << 
"ERROR: Can not open file \"" << outputSettings.mb_str(wxConvLocal) << 
"\"." << std::endl;
 
 1145         wxFileConfig settings(input);
 
 1147         settings.Read(
"/General/StepCount", &stepCount, 0);
 
 1150             errStream << 
"ERROR: User-setting does not define any output steps." << std::endl;
 
 1156             statusText = wxString::Format(_(
"Stitching using \"%s\""), outputSettings.c_str());
 
 1160             statusText = wxString::Format(_(
"Stitching using \"%s\""), desc.c_str());
 
 1162         wxString intermediateImageType = 
GetSettingString(&settings, 
"/General/IntermediateImageType", 
".tif");
 
 1164         if (intermediateImageType.Left(1).Cmp(
".")!=0)
 
 1166             intermediateImageType.Prepend(
".");
 
 1170         const bool needsWrapSwitch = (opts.
getHFOV() == 360.0) && (opts.
getWidth() == opts.
getROI().width());
 
 1171         const vigra::Rect2D roi(opts.
getROI());
 
 1172         wxString sizeString;
 
 1173         if (roi.top() != 0 || roi.left() != 0)
 
 1175             sizeString << roi.width() << 
"x" << roi.height() << 
"+" << roi.left() << 
"+" << roi.top();
 
 1179             sizeString << roi.width() << 
"x" << roi.height();
 
 1182         wxArrayString inputImages;
 
 1183         for (
auto& i : allActiveImages)
 
 1188         std::vector<HuginBase::UIntSet> exposureLayers;
 
 1189         wxArrayString exposureLayersFiles;
 
 1191         std::vector<HuginBase::UIntSet> stacks;
 
 1192         wxArrayString stacksFiles;
 
 1195         for (
size_t i = 0; i < stepCount; ++i)
 
 1197             wxString stepString(
"/Step");
 
 1199             if (!settings.HasGroup(stepString))
 
 1201                 errStream << 
"ERROR: Output specifies " << stepCount << 
" steps, but step " << i << 
" is missing in configuration." << std::endl;
 
 1205             settings.SetPath(stepString);
 
 1207             if (stepType.IsEmpty())
 
 1209                 errStream << 
"ERROR: \"" << stepString.mb_str(wxConvLocal) << 
"\" has no type defined." << std::endl;
 
 1216                 errStream << 
"ERROR: Step " << i << 
" has no arguments given." << std::endl;
 
 1221             if (stepType.CmpNoCase(
"remap") == 0)
 
 1224                 const bool outputLayers = (settings.Read(
"OutputExposureLayers", 0l) == 1l);
 
 1227                     args.Append(
" --create-exposure-layers -o " + 
wxEscapeFilename(prefix + 
"_layer"));
 
 1235                     args, description));
 
 1238                     if (exposureLayers.empty())
 
 1242                         fill_set(exposureLayersNumber, 0, exposureLayers.size() - 1);
 
 1246                     if (settings.Read(
"Keep", 0l) == 0l)
 
 1254                     const bool hdrOutput = args.MakeLower().Find(
"-r hdr") != wxNOT_FOUND;
 
 1260                     if (settings.Read(
"Keep", 0l) == 0l)
 
 1272                 if (stepType.CmpNoCase(
"merge") == 0)
 
 1276                     if (resultFile.IsEmpty())
 
 1278                         errStream << 
"ERROR: Step " << i << 
" has no result file specified." << std::endl;
 
 1282                     resultFile.Replace(
"%prefix%", prefix, 
true);
 
 1285                         errStream << 
"ERROR: Step " << i << 
" has missing %result% placeholder in arguments." << std::endl;
 
 1291                     if (BlenderInput.CmpNoCase(
"all") == 0)
 
 1295                             errStream << 
"ERROR: Step " << i << 
" has missing %input% placeholder in arguments." << std::endl;
 
 1302                         if (BlenderInput.CmpNoCase(
"stacks") == 0)
 
 1308                                 fill_set(stackNumbers, 0, stacks.size() - 1);
 
 1313                                 errStream << 
"ERROR: Step " << i << 
" has missing %input% placeholder in arguments." << std::endl;
 
 1320                             if (BlenderInput.CmpNoCase(
"layers") == 0)
 
 1322                                 if (exposureLayers.empty())
 
 1326                                     fill_set(exposureLayersNumber, 0, exposureLayers.size() - 1);
 
 1331                                     errStream << 
"ERROR: Step " << i << 
" has missing %input% placeholder in arguments." << std::endl;
 
 1338                                 errStream << 
"ERROR: Step " << i << 
" has invalid input type: \"" << BlenderInput.mb_str(wxConvLocal) << 
"\"." << std::endl;
 
 1344                     args.Replace(
"%size%", sizeString, 
true);
 
 1346                     if (needsWrapSwitch && !wrapSwitch.IsEmpty())
 
 1348                         args.Prepend(wrapSwitch + 
" ");
 
 1351                         args, description, errStream))
 
 1355                     outputFiles.Add(resultFile);
 
 1356                     if (settings.Read(
"Keep", 1l) == 0l)
 
 1358                         tempFilesDelete.Add(resultFile);
 
 1363                     if (stepType.CmpNoCase(
"stack") == 0)
 
 1370                             fill_set(stackNumbers, 0, stacks.size() - 1);
 
 1373                         const bool clean = (settings.Read(
"Keep", 0l) == 0l);
 
 1374                         args.Replace(
"%size%", sizeString, 
true);
 
 1376                         for (
size_t stackNr = 0; stackNr < stacks.size(); ++stackNr)
 
 1378                             wxString finalArgs(args);
 
 1382                                 errStream << 
"ERROR: Step " << i << 
" has missing %input% placeholder in arguments." << std::endl;
 
 1386                             if (finalArgs.Replace(
"%output%", 
wxEscapeFilename(stacksFiles[stackNr]), 
true) == 0)
 
 1388                                 errStream << 
"ERROR: Step " << i << 
" has missing %output% placeholder in arguments." << std::endl;
 
 1393                                 finalArgs, description, errStream))
 
 1397                             outputFiles.Add(stacksFiles[stackNr]);
 
 1400                                 tempFilesDelete.Add(stacksFiles[stackNr]);
 
 1406                         if (stepType.CmpNoCase(
"layer") == 0)
 
 1409                             if (exposureLayers.empty())
 
 1413                                 fill_set(exposureLayersNumber, 0, exposureLayers.size() - 1);
 
 1416                             const bool clean = (settings.Read(
"Keep", 0l) == 0l);
 
 1417                             args.Replace(
"%size%", sizeString, 
true);
 
 1419                             for (
size_t exposureLayerNr = 0; exposureLayerNr < exposureLayers.size(); ++exposureLayerNr)
 
 1421                                 wxString finalArgs(args);
 
 1425                                     errStream << 
"ERROR: Step " << i << 
" has missing %input% placeholder in arguments." << std::endl;
 
 1429                                 if (finalArgs.Replace(
"%output%", 
wxEscapeFilename(exposureLayersFiles[exposureLayerNr]), 
true) == 0)
 
 1431                                     errStream << 
"ERROR: Step " << i << 
" has missing %output% placeholder in arguments." << std::endl;
 
 1436                                     finalArgs, description, errStream))
 
 1440                                 outputFiles.Add(exposureLayersFiles[exposureLayerNr]);
 
 1443                                     tempFilesDelete.Add(exposureLayersFiles[exposureLayerNr]);
 
 1449                             if (stepType.CmpNoCase(
"modify") == 0)
 
 1453                                 if (inputFiles.IsEmpty())
 
 1455                                     errStream << 
"ERROR: Step " << i << 
" has no input/output file specified." << std::endl;
 
 1459                                 if (args.Find(
"%file%") == wxNOT_FOUND)
 
 1461                                     errStream << 
"ERROR: Step " << i << 
" has missing %file% placeholder in arguments." << std::endl;
 
 1468                                     errStream << 
"ERROR: Step " << i << 
" has invalid %prefix% placeholder in arguments." << std::endl;
 
 1474                                     errStream << 
"ERROR: Step " << i << 
" has invalid %width% placeholder in arguments." << std::endl;
 
 1480                                     errStream << 
"ERROR: Step " << i << 
" has invalid %height% placeholder in arguments." << std::endl;
 
 1485                                 if (progName.IsEmpty())
 
 1487                                     errStream << 
"ERROR: Step " << i << 
" has no program name specified." << std::endl;
 
 1494 #elif defined __WXMSW__ 
 1496                                 const wxString prog = MSWGetProgname(ExePath, progName);
 
 1498                                 const wxString prog = progName;
 
 1500                                 if (inputFiles.CmpNoCase(
"all") == 0)
 
 1502                                     for (
size_t imgNr = 0; imgNr < remappedImages.size(); ++imgNr)
 
 1504                                         wxString finalArgs(args);
 
 1505                                         finalArgs.Replace(
"%file%", 
wxEscapeFilename(remappedImages[imgNr]), 
true);
 
 1506                                         finalArgs.Replace(
"%sourceimage%", 
wxEscapeFilename(inputImages[imgNr]), 
true);
 
 1507                                         commands->push_back(
new NormalCommand(prog, finalArgs, description));
 
 1512                                     if (inputFiles.CmpNoCase(
"stacks") == 0)
 
 1516                                             errStream << 
"ERROR: Step " << i << 
" requests to modify stacks, but no stack was created before." << std::endl;
 
 1520                                         for (
size_t stackNr = 0; stackNr < stacksFiles.size(); ++stackNr)
 
 1522                                             wxString finalArgs(args);
 
 1524                                             commands->push_back(
new NormalCommand(prog, finalArgs, description));
 
 1529                                         if (inputFiles.CmpNoCase(
"layers") == 0)
 
 1531                                             if (exposureLayers.empty())
 
 1533                                                 errStream << 
"ERROR: Step " << i << 
" requests to modify exposure layers, but no exposure layer was created before." << std::endl;
 
 1537                                             for (
size_t layerNr = 0; layerNr < exposureLayersFiles.size(); ++layerNr)
 
 1539                                                 wxString finalArgs(args);
 
 1540                                                 finalArgs.Replace(
"%file%", 
wxEscapeFilename(exposureLayersFiles[layerNr]), 
true);
 
 1541                                                 commands->push_back(
new NormalCommand(prog, finalArgs, description));
 
 1546                                             inputFiles.Replace(
"%prefix%", prefix, 
true);
 
 1548                                             commands->push_back(
new NormalCommand(prog , args, description));
 
 1555                                 if (stepType.CmpNoCase(
"exiftool") == 0)
 
 1558                                     if (resultFile.IsEmpty())
 
 1560                                         errStream << 
"ERROR: Step " << i << 
" has no result file specified." << std::endl;
 
 1564                                     resultFile.Replace(
"%prefix%", prefix, 
true);
 
 1567                                         errStream << 
"ERROR: Step " << i << 
" has missing %result% placeholder in arguments." << std::endl;
 
 1573                                         args, description));
 
 1577                                     errStream << 
"ERROR: Step " << i << 
" has unknown Type \"" << stepType.mb_str(wxConvLocal) << 
"\"." << std::endl;
 
 1594         for (
size_t i = 0; i < files.size(); ++i)
 
const wxString GetSettingString(wxConfigBase *setting, const wxString &name, const wxString defaultValue)
read a string from setting and remove all whitespaces 
normal command for queue, processing is stopped if an error occurred in program 
PanoramaOptions::ProjectionFormat getProjection() const 
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks 
declaration of functions to handle stacks and layers 
EdgeFillMode edgeFillMode
std::vector< UIntSet > UIntSetVector
std::vector< UIntSet > getExposureLayers(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output exposure layers 
const wxString GetConfigTempDir(const wxConfigBase *config)
return the temp dir from the preferences, ensure that it ends with path separator ...
PanoramaData * getNewSubset(const UIntSet &imgs) const 
bool outputLDRLayers
save remapped layers (LDR) 
optional command for queue, processing of queue is always continued, also if an error occurred ...
interface of CommandQueue creating for stitching engine 
std::string outputLayersCompression
EdgeFillMode
edge fill modes 
bool outputHDRLayers
save remapped layers (HDR) 
unsigned int getHeight() const 
get panorama height 
#define HUGIN_EXIFTOOL_CREATE_GPANO
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI 
void AddToArray(const wxArrayString &input, wxArrayString &output)
append all strings from input array to output array 
#define HUGIN_USE_EXIFTOOL
wxString GetInternalProgram(const wxString &bindir, const wxString &name)
return path and name of external program, which comes bundled with Hugin 
bool set_contains(const _Container &c, const typename _Container::key_type &key)
std::string enfuseOptions
int getHeight() const 
Get the height of the image in pixels. 
std::string outputImageTypeCompression
unsigned int colorReferenceImage
bool outputLDRExposureBlended
< save exposure fused stacks (no exposure adjustment) 
void AddEdgeFillCommand(HuginQueue::CommandQueue *commands, const HuginBase::PanoramaOptions::EdgeFillMode &edgeFillMode, const wxString &ExePath, const wxString &inputFilename, const wxString &outputFilename, const wxString &compression)
adds the command for the edge fill option 
UIntVector getEstimatedBlendingOrder(const PanoramaData &pano, const UIntSet &images, const unsigned int referenceImage)
returns vector of image numbers for blending in approbiate order 
std::set< unsigned int > UIntSet
wxString GenerateFinalArgfile(const HuginBase::Panorama &pano, const wxString &projectName, const wxConfigBase *config, const HuginBase::UIntSet &images, const double exifToolVersion)
generate the final argfile 
const vigra::Rect2D & getROI() const 
std::string GetDataDir()
returns the full path to the data directory 
bool outputLDRBlended
save blended panorama (LDR) 
std::size_t getNrOfImages() const 
number of images. 
bool ReplaceWidthHeightPlaceHolder(wxString &args, const wxString name, int value)
std::vector< unsigned int > UIntVector
int getWidth() const 
Get the width of the image in pixels. 
wxString GetQuotedFilenamesString(const wxArrayString &files)
return a wxString with all files in files quoted 
bool outputHDRBlended
save blended panorama (HDR) 
#define HUGIN_NONA_USEGPU
bool ReplacePrefixPlaceholder(wxString &args, const wxString prefix)
UIntSet getActiveImages() const 
get active images 
std::string tiffCompression
std::string verdandiOptions
bool outputLDRExposureLayers
save blended exposure layers, do not perform fusion (no exposure adjustment) 
void CleanQueue(CommandQueue *queue)
clean the queue, delete all entries, but not the queue itself 
unsigned int getWidth() const 
bool AddBlenderCommand(CommandQueue *queue, const wxString &ExePath, const wxString &prog, const int &stepNr, const wxString &arguments, const wxString &description, std::ostream &errStream)
std::string enblendOptions
const PanoramaOptions & getOptions() const 
returns the options for this panorama 
HDRMergeType hdrMergeMode
const wxString GetSettingStringTranslated(wxConfigBase *setting, const wxString &name, const wxString defaultValue)
read a translated string from settings and remove all whitespaces 
str wxEscapeFilename(const str &arg)
special escaping routine for CommandQueues 
bool outputLDRExposureRemapped
save remapped layers (no exposure adjustment) 
bool outputLDRExposureLayersFused
save blended exposure layers which are then fused (no exposure adjustment) 
std::string outputImageType
std::string outputImageTypeHDR
std::string GetHuginVersion()
return a string with version numbers 
std::string hdrmergeOptions
const SrcPanoImage & getImage(std::size_t nr) const 
get a panorama image, counting starts with 0 
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
All variables of a source image. 
bool outputHDRStacks
save image stacks (HDR) 
CommandQueue * GetStitchingCommandQueueUserOutput(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project, const wxString &prefix, const wxString &outputSettings, wxString &statusText, wxArrayString &outputFiles, wxArrayString &tempFilesDelete, std::ostream &errStream)
generates the command queue for stitching a pano, the commands are parsed from the given executor out...
vigra::Size2D getSize() const 
get size of output image 
CommandQueue * GetStitchingCommandQueue(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project, const wxString &prefix, wxString &statusText, wxArrayString &outputFiles, wxArrayString &tempFilesDelete, std::ostream &errStream)
generates the command queue for stitching a pano it will also generate the necessary exiftool argfile...
BlendingMechanism blendMode
wxString GetExternalProgram(wxConfigBase *config, const wxString &bindir, const wxString &name)
return path and name of external program, which can be overwritten by the user 
std::vector< NormalCommand * > CommandQueue
wxString GetQuotedFilenamesStringForVerdandi(const wxArrayString &files, const HuginBase::Panorama &pano, const HuginBase::UIntSetVector &stacks, const int referenceImage, const bool hardSeam)
build quoted filename list for verdandi 
wxString PrintDetailInfo(const HuginBase::Panorama &pano, const HuginBase::PanoramaOptions &opts, const HuginBase::UIntSet &allActiveImages, const wxString &prefix, const wxString &bindir, wxConfigBase *config, double &exiftoolVersion)
double outputExposureValue
wxArrayString GetNumberedFilename(const wxString &prefix, const wxString &postfix, const HuginBase::UIntSet &img)
returns an array of filenames with numbers