Skip to content

Commit 59e29a2

Browse files
committed
feat(common): cleaner conversion from Vector2i to size_t
1 parent 2a832df commit 59e29a2

26 files changed

+95
-61
lines changed

include/tev/Channel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class Channel {
214214
bool isAlpha() const { return Channel::isAlpha(mName); }
215215
bool isTopmost() const { return Channel::isTopmost(mName); }
216216

217-
size_t numPixels() const { return (size_t)mSize.x() * mSize.y(); }
217+
size_t numPixels() const { return posProd(mSize); }
218218

219219
nanogui::Vector2i size() const { return mSize; }
220220
void setSize(nanogui::Vector2i size) { mSize = size; }

include/tev/Common.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,32 @@ template <size_t N_DIMS> nanogui::Array<float, N_DIMS> pow(const nanogui::Array<
220220
return result;
221221
}
222222

223+
template <typename T, size_t N_DIMS> auto prod(const nanogui::Array<T, N_DIMS>& v) {
224+
using area_t = std::conditional_t<std::is_integral_v<T>, std::conditional_t<std::is_signed_v<T>, ssize_t, size_t>, T>;
225+
area_t result = (T)1;
226+
227+
for (uint32_t i = 0; i < N_DIMS; ++i) {
228+
result *= (area_t)v[i];
229+
}
230+
231+
return result;
232+
}
233+
234+
template <typename T, size_t N_DIMS> auto posProd(const nanogui::Array<T, N_DIMS>& v) {
235+
using area_t = std::conditional_t<std::is_integral_v<T>, size_t, T>;
236+
area_t result = (T)1;
237+
238+
for (uint32_t i = 0; i < N_DIMS; ++i) {
239+
if (v[i] < 0) [[unlikely]] {
240+
throw std::runtime_error{std::format("Negative value {} encountered when computing positive product.", v)};
241+
}
242+
243+
result *= (area_t)v[i];
244+
}
245+
246+
return result;
247+
}
248+
223249
struct NVGcontext;
224250

225251
namespace tev {

include/tev/imageio/ImageLoader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Task<void> yCbCrToRgb(MultiChannelView<float> data, int priority, nanogui::Vecto
4343

4444
const nanogui::Vector2i size = data.size();
4545

46-
const auto numPixels = (size_t)size.x() * size.y();
46+
const auto numPixels = posProd(size);
4747
co_await ThreadPool::global().parallelFor(
4848
0uz,
4949
numPixels,
@@ -101,7 +101,7 @@ Task<void> toFloat32(
101101
}
102102

103103
const size_t numSamplesPerPixel = std::min(numSamplesPerPixelIn, floatData.nChannels());
104-
const size_t numPixels = (size_t)size.x() * size.y();
104+
const size_t numPixels = posProd(size);
105105

106106
const size_t expectedDataSize = numSamplesPerRowIn * size.y();
107107
if (imageData.size() < expectedDataSize) {

src/Channel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Channel::Channel(
9292
mDataOffset = dataOffset;
9393
mDataStride = dataStride;
9494
} else {
95-
mData = make_shared<PixelBuffer>(PixelBuffer::alloc((size_t)size.x() * size.y(), format));
95+
mData = make_shared<PixelBuffer>(PixelBuffer::alloc(posProd(size), format));
9696
mDataOffset = 0;
9797
mDataStride = 1;
9898
}
@@ -135,10 +135,10 @@ void Channel::updateTile(const Box2i bounds, const span<const float> newData) {
135135
return;
136136
}
137137

138-
const auto width = bounds.max.x() - bounds.min.x();
138+
const auto width = (size_t)(bounds.max.x() - bounds.min.x());
139139
for (int y = bounds.min.y(); y < bounds.max.y(); ++y) {
140140
for (int x = bounds.min.x(); x < bounds.max.x(); ++x) {
141-
dynamicSetAt({x, y}, newData[(x - bounds.min.x()) + (y - bounds.min.y()) * (size_t)width]);
141+
dynamicSetAt({x, y}, newData[(x - bounds.min.x()) + (y - bounds.min.y()) * width]);
142142
}
143143
}
144144
}

src/FalseColor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace tev {
2828
namespace colormap {
2929
span<const float> turbo() {
3030
// "turbo" colormap data generated with scripts/sample-colormap.py
31-
static constexpr array<float, 256 * 4> data = {
31+
static constexpr array data = {
3232
0.18995f, 0.07176f, 0.23217f, 1.0f,
3333
0.19483f, 0.08339f, 0.26149f, 1.0f,
3434
0.19956f, 0.09498f, 0.29024f, 1.0f,
@@ -292,7 +292,7 @@ namespace colormap {
292292

293293
span<const float> viridis() {
294294
// "viridis" colormap data generated with scripts/sample-colormap.py
295-
static constexpr array<float, 256 * 4> data = {
295+
static constexpr array data = {
296296
0.267004f, 0.004874f, 0.329415f, 1.0f,
297297
0.26851f, 0.009605f, 0.335427f, 1.0f,
298298
0.269944f, 0.014625f, 0.341379f, 1.0f,

src/Image.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ Task<void> prepareTextureChannel(T* data, const Channel* chan, Box2i box, size_t
761761
const T defaultVal = isAlpha ? (T)1.0f : (T)0.0f;
762762

763763
const auto size = box.size();
764-
const size_t numPixels = (size_t)size.x() * size.y();
764+
const size_t numPixels = posProd(size);
765765

766766
if (chan) {
767767
const auto copyChannel = [&](const auto view) -> Task<void> {
@@ -771,7 +771,7 @@ Task<void> prepareTextureChannel(T* data, const Channel* chan, Box2i box, size_t
771771
numPixels,
772772
[view, &data, numTextureChannels, channelIdx, width = size.x(), pos = box.min](int y) {
773773
for (int x = 0; x < width; ++x) {
774-
size_t tileIdx = x + y * (size_t)width;
774+
const auto tileIdx = x + y * (size_t)width;
775775
data[tileIdx * numTextureChannels + channelIdx] = view[pos.x() + x, pos.y() + y];
776776
}
777777
},
@@ -1184,7 +1184,7 @@ Task<HeapArray<float>> Image::getRgbaHdrImageData(
11841184

11851185
const size_t nColorChannels = alphaChannel ? (channels.size() - 1) : channels.size();
11861186

1187-
const auto numPixels = (size_t)imageRegion.size().x() * imageRegion.size().y();
1187+
const auto numPixels = imageRegion.area();
11881188
const auto nColorChannelsToSave = std::min(nColorChannels, 3uz);
11891189

11901190
// Flatten image into vector
@@ -1394,7 +1394,7 @@ Task<nanogui::Vector2i> orientToTopLeft(PixelBuffer& data, nanogui::Vector2i siz
13941394
nanogui::Vector2i otherSize = swapAxes ? nanogui::Vector2i{size.y(), size.x()} : size;
13951395

13961396
const size_t numBytesPerSample = nBytes(data.format());
1397-
const size_t numPixels = (size_t)size.x() * size.y();
1397+
const size_t numPixels = posProd(size);
13981398

13991399
if (numPixels == 0) {
14001400
co_return size;
@@ -1412,10 +1412,10 @@ Task<nanogui::Vector2i> orientToTopLeft(PixelBuffer& data, nanogui::Vector2i siz
14121412
numPixels,
14131413
[&](int y) {
14141414
for (int x = 0; x < size.x(); ++x) {
1415-
const size_t i = y * (size_t)size.x() + x;
1415+
const auto i = y * (size_t)size.x() + x;
14161416

14171417
const auto other = applyOrientation(orientation, nanogui::Vector2i{x, y}, size);
1418-
const size_t j = other.y() * (size_t)otherSize.x() + other.x();
1418+
const auto j = other.y() * (size_t)otherSize.x() + other.x();
14191419

14201420
memcpy(reorientedData.dataBytes() + i * numBytesPerPixel, data.dataBytes() + j * numBytesPerPixel, numBytesPerPixel);
14211421
}

src/UberShader.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,11 +508,14 @@ UberShader::UberShader(RenderPass* renderPass, float ditherScale) {
508508
mShader->set_buffer("position", VariableType::Float32, {4, 2}, positions);
509509

510510
const auto& fcd = colormap::turbo();
511+
if (fcd.size() % 4 != 0) {
512+
throw runtime_error{format("Invalid false color data size. Expected multiple of 4, got {}.", fcd.size())};
513+
}
511514

512515
mColorMap = new Texture{
513516
Texture::PixelFormat::RGBA, Texture::ComponentFormat::Float32, Vector2i{(int)fcd.size() / 4, 1}
514517
};
515-
mColorMap->upload((uint8_t*)fcd.data());
518+
mColorMap->upload(reinterpret_cast<const uint8_t*>(fcd.data()));
516519

517520
mDitherMatrix = new Texture{
518521
Texture::PixelFormat::R,
@@ -523,7 +526,12 @@ UberShader::UberShader(RenderPass* renderPass, float ditherScale) {
523526
Texture::WrapMode::Repeat,
524527
};
525528

526-
mDitherMatrix->upload((uint8_t*)ditherMatrix(ditherScale).data());
529+
const auto dmat = ditherMatrix(ditherScale);
530+
if (dmat.size() != posProd(mDitherMatrix->size())) {
531+
throw runtime_error{format("Invalid dither matrix size. Expected {}, got {}.", posProd(mDitherMatrix->size()), dmat.size())};
532+
}
533+
534+
mDitherMatrix->upload(reinterpret_cast<const uint8_t*>(dmat.data()));
527535
}
528536

529537
UberShader::~UberShader() {}

src/imageio/ClipboardImageLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Task<vector<ImageData>>
4646

4747
const Vector2i size{(int)spec.width, (int)spec.height};
4848

49-
const auto numPixels = (size_t)size.x() * size.y();
49+
const auto numPixels = posProd(size);
5050
if (numPixels == 0) {
5151
throw ImageLoadError{"Image has zero pixels."};
5252
}

src/imageio/Colors.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ Task<void> toLinearSrgbPremul(
912912
default: throw runtime_error{format("Invalid number of output channels {}", rgbaDst.nChannels())};
913913
}
914914

915-
const size_t numPixels = (size_t)size.x() * size.y();
915+
const size_t numPixels = posProd(size);
916916

917917
cmsHTRANSFORM transform = nullptr;
918918
if (cicp) {

src/imageio/DdsImageLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ Task<vector<ImageData>> DdsImageLoader::load(istream& iStream, const fs::path&,
237237

238238
const auto outView = MultiChannelView<float>{resultData.channels};
239239

240-
const auto numPixels = (size_t)size.x() * size.y();
240+
const auto numPixels = posProd(size);
241241
if (numPixels == 0) {
242242
throw ImageLoadError{"DDS image has zero pixels."};
243243
}

0 commit comments

Comments
 (0)