Skip to content

Commit 045233a

Browse files
authored
api: image_span-ify ImageBuf (#4814)
We've already done ImageInput, ImageOutput, ImageCache, TextureSystem. This applies the analogous set of changes to the public APIs of ImageBuf -- adding span and image_span versions of all the API calls that previously required raw pointers and strides. Many of the internals are still using the old versions, but at least this takes care of the interface. Specifically, this does constructors, reset(), and get_pixels(). --------- Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent f5b6c6c commit 045233a

5 files changed

Lines changed: 442 additions & 259 deletions

File tree

src/doc/imagebuf.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ Constructing a writable ImageBuf
6262
Constructing an ImageBuf that "wraps" an application buffer
6363
-------------------------------------------------------------
6464

65+
.. doxygenfunction:: OIIO::ImageBuf::ImageBuf(const ImageSpec &spec, const image_span<T>&)
66+
.. doxygenfunction:: OIIO::ImageBuf::reset(const ImageSpec &spec, const image_span<T>&)
67+
6568
.. doxygenfunction:: OIIO::ImageBuf::ImageBuf(const ImageSpec &spec, void *buffer, stride_t xstride = AutoStride, stride_t ystride = AutoStride, stride_t zstride = AutoStride)
6669
.. doxygenfunction:: OIIO::ImageBuf::reset(const ImageSpec &spec, void *buffer, stride_t xstride = AutoStride, stride_t ystride = AutoStride, stride_t zstride = AutoStride)
6770

@@ -176,6 +179,16 @@ Getting and setting pixel values
176179
177180
**Getting and setting regions of pixels -- fast**
178181

182+
.. doxygenfunction:: OIIO::ImageBuf::get_pixels(ROI, const image_span<T>&) const
183+
.. doxygenfunction:: OIIO::ImageBuf::get_pixels(ROI, TypeDesc, const image_span<std::byte>&) const
184+
185+
|
186+
187+
**Getting and setting regions of pixels -- deprecated**
188+
189+
These raw pointer versions of `get_pixels()` and `set_pixels()` should be
190+
converted to the `span` and `image_span` based versions.
191+
179192
.. doxygenfunction:: OIIO::ImageBuf::get_pixels(ROI, span<T>, stride_t, stride_t, stride_t) const
180193
.. doxygenfunction:: OIIO::ImageBuf::get_pixels(ROI, span<T>, T*, stride_t, stride_t, stride_t) const
181194
.. doxygenfunction:: OIIO::ImageBuf::set_pixels(ROI, span<T>, stride_t, stride_t, stride_t)

src/include/OpenImageIO/image_span.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ template<typename T, size_t Rank = 4> class image_span {
7070
// Validations:
7171
// - an image_span<byte> can have any chansize, but any other T must
7272
// have the chansize equal to the data type size.
73-
OIIO_DASSERT(nchannels > 0 && width > 0 && height > 0 && depth > 0);
7473
OIIO_DASSERT((std::is_same<std::remove_const_t<T>, std::byte>::value)
7574
|| chansize == sizeof(T));
7675

@@ -374,8 +373,8 @@ as_image_span_bytes(const image_span<T, Rank>& src) noexcept
374373
}
375374

376375

377-
/// Convert an image_span of any type to a mutable span of bytes covering
378-
/// the same range of memory.
376+
/// Convert an image_span of any nonconst type to a mutable span of bytes
377+
/// covering the same range of memory.
379378
template<typename T, size_t Rank>
380379
image_span<std::byte>
381380
as_image_span_writable_bytes(const image_span<T, Rank>& src) noexcept
@@ -386,7 +385,6 @@ as_image_span_writable_bytes(const image_span<T, Rank>& src) noexcept
386385
src.ystride(), src.zstride(), src.chansize());
387386
}
388387

389-
390388
/// Verify that the image_span has all its contents lying within the
391389
/// contiguous span.
392390
OIIO_API bool

src/include/OpenImageIO/imagebuf.h

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,40 @@ class OIIO_API ImageBuf {
281281
void* buforigin = nullptr, stride_t xstride = AutoStride,
282282
stride_t ystride = AutoStride, stride_t zstride = AutoStride);
283283

284+
/// Construct an ImageBuf that "wraps" existing pixel memory owned by the
285+
/// calling application. The ImageBuf does not own the pixel storage and
286+
/// will not free/delete that memory, even when the ImageBuf is destroyed.
287+
/// Upon successful initialization, the storage will be reported as
288+
/// `APPBUFFER`. Note that the ImageBuf will be writable if passed an
289+
/// `image_span<T>` with a mutable type `T`, but it will be "read-only" if
290+
/// passed an `image_span<const T>`.
291+
///
292+
/// @param spec
293+
/// An ImageSpec describing the image and its metadata. If
294+
/// not enough information is given to know the "shape" of
295+
/// the image (width, height, depth, channels, and data
296+
/// format), the ImageBuf will remain in an UNINITIALIZED
297+
/// state.
298+
/// @param buffer
299+
/// An image_span delineating the extent and striding of the
300+
/// safely accessible memory comprising the pixel data.
301+
template<typename T>
302+
ImageBuf(const ImageSpec& spec, const image_span<T>& buffer)
303+
: ImageBuf(spec, as_image_span_writable_bytes(buffer))
304+
{
305+
}
306+
template<typename T>
307+
ImageBuf(const ImageSpec& spec, const image_span<const T>& buffer)
308+
: ImageBuf(spec, as_image_span_bytes(buffer))
309+
{
310+
}
311+
// Special base case for read-only byte image_spans, this one does the
312+
// hard work.
313+
ImageBuf(const ImageSpec& spec, const image_span<const std::byte>& buffer);
314+
// Special base case for mutable byte image_spans, this one does the hard
315+
// work.
316+
ImageBuf(const ImageSpec& spec, const image_span<std::byte>& buffer);
317+
284318
// Unsafe constructor of an ImageBuf that wraps an existing buffer, where
285319
// only the origin pointer and the strides are given. Use with caution!
286320
OIIO_IB_DEPRECATE_RAW_PTR
@@ -332,6 +366,28 @@ class OIIO_API ImageBuf {
332366
set_name(name);
333367
}
334368

