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

« back to all changes in this revision

Viewing changes to src/hugin_base/algorithms/panorama_makefile/PanoramaMakefileExport.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
 
// -*- c-basic-offset: 4 -*-
2
 
/** @file PanoramaMakefileExport.h
3
 
 *
4
 
 *  @author Pablo d'Angelo <pablo.dangelo@web.de>
5
 
 *
6
 
 *  $Id: utils.h 1814 2006-12-31 14:37:05Z dangelo $
7
 
 *
8
 
 *  This is free software; you can redistribute it and/or
9
 
 *  modify it under the terms of the GNU General Public
10
 
 *  License as published by the Free Software Foundation; either
11
 
 *  version 2 of the License, or (at your option) any later version.
12
 
 *
13
 
 *  This software is distributed in the hope that it will be useful,
14
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 
 *  Lesser General Public License for more details.
17
 
 *
18
 
 *  You should have received a copy of the GNU General Public
19
 
 *  License along with this software; if not, write to the Free Software
20
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 
 *
22
 
 */
23
 
 
24
 
 
25
 
#include "PanoramaMakefileExport.h"
26
 
 
27
 
#include <fstream>
28
 
#include <iomanip>
29
 
#include <panodata/PanoramaData.h>
30
 
#include <hugin_utils/utils.h>
31
 
#include <algorithms/nona/ComputeImageROI.h>
32
 
#include <algorithms/basic/CalculateOverlap.h>
33
 
 
34
 
#if defined MAC_SELF_CONTAINED_BUNDLE
35
 
 #define COULD_EXECUTE_EXIFTOOL_WITH_PERL
36
 
#endif
37
 
 
38
 
namespace HuginBase {
39
 
 
40
 
using namespace std;
41
 
using namespace hugin_utils;
42
 
using namespace vigra;
43
 
 
44
 
 
45
 
// should be moved somewhere else (will be after GSOC anyway)
46
 
vector<UIntSet> getHDRStacks(const PanoramaData & pano, UIntSet allImgs)
47
 
{
48
 
    vector<UIntSet> result;
49
 
 
50
 
    // if no images are available, return empty result vector
51
 
    if ( allImgs.empty() )
52
 
    {
53
 
        return result;
54
 
    }
55
 
 
56
 
    UIntSet stack;
57
 
 
58
 
    HuginBase::CalculateImageOverlap overlap(&pano);
59
 
    overlap.calculate(10);  // we are testing 10*10=100 points
60
 
    do {
61
 
        unsigned srcImg = *(allImgs.begin());
62
 
        stack.insert(srcImg);
63
 
        allImgs.erase(srcImg);
64
 
 
65
 
        // find all images that have a suitable overlap.
66
 
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
67
 
            unsigned srcImg2 = *it;
68
 
            it++;
69
 
            if(overlap.getOverlap(srcImg,srcImg2)>0.7)
70
 
            {
71
 
                stack.insert(srcImg2);
72
 
                allImgs.erase(srcImg2);
73
 
            }
74
 
        }
75
 
        result.push_back(stack);
76
 
        stack.clear();
77
 
    } while (allImgs.size() > 0);
78
 
 
79
 
    return result;
80
 
}
81
 
 
82
 
// should be moved somewhere else (will be after GSOC anyway)
83
 
vector<UIntSet> getExposureLayers(const PanoramaData & pano, UIntSet allImgs)
84
 
{
85
 
    vector<UIntSet> result;
86
 
 
87
 
    // if no images are available, return empty result vector
88
 
    if ( allImgs.empty() )
89
 
    {
90
 
        return result;
91
 
    }
92
 
 
93
 
    UIntSet stack;
94
 
 
95
 
    do {
96
 
        unsigned srcImg = *(allImgs.begin());
97
 
        stack.insert(srcImg);
98
 
        allImgs.erase(srcImg);
99
 
 
100
 
        // find all images that have a suitable overlap.
101
 
        const SrcPanoImage & simg = pano.getImage(srcImg);
102
 
        // FIXME this should be a user preference
103
 
        double maxEVDiff = 0.5;
104
 
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
105
 
            unsigned srcImg2 = *it;
106
 
            it++;
107
 
            const SrcPanoImage & simg2 = pano.getImage(srcImg2);
108
 
            if ( fabs(simg.getExposureValue() - simg2.getExposureValue()) < maxEVDiff )
109
 
            {
110
 
                stack.insert(srcImg2);
111
 
                allImgs.erase(srcImg2);
112
 
            }
113
 
        }
114
 
        result.push_back(stack);
115
 
        stack.clear();
116
 
    } while (allImgs.size() > 0);
117
 
 
118
 
    return result;
119
 
}
120
 
 
121
 
 
122
 
// should be moved somewhere else (will be after GSOC anyway)
123
 
UIntSet getImagesinROI (const PanoramaData& pano, const UIntSet activeImages)
124
 
{
125
 
    UIntSet images;
126
 
    PanoramaOptions opts = pano.getOptions();
127
 
    for (UIntSet::const_iterator it = activeImages.begin(); it != activeImages.end(); ++it)
128
 
    {
129
 
        Rect2D roi = estimateOutputROI(pano, opts, *it);
130
 
        if (! (roi.isEmpty())) {
131
 
            images.insert(*it);
132
 
        }
133
 
    }
134
 
    return images;
135
 
}
136
 
 
137
 
/* write make file line for checking, if progCommand can be runned
138
 
   prints progName on command line */
139
 
void checkProg(std::ostream& o,const std::string& progName, const std::string& progCommand)
140
 
{
141
 
#ifdef _WINDOWS
142
 
    o << "\t@echo Checking " << progName << "..." << endl
143
 
      << "\t" << progCommand << " > NUL 2>&1 && echo " << progName << " is ok || echo " 
144
 
      << progName << " failed" << endl;
145
 
#else
146
 
    o << "\t@echo -n 'Checking " << progName << "...'" << endl
147
 
      << "\t" << progCommand << " > /dev/null 2>&1 && echo '[OK]' || echo '[FAILED]'" << endl;
148
 
#endif
149
 
};
150
 
 
151
 
void PanoramaMakefileExport::createMakefile(const PanoramaData& pano,
152
 
                                            const UIntSet& rimages,
153
 
                                            const std::string& ptofile,
154
 
                                            const std::string& outputPrefix,
155
 
                                            const PTPrograms& progs,
156
 
                                            const std::string& includePath,
157
 
                                            std::vector<std::string> & outputFiles,
158
 
                                            std::ostream& o,
159
 
                                            const std::string& tmpDir)
160
 
