Skip to content

Commit 235e979

Browse files
authored
api: image_span-ify ImageCache and TextureSystem (#4783)
I think this is all the span-izing that the public interface of ImageCache and TextureSystem needs. And it doesn't break ABI compatibility (unlike the ImageInput and ImageOutput changes recently) because these aren't virtual methods. --------- Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 4e56aa7 commit 235e979

9 files changed

Lines changed: 432 additions & 2 deletions

File tree

src/doc/imagecache.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ Below are some simple code fragments that shows ImageCache in action::
6060
// (for brevity of this example, let's assume that 'size' is the
6161
// number of channels times the number of pixels in the requested region)
6262
float pixels[size];
63-
cache->get_pixels ("file1.jpg", 0, 0, xbegin, xend, ybegin, yend,
64-
zbegin, zend, TypeDesc::FLOAT, pixels);
63+
cache->get_pixels ("file1.jpg", 0, 0, ROI(xbegin, xend, ybegin, yend),
64+
make_span(pixels));
6565

6666
// Get information about a file
6767
ImageSpec spec;

src/include/OpenImageIO/imagecache.h

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,139 @@ class OIIO_API ImageCache {
872872
/// @{
873873
/// @name Getting Pixels
874874

875+
/// For an image specified by name, retrieve the rectangle of pixels from
876+
/// the designated subimage and MIP level, storing the pixel values in the
877+
/// memory layout specified by `result`. The pixel values will be
878+
/// converted to the data type specified by `format`. The rectangular
879+
/// region to be retrieved, specified by `roi`, includes `begin` but does
880+
/// not include `end` (much like STL begin/end usage). Requested pixels
881+
/// that are not part of the valid pixel data region of the image file
882+
/// will be filled with zero values.
883+
///
884+
/// @param filename
885+
/// The name of the image, as a UTF-8 encoded ustring.
886+
/// @param subimage/miplevel
887+
/// The subimage and MIP level to retrieve pixels from.
888+
/// @param roi
889+
/// The range of pixels and channels to retrieve. The pixels
890+
/// retrieved include the begin values but not the end values
891+
/// (much like STL begin/end usage).
892+
/// @param format
893+
/// TypeDesc describing the data type of the values you want
894+
/// to retrieve into `result`. The pixel values will be
895+
/// converted to this type regardless of how they were
896+
/// stored in the cache.
897+
/// @param result
898+
/// An `image_span` describing the memory layout where the
899+
/// pixel values should be stored, including bounds and
900+
/// strides for each dimension.
901+
/// @param cache_chbegin/cache_chend
902+
/// These parameters can be used to tell the ImageCache to
903+
/// read and cache a subset of channels (if not specified or
904+
/// if they denote a non-positive range, all the channels of
905+
/// the file will be stored in the cached tile).
906+
/// @returns `true` upon success, or `false` upon failure.
907+
///
908+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
909+
/// the version of read_scanlines that takes raw pointers.
910+
///
911+
bool get_pixels(ustring filename, int subimage, int miplevel,
912+
const ROI& roi, TypeDesc format,
913+
const image_span<std::byte>& result, int cache_chbegin = 0,
914+
int cache_chend = -1);
915+
/// A more efficient variety of `get_pixels()` for cases where you can use
916+
/// an `ImageHandle*` to specify the image and optionally have a
917+
/// `Perthread*` for the calling thread.
918+
///
919+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
920+
/// the version of read_scanlines that takes raw pointers.
921+
bool get_pixels(ImageHandle* file, Perthread* thread_info, int subimage,
922+
int miplevel, const ROI& roi, TypeDesc format,
923+
const image_span<std::byte>& result, int cache_chbegin = 0,
924+
int cache_chend = -1);
925+
926+
/// A version of `get_pixels()` taking an `image_span<T>`, where the type
927+
/// of the underlying data is `T`. This is a convenience wrapper around
928+
/// the `get_pixels()` that takes an `image_span<std::byte>`.
929+
///
930+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
931+
/// the version of read_scanlines that takes raw pointers.
932+
template<typename T>
933+
bool get_pixels(ustring filename, int subimage, int miplevel,
934+
const ROI& roi, const image_span<T>& result,
935+
int cache_chbegin = 0, int cache_chend = -1)
936+
{
937+
static_assert(!std::is_const_v<T>,
938+
"get_pixels() does not accept image_span<const T>");
939+
return get_pixels(filename, subimage, miplevel, roi,
940+
TypeDescFromC<T>::value(),
941+
as_image_span_writable_bytes(result), cache_chbegin,
942+
cache_chend);
943+
}
944+
/// A more efficient variety of `get_pixels()` taking an `image_span<T>`,
945+
/// for cases where you can use an `ImageHandle*` to specify the image and
946+
/// optionally have a `Perthread*` for the calling thread.
947+
///
948+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
949+
/// the version of read_scanlines that takes raw pointers.
950+
template<typename T>
951+
bool get_pixels(ImageHandle* file, Perthread* thread_info, int subimage,
952+
int miplevel, const ROI& roi, const image_span<T>& result,
953+
int cache_chbegin = 0, int cache_chend = -1)
954+
{
955+
static_assert(!std::is_const_v<T>,
956+
"get_pixels() does not accept image_span<const T>");
957+
return get_pixels(file, thread_info, subimage, miplevel, roi,
958+
TypeDescFromC<T>::value(),
959+
as_image_span_writable_bytes(result), cache_chbegin,
960+
cache_chend);
961+
}
962+
963+
/// A version of `get_pixels()` taking a `span<T>`, which assumes
964+
/// contiguous strides in all dimensions. This is a convenience wrapper
965+
/// around the `get_pixels()` that takes an `image_span<T>`.
966+
///
967+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
968+
/// the version of read_scanlines that takes raw pointers.
969+
template<typename T>
970+
bool get_pixels(ImageHandle* file, Perthread* thread_info, int subimage,
971+
int miplevel, const ROI& roi, const span<T>& result,
972+
int cache_chbegin = 0, int cache_chend = -1)
973+
{
974+
static_assert(!std::is_const_v<T>,
975+
"get_pixels() does not accept span<const T>");
976+
auto ispan = image_span<T>(result.data(), roi.nchannels(), roi.width(),
977+
roi.height(), roi.depth());
978+
OIIO_DASSERT(result.size_bytes() == ispan.size_bytes()
979+
&& ispan.is_contiguous());
980+
return get_pixels(file, thread_info, subimage, miplevel, roi,
981+
TypeDescFromC<T>::value(),
982+
as_image_span_writable_bytes(result), cache_chbegin,
983+
cache_chend);
984+
}
985+
/// A more efficient variety of `get_pixels()` taking a `span<T>`, for
986+
/// cases where you can use an `ImageHandle*` to specify the image and
987+
/// optionally have a `Perthread*` for the calling thread.
988+
///
989+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
990+
/// the version of read_scanlines that takes raw pointers.
991+
template<typename T>
992+
bool get_pixels(ustring filename, int subimage, int miplevel,
993+
const ROI& roi, const span<T>& result,
994+
int cache_chbegin = 0, int cache_chend = -1)
995+
{
996+
static_assert(!std::is_const_v<T>,
997+
"get_pixels() does not accept span<const T>");
998+
auto ispan = image_span<T>(result.data(), roi.nchannels(), roi.width(),
999+
roi.height(), roi.depth());
1000+
OIIO_DASSERT(result.size_bytes() == ispan.size_bytes()
1001+
&& ispan.is_contiguous());
1002+
return get_pixels(filename, subimage, miplevel, roi,
1003+
TypeDescFromC<T>::value(),
1004+
as_image_span_writable_bytes(result), cache_chbegin,
1005+
cache_chend);
1006+
}
1007+
8751008
/// For an image specified by name, retrieve the rectangle of pixels
8761009
/// from the designated subimage and MIP level, storing the pixel values
8771010
/// beginning at the address specified by `result` and with the given
@@ -881,6 +1014,10 @@ class OIIO_API ImageCache {
8811014
/// usage). Requested pixels that are not part of the valid pixel data
8821015
/// region of the image file will be filled with zero values.
8831016
///
1017+
/// These pointer-based versions are considered "soft-deprecated" in
1018+
/// OpenImageIO 3.1, will be marked/warned as deprecated in 3.2, and will
1019+
/// be removed in 4.0.
1020+
///
8841021
/// @param filename
8851022
/// The name of the image, as a UTF-8 encoded ustring.
8861023
/// @param subimage/miplevel
@@ -926,6 +1063,10 @@ class OIIO_API ImageCache {
9261063
/// A more efficient variety of `get_pixels()` for cases where you can
9271064
/// use an `ImageHandle*` to specify the image and optionally have a
9281065
/// `Perthread*` for the calling thread.
1066+
///
1067+
/// These pointer-based versions are considered "soft-deprecated" in
1068+
/// OpenImageIO 3.1, will be marked/warned as deprecated in 3.2, and will
1069+
/// be removed in 4.0.
9291070
bool get_pixels(ImageHandle* file, Perthread* thread_info, int subimage,
9301071
int miplevel, int xbegin, int xend, int ybegin, int yend,
9311072
int zbegin, int zend, int chbegin, int chend,
@@ -937,15 +1078,24 @@ class OIIO_API ImageCache {
9371078

9381079
/// A simplified `get_pixels()` where all channels are retrieved,
9391080
/// strides are assumed to be contiguous.
1081+
///
1082+
/// These pointer-based versions are considered "soft-deprecated" in
1083+
/// OpenImageIO 3.1, will be marked/warned as deprecated in 3.2, and will
1084+
/// be removed in 4.0.
9401085
bool get_pixels(ustring filename, int subimage, int miplevel, int xbegin,
9411086
int xend, int ybegin, int yend, int zbegin, int zend,
9421087
TypeDesc format, void* result);
9431088
/// A more efficient variety of `get_pixels()` for cases where you can
9441089
/// use an `ImageHandle*` to specify the image and optionally have a
9451090
/// `Perthread*` for the calling thread.
1091+
///
1092+
/// These pointer-based versions are considered "soft-deprecated" in
1093+
/// OpenImageIO 3.1, will be marked/warned as deprecated in 3.2, and will
1094+
/// be removed in 4.0.
9461095
bool get_pixels(ImageHandle* file, Perthread* thread_info, int subimage,
9471096
int miplevel, int xbegin, int xend, int ybegin, int yend,
9481097
int zbegin, int zend, TypeDesc format, void* result);
1098+
9491099
/// @}
9501100

9511101
/// @{
@@ -1085,6 +1235,34 @@ class OIIO_API ImageCache {
10851235
stride_t ystride = AutoStride, stride_t zstride = AutoStride,
10861236
bool copy = true);
10871237

1238+
/// Preemptively add a tile corresponding to the named image, at the given
1239+
/// subimage, MIP level, and channel range. The tile added is the one
1240+
/// whose corner is (x,y,z), and buffer points to the pixels (in the given
1241+
/// format) which will be copied and inserted into the cache and made
1242+
/// available for future lookups. If chend < chbegin, it will add a tile
1243+
/// containing the full set of channels for the image. Note that if the
1244+
/// 'copy' flag is false, the data is assumed to be in some kind of
1245+
/// persistent storage and will not be copied, nor will its pixels take up
1246+
/// additional memory in the cache.
1247+
bool add_tile(ustring filename, int subimage, int miplevel, int x, int y,
1248+
int z, int chbegin, int chend, TypeDesc format,
1249+
const image_span<const std::byte>& buffer, bool copy = true);
1250+
1251+
/// A version of `add_tile()` taking an `image_span<T>`, where the type of
1252+
/// the underlying data is `T`. This is a convenience wrapper around the
1253+
/// `add_tile()` that takes an `image_span<std::byte>`.
1254+
template<typename T>
1255+
bool add_tile(ustring filename, int subimage, int miplevel, int x, int y,
1256+
int z, int chbegin, int chend, const image_span<T>& buffer,
1257+
bool copy = true)
1258+
{
1259+
static_assert(!std::is_const_v<T>,
1260+
"add_tile() does not accept image_span<const T>");
1261+
return add_tile(filename, subimage, miplevel, x, y, z, chbegin, chend,
1262+
TypeDescFromC<T>::value(), as_image_span_bytes(buffer),
1263+
copy);
1264+
}
1265+
10881266
/// @}
10891267

10901268
/// @{

src/include/OpenImageIO/texture.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,62 @@ class OIIO_API TextureSystem {
15141514
/// @param miplevel
15151515
/// The MIP level to retrieve pixels from (0 is the highest
15161516
/// resolution level).
1517+
/// @param roi
1518+
/// The range of pixels and channels to retrieve. The pixels
1519+
/// retrieved include the begin values but not the end values
1520+
/// (much like STL begin/end usage).
1521+
/// @param format
1522+
/// TypeDesc describing the data type of the values you want
1523+
/// to retrieve into `result`. The pixel values will be
1524+
/// converted to this type regardless of how they were
1525+
/// stored in the file or in the cache.
1526+
/// @param result
1527+
/// An `image_span` describing the memory layout where the
1528+
/// pixel values should be stored, including bounds and
1529+
/// strides for each dimension.
1530+
/// @returns
1531+
/// `true` for success, `false` for failure.
1532+
///
1533+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
1534+
/// the version of read_scanlines that takes raw pointers.
1535+
///
1536+
bool get_texels(ustring filename, TextureOpt& options, int miplevel,
1537+
const ROI& roi, TypeDesc format,
1538+
const image_span<std::byte>& result);
1539+
/// A more efficient variety of `get_texels()` for cases where you can
1540+
/// use a `TextureHandle*` to specify the image and optionally have a
1541+
/// `Perthread*` for the calling thread.
1542+
///
1543+
/// Added in OIIO 3.1, this is the "safe" preferred alternative to
1544+
/// the version of read_scanlines that takes raw pointers.
1545+
bool get_texels(TextureHandle* texture_handle, Perthread* thread_info,
1546+
TextureOpt& options, int miplevel, const ROI& roi,
1547+
TypeDesc format, const image_span<std::byte>& result);
1548+
1549+
/// For a texture specified by name, retrieve the rectangle of raw
1550+
/// unfiltered texels from the subimage specified in `options` and at
1551+
/// the designated `miplevel`, storing the pixel values beginning at the
1552+
/// address specified by `result`. The pixel values will be converted
1553+
/// to the data type specified by `format`. The rectangular region to be
1554+
/// retrieved includes `begin` but does not include `end` (much like STL
1555+
/// begin/end usage). Requested pixels that are not part of the valid
1556+
/// pixel data region of the image file will be filled with zero values.
1557+
/// Channels requested but not present in the file will get the
1558+
/// `options.fill` value.
1559+
///
1560+
/// These pointer-based versions are considered "soft-deprecated" in
1561+
/// OpenImageIO 3.1, will be marked/warned as deprecated in 3.2, and will
1562+
/// be removed in 4.0.
1563+
///
1564+
/// @param filename
1565+
/// The name of the texture, as a UTF-8 encode ustring.
1566+
/// @param options
1567+
/// A TextureOpt describing access options, including wrap
1568+
/// modes, fill value, and subimage, that will be used when
1569+
/// retrieving pixels.
1570+
/// @param miplevel
1571+
/// The MIP level to retrieve pixels from (0 is the highest
1572+
/// resolution level).
15171573
/// @param xbegin/xend/ybegin/yend/zbegin/zend
15181574
/// The range of pixels to retrieve. The pixels retrieved
15191575
/// include the begin value but not the end value (much like

0 commit comments

Comments
 (0)