369+
/// Destroy any previous contents of the ImageBuf and re-initialize it as
370+
/// if newly constructed with the same arguments, to "wrap" existing pixel
371+
/// memory owned by the calling application. See the ImageBuf constructor
372+
/// from an image_span for more details.
373+
template<typename T>
374+
void reset(const ImageSpec& spec, const image_span<T>& buffer)
375+
{
376+
// The general case for non-byte data types just converts to bytes and
377+
// calls the byte version.
378+
if constexpr (std::is_const_v<T>)
379+
reset(spec, as_image_span_bytes(buffer));
380+
else
381+
reset(spec, as_image_span_writable_bytes(buffer));
382+
}
383+
// Special base case for read-only byte spans, this one does the hard work.
384+
void reset(const ImageSpec& spec,
385+
const image_span<const std::byte>& buffer);
386+
// Special base case for mutable byte spans, this one does the hard work.
387+
void reset(const ImageSpec& spec, const image_span<std::byte>& buffer);
388+
389+
/// Slated for deprecation in favor of the image_span-based version.
390+
///
335391
/// Destroy any previous contents of the ImageBuf and re-initialize it as
336392
/// if newly constructed with the same arguments, to "wrap" existing pixel
337393
/// memory owned by the calling application.
@@ -929,6 +985,33 @@ class OIIO_API ImageBuf {
929985
setpixel(i, make_cspan(pixel, size_t(n)));
930986
}
931987

988+
/// Retrieve the rectangle of pixels spanning the ROI (including
989+
/// channels) at the current subimage and MIP-map level, storing the
990+
/// pixel values into the `buffer`.
991+
///
992+
/// @param roi
993+
/// The region of interest to copy into. A default
994+
/// uninitialized ROI means the entire image.
995+
/// @param buffer
996+
/// An image_span delineating the extent of the safely
997+
/// accessible memory where the results should be stored.
998+
/// @returns
999+
/// Return true if the operation could be completed,
1000+
/// otherwise return false.
1001+
///
1002+
template<typename T>
1003+
bool get_pixels(ROI roi, const image_span<T>& buffer) const
1004+
{
1005+
static_assert(!std::is_const_v<T>);
1006+
return get_pixels(roi, TypeDescFromC<T>::value(),
1007+
as_image_span_writable_bytes(buffer));
1008+
}
1009+
1010+
/// Base case of get_pixels: read into an image_span of generic bytes. The
1011+
/// requested data type is supplied by `format`.
1012+
bool get_pixels(ROI roi, TypeDesc format,
1013+
const image_span<std::byte>& buffer) const;
1014+
9321015
/// Retrieve the rectangle of pixels spanning the ROI (including
9331016
/// channels) at the current subimage and MIP-map level, storing the
9341017
/// pixel values into the `buffer`.
@@ -981,13 +1064,13 @@ class OIIO_API ImageBuf {
9811064

9821065
#ifndef OIIO_DOXYGEN
9831066
/// Base case of get_pixels: read into a span of generic bytes. The
984-
/// requested data type is supplied by `format.
1067+
/// requested data type is supplied by `format`.
9851068
bool get_pixels(ROI roi, TypeDesc format, span<std::byte> buffer,
9861069
void* buforigin = nullptr, stride_t xstride = AutoStride,
9871070
stride_t ystride = AutoStride,
9881071
stride_t zstride = AutoStride) const;
9891072

990-
/// Potentially unsafe get_pixels() using raw pointers. Use with catution!
1073+
/// Potentially unsafe get_pixels() using raw pointers. Use with caution!
9911074
OIIO_IB_DEPRECATE_RAW_PTR
9921075
bool get_pixels(ROI roi, TypeDesc format, void* result,
9931076
stride_t xstride = AutoStride,
@@ -1053,7 +1136,7 @@ class OIIO_API ImageBuf {
10531136

10541137
#ifndef OIIO_DOXYGEN
10551138
/// Base case of get_pixels: read into a span of generic bytes. The
1056-
/// requested data type is supplied by `format.
1139+
/// requested data type is supplied by `format`.
10571140
bool set_pixels(ROI roi, TypeDesc format, cspan<std::byte> buffer,
10581141
const void* buforigin = nullptr,
10591142
stride_t xstride = AutoStride,

0 commit comments

Comments
 (0)