{
161
 
    PanoramaOptions opts = pano.getOptions();
162
 
#ifdef UNIX_LIKE
163
 
    // set numeric locale to C, for correct number output
164
 
    char * t = setlocale(LC_NUMERIC,NULL);
165
 
    char * old_locale = (char*) malloc(strlen(t)+1);
166
 
    strcpy(old_locale, t);
167
 
    setlocale(LC_NUMERIC,"C");
168
 
#endif
169
 
 
170
 
    // output only images in current ROI
171
 
    UIntSet images = getImagesinROI(pano,rimages);
172
 
 
173
 
    // execute exiftool with perl if necessary
174
 
#ifdef COULD_EXECUTE_EXIFTOOL_WITH_PERL
175
 
    bool executeWithPerl = false;
176
 
    std::string perlCommand = "";
177
 
#if defined MAC_SELF_CONTAINED_BUNDLE
178
 
    // if exiftool is inside the bundle (not the best def, but works)
179
 
    if(progs.exiftool.find(".app") != std::string::npos)
180
 
    {
181
 
        executeWithPerl = true;
182
 
        perlCommand += "perl -w";
183
 
    }
184
 
#endif
185
 
#endif
186
 
 
187
 
    o << "# makefile for panorama stitching, created by hugin " << endl
188
 
      << endl;
189
 
 
190
 
    // pass settings for different temporary directory
191
 
    if (tmpDir != "") {
192
 
        o << "# set temporary directory" << endl;
193
 
#ifdef UNIX_LIKE
194
 
        o << "export TMPDIR=" << quoteStringShell(tmpDir) << endl;
195
 
#else // WINDOWS
196
 
        o << "export TEMP=" << quoteStringShell(tmpDir) << endl
197
 
          << "export TMP=" << quoteStringShell(tmpDir) << endl;
198
 
#endif
199
 
    }
200
 
 
201
 
#ifdef _WINDOWS
202
 
    o << "# Force using cmd.exe" << endl
203
 
      << "SHELL=" << getenv("ComSpec") << endl <<endl;
204
 
    
205
 
#endif
206
 
 
207
 
    o << endl
208
 
      << endl
209
 
      << "# Tool configuration" << endl
210
 
      << "NONA=" << quoteStringShell(progs.nona) << endl
211
 
      << "PTSTITCHER=" << quoteStringShell(progs.PTStitcher) << endl
212
 
      << "PTMENDER=" << quoteStringShell(progs.PTmender) << endl
213
 
      << "PTBLENDER=" << quoteStringShell(progs.PTblender) << endl
214
 
      << "PTMASKER=" << quoteStringShell(progs.PTmasker) << endl
215
 
      << "PTROLLER=" << quoteStringShell(progs.PTroller) << endl
216
 
      << "ENBLEND=" << quoteStringShell(progs.enblend) << endl
217
 
      << "ENFUSE=" << quoteStringShell(progs.enfuse) << endl
218
 
      << "SMARTBLEND=" << quoteStringShell(progs.smartblend) << endl
219
 
      << "HDRMERGE=" << quoteStringShell(progs.hdrmerge) << endl
220
 
#ifdef _WINDOWS
221
 
      << "RM=del" << endl
222
 
#else
223
 
      << "RM=rm" << endl
224
 
#endif
225
 
#ifdef COULD_EXECUTE_EXIFTOOL_WITH_PERL
226
 
      << "EXIFTOOL=" << (executeWithPerl? perlCommand+" " : "") << quoteStringShell(progs.exiftool) << endl
227
 
#else
228
 
      << "EXIFTOOL=" << quoteStringShell(progs.exiftool) << endl
229
 
#endif
230
 
      << endl
231
 
 
232
 
      << "# Project parameters" << endl
233
 
      << "HUGIN_PROJECTION=" << opts.getProjection() << endl
234
 
      << "HUGIN_HFOV=" << opts.getHFOV() << endl
235
 
      << "HUGIN_WIDTH=" << opts.getWidth() << endl
236
 
      << "HUGIN_HEIGHT=" << opts.getHeight() << endl
237
 
      << endl
238
 
 
239
 
      << "# options for the programs" << endl << endl;
240
 
 
241
 
    // set remapper specific settings
242
 
    switch(opts.remapper) {
243
 
        case PanoramaOptions::NONA:
244
 
            {
245
 
                o << "NONA_LDR_REMAPPED_COMP=";
246
 
                if (opts.outputImageType == "tif" && opts.outputLayersCompression.size() != 0) {
247
 
                    o << "-z " << opts.outputLayersCompression;
248
 
                } else if (opts.outputImageType == "jpg") {
249
 
                    o << "-z PACKBITS ";
250
 
                }
251
 
                o << endl;
252
 
                o << "NONA_OPTS=";
253
 
                if (opts.remapUsingGPU)
254
 
                {
255
 
                    o << "-g ";
256
 
                }
257
 
                o << endl;
258
 
            }
259
 
            break;
260
 
        case PanoramaOptions::PTMENDER:
261
 
            break;
262
 
    }
263
 
 
264
 
    // set blender specific settings
265
 
    switch(opts.blendMode) {
266
 
        case PanoramaOptions::ENBLEND_BLEND:
267
 
            {
268
 
                o << "ENBLEND_OPTS=" << opts.enblendOptions;
269
 
                if (opts.getHFOV() == 360.0) {
270
 
                    // blend over the border
271
 
                    o << " -w";
272
 
                }
273
 
                vigra::Rect2D roi = opts.getROI();
274
 
                if (roi.top() != 0 || roi.left() != 0 ) {
275
 
                    o << " -f" << roi.width() << "x" << roi.height() << "+" << roi.left() << "+" << roi.top();
276
 
                } else {
277
 
                    o << " -f" << roi.width() << "x" << roi.height();
278
 
                }
279
 
                o << endl;
280
 
 
281
 
                o << "ENBLEND_LDR_COMP=";
282
 
                if (opts.outputImageType == "tif" && opts.outputImageTypeCompression.size() != 0) {
283
 
                    o << "--compression " << opts.outputImageTypeCompression;
284
 
                } else if (opts.outputImageType == "jpg") {
285
 
                    o << "--compression " << opts.quality;
286
 
                }
287
 
                o << endl;
288
 
 
289
 
                o << "ENBLEND_HDR_COMP=";
290
 
                if (opts.outputImageTypeHDR == "tif" && opts.outputImageTypeHDRCompression.size() != 0) {
291
 
                    o << "--compression " << opts.outputImageTypeHDRCompression;
292
 
                }
293
 
                o << endl;
294
 
            }
295
 
            break;
296
 
        case PanoramaOptions::PTBLENDER_BLEND:
297
 
            {
298
 
                o << "PTBLENDER_OPTS=";
299
 
                    switch (opts.colorCorrection) {
300
 
                        case PanoramaOptions::NONE:
301
 
                            break;
302
 
                        case PanoramaOptions::BRIGHTNESS_COLOR:
303
 
                            o << " -k " << opts.colorReferenceImage;
304
 
                            break;
305
 
                        case PanoramaOptions::BRIGHTNESS:
306
 
                            o << " -k " << opts.colorReferenceImage;
307
 
                            break;
308
 
                        case PanoramaOptions::COLOR:
309
 
                            o << " -k " << opts.colorReferenceImage;
310
 
                            break;
311
 
                    }
312
 
                o << endl;
313
 
            }
314
 
            break;
315
 
        case PanoramaOptions::SMARTBLEND_BLEND:
316
 
            {
317
 
                o << "SMARTBLEND_OPTS=" << progs.smartblend_opts;
318
 
                if (opts.getHFOV() == 360.0) {
319
 
                    // blend over the border
320
 
                    o << " -w";
321
 
                }
322
 
                o << endl;
323
 
                // TODO: build smartblend command line from given images. (requires additional program)
324
 
            }
325
 
            break;
326
 
    }
327
 
 
328
 
    switch (opts.hdrMergeMode)
329
 
    {
330
 
        case PanoramaOptions::HDRMERGE_AVERAGE:
331
 
            o << "HDRMERGE_OPTS=" << opts.hdrmergeOptions << endl;
332
 
            break;
333
 
        case PanoramaOptions::HDRMERGE_DEGHOST:
334
 
            break;
335
 
    }
336
 
 
337
 
    o << "ENFUSE_OPTS=" << opts.enfuseOptions;
338
 
    // TODO: blend only over border if this is indeed a
339
 
    // image with 360 deg overlap
340
 
    if (opts.getHFOV() == 360.0) {
341
 
        // blend over the border
342
 
        o << " -w";
343
 
    }
344
 
    o << endl;
345
 
 
346
 
    o << "EXIFTOOL_COPY_ARGS=" << progs.exiftool_opts << endl;
347
 
    o << endl;
348
 
 
349
 
    string hdrExt = string(".") + opts.outputImageTypeHDR;
350
 
    string ldrExt = string(".") + opts.outputImageType;
351
 
    string ldrRemappedExt(".tif");
352
 
    string ldrRemappedMode("TIFF_m");
353
 
    string hdrRemappedExt = ".exr";
354
 
    string hdrRemappedMode = "EXR_m";
355
 
 
356
 
    // set a suitable target file.
357
 
    std::string output = outputPrefix;
358
 
 
359
 
//    bool externalBlender = false;
360
 
//    bool remapToMultiple = false;
361
 
 
362
 
    /*
363
 
    if (opts.blendMode == PT::PanoramaOptions::NO_BLEND) {
364
 
        // just remapping or simple blending
365
 
        if (opts.outputFormat == PT::PanoramaOptions::TIFF_m) {
366
 
            remapToMultiple = true;
367
 
        }
368
 
    } else {
369
 
        externalBlender = true;
370
 
        remapToMultiple = true;
371
 
    }
372
 
*/
373
 
    std::string sLDR_BLENDED = output + ldrExt;
374
 
    std::string sLDR_STACKED_BLENDED = output + "_fused" + ldrExt;
375
 
    std::string sLDR_EXPOSURE_LAYERS_FUSED = output + "_blended_fused" + ldrExt;
376
 
    std::string sHDR_BLENDED = output + "_hdr" + hdrExt;
377
 
 
378
 
    o << "# the output panorama" << endl
379
 
      << "LDR_REMAPPED_PREFIX=" << escapeStringMake(output) << endl
380
 
      << "LDR_REMAPPED_PREFIX_SHELL=" << quoteStringShell(output) << endl
381
 
 
382
 
    << "HDR_STACK_REMAPPED_PREFIX=" << escapeStringMake(output + "_hdr_") << endl
383
 
    << "HDR_STACK_REMAPPED_PREFIX_SHELL=" << quoteStringShell(output + "_hdr_") << endl
384
 
 
385
 
    << "LDR_EXPOSURE_REMAPPED_PREFIX=" << escapeStringMake(output + "_exposure_layers_") << endl
386
 
    << "LDR_EXPOSURE_REMAPPED_PREFIX_SHELL=" << quoteStringShell(output + "_exposure_layers_") << endl
387
 
 
388
 
    << "PROJECT_FILE=" << escapeStringMake(ptofile) << endl
389
 
    << "PROJECT_FILE_SHELL=" << quoteStringShell(ptofile) << endl
390
 
 
391
 
    << "LDR_BLENDED=" << escapeStringMake(sLDR_BLENDED) << endl
392
 
    << "LDR_BLENDED_SHELL=" << quoteStringShell(sLDR_BLENDED) << endl
393
 
 
394
 
    << "LDR_STACKED_BLENDED=" << escapeStringMake(sLDR_STACKED_BLENDED) << endl
395
 
    << "LDR_STACKED_BLENDED_SHELL=" << quoteStringShell(sLDR_STACKED_BLENDED) << endl
396
 
 
397
 
    << "LDR_EXPOSURE_LAYERS_FUSED=" << escapeStringMake(sLDR_EXPOSURE_LAYERS_FUSED) << endl
398
 
    << "LDR_EXPOSURE_LAYERS_FUSED_SHELL=" << quoteStringShell(sLDR_EXPOSURE_LAYERS_FUSED) << endl
399
 
 
400
 
    << "HDR_BLENDED=" << escapeStringMake(sHDR_BLENDED) << endl
401
 
    << "HDR_BLENDED_SHELL=" << quoteStringShell(sHDR_BLENDED) << endl
402
 
    << endl
403
 
    << "# first input image" << endl
404
 
    << "INPUT_IMAGE_1="  << escapeStringMake(pano.getImage(0).getFilename()) << endl
405
 
    << "INPUT_IMAGE_1_SHELL="  << quoteStringShell(pano.getImage(0).getFilename()) << endl
406
 
 
407
 
    << "# all input images" << endl
408
 
    << "INPUT_IMAGES=";
409
 
    for (unsigned int i=0; i < pano.getNrOfImages(); i++) {
410
 
        o << escapeStringMake(pano.getImage(i).getFilename());
411
 
        if (i+1 != pano.getNrOfImages()) o << "\\" << endl;
412
 
    }
413
 
    o << endl << endl;
414
 
 
415
 
    o << "INPUT_IMAGES_SHELL=";
416
 
    for (unsigned int i=0; i < pano.getNrOfImages(); i++) {
417
 
        o << quoteStringShell(pano.getImage(i).getFilename());
418
 
        if (i+1 != pano.getNrOfImages()) o << "\\" << endl;
419
 
    }
420
 
 
421
 
    vector<string> remappedImages;
422
 
    o << endl
423
 
      << endl
424
 
      << "# remapped images" << endl
425
 
      << "LDR_LAYERS=";
426
 
    for (UIntSet::iterator it = images.begin(); it != images.end();) {
427
 
        std::ostringstream fns;
428
 
        fns << output << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
429
 
        remappedImages.push_back(fns.str());
430
 
        o << escapeStringMake(fns.str());
431
 
        ++it;
432
 
        if (it != images.end()) o << "\\" << endl;
433
 
    }
434
 
 
435
 
    o << endl << endl
436
 
      << "LDR_LAYERS_SHELL=";
437
 
    for(int i=0; i < (int) remappedImages.size(); i++) {
438
 
        o << quoteStringShell(remappedImages[i]);
439
 
        if (i != remappedImages.size() -1) {
440
 
            o << "\\" << endl;
441
 
        }
442
 
    }
443
 
 
444
 
    vector<string> remappedHDRImages;
445
 
    o << endl
446
 
      << endl
447
 
      << "# remapped images (hdr)" << endl
448
 
      << "HDR_LAYERS=";
449
 
    for (UIntSet::iterator it = images.begin(); it != images.end();) {
450
 
        std::ostringstream fns;
451
 
        fns << output << "_hdr_" << std::setfill('0') << std::setw(4) << *it << hdrRemappedExt;
452
 
        remappedHDRImages.push_back(fns.str());
453
 
        o << escapeStringMake(fns.str());
454
 
        ++it;
455
 
        if (it != images.end()) o << "\\" << endl;
456
 
    }
457
 
    o << endl << endl
458
 
      << "HDR_LAYERS_SHELL=";
459
 
    for(int i=0; i < (int) remappedHDRImages.size(); i++) {
460
 
        o << quoteStringShell(remappedHDRImages[i]);
461
 
        if (i != remappedHDRImages.size() - 1) {
462
 
            o << "\\" << endl;
463
 
        }
464
 
    }
465
 
 
466
 
    vector<string> remappedHDRImagesGray;
467
 
    o << endl
468
 
      << endl
469
 
      << "# remapped maxval images" << endl
470
 
      << "HDR_LAYERS_WEIGHTS=";
471
 
    for (UIntSet::iterator it = images.begin(); it != images.end();) {
472
 
        std::ostringstream fns;
473
 
        fns << output << "_hdr_" << std::setfill('0') << std::setw(4) << *it << "_gray.pgm";
474
 
        remappedHDRImagesGray.push_back(fns.str());
475
 
        o << escapeStringMake(fns.str()) << " ";
476
 
        ++it;
477
 
        if (it != images.end()) o << "\\" << endl;
478
 
    }
479
 
    o << endl << endl
480
 
      << "HDR_LAYERS_WEIGHTS_SHELL=";
481
 
    for(unsigned i=0; i < remappedHDRImagesGray.size(); i++) {
482
 
        o << quoteStringShell(remappedHDRImagesGray[i]);
483
 
        if (i != remappedHDRImagesGray.size() - 1) {
484
 
            o << "\\" << endl;
485
 
        }
486
 
    }
487
 
    o << endl;
488
 
 
489
 
    vector<string> stackedImages;
490
 
    vector<UIntSet> stacks = getHDRStacks(pano, images);
491
 
    DEBUG_DEBUG( stacks.size() << " stacks found");
492
 
    o << endl
493
 
      << "# stacked images" << endl
494
 
      << "HDR_STACKS_NUMBERS = ";
495
 
    for (unsigned i=0; i < stacks.size(); i++)
496
 
        o << i << " ";
497
 
    o << endl;
498
 
    for (unsigned i=0; i < stacks.size(); i++) {
499
 
        std::ostringstream fns;
500
 
        fns << output << "_stack_hdr_" << std::setfill('0') << std::setw(4) << i << hdrRemappedExt;
501
 
        stackedImages.push_back(fns.str());
502
 
        std::ostringstream stackedImgVar;
503
 
        stackedImgVar << "HDR_STACK_" << i;
504
 
        o << stackedImgVar.str() << " = " << escapeStringMake(fns.str()) << endl;
505
 
        o << stackedImgVar.str() << "_SHELL = " << quoteStringShell(fns.str()) << endl;
506
 
        o << stackedImgVar.str() << "_INPUT = ";
507
 
        for (UIntSet::iterator it = stacks[i].begin(); it != stacks[i].end();) {
508
 
            std::ostringstream fns;
509
 
            fns << output << "_hdr_" << std::setfill('0') << std::setw(4) << *it << hdrRemappedExt;
510
 
            o << escapeStringMake(fns.str());
511
 
            ++it;
512
 
            if (it != stacks[i].end()) o << "\\" << endl;
513
 
        }
514
 
        o << endl << endl;
515
 
        o << stackedImgVar.str() << "_INPUT_SHELL = ";
516
 
        for (UIntSet::iterator it = stacks[i].begin(); it != stacks[i].end();) {
517
 
            std::ostringstream fns;
518
 
            fns << output << "_hdr_" << std::setfill('0') << std::setw(4) << *it << hdrRemappedExt;
519
 
            o << quoteStringShell(fns.str());
520
 
            ++it;
521
 
            if (it != stacks[i].end()) o << "\\" << endl;
522
 
        }
523
 
        o << endl << endl;
524
 
    }
525
 
    o << endl;
526
 
    o << "HDR_STACKS = ";
527
 
    for (unsigned i=0; i < stacks.size(); i++)
528
 
        o << "$(HDR_STACK_" << i << ") ";
529
 
    o << endl;
530
 
    o << "HDR_STACKS_SHELL = ";
531
 
    for (unsigned i=0; i < stacks.size(); i++)
532
 
        o << "$(HDR_STACK_" << i << "_SHELL) ";
533
 
    o << endl;
534
 
 
535
 
    // add support for exposure blending stuff...
536
 
    vector<string> similarExposureRemappedImages;
537
 
    vector<string> similarExposureImages;
538
 
    vector<UIntSet> similarExposures = getExposureLayers(pano, images);
539
 
    DEBUG_DEBUG( similarExposures.size() << " similar exposures found");
540
 
    o << endl
541
 
    << endl
542
 
    << "# number of image sets with similar exposure" << endl
543
 
    << "LDR_EXPOSURE_EXPOSURE_LAYERS_NUMBERS = ";
544
 
    for (unsigned i=0; i < similarExposures.size(); i++)
545
 
        o << i << " ";
546
 
    o << endl;
547
 
    for (unsigned i=0; i < similarExposures.size(); i++) {
548
 
        std::ostringstream fns;
549
 
        fns << output << "_exposure_" << std::setfill('0') << std::setw(2) << i << ldrExt;
550
 
        similarExposureImages.push_back(fns.str());
551
 
        string destImg = fns.str();
552
 
        std::ostringstream expImgVar;
553
 
        expImgVar << "LDR_EXPOSURE_LAYER_" << i;
554
 
        o << expImgVar.str() << " = " << escapeStringMake(destImg) << endl;
555
 
        o << expImgVar.str() << "_SHELL = " << quoteStringShell(destImg) << endl;
556
 
        o << expImgVar.str() << "_INPUT = ";
557
 
        double exposure=0;
558
 
        for (UIntSet::iterator it = similarExposures[i].begin(); it != similarExposures[i].end();) {
559
 
            exposure += pano.getImage(*it).getExposureValue();
560
 
            std::ostringstream fns;
561
 
            fns << output << "_exposure_layers_" << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
562
 
            similarExposureRemappedImages.push_back(fns.str());
563
 
            o << escapeStringMake(fns.str());
564
 
            ++it;
565
 
            if (it != similarExposures[i].end()) o << "\\" << endl;
566
 
        }
567
 
        o << endl << endl;
568
 
        o << expImgVar.str() << "_INPUT_SHELL = ";
569
 
        for (UIntSet::iterator it = similarExposures[i].begin(); it != similarExposures[i].end();) {
570
 
            std::ostringstream fns;
571
 
            fns << output << "_exposure_layers_" << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
572
 
            o << quoteStringShell(fns.str());
573
 
            ++it;
574
 
            if (it != similarExposures[i].end()) o << "\\" << endl;
575
 
        }
576
 
        o << endl << endl;
577
 
        o << expImgVar.str() << "_INPUT_PTMENDER = ";
578
 
        for (UIntSet::iterator it = similarExposures[i].begin(); it != similarExposures[i].end();) {
579
 
            std::ostringstream fns;
580
 
            fns << output << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
581
 
            o << escapeStringMake(fns.str());
582
 
            ++it;
583
 
            if (it != similarExposures[i].end()) o << "\\" << endl;
584
 
        }
585
 
 
586
 
        o << endl << endl << expImgVar.str() << "_INPUT_PTMENDER_SHELL = ";
587
 
        for (UIntSet::iterator it = similarExposures[i].begin(); it != similarExposures[i].end();) {
588
 
            std::ostringstream fns;
589
 
            fns << output << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
590
 
            o << quoteStringShell(fns.str());
591
 
            ++it;
592
 
            if (it != similarExposures[i].end()) o << "\\" << endl;
593
 
        }
594
 
        // calculate output exposure value for this set.
595
 
        o << endl
596
 
          << "LDR_EXPOSURE_LAYER_" << i << "_EXPOSURE = "
597
 
          << exposure / similarExposures[i].size() << endl;
598
 
    }
599
 
    o << endl;
600
 
    o << "LDR_EXPOSURE_LAYERS = ";
601
 
    for (unsigned i=0; i < similarExposures.size(); i++)
602
 
        o << "$(LDR_EXPOSURE_LAYER_" << i << ") ";
603
 
    o << endl;
604
 
    o << "LDR_EXPOSURE_LAYERS_SHELL = ";
605
 
    for (unsigned i=0; i < similarExposures.size(); i++)
606
 
        o << "$(LDR_EXPOSURE_LAYER_" << i << "_SHELL) ";
607
 
    o << endl;
608
 
    o << "LDR_EXPOSURE_LAYERS_REMAPPED = ";
609
 
    for (unsigned i=0; i < similarExposureRemappedImages.size(); i++)
610
 
    {
611
 
        o << escapeStringMake(similarExposureRemappedImages[i]);
612
 
        if (i+1 != similarExposureRemappedImages.size()) o << "\\" << endl;
613
 
    }
614
 
    o << endl << endl;
615
 
    o << "LDR_EXPOSURE_LAYERS_REMAPPED_SHELL = ";
616
 
    for (unsigned i=0; i < similarExposureRemappedImages.size(); i++)
617
 
    {
618
 
        o << quoteStringShell(similarExposureRemappedImages[i]);
619
 
        if (i+1 != similarExposureRemappedImages.size()) o << "\\" << endl;
620
 
    }
621
 
    o << endl << endl;
622
 
 
623
 
 
624
 
    vector<string> ldrStackedImages;
625
 
    o << endl
626
 
      << "# stacked images for enfuse or other automatic exposure blending tools" << endl
627
 
      << "LDR_STACKS_NUMBERS = ";
628
 
    for (unsigned i=0; i < stacks.size(); i++)
629
 
        o << i << " ";
630
 
    o << endl;
631
 
    for (unsigned i=0; i < stacks.size(); i++) {
632
 
        std::ostringstream fns;
633
 
        fns << output << "_stack_ldr_" << std::setfill('0') << std::setw(4) << i << ldrRemappedExt;
634
 
        ldrStackedImages.push_back(fns.str());
635
 
        std::ostringstream stackedImgVar;
636
 
        stackedImgVar << "LDR_STACK_" << i;
637
 
        o << stackedImgVar.str() << " = " << escapeStringMake(fns.str()) << endl;
638
 
        o << stackedImgVar.str() << "_SHELL = " << quoteStringShell(fns.str()) << endl;
639
 
        o << stackedImgVar.str() << "_INPUT = ";
640
 
        for (UIntSet::iterator it = stacks[i].begin(); it != stacks[i].end();) {
641
 
            std::ostringstream fns;
642
 
            fns << output << "_exposure_layers_" << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
643
 
            o << escapeStringMake(fns.str());
644
 
            ++it;
645
 
            if (it != stacks[i].end()) o << "\\" << endl;
646
 
        }
647
 
        o << endl << endl;
648
 
        o << stackedImgVar.str() << "_INPUT_SHELL = ";
649
 
        for (UIntSet::iterator it = stacks[i].begin(); it != stacks[i].end();) {
650
 
            std::ostringstream fns;
651
 
            fns << output << "_exposure_layers_" << std::setfill('0') << std::setw(4) << *it << ldrRemappedExt;
652
 
            o << quoteStringShell(fns.str());
653
 
            ++it;
654
 
            if (it != stacks[i].end()) o << "\\" << endl;
655
 
        }
656
 
        o << endl << endl;
657
 
    }
658
 
    o << endl;
659
 
    o << "LDR_STACKS = ";
660
 
    for (unsigned i=0; i < stacks.size(); i++)
661
 
        o << "$(LDR_STACK_" << i << ") ";
662
 
    o << endl;
663
 
    o << "LDR_STACKS_SHELL = ";
664
 
    for (unsigned i=0; i < stacks.size(); i++)
665
 
        o << "$(LDR_STACK_" << i << "_SHELL) ";
666
 
    o << endl;
667
 
 
668
 
 
669
 
    // TODO: include custom makefile here
670
 
    if (includePath.size() > 0) {
671
 
        o << "include " <<  escapeStringMake(includePath) <<  endl << endl;
672
 
    } else {
673
 
        // create rules for all possible targets.
674
 
 
675
 
        std::string targets;
676
 
        std::string cleanTargets;
677
 
 
678
 
        // output all targets
679
 
        if (opts.outputLDRBlended) {
680
 
            targets += "$(LDR_BLENDED) ";
681
 
            outputFiles.push_back(sLDR_BLENDED);
682
 
            o << "DO_LDR_BLENDED = 1" << endl;
683
 
            // depends on remapped ldr images and stacked ldr images
684
 
            if (! opts.outputLDRLayers) {
685
 
                outputFiles.insert(outputFiles.end(), remappedImages.begin(), remappedImages.end());
686
 
                cleanTargets += "$(LDR_LAYERS_SHELL) ";
687
 
            }
688
 
        }
689
 
 
690
 
        if (opts.outputLDRLayers) {
691
 
            targets +=  "$(LDR_LAYERS) ";
692
 
            outputFiles.insert(outputFiles.end(), remappedImages.begin(), remappedImages.end());
693
 
        }
694
 
 
695
 
        if (opts.outputLDRExposureRemapped) {
696
 
            targets += "$(LDR_EXPOSURE_LAYERS_REMAPPED) ";
697
 
            outputFiles.insert(outputFiles.end(), similarExposureRemappedImages.begin(), similarExposureRemappedImages.end());
698
 
        }
699
 
 
700
 
        if (opts.outputLDRExposureLayers) {
701
 
            targets += " $(LDR_EXPOSURE_LAYERS) ";
702
 
            outputFiles.insert(outputFiles.end(), similarExposureImages.begin(), similarExposureImages.end());
703
 
            if (! opts.outputLDRExposureRemapped) {
704
 
                outputFiles.insert(outputFiles.end(), similarExposureRemappedImages.begin(), similarExposureRemappedImages.end());
705
 
                cleanTargets += "$(LDR_EXPOSURE_LAYERS_REMAPPED_SHELL) ";
706
 
            }
707
 
        }
708
 
 
709
 
        if (opts.outputLDRExposureBlended) {
710
 
            targets += " $(LDR_STACKED_BLENDED) ";
711
 
            outputFiles.push_back(sLDR_STACKED_BLENDED);
712
 
            o << "DO_LDR_STACKED_BLENDED = 1" << endl;
713
 
            outputFiles.insert(outputFiles.end(),ldrStackedImages.begin(), ldrStackedImages.end());
714
 
            // always clean temp files used by exposure stacks
715
 
            cleanTargets += "$(LDR_STACKS_SHELL) ";
716
 
            if (! opts.outputLDRExposureRemapped && ! opts.outputLDRExposureLayers) {
717
 
                outputFiles.insert(outputFiles.end(), similarExposureRemappedImages.begin(), similarExposureRemappedImages.end());
718
 
                cleanTargets += "$(LDR_EXPOSURE_LAYERS_REMAPPED_SHELL) ";
719
 
            }
720
 
        }
721
 
 
722
 
        if (opts.outputLDRExposureLayersFused) {
723
 
            targets += " $(LDR_EXPOSURE_LAYERS_FUSED) ";
724
 
            outputFiles.push_back(sLDR_EXPOSURE_LAYERS_FUSED);
725
 
            o << "DO_LDR_EXPOSURE_LAYERS_FUSED = 1" << endl;
726
 
            outputFiles.insert(outputFiles.end(),similarExposureImages.begin(), similarExposureImages.end());
727
 
            if (! opts.outputLDRExposureRemapped && ! opts.outputLDRExposureLayers) {
728
 
                outputFiles.insert(outputFiles.end(), similarExposureRemappedImages.begin(), similarExposureRemappedImages.end());
729
 
                cleanTargets += "$(LDR_EXPOSURE_LAYERS_REMAPPED_SHELL) ";
730
 
                cleanTargets += "$(LDR_EXPOSURE_LAYERS_SHELL) ";
731
 
            }
732
 
        }
733
 
 
734
 
        if (opts.outputHDRLayers) {
735
 
            targets += "$(HDR_LAYERS) ";
736
 
            outputFiles.insert(outputFiles.end(),remappedHDRImages.begin(), remappedHDRImages.end());
737
 
            outputFiles.insert(outputFiles.end(),remappedHDRImagesGray.begin(), remappedHDRImagesGray.end());
738
 
        }
739
 
 
740
 
        if (opts.outputHDRStacks) {
741
 
            targets += "$(HDR_STACKS) ";
742
 
            outputFiles.insert(outputFiles.end(),stackedImages.begin(), stackedImages.end());
743
 
            if (!opts.outputHDRLayers) {
744
 
                outputFiles.insert(outputFiles.end(),remappedHDRImages.begin(), remappedHDRImages.end());
745
 
                outputFiles.insert(outputFiles.end(),remappedHDRImagesGray.begin(), remappedHDRImagesGray.end());
746
 
                cleanTargets += "$(HDR_LAYERS_SHELL) $(HDR_LAYERS_WEIGHTS_SHELL) ";
747
 
            }
748
 
        }
749
 
 
750
 
        if (opts.outputHDRBlended) {
751
 
            targets += "$(HDR_BLENDED) ";
752
 
            outputFiles.push_back(sHDR_BLENDED);
753
 
            o << "DO_HDR_BLENDED = 1" << endl;
754
 
            if (!opts.outputHDRStacks) {
755
 
                outputFiles.insert(outputFiles.end(),stackedImages.begin(), stackedImages.end());
756
 
                cleanTargets += "$(HDR_STACKS_SHELL) ";
757
 
                if (! opts.outputHDRLayers) {
758
 
                    outputFiles.insert(outputFiles.end(),remappedHDRImages.begin(), remappedHDRImages.end());
759
 
                    outputFiles.insert(outputFiles.end(),remappedHDRImagesGray.begin(), remappedHDRImagesGray.end());
760
 
                    cleanTargets += "$(HDR_LAYERS_SHELL) $(HDR_LAYERS_WEIGHTS_SHELL) ";
761
 
                }
762
 
            }
763
 
        }
764
 
 
765
 
        // targets and clean rule.
766
 
 
767
 
        o << "TEMP_FILES_SHELL = " << cleanTargets << endl
768
 
        << endl
769
 
        << "all: " << targets << endl << endl
770
 
        << "clean: " << endl
771
 
        << "\t-$(RM) $(TEMP_FILES_SHELL)" << endl
772
 
        << endl;
773
 
 
774
 
        // test rule
775
 
        o << "test: " << endl;
776
 
        // test remapper
777
 
        switch(opts.remapper) {
778
 
            case PanoramaOptions::NONA:
779
 
                checkProg(o,"nona","@-$(NONA) --help");
780
 
                break;
781
 
            case PanoramaOptions::PTMENDER:
782
 
                break;
783
 
        }
784
 
        // test blender
785
 
        switch(opts.blendMode) {
786
 
            case PanoramaOptions::ENBLEND_BLEND:
787
 
                checkProg(o,"enblend","@-$(ENBLEND) -h");
788
 
                break;
789
 
            case PanoramaOptions::PTBLENDER_BLEND:
790
 
                checkProg(o,"PTblender","@-$(PTBLENDER) -h");
791
 
                break;
792
 
            case PanoramaOptions::SMARTBLEND_BLEND:
793
 
                checkProg(o,"smartblend","@-$(SMARTBLEND)");
794
 
                break;
795
 
        }
796
 
        // test enfuse
797
 
        checkProg(o,"enfuse","@-$(ENFUSE) -h");
798
 
        // test hugin_hdrmerge
799
 
        checkProg(o,"hugin_hdrmerge","@-$(HDRMERGE) -h");
800
 
        // test exiftool
801
 
        checkProg(o,"exiftool","@-$(EXIFTOOL) -ver");
802
 
        // test rm
803
 
/* Needs to be replaced by a test that creates and deletes a file in the TEMP dir
804
 
        o << "\t@echo -n 'Checking rm...'" << endl
805
 
#ifdef MAC_OS_X
806
 
          << "\t@-which $(RM) > " << NULL_DEVICE << " 2>&1 && echo '[OK]' || echo '[FAIL]'" << endl;
807
 
#else
808
 
          << "\t@-$(RM) --version > " << NULL_DEVICE << " 2>&1 && echo '[OK]' || echo '[FAIL]'" << endl;
809
 
#endif
810
 
*/
811
 
        o << endl;
812
 
 
813
 
        // ==============================
814
 
        // output rules for all targets.
815
 
        // remapped LDR images for exposure stacks.
816
 
        switch(opts.remapper) {
817
 
            case PanoramaOptions::NONA:
818
 
                // produce rules for remapping with nona:
819
 
                {
820
 
                    o << "# Rules for ordinary TIFF_m output" << endl;
821
 
                    int i=0;
822
 
                    for (UIntSet::iterator it = images.begin();
823
 
                        it != images.end(); ++it)
824
 
                    {
825
 
                        string destImg = escapeStringMake(remappedImages[i]);
826
 
                        string srcImg = escapeStringMake(pano.getImage(*it).getFilename());
827
 
                        o << destImg << ": " << srcImg << " $(PROJECT_FILE)" << endl
828
 
                        << "\t$(NONA) $(NONA_OPTS) $(NONA_LDR_REMAPPED_COMP) -r ldr -m " << ldrRemappedMode << " -o $(LDR_REMAPPED_PREFIX_SHELL) -i " << *it << " $(PROJECT_FILE_SHELL)" << endl << endl;
829
 
                        i++;
830
 
                    }
831
 
 
832
 
                    o << "# Rules for merge to hdr output" << endl;
833
 
                    i=0;
834
 
                    for (UIntSet::iterator it = images.begin();
835
 
                        it != images.end(); ++it)
836
 
                    {
837
 
                        string destImg = escapeStringMake(remappedHDRImages[i]);
838
 
                        string srcImg = escapeStringMake(pano.getImage(*it).getFilename());
839
 
                        o << destImg << ": " << srcImg << " $(PROJECT_FILE)" << endl
840
 
                        << "\t$(NONA) $(NONA_OPTS) -r hdr -m " << hdrRemappedMode << " -o $(HDR_STACK_REMAPPED_PREFIX_SHELL) -i " << *it << " $(PROJECT_FILE_SHELL)" << endl << endl;
841
 
                        i++;
842
 
                    }
843
 
 
844
 
                    // rules for exposure sets.
845
 
                    o << "# Rules for exposure layer output" << endl;
846
 
                    int j=0;
847
 
                    for (unsigned i=0; i < similarExposures.size(); i++) {
848
 
                        for (UIntSet::iterator it = similarExposures[i].begin();
849
 
                            it != similarExposures[i].end(); ++it)
850
 
                        {
851
 
                            string destImg = escapeStringMake(similarExposureRemappedImages[j]);
852
 
                            string srcImg = escapeStringMake(pano.getImage(*it).getFilename());
853
 
                            /*
854
 
                            o << destImg << ": " << srcImg << " $(PROJECT_FILE)" << endl
855
 
                              << "\t$(NONA) -r ldr -e $(LDR_EXPOSURE_LAYER_" << i << "_EXPOSURE) -m "
856
 
                              << ldrRemappedMode << " -o $(LDR_EXPOSURE_REMAPPED_PREFIX) -i " << *it
857
 
                              << " $(PROJECT_FILE)" << endl << endl;
858
 
                            */
859
 
                            o << destImg << ": " << srcImg << " $(PROJECT_FILE)" << endl
860
 
                              << "\t$(NONA) $(NONA_OPTS) $(NONA_LDR_REMAPPED_COMP) -r ldr -e " << pano.getImage(*it).getExposureValue()
861
 
                              << " -m " << ldrRemappedMode << " -o $(LDR_EXPOSURE_REMAPPED_PREFIX_SHELL) -i " << *it
862
 
                              << " $(PROJECT_FILE_SHELL)" << endl << endl;
863
 
                            j++;
864
 
                        }
865
 
                    }
866
 
                }
867
 
                break;
868
 
            case PanoramaOptions::PTMENDER:
869
 
                    o << "$(LDR_LAYERS) : $(INPUT_IMAGES) $(PROJECT_FILE)" << endl
870
 
                    << "\t$(PTMENDER) -o $(LDR_REMAPPED_PREFIX_SHELL)  $(PROJECT_FILE_SHELL)" << endl << endl;
871
 
                break;
872
 
        }
873
 
 
874
 
        // ====================================
875
 
        // output rules for HDR merging
876
 
 
877
 
        // write rules for each HDR stack
878
 
        // only output pixes that are defined in all input images
879
 
        for (unsigned i=0; i < stacks.size(); i++) {
880
 
            o << "$(HDR_STACK_" << i << ") : $(HDR_STACK_" << i << "_INPUT)" << endl
881
 
            << "\t$(HDRMERGE) $(HDRMERGE_OPTS) -o $(HDR_STACK_" << i << "_SHELL) $(HDR_STACK_" << i << "_INPUT_SHELL)" << endl
882
 
            << endl;
883
 
        }
884
 
 
885
 
        // ====================================
886
 
        // output rules for LDR stack merging
887
 
 
888
 
        for (unsigned i=0; i < stacks.size(); i++) {
889
 
            o << "$(LDR_STACK_" << i << ") : $(LDR_STACK_" << i << "_INPUT)" << endl
890
 
            << "\t$(ENFUSE) $(ENFUSE_OPTS) -o $(LDR_STACK_" << i << "_SHELL) $(LDR_STACK_" << i << "_INPUT_SHELL)" << endl
891
 
            << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_STACK_" << i << "_SHELL)" << endl
892
 
            << endl;
893
 
        }
894
 
 
895
 
        switch(opts.blendMode) {
896
 
            case PanoramaOptions::ENBLEND_BLEND:
897
 
                // write rules for blending with enblend
898
 
                o << "$(LDR_BLENDED) : $(LDR_LAYERS)" << endl;
899
 
                o << "\t$(ENBLEND) $(ENBLEND_LDR_COMP) $(ENBLEND_OPTS) -o $(LDR_BLENDED_SHELL) $(LDR_LAYERS_SHELL) " << endl;
900
 
                o << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_BLENDED_SHELL)" << endl << endl;
901
 
 
902
 
                // for LDR exposure blend planes
903
 
                for (unsigned i=0; i < similarExposures.size(); i++) {
904
 
                    o << "$(LDR_EXPOSURE_LAYER_" << i <<") : $(LDR_EXPOSURE_LAYER_" << i << "_INPUT)" << endl
905
 
                      << "\t$(ENBLEND) $(ENBLEND_LDR_COMP) $(ENBLEND_OPTS) -o $(LDR_EXPOSURE_LAYER_" << i <<"_SHELL) $(LDR_EXPOSURE_LAYER_" << i << "_INPUT_SHELL)" << endl
906
 
                      << "\t-$(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_EXPOSURE_LAYER_" << i <<"_SHELL)" << endl << endl;
907
 
                }
908
 
 
909
 
                // rules for enfuse blending
910
 
                o << "$(LDR_STACKED_BLENDED) : $(LDR_STACKS)" << endl
911
 
                  << "\t$(ENBLEND) $(ENBLEND_LDR_COMP) $(ENBLEND_OPTS) -o $(LDR_STACKED_BLENDED_SHELL) $(LDR_STACKS_SHELL) " << endl
912
 
                  << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_STACKED_BLENDED_SHELL)" << endl << endl;
