~ubuntu-branches/ubuntu/trusty/hugin/trusty-proposed

« back to all changes in this revision

Viewing changes to src/hugin_base/algorithms/panorama_makefile/PanoramaMakefilelibExport.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2011-01-06 14:28:24 UTC
  • mfrom: (1.1.9 upstream) (0.1.21 experimental)
  • Revision ID: james.westby@ubuntu.com-20110106142824-zn9lxylg5z44dynn
* Drop Cyril Brulebois from Uploaders. Thank you very much for your work.
* Bump package version. (rc3 was re-released as 2010.4.0).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
This file is part of hugin.
 
3
 
 
4
hugin is free software: you can redistribute it and/or modify
 
5
it under the terms of the GNU General Public License as published by
 
6
the Free Software Foundation, either version 2 of the License, or
 
7
(at your option) any later version.
 
8
 
 
9
hugin is distributed in the hope that it will be useful,
 
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
GNU General Public License for more details.
 
13
 
 
14
You should have received a copy of the GNU General Public License
 
15
along with hugin.  If not, see <http://www.gnu.org/licenses/>.
 
16
*/
 
17
 
 
18
/**
 
19
 * @file PanoramaMakefilelibExport.cpp
 
20
 * @brief
 
21
 *  Created on: Aug 5, 2010
 
22
 * @author Florian Achleitner <florian.achleitner.2.6.31@gmail.com>
 
23
 */
 
24
 
 
25
#include "PanoramaMakefilelibExport.h"
 
26
 
 
27
#include <makefilelib/char_type.h>
 
28
#include <iostream>
 
29
#include <stdexcept>
 
30
#include <fstream>
 
31
#include <sstream>
 
32
#include <locale>
 
33
#include <makefilelib/Comment.h>
 
34
#include <makefilelib/Variable.h>
 
35
#include <makefilelib/VariableDef.h>
 
36
#include <makefilelib/VariableRef.h>
 
37
#include <makefilelib/MakefileItem.h>
 
38
#include <makefilelib/Makefile.h>
 
39
#include <makefilelib/AutoVariable.h>
 
40
#include <makefilelib/Newline.h>
 
41
#include <makefilelib/Rule.h>
 
42
#include <makefilelib/Conditional.h>
 
43
#include <makefilelib/Manager.h>
 
44
#include <makefilelib/Anything.h>
 
45
 
 
46
#include <panodata/PanoramaData.h>
 
47
#include <hugin_utils/utils.h>
 
48
#include <hugin_version.h>
 
49
#include <algorithms/basic/CalculateOverlap.h>
 
50
#include <algorithms/nona/ComputeImageROI.h>
 
51
#ifdef _WINDOWS
 
52
#include "windows.h"
 
53
#endif
 
54
 
 
55
/// Automates an very often occuring sequence
 
56
#define  newVarDef(var, name, ...) \
 
57
mf::Variable* var = mgr.own(new mf::Variable(name, __VA_ARGS__)); \
 
58
var->getDef().add();
 
59
 
 
60
namespace HuginBase
 
61
{
 
62
using namespace makefile;
 
63
using namespace std;
 
64
using namespace vigra;
 
65
namespace mf = makefile;
 
66
 
 
67
/// constants
 
68
static const makefile::string hdrgrayRemappedExt("_gray.pgm");
 
69
static const makefile::string hdrRemappedExt(".exr");
 
70
static const makefile::string ldrRemappedExt(".tif");
 
71
static const makefile::string ldrRemappedMode("TIFF_m");
 
72
static const makefile::string hdrRemappedMode("EXR_m");
 
73
 
 
74
// should be moved somewhere else (will be after GSOC anyway)
 
75
vector<UIntSet> getHDRStacks(const PanoramaData & pano, UIntSet allImgs)
 
76
{
 
77
    vector<UIntSet> result;
 
78
 
 
79
    // if no images are available, return empty result vector
 
80
    if ( allImgs.empty() )
 
81
    {
 
82
        return result;
 
83
    }
 
84
 
 
85
    UIntSet stack;
 
86
 
 
87
    CalculateImageOverlap overlap(&pano);
 
88
    overlap.calculate(10);  // we are testing 10*10=100 points
 
89
    do {
 
90
        unsigned srcImg = *(allImgs.begin());
 
91
        stack.insert(srcImg);
 
92
        allImgs.erase(srcImg);
 
93
 
 
94
        // find all images that have a suitable overlap.
 
95
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
 
96
            unsigned srcImg2 = *it;
 
97
            it++;
 
98
            if(overlap.getOverlap(srcImg,srcImg2)>0.7)
 
99
            {
 
100
                stack.insert(srcImg2);
 
101
                allImgs.erase(srcImg2);
 
102
            }
 
103
        }
 
104
        result.push_back(stack);
 
105
        stack.clear();
 
106
    } while (allImgs.size() > 0);
 
107
 
 
108
    return result;
 
109
}
 
110
 
 
111
// should be moved somewhere else (will be after GSOC anyway)
 
112
vector<UIntSet> getExposureLayers(const PanoramaData & pano, UIntSet allImgs)
 
113
{
 
114
    vector<UIntSet> result;
 
115
 
 
116
    // if no images are available, return empty result vector
 
117
    if ( allImgs.empty() )
 
118
    {
 
119
        return result;
 
120
    }
 
121
 
 
122
    UIntSet stack;
 
123
 
 
124
    do {
 
125
        unsigned srcImg = *(allImgs.begin());
 
126
        stack.insert(srcImg);
 
127
        allImgs.erase(srcImg);
 
128
 
 
129
        // find all images that have a suitable overlap.
 
130
        SrcPanoImage simg = pano.getSrcImage(srcImg);
 
131
        // FIXME this should be a user preference
 
132
        double maxEVDiff = 0.5;
 
133
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
 
134
            unsigned srcImg2 = *it;
 
135
            it++;
 
136
            SrcPanoImage simg2 = pano.getSrcImage(srcImg2);
 
137
            if ( fabs(simg.getExposureValue() - simg2.getExposureValue()) < maxEVDiff )
 
138
            {
 
139
                stack.insert(srcImg2);
 
140
                allImgs.erase(srcImg2);
 
141
            }
 
142
        }
 
143
        result.push_back(stack);
 
144
        stack.clear();
 
145
    } while (allImgs.size() > 0);
 
146
 
 
147
    return result;
 
148
}
 
149
 
 
150
 
 
151
// should be moved somewhere else (will be after GSOC anyway)
 
152
UIntSet getImagesinROI (const PanoramaData& pano, const UIntSet activeImages)
 
153
{
 
154
    UIntSet images;
 
155
    PanoramaOptions opts = pano.getOptions();
 
156
    for (UIntSet::const_iterator it = activeImages.begin(); it != activeImages.end(); ++it)
 
157
    {
 
158
        Rect2D roi = estimateOutputROI(pano, opts, *it);
 
159
        if (! (roi.isEmpty())) {
 
160
            images.insert(*it);
 
161
        }
 
162
    }
 
163
    return images;
 
164
}
 
165
 
 
166
bool PanoramaMakefilelibExport::createItems()
 
167
{
 
168
    // we use this Variable for initializing pointers that get an object only under certain conditions
 
169
    mf::Variable* nullvar = mgr.own(new mf::Variable("NOT_DEFINED", "This_variable_has_not_been_defined"));
 
170
 
 
171
    mgr.own_add((new Comment(
 
172
        "makefile for panorama stitching, created by hugin using the new makefilelib")));
 
173
 
 
174
    //----------
 
175
    // set temporary dir if defined
 
176
    if(!tmpDir.empty())
 
177
    {
 
178
#ifdef UNIX_LIKE
 
179
        mgr.own_add(new Comment("set temporary directory for UNIX_LIKE"));
 
180
        mf::Variable* vtmpdir = mgr.own(new mf::Variable("TMPDIR", tmpDir));
 
181
        vtmpdir->setExport(true); vtmpdir->getDef().add();
 
182
#else
 
183
        mgr.own_add(new Comment("set temporary directory for not UNIX_LIKE"));
 
184
        mf::Variable* vtmpdir = mgr.own(new mf::Variable("TEMP", tmpDir));
 
185
        vtmpdir->setExport(true); vtmpdir->getDef().add();
 
186
        mf::Variable* vtmpdir2 = mgr.own(new mf::Variable("TMP", tmpDir));
 
187
        vtmpdir2->setExport(true); vtmpdir2->getDef().add();
 
188
#endif
 
189
    }
 
190
 
 
191
#ifdef _WINDOWS
 
192
    mgr.own_add(new Comment("Force using cmd.exe"));
 
193
    mf::Variable* winshell = mgr.own(new mf::Variable("SHELL", getenv("ComSpec")));
 
194
    winshell->getDef().add();
 
195
#endif
 
196
 
 
197
    //----------
 
198
    // set the tool commands
 
199
    mgr.own_add(new Comment("Tool configuration"));
 
200
    newVarDef(vnona, "NONA", progs.nona);
 
201
    newVarDef(vPTStitcher, "PTSTITCHER", progs.PTStitcher);
 
202
    newVarDef(vPTmender, "PTMENDER", progs.PTmender);
 
203
    newVarDef(vPTblender, "PTBLENDER", progs.PTblender);
 
204
    newVarDef(vPTmasker, "PTMASKER", progs.PTmasker);
 
205
    newVarDef(vPTroller, "PTROLLER", progs.PTroller);
 
206
    newVarDef(venblend, "ENBLEND", progs.enblend);
 
207
    newVarDef(venfuse, "ENFUSE", progs.enfuse);
 
208
    newVarDef(vsmartblend, "SMARTBLEND", progs.smartblend);
 
209
    newVarDef(vhdrmerge, "HDRMERGE", progs.hdrmerge);
 
210
#ifdef _WINDOWS
 
211
    newVarDef(vrm, "RM", "del", Makefile::NONE);
 
212
#else
 
213
    newVarDef(vrm, "RM", "rm");
 
214
#endif
 
215
 
 
216
    mf::Variable* vexiftool = mgr.own(new mf::Variable("EXIFTOOL", progs.exiftool));
 
217
    vexiftool->getDef().add();
 
218
 
 
219
    //----------
 
220
    // Project parameters
 
221
    mgr.own_add(new Comment("Project parameters"));
 
222
    PanoramaOptions opts = pano.getOptions();
 
223
    mf::Variable* vhugin_projection = mgr.own(new mf::Variable("HUGIN_PROJECTION",
 
224
            opts.getProjection()));
 
225
    vhugin_projection->getDef().add();
 
226
 
 
227
    mf::Variable* vhugin_hfov = mgr.own(new mf::Variable("HUGIN_HFOV", opts.getHFOV()));
 
228
    vhugin_hfov->getDef().add();
 
229
    mf::Variable* vhugin_width = mgr.own(new mf::Variable("HUGIN_WIDTH", opts.getWidth()));
 
230
    vhugin_width->getDef().add();
 
231
    mf::Variable* vhugin_height = mgr.own(new mf::Variable("HUGIN_HEIGHT", opts.getHeight()));
 
232
    vhugin_height->getDef().add();
 
233
 
 
234
    //----------
 
235
    // options for the programs
 
236
    mgr.own_add(new Comment("options for the programs"));
 
237
    // set remapper specific settings
 
238
    mf::Variable* vnonaldr = nullvar;
 
239
    mf::Variable* vnonaopts = nullvar;
 
240
    if(opts.remapper == PanoramaOptions::NONA)
 
241
    {
 
242
        makefile::string val;
 
243
        if (opts.outputImageType == "tif" && opts.outputLayersCompression.size() != 0)
 
244
            val = "-z " + opts.outputLayersCompression;
 
245
        else if (opts.outputImageType == "jpg")
 
246
            val = "-z LZW ";
 
247
 
 
248
        vnonaldr = mgr.own(new mf::Variable("NONA_LDR_REMAPPED_COMP", val, Makefile::NONE));
 
249
        vnonaldr->getDef().add();
 
250
 
 
251
        vnonaopts = mgr.own(new mf::Variable("NONA_OPTS",
 
252
                opts.remapUsingGPU ? "-g " : "", Makefile::NONE));
 
253
        vnonaopts->getDef().add();
 
254
    }
 
255
 
 
256
    // set blender specific settings
 
257
    mf::Variable* venblendopts = nullvar;
 
258
    mf::Variable* venblendldrcomp = nullvar;
 
259
    mf::Variable* venblendhdrcomp = nullvar;
 
260
 
 
261
    if(opts.blendMode == PanoramaOptions::ENBLEND_BLEND)
 
262
    {
 
263
        {
 
264
            valuestream.str("");    // clear the streams buffer
 
265
            valuestream << opts.enblendOptions;
 
266
            if (opts.getHFOV() == 360.0)
 
267
                // blend over the border
 
268
                valuestream << " -w";
 
269
 
 
270
            vigra::Rect2D roi = opts.getROI();
 
271
            if (roi.top() != 0 || roi.left() != 0 )
 
272
                valuestream << " -f" << roi.width() << "x" << roi.height() << "+" << roi.left() << "+" << roi.top();
 
273
            else
 
274
                valuestream << " -f" << roi.width() << "x" << roi.height();
 
275
            venblendopts = mgr.own(new mf::Variable("ENBLEND_OPTS", valuestream.str(), Makefile::NONE));
 
276
            venblendopts->getDef().add();
 
277
        }
 
278
 
 
279
        {
 
280
            valuestream.str("");
 
281
            if (opts.outputImageType == "tif" && opts.outputImageTypeCompression.size() != 0)
 
282
                valuestream << "--compression=" << opts.outputImageTypeCompression;
 
283
            else if (opts.outputImageType == "jpg")
 
284
                valuestream << "--compression=" << opts.quality;
 
285
 
 
286
            venblendldrcomp = mgr.own(new mf::Variable("ENBLEND_LDR_COMP", valuestream.str(), Makefile::NONE));
 
287
            venblendldrcomp->getDef().add();
 
288
        }
 
289
 
 
290
        {
 
291
            makefile::string val;
 
292
            if (opts.outputImageTypeHDR == "tif" && opts.outputImageTypeHDRCompression.size() != 0) {
 
293
                val += "--compression=" + opts.outputImageTypeHDRCompression;
 
294
            }
 
295
            venblendhdrcomp = mgr.own(new mf::Variable("ENBLEND_HDR_COMP", val, Makefile::NONE));
 
296
            venblendhdrcomp->getDef().add();
 
297
        }
 
298
    }
 
299
 
 
300
    mf::Variable* vptblenderopts = nullvar;
 
301
    if(opts.blendMode == PanoramaOptions::PTBLENDER_BLEND)
 
302
    {
 
303
        valuestream.str("");
 
304
        switch (opts.colorCorrection)
 
305
        {
 
306
            case PanoramaOptions::NONE:
 
307
                break;
 
308
            case PanoramaOptions::BRIGHTNESS_COLOR:
 
309
                valuestream << " -k " << opts.colorReferenceImage;
 
310
                break;
 
311
            case PanoramaOptions::BRIGHTNESS:
 
312
                valuestream << " -k " << opts.colorReferenceImage;
 
313
                break;
 
314
            case PanoramaOptions::COLOR:
 
315
                valuestream << " -k " << opts.colorReferenceImage;
 
316
                break;
 
317
        }
 
318
        vptblenderopts = mgr.own(new mf::Variable("PTBLENDER_OPTS", valuestream.str(), Makefile::NONE));
 
319
        vptblenderopts->getDef().add();
 
320
    }
 
321
 
 
322
    //----------
 
323
    mf::Variable* vsmartblendopts = nullvar;
 
324
    if(opts.blendMode == PanoramaOptions::SMARTBLEND_BLEND)
 
325
    {
 
326
        vsmartblendopts = mgr.own(new mf::Variable(
 
327
            "SMARTBLEND_OPTS",
 
328
            opts.getHFOV() == 360.0 ? " -w" : ""));
 
329
        vsmartblendopts->getDef().add();
 
330
        // TODO: build smartblend command line from given images. (requires additional program)
 
331
    }
 
332
 
 
333
    //----------
 
334
    mf::Variable* vhdrmergeopts = nullvar;
 
335
    if(opts.hdrMergeMode == PanoramaOptions::HDRMERGE_AVERAGE)
 
336
    {
 
337
        vhdrmergeopts = mgr.own(new mf::Variable(
 
338
                "HDRMERGE_OPTS", opts.hdrmergeOptions, Makefile::NONE));
 
339
        vhdrmergeopts->getDef().add();
 
340
    }
 
341
 
 
342
    //----------
 
343
    newVarDef(venfuseopts,
 
344
            "ENFUSE_OPTS", opts.enfuseOptions +
 
345
            (opts.getHFOV() == 360.0 ? " -w" : ""), Makefile::NONE);
 
346
 
 
347
    //----------
 
348
    newVarDef(vexiftoolcopyargs,
 
349
            "EXIFTOOL_COPY_ARGS", progs.exiftool_opts, Makefile::NONE);
 
350
 
 
351
 
 
352
    //----------
 
353
    // Panorama output
 
354
    mgr.own_add(new Comment("the output panorama"));
 
355
 
 
356
    newVarDef(vldrremappedprefix,
 
357
        "LDR_REMAPPED_PREFIX", outputPrefix, Makefile::MAKE);
 
358
    newVarDef(vldrremappedprefixshell,
 
359
        "LDR_REMAPPED_PREFIX_SHELL", vldrremappedprefix->getValue(), Makefile::SHELL);
 
360
 
 
361
    newVarDef(vhdrstackremappedprefix,
 
362
        "HDR_STACK_REMAPPED_PREFIX", outputPrefix + "_hdr_", Makefile::MAKE);
 
363
    newVarDef(vhdrstackremappedprefixshell,
 
364
        "HDR_STACK_REMAPPED_PREFIX_SHELL", vhdrstackremappedprefix->getValue(), Makefile::SHELL);
 
365
 
 
366
    newVarDef(vldrexposureremappedprefix,
 
367
        "LDR_EXPOSURE_REMAPPED_PREFIX", outputPrefix + "_exposure_layers_", Makefile::MAKE);
 
368
    newVarDef(vldrexposureremappedprefixshell,
 
369
        "LDR_EXPOSURE_REMAPPED_PREFIX_SHELL", vldrexposureremappedprefix->getValue(), Makefile::SHELL);
 
370
 
 
371
    newVarDef(vprojectfile, "PROJECT_FILE", ptofile, Makefile::MAKE);
 
372
    newVarDef(vprojectfileshell, "PROJECT_FILE_SHELL", ptofile, Makefile::SHELL);
 
373
 
 
374
    newVarDef(vldrblended, "LDR_BLENDED", outputPrefix + "." + opts.outputImageType, Makefile::MAKE);
 
375
    newVarDef(vldrblendedshell, "LDR_BLENDED_SHELL", vldrblended->getValue(), Makefile::SHELL);
 
376
 
 
377
    newVarDef(vldrstackedblended, "LDR_STACKED_BLENDED", outputPrefix + "_fused." + opts.outputImageType, Makefile::MAKE);
 
378
    newVarDef(vldrstackedblendedshell, "LDR_STACKED_BLENDED_SHELL", vldrstackedblended->getValue(), Makefile::SHELL);
 
379
 
 
380
    newVarDef(vldrexposurelayersfused,
 
381
        "LDR_EXPOSURE_LAYERS_FUSED", outputPrefix + "_blended_fused." + opts.outputImageType, Makefile::MAKE);
 
382
    newVarDef(vldrexposurelayersfusedshell,
 
383
        "LDR_EXPOSURE_LAYERS_FUSED_SHELL", vldrexposurelayersfused->getValue(), Makefile::SHELL);
 
384
 
 
385
    newVarDef(vhdrblended, "HDR_BLENDED", outputPrefix + "_hdr." + opts.outputImageTypeHDR, Makefile::MAKE);
 
386
    newVarDef(vhdrblendedshell, "HDR_BLENDED_SHELL", vhdrblended->getValue(), Makefile::SHELL);
 
387
 
 
388
    //----------
 
389
    // Input Image filenames
 
390
    mgr.own_add(new Comment ("first input image"));
 
391
    newVarDef(vinimage1, "INPUT_IMAGE_1", pano.getImage(0).getFilename(), Makefile::MAKE);
 
392
    newVarDef(vinimage1shell, "INPUT_IMAGE_1_SHELL", pano.getImage(0).getFilename(), Makefile::SHELL);
 
393
 
 
394
    mgr.own_add(new Comment("all input images"));
 
395
    // Assemble them all into one string
 
396
    std::vector<std::string> inimages;
 
397
 
 
398
    for (unsigned int i=0; i < pano.getNrOfImages(); i++)
 
399
    {
 
400
        inimages.push_back(pano.getImage(i).getFilename());
 
401
    }
 
402
    newVarDef(vinimages, "INPUT_IMAGES", inimages.begin(), inimages.end(), Makefile::MAKE, "\\\n");
 
403
    newVarDef(vinimagesshell, "INPUT_IMAGES_SHELL", inimages.begin(), inimages.end(), Makefile::SHELL, "\\\n");
 
404
 
 
405
    //----------
 
406
    std::vector<std::string> remappedImages;
 
407
    std::vector<std::string> remappedHDRImages;
 
408
    std::vector<std::string> remappedHDRgrayImages;
 
409
 
 
410
    for (UIntSet::const_iterator it = images.begin(); it != images.end(); it++)
 
411
    {
 
412
        std::ostringstream fn1, fn2, fn3;
 
413
        fn1 << outputPrefix << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
 
414
        fn2 << outputPrefix << "_hdr_" << std::setfill('0') << std::setw(4) << *it << hdrRemappedExt;
 
415
        fn3 << outputPrefix << "_hdr_" << std::setfill('0') << std::setw(4) << *it << hdrgrayRemappedExt;
 
416
        remappedImages.push_back(fn1.str());
 
417
        remappedHDRImages.push_back(fn2.str());
 
418
        remappedHDRgrayImages.push_back(fn3.str());
 
419
    }
 
420
    mgr.own_add(new Comment("remapped images"));
 
421
    newVarDef(vldrlayers, "LDR_LAYERS", remappedImages.begin(), remappedImages.end(), Makefile::MAKE, "\\\n");
 
422
    newVarDef(vldrlayersshell, "LDR_LAYERS_SHELL", remappedImages.begin(), remappedImages.end(), Makefile::SHELL, "\\\n");
 
423
 
 
424
    mgr.own_add(new Comment("remapped images (hdr)"));
 
425
    newVarDef(vhdrlayers, "HDR_LAYERS", remappedHDRImages.begin(), remappedHDRImages.end(), Makefile::MAKE, "\\\n");
 
426
    newVarDef(vhdrlayersshell, "HDR_LAYERS_SHELL", remappedHDRImages.begin(), remappedHDRImages.end(), Makefile::SHELL, "\\\n");
 
427
 
 
428
    mgr.own_add(new Comment("remapped maxval images"));
 
429
    newVarDef(vhdrgraylayers, "HDR_LAYERS_WEIGHTS", remappedHDRgrayImages.begin(), remappedHDRgrayImages.end(), Makefile::MAKE, "\\\n");
 
430
    newVarDef(vhdrgraylayersshell, "HDR_LAYERS_WEIGHTS_SHELL", remappedHDRgrayImages.begin(), remappedHDRgrayImages.end(), Makefile::SHELL, "\\\n");
 
431
 
 
432
    //----------
 
433
    // hdr, exposure, ldr stacks
 
434
    std::vector<mf::Variable*> hdr_stacks, hdr_stacks_shell, hdr_stacks_input, hdr_stacks_input_shell;
 
435
    mgr.own_add(new Comment("stacked hdr images"));
 
436
    std::vector<UIntSet> stacks = getHDRStacks(pano, images);
 
437
    mf::Variable* vhdrstacks,* vhdrstacksshell;
 
438
    std::vector<std::string> stackedhdrImgs;
 
439
    createstacks(stacks, "HDR_STACK", "_stack_hdr_", "_hdr_", hdrRemappedExt,
 
440
            hdr_stacks, hdr_stacks_shell, hdr_stacks_input, hdr_stacks_input_shell, vhdrstacks, vhdrstacksshell, stackedhdrImgs);
 
441
 
 
442
    std::vector<mf::Variable*> ldrexp_stacks, ldrexp_stacks_shell, ldrexp_stacks_input, ldrexp_stacks_input_shell, ldrexp_stacks_pt_input, ldrexp_stacks_input_pt_shell;
 
443
    mgr.own_add(new Comment("number of image sets with similar exposure"));
 
444
    mf::Variable* vldrexposurelayers,* vldrexposurelayersshell,* vldrexposurelayersremapped,* vldrexposurelayersremappedshell;
 
445
    std::vector<UIntSet> exposures = getExposureLayers(pano, images);
 
446
    std::vector<std::string> exposureimgs;
 
447
    createexposure(exposures, "LDR_EXPOSURE_LAYER", "_exposure_", "_exposure_layers_", ldrRemappedExt,
 
448
                ldrexp_stacks, ldrexp_stacks_shell, ldrexp_stacks_input, ldrexp_stacks_input_shell, ldrexp_stacks_pt_input, ldrexp_stacks_input_pt_shell,
 
449
                vldrexposurelayers, vldrexposurelayersshell, vldrexposurelayersremapped, vldrexposurelayersremappedshell,
 
450
                exposureimgs);
 
451
 
 
452
    std::vector<mf::Variable*> ldr_stacks, ldr_stacks_shell, ldr_stacks_input, ldr_stacks_input_shell;
 
453
    mgr.own_add(new Comment("stacked ldr images"));
 
454
    mf::Variable* vldrstacks,* vldrstacksshell;
 
455
    std::vector<std::string> stackedldrimgs;
 
456
    createstacks(stacks, "LDR_STACK", "_stack_ldr_", "_exposure_layers_", ldrRemappedExt,
 
457
            ldr_stacks, ldr_stacks_shell, ldr_stacks_input, ldr_stacks_input_shell, vldrstacks, vldrstacksshell, stackedldrimgs);
 
458
 
 
459
 
 
460
    //----------
 
461
    if(!includePath.empty())
 
462
    {
 
463
        mgr.own_add(new Anything("include " + Makefile::quote(includePath, Makefile::MAKE)));
 
464
        return true;
 
465
    }
 
466
 
 
467
    //----------
 
468
    // Collect prerequisites
 
469
 
 
470
    std::vector<mf::Variable*> allprereqs, cleanprereqs;
 
471
 
 
472
    if(opts.outputLDRBlended)
 
473
    {
 
474
        allprereqs.push_back(vldrblended);
 
475
        append(outputFiles, vldrblended->getValues());
 
476
        newVarDef(vdoldrblend, "DO_LDR_BLENDED", 1);
 
477
        if(!opts.outputLDRLayers)
 
478
        {
 
479
            cleanprereqs.push_back(vldrlayersshell);
 
480
            append(outputFiles, vldrlayers->getValues());
 
481
        }
 
482
    }
 
483
 
 
484
    if(opts.outputLDRLayers)
 
485
    {
 
486
        allprereqs.push_back(vldrlayers);
 
487
        append(outputFiles, vldrlayers->getValues());
 
488
    }
 
489
 
 
490
    if(opts.outputLDRExposureRemapped)
 
491
    {
 
492
        allprereqs.push_back(vldrexposurelayersremapped);
 
493
        append(outputFiles, vldrexposurelayersremapped->getValues());
 
494
    }
 
495
 
 
496
    if(opts.outputLDRExposureLayers)
 
497
    {
 
498
        allprereqs.push_back(vldrexposurelayers);
 
499
        append(outputFiles, exposureimgs);
 
500
        if(!opts.outputLDRExposureRemapped)
 
501
        {
 
502
            cleanprereqs.push_back(vldrexposurelayersremappedshell);
 
503
            append(outputFiles, vldrexposurelayersremapped->getValues());
 
504
        }
 
505
    }
 
506
 
 
507
    if(opts.outputLDRExposureBlended)
 
508
    {
 
509
        allprereqs.push_back(vldrstackedblended);
 
510
        append(outputFiles, vldrstackedblended->getValues());
 
511
        newVarDef(vdoldrstackedblended, "DO_LDR_STACKED_BLENDED", 1);
 
512
        cleanprereqs.push_back(vldrstacksshell);
 
513
        append(outputFiles, stackedldrimgs);
 
514
        if(!opts.outputLDRExposureRemapped && !opts.outputLDRExposureLayers)
 
515
        {
 
516
            cleanprereqs.push_back(vldrexposurelayersremappedshell);
 
517
            append(outputFiles, vldrexposurelayersremapped->getValues());
 
518
        }
 
519
    }
 
520
 
 
521
    if(opts.outputLDRExposureLayersFused)
 
522
    {
 
523
        allprereqs.push_back(vldrexposurelayersfused);
 
524
        append(outputFiles, vldrexposurelayersfused->getValues());
 
525
        newVarDef(vdoldrexposurelayersfused, "DO_LDR_EXPOSURE_LAYERS_FUSED", 1);
 
526
        append(outputFiles, exposureimgs);
 
527
        if(!opts.outputLDRExposureRemapped && !opts.outputLDRExposureLayers)
 
528
        {
 
529
            cleanprereqs.push_back(vldrexposurelayersremappedshell);
 
530
            append(outputFiles, vldrexposurelayersremapped->getValues());
 
531
            cleanprereqs.push_back(vldrexposurelayersshell);
 
532
        }
 
533
    }
 
534
 
 
535
    if(opts.outputHDRLayers)
 
536
    {
 
537
        allprereqs.push_back(vhdrlayers);
 
538
        append(outputFiles, vhdrlayers->getValues());
 
539
        append(outputFiles, vhdrgraylayers->getValues());
 
540
    }
 
541
 
 
542
    if(opts.outputHDRStacks)
 
543
    {
 
544
        allprereqs.push_back(vhdrstacks);
 
545
        append(outputFiles, stackedhdrImgs);
 
546
        if(!opts.outputHDRLayers)
 
547
        {
 
548
            cleanprereqs.push_back(vhdrlayersshell);
 
549
            cleanprereqs.push_back(vhdrgraylayersshell);
 
550
            append(outputFiles, vhdrlayers->getValues());
 
551
            append(outputFiles, vhdrgraylayers->getValues());
 
552
        }
 
553
    }
 
554
 
 
555
    if(opts.outputHDRBlended)
 
556
    {
 
557
        allprereqs.push_back(vhdrblended);
 
558
        append(outputFiles, vhdrblended->getValues());
 
559
        newVarDef(vdohdrblended, "DO_HDR_BLENDED", 1);
 
560
        if(!opts.outputHDRStacks)
 
561
        {
 
562
            cleanprereqs.push_back(vhdrstacksshell);
 
563
            append(outputFiles, stackedhdrImgs);
 
564
            if(!opts.outputHDRLayers)
 
565
            {
 
566
                cleanprereqs.push_back(vhdrlayersshell);
 
567
                cleanprereqs.push_back(vhdrgraylayersshell);
 
568
                append(outputFiles, vhdrlayers->getValues());
 
569
                append(outputFiles, vhdrgraylayers->getValues());
 
570
            }
 
571
        }
 
572
    }
 
573
 
 
574
    //----------
 
575
    // Assemble all and clean rules
 
576
 
 
577
    Rule* start = mgr.own(new Rule());
 
578
    start->addTarget("startStitching");
 
579
    echoInfo(*start,"===========================================================================");
 
580
    echoInfo(*start,"Stitching panorama");
 
581
    echoInfo(*start,"===========================================================================");
 
582
 
 
583
    Rule* all = mgr.own(new Rule());
 
584
    all->addTarget("all");
 
585
    all->addPrereq(start);
 
586
    for(std::vector<mf::Variable*>::const_iterator it = allprereqs.begin(); it != allprereqs.end(); it++)
 
587
    {
 
588
        all->addPrereq((*it));
 
589
    }
 
590
    all->add();
 
591
 
 
592
    start->add();       // add all as the first target, so it is the default.
 
593
 
 
594
    Rule* clean = mgr.own(new Rule());
 
595
    clean->addTarget("clean");
 
596
    echoInfo(*clean,"===========================================================================");
 
597
    echoInfo(*clean,"Remove temporary files");
 
598
    echoInfo(*clean,"===========================================================================");
 
599
    std::string vdefs;
 
600
    for(std::vector<mf::Variable*>::const_iterator it = cleanprereqs.begin(); it != cleanprereqs.end(); it++)
 
601
    {
 
602
        vdefs += (*it)->getRef() + " ";
 
603
    }
 
604
    if(vdefs.length()>0)
 
605
    {
 
606
        clean->addCommand(vrm->getRef() + " " + vdefs,true,true);
 
607
    };
 
608
    clean->add();
 
609
 
 
610
    //----------
 
611
    // Test rules check if programs exist.
 
612
    Rule* test = mgr.own(new Rule());
 
613
    test->addTarget("test");
 
614
    echoInfo(*test,"===========================================================================");
 
615
    echoInfo(*test,"Testing programs");
 
616
    echoInfo(*test,"===========================================================================");
 
617
    // test remapper
 
618
    switch(opts.remapper) {
 
619
        case PanoramaOptions::NONA:
 
620
            createcheckProgCmd(*test,"nona",vnona->getRef()+" --help");
 
621
            break;
 
622
        case PanoramaOptions::PTMENDER:
 
623
            break;
 
624
    }
 
625
    // test blender
 
626
    switch(opts.blendMode) {
 
627
        case PanoramaOptions::ENBLEND_BLEND:
 
628
            createcheckProgCmd(*test,"enblend",venblend->getRef()+" -h");
 
629
            break;
 
630
        case PanoramaOptions::PTBLENDER_BLEND:
 
631
            createcheckProgCmd(*test,"PTblender",vPTblender->getRef()+" -h");
 
632
            break;
 
633
        case PanoramaOptions::SMARTBLEND_BLEND:
 
634
            createcheckProgCmd(*test,"smartblend",vsmartblend->getRef());
 
635
            break;
 
636
    }
 
637
    // test enfuse
 
638
    createcheckProgCmd(*test,"enfuse",venfuse->getRef()+" -h");
 
639
    // test hugin_hdrmerge
 
640
    createcheckProgCmd(*test,"hugin_hdrmerge",vhdrmerge->getRef()+" -h");
 
641
    // test exiftool
 
642
    createcheckProgCmd(*test,"exiftool",vexiftool->getRef()+" -ver");
 
643
    test->add();
 
644
 
 
645
    //----------
 
646
    // Info rule to get some infomation about project
 
647
    Rule* info = mgr.own(new Rule());
 
648
    info->addTarget("info");
 
649
    echoInfo(*info,"===========================================================================");
 
650
    echoInfo(*info,"***************  Panorama makefile generated by Hugin       ***************");
 
651
    echoInfo(*info,"===========================================================================");
 
652
    echoInfo(*info,"System information");
 
653
    echoInfo(*info,"===========================================================================");
 
654
    std::ostringstream infostream;
 
655
    infostream.imbue(makefile::GetMakefileLocale());
 
656
    infostream << fixed;
 
657
    printSystemInfo(*info);
 
658
    infostream.str("");
 
659
    infostream << DISPLAY_VERSION;
 
660
    echoInfo(*info,"===========================================================================");
 
661
    echoInfo(*info,"Output options");
 
662
    echoInfo(*info,"===========================================================================");
 
663
    echoInfo(*info,"Hugin Version: "+infostream.str());
 
664
    echoInfo(*info,"Project file: "+ptofile);
 
665
    echoInfo(*info,"Output prefix: "+outputPrefix);
 
666
    pano_projection_features proj;
 
667
        if (panoProjectionFeaturesQuery(opts.getProjection(), &proj)) 
 
668
    {
 
669
        infostream.str("");
 
670
        infostream << proj.name << " (" << opts.getProjection() << ")";
 
671
        echoInfo(*info,"Projection: "+infostream.str());
 
672
    }
 
673
    std::vector<double> parameters=opts.getProjectionParameters();
 
674
    if(parameters.size()>0)
 
675
    {
 
676
        infostream.str("");
 
677
        unsigned int i=0;
 
678
        infostream << setprecision(2) << parameters[i];
 
679
        i++;
 
680
        while(i<parameters.size())
 
681
        {
 
682
            infostream << ", " << parameters[i];
 
683
            i++;
 
684
        };
 
685
        echoInfo(*info,"Projection parameters: "+infostream.str());
 
686
    };
 
687
    infostream.str("");
 
688
    infostream << setprecision(0) << opts.getHFOV() << " x " << setprecision(0) << opts.getVFOV();
 
689
    echoInfo(*info,"Field of view: "+infostream.str());
 
690
    infostream.str("");
 
691
    infostream << opts.getWidth() << " x " << opts.getHeight();
 
692
    echoInfo(*info,"Canvas dimensions: "+infostream.str());
 
693
    infostream.str("");
 
694
    infostream << "(" << opts.getROI().left() << "," << opts.getROI().top() << ") - (" << opts.getROI().right() << "," << opts.getROI().bottom() << ")";
 
695
    echoInfo(*info,"Crop area: "+infostream.str());
 
696
    infostream.str("");
 
697
    infostream << setprecision(2) << opts.outputExposureValue;
 
698
    echoInfo(*info,"Output exposure value: "+infostream.str());
 
699
    echoInfo(*info,"Selected outputs");
 
700
    if(opts.outputLDRBlended || opts.outputLDRLayers)
 
701
    {
 
702
        echoInfo(*info,"Normal panorama");
 
703
        if(opts.outputLDRBlended)
 
704
            echoInfo(*info,"* Blended panorama");
 
705
        if(opts.outputLDRLayers)
 
706
            echoInfo(*info,"* Remapped images");
 
707
    };
 
708
    if(opts.outputLDRExposureBlended || opts.outputLDRExposureLayersFused || opts.outputLDRExposureLayers || opts.outputLDRExposureRemapped)
 
709
    {
 
710
        echoInfo(*info,"Exposure fusion");
 
711
        if(opts.outputLDRExposureBlended)
 
712
            echoInfo(*info,"* Fused and blended panorama");
 
713
        if(opts.outputLDRExposureLayersFused)
 
714
            echoInfo(*info,"* Blended and fused panorama");
 
715
        if(opts.outputLDRExposureLayers)
 
716
            echoInfo(*info,"* Blended exposure layers");
 
717
        if(opts.outputLDRExposureRemapped)
 
718
            echoInfo(*info,"* Remapped images");
 
719
    };
 
720
    if(opts.outputHDRBlended || opts.outputHDRLayers || opts.outputHDRStacks)
 
721
    {
 
722
        echoInfo(*info,"HDR merging");
 
723
        if(opts.outputHDRBlended)
 
724
            echoInfo(*info,"* Merged and blended panorama");
 
725
        if(opts.outputHDRStacks)
 
726
            echoInfo(*info,"* Remapped merged stacks");
 
727
        if(opts.outputHDRLayers)
 
728
            echoInfo(*info,"* Remapped images");
 
729
    };
 
730
    if(opts.remapUsingGPU)
 
731
        echoInfo(*info,"Using GPU for remapping");
 
732
 
 
733
    echoInfo(*info,"===========================================================================");
 
734
    echoInfo(*info,"Input images");
 
735
    echoInfo(*info,"===========================================================================");
 
736
    infostream.str("");
 
737
    infostream << pano.getNrOfImages();
 
738
    echoInfo(*info,"Number of images in project file: "+infostream.str());
 
739
    infostream.str("");
 
740
    infostream << images.size();
 
741
    echoInfo(*info,"Number of active images: "+infostream.str());
 
742
    for(UIntSet::const_iterator it=images.begin();it!=images.end();it++)
 
743
    {
 
744
        infostream.str("");
 
745
        const HuginBase::SrcPanoImage &img=pano.getImage(*it);
 
746
        infostream << "Image " << *it << ": " << img.getFilename();
 
747
        echoInfo(*info,infostream.str());
 
748
        infostream.str("");
 
749
        infostream << "Image " << *it << ": Size " << img.getSize().width() << "x" << img.getSize().height() << ", Exposure: " << setprecision(2) << img.getExposureValue();
 
750
        echoInfo(*info,infostream.str());
 
751
    };
 
752
    info->add();
 
753
 
 
754
    //----------
 
755
    // Rules for every single file
 
756
    if(opts.remapper == PanoramaOptions::NONA)
 
757
    {
 
758
        mgr.own_add(new Comment("Rules for ordinary TIFF_m and hdr output"));
 
759
        UIntSet::const_iterator it = images.begin();
 
760
        size_t i=0;
 
761
        for(; it != images.end(); it++, i++)
 
762
        {
 
763
            std::string source = Makefile::quote(pano.getImage(*it).getFilename(), Makefile::MAKE);
 
764
            std::ostringstream imgnr;
 
765
            imgnr << *it;
 
766
 
 
767
            // ldr part
 
768
            Rule* ruleldr = mgr.own(new Rule()); ruleldr->add();
 
769
            ruleldr->addTarget(Makefile::quote(remappedImages[i], Makefile::MAKE));
 
770
            ruleldr->addPrereq(source);
 
771
            ruleldr->addPrereq(vprojectfile);
 
772
            ruleldr->addCommand(
 
773
                    vnona->getRef() +" "+ vnonaopts->getRef() +" "+ vnonaldr->getRef()
 
774
                    + " -r ldr -m " + ldrRemappedMode + " -o " + vldrremappedprefixshell->getRef() +
 
775
                    " -i " + imgnr.str() +" "+ vprojectfileshell->getRef());
 
776
 
 
777
            // hdr part
 
778
            Rule* rulehdr = mgr.own(new Rule()); rulehdr->add();
 
779
            rulehdr->addTarget(Makefile::quote(remappedHDRImages[i], Makefile::MAKE));
 
780
            rulehdr->addPrereq(source);
 
781
            rulehdr->addPrereq(vprojectfile);
 
782
            rulehdr->addCommand(
 
783
                    vnona->getRef() +" "+ vnonaopts->getRef() +" -r hdr -m " + hdrRemappedMode + " -o " +
 
784
                    vhdrstackremappedprefixshell->getRef() + " -i " + imgnr.str() +" "+ vprojectfileshell->getRef());
 
785
        }
 
786
 
 
787
        mgr.own_add(new Comment("Rules for exposure layer output"));
 
788
 
 
789
        size_t j=0;
 
790
        for(i=0; i < exposures.size(); i++)
 
791
        {
 
792
            for(UIntSet::const_iterator it = exposures[i].begin(); it != exposures[i].end(); it++, j++)
 
793
            {
 
794
                std::ostringstream expvalue, imgnr;
 
795
                imgnr << *it;
 
796
                expvalue.imbue(makefile::GetMakefileLocale());
 
797
                expvalue <<  pano.getSrcImage(*it).getExposureValue();
 
798
                Rule* rule = mgr.own(new Rule()); rule->add();
 
799
                rule->addTarget(Makefile::quote(vldrexposurelayersremapped->getValues()[j], Makefile::MAKE));
 
800
                rule->addPrereq(Makefile::quote(pano.getImage(*it).getFilename(), Makefile::MAKE));
 
801
                rule->addPrereq(vprojectfile);
 
802
                rule->addCommand(
 
803
                        vnona->getRef() +" "+ vnonaopts->getRef() +" "+ vnonaldr->getRef()
 
804
                        + " -r ldr -e " + expvalue.str() + " -m " + ldrRemappedMode + " -o " + vldrexposureremappedprefixshell->getRef() +
 
805
                        " -i " + imgnr.str() +" "+ vprojectfileshell->getRef());
 
806
 
 
807
            }
 
808
        }
 
809
    }
 
810
 
 
811
    if(opts.remapper == PanoramaOptions::PTMENDER)
 
812
    {
 
813
        Rule* rule = mgr.own(new Rule()); rule->add();
 
814
        rule->addTarget(vldrlayers);
 
815
        rule->addPrereq(vinimages);
 
816
        rule->addPrereq(vprojectfile);
 
817
        rule->addCommand(vPTmender->getRef() + " -o " + vldrremappedprefixshell->getRef() +" "+
 
818
                vprojectfileshell->getRef());
 
819
    }
 
820
 
 
821
    //----------
 
822
    // Rules for LDR and HDR stack merging, a rule for each stack
 
823
    mgr.own_add(new Comment("Rules for LDR and HDR stack merging, a rule for each stack"));
 
824
    for(size_t i=0; i< stacks.size(); i++)
 
825
    {
 
826
        std::ostringstream imgnr;
 
827
        imgnr << i;
 
828
 
 
829
        Rule* ruleldr = mgr.own(new Rule()); ruleldr->add();
 
830
        ruleldr->addTarget(ldr_stacks[i]);
 
831
        ruleldr->addPrereq(ldr_stacks_input[i]);
 
832
        ruleldr->addCommand(venfuse->getRef() +" "+ venfuseopts->getRef() + " -o " +
 
833
                ldr_stacks_shell[i]->getRef() +" "+ ldr_stacks_input_shell[i]->getRef());
 
834
        ruleldr->addCommand("-" + vexiftool->getRef() + " -overwrite_original_in_place -TagsFromFile " +
 
835
                vinimage1shell->getRef() +" "+ vexiftoolcopyargs->getRef() +" "+ ldr_stacks_shell[i]->getRef());
 
836
 
 
837
        Rule* rulehdr = mgr.own(new Rule()); rulehdr->add();
 
838
        rulehdr->addTarget(hdr_stacks[i]);
 
839
        rulehdr->addPrereq(hdr_stacks_input[i]);
 
840
        rulehdr->addCommand(vhdrmerge->getRef() +" "+ vhdrmergeopts->getRef() + " -o " +
 
841
                hdr_stacks_shell[i]->getRef() +" "+ hdr_stacks_input_shell[i]->getRef());
 
842
    }
 
843
    //----------
 
844
    // Blend modes
 
845
    // these commands are often occuring
 
846
    const std::string enblendcmd = venblend->getRef() +" "+ venblendldrcomp->getRef() +" "+
 
847
            venblendopts->getRef() + " -o ";
 
848
    const std::string exifcmd = "-" + vexiftool->getRef() + " -overwrite_original_in_place -TagsFromFile " +
 
849
            vinimage1shell->getRef() +" "+ vexiftoolcopyargs->getRef() +' ';
 
850
    const std::string ptrollercmd = vPTroller->getRef() + " -o ";
 
851
 
 
852
    if(opts.blendMode == PanoramaOptions::ENBLEND_BLEND)
 
853
    {
 
854
        Rule* rule = mgr.own(new Rule()); rule->add();
 
855
 
 
856
        // write rules for blending with enblend
 
857
        rule->addTarget(vldrblended);
 
858
        rule->addPrereq(vldrlayers);
 
859
        rule->addCommand(enblendcmd + vldrblendedshell->getRef() +" "+ vldrlayersshell->getRef());
 
860
        rule->addCommand(exifcmd + vldrblendedshell->getRef());
 
861
 
 
862
        // for LDR exposure blend planes
 
863
        for(unsigned i=0; i < exposures.size(); i++)
 
864
        {
 
865
            rule = mgr.own(new Rule()); rule->add();
 
866
            rule->addTarget(ldrexp_stacks[i]);
 
867
            rule->addPrereq(ldrexp_stacks_input[i]);
 
868
            rule->addCommand(enblendcmd + ldrexp_stacks_shell[i]->getRef() +" "+ ldrexp_stacks_input_shell[i]->getRef());
 
869
            rule->addCommand(exifcmd + ldrexp_stacks_shell[i]->getRef());
 
870
        }
 
871
 
 
872
        // rules for enfuse blending
 
873
        rule = mgr.own(new Rule()); rule->add();
 
874
        rule->addTarget(vldrstackedblended);
 
875
        rule->addPrereq(vldrstacks);
 
876
        rule->addCommand(enblendcmd + vldrstackedblendedshell->getRef() +" "+ vldrstacksshell->getRef());
 
877
        rule->addCommand(exifcmd + vldrstackedblendedshell->getRef());
 
878
 
 
879
        // rules for fusing blended layers
 
880
        rule = mgr.own(new Rule()); rule->add();
 
881
        rule->addTarget(vldrexposurelayersfused);
 
882
        rule->addPrereq(vldrexposurelayers);
 
883
        rule->addCommand(venfuse->getRef() +" "+ venblendldrcomp->getRef() +" "+ venfuseopts->getRef() + " -o " +
 
884
                vldrexposurelayersfusedshell->getRef() +" "+ vldrexposurelayersshell->getRef());
 
885
        rule->addCommand(exifcmd + vldrexposurelayersfusedshell->getRef());
 
886
 
 
887
        // rules for hdr blending
 
888
        rule = mgr.own(new Rule()); rule->add();
 
889
        rule->addTarget(vhdrblended);
 
890
        rule->addPrereq(vhdrstacks);
 
891
        rule->addCommand(venblend->getRef() +" "+ venblendhdrcomp->getRef() +" "+ venblendopts->getRef() + " -o " +
 
892
                vhdrblendedshell->getRef() +" "+ vhdrstacksshell->getRef());
 
893
 
 
894
        // rules for multilayer output
 
895
        rule = mgr.own(new Rule()); rule->add();
 
896
        rule->addTarget(vldrremappedprefix->getRef() + "_multilayer.tif");
 
897
        rule->addPrereq(vldrlayers);
 
898
        rule->addCommand("tiffcp " + vldrlayersshell->getRef() +" "+ vldrremappedprefixshell->getRef() + "_multilayer.tif");
 
899
 
 
900
        rule = mgr.own(new Rule()); rule->add();
 
901
        rule->addTarget(vldrremappedprefix->getRef() + "_fused_multilayer.tif");
 
902
        rule->addPrereq(vldrstacks);
 
903
        rule->addPrereq(vldrexposurelayers);
 
904
        rule->addCommand("tiffcp " + vldrstacksshell->getRef() +" "+ vldrexposurelayersshell->getRef() +" "+ vldrremappedprefixshell->getRef() + "_fused_multilayer.tif");
 
905
 
 
906
        rule = mgr.own(new Rule()); rule->add();
 
907
        rule->addTarget(vldrremappedprefix->getRef() + "_multilayer.psd");
 
908
        rule->addPrereq(vldrlayers);
 
909
        rule->addCommand("PTtiff2psd -o " + vldrremappedprefixshell->getRef() + "_multilayer.psd " + vldrlayersshell->getRef());
 
910
 
 
911
        rule = mgr.own(new Rule()); rule->add();
 
912
        rule->addTarget(vldrremappedprefix->getRef() + "_fused_multilayer.psd");
 
913
        rule->addPrereq(vldrstacks);
 
914
        rule->addPrereq(vldrexposurelayers);
 
915
        rule->addCommand("PTtiff2psd -o " + vldrremappedprefixshell->getRef() + "_fused_multilayer.psd " + vldrstacksshell->getRef() +
 
916
                vldrexposurelayersshell->getRef());
 
917
    }
 
918
 
 
919
 
 
920
    if(opts.blendMode == PanoramaOptions::NO_BLEND)
 
921
    {
 
922
        Rule* rule = mgr.own(new Rule()); rule->add();
 
923
 
 
924
        // write rules for blending with enblend
 
925
        rule->addTarget(vldrblended);
 
926
        rule->addPrereq(vldrlayers);
 
927
        rule->addCommand("-" + vrm->getRef() +" "+ vldrblendedshell->getRef());
 
928
        rule->addCommand(ptrollercmd + vldrblendedshell->getRef() +" "+ vldrlayersshell->getRef());
 
929
        rule->addCommand(exifcmd + vldrblendedshell->getRef());
 
930
 
 
931
        // for LDR exposure blend planes
 
932
        for(unsigned i=0; i < exposures.size(); i++)
 
933
        {
 
934
            rule = mgr.own(new Rule()); rule->add();
 
935
            rule->addTarget(ldrexp_stacks[i]);
 
936
            rule->addPrereq(ldrexp_stacks_input[i]);
 
937
            rule->addCommand("-" + vrm->getRef() +" "+ ldrexp_stacks_shell[i]->getRef());
 
938
            rule->addCommand(ptrollercmd + ldrexp_stacks_shell[i]->getRef());
 
939
            rule->addCommand(exifcmd + ldrexp_stacks_shell[i]->getRef());
 
940
        }
 
941
 
 
942
        rule = mgr.own(new Rule()); rule->add();
 
943
        rule->addTarget(vldrstackedblended);
 
944
        rule->addPrereq(vldrstacks);
 
945
        rule->addCommand("-" + vrm->getRef() +" "+ vldrstackedblendedshell->getRef());
 
946
        rule->addCommand(ptrollercmd + vldrstackedblendedshell->getRef() +" "+ vldrstacksshell->getRef());
 
947
        rule->addCommand(exifcmd + vldrstackedblendedshell->getRef());
 
948
 
 
949
        // rules for non-blended HDR panoramas
 
950
        rule = mgr.own(new Rule()); rule->add();
 
951
        rule->addTarget(vhdrblended);
 
952
        rule->addPrereq(vhdrlayers);
 
953
        rule->addCommand(vhdrmerge->getRef() +" "+ vhdrmergeopts->getRef() + " -o " +
 
954
                vhdrblendedshell->getRef() +" "+ vhdrlayersshell->getRef());
 
955
    }
 
956
    return true;
 
957
}
 
