// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "libvideostitch/imageMergerFactory.hpp" #include "core1/arrayImageMerger.hpp" #include "core1/checkerboardImageMerger.hpp" #include "core1/diffImageMerger.hpp" #include "core1/exposureDiffImageMerger.hpp" #include "core1/gradientImageMerger.hpp" #include "core1/laplacianImageMerger.hpp" #include "core1/stackImageMerger.hpp" #include "core1/noblendImageMerger.hpp" #include "coredepth/sphereSweepMerger.hpp" #include "libvideostitch/logging.hpp" #include "libvideostitch/parse.hpp" #include <cassert> #include <mutex> #include <iostream> namespace VideoStitch { namespace Core { const std::vector<std::string>& ImageMergerFactory::availableMergers() { static std::vector<std::string> availableMergers; // Lazily fill in the list of mergers. TODO: use a better, macro-based, registration pattern. static std::mutex mutex; { std::unique_lock<std::mutex> lock(mutex); if (availableMergers.empty()) { #ifndef VS_OPENCL availableMergers.push_back("laplacian"); #endif availableMergers.push_back("gradient"); availableMergers.push_back("noblendv1"); availableMergers.push_back("diff"); availableMergers.push_back("exposure_diff"); availableMergers.push_back("checkerboard"); availableMergers.push_back("array"); availableMergers.push_back("stack"); availableMergers.push_back("sphere_sweep"); } } return availableMergers; } Potential<ImageMergerFactory> ImageMergerFactory::createMergerFactory(const Ptv::Value& value) { // Make sure value is an object. if (!Parse::checkType("ImageMergerFactory", value, Ptv::Value::OBJECT)) { return {Origin::Stitcher, ErrType::InvalidConfiguration, "Invalid type for 'ImageMergerFactory' configuration, expected object"}; } std::string type; if (Parse::populateString("ImageMergerFactory", value, "type", type, false) == Parse::PopulateResult_WrongType) { return {Origin::Stitcher, ErrType::InvalidConfiguration, "Invalid type for 'ImageMergerFactory' configuration, expected string"}; } if (type == "laplacian") { return LaplacianImageMerger::Factory::parse(value); } else if (type == "gradient") { return GradientImageMerger::Factory::parse(value); } else if (type == "noblendv1") { return Potential<ImageMergerFactory>(new NoBlendImageMerger::Factory()); } else if (type == "diff") { return Potential<ImageMergerFactory>(new DiffImageMerger::Factory()); } else if (type == "exposure_diff") { return Potential<ImageMergerFactory>(new ExposureDiffImageMerger::Factory()); } else if (type == "checkerboard") { return CheckerboardImageMerger::Factory::parse(value); } else if (type == "array") { return Potential<ImageMergerFactory>(new ArrayImageMerger::Factory()); } else if (type == "stack") { return Potential<ImageMergerFactory>(new StackImageMerger::Factory()); } else if (type == "sphere_sweep") { return Potential<ImageMergerFactory>(new SphereSweepMerger::Factory()); } else { return {Origin::Stitcher, ErrType::InvalidConfiguration, "Unknown merger type: '" + type + "'"}; } } Potential<PanoMerger> ImageMergerFactory::createDepth(const PanoDefinition& /* pano */) const { return {Origin::Stitcher, ErrType::ImplementationError, "ImageMergerFactory does not implement pano merging."}; }; bool ImageMergerFactory::equal(const ImageMergerFactory& other) const { return hash() == other.hash(); } uint32_t ImageMergerFactory::getBlockAlignment() const { return ImageMerger::CudaBlockSize; } namespace { /** * A merger factory that cannot instanciate a merger. This can be useful when creating a merger without stitchers. */ class ImpotentMergerFactory : public ImageMergerFactory { public: virtual Potential<ImageMerger> create(const PanoDefinition& /*pano*/, ImageMapping& /*fromIm*/, const ImageMerger* /*to*/, bool) const { return Status{Origin::Stitcher, ErrType::ImplementationError, "Cannot create impotent merger"}; } virtual ~ImpotentMergerFactory() {} Ptv::Value* serialize() const { return NULL; } virtual CoreVersion version() const { return Impotent; } virtual ImageMergerFactory* clone() const { return new ImpotentMergerFactory(); } virtual std::string hash() const { return "impotentMerger"; } }; } // namespace Potential<ImageMergerFactory> ImageMergerFactory::newImpotentMergerFactory() { return Potential<ImageMergerFactory>(new ImpotentMergerFactory); } } // namespace Core } // namespace VideoStitch