913
 
 
914
 
                // rules for fusing blended layers
915
 
                o << "$(LDR_EXPOSURE_LAYERS_FUSED) : $(LDR_EXPOSURE_LAYERS)" << endl
916
 
                  << "\t$(ENFUSE) $(ENBLEND_LDR_COMP) $(ENFUSE_OPTS) -o $(LDR_EXPOSURE_LAYERS_FUSED_SHELL) $(LDR_EXPOSURE_LAYERS_SHELL) " << endl
917
 
                  << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_EXPOSURE_LAYERS_FUSED_SHELL)" << endl << endl;
918
 
 
919
 
                // rules for hdr blending
920
 
                o << "$(HDR_BLENDED) : $(HDR_STACKS)" << endl;
921
 
                o << "\t$(ENBLEND) $(ENBLEND_HDR_COMP) $(ENBLEND_OPTS) -o $(HDR_BLENDED_SHELL) $(HDR_STACKS_SHELL) " << endl << endl;
922
 
 
923
 
                // rules for multilayer output
924
 
 
925
 
                o << "$(LDR_REMAPPED_PREFIX)_multilayer.tif : $(LDR_LAYERS)" << endl;
926
 
                o << "\ttiffcp $(LDR_LAYERS_SHELL) $(LDR_REMAPPED_PREFIX_SHELL)_multilayer.tif" << endl << endl;