958
 
 
959
 
 
960
void PanoramaMakefilelibExport::createstacks(const std::vector<UIntSet> stackdata,
 
961
        const std::string stkname,
 
962
        const std::string filenamecenter, const std::string inputfilenamecenter, const std::string filenameext,
 
963
        std::vector<mf::Variable*>& stacks,
 
964
        std::vector<mf::Variable*>& stacks_shell,
 
965
        std::vector<mf::Variable*>& stacks_input,
 
966
        std::vector<makefile::Variable*>& stacks_input_shell,
 
967
        mf::Variable*& vstacks,
 
968
        mf::Variable*& vstacksshell,
 
969
        std::vector<std::string>& allfiles)
 
970
{
 
971
    std::ostringstream stknrs;
 
972
    for (unsigned i=0; i < stackdata.size(); i++)
 
973
    {
 
974
        stknrs << i << " ";
 
975
        std::ostringstream filename, stackname;
 
976
        filename << outputPrefix << filenamecenter << std::setfill('0') << std::setw(4) << i << filenameext;
 
977
        stackname << stkname << "_" << i;
 
978
        allfiles.push_back(filename.str());
 
979
 
 
980
        std::vector<std::string> inputs;
 
981
        for (UIntSet::const_iterator it = stackdata[i].begin(); it != stackdata[i].end(); it++)
 
982
        {
 
983
            std::ostringstream fns;
 
984
            fns << outputPrefix << inputfilenamecenter << std::setfill('0') << std::setw(4) << *it << filenameext;
 
985
            inputs.push_back(fns.str());
 
986
        }
 
987
        mf::Variable* v;
 
988
        v = mgr.own(new mf::Variable(stackname.str(), filename.str(), Makefile::MAKE));
 
989
        stacks.push_back(v);
 
990
        v->getDef().add();
 
991
 
 
992
        v = mgr.own(new mf::Variable(stackname.str() + "_SHELL", filename.str(), Makefile::SHELL));
 
993
        stacks_shell.push_back(v);
 
994
        v->getDef().add();
 
995
 
 
996
        v= mgr.own(new mf::Variable(stackname.str() + "_INPUT", inputs.begin(), inputs.end(), Makefile::MAKE, "\\\n"));
 
997
        stacks_input.push_back(v);
 
998
        v->getDef().add();
 
999
 
 
1000
        v = mgr.own(new mf::Variable(stackname.str() + "_INPUT_SHELL", inputs.begin(), inputs.end(), Makefile::SHELL, "\\\n"));
 
1001
        stacks_input_shell.push_back(v);
 
1002
        v->getDef().add();
 
1003
    }
 
1004
    newVarDef(vhdrstacksnr, stkname + "S_NUMBERS", stknrs.str(), Makefile::NONE);
 
1005
 
 
1006
    std::string stackrefs;
 
1007
    std::string stackrefsshell;
 
1008
    std::vector<mf::Variable*>::const_iterator it, it2;
 
1009
    it = stacks.begin();
 
1010
    it2 = stacks_shell.begin();
 
1011
    for(; it != stacks.end() && it2 != stacks_shell.end(); it++, it2++)
 
1012
    {
 
1013
        stackrefs += (*it)->getRef() + " ";
 
1014
        stackrefsshell += (*it2)->getRef() + " ";
 
1015
    }
 
1016
    vstacks = mgr.own(new mf::Variable(stkname + "S", stackrefs, Makefile::NONE));
 
1017
    vstacks->getDef().add();
 
1018
    vstacksshell = mgr.own(new mf::Variable(stkname + "S_SHELL", stackrefsshell, Makefile::NONE));
 
1019
    vstacksshell->getDef().add();
 
1020
 
 
1021
}
 
