Skip to content

Commit aefe764

Browse files
committed
more thorough test and some fixes
Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 2227a96 commit aefe764

3 files changed

Lines changed: 120 additions & 41 deletions

File tree

src/include/OpenImageIO/image_span.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ template<typename T, size_t Rank = 4> class image_span {
205205
/// un-typed memory.
206206
image_span<const std::byte> as_bytes_image_span() const noexcept
207207
{
208-
return image_span<const std::byte>(static_cast<const std::byte*>(m_data),
208+
return image_span<const std::byte>(reinterpret_cast<const std::byte*>(
209+
m_data),
209210
nchannels(), width(), height(),
210211
depth(), chanstride(), xstride(),
211212
ystride(), zstride(), m_chansize);
@@ -216,7 +217,7 @@ template<typename T, size_t Rank = 4> class image_span {
216217
/// Note that this will not work (be a compiler error) if T a const type.
217218
image_span<std::byte> as_writable_bytes_image_span() const noexcept
218219
{
219-
return image_span<std::byte>(static_cast<std::byte*>(m_data),
220+
return image_span<std::byte>(reinterpret_cast<std::byte*>(m_data),
220221
nchannels(), width(), height(), depth(),
221222
chanstride(), xstride(), ystride(),
222223
zstride(), m_chansize);

src/libOpenImageIO/image_span_test.cpp

Lines changed: 116 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -93,28 +93,72 @@ test_image_span()
9393

9494

9595

96+
template<typename T>
97+
T
98+
testvalue(int x, int y, int z, int c)
99+
{
100+
return T(x + y + z + c);
101+
}
102+
103+
104+
// Fill an image span in a characteristic way
105+
template<typename T>
106+
void
107+
fill_image_span(image_span<T> img)
108+
{
109+
// Fill the image with a constant value
110+
for (uint32_t z = 0; z < img.depth(); ++z) {
111+
for (uint32_t y = 0; y < img.height(); ++y) {
112+
for (uint32_t x = 0; x < img.width(); ++x) {
113+
for (uint32_t c = 0; c < img.nchannels(); ++c) {
114+
img(x, y, z)[c] = testvalue<T>(x, y, z, c);
115+
}
116+
}
117+
}
118+
}
119+
}
120+
121+
122+
// Check that an image span in the characteristic way
123+
template<typename T>
124+
bool
125+
check_image_span(image_span<T> img, int xoff = 0, int yoff = 0, int zoff = 0)
126+
{
127+
// Fill the image with a constant value
128+
for (uint32_t z = 0; z < img.depth(); ++z) {
129+
for (uint32_t y = 0; y < img.height(); ++y) {
130+
for (uint32_t x = 0; x < img.width(); ++x) {
131+
for (uint32_t c = 0; c < img.nchannels(); ++c) {
132+
auto v = testvalue<T>(x + xoff, y + yoff, z + zoff, c);
133+
OIIO_CHECK_EQUAL(img(x, y, z)[c], v);
134+
if (img(x, y, z)[c] != v) {
135+
print("\tError at ({}, {}, {})[{}]\n", x, y, z, c);
136+
return false;
137+
}
138+
}
139+
}
140+
}
141+
}
142+
return true;
143+
}
144+
145+
146+
96147
template<typename T = float>
97148
void
98-
benchmark_image_span_copy_image()
149+
test_image_span_copy_image()
99150
{
100-
// Benchmark old (ptr) versus new (span) copy_image functions
101-
Benchmarker bench;
102-
bench.units(Benchmarker::Unit::us);
103151
const int xres = 2048, yres = 1536, nchans = 4;
104-
std::vector<T> sbuf(xres * yres * nchans);
105-
std::vector<T> dbuf(xres * yres * nchans);
106152
const size_t chansize = sizeof(T);
107-
108-
print("Benchmarking copy_image {} (total {} MB):\n",
109-
TypeDescFromC<T>::value(),
153+
print("\nTesting copy_image {} (total {} MB):\n", TypeDescFromC<T>::value(),
110154
xres * yres * nchans * chansize * 3 / 4 / 1024 / 1024);
111155

112156
// We test different amounts of contiguity. Each test copies 3/4 of the
113157
// total image, to keep the total number of bytes copied identical.
114158
const stride_t src_xstride(chansize * nchans);
115159
const stride_t src_ystride(src_xstride * xres);
116160
for (int i = 0; i < 3; ++i) {
117-
size_t nc(nchans), pixsize(chansize * nchans), w(xres), h(yres);
161+
size_t nc(nchans), w(xres), h(yres);
118162
std::string label;
119163
if (i == 0) {
120164
// Fully contiguous region -- copy 3/4 of the image.
@@ -129,14 +173,31 @@ benchmark_image_span_copy_image()
129173
label = "contig pixels";
130174
nc = nc * 3 / 4;
131175
}
132-
bench(Strutil::format(" copy_image image_span {}", label), [&]() {
133-
copy_image(image_span<T>(dbuf.data(), nc, w, h, 1, chansize,
134-
src_xstride, src_ystride, AutoStride,
135-
chansize),
136-
image_span<const T>(sbuf.data(), nc, w, h, 1));
137-
});
138-
bench(Strutil::format(" copy_image raw ptrs {}", label), [&]() {
139-
copy_image(nc, w, h, 1, sbuf.data(), pixsize, src_xstride,
176+
177+
print(" test image_span copy_image {}\n", label);
178+
std::vector<T> sbuf(xres * yres * nchans);
179+
std::vector<T> dbuf(w * h * nc);
180+
181+
// Spans for src and dst -- src has the "original" strides, dst
182+
// has contiguous strides.
183+
image_span<T> sispan(sbuf.data(), nc, w, h, 1, chansize, src_xstride,
184+
src_ystride, AutoStride);
185+
image_span<T> dispan(dbuf.data(), nc, w, h, 1);
186+
187+
// Test correctness
188+
fill_image_span(sispan);
189+
copy_image(dispan, sispan);
190+
OIIO_CHECK_ASSERT(check_image_span(dispan));
191+
192+
// Benchmark old (ptr) versus new (span) copy_image functions
193+
Benchmarker bench;
194+
bench.units(Benchmarker::Unit::us);
195+
196+
bench(Strutil::format(" copy_image image_span {}", label),
197+
[&]() { copy_image(dispan, sispan); });
198+
// Test equivalent version with pointers
199+
bench(Strutil::format(" copy_image raw ptrs {}", label), [&]() {
200+
copy_image(nc, w, h, 1, sbuf.data(), nc * chansize, src_xstride,
140201
src_ystride, AutoStride, dbuf.data(), AutoStride,
141202
AutoStride, AutoStride);
142203
});
@@ -147,23 +208,19 @@ benchmark_image_span_copy_image()
147208

148209
template<typename T = float>
149210
void
150-
benchmark_image_span_contiguize()
211+
test_image_span_contiguize()
151212
{
152213
// Benchmark old (ptr) versus new (span) contiguize functions
153214
using pvt::contiguize;
154215

155-
// Benchmark old (ptr) versus new (span) contiguize functions
156-
Benchmarker bench;
157-
bench.units(Benchmarker::Unit::us);
158216
const int xres = 2048, yres = 1536, nchans = 4;
159-
std::vector<T> sbuf(xres * yres * nchans);
160-
std::vector<T> dbuf(xres * yres * nchans);
161217
const size_t chansize = sizeof(T);
162-
163-
print("Benchmarking contiguize {} (total {} MB):\n",
164-
TypeDescFromC<T>::value(),
218+
print("\nTesting contiguize {} (total {} MB):\n", TypeDescFromC<T>::value(),
165219
xres * yres * nchans * chansize * 3 / 4 / 1024 / 1024);
166220

221+
// std::vector<T> sbuf(xres * yres * nchans);
222+
// std::vector<T> dbuf(xres * yres * nchans);
223+
167224
// We test different amounts of contiguity. Each test copies 3/4 of the
168225
// total image, to keep the total number of bytes copied identical.
169226
const stride_t src_xstride(chansize * nchans);
@@ -184,15 +241,35 @@ benchmark_image_span_contiguize()
184241
label = "contig pixels";
185242
nc = nc * 3 / 4;
186243
}
187-
bench(Strutil::format(" contiguize image_span {}", label), [&]() {
188-
auto r = contiguize(image_span(reinterpret_cast<const std::byte*>(
189-
sbuf.data()),
190-
nc, w, h, 1, chansize, src_xstride,
191-
src_ystride, AutoStride, chansize),
244+
245+
print(" test image_span contiguize {}\n", label);
246+
std::vector<T> sbuf(xres * yres * nchans, T(100));
247+
std::vector<T> dbuf(w * h * nc, T(100));
248+
249+
// Spans for src and dst -- src has the "original" strides, dst
250+
// has contiguous strides.
251+
image_span<T> sispan(sbuf.data(), nc, w, h, 1, chansize, src_xstride,
252+
src_ystride, AutoStride);
253+
image_span<T> dispan(dbuf.data(), nc, w, h, 1);
254+
255+
// Test correctness
256+
fill_image_span(sispan);
257+
auto rspan = contiguize(sispan.as_bytes_image_span(),
258+
as_writable_bytes(make_span(dbuf)));
259+
OIIO_CHECK_ASSERT(check_image_span(
260+
image_span<const T>(reinterpret_cast<const T*>(rspan.data()), nc, w,
261+
h, 1)));
262+
263+
// Benchmark old (ptr) versus new (span) contiguize functions
264+
Benchmarker bench;
265+
bench.units(Benchmarker::Unit::us);
266+
267+
bench(Strutil::format(" contiguize image_span {}", label), [&]() {
268+
auto r = contiguize(sispan.as_writable_bytes_image_span(),
192269
as_writable_bytes(make_span(dbuf)));
193270
OIIO_ASSERT(r.size_bytes() == nc * w * h * sizeof(T));
194271
});
195-
bench(Strutil::format(" contiguize raw ptrs {}", label), [&]() {
272+
bench(Strutil::format(" contiguize raw ptrs {}", label), [&]() {
196273
contiguize(sbuf.data(), nc, src_xstride, src_ystride,
197274
src_ystride * h, dbuf.data(), w, h, 1,
198275
TypeDescFromC<T>::value());
@@ -212,13 +289,13 @@ main(int /*argc*/, char* /*argv*/[])
212289
test_image_span<uint8_t>();
213290
test_image_span<const uint8_t>();
214291

215-
benchmark_image_span_copy_image<float>();
216-
benchmark_image_span_copy_image<uint16_t>();
217-
benchmark_image_span_copy_image<uint8_t>();
292+
test_image_span_copy_image<float>();
293+
test_image_span_copy_image<uint16_t>();
294+
test_image_span_copy_image<uint8_t>();
218295

219-
benchmark_image_span_contiguize<float>();
220-
benchmark_image_span_contiguize<uint16_t>();
221-
benchmark_image_span_contiguize<uint8_t>();
296+
test_image_span_contiguize<float>();
297+
test_image_span_contiguize<uint16_t>();
298+
test_image_span_contiguize<uint8_t>();
222299

223300
return unit_test_failures;
224301
}

src/libOpenImageIO/imageio.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ pvt::contiguize(image_span<const std::byte> src, span<std::byte> dst)
750750
image_span dstspan(dst.data(), src.nchannels(), src.width(),
751751
src.height(), src.depth(), AutoStride, AutoStride,
752752
AutoStride, AutoStride, src.chansize());
753+
OIIO_DASSERT(dstspan.size_bytes() == src.size_bytes());
753754
copy_image(dstspan, src);
754755
return make_cspan(dst.data(), src.size_bytes());
755756
}

0 commit comments

Comments
 (0)