927
 
 
928
 
                o << "$(LDR_REMAPPED_PREFIX)_fused_multilayer.tif : $(LDR_STACKS) $(LDR_EXPOSURE_LAYERS)" << endl;
929
 
                o << "\ttiffcp $(LDR_STACKS_SHELL) $(LDR_EXPOSURE_LAYERS_SHELL) $(LDR_REMAPPED_PREFIX_SHELL)_fused_multilayer.tif" << endl << endl;
930
 
 
931
 
                o << "$(LDR_REMAPPED_PREFIX)_multilayer.psd : $(LDR_LAYERS)" << endl;
932
 
                o << "\tPTtiff2psd -o $(LDR_REMAPPED_PREFIX_SHELL)_multilayer.psd $(LDR_LAYERS_SHELL)" << endl << endl;
933
 
 
934
 
                o << "$(LDR_REMAPPED_PREFIX)_fused_multilayer.psd : $(LDR_STACKS) $(LDR_EXPOSURE_LAYERS)" << endl;
935
 
                o << "\tPTtiff2psd -o $(LDR_REMAPPED_PREFIX_SHELL)_fused_multilayer.psd $(LDR_STACKS_SHELL) $(LDR_EXPOSURE_LAYERS_SHELL)" << endl << endl;
936
 
 
937
 
                break;
