Skip to content

Conversation

@lgritz
Copy link
Collaborator

@lgritz lgritz commented May 11, 2025

ImageInput methods that read scanlines, tiles, and image are given new flavors that take image_span, much like the changes of PR #4727 did for ImageOutput.

Generally, for each, there are three versions: (1) a low-level virtual method base case that takes an image_span<byte> that describes the underlying memory, and an explicit TypeDesc that specifies the data type conversion (including allowing TypeUnknown to indicate keeping channels in their native per-channel format from the file); (2) a templated version taking an image_span<T> that infers the data type conversion from T (must be a single type for all channels); (3) a templated version taking a span<T> that further implies a contiguous buffer in all dimensions.

For now, the default implementations of these new ImageInput methods are just wrappers that call the old pointer-based ones. One by one, over time, we can swap them, changing the format implementations to have a full implementation of the new bounded versions, and make their raw pointer versions call the wrappers. The raw pointer ones will be understood to be "unsafe", merely assuming that the pointers always refer to appropriately-sized memory areas. Meanwhile, the ones using spans and image_spans will, due to assertions in their implementations, make it easier to verify (at least in debug mode), that we never touch memory outside these bounds.

ImageInput methods that read scanlines, tiles, and image are given new
flavors that take image_span, much like the changes of PR 4727 did for
ImageOutput.

Generally, for each, there are three versions: (1) a low-level base
case that takes an image_span<byte> that describes the underlying
memory, and an explicit TypeDesc that specifies the data type
conversion (including allowing TypeUnknown to indicate keeping
channels in their native per-channel format from the file); (2) a
version taking an `image_span<T>` that infers the data type conversion
from `T (must be a single type for all channels); (3) a version taking
a `span<T>` that further implies a contiguous buffer in all
dimensions.

For now, the default implementations of these new ImageInput methods
are just wrappers that call the old pointer-based ones. One by one, over
time, we can swap them, changing the format implementations to have a
full implementation of the new bounded versions, and make their raw
pointer versions call the wrappers. The raw pointer ones will be
understood to be "unsafe", merely assuming that the pointers always
refer to appropriately-sized memory areas. Meanwhile, the ones using
spans and image_spans will, due to assertions in their implementations,
make it easier to verify (at least in debug mode), that we never touch
memory outside these bounds.

Signed-off-by: Larry Gritz <[email protected]>
@lgritz lgritz added core APIs Affecting public APIs of core functionality classes, such as ImageInput, ImageOutput, ImageBuf. roadmap This is a priority item on the roadmap for the next major release. strategic Strategic initative with far-reaching effects (in time and code space) labels May 17, 2025
@lgritz
Copy link
Collaborator Author

lgritz commented May 17, 2025

We'll have time for discussion of this at the TSC meeting on Monday, but if there are no concerns there, nor voiced here by Monday or so, I will merge. This is really just applying the same set of changes we already did for ImageOutput, but here analogously to the ImageInput class. So it would be very surprising if somebody thought that one was ok but this one was not.

ImageInput::read_image(int subimage, int miplevel, int chbegin, int chend,
TypeDesc format, const image_span<std::byte>& data)
{
#if 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to leave this #if 0 in?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the new methods I added are (currently) just having the new API call the old one underneah. This is the one where I did a full implementation to make sure it was working as intended, and I wanted (for now) to have a means of switching back and forth between new and old for debugging purposes.

@jessey-git
Copy link
Contributor

Generally looks ok I think save for 1 thing I noticed. The chend parameter is checked for out of range, but shouldn't we also validate chbegin in some way? What if someone passes in -2 or a value which is > chend?

@lgritz
Copy link
Collaborator Author

lgritz commented May 20, 2025

Generally looks ok I think save for 1 thing I noticed. The chend parameter is checked for out of range, but shouldn't we also validate chbegin in some way? What if someone passes in -2 or a value which is > chend?

Amended to have an extra check.

Copy link
Contributor

@jessey-git jessey-git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good I think.

@jessey-git
Copy link
Contributor

Except for the clang-format problem though, seems easy enough to address during commit though.

Signed-off-by: Larry Gritz <[email protected]>
@lgritz
Copy link
Collaborator Author

lgritz commented May 20, 2025

updated with formatting fix

@lgritz lgritz merged commit 488dfb2 into AcademySoftwareFoundation:main May 20, 2025
29 of 30 checks passed
@lgritz lgritz deleted the lg-imageio-span-read branch May 20, 2025 05:59
zachlewis pushed a commit to zachlewis/OpenImageIO that referenced this pull request Aug 1, 2025
…oundation#4748)

ImageInput methods that read scanlines, tiles, and image are given new
flavors that take image_span, much like the changes of PR AcademySoftwareFoundation#4727 did for
ImageOutput.

Generally, for each, there are three versions: (1) a low-level virtual
method base case that takes an `image_span<byte>` that describes the
underlying memory, and an explicit TypeDesc that specifies the data type
conversion (including allowing TypeUnknown to indicate keeping channels
in their native per-channel format from the file); (2) a templated
version taking an `image_span<T>` that infers the data type conversion
from `T` (must be a single type for all channels); (3) a templated
version taking a `span<T>` that further implies a contiguous buffer in
all dimensions.

For now, the default implementations of these new ImageInput methods are
just wrappers that call the old pointer-based ones. One by one, over
time, we can swap them, changing the format implementations to have a
full implementation of the new bounded versions, and make their raw
pointer versions call the wrappers. The raw pointer ones will be
understood to be "unsafe", merely assuming that the pointers always
refer to appropriately-sized memory areas. Meanwhile, the ones using
spans and image_spans will, due to assertions in their implementations,
make it easier to verify (at least in debug mode), that we never touch
memory outside these bounds.

---------

Signed-off-by: Larry Gritz <[email protected]>
zachlewis pushed a commit to zachlewis/OpenImageIO that referenced this pull request Sep 1, 2025
…oundation#4748)

ImageInput methods that read scanlines, tiles, and image are given new
flavors that take image_span, much like the changes of PR AcademySoftwareFoundation#4727 did for
ImageOutput.

Generally, for each, there are three versions: (1) a low-level virtual
method base case that takes an `image_span<byte>` that describes the
underlying memory, and an explicit TypeDesc that specifies the data type
conversion (including allowing TypeUnknown to indicate keeping channels
in their native per-channel format from the file); (2) a templated
version taking an `image_span<T>` that infers the data type conversion
from `T` (must be a single type for all channels); (3) a templated
version taking a `span<T>` that further implies a contiguous buffer in
all dimensions.

For now, the default implementations of these new ImageInput methods are
just wrappers that call the old pointer-based ones. One by one, over
time, we can swap them, changing the format implementations to have a
full implementation of the new bounded versions, and make their raw
pointer versions call the wrappers. The raw pointer ones will be
understood to be "unsafe", merely assuming that the pointers always
refer to appropriately-sized memory areas. Meanwhile, the ones using
spans and image_spans will, due to assertions in their implementations,
make it easier to verify (at least in debug mode), that we never touch
memory outside these bounds.

---------

Signed-off-by: Larry Gritz <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core APIs Affecting public APIs of core functionality classes, such as ImageInput, ImageOutput, ImageBuf. roadmap This is a priority item on the roadmap for the next major release. strategic Strategic initative with far-reaching effects (in time and code space)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants