diff --git a/src/aliceVision/calibration/exportData.cpp b/src/aliceVision/calibration/exportData.cpp index 27147557aa..a15bc2d8ae 100644 --- a/src/aliceVision/calibration/exportData.cpp +++ b/src/aliceVision/calibration/exportData.cpp @@ -55,7 +55,7 @@ void exportImages(aliceVision::dataio::FeedProvider& feed, aliceVision::camera::UndistortImage(inputImage, &camera, outputImage, static_cast(0)); const boost::filesystem::path imagePath = boost::filesystem::path(debugFolder) / (std::to_string(currentFrame) + suffix); - aliceVision::image::writeImage(imagePath.string(), outputImage, image::EImageColorSpace::AUTO); + aliceVision::image::writeImage(imagePath.string(), outputImage, image::ImageWriteOptions()); } ALICEVISION_LOG_DEBUG("... finished"); } diff --git a/src/aliceVision/depthMap/DepthSimMap.cpp b/src/aliceVision/depthMap/DepthSimMap.cpp index a2a106d80d..510a7998b1 100644 --- a/src/aliceVision/depthMap/DepthSimMap.cpp +++ b/src/aliceVision/depthMap/DepthSimMap.cpp @@ -196,14 +196,14 @@ float DepthSimMap::getPercentileDepth(float perc) const * @brief Get depth map at the size of our input image (with _scale applied) * from an internal buffer only computed for a subpart (based on the step). */ -void DepthSimMap::getDepthMapStep1(StaticVector& out_depthMap) const +void DepthSimMap::getDepthMapStep1(image::Image& out_depthMap) const { // Size of our input image (with _scale applied) const int wdm = _mp.getWidth(_rc) / _scale; const int hdm = _mp.getHeight(_rc) / _scale; // Create a depth map at the size of our input image - out_depthMap.resize(wdm * hdm); + out_depthMap.resize(wdm, hdm); const double ratio = 1.0 / double(_step); @@ -215,19 +215,19 @@ void DepthSimMap::getDepthMapStep1(StaticVector& out_depthMap) const { const double ox = (double(x) - 0.5) * ratio; const float depth = getPixelValueInterpolated(_dsm, ox, oy, _w, _h).depth; - out_depthMap[y * wdm + x] = depth; + out_depthMap(y, x) = depth; } } } -void DepthSimMap::getSimMapStep1(StaticVector& out_simMap) const +void DepthSimMap::getSimMapStep1(image::Image& out_simMap) const { // Size of our input image (with _scale applied) const int wdm = _mp.getWidth(_rc) / _scale; const int hdm = _mp.getHeight(_rc) / _scale; // Create a depth map at the size of our input image - out_simMap.resize(wdm * hdm); + out_simMap.resize(wdm, hdm); const double ratio = 1.0 / double(_step); @@ -239,7 +239,7 @@ void DepthSimMap::getSimMapStep1(StaticVector& out_simMap) const { const double ox = (double(x) - 0.5) * ratio; const float sim = getPixelValueInterpolated(_dsm, ox, oy, _w, _h).sim; - out_simMap[y * wdm + x] = sim; + out_simMap(y, x) = sim; } } } @@ -318,7 +318,8 @@ void DepthSimMap::initJustFromDepthMap(const DepthSimMap& depthSimMap, float def } } -void DepthSimMap::initFromDepthMapAndSimMap(StaticVector* depthMapT, StaticVector* simMapT, +void DepthSimMap::initFromDepthMapAndSimMap(const image::Image& depthMapT, + const image::Image& simMapT, int depthSimMapsScale) { int wdm = _mp.getWidth(_rc) / depthSimMapsScale; @@ -331,34 +332,34 @@ void DepthSimMap::initFromDepthMapAndSimMap(StaticVector* depthMapT, Stat if ((x < wdm) && (y < hdm)) { int index = y * wdm + x; - _dsm[i].depth = (*depthMapT)[index]; - _dsm[i].sim = (*simMapT)[index]; + _dsm[i].depth = depthMapT(index); + _dsm[i].sim = simMapT(index); } } } -void DepthSimMap::getDepthMap(StaticVector& out_depthMap) const +void DepthSimMap::getDepthMap(image::Image& out_depthMap) const { - out_depthMap.resize(_dsm.size()); + out_depthMap.resize(_w, _h); for (int i = 0; i < _dsm.size(); i++) { - out_depthMap[i] = _dsm[i].depth; + out_depthMap(i) = _dsm[i].depth; } } -void DepthSimMap::getSimMap(StaticVector& out_simMap) const +void DepthSimMap::getSimMap(image::Image& out_simMap) const { - out_simMap.resize(_dsm.size()); + out_simMap.resize(_w, _h); for (int i = 0; i < _dsm.size(); i++) { - out_simMap[i] = _dsm[i].sim; + out_simMap(i) = _dsm[i].sim; } } void DepthSimMap::saveToImage(const std::string& filename, float simThr) const { const int bufferWidth = 2 * _w; - std::vector colorBuffer(bufferWidth * _h); + image::Image colorBuffer(bufferWidth, _h); try { @@ -384,16 +385,15 @@ void DepthSimMap::saveToImage(const std::string& filename, float simThr) const { const DepthSim& depthSim = _dsm[y * _w + x]; float depth = (depthSim.depth - maxMinDepth.y) / (maxMinDepth.x - maxMinDepth.y); - colorBuffer.at(y * bufferWidth + x) = getColorFromJetColorMap(depth); + colorBuffer(y, x) = getColorFromJetColorMap(depth); float sim = (depthSim.sim - maxMinSim.y) / (maxMinSim.x - maxMinSim.y); - colorBuffer.at(y * bufferWidth + _w + x) = getColorFromJetColorMap(sim); + colorBuffer(y, _w + x) = getColorFromJetColorMap(sim); } } - - oiio::ParamValueList metadata; - image::writeImage(filename, bufferWidth, _h, colorBuffer, image::EImageQuality::LOSSLESS, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION), metadata); + image::writeImage(filename, colorBuffer, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Float)); } catch (...) { @@ -403,8 +403,8 @@ void DepthSimMap::saveToImage(const std::string& filename, float simThr) const void DepthSimMap::save(const std::string& customSuffix, bool useStep1) const { - StaticVector depthMap; - StaticVector simMap; + image::Image depthMap; + image::Image simMap; if (useStep1) { getDepthMapStep1(depthMap); @@ -419,9 +419,6 @@ void DepthSimMap::save(const std::string& customSuffix, bool useStep1) const const int step = (useStep1 ? 1 : _step); const int scaleStep = _scale * step; - const int width = _mp.getWidth(_rc) / scaleStep; - const int height = _mp.getHeight(_rc) / scaleStep; - auto metadata = image::getMetadataFromMap(_mp.getMetadata(_rc)); metadata.push_back(oiio::ParamValue("AliceVision:downscale", _mp.getDownscaleFactor(_rc) * scaleStep)); @@ -456,30 +453,30 @@ void DepthSimMap::save(const std::string& customSuffix, bool useStep1) const metadata.push_back(oiio::ParamValue("AliceVision:P", oiio::TypeDesc(oiio::TypeDesc::DOUBLE, oiio::TypeDesc::MATRIX44), 1, matrixP.data())); } - const int nbDepthValues = std::count_if(depthMap.begin(), depthMap.end(), [](float v) { return v > 0.0f; }); + const int nbDepthValues = std::count_if(depthMap.data(), depthMap.data() + depthMap.size(), [](float v) { return v > 0.0f; }); metadata.push_back(oiio::ParamValue("AliceVision:nbDepthValues", oiio::TypeDesc::INT32, 1, &nbDepthValues)); image::writeImage(getFileNameFromIndex(_mp, _rc, mvsUtils::EFileType::depthMap, _scale, customSuffix), - width, height, depthMap.getDataWritable(), image::EImageQuality::LOSSLESS, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION), metadata); + depthMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Float), metadata); image::writeImage(getFileNameFromIndex(_mp, _rc, mvsUtils::EFileType::simMap, _scale, customSuffix), - width, height, simMap.getDataWritable(), image::EImageQuality::OPTIMIZED, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION), metadata); + simMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Half), metadata); } void DepthSimMap::load(int fromScale) { - int width, height; - - StaticVector depthMap; - StaticVector simMap; + image::Image depthMap; + image::Image simMap; image::readImage(getFileNameFromIndex(_mp, _rc, mvsUtils::EFileType::depthMap, fromScale), - width, height, depthMap.getDataWritable(), image::EImageColorSpace::NO_CONVERSION); + depthMap, image::EImageColorSpace::NO_CONVERSION); image::readImage(getFileNameFromIndex(_mp, _rc, mvsUtils::EFileType::simMap, fromScale), - width, height, simMap.getDataWritable(), image::EImageColorSpace::NO_CONVERSION); + simMap, image::EImageColorSpace::NO_CONVERSION); - initFromDepthMapAndSimMap(&depthMap, &simMap, fromScale); + initFromDepthMapAndSimMap(depthMap, simMap, fromScale); } } // namespace depthMap diff --git a/src/aliceVision/depthMap/DepthSimMap.hpp b/src/aliceVision/depthMap/DepthSimMap.hpp index d2039ebef3..9a7b1e0b5b 100644 --- a/src/aliceVision/depthMap/DepthSimMap.hpp +++ b/src/aliceVision/depthMap/DepthSimMap.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -97,8 +98,9 @@ class DepthSimMap void initJustFromDepthMap(const StaticVector& depthMap, float defaultSim); void initJustFromDepthMap(const DepthSimMap& depthSimMap, float defaultSim); - void initFromDepthMapAndSimMap(StaticVector* depthMapT, StaticVector* simMapT, - int depthSimMapsScale); + void initFromDepthMapAndSimMap(const image::Image& depthMapT, + const image::Image& simMapT, + int depthSimMapsScale); void initFromSmaller(const DepthSimMap& depthSimMap); void init(const DepthSimMap& depthSimMap); @@ -107,10 +109,10 @@ class DepthSimMap Point2d getMaxMinSim() const; float getPercentileDepth(float perc) const; - void getDepthMapStep1(StaticVector& out_depthMap) const; - void getSimMapStep1(StaticVector& out_simMap) const; - void getDepthMap(StaticVector& out_depthMap) const; - void getSimMap(StaticVector& out_simMap) const; + void getDepthMapStep1(image::Image& out_depthMap) const; + void getSimMapStep1(image::Image& out_simMap) const; + void getDepthMap(image::Image& out_depthMap) const; + void getSimMap(image::Image& out_simMap) const; void getDepthMapStep1XPart(StaticVector& out_depthMap, int xFrom, int partW); void getSimMapStep1XPart(StaticVector& out_depthMap, int xFrom, int partW); diff --git a/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.cpp b/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.cpp index af4579692f..6f0e0a5c1d 100644 --- a/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.cpp +++ b/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.cpp @@ -679,8 +679,8 @@ void PlaneSweepingCuda::deleteNormalMapping( NormalMapping* m ) bool PlaneSweepingCuda::computeNormalMap( NormalMapping* mapping, - const std::vector& depthMap, - std::vector& normalMap, + const image::Image& depthMap, + image::Image& normalMap, int rc, int scale, float igammaC, float igammaP, int wsh) { @@ -696,7 +696,7 @@ bool PlaneSweepingCuda::computeNormalMap( cps_host_fillCamera( *mapping->camsBasesHst, rc, _mp, scale ); mapping->loadCameraParameters(); mapping->allocHostMaps( w, h ); - mapping->copyDepthMap( depthMap ); + mapping->copyDepthMap(depthMap.data(), depthMap.size()); ps_computeNormalMap( mapping, w, h, scale - 1, @@ -714,9 +714,9 @@ bool PlaneSweepingCuda::computeNormalMap( { for (int i = 0; i < w * h; i++) { - normalMap[i].r() = normalMapPtr[i].x; - normalMap[i].g() = normalMapPtr[i].y; - normalMap[i].b() = normalMapPtr[i].z; + normalMap(i).r() = normalMapPtr[i].x; + normalMap(i).g() = normalMapPtr[i].y; + normalMap(i).b() = normalMapPtr[i].z; } } diff --git a/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.hpp b/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.hpp index 21029dbd8c..a1e8d2684a 100644 --- a/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.hpp +++ b/src/aliceVision/depthMap/cuda/PlaneSweepingCuda.hpp @@ -143,8 +143,8 @@ class PlaneSweepingCuda void deleteNormalMapping( NormalMapping* m ); bool computeNormalMap( NormalMapping* mapping, - const std::vector& depthMap, - std::vector& normalMap, + const image::Image& depthMap, + image::Image& normalMap, int rc, int scale, float igammaC, float igammaP, int wsh); diff --git a/src/aliceVision/depthMap/cuda/normalmap/normal_map.cu b/src/aliceVision/depthMap/cuda/normalmap/normal_map.cu index 058704231f..0a546aea36 100644 --- a/src/aliceVision/depthMap/cuda/normalmap/normal_map.cu +++ b/src/aliceVision/depthMap/cuda/normalmap/normal_map.cu @@ -232,14 +232,14 @@ void NormalMapping::allocHostMaps( int w, int h ) } } -void NormalMapping::copyDepthMap( const std::vector& depthMap ) +void NormalMapping::copyDepthMap(const float* depthMap , int depthMapSize) { - if( _allocated_floats > depthMap.size() ) + if (_allocated_floats > depthMapSize) { std::cerr << "WARNING: " << __FILE__ << ":" << __LINE__ << ": copying depthMap whose origin is too small" << std::endl; } - memcpy( _depthMapHst, depthMap.data(), _allocated_floats*sizeof(float) ); + memcpy( _depthMapHst, depthMap, _allocated_floats*sizeof(float) ); } const float* NormalMapping::getDepthMapHst() const diff --git a/src/aliceVision/depthMap/cuda/normalmap/normal_map.hpp b/src/aliceVision/depthMap/cuda/normalmap/normal_map.hpp index 5ec87e56ea..37acbb70d0 100644 --- a/src/aliceVision/depthMap/cuda/normalmap/normal_map.hpp +++ b/src/aliceVision/depthMap/cuda/normalmap/normal_map.hpp @@ -19,7 +19,7 @@ class NormalMapping void loadCameraParameters(); void allocHostMaps( int w, int h ); - void copyDepthMap( const std::vector& depthMap ); + void copyDepthMap(const float* depthMap, int depthMapSize); const float* getDepthMapHst() const; // an input float3* getNormalMapHst(); // an output diff --git a/src/aliceVision/depthMap/depthMap.cpp b/src/aliceVision/depthMap/depthMap.cpp index 7075cf7241..1cc2e7a2b0 100644 --- a/src/aliceVision/depthMap/depthMap.cpp +++ b/src/aliceVision/depthMap/depthMap.cpp @@ -124,19 +124,16 @@ void computeNormalMaps(int cudaDeviceIndex, mvsUtils::MultiViewParams& mp, const if (!fs::exists(normalMapFilepath)) { - std::vector depthMap; - int w = 0; - int h = 0; - readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::depthMap, 0), w, h, depthMap, + image::Image depthMap; + readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::depthMap, 0), depthMap, image::EImageColorSpace::NO_CONVERSION); - std::vector normalMap; - normalMap.resize(mp.getWidth(rc) * mp.getHeight(rc)); + image::Image normalMap(mp.getWidth(rc), mp.getHeight(rc)); cps.computeNormalMap(mapping, depthMap, normalMap, rc, 1, gammaC, gammaP, wsh); - image::writeImage(normalMapFilepath, mp.getWidth(rc), mp.getHeight(rc), normalMap, - image::EImageQuality::LOSSLESS, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION)); + image::writeImage(normalMapFilepath, normalMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Float)); } } cps.deleteNormalMapping(mapping); diff --git a/src/aliceVision/fuseCut/DelaunayGraphCut.cpp b/src/aliceVision/fuseCut/DelaunayGraphCut.cpp index ab59248c3b..4c0937e704 100644 --- a/src/aliceVision/fuseCut/DelaunayGraphCut.cpp +++ b/src/aliceVision/fuseCut/DelaunayGraphCut.cpp @@ -295,14 +295,12 @@ void createVerticesWithVisibilities(const StaticVector& cams, std::vector

depthMap; - std::vector simMap; - int width, height; + image::Image depthMap; + image::Image simMap; { const std::string depthMapFilepath = getFileNameFromIndex(mp, c, mvsUtils::EFileType::depthMap, 0); - image::readImage(depthMapFilepath, width, height, depthMap, - image::EImageColorSpace::NO_CONVERSION); - if(depthMap.empty()) + image::readImage(depthMapFilepath, depthMap, image::EImageColorSpace::NO_CONVERSION); + if (depthMap.size() == 0) { ALICEVISION_LOG_WARNING("Empty depth map: " << depthMapFilepath); continue; @@ -313,33 +311,32 @@ void createVerticesWithVisibilities(const StaticVector& cams, std::vector

simMapTmp(simMap.size()); - imageAlgo::convolveImage(width, height, simMap, simMapTmp, "gaussian", simGaussianSize, - simGaussianSize); + image::Image simMapTmp; + imageAlgo::convolveImage(simMap, simMapTmp, + "gaussian", simGaussianSize, simGaussianSize); simMap.swap(simMapTmp); } } else { ALICEVISION_LOG_WARNING("simMap file can't be found."); - simMap.resize(width * height, -1); + simMap.resize(depthMap.Width(), depthMap.Height(), true, -1); } } // Add visibility #pragma omp parallel for - for(int y = 0; y < height; ++y) + for (int y = 0; y < depthMap.Height(); ++y) { - for(int x = 0; x < width; ++x) + for(int x = 0; x < depthMap.Width(); ++x) { - const std::size_t index = y * width + x; - const float depth = depthMap[index]; + const std::size_t index = y * depthMap.Width() + x; + const float depth = depthMap(index); if(depth <= 0.0f) continue; @@ -368,7 +365,7 @@ void createVerticesWithVisibilities(const StaticVector& cams, std::vector

depthMap; - int width, height; + image::Image depthMap; { const std::string depthMapFilepath = getFileNameFromIndex(_mp, c, mvsUtils::EFileType::depthMap, 0); - image::readImage(depthMapFilepath, width, height, depthMap, - image::EImageColorSpace::NO_CONVERSION); - if(depthMap.empty()) + image::readImage(depthMapFilepath, depthMap, image::EImageColorSpace::NO_CONVERSION); + if(depthMap.size() == 0) { ALICEVISION_LOG_WARNING("Empty depth map: " << depthMapFilepath); continue; } } + const int width = depthMap.Width(); + const int height = depthMap.Height(); int syMax = divideRoundUp(height, step); int sxMax = divideRoundUp(width, step); @@ -977,7 +974,7 @@ void DelaunayGraphCut::addMaskHelperPoints(const Point3d voxel[8], const StaticV for(int x = sx * step, xmax = std::min((sx + 1) * step, width); x < xmax; ++x) { const std::size_t index = y * width + x; - const float depth = depthMap[index]; + const float depth = depthMap(index); // -2 means that the pixels should be masked-out with mask helper points if(depth > -1.5f) @@ -991,7 +988,7 @@ void DelaunayGraphCut::addMaskHelperPoints(const Point3d voxel[8], const StaticV for(int lx = std::max(x - kernelSize, 0), lxMax = std::min(x + kernelSize, width - 1); lx < lxMax; ++lx) { - if(depthMap[ly * width + lx] > 0.0f) + if (depthMap(ly * width + lx) > 0.0f) ++nbValidDepth; } } @@ -1089,39 +1086,42 @@ void DelaunayGraphCut::fuseFromDepthMaps(const StaticVector& cams, const Po #pragma omp parallel for num_threads(3) for(int c = 0; c < cams.size(); c++) { - std::vector depthMap; - std::vector simMap; - std::vector numOfModalsMap; + image::Image depthMap; + image::Image simMap; + image::Image numOfModalsMap; int width, height; { const std::string depthMapFilepath = getFileNameFromIndex(_mp, c, mvsUtils::EFileType::depthMap, 0); - image::readImage(depthMapFilepath, width, height, depthMap, - image::EImageColorSpace::NO_CONVERSION); - if(depthMap.empty()) + image::readImage(depthMapFilepath, depthMap, image::EImageColorSpace::NO_CONVERSION); + if (depthMap.size() == 0) { ALICEVISION_LOG_WARNING("Empty depth map: " << depthMapFilepath); continue; } + width = depthMap.Width(); + height = depthMap.Height(); + int wTmp, hTmp; const std::string simMapFilepath = getFileNameFromIndex(_mp, c, mvsUtils::EFileType::simMap, 0); // If we have a simMap in input use it, // else init with a constant value. if(boost::filesystem::exists(simMapFilepath)) { - image::readImage(simMapFilepath, wTmp, hTmp, simMap, - image::EImageColorSpace::NO_CONVERSION); - if(wTmp != width || hTmp != height) + image::readImage(simMapFilepath, simMap, image::EImageColorSpace::NO_CONVERSION); + if (simMap.Width() != width || simMap.Height() != height) throw std::runtime_error("Wrong sim map dimensions: " + simMapFilepath); { - std::vector simMapTmp(simMap.size()); - imageAlgo::convolveImage(width, height, simMap, simMapTmp, "gaussian", - params.simGaussianSizeInit, params.simGaussianSizeInit); simMap.swap(simMapTmp); + image::Image simMapTmp; + imageAlgo::convolveImage(simMap, simMapTmp, "gaussian", + params.simGaussianSizeInit, + params.simGaussianSizeInit); + simMap.swap(simMapTmp); } } else { ALICEVISION_LOG_WARNING("simMap file can't be found."); - simMap.resize(width * height, -1); + simMap.resize(width, height, true, -1); } const std::string nmodMapFilepath = getFileNameFromIndex(_mp, c, mvsUtils::EFileType::nmodMap, 0); @@ -1129,15 +1129,15 @@ void DelaunayGraphCut::fuseFromDepthMaps(const StaticVector& cams, const Po // else init with a constant value. if(boost::filesystem::exists(nmodMapFilepath)) { - image::readImage(nmodMapFilepath, wTmp, hTmp, numOfModalsMap, + image::readImage(nmodMapFilepath, numOfModalsMap, image::EImageColorSpace::NO_CONVERSION); - if(wTmp != width || hTmp != height) + if (numOfModalsMap.Width() != width || numOfModalsMap.Height() != height) throw std::runtime_error("Wrong nmod map dimensions: " + nmodMapFilepath); } else { ALICEVISION_LOG_WARNING("nModMap file can't be found."); - numOfModalsMap.resize(width*height, 1); + numOfModalsMap.resize(width, height, true, 1); } } @@ -1161,7 +1161,7 @@ void DelaunayGraphCut::fuseFromDepthMaps(const StaticVector& cams, const Po x < xmax; ++x) { const std::size_t index = y * width + x; - const float depth = depthMap[index]; + const float depth = depthMap(index); if(depth <= 0.0f) continue; @@ -1171,13 +1171,13 @@ void DelaunayGraphCut::fuseFromDepthMaps(const StaticVector& cams, const Po { for(int lx = std::max(x-scoreKernelSize, 0), lxMax = std::min(x+scoreKernelSize, width-1); lx < lxMax; ++lx) { - if(depthMap[ly * width + lx] > 0.0f) + if (depthMap(ly * width + lx) > 0.0f) { - numOfModals += 10 + int(numOfModalsMap[ly * width + lx]); + numOfModals += 10 + int(numOfModalsMap(ly * width + lx)); } } } - float sim = simMap[index]; + float sim = simMap(index); sim = sim < 0.0f ? 0.0f : sim; // clamp values < 0 // remap similarity values from [-1;+1] to [+1;+simScale] // interpretation is [goodSimilarity;badSimilarity] diff --git a/src/aliceVision/fuseCut/Fuser.cpp b/src/aliceVision/fuseCut/Fuser.cpp index 43d20ebd5c..5035aabba6 100644 --- a/src/aliceVision/fuseCut/Fuser.cpp +++ b/src/aliceVision/fuseCut/Fuser.cpp @@ -41,18 +41,16 @@ unsigned long computeNumberOfAllPoints(const mvsUtils::MultiViewParams& mp, int if(nbDepthValues < 0) { - int width, height; - StaticVector depthMap; + image::Image depthMap; nbDepthValues = 0; ALICEVISION_LOG_WARNING("Can't find or invalid 'nbDepthValues' metadata in '" << filename << "'. Recompute the number of valid values."); image::readImage(mvsUtils::getFileNameFromIndex(mp, rc, mvsUtils::EFileType::depthMap, scale), - width, height, depthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); + depthMap, image::EImageColorSpace::NO_CONVERSION); // no need to transpose for this operation - for(int i = 0; i < sizeOfStaticVector(&depthMap); ++i) - nbDepthValues += static_cast(depthMap[i] > 0.0f); + for(int i = 0; i < depthMap.size(); ++i) + nbDepthValues += static_cast(depthMap(i) > 0.0f); } npts += nbDepthValues; @@ -83,7 +81,8 @@ Fuser::~Fuser() * @param[in] scale */ bool Fuser::updateInSurr(float pixToleranceFactor, int pixSizeBall, int pixSizeBallWSP, Point3d& p, int rc, int tc, - StaticVector* numOfPtsMap, StaticVector* depthMap, StaticVector* simMap, + StaticVector* numOfPtsMap, + const image::Image& depthMap, const image::Image& simMap, int scale) { int w =_mp.getWidth(rc) / scale; @@ -104,7 +103,7 @@ bool Fuser::updateInSurr(float pixToleranceFactor, int pixSizeBall, int pixSizeB int d = pixSizeBall; - float sim = (*simMap)[cell.y * w + cell.x]; + const float sim = simMap(cell.y, cell.x); if(sim >= 1.0f) { d = pixSizeBallWSP; @@ -119,7 +118,7 @@ bool Fuser::updateInSurr(float pixToleranceFactor, int pixSizeBall, int pixSizeB for(ncell.y = std::max(0, cell.y - d); ncell.y <= std::min(h - 1, cell.y + d); ncell.y++) { // printf("%i %i %i %i %i %i %i %i\n",ncell.x,ncell.y,w,h,w*h,depthMap->size(),cam,scale); - float depth = (*depthMap)[ncell.y * w + ncell.x]; + const float depth = depthMap(ncell.y, ncell.x); // Point3d p1 = _mp.CArr[rc] + // (_mp.iCamArr[rc]*Point2d((float)ncell.x*(float)scale,(float)ncell.y*(float)scale)).normalize()*depth; // if ( (p1-p).size() < pixSize ) { @@ -160,23 +159,17 @@ bool Fuser::filterGroupsRC(int rc, float pixToleranceFactor, int pixSizeBall, in int w = _mp.getWidth(rc); int h = _mp.getHeight(rc); - StaticVector depthMap; - StaticVector simMap; + image::Image depthMap; + image::Image simMap; - { - int width, height; - - image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, 1), - width, height, depthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::simMap, 1), - width, height, simMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - } + image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, 1), + depthMap, image::EImageColorSpace::NO_CONVERSION); + image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::simMap, 1), + simMap, image::EImageColorSpace::NO_CONVERSION); - std::vector numOfModalsMap(w * h, 0); + image::Image numOfModalsMap(w, h, true, 0); - if((depthMap.empty()) || (simMap.empty()) || (depthMap.size() != w * h) || (simMap.size() != w * h)) + if ((depthMap.size() != w * h) || (simMap.size() != w * h)) { std::stringstream s; s << "filterGroupsRC: bad image dimension for camera: " << _mp.getViewId(rc) << "\n"; @@ -195,42 +188,37 @@ bool Fuser::filterGroupsRC(int rc, float pixToleranceFactor, int pixSizeBall, in numOfPtsMap->resize_with(w * h, 0); int tc = tcams[c]; - StaticVector tcdepthMap; + image::Image tcdepthMap; - { - int width, height; - image::readImage(getFileNameFromIndex(_mp, tc, mvsUtils::EFileType::depthMap, 1), - width, height, tcdepthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - } + image::readImage(getFileNameFromIndex(_mp, tc, mvsUtils::EFileType::depthMap, 1), + tcdepthMap, image::EImageColorSpace::NO_CONVERSION); - if(!tcdepthMap.empty()) + if (tcdepthMap.Height() > 0 && tcdepthMap.Width() > 0) { for(int y = 0; y < h; ++y) { for(int x = 0; x < w; ++x) { - float depth = tcdepthMap[y * w + x]; + float depth = tcdepthMap(y, x); if(depth > 0.0f) { Point3d p = _mp.CArr[tc] + (_mp.iCamArr[tc] * Point2d((float)x, (float)y)).normalize() * depth; - updateInSurr(pixToleranceFactor, pixSizeBall, pixSizeBallWSP, p, rc, tc, numOfPtsMap, &depthMap, &simMap, 1); + updateInSurr(pixToleranceFactor, pixSizeBall, pixSizeBallWSP, p, rc, tc, numOfPtsMap, depthMap, simMap, 1); } } } for(int i = 0; i < w * h; i++) { - numOfModalsMap.at(i) += static_cast((*numOfPtsMap)[i] > 0); + numOfModalsMap(i) += static_cast((*numOfPtsMap)[i] > 0); } } } - { - image::writeImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::nmodMap), w, h, - numOfModalsMap, image::EImageQuality::LOSSLESS, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION)); - } + image::writeImageWithFloat(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::nmodMap), + numOfModalsMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Float)); delete numOfPtsMap; @@ -263,52 +251,58 @@ bool Fuser::filterDepthMapsRC(int rc, int minNumOfModals, int minNumOfModalsWSP2 int w = _mp.getWidth(rc); int h = _mp.getHeight(rc); - std::vector depthMap; - std::vector simMap; - std::vector numOfModalsMap; + image::Image depthMap; + image::Image simMap; + image::Image numOfModalsMap; { int width, height; image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, 1), - width, height, depthMap, image::EImageColorSpace::NO_CONVERSION); + depthMap, image::EImageColorSpace::NO_CONVERSION); image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::simMap, 1), - width, height, simMap, image::EImageColorSpace::NO_CONVERSION); + simMap, image::EImageColorSpace::NO_CONVERSION); image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::nmodMap), - width, height, numOfModalsMap, image::EImageColorSpace::NO_CONVERSION); + numOfModalsMap, image::EImageColorSpace::NO_CONVERSION); + } + + if (depthMap.Width() != simMap.Width() || depthMap.Width() != numOfModalsMap.Width() || + depthMap.Height() != simMap.Height() || depthMap.Height() != numOfModalsMap.Height()) + { + throw std::invalid_argument("depthMap, simMap and numOfModalsMap must have same size"); } int nbDepthValues = 0; - for(int i = 0; i < w * h; i++) + for(int i = 0; i < depthMap.size(); i++) { // if the point is part of a mask (alpha) skip - if(depthMap.at(i) <= -2.0f) + if (depthMap(i) <= -2.0f) continue; // if the reference point is consistent in three target cameras and is denoted as weakly supported point // make him strongly supported - if((numOfModalsMap.at(i) >= minNumOfModalsWSP2SSP - 1) && (simMap.at(i) >= 1.0f)) + if ((numOfModalsMap(i) >= minNumOfModalsWSP2SSP - 1) && (simMap(i) >= 1.0f)) { - simMap[i] = simMap[i] - 2.0f; + simMap(i) = simMap(i) - 2.0f; } // if it is conistent in only one camera and is weakly supported then remove him // weakly supported point must be consisten in at least two cameras - if((numOfModalsMap.at(i) <= 1) && (simMap.at(i) >= 1.0f)) + if ((numOfModalsMap(i) <= 1) && (simMap(i) >= 1.0f)) { - depthMap[i] = -1.0f; - simMap[i] = 1.0f; + depthMap(i) = -1.0f; + simMap(i) = 1.0f; } // if it is not conistent in minimal number of cameras and is strongly supported then remove him - if((numOfModalsMap.at(i) < minNumOfModals - 1) && (simMap.at(i) < 1.0f)) + if((numOfModalsMap(i) < minNumOfModals - 1) && (simMap(i) < 1.0f)) { - depthMap[i] = -1.0f; - simMap[i] = 1.0f; + depthMap(i) = -1.0f; + simMap(i) = 1.0f; } - if(depthMap[i] > 0.0f) + if(depthMap(i) > 0.0f) ++nbDepthValues; } @@ -329,12 +323,12 @@ bool Fuser::filterDepthMapsRC(int rc, int minNumOfModals, int minNumOfModalsWSP2 metadata.push_back(oiio::ParamValue("AliceVision:P", oiio::TypeDesc(oiio::TypeDesc::DOUBLE, oiio::TypeDesc::MATRIX44), 1, matrixP.data())); } - image::writeImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, 0), w, h, depthMap, - image::EImageQuality::LOSSLESS, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION), metadata); - image::writeImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::simMap, 0), w, h, simMap, - image::EImageQuality::OPTIMIZED, - image::OutputFileColorSpace(image::EImageColorSpace::NO_CONVERSION), metadata); + image::writeImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, 0), depthMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Float), metadata); + image::writeImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::simMap, 0), simMap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR) + .storageDataType(image::EStorageDataType::Half), metadata); ALICEVISION_LOG_DEBUG(rc << " solved."); mvsUtils::printfElapsedTime(t1); @@ -357,20 +351,19 @@ float Fuser::computeAveragePixelSizeInHexahedron(Point3d* hexah, int step, int s int rc = cams[c]; int h = _mp.getHeight(rc) / scaleuse; int w = _mp.getWidth(rc) / scaleuse; - StaticVector rcdepthMap; + image::Image rcdepthMap; - { - int width, height; - image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), - width, height, rcdepthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - } + image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), + rcdepthMap, image::EImageColorSpace::NO_CONVERSION); + + if (rcdepthMap.size() < w * h) + throw std::runtime_error("Invalid image size"); for(int y = 0; y < h; y++) { for(int x = 0; x < w; ++x) { - float depth = rcdepthMap[y * w + x]; + const float depth = rcdepthMap(y, x); if(depth > 0.0f) { if(j % step == 0) @@ -457,20 +450,15 @@ void Fuser::divideSpaceFromDepthMaps(Point3d* hexah, float& minPixSize) { int w = _mp.getWidth(rc); - StaticVector depthMap; - { - int width, height; + image::Image depthMap; + image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), + depthMap, image::EImageColorSpace::NO_CONVERSION); - image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), - width, height, depthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - } - - for(int i = 0; i < sizeOfStaticVector(&depthMap); i += stepPts) + for(int i = 0; i < depthMap.size(); i += stepPts) { int x = i % w; int y = i / w; - float depth = depthMap[i]; + float depth = depthMap(i); if(depth > 0.0f) { Point3d p = _mp.CArr[rc] + (_mp.iCamArr[rc] * Point2d((float)x, (float)y)).normalize() * depth; @@ -503,20 +491,16 @@ void Fuser::divideSpaceFromDepthMaps(Point3d* hexah, float& minPixSize) { int w = _mp.getWidth(rc); - StaticVector depthMap; - { - int width, height; + image::Image depthMap; - image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), - width, height, depthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - } + image::readImage(getFileNameFromIndex(_mp, rc, mvsUtils::EFileType::depthMap, scale), + depthMap, image::EImageColorSpace::NO_CONVERSION); for(int i = 0; i < depthMap.size(); i += stepPts) { int x = i % w; int y = i / w; - float depth = depthMap[i]; + float depth = depthMap(i); if(depth > 0.0f) { Point3d p = _mp.CArr[rc] + (_mp.iCamArr[rc] * Point2d((float)x, (float)y)).normalize() * depth; @@ -778,18 +762,17 @@ std::string generateTempPtsSimsFiles(const std::string& tmpDir, mvsUtils::MultiV pts->reserve(w * h); sims->reserve(w * h); - StaticVector depthMap; - StaticVector simMap; + image::Image depthMap; + image::Image simMap; + + image::readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::depthMap, scale), + depthMap, image::EImageColorSpace::NO_CONVERSION); + image::readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::simMap, scale), + simMap, image::EImageColorSpace::NO_CONVERSION); + if (depthMap.size() != (w * h) || simMap.size() != (w * h)) { - int width, height; - - image::readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::depthMap, scale), - width, height, depthMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); - image::readImage(getFileNameFromIndex(mp, rc, mvsUtils::EFileType::simMap, scale), - width, height, simMap.getDataWritable(), - image::EImageColorSpace::NO_CONVERSION); + throw std::runtime_error("Invalid image size"); } if(addRandomNoise) @@ -798,7 +781,7 @@ std::string generateTempPtsSimsFiles(const std::string& tmpDir, mvsUtils::MultiV idsAlive->reserve(w * h); for(int i = 0; i < w * h; i++) { - if(depthMap[i] > 0.0f) + if (depthMap(i) > 0.0f) { idsAlive->push_back(i); } @@ -816,9 +799,9 @@ std::string generateTempPtsSimsFiles(const std::string& tmpDir, mvsUtils::MultiV { int id = y * w + x; int i = (*idsAlive)[randIdsAlive[id]]; - double depth = depthMap[i]; + double depth = depthMap(i); - double sim = simMap[i]; + double sim = simMap(i); if(depth > 0.0f) { Point3d p = mp.CArr[rc] + @@ -873,8 +856,8 @@ std::string generateTempPtsSimsFiles(const std::string& tmpDir, mvsUtils::MultiV for(int y = 0; y < h; y++) { int i = x * h + y; - double depth = depthMap[i]; - double sim = simMap[i]; + double depth = depthMap(i); + double sim = simMap(i); if(depth > 0.0f) { Point3d p = diff --git a/src/aliceVision/fuseCut/Fuser.hpp b/src/aliceVision/fuseCut/Fuser.hpp index ad8818c85d..923786db5d 100644 --- a/src/aliceVision/fuseCut/Fuser.hpp +++ b/src/aliceVision/fuseCut/Fuser.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -46,7 +47,7 @@ class Fuser private: bool updateInSurr(float pixToleranceFactor, int pixSizeBall, int pixSizeBallWSP, Point3d& p, int rc, int tc, StaticVector* numOfPtsMap, - StaticVector* depthMap, StaticVector* simMap, int scale); + const image::Image& depthMap, const image::Image& simMap, int scale); }; unsigned long computeNumberOfAllPoints(const mvsUtils::MultiViewParams& mp, int scale); diff --git a/src/aliceVision/hdr/hdrTestCommon.hpp b/src/aliceVision/hdr/hdrTestCommon.hpp index df55a0bc69..bc443ea666 100644 --- a/src/aliceVision/hdr/hdrTestCommon.hpp +++ b/src/aliceVision/hdr/hdrTestCommon.hpp @@ -167,7 +167,8 @@ bool buildBrackets(std::vector& paths, std::vector& times, ALICEVISION_LOG_INFO("writing to " << temp.string()); - image::writeImage(temp.string(), img_bracket, image::EImageColorSpace::LINEAR); + image::writeImage(temp.string(), img_bracket, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR)); paths.push_back(temp.string()); } diff --git a/src/aliceVision/image/filtering_test.cpp b/src/aliceVision/image/filtering_test.cpp index 3fff73452a..4c62fc8812 100644 --- a/src/aliceVision/image/filtering_test.cpp +++ b/src/aliceVision/image/filtering_test.cpp @@ -33,8 +33,10 @@ BOOST_AUTO_TEST_CASE(Image_Convolution) Image outFiltered(250, 250, true); ImageGaussianFilter( in, 6.0, outFiltered); - BOOST_CHECK_NO_THROW(writeImage("in.png", in, image::EImageColorSpace::NO_CONVERSION)); - BOOST_CHECK_NO_THROW(writeImage("outfilter.png", outFiltered, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage("in.png", in, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); + BOOST_CHECK_NO_THROW(writeImage("outfilter.png", outFiltered, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); // Check that gaussian filtering have smooth at border of the white random square BOOST_CHECK(outFiltered(5,5)>0); @@ -80,8 +82,10 @@ BOOST_AUTO_TEST_CASE(Image_Convolution_Scharr_X_Y) Image inCast = Image(in.cast()); Image outFilteredCast = Image(outFiltered.cast()); - BOOST_CHECK_NO_THROW(writeImage("in_Scharr.png", inCast, image::EImageColorSpace::NO_CONVERSION)); - BOOST_CHECK_NO_THROW(writeImage("out_ScharrX.png", outFilteredCast, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage("in_Scharr.png", inCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); + BOOST_CHECK_NO_THROW(writeImage("out_ScharrX.png", outFilteredCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); outFiltered.fill(0.0f); ImageScaledScharrYDerivative( in, outFiltered, 1); @@ -95,7 +99,8 @@ BOOST_AUTO_TEST_CASE(Image_Convolution_Scharr_X_Y) // Check it exist a horizontal black band BOOST_CHECK_EQUAL(0.f, outFiltered.block(10+3,0,20-2*3,40).array().abs().sum()); outFilteredCast = Image(outFiltered.cast()); - BOOST_CHECK_NO_THROW(writeImage("out_ScharrY.png", outFilteredCast, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage("out_ScharrY.png", outFilteredCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); } BOOST_AUTO_TEST_CASE(Image_Convolution_Sobel_X_Y) @@ -118,8 +123,10 @@ BOOST_AUTO_TEST_CASE(Image_Convolution_Sobel_X_Y) Image inCast = Image(in.cast()); Image outFilteredCast = Image(outFiltered.cast()); - BOOST_CHECK_NO_THROW(writeImage("in_Scharr.png", inCast, image::EImageColorSpace::NO_CONVERSION)); - BOOST_CHECK_NO_THROW(writeImage("out_SobelX.png", outFilteredCast, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage("in_Scharr.png", inCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); + BOOST_CHECK_NO_THROW(writeImage("out_SobelX.png", outFilteredCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); outFiltered.fill(0.0f); ImageSobelYDerivative( in, outFiltered); @@ -133,5 +140,6 @@ BOOST_AUTO_TEST_CASE(Image_Convolution_Sobel_X_Y) // Check it exist a horizontal black band BOOST_CHECK_EQUAL(0.f, outFiltered.block(10+3,0,20-2*3,40).array().abs().sum()); outFilteredCast = Image(outFiltered.cast()); - BOOST_CHECK_NO_THROW(writeImage("out_SobelY.png", outFilteredCast, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage("out_SobelY.png", outFilteredCast, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); } diff --git a/src/aliceVision/image/imageAlgo.cpp b/src/aliceVision/image/imageAlgo.cpp index 0ecb6aa854..19f1638e9e 100644 --- a/src/aliceVision/image/imageAlgo.cpp +++ b/src/aliceVision/image/imageAlgo.cpp @@ -226,43 +226,6 @@ void colorconvert(oiio::ImageBuf& dst, const oiio::ImageBuf& src, colorconvert(dst, fromColorSpace, toColorSpace); } -template -void transposeImage(oiio::TypeDesc typeDesc, - int width, - int height, - int nchannels, - std::vector& buffer) -{ - oiio::ImageSpec imageSpec(width, height, nchannels, typeDesc); - - oiio::ImageBuf inBuf(imageSpec, buffer.data()); - oiio::ImageBuf transposeBuf; - - oiio::ImageBufAlgo::transpose(transposeBuf, inBuf, oiio::ROI::All()); - - transposeBuf.get_pixels(oiio::ROI::All(), typeDesc, buffer.data()); -} - -void transposeImage(int width, int height, std::vector& buffer) -{ - transposeImage(oiio::TypeDesc::UCHAR, width, height, 1, buffer); -} - -void transposeImage(int width, int height, std::vector& buffer) -{ - transposeImage(oiio::TypeDesc::UCHAR, width, height, 3, buffer); -} - -void transposeImage(int width, int height, std::vector& buffer) -{ - transposeImage(oiio::TypeDesc::FLOAT, width, height, 1, buffer); -} - -void transposeImage(int width, int height, std::vector& buffer) -{ - transposeImage(oiio::TypeDesc::FLOAT, width, height, 3, buffer); -} - template void resizeImage(oiio::TypeDesc typeDesc, int inWidth, @@ -282,45 +245,14 @@ void resizeImage(oiio::TypeDesc typeDesc, oiio::ImageBufAlgo::resize(outBuf, inBuf, filter, filterSize, oiio::ROI::All()); } -template -void resizeImage(oiio::TypeDesc typeDesc, - int inWidth, - int inHeight, - int nchannels, - int downscale, - const std::vector& inBuffer, - std::vector& outBuffer, - const std::string& filter = "", - float filterSize = 0) -{ - const int outWidth = inWidth / downscale; - const int outHeight = inHeight / downscale; - outBuffer.resize(outWidth * outHeight); - resizeImage(typeDesc, inWidth, inHeight, outWidth, outHeight, nchannels, - inBuffer.data(), outBuffer.data(), filter, filterSize); -} - -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter, float filterSize) -{ - resizeImage(oiio::TypeDesc::UCHAR, inWidth, inHeight, 1, downscale, inBuffer, outBuffer, filter, filterSize); -} - -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter, float filterSize) -{ - resizeImage(oiio::TypeDesc::UCHAR, inWidth, inHeight, 3, downscale, inBuffer, outBuffer, filter, filterSize); -} - -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter, float filterSize) +void resizeImage(int downscale, const image::Image& inImage, + image::Image& outImage, const std::string& filter, float filterSize) { - resizeImage(oiio::TypeDesc::FLOAT, inWidth, inHeight, 1, downscale, inBuffer, outBuffer, filter, filterSize); -} - -void resizeImage(int inWidth, int inHeight, int downscale, - const std::vector& inBuffer, - std::vector& outBuffer, - const std::string& filter, float filterSize) -{ - resizeImage(oiio::TypeDesc::FLOAT, inWidth, inHeight, 3, downscale, inBuffer, outBuffer, filter, filterSize); + const int outWidth = inImage.Width() / downscale; + const int outHeight = inImage.Height() / downscale; + outImage.resize(outWidth, outHeight); + resizeImage(oiio::TypeDesc::FLOAT, inImage.Width(), inImage.Height(), outWidth, outHeight, 1, + inImage.data(), outImage.data(), filter, filterSize); } void resizeImage(int downscale, const image::Image &inImage, @@ -350,43 +282,56 @@ void convolveImage(oiio::TypeDesc typeDesc, int inWidth, int inHeight, int nchannels, - const std::vector& inBuffer, - std::vector& outBuffer, + const T* inBuffer, + T* outBuffer, const std::string& kernel, float kernelWidth, float kernelHeight) { - outBuffer.resize(inBuffer.size()); - - const oiio::ImageBuf inBuf(oiio::ImageSpec(inWidth, inHeight, nchannels, typeDesc), const_cast(inBuffer.data())); - oiio::ImageBuf outBuf(oiio::ImageSpec(inWidth, inHeight, nchannels, typeDesc), outBuffer.data()); + const oiio::ImageBuf inBuf(oiio::ImageSpec(inWidth, inHeight, nchannels, typeDesc), const_cast(inBuffer)); + oiio::ImageBuf outBuf(oiio::ImageSpec(inWidth, inHeight, nchannels, typeDesc), outBuffer); oiio::ImageBuf K = oiio::ImageBufAlgo::make_kernel(kernel, kernelWidth, kernelHeight); oiio::ImageBufAlgo::convolve(outBuf, inBuf, K); } - -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel, float kernelWidth, float kernelHeight) +void convolveImage(const image::Image& inBuffer, + image::Image& outBuffer, + const std::string& kernel, float kernelWidth, float kernelHeight) { - convolveImage(oiio::TypeDesc::UCHAR, inWidth, inHeight, 1, inBuffer, outBuffer, kernel, kernelWidth, kernelHeight); + outBuffer.resize(inBuffer.Width(), inBuffer.Height()); + convolveImage(oiio::TypeDesc::UCHAR, inBuffer.Width(), inBuffer.Height(), 1, + inBuffer.data(), outBuffer.data(), + kernel, kernelWidth, kernelHeight); } -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel, float kernelWidth, float kernelHeight) +void convolveImage(const image::Image& inBuffer, image::Image& outBuffer, + const std::string& kernel, float kernelWidth, float kernelHeight) { - convolveImage(oiio::TypeDesc::UCHAR, inWidth, inHeight, 3, inBuffer, outBuffer, kernel, kernelWidth, kernelHeight); + outBuffer.resize(inBuffer.Width(), inBuffer.Height()); + convolveImage(oiio::TypeDesc::UCHAR, inBuffer.Width(), inBuffer.Height(), 3, + inBuffer.data(), outBuffer.data(), + kernel, kernelWidth, kernelHeight); } -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel, float kernelWidth, float kernelHeight) +void convolveImage(const image::Image& inBuffer, image::Image& outBuffer, + const std::string& kernel, float kernelWidth, float kernelHeight) { - convolveImage(oiio::TypeDesc::FLOAT, inWidth, inHeight, 1, inBuffer, outBuffer, kernel, kernelWidth, kernelHeight); + outBuffer.resize(inBuffer.Width(), inBuffer.Height()); + convolveImage(oiio::TypeDesc::FLOAT, inBuffer.Width(), inBuffer.Height(), 1, + inBuffer.data(), outBuffer.data(), + kernel, kernelWidth, kernelHeight); } -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, - std::vector& outBuffer, const std::string& kernel, - float kernelWidth, float kernelHeight) +void convolveImage(const image::Image& inBuffer, + image::Image& outBuffer, + const std::string& kernel, float kernelWidth, float kernelHeight) { - convolveImage(oiio::TypeDesc::FLOAT, inWidth, inHeight, 3, inBuffer, outBuffer, kernel, kernelWidth, kernelHeight); + outBuffer.resize(inBuffer.Width(), inBuffer.Height()); + convolveImage(oiio::TypeDesc::FLOAT, inBuffer.Width(), inBuffer.Height(), 3, + inBuffer.data(), outBuffer.data(), + kernel, kernelWidth, kernelHeight); } void fillHoles(int inWidth, int inHeight, image::RGBfColor* colorBuffer, @@ -410,12 +355,6 @@ void fillHoles(int inWidth, int inHeight, image::RGBfColor* colorBuffer, oiio::ImageBufAlgo::copy(rgbBuf, filledBuf); } -void fillHoles(int inWidth, int inHeight, std::vector& colorBuffer, - const std::vector& alphaBuffer) -{ - fillHoles(inWidth, inHeight, colorBuffer.data(), alphaBuffer); -} - void fillHoles(image::Image& image, const std::vector& alphaBuffer) { fillHoles(image.Width(), image.Height(), image.data(), alphaBuffer); diff --git a/src/aliceVision/image/imageAlgo.hpp b/src/aliceVision/image/imageAlgo.hpp index f507073908..406a94765d 100644 --- a/src/aliceVision/image/imageAlgo.hpp +++ b/src/aliceVision/image/imageAlgo.hpp @@ -46,21 +46,8 @@ void colorconvert(image::Image& image, image::EImageColorSpac void colorconvert(oiio::ImageBuf& dst, const oiio::ImageBuf& src, image::EImageColorSpace fromColorSpace, image::EImageColorSpace toColorSpace); -/** - * @brief transpose a given image buffer - * @param[in] width The image buffer width - * @param[in] height The image buffer height - * @param[in,out] buffer The image buffer - */ -void transposeImage(int width, int height, std::vector& buffer); -void transposeImage(int width, int height, std::vector& buffer); -void transposeImage(int width, int height, std::vector& buffer); -void transposeImage(int width, int height, std::vector& buffer); - /** * @brief resize a given image buffer - * @param[in] inWidth The input image buffer width - * @param[in] inHeight The input image buffer height * @param[in] downscale The resize downscale * @param[in] inBuffer The input image buffer * @param[out] outBuffer The output image buffer @@ -69,12 +56,8 @@ void transposeImage(int width, int height, std::vector& buffer * See openImageIO documentation "ImageBufAlgo filtername" * @param[in] filterSize The resize filter size */ -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter = "", float filterSize = 0); -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter = "", float filterSize = 0); -void resizeImage(int inWidth, int inHeight, int downscale, const std::vector& inBuffer, std::vector& outBuffer, const std::string& filter = "", float filterSize = 0); -void resizeImage(int inWidth, int inHeight, int downscale, - const std::vector& inBuffer, - std::vector& outBuffer, +void resizeImage(int downscale, const image::Image& inImage, + image::Image& outImage, const std::string& filter = "", float filterSize = 0); void resizeImage(int downscale, const image::Image& inImage, image::Image& outImage, @@ -85,8 +68,6 @@ void resizeImage(int downscale, const image::Image& inImage, /** * @brief convolve a given image buffer - * @param[in] inWidth The input image buffer width - * @param[in] inHeight The input image buffer heightt * @param[in] inBuffer The input image buffer * @param[out] outBuffer outBuffer The output image buffer * @param[in] kernel The kernel name, can be "gaussian", "sharp-gaussian", "box", ... @@ -95,23 +76,30 @@ void resizeImage(int downscale, const image::Image& inImage, * @param[in] kernelWidth The kernel width * @param[in] kernelHeight The kernal height */ -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel = "gaussian", float kernelWidth = 5.0f, float kernelHeight = 5.0f); -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel = "gaussian", float kernelWidth = 5.0f, float kernelHeight = 5.0f); -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, std::vector& outBuffer, const std::string& kernel = "gaussian", float kernelWidth = 5.0f, float kernelHeight = 5.0f); -void convolveImage(int inWidth, int inHeight, const std::vector& inBuffer, - std::vector& outBuffer, +void convolveImage(const image::Image& inBuffer, + image::Image& outBuffer, const std::string& kernel = "gaussian", float kernelWidth = 5.0f, float kernelHeight = 5.0f); +void convolveImage(const image::Image& inBuffer, image::Image& outBuffer, + const std::string& kernel = "gaussian", + float kernelWidth = 5.0f, float kernelHeight = 5.0f); + +void convolveImage(const image::Image& inBuffer, image::Image& outBuffer, + const std::string& kernel = "gaussian", + float kernelWidth = 5.0f, float kernelHeight = 5.0f); + +void convolveImage(const image::Image& inBuffer, + image::Image& outBuffer, + const std::string& kernel = "gaussian", + float kernelWidth = 5.0f, float kernelHeight = 5.0f); + + /** * @brief fill holes in a given image buffer with plausible values - * @param[in] inWidth The input image buffer width - * @param[in] inHeight The input image buffer height * @param[in,out] colorBuffer The image buffer to fill * @param[in] alphaBuffer The input alpha buffer containing 0.0/1.0 for empty/valid pixels */ -void fillHoles(int inWidth, int inHeight, std::vector& colorBuffer, - const std::vector& alphaBuffer); void fillHoles(image::Image& image, const std::vector& alphaBuffer); /** diff --git a/src/aliceVision/image/io.cpp b/src/aliceVision/image/io.cpp index 0dae40f6f0..72bec0791a 100644 --- a/src/aliceVision/image/io.cpp +++ b/src/aliceVision/image/io.cpp @@ -155,7 +155,8 @@ std::string EStorageDataType_informations() return EStorageDataType_enumToString(EStorageDataType::Float) + ", " + EStorageDataType_enumToString(EStorageDataType::Half) + ", " + EStorageDataType_enumToString(EStorageDataType::HalfFinite) + ", " + - EStorageDataType_enumToString(EStorageDataType::Auto); + EStorageDataType_enumToString(EStorageDataType::Auto) + ", " + + EStorageDataType_enumToString(EStorageDataType::Undefined); } EStorageDataType EStorageDataType_stringToEnum(const std::string& dataType) @@ -167,6 +168,7 @@ EStorageDataType EStorageDataType_stringToEnum(const std::string& dataType) if (type == "half") return EStorageDataType::Half; if (type == "halffinite") return EStorageDataType::HalfFinite; if (type == "auto") return EStorageDataType::Auto; + if (type == "undefined") return EStorageDataType::Undefined; throw std::out_of_range("Invalid EStorageDataType: " + dataType); } @@ -179,6 +181,7 @@ std::string EStorageDataType_enumToString(const EStorageDataType dataType) case EStorageDataType::Half: return "half"; case EStorageDataType::HalfFinite: return "halfFinite"; case EStorageDataType::Auto: return "auto"; + case EStorageDataType::Undefined: return "undefined"; } throw std::out_of_range("Invalid EStorageDataType enum"); } @@ -506,7 +509,7 @@ void writeImage(const std::string& path, oiio::TypeDesc typeDesc, int nchannels, const Image& image, - OutputFileColorSpace colorspace, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList(), const oiio::ROI& roi = oiio::ROI()) { @@ -518,12 +521,15 @@ void writeImage(const std::string& path, const bool isJPG = (extension == ".jpg"); const bool isPNG = (extension == ".png"); - if (colorspace.to == EImageColorSpace::AUTO) + auto toColorSpace = options.getToColorSpace(); + auto fromColorSpace = options.getFromColorSpace(); + + if (toColorSpace == EImageColorSpace::AUTO) { if (isJPG || isPNG) - colorspace.to = EImageColorSpace::SRGB; + toColorSpace = EImageColorSpace::SRGB; else - colorspace.to = EImageColorSpace::LINEAR; + toColorSpace = EImageColorSpace::LINEAR; } @@ -543,18 +549,20 @@ void writeImage(const std::string& path, } std::string currentColorSpace = imageSpec.get_string_attribute("AliceVision:ColorSpace", "Linear"); - imageSpec.attribute("AliceVision:ColorSpace", (colorspace.to == EImageColorSpace::NO_CONVERSION) ? currentColorSpace : EImageColorSpace_enumToString(colorspace.to)); + imageSpec.attribute("AliceVision:ColorSpace", + (toColorSpace == EImageColorSpace::NO_CONVERSION) + ? currentColorSpace : EImageColorSpace_enumToString(toColorSpace)); const oiio::ImageBuf imgBuf = oiio::ImageBuf(imageSpec, const_cast(image.data())); // original image buffer const oiio::ImageBuf* outBuf = &imgBuf; // buffer to write oiio::ImageBuf colorspaceBuf; // buffer for image colorspace modification - if (colorspace.from == colorspace.to) + if (fromColorSpace == toColorSpace) { // Do nothing. Note that calling imageAlgo::colorconvert() will copy the source buffer // even if no conversion is needed. } - else if((colorspace.to == EImageColorSpace::ACES2065_1) || (colorspace.to == EImageColorSpace::ACEScg)) + else if ((toColorSpace == EImageColorSpace::ACES2065_1) || (toColorSpace == EImageColorSpace::ACEScg)) { const auto colorConfigPath = getAliceVisionOCIOConfig(); if (colorConfigPath.empty()) @@ -564,20 +572,29 @@ void writeImage(const std::string& path, oiio::ColorConfig colorConfig(colorConfigPath); oiio::ImageBufAlgo::colorconvert(colorspaceBuf, *outBuf, - EImageColorSpace_enumToOIIOString(colorspace.from), - EImageColorSpace_enumToOIIOString(colorspace.to), true, "", "", + EImageColorSpace_enumToOIIOString(fromColorSpace), + EImageColorSpace_enumToOIIOString(toColorSpace), true, "", "", &colorConfig); outBuf = &colorspaceBuf; } else { - imageAlgo::colorconvert(colorspaceBuf, *outBuf, colorspace.from, colorspace.to); + imageAlgo::colorconvert(colorspaceBuf, *outBuf, fromColorSpace, toColorSpace); outBuf = &colorspaceBuf; } oiio::ImageBuf formatBuf; // buffer for image format modification if(isEXR) { + // Storage data type may be saved as attributes to formats that support it and then come back + // as metadata to this function. Therefore we store the storage data type to attributes if it + // is set and load it from attributes if it isn't set. + if (options.getStorageDataType() != EStorageDataType::Undefined) + { + imageSpec.attribute("AliceVision:storageDataType", + EStorageDataType_enumToString(options.getStorageDataType())); + } + const std::string storageDataTypeStr = imageSpec.get_string_attribute("AliceVision:storageDataType", EStorageDataType_enumToString(EStorageDataType::HalfFinite)); EStorageDataType storageDataType = EStorageDataType_stringToEnum(storageDataTypeStr); @@ -620,7 +637,7 @@ template void writeImageNoFloat(const std::string& path, oiio::TypeDesc typeDesc, const Image& image, - EImageColorSpace imageColorSpace, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList()) { const fs::path bPath = fs::path(path); @@ -631,6 +648,7 @@ void writeImageNoFloat(const std::string& path, const bool isJPG = (extension == ".jpg"); const bool isPNG = (extension == ".png"); + auto imageColorSpace = options.getToColorSpace(); if(imageColorSpace == EImageColorSpace::AUTO) { if(isJPG || isPNG) @@ -704,84 +722,75 @@ void readImage(const std::string& path, Image& image, const ImageReadO readImage(path, oiio::TypeDesc::UINT8, 3, image, imageReadOptions); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImageNoFloat(path, oiio::TypeDesc::UINT8, image, outputImageColorSpace, metadata); + writeImageNoFloat(path, oiio::TypeDesc::UINT8, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImageNoFloat(path, oiio::TypeDesc::INT32, image, outputImageColorSpace, metadata); + writeImageNoFloat(path, oiio::TypeDesc::INT32, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImageNoFloat(path, oiio::TypeDesc::UINT32, image, outputImageColorSpace, metadata); + writeImageNoFloat(path, oiio::TypeDesc::UINT32, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata, const oiio::ROI& roi) -{ - writeImage(path, oiio::TypeDesc::FLOAT, 4, image, - OutputFileColorSpace{EImageColorSpace::LINEAR, outputImageColorSpace }, metadata,roi); -} - -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata, + const oiio::ROI& roi) { - writeImage(path, oiio::TypeDesc::UINT8, 4, image, - OutputFileColorSpace{EImageColorSpace::LINEAR, outputImageColorSpace }, metadata); + writeImage(path, oiio::TypeDesc::FLOAT, 1, image, options, metadata,roi); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata, const oiio::ROI &roi) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata, + const oiio::ROI& roi) { - writeImage(path, oiio::TypeDesc::FLOAT, 3, image, - OutputFileColorSpace{EImageColorSpace::LINEAR, outputImageColorSpace }, metadata,roi); + writeImage(path, oiio::TypeDesc::FLOAT, 4, image, options, metadata,roi); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata, const oiio::ROI& roi) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImage(path, oiio::TypeDesc::FLOAT, 1, image, - OutputFileColorSpace{EImageColorSpace::LINEAR, outputImageColorSpace }, metadata,roi); + writeImage(path, oiio::TypeDesc::UINT8, 4, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata, + const oiio::ROI& roi) { - writeImage(path, oiio::TypeDesc::UINT8, 3, image, - OutputFileColorSpace{EImageColorSpace::LINEAR, outputImageColorSpace }, metadata); + writeImage(path, oiio::TypeDesc::FLOAT, 3, image, options, metadata, roi); } -void writeImage(const std::string& path, const Image& image, OutputFileColorSpace colorspace, - const oiio::ParamValueList& metadata, const oiio::ROI& roi) +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImage(path, oiio::TypeDesc::FLOAT, 1, image, colorspace, metadata,roi); + writeImage(path, oiio::TypeDesc::UINT8, 3, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, const oiio::ParamValueList& metadata, - const oiio::ROI& roi) +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImage(path, oiio::TypeDesc::FLOAT, 4, image, colorspace, metadata,roi); + writeImage(path, oiio::TypeDesc::UINT8, 1, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, - const oiio::ParamValueList& metadata) +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImage(path, oiio::TypeDesc::UINT8, 4, image, colorspace, metadata); + writeImage(path, oiio::TypeDesc::INT32, 1, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, const oiio::ParamValueList& metadata, - const oiio::ROI& roi) +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, const oiio::ParamValueList& metadata) { - writeImage(path, oiio::TypeDesc::FLOAT, 3, image, colorspace, metadata, roi); + writeImage(path, oiio::TypeDesc::UINT32, 1, image, options, metadata); } -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::UINT8, 3, image, colorspace, metadata); -} bool tryLoadMask(Image* mask, const std::vector& masksFolders, const IndexT viewId, const std::string & srcImage) @@ -809,245 +818,6 @@ bool tryLoadMask(Image* mask, const std::vector& mas return false; } -template -void readImage(const std::string& path, - oiio::TypeDesc typeDesc, - int nchannels, - int& width, - int& height, - std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - ALICEVISION_LOG_DEBUG("[IO] Read Image: " << path); - - // check requested channels number - if (nchannels == 0) - throw std::runtime_error("Requested channels is 0. Image file: '" + path + "'."); - if (nchannels == 2) - throw std::runtime_error("Load of 2 channels is not supported. Image file: '" + path + "'."); - - oiio::ImageSpec configSpec; - - // libRAW configuration - configSpec.attribute("raw:auto_bright", 0); // don't want exposure correction - configSpec.attribute("raw:use_camera_wb", 1); // want white balance correction - configSpec.attribute("raw:use_camera_matrix", 3); // want to use embeded color profile - configSpec.attribute("raw:ColorSpace", "Linear"); // want linear colorspace with sRGB primaries - - oiio::ImageBuf inBuf(path, 0, 0, NULL, &configSpec); - - inBuf.read(0, 0, true, oiio::TypeDesc::FLOAT); // force image convertion to float (for grayscale and color space convertion) - - if(!inBuf.initialized()) - throw std::runtime_error("Cannot find/open image file '" + path + "'."); - - const oiio::ImageSpec& inSpec = inBuf.spec(); - - // check picture channels number - if (inSpec.nchannels == 0) - throw std::runtime_error("No channel in the input image file: '" + path + "'."); - if (inSpec.nchannels == 2) - throw std::runtime_error("Load of 2 channels is not supported. Image file: '" + path + "'."); - - // color conversion - if (toColorSpace == image::EImageColorSpace::AUTO) - throw std::runtime_error("You must specify a requested color space for image file '" + path + "'."); - - const std::string& fromColorSpaceName = inSpec.get_string_attribute("oiio:ColorSpace", "sRGB"); // default image color space is sRGB - ALICEVISION_LOG_TRACE("Read image " << path << " (encoded in " << fromColorSpaceName << " colorspace)."); - const auto fromColorSpace = image::EImageColorSpace_OIIOstringToEnum(fromColorSpaceName); - - if (toColorSpace != image::EImageColorSpace::NO_CONVERSION) - imageAlgo::colorconvert(inBuf, fromColorSpace, toColorSpace); - - // convert to grayscale if needed - if(nchannels == 1 && inSpec.nchannels >= 3) - { - // convertion region of interest (for inSpec.nchannels > 3) - oiio::ROI convertionROI = inBuf.roi(); - convertionROI.chbegin = 0; - convertionROI.chend = 3; - - // compute luminance via a weighted sum of R,G,B - // (assuming Rec709 primaries and a linear scale) - const float weights[3] = {.2126, .7152, .0722}; - oiio::ImageBuf grayscaleBuf; - oiio::ImageBufAlgo::channel_sum(grayscaleBuf, inBuf, weights, convertionROI); - inBuf.copy(grayscaleBuf); - - // TODO: if inSpec.nchannels == 4: premult? - } - - // duplicate first channel for RGB - if (nchannels >= 3 && inSpec.nchannels == 1) - { - oiio::ImageSpec requestedSpec(inSpec.width, inSpec.height, 3, typeDesc); - oiio::ImageBuf requestedBuf(requestedSpec); - int channelOrder[] = { 0, 0, 0 }; - float channelValues[] = { 0 /*ignore*/, 0 /*ignore*/, 0 /*ignore*/ }; - oiio::ImageBufAlgo::channels(requestedBuf, inBuf, 3, channelOrder, channelValues); - inBuf.swap(requestedBuf); - } - - // Add an alpha channel if needed - if (nchannels == 4 && inBuf.spec().nchannels == 3) - { - oiio::ImageSpec requestedSpec(inSpec.width, inSpec.height, 3, typeDesc); - oiio::ImageBuf requestedBuf(requestedSpec); - int channelOrder[] = { 0, 1, 2, -1 /*constant value*/ }; - float channelValues[] = { 0 /*ignore*/, 0 /*ignore*/, 0 /*ignore*/, 1.0 }; - oiio::ImageBufAlgo::channels(requestedBuf, inBuf, - 4, // create an image with 4 channels - channelOrder, - channelValues); // only the 4th value is used - inBuf.swap(requestedBuf); - } - - width = inSpec.width; - height = inSpec.height; - - buffer.resize(inSpec.width * inSpec.height); - - { - oiio::ROI exportROI = inBuf.roi(); - exportROI.chbegin = 0; - exportROI.chend = nchannels; - - inBuf.get_pixels(exportROI, typeDesc, buffer.data()); - } -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::UCHAR, 1, width, height, buffer, toColorSpace); -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::UINT16, 1, width, height, buffer, toColorSpace); -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::UCHAR, 3, width, height, buffer, toColorSpace); -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::FLOAT, 1, width, height, buffer, toColorSpace); -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::FLOAT, 3, width, height, buffer, toColorSpace); -} - -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - image::EImageColorSpace toColorSpace) -{ - readImage(path, oiio::TypeDesc::FLOAT, 4, width, height, buffer, toColorSpace); -} - -template -void writeImage(const std::string& path, - oiio::TypeDesc typeDesc, - int width, - int height, - int nchannels, - const std::vector& buffer, - EImageQuality imageQuality, - OutputFileColorSpace colorspace, - const oiio::ParamValueList& metadata) -{ - const fs::path bPath = fs::path(path); - const std::string extension = bPath.extension().string(); - const std::string tmpPath = (bPath.parent_path() / bPath.stem()).string() + "." + fs::unique_path().string() + extension; - const bool isEXR = (extension == ".exr"); - //const bool isTIF = (extension == ".tif"); - const bool isJPG = (extension == ".jpg"); - const bool isPNG = (extension == ".png"); - - if (colorspace.to == image::EImageColorSpace::AUTO) - { - if (isJPG || isPNG) - colorspace.to = image::EImageColorSpace::SRGB; - else - colorspace.to = image::EImageColorSpace::LINEAR; - } - - ALICEVISION_LOG_DEBUG("[IO] Write Image: " << path << std::endl - << "\t- width: " << width << std::endl - << "\t- height: " << height << std::endl - << "\t- channels: " << nchannels); - - oiio::ImageSpec imageSpec(width, height, nchannels, typeDesc); - imageSpec.extra_attribs = metadata; // add custom metadata - - imageSpec.attribute("jpeg:subsampling", "4:4:4"); // if possible, always subsampling 4:4:4 for jpeg - imageSpec.attribute("compression", isEXR ? "zips" : "none"); // if possible, set compression (zips for EXR, none for the other) - - const oiio::ImageBuf imgBuf = oiio::ImageBuf(imageSpec, const_cast(buffer.data())); // original image buffer - const oiio::ImageBuf* outBuf = &imgBuf; // buffer to write - - oiio::ImageBuf colorspaceBuf; // buffer for image colorspace modification - imageAlgo::colorconvert(colorspaceBuf, *outBuf, colorspace.from, colorspace.to); - outBuf = &colorspaceBuf; - - oiio::ImageBuf formatBuf; // buffer for image format modification - if (imageQuality == EImageQuality::OPTIMIZED && isEXR) - { - formatBuf.copy(*outBuf, oiio::TypeDesc::HALF); // override format, use half instead of float - outBuf = &formatBuf; - } - - // write image - if (!outBuf->write(tmpPath)) - throw std::runtime_error("Can't write output image file '" + path + "'."); - - // rename temporary filename - fs::rename(tmpPath, path); -} - -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::UCHAR, width, height, 1, buffer, imageQuality, colorspace, metadata); -} - -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::UINT16, width, height, 1, buffer, imageQuality, colorspace, metadata); -} - -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::UCHAR, width, height, 3, buffer, imageQuality, colorspace, metadata); -} - -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::FLOAT, width, height, 1, buffer, imageQuality, colorspace, metadata); -} - -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata) -{ - writeImage(path, oiio::TypeDesc::FLOAT, width, height, 3, buffer, imageQuality, colorspace, metadata); -} - static std::string aliceVisionRootOverride; std::string getAliceVisionRoot() diff --git a/src/aliceVision/image/io.hpp b/src/aliceVision/image/io.hpp index 3588b0ee14..694b70650b 100644 --- a/src/aliceVision/image/io.hpp +++ b/src/aliceVision/image/io.hpp @@ -26,27 +26,6 @@ class rgb; namespace image { -struct OutputFileColorSpace -{ - EImageColorSpace from{EImageColorSpace::LINEAR}; - EImageColorSpace to{EImageColorSpace::AUTO}; - - OutputFileColorSpace(EImageColorSpace from_, EImageColorSpace to_) - : from(from_) - , to(to_) - { - } - /// @brief Assumes that @p from is LINEAR - explicit OutputFileColorSpace(EImageColorSpace to_) - { - if(to_ == EImageColorSpace::NO_CONVERSION) - to = from; - else - to = to_; - } - OutputFileColorSpace() = default; -}; - /** * @brief Available image file type for pipeline output */ @@ -59,25 +38,6 @@ enum class EImageFileType NONE }; -/** - * @brief aggregate for multiple image reading options - */ -struct ImageReadOptions -{ - ImageReadOptions(EImageColorSpace colorSpace = EImageColorSpace::AUTO, bool useWhiteBalance = true, const oiio::ROI & roi = oiio::ROI()) : - workingColorSpace(colorSpace), applyWhiteBalance(useWhiteBalance), subROI(roi) - { - } - - EImageColorSpace workingColorSpace; - bool applyWhiteBalance; - - //ROI for this image. - //If the image contains an roi, this is the roi INSIDE the roi. - oiio::ROI subROI; -}; - - /** * @brief get informations about each image file type * @return String @@ -136,7 +96,8 @@ enum class EStorageDataType Float, //< Use full floating point precision to store Half, //< Use half (values our of range could become inf or nan) HalfFinite, //< Use half, but ensures out-of-range pixels are clamps to keep finite pixel values - Auto //< Use half if all pixels can be stored in half without clamp, else use full float + Auto, //< Use half if all pixels can be stored in half without clamp, else use full float + Undefined //< Storage data type is not defined and should be inferred from other sources }; std::string EStorageDataType_informations(); @@ -190,6 +151,64 @@ std::ostream& operator<<(std::ostream& os, EImageQuality imageQuality); */ std::istream& operator>>(std::istream& in, EImageQuality& imageQuality); + +/** + * @brief aggregate for multiple image reading options + */ +struct ImageReadOptions +{ + ImageReadOptions(EImageColorSpace colorSpace = EImageColorSpace::AUTO, + bool useWhiteBalance = true, const oiio::ROI & roi = oiio::ROI()) : + workingColorSpace(colorSpace), + applyWhiteBalance(useWhiteBalance), + subROI(roi) + { + } + + EImageColorSpace workingColorSpace; + bool applyWhiteBalance; + + //ROI for this image. + //If the image contains an roi, this is the roi INSIDE the roi. + oiio::ROI subROI; +}; + +/** + * @brief aggregate for multiple image writing options + */ +class ImageWriteOptions +{ +public: + ImageWriteOptions() = default; + + EImageColorSpace getFromColorSpace() const { return _fromColorSpace; } + EImageColorSpace getToColorSpace() const { return _toColorSpace; } + EStorageDataType getStorageDataType() const { return _storageDataType; } + + ImageWriteOptions& fromColorSpace(EImageColorSpace colorSpace) + { + _fromColorSpace = colorSpace; + return *this; + } + + ImageWriteOptions& toColorSpace(EImageColorSpace colorSpace) + { + _toColorSpace = colorSpace; + return *this; + } + + ImageWriteOptions& storageDataType(EStorageDataType storageDataType) + { + _storageDataType = storageDataType; + return *this; + } + +private: + EImageColorSpace _fromColorSpace{EImageColorSpace::LINEAR}; + EImageColorSpace _toColorSpace{EImageColorSpace::AUTO}; + EStorageDataType _storageDataType{EStorageDataType::Undefined}; +}; + /** * @brief Test if the extension is supported for undistorted images. * @param[in] ext The extension with the dot (eg ".png") @@ -282,81 +301,53 @@ void readImageDirect(const std::string& path, Image& image); * @param[in] path The given path to the image * @param[in] image The output image buffer */ -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata = oiio::ParamValueList(),const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata = oiio::ParamValueList(),const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace,const oiio::ParamValueList& metadata = oiio::ParamValueList(),const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, EImageColorSpace outputImageColorSpace, const oiio::ParamValueList& metadata = oiio::ParamValueList()); - -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace imageColorSpace, +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); + +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); + +void writeImage(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); + +void writeImage(const std::string& path, const Image& image, const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList(), const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, +void writeImage(const std::string& path, const Image& image, const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList(), const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, +void writeImage(const std::string& path, const Image& image, const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, +void writeImage(const std::string& path, const Image& image, const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList(), const oiio::ROI& roi = oiio::ROI()); -void writeImage(const std::string& path, const Image& image, - OutputFileColorSpace colorspace, +void writeImage(const std::string& path, const Image& image, const ImageWriteOptions& options, const oiio::ParamValueList& metadata = oiio::ParamValueList()); /** - * @brief read an image with a given path and buffer + * @brief write an image with a given path and buffer, converting to float as necessary to perform + * intermediate calculations. * @param[in] path The given path to the image - * @param[out] width The output image width - * @param[out] height The output image height - * @param[out] buffer The output image buffer - * @param[in] image color space + * @param[in] image The output image buffer */ -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); -void readImage(const std::string& path, int& width, int& height, std::vector& buffer, - EImageColorSpace toColorSpace); +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); -/** - * @brief write an image with a given path and buffer - * @param[in] path The given path to the image - * @param[in] width The input image width - * @param[in] height The input image height - * @param[in] buffer The input image buffer - */ -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata = oiio::ParamValueList()); -void writeImage(const std::string& path, int width, int height, const std::vector& buffer, - EImageQuality imageQuality, const OutputFileColorSpace& colorspace, - const oiio::ParamValueList& metadata = oiio::ParamValueList()); +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); + +void writeImageWithFloat(const std::string& path, const Image& image, + const ImageWriteOptions& options, + const oiio::ParamValueList& metadata = oiio::ParamValueList()); template struct ColorTypeInfo diff --git a/src/aliceVision/image/io_test.cpp b/src/aliceVision/image/io_test.cpp index 9bcb95ee3d..c8f31e3b6d 100644 --- a/src/aliceVision/image/io_test.cpp +++ b/src/aliceVision/image/io_test.cpp @@ -146,7 +146,8 @@ BOOST_AUTO_TEST_CASE(read_write_grayscale) { for(const auto& extension : extensions) { const std::string filename = "test_write." + extension; - BOOST_CHECK_NO_THROW(writeImage(filename, image, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage(filename, image, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); Image read_image; BOOST_CHECK_NO_THROW(readImage(filename, read_image, image::EImageColorSpace::NO_CONVERSION)); @@ -164,7 +165,8 @@ BOOST_AUTO_TEST_CASE(read_write_rgb) { for(const auto& extension : extensions) { const std::string filename = "test_write_rgb." + extension; - BOOST_CHECK_NO_THROW(writeImage(filename, image, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage(filename, image, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); Image read_image; BOOST_CHECK_NO_THROW(readImage(filename, read_image, image::EImageColorSpace::NO_CONVERSION)); @@ -196,7 +198,8 @@ BOOST_AUTO_TEST_CASE(read_write_rgba) { continue; // doesn't support 4 channels const std::string filename = "test_write_rgba." + extension; - BOOST_CHECK_NO_THROW(writeImage(filename, image, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage(filename, image, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); Image read_image; BOOST_CHECK_NO_THROW(readImage(filename, read_image, image::EImageColorSpace::NO_CONVERSION)); @@ -224,7 +227,8 @@ BOOST_AUTO_TEST_CASE(read_write_from_rgb_to_grayscale) { for(const auto& extension : extensions) { const std::string filename = "test_write_from_grayscale." + extension; - BOOST_CHECK_NO_THROW(writeImage(filename, imageRGB, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage(filename, imageRGB, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); Image read_image; BOOST_CHECK_NO_THROW(readImage(filename, read_image, image::EImageColorSpace::NO_CONVERSION)); @@ -245,7 +249,8 @@ BOOST_AUTO_TEST_CASE(read_write_from_grayscale_to_rgb) { for(const auto& extension : extensions) { const std::string filename = "test_write_from_rgb." + extension; - BOOST_CHECK_NO_THROW(writeImage(filename, imageGrayscale, image::EImageColorSpace::NO_CONVERSION)); + BOOST_CHECK_NO_THROW(writeImage(filename, imageGrayscale, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); Image read_image; BOOST_CHECK_NO_THROW(readImage(filename, read_image, image::EImageColorSpace::NO_CONVERSION)); diff --git a/src/aliceVision/image/resampling_test.cpp b/src/aliceVision/image/resampling_test.cpp index 7fcfacd667..21621df3c1 100644 --- a/src/aliceVision/image/resampling_test.cpp +++ b/src/aliceVision/image/resampling_test.cpp @@ -46,7 +46,8 @@ BOOST_AUTO_TEST_CASE(Ressampling_SampleSamePosition) GenericRessample( image , sampling_grid , image.Width() , image.Height() , sampler , imageOut ) ; std::string out_filename = ("test_ressample_same.png"); - BOOST_CHECK_NO_THROW( writeImage( out_filename, imageOut, image::EImageColorSpace::NO_CONVERSION) ) ; + BOOST_CHECK_NO_THROW( writeImage( out_filename, imageOut, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION))); } // Iterative image rotations @@ -105,7 +106,8 @@ void ImageRotation( std::stringstream str ; str << "test_ressample_"<< samplerString <<"_rotate_" << id_rot << ".png" ; - writeImage(str.str(), imageOut, image::EImageColorSpace::NO_CONVERSION); + writeImage(str.str(), imageOut, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); image = imageOut ; } } diff --git a/src/aliceVision/mesh/Texturing.cpp b/src/aliceVision/mesh/Texturing.cpp index e1407bb73d..c9b40e72c2 100644 --- a/src/aliceVision/mesh/Texturing.cpp +++ b/src/aliceVision/mesh/Texturing.cpp @@ -905,11 +905,10 @@ void Texturing::writeTexture(AccuImage& atlasTexture, const std::size_t atlasID, bfs::path texturePath = outPath / textureName; ALICEVISION_LOG_INFO(" - Writing texture file: " << texturePath.string()); - image::OutputFileColorSpace colorspace(texParams.processColorspace, image::EImageColorSpace::AUTO); - oiio::ParamValueList metadata; - metadata.push_back(oiio::ParamValue("AliceVision:storageDataType", - EStorageDataType_enumToString(image::EStorageDataType::Half))); - image::writeImage(texturePath.string(), atlasTexture.img, colorspace, metadata); + image::writeImage(texturePath.string(), atlasTexture.img, + image::ImageWriteOptions().fromColorSpace(texParams.processColorspace) + .toColorSpace(image::EImageColorSpace::AUTO) + .storageDataType(image::EStorageDataType::Half)); } @@ -1312,8 +1311,8 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp ALICEVISION_LOG_INFO("Generating Height and Normal Maps for atlas " << atlasID + 1 << "/" << _atlases.size() << " (" << _atlases[atlasID].size() << " triangles)."); - std::vector normalMap(texParams.textureSide * texParams.textureSide); - std::vector heightMap(texParams.textureSide * texParams.textureSide); + image::Image normalMap(texParams.textureSide, texParams.textureSide); + image::Image heightMap(texParams.textureSide, texParams.textureSide); const auto& triangles = _atlases[atlasID]; // iterate over atlas' triangles @@ -1412,7 +1411,7 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp if(intersection) { computeNormalHeight(*denseMeshAABB.mesh(), 1.0, t, f, worldToTriangleMatrix, q, qA1, qB1, - heightMap[xyoffset], normalMap[xyoffset]); + heightMap(xyoffset), normalMap(xyoffset)); } else { @@ -1422,12 +1421,12 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp if(intersection) { computeNormalHeight(*denseMeshAABB.mesh(), -1.0, t, f, worldToTriangleMatrix, q, qA2, qB2, - heightMap[xyoffset], normalMap[xyoffset]); + heightMap(xyoffset), normalMap(xyoffset)); } else { - heightMap[xyoffset] = 0.0f; - normalMap[xyoffset] = image::RGBfColor(0.0f, 0.0f, 0.0f); + heightMap(xyoffset) = 0.0f; + normalMap(xyoffset) = image::RGBfColor(0.0f, 0.0f, 0.0f); } } } @@ -1442,12 +1441,11 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp if(texParams.downscale > 1) { ALICEVISION_LOG_INFO("Downscaling normal map (" << texParams.downscale << "x)."); - std::vector resizedBuffer; + image::Image resizedBuffer; outTextureSide = texParams.textureSide / texParams.downscale; // use nearest-neighbor interpolation to avoid meaningless interpolation of normals on edges. const std::string interpolation = "box"; - imageAlgo::resizeImage(texParams.textureSide, texParams.textureSide, texParams.downscale, normalMap, - resizedBuffer, interpolation); + imageAlgo::resizeImage(texParams.downscale, normalMap, resizedBuffer, interpolation); std::swap(resizedBuffer, normalMap); } @@ -1456,22 +1454,22 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp // Y: -1 to +1 : Green : 0 to 255 // Z: 0 to -1 : Blue : 128 to 255 OR 0 to 255 (like Blender) for(unsigned int i = 0; i < normalMap.size(); ++i) - // normalMap[i] = image::RGBfColor(normalMap[i].r * 0.5 + 0.5, + // normalMap(i) = image::RGBfColor(normalMap[i].r * 0.5 + 0.5, // normalMap[i].g * 0.5 + 0.5, // normalMap[i].b); // B: // 0:+1 => 0-255 - normalMap[i] = image::RGBfColor(normalMap[i].r() * 0.5 + 0.5, - normalMap[i].g() * 0.5 + 0.5, - normalMap[i].b() * 0.5 + 0.5); // B: -1:+1 => 0-255 which means 0:+1 => 128-255 + normalMap(i) = image::RGBfColor(normalMap(i).r() * 0.5 + 0.5, + normalMap(i).g() * 0.5 + 0.5, + normalMap(i).b() * 0.5 + 0.5); // B: -1:+1 => 0-255 which means 0:+1 => 128-255 const std::string name = "Normal_" + std::to_string(1001 + atlasID) + "." + EImageFileType_enumToString(bumpMappingParams.bumpMappingFileType); bfs::path normalMapPath = outPath / name; ALICEVISION_LOG_INFO("Writing normal map: " << normalMapPath.string()); - image::OutputFileColorSpace outputColorSpace(image::EImageColorSpace::NO_CONVERSION, - image::EImageColorSpace::NO_CONVERSION); - image::writeImage(normalMapPath.string(), outTextureSide, outTextureSide, normalMap, - image::EImageQuality::OPTIMIZED, outputColorSpace); + image::writeImage(normalMapPath.string(), normalMap, + image::ImageWriteOptions().fromColorSpace(image::EImageColorSpace::NO_CONVERSION) + .toColorSpace(image::EImageColorSpace::NO_CONVERSION) + .storageDataType(image::EStorageDataType::Half)); } // Save Height Maps @@ -1481,10 +1479,9 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp if(texParams.downscale > 1) { ALICEVISION_LOG_INFO("Downscaling height map (" << texParams.downscale << "x)."); - std::vector resizedBuffer; + image::Image resizedBuffer; outTextureSide = texParams.textureSide / texParams.downscale; - imageAlgo::resizeImage(texParams.textureSide, texParams.textureSide, texParams.downscale, heightMap, - resizedBuffer); + imageAlgo::resizeImage(texParams.downscale, heightMap, resizedBuffer); std::swap(resizedBuffer, heightMap); } @@ -1494,18 +1491,18 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp //{ // // Y: [-1, 0, +1] => [0, 128, 255] // for(unsigned int i = 0; i < heightMap.size(); ++i) - // heightMap[i] = heightMap[i] * 0.5 + 0.5; + // heightMap(i) = heightMap(i) * 0.5 + 0.5; //} // Save Bump Map - image::OutputFileColorSpace outputColorSpace(image::EImageColorSpace::AUTO); if(bumpMappingParams.bumpType == EBumpMappingType::Height) { const std::string bumpName = "Bump_" + std::to_string(1001 + atlasID) + "." + EImageFileType_enumToString(bumpMappingParams.bumpMappingFileType); bfs::path bumpMapPath = outPath / bumpName; ALICEVISION_LOG_INFO("Writing bump map: " << bumpMapPath); - image::writeImage(bumpMapPath.string(), outTextureSide, outTextureSide, heightMap, - image::EImageQuality::OPTIMIZED, outputColorSpace); + + image::writeImage(bumpMapPath.string(), heightMap, + image::ImageWriteOptions().storageDataType(image::EStorageDataType::Half)); } // Save Displacement Map if(bumpMappingParams.displacementFileType != image::EImageFileType::NONE) @@ -1513,8 +1510,9 @@ void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp const std::string dispName = "Displacement_" + std::to_string(1001 + atlasID) + "." + EImageFileType_enumToString(bumpMappingParams.displacementFileType); bfs::path dispMapPath = outPath / dispName; ALICEVISION_LOG_INFO("Writing displacement map: " << dispMapPath); - image::writeImage(dispMapPath.string(), outTextureSide, outTextureSide, heightMap, - image::EImageQuality::OPTIMIZED, outputColorSpace); + + image::writeImage(dispMapPath.string(), heightMap, + image::ImageWriteOptions().storageDataType(image::EStorageDataType::Half)); } } } diff --git a/src/samples/imageDescriberMatches/main_describeAndMatch.cpp b/src/samples/imageDescriberMatches/main_describeAndMatch.cpp index a853c564b6..f8382beffd 100644 --- a/src/samples/imageDescriberMatches/main_describeAndMatch.cpp +++ b/src/samples/imageDescriberMatches/main_describeAndMatch.cpp @@ -118,7 +118,8 @@ int main(int argc, char **argv) Image concat; ConcatH(imageL, imageR, concat); const std::string out_filename = "00_images.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } { @@ -136,7 +137,8 @@ int main(int argc, char **argv) DrawCircle(imaB.x()+imageL.Width(), imaB.y(), 3.0f, 255, &concat); } const std::string out_filename = "01_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //-- diff --git a/src/samples/kvldFilter/main_kvldFilter.cpp b/src/samples/kvldFilter/main_kvldFilter.cpp index 342ef1c060..70ec4f255e 100644 --- a/src/samples/kvldFilter/main_kvldFilter.cpp +++ b/src/samples/kvldFilter/main_kvldFilter.cpp @@ -126,7 +126,8 @@ int main(int argc, char **argv) Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "00_images.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -144,7 +145,8 @@ int main(int argc, char **argv) DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "01_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; @@ -294,12 +296,14 @@ int main(int argc, char **argv) { std::string out_filename = "07_Left-K-VLD-MASK.jpg"; out_filename = (fs::path(outputFolder) / out_filename).string(); - writeImage(out_filename, imageOutL, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, imageOutL, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } { std::string out_filename = "08_Right-K-VLD-MASK.jpg"; out_filename = (fs::path(outputFolder) / out_filename).string(); - writeImage(out_filename, imageOutR, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, imageOutR, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } return EXIT_SUCCESS; diff --git a/src/samples/robustEssential/main_robustEssential.cpp b/src/samples/robustEssential/main_robustEssential.cpp index 4484f39f1b..04a9b4b116 100644 --- a/src/samples/robustEssential/main_robustEssential.cpp +++ b/src/samples/robustEssential/main_robustEssential.cpp @@ -78,7 +78,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -96,7 +97,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp index 1e9f48a70c..8f23cc4702 100644 --- a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp +++ b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp @@ -86,7 +86,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -104,7 +105,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp index 1a82fc6ccd..5eff9b0eec 100644 --- a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp +++ b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp @@ -76,7 +76,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -94,7 +95,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/robustFundamental/main_robustFundamental.cpp b/src/samples/robustFundamental/main_robustFundamental.cpp index 6a716213b3..39ded7532d 100644 --- a/src/samples/robustFundamental/main_robustFundamental.cpp +++ b/src/samples/robustFundamental/main_robustFundamental.cpp @@ -104,7 +104,8 @@ int main(int argc, char **argv) Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -122,7 +123,8 @@ int main(int argc, char **argv) DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp index df92655005..1312111bf9 100644 --- a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp +++ b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp @@ -63,7 +63,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -81,7 +82,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/robustHomography/main_robustHomography.cpp b/src/samples/robustHomography/main_robustHomography.cpp index d6f0722578..280645858e 100644 --- a/src/samples/robustHomography/main_robustHomography.cpp +++ b/src/samples/robustHomography/main_robustHomography.cpp @@ -66,7 +66,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -84,7 +85,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; @@ -196,13 +198,13 @@ int main() { //--------------------------------------- // reread right image that will be warped to fit left image readImage(jpg_filenameR, image, image::EImageColorSpace::NO_CONVERSION); - writeImage("query.png", image, image::EImageColorSpace::NO_CONVERSION); + writeImage("query.png", image, image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); // Create and fill the output image Image imaOut(imageL.Width(), imageL.Height()); image::Warp(image, H.getMatrix(), imaOut); const std::string imageNameOut = "query_warped.png"; - writeImage(imageNameOut, imaOut, image::EImageColorSpace::NO_CONVERSION); + writeImage(imageNameOut, imaOut, image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } else { std::cout << "ACRANSAC was unable to estimate a rigid homography" diff --git a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp index 3963603ff1..a819858847 100644 --- a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp +++ b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp @@ -64,7 +64,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "01_concat.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //- Draw features on the two image (side by side) @@ -82,7 +83,8 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } std::string out_filename = "02_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } std::vector vec_PutativeMatches; diff --git a/src/samples/siftPutativeMatches/main_siftMatching.cpp b/src/samples/siftPutativeMatches/main_siftMatching.cpp index 86458bb48b..85c1eea2d0 100644 --- a/src/samples/siftPutativeMatches/main_siftMatching.cpp +++ b/src/samples/siftPutativeMatches/main_siftMatching.cpp @@ -53,7 +53,8 @@ int main() { Image concat; ConcatH(imageL, imageR, concat); std::string out_filename = "00_images.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } const SIFT_Regions* regionsL = dynamic_cast(regions_perImage.at(0).get()); @@ -74,7 +75,7 @@ int main() { DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } const std::string out_filename = "01_features.jpg"; - writeImage(out_filename, concat, image::EImageColorSpace::NO_CONVERSION); + writeImage(out_filename, concat, image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //-- Perform matching -> find Nearest neighbor, filtered with Distance ratio diff --git a/src/samples/texturing/main_evcorrection.cpp b/src/samples/texturing/main_evcorrection.cpp index 4ed63f431b..da237bb91e 100644 --- a/src/samples/texturing/main_evcorrection.cpp +++ b/src/samples/texturing/main_evcorrection.cpp @@ -129,7 +129,9 @@ int main(int argc, char **argv) std::string outputPath = outputFilePath + fs::path(view.getImagePath()).stem().string() + ".EXR"; oiio::ParamValueList metadata = image::getMetadataFromMap(view.getMetadata()); - image::writeImage(outputPath, img, image::EImageColorSpace::LINEAR, metadata); + image::writeImage(outputPath, img, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR), + metadata); } /* diff --git a/src/samples/undistoBrown/main_undistoBrown.cpp b/src/samples/undistoBrown/main_undistoBrown.cpp index 886e093dad..35c479700e 100644 --- a/src/samples/undistoBrown/main_undistoBrown.cpp +++ b/src/samples/undistoBrown/main_undistoBrown.cpp @@ -132,7 +132,8 @@ int main(int argc, char **argv) const PinholeRadialK3 cam(image.Width(), image.Height(), f, c(0), c(1), k(0), k(1), k(2)); UndistortImage(image, &cam, imageUd, BLACK); - writeImage(outFileName, imageUd, image::EImageColorSpace::NO_CONVERSION); + writeImage(outFileName, imageUd, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } //end loop for each file return EXIT_SUCCESS; diff --git a/src/software/convert/main_convertRAW.cpp b/src/software/convert/main_convertRAW.cpp index 0718bdca1f..e2ed1e18c9 100644 --- a/src/software/convert/main_convertRAW.cpp +++ b/src/software/convert/main_convertRAW.cpp @@ -135,7 +135,7 @@ int aliceVision_main(int argc, char** argv) // write output image try { - image::writeImage(outputPath, image, image::EImageColorSpace::AUTO, metadata); + image::writeImage(outputPath, image, image::ImageWriteOptions(), metadata); } catch(std::exception& e) { diff --git a/src/software/export/main_exportAnimatedCamera.cpp b/src/software/export/main_exportAnimatedCamera.cpp index ff2ffbc93a..67bd407abd 100644 --- a/src/software/export/main_exportAnimatedCamera.cpp +++ b/src/software/export/main_exportAnimatedCamera.cpp @@ -300,7 +300,7 @@ int aliceVision_main(int argc, char** argv) const std::string dstImage = (undistortedImagesFolderPath / (std::to_string(intrinsicPair.first) + "_UVMap_Undistort." + image::EImageFileType_enumToString(outputMapFileType))).string(); - image::writeImage(dstImage, image_dist, image::EImageColorSpace::AUTO); + image::writeImage(dstImage, image_dist, image::ImageWriteOptions()); } // UV Map: Distort @@ -323,7 +323,7 @@ int aliceVision_main(int argc, char** argv) const std::string dstImage = (undistortedImagesFolderPath / (std::to_string(intrinsicPair.first) + "_UVMap_Distort." + image::EImageFileType_enumToString(outputMapFileType))).string(); - image::writeImage(dstImage, image_dist, image::EImageColorSpace::AUTO); + image::writeImage(dstImage, image_dist, image::ImageWriteOptions()); } } } @@ -375,18 +375,18 @@ int aliceVision_main(int argc, char** argv) std::to_string(rod.ybegin) + ";" + std::to_string(rod.yend)); camera::UndistortImage(image, cam, image_ud, image::FBLACK, correctPrincipalPoint, rod); const oiio::ROI roi = convertRodToRoi(cam, rod); - writeImage(dstImage, image_ud, image::EImageColorSpace::AUTO, oiio::ParamValueList(), roi); + writeImage(dstImage, image_ud, image::ImageWriteOptions(), oiio::ParamValueList(), roi); } else { camera::UndistortImage(image, cam, image_ud, image::FBLACK, correctPrincipalPoint); - image::writeImage(dstImage, image_ud, image::EImageColorSpace::AUTO, metadata); + image::writeImage(dstImage, image_ud, image::ImageWriteOptions(), metadata); } } else // (no distortion) { // copy the image since there is no distortion - image::writeImage(dstImage, image, image::EImageColorSpace::AUTO, metadata); + image::writeImage(dstImage, image, image::ImageWriteOptions(), metadata); } } diff --git a/src/software/export/main_exportMVE2.cpp b/src/software/export/main_exportMVE2.cpp index 541c0839d0..5ebc634d9d 100644 --- a/src/software/export/main_exportMVE2.cpp +++ b/src/software/export/main_exportMVE2.cpp @@ -142,7 +142,8 @@ bool exportToMVE2Format( // Undistort and save the image readImage(srcImage, image, image::EImageColorSpace::NO_CONVERSION); UndistortImage(image, cam, image_ud, BLACK); - writeImage(dstImage, image_ud, image::EImageColorSpace::NO_CONVERSION); + writeImage(dstImage, image_ud, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } else // (no distortion) { @@ -155,7 +156,8 @@ bool exportToMVE2Format( else { readImage( srcImage, image, image::EImageColorSpace::NO_CONVERSION); - writeImage( dstImage, image, image::EImageColorSpace::NO_CONVERSION); + writeImage(dstImage, image, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } } @@ -208,7 +210,8 @@ bool exportToMVE2Format( // Save a thumbnail image "thumbnail.png", 50x50 pixels thumbnail = create_thumbnail(image, 50, 50); const std::string dstThumbnailImage = (fs::path(sOutViewIteratorDirectory) / "thumbnail.png").string(); - writeImage(dstThumbnailImage, thumbnail, image::EImageColorSpace::NO_CONVERSION); + writeImage(dstThumbnailImage, thumbnail, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); ++view_index; } diff --git a/src/software/export/main_exportMatches.cpp b/src/software/export/main_exportMatches.cpp index 847d413993..afdf8e5c31 100644 --- a/src/software/export/main_exportMatches.cpp +++ b/src/software/export/main_exportMatches.cpp @@ -202,7 +202,8 @@ int aliceVision_main(int argc, char ** argv) image::Image originalImage; image::readImage(viewImagePathI, originalImage, image::EImageColorSpace::LINEAR); destFilename_I = (fs::path(outputFolder) / (origFilename + ".png")).string(); - image::writeImage(destFilename_I, originalImage, image::EImageColorSpace::SRGB); + image::writeImage(destFilename_I, originalImage, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::SRGB)); } { @@ -211,7 +212,8 @@ int aliceVision_main(int argc, char ** argv) image::Image originalImage; image::readImage(viewImagePathJ, originalImage, image::EImageColorSpace::LINEAR); destFilename_J = (fs::path(outputFolder) / (origFilename + ".png")).string(); - image::writeImage(destFilename_J, originalImage, image::EImageColorSpace::SRGB); + image::writeImage(destFilename_J, originalImage, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::SRGB)); } const std::pair dimImageI = std::make_pair(viewI->getWidth(), viewI->getHeight()); diff --git a/src/software/export/main_exportMeshroomMaya.cpp b/src/software/export/main_exportMeshroomMaya.cpp index 6e95d38629..1669e3452c 100644 --- a/src/software/export/main_exportMeshroomMaya.cpp +++ b/src/software/export/main_exportMeshroomMaya.cpp @@ -147,10 +147,10 @@ int aliceVision_main(int argc, char **argv) const std::string basename = fs::path(view.getImagePath()).stem().string(); image::writeImage(outputFolder + "/undistort/proxy/" + basename + "-" + std::to_string(view.getViewId()) + "-UOP.jpg", - imageProxy, image::EImageColorSpace::AUTO); + imageProxy, image::ImageWriteOptions()); image::writeImage(outputFolder + "/undistort/thumbnail/" + basename + "-" + std::to_string(view.getViewId()) + "-UOT.jpg", - imageThumbnail, image::EImageColorSpace::AUTO); + imageThumbnail, image::ImageWriteOptions()); ++progressDisplay; } diff --git a/src/software/export/main_exportPMVS.cpp b/src/software/export/main_exportPMVS.cpp index 1c794159ca..b20f4f6808 100644 --- a/src/software/export/main_exportPMVS.cpp +++ b/src/software/export/main_exportPMVS.cpp @@ -128,7 +128,8 @@ bool exportToPMVSFormat( // undistort the image and save it readImage( srcImage, image, image::EImageColorSpace::NO_CONVERSION); UndistortImage(image, cam, image_ud, BLACK); - writeImage(dstImage, image_ud, image::EImageColorSpace::NO_CONVERSION); + writeImage(dstImage, image_ud, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } else // (no distortion) { @@ -141,7 +142,8 @@ bool exportToPMVSFormat( else { readImage(srcImage, image, image::EImageColorSpace::NO_CONVERSION); - writeImage(dstImage, image, image::EImageColorSpace::NO_CONVERSION); + writeImage(dstImage, image, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } } } diff --git a/src/software/pipeline/main_LdrToHdrMerge.cpp b/src/software/pipeline/main_LdrToHdrMerge.cpp index 1d6c8187d8..2c83bb4f37 100644 --- a/src/software/pipeline/main_LdrToHdrMerge.cpp +++ b/src/software/pipeline/main_LdrToHdrMerge.cpp @@ -315,10 +315,10 @@ int aliceVision_main(int argc, char** argv) // Write an image with parameters from the target view oiio::ParamValueList targetMetadata = image::readImageMetadata(targetView->getImagePath()); - targetMetadata.push_back(oiio::ParamValue("AliceVision:storageDataType", image::EStorageDataType_enumToString(storageDataType))); - targetMetadata.add_or_replace(oiio::ParamValue("AliceVision:ColorSpace", image::EImageColorSpace_enumToString(image::EImageColorSpace::LINEAR))); - - image::writeImage(hdrImagePath, HDRimage, image::EImageColorSpace::AUTO, targetMetadata); + targetMetadata.add_or_replace(oiio::ParamValue("AliceVision:ColorSpace", + image::EImageColorSpace_enumToString(image::EImageColorSpace::LINEAR))); + image::writeImage(hdrImagePath, HDRimage, + image::ImageWriteOptions().storageDataType(storageDataType), targetMetadata); } return EXIT_SUCCESS; diff --git a/src/software/pipeline/main_LdrToHdrSampling.cpp b/src/software/pipeline/main_LdrToHdrSampling.cpp index 75167e6c96..c3da84b646 100644 --- a/src/software/pipeline/main_LdrToHdrSampling.cpp +++ b/src/software/pipeline/main_LdrToHdrSampling.cpp @@ -272,7 +272,7 @@ int aliceVision_main(int argc, char** argv) metadata.push_back(oiio::ParamValue("AliceVision:medianNbUsedBrackets", extract::median(acc_nbUsedBrackets))); image::writeImage((fs::path(outputFolder) / (std::to_string(groupIdx) + "_selectedPixels.png")).string(), - selectedPixels, image::EImageColorSpace::AUTO, metadata); + selectedPixels, image::ImageWriteOptions(), metadata); } diff --git a/src/software/pipeline/main_distortionCalibration.cpp b/src/software/pipeline/main_distortionCalibration.cpp index 9395100de1..c42f06d630 100644 --- a/src/software/pipeline/main_distortionCalibration.cpp +++ b/src/software/pipeline/main_distortionCalibration.cpp @@ -163,7 +163,8 @@ bool retrieveLines(std::vector & lineWithPoints, co { image::Image drawing = input; detect.drawCheckerBoard(drawing); - image::writeImage(checkerImagePath, drawing, image::EImageColorSpace::NO_CONVERSION); + image::writeImage(checkerImagePath, drawing, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } lineWithPoints.clear(); @@ -761,10 +762,11 @@ int aliceVision_main(int argc, char* argv[]) Vec2 offset; image::Image ud = undistort(offset, cameraPinhole, input); - image::writeImage(undistortedImagePath, ud, image::EImageColorSpace::AUTO); + image::writeImage(undistortedImagePath, ud, image::ImageWriteOptions()); image::Image stmap = undistortSTMAP(offset, cameraPinhole, input); - image::writeImage(stMapImagePath, stmap, image::EImageColorSpace::NO_CONVERSION); + image::writeImage(stMapImagePath, stmap, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); } } diff --git a/src/software/pipeline/main_imageMasking.cpp b/src/software/pipeline/main_imageMasking.cpp index 9fd6e9a606..6c0192548d 100644 --- a/src/software/pipeline/main_imageMasking.cpp +++ b/src/software/pipeline/main_imageMasking.cpp @@ -403,7 +403,8 @@ int main(int argc, char **argv) } const auto resultFilename = fs::path(std::to_string(index)).replace_extension("png"); const std::string resultPath = (fs::path(outputFilePath) / resultFilename).string(); - image::writeImage(resultPath, result, image::EImageColorSpace::LINEAR); + image::writeImage(resultPath, result, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::LINEAR)); } ALICEVISION_LOG_INFO("Task done in (s): " + std::to_string(timer.elapsed())); diff --git a/src/software/pipeline/main_panoramaCompositing.cpp b/src/software/pipeline/main_panoramaCompositing.cpp index 948fa2bf43..a24177ffc2 100644 --- a/src/software/pipeline/main_panoramaCompositing.cpp +++ b/src/software/pipeline/main_panoramaCompositing.cpp @@ -539,14 +539,15 @@ bool processImage(const PanoramaMap & panoramaMap, const std::string & composite } oiio::ParamValueList metadata; - metadata.push_back(oiio::ParamValue("AliceVision:storageDataType", EStorageDataType_enumToString(storageDataType))); metadata.push_back(oiio::ParamValue("AliceVision:offsetX", int(referenceBoundingBox.left))); metadata.push_back(oiio::ParamValue("AliceVision:offsetY", int(referenceBoundingBox.top))); metadata.push_back(oiio::ParamValue("AliceVision:panoramaWidth", int(panoramaMap.getWidth()))); metadata.push_back(oiio::ParamValue("AliceVision:panoramaHeight", int(panoramaMap.getHeight()))); metadata.push_back(oiio::ParamValue("AliceVision:ColorSpace", colorSpace)); - image::writeImage(outputFilePath, output, image::EImageColorSpace_stringToEnum(colorSpace), metadata); + image::writeImage(outputFilePath, output, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace_stringToEnum(colorSpace)) + .storageDataType(storageDataType), metadata); return true; } diff --git a/src/software/pipeline/main_panoramaInit.cpp b/src/software/pipeline/main_panoramaInit.cpp index 0bc2784766..cb1ab8ff30 100644 --- a/src/software/pipeline/main_panoramaInit.cpp +++ b/src/software/pipeline/main_panoramaInit.cpp @@ -602,7 +602,7 @@ class CircleDetector { boost::filesystem::path filepath = boost::filesystem::path(_debugDirectory) / (name + "_" + std::to_string(pyramid_id) + "_" + std::to_string(level) + ".exr"); - image::writeImage(filepath.string(), toSave, image::EImageColorSpace::AUTO); + image::writeImage(filepath.string(), toSave, image::ImageWriteOptions()); } private: diff --git a/src/software/pipeline/main_panoramaMerging.cpp b/src/software/pipeline/main_panoramaMerging.cpp index 260e645d53..b2df525f51 100644 --- a/src/software/pipeline/main_panoramaMerging.cpp +++ b/src/software/pipeline/main_panoramaMerging.cpp @@ -164,12 +164,12 @@ int aliceVision_main(int argc, char** argv) } } - image::EImageColorSpace outputColorSpace = colorSpace.empty() ? image::EImageColorSpace::AUTO : image::EImageColorSpace_stringToEnum(colorSpace); + image::EImageColorSpace outputColorSpace = colorSpace.empty() + ? image::EImageColorSpace::LINEAR : image::EImageColorSpace_stringToEnum(colorSpace); - oiio::ParamValueList targetMetadata; - targetMetadata.push_back(oiio::ParamValue("AliceVision:storageDataType", image::EStorageDataType_enumToString(storageDataType))); - targetMetadata.add_or_replace(oiio::ParamValue("AliceVision:ColorSpace", colorSpace = colorSpace.empty() ? "Linear" : colorSpace)); - image::writeImage(outputPanoramaPath, panorama, outputColorSpace, targetMetadata); + image::writeImage(outputPanoramaPath, panorama, + image::ImageWriteOptions().storageDataType(storageDataType) + .toColorSpace(outputColorSpace)); return EXIT_SUCCESS; } diff --git a/src/software/pipeline/main_panoramaPrepareImages.cpp b/src/software/pipeline/main_panoramaPrepareImages.cpp index 5fa6ecf6cb..3394922bba 100644 --- a/src/software/pipeline/main_panoramaPrepareImages.cpp +++ b/src/software/pipeline/main_panoramaPrepareImages.cpp @@ -333,7 +333,7 @@ int aliceVision_main(int argc, char* argv[]) return EXIT_FAILURE; } - image::writeImage(rotatedImagePath, output, image::EImageColorSpace::AUTO, metadata); + image::writeImage(rotatedImagePath, output, image::ImageWriteOptions(), metadata); v.second->setWidth(output.Width()); v.second->setHeight(output.Height()); v.second->setImagePath(rotatedImagePath); diff --git a/src/software/pipeline/main_panoramaSeams.cpp b/src/software/pipeline/main_panoramaSeams.cpp index 009f8ed44d..2699dc6f18 100644 --- a/src/software/pipeline/main_panoramaSeams.cpp +++ b/src/software/pipeline/main_panoramaSeams.cpp @@ -321,7 +321,8 @@ int aliceVision_main(int argc, char** argv) } } - image::writeImage(outputLabels, labels, image::EImageColorSpace::NO_CONVERSION); + image::writeImage(outputLabels, labels, + image::ImageWriteOptions().toColorSpace(image::EImageColorSpace::NO_CONVERSION)); return EXIT_SUCCESS; } diff --git a/src/software/pipeline/main_prepareDenseScene.cpp b/src/software/pipeline/main_prepareDenseScene.cpp index 7d8c3d0a3d..32861d1338 100644 --- a/src/software/pipeline/main_prepareDenseScene.cpp +++ b/src/software/pipeline/main_prepareDenseScene.cpp @@ -66,11 +66,11 @@ void process(const std::string &dstColorImage, const IntrinsicBase* cam, const o using Pix = typename ImageT::Tpixel; Pix pixZero(Pix::Zero()); UndistortImage(image, cam, image_ud, pixZero); - writeImage(dstColorImage, image_ud, image::EImageColorSpace::AUTO, metadata); + writeImage(dstColorImage, image_ud, image::ImageWriteOptions(), metadata); } else { - writeImage(dstColorImage, image, image::EImageColorSpace::AUTO, metadata); + writeImage(dstColorImage, image, image::ImageWriteOptions(), metadata); } } diff --git a/src/software/utils/main_colorCheckerCorrection.cpp b/src/software/utils/main_colorCheckerCorrection.cpp index 1d1b524cc9..212a93dc78 100644 --- a/src/software/utils/main_colorCheckerCorrection.cpp +++ b/src/software/utils/main_colorCheckerCorrection.cpp @@ -116,17 +116,18 @@ void saveImage(image::Image& image, const std::string& inputP // Read metadata based on a filepath oiio::ParamValueList metadata = image::readImageMetadata(metadataFilePath); + image::ImageWriteOptions options; + if(isEXR) { // Select storage data type - metadata.push_back( - oiio::ParamValue("AliceVision:storageDataType", image::EStorageDataType_enumToString(storageDataType))); + options.storageDataType(storageDataType); } // Save image ALICEVISION_LOG_TRACE("Export image: '" << outputPath << "'."); - image::writeImage(outputPath, image, image::EImageColorSpace::AUTO, metadata); + image::writeImage(outputPath, image, options, metadata); } diff --git a/src/software/utils/main_fisheyeProjection.cpp b/src/software/utils/main_fisheyeProjection.cpp index 19cea3d28a..b99dd78862 100644 --- a/src/software/utils/main_fisheyeProjection.cpp +++ b/src/software/utils/main_fisheyeProjection.cpp @@ -247,7 +247,7 @@ void stitchPanorama(const std::vector& imagePaths, const std::vecto { outputPath = (fs::path(outputPath) / ("panorama.exr")).string(); } - image::writeImage(outputPath, imageOut, image::EImageColorSpace::AUTO, bufferOut.specmod().extra_attribs); + image::writeImage(outputPath, imageOut, image::ImageWriteOptions(), bufferOut.specmod().extra_attribs); ALICEVISION_LOG_INFO("Panorama successfully written as " << outputPath); } diff --git a/src/software/utils/main_imageProcessing.cpp b/src/software/utils/main_imageProcessing.cpp index 8ec03c4b5e..fec09c7629 100644 --- a/src/software/utils/main_imageProcessing.cpp +++ b/src/software/utils/main_imageProcessing.cpp @@ -450,12 +450,12 @@ void saveImage(image::Image& image, const std::string& inputP oiio::ParamValueList metadata = image::readImageMetadata(metadataFilePath); - metadata.add_or_replace(oiio::ParamValue("AliceVision:ColorSpace", (workingColorSpace == image::EImageColorSpace::LINEAR) ? "Linear" : image::EImageColorSpace_enumToString(workingColorSpace))); + auto options = image::ImageWriteOptions().toColorSpace(workingColorSpace); if(isEXR) { // Select storage data type - metadata.push_back(oiio::ParamValue("AliceVision:storageDataType", image::EStorageDataType_enumToString(storageDataType))); + options.storageDataType(storageDataType); } // Save image @@ -465,18 +465,18 @@ void saveImage(image::Image& image, const std::string& inputP { image::Image outputImage; image::ConvertPixelType(image, &outputImage); - image::writeImage(outputPath, outputImage, outputColorSpace, metadata); + image::writeImage(outputPath, outputImage, options, metadata); } else if(outputFormat == EImageFormat::RGB) { image::Image outputImage; image::ConvertPixelType(image, &outputImage); - image::writeImage(outputPath, outputImage, outputColorSpace, metadata); + image::writeImage(outputPath, outputImage, options, metadata); } else { // Already in RGBAf - image::writeImage(outputPath, image, outputColorSpace, metadata); + image::writeImage(outputPath, image, options, metadata); } } diff --git a/src/software/utils/main_lightingEstimation.cpp b/src/software/utils/main_lightingEstimation.cpp index 30c3b0a30d..aec32c5944 100644 --- a/src/software/utils/main_lightingEstimation.cpp +++ b/src/software/utils/main_lightingEstimation.cpp @@ -206,7 +206,7 @@ void initAlbedo(image::Image& albedo, const image::Image& albedo, const image::Image& albedo, const image::Image& picture, oiio::ImageBuf albedoBuf(oiio::ImageSpec(picture.Width(), picture.Height(), 1, oiio::TypeDesc::FLOAT), albedo.data()); oiio::ImageBufAlgo::median_filter(albedoBuf, pictureBuf, albedoEstimationFilterSize, albedoEstimationFilterSize); image::writeImage((fs::path(outputFolder) / (std::to_string(viewId) + "_albedo.jpg")).string(), albedo, - image::EImageColorSpace::AUTO); + image::ImageWriteOptions()); } break; case EAlbedoEstimation::BLUR_FILTER: @@ -256,7 +256,7 @@ void initAlbedo(image::Image& albedo, const image::Image& picture, oiio::ImageBuf K = oiio::ImageBufAlgo::make_kernel("gaussian", albedoEstimationFilterSize, albedoEstimationFilterSize); oiio::ImageBufAlgo::convolve(albedoBuf, pictureBuf, K); image::writeImage((fs::path(outputFolder) / (std::to_string(viewId) + "_albedo.jpg")).string(), albedo, - image::EImageColorSpace::AUTO); + image::ImageWriteOptions()); } break; } diff --git a/src/software/utils/main_split360Images.cpp b/src/software/utils/main_split360Images.cpp index 854b6c81ef..7d25966d08 100644 --- a/src/software/utils/main_split360Images.cpp +++ b/src/software/utils/main_split360Images.cpp @@ -132,7 +132,7 @@ bool splitDualFisheye(const std::string& imagePath, const std::string& outputFol boost::filesystem::path path(imagePath); image::writeImage(outputFolder + std::string("/") + path.stem().string() + std::string("_") + std::to_string(i) + path.extension().string(), - imageOut, image::EImageColorSpace::AUTO, image::readImageMetadata(imagePath)); + imageOut, image::ImageWriteOptions(), image::readImageMetadata(imagePath)); } ALICEVISION_LOG_INFO(imagePath + " successfully split"); return true; @@ -198,7 +198,7 @@ bool splitEquirectangular(const std::string& imagePath, const std::string& outpu boost::filesystem::path path(imagePath); image::writeImage(outputFolder + std::string("/") + path.stem().string() + std::string("_") + std::to_string(index) + path.extension().string(), - imaOut, image::EImageColorSpace::AUTO, outMetadataSpec.extra_attribs); + imaOut, image::ImageWriteOptions(), outMetadataSpec.extra_attribs); ++index; } diff --git a/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp b/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp index 9c1632a926..d41d668cac 100644 --- a/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp +++ b/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp @@ -280,8 +280,8 @@ bool ColorHarmonizationEngineGlobal::Process() std::string out_filename_J = "00_mask_J.png"; out_filename_J = (fs::path(sEdge) / out_filename_J).string(); - writeImage(out_filename_I, maskI, image::EImageColorSpace::AUTO); - writeImage(out_filename_J, maskJ, image::EImageColorSpace::AUTO); + writeImage(out_filename_I, maskI, image::ImageWriteOptions()); + writeImage(out_filename_J, maskJ, image::ImageWriteOptions()); } //-- Compute the histograms @@ -432,7 +432,7 @@ bool ColorHarmonizationEngineGlobal::Process() fs::create_directory(out_folder); const std::string out_filename = (fs::path(out_folder) / fs::path(_fileNames[ imaNum ]).filename() ).string(); - writeImage(out_filename, image_c , image::EImageColorSpace::AUTO); + writeImage(out_filename, image_c , image::ImageWriteOptions()); } return true; }