1022
void PanoramaMakefilelibExport::createexposure(const std::vector<UIntSet> stackdata,
 
1023
        const std::string stkname,
 
1024
        const std::string filenamecenter, const std::string inputfilenamecenter, const std::string filenameext,
 
1025
        std::vector<mf::Variable*>& stacks,
 
1026
        std::vector<mf::Variable*>& stacks_shell,
 
1027
        std::vector<mf::Variable*>& stacks_input,
 
1028
        std::vector<mf::Variable*>& stacks_input_shell,
 
1029
        std::vector<mf::Variable*>& stacks_input_pt,
 
1030
        std::vector<mf::Variable*>& stacks_input_pt_shell,
 
1031
        mf::Variable*& vstacks,
 
1032
        mf::Variable*& vstacksshell,
 
1033
        mf::Variable*& vstacksrem,
 
1034
        mf::Variable*& vstacksremshell,
 
1035
        std::vector<std::string>& alllayers)
 
1036
{
 
1037
    std::vector<std::string> allimgs;
 
1038
    std::ostringstream stknrs;
 
1039
    for (unsigned i=0; i < stackdata.size(); i++)
 
1040
    {
 
1041
        stknrs << i << " ";
 
1042
        std::ostringstream filename, stackname;
 
1043
        filename << outputPrefix << filenamecenter << std::setfill('0') << std::setw(4) << i << filenameext;
 
1044
        stackname << stkname << "_" << i;
 
1045
        alllayers.push_back(filename.str());
 
1046
 
 
1047
        std::vector<std::string> inputs, inputspt;
 
1048
        double exposure = 0;
 
1049
        for (UIntSet::const_iterator it = stackdata[i].begin(); it != stackdata[i].end(); it++)
 
1050
        {
 
1051
            std::ostringstream fns, fnpt;
 
1052
            fns << outputPrefix << inputfilenamecenter << std::setfill('0') << std::setw(4) << *it << filenameext;
 
1053
            fnpt << outputPrefix << std::setfill('0') << std::setw(4) << *it << filenameext;
 
1054
            inputs.push_back(fns.str());
 
1055
            inputspt.push_back(fnpt.str());
 
1056
 
 
1057
            exposure += pano.getSrcImage(*it).getExposureValue();
 
1058
            allimgs.push_back(fns.str());
 
1059
        }
 
1060
        mf::Variable* v;
 
1061
        v = mgr.own(new mf::Variable(stackname.str(), filename.str(), Makefile::MAKE));
 
1062
        stacks.push_back(v);
 
1063
        v->getDef().add();
 
1064
 
 
1065
        v = mgr.own(new mf::Variable(stackname.str() + "_SHELL", filename.str(), Makefile::SHELL));
 
1066
        stacks_shell.push_back(v);
 
1067
        v->getDef().add();
 
1068
 
 
1069
        v= mgr.own(new mf::Variable(stackname.str() + "_INPUT", inputs.begin(), inputs.end(), Makefile::MAKE, "\\\n"));
 
1070
        stacks_input.push_back(v);
 
1071
        v->getDef().add();
 
1072
 
 
1073
        v = mgr.own(new mf::Variable(stackname.str() + "_INPUT_SHELL", inputs.begin(), inputs.end(), Makefile::SHELL, "\\\n"));
 
1074
        stacks_input_shell.push_back(v);
 
1075
        v->getDef().add();
 
1076
 
 
1077
        v= mgr.own(new mf::Variable(stackname.str() + "_INPUT_PTMENDER", inputspt.begin(), inputspt.end(), Makefile::MAKE, "\\\n"));
 
1078
        stacks_input_pt.push_back(v);
 
1079
        v->getDef().add();
 
1080
 
 
1081
        v = mgr.own(new mf::Variable(stackname.str() + "_INPUT_PTMENDER_SHELL", inputspt.begin(), inputspt.end(), Makefile::SHELL, "\\\n"));
 
1082
        stacks_input_pt_shell.push_back(v);
 
1083
        v->getDef().add();
 
1084
 
 
1085
        v = mgr.own(new mf::Variable(stackname.str() + "_EXPOSURE", exposure / stackdata[i].size()));
 
1086
        v->getDef().add();
 
1087
    }
 
1088
    newVarDef(vhdrstacksnr, stkname + "S_NUMBERS", stknrs.str(), Makefile::NONE);
 
1089
 
 
1090
    std::string stackrefs;
 
1091
    std::string stackrefsshell;
 
1092
    std::vector<mf::Variable*>::const_iterator it, it2;
 
1093
    it = stacks.begin();
 
1094
    it2 = stacks_shell.begin();
 
1095
    for(; it != stacks.end() && it2 != stacks_shell.end(); it++, it2++)
 
1096
    {
 
1097
        stackrefs += (*it)->getRef() + " ";
 
1098
        stackrefsshell += (*it2)->getRef() + " ";
 
1099
    }
 
1100
    vstacks = mgr.own(new mf::Variable(stkname + "S", stackrefs, Makefile::NONE));
 
1101
    vstacks->getDef().add();
 
1102
    vstacksshell = mgr.own(new mf::Variable(stkname + "S_SHELL", stackrefsshell, Makefile::NONE));
 
1103
    vstacksshell->getDef().add();
 
1104
    vstacksrem = mgr.own( new mf::Variable(stkname + "S_REMAPPED", allimgs.begin(), allimgs.end(), Makefile::MAKE, "\\\n"));
 
1105
    vstacksrem->getDef().add();
 
1106
    vstacksremshell = mgr.own( new mf::Variable(stkname + "S_REMAPPED_SHELL", allimgs.begin(), allimgs.end(), Makefile::SHELL, "\\\n"));
 
1107
    vstacksremshell->getDef().add();
 
1108
}
 