938
 
            case PanoramaOptions::NO_BLEND:
939
 
                o << "$(LDR_BLENDED) : $(LDR_LAYERS)" << endl
940
 
                  << "\t-$(RM) $(LDR_BLENDED_SHELL)" << endl
941
 
                  << "\t$(PTROLLER) -o $(LDR_BLENDED_SHELL) $(LDR_LAYERS_SHELL) " << endl
942
 
                  << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_BLENDED_SHELL)" << endl << endl;
943
 
 
944
 
                // for LDR exposure blend planes
945
 
                for (unsigned i=0; i < similarExposures.size(); i++) {
946
 
                    o << "$(LDR_EXPOSURE_LAYER_" << i <<") : $(LDR_EXPOSURE_LAYER_" << i << "_INPUT)" << endl
947
 
                      << "\t-$(RM) $(LDR_EXPOSURE_LAYER_" << i <<"_SHELL)" << endl
948
 
                      << "\t$(PTROLLER) -o $(LDR_EXPOSURE_LAYER_" << i <<"_SHELL) $(LDR_EXPOSURE_LAYER_" << i << "_INPUT_SHELL)" << endl
949
 
                      << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_EXPOSURE_LAYER_" << i <<"_SHELL)" << endl << endl;
950
 
                }
951
 
 
952
 
                o << "$(LDR_STACKED_BLENDED) : $(LDR_STACKS)" << endl
