diff --git a/src/qtAliceVision/AsyncFetcher.cpp b/src/qtAliceVision/AsyncFetcher.cpp index 50d19959..5ca8417c 100644 --- a/src/qtAliceVision/AsyncFetcher.cpp +++ b/src/qtAliceVision/AsyncFetcher.cpp @@ -218,7 +218,9 @@ bool AsyncFetcher::getFrame(const std::string& path, std::shared_ptr>& image, oiio::ParamValueList& metadatas, size_t& originalWidth, - size_t& originalHeight) + size_t& originalHeight, + bool & missingFile, + bool & loadingError) { // Need a cache if (!_cache) @@ -251,6 +253,8 @@ bool AsyncFetcher::getFrame(const std::string& path, metadatas = copy_metadatas; originalWidth = value.getOriginalWidth(); originalHeight = value.getOriginalHeight(); + missingFile = value.isFileMissing(); + loadingError = value.hadErrorOnLoad(); if (image) { diff --git a/src/qtAliceVision/AsyncFetcher.hpp b/src/qtAliceVision/AsyncFetcher.hpp index c7bf747a..94c87ba9 100644 --- a/src/qtAliceVision/AsyncFetcher.hpp +++ b/src/qtAliceVision/AsyncFetcher.hpp @@ -54,13 +54,17 @@ class AsyncFetcher : public QObject, public QRunnable * @param metadatas the image metadatas found in the file * @param originalWidth the image width before the resize * @param originalHeight the image height before the resize + * @param missingFile the image cache entry indicates a missing file + * @param loadingError the image cache entry indicates a file loading error * @return true if the image was succesfully found in the cache */ bool getFrame(const std::string& path, std::shared_ptr>& image, oiio::ParamValueList& metadatas, std::size_t& originalWidth, - std::size_t& originalHeight); + std::size_t& originalHeight, + bool & missingFile, + bool & loadingError); /** * @brief Internal function for QT to start the asynchronous mode diff --git a/src/qtAliceVision/FloatImageViewer.cpp b/src/qtAliceVision/FloatImageViewer.cpp index e9c7a2b6..ae805397 100644 --- a/src/qtAliceVision/FloatImageViewer.cpp +++ b/src/qtAliceVision/FloatImageViewer.cpp @@ -325,6 +325,7 @@ FloatImageViewer::FloatImageViewer(QQuickItem* parent) connect(&_singleImageLoader, &imgserve::SingleImageLoader::requestHandled, this, &FloatImageViewer::reload); connect(&_sequenceCache, &imgserve::SequenceCache::requestHandled, this, &FloatImageViewer::reload); connect(this, &FloatImageViewer::useSequenceChanged, this, &FloatImageViewer::reload); + connect(this, &FloatImageViewer::sequenceChanged, this, &FloatImageViewer::reload); } FloatImageViewer::~FloatImageViewer() {} diff --git a/src/qtAliceVision/ImageCache.hpp b/src/qtAliceVision/ImageCache.hpp index 4951f557..6dbf8c85 100644 --- a/src/qtAliceVision/ImageCache.hpp +++ b/src/qtAliceVision/ImageCache.hpp @@ -59,9 +59,11 @@ class CacheValue { public: template - CacheValue(unsigned frameId, std::shared_ptr> img) + CacheValue(unsigned frameId, std::shared_ptr> img, bool missingFile, bool loadError) : _vimg(img), - _frameId(frameId) + _frameId(frameId), + _missingFile(missingFile), + _loadError(loadError) {} public: @@ -124,6 +126,24 @@ class CacheValue return std::visit([](const auto& arg) -> unsigned long long int { return arg->memorySize(); }, _vimg); } + /** + * @brief did the load failed ? + * @return true if something bad happened during the loading + */ + bool hadErrorOnLoad() const + { + return _loadError; + } + + /** + * @brief is the file requested missing ? + * @return true if the file doesn't exist + */ + bool isFileMissing() const + { + return _missingFile; + } + private: std::variant>, std::shared_ptr>, @@ -137,6 +157,8 @@ class CacheValue unsigned _originalHeight; oiio::ParamValueList _metadatas; unsigned _frameId; + bool _loadError; + bool _missingFile; }; /** @@ -363,6 +385,10 @@ std::optional ImageCache::get(const std::string& filename, unsigned template std::optional ImageCache::load(const CacheKey& key, unsigned frameId) { + // Increment disk access stats + // This is incremented whatever happens next + _info.incrementDisk(); + aliceVision::image::Image img; auto resized = std::make_shared>(); @@ -370,35 +396,52 @@ std::optional ImageCache::load(const CacheKey& key, unsigned frameId int height = 0; oiio::ParamValueList metadatas; - try - { - metadatas = aliceVision::image::readImageMetadata(key.filename, width, height); + bool loadError = false; + bool missingFile = false; - // load image from disk - readImage(key.filename, img, _options); - } - catch (...) + + //First check if the files exists on disk + //LastWriteTime equals 0 if the file doesn't exist + if (key.lastWriteTime == 0) { - return std::nullopt; + missingFile = true; + loadError = true; } + else + { + //If the file exist, then try to load it. + try + { + //Retrieve metadatas + metadatas = aliceVision::image::readImageMetadata(key.filename, width, height); - // Compute new size, make sure the size is at least 1 - double dw = key.resizeRatio * double(img.width()); - double dh = key.resizeRatio * double(img.height()); - int tw = static_cast(std::max(1, int(std::ceil(dw)))); - int th = static_cast(std::max(1, int(std::ceil(dh)))); + // load image from disk + readImage(key.filename, img, _options); + } + catch (...) + { + loadError = true; + } + } - using TInfo = aliceVision::image::ColorTypeInfo; - cleanup(tw * th * std::size_t(TInfo::size), key); + if (!loadError) + { + // Compute new size, make sure the size is at least 1 + double dw = key.resizeRatio * double(img.width()); + double dh = key.resizeRatio * double(img.height()); + int tw = static_cast(std::max(1, int(std::ceil(dw)))); + int th = static_cast(std::max(1, int(std::ceil(dh)))); - // apply downscale - aliceVision::imageAlgo::resizeImage(tw, th, img, *resized); + using TInfo = aliceVision::image::ColorTypeInfo; + cleanup(tw * th * std::size_t(TInfo::size), key); - // Increment disk access stats - _info.incrementDisk(); + // apply downscale + aliceVision::imageAlgo::resizeImage(tw, th, img, *resized); + } // create wrapper around shared pointer - CacheValue value(frameId, resized); + // Note that we store cache item even on problem to not repeat trials + CacheValue value(frameId, resized, missingFile, loadError); // Add additional information about the image value.setOriginalHeight(static_cast(height)); diff --git a/src/qtAliceVision/SequenceCache.cpp b/src/qtAliceVision/SequenceCache.cpp index 53c638da..2e1b49d5 100644 --- a/src/qtAliceVision/SequenceCache.cpp +++ b/src/qtAliceVision/SequenceCache.cpp @@ -114,12 +114,28 @@ ResponseData SequenceCache::request(const RequestData& reqData) oiio::ParamValueList metadatas; size_t originalWidth = 0; size_t originalHeight = 0; + bool hadErrorOnLoad = false; + bool isFileMissing = false; - if (!_fetcher.getFrame(reqData.path, image, metadatas, originalWidth, originalHeight)) + if (!_fetcher.getFrame(reqData.path, image, metadatas, + originalWidth, originalHeight, + isFileMissing, hadErrorOnLoad)) { return response; } + if (isFileMissing) + { + response.error = MISSING_FILE; + return response; + } + + if (hadErrorOnLoad) + { + response.error = LOADING_ERROR; + return response; + } + //Build a new response with information fetched response.metadata.clear();