1109
 
 
1110
void PanoramaMakefilelibExport::createcheckProgCmd(Rule& testrule, const std::string& progName, const std::string& progCommand)
 
1111
{
 
1112
    std::string command;
 
1113
#ifdef _WINDOWS
 
1114
    testrule.addCommand("echo Checking " + progName + "...", false);
 
1115
    testrule.addCommand(progCommand + " > NUL 2>&1 && echo " + progName + " is ok || echo " +
 
1116
            progName + " failed", false, true);
 
1117
#else
 
1118
    testrule.addCommand("echo -n 'Checking " + progName + "...'", false);
 
1119
    testrule.addCommand(progCommand + " > /dev/null 2>&1 && echo '[OK]' || echo '[FAILED]'", false, true);
 
1120
#endif
 
1121
}
 
1122
 
 
1123
void PanoramaMakefilelibExport::echoInfo(Rule& inforule, const std::string& info)
 
1124
{
 
1125
#ifdef _WINDOWS
 
1126
    inforule.addCommand("echo " + info, false);
 
1127
#else
 
1128
    inforule.addCommand("echo '" + info + "'", false);
 
1129
#endif
 
1130
}
 
1131
 
 
1132
void PanoramaMakefilelibExport::printSystemInfo(Rule& inforule)
 