953
 
                  << "\t-$(RM) $(LDR_STACKED_BLENDED_SHELL)" << endl
954
 
                  << "\t$(PTROLLER) -o $(LDR_STACKED_BLENDED_SHELL) $(LDR_STACKS_SHELL)" << endl
955
 
                  << "\t- $(EXIFTOOL) -overwrite_original_in_place -TagsFromFile $(INPUT_IMAGE_1_SHELL) $(EXIFTOOL_COPY_ARGS) $(LDR_STACKED_BLENDED_SHELL)" << endl << endl;
956
 
 
957
 
                // rules for non-blended HDR panoramas
958
 
                o << "$(HDR_BLENDED) : $(HDR_LAYERS)" << endl;
959
 
                o << "\t$(HDRMERGE) $(HDRMERGE_OPTS) -o $(HDR_BLENDED_SHELL) $(HDR_LAYERS_SHELL)"   << endl << endl;
960
 
 
961
 
                break;
962
 
            case PanoramaOptions::PTBLENDER_BLEND:
963
 
                // TODO: output PTBlender + PTmasker + PTroller rules
964
 
                break;
965
 
            case PanoramaOptions::SMARTBLEND_BLEND:
966
 
                // TODO: build smartblend command line from given images. (requires additional program)
967
 
                break;
968
 
            default:
969
 
                // TODO:
970
 
                break;
971
 
        }
972
 
    }
973
 
 
974
 
#ifdef UNIX_LIKE
975
 
    // reset locale
976
 
    setlocale(LC_NUMERIC,old_locale);
977
 
    free(old_locale);
978
 
#endif
979
 
 
980
 
}
981
 
 
982
 
} //namespace