Skip to content

Add color management to texture lookups #3761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ Release 2.5 (summer 2023?) -- compared to 2.4
New minimum dependencies and compatibility changes:

New major features and public API changes:
* TextureSystem color management: #3761 (2.5.1.0)
- TextureOpt and TextureOptBatch have a new field, `colortransformid`,
which supplies an integer ID for a requested color space transformation
to be applied as texture tiles are read. The default value 0 means no
transformation because the texture is presumed to be in the working
color space (this is the old behavior, and most performant). Tiles from
the same texture file but using different color transformations are
allowed and will not interfere with each other in the cache.
- New `TextureSystem::get_colortransform_id(from, to)` maps from/to named
color spaces to a color transform ID that can be passed to texture
lookup calls.
- `ImageCache::get_image_handle` and `TextureSystem::get_texture_handle`
now take an optional `TextureOpt*` parameter that can supply additional
constraints (such as color transformation) that TS/IC implementations
may wish to split into separate handles. This is currently not used, but
is reserved so that the API doesn't need to be changed if we use it in
the future.
- texture.h defines symbol `OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE` that
can be tested for existence to know if the new fields are in the
TextureOpt structure.
* ImageBufAlgo additions:
- A new flavor of `ociodisplay()` now contains an inverse parameter.
#3650 (2.5.0.0)
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

cmake_minimum_required (VERSION 3.12)

set (OpenImageIO_VERSION "2.5.0.2")
set (OpenImageIO_VERSION "2.5.1.0")
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)
Expand Down
1 change: 1 addition & 0 deletions src/cmake/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ macro (oiio_add_all_tests)
texture-stats
texture-threadtimes
texture-env
texture-colorspace
)
oiio_add_tests (${all_texture_tests})
# Duplicate texture tests with batch mode
Expand Down
32 changes: 22 additions & 10 deletions src/include/OpenImageIO/imagecache.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

OIIO_NAMESPACE_BEGIN

// Forward declaration
class TextureOpt;