1133
{
 
1134
    std::ostringstream infostream("");
 
1135
    infostream.imbue(makefile::GetMakefileLocale());
 
1136
#ifdef _WINDOWS
 
1137
    OSVERSIONINFOEX osvi;
 
1138
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
 
1139
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
 
1140
    if(!GetVersionEx((OSVERSIONINFO *) &osvi))
 
1141
        return;
 
1142
    SYSTEM_INFO siSysInfo;
 
1143
    GetSystemInfo(&siSysInfo);
 
1144
    MEMORYSTATUSEX statex;
 
1145
    statex.dwLength = sizeof(statex);
 
1146
    GlobalMemoryStatusEx(&statex);
 
1147
 
 
1148
    infostream << "Windows ";
 
1149
 
 
1150
    if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion > 4)
 
1151
    {
 
1152
        if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
 
1153
            infostream << "2000 ";
 
1154
        if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1)
 
1155
            infostream << "XP ";
 
1156
        if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2 && osvi.wProductType==VER_NT_WORKSTATION && siSysInfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
 
1157
            infostream << "XP Professional x64 Edition ";
 
1158
        if(osvi.dwMajorVersion==6)
 
1159
        {
 
1160
            if(osvi.dwMinorVersion==0)
 
1161
            {
 
1162
                if(osvi.wProductType==VER_NT_WORKSTATION)
 
1163
                    infostream << "Vista ";
 
1164
                else
 
1165
                    infostream << "Server 2008 ";
 
1166
            }
 
1167
            if(osvi.dwMinorVersion==1)
 
1168
            {
 
1169
                if(osvi.wProductType==VER_NT_WORKSTATION)
 
1170
                    infostream << "7 ";
 
1171
                else
 
1172
                    infostream << "Server 2008 R2 ";
 
1173
            }
 
1174
        };
 
