From 8b9e04b7a088968a2aaa275f6e4ffcc07f5d8f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 1 Oct 2024 15:12:29 +0200 Subject: [PATCH] Fix several points of failure with pixel counts in the billions --- include/tev/Box.h | 7 ++++--- include/tev/Channel.h | 6 +++--- src/Channel.cpp | 2 +- src/Image.cpp | 2 +- src/ImageCanvas.cpp | 21 +++++++++++---------- src/imageio/ExrImageLoader.cpp | 2 +- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/include/tev/Box.h b/include/tev/Box.h index a4b4ba6..d5c39ff 100644 --- a/include/tev/Box.h +++ b/include/tev/Box.h @@ -30,11 +30,12 @@ struct Box { return nanogui::max(max - min, Vector{(T)0}); } - T area() const { + using area_t = std::conditional_t, size_t, T>; + area_t area() const { auto size = this->size(); - T result = (T)1; + area_t result = (T)1; for (uint32_t i = 0; i < N_DIMS; ++i) { - result *= size[i]; + result *= (area_t)size[i]; } return result; diff --git a/include/tev/Channel.h b/include/tev/Channel.h index e21cfca..b0abe5e 100644 --- a/include/tev/Channel.h +++ b/include/tev/Channel.h @@ -49,7 +49,7 @@ class Channel { return 0; } - return mData[index.x() + index.y() * mSize.x()]; + return mData[index.x() + index.y() * (size_t)mSize.x()]; } float& at(size_t index) { @@ -61,11 +61,11 @@ class Channel { } float& at(nanogui::Vector2i index) { - return at(index.x() + index.y() * mSize.x()); + return at(index.x() + index.y() * (size_t)mSize.x()); } float at(nanogui::Vector2i index) const { - return at(index.x() + index.y() * mSize.x()); + return at(index.x() + index.y() * (size_t)mSize.x()); } size_t numPixels() const { diff --git a/src/Channel.cpp b/src/Channel.cpp index d3998f5..fb0ff7b 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -79,7 +79,7 @@ void Channel::updateTile(int x, int y, int width, int height, const vectorat({x + posX, y + posY}); } } diff --git a/src/ImageCanvas.cpp b/src/ImageCanvas.cpp index c335880..5605bdf 100644 --- a/src/ImageCanvas.cpp +++ b/src/ImageCanvas.cpp @@ -891,18 +891,19 @@ Task> ImageCanvas::computeCanvasStatistics( int nChannels = result->nChannels = alphaChannel ? (int)flattened.size() - 1 : (int)flattened.size(); - int pixelCount = 0; + size_t pixelCount = region.area(); for (int i = 0; i < nChannels; ++i) { const auto& channel = flattened[i]; for (int y = region.min.y(); y < region.max.y(); ++y) { for (int x = region.min.x(); x < region.max.x(); ++x) { - auto v = channel.at(Vector2i{x, y}); - if (!isnan(v)) { - mean += v; - maximum = max(maximum, v); - minimum = min(minimum, v); - pixelCount++; + auto v = channel.at({x, y}); + if (!isfinite(v)) { + continue; } + + mean += v; + maximum = max(maximum, v); + minimum = min(minimum, v); } } } @@ -944,17 +945,17 @@ Task> ImageCanvas::computeCanvasStatistics( } auto regionSize = region.size(); - auto numPixels = region.area(); + size_t numPixels = region.area(); std::vector indices(numPixels * nChannels); vector> tasks; for (int i = 0; i < nChannels; ++i) { const auto& channel = flattened[i]; tasks.emplace_back( - ThreadPool::global().parallelForAsync(0, numPixels, [&, i](int j) { + ThreadPool::global().parallelForAsync((size_t)0, numPixels, [&, i](size_t j) { int x = (j % regionSize.x()) + region.min.x(); int y = (j / regionSize.x()) + region.min.y(); - indices[j + i * numPixels] = valToBin(channel.at(Vector2i{x, y})); + indices[j + i * numPixels] = valToBin(channel.at({x, y})); }, priority) ); } diff --git a/src/imageio/ExrImageLoader.cpp b/src/imageio/ExrImageLoader.cpp index 135a86c..c301b29 100644 --- a/src/imageio/ExrImageLoader.cpp +++ b/src/imageio/ExrImageLoader.cpp @@ -116,7 +116,7 @@ class RawChannel { auto data = reinterpret_cast(mData.data()); co_await ThreadPool::global().parallelForAsync(0, channel.size().y(), [&, data](int y) { for (int x = 0; x < width; ++x) { - channel.at({x, y}) = data[x / mImfChannel.xSampling + (y / mImfChannel.ySampling) * widthSubsampled]; + channel.at({x, y}) = data[x / mImfChannel.xSampling + (y / mImfChannel.ySampling) * (size_t)widthSubsampled]; } }, priority); }