namespace pvt {
// Forward declaration
class ImageCacheImpl;
Expand Down Expand Up @@ -216,6 +219,11 @@ class OIIO_API ImageCache {
/// enabled, this reduces the number of file opens, at the
/// expense of not being able to open files if their format do
/// not actually match their filename extension). Default: 0
/// - `string colorspace` :
/// The working colorspace of the texture system. Default: none.
/// - `string colorconfig` :
/// Name of the OCIO config to use. Default: "" (meaning to use
/// the default color config).
///
/// - `string options`
/// This catch-all is simply a comma-separated list of
Expand Down Expand Up @@ -467,18 +475,22 @@ class OIIO_API ImageCache {
/// internals.
typedef pvt::ImageCacheFile ImageHandle;

/// Retrieve an opaque handle for fast image lookups. The filename is
/// presumed to be UTF-8 encoded. The opaque `pointer thread_info` is
/// thread-specific information returned by `get_perthread_info()`.
/// Return NULL if something has gone horribly wrong.
virtual ImageHandle* get_image_handle (ustring filename,
Perthread *thread_info=NULL) = 0;
/// Retrieve an opaque handle for fast texture lookups, or nullptr upon
/// failure. The filename is presumed to be UTF-8 encoded. The `options`,
/// if not null, may be used to create a separate handle for certain
/// texture option choices. (Currently unused, but reserved for the future
/// or for alternate IC implementations.) The opaque pointer `thread_info`
/// is thread-specific information returned by `get_perthread_info()`.
virtual ImageHandle* get_image_handle(ustring filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) = 0;

/// Get an ImageHandle using a UTF-16 encoded wstring filename.
ImageHandle* get_image_handle (const std::wstring& filename,
Perthread *thread_info=NULL) {
return get_image_handle (ustring(Strutil::utf16_to_utf8(filename)),
thread_info);
ImageHandle* get_image_handle(const std::wstring& filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) {
return get_image_handle(ustring(Strutil::utf16_to_utf8(filename)),
thread_info, options);
}

/// Return true if the image handle (previously returned by
Expand Down
41 changes: 30 additions & 11 deletions src/include/OpenImageIO/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// Define symbols that let client applications determine if newly added
// features are supported.
#define OIIO_TEXTURESYSTEM_SUPPORTS_CLOSE 1
#define OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE 1

// Is the getattributetype() method present? (Added in 2.5)
#define OIIO_TEXTURESYSTEM_SUPPORTS_GETATTRIBUTETYPE 1
Expand Down Expand Up @@ -232,6 +233,7 @@ class OIIO_API TextureOpt {
fill(0.0f), missingcolor(nullptr),
time(0.0f), rnd(-1.0f), samples(1),
rwrap(WrapDefault), rblur(0.0f), rwidth(1.0f),
colortransformid(0),
envlayout(0)
{ }

Expand Down Expand Up @@ -264,6 +266,8 @@ class OIIO_API TextureOpt {
float rblur; ///< Blur amount in the r direction
float rwidth; ///< Multiplier for derivatives in r direction

int colortransformid; ///< Color space id of the texture
Copy link
Contributor

Choose a reason for hiding this comment

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

If colortransformid can never be negative, why not make it an unsigned int?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just general animus toward unsigned types? All the other fields in this struct were int even though they technical have no meaningful negative values.


/// Utility: Return the Wrap enum corresponding to a wrap name:
/// "default", "black", "clamp", "periodic", "mirror".
static Wrap decode_wrapmode(const char* name)
Expand Down Expand Up @@ -313,9 +317,7 @@ class OIIO_API TextureOptBatch {
alignas(Tex::BatchAlign) float twidth[Tex::BatchWidth];
alignas(Tex::BatchAlign) float rwidth[Tex::BatchWidth];
// Note: rblur,rwidth only used for volumetric lookups
#if OIIO_VERSION_GREATER_EQUAL(2,4,0)
alignas(Tex::BatchAlign) float rnd[Tex::BatchWidth];
#endif

// Options that must be the same for all points we're texturing at once
int firstchannel = 0; ///< First channel of the lookup
Expand All @@ -330,6 +332,7 @@ class OIIO_API TextureOptBatch {
int conservative_filter = 1; ///< True: over-blur rather than alias
float fill = 0.0f; ///< Fill value for missing channels
const float *missingcolor = nullptr; ///< Color for missing texture
int colortransformid = 0; ///< Color space id of the texture

private:
// Options set INTERNALLY by libtexture after the options are passed
Expand Down Expand Up @@ -551,6 +554,10 @@ class OIIO_API TextureSystem {
/// - `int max_errors_per_file` :
/// Limits how many errors to issue for each file. (default:
/// 100)
/// - `string colorspace` :
/// The working colorspace of the texture system.
/// - `string colorconfig` :
/// Name of the OCIO config to use (default: "").
///
/// Texture-specific settings:
/// - `matrix44 worldtocommon` / `matrix44 commontoworld` :
Expand Down Expand Up @@ -788,16 +795,20 @@ class OIIO_API TextureSystem {
class TextureHandle;

/// Retrieve an opaque handle for fast texture lookups. The filename is
/// presumed to be UTF-8 encoded. The opaque pointer `thread_info` is
/// thread-specific information returned by `get_perthread_info()`.
/// Return nullptr if something has gone horribly wrong.
virtual TextureHandle* get_texture_handle (ustring filename,
Perthread *thread_info=nullptr) = 0;
/// presumed to be UTF-8 encoded. The `options`, if not null, may be used
/// to create a separate handle for certain texture option choices
/// (currently: the colorspace). The opaque pointer `thread_info` is
/// thread-specific information returned by `get_perthread_info()`. Return
/// nullptr if something has gone horribly wrong.
virtual TextureHandle* get_texture_handle(ustring filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) = 0;
/// Get a TextureHandle using a UTF-16 encoded wstring filename.
TextureHandle* get_texture_handle (const std::wstring& filename,
Perthread *thread_info=nullptr) {
return get_texture_handle (ustring(Strutil::utf16_to_utf8(filename)),
thread_info);
TextureHandle* get_texture_handle(const std::wstring& filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) {
return get_texture_handle(ustring(Strutil::utf16_to_utf8(filename)),
thread_info, options);
}

/// Return true if the texture handle (previously returned by
Expand All @@ -810,6 +821,14 @@ class OIIO_API TextureSystem {
/// This method was added in OpenImageIO 2.3.
virtual ustring filename_from_handle(TextureHandle* handle) = 0;

/// Retrieve an id for a color transformation by name. This ID can be used
/// as the value for TextureOpt::colortransformid. The returned value will
/// be -1 if either color space is unknown, and 0 for a null
/// transformation.
virtual int get_colortransform_id(ustring fromspace,
ustring tospace) const = 0;
virtual int get_colortransform_id(ustringhash fromspace,
ustringhash tospace) const = 0;
/// @}

/// @{
Expand Down
Loading