1175
    }
 
1176
 
 
1177
    infostream << "(" << osvi.dwMajorVersion << "." << osvi.dwMinorVersion << " " << osvi.szCSDVersion << ")";
 
1178
    echoInfo(inforule,"Operating System: "+infostream.str());
 
1179
    switch(siSysInfo.wProcessorArchitecture)
 
1180
    {
 
1181
        case PROCESSOR_ARCHITECTURE_INTEL:
 
1182
            infostream.str("x86");
 
1183
            break;
 
1184
        case PROCESSOR_ARCHITECTURE_AMD64:
 
1185
            infostream.str("AMD64");
 
1186
            break;
 
1187
        default:
 
1188
            infostream.str("unknown");
 
1189
            break;
 
1190
    };
 
1191
    echoInfo(inforule,"Architecture: "+infostream.str());
 
1192
    infostream.str("");
 
1193
    infostream << siSysInfo.dwNumberOfProcessors;
 
1194
    echoInfo(inforule,"Number of logical processors: "+infostream.str());
 
1195
    infostream.str("");
 
1196
    infostream << statex.ullTotalPhys/1024 << " kiB (" << setprecision(2) << statex.dwMemoryLoad << "%% occupied)";
 
1197
    echoInfo(inforule,"Physical memory: "+infostream.str()); 
 
