Hugin trunk 0.1
Loading...
Searching...
No Matches
fulla.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
27#include <hugin_config.h>
28#include <fstream>
29#include <sstream>
30
31#include <vigra/error.hxx>
32#include <vigra/impex.hxx>
33#include <vigra/codec.hxx>
35#include <getopt.h>
36
38#include <nona/SpaceTransform.h>
40
41#include <hugin_basic.h>
42#include <lensdb/LensDB.h>
43
44#include <tiffio.h>
46
47template <class SrcImgType, class AlphaImgType, class FlatImgType, class DestImgType>
50 const FlatImgType& srcFlat,
52 vigra_ext::Interpolator interpolator,
53 double maxValue,
56 bool doCrop,
58
59template <class PIXELTYPE>
60void correctRGB(HuginBase::SrcPanoImage& src, vigra::ImageImportInfo& info, const char* outfile,
61 bool crop, const std::string& compression, AppBase::ProgressDisplay* progress);
62
63static void usage(const char* name)
64{
65 std::cout << name << ": correct lens distortion, vignetting and chromatic abberation" << std::endl
66 << "fulla version " << hugin_utils::GetHuginVersion() << endl
67 << std::endl
68 << "Usage: " << name << " [options] inputfile(s) " << std::endl
69 << " option are: " << std::endl
70 << " --green=db|a:b:c:d Correct radial distortion for all channels" << std::endl
71 << " Specify 'db' for database lookup or" << std::endl
72 << " the 4 coefficients a:b:c:d" << std::endl
73 << " --blue=db|a:b:c:d Correct radial distortion for blue channel," << std::endl
74 << " this is applied on top of the --green" << std::endl
75 << " distortion coefficients, use for TCA corr" << std::endl
76 << " Specify 'db' for database lookup or" << std::endl
77 << " the 4 coefficients a:b:c:d" << std::endl
78 << " --red=db|a:b:c:d Correct radial distortion for red channel," << std::endl
79 << " this is applied on top of the --green" << std::endl
80 << " distortion coefficients, use for TCA corr" << std::endl
81 << " Specify 'db' for database lookup or" << std::endl
82 << " the 4 coefficients a:b:c:d" << std::endl
83 << " --camera-maker=Maker Camera manufacturer, for database query" << std::endl
84 << " --camera-model=Cam Camera name, for database query" << std::endl
85 << " --lensname=Lens Lens name, for database query" << std::endl
86 << " Specify --camera-maker and --camera-model" << std::endl
87 << " for fixed lens cameras or --lensname" << std::endl
88 << " for interchangeable lenses." << std::endl
89 << " --focallength=50 Specify focal length in mm, for database query" << std::endl
90 << " --aperture=3.5 Specify aperture for vignetting data database query" << std::endl
91 << " --dont-rescale Do not rescale the image to avoid black borders." << std::endl
92 << std::endl
93 << " --flatfield=filename Vignetting correction by flatfield division" << std::endl
94 << " I = I / c, c = flatfield / mean(flatfield)" << std::endl
95 << " --vignetting=db|a:b:c:d Correct vignetting (by division)" << std::endl
96 << " Specify db for database look up or the " << std::endl
97 << " the 4 coefficients a:b:c:d" << std::endl
98 << " I = I / ( a + b*r^2 + c*r^4 + d*r^6)" << std::endl
99 << " --linear Do vignetting correction in linear color space" << std::endl
100 << " --gamma=value Gamma of input data. used for gamma correction" << std::endl
101 << " before and after flatfield correction" << std::endl
102 << " --help Display help (this text)" << std::endl
103 << " --output=name Set output filename. If more than one image is given," << std::endl
104 << " the name will be uses as suffix" << std::endl
105 << " (default suffix: _corr)" << std::endl
106 << " --compression=value Compression of the output files" << std::endl
107 << " For jpeg output: 0-100" << std::endl
108 << " For tiff output: PACKBITS, DEFLATE, LZW" << std::endl
109 << " --offset=X:Y Horizontal and vertical shift" << std::endl
110 << " --verbose Verbose" << std::endl;
111}
112
113
114int main(int argc, char* argv[])
115{
116 // parse arguments
117 const char* optstring = "e:g:b:r:m:n:l:d:sf:c:i:t:ho:x:va:";
118 int o;
119 enum
120 {
121 LINEAR_RESPONSE = 1000
122 };
123 static struct option longOptions[] =
124 {
125 { "linear", no_argument, NULL, LINEAR_RESPONSE },
126 { "green", required_argument, NULL, 'g' },
127 { "blue", required_argument, NULL, 'b' },
128 { "red", required_argument, NULL, 'r' },
129 { "lensname", required_argument, NULL, 'l' },
130 { "camera-maker", required_argument, NULL, 'm' },
131 { "camera-model", required_argument, NULL, 'n' },
132 { "aperture", required_argument, NULL, 'a' },
133 { "focallength", required_argument, NULL, 'd' },
134 { "flatfield", required_argument, NULL, 'f' },
135 { "dont-rescale", no_argument, NULL, 's' },
136 { "vignetting", required_argument, NULL, 'c' },
137 { "gamma", required_argument, NULL, 'i' },
138 { "threads", required_argument, NULL, 't' },
139 { "output", required_argument, NULL, 'o' },
140 { "compression", required_argument, NULL, 'e' },
141 { "offset", required_argument, NULL, 'x' },
142 { "verbose", no_argument, NULL, 'v' },
143 { "help", no_argument, NULL, 'h' },
144 0
145 };
146
147 std::vector<double> vec4(4);
148 bool doFlatfield = false;
149 bool doVigRadial = false;
150 bool doCropBorders = true;
151 unsigned verbose = 0;
152
153 std::string batchPostfix("_corr");
154 std::string outputFile;
155 std::string compression;
156 bool doLookupDistortion = false;
157 bool doLookupTCA = false;
158 bool doLookupVignetting = false;
159 std::string cameraMaker;
160 std::string cameraName;
161 std::string lensName;
162 float focalLength=0;
163 float aperture = 0;
164 double gamma = 1.0;
165 double shiftX = 0;
166 double shiftY = 0;
167 std::string argument;
168
170 while ((o = getopt_long(argc, argv, optstring, longOptions, nullptr)) != -1)
171 switch (o)
172 {
173 case 'e':
174 compression = optarg;
175 break;
176 case 'r':
179 if (argument == "db")
180 {
181 doLookupTCA = true;
182 }
183 else
184 {
185 if (sscanf(optarg, "%lf:%lf:%lf:%lf", &vec4[0], &vec4[1], &vec4[2], &vec4[3]) != 4)
186 {
187 std::cerr << hugin_utils::stripPath(argv[0]) << ": invalid -r argument" << std::endl;
188 return 1;
189 }
190 srcImg.setRadialDistortionRed(vec4);
191 };
192 break;
193 case 'g':
196 if (argument == "db")
197 {
198 doLookupDistortion = true;
199 }
200 else
201 {
202 if (sscanf(optarg, "%lf:%lf:%lf:%lf", &vec4[0], &vec4[1], &vec4[2], &vec4[3]) != 4)
203 {
204 std::cerr << hugin_utils::stripPath(argv[0]) << ": invalid -g argument" << std::endl;
205 return 1;
206 }
207 srcImg.setRadialDistortion(vec4);
208 };
209 break;
210 case 'b':
213 if (argument == "db")
214 {
215 doLookupTCA = true;
216 }
217 else
218 {
219 if (sscanf(optarg, "%lf:%lf:%lf:%lf", &vec4[0], &vec4[1], &vec4[2], &vec4[3]) != 4)
220 {
221 std::cerr << hugin_utils::stripPath(argv[0]) << ": invalid -b argument" << std::endl;
222 return 1;
223 }
224 srcImg.setRadialDistortionBlue(vec4);
225 };
226 break;
227 case 's':
228 doCropBorders = false;
229 break;
230 case 'f':
231 srcImg.setFlatfieldFilename(optarg);
232 doFlatfield = true;
233 break;
234 case 'i':
235 gamma = atof(optarg);
236 srcImg.setGamma(gamma);
237 break;
238 case 'm':
240 break;
241 case 'n':
243 break;
244 case 'l':
246 break;
247 case 'd':
249 break;
250 case 'a':
251 aperture = atof(optarg);
252 break;
253 case 'c':
256 if (argument == "db")
257 {
258 doLookupVignetting = true;
259 }
260 else
261 {
262 if (sscanf(optarg, "%lf:%lf:%lf:%lf", &vec4[0], &vec4[1], &vec4[2], &vec4[3]) != 4)
263 {
264 std::cerr << hugin_utils::stripPath(argv[0]) << ": invalid -c argument" << std::endl;
265 return 1;
266 }
267 srcImg.setRadialVigCorrCoeff(vec4);
268 };
269 doVigRadial = true;
270 break;
271 case 'h':
273 return 0;
274 case 't':
275 std::cout << "WARNING: Switch --threads is deprecated. Set environment variable OMP_NUM_THREADS instead" << std::endl;
276 break;
277 case 'o':
279 break;
280 case 'x':
281 if (sscanf(optarg, "%lf:%lf", &shiftX, &shiftY) != 2)
282 {
283 std::cerr << hugin_utils::stripPath(argv[0]) << ": invalid -x argument" << std::endl;
284 return 1;
285 }
286 srcImg.setRadialDistortionCenterShift(hugin_utils::FDiff2D(shiftX, shiftY));
287 break;
288 case 'v':
289 verbose++;
290 break;
291 case LINEAR_RESPONSE:
293 break;
294 case ':':
295 case '?':
296 // missing argument or invalid switch
297 return 1;
298 break;
299 default:
300 // this should not happen
301 abort();
302 }
303
305 {
306 std::cerr << hugin_utils::stripPath(argv[0]) << ": cannot use -f and -c at the same time" << std::endl;
307 return 1;
308 }
309
311
312 if (doVigRadial)
313 {
315 }
316 if (doFlatfield)
317 {
319 }
320
322 srcImg.setVigCorrMode(vm);
323
324 unsigned nFiles = argc - optind;
325 if (nFiles == 0)
326 {
327 std::cerr << hugin_utils::stripPath(argv[0]) << ": No input file(s) specified" << std::endl;
328 return 1;
329 }
330
331 // get input images.
332 std::vector<std::string> inFiles;
333 std::vector<std::string> outFiles;
334 if (nFiles == 1)
335 {
336 if (outputFile.length() !=0)
337 {
338 inFiles.push_back(std::string(argv[optind]));
339 outFiles.push_back(outputFile);
340 }
341 else
342 {
343 std::string name(argv[optind]);
344 inFiles.push_back(name);
345 std::string basen = hugin_utils::stripExtension(name);
346 outFiles.push_back(basen.append(batchPostfix.append(".").append(hugin_utils::getExtension(name))));
347 }
348 }
349 else
350 {
351 // multiple files
352 bool withExtension = false;
353 if (outputFile.length() != 0)
354 {
356 withExtension = (batchPostfix.find('.') != std::string::npos);
357 }
358 for (int i = optind; i < argc; i++)
359 {
360 std::string name(argv[i]);
361 inFiles.push_back(name);
362 if (withExtension)
363 {
365 }
366 else
367 {
369 };
370 }
371 }
372
374 {
375 if (lensName.empty())
376 {
377 if (!cameraMaker.empty() && !cameraName.empty())
378 {
380 lensName.append("|");
381 lensName.append(cameraName);
382 };
383 };
384 };
385
386 // suppress tiff warnings
388
390 if (verbose > 0)
391 {
392 pdisp = new AppBase::StreamProgressDisplay(std::cout);
393 }
394 else
395 {
397 };
398
400 try
401 {
402 std::vector<std::string>::iterator outIt = outFiles.begin();
403 for (std::vector<std::string>::iterator inIt = inFiles.begin(); inIt != inFiles.end() ; ++inIt, ++outIt)
404 {
405 if (verbose > 0)
406 {
407 std::cerr << "Correcting " << *inIt << " -> " << *outIt << endl;
408 }
410 currentImg.setFilename(*inIt);
411
412 // load the input image
413 vigra::ImageImportInfo info(inIt->c_str());
414 const char* pixelType = info.getPixelType();
415 int bands = info.numBands();
416 int extraBands = info.numExtraBands();
417
418 // do database lookup
420 {
421 currentImg.readEXIF();
422 if (lensName.empty())
423 {
424 if (currentImg.getDBLensName().empty())
425 {
426 std::cerr << "Not enough data for database lookup" << std::endl
427 << "Specify lensname (--lensname) or camera maker and model " << std::endl
428 << "(--camera-maker and --camera-model) as parameter." << std::endl;
429 continue;
430 };
431 }
432 else
433 {
434 currentImg.setExifLens(lensName);
435 }
436 if (fabs(focalLength) < 0.1)
437 {
438 if (fabs(currentImg.getExifFocalLength()) < 0.1)
439 {
440 std::cerr << "Could not determine focal length." << std::endl
441 << "Specify focal length (--focallength) as parameter." << std::endl;
442 continue;
443 };
444 }
445 else
446 {
447 currentImg.setExifFocalLength(focalLength);
448 };
449 if (verbose > 1)
450 {
451 std::cout << "Lookup in database for " << currentImg.getDBLensName() << " @ " << currentImg.getExifFocalLength() << " mm" << std::endl;
452 };
454 {
455 if (!currentImg.readDistortionFromDB())
456 {
457 std::cerr << "No suitable distortion data found in database." << std::endl
458 << "Skipping image." << std::endl;
459 continue;
460 };
461 if (verbose > 1)
462 {
463 std::vector<double> dist = currentImg.getRadialDistortion();
464 std::cout << "Read distortion data: " << dist[0] << ", " << dist[1] << ", " << dist[2] << ", " << dist[3] << std::endl;
465 };
466 };
468 {
469 if (fabs(aperture) < 0.1)
470 {
471 if (fabs(currentImg.getExifAperture()) < 0.1)
472 {
473 std::cerr << "Could not determine aperture." << std::endl
474 << "Specify aperture (--aperture) as parameter." << std::endl;
475 continue;
476 };
477 }
478 else
479 {
480 currentImg.setExifAperture(aperture);
481 };
482 if (!currentImg.readVignettingFromDB())
483 {
484 std::cerr << "No suitable vignetting data found in database." << std::endl
485 << "Skipping image." << std::endl;
486 continue;
487 };
488 if (verbose > 1)
489 {
490 std::vector<double> vig = currentImg.getRadialVigCorrCoeff();
491 std::cout << "Read vigneting data: " << vig[1] << ", " << vig[2] << ", " << vig[3] << std::endl;
492 };
493 };
494
495 if (doLookupTCA)
496 {
497 std::vector<double> tcaRed, tcaBlue;
498 if (lensDB.GetTCA(currentImg.getDBLensName(), currentImg.getExifFocalLength(), tcaRed, tcaBlue))
499 {
500 currentImg.setRadialDistortionRed(tcaRed);
501 currentImg.setRadialDistortionBlue(tcaBlue);
502 }
503 else
504 {
505 std::cerr << "No suitable tca data found in database." << std::endl
506 << "Skipping image." << std::endl;
507 continue;
508 };
509 if (verbose>1)
510 {
511 std::cout << "Read tca data red: " << tcaRed[0] << ", " << tcaRed[1] << ", " << tcaRed[2] << ", " << tcaRed[3] << std::endl;
512 std::cout << "Read tca data blue: " << tcaBlue[0] << ", " << tcaBlue[1] << ", " << tcaBlue[2] << ", " << tcaBlue[3] << std::endl;
513 };
514 };
515 };
516 currentImg.setSize(info.size());
517 // stitch the pano with a suitable image type
518 if (bands == 3 || (bands == 4 && extraBands == 1))
519 {
520 // TODO: add more cases
521 if (strcmp(pixelType, "UINT8") == 0)
522 {
524 }
525 else if (strcmp(pixelType, "UINT16") == 0)
526 {
528 }
529 else if (strcmp(pixelType, "INT16") == 0)
530 {
532 }
533 else if (strcmp(pixelType, "UINT32") == 0)
534 {
536 }
537 else if (strcmp(pixelType, "FLOAT") == 0)
538 {
539 correctRGB<vigra::RGBValue<float> >(currentImg, info, outIt->c_str(), doCropBorders, compression, pdisp);
540 }
541 else if (strcmp(pixelType, "DOUBLE") == 0)
542 {
544 }
545 }
546 else
547 {
548 DEBUG_ERROR("unsupported depth, only 3 channel images are supported");
549 delete pdisp;
551 throw std::runtime_error("unsupported depth, only 3 channels images are supported");
552 return 1;
553 }
554 }
555 }
556 catch (std::exception& e)
557 {
558 std::cerr << "caught exception: " << e.what() << std::endl;
559 delete pdisp;
561 return 1;
562 }
563 delete pdisp;
565 return 0;
566}
567
569{
570public:
571 bool transformImgCoord(double & x_dest, double & y_dest, double x_src, double y_src) const
572 {
573 x_dest = x_src;
574 y_dest = y_src;
575 return true;
576 };
577};
578
579
585template <class SrcImgType, class AlphaImgType, class FlatImgType, class DestImgType>
587 const AlphaImgType& srcAlpha,
590 vigra_ext::Interpolator interpolator,
591 double maxValue,
594 bool doCrop,
596{
597 typedef typename SrcImgType::value_type SrcPixelType;
598 typedef typename DestImgType::value_type DestPixelType;
599
600 // prepare some information required by multiple types of vignetting correction
601 progress->setMessage("correcting image");
602
603 vigra::Diff2D shiftXY(- hugin_utils::roundi(src.getRadialDistortionCenterShift().x),
604 - hugin_utils::roundi(src.getRadialDistortionCenterShift().y));
605
606 if ((src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_FLATFIELD)
607 || (src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_RADIAL))
608 {
610 if (src.getResponseType() == HuginBase::BaseSrcPanoImage::RESPONSE_EMOR)
611 {
612 std::vector<double> outLut;
613 vigra_ext::EMoR::createEMoRLUT(src.getEMoRParams(), outLut);
615 invResp.setOutput(1.0 / pow(2.0, src.getExposureValue()), outLut, maxValue);
616 if (maxValue != 1.0)
617 {
618 // transform to range 0..1 for vignetting correction
619 vigra::transformImage(srcImageRange(srcImg), destImage(srcImg), vigra::functor::Arg1()/vigra::functor::Param(maxValue));
620 };
621 };
622
623 invResp.enforceMonotonicity();
624
625 NullTransform transform;
626 // dummy alpha channel
627 vigra::BImage alpha(destImg.size());
628
629 if (src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_FLATFIELD)
630 {
631 invResp.setFlatfield(&srcFlat);
632 // transform flatfield to linear space if needed
633 if (src.getResponseType() == HuginBase::BaseSrcPanoImage::RESPONSE_EMOR)
634 {
638 invRespFlat.setHDROutput(true, 1.0);
639 if (maxValue != 1.0)
640 {
641 vigra::transformImage(vigra::srcImageRange(srcFlat), vigra::destImage(srcFlat), vigra::functor::Arg1() / vigra::functor::Param(maxValue));
642 };
643 vigra_ext::transformImage(vigra::srcImageRange(srcFlat), vigra::destImageRange(srcFlat), vigra::destImage(alpha), vigra::Diff2D(0, 0), transform, invRespFlat, false, vigra_ext::INTERP_SPLINE_16, progress);
644 };
645 // smooth flatfield
646 vigra::gaussianSmoothing(vigra::srcImageRange(srcFlat), vigra::destImage(srcFlat), 20);
647 // calculate mean of flatfield and transform flat to vignetting correction values
648 vigra::FindAverage<typename FlatImgType::value_type> meanFlat;
649 vigra::inspectImage(vigra::srcImageRange(srcFlat), meanFlat);
650 vigra::transformImage(vigra::srcImageRange(srcFlat), vigra::destImage(srcFlat), vigra::functor::Arg1() / vigra::functor::Param(meanFlat.average()));
651 }
652 vigra_ext::transformImage(srcImageRange(srcImg), destImageRange(srcImg), destImage(alpha), vigra::Diff2D(0, 0), transform, invResp, false, vigra_ext::INTERP_SPLINE_16, progress);
653
654 }
655
656 // radial distortion correction
657 if (doCrop)
658 {
660 DEBUG_DEBUG("Black border correction scale factor: " << scaleFactor);
661 double sf=scaleFactor;
662 std::vector<double> radGreen = src.getRadialDistortion();
663 for (int i=0; i < 4; i++)
664 {
665 radGreen[3-i] *=sf;
666 sf *=scaleFactor;
667 }
668 src.setRadialDistortion(radGreen);
669 }
670
672
673 if (src.getCorrectTCA())
674 {
675 /*
676 DEBUG_DEBUG("Final distortion correction parameters:" << endl
677 << "r: " << radRed[0] << " " << radRed[1] << " " << radRed[2] << " " << radRed[3] << endl
678 << "g: " << radGreen[0] << " " << radGreen[1] << " " << radGreen[2] << " " << radGreen[3] << endl
679 << "b: " << radBlue[0] << " " << radBlue[1] << " " << radBlue[2] << " " << radBlue[3] << endl);
680 */
681 // remap individual channels
685 if (transfr.isIdentity())
686 {
687 vigra::copyImage(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::RedAccessor<SrcPixelType>()),
688 destIter(destImg.upperLeft(), vigra::RedAccessor<DestPixelType>()));
689 vigra::copyImage(srcImageRange(srcAlpha), destImage(redAlpha));
690 }
691 else
692 {
693 vigra_ext::transformImageAlpha(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::RedAccessor<SrcPixelType>()),
694 srcImage(srcAlpha),
695 destIterRange(destImg.upperLeft(), destImg.lowerRight(), vigra::RedAccessor<DestPixelType>()),
696 destImage(redAlpha),
697 shiftXY,
698 transfr,
699 ptf,
700 false,
702 progress);
703 }
704
708 if (transfg.isIdentity())
709 {
710 vigra::copyImage(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::GreenAccessor<SrcPixelType>()),
711 destIter(destImg.upperLeft(), vigra::GreenAccessor<DestPixelType>()));
712 vigra::copyImage(srcImageRange(srcAlpha), destImage(greenAlpha));
713 }
714 else
715 {
716 transformImageAlpha(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::GreenAccessor<SrcPixelType>()),
717 srcImage(srcAlpha),
718 destIterRange(destImg.upperLeft(), destImg.lowerRight(), vigra::GreenAccessor<DestPixelType>()),
719 destImage(greenAlpha),
720 shiftXY,
721 transfg,
722 ptf,
723 false,
725 progress);
726 }
727
731 if (transfb.isIdentity())
732 {
733 vigra::copyImage(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::BlueAccessor<SrcPixelType>()),
734 destIter(destImg.upperLeft(), vigra::BlueAccessor<DestPixelType>()));
735 vigra::copyImage(srcImageRange(srcAlpha), destImage(blueAlpha));
736
737 }
738 else
739 {
740 transformImageAlpha(srcIterRange(srcImg.upperLeft(), srcImg.lowerRight(), vigra::BlueAccessor<SrcPixelType>()),
741 srcImage(srcAlpha),
742 destIterRange(destImg.upperLeft(), destImg.lowerRight(), vigra::BlueAccessor<DestPixelType>()),
743 destImage(blueAlpha),
744 shiftXY,
745 transfb,
746 ptf,
747 false,
749 progress);
750 }
751 vigra::combineThreeImages(srcImageRange(redAlpha), srcImage(greenAlpha), srcImage(blueAlpha), destImage(destAlpha),
752 vigra::functor::Arg1() & vigra::functor::Arg2() & vigra::functor::Arg3());
753 }
754 else
755 {
756 // remap with the same coefficient.
759 std::vector <double> radCoeff = src.getRadialDistortion();
760 if (transf.isIdentity() ||
761 (radCoeff[0] == 0.0 && radCoeff[1] == 0.0 && radCoeff[2] == 0.0 && radCoeff[3] == 1.0))
762 {
763 vigra::copyImage(srcImageRange(srcImg), destImage(destImg));
764 vigra::copyImage(srcImageRange(srcAlpha), destImage(destAlpha));
765 }
766 else
767 {
769 transformImageAlpha(srcImageRange(srcImg),
770 srcImage(srcAlpha),
771 destImageRange(destImg),
772 destImage(destAlpha),
773 shiftXY,
774 transf,
775 ptfRGB,
776 false,
778 progress);
779 }
780 }
781}
782
783
784//void correctRGB(SrcImageInfo & src, ImageImportInfo & info, const char * outfile)
785template <class PIXELTYPE>
786void correctRGB(HuginBase::SrcPanoImage& src, vigra::ImageImportInfo& info, const char* outfile,
787 bool crop, const std::string& compression, AppBase::ProgressDisplay* progress)
788{
789 vigra::BasicImage<vigra::RGBValue<double> > srcImg(info.size());
790 vigra::BasicImage<PIXELTYPE> output(info.size());
791 vigra::BImage alpha(info.size(), 255);
792 vigra::BImage outputAlpha(output.size());
793 if (info.numBands() == 3)
794 {
795 vigra::importImage(info, destImage(srcImg));
796 }
797 else
798 {
799 importImageAlpha(info, destImage(srcImg), destImage(alpha));
800 };
801 vigra::FImage flatfield;
802 if (src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_FLATFIELD)
803 {
804 vigra::ImageImportInfo finfo(src.getFlatfieldFilename().c_str());
805 flatfield.resize(finfo.size());
806 vigra::importImage(finfo, destImage(flatfield));
807 }
809 output, outputAlpha, crop, progress);
810 vigra::ImageExportInfo outInfo(outfile);
811 outInfo.setICCProfile(info.getICCProfile());
812 outInfo.setPixelType(info.getPixelType());
813 if (!compression.empty())
814 {
815 outInfo.setCompression(compression.c_str());
816 }
817 const std::string filetype(vigra::getEncoder(outInfo.getFileName())->getFileType());
818 if (vigra::isBandNumberSupported(filetype, 4))
819 {
820 // image format supports alpha channel
821 std::cout << "Saving " << outInfo.getFileName() << std::endl;
822 vigra::exportImageAlpha(srcImageRange(output), srcImage(outputAlpha), outInfo);
823 }
824 else
825 {
826 // image format does not support an alpha channel, disregard alpha channel
827 std::cout << "Saving " << outInfo.getFileName() << " without alpha channel" << std::endl
828 << "because the fileformat " << filetype << " does not support" << std::endl
829 << "an alpha channel." << std::endl;
830 exportImage(srcImageRange(output), outInfo);
831 };
832}
Contains functions to transform whole images.
class to access Hugins camera and lens database
static void usage()
Definition Main.cpp:32
implementation of Space Transformation
Dummy progress display, without output.
a progress display to print progress reports to a stream
VignettingCorrMode
vignetting correction mode (bitflags, no real enum)
@ VIGCORR_DIV
correct by division.
@ VIGCORR_FLATFIELD
flatfield correction
@ VIGCORR_NONE
no vignetting correction
@ VIGCORR_RADIAL
radial vignetting correction
@ RESPONSE_LINEAR
linear response
@ RESPONSE_EMOR
empirical model of response
main database class
Definition LensDB.h:45
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program
Definition LensDB.cpp:2010
static LensDB & GetSingleton()
returns the static LensDB instance
Definition LensDB.cpp:2001
void InitRadialCorrect(const vigra::Size2D &sz, const std::vector< double > &radDist, const hugin_utils::FDiff2D &centerShift)
transformation for radial correction only
radiometric transformation, includes exposure, vignetting and white balance
All variables of a source image.
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
Definition fulla.cpp:571
int main(int argc, char *argv[])
Definition fulla.cpp:114
void correctImage(SrcImgType &srcImg, const AlphaImgType &srcAlpha, const FlatImgType &srcFlat, HuginBase::SrcPanoImage src, vigra_ext::Interpolator interpolator, double maxValue, DestImgType &destImg, AlphaImgType &destAlpha, bool doCrop, AppBase::ProgressDisplay *progress)
void correctRGB(HuginBase::SrcPanoImage &src, vigra::ImageImportInfo &info, const char *outfile, bool crop, const std::string &compression, AppBase::ProgressDisplay *progress)
Definition fulla.cpp:786
class AlphaIterator class AlphaAccessor inline void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
#define DEBUG_ERROR(msg)
Definition utils.h:76
#define DEBUG_DEBUG(msg)
Definition utils.h:68
double estScaleFactorForFullFrame(const SrcPanoImage &src)
Calculate effective scaling factor for a given source image.
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition utils.cpp:130
std::string getExtension(const std::string &basename2)
Get extension of a filename.
Definition utils.cpp:99
int roundi(T x)
Definition hugin_math.h:73
std::string tolower(const std::string &s)
convert a string to lowercase
Definition stl_utils.h:49
std::string GetHuginVersion()
return a string with version numbers
Definition utils.cpp:907
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition utils.cpp:160
void createEMoRLUT(const std::vector< float > &params, VECTOR &lut)
Definition emor.h:44
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
void transformImageAlpha(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, std::pair< SrcAlphaIterator, SrcAlphaAccessor > srcAlpha, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform image, and respect a possible alpha channel.
double getMaxValForPixelType(const std::string &v)
Definition utils.h:89
Interpolator
enum with all interpolation methods
void enforceMonotonicity(LUT &lut)
enforce monotonicity of an array (mostly used for lookup tables)
Definition lut.h:87
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41