32 #include <vigra/imageinfo.hxx>
33 #include <vigra/codec.hxx>
34 #include <vigra/stdimage.hxx>
36 #include <vigra/tiff.hxx>
41 void SetCompression(vigra::ImageExportInfo& output,
const std::string& compression)
44 if (!compression.empty())
46 if (ext ==
"JPEG" || ext ==
"JPG")
48 output.setCompression(std::string(
"JPEG QUALITY=" + compression).c_str());
52 output.setCompression(compression.c_str());
58 template <
class ImageType,
class MaskType>
59 bool SaveImage(
ImageType& image, MaskType& mask, vigra::ImageExportInfo& exportImageInfo, std::string filetype, std::string pixelType)
61 typedef typename vigra::NumericTraits<typename ImageType::value_type>::isScalar scalar;
62 const int numberChannels = scalar().asBool ? 1 : 3;
63 exportImageInfo.setPixelType(pixelType.c_str());
64 if (vigra::isBandNumberSupported(filetype, numberChannels +1))
70 catch (std::exception& e)
72 std::cerr <<
"ERROR: Could not save " << exportImageInfo.getFileName() << std::endl
73 <<
"Cause: " << e.what() << std::endl;
80 if (vigra::isBandNumberSupported(filetype, numberChannels))
82 std::cout <<
"Warning: Filetype " << filetype <<
" does not support alpha channels." << std::endl
83 <<
"Saving image without alpha channel." << std::endl;
88 catch (std::exception& e)
90 std::cerr <<
"ERROR: Could not save " << exportImageInfo.getFileName() << std::endl
91 <<
"Cause: " << e.what() << std::endl;
98 std::cerr <<
"ERROR: Output filetype " << filetype <<
" does not support " << numberChannels <<
" channels." << std::endl
99 <<
"Can't save image." << std::endl;
106 template <
class ImageType,
class MaskType>
109 VIGRA_UNIQUE_PTR<vigra::Encoder> encoder(vigra::encoder(output));
110 if (vigra::isPixelTypeSupported(encoder->getFileType(), inputPixelType))
112 return SaveImage(image, mask, output, encoder->getFileType(), inputPixelType);
116 if (vigra::isPixelTypeSupported(encoder->getFileType(),
"UINT8"))
119 output.setForcedRangeMapping(0, vigra::NumericTraits<
typename vigra::NumericTraits<typename ImageType::PixelType>::ValueType>::
max(), 0, 255);
120 return SaveImage(image, mask, output, encoder->getFileType(),
"UINT8");
124 std::cerr <<
"ERROR: Output file type " << encoder->getFileType() <<
" does not support" << std::endl
125 <<
"requested pixeltype " << inputPixelType <<
"." << std::endl
126 <<
"Save output in other file format." << std::endl;
135 std::cout << name <<
": stack images" << std::endl
138 <<
"Usage: " << name <<
" [options] images" << std::endl
140 <<
" --output=FILE Set the filename for the output file." << std::endl
141 <<
" --compression=value Compression of the output files" << std::endl
142 <<
" For jpeg output: 0-100" << std::endl
143 <<
" For tiff output: PACKBITS, DEFLATE, LZW" << std::endl
144 <<
" --mode=STRING Select the mode for stacking" << std::endl
145 <<
" Possible names are described below." << std::endl
147 <<
" min|minimum|darkest Select the darkest pixel" << std::endl
148 <<
" max|maximum|brightest Select the brightest pixel" << std::endl
149 <<
" avg|average|mean Calculate the mean for each position" << std::endl
150 <<
" median Calculate the median for each position" << std::endl
151 <<
" winsor Calculate the Winsor trimmed mean" << std::endl
152 <<
" for each position. The parameter can be" << std::endl
153 <<
" set with --winsor-trim=NUMBER (default: 0.2)" << std::endl
154 <<
" sigma Calculate the sigma clipped mean for" << std::endl
155 <<
" each position. Fine-tune with" << std::endl
156 <<
" --max-sigma=NUMBER (default: 2) and" << std::endl
157 <<
" --max-iterations=NUMBER (default: 5)" << std::endl
159 <<
" --mask-input Mask input images" << std::endl
160 <<
" Only pixel which differ more than" << std::endl
161 <<
" mask-sigma * standard deviation" << std::endl
162 <<
" are visible in output" << std::endl
163 <<
" available for modes median, winsor or sigma" << std::endl
164 <<
" --mask-suffix=STRING Suffix for the masked input images" << std::endl
165 <<
" (default: _mask)" << std::endl
166 <<
" --mask-sigma=NUMBER Sigma parameter for input images masking" << std::endl
167 <<
" (default: 2)" << std::endl
168 <<
" --multi-layer-output Output layered TIFF instead of single images" << std::endl
169 <<
" (has only effect with --mask-input)" << std::endl
170 <<
" --bigtiff Write output in BigTIFF format" << std::endl
171 <<
" (only with TIFF output)" << std::endl
172 <<
" -h, --help Shows this help" << std::endl
265 template<
class ValueType>
266 void getValue(
const int x, vigra::RGBValue<ValueType>& value, ValueType& mask)
270 mask = vigra::NumericTraits<ValueType>::zero();
276 mask = vigra::NumericTraits<ValueType>::zero();
282 const ValueType* band0=
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(0));
283 const ValueType* band1 =
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(1));
284 const ValueType* band2 =
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(2));
290 const ValueType* band3 =
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(3));
298 value = vigra::RGBValue<ValueType>(*band0, *band1, *band2);
302 mask = vigra::NumericTraits<ValueType>::zero();
307 template<
class ValueType>
308 void getValue(
const int x, ValueType& value, ValueType& mask)
312 mask = vigra::NumericTraits<ValueType>::zero();
318 mask = vigra::NumericTraits<ValueType>::zero();
324 const ValueType* band0 =
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(0));
328 const ValueType* band1 =
static_cast<const ValueType*
>(
m_decoder->currentScanlineOfBand(1));
340 mask = vigra::NumericTraits<ValueType>::zero();
356 template<
class ValueType>
357 void getMean(
const std::vector<ValueType>& values, ValueType& val)
360 typedef vigra::NumericTraits<ValueType> RealTraits;
361 typename RealTraits::RealPromote mean = RealTraits::zero();
362 for (
auto& x : values)
365 mean += (x - mean) / n;
367 val = RealTraits::fromRealPromote(mean);
370 template<
class ValueType>
371 void getMeanSigma(
const std::vector<ValueType>& values, ValueType& val,
typename vigra::NumericTraits<ValueType>::RealPromote&
sigma)
373 typedef vigra::NumericTraits<ValueType> RealTraits;
374 typedef typename RealTraits::RealPromote RealType;
376 RealType mean = RealTraits::zero();
377 RealType m2 = RealTraits::zero();
378 for (
auto& x : values)
381 const RealType delta = x - mean;
383 const RealType delta2 = x - mean;
386 val = RealTraits::fromRealPromote(mean);
389 sigma = sqrt(m2 / n);
393 sigma = vigra::NumericTraits<RealType>::zero();
397 template<
class ValueType>
403 void operator()(
const ValueType& val, vigra::VigraFalseType) {
if (val.luminance() <
m_min.luminance())
m_min = val; }
406 typedef typename vigra::NumericTraits<ValueType>::isScalar is_scalar;
415 template<
class ValueType>
421 void operator()(
const ValueType& val, vigra::VigraFalseType) {
if (val.luminance() >
m_max.luminance())
m_max = val;}
424 typedef typename vigra::NumericTraits<ValueType>::isScalar is_scalar;
433 template<
class ValueType>
443 typename vigra::NumericTraits<ValueType>::RealPromote
m_sum;
447 template<
class ValueType>
462 const int index =
m_values.size() / 2;
476 const int index =
m_values.size() / 2;
482 const std::string
getName()
const {
return "median"; };
485 void sort(vigra::VigraTrueType)
490 void sort(vigra::VigraFalseType)
493 [](
const ValueType & a,
const ValueType & b) {
return a.luminance() < b.luminance(); });
498 typedef typename vigra::NumericTraits<ValueType>::isScalar is_scalar;
505 template<
class ValueType>
513 for (
size_t i = 0; i < indexTrim; ++i)
517 for (
size_t i = this->
m_values.size() - indexTrim; i < this->
m_values.size(); ++i)
527 for (
size_t i = 0; i < indexTrim; ++i)
531 for (
size_t i = this->
m_values.size() - indexTrim; i < this->
m_values.size(); ++i)
537 const std::string
getName()
const {
return "Winsor clipped mean"; };
540 template<
class ValueType>
549 typedef typename vigra::NumericTraits<ValueType>::isScalar is_scalar;
554 size_t iteration = 0;
581 size_t iteration = 0;
584 double grayMean, graySigma;
607 const std::string
getName()
const {
return "sigma clipped mean"; };
614 bool CheckInput(
const std::vector<InputImage*>& images, vigra::Rect2D& outputROI, vigra::Size2D& canvasSize)
621 outputROI = images[0]->getROI();
622 canvasSize = images[0]->getCanvasSize();
623 for (
size_t i = 1; i < images.size(); ++i)
625 outputROI |= images[i]->getROI();
626 if (images[i]->getCanvasSize().width() > canvasSize.width())
628 canvasSize.setWidth(images[i]->getCanvasSize().width());
630 if (images[i]->getCanvasSize().height() > canvasSize.height())
632 canvasSize.setHeight(images[i]->getCanvasSize().height());
635 if (outputROI.area() == 0)
637 std::cerr <<
"ERROR: You can't stack non-overlapping images." << std::endl;
644 template <
class PixelType,
class Functor>
645 bool StackImages(std::vector<InputImage*>& images, Functor& stacker)
647 typedef typename vigra::NumericTraits<PixelType>::ValueType ChannelType;
648 vigra::Rect2D outputROI;
649 vigra::Size2D canvasSize;
650 if (!
CheckInput(images, outputROI, canvasSize))
655 vigra::ImageExportInfo exportImageInfo(
Parameters.outputFilename.c_str(),
Parameters.useBigTIFF ?
"w8" :
"w");
656 exportImageInfo.setXResolution(images[0]->getXResolution());
657 exportImageInfo.setYResolution(images[0]->getYResolution());
658 exportImageInfo.setPosition(outputROI.upperLeft());
659 exportImageInfo.setCanvasSize(canvasSize);
660 exportImageInfo.setICCProfile(images[0]->getICCProfile());
662 vigra::BasicImage<PixelType> output(outputROI.size());
663 vigra::BImage mask(output.size(),vigra::UInt8(0));
665 for (
size_t y = outputROI.top(); y < outputROI.bottom(); ++y)
668 #pragma omp parallel for
669 for (
int i = 0; i < images.size(); ++i)
671 images[i]->readLine(y);
674 #pragma omp parallel for schedule(static, 100)
675 for (
int x = outputROI.left(); x < outputROI.right(); ++x)
678 Functor privateStacker(stacker);
679 privateStacker.reset();
680 for (
size_t i = 0; i < images.size(); ++i)
683 ChannelType maskValue;
684 images[i]->getValue(x, value, maskValue);
687 privateStacker(value);
690 if (privateStacker.IsValid())
692 privateStacker.getResult(output(x - outputROI.left(), y - outputROI.top()));
693 mask(x-outputROI.left(), y-outputROI.top()) = 255;
697 std::cout <<
"Write result to " <<
Parameters.outputFilename << std::endl;
698 return SaveFinalImage(output, mask, images[0]->getPixelType(), exportImageInfo);
701 template <
class PixelType>
705 typedef typename vigra::NumericTraits<PixelType>::RealPromote
realPixelType;
710 vigra::UInt8
operator()(
const vigra::TinyVector<realPixelType, 2>& limits,
const PixelType& color,
const vigra::UInt8& mask, vigra::VigraFalseType)
const
712 if (mask > 0 && (color.red() < limits[0].red() || color.red()>limits[1].red() ||
713 color.green() < limits[0].green() || color.green() > limits[1].green() ||
714 color.blue() < limits[0].blue() || color.blue() > limits[1].blue()))
724 vigra::UInt8
operator()(
const vigra::TinyVector<realPixelType, 2>& limits,
const PixelType& gray,
const vigra::UInt8& mask, vigra::VigraTrueType)
const
726 if (mask > 0 && (gray < limits[0] || gray>limits[1]))
736 vigra::UInt8
operator()(
const vigra::TinyVector<realPixelType, 2>& limits,
const PixelType& pixel,
const vigra::UInt8& mask)
const
738 typedef typename vigra::NumericTraits<PixelType>::isScalar is_scalar;
739 return (*
this)(limits, pixel, mask, is_scalar());
744 template <
class PixelType,
class Functor>
747 typedef typename vigra::NumericTraits<PixelType>::ValueType ChannelType;
748 vigra::Rect2D outputROI;
749 vigra::Size2D canvasSize;
750 if (!
CheckInput(images, outputROI, canvasSize))
755 vigra::ImageExportInfo exportImageInfo(
Parameters.outputFilename.c_str(),
Parameters.useBigTIFF ?
"w8" :
"w");
756 exportImageInfo.setXResolution(images[0]->getXResolution());
757 exportImageInfo.setYResolution(images[0]->getYResolution());
758 exportImageInfo.setPosition(outputROI.upperLeft());
759 exportImageInfo.setCanvasSize(canvasSize);
760 exportImageInfo.setICCProfile(images[0]->getICCProfile());
763 vigra::TiffImage* tiffImage;
764 vigra::BasicImage<PixelType> output(outputROI.size());
765 vigra::BImage mask(output.size(), vigra::UInt8(0));
766 vigra::BasicImage<vigra::TinyVector<typename vigra::NumericTraits<PixelType>::RealPromote, 2>> limits(output.size());
768 for (
size_t y = outputROI.top(); y < outputROI.bottom(); ++y)
771 #pragma omp parallel for
772 for (
int i = 0; i < images.size(); ++i)
774 images[i]->readLine(y);
777 #pragma omp parallel for schedule(static, 100)
778 for (
int x = outputROI.left(); x < outputROI.right(); ++x)
781 Functor privateStacker(stacker);
782 privateStacker.reset();
783 for (
size_t i = 0; i < images.size(); ++i)
786 ChannelType maskValue;
787 images[i]->getValue(x, value, maskValue);
790 privateStacker(value);
793 if (privateStacker.IsValid())
796 typename vigra::NumericTraits<PixelType>::RealPromote
sigma;
797 privateStacker.getResultAndSigma(mean, sigma);
798 output(x - outputROI.left(), y - outputROI.top()) = mean;
799 mask(x - outputROI.left(), y - outputROI.top()) = 255;
800 limits(x - outputROI.left(), y - outputROI.top()) = vigra::TinyVector<PixelType, 2>(mean -
Parameters.maskSigma*sigma, mean +
Parameters.maskSigma*sigma);
804 std::cout <<
"Write result to " <<
Parameters.outputFilename << std::endl;
807 tiffImage = TIFFOpen(
Parameters.outputFilename.c_str(),
"w");
810 outputROI.upperLeft(), canvasSize, images[0]->getICCProfile());
812 TIFFFlush(tiffImage);
816 if (!
SaveFinalImage(output, mask, images[0]->getPixelType(), exportImageInfo))
823 std::cout <<
"Masking input images with sigma=" <<
Parameters.maskSigma;
826 std::cout << std::endl;
830 std::cout <<
" and suffix " <<
Parameters.maskSuffix <<
".tif" << std::endl;
832 for (
size_t i = 0; i < images.size(); ++i)
834 std::cout <<
"Masking " << images[i]->getFilename();
837 std::cout << std::endl;
841 std::cout <<
" -> " << images[i]->getMaskFilename() << std::endl;
843 vigra::BasicImage<PixelType> image(images[i]->getROI().size());
844 vigra::BImage mask(image.size(), 255);
845 if (images[i]->numExtraBands() == 1)
851 vigra::importImage(images[i]->getImageImportInfo(),
vigra::destImage(image));
853 vigra::Rect2D roi = images[i]->getROI();
854 roi.moveBy(-outputROI.upperLeft());
858 std::cout <<
"Masked file \"" << images[i]->getMaskFilename() <<
"\" already exists." << std::endl
859 <<
"Processing aborted." << std::endl;
866 images[i]->getROI().upperLeft(), images[i]->getCanvasSize(), images[i]->getICCProfile());
868 TIFFFlush(tiffImage);
872 vigra::ImageExportInfo exportMaskImage(images[i]->getMaskFilename().c_str(),
Parameters.useBigTIFF ?
"w8" :
"w");
873 exportMaskImage.setXResolution(images[i]->getXResolution());
874 exportMaskImage.setYResolution(images[i]->getYResolution());
875 exportMaskImage.setPosition(images[i]->getROI().upperLeft());
876 exportMaskImage.setCanvasSize(images[i]->getCanvasSize());
877 exportMaskImage.setICCProfile(images[i]->getICCProfile());
878 exportMaskImage.setPixelType(images[i]->getPixelType().c_str());
879 exportMaskImage.setCompression(
"LZW");
884 catch (std::exception& e)
886 std::cerr <<
"Could not save masked images \"" << exportMaskImage.getFileName() <<
"\"." << std::endl
887 <<
"Error code: " << e.what() << std::endl
888 <<
"Processing aborted." << std::endl;
895 TIFFClose(tiffImage);
900 void CleanUp(std::vector<InputImage*>& images)
902 for (
auto& img : images)
908 template <
class PixelType>
913 std::cout <<
"Merging stack with minimum operator." << std::endl;
915 return StackImages<PixelType>(images, stacker);
921 std::cout <<
"Merging stack with maximum operator." << std::endl;
923 return StackImages<PixelType>(images, stacker);
929 std::cout <<
"Merging stack with average operator." << std::endl;
931 return StackImages<PixelType>(images, stacker);
938 std::cout <<
"Merging stack with median operator." << std::endl;
941 return StackImagesAndMask<PixelType>(images, stacker);
945 return StackImages<PixelType>(images, stacker);
953 std::cout <<
"Merging stack with Winsor clipping operator (trim=" <<
Parameters.winsorTrim <<
")." << std::endl;
956 return StackImagesAndMask<PixelType>(images, stacker);
960 return StackImages<PixelType>(images, stacker);
968 std::cout <<
"Merging stack with sigma clipping operator (max sigma=" <<
Parameters.sigma <<
", max " <<
Parameters.maxIterations <<
" iterations)." << std::endl;
971 return StackImagesAndMask<PixelType>(images, stacker);
975 return StackImages<PixelType>(images, stacker);
980 std::cerr <<
"ERROR: " <<
"\"" <<
Parameters.stackMode <<
"\" is not a valid stack mode." << std::endl
981 <<
" Allowed values are min|max|average|median|winsor|sigma" << std::endl;
991 int main(
int argc,
char* argv[])
994 const char* optstring =
"o:h";
998 OPT_COMPRESSION = 1000,
1009 static struct option longOptions[] =
1011 {
"output", required_argument, NULL,
'o' },
1012 {
"compression", required_argument, NULL, OPT_COMPRESSION },
1013 {
"mode", required_argument, NULL, OPT_STACKMODE },
1014 {
"winsor-trim", required_argument, NULL, OPT_WINSOR_TRIM},
1015 {
"max-sigma", required_argument, NULL, OPT_SIGMA_MAX},
1016 {
"max-iterations", required_argument, NULL, OPT_MAX_ITER},
1017 {
"mask-input", no_argument, NULL, OPT_MASK_INPUT},
1018 {
"mask-suffix", required_argument, NULL, OPT_MASK_SUFFIX},
1019 {
"mask-sigma", required_argument, NULL, OPT_MASK_SIGMA },
1020 {
"multi-layer-output", no_argument, NULL, OPT_MULTILAYER },
1021 {
"bigtiff", no_argument, NULL, OPT_BIGTIFF },
1022 {
"help", no_argument, NULL,
'h' },
1027 while ((c = getopt_long(argc, argv, optstring, longOptions,
nullptr)) != -1)
1038 case OPT_COMPRESSION:
1045 case OPT_WINSOR_TRIM:
1047 std::string text(optarg);
1048 int pos = text.find(
"%");
1049 if (pos != std::string::npos)
1051 text = text.substr(0, pos);
1054 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": No valid number for Winsor trim factor given." << std::endl;
1063 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": No valid number for Winsor trim factor given." << std::endl;
1076 std::string text(optarg);
1079 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": No valid number for maximal sigma value." << std::endl;
1084 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Maximal sigma value have to be positive." << std::endl;
1091 std::string text(optarg);
1094 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": No valid number for maximal iterations." << std::endl;
1099 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Maximal iterations values have to be at least 1." << std::endl;
1104 case OPT_MASK_INPUT:
1107 case OPT_MASK_SUFFIX:
1110 case OPT_MASK_SIGMA:
1112 std::string text(optarg);
1115 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": No valid number for maximal sigma value." << std::endl;
1120 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": Maximal sigma value have to be positive." << std::endl;
1125 case OPT_MULTILAYER:
1142 unsigned nFiles = argc - optind;
1145 std::cerr <<
hugin_utils::stripPath(argv[0]) <<
": at least one image need to be specified" << std::endl;
1150 std::vector<std::string> files;
1151 for (
size_t i = 0; i < nFiles; i++)
1153 std::string currentFile(argv[optind + i]);
1157 files.push_back(currentFile);
1179 if (
Parameters.multiLayer && extension !=
"tif" && extension !=
"tiff")
1181 std::cerr <<
"ERROR: Multi layer output expects a tiff file as output." << std::endl
1182 <<
" Other image formates are not compatible with this option." << std::endl;
1185 bool success =
false;
1186 std::vector<InputImage*> images;
1187 for (
size_t i = 0; i < files.size(); ++i)
1191 if (!images[0]->isColor() && !images[0]->isGrayscale())
1193 std::cerr <<
"ERROR: Only RGB and grayscale images are supported." << std::endl
1194 <<
" Image \"" << images[0]->getFilename() <<
"\" has " << images[0]->numPixelSamples() <<
" channels per pixel." << std::endl;
1198 if (images[0]->numExtraBands() > 1)
1200 std::cerr <<
"ERROR: Images with several alpha channels are not supported." << std::endl
1201 <<
" Image \"" << images[0]->getFilename() <<
"\" has " << images[0]->numExtraBands() <<
" extra channels." << std::endl;
1205 const std::string pixeltype(images[0]->getPixelType());
1207 for (
size_t i = 1; i < files.size(); ++i)
1209 if (!images[i]->isColor() && !images[i]->isGrayscale())
1211 std::cerr <<
"ERROR: Only RGB and grayscale images are supported." << std::endl
1212 <<
" Image \"" << images[i]->getFilename() <<
"\" has " << images[i]->numPixelSamples() <<
" channels per pixel." << std::endl;
1216 if (images[i]->numExtraBands() > 1)
1218 std::cerr <<
"ERROR: Images with several alpha channels are not supported." << std::endl
1219 <<
" Image \"" << images[i]->getFilename() <<
"\" has " << images[i]->numExtraBands() <<
" extra channels." << std::endl;
1223 if (images[0]->isColor() != images[i]->isColor())
1225 std::cerr <<
"ERROR: You can't merge color and grayscale images." << std::endl;
1229 if (images[0]->numPixelSamples() != images[i]->numPixelSamples())
1231 std::cerr <<
"ERROR: You can't merge image with different number of channels." << std::endl
1232 <<
" Image \"" << images[0]->getFilename() <<
"\" has " << images[0]->numBands() <<
" channels," << std::endl
1233 <<
" but image \"" << images[i]->getFilename() <<
"\" has " << images[i]->numBands() <<
" channels." << std::endl;
1237 if (pixeltype!=images[i]->getPixelType())
1239 std::cerr <<
"ERROR: You can't merge images with different pixel types." << std::endl
1240 <<
" Image \"" << images[0]->getFilename() <<
"\" has pixel type " << images[0]->getPixelType() <<
"," << std::endl
1241 <<
" but image \"" << images[i]->getFilename() <<
"\" has pixel type " << images[i]->getPixelType() <<
"." << std::endl;
1247 if (images[0]->isColor())
1249 if (pixeltype ==
"UINT8")
1251 success = main_stacker<vigra::RGBValue<vigra::UInt8>>(images);
1253 else if (pixeltype ==
"UINT16")
1255 success = main_stacker<vigra::RGBValue<vigra::UInt16>>(images);
1257 else if (pixeltype ==
"UINT32")
1259 success = main_stacker<vigra::RGBValue<vigra::UInt32>>(images);
1261 else if (pixeltype ==
"FLOAT")
1263 success = main_stacker<vigra::RGBValue<float>>(images);
1265 else if (pixeltype ==
"DOUBLE")
1267 success = main_stacker<vigra::RGBValue<double>>(images);
1271 std::cerr <<
" ERROR: unsupported pixel type: " << pixeltype << std::endl;
1277 if (pixeltype ==
"UINT8")
1279 success = main_stacker<vigra::UInt8>(images);
1281 else if (pixeltype ==
"UINT16")
1283 success = main_stacker<vigra::UInt16>(images);
1285 else if (pixeltype ==
"UINT32")
1287 success = main_stacker<vigra::UInt32>(images);
1289 else if (pixeltype ==
"FLOAT")
1291 success = main_stacker<float>(images);
1293 else if (pixeltype ==
"DOUBLE")
1295 success = main_stacker<double>(images);
1299 std::cerr <<
" ERROR: unsupported pixel type: " << pixeltype << std::endl;
virtual void getResult(ValueType &val)
std::vector< double > m_sortValues
bool FileExists(const std::string &filename)
checks if file exists
const std::string getName() const
std::string outputFilename
virtual void getResultAndSigma(ValueType &val, typename vigra::NumericTraits< ValueType >::RealPromote &sigma)
void CleanUp(std::vector< InputImage * > &images)
PixelType second_argument_type
bool StackImages(std::vector< InputImage * > &images, Functor &stacker)
loads images line by line and merge into final image, save the result
vigra::UInt8 third_argument_type
Some functions to create tiff images with masks.
vigra::UInt8 operator()(const vigra::TinyVector< realPixelType, 2 > &limits, const PixelType &gray, const vigra::UInt8 &mask, vigra::VigraTrueType) const
vigra::TinyVector< realPixelType, 2 > first_argument_type
static struct GeneralParameters Parameters
void operator()(const ValueType &val, vigra::VigraFalseType)
void EnforceExtension(std::string &filename, const std::string &defaultExtension)
check if filename contains extension, if not add default extension
virtual void operator()(const ValueType &val)
virtual void getResultAndSigma(ValueType &val, typename vigra::NumericTraits< ValueType >::RealPromote &sigma)
void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
Write the image and its alpha channel to a file.
bool CheckInput(const std::vector< InputImage * > &images, vigra::Rect2D &outputROI, vigra::Size2D &canvasSize)
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
std::string toupper(const std::string &s)
virtual void getResult(ValueType &val)
vigra::UInt8 operator()(const vigra::TinyVector< realPixelType, 2 > &limits, const PixelType &color, const vigra::UInt8 &mask, vigra::VigraFalseType) const
vigra::NumericTraits< ValueType >::RealPromote m_sum
void operator()(const ValueType &val, vigra::VigraTrueType)
void combineThreeImages(SrcImageIterator1 src1_upperleft, SrcImageIterator1 src1_lowerright, SrcAccessor1 src1_acc, SrcImageIterator2 src2_upperleft, SrcAccessor2 src2_acc, SrcImageIterator3 src3_upperleft, SrcAccessor3 src3_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
bool IsFileTypeSupported(const std::string &filename)
return true, if file type by extension is supported by vigra
std::string getExtension(const std::string &basename2)
Get extension of a filename.
vigra::FRGBImage ImageType
void operator()(const ValueType &val)
void operator()(const ValueType &val, vigra::VigraFalseType)
vigra::NumericTraits< PixelType >::RealPromote realPixelType
void createAlphaTiffImage(ImageIterator upperleft, ImageIterator lowerright, ImageAccessor a, AlphaIterator alphaUpperleft, AlphaAccessor alphaA, vigra::TiffImage *tiff)
std::string stripExtension(const std::string &basename2)
remove extension of a filename
void operator()(const ValueType &val, vigra::VigraTrueType)
void getMeanSigma(const std::vector< ValueType > &values, ValueType &val, typename vigra::NumericTraits< ValueType >::RealPromote &sigma)
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
void createTiffDirectory(vigra::TiffImage *tiff, const std::string &pagename, const std::string &documentname, const std::string comp, uint16_t page, uint16_t nImg, vigra::Diff2D offset, vigra::Size2D fullSize, const vigra::ImageExportInfo::ICCProfile &icc)
write a new Tiff directory, for a new layer
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel...
bool main_stacker(std::vector< InputImage * > &images)
bool SaveImage(ImageType &image, MaskType &mask, vigra::ImageExportInfo &exportImageInfo, std::string filetype, std::string pixelType)
save image, when possible with alpha channel, take care of formats which does not support alpha chann...
virtual void operator()(const ValueType &val)
void operator()(const ValueType &val, vigra::VigraFalseType)
void getMean(const std::vector< ValueType > &values, ValueType &val)
std::string GetHuginVersion()
return a string with version numbers
bool StackImagesAndMask(std::vector< InputImage * > &images, Functor &stacker)
std::vector< ValueType > m_values
const std::string getName() const
void operator()(const ValueType &val, vigra::VigraTrueType)
void getResult(ValueType &val)
bool SaveFinalImage(ImageType &image, MaskType &mask, const std::string &inputPixelType, vigra::ImageExportInfo &output)
save final image, take care of some supported pixel types and convert when necessary to smaller pixel...
virtual void getResult(ValueType &val)
virtual void getResult(ValueType &val)
std::string tolower(const std::string &s)
convert a string to lowercase
virtual void operator()(const ValueType &val)
vigra::UInt8 operator()(const vigra::TinyVector< realPixelType, 2 > &limits, const PixelType &pixel, const vigra::UInt8 &mask) const
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
void SetCompression(vigra::ImageExportInfo &output, const std::string &compression)
set compression for jpeg or tiff
int main(int argc, char *argv[])