1198
    unsigned __int64 freeBytes;
 
1199
    if(GetDiskFreeSpaceEx(NULL,(PULARGE_INTEGER)&freeBytes,NULL,NULL))
 
1200
    {
 
1201
        infostream.str("");
 
1202
        infostream << freeBytes/(1024*1024) << " MiB";
 
1203
        echoInfo(inforule,"Free space on disc: " + infostream.str());
 
1204
    };
 
1205
    infostream.str("");
 
1206
    UINT cp=GetACP();
 
1207
    infostream << cp;
 
1208
    switch(cp)
 
1209
    {
 
1210
    case 1250:
 
1211
        infostream << " (Central European Windows)";
 
1212
        break;
 
1213
    case 1251:
 
1214
        infostream << " (Cyrillic Windows)";
 
1215
        break;
 
1216
    case 1252:
 
1217
        infostream << " (Western European Windows)";
 
1218
        break;
 
1219
    case 1253:
 
1220
        infostream << " (Greek Windows)";
 
1221
        break;
 
1222
    case 1254:
 
1223
        infostream << " (Turkish Windows)";
 
1224
        break;
 
1225
    case 1255:
 
1226
        infostream << " (Hebrew Windows)";
 
1227
        break;
 
1228
    case 1256:
 
1229
        infostream << " (Arabic Windows)";
 
1230
        break;
 
1231
    case 1257:
 
1232
        infostream << " (Baltic Windows)";
 
1233
        break;
 
1234
    case 1258:
 
1235
        infostream << " (Vietnamese Windows)";
 
1236
        break;
 
1237
    };
 
1238
    echoInfo(inforule,"Active codepage: " + infostream.str());
 
1239
#else
 
1240
#ifdef __APPLE__
 
1241
    inforule.addCommand("system_profiler SPSoftwareDataType SPHardwareDataType", false, true);
 
1242
    echoInfo(inforule,"Disc usage");
 
1243
    inforule.addCommand("df -h", false, true);
 
1244
#else
 
1245
    inforule.addCommand("echo -n 'Operating system: '", false);
 
1246
    inforule.addCommand("uname -o", false, true);
 
1247
    inforule.addCommand("echo -n 'Release: '", false);
 
1248
    inforule.addCommand("uname -r", false, true);
 
1249
    inforule.addCommand("echo -n 'Kernel version: '", false);
 
1250
    inforule.addCommand("uname -v", false, true);
 
1251
    inforule.addCommand("echo -n 'Machine: '", false);
 
1252
    inforule.addCommand("uname -m", false, true);
 
1253
    echoInfo(inforule,"Disc usage");
 
1254
    inforule.addCommand("df -h", false, true);
 
1255
    echoInfo(inforule,"Memory usage");
 
1256
    inforule.addCommand("free -m", false, true);
 
1257
#endif
 
1258
#endif
 
1259
};
 
1260
 
 
1261
void printstacks(const std::vector<UIntSet>& stackdata)
 
1262
{
 
1263
    std::cout << "printstacks: \n";
 
1264
    for(std::vector<UIntSet>::const_iterator itv = stackdata.begin(); itv != stackdata.end(); itv++)
 
1265
    {
 
1266
        for(UIntSet::const_iterator itu = itv->begin(); itu != itv->end(); itu++)
 
1267
        {
 
1268
            std::cout << *itu << " ";
 
1269
        }
 
1270
        std::cout << "\n";
 
1271
    }
 
1272
}
 
1273
 
 
1274
template<typename T>
 
1275
void append(std::vector<T>& dst, const std::vector<T>& src)
 
1276
{
 
1277
    dst.insert(dst.end(), src.begin(), src.end());
 
1278
}
 
1279
template<typename T>
 
1280
void append(std::vector<T>& vec, const T& element)
 
1281
{
 
1282
    vec.push_back(element);
 
1283
}
 
1284
}