Compare commits

...
881 Commits
Author SHA1 Message Date
Larry Gritz d9e0610989 refactor(imageinput): consolidate decompression-bomb guard (#5328)
Move the decompression bomb detection in the TIFF reader into into
ImageInput::check_compression_ratio() so it can be used uniformly for
other input types as well.

Assisted-by: Claude Code / Claude Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-19 21:43:06 -07:00
Larry Gritz 51f99b8f14 admin: update SECURITY with new CVE assignments (#5329)
Also typo fix in CONTRIBUTING

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-17 18:35:46 -07:00
Larry Gritz ba4bb4920b fix(softimage): support channel packets with differing bit depths (#5309)
A Softimage PIC file stores a chain of channel packets, each carrying
its own bit depth (8 or 16). The reader assumed one uniform per-channel
size for the whole image, so a file mixing depths (e.g. 16-bit R with
8-bit G) wrote past the end of the scanline buffer.

Fix: always expose one uniform pixel format, the widest depth among the
file's packets, and promote narrower channels to it on read via exact
bit replication (v*257 for 8->16), which preserves the normalized value
exactly. This keeps the pixel layout naturally aligned; representing
channels with their true differing formats instead would pack them at
non-uniform, sometimes misaligned byte offsets.

Assisted-by: Claude Code / claude-sonnet-5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-17 11:06:40 -07:00
Larry Gritz 4500a872b9 fix(psd): avoid signed overflow computing layer/mask extents (#5306)
read_layer_record computed a layer's width/height as `std::abs((int)right
- (int)left)`. The rectangle coordinates are signed 32-bit values (layers
can have negative offsets), but were stored in unsigned (uint32_t)
struct fields, and subtracting two ints near the extremes overflows --
undefined behavior that UBSan flagged on a fuzzed file (1615681375 -
-1605526113 cannot be represented in type 'int').

Retype Layer's and MaskData's top/left/bottom/right fields as int32_t,
matching what they actually hold, instead of reinterpreting bits at the
point of use. Widen to int64_t before subtracting so the computation
can't overflow; the absolute difference of two int32 values always fits
in uint32, and validate_resolution still rejects implausibly large
extents.

The mask data rect (used for layer masks) had the identical
std::abs((int)right - (int)left) overflow hazard in load_layer_channel
and gets the same fix.

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-17 10:54:31 -07:00
Larry Gritz ac7e5d48cf fix(dpx): fix heap overflow in 1-channel 10-bit filled scanline swap (#5298)
Read10bitFilled() unpacks a scanline of 10-bit "filled" (Method A/B)
samples backwards, and for 1-channel images applies a workaround that
swaps the first and third datum of each group of 3 packed samples (so
column order comes out right). The swap didn't check that a full group
of 3 remained in bounds. Guard the swap so it only fires when a complete
group of 3 remains.

Add a regression test in testsuite/dpx.

Assisted-by: Claude Code / Sonnet 5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-16 20:01:51 -07:00
Larry Gritz 5b4a231634 build(opencv): support OpenCV 5, add standalone header smoke test (#5326)
Find OpenCV via its exported CMake config (PREFER_CONFIG) so OpenCV 5 is
located correctly.

Modify our imagebufalgo_opencv.h to work with OpenCV 5. But how to test
whether we did it correctly?

We never had an actual test for the OpenCV interop. So set one up.

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-16 19:54:25 -07:00
Larry Gritz c5e085eee3 fix: beef up Exif error detection (#5322)
One small improvement in how decode_exif detects corruption, to ensure
that the initial header examination doesn't read past the array bounds
-- by starting off with a check that the exif blob's size is at least a
big as a TIFFHeader, otherwise parsing it is pointless.

Then the rest of the changes are finding places where readers call
decode_exif but ignore the results, effectively ignoring corrupt Exif
blobs. That is in fact the default intended behavior (if the rest of the
image file can be read properly), but we are supposed to be checking the
global "imageinput:strict" attribute and considering it a hard error
when in strict mode. There were several places where we didn't handle
that case, in the JPEG, PNG, WebP, and Heif readers.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 23:41:20 -07:00
Anton Dukhovnikov a9a170244c raw: pass the bad pixels param to libraw (#5323)
Adds a hint "raw:bad_pixels" which passes a filename for bad pixel data
to libraw.

I haven't added any tests, can't think of a good way of testing this.
Open to suggestions.
This functionality has been tested in a client code.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2026-07-15 22:05:09 -07:00
Larry Gritz 526beeb7f6 fix(tiff): fix some int32 overflows, guard against decompression bomb (#5319)
Fixes #5316

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 21:38:12 -07:00
Larry Gritz a9f5e9240d fix(sgi): deal with corrupt 16 bit RLE runs with odd byte counts (#5321)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 21:34:22 -07:00
Larry Gritz b3e38593b1 build: FORTIFY and sanitize/debug are not compatible (#5318)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 21:22:24 -07:00
Larry Gritz a0d5e27dae admin: very minor fixes to README & SECURITY (#5320)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 18:00:49 -07:00
Larry Gritz 7303134f13 fix(exr): use rectangle row stride for partial edge tile reads (#5295)
read_native_tiles() on a tiled EXR whose dimensions aren't a multiple of
the tile size wrote past the caller's buffer when reading an edge tile
range: both readers used a row stride padded up to a whole number of
tiles (nxtiles*tile_width) instead of the caller's actual rectangle
width, overrunning the buffer whenever the last tile column is partial.

Fixed in both exrinput_c.cpp (Core reader) and exrinput.cpp (classic
reader) to use the requested rectangle width as the destination row
stride instead. exrinput.cpp additionally needs the pre-clamp width
specifically, since read_native_tile() forwards a tile-aligned xend past
the image edge for ordinary full-tile reads.

Adds testsuite/openexr-partialtile, a compiled regression test that
calls read_native_tiles() directly for both readers -- the only path
that exercises this code -- and checks pixels and buffer bounds.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-15 17:59:25 -07:00
Larry Gritz ce1be97495 fix: avoid leaks in the per-ImageInput/Output error message (#5276)
(The same problem and set of fixes were applied to both ImageInput and
ImageOutput. For brevity, we will only discuss ImageInput below.)

ImageInput error messages are stored in a thread_local map keyed by a
unique per-instance id (m_id). The destructor's erase of that entry was
commented out (over caution about the static destruction order fiasco),
so every ImageInput that accumulated an error and was destroyed without
its error being cleared via geterror() leaked one map entry. The id is
monotonically increasing, so entries never get reused and the map grows
without bound.

How did we find this? A fuzzer opening hundreds of thousands of corrupt
files -- each of which errors, and each ImageInput::create() attempt
tries several readers -- grew the map to tens of MB and eventually
OOMed. The leak was traced to this issue.

So we re-enable the erase, guarded against the destruction order fiasco:
the thread_local map is wrapped in a struct whose destructor clears an
'alive' flag, and the ImageInput destructor only touches the map while
it is alive. Each ImageInput removes only its own entry (keyed by its
unique id); other inputs' errors are untouched.

Cross-thread cleanup is still a known limitation -- errors accumulated
in a different thread than the one that descroys the ImageInput are
still leaked, noted in a TODO. However, this should be exceptionally
rare, since not only do you need the two-thread situation, but the one
that made the call that produced an error needs to not check for errors
and return/clear the message. So only badly behaving user code that
fails to check and retrieve errors should have this minor leak. And we
are in the process of adding compile-time warnings for not capturing the
error status values from our APIs.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-14 13:51:52 -07:00
Larry Gritz f70367d3de fix(jpeg2000): reject corrupt component geometry and subsampling (#5270)
A fuzzed JPEG2000 caused a heap-buffer-overflow (caught by ASan) when
copy_scanline read past the end of openjpeg's decoded component buffer.
The file's image canvas was 32x32, but one of its three components had a
horizontal subsampling factor dx=249 (larger than the entire image).
OIIO derives the ImageSpec size from the union of each component's
x0+w*dx / y0+h*dy window, so that bogus component inflated the spec to
249x32. copy_scanline then iterated x over the inflated width while
indexing a component whose data array only held 1 column, walking off
the end. The per-sample guard was also broken: it compared the component
row index against reference-grid offsets (wrong units) and used `>`
instead of `>=` on the column.

Two fixes:

1. Detect the corruption at open(): the JPEG2000 canvas (x1-x0, y1-y0)
is the authoritative image size, and a component's subsampling factor
must be nonzero and no larger than the canvas. Reject files that violate
this instead of decoding a nonsensical, inflated image.

2. Harden copy_scanline by bounds-checking each access against the
actual component array geometry and skip the channel (zero-fill) when
comp.data is null or a subsampling factor is zero, which also closes a
latent divide-by-zero on comp.dx/comp.dy.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-11 11:52:26 -07:00
Larry Gritz e3c14a0736 ptex: More comprehensive valid_file and validation of header (#5265)
Previously, we did not have a PtexInput::valid_file() method, and our
open() method just directly called PtexTexture::open(), which is really
bad with validity checks and can crash or OOM with corrupted files.

But Ptex has a fixed 64 byte header (cheap to read and inspect) that has
lots of fields that let us more accurately check for reasonable file
validity. Therefore, we both implement valid_file, and also have open()
do these checks (rejecting many forms of corruption) before turning the
job over to the Ptex library itself.

Assisted-by: Claude Code / opus-4.8

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-10 22:55:43 -07:00
Larry Gritz d33cb2a0e0 fix(build): fix EMBEDPLUGINS=0, make many build options env-override (#5272)
Change several build-time options from `option()` to our `set_option()`,
which mostly has the effect of allowing them to be overridden by
environment variables of the same name, which is really handy for CI
variants.

In the process, realized that we had some real problems with handling of
EMBEDPLUGINS=0, it probably hasn't worked properly for years and went
unnoticed because the one CI job variant that was trying to test
EMBEDPLUGINS=0 actually *was not* because it was trying to do it by
setting the environment variable, unaware that it could not be used to
set the option until this patch. So there is a bit of cmake and linkage
fixing that needed to be done to get it squared away.

Assisted-by: Claude Code / opus-4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-10 22:55:26 -07:00
Larry Gritz b2d3328b3d feat: add "limits:resolution" global attribute to cap per-dimension size (#5297)
The existing "limits:imagesize_MB" rejects files whose total
uncompressed size exceeds a cap, but it cannot catch an image that is
tiny in one dimension yet absurdly large in another (e.g. an image
claiming 32 x 50331680, which slips under the 32 GB default). Add a
companion global attribute, "limits:resolution", that caps the maximum
number of pixels along any single dimension.

Like imagesize_MB, this is enforced only in ImageInput::check_open(),
intended for validity checks when reading untrusted files.

Applications may set the attribute larger or smaller than this default,
depending on their need to deal with images larger than these limits,
and/or willingness to risk mistaking a corrupted or maliciously crafted
image for a legitimate one on this basis.

Now then, with this in place, we can clean up some of the values we used
in passing valid resolution ranges to check_open(). That was originally
meant to express the true limits of what was valid in the file formats,
but had in many cases been conflated with common sense "what value is so
big that it's probably bogus". Now we can disentangle these ideas -- the
value passed to check_open is the definitional limit of the file format
itself, and the "limits:resolution" is the overrideable global policy
for what we consider more likely to be malicious/corrupted than merely
legit big.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-10 22:54:56 -07:00
Larry Gritz 4995b25b82 fix(psd): guard row interleave bounds on corrupt data (#5307)
Validate channel-row byte availability before interleaving scanlines in
PSD reads, and fail gracefully with an error instead of risking
out-of-bounds access on malformed files.

Assisted-by: GitHub Copilot / GPT-5.3-Codex

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-10 17:11:15 -07:00
Larry Gritz 0adaf3a56c admin: SECURITY.md updates (#5311)
- Add recently published security advisories to SECURITY.md
- Revision of security policy and definitions of vulnerability.
- Also some minor forward-ports and adjustments of CHANGES.

The substantive change is explaining that our policy is to only consider
vulnerabilities if they (a) allow remote code execution, privilege
escalation, and other very severe problems (not crashes, OOM, or most
"DoS" scenaries), and (b) are exploitable in practice by untrusted
actors merely by presenting malicious routine input such as image files
(misuse of APIs, for example, is not a vulnerability).

Everything else should be reported through the usual Issue/PR mechanism,
and not use the security vulnerability reporting regime, which is
massively more overhead for the maintainers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-10 15:04:36 -07:00
Larry Gritz 4ee7fa0ea4 Update CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-09 18:01:21 -07:00
Larry Gritz 7a08623f52 fix(python): update getattribute one-arg test for unified bindings (#5308)
PRs #5260 and #5254 interact: #5254 exposed the default type arg on the
module getattribute (`"type"_a = TypeUnknown`), so a one-arg call now
returns None instead of raising TypeError. #5260's test still expected
the old pybind behavior. Update the test and ref to the intended new
behavior.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-09 11:30:57 -07:00
Aleksandr Motsjonov 667365f45b Unify pybind11 and nanobind into single-source bindings (#5254)
Exploring an idea Anton had about unifiying two python backends into
single source since they are so similar.

## Summary

This PR unifies the early nanobind migration with the existing pybind11
Python bindings by compiling **shared sources** from `src/python/` for
both backends, instead of maintaining parallel copies under
`src/python-nanobind/`.

Migrated modules so far: `ROI`, `TypeDesc`, `ImageSpec`, `ParamValue` /
`ParamValueList`, plus the core `OpenImageIO` module helpers in
`py_oiio.cpp`. Backend differences are isolated in `py_backend.h` (type
aliases, binding API macros like `.OIIO_PY_RW(...)`, and small
`oiio_py::` helpers). Shared Python↔C++ conversion logic lives in
`py_oiio.h` with `#if` only where the backends genuinely differ.

CMake is updated so that when `-DOIIO_PYTHON_BINDINGS_BACKEND=nanobind`
is selected, the module is built from the unified sources and installed
as the main `OpenImageIO` package in the expected location. With `both`,
pybind11 remains the primary module and nanobind builds as
`PyOpenImageIONanobind` for side-by-side testing.

Duplicate nanobind-only `.cpp` files are removed (~1.8k lines deleted
net). Testsuite coverage is extended with explicit roundtrip checks for
shared helper paths (attributes, buffers, tuples).

---

## Pros

- **Single source of truth** for migrated bindings — no more keeping two
copies of `py_roi.cpp`, `py_imagespec.cpp`, etc. in sync by hand.
- **Lower risk of backend drift** — a fix or API tweak in a migrated
module automatically applies to both pybind11 and nanobind.
- **Net code reduction** — removes a large duplicated tree under
`src/python-nanobind/` while centralizing shared logic in one place.
- **Clearer migration path** — `MIGRATION_STATUS.md` documents what is
fully migrated, partially migrated, and still pybind-only.
- **Better nanobind-only build layout** — on `main`, choosing nanobind
does not install into the same package layout as pybind11; this PR fixes
that for the migrated surface.
- **Side-by-side validation** — `OIIO_PYTHON_BINDINGS_BACKEND=both`
builds both modules so existing `testsuite/python-*` and `*.nanobind`
variants can be run against the same C++ sources.
- **Explicit parity tests** — new/extended tests cover shared conversion
paths (typed attributes, buffer→vector, tuple roundtrips) rather than
relying on import smoke tests alone.
- **Maintainable binding style** — method-name macros
(`.OIIO_PY_RW(...)`) keep clang-format happy without `clang-format off`
regions.

---

## Cons

- **Added abstraction in the pybind11 path** — even pybind-only builds
now go through `py_backend.h`, macros, and shared helpers; slightly more
indirection than plain `.def_readwrite(...)`.
- **Regression risk for pybind11** — adapting existing pybind code to
work for both backends could subtly change pybind11 behavior at the
edges (init, casting, error paths, ownership).
- **Incomplete migration** — most of the Python API (`ImageBuf`,
`ImageInput`/`ImageOutput`, `ImageBufAlgo`, texture system, etc.) is
still pybind-only; this PR is a foundation, not full nanobind coverage.
- **Known nanobind gaps remain** — module-level exports and helpers
listed in `MIGRATION_STATUS.md` are still missing or intentionally
different vs pybind11.
- **Higher review and test burden** — reviewers need to think about two
backends; CI/local testing should cover both pybind and `.nanobind`
variants for touched code.
- **Conditional compilation complexity** — `#if
defined(OIIO_PY_BACKEND_NANOBIND)` remains in a few places (e.g.
`ParamValue` constructors, buffer dispatch); easy to get wrong if
extended carelessly.
- **Slightly less obvious binding code** — `.OIIO_PY_RW("x", ...)` reads
less directly than `.def_readwrite("x", ...)` until you know the macro
map.

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2026-07-09 10:26:04 -07:00
Larry Gritz fed212a115 fix(jxl): guard corrupt basic-info dimensions early (#5305)
Run check_open on JXL basic-info dimensions/channels before decode
output allocation to prevent oversized allocation paths on malformed
input.

Also update ref output for libjxl 0.12.0.

Assisted-by: GitHub Copilot / GPT-5.3-Codex

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-08 16:36:59 -07:00
Larry Gritz 0670f1f314 fix(psd): identify corruptions of layer resolutions, eof in strings (#5259)
* Find corruptions by validating layer resolutions.
* Find corruptions when eof is hit in the middle of a string.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-08 10:14:20 -07:00
Larry Gritz b590a26a0a fix(sgi): prevent oversized-allocation crash from bogus RLE length/offset table (#5303)
Truncating a corrupt uint32 length_tab entry into `int` could yield a
huge negative value, causing a runaway allocation and crash in
uncompress_rle_channel. Validate offset/length against the file size
instead.

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-07 21:02:57 -07:00
Nick D'Ademo 14e30d8abb build: wasm build (#5304) 2026-07-07 19:36:18 -07:00
Larry Gritz 2ecbde6e5d ci: Add vfx2027 container tests (#5302)
One gcc and one clang based test in the new containers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-06 22:43:47 -07:00
Larry Gritz 0494901b00 build: fix certain clang varieties warning about giflib headers (#5263)
Assisted-by: Claude Code / sonnet-4.6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-06 18:20:21 -07:00
Dongju Lee d9fc577ab0 fix(ffmpeg): align swscale output buffers (#5301)
This aligns FFmpeg/libswscale destination image buffers and validates
the buffer-size, frame-fill, and swscale return paths before decoded
pixels are consumed.

The change prevents narrow high-bit-depth VP9/GBR inputs from writing
past OIIO's destination buffer during swscale conversion, and adds a
regression case for the width-1 high-bit-depth FFmpeg path.

Signed-off-by: Dongju Lee <dongpago2@gmail.com>
2026-07-06 18:14:58 -07:00
Dongju Lee 4e4a1df806 fix(gif): guard canvas index overflow (#5299)
This handles malformed GIF files whose logical canvas dimensions can
overflow legacy int-indexed canvas calculations.

The patch rejects oversized canvas dimensions before scanline/canvas
indexing and adds a regression test for the malformed oversized-canvas
case.

Signed-off-by: Dongju Lee <dongpago2@gmail.com>
2026-07-06 17:45:40 -07:00
Dongju LeeandLarry Gritz 21a293a319 fix(imageio): ignore invalid RowsPerStrip chunking (#5300)
This treats non-positive tiff:RowsPerStrip metadata as absent before
using it to align generic scanline read/write chunks. That avoids
feeding invalid chunking metadata into round_to_multiple while
preserving normal positive RowsPerStrip behavior.

The patch adds regression coverage for an OpenEXR file carrying
RowsPerStrip=0 through iinfo --hash, iinfo --stats, and an oiiotool
conversion path.

---------

Signed-off-by: Dongju Lee <dongpago2@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2026-07-06 17:28:48 -07:00
Larry Gritz 134977da62 fix(gif): avoid int32 overflow in palette-split pixel-count math (#5292)
GifSplitPalette() computed `numPixels * (splitElt - firstElt)` as a
32-bit int before dividing. For any image over roughly 16.9M pixels
(e.g. 4117x4117), that intermediate multiplication overflows INT_MAX and
is undefined behavior; in practice it produced a bogus negative/garbage
split count that could drive later indexing into `image` out of its
bounds.

Do the multiply in 64 bits and narrow back afterward -- the quotient is
always <= numPixels, so the narrowing itself is safe.

Assisted-by: Claude Code / Sonnet 5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-05 17:51:40 -07:00
Larry Gritz 002ab7a7b8 fix(iff): reject implausible image dimensions before allocating tile buffer (#5284)
TBHD width/height/channel fields were never cross-checked against how
much tile data the file actually contains, so a corrupt header could
claim an arbitrarily large image (e.g. 16k x 16k) backed by only a few
hundred bytes of real data. readimg() would then resize() a
multi-gigabyte buffer for a tiny malformed file, hanging (or very slowly
succeeding) instead of failing -- a resource-exhaustion DoS on untrusted
input, found via fuzzing.

Bound the claimed image size against how much tile data remains in the
file, generously allowing for RLE's worst-case 128x expansion ratio, and
fail fast if it's implausible.

Assisted-by: Claude Code / claude-sonnet-5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-05 17:04:03 -07:00
Larry Gritz 6f2b2e85b3 fix(cineon): validate bit depth against libcineon's supported set (#5283)
CineonInput::open() accepted any per-channel bit depth in [1,32], but
libcineon's ComponentDataSize()/ComponentByteCount() only recognize
{8,10,12,16,32,64} and assert(0) on anything else. A crafted file with
an unsupported bit depth (e.g. 26) passed the OIIO-side check and then
aborted deep inside the vendored library instead of failing cleanly.

Tighten the check to libcineon's actual whitelist so bogus bit depths
are rejected with a proper errorfmt() before ever reaching the vendored
code. Adds a regression fixture (broken_bitdepth2.cin) to the cineon
testsuite.

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-05 17:02:48 -07:00
Larry Gritz 0c5352be3b fix(iff): add resolution validity checking (#5285)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-05 17:02:01 -07:00
Larry Gritz f717fc73db fix(raw): apply LibRaw memory cap before unpack to prevent OOM (#5275)
open_raw set imgdata.rawparams.max_raw_memory_mb *after* calling
m_processor->unpack(), so LibRaw's allocation cap never protected the
unpack step -- which is exactly where LibRaw allocates the raw image
buffer. A corrupt raw file claiming huge dimensions could therefore
allocate unbounded and OOM (showing up on the fuzzer as a 0-length crash
artifact from an out-of-memory trip rather than a normal reproducer).

Move the max_raw_memory_mb assignment to immediately after open_file
succeeds, before unpack(), so the cap (default 2048 MB) actually bounds
the allocation. LibRaw then fails the file cleanly instead of OOMing.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-05 17:00:04 -07:00
Aleksandr Motsjonov c8f2c70b54 python/testing: Improve python test coverage (#5260)
While working on
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5254,
where we're introducing changes that could surface bugs in pybind11 code
that's in production today, I figured I'd try adding some tests.

This was a fairly loose-handed effort. To be upfront: most of it was
LLM-generated. I did some research into which modules were lacking
coverage the most, and those are what this PR targets. I haven't gone
through every line of the generated code.

I hate being asked to review something that was clearly vibe-coded with
no real effort put in, so I'm saying that here rather than pretending
otherwise. I can try to review it properly, but without deep codebase
knowledge it'll be slow and painful. Since these are just tests, my
thinking was: even if there are silly bits here and there, it shouldn't
hurt much, as long as things go green and we cover more logic and
branches. Worth offering as-is.

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2026-07-04 18:32:26 -07:00
Larry Gritz 6e9b86ee4c fix(tiff): fix heap overflow unpacking sub-8-bit contig CMYK samples (#5296)
We had missed a case where bit_convert needed outputs to go to the
scratch buffer: PHOTOMETRIC_SEPARATED, but not requesting raw color.
(Because the real number of channels differ from what we are presenting
to the caller.)

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-04 15:57:32 -07:00
Larry Gritz 72cea5a2cf fix(psd): detect implausibly large ICC, Exif, XMP before allocating (#5288)
10MB was conservatively chosen as big enough that anything larger is
definitely bogus for an ICC, Exif, or XMP block in a PSD file.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-03 20:55:42 -07:00
Larry Gritz 31201c22df fix(tiff): avoid use-after-scope in multithreaded scanline reads (#5294)
read_native_scanlines declared task_set before the locals its queued
decompression lambdas capture (ok, compressed_scratch). On the
leftover-scanline early-return path those locals were destroyed before
~task_set() waited for the queued work, so workers could write through a
dangling ok and hand a freed compressed buffer to zlib.

Declare task_set after the captured locals so its destructor wait runs
while they are still alive, and propagate async decompression failures
via return ok instead of unconditionally returning true.

Assisted-by: Claude Code / opus-4.8

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-03 20:53:11 -07:00
Larry Gritz 50481b0f90 fix(psd): validate color_mode before RawColor early return (#5282)
validate_header() let the oiio:RawColor/psd:RawData path return true
before the switch that rejects unknown m_header.color_mode values, so an
out-of-range or "hole" (undocumented) color mode reached setup(), which
unconditionally indexes the fixed 10-entry mode_channel_count /
mode_channel_names tables with the attacker-controlled value -- a global
out-of-bounds read (and, per external report, a path to unbounded/bogus
allocation) reachable via the public RawColor config attribute on a
crafted PSD.

Move the "is this a color mode we know about at all" check ahead of the
RawColor early return so it always runs, and keep the existing
Duotone/Lab-unsupported-without-raw check as a second pass after the
early return, preserving current behavior for every valid mode.

Assisted-by: Claude Code / claude-sonnet-5

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-03 20:29:46 -07:00
Larry Gritz 73e32c096c fix(targa): reject implausible image dimensions before allocating (#5293)
An 18-byte TGA file consisting of just a header (no pixel data) can
claim an arbitrary width/height/bpp -- e.g. a 1472x12000 24bpp image --
and readimg() would allocate the full ~53MB buffer and only discover the
truncation once the first read hits EOF. Worse, the resulting
partially-formed ImageSpec could still propagate to a downstream writer
before the read failure was acted on.

Cross-check the header's width/height/bpp against how many bytes of
pixel data the file could plausibly contain before committing to the
allocation, mirroring the existing pattern in iff.imageio and
jpeg2000.imageio. The check compares against the *on-disk* pixel size
(palette/16-bit storage is smaller per pixel than the decoded, unpacked
ImageSpec) and allows up to 128x expansion for RLE-compressed images (a
1-byte run-length count can encode up to 128 output pixels).

Updated testsuite/targa/ref/out.txt: several existing corrupt-file
regression cases (crash1.tga, crash6.tga, crash3952.tga) are now caught
earlier with clearer messages, and two real oiio-images TGA files
(UCM8.TGA, UTC16.TGA) that use palette/16-bit storage smaller than their
decoded size continue to read correctly.

Assisted-by: Claude Code / Sonnet 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-03 19:21:23 -07:00
Larry Gritz 13ffc025e8 fix(ico,png): avoid leaking error string across png_chunk_error longjmp (#5289)
PngReadCallback passed input->geterror(false).c_str() to
png_chunk_error() when a PNG read failed. png_chunk_error() does not
return -- it longjmp's back to libpng's setjmp point, which skips C++
destructors, so the temporary std::string returned by geterror() was
never freed. The fuzzer surfaced this as a small, intermittent leak (a
few KB across hundreds of thousands of runs).

Copy the message into a plain stack buffer (no destructor) before
calling png_chunk_error, so nothing heap-allocated is alive across the
longjmp.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-03 13:06:41 -07:00
Larry Gritz a9f7a359a3 fix(ico): Better error checking for PNG-in-ICO files (#5264)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-02 13:16:03 -07:00
Larry Gritz d11941efe7 fix(dds): clamp pixel memcpy to sizeof(uint32_t) to prevent stack overflow (#5287)
The mask-based uncompressed decode path copies m_Bpp bytes into a
uint32_t pixel variable. m_Bpp is validated up to 16 (for 128-bit DXGI
formats), but the legacy fmt.masks[] are uint32_t and can only address
32 bits. A corrupt file with m_Bpp > 4 caused a stack-buffer-overflow.
Clamp the copy to sizeof(pixel) = 4 bytes, which is all the masks can
reference anyway.

Assisted-by: Claude Code / claude-sonnet-4-6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-02 13:15:34 -07:00
Larry Gritz 94b73bd1ed fix(dds): reject corrupt bytes-per-pixel before it forces a huge allocation (#5286)
A DDS file with a garbage pixel-format bpp field (e.g. fmt.bpp ~2.5e9)
yields a native bytes-per-pixel (m_Bpp) of hundreds of millions.
internal_readimg() then does `new uint8_t[width * m_Bpp]`, a multi-GB
allocation that OOMs. The core resolution/imagesize limits do not catch
this: they only see the small output ImageSpec, not the native pixel
size, and the existing fmt.bpp check is gated on RGB/LUM/YUV/ALPHA flags
that a corrupt header can simply omit.

Validate m_Bpp for uncompressed formats right after it is computed in
open(): the largest real uncompressed DDS/DXGI pixel is 128-bit (16
bytes), so anything outside [1,16] is a corrupt header and is rejected
before any allocation. The check is confined to uncompressed formats
because m_Bpp is neither set nor used for compressed (block) formats,
which size their data via GetStorageRequirements.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-02 13:14:57 -07:00
Larry Gritz 9cda48b150 fix(iff): detect corrupt chunk sizes, flags, channel configs (#5268)
Detect and reject corrupt chunk sizes, flags, and channel configurations
in the header.

Assisted-by: Claude Code / Claude Opus 4.8

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-07-02 09:09:14 -07:00
Larry Gritz 30cb21ac8c webp: Improve valid_file to check the header for magic words (#5266)
This is MUCH faster than asking libwebp to open the file!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-30 19:09:26 -07:00
Larry Gritz 6912562187 fix(openexr): Add check_open to exrinput_c (#5280)
Somehow the check_open validation was only in exrinput.cpp (using the
old C++ AP), but not exrinput_c.cpp (using the C "Core API").

Also adjust the allowable z resolution to reflect that OpenEXR doesn't
support volumetric images. (This was obviously a cut and paste error
long ago.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-30 19:08:49 -07:00
Larry Gritz 1368f9eb38 fix(sgi): size RLE offset tables by spec dims to prevent OOB on corrupt headers (#5279)
read_offset_tables() sized the RLE start/length tables from the raw
header (`ysize * zsize`), but read_native_scanline() indexes them by the
spec dimensions (`height * nchannels`, derived from the image's
dimension field). A corrupt header (e.g. dimension=1 with zsize=0) makes
`ysize*zsize` = 0 so the tables are empty, while indexing still uses
`height*nchannels` = 1 -- a null-pointer dereference and crash.

Size the tables by `m_spec.height * m_spec.nchannels`, the same quantity
used to index them, so the two can never desync. For well-formed files
this equals ysize*zsize, so behavior is unchanged; a corrupt file now
fails cleanly when the (too-short) table read hits EOF. Also guard
against non-positive table sizes, use vector::data() instead of `&v[0]`
(UB on empty), and fix an off-by-one in the scanline bounds check (y ==
height would index start_tab[-1]).

Add the fuzzer reproducer as testsuite/sgi/src/broken02.sgi.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-30 19:07:35 -07:00
Luna Kim 38b8955374 api(deepdata): change merge_deep_pixels return type, add OIIO_NODISCARD_ERROR (#5253)
`merge_deep_pixels()` calls `copy_deep_sample()`, which has an error
status return, so change `merge_deep_pixels()`'s return type from void
to bool.
    
For OIIO_NODISCARD_ERROR, all internal calls that previously ignored
return values are handled:
- OIIO_CONTRACT_ASSERT where the call can't fail in context, or the
caller is a void function or a constructor.
 - `return false` where the caller already returns a bool error state.
 - `(void)` cast for the deprecated internal overload.
    
Follow-up to #5252
Part of #4781

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-30 19:06:57 -07:00
Larry Gritz 67dc210984 deps: New PugiXML min 1.11, rely on cmake config now, bump vendored version (#5246)
Upgrade the embedded/vendored pugixml to 1.16, also the default version
that we use for CI with build_pugixml.bash.

Raise PugiXML minimum to from 1.8 to 1.11 (late 2020, over 5 years ago).

Rely completely on pugixml exported cmake config, eliminate our
Findpugixml.cmake. This is possible because we raised our minimum
pugixml to 1.11, which is the point where its exported cmake configs
were reliable.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-30 17:02:14 -07:00
Larry Gritz 93b909d131 build: openjph auto-build and better exception handling (#5247)
Add scripts for openjph auto-build when not found (and
OpenImageIO_BUILD_MISSING_DEPS specifies it, or "all"). Build openjph
0.30.1 when missing.

Since we can build it when missing, take away the various missing
openjph allowances from our CI; auto-build when needed for all variants.

More thorough exception catching for openjph in our jpeg2000input.cpp.

When I compile openjph with clang (including icx), I get some runtime
exceptions. Not when I build it with gcc! I don't have the time or
inclination to investigate why, so for our CI, rig it to build openjph
with gcc even when I'm building OIIO with clang/icx.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-30 16:09:38 -07:00
Larry Gritz 5beff968ed build(tiff): recommend libtiff 4.5+ for security fixes (#5277)
Circular IFD chain loop detection (identified by for CVE-2022-3970) was
fixed in libtiff by MR 386
(https://gitlab.com/libtiff/libtiff/-/merge_requests/386), released in
libtiff 4.5.0.

Raise the recommended minimum from 4.2 to 4.5 so users on older
installations get a build-time advisory. The hard minimum stays at 4.0
(for now) to preserve compatibility.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 15:13:59 -07:00
Larry Gritz 0421dc6338 fix(filesystem): overflow-safe bounds check in IOMemReader::pread (#5262)
IOMemReader::pread guarded its memcpy with `size + size_t(offset) >
m_buf.size()`. For a large or negative offset, that addition wraps
around size_t and can compare as in-bounds, skipping both the error path
and the size clamp, so the memcpy reads past (or before) the buffer.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 13:19:06 -07:00
Larry Gritz 88cde4b19b perf: less redundant opening when files fail (#5267)
When creating an ImageInput, if the initial guess (based on the file
extension) fails to open, we try all the others in turn.

This tries to make that a little cheaper by not doing a full open() but
instead first checking for valid_file, which in theory is a much less
expensive approximate check.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 13:18:34 -07:00
Larry Gritz cf7152d479 fix(gif): address corrupt files with bad resolutions and overflow int (#5257)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 09:57:37 -07:00
Larry Gritz bb5beea8aa fix(hdr): validate resolution to find corrupted files (#5256)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 09:31:20 -07:00
Larry Gritz 629c8340e8 fix(bmp): validate scanline file position before reading (#5274)
read_native_scanline computed the scanline's file position as
m_bmp_header.offset + y * m_padded_scanline_size and seeked there
without checking it against the file size. A corrupt header (bogus
pixel-data offset or scanline size) can place that position far outside
the file.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 09:30:43 -07:00
Larry Gritz 5d49c3e54e fix(dpx): detect corrupt userbuf size, overflow guard (#5271)
- Detect corrupted userbuf size.
- Protection against integer multiply overflow in various places in the
DPX reading code.
- Also fix memory load alignment issue. Didn't seem to be a problem in
practice, but the sanitizers weren't happy on some platforms.

Assisted-by: Claude Code / sonnet-4.6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-29 09:24:24 -07:00
Larry Gritz 0679efd872 fix(gif): Handle empty error from gif_lib (#5269)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-28 21:23:43 -07:00
Larry Gritz 393899e7f2 fix(tiff): The "tiff:half" hint was only applying to first MIP level (#5240)
IBA::make_texture() only passes the full metadata to the first level of
a MIPmap, and that might include output behavior hints, too! Make this
hint "sticky" in the TIFF writer, so if any subimage's first level's
spec enables half output, all the MIP levels of that subimage will allow
it.

Fixes #5239

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-28 09:28:12 -07:00
Larry Gritz 77906d3802 fix(hdr): Make the HDR reader tolerant to CR in the ASCII header (#5261)
Carelessly written hdr/rgbe files, or correctly written ones that are
checked out by git on windows if you're not careful, might use Windows
CRLF line endings. Be silently tolerant of that.

Assisted-by: Claude Code / opus-4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-27 16:45:14 -07:00
Larry Gritz 41cb45e287 docs: fix typo in bitcast docs (#5255)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-27 07:47:00 -07:00
Larry Gritz f01bd16764 fix(iff): Fix allocation bug when reading 16 bit RGBA + float z (#5251)
We were allocating a temporary buffer big enough for the RGBA but
neglecting the z. Only for the 16 bit case.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-27 07:46:24 -07:00
Larry Gritz 908f22f552 fix(cineon): more robust to invalid numbers of channels & bit depth (#5250)
Guard against corrupted images, which if they said they had more than
the 8 channels allowed by Cineon format, would overrun array bounds
while reading the file. And check for valid bit depths.

Also opportunistically fix a bug I spotted where a red channel was
incrementing the count of greyscale channels rather than the count of
red channels -- which must have been a copy and paste error from
literally 15 years ago. (But those counters are only used for channel
naming, and only if there is more than one greyscale or red channel in
the file. So I doubt anybody has ever hit this bug, or ever would have
in the future.)

Fix possible memory leak by having init() call `m_cin.SetInStream()`
with a null handle to clear out the internals.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-27 07:45:15 -07:00
Larry Gritz 52a4a98ceb ci: upgrade 'latest' CI tests to OpenEXR v3.4.14, fmt 12.2, PugiXML v1.16 (#5245)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-26 09:04:02 -07:00
Larry Gritz 446f090497 fix(ImageBuf): Copy ctor of IC-backed ImageBuf zeroed bufspan strides (#5244)
When copy-constructing an ImageCache-backed ImageBuf, the "cache-based
or deep" branch set `m_bufspan = {}`, a default-constructed image_span
whose strides are all zero. retile() addresses a pixel within a cache
tile as `offset = pixelindex * m_bufspan.xstride()`, so a zero xstride
made every pixel resolve to tile offset 0 -- the whole copied image read
back as a constant color (the value of pixel 0,0).

Fixes #5243

Added a regression test (test_copy_of_imagecache_backed) that copies a
cache-backed buffer with distinct per-pixel values and verifies the copy
does not read back a constant.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-26 09:03:12 -07:00
Luna Kim 83fb484e88 api(deepdata): widen merge_deep_pixels srcpixel to int64_t (#5252)
To avoid breaking ABI, the old int overload is kept, but its declaration
is hidden behind `#ifdef OIIO_INTERNAL`. Downstream code only sees the
int64_t version, but old binaries still work. The forwarding wrapper
handles it until the next first-digit version changes.

Also, the Python binding is adjusted using a wrapper to resolve the
overload ambiguity. While adding the wrapper, I noticed other bindings
still took `int pixel`, so widened them to `int64_t` for consistency.

Follow-up to #2363
Fixes #5242

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-23 14:47:15 -07:00
Luna Kim 629becd6c6 fix(deepdata): correct Zback channel in sort(), change int pixel to int64_t (#5241)
- Fix sort(), incorrectly using the front Z channel in a place where it should have instead used Zback channel.
- Widen pixel indices from int to int64_t (internal only, follow-up to #2363).
- Cleanup unreachable branches in merge_overlaps().

Modified the `DeepData::sort` test to include samples with a tied front
Z, so it verifies the Zback fallback.

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-23 13:28:12 -07:00
Larry Gritz b0de7d40d0 fix(fits): Fix recursion stack overflow with too many header blocks (#5248)
FITS files are allowed to have multiple "header blocks".

Unfortunately, as originally written, our fits input used *recursion* to
read them. If there is a file with too many header blocks, it can crash
with a stack overflow.

Change to use a loop instead of recursion. And put a maximum iteration
limit of 10000 headers in one file before giving up.

(Note to reviewers: the diff looks bigger than it really is. By
surrounding the contents of read_fits_header with a `for` loop, it
reindented it, and that is the vast majority of the change. I wish
GitHub review diffs more clearly visualized which changed lines are only
whitespace changes.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-20 20:47:34 -07:00
Larry Gritz c62e7ca911 build: Support C++26, and test it in CI in the bleeding edge test (#5230)
Bump the "bleeding edge" test to C++26 (from 23), and the "latest
releases" Linux test to C++23 (from 20). There are still other variants
that test C++20 including anything based on the VFX2026 platform.

Just one tiny change needed to compile in C++26 mode, related to a
deprecated std type_traits template.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-17 16:33:40 -07:00
Luna Kim bff962d07c docs: fix typos and update reference link in deepdata comments (#5238)
The InterpretingDeepPixels reference link expired. It moved to an
HTML page on the OpenEXR docs site, so update the comments to the
working URL.

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-17 16:32:42 -07:00
Anton Dukhovnikov 16e0e7f0bb build: suppress warnings in fmt when building on mac (#5237)
This suppresses the warnings in the fmt library code which have started
appearing recently when building on a Mac.
I suspect the warnings were triggered by the clang toolchain being
updated to v21, but to be fair I haven't tried to downgrade to confirm
that.

No extra tests. The changes allow OIIO to build with "exit on warning"
on Mac with the latest build tools, whereas without the changes the
build fails.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2026-06-16 13:47:07 -07:00
Larry Gritz ffc84fab93 cleanup: Get rid of some old files that have no use (#5234)
python_tests was from 2010 and either was checked in inadvertently, or
has long, long been supplanted by our real testsuite feature.

The various TRAVIS_SKIP_LSAN file used to mark certain tests as
skippable when running the leak sanitizer... but we long ago removed the
code in runtest.py that recognized its presence and took action. So it
has served no purpose for quite some time.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-14 23:40:55 -07:00
Vlad Erium 08acb93ef1 build: Option to use compiled fmt library (#5231)
OpenImageIO uses the fmt library, but spdlog is also quite common and
uses the fmt library. This fix should allow to use precompiled fmt
library in both spdlog and oiio if they are used in same project.

Added `OIIO_USE_COMPILED_FMT` CMake option to allow linking against a
compiled fmt (fmt::fmt) instead of the header-only variant.
Update externalpackages.cmake to expose the option, select the
appropriate fmt target and include dir, and pass the value into
generated headers via oiioversion.h.
Adjust Config.cmake.in to avoid forcing find_dependency(fmt) when
header-only behavior is overridden. Modify detail/fmt.h to skip defining
`FMT_HEADER_ONLY `when compiled fmt is used, and update libutil
CMakeLists and ustring.cpp to link/use the compiled fmt target and use
fmt::runtime for dynamic format strings.

Assisted-by: Codex 5.5 ExtraHigh

---------

Signed-off-by: Vlad <shaamaan@gmail.com>
2026-06-14 22:40:11 -07:00
Larry Gritz d47766dd99 admin: Update security alerts and clarify security policy (#5232)
Also make our CONTRIBUTING guide link to, and be consistent with,
our SECURITY.md policy file.

Follow OpenEXR's lead by explaining briefly that we only consider
something to be a security issue if it can plausibly be triggered by
ordinary inputs coming from untrusted parties. For example, a
maliciously crafted input image may be a vulnerability, but incorrect
use of an API call is not, because only trusted parties should have
direct access to the APIs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-14 15:43:01 -07:00
Larry Gritz 6f3cc11124 admin: Misc administrative docs fixups (#5233)
Some minor fixes and inconsistencies.

- Per the ASWF [repo best practices
guide](https://tac.aswf.io/project_best_practices_guides/repo.html), the
project's technical charter should NOT be redundantly stored in our
repo, but instead we should just link to the canonical copy that the
ASWF maintains.
- Fix incorrect relaive path to CONTRIBUTING.md.
- Fix leftover "interim" designations from TSC members.
- Remove Lewis Wakeland from the TSC roster (he retired some months
back, but somehow we neglected to remove him from the file)
- Add a link to the Google doc with meeting notes.
- Remove stray reference to a 2024 release.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-14 15:42:22 -07:00
Larry Gritz f762c35c29 deps: auto-build pystring update to v1.2.0 (#5235)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-14 10:34:43 -07:00
Larry Gritz 242ac1cbd0 api: span and string_view get extra contract asserts per std (#5224)
According to C++26, some newly required std container hardening for
std::span and std::string_view were not reflected in our own analogous
types. In particular, some more precondition checking was required for
span::subspan, first, last, and string_view::remove_prefix and
remove_suffix in order to match the expectations of true parity with
with the std versions.

This is important because some day, we will probably discard our own
string_view and span for the std ones (especially when we are using
compilers in which they are fully hardened).

I found a couple spots where we used remove_prefix and remove_suffix
that assumed the range would be clamped, as it is in our version, rather
than contractually require them to be valid ranges as in std. This would
eventually fail if replaced by std::string_view, so fixing now.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-12 19:19:09 -07:00
Larry Gritz 22a3543e71 build: Support gcc-16 and test it in CI (#5225)
Bump the "bleeding edge" variant to gcc-16, and the "latest releases"
variant to gcc-15.

One minor fix needed to make gcc16 happy -- it is better than earlier
versions at discovering variables whose values are not used.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-10 11:22:19 -07:00
Larry Gritz 12d55da75a docs: Clarify plugin.h explanations by saying their Unix-like equivalents (#5226)
Mostly for the sake of bots (but also humans) reading plugin.h and
trying to figure out exactly what each function does, just plainly state
which Unix-like dlopen/dlsym/etc function it is the equivalent of.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-09 23:20:16 -07:00
Larry Gritz 2c853ab9a4 ci: Fixes to build_opencolorio.bash script (#5219)
It was throwing things off to set CMAKE_CXX_COMPILER in this way,
wrecking the ability to just run as a utility from the command line
without it being set. It was not necessary, as far as I can tell.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-06-09 23:16:33 -07:00
Luna Kim 1735591356 fix(fmath.h): typo in convert_type default argument, min() to max() (#5227)
Fix typo in convert_type default argument. 
Fixes #5223

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-04 23:16:18 -07:00
Luna Kim 716311a57f api(fmath.h): apply OIIO_NODISCARD (integer helpers, float utilities) (#5221)
Part of #4781
No callers within OIIO ignore the return value.


Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-01 16:51:59 -07:00
Luna Kim b49dddb309 docs: fix typos in fmath.h comments (#5222)
Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-06-01 14:51:47 -07:00
Larry Gritz 36a7ff0cd4 docs: CHANGES update (#5220)
Just catching up from the releases in other branches.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-31 22:15:46 -07:00
Hunter b59db08e72 api: add OIIO_NODISCARD_ERROR to Imageio.h (#5218)
Add OIIO_NODISCARD_ERROR to make sure callers check their bool return
values

Assisted by: Claude Sonnet 4.6
Reference:
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4781

---------

Signed-off-by: Hunter <zoomhunter2010@gmail.com>
2026-05-31 10:32:34 -07:00
Larry Gritz b12dc295df admin: Add CVE-2024-55194 to our security alerts (long ago fixed) (#5216)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-28 23:00:46 -07:00
Larry Gritz b2d32a1ab0 admin: Add AI coding assistant configuration (#5206)
Adds agent configuration supporting Claude Code, Cursor, GitHub
Copilot, OpenAI Codex, and Opencode. A single AGENTS.md and contents
of .agents subdirectory serve as the canonical source for
instructions, skills, and other things that can be used across
multiple tools.

A script can be invoked by users to do the local setup of links or
references to allow them to use a particular tool:
`.agents/setup-agent TOOL` Currently supported tools by this script
include Claude Code, Codex, Cursor, GitHub Copilot, and OpenCode.

This initial commit includes two skills that I wrote and have used for
the last couple monthly releases: release-notes-update and
prepare-patch-release. I assume that we will add more over time as we
discover tasks that we want to make standard skill automation for.

Assisted-by: Claude Code / claude-sonnet-4-6

The AGENTS.md, Claude skills, and general scheme are entirely from me.
I used Claude to help me establish the setup script for the other
tools I don't happen to use.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-28 13:35:31 -07:00
Vlad Erium 6b7fe61418 fix(psd): fix indexed transparency (#5177)
Fixes indexed-color PSD transparency handling when the transparent
palette index is `0`.

Before this change, the PSD reader used `m_transparency_index` both as the
palette index value and as the signal that a transparency-index resource was
present. That made index `0` ambiguous: it is a valid transparent palette index,
but it evaluated as false when deciding whether to add an alpha channel.

As a result, an indexed PSD with transparency index `0` could expose a
3-channel output spec, then later `indexed_to_rgb()` would treat
`m_transparency_index >= 0` as meaning transparency exists and write 4
bytes per pixel. That could write a 4-channel row into a caller buffer sized for
3 channels.

The fix separates those two pieces of state:

- `m_has_transparency_index` records whether the transparency resource exists.
- `m_transparency_index` stores only the numeric palette index.
- Index `0` now correctly adds an alpha channel.
- Transparency indexes outside the valid palette range `0..255` are rejected.
- `indexed_to_rgb()` now checks source and destination spans before writing.

### Tests

Added regression coverage to `testsuite/psd-colormodes`.

The test now generates indexed PSD variants from the existing
`pattern2-8-indexed.psd` fixture with transparency indexes:

- `0`: valid, should report/read as 4-channel PSD.
- `255`: valid, should report/read as 4-channel PSD.
- `256`: invalid, should be rejected.

Validated locally with:

```bash
python3 -m py_compile testsuite/psd-colormodes/run.py \
    testsuite/psd-colormodes/src/make-indexed-transparency-psds.py

ninja -C build-psd oiiotool iconvert idiff
```

Also ran the generated PSD cases and a manual full psd-colormodes test;
final out.txt matched the updated reference

Assisted-by: Codex GPT5.5xHigh

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2026-05-27 22:25:07 -07:00
Larry GritzandCopilot Autofix powered by AI 64e0b40879 feat(oiiotool): flexible offset notation with commas (#5209)
Fixes #5207

Sometimes the `WxH+X+Y` and `+X+Y` notation (borrowed from X11!) can be
a little awkward. This patch extends the accepted syntax to allow commas
to separate the offset components, for example also accepting `WxY,X,Y`
and `X,Y`.

This affects the commands

    --create
    --crop
    --cut
    --fit
    --fullsize
    --origin
    --originoffset
    --paste
    --pattern
    --printstats
    --resize

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-26 11:12:47 -07:00
Larry Gritz 0078f36a97 feat: allow freeing of ustring table for debugging cases (#5213)
This patch optionally frees the contents of the ustring table as the
process is exiting. It's triggered one of two ways:

- `OIIO::attribute("ustring:cleanup", 1);`
- Environment variable `OIIO_USTRING_CLEANUP=1`

If neither is used, the teardown won't happen, thus avoiding any
pointless work when it should be exiting the process.

The purpose of this is that when using certain debugging tools, the
ustring table (which only grows and never frees) looks like a memory
leak, even though it's by design. Someimes, it's useful to make it not
appear ot leak, and you are happy for a large table to spend time
pointlessly freeing all the data.

Fixes #3913

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-26 11:11:46 -07:00
Larry Gritz 221c713330 ci: Remove jobs using the aswf-docker 2022 containers (#5204)
In main (working toward the late-2026/2027 releases) these 2022
containers are both outside the promised 3 year support window, and also
are using CentOS 7-based containers that are essentially irrelevant now
that all the studios have moved to RHEL9 (and Rocky/Alma) compatible OS
distros. So there is really no need to continue CI testing on them for
branches aimed at the future.

Note that we still have Ubuntu-based "oldest gcc" and "oldest clang"
jobs, so dropping this does not actually impact our ability to test
against the oldest gcc, C++, and python that we claim to support.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-25 12:12:06 -07:00
Larry Gritz dcf0bc2815 testing: new ref image for libheif 1.22 (#5212)
New release of libheif, which continues to live up to its habit of
changing pixel values ever so slightly with each release.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-25 12:09:48 -07:00
Luna Kim 125e514ec0 build: remove -Wno-unused-result from gcc options (#5214)
Background: this flag was originally added in commit c5494ac06
(2015-11-24) with the message "...now builds linux+gcc...". It was later
refactored in commit 62d7164d3 (2017-01-23). From investigation, it
seems to be preventative rather than reactive because it does not
actively suppress warnings, but `-Werror` is enabled under the condition
NOT MSVC + STOP_ON_WARNING (originally in CMakeLists.txt, now in
compiler.cmake:126).

Compile tests without `-Wno-unused-result` but with `-Wunused-result`
explicitly enabled were conducted on the following commits, and all
compiled successfully without unused result warnings. Also, tests
confirmed that the warning triggers if there is an unused return value.
- 312793af4 (2026-01-01)
- 682825f9d (2025-01-01)
- 48362b26c (2024-01-01)
- 3b8807df8 (2023-01-01)
- 62d7164d3 (2017-01-23): refactored
- c5494ac06 (2015-11-24): originally added

Decision: the flag can be safely removed. Removing it allows gcc to
catch unused return values, which is required for the `OIIO_NODISCARD`
and `OIIO_NODISCARD_ERROR` macros to work as intended.

Related: #5196
Assisted-by: Claude / Opus 4.7


Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-05-23 20:06:00 -07:00
Larry Gritz df6c3ead1c build: Improve error message about mismatching git tags (#5205)
This message is triggered by the check that the tag of an auto-build
dependency matches the SHA hash we use as a cross-check. This patch is
just amending the error message to reveal the way to override the check,
so people (like me) don't have to go hunting for it if they are
purposely trying to build from a nonstandard commit of a dependency.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-22 14:50:58 -07:00
Larry Gritz 1706f9ad10 fix(color mgmt): More sensible OCIO file rules (#5194)
I recently discovered that OCIO's built-in configs' "file rules" that
come into play when using getColorSpaceFromFilepath actually do not
incorporate the search for color space name embedded in the filename
into the logic, and moreover, assume that files ending in ".exr" are
ACES2065-1, of all things. This seems an unfortunate choice because in
the real world, almost no exr files people will encounter actually use
the ap0 primaries.

This PR does the following to shore up this and related edge cases:

* For OCIO built-in configs, fully replace the existing file rules with
a blank slate that just uses the path parsing rule. Everything else is
categorized as "unknown". (Though many of our format readers already do
something better, setting the metadata if they actually know what the
file is.)

* Recognize "unknown" as equivalent to having an empty color space, an
error if you pass such a color space name to IBA color transform
functions.

* For all IBA color conversion, if the input space is not color managed,
be sure NOT TO mark the output color space as the original `to` request!
Input raw means output is also raw.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-20 23:40:55 -07:00
Larry Gritz 8014367200 fix: Remove redundant declarations (#5210)
This is an emergency fix on top of #5201.

PR #5201 passed CI completely. Then I merged it, and now it fails. How
did that happen?

OOOOOOH. The imagespeed_test.cpp is not compiled at all for CI! Only for
local builds. So a build break in it will not be caught in CI. OK,
fixing that, too. It doesn't run in CI, it's not that kind of test, it's
a special benchmarking test meant to run locally and needs to be told a
specific image file to test with. But at least build it for CI so we
can't inadvertently break it again.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-19 22:22:12 -07:00
rose413 bd7c698f66 api: add OIIO_NODISCARD_ERROR to ImageOutput methods (#5201)
- Annotate all ImageOutput write methods (write_image, write_scanline,
write_scanlines, write_tile, write_tiles, write_rectangle,
write_deep_scanlines, write_deep_tiles, write_deep_image), as well as
open, close, and copy_image, with OIIO_NODISCARD_ERROR.
- Also fix the handful of internal callsites (imagebuf.cpp,
maketexture.cpp, py_imagebuf.cpp, iconvert.cpp, imagebufalgo_test.cpp,
and imagespeed_test.cpp) that were previously ignoring the return value
of close(), either by propagating the error or by casting to void where
the error path is already being handled.
- Reference: #4781 

### Tests

- tested against unit_imageinout, unit_imagebuf, unit_imagebufalgo

Assisted-by: Claude Sonnet 4.6

---------

Signed-off-by: rose413 <116857309+rose413@users.noreply.github.com>
2026-05-19 19:26:01 -07:00
Maxwell Iverson 386d459d0c fix(pnm,jxl): Prevent PNM/JXL readers from loading arbitrarily large non-image files (#5203)
##### PNM

The PNM reader did not provide an optimized `valid_file` implementation.
While `PNMInput::open` would perform basic validation of the PNM header,
it would only do this after having read the entire contents of the file
into memory. Besides the obvious risks/issues with having `open`
unconditionally read arbitrarily large files into memory, this also
meant that any call to `valid_file` would necessarily do the same (as
the default implementation delegates to `open` when ioproxy support is
present).

To fix these issues, the following changes were made:
* Provide an efficient implementation of `valid_file` for `PNMInput`
that only loads the header, and then validates magic number/dimensions.
* In `PNMInput::open`, first load only the header to memory, and
subsequently, only load the rest of the image data if the header is
parsed successfully, and the data contained within is valid.
* Added a rough limit to header read size of 1KiB.
* Added a rough limit to full file read size of 1GiB.

Note that, for now, if the file size exceeds the 1GiB limit, the read is
simply truncated to 1GiB, rather than failing altogether.

##### JPEGXL

The JXL reader already provided an efficient `valid_file` override,
implemented by validating the 128 byte JXL signature. The signature,
however, was not being validated in `JxlInput::open` before attempting
to decode the file.

The process of JXL decoding appears to read the entire contents of the
file to memory (at least for some non-JXL inputs). Taken in combination,
this means that when `JXLInput::open` was called on arbitrarily large
non-JXL inputs, the entire file was being read into memory before `open`
would fail.

As a simple fix for this, `JxlInput::open` now checks the result of
`valid_file` before attempting any decoding.

### Tests

I did not add a new testsuite case for this, but did test on my end that
for both PNM and JPEGXL, large invalid files are no longer being read
into memory, while valid images (of their respective types) are still
read/opened successfully.

---------

Signed-off-by: maxwelliverson <maxwelliverson@gmail.com>
2026-05-19 09:01:52 -07:00
Hannah Gulka 539aba4192 int(webp,jpeg-xl): Added check_open for WebP and JPEG XL readers (#5202)
This PR addresses the feature request in issue
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3974

Continuing from previous work done on this feature request, I have added
`check_open` calls to two new format readers, using file format specs
found online:
- WebP:
https://developers.google.com/speed/webp/faq#what_is_the_maximum_size_a_webp_image_can_be
- JPEG XL: https://jpegxl.info/resources/battle-of-codecs.html

I also cross-referenced this info with the corresponding
ImageOutput::check_open calls for sanity, and they seemed to align.


Signed-off-by: Hannah Gulka <hannahkg8@gmail.com>
2026-05-15 21:32:27 -07:00
Luna Kim 1711c39a92 api: apply OIIO_NODISCARD to color.h (#5196)
Adds `OIIO_NODISCARD` and `OIIO_NODISCARD_ERROR` to `color.h`.
Deprecated functions are left unannotated.

Part of #4781 

Assisted-by: Claude / Opus 4.7

---------

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
2026-05-15 21:10:23 -07:00
Larry Gritz 67a4307da1 ci: Fix broken CI by locking down aswf container for 2023 (#5200)
Our CI job that builds against VFX Platform 2023 via docker container
aswf/ci-osl:2023-clang15 broke after some dependency changes in a recent
aswf docker container update. It's not worth trying to "fix" an old
year, just lock down to the previous version of the container that is
known to work.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-15 18:43:01 -07:00
Lumina Wang 9968f8c637 perf(filesystem.h): Speedup other file ops on Windows (#5199)
Similar to https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4977,
replace `std::filesystem` with Windows APIs for better performance.

Signed-off-by: Lumina Wang <lumina.wang@autodesk.com>
2026-05-15 15:54:19 -07:00
Danny Greenstein a6fd93abac oiiotool: Add --nchannels flag for parity with maketx (#5198)
This PR adds a `--nchannels` flag to oiiotool, providing parity with the
existing flag in maketx.

### Problem:

When processing images from varied sources in automated pipelines, using
name-based channel selection (e.g., --ch R,G,B) is fragile. If an input
image uses non-standard names (e.g., X,Y,Z or 1,2,3), the command may
output black channels or issue warnings that are easily missed in large
logs.

### Solution:

While you can solve this by specifiying the indices of the channnels,
e.g --ch 0,1,2, the `--nchannels` flag offers a more intuitive and
robust "shortcut" to force an image to a specific channel count. maketx
has had one for years and I found that it works really well and often
wished oiiotool would have one too.

### Implementation:

The implementation acts as a wrapper around action_channels,
programmatically generating the index string. It uses ustring to intern
the generated string, ensuring memory safety even if the action
execution is deferred/postponed.

Assisted-by: Google Gemini (advice on ustring interning and
architectural structure).

### Tests

I added some tests to showcase what this is trying to solve

Signed-off-by: Danny Greenstein <danny.gr@gmail.com>
2026-05-14 23:55:24 -07:00
Marta Feriani de9eade170 docs: Conversion of ImageOutput docs to tests for the copy image example (#5197)
### Description

Convert C++ and Python example from the [ImageOutput: Copying an entire
image](https://openimageio.readthedocs.io/en/latest/imageoutput.html#copying-an-entire-image)
chapter into tests within the `docs-examples-{cpp,python}` test suites.
This was done following the steps outlined in [Converting documentation
examples to
tests](https://github.com/AcademySoftwareFoundation/OpenImageIO/wiki/Converting-documentation-examples-to-tests).

----
* This PR contributes to addressing issue
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3992.
* This PR supersedes the closed PR
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5195.
----

#### Notes

- In both `python` and `cpp` I have replaced the file
`{input,output}.jpg` mentioned in the example with `{input,output}.exr`
in the test, so to reuse existing resource files (i.e.
`testsuite/common/grid-small.exr`): do let me know if you prefer the
tests also use a `.jpg`, in which case I'll add a new resource to that
effect.
- The `cpp` example code was further modified to:
1. pass the requirements of `clang-format` (see original failing output
[here](https://github.com/demiaster/OpenImageIO/actions/runs/25871058187/job/76026144354))
  2. successfully run `ImageOutput.copy_image`
- The `python` example code was further modified to remove unnecessary
whitespace before the brackets of function calls.

Finally, when following the [conversion
docs](https://github.com/AcademySoftwareFoundation/OpenImageIO/wiki/Converting-documentation-examples-to-tests),
I have not addressed point `5`: again, let me know if you prefer to have
a positive fixture to compare the test output against.


### Tests

I have checked that, on my fork:
* The CI passes successfully:
https://github.com/demiaster/OpenImageIO/actions/runs/25888576608
* The docs build successfully:
https://github.com/demiaster/OpenImageIO/actions/runs/25888576599
* The replaced docs examples render correctly (see excerpt from above
build here:
[imageoutput.html](https://github.com/user-attachments/files/27781020/imageoutput.html))


Signed-off-by: Marta Feriani <marta.celeste.feriani@gmail.com>
2026-05-14 23:27:08 -07:00
Larry Gritz ddba92fe98 fix(oiiotool): be cautious promoting to float due to color space name with --autocc (#5192)
Background: OCIO 1.x configs were LUT based and so tended to have
different color space names for different data types/bit depths. We
capitalized on this to let `oiiotool --autocc` also select type/bits,
but this trick doesn't work so well for OCIO 2.x configs with procedural
(non-LUT) transformations that all look like "float". We don't want to
promote to float just because of this!

Solution: When using color space data type (nearly always float for new
configs and certainly the built-in configs) to infer output, DO NOT use
"float" as a real request. Treat it as not being a specific type, don't
let it override the intended output type for --autocc. (But a color
space still marked as a particular integer bit depth is still an
--autocc inferred request.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-12 23:03:34 -07:00
Larry Gritz 90f308b2a1 api(ColorConfig): add isData, fix python isColorSpaceLinear. (#5191)
* Add `ColorConfig::isData(name)` method to C++ and Python APIs.
* Fix `ColorConfig.isColorSpaceLinear()` that was missing from the
Python bindings. (Tests added as well.)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-12 21:41:04 -07:00
Larry Gritz 6e42dfb6cc int: Add some more debugging help for OCIO exceptions (#5190)
In PR #5164, we changed to not be quite as aggressive in treating OCIO
exceptions as real errors. All still good with that, but sometimes it is
helpful to know exactly what OCIO wants to tell us, for debugging.

In this PR, we allow our color debug mode (triggered when environment
variable OIIO_DEBUG_COLOR is set to nonzero) to print debugging messages
that reveal the exception messages. It's a debugging aid for developers,
no users will want this. In ordinary operations, we really do want to
just ignore those exceptions. But if something is misbehaving and we
don't know why, it may be helpful to know which of the exceptions is
being caught and what the message was.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-12 15:51:42 -07:00
Larry Gritz 75b4586b23 ci: Remove deprecated windows-2025 runner (#5189)
We test on 3 Windows runner configurations currently -- Windows 2022
with VS2022, Windows 2025 with VS2022, and Windows 2025 with VS2026.
GitHub says the middle one will go away imminently (actually, it won't
"break", but it will redirect to Windows 2025 with VS2026, which we
already test). So take it out of our lineup, it's just waste.

The one thing the middle one did differently than the others is test
nanobind, so just move that to the VS2026 one.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-09 23:26:47 -07:00
Larry Gritz 9360099d6c feat(iconvert): allow -o for convenience (#5173)
iconvert was the very first command line utility for OIIO, and its
syntax was just `iconvert [options] infile outfile`. YEARS later,
oiiotool came along, superceding iconvert with 100x the functionality,
and also differed by requiring `-o` to specify output file.

iconvert still exists for testing and examples -- iconvert uses just
plain old ImageInput + ImageOutput straightforwardly, whereas oiiotool
is a very complex app that's ImageBuf powered. It's often useful for
debugging to test the ImageInput/ImageOutput layer without any extra
complication, or to directly see how going through an ImageBuf might
differ.

The fact that oiiotool requires `-o` to specify an output file, whereas
iconvert considers that an error, is a minor annoyance when switching
back and forth while debugging, and it's really bugging me.

So here it is, a tiny patch to let iconvert silently accept -o, or not,
and do the obviously right thing. A little quality of life gift to
myself.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-09 23:22:50 -07:00
Lumina Wang b0039a7dbf fix(gif): Preserve RGB values of transparent pixels (#5188)
Preserve RGB of transparent color index pixels in GIF files.

When reading GIF files, pixels of transparent color index were skipped.
This left their RGB channels zeroed, discarding possible valid colormap
data. To preserve the RGB values, we change to always write the
colormap's RGB and set alpha conditionally.

According to [GIF spec](https://www.w3.org/Graphics/GIF/spec-gif89a.txt):

>viii) Transparency Index - The Transparency Index is such that when
encountered, the corresponding pixel of the display device is not
modified and processing goes on to the next pixel. The index is present
if and only if the Transparency Flag is set to 1.

So basically, it just defines a display compositing behavior but says
nothing about the color table entry for that index being invalid or
empty. In practice, encoders may still assign meaningful RGB values to
the transparent index, and those values are perfectly well-defined in
the colormap. For example, GIMP reads the valid RGB values ​​of
transparent pixels (see attachment below).

### Tests

A new test image and test case is added:
https://github.com/AcademySoftwareFoundation/OpenImageIO-images/pull/11

<img width="847" height="695" alt="image"
src="https://github.com/user-attachments/assets/484c8b53-5a1b-4732-b95c-55a2f52021b5"
/>


Signed-off-by: Lumina Wang <lumina.wang@autodesk.com>
2026-05-09 12:50:47 -07:00
Larry Gritz 42b6359c55 fix(softimage): Fix possible small allocation leak (#5182)
We used new/delete for some small allocations, but there was a possible
leak because early returns would skip the delete. But even when not
leaking, this was wasteful. Replace by a stack allocation using
OIIO_ALLOCA outside the loop -- both problems solved.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-06 21:34:58 -07:00
Vlad Erium 91ee4025b8 fix(jpeg): more correctly handle metadata marker bounds (#5174)
Fixes bounds checks for malformed JPEG APP1 Exif and APP2 ICC metadata
markers.

Before this change, APP1 markers were treated as Exif when they started
with
`"Exif"` and had at least 4 bytes. The reader then skipped 6 bytes for
the
`Exif\0\0` prefix, so short payloads such as `Exif` or `Exif\0` could
advance
past the saved marker buffer and underflow the remaining length passed
to the
Exif parser.

The APP2 ICC path also used `strcmp()` on raw marker bytes before
proving the
marker was long enough or NUL-terminated. Short APP2 markers could
therefore be
read past the saved marker buffer, and the code later accessed sequence
bytes
and subtracted `ICC_HEADER_SIZE` without first checking the marker
length.

This is reachable by normal OpenImageIO image-open paths, including
tools such
as `iinfo`, `iconvert`, and `oiiotool`, when opening a malformed JPEG.

The fix adds bounded marker-prefix helpers:
- APP1 Exif is accepted only when the full `Exif\0\0` prefix is present.
- APP2 ICC is accepted only when the marker is at least
`ICC_HEADER_SIZE` bytes
  and matches `ICC_PROFILE\0` using bounded comparison.

### Tests

Added coverage to `testsuite/jpeg-corrupt` for short APP1/APP2 metadata
markers:
- APP1 Exif payload lengths 4 and 5
- APP2 ICC payload lengths 11, 12, and 13

Validated locally with:

`ctest --test-dir build-jpeg-only -R '^jpeg-corrupt$'
--output-on-failure`

Assisted-by: Codex GPT 5.5xHigh

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2026-05-05 21:43:17 -07:00
Larry Gritz d721d06bd8 perf(dpx): use default_init_vector to speed up allocation for internal buffers (#5183)
This just avoids needing to zero out the allocated buffer, since we know
we are allocating it merely to write into it. Uninitialized contents is
ok and faster.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-05 14:44:52 -07:00
Larry Gritz 1d28b1e8c7 admin: Amend SECURITY.md with recently assigned CVE numbers (#5187)
These are all items fixed and documented in the latest releases. I had
hoped that the CVE reference numbers would be ready before I pushed
those releases out. But let's just say that GitHub's "3 business days to
assign a CVE" claim is aspirational.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-05 14:44:14 -07:00
Larry Gritz a11ee11dfc dicom: enforce reasonable resolution limits to guard against corrupt file (#5167)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-05 12:45:08 -07:00
Aleksandr Motsjonov 6ea45b11cc ci: Run both tests pybind11 and nanobind in CI (#5176)
Follow up to
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5084

Here we make at last one OS to run both tests

Assisted-by: Cursor/Composer-2

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2026-05-04 22:16:55 -07:00
Vlad Erium a9bcad4b70 fix(webp): fix exif chunk bounds handling (#5175)
Fixes bounds handling for WebP EXIF metadata chunks.

Before this change, the WebP reader always skipped the first 6 bytes of
an EXIF chunk before calling `decode_exif()`:

```cpp
bytes + 6
size - 6
```

That assumed every WebP EXIF chunk was at least 6 bytes long and always
started with the optional Exif\0\0 prefix. A malformed WebP file with a shorter EXIF
chunk could therefore advance the pointer past the chunk payload and
underflow the remaining size passed to the EXIF parser.

This is reachable through normal OpenImageIO image-open paths, including
tools such as iinfo, iconvert, and oiiotool, when opening a malformed WebP
file.

The fix changes the WebP reader to treat the EXIF chunk as a bounded byte span.
Before calling decode_exif(), it now verifies that the payload contains enough
bytes for a TIFF header, either at the start of the chunk or after an optional
Exif\0\0 prefix. The WebP reader no longer performs an unconditional 6-byte
skip; the shared EXIF decoder already handles the optional prefix safely.

### Tests

Added WebP regression coverage for malformed short EXIF chunks.

The testsuite/webp test now generates WebP files with EXIF chunk payload
lengths:

- 0 bytes
- 4 bytes: Exif
- 5 bytes: Exif\0
- 6 bytes: Exif\0\0
- 13 bytes: Exif\0\0 plus a truncated TIFF header

Each generated file is opened through oiiotool to verify that malformed EXIF
metadata does not crash or read past the chunk buffer.

Validated locally with:

python3 -m py_compile testsuite/webp/src/make-short-exif-webp.py
git diff --check
cmake --build build-webp --target oiiotool -j 8

Also ran direct oiiotool smoke tests for all generated malformed WebP
inputs.

Assisted-by: Codex GPT5.5xHigh

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2026-05-04 21:52:27 -07:00
Larry Gritz 3091061460 admin: CHANGES, update SECURITY, bump version designation to 3.2.0.2-dev (#5181)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-04 17:42:19 -07:00
Larry Gritz a2506751bb fix(dpx): Several safety fixes for corrupt DPX files (#5170)
* SWAPRGBABytes: convert to from raw pointers to span-based.
* A variety of overflow safety fixes, replace int (32 bit) with size_t
or int64_t and use safe_mult64.
* Use ImageInput::check_open() for dpx files to check for
reasonable/legal resolutions and channel counts
* Comment out more function declarations not used by OIIO.

Aside:

I should say, this code was originally imported/vendored from another
project by Patrick Palmer: https://github.com/PatrickPalmer/dpx
We imagined it might be an ongoing/improving work, so we made some very
minor changes here and there but endeavoured to make as little change as
possible -- even excluding it from our clang-format rules! -- so that we
could diff against the changing dpx project and pull in any changes or
even use it as an external dependency.

But as you can see if you go there, it hasn't had any modifications for
17 years! So we never needed the "feature" of minimizing divergence from
the original. And now I think with the rate of discovery and reporting
of vulnerabilities and bugs accelerating, the pressure is on to make
this code "safer," for example with these changes in this PR.

I think it's time to give up the pretense entirely and just allow
ourselves to fully absorb this code as our own, be unconcerned about
divergence. So after this PR is merged, I expect follow-ons to:
- Once and for all, fully remove the "dead code" parts that we commented
out because they aren't used in OIIO.
- Allow clang-format to process these files and bring them into
formatting unity with the rest of OIIO.
- Convert all the raw pointer use to spans
- Remove redundant code -- functions in the original dpx project that
were functionality equivalent to things already in OIIO -- where we kept
the originals in place for the sake of minimizing divergence. Let's just
use the OIIO ones we use everywhere else, in cases where they already
exist.
- Root out all remaining overflow and bounds issues, some of the new LLM
based tools are really good at finding those.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-03 21:10:17 -07:00
Larry Gritz 50962c9c50 ci: Temporary fix -- make libheif optional for Ubuntu jobs (#5180)
This will get us through the great Canonical attack of May 2026, where
it seems that `add-apt-repository ppa:strukturag` is still unreliable
even as we are now multiple days overdue to get our releases out.

We will revert this after everything is fixed. I don't like it silently
passing when we think it's testing heif files but it's really not, any
longer than we have to be in that state.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-03 18:53:03 -07:00
Larry Gritz 3bed17598e ci: need ref output for libheif 1.17 (#5179)
This is mostly to get it to pass when the GHA runners can't
add-apt-repository ppa:strukturag when it's glitchy down. It can fall
back to an older libheif 1.17 that's already on those runners, but needs
a matching reference output for that version. This is it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-05-03 17:41:03 -07:00
Larry Gritz 85cca81613 fix(softimage): Various fixes for malformed channel packets (#5156)
* Fix bugs when channel order isn't strictly R,G,B,A by using a
`m_channel_map`.
* Detect malformed file with too many channel packets.
* Gracefully handle duplicate channel bits across packets by not
thinking that there are duplicate channels.
* Guard against channel packets that contain no channels.

Assisted-by: Claude Code / Opus 4.6
(mostly for analysis/identification of the potential problems; touching
the code only for the out-of-order channels fix)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-30 18:34:27 -07:00
Larry Gritz 6ec094cede fix(softimage): More hardening against corrupted input files (#5155)
* Fix incorrect return check for fread in read_pixels_pure_run_length.
* Detect and report error for unsupported packet type.
* Fix possible infinite loop from malformed RLE packet with a zero
run-count.
* Check for valid y range in read_native_scanline.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-30 17:48:06 -07:00
Larry Gritz 2cdaedc1e1 fix(heif): Fix incorrect tracking of current subimage (#5166)
Oh dear, somehow our heif reader never correctly overloaded the
current_subimage method, instead inheriting the one from the base class
that always returns 0. That's very bad for a file type that supports
multiple subimages.

Along the way, simplified how we deal with the fact that the "primary"
subimage doesn't need to be first in the file, but we always want to
present it as if it were first. There was a point where I thought that
was related to the bug so I was rewriting it; it turned out to not be
the problem, but I'd still like to keep the cleanup I had done.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-29 21:58:56 -07:00
Aleksandr Motsjonov 409621b0f9 feat: Nanobind for python bindings (first steps -- pybind11 still working) (#5084)
First PR on the way to a migration from pybind11 to nanobind.

New env flag introduced `OIIO_PYTHON_BINDINGS_BACKEND` = `pybind11` or
`nanobind` or `both`

> Select which Python binding backend(s) to configure. `both` keeps the
existing pybind11 module and also builds the experimental nanobind
module.

When it is nanobine one is build it is in
`PyOpenImageIONanobindExperimental` target.

```
cmake --fresh -S . -B build \
  -DUSE_CCACHE=OFF \
  -Dfmt_DIR=/opt/homebrew/lib/cmake/fmt \
  -DOpenColorIO_DIR=/opt/homebrew/lib/cmake/OpenColorIO \
  -DOIIO_INTERNALIZE_FMT=ON \
  -DOIIO_PYTHON_BINDINGS_BACKEND=both
```

### Checklist:

<!-- Put an 'x' in the boxes as you complete the checklist items -->

- [x] **I have read the guidelines** on
[contributions](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/CONTRIBUTING.md)
and [code review
procedures](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/docs/dev/CodeReview.md).
- [x] **I have updated the documentation** if my PR adds features or
changes
  behavior.
- [x] **I am sure that this PR's changes are tested somewhere in the
  testsuite**.
- [x] **I have run and passed the testsuite in CI** *before* submitting
the
  PR, by pushing the changes to my fork and seeing that the automated CI
passed there. (Exceptions: If most tests pass and you can't figure out
why
the remaining ones fail, it's ok to submit the PR and ask for help. Or
if
any failures seem entirely unrelated to your change; sometimes things
break
  on the GitHub runners.)
- [x] **My code follows the prevailing code style of this project** and
I
  fixed any problems reported by the clang-format CI test.
- [x] If I added or modified a public C++ API call, I have also amended
the
corresponding Python bindings. If altering ImageBufAlgo functions, I
also
  exposed the new functionality as oiiotool options.

This code contribution was assisted by Cursor/Composer-2

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2026-04-29 17:25:27 -07:00
Larry Gritz d1de954175 fix(rla): immediate fix for PR #5153 error (#5172)
Caught in review, but I didn't see the comment before I merged.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-29 17:25:05 -07:00
Larry Gritz aae20f0a90 fix: immediate fix to PR 5154, uncheked return (#5171)
PR #5154 crossed streams with another that turned on more warnings for
unchecked errors. The check isn't necessary here, though.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-29 14:15:22 -07:00
Larry Gritz 247e61bb99 fix(rla): Harden against corrupted files (#5153)
1. Harden against buffer overruns from malformed RLE blocks. The simple
fix is the `if (count > ...)` clauses on lines 503 & 510, but I also
took the opportunity to rewrite decode_rle_span using spans rather than
raw pointers.

Fixes #5152

2. Clean up seeking methodology to be more robust.

Fixes #5159

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-29 11:44:33 -07:00
Larry Gritz 40011546a4 feat(IBA): Add FLIP perceptual image difference metric (#5154)
Implements the FLIP algorithm from Andersson et al. 2020, rewritten with
OIIO idioms (no source code from the BSD-licensed reference FLIP.h is
directly incorporated). Included are C++ and Python API for
ImageBufAlgo::FLIP_diff(), and `oiiotool --flipdiff` command. The basic
operation is to compare two images and produce a per-pixel error map
that conveys perceptual difference to human observers.

I won't explain it all here; see the extensive comments in
imagebufalgo.h, imagebufalgo_flip.cpp, oiiotool.cpp, imagebufalgo.rst,
oiiotool.rst.

There are some important changes (especially for how we expose this via
oiiotool) versus the way the original NVIDIA reference implementation's
command line tool worked. Please read the extensive comments at the top
of imagebufalgo_flip.cpp for details.

This is a preliminary, experimental implementation. It's hidden behind
an `experimental` namespace (and the oiiotool command requires use of
the `--experimental` argument) to emphasize that it may change and is
not yet considered part of OIIO's public API, and thus is exempt from
our usual strict rules about breaking backward compatibility. Try it out
and give feedback, but do not rely on this yet!

Assisted-by: Claude Code / sonnet-4.6 + opus-4.6

I used Claude Code for the inital stab at transforming the NVIDIA
reference implementation into OIIO idiomatic equivalents. But to be
honest, that got me over the hump of the blank page, but I rewrote most
of it bit by bit as I continued to refine my design ideas for how it
should work and be exposed to users.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-29 11:35:03 -07:00
Larry Gritz a543661149 api(memory.h): default_init_allocator/default_init_vector (#5169)
Move this from internal-only in imageio_pvt.h to be public in memory.h.
It's useful and we've used it in limited ways for a while without
needing any changes. It seems ready for prime-time (for example,
allowing it to be used in reader/writer plugins). None of the logic
changes, it's just moving from a private header to a public header and
out of the 'pvt' sub-namespace.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-28 15:18:33 -07:00
Larry Gritz 364abedd51 fix(iinfo): Better iinfo error handling, especially from --hash (#5168)
Try to bubble up errors, stop processing as soon as an error has
occurred, correct return code if a file could not be read properly.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-28 15:18:16 -07:00
Larry Gritz 3c2e174a64 fix: Relax OpenColorIO exception handling (#5164)
In PR #5114, just a few weeks ago, I was trying to catch every possible
OCIO exception. That was a good idea, but I was over-eager and treated
every OCIO exception as if something really bad happened. I should have
recognized that OCIO enjoys throwing exceptions for things where I would
have just used an empty return value to indicate a simple failure to do
what was asked.

So this patch is revising the approach as follows:

* Exceptions thrown because it couldn't read a config properly (it was
missing or broken), or couldn't produce a ColorProcessor when asked --
those are real problems that we should treat as serious errors.

* Exceptions thrown because it can't satisfy a simple request (like
"what is the name of the color space for this role" in a case where the
role you passed is not known by the config) -- we should catch those
exceptions, but it's not an "error" for OIIO, we just return an empty
string because there is no color space for that role.

Also beefed up some of the documentation of our ColorConfig class
methods to describe what happens with certain kinds of failures.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-27 09:53:53 -07:00
Larry Gritz 3602148092 ci: Try to reduce costs and timeouts for expensive tests in debug mode (#5150)
* Fix setting and response of OIIO_CI -- it was less functional before
than I had thought because we didn't actually define the symbol for
compilation.

* More aggressive cost reduction when combining CI + Debug builds,
reduce resolution of some benchmarks, etc., in addition to reducing
iterations as we had done before.

* Mark the most expensive unit tests with a cost, so CTest knows to
start them first. (more explanation below)

* Add Testing/Temporary/CTestCostData.txt to the cache-save paths --
that preserves CTest's understanding of how much each test costs so it
can schedule it more intellegently for the next run.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-26 18:52:27 -07:00
Larry Gritz c3fbed1ba3 fix(tiff): more care ignoring XMP tags that should not be used (#5162)
Guard against corrupt XMP blocks with TIFF related names: if the XMP
item starts with "tiff:", just ignore it if it's not one of the few
TIFF-related XMP items we recognize of if it's marked redundant, and
don't *replace* a TIFF related item that already had a value in the
spec.

Fixes #5157

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-25 21:35:57 -07:00
Larry Gritz 670c2616aa fix(xmp): Correctly parse XMP with self-closing elements (#5106)
decode_xmp() only searched for `</rdf:Description>` end tags, so
self-closing `<rdf:Description ... />` elements (valid XML) were
silently skipped. Now detect both `/>` and `</rdf:Description>` endings,
plus simplify quite a bit generally, by rewriting decode_xmp to use
pugixml more thoroughly to do the whole parse job instead of trying to
hunt for tags ourselves.

Fixes #5021

Assisted-by: Claude Code / Opus 4.6

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-25 21:35:11 -07:00
Larry Gritz f0aab066d0 fix(targa): Protection against corrupt, mis-sized palette (#5165)
* Check that the palette isn't senselessly bigger than the bpp calls
for.
* Protection against integer overflow when addressing the palette.
* Fix misunderstanding of the role of the palette "start" index. Pixel
values are absolute, not relative to the start index. The bug would have
produced incorrect images (or incorrectly reported image corruptions) if
we ever came across an tga file with a non-zero palette start index.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-25 21:33:53 -07:00
Larry Gritz 0e420932a8 build: Fix Makefile wrapper to properly quote test regex (#5146)
This fixes a longstanding issue where saying

    make test TEST="foo|bar"

would be malformed, instead of running tests that matched either foo or
bar (misinterpreting the `|` as a pipe). The problem was just not
quoting it properly.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-23 08:44:23 -07:00
Larry Gritz d0429b5c2e fix(tiff): care with missing rowsperstrip (#5160)
According to the TIFF spec, TIFF files with a missing rowsperstrip
should assume the whole image is one strip.

Somewhat related (found in debugging): add a DASSERT to help debug if
fmath.h's round_to_multiple() is given an invalid denominator.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-23 08:42:48 -07:00
Larry Gritz 19c4563148 fix(bmp): Correctly handle the combination of greyscale + RLE compression (#5163)
Fixes #5158

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-23 00:12:09 -07:00
Larry Gritz caa51746f4 fix(ImageSpec): ImageSpec::get_string_attribute didn't correctly translate to string (#5161)
This method is advertised as being able to convert any type of the
attribute into a string, but actually, it would only *search* for
attributes that were entered as strings, so there was no conversion
happening.

Beef up testing of paramlist and imagespec to cover the holes that let
this mistake happen.

Fixed a couple typos in imageio.h comments as well.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-22 22:49:03 -07:00
Larry Gritz 0e43845c6a fix(jpeg2000): Watch out for int overflow in buffer size computation (#5143)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-22 21:20:55 -07:00
Larry Gritz 6e8d62b75b fix(softimage): Prevent buffer overruns from corrupt RLE (#5142)
* Check for buffer overruns.
* Use check_open.
* Check for invalid bit depths.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-21 20:36:24 -07:00
Larry Gritz 6e1b49358e int: Turn on OIIO_NODISCARD_ERROR_ENABLE for internal builds (#5145)
Rearrange the automatic setting of `OIIO_NODISCARD_ERROR_ENABLE` so that
for external (not OIIO itself) builds, we default to enabling for OIIO
>= 3.3, and disabling for older and current versions. But now, when
building OIIO itself, it is ENABLED regardless of version.

So this means that as we add OIIO_NODISCARD_ERROR annotations to
functions, we MUST fix any calls to those functions where we ourselves
don't check their return values, and can't accidentally add new breaking
code.

Also, had to fix a bunch of spots that were missed in the original PR,
places where we didn't patch up our sloppy uses of what was annotated in
that patch. I'm not sure I understand how these could have been missed
in that last PR, since that PR did fix other uses of the annotated
functions.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-20 22:17:37 -07:00
Larry Gritz c6c80bc1ac admin: Update security instructions to emphasize reporting via GitHub (#5149)
The security@openimageio.org is still fine, but we prefer that true
vulnerability reports come via the GitHub security advisory mechanism.
(That makes it easy for us to turn them into CVEs when needed, among
other administrative niceties.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-20 09:27:07 -07:00
Larry Gritz ba8d726064 api(fmath.h): make degrees and radians constexpr (#5151)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-20 09:26:06 -07:00
Larry Gritz 78350913ff oiiotool: Add --experimental command line argument. (#5147)
Introducing this as a way to allow us to have experimental oiiotool
features or behaviors that are enabled only if this flag is also
present.

It's a way of allowing features to be turned on for feedback before
we're sure it's in a form that can be a permanent, supported feature,
thus allowing it to undergo further change that is exempt from our usual
rules about what may change in which versions. By forcing users to also
employ this flag to enable the trial behavior, there's no way that they
can inadvertently come to depend on a temporary behavior and be
surprised if it changes later.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-19 17:21:09 -07:00
Larry Gritz 76451af098 fmath.h: re-inline convert_type() half varieties (#5130)
A few years ago, in PR #3301, we made a big effort to remove Imath types
as much as possible from the public APIs. Somehow, as part of that
refactor, we ended up with just the half-varieties of fmath.h's
convert_types() templates actually being implemented in fmath.cpp and
only declared (by default) in fmath.h. I'm honestly not sure why I did
that now, and the PR doesn't explain that particular point.

But that sets up a potential link incompatibility if OIIO used a
different release of Imath than the use is using when calling that
utility function.

So this PR makes it fully inline again, so the Imath version the
downstream package uses just doesn't need to match what was found/used
at the time that OIIO was built.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-18 12:32:50 -07:00
Peter Kovář 235e364996 deps: Update to the R3D SDK version 9.2.0 (#5148)
Only version has been changed and one line removed.

---------

Signed-off-by: Peter Kovář <peter.kovar@reflexion.tv>
2026-04-18 12:31:46 -07:00
Larry Gritz 94ec2deec3 fix(dds): corruption protection: validate resolution + overflow care (#5131)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-15 16:07:22 -07:00
Larry Gritz ec92d1eb71 fix(sgi): Better detection of corrupt RLE info that could overflow (#5141)
* Change DASSERTs (which were correct, but did not enforce anything in
release builds) into real checks that will return error messages and
flags if the corruptions are found.
* Switch to using spans for extra checks if anything goes wrong.
* Use check_open.
* Check that various header items are valid enum values.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-15 12:26:26 -07:00
Larry Gritz 6d02579559 fix: incorrect test for when it's safe to use hwy code path (#5138)
We didn't have a complete enough test for when it was safe to hwy on a
buffer. Encapsulate in new function HwySupports so that all the logic
lives in one place and doesn't have to be replicated everywhere. The
more complete test now checks for:

- contiguous scanlines
- right number of channels (only indirectly checked)
- 2D image, not 3D volume (not previously checked)
- pixel data window fully contains the ROI (not previously checked)
- correct data type (should always be true, but was not checked)

This eliminates some test failures, which were specifically cases
where the ROI being operated on did not overlap with the data area of
the ImageBufs, and the Highway related code did not handle those in
the way that the old ImageBuf::Iterator transparently handled running
off the edge and various wrap modes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-15 11:34:36 -07:00
Larry Gritz b56d00dead int: Some minor cleanup of the hwy related code (#5137)
* imageio.h: Document 'enable_hwy' global option.

* imagebufalgo_hwy_pvt.h: Remove RoiNChannels -- it's the same as
roi.nchannels()

* Macros: we can simply test OIIO_USE_HWY, since it's always defined;
there is no need to also test defined(OIIO_USE_HWY).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-14 21:46:33 -07:00
Larry Gritz 4f40fcf6f6 testing: hwy testing strategies (#5136)
1. Some tests are repeated, run once with hwy off and once with hwy on.
The "on" versions append ".hwy" to the test name and set the
OPENIMAGEIO_ENABLE_HWY=1 environment variable to force it on while
running the test. The advantage to this approach is that the test itself
doesn't need to change at all, we just run it separately in each mode.

In this PR, I do this with oiiotool, oiiotool-xform, and
docs-examples-cpp.

For now, while hwy is not enabled by default, it's doing these extra
things to enable hwy. Eventually, if/when hwy is enabled by default,
we'll flip the sense and use the env variable to turn it off.

2. Some tests do certain operations both ways when hwy support was
enabled at build time. This is more convenient for certain unit test
executables, where perhaps we want to benchmark both ways and have those
show up right next to each other within the run.

   In this PR, I do this with the imagebufalgo_test unit test.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-14 21:46:16 -07:00
Larry Gritz fb9a36aa56 ImageBuf: contiguous_scanline() + fixes to internal span (#5135)
Add a new ImageBuf method: `contiguous_scanline()`, which reveals if
each scanline is contiguous in the ImageBuf's internal memory (no
padding or unusual spacing between channels or pixels). It's analogous
to the existing `contiguous()`, but the latter also tests contiguity in
y and z.

Additional internal fixes:

* Always and only set m_bufspan via calls to `set_bufspan()`, so it's
consistent. In particular, it ensures that we correctly set the channel
size, which some call sites previously did not do correctly for untyped
"byte" buffers.

* Re-evaluate the contiguous flags whenever resetting m_bufspan.

* contiguous() calls need to call validate_pixels().

An IB from a file that hasn't been read yet into memory yet isn't
considered contiguous. But once it's read, it will be (if it's got the
strides right, etc.). So when somebody asks if it's contiguous, what
does that mean? They are asking because they are about to do something
that requires memory contiguity (meaning, it needs to be IN memory),
just like if they call localpixels(). So just like localpixels(), we
need to call validate_pixels() to assure that if the pixels are destined
for the local buffer, it's done now if not yet.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-14 21:45:58 -07:00
Larry Gritz 84e04acd2b testing: Fix ref output for jpeg-corrupt tet (#5144)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-14 10:33:20 -07:00
Larry Gritz 816ab93a3a fix(jpeg): be a little more flexible with corrupt IPTC blocks (#5140)
Recent PR #5081 added more detection of corruptions in (among other
places) the IPTC blocks in a JPEG file.

But we maybe got a little too aggressive, since there appear to be some
jpg files out there that have strange (maybe technically incorrect?)
IPTC blocks but are otherwise fine.

Anyway, I noticed that for ICC profiles in JPEG files, we use the OIIO
attribute "imageinput:strict" to decide whether a localized corruption
in the ICC profile ONLY causes the ICC profile to be skipped (reading
the pixels just fine), or a stricter mode where anything suspicious is
grounds to stop reading the file entirely and declare it corrupt.

So in this patch, I'm using the same control for the analogous purpose
when reading the IPTC blocks. By default, just skip the IPTC block if we
don't know how to decode it. But if in strict mode, make a full error
that will cause us to stop reading the file.

With this change, I needed to update the jpeg-corrupt test to force
strict node, and update some some ref outputs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-13 11:06:47 -07:00
Matt Van HornandLarry Gritz c9662327cd api: Add OIIO_NODISCARD to ImageInput create/open/read methods (#5111)
## Summary

Adds `OIIO_NODISCARD` to `ImageInput::create()`, `open()`,
`read_image()`, and `read_scanlines()` methods. Callers ignoring return
values from these methods now get a compiler warning.

## Why this matters

As noted in #4781, it's easy to accidentally ignore the bool return from
`read_image()` or `open()`. These methods return false on failure, and
silently proceeding with bad data leads to hard-to-debug issues.
`create()` returns a unique_ptr that should never be discarded.

## Changes

- `src/include/OpenImageIO/imageio.h`: Added `OIIO_NODISCARD` to 14
method declarations in the `ImageInput` class, covering `create()` (2
overloads), `open()` (4 overloads), `read_image()` (4 overloads), and
`read_scanlines()` (4 overloads).

Scoped to `ImageInput` only per @lgritz's guidance to start with one
class and iterate.

## Testing

- Header compiles (syntax validated)
- No behavioral changes - annotation only

Partial fix for #4781

Assisted-by: Claude Code / Claude Opus 4.6 (1M context) 

Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2026-04-12 16:42:44 -07:00
Larry Gritz f518355bb9 build: Minor debugging fixes to dependency_utils (#5128)
* Have build_dependency_with_cmake print the error message if the git
repo can't be cloned.
* Fix mis-quoted env variable in status message.
* Improve grammar of status message.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-11 10:58:18 -07:00
Larry Gritz d55f7b10c6 int: No longer force disabling of fmt exceptions (#5118)
I think forcing fmt to disable exceptions is probably doing more harm
than good, probably does not work as expected for apps that use fmt
elsewhere (when we first started using fmt, it was not super popular, so
we weren't really concerned about how we might conflict with other
libraries in the same app), and disabling exceptions makes it behave
differently than std::format/print.

So let's stop doing this and see what happens! (In main.)

Also, declutter by removing the FMT_USE_GRISU definition, which was only
meaningful for very old fmt versions that are older than our minimum
supported version now.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-10 21:17:01 -07:00
Larry Gritz 201fecbff6 int: Remove deprecated std::codecvt from strutil.cpp internals (#5107)
For the sake of Windows' need for wstring filenames, we do some
utf8<->utf16 conversion in strutil.cpp. That has always used the
std::codecvt set of functions, but they have been deprecated beginning
in C++17 and will be removed entirely in C++26, so their days are
numbered and we already have to suppress warnings to get the compiler to
shut up about it.

Assisted-by: Claude Code / Opus 4.6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-10 21:16:22 -07:00
Larry Gritz 5b481fd914 ci: Unbreak Mac CI by adding jpeg-xl install (#5139)
It must have been among the homebrew packages in the base Mac
installation on GHA, until just a couple days ago?

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-09 23:14:19 -07:00
Larry Gritz 70c6fc1782 fix(dds): Fix broken reading of volumetric DDS files by emulating tiles (#5133)
Fixes #5132.

Reading DDS volumetric files used to work, but was broken by PR #4669
last year, the one where we added all the span-oriented API calls.

At that time, I did not realize/remember that DDS files could be
volumetric, observed that all the (other) volumetric files only
supported tiled access, and so in the course of that API refactor, I
removed the z parameter from the new read_scanlines API.

I don't want to break ABI compatibility again for this, so the solution
I came up with in this PR is just to make DDS volume files report
themselves as "tiled", with each tile being (width x 1 x 1), i.e. what
used to be one scanline, and it all just works out.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-07 17:38:42 -07:00
Larry Gritz 19cbc6d3ea build: Fixes for gcc-15, add to CI, update INSTALL.md versions (#5126)
Fix warnings for gcc15:

* Suppress warnings about deprecated utf conversion (already suppressed
for clang, needed to do so for gcc >= 15 as well).
* Rename some internal methods that gcc 15 was warning were shadowing
the names of virtual methods.

Also took the opportunity to update INSTALL.md to reflect the latest
dependency versions that we have tested against.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-07 15:12:39 -07:00
Vlad Erium 556198f990 Add Highway SIMD acceleration to ImageBufAlgo [add, sub, mul, div, mad, resample] (#4994)
Optional SIMD optimizations for selected ImageBufAlgo operations using
the Google Highway library: 

* add/sub
* mul/div
* mad
* resample

Adds CMake and build system support, new implementation helpers, and
developer documentation.

This is currently off by default, needing to be enabled at build time both by
setting CMake variable `OIIO_USE_HWY` to ON *and* having the Highway
library installed and able to be found (we do not yet auto-build it). And even
if enabled at build time, currently it is only enabled at runtime by setting the
environment variable `OPENIMAGEIO_ENABLE_HWY=1` *or* setting the
global attribute `OIIO::attribute("enable_hwy", 1)`. We hope that the defaults
might be changed to fully enabled by the time we release OIIO 3.2.

Assisted by: Opus4.5 and Codex GPT5.2

_Code mostly wrote using frontier Opus4.5 and Codex GPT5.2 High models
with a strict rules._

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2026-04-07 10:04:31 -07:00
Larry Gritz 59a3201574 ci: Turn off fail-fast for the wheel workflow (#5123)
We have enough spurious failures that I don't want all of the variants
in a job matrix to fail just because one goes wrong.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-06 14:56:13 -07:00
Larry Gritz c75e31faa1 testing: speed up exr-decreasingy test (#5121)
This test did more than was really necessary. It resized a small image
(twice) to get big images, but the contents didn't matter, so just using
a gradient is good enough. Also, we can check results just by using the
hash of the image contents, don't need to do extra idiff calls.

It's barely noticeable on a regular release build, since the whole test
was only a couple seconds on my laptop and maybe 15 seconds on the GH
runners. But for the CI "sanitize" test, this cuts about 30 seconds from
this test! Every little bit helps, the sanitize tests are usually the
last to complete in a CI run.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-04 16:28:42 -07:00
Qi-fly ac3a9e71cf fix: encode_xmp() for aliased metadata names such as IPTC:Rating / xmp:Rating (#5108)
This PR fixes an inconsistency in OIIO's XMP write path that prevents
some metadata fields from being emitted into XMP, even when they are
present in `ImageSpec::extra_attribs`.

**Problem**

`encode_xmp()` gathers attributes through `gather_xmp_attribs()`, which
currently does:

```cpp
const XMPtag* tag = xmp_tagmap_ref().find(p.name());
if (tag) {
    if (!Strutil::iequals(p.name(), tag->oiioname))
        continue;
    ...
}
```

At the same time, `xmp_tagmap_ref()` builds its lookup map using
`xmpname`, not `oiioname`.

This becomes self-contradictory for mappings where the XMP name and the
OIIO-facing attribute name differ.

A concrete example from `xmp.cpp` is:

```cpp
{ "xmp:Rating", "IPTC:Rating", TypeDesc::INT, 0 },
```

With the current implementation:

- If the spec contains `IPTC:Rating`, lookup fails because the map is
keyed by `xmpname`.
- If the spec contains `Xmp:Rating` / `xmp:Rating`, lookup succeeds, but
the attribute is then rejected because it does not match `oiioname`.

As a result, `encode_xmp()` does not emit the rating field, and format
writers that rely on `encode_xmp()` (for example JPEG and TIFF) may fail
to write an XMP packet for such metadata.

**Fix**

This patch makes the XMP tag lookup accept both spellings:

- the XMP name (`xmpname`)
- the OIIO metadata name (`oiioname`)

and allows `gather_xmp_attribs()` to accept either as a valid match.

This preserves existing behavior for fields where `xmpname == oiioname`,
while fixing aliased mappings such as rating.

**Why this is correct**

OIIO already models these fields as explicit mappings between an XMP
name and an OIIO attribute name. The write-side gather logic should
therefore be able to consume metadata stored under either spelling.

Without this, some entries in the XMP mapping table are not actually
encodable.

**Observed impact**

In a local reproduction using JPEG output:

- `IPTC:Rating` was present in `ImageSpec::extra_attribs`
- the JPEG writer called `encode_xmp()`
- no XMP APP1 segment was written to the final file

This was traced back to the lookup/match mismatch described above.

**Testing**

I recommend adding tests that cover both direct XMP naming and aliased
OIIO naming.

1. Unit test: `IPTC:Rating` is encoded as XMP rating

```cpp
ImageSpec spec(1, 1, 3, TypeDesc::UINT8);
spec.attribute("IPTC:Rating", 4);
std::string xmp = encode_xmp(spec, true);
CHECK(xmp.find("xmp:Rating=\"4\"") != std::string::npos);
```

2. Unit test: `xmp:Rating` is encoded as XMP rating

```cpp
ImageSpec spec(1, 1, 3, TypeDesc::UINT8);
spec.attribute("xmp:Rating", 4);
std::string xmp = encode_xmp(spec, true);
CHECK(xmp.find("xmp:Rating=\"4\"") != std::string::npos);
```

3. Optional integration test: JPEG writer emits an XMP APP1 segment when
rating is present

- Create a small image
- Add `IPTC:Rating` or `xmp:Rating`
- Write JPEG
- Inspect the output bytes for the standard XMP APP1 namespace header:
  `http://ns.adobe.com/xap/1.0/\0`

This verifies the full `encode_xmp()` -> JPEG writer path, not just the
XML generator.

**Notes**
This patch is intentionally narrow:
- it does not change the XMP mapping table itself
- it only fixes how mapped attributes are discovered during XMP
generation

Signed-off-by: Qi-fly <72260719+Qi-fly@users.noreply.github.com>
2026-04-04 16:25:32 -07:00
Asish Kumar 09a0352137 build(win): only pass /MANIFEST:NO to MSVC (#5129)
Fixes #5124

`fancy_add_executable()` currently adds the Windows manifest resource
file for all
`WIN32` builds, but it also unconditionally passes `/MANIFEST:NO` to the
linker.
That switch is MSVC-specific, so MinGW ends up forwarding it to `ld` as
a path
and the executable link fails.

This change keeps embedding `src/windows/oiio_exe.rc` for all Windows
toolchains,
but only adds `/MANIFEST:NO` when the build is using MSVC.

That preserves the intended long-path manifest behavior from #5066 while
letting
MinGW link the Windows executables again.

Assisted-by: Codex / GPT-5

Tests:

- Ran a targeted CMake smoke test that configures a dummy executable
with
  `WIN32=TRUE,MSVC=TRUE` and verified that `/MANIFEST:NO` is present in
  `LINK_OPTIONS` and the `.rc` file is attached as a source.
- Ran the same smoke test with `WIN32=TRUE,MSVC=FALSE` and verified that
the
  `.rc` file is still attached but `/MANIFEST:NO` is not added.
- I could not run an actual MinGW build locally in this environment
because a
  MinGW toolchain is not installed here.

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
2026-04-04 16:20:27 -07:00
Larry Gritz 735572810e ci: fix breakage because fmtlib changed 'master' to 'main' (#5127)
fmtlib renamed its "master" branch to "main" yesterday. So now our
"bleeding edge" test that requests fmt "master" fails.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-03 18:40:59 -07:00
Larry Gritz 4e9172924a fix(ustring): protect against idempotent rehash upon collision (#5090)
Some fuzzing stumbled across a very interesting edge case in the
rehashing logic of ustring internals:

If the initial hash location of a newly ustring-ized string is already
occupied, it rehashes. But we never considered what happens if it ends
up rehashing to the same slot! And in fact, that can happen if the true
hash is 0 (I'm not sure if it can/does for any other value). And we may
have thought that the only string that would ever hash to 0 is the empty
string (which is 0 hash by design, and doesn't need to rehash because
the table is seeded with that entry already in its correct slot).

So anyway, if there was some other string that happened to hash to 0, it
would get caught in an infinite loop of rehashing but never finding a
free slot, because it keeps rehashing to the very same occupied slot.

And would you believe that there IS such a string, and it is this one:

"\t\n\n\t\301\350`O\217c85?\202\200\251r|}\304\351\2517\337K'\217C\240"

(unprintable chars expressed as escaped octal values)

The crux of this patch is to notice when the old and new hash bit
pattern has not changed, and bump it by 7 (a prime number, so it should
not land on the same location again until every slot in the bin has been
exhausted).

Solution entirely from my own human brain, in case you're wondering.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-04-01 16:47:52 -07:00
Larry Gritz 9c7b98c88c CHANGES updates
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-31 17:31:21 -07:00
Larry Gritz d66f87c839 docs: Various updates related to the AI policy (#5116)
I was reminded by Eric Enderton that we should mention and cross
reference the recently-added AI policy docs in other places, since it
can easily be overlooked now, buried in the docs directory.

* Mention it in the pull request template's checklist.
* In the CONTRIBUTING guide.
* Briefly mention in the main README in the list of important
documentation for developers.
* A few very minor touch-ups and wordsmithing in other areas, no
substantive changes.

Also, responding to comments at the OSL TSC meeting this week, I added
a brief section explaining that we don't have any specific guidance for
how AI tools should or shouldn't be used for "artistically creative"
work, since this project repo doesn't really house such things. This
is mostly for the benefit of other projects that may use our policy
document as inspiration, to warn them that they may have issues that
need policy guidance but that we do not address.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-31 11:37:59 -07:00
Larry Gritz 144143df6e ci: update container versions, move 3 variants from 2022 to Ubuntu (#5119)
TL;DR:
* Bump ASWF containers to the latest versions for their years.
* Move the "oldest" and "hobbled" tests off the 2022 containers
entirely, do as close as possible to equivalent on Unbuntu.

Detailed explanation follows:

First of all, bump to the latest ASWF docker containers for each year.
We had been locking down, but hadn't bumped to the latest for a while.
(Exception: leave the sanitizer test where it is -- the newer containers
have additional checks that are catching UB that I am tracking down
separately.)

Also, we are trying to reduce the surface area of the CentOS 7-based
2022 aswf-docker containers, which are getting long in the tooth, cannot
upgrade to the latest "actions" (because of a tricky interplay between
runner configuration, node version the actions require, and glibc on the
old containers), and may have a limited time that they will continue
working.

In most film studios, CentOS is long gone or taking its last breaths, so
being able to support and test on 2022 era dependencies and OS distros
is of dwindling relevance. We do, however, want to keep testing versus
the oldest supported versions we can muster for many major dependencies.

So to this end, this PR also does the following:

* Move three tests from running in the 2022 containers to just running
on bare Ubutu and by hook or by crook using the right dependencies:
- the "oldest" versions we claim to support for as much of the toolchain
toolchain and dependencies as is easily achievable, built with gcc
  - and the same, built with clang
- the "hobbled" test, which is similar to the "oldest" test but with as
many of the optional dependencies missing or disabled, to make sure we
really do build with only required dependencies (this also is the test
build for no SIMD use)
* Keep two last tests running on 2022 containers, these are only for the
purpose of testing "pure" CentOS VFX Platform 2022 compliance for just a
bit longer.
* A few minor related touch-ups necessary to force some older
dependencies on the bare Ubuntu runner.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-30 19:28:26 -07:00
Larry Gritz b7580f4a64 fix(IBA): Handle offset data windows in fillholes_pushpull (#5105)
Fixes #4942

IBA::fillholes_pushpull() produced incorrect results when the source
image had a non-zero data window origin (such as exr files with
overscan).

Two interrelated bugs:

1. The paste() call double-applied the data window offset. paste() maps
source pixel (0,0) to destination (xbegin,ybegin), but since the source
data starts at (x,y), passing (x,y) as the offset shifted every pixel by
an extra (x,y). Pixels in the negative-coordinate region landed outside
the destination buffer and were silently lost.

2. The top pyramid level preserved the original display/full window
while all smaller levels had full=data at (0,0). Since resize() uses the
full window for coordinate mapping, it only sampled the display window
portion of the top level, losing all overscan data.

Fix by shifting the top pyramid level to origin (0,0) with full=data,
making all levels coordinate-consistent. The initial paste translates
source pixels into the origin-based pyramid, and the final paste (which
was already using src origin offsets) correctly translates back.

Add test cases in testsuite/oiiotool for fillholes with an offset data
window, and an offset display window, to ensure that both cases work.

Also, for the existing fillholes related test, move the source image
from ref (never should have been there) to src.

Assisted-by: Claude Code / claude-opus-4-6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-30 10:47:58 -07:00
Larry Gritz 0b93c3ef4c fix: fix possible fmt exceptions where we might have passed null string (#5115)
I've heard occasional reports of uncaught exceptions in print
statements. I haven't caught it in the act yet, but one set of reports
involved the following output:

OpenImageIO/detail/fmt/format-inl.h:40: assertion failed: string pointer
is null

So I'm proactively trying to find places that might be passing a null as
a string. I'm just guessing here, but these are plausible candidates.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-29 20:40:30 -07:00
Larry Gritz 1dff182d2d ci: Fix UB in exif parse, revert PR #5113, move sanitizer test to 2026 (#5120)
PR #5113 didn't fix all the problems after all. Revert it, because it's
not needed after the real solution.

The real solution is to mark tiff_datatype_to_typedesc() with
OIIO_NO_SANITIZE_UNDEFINED to have the sanitizer skip it. What's
happening is that corrupted files end up with a value in the data type
field that is not a valid value of the TIFFDataType enum, and ubsan is
flagging that. BUT... `tiff_datatype_to_typedesc()` itself is actually
safe in that circumstance, because it's got a 'default` clause that
handles the unknown enum values just fine.

In contrast, I've been running around in circles trying to find
something to do *within* that function to make it "safe" (by the
sanitizer's reckoning), and trying to check for valid values prior to
converting to a TIFFDataType is just too hard, partly because there are
places where that conversion happens unchecked inside libtiff (C
language, just does a cast), so it comes to us as a TIFFDataType already
with an invalid value. It's easier to just mark the whole function as
being ignored by ubsan, given that we can see by inspection that it has
totally deterministic and desired behavior for the illegal values.

Making this spurious ubsan error disappear allows us to upgrade the
container version we are using for the "sanitizer" CI test variant, so
we also push that all the way up to 2026.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-29 20:36:32 -07:00
Larry Gritz 48181b2351 fix: Fix UB in exif parsing of corrupt data (#5113)
Corrupted exif data could put a value in a "tiff data type" field that
is not one of the valid enum values. That's UB. Identified by running
the sanitizer with a newer clang than we usually do.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-28 15:35:47 -07:00
Larry Gritz b5ebc71d61 docs: Fix misstatement about oiiotool --if (#5102)
There is no `--then`, you just say `--if condition commands...`

Fixes #5068

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-27 17:15:15 -07:00
Larry Gritz 46d0b4ef7e ci: Yet another tiff-misc ref output (#5112)
When reading corrupt files, sometimes there are a lot of different
potential error messages reported by libtiff depending on the exact
version and platform, and which corruption it encounters or notices
first. So we tend to have to add new refs frequently as libtiff changes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-27 17:10:29 -07:00
Larry Gritz df91ddd0f6 fix: enhanced exception safety for our use of OpenColorIO (#5114)
https://opencolorio.readthedocs.io/en/latest/api/exceptions.html

"All functions in the Config class can potentially throw this
exception."

Oh dear, that is not something I previously fully understood the
implications of. This patch makes extra sure that there's try/catch
around every call to OCIO::Config methods. Some previously did, but some
that were less obvious that they might throw did not try/catch. No
matter how benign they look, I'm taking no chances now.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-27 09:40:30 -07:00
Larry Gritz e399c8c041 fix: catch exceptions in print-uncaught-messages destructor (#5103)
Fixes #5063

In that issue, it was reported that the printing of any unretrieved
error messages upon destruction of an ImageBuf could itself have an
exception (including if it, for some reason, could not correctly fwrite
the output). And if that is the case, it could terminate the app.

So for safety, this patch encloses this particular print statement in a
try/catch. And also found another in ErrorHolder in the internals of
Strutil, which is used for "global" errors issued to OIIO::errorfmt().

Assisted-by: Claude Code / Opus 4.6

I did the fix in ImageBuf, then Claude found the other spot in
ErrorHolder that also needed the fix.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-25 00:16:49 -07:00
Larry Gritz 10533de026 fix: Fix UB-sanitizer warning about alignment (#5097)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-25 00:02:10 -07:00
Larry Gritz 4413110dd5 ci: Push to newest actions except jobs needing old containers (#5110)
Rather than use old actions across the board for a handful of job
variants that need old containers, use the obsolete actions only where
really needed. This involves duplicating the some steps within the
workflow, and choosing whether to use old or new based on job. We'll get
rid of the "old" versions when we retire the 2022 containers that
require them.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-24 17:34:52 -07:00
Larry Gritz 1afbdb439a build: Include idiff in the python wheels we build (#5104)
Fixes #5062

This was a suggestion for the sake of helping OpenUSD.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-23 16:48:49 -07:00
Larry Gritz 48ae402002 admin: Draft policy on use of AI coding assistants (#5072)
Summary of our core values:
- Human always in the loop and is the responsible party.
- You're still on the hook for fully understanding and standing behind what you submit.
- Interact with the project and community yourself, not by agent.
- Disclose what tools you used and how. At the very least, have an `Assisted-by TOOL / MODEL` line.
- Don't waste maintainer time with low quality PRs.
- Try to reserve the curated Dev Days and "Good First Issues" tags for human learning.


---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-23 16:47:17 -07:00
Larry Gritz 6145def173 fix(jpeg2000): Suppress leak when reading with OpenJPH (#5098)
The jph_infile class itself did not change, it just moved up in the file
to be defined before it was used. It's the use of the persistent
unique_ptr that fixes the leak.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-23 13:49:01 -07:00
Larry Gritz ab3905a7e8 fix(rla): lots of additional validity checking and safety (#5094)
* Validity-check resolution of RLA files with check_open. RLA file
headers contain int16_t values for left & right (and top/bottom) window
coordinate, leading to a maximum resolution of 2^16-1.

* Fix potential bug with sign extension in RLE decoding -- if a signed
char is -128, negating it can't make signed char 128 (no such thing), so
must widen the var to an int.

* Fix potential bug by detecting when the number of matte or auxiliary
bits is 0, but the number of matte or aux channels, respectively, is
not.

* Better bounds checking in decode_channel_group. We did the checks
before, but after some accesses that would have been out of bounds! Move
the checks earlier than all the accesses. It actually looks like was the
result of a cut and paste error long ago.

* More care in read_native_scanline for checking valid scanline numbers,
offset into m_sot, and check whether ioseek succeeded (i.e. whether the
offsets loaded from the file are within the range of the size of the
file).

Code and fixes all are from my own brain, but some of the analysis of
which spots have bounds issues were identified in part by conversation
with Claude Code Opus 4.6.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-23 12:38:05 -07:00
Larry Gritz e014c1e28a fix: ImageSpec::metadata_val improved safety (#5096)
If certain camera metadata was mangled and or otherwise wasn't one of
the known metadata names, it could run off the end of the list and
dereference a null pointer.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-23 11:44:48 -07:00
Larry Gritz d21d027663 deps: Need new ref output for ffmpeg 8.1 (#5099)
A visual inspection shows that it works fine and the images are a visual
match. But some numeric changes in ffmpeg 8.1 make it need new hashes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-21 10:09:48 -07:00
Larry Gritz dacb02ac07 fix(ico): Various validity checks and error handling for corruptions (#5088)
1. Validity check the resolution/channels.

2. Also, in png_pvt.h's `read_info()`, found a spot where errors were
being sent to the global error reporter instead of to the PNG reader's
own error store. (It is relevant to this PR because that is called by
the ICO code for certain ico files that are really using PNG encoding.)

3. Handle scanline width that's not 8 pixel multiple without running
over buffer limits.

4. Guard against possible palette array overrun for 4bpp case. The 1-
and 8-bpp palette cases already had computed the palette index and
checked for being in range before accessing the array. But the 4-bpp
case did not!

Items 1 & 2 were entirely LG. Items 3 & 4 were identified and fixed with
the assistance of Claude Code / Opus 4.6 -- it was really helpful! I'm
honestly not sure if it saved me 5 hours or closer to 5 minutes, but
even if short, it would not have been at all fun to trace through by
hand to find a subtle case that we previously forgot to check.

Assisted-by: Claude Opus 4.6

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-20 15:58:44 -07:00
Larry Gritz 76e6677d98 build: Fix broken Mac wheel building by specifying compiler path (#5101)
This had been biting our wheel building for a couple weeks before it hit
the regular CI jobs, I guess? And I didn't even know it or fully
understand the cause. But it's the same solution as the other fix from
yesterday: explicitly specify the path to the xcode version of clang, so
it doesn't accidentally pick up the homebrew copy of a different clang.
(Either is ok, but mixing and matching is no good.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-20 13:08:21 -07:00
Larry Gritz 09461a23fe ci: Try to fix broken Mac CI with full compiler paths to Apple clang (#5100)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-19 19:56:35 -07:00
Larry Gritz b4541ec785 ci: Bump GitHub Actions to latest versions (#5078)
Update action version pins to their latest releases, referenced by full
commit hash with version tag as a comment. Except for a couple, as noted
below.

| Action                              | Old        | New        |
|-------------------------------------|------------|------------|
| actions/checkout                    | v4.2.2     | v4.3.0     |
| actions/upload-artifact             | v4.5.0     | v7.0.0     |
| actions/download-artifact           | v4.1.8     | v8.0.0     |
| actions/setup-python                | v5.2.0     | v6.2.0     |
| pypa/cibuildwheel                   | v3.2.1     | v3.4.0     |
| pypa/gh-action-pypi-publish         | release/v1 | v1.13.0    |
| sonarsource/sonarqube-scan-action   | v6.0.0     | v7.0.0     |
| ossf/scorecard-action               | v2.3.1     | v2.4.3     |
| github/codeql-action/upload-sarif   | v2.3.6     | v3.32.6    |
| sigstore/gh-action-sigstore-python  | v3.0.0     | v3.2.0     |
| jmertic/slack-release-notifier      | main       | 0.1        |

Note that all are locked down to hashes now, including a couple which
hadn't been previously.

We wish we could upgrade actions/checkout all the way to the latest
versions. But in both cases, they require nodejs 24, which in turn needs
a glibc that's too new for our ASWF VFX Platform 2022 containers. So
we're going to have to keep them locked to old versions until we're
ready to retire the 2022 containers, which we hope is soon. The checkout
action is upgraded from 4.2.2 to 4.3.0 only, intead of the latest 6.0.2,
and the cache actions had to remain on 4.3.0 as it was before, instead
of upgrading to the latest, 5.0.3.

The initial gruntwork of tracking down the latest versions and upgrading
was done by Claude Code using the Sonnet 4.6 model using the following
prompt:
```
For all the workflows in @.github/workflows/ , check every action
version reference to see if it is using the latest release
version. Upgrade any that are not the latest. Be sure to refer to the
action by full hash, not version number (but put the corresponding
version number as a comment).
```

That upgraded everything possible without me needing to track down each
action myself, though it was only a partial solution: the newest actions
failed on the old containers (as noted above) and it took me a while to
sort out by hand which ones needed to be held back to run on the old
containers. So Claude helped with the first 80% and then I did the
remaining 80% of the work.

Assisted-By: Claude Sonnet 4.6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-18 16:43:13 -07:00
Brecht Van Lommel ad0abdad52 fix(heif): Invalid read writing 8bit and dimensions not a multiple of 64 (#5095)
Don't copy from memory using the stride, as this can get padded and read
past the end of the input pixel data. The 10 and 12 bit paths were
correct.

Test added, this only failed with address sanitizer.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-03-18 10:47:34 -07:00
Larry Gritz e109d8216f cleanup: Add .cache to .gitignore (#5092)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-18 10:04:07 -07:00
Larry Gritz cb87a4b557 docs: Fix typos and incorrect attribute name in a comment (#5093)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-17 22:53:51 -07:00
Larry Gritz d3aa1658fc fix(psd): fixes against corrupt files with better validation (#5089)
1. Validate channel count against color mode to prevent heap buffer
   overflow.

2. Corrupted PSD files can declare a color mode (e.g. RGB, needing 3
   channels) with transparency (needing +1) but report fewer channels
   in the header.  This caused an out-of-bounds read in
   read_native_scanline when setup() built channel pointer arrays
   using mode_channel_count, which exceeded the actual
   m_image_data.channel_info size.

3. Additional buffer overflow protection, error checking and
propagation.

4. Avoid leak by properly freeing z_stream resources in decompress_zip.

Used Claude Code / Opus 4.6 to help narrow down and confirm the bugs 1
and 2.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-17 16:39:17 -07:00
Larry Gritz 7d16832211 fix(tiff): check for invalid bit depth for palette images (#5091)
Reading the TIFF 6.0 spec, on p. 23, it sure looks like palette images
can only be 4 or 8 bits per sample. But the libtiff set of test images
indeed has 2, 4, 8, and yes, 16 bps palette images among the examples.
So I think we should support up to 16, since we might encounter it in
the wild, but no higher.

We didn't previously check for this, though, and that could lead to
accepting invalid TIFF files, and then potentially have problems with
`(1 << m_bitspersample)` which appears several times. That of course is
safe if m_bitspersample can't be > 16.

Also check and proper error for a file that has a bitspersample that is
not one of the valid choices (1, 2, 4, 6, 8, 10, 12, 14, 16, 24, 32,
64), and proper errors for if the sampleformat was an unknown value or
was not a valid value for the number of bits per sample.

Note that this changes the reference output of some tests because the
new checks can alter the first error discovered in a corrupt file.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-17 16:05:46 -07:00
Larry Gritz 8abf94e4bd fix(bmp): use check_open to guard against corrupt resolutions (#5086)
Also change the x and y counters to uint64_t to prevent any possible
overflow as it's computing offsets.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 22:35:00 -07:00
Larry Gritz 95b339b3ef ci: Speed up slow benchmarks for debug and sanitizer CI tests (#5077)
Be even more aggressive for the runs that are both debug mode (including
sanitizers) and a CI run. Speeds up the slowest GHA test runs. Should
not affect ordinary builds.

This shaves about 8 minutes off the long "sanitizer" run, which is often
the last job to finish in our CI workflows.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 22:33:59 -07:00
Larry Gritz 5579f53eae build: Improve security by pinning auto-build dependencies by hash (#5076)
The files that match the pattern "src/cmake/build_<dependency>.cmake"
are all similar and each one is called by our build system if a
dependency is not found, to download and built it locally to be
incorporated into our build. One example is src/cmake/build_TIFF.cmake.

Within these files, the version to be retrieved is determined by a pair
of lines such as
```
set_cache (TIFF_BUILD_VERSION 4.7.1 "TIFF version for local builds")
set_cache (TIFF_GIT_TAG "v${TIFF_BUILD_VERSION}" "Git branch or tag")
```

The tag is passed to `build_dependency_with_cmake` with the `GIT_TAG`
argument. There is also an optional `GIT_COMMIT` argument, that we
usually do not use (previously, only needed if we wanted to build from a
commit that didn't have a version tag).

But it turns out that it's probably not safe to blindly retrieve a tag,
in case the dependency's repo has been hijacked and the tag reset to
point to a malicious commit.

So here is how to address this:

- `build_dependency_with_cmake` modifies its internal logic:
- If only the GIT_COMMIT is passed and GIT_TAG is blank, use the commit.
- If both GIT_COMMIT and GIT_TAG are passed, check out the tag but
verify that it is the commit specified, and if not, then consider it an
error and do not proceed with building the dependency.
- If only GIT_TAG is passed and not GIT_COMMIT, warn about the potential
safety problem.
- But as a special option for dangerous tasks, an override called
OpenImageIO_DEPENDENCY_BUILD_ALLOW_UNVERIFIED_TAGS allows an unverified
git tag to be checked out. This is how we make the "bleeding edge" test
still build against dependecy main/masters.

- For each of the `build_<dependency>.cmake` files, change it as
follows:
- Determine the commit hash of the specified version by checking the
repository.
- Add a line setting `<dependency>_GIT_COMMIT` to the corresponding
hash.
  - Pass both arguments to build_dependency_with_cmake.

This patch was made with the help of Claude Code using Opus 4.6. I
started the dialog with a prompt that was substantially similar to the
description above, detailing my proposed plan.

I first suggested that if only the TAG is present, to allow it as long
as it turned out to be an immutable git release tag, but it pointed out
that (a) this requires a build-time dependency on the `gh` command line
util, (b) not all our dependencies are on GitHub (such as libtiff on
GitLab), so we modified the plan to warn in that case rather than try to
determine if it's immutable. The rest proceeded more or less as
expected, with a few rounds of back and forth and corrections.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 22:33:21 -07:00
Larry Gritz f2e6f0c4b2 fix(tiff): fix buffer overrun and make better error reporting (#5082)
Certain CMYK files (maybe only corrupt ones?) hit an edge case that
caused us to read the original 4 channels but into space for only the 3
channels we ultimately report back. Fix that logic.

Also noticed several spots where we didn't correctly report back error
messages for newer versions of libtiff. This was some kind of oversight
from long ago.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 19:12:23 -07:00
Larry Gritz 7841ab5924 fix(jpeg): Improved safety and error reporting for jpeg and iptc (#5081)
* `decide_iptc_iim()` (semi-public) : change from taking a pointer &
length to a string_view, and internal safety checks.

* `jpeg_decode_iptc()` (non-public): change from taking an unlengthed
pointer (!) to a string_view, and internal safety checks.

* JpgInput::open(): a number of extra checks for memory bounds validity.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 14:47:10 -07:00
Larry Gritz 10f4e756c8 ImageInput::check_open fixes and new checks (#5087)
* fix check_open used m_spec instead of parameter spec!
  The function advertised that its doing checks on the parameter passed
  to it, but -- oops -- it was really doing it on this->m_spec. They
  were almost always (or always always?) the same, but still. Bug.
    
* Check zero-sized images separately from nonsensical negative sizes.
  By being togther, there was some confusion about whether "noimage"
  feature should negate the error (that feature should allow
  zero-sized images, but not negative dimensions).
    
* Add new checks for the full_width/etc to also be sensible.
    
* Some other minor refactoring of check_open.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 12:39:29 -07:00
Larry Gritz f672e8648d docs: keep TextureSystem docs in sync with ImageCache (#5085)
The docs for TexturesSystem::attribute() had a summary of ImageCache
options that were accepted and passed along. Over the years, a couple
had been added to IC without being reflected in the TS docs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-15 00:35:12 -07:00
Larry Gritz ceff8075ba fix(tiff): wrong number of values passed to invert_photometric (#5083)
stripchans was multiplied in twice (it was already part of stripvals).
The error could overrun buffers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-14 23:54:33 -07:00
Pascal Lecocq 92c6c6898c fix(texture): remove legacy_texture_blur override (#5080)
The m_legacy_texture_blur flag is set in TextureSystemImpl::Init, which
overrides the default initialisation depending on the OIIO version.

In other words, the texture blur fix was always enabled, regardless of
the OIIO version.

I also updated the help description for this flag in testtex.

This fixes minor shortcomings of #5071

---------

Signed-off-by: Pascal Lecocq <pascal.lecocq@gmail.com>
2026-03-11 16:57:25 -07:00
Larry Gritz dfdb5ef502 testing: New ref output for heif no-avif case (#5079)
Encountered at work: when using certain libheif dependency builds that
can read, but not write, avif files, we needed an additional reference
output.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-11 11:18:20 -07:00
Larry Gritz 62d5d9196f ci: For security, replace some workflow substitutions with safer env substitutions (#5070)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-10 17:11:10 -07:00
Larry Gritz bea3e7599d fix(oiiotool): better type understanding with -i:ch= and other cleanup (#5056)
Background: oiiotool is pretty good at remembering the data type of the
first file it reads in a command, and ensuring that the output preserves
the same types, despite the fact that internally, it tends to keep
everything in float. (As a further reminder: -d can override the
heuristics that make this work.)

But there was an exception: when `-i` was used with the optinal modifier
`-i:ch=...` to select a subset of channels or reorder channels upon
read, the underlying call to IBA::channels would cause it to not have
that information in the "nativespec" at the right time that it was
collected.

This PR primarily ensures that the `-i:ch=...` preserves the information
about which channels had which data types, despite the channel shuffle.

Some other bits and pieces along the way:

* A new `TypeDesc::basetype_merge()` variety that take a
`cspan<TypeDesc>`.
* A new utility `TypeDesc::all_types_equal(cspan<TypeDesc>)`
* Cleanup in IBA::channels() to more correctly compute the common type
of the channel subset that you actually specify.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-10 17:09:45 -07:00
Nathan Rusch 1d940693be fix(win): Embed manifest in OIIO .exes to enable long path handling (#5066)
Adds an embedded manifest to OIIO's generated executables on Windows,
which enables "long path" awareness.

This is done via a "resource" file, with the manifest resource ID
specified. From what I've read, this is more broadly compatible with
e.g. non-MSVC build toolchains like MinGW.

The manifest file was created by building OIIO from `main`, extracting
the manifest from the resulting `oiiotool` (using the `mt` tool), and
manually adding in the XML snippet from
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry#application-manifest-updates-to-declare-long-path-capability.

Fixes #5064 

Added a new Windows-only test to validate that `oiiotool` can correctly
read long image paths.

The one executable that I have not tested is `iv`. The only reason I'm
more curious about it than others is that it is a GUI executable, so I'm
not sure if its default

---------

Signed-off-by: Nathan Rusch <nrusch@users.noreply.github.com>
2026-03-07 13:23:02 -08:00
Larry Gritz 7c4b306ab8 fix(python): Address new pybind11 float/int auto-conversion behavior (#5058)
It's not in any pybind11 tagged release yet, but in its master, a change
has been introduced that causes it to allow functions with float
paramters to automatically match int arguments. This is fatal for us, as
we have set up several cases of methods that overload on int vs float,
and with this change, the float one gets called when an int is passed.
Pybind11 docs say that the `.noconvert()` modifier on the argument will
do the trick, but I'm finding that it doesn't help for overloaded
function names.

The solution is to find these cases, change our declaration to a generic
py::object, and then sort out what type was passed with py::isinstance.
It seems to mainly affect `attribute()` style calls.

In the process, minor changes to the pybind11 auto-builder allow it to
take a git commit hash directly. Also, I took the opportunity to remove
a few reference outputs that are no longer needed because they were
python2-specific.

Meanwhile, just in case anybody had been paying attention, the problem
in pybind11 master that had caused us to temporarily stop CI testing
against master seems to have been resolved. So re-enable the bleeding
edge test to use pybind11 master (which will fail if not for this PR
here), and bump the "latest version" tests to the latest pybind11 3.0.2.

I diagnosed the problem myself, wrote the solution for one class and
verified that it solved the issues with that class. Then I used Claude
Code to make the analogous set of changes to the other classes that
needed them and I reviewed that it was correct.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-07 10:59:29 -08:00
Larry Gritz 8ab986ba81 build: Test building with clang 22.1, fix warnings uncovered (#5067)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-07 10:58:41 -08:00
Pascal Lecocq 30142ed8d3 fix(texture): fix texture overblur with st-blur parameters (#5071)
Fixes #5069

This PR fixes the texture blur overstimate reported in #5069

We provide the following changes:
* Use the mathematically correct Pythagorean form to properly adjust the
ellispse footprint with st-blur parameters.
* Add a new legacy_texture_blur attribute in TextureSystem to opt into
the fix without breaking existing renders.
* Add a new --fix-texture-blur option in testtex to enable the fix.
* Add a new texture-blurfix test.

Note: This PR has been partially edited using the Claude coding
assistant.

---------

Signed-off-by: Pascal Lecocq <pascal.lecocq@gmail.com>
2026-03-07 10:57:28 -08:00
Larry Gritz 583ace5c55 docs: fix formatting examples for version macros (#5073)
The comments that explain how to use the OIIO_MAKE_VERSION and related
macros actually were using formatting that would have been rejected by
our own clang-format settings. Change those examples so that they use
the correct formatting that woule be accepted by the project.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-07 00:58:13 -08:00
Larry Gritz f1b399b768 test: Add new ref output for tiff-misc (#5075)
I don't know why, maybe some slightly different version of libtiff
rolled out to the GHA runners, but despite no changes to our TIFF
handling in the recent past, just today we started intermittently
getting different output for this test on some of the Linux runners.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-07 00:57:14 -08:00
Aamir Raza 0156e6e951 docs: Update description for dwaCompressionLevel (#5074)
Clarify in the documentation that `openexr:dwaCompressionLevel` is a
read-only attribute and cannot be used to set the compression level on
write.

Not sure if this is an obvious change or not, but it wasn't immediately
clear if the attribute is meant to be writable.

Signed-off-by: Aamir Raza <aamir_raza@outlook.com>
2026-03-06 20:31:30 -08:00
Larry Gritz 18619b8f48 ci: On Mac Intel CI variant, don't insall openvdb, for speed (#5065)
Lately, some Mac Intel CI runs have taken forever or failed because of
timeout. It appears to be because some packages are maybe not cached
(bottled) for Intel anymore? It only happens sometimes, so maybe it
fails when the package version has just been bumped, but eventually
somebody published a pre-built bottle and then it's ok?

openvdb and its dependencies seem to be a frequent culprit. Let's just
skip them for this one soon-to-be-obosolete variant.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-06 20:11:17 -08:00
Larry GritzandCopilot 33c9999adb feat(tiff): Support GPS fields, and other metadata enhancements (#5050)
Most visible change: The TIFF reader and writer now correctly handle GPS
tags.

Fixes #5049

But along the way, and to get it completely right, a fairly extensive
refactoring of our TIFF tag handling was needed. The libtiff behavior
around different tags is extremely convoluted, and there were a bunch of
cases we either didn't handle correctly, or were dropping on the floor.
So there are also some other non-GPS tags that we missed all along but
now read properly.

Note that the support for separate IFDs for GPS tags is only supported
via the API in libtiff 4.2 and newer, so this is disabled when bulding
against older libtiff versions. (Our support of old libtiff versions
extends extraordinarily far back in time.)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-04 10:07:38 -08:00
Larry Gritz 43b8aa9cb6 ci: Add CI test for MSVS 2026 (#5060)
And some minor fixes discovered along the way.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-03-01 14:13:28 -08:00
Larry Gritz 5125c96687 Bump version after developer preview tag
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-28 15:14:58 -08:00
Larry Gritz a0940a9f1e Update CHANGES and stage for tagging 3.2.0.0-dev preview
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-28 14:28:26 -08:00
Larry Gritz fed1137c1a ci: add MacOS 26 (ARM) to the CI lineup (#5059)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-27 17:09:17 -08:00
Larry Gritz 97597da8ed fix(oiiotool): make sure oiiotool --compression does expression substitution (#5055)
`oiiotool --compression XXX` just used the argument as a literal, and
wasn't able to use expression substitution for the value. That made it
behave differently than the supposedly synonymous `--attrib compression
XXX` in the case that the argument was an expression rather than a
literal value.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-27 17:08:17 -08:00
Larry Gritz 3cefa62f9c fix: Fixups for new TypeURational after PR #5036 (#5057)
PR #5036 incidentally added a new TypeURational alias, but I neglected
to make the corresponding change on the Python bindings, to update some
of the docs, or to fully test it. This PR completes those items.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-26 05:54:30 -08:00
Larry Gritz 21dbd07a7c fix(oiiotool): -d SUBIMAGENAME.* didn't work properly (#5048)
The docs described a syntax where you could use `-d` to change the data
type of all channels in one subimage of a multi-subimage image. But it
didn't work, as revealed in #5047.

Fixes #5047

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-26 05:22:46 -08:00
Larry Gritz 3092c42b52 build: use quote to avoid error if variable is empty (#5053)
Problem identified by @irieger Ingmar Rieger, solves a problem that pops
up when Conan build provides the targets.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-26 05:06:15 -08:00
Shane Smith 3ec0b8a9d9 jxl: Extending JXL CICP support to include P3 / color primaries 12 (#5054)
I tested out the JPEG XL CICP support and noticed that color primaries
12 was not supported. This pull request is looking to extend P3 support
for color primaries 12.
Note: color primaries 11 uses the DCI white point and color primaries 12
uses the D65 white point.

The JxlPrimaries enum only covers P3 primaries as value 11 and not 12.
See,

https://github.com/libjxl/libjxl/blob/main/lib/include/jxl/color_encoding.h#L55-L75
Further code is therefore required to account for this on read and
write.

Tests for read and write of color primaries 11 and 12 were added.

Signed-off-by: Shane Smith <shane.smith@dreamworks.com>
2026-02-23 20:36:56 -08:00
Larry Gritz 0ceac85217 fix: address fmath.h warning with ispow2 (#5033)
I was seeing warnings with instantiation of the ispow2 function template
for unsigned type, where the `x >= 0` clause is meaningless. Use a
constexpr if to eliminate that pointless test for unsigned types.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-23 20:31:49 -08:00
Larry Gritz e94a27004e ci: temporarily disable python stub checking (#5061)
The CI stub generation has been broken for a few days, failing CI every
time. The checked-in stub files seem fine. Just turn off this check
until we can figure out why it is broken.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-23 12:32:49 -08:00
Larry Gritz da49cd8a12 build(deps): Raise minimum fmt library version to 9.0 (#5041)
The previous minimum, 7.0, dated from mid-2020.

We are raising now (in main / future 3.2 only) to 9.0, which dates from
mid-2022, so we're still supporting several versions and/or years back.

Because this changes minimum dependency versions, it will NOT be
backported to release branches (3.1 or earlier).

I had to remove the CI test variant for icc, because ancient icc can't
correctly build newer versions of fmt, it seems. There is a separate PR
to simply drop icc from our list of supported compilers.

If anybody wants to argue for pulling the minimum up even farther (say,
to fmt 10.0, released in 2023, so still supporting 3 years back), which
would simplify even more places, I would consider it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-21 16:31:45 -08:00
Larry Gritz d2f45dbbdd build: Remove support for deprecated Intel icc compiler (#5040)
Intel icc is deprecated and hasn't had a release for a few years. It's
holding us back, both by making us work around an ever growing number of
icc bugs and limitation that will never be fixed, as well as not
allowing us to upgrade minimum versions of certain dependencies, because
icc can't correctly compile newer versions (as an example, it cannot use
a 'fmt' library newer than the oldest we support, 7.0).

So it's time to thank icc for its service and put it on the ice floe for
the polar bears to eat. This is of course in main (future 3.2), and will
not be backported to release branches, since we never stop support of a
dependency or toolchain of existing releases. People requiring icc for
whatever reason may keep using OIIO 3.1 or older.

We will continue to support and test icx, the fully supported Intel
LLVM-based compiler.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-21 14:06:32 -08:00
Larry Gritz 944ffd50f7 test: imageinout_test: add benchmark of read and write speed vs tile size (#5037)
For various tile sizes (and scanline), benchmark how long it takes to
read and write a 4k x 2k image.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-21 14:06:07 -08:00
Larry Gritz 14dbd96dbb build: self-builder logic fixes for deep vs shallow clones (#5034)
* cmake utility build_dependency_with_cmake was unconditionally doing a
shallow clone and using `clone -b`, but that only works if it's got a
branch or tag name, not if it has a commit hash. So change the logic so
it does a shallow clone only if GIT_TAG is specified but GIT_COMMIT is
not.
* pybind11 self-builder is modified to allow a git commit override.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-19 22:47:59 -08:00
Larry Gritz 2486b66af8 fix(oiiotool): Fix expression BOTTOM when there are exactly two images (#5046)
Fixes #5044

Oops, the logic was a little mixed up when there were exactly two
images. One reason that this was a special case is that conceptually,
there is just a stack, but the implementation is that there is a
separate variable for the top item, and then the actual stack is all the
other items.

Also add more thorough testing of TOP/BOTTOM, including what happens for
2, 1, and also 0 items on the image stack (errors in that last case).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-19 10:28:06 -08:00
Larry Gritz 0457774292 fix(tiff): Correctly read TIFF EXIF fields for ExifVersion and FlashPixVersion (#5045)
This allows us to correctly read the ExifVersion and FlashPixVersion
metadata in an EXIF block of a TIFF file.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-14 04:59:46 -08:00
Brecht Van Lommel bf7bc9c6ef feat(heif): Monochrome channel read and write support, fix crash (#5043)
Implement support for reading and writing monochrome. Reading requires
libheif 1.17+ for heif_image_handle_get_preferred_decoding_colorspace.

Previously writing a single channel image would cause an exception due
to
wrong parameters, but close() would continue writing the image and
crash.
Destroy m_ctx on exception to prevent that for other potential errors.

Test added for monochrome read and write.

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-02-13 12:38:19 -08:00
Larry Gritz 758082a9c7 ci: Turn off nightly workflows for user forks (#5042)
Also switch to a better idiom for detecting if we're a fork.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-12 21:29:24 -08:00
Lumina Wang 15034bb670 fix: gamma precision (#5038)
This is a PR proposing to keep the gamma precision.

In some cases, we need more precise gamma values, while the existing
rounding operation loses most of the precision. This change will
continue to use rounded values to calculate and store color space
information, but retain the original value in the "Gamma" parameter. In
addition, it can also tidy up existing code.

I've verified with png/exif.png & python-colorconfig tests. No
regression is introduced.

Signed-off-by: Lumina Wang <lumina.wang@autodesk.com>
2026-02-12 11:51:37 -08:00
Larry Gritz 8a39d36304 fix(tiff): Improve TIFF robustness for non-matching tag/metadata types (#5036)
This is a more comprehensive fix for issues discovered in PR #5035.

The original problem reported in Issue #5023 was a crash when writing
TIFF information that was supposed to be arrays of more than one
rational, it was reading past the end of a memory array.

#5035 is a minimal, immediate fix to address the crashes. But in the
process, I saw a number of ways in which we were dropping metadata on
the floor when the types didn't exactly match, but that we *could*
handle with automatic conversion.

The new cases that we handle with this PR are:

* Exif RESOLUTIONUNIT tag is a short, but by convention we store it by
the name as a string in OIIO metadata, so we need to convert back to a
code (we did so for the main TIFF metadata, but not for Exif in TIFF).
* Handle Exif "version" and "flashpixversion" metadata which have
unusual encoding in TIFF files (they are 4-character strings, but must
be stored in a TIFF tag of type BYTES, not as the usual type ASCII that
most strings use.
* Handle things that TIFF insists are ASCII but that come to us as
metadata that's strings. Easy -- our `ParamValue.get_string()`
automatically converts ther things like ints or floats into string
representation.
* Much more flexibility in automatically converting among the signed and
unsigned, 16 and 32 bit, integer types when the metadata in our
ImageSpec is integer but not the specific type of integer that TIFF/Exif
thinks it should be.

This doesn't appear to change the results of anything in our testsuite,
but it's possible that some non-TIFF-to-TIFF image conversions that
contain Exif data may now do certain type conversions properly instead
of just silently dropping the metadata that had non-matching (but
reasonably valid) types.

Additionally, to do this nicely, I ended up adding a new TypeURational
alias in typedesc.h (similar to TypeRational, but the case where both
numerator and denominator are unsigned ints).

And also fixed a random comment typo I noticed in tiffinput.cpp.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-11 16:04:03 -08:00
Larry Gritz 27b6799b52 build: Raise fmt auto-build version to 12.1, handle Windows flags (#5039)
Bump the version of 'fmt' library that we download and build (if not
found) from 10.2 to 12.1.

Some other touch-ups in build_fmt.cmake.

Also, we have seen that recent fmt versions will fail to compile on MSVC
unless using the `/utf-8` compiler flag, so ensure that is used and also
passed on to other clients of libOpenImageIO_Util (which expose
templates using those headers).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-10 21:06:41 -08:00
Larry Gritz 5e005e68a0 fix(tiff): Fix TIFF output crash for multi-count Exif metadata (#5035)
Fixes #5023

This was crashing when writing TIFF information that was supposed to be
arrays of more than one rational, but in fact was provided as a single
value, it was reading past the end of a memory array.

I noticed that this whole region needs a cleanup, this is not the only
problem. But a full overhaul seems too risky to backport, so my strategy
is as follows:

* THIS fix first, which I will backport right away to 3.0 and 3.1.

* I will then submit a separate PR (already implemented and tested) that
is a much more complete fix and overhaul of this portion of the code
(and other places). That will get merged into main when approved.

* After the second PR is merged, I'll hold it in main for a while to
test its safety, and then decide if it seems ok to backport to 3.1 (but
definitely not 3.0).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-10 17:14:57 -08:00
Larry Gritz ee3370d004 fix(bmp): detect corrupt files where palette doesn't match bpp (#5030)
Extra protections for corrupted BMP files that claim to be palette
images, but have a BPP that doesn't support palette images. Also an
extra guard around accessing the palette array if it is empty.

Add an extra test case for this kind of corruption.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-07 03:04:06 -08:00
Larry Gritz 1188706bac ci: Don't install OpenCV on Mac Intel job variant (#5032)
Mac Intel is getting long in the tooth, and quite often the Homebrew
packages for Intel are found to be uncached and will try to build from
source. When it's OpenCV, that's disastrous for our CI build times, it
can get stalled for hours building all of OpenCV and its dependencies.
So disable it for that one build variant.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-06 22:10:51 -08:00
Larry Gritz 81c54c46b5 api: OIIO_CONTRACT_ASSERT and other hardening improvements (#5006)
Review: we have long had two assertion macros: OIIO_ASSERT which aborts
upon failure in Debug builds and prints but continues in Release builds,
and OIIO_DASSERT which aborts in Debug builds and is completely inactive
for Relase builds.

Inspired by C++26 contracts, and increasingly available "hardening
modes" in major compilers (especially with the LLVM/clang project's
libc++), I'm introducing some new verification helpers.

New macro `OIIO_CONTRACT_ASSERT` more closely mimics C++26
contract_assert in many ways, and perhaps will simply wrap C++
contract_assert when C++26 is on our menu.

Important ways that OIIO_CONTRACT_ASSERT differs from OIIO_ASSERT and
OIIO_DASSERT:

* Keeping in line with C++ contracts, there are 4 possible responses to
a failed contract assertion: Ignore, Observe (print only), Enforce
(print and abort) and Quick-Enforce (just abort).

* Also define hardening levels: None, Fast, Extensive, and Debug,
mimicking the levels of libc++. The idea is that maybe there will be
some CONTRACT_ASSERT checks you only want to do for certain hardening
levels.

* By default, the contract failure response is Enforce, unless it's both
a release build and the hardening level is set to None (in which case
the response will be Ignore). But it's also overrideable optionally on a
per-translation-unit basis by setting OIIO_ASSERTION_RESPONSE_DEFAULT
before any OIIO headers are included (though obviously that only applies
to inline functions or templates, not to any already-compiled code in
the library).

* Macros for explicit hardening levels: OIIO_HARDENING_ASSERT_FAST(),
EXTENSIVE(), and DEBUG(), which call CONTRACT_ASSERT only when the
hardening level is what's required or stricter.

I also changed the bounds checking in operator[] of string_view, span,
and image_span to use the contract assertions. Note that this adds a
tiny bit of overhead, since the default is "enforce" for release builds
(previously, using OIIO_DASSERT, it did no checks for release builds).
But the benchmarks seem to idicate that the perf difference is barely
measurable.

I added some benchmarking that proves that the bounds check adds a
minute overhead to an element access for a trivial `span<float>`, maybe
even indescernable. Here are benchmarks comparing raw pointer access,
std::array access, span access with the new checks, span access
carefully bypassing the tests.

Linux workstation, gcc-11, on my work computer:

    pointer operator[]:     647.8 ns (+/- 0.1ns)
    std::array operator[]:  647.8 ns (+/- 0.1ns)
    span operator[] :       657.6 ns (+/- 0.5ns)
    span unsafe indexing:   648.2 ns (+/- 0.2ns)
    span range      :       648.1 ns (+/- 0.1ns)

These are the most stable tests I have, with the least trial-to-trial
variation, and show about a 1.5% speed hit on the bounds-checked span
access itself, which I think will be truly un-measurable in the context
of being interleaved with any other operations that you do with the data
you pull from the span.

Mac Intel, Apple Clang 17, on my (old) personal laptop: (much more
variable timing, probably from MacOS scheduler quirks)

    pointer operator[]:     929.2 ns (+/- 6.7ns)
    std::array operator[]:  913.1 ns (+/- 20.6ns)
    span operator[] :       905.8 ns (+/- 13.3ns)
    span unsafe indexing:   913.9 ns (+/- 16.6ns)
    span range      :       916.4 ns (+/- 20.3ns)

You can see that here there is no obvious penalty, in fact it appears a
little faster, but all within the timing uncertainty of the multiple
trials, so statistically it's hard to discern any penalty.

And a couple more for good measure from our CI, but note that because
these are uncontrolled machines somewhere on the GitHub cloud, the
timings might not be as reliable:

Windows, MSVS 2022:

    pointer operator[]:    3716.3 ns (+/- 6.3ns)
    std::array operator[]: 3715.5 ns (+/- 3.4ns)
    span operator[] :      3715.6 ns (+/- 2.6ns)
    span unsafe indexing:  3712.1 ns (+/- 0.7ns)
    span range      :      3714.2 ns (+/- 2.9ns)

Linux, gcc-14, C++20:

    pointer operator[]:    1130.9 ns (+/- 0.2ns),  884.2 k/s
    std::array operator[]: 1132.0 ns (+/- 0.4ns),  883.4 k/s
    span operator[] :      1133.7 ns (+/- 0.4ns),  882.1 k/s
    span unsafe indexing:  1134.2 ns (+/- 1.6ns),  881.7 k/s
    span range      :      1133.9 ns (+/- 0.7ns),  881.9 k/s

MacOS ARM:

    pointer operator[]:    3456.6 ns (+/- 7.5ns)
    std::array operator[]: 3466.8 ns (+/- 12.2ns)
    span operator[] :      3610.9 ns (+/- 11.0ns)
    span unsafe indexing:  3607.4 ns (+/- 4.9ns)
    span range      :      3612.4 ns (+/- 12.2ns)

Windows with MSVS and Linux with newer g++ don't appear to show any
penalty, and the bracketing of trial times indicates that maybe it's
consistent enough to be meaningful? I can't think of anything I'm doing
wrong here that would throw off the timing or disable the range checking
on these tests.

For MacOS ARM, the span looks like it has about a 4% penalty versus raw
pointers? But OTOH, span bounds-checked vs non-checked vs range-for are
all the same, so maybe the speed vs raw pointer is something else
entirely?

Also please note that a preferred way to avoid these extra bounds checks
entirely is to change an index-oriented loop like

    span s;
    for (size_t i = 0; i < s.size(); ++i)
        foo(s[i]);   // maybe bounds check on each iteration?

to a range based loop:

    span s;
    for (auto& v : s)
        foo(v);

which should be inherently safe and require no in-loop checks at all.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-06 13:57:03 -08:00
Jesse Yurkovich ae20fc7894 cleanup: remove left over tile emulation code for various formats (#5029)
Since the OpenImageIO 2.5 series, when calls to `check_open` were added,
any format that did not declare support for "tiles" would immediately
fail to open. But many of the formats which attempted to emulate tiles,
by buffering the contents and writing it all as scanlines at the end,
were not updated. All of the tile emulation code for these formats is
effectively dead-code and untested.

Remove the tile emulation code from these formats.

An example of what the failure currently looks like:
```python
>>> out = oiio.ImageOutput.create("test.png")
>>> spec = oiio.ImageSpec(64, 64, 3, 'uint8')
>>> spec.tile_width = 64
>>> out.open("test.png", spec)
False

>>> out.geterror()
'png does not support tiled images'
```

No tests were impacted.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2026-02-06 13:55:43 -08:00
Larry Gritz 57d1ab4ee3 testing: Add testsuite/heif ref output for libheif 1.21 + avif support (#5031)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-05 19:08:29 -08:00
Larry Gritz e1575d2eb4 fix(win): oiiotool --buildinfo misreported platform on MSVS (#5027)
Need to test some MSVS-specific macros to determine what architecture to
report.

And especially, if it doesn't know the processor architecture, it still
should be *appending* that to the platform, not replacing it! This
caused MSVS-compiled OIIO on Windows to report "unknown arch?"

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-02 13:42:10 -08:00
Larry Gritz a8d013c765 fix: conform certain attrib names "exif:*" to our "Exif:*" convention (#5025)
I think it was basically harmless, since we do all the metadata name
comparisons using case-insensitive comparisons. But we use "Exif:" as
our prefix for Exif data throughout OIIO by convention, and there was
this tiny handful of places where we said "exif:".

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-02 12:30:05 -08:00
Larry Gritz a0426d6e6e testing: Adjust test comparision thresholds for Mac ARM (#5026)
Even though we have CI testing on Mac with ARM CPU that were passing,
after getting a new laptop, I saw some test failures that were due to
just a few pixels on a few tests needing a higher comparision threshold.
Results are correct, just different due to the math. I guess this
machine (CPU? build flags? specific compiler or library versions?) is
ever so slightly different than the CI Macs, so I caught a few more
instances that needed to be adjusted.

I tried to increase the thresholds as little as possible to fix the
problem.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-01 12:33:10 -08:00
Larry Gritz 9e7444a2e0 CHANGES udpates (#5028)
Reflecting this month's releases and other things that recently went
into main.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-02-01 12:31:31 -08:00
Valery Angelique 721c41e61b feat(iv): flip, rotate and save image (#5003)
Fixes #4715 

- Added save functionality
- Added flipping and rotation capabilities via metadata.
- Hotkeys: Ctrl-Shift-R and L to rotate the image left and right. 

Note that the actual pixel data remains unchanged, so only image formats
that support the rotation metadata will reflect the changes.

I thought that it made sense for the flip and rotate to be under the
tool section, similar to where the macbook Preview app places it.
Keyboard shortcuts also follow the shortcuts that Preview uses.

Tests

Used a .jpeg photo to test:
- saving
- making changes with/without saving and re-opening the image
- flipping and rotation from different initial rotation/mirrored states

Otherwise there doesn't seem to be a test suite for iv? 

Signed-off-by: valery <71804886+vangeliq@users.noreply.github.com>
2026-01-31 17:52:00 -08:00
Larry Gritz 0839a389ef ci: lock bleeding edge to pybind11 latest version (#5024)
There's something in pybind11 master at the moment that is crashing in
its destructors. It's been causing our "bleeding edge" test to fail for
over a week now. I'm tired of our test failing, so I'm locking down to
the last known working version. Will check back periodically and return
to testing against pybind11 master after they have fixed it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-31 13:41:10 -08:00
Zach Lewis 81b30d17a6 build(ocio): bump build ver to 2.5.1 (#5022)
Makes OpenColorIO 2.5.1 the default version when building OCIO locally.
This will cause the released python wheels to build against the
currently-latest version of OCIO.

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2026-01-30 10:43:49 -08:00
Brecht Van Lommel fb8cde9b35 fix(webp): Missing oiio:UnassociatedAlpha on input (#5020)
Like other file formats, the returned ImageSpec should indicate if the
image contains unassociated alpha.

This was an oversight in #4770.

Test added.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-01-29 14:56:15 -08:00
Brecht Van Lommel ae120afe97 feat(heif): Add IOProxy for input and output (#5017)
Add IOProxy support similar to other file formats.

MyHeifWriter was renamed for consistency with other code.

All input and output now goes through the proxy, so this is covered by
existing tests.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-01-28 10:17:32 -08:00
Brecht Van Lommel 19c72c117e fix(heif): Error saving multiple images with different bit depths (#5018)
This variable should not have been static.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-01-28 10:13:00 -08:00
Larry Gritz 4f08ac0f85 api(ImageBuf): IB::localpixels_as_[writable_]byte_image_span (#5011)
Utilities to ask the IB for the local pixels as an untyped span of
bytes. This is a "safe" alternative to `localpixels()`, which just
returned a single pointer, instead returning an image_span that
understands the sizes and strides of the buffer.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-28 07:54:22 -08:00
Larry Gritz bdb4208ef5 api: IBA::make_texture now honors "maketx:threads" hint (#5014)
Nearly all IBA functions take an optional parameter controlling the
threading. But make_texture() did not, so there was no way to control
its thread usage (it would always use the default number of threads).

Without changing the call signature or ABI, this patch merely makes
make_texture honor any "maketx:threads" hint passed in the config
ImageSpec that it already takes to convey all sorts of controls over the
texture creation process. Then this value is passed to any IBA
functions, use of parallel_image, and anything else in the
implementation of make_texture that would end up using the thread pool.

Fixes #4254

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-28 04:09:23 -08:00
Jesse Yurkovich d7dabc92f3 fix(webp): Use correct resolution limits for WebpOutput::open (#5016)
The WebP format is very limited in the maximum resolution it supports.
We need to change the values we allow to be much smaller.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2026-01-27 20:24:47 -08:00
Brecht Van Lommel e6ccb76a29 fix(heif): Can not output AVIF when libheif has no HEVC support (#5013)
Initializing the encoder to `heif_compression_HEVC` by default throws an
exception when libheif was built without HEVC support, which prevents it
from being used entirely even if there is AVIF support.

So delay that initialization until we are sure which encoding we want.

Not really any practical way to automatically test this.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2026-01-23 11:37:58 -08:00
Larry Gritz a0db58037c build: fully disable tests when their required dependencies are missing (#5005)
We previously merely *marked* tests as "broken" in this case, and
depended on ctest being launched with `-E broken` to ensure those were
skipped. Not everybody did. Let's just truly skip them.

Fixes #4979

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-22 17:19:22 -08:00
Larry GritzandCopilot 96a875c78a build: Use libheif exported config if available (#5012)
Needed to change the Libheif::Libheif target we set up ages ago to the
"heif" name that the package's exported config uses.

Also, need to give the warning about static libraries occur any time we
are using static libheif, even if we didn't set LIBSTATIC to try to
force all static libraries.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-20 17:29:48 -08:00
Larry Gritz f862c0688a fix: several bug fixes related to internal use of image_span (#5004)
* ImageBuf internal buffer span lacked correct chansize. The internal
`m_bufspan` is an `image_span<byte>`, and as such, it needs to remember
the size of the original data type. Otherwise, there's a cascade of
potential errors when it thinks that the individual values are byte
sized.

* In both ImageInput and ImageOutput, several sanity checks of
image_span size versus expectations were incorrect. They were only
checking if the total byte sizes matched expectations, but they are
allowed to disagree when you consider type conversions (in which case,
it's the total number of values that need to match, not the total byte
sizes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-18 09:24:10 -08:00
Larry Gritz 550264b4e4 ci: test against libraw 0.22 for 'latest' test variants (#5009)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-17 11:10:01 -08:00
Larry Gritz 339449f470 ci: Windows runners switched which python version they had (#5010)
Yay, I love how these things just break with no notice.

Fixes CI that broke a couple days agi.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-17 08:41:09 -08:00
Larry Gritz 5f8fcc4f79 docs: Remove outdated/wrong description in INSTALL.md (#5008)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-15 10:54:47 -08:00
Larry Gritz df75f8bc02 test: Add new ref image for jpeg test (#5007)
Needed for some systems after the changes of #4963.

Ever so slightly different LSB somewhere makes the hashes not match, but
it's a correct visual result.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-14 14:16:30 -08:00
Larry Gritz b86a46abf5 build: Fix HARDENING build options (#4996)
Due to typos in the option name in compiler.cmake (HARDENING vs
OIIO_HARDENING, oops), I think we were never really setting the intended
compiler flags. Fix that all up, and repair the other problems that it
revealed -- some compiler version and option combinations weren't happy
with each other, etc.

One notable change is in encode_iptc_iim_one_tag: I think I made it
safer by taking an early out for 0-sized data, and also it needed a
warning suppression when certain gcc hardening levels were used.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-13 12:13:24 -08:00
Larry Gritz 0a30218836 admin: Refine PR template to give more visual separation (#4995)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-10 09:46:21 -08:00
Brad Smith 342da8ee6e fix(build): Fix building on OpenBSD (#5001)
Fixes #5000

Signed-off-by: Brad Smith <brad@comstyle.com>
2026-01-09 16:55:11 -08:00
Larry Gritz e095329ff7 ci: don't run non-wheel workflows when only pyproject.toml changes (#4997)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-09 14:49:05 -08:00
Larry Gritz 493342a182 ci: Speed up macos15 intel variant by not installing Qt (#4998)
The Intel MacOS 15 CI testing is getting dicier... lots of times,
Homebrew doesn't have cached versions of updated packages, so it tries
to build from source, which takes forever. The big culprit today is Qt.
So, basically, just on this one CI job variant, don't ask it to install
Qt. If it's there, it's there. If not, just skip it. It's tested plenty
in other variants.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-09 12:33:43 -08:00
Larry Gritz b30ddcee0b ci/deps: Freetype adjustments (#4999)
* CI test vs the latest freetype 2.14.1
* Bump the version of freetype that we auto-build to the latest (from
2.13.2)
* Simplify BZip2 finding logic, switch to using targets

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-09 12:33:27 -08:00
Larry Gritz 774368db0b perf: IBA::resample improvements to speed up 20x or more (#4993)
For IBA::resample() when bilinear interpolation is used, almost all of
the expense was due to its relying on ImageBuf::interppixel which is
simple but constructs a new ImageBuf::ConstIterator EVERY TIME, which is
very expensive.

Reimplement in a way that reuses a single iterator. This speeds up
IBA::resample by 20x or more typicaly.

Also refactor resample to pull the handling of deep images into a
separate helper function and out of the main inner loop. And add some
benchmarking.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-08 11:47:37 -08:00
Larry Gritz c3ccc9e726 deps: libheif 1.21 support (#4992)
Starting with 1.21, libheif seems to change behavior: When no CICP
metadata is present, libheif now returns 2,2,2 (all unspecified) on
read. OIIO convention, though, is to not set the attribute if valid CICP
data is not in the file.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-05 10:31:46 -08:00
Larry Gritz 312793af4a docs: Update CHANGES (#4991)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2026-01-01 11:03:27 -08:00
Jesse Yurkovich 81fde9cb77 feat(sgi): Implement RLE encoding support for output (#4990)
Implement RLE compression support for the SGI output plugin. Reading RLE
encoded images was already supported, but writing was never done up
until this point.

The existing sgi test seems sufficient to catch issues and it covers
input/output of both 1 byte-per-pixel and 2 byte-per-pixel files.

The documentation for the image plugins are sometimes not very clear
about which attributes are relevant for input vs. output. There's
usually 3 sections: Attributes, Attributes for Input, and Attributes for
Output.

Before this PR, SGI mentioned the "compression" attribute in the
"general" Attributes section (rather than say just the Input section),
which caused a bit of grief as the only way to discover that RLE was not
implemented for Output was to glance at the file size of the resulting
file... I had assumed that compression was supported for output too but
discovered that it was not.

Now that this PR implements the attribute for output I've left the
documentation as-is in the "general" Attributes section since it applies
to both read/writing now. But I'm open for suggestions here.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-12-30 23:45:23 -08:00
Larry Gritz 0d5e78ddc5 deps: Test against libraw 0.21.5 (#4988)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-30 11:27:23 -08:00
Larry Gritz 4134467ced docs: fix missing docs for OIIO:attribute() and OIIO::getattribute() (#4987)
Rearrangements in 3.1 dropped the list of recognized attributes from
the visible online docs and failed to document the span varieties. We
fix and also reword a lot of the descriptions for clarity and uniformity.

The previous organization was that there were several varieties of attribute(). In the header, the first one had the overall long explanation, including the list of all the recognized attributes. The other ones had short explanations of how they differed. In the docs, each one was referenced explicitly, pulling in its attendant bit of documentation.

What really happened is that in the header, I made the new span-based version the "flagship" one with the full explanation, but I neglected to reference it in the docs, so the long description disappeared.

I could have fixed by just adding refs to the new functions to the docs, as I originally meant to. But while I was there, I took the opportunity to surround the whole collection with a group marker, and then include the lot of them with a single reference to the group, rather than need to refer to each function variant individually. And while I was at it, I also reworded (and hopefully improved) some of those explanations.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-29 17:36:38 -08:00
Brecht Van Lommel ff89654492 feat(JXL): CICP read and write support for JPEG XL (#4968)
The JPEG XL color encoding metadata only supports a subset of CICP. So
for
example `srgb_p3d65_display` and `pq_rec2020_display` are supported, but
`g26_xyzd65_display` is not.

Custom primaries, custom white point and arbitrary gamma could be used
to
support more, but I didn't implement that.

Tests for read and write were added.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-12-22 10:24:15 -08:00
Brecht Van Lommel 693b09b4ff feat(exr): Write OpenEXR colorInteropID metadata based on oiio:ColorSpace (#4967)
If the colorspace exists and has an interop ID in an OCIO 2.5 config,
use that.
Otherwise check if the colorspace is equivalent to a known color interop
ID.

Tests were added.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-12-19 12:37:06 -08:00
Larry Gritz deb68be8cd admin: Minor rewording in the issue and PR templates (#4982)
Periodic revisiting of the phrasing in the hopes of improving PR and
Issue quality / actionability. Not that I think they are bad now, just
always looking to guide people to improvements.

Will it work? 🤷 Let's try and see if we think PRs improve. If not, we
can revise again later.

Also make the issue title prefixes less yelly and shorter (makes it
easier to see the actual title on phone or other limited width display
of messages).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-19 12:09:03 -08:00
Larry Gritz 0fe78f7c27 fix(png): We were not correctly suppressing hint metadata (#4983)
Each file writer that is capable of writing arbitrary metadata is
supposed to tace care to suppress hints meant for other writers, or for
OIIO in general, not interpret them as literal metadata to write to the
file. PNG was not doing so, and ended up writing hints as literal
metadata. This brings it in line with our behavior when writing OpenEXR
and other formats.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-19 12:08:35 -08:00
Pavan Madduri 4e9e70f4dd fix(IBA): IBA::compare_Yee() accessed the wrong channel (#4976)
The GaussianPyramid::value() method used by IBA::compare_Yee() was
incorrectly accessing channel 1 instead of channel 0. This fix corrects the
channel access to properly retrieve the luminance value from the
single-channel pyramid levels.

One oddity this led to is that `idiff -p` would appear to PASS for
some clearly different images if they had different data windows.

Update reference outputs to reflect the corrected perceptual diff results
(Max error changes from 1 to 10 for the test images).

Fixes #4948

Signed-off-by: pmady <pavan4devops@gmail.com>
2025-12-17 03:38:44 -08:00
Larry Gritz f5022d7960 ci: unbreak CI by adjusting Ubuntu installs (#4981)
The default Ubuntu images keep shifing around. Last week, some packages
that used to be installed disappeared. Need to adjust what we install in
gh-installdeps.bash, and slightly adjust the optional deps in ci.yml to
allow some things that seem to be only on some runners to be missing.
Also bump the clang test to clang18 on an ubuntu-24 runner (from clang
15 on ubuntu 22).

Gets us back to all-passing CI after a week of all sorts of failures in
tests that used to work.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-16 21:46:05 -08:00
Larry Gritz febafce408 ci: build_Ptex.bash should build Ptex using C++17 (#4978)
If we don't specify anything, it seems that Ptex will think it's using
C++98, which it is in fact not capable of doing.

Meanwhile, since OIIO's own minimum requirement is C++17, it certainly
meand that any compiler we're using can support 17 as a minimum when
building Ptex as well.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-15 11:32:57 -08:00
Larry Gritz afb365c3b6 ci: optimize install_homebrew_deps by coalescing installs (#4975)
There seems to be a couple seconds overhead for each "brew install".
Refactor install_homebrew_deps.bash to first assemble the list of all
packages to install, and then do a single `brew install` for the whole
list.

Also remove mention of packages that are pre-installed on the Mac GHA
runners or that we don't need.

In the process, by using the `OIIO_BREW_INSTALL_PACKAGES` variable and
only setting it if empty, we now have the ability to fully override the
list of packages that brew will install on a per-job basis.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-14 02:57:36 -08:00
JacksonSun-adsk ae04b6ed3b Speedup to detect the existence of files on Windows (#4977)
On Windows, `Filesystem::exists` forward the call to
`std::filesystem::exists`, and finally calls `_std_fs_get_stats` .
`_std_fs_get_stats` is slow if the argument is a netwok path.

Signed-off-by: Jackson Sun <jackson.sun@autodesk.com>
2025-12-12 15:11:52 -08:00
Brecht Van Lommel 9229cf33c9 feat: Auto convert between oiio:ColorSpace and CICP attributes in I/O (#4964)
When reading image files with CICP metadata, automatically set the
corresponding "oiio:ColorSpace". When writing files that support CICP
and no other colorspace metadata can represent "oiio:ColorSpace",
automatically write CICP metadata.

Setting "oiio:ColorSpace" on read prefers scene referred over display
referred color spaces, changing existing behavior as little as possible.
The alternative would have been to interpret the presence of CICP
metadata as an indication that the image is likely display referred,
which might be reasonable too. Either way it's a guess.

There is no automatic mapping from `g22_rec709_display` to CICP
currently to keep behavior unchanged, as this is often not what you want
and further discussion is needed to decided on the right behavior.

Also add new ColorConfig `get_cicp` and `get_color_interop_id` API
functions to share logic between file formats.

## Tests

Tests were updated, the auto detected color space name appears in the
output.

Commands like these should also do the right thing automatically.
```
oiiotool in.exr --ociodisplay "Rec.2100-PQ - Display" "ACES 2.0 - HDR 1000 nits (P3 D65)" -o out.avif
oiiotool out.avif --autocc -o out.exr
```

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-12-12 00:03:23 -08:00
Pavan Madduri fd5ac81e91 fix(webp): Allow out-of-order scanlines when writing webp (#4973)
Move write_complete_data() to close() for proper scanline order support 

The WebP output plugin incorrectly assumed that scanlines would be
written in sequential order, triggering the final write when y == height
- 1. This violated the write_scanline API contract which allows
scanlines to be written in any order (the plugin even advertises
'random_access' support).

Changes:
- Remove premature write_complete_data() call from write_scanline()
- Move final encoding/writing to close() where it belongs
- Add m_image_complete flag to track write state
- Move buffer cleanup to after write_complete_data() in close()

Fixes the issue where writing scanlines out of order would result in
incomplete or corrupted WebP files.

Signed-off-by: pmady <pavan4devops@gmail.com>
2025-12-08 01:07:27 -08:00
Larry Gritz 2d5e44289c ci: Address tight disk space on GHA runners (#4974)
- Mount the host's root under /host/root so it's visible in the
containers.
- Remove stuff we don't need to free lots of disk space.
- While we're at it, arrange for the commands (copied from OSL) that
allow the containers to see a CPU, when available.

This is freeing 20+ GB!

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-12-06 11:42:19 -08:00
Larry Gritz 203d6695c4 ci: Try python 3.13 to fix Mac breakage on CI (#4970)
I think something changed with Homebrew on the runners, this worked
until last week.

Emergency fix, will merge immediately if CI finally passes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-30 10:28:40 -08:00
Larry Gritz 4be8b0a2a2 ci: Emergency fix change deprecated sonarqube action (#4969)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-29 23:46:16 -08:00
Brecht Van Lommel 4a13f4b6df fix(exr): ACES container writes colorInteropId instead of colorInteropID (#4966)
The EXR reading code was correct. These attribute names are case
sensitive in OpenEXR.

Test output was updated.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-11-27 22:07:36 -08:00
Larry Gritz ed408595b4 fix(jpeg): Fix wrong pointers/crashing when decodng CMYK jpeg files (#4963)
Was just wrong. Presumably broken recently.

In the process, switched internal cmyk->rgb conversion to be span based.

Fixes #4962

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-26 18:21:41 -08:00
Larry Gritz 5f728801d6 fix(exif): Support EXIF 3.0 tags (#4961)
We were supporting Exif 2.3, but in 2024, Exif 3.0 was published and it
adds some more tags for us to recognize.

The only part I am not sure about here is that the ExifVersion we output
is still marked as 2.3, not 3.0, because I'm worried that if we mark it
as 3.0, older software reading the images will reject it. Let's see what
happens. If downstream apps care, maybe we can bump to 3.0, or even bump
to 3.0 only if any of the 3.0 tags are used (that is more involved).

Fixes #4960

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-24 12:51:28 -08:00
Larry Gritz 62be33f577 fix: Fix some legacy 'Linear' color references (#4959)
Convert to modern oiio color space nomenclature.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-21 22:31:56 -08:00
Larry Gritz 1e8b0de711 admin: Update some license notices (#4955)
Result of our annual license scan.

* Add license notices some places we had missed (mostly documentation).
* Double check some of the code files that are still marked as a mix of
Apache 2.0 + BSD, see if there are any remaining lines that are from
authors that hadn't relicensed their contributions -- there were a few
that had none of those old lines left, so they can be changed to
advertise that they are purely Apache 2.0.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-17 10:24:43 -08:00
Larry Gritz 936cb34a75 ci: unbreak icc/icx CI (#4958)
A few days ago, the icc and icx CI tests started failing, saying they
were out of disk space while installing dependencies (specifically, the
intel compilers themselves).

Now, the VFX Platform 2023 asf docker image I'm using hasn't changed,
and neither has the years-old Intel rpms with the compilers. So maybe
the runners themselves just changed again, in a way that adds some
pre-installs and leaving us not quite enough disk space for everything
else we need?

Asking for a few less things to get installed seems to free up just
enough space. And for the icx one, I also swtiched to the 2025
container, which let me use a slightly newer icx version.

Also: Don't try to install giflib needlessly, which speeds up the setup
time. And remove some dead code in my dependency setup script.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-17 10:24:03 -08:00
LI JI 88870777cd build: Disable LERC in libTIFF local build script (#4957)
Recently, when building OIIO using `OpenImageIO_BUILD_LOCAL_DEPS=all` cmake option, I noticed a reference to `lerc` that fails during the linker stage, when compiling the simd tests:

```
[ 71%] Building CXX object src/libutil/CMakeFiles/simd_test.dir/simd_test.cpp.o
[ 71%] Linking CXX executable ../../bin/simd_test
/usr/bin/ld: ../../lib/libOpenImageIO.so.3.1.7: undefined reference to `lerc_decode'
/usr/bin/ld: ../../lib/libOpenImageIO.so.3.1.7: undefined reference to `lerc_encodeForVersion'
/usr/bin/ld: ../../lib/libOpenImageIO.so.3.1.7: undefined reference to `lerc_getBlobInfo'
collect2: error: ld returned 1 exit status
gmake[2]: *** [src/libutil/CMakeFiles/simd_test.dir/build.make💯 bin/simd_test] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:2158: src/libutil/CMakeFiles/simd_test.dir/all] Error 2
gmake: *** [Makefile:166: all] Error 2
```
`lerc` is an image compression library from ESRI: https://github.com/Esri/lerc

A deeper dive of this reference to lerc shows that it is referred in `libtiff`. `libtiff`, however, did not seem to correctly export this dependency to OIIO when being built locally. 

If someone was building OIIO with a system-installed `libtiff`, this error is unlikely to happen.

By disabling `lerc` in `libTiff`, the local build scripts ( `OpenImageIO_BUILD_LOCAL_DEPS=all` ) runs without a problem.

Tested build OIIO with  `OpenImageIO_BUILD_LOCAL_DEPS=all` with this patch and was successful in finishing the build.
2025-11-14 19:27:17 -08:00
Larry Gritz 5482ecd29d fix(exr): improve attribute translation rules (#4946)
In exr output, we were doing attribute name substitutions using
case-insensitive comparisions, whereas on the exr input side, we were
using case-sensitive comparisons. This was leading to some strange
behavior where certain attributes were not properly "round tripping"
when reading and writing exr files, particularly when it involved
attribute names that differed only in case from certain
reserved/standard names.

Also be a little more flexible in adjusting exr attributes that have the
wrong type, by being able to convert int or float to a value that's
required to be a string.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-12 13:36:49 -08:00
Larry Gritz 1417836d1c ci: fix broken ci, debug and static cases, bump some latest (#4954)
Two Ubuntu-based cases (debug build and static build) started failing
this past week, unrelated to us. I think the runners changed yet again,
it seems to be having particular trouble because those tests were trying
to use gcc-9. But there's no particular need for that anyway, it just
reflects how long ago we last modified those tests.

So this spurred a grab bag of CI fixes:

* Move the debug and static linkage tests off of raw ubuntu runners and
to using the ASWF docker VFX Platform 2025 containers. This makes them
more modern and also more stable.

* Turns out the "static" test hadn't been working properly lately -- it
was accidentally building dynamic libs, not static at all! Fix that, but
then it uncovered some problems that are out of scope to fix in this PR.
I will look into it separately, but in the mean time I have commented
out the static build test to suppress the failures.

* Bump a few of the "latest" dependencies to the most recent.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-12 13:20:27 -08:00
Larry Gritz 72d79910ef test: image_span_test reduce benchmark load for debug and CI renders (#4951)
Almost all the other unit tests do this, just adding it to
image_span_test: automatic reduction in test load for CI and debug
renders by doing fewer time trials. This cuts down on runtime for CI,
but stil exercises the test code. Command line arguments allow you to
override, in cases where you need really good timing fidelity even for a
debug run.

Also conform simd_test to the usual standard `-iters` used elsewhere
instead of being the one place that uses `-iterations`.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-11 14:02:58 -08:00
Larry Gritz e8667166c3 fix: type warning in assertion in jpeg2000output.cpp (#4952)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-10 23:23:30 -08:00
Larry Gritz 6b4f081b9d fix(imagebuf): fix set_pixels bug, didn't consider roi = All (#4949)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-07 10:00:48 -08:00
Larry Gritz 98e7dea3b5 CHANGES updates (#4947)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-11-01 17:09:54 -07:00
Jonathan Brown 6cd6127fae fix(JXL): Correctly set Quality for JPEG XL (#4933)
Distance in JPEG XL isn't linear, causing previous quality settings to
scale between lossless and visually lossless, instead of lossless and
the lowest quality.

Quality | libjxl Distance | Old OIIO Distance
|--------|------|------|
| 99 | 0.19 | 0.01 |
| 90  | 1.00 | 0.01 |
| 80  | 1.90 | 0.01 |
| 70  | 2.80 | 0.01 |
| 60  | 3.70 | 0.02 |
| 50  | 4.60 | 0.02 |
| 40  | 5.50 | 0.03 |
| 30  | 6.40 | 0.03 |
| 20  | 8.13 | 0.05 |
| 10  | 13.27 | 0.10 |
| 1   | 24.24 | 1.00 |
| 0   | 25.00 | Error |

Thankfully libjxl has a built in function to convert Quality to
Distance, so I've swapped it in.
Unable to test it myself, but it's a simple fix that I ran by another
libjxl dev too.

---------

Signed-off-by: Jonathan Brown <jonathanbr30@gmail.com>
2025-10-31 12:58:03 -07:00
Larry Gritz dcdb216a4c docs: Update/correct explanation of "openexr:core" attribute, and typo fixes (#4943)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-31 12:39:42 -07:00
Jesse Yurkovich b5219dfbe0 admin: Correct spelling in build_problem.md template (#4945)
Small typo in our `build_problem.md` github template.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-10-31 12:39:14 -07:00
Larry Gritz 4b71e0523c testing: Update ref images for heif (#4941)
I think that in a recent checkin, we accidentally made some ref outputs
for this test be identical, that were supposed to be for when libheif is
built without avif support.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-30 22:42:05 -07:00
Larry Gritz 70b9bd380e ci: We were not correctly setting fmt version from job options (#4939)
Ugh, used the wrong option name. Also, it's sufficient to just do it
with the env variable, don't need extra logic in ci-build.bash.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-28 13:03:11 -07:00
Larry Gritz 6e9e5cef05 fix: uninitialized value revealed by clang-21 warning (#4940)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-27 00:02:59 -07:00
Larry GritzandCopilot e937e8f1ee ci: simplify ci workflow by using build-steps for old aswf containers, too (#4932)
Trick learned from the rawtoaces CI workflow

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-26 15:10:26 -07:00
Oktay Comu 4bf81a0af2 feat(openexr): ACES Container hint for exr outputs (#4907)
Closes #4791 

This PR introduces the `oiio:ACESContainer` hint for OpenEXR outputs.
The hint can take one of the following values: `none` (default),
`strict`, or `relaxed`. If not `none`, the spec will be checked to see
if it is compliant with the ACES Container format defined in [ST
2065-4](https://pub.smpte.org/pub/st2065-4/st2065-4-2023.pdf). If it is,
chromaticities will be set to the ACES AP0 ones, and the
acesImageContainerFlag attribute will be set to 1. In `strict` mode, if
the spec is non-compliant, the output will throw an error and avoid
writing the image. While in `relaxed` mode, if the spec in
non-compliant, only a warning will be printed and the attributes
mentioned above will not be written to the spec.

I've added several tests under `openexr-suite`. These use oiiotool to
attempt writing several EXRs with the `oiio:ACESContainer` hint.

---------

Signed-off-by: glowies <self@oktaycomu.com>
Signed-off-by: Oktay Comu <self@oktaycomu.com>
2025-10-25 19:04:36 -07:00
Zach Lewis 2ae555445e ci(wheels): unbreak wheel release + other enhancements pt 1 (#4937)
## Description

This PR fixes and improves a handful of wheels-related items:
- Fix an issue where wheels produced with v3.1 releases were not getting
uploaded to pypi
 - Update cibuildwheel to latest version (v3.2.1)
- Remove the manylinux2014 builds, replace with manylinux_2_28 builds
where applicable
 - Add CPython 3.14 wheels
 - Update macos-x86 runner to `macos-15-intel`
 - Update Python typestubs

## Notes
- This PR ends support for pre-built wheels for glibc < 2.27 (CentOS-7
etc). However, the module can still be pip-installed locally, provided
devtoolset-7+ (e.g., gcc-9+) is available.
- Unless we arrive at a more elegant solution, we must remember to
change the conditional in the "upload_pypi" step for every major OIIO
release.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-10-20 11:36:58 -07:00
Larry Gritz 4c27f292bf build: Make dependency report more clear about what was required (#4929)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-20 11:13:12 -07:00
Brecht Van Lommel aa31926cba fix(ffmpeg): 10 bit video has wrong green channel (#4935)
Due to apparent limitations or bugs in swscale, there is a problem
reading the 16 bit green channel that is not 4 byte aligned like red and
blue. Reading each channel into its own plane solves the issue.

This also addresses an existing comment about 32 bit float being read as
16 bit. This needed the same mechanism of reading separate planes, so
the same code is reused to implement that.

Resolves #4901

I added a 10 bit test file encoded with VP9 and Matroska, same as the
existing 8 bit test file to maximize compatibility. I verified this now
converts correctly to a HDR PNG file.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-10-18 20:23:35 -07:00
Larry Gritz 0f72f73993 ci: Try to avoid ffmpeg install failures (#4936)
A small portion of time -- maybe 10%, just enough for many CI workflow
runs to have a single job fail -- our attempt to `dnf install ffmpeg`
fails.

I thought maybe it was an intermittent, transient failure. But looping
to try multiple times with delays in between does not help. A job that
fails once either succeeds initially or fails over and over. I'm now
leaning toward the belief that rather than a transient failures, there
are just a subset of GHA runners that will always fail, and the
semi-random nature of our job failures is just random luck of the draw
in runner selection.

Anyway, so I'm not going to merge the try-in-a-loop approach. Instead,
this PR just makes ffmpeg an optional dependency, so the failures to get
the dependency won't fail the OIIO build and therefore the CI. It seems
like most of the time we really do get the dependency, but I'm out of
better ideas at the moment.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-18 20:22:33 -07:00
Larry Gritz 24d4ff0bb1 feat(openexr): Support for idManifest and deepImageState (#4877)
Support for retrieving and setting the idManifest for deep image files
with object ID channels. This is an OpenEXR feature where the image
header can contian metadata that maps all the object ID channel integer
codes to strings of the object names.

We report this in the ImageSpec as the metadata
"openexr:compressedIDManifest", whose type is an array of uint8 (byte)
values. It is encoded the same way it appears in the exr file itself:
the first 8 bytes are a little endian uint64_t giving the *uncompressed*
size of a serialized OpenEXR IDManifest object, and then starting at
byte 8, the zip-compressed seriailized IDManifest. Therefore, the
compressed block size is the size of the metadata blob, minus 8 bytes
for the length. It is up to the caller to use the OpenEXR APIs to turn
this compressed serialized IDManifest into a fully expanded IDManifest,
if that's what they want to do.

It works for output, too, so it should copy the manifests correctly
between files, even if the app doesn't know what to do with the binary
data it contains.

Also added support for deepImageState, which we previously had ignored.
We report this as the metadata "openexr:deepImageState", a string, which
if present has one of the values "messy", "sorted", "non_overlapping",
or "tidy".

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-18 20:15:05 -07:00
Larry Gritz d423a14377 fix(iff): Handle non-zero origin, protect against buffer overflows (#4925)
IffInput::read_native_tile was simply incorrect for images with nonzero
data window origin. Fix!

Also switch the forumulation to use spancpy rather than memcpy, to be a
little more careful that we are't overwriting the presumed sizes of the
buffers.

And while I'm in there, I realized we can hold the mutex for less time.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-18 20:14:40 -07:00
Larry Gritz 743a267bbb ci: drop deprecated macos-13 (intel) platform, add macos-15-intel (#4930)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-16 22:31:34 -07:00
Larry Gritz ff46d14532 build: allow auto-build of just requried packages (#4927)
The CMake (or env) variable OpenImageIO_BUILD_MISSING_DEPS enumerates
dependencies to try to locally auto-build if not found. If set to "all",
it will build them all.

This patch also allows you to set it to "required", which will try to
auto-build any missing dependences that are required, but not bother
with non-required missing packages.

It also works to use required and also have list items naming additional
optional dependencies, such as

    -DOpenImageIO_BUILD_MISSING_DEPS="required;WebP"

build all required dependecies, and also WebP (which is optional), if
they are no found already installed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-14 23:07:12 -07:00
Danny GreensteinandLarry Gritz 2ccad14cd6 deps: cmake script to auto download and install the openjpeg dependency (#4911)
sub task of :
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4387
for sep 2025 dev days.

Adding a autobuild cmake file for OpenJPEG.

Includes some changes to recognize and use static OpenJPEG if available.

---------

Signed-off-by: grdanny <danny.gr@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2025-10-14 17:19:28 -07:00
Larry Gritz 8def63c1e4 fix(api/docs): Fix IBA::set_pixels declaration and docs (#4926)
Two places where the docs and header for ImageBuf::set_pixels did not
match.

In one case, the docs were right, the declaration was supposed to have a
parameter that was a `const image_span<T>&` but the `&` was left out.
Now, if this was an actual linkable function, we wouldn't be able to fix
it until a compatibility-breaking boundary. But because it's a template
and inline, I believe it is actually safe to fix it in situ without
breaking ABI compatibility (and it seems to pass our ABI check in CI).

In the second case, the header was correct but the docs used the wrong
declaration (leaving out a `const`) and made the docs fail to pull in
the right explanation.

Fixes #4923

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-12 09:19:28 -07:00
Larry Gritz f6be156cb2 fix(win): Address Windows crashes from issue 4641 (#4914)
Fixes #4641

Has something to do with mixing Windows compiler versions, there's a
subtle ABI compatibility issue that this sidesteps.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-11 11:42:40 -07:00
Larry Gritz 6bc8627803 ci: For python wheel generation, use ccache (#4924)
Building the python wheels takes a long time! I really hate waiting for
that when testing PRs, there must be a way to speed it up.

* For the wheel workflow, add cache actions to save and restore the
CCACHE_DIR. Hey, it's no easy feat to figure out what the path should be
to that directory, especially on Linux where the wheels are built in a
container, so the paths inside the container (where the wheel is built
and the C++ compilation happens) don't match the paths outside the
container (where the cache restore and save actions execute).

* I had a heck of a time on Linux trying to get a pre-built ccache
installed and had to resort to writing a bash script to build ccache
itself from scratch, which is much more expensive than I'd like, but
we'll have to come back to fix that separately.

* Changed our "auto-build" utility build_dependency_with_cmake to print
the amount of time it takes to build each dependency.

* When auto-building, pass along CMAKE_CXX_COMPILER_LAUNCHER so that the
dependenencies also for sure use ccache.

* Use CMAKE_BUILD_PARALLEL_LEVEL on the wheel run to use all the cores
and compile in parallel. (We did that on the regular CI but I think not
for the wheel building.)

* Fixes to the logic in our compiler.cmake where it tries to use ccache
even if the magic CMAKE_CXX_COMPILER_LAUNCHER isn't set -- I have come
to believe we were doing it wrong before, it was having no effect, and
all along we only got ccache working on CI because we *also* set the env
variable.

* For CI, set CCACHE_COMPRESSION=1 to make the caches take less space
against the precious limit of how much cache we can use total on GHA.

So, the result of all this:

**Previous times (typical), and first wheel run for any git branch**

| platform    | total | compile OIIO + deps |
| ----------- | ----- | ------------------- |
| Linux Intel | 10:35 |  500s               |
| Linux ARM   |  7:20 |  294s               |
| Mac Intel   | 20:18 | 1146s               |
| Mac ARM     |  7:19 |  388s               |
| Windows     | 14:00 |  759s               |

**With ccache active, 2nd or more wheel run for a git branch**

| platform    | total | compile OIIO + deps |
| ----------- | ----- | ------------------- |
| Linux Intel |  3:33 |  98s                |
| Linux ARM   |  3:34 |  83s                |
| Mac Intel   |  5:01 | 212s                |
| Mac ARM     |  2:30 |  95s                |
| Windows     |   N/A | not using ccache    |

The "compile OIIO + deps" column is the isolated time to build OIIO and
also any auto-building of dependencies from source that we do. But it
does not include any other setup, such as 40-60s of container setup on
Linux, 20-40s setting up Python on Mac, or -- ick! -- 45-60 seconds to
build cmake itself from scratch.

So this is considerably better, speeding up the full wheel workflow by
2-4x on all platforms but Windows. Remaining room for improvement
(possibly in subsequent PRs, hopefully not necessarily by me):

* Is there a way to use ccache on Windows? I'm not sure if there is,
when using MSVS.
* Find a way to install pre-built binaries on Linux rather than building
ccache from scratch, which would save almost a whole minute per job.
* Organize each platform to build all of its wheels (i.e. all of the
python versions we are building for on that platform) in a single job
rather than as completely independent jobs, allowing (a) the fixed
per-job overhead such as container initialization, and installing
python, and building of certain dependencies to happen ONCE per platform
instead of separately for each wheel, and (b) the magic of ccache to
speed up the builds *across* those wheels, since only a tiny amount of
OIIO source codes depend on python at all.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-10 18:51:18 -07:00
Valery Angelique 6f25722043 build(gif): Add GIF library auto-build (#4921)
Fixes #4387 

Added build_GIF.cmake module for GIF library dependency management.
Since GIFLIB does not provide a CMakeLists.txt, I created a custom one
that gets added to the cloned repository.

The flow is similar to other libraries with cmake support, so I added a
conditional statement in the build_dependency_with_cmake macro that, if
a cmakelists.txt path is provided, will add/replace existing
CMakeLists.txt files on the cloned repository.

Signed-off-by: Valery Angelique <71804886+vangeliq@users.noreply.github.com>
2025-10-05 20:57:01 -07:00
Larry Gritz b82f3496fa fix(api): Restore definition of OIIO_NAMESPACE_USING macro (#4920)
Version 3.1 removed this definition, thinking it was safe because we
didn't use it anywhere, didn't document it, and what it expands to
(`using namespace OIIO`) isn't any longer than the macro name, so is
pointless to use.

But downstream projects did use it. Oops.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-03 20:50:09 -07:00
Larry Gritz 046b20f605 docs: CHANGES and other misc docs changes from the 3.1 release (#4918)
Forward-porting some docs touch-ups that were part of the 3.1 release
staging.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-02 18:42:56 -07:00
Larry Gritz 9529077914 deps: Support for OpenColorIO 2.5 (#4916)
A test needed updating because the set of color spaces in the built-in
config are different than for 2.4.

Fixes #4915

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-10-01 12:51:44 -07:00
shanesmith-dwa 0e5c5a5a36 feat(jpeg-xl): ICC read and write for JPEG-XL files (issue 4649) (#4905)
This PR addresses
[4649](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4649)
implementing ICC read and write support for JPEG-XL.

Fixes #4969

The jxl testsuite directory was added with tests.

---------

Signed-off-by: Shane Smith <shane.smith@dreamworks.com>
2025-09-30 12:32:48 -07:00
Larry Gritz 46ce8ee85e build: Update autobuild defaults for some dependencies (#4910)
Raise the version we "autobuild" for some packages:
* OpenJPEG 2.5.2 -> 2.5.4
* pybind11 3.0.0 -> 3.0.1
* libtiff 4.6.0 -> 4.7.1
* webp 1.4.0 -> 1.6.0
* libjpeg-turbo 3.0.4 -> 3.1.2

And some minor debugging and other aids along the way:

* After a build, on linux, do a `ldd` to verify what libraries are
linked dynamically for the logs.
* Enhance build_dependency_with_cmake macro to allow optional commands:
GIT_COMMIT, GIT_SHALLOW, QUIET

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-28 23:21:01 -07:00
omcaif 168d797977 build: fix some build issues encountered on a musl libc system (#4903)
Two small fixes to  compile on musl libc systems.

The first commit is about the use of `__WORDSIZE`, which is not a
standard define and is defined another header in musl libc. I decided to
fix this by following what was done in `libdnf` in [this
commit](https://github.com/rpm-software-management/libdnf/pull/1159/commits/82a07dbe6e53fccfe3a8f8e0d951618e0aa72999).
However, there are other ways, such as including `bits/reg.h` or
`bits/user.h`, which define `__WORDSIZE` in musl libc, or using
`__LP64__` to check for 64 bit instead (inspired by [Alpine Linux's
patch](https://gitlab.alpinelinux.org/alpine/aports/-/blob/0f71e9504b59049e0ec1abb486ba455ab2650c83/community/openimageio/0001-fix-compile-error.patch)):

```c
#if defined(__GNUC__) && (__WORDSIZE == 64 || (defined(__LP64__) && __LP64__)) && !(defined(__APPLE__) && defined(__MACH__)) || defined(__NetBSD__)
```

The second commit is about the use of the `feenableexcept` function.
This function is only defined by glibc. The original code assumed all
Linux systems use glibc (checking `__linux__` define), so I just changed
it to check for glibc directly (by checking the `__GLIBC__` define).


I have only tested it on my musl libc system. I think just compiling it
on different systems is enough of a test in this case...

---------

Signed-off-by: omcaif <103504667+omcaif@users.noreply.github.com>
2025-09-26 21:33:25 -07:00
Carine Touraille d9442d27f4 fix(oiiotool): Ignore empty subimage(s) when calculating non-zero region (#4909)
Fixes #4799

When trimming an image that contains an empty subimage, the resulting
ROI unexpectedly included the top-left pixel even if zero in all
subimages.

To avoid this, empty ROIs are ignored when computing the overall
non-zero region.
If all subimages are empty, the first subimage ROI is used and doctored
to be 1 pixel.

Two tests have been added to the oiiotool testsuite:
 - 1 to check the trimming of an empty image
 - 1 to check the trimming of a non-empty image with an empty subimage

Signed-off-by: Carine Touraille <carine@raynault.com>
2025-09-26 19:15:53 -07:00
Connie Chang b570c0ad73 docs: Add type hints to Python docs (#4908)
Closes https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4752

Add Python type hints into documentation, in places where example code
defines a function. That ended up being just
`src/doc/pythonbindings.rst`. I also updated `testsuite/runtest.py` and
the functions in `testsuite/docs-examples-python/src/docs-examples-*.py`.

While I was in `pythonbindings.rst`, I noticed a couple places with
`py::method` (note the double colon). These lines didn't render in the
docs, so I removed the extra colon to match other usage.

I locally built the docs to make sure html looks good. I ran the tests
with `ctest` and the tests ran, so I'm taking that as a sign that
`runtest.py` still works.

Signed-off-by: Connie Chang <connie.chang@dreamworks.com>
2025-09-26 18:28:25 -07:00
Larry Gritz ca4499a4dd ci: require all dependencies, with explicit exceptions (#4898)
We recently had a problem where our use of a dependency was broken, and
it had gone unnoticed because none of our CI jobs actually had the
dependency present and tested it. This can easily happen because so many
of our dependencies are "optional" -- our build will just give a warning
and silently disable the functionality that would have been supported by
the missing dependency.

We have long had build-time options `OpenImageIO_REQUIRED_DEPS`, to
consider specific dependencies (or "all") required even if they would
ordinarily be optional, and `OpenImageIO_OPTIONAL_DEPS`, to make
exceptions. But we didn't use these in CI.

So this PR makes sets `OpenImageIO_REQUIRED_DEPS=all` to make all
dependencies ostensibly required, and then list all exceptions
explicitly. This should make it much more difficult in the future to
make a mistake where use of a dependency is completely untested in our
CI without our being aware of it. And it gives us a visible "hit list"
of untested or under-tested dependencies to slowly whittle down.

Some changes that came long for the ride:

* checked_find_package: explicitly disabled packages are treated as
optional.

* cuda_macros.cmake: Only look for CUDA on platforms that might
conceivably have it (i.e., don't even look on Mac).

* Separate linux-aswf from linux-ubuntu into separate job groups,
because that makes it easier to have shared commonalities of which
dependencies they test.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-25 14:45:32 -07:00
Jesse Yurkovich f0fe800a3d fix(oiiotool): Use normalized path when creating wildcard path pattern (#4904)
On Windows, using a wildcard input path containing `\` back slashes
would lead to failures because it would be compared with file paths
containing `/` forward slashes. Use the existing
`Filesystem::generic_filepath` API (which calls `path::generic_string`)
to get a normalized path containing consistent directory separators.

An example of the existing failure:
```
.\oiiotool.exe -v t:\render\foo_#.png --resize 160x90 -o t:\smaller_#.png

oiiotool WARNING : No frame number or views matched the wildcards
oiiotool ERROR: read : File does not exist: "t:\render\foo_#.png"
Full command line was:
> oiiotool.exe -v t:\\render\\foo_#.png --resize 160x90 -o t:\\smaller_#.png
```
Workaround - without this PR you would have to use an input path
containing `/`:
```
.\oiiotool.exe -v t:/render/foo_#.png --resize 160x90 -o t:\smaller_#.png
Reading t:/render/foo_0001.png
Writing t:\smaller_0001.png
Reading t:/render/foo_0002.png
Writing t:\smaller_0002.png
```

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-09-25 13:52:04 -07:00
Larry Gritz abce1cb252 ci: Add more exceptions to when we test docs building (#4899)
These additional things need not trigger a CI test build of the online
documentation:

* Build scripts
* Markdown docs that aren't part of the documentation we're generating
(like the main README.md, INSTALL.md, etc.)

Doing so just makes CI take longer and wastes resources.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-24 15:41:25 -07:00
vvalderrv 2c203705c2 fix: sonar scan guard (#4902)
We recreated the SonarCloud project to clear the 404s. This commit fixes
the workflow condition by comparing to the string '1', so the Sonar scan
step runs and uploads results.

Updates the GHA workflow guard so the Sonar scan actually executes:
- Change `if: inputs.sonar == 1` → `if: inputs.sonar == '1'` because
`inputs.sonar` is a string (from `workflow_call` inputs).

No unit tests added (CI-only change). Validation: run the “Analysis”
workflow and confirm SonarCloud receives results.

Signed-off-by: Vanessa Valderrama <vvalderrama@linuxfoundation.org>
2025-09-23 22:18:26 -07:00
Larry Gritz f9137b1b5c CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-19 22:05:04 -07:00
Larry Gritz 8530a870bf build: fix openjph target use (#4894)
PR #4875, switched to using openjph's exported cmake config instead of
our own FindOpenJPH.cmake, and in the process also renamed OpenJPH ->
openjph to follow their convention.

But I botched it, still using the old OPENJPH_LIBRARIES (etc.)
variables instead of fully switching to the correct targets exported
from their config.

This PR minimally fixes that error, re-enabling use of openjph.

Fixes #4893

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-18 14:25:42 -07:00
Larry Gritz 5092f32618 fix: gif output didn't handle FramesPerSecond attribute correctly (#4890)
The version of open that takes an array of subimage specs didn't use
them properly for finding the FramesPerSecond hint (or the ioproxy!).

Fixes #3716

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-17 20:56:38 -07:00
Zach Lewis 333b63bac6 ci: Fix broken python wheel building (#4855)
Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-09-16 17:04:15 -07:00
Anton Dukhovnikov da4fb55e6b feat(raw): add thumbnail support to the raw input plugin (#4887)
This adds thumbnail support to the raw input plugin. 

Fixes #4107

This supports 3 of the 4 formats of thumbnails Libraw provides: BMP,
JPEG, JPEGXL(untested). H265 is not supported, I don't know of any
camera using it, and expect the code being significantly different from
the other formats, given that the H265 is a movie container.

One thing I don't like about this implementation - I understand there is
no way to query the number of thumbnails available in the file? We are
expected to iterate, until `get_thumbnail()` returns false? If
`get_thumbnail()` returns false not because there is no thumbnail for
the requested index, but any other reason, we are not going to try
reading past that index.

## Tests

I have tested manually with a bunch of raw images having either JPEG or
BMP thumbnails.

I have not tested the JPEGXL branch, as I'm not aware of any cameras
using that for thumbnails. The code is identical to the JPEG branch
though, so I'm not expecting any issues with that.

I couldn't see any unit tests around the thumbnail functionality at all.
Should I add some? I assume we can't use `oiiotool` for this?

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-09-16 16:12:04 -07:00
Larry Gritz b602875214 ci: Fix testsuite/heif ref output (#4892)
PR #4880 checked in some output reference that contained version
numbers, which passed in main but failed when backported to 3.1. This
repairs it and makes the output suitable for any version that contains
the patch.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-16 15:08:26 -07:00
vvalderrv 0afe9ef567 fix: Switch to compile-commands (#4879)
Fix SonarCloud analysis failures by switching the C/C++ configuration
from the
deprecated `sonar.cfamily.build-wrapper-output` property to the current
`sonar.cfamily.compile-commands` property.

**Changes**
- Remove `sonar.cfamily.build-wrapper-output` from
`sonar-project.properties`.
- In `.github/workflows/build-steps.yml`, pass  
`--define
sonar.cfamily.compile-commands="$BUILD_WRAPPER_OUT_DIR/compile_commands.json"`.

**Root cause**  
The SonarCloud config still used the deprecated
`sonar.cfamily.build-wrapper-output`
property. The current CFamily analyzer expects a `compile_commands.json`
(produced by build-wrapper). Using the old property caused scanner
failures and
blocked analysis.

**Validation**  
Regenerated `bw_output/compile_commands.json`, ran `sonar-scanner`, and
confirmed the scan completed and uploaded successfully.

**Tests**

CI-only change. Verified locally by running the scanner against a fresh
build-wrapper capture.

---------

Signed-off-by: Vanessa Valderrama <vvalderrama@linuxfoundation.org>
2025-09-15 12:23:39 -07:00
Larry Gritz d6653b95ef admin: Adjust license notices of A2-only source (#4884)
There are still a few historical authors who never signed on to the
relicensing of OpenImageIO from BSD-3-Clause to Apache-2.0 two years
ago, usually because we could find no current way to contact them.

The few (< 25) files that still had their extant code were therefore
marked as using both licenses. They they almost always are down to just
a few lines in the whole file that are still original to those authors
(and therefore BSD), so every once in a while, natural code churn and
rewrites of what they touched remove the very last of these lines from a
file, leaving that file entirely Apache-2.0. I noticed that this was the
case for these three files, and so removed the reference to BSD license,
which no longer applies.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-15 10:50:01 -07:00
Brecht Van Lommel b9e3a9931f fix(ffmpeg): FFmpeg sets zero oiio:BitsPerSample (#4885)
Many codecs don't provide `bits_per_raw_sample`. The bit depth of the
luma channel is the closest equivalent to a single bit depth then, while
the chroma channels may be subsampled.

Tested on basically all the video files on my computer, they all give a
non-zero bit depth that looks correct now.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-09-15 10:47:05 -07:00
Zach Lewis c673643ba1 ci: disable macos-x86 wheels. (#4886)
Temporary workaround to unblock publishing of other wheels for 3.1
release

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-09-15 10:43:17 -07:00
Larry Gritz 98f43a663a ci: better spread of libpng versions we test against (#4883)
* The "oldest" didn't really test against the oldest we claim to
support.
* The "latest versions" didn't really test against the latest versions.
* The "bleeding edge" didn't really test against libpng master.
* The auto-build was unnecessarily a few releases behind.
* Documentation touch-ups

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-14 14:45:20 -07:00
Brecht Van Lommel 40810e2e0b feat(heif): Read and write of CICP and bit depth 10 and 12 (#4880)
* Read and write 10 and 12 bit images
* Read and write CICP

This makes it possible to write HDR images that are much smaller than
PNGs, in a file format that is supported in all modern web browsers.

By setting the matrix coefficients, the library will perform RGB to YUV
conversion on write. The YUV to RBG conversion was already happening on
read automatically.

A future improvement would be a better default choice of matrix
coefficients for writing. When no CICP is specified or when CICP is read
from PNG, then no conversion to YUV will be performed and compression
will not work as well. This is the same behavior as before. When there
is support for conversion between CICP and display interop ID, a good
default choice for matrix coefficients could be made as part of that.

Tests for CICP and 10 bit were added.

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-09-13 21:54:02 -07:00
Larry Gritz 8e9d4ff9f5 api: Versioned namespace to preserve ABI compatibility between minor releases (#4869)
This patch implements the new scheme that we hope will preserve ABI
compatibility across minor (yearly) releases.

Brief summary:

* We will strive to have annual minor releases (e.g., 3.1.x -> 3.2.x)
  be ABI/link backwards-compatible, as strongly as monthly patch
  releases (3.1.5 -> 3.1.6) always have been. Every-several-years
  major releases (3.x -> 4.x) are still a potential full compatibility
  break.

* Consumers of OpenImageIO don't need to change their code, and can
  just continue to refer to `OIIO::Foo` or `OIIO::Bar()` as always.

* Internally, all items in the public OIIO APIs will be in a versioned
  inner namespace, and will continue to live in the versioned
  namespace where they were first introduced, forever. (Well, until the
  next first-digit-changing major release, at which point we will clean
  up the old cruft and version everything up.)  If anything needs to
  change in an ABI-breaking way, it will be *duplicated* in the newer
  namespaces, so the old version continues to be available in the old
  namespace.

* The new header nsversions.h contains a long and detailed comment
  explaining how all the new declarations work.

---

Detailed explanation:

"Major" or "first digit" releases, which only happen once every
several years for us, are full ABI+API breaks. Previously, "minor" or
"second digit" releases, which are annual, have fully incompatible
ABIs, with separate namespaces to enforce it. Here, we are striving to
allow our annual/minor releases to no longer break ABI, to make
upgrading
easier for downstream users.

The basics are that once a symbol is introduced, it will forever live
in the namespace of that release. Subsequent release years will have
their own namespaces, but will either alias or duplicate the original
symbols.  This is enabled by our recent (in the lead-up to 3.1)
introduction of a split 2-part namespacing scheme. So 3.2 is the first
release that has the potential to perserve compatibility with 3.1 in
this way.

In this PR, I have done this for the whole codebase.  It works! -- as
measured by being able to have our automated ABI checker show 100%
back compatibility with 3.1. So currently, even though this is the
nascent 3.2 tree, everything in the public APIs live in the 3.1 ABI
namespace. And so they will remain, except for changes that cannot be
done without breaking ABI back-compatibility, which will then end up
with multiple versions in different versioned namespaces.

Let's look this over and decide if we like it. It does involve our
developers to do some hoop jumping and take extra care as we develop,
to keep things associated with the right namespaces.

Users of OpenImageIO shouldn't need to change anything on their end,
nor to be aware of this at all.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-13 19:02:33 -07:00
Larry Gritz 47a8a2d683 ci: fix analysis workflow configuration (#4881)
Something must have changed with the containers, it was failing on the
build step, before ever getting to the actual sonar analysis.

Switch to the same container and OCIO version that we use for the
regular 2024 era container CI.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-13 16:52:03 -07:00
Brecht Van Lommel 4945b57f65 feat(ffmpeg): Read CICP metadata, and add test (#4882)
The actual CICP reading code is trivial.

Also recognize mkv (Matroska) extension for the test.

Add test using Matroska + VP9, to maximize the chance of an ffmpeg build
supporting them. They are royalty free, built into ffmpeg and relatively
old.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-09-13 16:50:42 -07:00
Jesse Yurkovich 1cec592fbf feat(webp): Support reading/writing the ICCProfile attribute (#4878)
Enable ICCProfile attribute support for WEBP for both input and output.
Like other formats this support is passive; pixel data will not be
altered by the mere presence of the ICCProfile attribute (i.e. it
functions like other informational metadata only).

The WebP API is a bit odd when it comes to writing the ICCProfile. We
must use the "mux" API set; the "advanced" API is apparently not
advanced enough to add the metadata to the file. This wouldn't be too
bad except that the mux API is at odds with how we write out the data.
Before: When it comes time to do the file write, we would pass our own
file writer into webp. The writes would go straight to disk. Now: If ICC
profile data is necessary to write, we let webp use its own writer to
write to memory. We then assemble the in-memory file and the ICC profile
data together and pass that entire package to our writer as a final
step.

When no ICC profile data is used, the old write behavior is kept.

Added `oiiotool` test variations which uses ICC profiles with WEBP.

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-09-13 14:36:19 -07:00
Zach Lewis 4d1b420b5e feat: CICP metadata support for PNG (#4746)
This PR addresses the primary concern of #4678 -- implement support for
reading and writing the `cICP` chunk for PNGs.

CICP (Coding Independent Code Points) is a means for using a tuple of
integers to communicate characteristics of a variety of, traditionally,
video encodings. The tuple is a series of four values that map to
integer enumerations (codified in [ITU-T
H.273](https://www.itu.int/rec/T-REC-H.273-202407-I/en)) representing a
certain ColourPrimaries, TransferCharacteristics, and
MatrixCoefficients, as well as a VideoFullRangeFlag.

In particular, CICP is used for describing HDR encodings to browsers and
image viewers capable of displaying the image as intended. For example,
if one were to write P3-D65 PQ-encoded RGB values to a PNG, it will only
look "correct" if there's an appropriate `cICP` chunk describing the
primaries (14) and transfer function (16); without such metadata,
PQ-encoded images will appear significantly darker and lower in
contrast.

Internally, CICP metadata is stored in a `int[4]` type `CICP` ImageSpec
attribute.

This PR adds the following:
- An oiiotool `--cicp` flag for setting, modifying, or removing CICP
metadata for the top image
- Methods for reading and writing PNG `cICP` chunk metadata <-->
ImageSpec `CICP`
  - Tests


I've included tests. I've also embedded CICP metadata in the existing
16-bit test png in the testsuite.

But to see what this is all about with your own eyes, you can quickly
convert a scene-linear AP0-encoded EXR to a PQ-encoded P3D65 HDR PNG
with the following command:

`$ oiiotool -i input_linap0.exr --ociodisplay:from=ACES2065-1
"ST2084-P3-D65 - Display" "ACES 1.1 - HDR Video (1000 nits & P3 lim)"
--cicp "12,16,0,1" -o output_p3d65pq.png`

If you compare in a capable image viewer on a capable display the image
produced with the above command compared to another one that lacks CICP
metadata, you should see a pretty significant difference:

`$ oiiotool -i output_p3d65pq.png --cicp "" -o output_no_cicp.png`

("Preview" on a ~5 year old Macbook should suffice).

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-09-13 13:10:56 -07:00
Larry Gritz d6f5bafa9d ci: Test freetype 2.14 and document that it works (#4876)
Freetype 2.14 was recently released and just became the default for
homebrew.

It seems that no changes are needed on our end and no output references
even need to change!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-11 16:26:16 -07:00
Larry GritzandCopilot 81acb236c3 build: several OpenEXR and OpenJPH build related fixes (#4875)
Original changes and goal:

* Bump our "latest releases" CI tests to OpenEXR 3.4.0
* cleanup: dead guard removal for openexr -- our minimum OpenEXR release
supports float vectors, so we don't need any `#if` guards for it
anymore.
* Fix warnings related to mixing Core and C++ library constants for
H2J2K compression enums within a switch statement (only noticed on ARM
Linux with Clang 18).

But it seems that OpenEXR 3.4's auto-building of OpenJPH (to support
exr's new h2j2k compression methods) revealed that our CI wasn't
building and testing against OpenJPG as well as we thought. So:

* Clean up some openjph API use and type mismatches
* Suppress warnings on clang and recent gcc versions had with the
OpenJPH headers and our use of them.
* Fix our test scripts and reference output for the htj2k tests; I think
maybe they weren't running at all before, and nad some incorrect file
paths.

Finally,

* When no OpenEXR is found, update the auto-build version to 3.3.5. I
wish I could go all the way to 3.4.0, but the OpenEXR 3.4.0 currently
auto-builds OpenJPH in a way that (I think incorrectly) installs the
OpenJPH components in ways that can overwrite or break existing
installations.

* Remove FindOpenJPH.cmake, the nomenclature clashes with the lowercase
"openjph" used by the new OpenJPH exported cmake configs.
* But those are only generated for OpenJPH >= 0.21.2, so make that our
new minimum. (This only affects OIIO 3.1 and higher, so it's safe to do
this.)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-09 15:54:17 -07:00
Larry Gritz 0b2e4a3ac5 feat(oiiotool): allow easy splitting of subimages by name (#4874)
Say you need to take a multi-part exr file and split it into separate
files for each part. (Note: what OpenEXR calls "parts", OIIO calls
"subimages.") You could do this

    oiiotool multipart.exr --sisplit -o:all=1 "part.%04d.exr"

But this would name the parts part.0001.exr, part.0002.exr, etc. Maybe
you would prefer to split them into files that contain the subimage name
rather than just the inscrutible index number (which may also not be
consistent across files)? You could try this dance to loop over the
subimages and write each one with a name extracted from its metadata:

oiiotool multipart.exr --for i {TOP.SUBIMAGES} --dup --subimage {i} -o
"subimage_{TOP.'oiio:subimagename'}.exr

That works, but that's a little awkward and hard to remember off the top
of your head. Perhaps instead we would prefer a simpler version:

oiiotool multipart.exr --sisplit -o:all=1
"part.{TOP.'oiio:subimagename'}.exr"

This PR makes that last command work. It actually only required a small
change, which is that the function that handles the `-o` command needs
to defer the evaluation of the expression subsitution in the filename to
occur separately for each subimage being output, rather than just once
for the whole `-o:all=1` (which would have baked the FIRST subimage name
into all the output file names).

Docs are updated to give examples of how to do this.

Also fixed a silly typo in the test script.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-09-08 20:02:08 -07:00
Alex Fuller 7aabc2b2ac build: Look for boost headers for OpenVDBs older than 12 (#4873)
Signed-off-by: Alex Fuller <boberfly@gmail.com>
2025-09-06 14:47:26 -07:00
Larry Gritz 5280eb69a8 build: ffmpeg 8 support (#4870)
* Try a build against ffmpeg 8 -- seems to work out of the box, so
document that we support that version in INSTALL.md.
* Augment FindFFmpeg.cmake to correctly identify 7.1 and 8.0 by the very
non-intuitive versioning scheme of ffmpeg's headers.
* Add a FFMPEG_EXTRA_LIBRARIES variable to FindFFmpeg.cmake to allow us
to easily inject extra library dependencies (coincidentally, I need this
at work to force it to use static libraries).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-31 14:36:03 -07:00
Todica Ionut b979bace3e exr: OpenEXR 3.4 supports two compression types for HTJ2K (#4871)
`htj2k32` or `htj2k256` compression options.

Signed-off-by: Todica Ionut <todicaionut2000111@gmail.com>
2025-08-29 09:55:00 -07:00
Larry Gritz 1c50410cb8 build: clean up obsolete logic for old compilers (#4849)
* Enforce gcc, clang, and apple clang minimum versions.

* Raise advertised minimum clang version to 10.0. Error for clang < 5,
  which we know is the true minimum because earlier than that won't
  support C++17 which we require. But in truth, we haven't tested
  versions older than 10.0 for a long time, so we should not be
  implying we know older versions will work or that we will support
  them.

* Simplify cases no longer relevant for older gcc and clang.

* Remove unneeded gcc guard in simd.h.  I think it was important only
  for gcc 5! But it was also preventing the slightly faster construct
  from activating for clang. Seems to pass all our CI jobs with this
  simplified.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-23 10:37:22 -07:00
Larry Gritz 0b7ff61082 build: Some more minor wheel workflow changes after the py 3.9 bump (#4867)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-22 14:20:14 -07:00
Larry Gritz 967eaf8464 ci: Update ABI standard after bumping 3.2 version number (#4868)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-22 14:17:01 -07:00
Larry Gritz ae5dca7865 admin: Prepare main for 3.2 development (#4864)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-22 13:09:30 -07:00
Larry Gritz 8706ca40a5 deps: Raise OpenColorIO minimum to 2.3 (#4865)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-20 09:21:25 -07:00
Larry GritzandDoug Walker 5e3c29e989 feat: color space renaming to adhere to CIF conventions (#4860)
This doesn't really change any of the color management algorithms per
se, or change how we use OCIO. That will come later.

But this tries as best as we can to shift to CIF recommended interop
names for color spaces.

* "srgb_rec709_scene" as the canonical name for what we used to refer to
as "sRGB".
* "lin_rec709_scene" as the canonical name for what we used to refer to
as "lin_rec709" and several other names.
* "lin_ap1_scene" as the canonical name for ACEScg.
* Stop setting "oiio:Gamma" metadata (though we still accept it for back
compatibility), instead using space names like "g22_rec709_scene" and so
on. We never came across files with truly arbitrary gamma.

If I've done it right, the old names will continue to be accepted as
aliases.

I recognize that changing the output (when printing metadata) to the
canonical names might be an inconvenience at first, but in the long run,
I think it's better to comply with the conventions that will be used for
USD, MaterialX, and OpenEXR.

I'm fine with the new wordy and pedantic names as what is stored
underneath as the "oiio:ColorSpace" alias or stored in an OpenEXR file
in the colorInteropID metadata. But I gotta say, from a UI/UX
perspective, I do not feel good about replacing "srgb" and "acescg" as
things that are easy to type and are known/understood by the vast
majority of OIIO users with a change to these wonky, error-prone,
hard-to-type names. So I'm very uncertain about changing oiiotool
documentation, say, away from the short and widely understood aliases.
Seeking feedback on what to do here!

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Doug Walker <doug.walker@autodesk.com>
2025-08-19 12:09:25 -07:00
Larry Gritz 4c4e397ef1 ci: Bump webp and openexr for "latest versions" test (#4861)
* Test against alpha of openexr 3.4.
* Document that we build against several things we know work but hadn't
updated INSTALL.md in a while.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-18 11:09:59 -07:00
Larry Gritz 3c50c41a70 ci: Lock down to ci-oiio container with correct llvm components (#4859)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-15 07:33:26 -07:00
Thomas Klausner 12300bb550 build: fix build on NetBSD (#4857) 2025-08-14 23:12:52 -07:00
Larry Gritz 79e7e39741 ci: Add a VFX Platform 2026 CI job (#4856)
And a bunch of other minor updates:
* Change from 'testing' to regular containers
* Add forgotten 'export'
* Update default self-build pybind11 to 3.0.0

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-14 10:53:49 -07:00
Larry Gritz 1cf0131869 docs: fix typo (#4848)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-08 14:20:01 -07:00
toge ae46891401 deps: use get_plane2 introduced by libheif 1.20.2 (#4851)
libheif 1.20.2 introduces `get_plane2()` for compatibility.
[ref](https://github.com/strukturag/libheif/issues/1566)

Because `get_plane()` has been marked as deprecated, we should use
`get_plane2()` instead.

---------

Signed-off-by: toge <toge.mail@gmail.com>
2025-08-07 12:25:10 -07:00
Larry Gritz 6a4ab7533b build: C++23 support (#4844)
* CI build as C++23 for bleeding edge test

* Fixes to disambiguate OIIO::print from std::print. Apparently, at
least for gcc14, std::print ends up in the global namespace and really
messes with things.

* Change to the library that contains the implementation of C++23
stacktrace in gcc14 vs 12/13.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-06 10:46:36 -07:00
Larry Gritz ad4d892b54 deps: Raise minimum supported Python from 3.7 to 3.9 (#4830)
Remove the CI jobs that tested VFXPlatform 2021 era, which we only were
still doing for the sake of python 3.7.
Also stop building Python wheels for any python versions older than 3.9
(we never built 3.7 wheels, but we did build 3.8).

This is just in main, a.k.a. OIIO 3.1, to be released in fall 2025 and
expected to be the main release series people are using in 2026.

VFX Platform has been 3.9+ since 2022, that's more than the "3 years
back" rule dictates. And in the real world, it hasn't been "current"
since 2020.

Just to be extra safe, I'm documenting 3.9 as the minimum and removing
all 3.7 tests, but I'm not having the build affirmatively reject 3.7 for
now, just in case somebody needs it. It should continue to work if
someone tries it, with no guarantees or support. But probably by the
time we do a 3.1 release in September, we will make it actually reject
3.7.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-04 22:20:36 -07:00
Larry Gritz 015cd24eeb CHANGES update (#4847)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-03 16:22:08 -07:00
Larry Gritz 2bbc0385f1 ci: Update ABI check standard (#4846)
ABI changed slightly after #4827. (Allowed in main but requires an
update of the reference.)

Also, bump to using the 2025 container for the ABI check.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-03 16:21:32 -07:00
Larry Gritz 9a990c8219 test: Update ref output (#4845)
PRs #4840 and #4841 crossed in flight with their tests passing
individually, but they needed one small adjustment to reference output
in order to to account for their interaction in main.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-01 12:51:30 -07:00
Larry Gritz e36031ce4e api: span-ify attribute/getattribute everywhere (#4838)
* span-ify ParamValue (including ctr and init)
* add span versions of attribute() and getattribute() to the classes
that have them: ParamValueList, ImageSpec, ImageCache, TextureSystem.

Much like the previous span/image_span additions we've made elsewhere,
now each of these calls has 3 flavors:
1. The previously existing -- but acknowledged "unsafe" -- version that
takes a TypeDesc and a raw pointer (which had better match the TypeDesc
in type and size, but who knows?)
2. A version that takes a TypeDesc and a `span<std::byte>` delineating
the raw memory to use, that must match the size implied by the type, and
is implemented underneath (for now) by calling the pointer version after
checking that the size is adequate.
3. A template version that takes a TypeDesc and a `span<T>` that must
match both in total size and appropriate type and asserts in debug
builds if they don't. It's implemented by calling the raw byte version
after the type check.

The third variety is the preferred one for apps to call, whenever
possible, but the others are still exposed for special cases.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-08-01 11:22:05 -07:00
Larry Gritz 4bba40d1ee build: Propagate CMAKE_MSVC_RUNTIME_LIBRARY (#4842)
* Allow CMAKE_MSVC_RUNTIME_LIBRARY to be initialized from an environment
variable of the same name. (CMake doesn't do that on its own.)

* If set, propagate CMAKE_MSVC_RUNTIME_LIBRARY to any packages we
auto-build within our build system.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-31 21:57:59 -07:00
Larry Gritz 9c4a3fd7ca exr: Don't assume unlabeled OpenEXR files are lin_rec709 (#4840)
New logic for reading OpenEXR files:

1. Recognize "acesImageContainerFlag" as always being lin_ap0_scene.
2. If the new colorInteropID is present in the metadata, that's the single source of truth about color space.
3. Otherwise, leave it blank, don't make any assumptions about color space.

It was a mistake for OIIO 3.0 to assume that completely unlabeled openexr
files are lin_rec709.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-31 19:24:22 -07:00
Larry Gritz a6cdf773c0 fix(ImageInput): incorrect IOProxy logic related to valid_file (#4839)
Inside ImageInput::create(), there's a section where the created
ImageInput tries to do a quick call to its valid_file() method to do an
inexpensive check that the file appears to be the right file format
corresponding to the ImageInput subclass. However, it always called the
variety of valid_file() that takes a string filename, ignoring the fact
that create() itself may have been passed an IOProxy, which should
always take precedence over trying to open a real file.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-31 10:16:27 -07:00
Larry Gritz 0a8c875241 fix(python): got strides wrong passing 2D numpy pixel array (#4843)
When passing numpy arrays for pixel blocks (say, to
ImageOutput.write_image), the sorting out of what the numpy arrays meant
had an error for the 2D case. A typo (or maybe copy pasta) got the
stride wrong.

This took a long time to be discovered because if there is more than one
channel, it gets passed as a 3D numpy array (height, width, chans). So
only for 1-channel images would it stumble across the bad code if it
were passed as a 2D (height, width) numpy array with no dimension for
channels.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-31 07:48:35 -07:00
Scott Milner 09ba836ed7 feat(maketx): Add maketx flags to increase feature parity with txmake (#4841)
Submitting this from my work as an intern on the RenderMan development
team.

- Bug fix with prman tile size for bumpslopes textures.
- `--slopefilter`: maketx has used sobel, txmake uses centraldiff
because sobel sometimes has ringing artifacts
- `--bumpinverts`: invert slopes in the s dir, txmake default behavior
has this on
- `--bumpinvertt`: invert slopes in the t dir, txmake default behavior
has this on
- `--bumpscale`: scale the strength of the resulting map
- `--bumprange`: support normal map values  on either [-1,1] or [0,1]
- `--keepaspect`: sets PixelAspectRatio metadata to match txmake `up`
resize behavior.

`txmake -bumprough 1 0 0 0 0 0`: `maketx --bumpslopes --bumpinverts
--bumpinvertt --slopefilter centraldiff`
`txmake -bumprough 2.5 0 0 1 0 0`: `maketx --bumpslopes --bumpscale 2.5
--bumpinvertt --slopefilter centraldiff`

---------

Signed-off-by: Scott Milner <smilner@pixar.com>
2025-07-30 17:14:14 -07:00
Larry Gritz 9b5b5257df perf(exr): Speed up OpenEXR non-core header read time (#4832)
Recent OpenEXR internals changes make header reads via the C++ library
dramatically slower if a Imf::IStream subclass does not implement the
size() and stateless-read method.

See https://github.com/AcademySoftwareFoundation/openexr/issues/1984

On my laptop, when forcing OIIO to avoid the "core" library and use the
C++ API to OpenEXR, this speeds up the reading of small exr files by
about 6x.

These changes were introduced with OpenEXR 3.3 and we never changed our
side.

(Also opportunistically added a couple DASSERT's to the existing
functions.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-23 21:20:47 -07:00
Vlad Erium 49efbd604d ffmpeg: Replace deprecated and soon removed avcodec_close with avcodec_free_context (#4837)
avcodec_close (AVCodecContext *avctx) removing in ffmpeg 7.2 and was
deprecated for couple years

Global avcodec_close (AVCodecContext *avctx)
Do not use this function. Use avcodec_free_context() to destroy a codec
context (either open or closed). Opening and closing a codec context
multiple times is not supported anymore – use multiple codec contexts
instead.

In ffmpeg master, it has already been removed. But still work in v7.1

We checked the ffmpeg changelog, and avcodec_free_context was added 7 years ago and should be present in ffmpeg 4.0, the oldest version we support.

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2025-07-23 09:00:47 -07:00
Larry Gritz 2422ee5d1e build: PNG auto-build improvements (#4835)
The main thing is no longer using a custom namespace prefix for
auto-built libpng. We're already building it statically by default and
hiding the symbols, so the custom prefix only serves to make occasional
build problems by having different symbols than typically found in the
library. We still keep it as an option that can be enabled.

Also, be a little more careful in clearing unneeded variable that may
have been set by an earier attempt to find the package but that failed
to turn up a version we were happy with.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-22 17:22:11 -07:00
Peter Kovář 9a3faace95 fix(build): update jpeg2000input.cpp to include cstdarg (#4836)
Add missing C++ header file

On the F41 and F42 compilation using LLVM based Clang++ failed.

```
[ 23%] Building CXX object
src/libOpenImageIO/CMakeFiles/OpenImageIO.dir/__/jpeg2000.imageio/jpeg2000input.cpp.o
/usr/src/github.com/1div0/OpenImageIO/src/jpeg2000.imageio/jpeg2000input.cpp:462:9:
error: use of undeclared identifier 'va_start'
  462 |         va_start(args, fmt);
      |         ^

/usr/src/github.com/1div0/OpenImageIO/src/jpeg2000.imageio/jpeg2000input.cpp:464:9:
error: use of undeclared identifier 'va_end'
  464 |         va_end(args);
      |         ^
2 errors generated.
```

Signed-off-by: Peter Kovář <peter.kovar@reflexion.tv>
2025-07-20 08:42:08 -07:00
Aleksandr Motsjonov 64ee5187ae iv: Add min/max/avg and sizing to pixel closeup view (#4807)
This changeset has bunch of improvements for pixel closeup window
feature:
- Min/max/avg values
- RGB channels are colored with respective color
- Pixel colors in preview window are showing actual colors (previously
there was semi-dimming overlay on top of them)
- Center pixel is now marked including corner cases when close to the
edge
- During follow cursor mode window switches the the left from the cursor
when too close to right edge, and at the top when too close to bottom
edge
- Number of previeable pixels is configurable
- Number of pixels in a preview used for averaging is configurable
-- When avg subset is smaller then main closeup window there is an
indicator showing are that being averaged

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-07-16 18:36:06 -07:00
Larry Gritz 7d22e1f23e ci: Bump 'latest releases' tests to use pybind11 3.0.0 (#4828)
Also found one stray test that was using a pybind11 version older than
we claim to use, so bump that up to the advertised minimum.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-16 08:33:07 -07:00
Mikael Sundell 2f1912cbf5 Switch to posix_spawnp for macOS background launch to enable PATH lookup (#4834)
Switch to posix_spawnp for macOS background launch to enable PATH
lookup, this is a fix for:
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4640

Description:
Previously, the code used posix_spawn with argv[0] as the executable
name. This failed when argv[0] was not an absolute or relative path
(e.g., just "iv"), because posix_spawn does not perform PATH lookups.

Switched to posix_spawnp, which behaves like execvp and searches PATH
when argv[0] does not contain a '/' character. This allows the program
to re-spawn in the background using the original command name, without
requiring _NSGetExecutablePath() to resolve the full path.

Signed-off-by: Mikael Sundell <mikael.sundell@gmail.com>
2025-07-16 08:32:12 -07:00
Larry Gritz 09e88ab91c build: fix typo related to finding ccache (#4833)
Wow, my fingers are so used to typing "exr", and I don't use the OS that
would make me ever type "exe", so...

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-15 19:13:37 -07:00
Larry Gritz f0552d65ce admin: Update SECURITY to reflect that 2.5 only gets critical fixes now (#4829)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-14 09:33:04 -07:00
Larry Gritz 3965255940 api: image_span-ify ImageBuf::set_pixels() (#4827)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-13 21:30:12 -07:00
Larry Gritz 7e687aa361 build: For python stub generation, lock pybind11 to pre-3.0 (#4831)
pybind11 3.0 changed the generated stubs, causing CI to fail, so lock
down to no later than the last version before it broke.

We think the pybind11 3.0 generated stubs are mostly better, so at some
point soon, when we have more time to look at it carefully, we will come back
to this topic and bump our wheel workflow to use pybind11 3.0 and update
the stubs accordintly.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-13 14:52:22 -07:00
Larry Gritz 15aa81bde8 perf: Speed up maketx --envlatl when multithreaded by over 10x. (#4825)
[As reported on Slack](https://academysoftwarefdn.slack.com/archives/C05782U3806/p1751642730171029),
between OIIO 2.5 and 3.0, we had a big slowdown when doing a
multithreaded `maketx --envlatl`, which was traced almost entirely to
the new mutex lock in ImageBuf::IteratorBase::init_ib(), which were all
happening inside the call stack of `resize_block_<float>()`.

The reason was that it was calling ImageBuf::interppixel_NDC for every
pixel, which in turn works by creating (internally) an
ImageBuf::ConstIterator to sample the 4 nearby pixels. But every one of
those ConstIterator constructors called init_ib, which briefly grabbed
the mutex for the IB, which in addition to being wasteful on its own,
caused the threads to block on each other.

The solution is straightforward: there is no need to construct a new
Iterator for every pixel. We can create the iterator once (a single call
to the init_ib for each thread region of the image) and then for each
pixel, just call its `rerange()` method to reset the set of pixels to
loop over for the samples needed for that pixel.

I also opportunistically eliminated a few redundant spec() calls in
various routines in imagebuf.cpp.

On my Mac laptop, when doing a maketx --latlong on a 16k image with 16
threads, it was previously taking 170.5s (including 117.8s for the
initial resize and 42.8s for the MIP computations). With this change,
the same operation takes 12.4s (including 3.7s for the initial resize
and 1.6s for he MIP computations). That's almost a 14x speedup. YMMV,
depending on platform, compiler, image size, and number of threads.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-13 11:42:50 -07:00
Larry Gritz 691acac172 fix: correct docs and type of "resident_memory_used_MB" attribute (#4824)
It was implemented as int, documented as float. Change the docs to match
what was always indended (int), and also switch the implementation so
that either int or float will be transparently accepted.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-08 15:37:44 -07:00
Larry Gritz 70636df380 docs: CHANGES update (#4823)
Just my periodic updating of the CHANGES doc in main.
Will merge immediately, as it's administrative docs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-06 17:23:47 -07:00
Larry Gritz c610e48c40 fix(oiiotool): Allow thread control for --parallel-frames (#4818)
Fixes #4811

This patch makes oiiotool's initial cursory scan of the command line
notice a `--threads` and carfully honor it when parallelizing the frame
loop.

Explanatory background info:

The cited issue shows something subtle happening with oiiotool's
`--parallel-frames` argument. The symptom was that it was using too many
threads and running out of memory, and seemed impervious to the use of
`--threads` to properly control it.

The reason is that oiiotool first scans the command line args in a
cursory way looking for signs of a "sequence", like a `--frames` or any
filename containing frame wildcards (like `linear.%04d.exr`) and also
noting if there is a `--parallel-frames`, but not actually taking any
actions for any of the commands yet.

Having seen that there are frame wildcards, what it then does is execute
the whole command line, once for each frame number that matched the
pattern. And since it noted that a `--parallel-frames` argument was
present somewhere, it does it with a parallel for loop. But how many
threads does it use? Well, enough for all the cores, since in some sense
it has not yet noticed the `--threads` argument. Moving the `--threads`
to be placed prior to the `--parallel-frames` doesn't help, either.

The suggested workaround was to set the default number of threads with
the environment variable `OPENIMAGEIO_THREADS` prior to launching
oiiotool. But this patch is a more robust solution.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-06 10:34:06 -07:00
Rui ChenandLarry Gritz 09250af27d build: Fixes to build against libheif 1.20(#4822)
Seeing build failures when building against libheif 1.20:

```
  /private/tmp/openimageio-20250701-18561-96sl0/OpenImageIO-3.0.8.0/src/heif.imageio/heifinput.cpp:390:37: error: no matching member function for call to 'get_plane'
    390 |     const uint8_t* hdata = m_himage.get_plane(heif_channel_interleaved,
        |                            ~~~~~~~~~^~~~~~~~~
  /opt/homebrew/include/libheif/heif_cxx.h:909:32: note: candidate function not viable: no known conversion from 'int *' to 'size_t *' (aka 'unsigned long *') for 2nd argument
    909 |   inline const uint8_t* Image::get_plane(enum heif_channel channel, size_t* out_stride) const noexcept
        |                                ^                                    ~~~~~~~~~~~~~~~~~~
  /opt/homebrew/include/libheif/heif_cxx.h:914:26: note: candidate function not viable: no known conversion from 'int *' to 'size_t *' (aka 'unsigned long *') for 2nd argument
    914 |   inline uint8_t* Image::get_plane(enum heif_channel channel, size_t* out_stride) noexcept
        |                          ^                                    ~~~~~~~~~~~~~~~~~~
  1 error generated.
```

relates to https://github.com/Homebrew/homebrew-core/pull/228740

Starting with 1.20, libheif changed the type of a stride parameter.

---------

Signed-off-by: Rui Chen <rui@chenrui.dev>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2025-07-04 22:28:52 -07:00
Larry Gritz 045233a7ee 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>
2025-07-04 21:17:09 -07:00
Jonathan Brown f5b6c6c87d docs: Clarify description of JPEG XL faster decoding modes (#4812)
Fixes #4584
A minor edit with large consequences.

Previously the setting would encode uncompressed files due to a bug,
causing the much faster encoding as stated in the old description.

In the upcoming v0.12 libjxl release, [my
PR](https://github.com/libjxl/libjxl/pull/4201) overhauls the setting,
to correctly scale decode speed at the cost of density.

---------

Signed-off-by: Jonathan Brown <jonathanbr30@gmail.com>
2025-07-03 10:36:12 -07:00
Larry Gritz c104dd0e77 ci: Bump 'latest' test versions (#4819)
Some actual bumps in CI, others just bringing the INSTALL documentation
up to date with what we have been testing and know works.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-03 10:23:45 -07:00
Larry Gritz cbbb98cf2f build: wheel upload_pypi step should only run from main repo (#4820)
The upload_pypi step only happened for tags, not for other events like
PRs. But it would TRY (and fail) if you pushed a v3.0.* tag to your own
fork. This patch makes it not even attempt it, except when the tag is
pushed to the official repo.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-07-02 20:36:22 -07:00
Peter Kovář db878e0855 jpegxl: Handle various bits per sample values in JPEG XL files (#4738)
Handle bps other than 8, 16, 32, with appropriate conversion.

---------

Signed-off-by: Peter Kovář <peter.kovar@reflexion.tv>
2025-07-02 20:34:09 -07:00
Larry Gritz 255a84fb3c build: Adjust pystring finding (#4816)
We have been having intermittent CI failures when the auto-build of
OpenColorIO triggers the auto-build of Pystring, and then sometimes
immediately seems to think the version it installed is not correct.

I'm jiggling some things here to see if I can get it to stop
occasionally failing. I've run the testsuite on this patch several times
without seeing any failures that in recent days had been happening
typically in 1-2 jobs per CI run. So maybe this fixes it? I'd be lying
if I claimed to have a coherent and full explanation for exactly why
these changes help.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-30 18:53:15 -07:00
Larry Gritz ab2f988f3f testing: remove old test reference output we no longer need (#4817)
Delete some reference test output for older toolchains and dependency
versions that seem no longer needed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-29 14:43:52 -07:00
Larry Gritz 7aa01fe427 admin: Remove stale intake documents (#4815)
We had a couple documents that were temporary checklists and status
reports from back when the project was first coming into the ASWF,
reminding us of tasks that needed to be performed.

That was years ago! All done, and OIIO is even a fully
"adopted/graduated" project. Remove the files, which are misleadingly
out of date and no longer needed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-29 14:43:38 -07:00
Larry Gritz c2c3cbf421 ci: Simplify gh-win-installdeps, no more vcpkg (#4809)
Among other simplifications, remove all vcpkg builds from windows CI,
don't need them. Just rely on our auto-build. Shortens the build time on
Windows!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-28 13:19:19 -07:00
Jesse Yurkovich 7b9b1401c2 build(jxl): Use correct cmake variables for the include directories (#4813)
There was feedback[1] in the prior commit that the changes were a bit
atypical when it comes to cmake conventions.

This is a partial revert of 5ca82dcd67 to
better align with conventions but still fix the problem.

[1]
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4810#discussion_r2163183241


Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-06-28 13:18:18 -07:00
Larry Gritz b8fe2612f3 fix(ImageBuf): Better errors for nonexistant subimages/mips (#4801)
An important clarification: ImageInput::seek_subimage() returns false
but does not set an error message if the only thing wrong is
requesting a non-existent subimage or miplevel, and similarly,
ImageInput::spec() and spec_dimensions() set an empty spec (easy to
tell by spec.format == TypeUnknown) in that case. All three of these
only set an error message if the reason it couldn't perform the task
because there was actually something wrong with the file or the
I/O. (Put another way, it's common to use these to simply probe which
subimages or mip levels exist, and returning false for "no it doesn't"
isn't really an error, it's expected behavior.)

OK, then.

We weren't always following these rules, sometimes setting
error messages when we shouldn't.

Other times (in different routines) when we didn't set error messages
but should have. And also, there are some downstream places such as
ImageBuf::init_spec() that assumed that seek_subimage / spec /
spec_dimensions set an error message (but they didn't, by design) and
should have raised their own errors when discovering that a requested
subimage or miplevel didn't exist.

Also, there were a couple spots in ImageBuf internals where we tried
to do the right thing, but instead of calling ImageBufImpl::error(),
we called errorfmt(), which didn't exist in ImageBufImpl, and so was
calling the global OIIO::errorfmt(), which therefore was setting the
error on the wrong object entirely. (Fix that by adding an errorfmt
method in ImageBufImpl so that mistake is not possible. Should have
been like that all along.)

All this leads to more consistent error reporting (and not reporting,
in the cases we weren't supposed to), especially for people calling
ImageBuf::read() and ImageBuf::init_spec().

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-26 14:46:55 -07:00
Jesse Yurkovich 5ca82dcd67 build(jxl): Use correct cmake variables for the include directories (#4810)
I'm unsure how this could have worked correctly. There were three
different variables used before, now there is only one.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-06-22 20:25:19 -07:00
Anton Dukhovnikov ff44d10c9f feat(iba): add 'auto' value for all options of IBA::demosaic (#4786)
- The parameter 'pattern' now supports a special value 'auto', which is
also default.
- The parameter 'layout' now supports a special value 'auto', which is
also default.
- The parameter 'algorithm' now supports a special value 'auto', which
is also default.
- New parameter 'white_balance_mode.
- The raw input plugin now adds an attribute 'raw:WhiteBalance' in
addition to the libraw-specific 'raw:cam_mul', carrying the same values.

This changes the current behaviour, please read below.

Previously, the parameter 'pattern' defaulted to 'bayer'. The new default
value of 'auto' makes OIIO look for the input ImageBuf's attribute
'raw:FilterPattern', and deduct the pattern from its value. If the
attribute is missing, 'bayer' is assumed.

Previously, the parameter 'layout' defaulted to 'RGGB' for Bayer pattern,
or 'GRBGBR BGGRGG RGGBGG GBRGRB RGGBGG BGGRGG' for X-Trans. The new
default value of 'auto' makes OIIO look for the input ImageBuf's
attribute 'raw:FilterPattern', and deduct the layout from its value. If
the attribute is missing, the old default values are assumed.

Technically the 2 changes above the current behaviour may change, but
only in a very rare use case: when the user relies on the old default
values to decode the image, and there is metadata present in the
ImageBuf saying that the pattern and/or layout is different from the
default.

Previously, the parameter 'algorithm' defaulted to 'linear'. The new
default value 'auto' maps to 'MHC' for the Bayer pattern, and 'linear'
for the X-Trans.

The newly added parameter 'white_balance_mode' can have one of the
following three values:
- 'auto' (default) - the white-balancing weights are read from the input
ImageBuf's attribute 'raw:WhiteBalance', defaulting to (1, 1, 1, 1).
- 'manual' - the white-balancing weights are read from the parameter
'white_balance'.
- 'none' - same as 'manual' with the weights of (1, 1, 1, 1).

This changes the current behaviour where the white-balancing weights
from the parameter 'white_balance' get applied if present. Now, in
addition to providing them, you need to explicitly set
'white_balance_mode' to 'manual'.

I've updated the unit tests to cover the new 'auto' mode. 

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-06-20 10:36:01 -07:00
Larry Gritz 731b90b135 api: Add new ImageInput::supports() query: "mipmap" (#4800)
ImageOutput::supports() recognized queries for "multiimage" and
"mipmap". But ImageInput::supports() only recognized "multiimage". Add
"mipmap" to make it easier for client software to know if the image file
format they're reading from allows the possibility of MIP-mapping.

As far as I can tell, only OpenEXR, TIFF, Ptex, and DDS do, among the
file types we currently support.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-19 19:39:53 -07:00
Anthony Roberts 1516226877 build: Add arm_neon.h include on Windows ARM64 with clang-cl (#4691)
On Windows ARM64, when building with clang-cl, LLVM can sometimes use it's own built-in intrin.h file, located in `<LLVM INSTALL PATH>\lib\clang\20\include`.

This file, as opposed to the built-in one that ships with the Windows SDK that MSVC uses, doesn't have an inclusion of arm_neon.h. This PR adds a small check to the simd.h file to include this header.

I didn't add an extra check to specifically only do this for clang, as it seemed a little messy - I can do this, but it's relatively harmless for MSVC given intrin.h includes it anyway for that compiler.

This change has already been in place for some time in Blender, this is just an upstreaming PR for that change: https://projects.blender.org/blender/blender/src/commit/ea604b6b80e49adb51d12df4e4edd5af1c51f446/build_files/build_environment/patches/oiio_windows_arm64.diff
2025-06-19 10:39:56 -07:00
Larry Gritz 5e5e09cbb5 fix(oiiotool): fixes to --missingfile behavior (#4803)
Fix some `oiiotool --missingfile` behavioral corner cases:

When substituting, warn rather than making a true error. This didn't
seem like a big deal for a single command line, but when doing a loop
over frames, it would prevent correct behavior from pressing on to the
next iteration.

How big is the substitute image? It uses the rez and channels of the
first image successfully read (if available). But it when in a frame
loop, it resets this on every iteration, so any missing frame looks like
it doesn't have a good size guess -- but it does, as long as it's not
the first iteration of the loop. This involves safely gettingthe first
image dimensions from the *parent* (each iteration is a child Oiiotool
object).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-17 08:55:21 -07:00
Larry Gritz b7e1862d3a feat(oiiotool): New expression pseudo-metadata term: SUBIMAGES (#4804)
When doing oiiotool command line expression substitution, asking for
this metadata evaluates to the number of subimages in the referenced
image.

The purpose is that asking to retrieve, say, `{TOP.'oiio:subimages'}`
might look right, but generally it's only added to images (or format
readers) that are potentially multi-image. Whereas SUBIMAGES is not
actual image metadata, it's just an evaluation token that will always be
the number of subimages.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-17 08:54:52 -07:00
Larry Gritz 771bc2d68f fix(python): python ImageBuf.init_spec did not return correct value (#4805)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-15 21:57:38 -07:00
Larry Gritz ed3adba51d ci: Various ccache save/restore improvements for CI runs (#4797)
Improvements to the way our CI utilizes ccache to speed up build. Ported
from OSL:

- Split caching into separate restore/save, and rearrange the step order
so we save cache before tests run. This allows us to save the ccache
even for jobs with failed tests (where the all-in-one unsplit approach
would skip the cache save step for a failed job), or for jobs that we
purposely end early (maybe because we see failing tests), not only when
all tests finish and succeed. This makes subsequent builds, that we do
on the same branch while attempting to fix failures, go faster by using
the cache.

- Make subsequent pushes to the same PR or REF to cancel any previous
jobs, so if we push updates before the last CI run of the same branch
completes, it won't keep those going as useless zombie jobs.

- Change the cache key names we use to remove the github ref to
encourage cache reuse across different commits or branches (I think),
and to fix a couple errors where we had mis-named things and were
sharing caches between jobs when we shouldn't or vice versa.

- Be more careful about the location of the cache, making sure we were
for sure telling the GHA cache action to be saving/restoring the same
directory location that we told ccache to use as its cache location.

- Use CCACHE_COMPRESSION env var to be extra sure we're using compressed
caches to be sure we get the best bang for buck on the limited cache
storage we're allowed.

- Set CMAKE_CXX_COMPILER_LAUNCHER and CMAKE_C_COMPILER_LAUNCHER in the
shell for CI in the hopes of making more dependencies we build also use
ccache.

- Alternate launcher structure -- use LANG_COMPILER_LAUNCHER, not
RULE_LAUNCH.

A sampling of typical results:

    test                         build deps     build oiio
    -----------------------      ----------     ----------
    VP 2024 (cold)                N/A            6:22
    VP 2024 (cached)              N/A            0:55 (7x)

    latest rels (cold)            8:29           5:30
    latest rels (cached)          2:24 (3.5x)    0:45 (7.3x)

(The N/A is because that run gets all its dependencies from the
container and doesn't have to build any from scratch.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-14 11:11:27 -07:00
Larry Gritz 725885f42d ci: fix broken bleeding edge CI (#4798)
Just on the "bleeding edge" CI job, we were refraining from doing the
apt-get update. It was breaking something last year. Now NOT doing it is
breaking something in this CI test, just since this week (presumably
some default package on the GH runners changed, I haven't been able to
isolate any other reason). But bringing all the apt packages up to date
makes it go away.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-13 15:23:36 -07:00
Aleksandr Motsjonov 34cffacaa0 int(iv): Add raw string syntax modifier for VSCode and Cursor to understand its glsl (#4796)
Sorry for not doing it in a first PR. I thought to see if I can make
VSCode / Cursor to actually syntax highlight that raw string literal
content. And I found a way. Seems like if you change the delimiter using
language of content syntax name you make VSCode to syntax highlight it:

![Screenshot 2025-06-08 at 11 12
45 pm](https://github.com/user-attachments/assets/278ac078-e895-4565-9e68-8f5b80f3f3c6)

I don't think those clang exceptions are needed now.

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-06-08 09:23:35 -07:00
zachlewis 8f83072a0e feat: support OCIO Viewing Rules, other OCIO-related improvements (#4780)
This PR fixes and improves a tiny constellation of OCIO-related bits,
directly or indirectly pertaining to OCIO Viewing Rules and File Rules,
and the propagation of `oiio:ColorSpace`.

## Description

The focus of this PR:
- feat: Permit the `ociodisplay` ImageBufAlgo to dynamically select a
default View for the `fromspace` (or current `oiio:ColorSpace` value),
as directed by the OCIO config's Viewing Rules (if present)
- feat: Have the `ociodisplay` IBA appropriately set the destination
ImageSpec's color space.
 
As part of this effort, a handful of additional changes and improvements
are addressed:
- fix: Re-enable the "looks" override functionality, matching the
previous OCIO-1-style behavior.
- fix: Improve `ColorConfig::getDisplayViewColorSpaceName(...)`'s
handling of Shared Views
- feat: Overload `ColorConfig::getDefaultViewName(...)` with function
that takes an additional `inputColorSpace` argument
- change: Alter the `ociofiletransform` IBA's behavior pertaining to
setting the destination spec's color space: instead of storing the
filepath as the `oiio:ColorSpace` value, attempt to get the color space
from the filepath; else, leave the `oiio:ColorSpace` attribute alone.
This isn't 100% foolproof, obviously, but I'd prefer to reserve the
`oiio:ColorSpace` attribute for color space names, unless there's a
reason not to. In a future PR, we can additionally attempt to divine a
valid color space string from specific CLF and CTF metadata, if present.
- feat: Implement a `ColorConfig::filepathOnlyMatchesDefaultRule(...)`
function, which wraps the OCIO::Config function of the same name.
- change: Alter `ColorConfig::getColorSpaceFromFilepath(...)` to behave
more like the OCIO::Config function of the same name. In particular,
return the Config's default color space name (instead of failing over to
OCIO-1 string-parsing heuristics, which, in turn, fail over to an empty
string); and provide an overloaded variant for implementing the legacy
(i.e., current) behavior. Update all usages in the codebase (i.e., in
oiiotool, w.r.t. autocc) to use the overloaded variant, so there's no
apparent change in behavior to how autocc functions.


## Background 

This PR was inspired by #4753, which adds to the Python ImageBuf
bindings a `_repr_png_` magic method which returns a PNG bytestring
(which Jupyter notebooks can display inline), similar in behavior to
other libraries, like Pillow. This is great for previewing gamma-encoded
output-referred buffer data, but less great for previewing "linear"
encodings. Ideally, the `_repr_png_` method would apply an `ociodisplay`
ImageBufAlgo just before writing the PNG; but there would need to be
some means of controlling for the buffer "image state" when determining
how / whether to apply an `ociodisplay` IBA. For example, it would be
appropriate to apply the default ColorConfig's "ACES 1.0 - SDR Video"
View to an image buffer that contains scene-referred data; but very
evidently inappropriate to apply that same View to an image buffer that
holds display-referred data, yielding a "double-LUTted" appearance.

Fortunately, OCIO-2 `Viewing Rules` provides a solution. Viewing Rules
allow OCIO Config authors to selectively filter the set of Views
available for a given Display, on a per-input-colorspace basis.
Ostensibly, applications use the OCIO API's DisplayViewHelper class for
building View menu UX widgets that dynamically update as a function of
both the selected Display and Input Color Space; but there are
implications for headless applications, as well -- crucially, the Config
author may order Active Views such that different Input Color Spaces
elicit different default Views.

## Tests
I've included a test OCIO config with some Viewing Rules and File Rules
in testsuite/python-colorconfig; I'm testing that the new and updated
python bindings behave as expected; and I'm testing that the
`ociodisplay` IBA is OCIO-Viewing-Rules-aware and is properly
propagating `oiio:ColorSpace` to the dst buffer's spec.

Notably:
```python
import os
import OpenImageIO as oiio
import numpy as np

os.environ["OCIO"] = "/path/to/testsuite/python-colorconfig/src/oiio_test_v0.9.2.ocio"

a = oiio.ImageBuf(np.array([[[0.1, 0.2, 0.3]]]))

# The first time the ociodisplay IBA is applied, the lack of an `oiio:ColorSpace` 
# attribute will be interpreted as the OCIO config's default color space -- in this case,
# "lin_rec709", which corresponds to a scene-referred default view (ACES 1.0 - SDR Video).

b = oiio.ImageBufAlgo.ociodisplay(a, "", "")

#  The second time around, the `oiio:ColorSpace` attribute is now "sRGB (~2.22) - Display", 
# a display-referred color space, thanks to the previous operation; as such, the IBA uses 
# a different colorimetric "pass-thru" View as its default ("Colorimetry"), instead of the 
# ACES View. Upshot is, values remain unchanged this time.

assert b.spec()['oiio:ColorSpace'], 'sRGB (~2.22) - Display'

c = oiio.ImageBufAlgo.ociodisplay(b, "", "")

assert c.spec()['oiio:ColorSpace'], 'sRGB (~2.22) - Display'

# Subsequent applications will be noops as well.
d = oiio.ImageBufAlgo.ociodisplay(c, "", "")


assert np.allclose(b.get_pixels(), c.get_pixels())
assert np.allclose(b.get_pixels(), d.get_pixels())
assert not np.allclose(b.get_pixels(), a.get_pixels())
```

## TL;DR
This PR enables OCIO config authors to dynamically control `ociodisplay`
IBA behavior w.r.t. the `oiio:ColorSpace` attribute, such that
`ImageBufAlgo.ociodisplay(buf, "", "")` always "does the right thing",
regardless of whether `buf` holds scene-referred or display-referred
data.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-06-07 11:47:11 -07:00
Larry Gritz 98dec00299 ci: Remove tests on Windows-2019 GitHub runner (#4793)
This flavor of runner will be retired at the end of the month and is
already experiencing intentional brown-outs to warn us.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-07 09:46:00 -07:00
Aleksandr Motsjonov 61227e3ec9 Use R"()" syntax for glsl shader strings for better readability (#4795)
Small PR to improve redability of shader code parts.

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-06-06 10:11:26 -07:00
Larry Gritz fcfae699e2 fix: build break from untested combo of two PRs (#4794)
Oops, my bad. Looks like #4664 (merged about a week ago) and #4783
(merged today, but authored before #4664 was merged) interacted in a way
that produced a build break. This tiny fix is essential to unbreak it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-06-05 17:14:27 -07:00
Larry Gritz 235e97930f 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>
2025-06-05 13:20:35 -07:00
Danielle Imogu 4e56aa7b6f feat(iv): area probe (#4767)
Fixes #4714 

This PR adds support for selecting a rectangular region within an image
to compute and display per-channel minimum, maximum, and average values.

The feature can be activated through the Tools menu or by using a
keyboard shortcut (Ctrl-A / Cmd-A) . Once active, the user can click and
drag with the left mouse button to define a rectangular area, which is
visually indicated by a blue outline. Upon releasing the mouse button,
the tool calculates statistics for all pixels within the selected area
and displays the results in the status bar.

---------

Signed-off-by: Danielle Imogu <dannieim689@gmail.com>
2025-06-05 12:38:35 -07:00
Sam Richards 4bb092ed2f feat(openjpeg): Write .j2c by adding HTJ2K Encoding using the OpenJPH library. (#4699)
OIIO did already have a decompressor for HTJ2K via the OpenJpeg library,
but nothing for encoding. This adds the encoder using the OpenJPH
library, which will be needed for the HTJ2K encoding for OpenEXR too.

This is a merge with the OpenJpeg plugin, the reader will attempt to
use the OpenJPH library (if found) to read the input file, if it cannot
read it, it will fall back on OpenJpeg to read it. For writing with the
OpenJpeg library, if the compression flag is set to htj2k or the file
extension is j2c the OpenJPH library will be called to write out the
file.

If you want to do a lossy encode you can do it with:

```
oiiotool -i INPUTFILE --attrib jph:qstep 0.03 -o OUTPUTFILE.j2c

oiiotool -i INPUTFILE --compression htj2k --attrib jph:qstep 0.03 -o
OUTPUTFILE.j2k
```

Other options include:

```oiiotool -i INPUTFILE --compression htj2k --attrib jph:qstep 0.03
--attrib jph:num_decomps 3 --attrib jph:block_size 32,32 --attrib
jph:prog_order CPRL --attrib jph:precincts 128,128,256,256 -o
OUTPUTFILE.j2c
```

Added a htj2k test, it tests encoding a dox and a jpeg file, both
lossless and lossy.

---------

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
2025-06-01 10:46:45 -07:00
Larry Gritz befbba82cf fix(exr): not honoring 'missingcolor' for scanline files (#4757)
As a reminder, the global OIIO attribute "missingcolor", or the
file-specific ImageInput open hint "oiio:missingcolor" is designed to
treat missing scanlines or tiles as not a true error, but instead just
pass over them and substitute the missingcolor value for those missing
areas on the file.

The nature of this PR is that while we had implemented this behavior
fully for tile-based exr files, we never did so for scanline-based
files. So here we do.

Now then, unfortunately, it does not work. I think it's a bug in the
OpenEXR library itself, but we're still trying to figure that out. But
nonetheless, I believe this change is correct.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-31 13:48:34 -07:00
Larry Gritz f2438975ee fix: ImageOutput::check_open logic was flawed (#4779)
We documented this function as checking the valid range of pixel
coordinates, but we CALLED it everywhere as if we were only checking the
resolution.

But we IMPLEMENTED as if we were checking the range, generating errors
for outputting exr files with negative pixel window origins. But why was
nobody seeing those errors when writing exr files with negative origins?
Because the openexr writer BOTCHED it by not noticing the return value
and considering it a failure.

Oh boy. All my fault.

So the fix:

* Change the comment documenting check_open() to match the way we had
been using it at the call sites.

* Change the implementation of check_open() to match this by no longer
checking whether all four corners were in the range -- only check if
each dimension's size is within the limit for that dimension.

* Fix the OpenEXR writer's failure to notice the check_open failure.

* Does this eliminate necessary checks? No! We already separately
checked that nonzero origins were only allowed for formats that support
it, and that negative origins were only allowed for formats that support
that. So the flawed check was redundant anyway. Ha!

* Add a test verifying that we can write exr files with negative
origins. (Technically, that would have passed before, but only because
we were ignoring the incorrect error.)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-31 13:47:42 -07:00
Larry Gritz 25eb7182ce api: image_span_within_span (#4784)
A utility to confirm that an image_span (possibly with non-contiguous
strides) entirely fits within another contiguous span.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-31 13:45:48 -07:00
LI JI 8031b57e6e openexr: Add htj2k as a compression option for OpenEXR (#4785)
After adding the new `htj2k` compression codec to OpenEXR, here we
enable it in the OIIO stack so it will be recognized by the library and
binary tools, such as using `oiiotool` to directly change compression
type into htj2k.

---------

Signed-off-by: lji <lji@ilm.com>
2025-05-28 16:07:58 -07:00
Basile Fraboni f7cd3a19c3 imagecache: remove redundant ImageSpec from ImageCache internals (#4664)
Backend changes for issue
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4436.

## Description

- add `ImageDims` struct to store only a subset of `ImageSpec` or use it
as a view on an existing ImageSpec.
- move `ImageDims` and `ImageSpec` ownership to `ImageCacheFile` and use
them as a pool
- add `ImageSpec* m_spec` in `SubimageInfo` to access the descriptors
that are common across all mip level
- add `ImageDims* m_dims` in `LevelInfo` to access the despcriptors that
differ per mip level
- add functions to access to mip level dimensions:
```c++
const Dimensions& SubimageInfo::leveldims(int miplevel) const;
```
- do the plumbing across all `libtexture` to use the new interface

## Tests

I performed a batch of testing to compare the memory usage and
performance of different strategies using 17 `ptex` files from the PTex
library samples (some from the Moana Island dataset, so they are quite
heavy). The baseline numbers are approximates but gives a good estimate
of the memory usage.

Baseline | Total (MB) | Specs (MB) (%) | # specs | Subimages (MB) (%)
-- | -- | -- | -- | -- 
OIIO 3.0 main | 1500 | 1200 (80%) | 4936364 | 300 (20%)


Method | Total (MB) | Specs (MB) (%) | # specs | Subimages (MB) (%)
-- | -- | -- | -- | -- 
No reuse | 787,2 | 454,3 (58%) | 4936381 | 332,5 (42%)
Reuse dist=1 | 442,2 | 109,3 (25%) | 1193485 | 332,5 (75%)
Reuse dist=10 | 368,5 | 35,6 (10%) | 380506 | 332,5 (90%)
Reuse dist=inf | 333,2 | 0,292 (<1%) | 3020 | 332,5 (>99%)

These numbers shows that the memory is now bounded by the `SubimageInfo`
+ `LevelInfo` structure sizes, and not from the descriptors `ImageSpec`
+ `Dimensions`  with the right amount of reuse across subimages and mip
levels.

---------

Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
2025-05-27 14:15:53 -07:00
Larry Gritz 9e288004b8 CHANGES update
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-25 10:59:25 -07:00
Larry Gritz 3aae7215bb ci: Update linux arm clang reference output (#4782)
Two PRs crossed paths in flight last week -- one adding the ARM tests,
the other doing something that changed the reference output of this test
slightly. Both passed on their own, but the combo left one platform's
output needing the update.

Also, edit nicknames of two tests, they were not unique.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-24 17:07:58 -07:00
Larry Gritz 7554792f4e ci: Add Linux ARM test (#4749)
GHA offers free runners for Linux on ARM based machines. Let's throw
them into the testing mix!

A very small number of tests needed additional reference outputs saved,
due to a few LSB type errors in the math.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-21 11:27:19 -07:00
Larry Gritz 8b9a13038f docs: Update Windows build instructions to rely on deps auto-build (#4769)
The INSTALL.md Windows building instructions were out of date in two
important ways: (1) they neglected to mention OpenColorIO as a (newly)
required dependency nor give instructions for how to build it; (2) it
doesn't mention the new BUILD_MISSING_DEPS capabilities.

So basically, this PR modifies our Windows build guidance to set
OpenImageIO_BUILD_MISSING_DEPS=all and rely on that without needing to
document any additional steps for dependencies.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-21 11:09:24 -07:00
Lydia Zheng caa665d93e feat(oiiotool): --eraseattrib:fromfile=1 (#4763)
Extended eraseattrib to be able to read regex patterns from a file,
one per line, with `--eraseattrib:fromfile=1 filename`.
Erases all metadata attribute fields that match.

Added a new test to `oiiotool-attribs` which has been verified
painstakenly to be working!
Also tried running the command directly from dist/bin and verified with
`oiiotool --info -v`.

More detail on the motivation:

It's common in a studio to have tools insert all sorts of metadata into files as they're rendered, etc. But a lot of that are things that SHOULD NOT leave the facility -- like security issues from internal pathnames or network info, or secrets like plot details revealed by sequence or character names. So generally you want to scrub the metadata from the final images before they are shipped to the client or to marketing or whatever.

oiiotool's --eraseattrib is handy for this, but it takes a single regex. But we were thinking that:

-  You may have several patterns to fully describe the metadata you want to be sure not to ship. This could be an unwieldy regex or a cluttered series of multiple --eraseattrib commands.
-  That list of patterns may change over time, and it would be error prone to have to change it in every script that calls oiiotool.
-  That list of patterns may need to be different per show.

We thought a solution to facilitate this might be a version of --eraseattrib that takes a filename that contains a list of regexes, one per line of the text file. So that master list of things to scrub could be maintained in a central place and not need to update every oiiotool-calling script in order to update it. Furthermore, you could have the command say something like

    $ oiiotool ready_to_ship.exr --eraseattrib:fromfile=1 /blah/$SHOW/nometadata.txt -o clean.exr

to make a single command that allows per-show customization.

---------

Signed-off-by: Lydia Zheng <lydiamzheng@gmail.com>
2025-05-20 19:40:26 -07:00
Dharshan Vishwanatha c4f01e7f61 feat(oiiotool): Added create-dir cmd arg to create dir if it doesn't exist (#4762)
Fixes #4598.

It was noted in the issue that running `oiiotool` with output filename
inside a folder that doesn't exist will cause OIIO to consume time and
resources, but fail eventually due to the folder not existing.

Take for example the command:
```
oiiotool --create-dir -i input.png -o ./output_folder/output.png -o ./output_folder_2/output.png
```

During the output action, it creates the directories if needed
(`output_folder` and `output_folder_2`), and outputs the images into the
folder.

Added unit tests. Tested it locally, and it creates both the above
folders and outputs the image.

---------

Signed-off-by: DharshanV <dharshanv1999@gmail.com>
2025-05-20 17:42:01 -07:00
Jesse Yurkovich 73be2d80a3 feat(webp): Allow finer grained control over WEBP compression settings (#4772)
WEBP uses the `WebPConfig::factor` setting to also control how hard it
tries to compress when lossless compression is used. It also uses
another `WebPConfig::method` setting to further tune both lossless and
lossy schemes. [1]

Expose both of these settings so client applications using OIIO can
adjust these values as they see fit.

This PR makes 4 changes:
- Adds support for using a `lossless:factor` value for the `compression`
attribute. The 'factor' value controls the effort that WEBP uses during
the compression process.
- Adds support for using a `webp:method` int attribute. The value of
this attribute controls the `WebPConfig::method` setting. Note: this is
different than the compression settings but will also affect speed and
quality in various ways.
- Sets `WebPPicture::use_argb` to `true` when using lossless compression
(per the WEBP documentation[2])
- Changes default lossless "quality" from 100 to 70. This results in
much faster image output at a very minor increase in file size (e.g. a
2048x2048 test image goes from 1300ms/364kb to 800ms/371kb after this
change)

Before - just 2 basic forms were possible:
```
Client uses "compression=lossless"
- OIIO uses lossless=true, method=6, quality=100, use_argb=false
Client uses "compression=webp:90"
- OIIO uses lossless=false, method=6, quality=90, use_argb=false
```

After - several additional variations are possible:
```
Client uses "compression=lossless"
- OIIO uses lossless=true, method=6, quality=70, use_argb=true
Client uses "compression=lossless:100" and "webp:method=4"
- OIIO uses lossless=true, method=4, quality=100, use_argb=true
Client uses "compression=webp:90"
- OIIO uses lossless=false, method=6, quality=90, use_argb=false
Client uses "compression=webp:90" and "webp:method=4"
- OIIO uses lossless=false, method=4, quality=90, use_argb=false
```

[1]
https://developers.google.com/speed/webp/docs/api#advanced_encoding_api
[2] See notes around `use_argb` from the above link and see also the
internal Encode helper function which keeps lossless and use_argb in
sync:
https://github.com/webmproject/libwebp/blob/main/src/enc/picture_enc.c#L241


Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-05-20 17:37:11 -07:00
Larry Gritz f698ae38df fix(python): IBA.demosaic had GIL release in wrong spot (#4777)
Only symptomatic on debug builds, but I was seeing exceptions from
pybind11 about bad GIL release. I traced it to the recent
implementations of demosaic. Apparently it's not safe to release the GIL
until AFTER the call to py_to_stdvector. Which makes sense when you
think about it -- we need the lock whenever we are interacting directly
with Python calls or data structures (such as what py_to_stdvector is
doing), but we release it when we're done with the python and only
calling OIIO internals (such as IBA::demosaic() itself).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-20 13:04:05 -07:00
Larry Gritz 54d012e9e0 ci: Adjust ABI standard commit after ABI-breaking change of PR 4748 (#4778)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-20 08:27:29 -07:00
Larry Gritz 488dfb2408 api!: add image_span versions of ImageInput methods (#4748)
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.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-19 22:21:29 -07:00
Aleksandr Motsjonov d694b60a69 feat(iv): Implement files drag and drop into an iv window (#4774)
Drag and drop of files. Tested on my own Mac and it seem to work just
fine.

Fixes #4771

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-05-19 12:21:57 -07:00
Larry Gritz cc794f2d1c ci: add facility for benchmarking as part of CI (#4745)
Make it so that CI test cases that set the GHA variable "benchmark" to 1
will add a benchmarking step to the workflow that runs a new
ci-benchmark.bash script.

The script runs selected unit tests containing benchmarks (currently,
only image_span_test, but we can amend later as needed). Those
designated tests are run, and their output both echoed to the log for
that step and also put in build/benchmarks/TESTNAME and saved as a build
artifact for optional download.

Most test cases will not turn benchmarking on -- it probably will end up
adding a few minutes so do it very selectively (once per major platform
or compiler version is plenty).

I would have previously guessed that any attempts at benchmarking on GHA
runners was doomed, but in practice, I'm surprised to find that there's
almost as much run-to-run consistency as I find doing casual benchmarks
on my own machine. As such, I think this can be a handy way to do some
rough benchmarking using CI, to compare platforms or compilers, or
verify that changes we want to make don't introduce performance
regressions.

Caveats to remember in the future:

* Take it all with a big grain of salt, and watch the benchmark numbers
for the trial-to-trial range of times -- wide variation means that the
numbers probably can't be trusted.
* The GH runners themselves may change without warning, so beware
benchmark stability over time, or if they ever have pools of
heterogeneous machine generations/configurations.
* While my results indicate a decent amount of timing reliability for
purely computational tests, I assume that there will be enormous
run-to-run variation in anything involving I/O or networking. So this is
unlikely to be a fruitful way of testing for performance regressions in
image format I/O speed (but probably is useful for a variety of
in-memory operations).
* As we add more unit tests to what we benchmark in the future, keep an
eye how much time we're spending running these benchmarks. A few minutes
on a small subset of the test jobs is probably fine, but I wouldn't want
it to make the overall wait for a full CI run to become substantially
longer because of it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-19 09:48:02 -07:00
Aleksandr Motsjonov 6cb871490a fix(iv): Bug fix for iv window loosing focus on mac on startup (#4773)
Master version of the iv today when opening on mac sometimes opens
without a focus, which causes top menu bar not to be populated (just
`iv` on the left). Workaround is to switch back and forth once to and
from another app for menu bar too get populated.

It is unclear to me how reliably replicate the bug so that I have a
solid prove, that this fix works. But since building with this line it
never happened to me yet.

Maybe more knowledgeable in Qt can verify if it makes sense.

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-05-18 22:56:32 -07:00
Scott Wilson f508e6e277 ci: pkg config libdir fix (#4775)
This was causing the Rust bindings to fail because the pkgconfig was
pointing to a path that didn't exist (the libdir was the full root
appended to itself).

Signed-off-by: Scott Wilson <scott@propersquid.com>
2025-05-18 22:49:03 -07:00
Jesse Yurkovich 01392e63b9 feat(webp): Respect the oiio:UnassociatedAlpha attribute (#4770)
Similar to other formats like PNG, make WEBP respect the
`oiio:UnassociatedAlpha` attribute value in case client applications are
already handling the alpha association themselves.

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-05-17 18:56:13 -07:00
Larry Gritz 4dfff31514 fix: ImageInput/ImageOutput did not set per-file threads correctly (#4750)
II and IO were documented as initializing their internal "how many
threads to use when reading/writing this particular file" to the global
"threads" OIIO attribute. But they did not, they always initialized to 0
("all the threads") even if the global attribute had been set
differently prior to creation of the reader or writer.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-17 16:49:44 -07:00
Larry Gritz 96c536eb1e build: fix failed test with old fmt (#4758)
Our fmath_test (a.k.a. unit_fmath) test was failing with an exception
thrown by the fmt library because we used a width specifier when
formatting a TypeDesc.

It was really only an issue when using old fmt < 10.0, so I'm just
solving it trivially by ignoring that specifier for old fmt. It doesn't
seem necessary to make it work correctly with width specifiers for old
versions, when we don't in any way rely on it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-17 10:45:58 -07:00
Aleksandr Motsjonov 47a0acc0c1 iv: Use screen pixel ratio to render sharp text in pixel view tool (#4768)
Improve sharpness of text in pixel view tool for HiDPI screen

Before:
![Screenshot 2025-05-17 at 4 45
50 pm](https://github.com/user-attachments/assets/f2b14aa6-dcbe-46a7-a2d5-a83097baa94d)

After:
![Screenshot 2025-05-17 at 4 47
11 pm](https://github.com/user-attachments/assets/be42f794-d6e0-4b9f-8847-da733b3a3872)


Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-05-17 10:33:58 -07:00
Oktay Comu 830db0fdd1 feat(python): _repr_png_ implementation for ImageBuf (#4753)
Fixes #4680

Adds a `_repr_png_` implementation to the Python bindings of ImageBuf.

This allows ImageBuf objects to be displayed in Jupyter
notebooks, as requested in #4680
Uses the IOVecOutput IOProxy to write the ImageBuf as a png into memory.
Then, reads and returns that as a python bytes object.

![image](https://github.com/user-attachments/assets/ba1a5bd6-d50b-41ce-a00e-6746b906e763)

---------

Signed-off-by: glowies <comuokta@gmail.com>
2025-05-16 22:46:45 -07:00
Aleksandr Motsjonov 044337ba85 fix(iv): do not resize on open and other zoom fixes (#4766)
Fixes #4718

See the demo of problems that were fixed and of fixes in action over
here: https://www.loom.com/share/3bdee20b32434e0bbba47d393928d4f7

There are fixed for three problems:
1) Window is not resizing when new image is loaded in (it still does
when image being loaded is the only one)
2) When you using scroll mouse wheel it is taking into account where the
cursor is (there is some corner case when it doesn't do it perfectly,
that I can't catch when it doesn't follow it exactly, but a bit of
panning fixes it)
~~3) Switching between images recenters (if image is smaller) or making
some other panning nessery to have image in the viewport. I believe it
is doing same stuff what happens when window is resized.~~ This has been
reverted.

---------

Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
2025-05-16 17:20:23 -07:00
Larry Gritz 4f3f04c72d testing: Update ref image for slightly changed freetype accents (#4765)
Freetype master (presumably a change that will be in the next release)
broke our CI this week by changing how the accents on certain unicode
characters are rasterized. So we needed a new reference image on our
end.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-15 20:20:20 -07:00
Larry Gritz 03c2383b4b ci: update ref output to compensate for GitHub windows drive changes (#4761)
Apparently, the runners used to check things out on drive D:, but today
they are doing so on C:, and that changes some filenames in the
reference
output.

Also, fix missing nametag needed for Windows artifacts.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-15 20:17:27 -07:00
Anton Dukhovnikov 362a9fb37f fix(iv): fix crash on .DS_Store; fix uppercase extensions (#4764)
I've found a couple issues with iv when launched with a directory name
as input, while iterating through the files in the directory:
1. Crash on .DS_Store file
2. The files with extension in capital letters are not recognised as
valid images, due to case-sensitive compare. Capitalised extensions are
common in raw camera images.


Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-05-15 20:15:29 -07:00
Chad Dombrova 7f4c1b3ca6 ci: Upload fixed python stubs as an artifact in CI (#4754)
If the python stubs test fails (because the API changed in some way that needs
the stubs regenerated, but the submitter of the PR did not or could not,
the wheel CI will regenerate the stubs and include them in the failure artifact.

This provides a path for users who can't build the stubs locally.

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
2025-05-15 12:23:05 -07:00
Larry Gritz 88c2d75380 fix(exr): did not properly allocate 'missingcolor' vector (#4751)
Oops, this internal vector called `reserve()` and then filled in
results. Should have been `resize()`.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-14 22:13:19 -07:00
Chad Dombrova e787dc6ef1 feat: Add python stub files (#4692)
Add python stub files for code completion and static analysis.

Fixes
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
2025-05-13 18:09:01 -07:00
Larry Gritz 7a3b76d8b6 simd.h: renaming and fixing of shuffle template (#4739)
While I was investigating some SonarQube warnings about our simd
`shuffle<>` templates (which are a false positive and I have a separate
PR to simply silence it), I did get to thinking about the naming, and
want to make a couple changes:

* I decided that the 1-template-argument version of this function,
`shuffle<int i>(simd_type)` would actually be more clear and
self-documenting if renamed `broadcast_element` to emphasize that it is
taking just one simd lane/element and broadcasting it to all lanes. (The
multi-argument shuffle really is doing a true shuffle, giving an index
for each lane to make a permutation of swizzle, so I'm not renaming that
one.) To avoid breaking source compatibility, I am leaving the old name
as well as a synonym, but commenting it as deprecated and I will phase
out its use. It will disappear entirely from a future OIIO version
that's safe to break compatibility.

* For 16-wide simd, the 1-arg template we called shuffle was not doing
the same operation -- it was replicating one group of 4 elements instead
of a single element. We didn't use it anywhere, so I'm redefining it to
do the analogous thing as it does for 4-wide and 8-wide.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-12 12:55:46 -07:00
Larry Gritz c7b08d7eaa ci: Bump abi_check standard after ImageOutput changes (#4747)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-11 10:05:59 -07:00
Larry Gritz b356152003 api!: add image_span versions of ImageOutput methods (#4727)
* ImageOutput methods that write scanlines, tiles, and images, which are
the main customization points for format output implementations, are
given additional methods that take `image_span` in place of raw pointers
and strides.

* Generally, for each, there is a templated version that takes
`image_span<T>` that communicates both the memory area and the data type
conversion requested, a "base case" that takes an explicit TypeDesc for
the conversion type and a `image_view<std::byte>` giving the raw memory
layout, and a `span<T>` convenience version for when there are
contiguous strides. Note that when reading mixed channel data types in
"native" mode (no type conversion, just leave the data in its original
types), you have to use the std::byte image_span version, since the idea
is not to do any format conversion, and there may not be a single type
involved.

* For now, the default implementations of these new ImageOutput 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 <lg@larrygritz.com>
2025-05-11 08:38:35 -07:00
Mikael Sundell 946a9d3a4f fix(iff): Improved IFF support reading and writing z buffers (#4673)
Added support for reading and writing ZBUF chunks, also known as
Z-buffers or depth maps.
Removed noproxy versions, no longer needed.

---------

Signed-off-by: Mikael Sundell <mikael.sundell@gmail.com>
2025-05-11 08:27:10 -07:00
Larry Gritz fe04d57061 ci: new variants for VFXP 2025, Windows 2025 (#4744)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-09 22:29:56 -07:00
Larry Gritz 36f7c15cb0 oiiotool: -i:native=1, fix --native behavior, fix convert datatype (#4708)
A constellation of closely related fixes and additions related to
oiiotool `-i` behavior:

* When using `-i:now=1` to force for immediate read rather than using an
ImageCache, it would "forget" any prior setting of `--native`. This is
fixed now to correctly combine desire for bypassing the cache with
hinting to maintain native data type.

* When restricting channel subset with `-i:ch=...`, use of the
`--native` flag was incorrect in some cases -- it would use the overall
best single data format of all channels, rather than restricting that to
the selected channel range. So, for example, if you said `-i:ch=R,G,B,A`
and those channels were all `half`, but channel 17 (not selected) was
`float`, you would get a conversion to float rather than keeping the
selected channels at their native half. The solution here is that the
type chosen for `--native` behavior should only consider the selected
channel subset, not all channels.

* Add a new `-i` modifier: `:native=1`, allowing you to select the
"native" behavior on a per-input-file basis (the existing `--native`
command sets the default).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-09 09:15:00 -07:00
Larry Gritz 0e71adbb4a docs: Fix furo requirement after recently breaking docs (#4743)
PR #4736 bumped the version of sphinx we use on readthedocs, and that
was incompatible with the old version of furo we specified.

I'm not sure how the problem was not caught by our "docs" workflow.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-07 11:01:50 -07:00
Larry Gritz 51020abde8 docs: Online docs improvements, mostly formatting (#4736)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-07 07:19:06 -07:00
Larry Gritz 569c11825f build: fix fmt throwing behavior warnings (#4730)
Certain version combinations of fmt and gcc were warning, and it all
boiled down to the knots we tied ourselves into to replace the function
fmt uses instead of throwing exceptions, when they are disabled. I can't
seem to find any harm in letting it do its default thing, so simplify
our side to silence the warnings.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-07 07:18:40 -07:00
Larry Gritz db5e16ed63 build: Detect libultrahdr version and enforce minimum of 1.3 (#4729)
I discovered, by testing against the latest libultrahdr, that only
starting in 1.3 does it support the "64 bit 'half' RGBA" variety of UHDR
that is the flavor used by the testsuite example. But our "auto-build"
is pegged to 1.2, which means that all along, we were not decoding that
test file properly as UHDR and our test reference output was therefore
wrong. We also didn't detect libuhdr's version at all, let alone exclude
versions that were too old.

Remediations:

* Amend Findlibuhdr.cmake to detect the version from symbols in its
header files.

* Have our search for libuhdr enforce a minimum version of 1.3. (I feel
bad about "changing minimum dependencies" in a release branch, which we
usually disallow, but I think this time is an exception since we know
versions < 1.3 are broken.)

* Change the auto-build selected version to 1.4, the latest.

* Mention libuhdr in the INSTALL description of dependencies and
acknowledgement in the docs, where it had previously been omitted in
those places.

* Update the testsuite/jpeg-ultrahdr test reference output. (You can
tell it was wrong before because the "max" channel value was 1.0, and
now it's 4.6.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-04 21:14:07 -07:00
Larry Gritz 3a80262bc8 ci: save time by not checking out entire project history (#4731)
Seems to shave about 5s off of each and every CI run variant. Every
little bit helps.

Also update the versions of some actions we're using to the latest.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-04 21:13:28 -07:00
Larry Gritz ff8d777ba6 int: Address safety warnings in pvt::append_tiff_dir_entry (#4737)
I think what we were doing here was fine all along, but the idiom was
confusing to static analyzers who identified a danger that we were
memcpy'ing into a field that was potentially not big enough. A minor
restructuring of the code and a new assertion should verify that it's
safe and also make it clear to the static analyzer that we aren't
falling into the case it warned about.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-03 21:24:46 -07:00
Larry Gritz ff2ebd87f4 fmath.h: add span-based bit_unpack() utility (#4723)
This also fixes a sonar warning about being unsure of a raw pointer was
used out of range.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-03 13:45:23 -07:00
Larry Gritz 7fbfedc0d2 refactor: Rearrange initialize_cuda() for better err check, no warn (#4726)
Sonar was complaining that initialize_cuda() contained a loop that would
only iterate once. Upon looking, this was true, but mainly because we
just didn't adequately check errors. Fix up, which should both make the
code more robust and also silence the Sonar complaint.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-02 22:04:39 -07:00
Larry Gritz 2015a79758 build: Restore OIIO_AVX512ER_ENABLED preprocessor symbol (#4735)
This useless symbol was removed in PR #4724, but maybe downstream things
used it and will break simply because it was removed, even though it
never would have been nonzero. It should not have been completely
removed except at a compatibility-breaking version boundary.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-05-02 11:09:58 -07:00
Larry Gritz b8ffc1249b api: add image_span, deprecate image_view (#4703)
* `image_span<T,Rank>` is a 2D-to-4D bounded span with byte-measured
strides (describing data layout with dimensions for channel, x, y, z)
for us to have future APIs deal with bounded+strided regions rather than
YOLOing raw pointers. Among other advantages, image_span will have
robust bounds checking in debug builds. It also simplifies interfaces to
pass a single image_span that encapsulates everything about an up-to-4D
data layout, rather than needing to pass a long list of individual
pointers, sizes, and strides.

* I've templated image_span on Rank, but default to Rank=4 and am using
that version only in practice. The templating by rank allows future
expansion to describe one scanline (rank 2) or 2D image plane (Rank 3)
if we want to do so for certain API calls, but I'm not sure yet whether
to bother with that, so for now, the ability to template by Rank is just
flexibility for the future.

* Add image_span based versions of copy_image(), contiguize(),
convert_pixel_values(), convert_image(), and parallel_convert_image()
utilities. I added tests and benchmarks to verify their correctness and
that they have similar performance to the pointer based versions.

* Deprecate image_view, which we did not ever use internally to OIIO or
in its APIs. But since we published the headers, there's a chance it's
used downstream and would be unwise to change its behavior or data
layout. The new image_span is what we will use moving forward so that we
are free to modify it and start with a fresh slate. Keeping the
definition/header for now, but marking it with a deprecation warning.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-28 00:27:11 -07:00
Larry Gritz 88c3cbe2ae int: Address some nickpick sonar warnings about TileID initialization (#4722)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-26 14:46:07 -07:00
Larry Gritz 23f17acdc7 simd.h: address compiler warnings (#4724)
* We passed a bad flag to _mm512_cvtps_ph intrinsics because of what I
can only imagine was a bad cut-and-paste years ago. (Harmless because it
set bits never used, but a warning on Windows.)

* Remove clauses for AVX512-EL, I'm not sure why they were there,
because those instructions were only for "Knights Landing" which was
never made available to the general public and has been discontinued. It
must be that years ago, I got a little overzealous with the SIMD
intrinsics.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-26 13:45:29 -07:00
Larry Gritz 0e03e5cde6 fix: clean up Windows compilation warnings (#4706)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-26 13:45:03 -07:00
Larry Gritz b48577761d build: Fix broken OIIO_SITE customization (#4709)
Somewhere along the road to 3.0, the build files changed in such a way
that OIIO_SITE was not correctly passed down to C++ symbols, and some
SPI-specific (sorry) color space handling was inadvertently disabled as
a result. This restores things to the way it was in 2.5, and should not
affect anybody else.

Also eliminate some old SPI-specific code that's no longer needed (and
clearly hasn't been needed for a long time, because we had been naming
the site "spi" but testing "SPI", and no problems were evident with
skipping that ancient code).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-24 15:28:47 -07:00
Larry Gritz 3b69478c18 api(typedesc.h): tidying of type trait templates (#4705)
* Use constexpr inside BaseTypeToC templates.
* Add BaseTypeToC_v and TypeDescToC_v convenience aliases, much like is
done in C++ standard type trait helpers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-19 12:03:57 -07:00
Larry Gritz a5cb8b2f0e int: Experimental default_init_allocator and default_init_vector (#4677)
Inspired by a link from EmilDohne in an unrelated PR, this introduces
`default_init_allocator`, an experimental custom allocator that default
initializes, rather than value-0-initializes, POD/non-class types.

This is useful for being able to make a std::vector with this allocator
(`default_init_vector`), thus having the property of not incurring a
large cost of needlessly initializing the elements when they are
allocated, as a default std::vector does.

I picked two spots sort of randomly, in which we previously avoided
using std::vector and instead did a unique_ptr / new[] dance to do
scoped heap allocation without paying the vector initialization tax. By
using default_init_vector, we avoid the extra cost while still using the
much more convenient vector type.

These two places are just to prove it works. There's no particular need
to proactively root out every use of the unique_ptr trick. But for
future development, we can use now use std::vector without the
construction cost when we allocate.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-17 22:00:16 -07:00
Larry Gritz a2c87a45a4 doc: INSTALL.md reset updated minimum dependencies from 3.0 (#4700)
INSTALL.md bolds *changed* minimums of dependencies since the last
release. Now that 3.0 is released and main is working toward 3.1, remove
those highlights from the last release so they won't get mixed up with
future changes for 3.1.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-16 21:07:18 -07:00
Larry Gritz 80de69b5d3 build: Address Robin-map vs CMake 4.0 compatibility (#4701)
* Raise auto-build version of Robinmap to 1.4.
* Add the magic CMAKE_POLICY_VERSION_MINIMUM to our auto-build of
Robinmap in case an older version is selected for auto-build. (Mimicking
the fix we did for other packages.)
* Add Robin-map to the INSTALL.md list of dependencies, somehow it had
been overlooked before.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-16 21:06:58 -07:00
Anton Dukhovnikov 5dd4f6e658 feat(raw): add raw:ForceLoad hint (#4704)
The raw input plugin populates the attributes in the ImageSpec from the
libraw structures in the RawInput::open_raw() method. That is done
before the actual image data being decompressed on demand in
RawInput::read_native_scanline(). Libraw re-calculates some values after
the pixels get available, it is impossible to access those, as the
ImageBuf's spec does not get updated, and the updated ImageSpec is not
available from outside of RawInput when/after the pixels are being
processed.

An example: the initial values for the white balancing weights get
populated from the image file metadata, those get copied into the
ImageSpec. If the libraw was configured to white balance by averaging
the pixels of the whole image or a region, the white balancing weights
would get re-calculated by libraw after processing the pixels, but the
updated numbers are impossible to access from outside of the RawInput
plugin.

This change adds a hint "raw:ForceLoad", which, if set to 1, forces
libraw to decompress and process the image in RawInput::open_raw(), so
the image attributes returned from that method would contain the final
values.

I am not certain if this is the best way to achieve what I needed. I
have also looked into making the ImageBuf retain the ImageInput object
instead of spawning multiple transient objects, but that seemed too
complicated.

I have not added any unit tests, not sure how to approach that. I have
tested that the image does not get decompressed multiple times in a
bunch of scenarios.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-04-15 13:59:31 -07:00
Jesse Yurkovich e43fada799 build: Include Windows version information on produced binaries (#4696)
This change embeds version information into our Windows binaries. This
is done by ways of a `version_win32.rc` resource file[1] populated at
CMake configure time with our major.minor.patch version information.

This not only allows at a glance to discover what version a particular
OIIO binary is (see screenshot), but it also impacts certain MSI
installer behaviors. If this is a MSI install which updates a prior
installation, and the shared libs/dlls don't have version information,
then the installer assumes the binaries are equal and just skips them.
This can be problematic for applications that package OIIO etc.

Old on left, New on right:

![old-vs-new](https://github.com/user-attachments/assets/2ff354ab-54a9-4dfb-8d97-90b138472bd7)

[1]
https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-04-13 22:16:59 -07:00
Larry Gritz 0201e5ca34 feat(oiiotool): add --render_text modifiers measure= and render= (#4681)
`--render_text:measure=1` causes the render_text command to set user
variables `TEXT_X`, `TEXT_Y`, `TEXT_WIDTH`, and `TEXT_HEIGHT` (as if set
by `--set`) to the origin offset and dimensions of the rendered text
size. These can then be accessed in subsequent expression evaluation.

`--render_text:render=0` causes the text to not actually be rendered
into the image. (The default is 1.) This is primarily of use in
conjunction with `measure=1` if you want to measure the size that text
would have taken, then use the variables for subsequent commands, but
not actually draw the text.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-12 12:19:59 -07:00
Larry Gritz a9bc8ea351 fix(build): Fix new dcmtk 3.6.9 vs C++ warning (#4698)
Some new changes in DCMTK 3.6.9 that triggers warnings.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-12 10:39:19 -07:00
Jesse Yurkovich 0f008f9283 fix(sgi): Fix valid_file to properly swap bytes on little-endian platforms (#4697)
The SGI IRIS format is big-endian so incoming multi-byte fields need to
be swapped. This wasn't being done in the `valid_file` call so the magic
test would always fail on little-endian platforms.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-04-11 19:08:05 -07:00
Campbell Barton bb70340f33 Docs: specify the units for DPX scanned size (#4694)
From the PDF:
https://pub.smpte.org/doc/st268/20030505-pub/st0268-2003.pdf

3.31 X scanned size: Defines the horizontal size of the original scanned
optical image in millimeters. [42.1]
3.32 Y scanned size: Defines the vertical size of the original scanned
optical image in millimeters. [42.2]

----

This is a small PR that simply clarifies the units in the documentation.

Signed-off-by: Campbell Barton <ideasman42@gmail.com>
2025-04-07 21:16:08 -07:00
Campbell Barton 07a5079254 Docs: correct the type for BMP x/y density (#4695)
These values are read & written as integers
and don't work unless they are accessed using int accessors.

m_dib_header.hres = m_spec.get_int_attribute("XResolution");

Correct documentation.

BMP uses integer access:
- `./src/bmp.imageio/bmpinput.cpp:`, `m_spec.attribute("XResolution",
(int)m_dib_header.hres);`
- `./src/bmp.imageio/bmpoutput.cpp`, `m_dib_header.hres =
m_spec.get_int_attribute("XResolution");`

Signed-off-by: Campbell Barton <ideasman42@gmail.com>
2025-04-07 21:12:17 -07:00
Larry Gritz 0a3adc2628 fix(python): fix handle leak (#4685)
Seems that for quite some time, there have been particular circumstances
in which the Python bindings have leaked ImageInput or ImageOutput
objects. That's bad enough on its own, but it also leaves file handles
open if code was depending on the fact that the ImageInput and
ImageOutput destructors close the files if they haven't already been
closed.

I think the offending part is that the `unique_ptr<ImageInput>` extracts
its raw pointer and gives it to Python, on the mistaken assumption that
it would be reference counted as a python object. But apparently, it's
not. Oops.

Leaving it as a unique_ptr turns out to be fine, as far as pybind11 is
concerned! And on top of that, if you give an uninitialized unique_ptr
to pybind11, it considers that a Python `None`, which means we can
further simplify some places where we explicitly had to return a
py::object and figure out if it should be None or not, but actually it's
all ok to just give the unique_ptr and pybind11 figures the whole thing
out for us.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-07 13:55:00 -07:00
Larry Gritz 357648f2ae docs: CHANGES updates (#4690)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-02 20:52:37 -07:00
Larry Gritz ff996f2871 int: Switch to spans for some exif manipulation, fixing warnings (#4689)
We recently started getting some CI failures on the "bleeding edge" test
that uses the new gcc 14, seems that the newest cut of that compiler was
giving us new warnings where it suspected we were writing past the valid
bounds of some memory areas, but it was very hard to decipher the
circumstances and either find the bug or convince myself that is was a
false positive.

To help me debug it, I switched some of the internals of exif.cpp that
passed around raw pointers in very hard-to-validate ways to instead
use spans with explicit lengths, in the hopes that the debug-mode
bounds checking it provides would allow me to more easily track down the
problem.

Now it no longer gets compiler warnings.

Did I fix a very subtle bug in the process?

Does the reformulation with spans make it easier for the compiler to
verify that we aren't stomping on memory, and that suppresses the
warning?

Either way, it now passes all CI tests and I think the new code is safer
and aligned with our strategy of slowly changing raw unbounded pointers
to using spans in order to make these kinds of bugs harder to introduce.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-02 11:50:45 -07:00
Larry Gritz 8b9227f6a6 build: More changes to be robust for cmake 4.0 (#4688)
zlib needed the treatment, too.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-02 10:16:39 -07:00
Larry Gritz 89adbe2a33 build: cmake 4.0 compatibility (#4686)
The latest cmake in some package repos is 4.0. CMake 4.0 drops support
for compatibility with cmake < 3.5, and thus errors when building our
own dependencies that happen to have their own cmake scripts asking for
compatibility with something older than that.

Setting CMAKE_POLICY_VERSION_MINIMUM=3.5 environment and/or cmake
variable seems like a hack that could hide true incompatibilities, but
will get us past this for now.

Change our own minimum to the range of 3.18.2...4.0 to correctly reflect
the range of versions that we believe will work.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-01 16:06:00 -07:00
Larry Gritz 839b291e2a ci: Update ABI standard after PR 4669 (#4687)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-01 14:44:08 -07:00
Larry Gritz 730687ae79 api: start span-ifying ImageInput (#4669)
Add new ImageInput varieties of read_native_scanlines,
read_native_tiles, and a new read_native_voluemetric_tiles (all-channel
and channel-subset varieties of each) that take a `span<byte>`
describing the area to deposit the contiguous native-datatype values.

Moving forward, these will be the primary pixel-reading customization
points of the format readers. For now, these default to calling the
pointer-based varieties (so that old plugins keep working), but
eventually, the pointer-based varieties will be deprecated.

Notes:

* Omit the single-scanline and single-tile versions. Just keep the more
general multi-scanline, multi-tile versions, which of course people are
free to call with ranges that request just one scanline or tile.

* Omit the z coordintes for read_native_scanlines, since we know of no
volumetric format that allows reading of individual "scanlines".

* Omit the z coordinates from read_native_tiles to simplify the common
case of 2D images, but add a new read_native_volumetric_tiles() to
handle the volumetric case separately. This only needs to be supplied
for volume formats,

* The default implementations of the new methods is simply to call the
old, unsafe, raw pointer based versions. Thus, an ImageInput that still
supplies pointer based versions but not the span-based ones will not
break. Eventually, we will switch to the other way around, where all
ImageInput subclasses are expected to fully implement the span version,
and the pointer version will default to just be wrappers around the span
version for backward incompatibility. Way, way down the line, we'll
probably remove the pointer based varieties entirely.

Note that for this PR, we are only tinkering with the `read_native_`
functions that the ImageInput format readers supply. In a later PR,
we'll handle all the client-facing API calls to have span-based
varieties, as well as the analogous functions on the ImageOutput side.

In this PR, we do the overhaul on the JPEG and TIFF readers, to prove
that the whole scheme works. Over time, we will do the similar overhaul
of the other format readers.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-01 09:02:51 -07:00
Larry Gritz 164c58581b ci: bump dependencies for "latest versions" CI test (#4683)
Bump to the latest in several cases. Also make sure the INSTALL.md is in
line with what we support and/or test.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-04-01 09:01:51 -07:00
LI JI c5c8fb9a6f build: Bump auto-build libdeflate to 1.23 to avoid AVX512 not available errors (#4679)
When using `OpenImageIO_BUILD_LOCAL_DEPS` environment variable to build
all OIIO's dependency locally, OIIO's build script specifies a set of
default versions of the dependent libraries. In particular,
`ebiggers/libdeflate` is set to `1.20`.

This 1.20 version of libdeflate fails to build on platforms where AVX512
is not available and the make tool chain did not correctly tell the C
compiler about it.

```
-- Building package TIFF  locally
--         Building package libdeflate  locally
--                 Building local libdeflate 1.20 from https://github.com/ebiggers/libdeflate
/usr/tmp/ccCelbo5.s: Assembler messages:
/usr/tmp/ccCelbo5.s:649: Error: unsupported instruction `vpdpbusd'
/usr/tmp/ccCelbo5.s:650: Error: unsupported instruction `vpdpbusd'
```

This issue is fixed in libdeflate Merge Request 389
https://github.com/ebiggers/libdeflate/pull/389, by explicitly calling
CMake facilities to detect whether AVX512 is present, and set compiler
preprocessor flags accordingly in the cmake file. This libdeflate MR is
after version 1.20.

To fix OIIO's build error when building this dependency locally, one can
either set `libdeflate_BUILD_VERSION` to include this patch, (for
example `export libdeflate_BUILD_VERSION=1.23`) or change the default
version in OIIO's local dependency build script to 1.23. This PR makes
the change in OIIO's local dependency build script.

Assembler build error resolved after using libdeflate v1.23 for local
TIFF build.


Signed-off-by: lji <lji@ilm.com>
2025-03-27 15:26:10 -07:00
Larry Gritz 399ad82f83 ci: Fix wheel building on Mac ARM (continuation of #4668) (#4675)
The Intel Macs had this problem last week and #4668 fixed it. Now
suddenly the ARM Macs had it this week. Seems to be something changing
on the skbuild side.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-22 11:02:58 -07:00
Larry Gritz db36ed14a9 fix: Partial reversion to fix ABI checker false positive (#4676)
I still think that the "abi break" is a false positive. But I really
didn't need the new constructor that seemed to confuse the abi checker,
so just to be extra sure that there is no break that I simply
misunderstand, change to make abicheck happy.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-22 11:02:35 -07:00
Larry Gritz 1a34ef7011 feat: oiiotool --mergemeta pt 2: fold into --pastemeta (#4674)
After merging #4672, we noticed some things that could be improved, so
this is a further revision (and partial retraction).

There was already an oiiotool flag, `--metamerge`, which in retrospect
make it seem unnecessarily confusing to add --mergemeta. So this PR
removes this extra new command, instead simply piggy-backing on the
existing --pastemeta by adding to it optional modifiers:

- `:merge=` controls the merge strategy, 0 (default) means discard the
existing metadata entirely and use only the pasted, matching the
original --pastemeta behavior; 1 means merge nondestructively (no
existing metadata will be altered or removed); 2 means destructive
merge, where pasted metadata will overwrite existing metadata having the
same name, but conflict-free existing metadata will remain.

- `:pattern=` regex selects only some metadata.

Additionally, we noticed an interesting corner case that surprised users
when testing the new metadata merging feature from the last PR: What
happens if the metadata source image has fewer subimages than the pixel
source images? The behavior generally for oiiotool is that when binary
operations (those taking two images as input) are on images with
differing numbers of subimages, the output gets the number of subimges
as the FIRST input (assuming -a instructed us to consider subimages at
all). But that's not what we want here! If the metadata source has one
subimage and the pixel source has many, clearly the intuitive result is
for that one metadata set to be pasted into all of the subimages from
the pixel-supplying image.

So we fix that so that for --pastemeta, it's the second input image (not
the first) that takes the lead in determining the number of subimages we
will process. This in turn took a bit of extra infrastructure fixing in
the OiiotoolOp class that controls this logic.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-21 19:32:14 -07:00
Larry Gritz 7fc6a7bee9 feat: ImageBuf::merge_metadata and oiiotool --mergemeta (#4672)
Clarify that IB::copy_metadata and oiiotool --pastemea fully replace all
existing metadata with that of the other IB.

Add a new IB::merge_metadata() and oiiotool --mergemeta that merges in
metadata from the other IB, preserving metadata in `this` that was not
in the other IB. Optionally, metadata that existed in both can be
overridden. Optionally, a subset of metadata to be merged can be
selected via a regex.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-19 14:01:55 -07:00
Larry Gritz d8285600e9 ci: step naming adustments (#4658)
* Give names to some CI steps that didn't have them -- makes it nicer to
read the logs and CI status dashboard.
* Make sure no job nametag is a substring of another, or it might find
the wrong cache, which is based on the job name.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-19 12:28:56 -07:00
Basile Fraboni aeecb4457b fix: invalid loop bound when appending mipmap textures using oiiotool (#4671)
The following command fails for images with mip map levels due to a bug:
```
oiiotool mipmap_images.*.exr --siappendall -o all_images.exr
```

If the option `-a` is not appended to the command, mip levels higher
than 0 should be ignored, instead it just segfault due to out of bound
access; I just fixed the it in the PR cf. [my comment
below](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4671#discussion_r1999705885).

Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
2025-03-19 12:27:31 -07:00
vernalchen 415fe634ba fix(tiff): the default value for bitspersample should be 1 (#4670)
The default value for m_bitspersample should be 1 when
TIFFTAG_BITSPERSAMPLE is not present in the directory.

Signed-off-by: vernalchen <shaochun.chen@autodesk.com>
2025-03-17 09:50:04 -07:00
Larry Gritz 976e6dbe05 api(span.h): OIIO::span improvements (#4667)
Additions to `OIIO::span<>`:

* New flavors of `as_bytes()`, `as_writable_bytes()` that take a raw
pointer + length, turning them into `cspan<byte>` and `span<byte>`,
respectively.
* `span_cast<T>()`: "cast" a span of one type into a span of a different
type covering the same memory. Use with caution!

Safety improvements to existing functionality:

* front(), back(): Add a debug assertion to validate that there is at
least one element.
* first(), last(), subspan(): clamp offsets and counts so that the
result can't possibly return a span referencing memory that wasn't
inside the original bounds.
* The copy constructor that takes a non-matching span was much too
flexible. Now it uses enable_if to ensure that it can't be used to
change data types or lengths, it can only turn span of non-const into
span of const, and span of fixed extent into span of dynamic extent.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-16 16:55:01 -07:00
Larry Gritz 748c3d216d ci: Update libPNG address and version for ci & autobuild (#4659)
* The GitHub account has changed (the old one redirects, but still,
let's update to the current canonical name).
* Update the version we use in CI and for "autobuild" to the latest
tagged release instead of one that's years old.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-16 16:54:27 -07:00
Larry Gritz c0f0c5a9b2 ci: Fix wheel building on Mac (#4668)
This used to work until a few days ago. Then it stopped. I think that
GitHub changed the Mac runner configuration in some way that broke it,
now it's complaining about not being able to find ninja, so easily fixed
by instructing it to generate regular makefiles instead.

Along for the ride: If ONLY the wheel making workflow changes, there's
no need to rerun the regular CI, docs, or analysis workflows.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-15 14:59:25 -07:00
Larry Gritz c4fc6da0a3 api(span.h): Only allow span-from-array if array for compatible size (#4656)
From an array of known size, we can implicitly construct a span of
dynamic length, or of fixed length equal to the array length. Use
template enable_if trick to restrict to these cases.

Previously, the constructor would have allowed a fixed-length span to be
constructed from an array of differing length, which should obviously
have been disallowed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-14 20:53:50 -07:00
jreichel-nvidia 77544bf5e8 fix(build): Improve OpenJpeg version detection. (#4665)
Also detect patch level version. E.g. useful when checking for included
security fixes.

I ran `oiiotool --help` manually, and checked that the macro is
available already in 2.1.0.


Signed-off-by: Joachim Reichel <43646584+jreichel-nvidia@users.noreply.github.com>
2025-03-14 09:36:52 -07:00
Lydia Zheng 86d7639de0 fix(psd): Updated tag recognition for psb (#4663)
There were some psd/psb files that were not opening with oiiotool, failing
on the signature.
Some keys were missing for the additional layer information, leading to
the pointer to misalign when reading the file, expecting the next 4
bytes rather than 8 bytes where needed for parsing.

No additional test suites added.

After deliberating, it is unclear if we should have a strict mode, or
keep parsing the rest of the file after a failed signature, given that
in this case the signature is not the part that's actually causing the
issue. Might be useful as a future feature, if there is an use case for
that?

---------

Signed-off-by: Lydia Zheng <lydiamzheng@gmail.com>
Signed-off-by: Lydia Zheng <36296057+lydia-zheng@users.noreply.github.com>
2025-03-11 14:52:38 -07:00
Larry Gritz 516521bbed build: Better disabling of work when USE_PYTHON=0 (#4657)
When USE_PYTHON is disabled, don't even bother looking for python.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-08 23:15:54 -08:00
Jesse Yurkovich b28d802679 fix(png): increase allowed width/height limit (#4655)
The current width/height limit enforced by the `check_open` API is too
low for PNG files. Each dimension can technically be up to `2^31 - 1`
but using that value would defeat the purpose of the check here. Use `1
<< 20` like what is used for TIFF and EXR instead.

The situation was triggered while trying to write an 85000x28400 px
image, which is smaller than 65536*65536 but the dimensions are checked
individually rather than as a total pixel count or similar.

Also looks like the PNG output was allowing too many channels so fix
that too.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-03-08 09:39:38 -08:00
zachlewis e0bc3dd58b ci(wheels): Add numpy as a runtime requirement (#4654)
Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-03-05 16:19:37 -08:00
Larry Gritz 91d9c5e047 fix: eliminate needless definitions of std::size (#4652)
Since C++17 defines std::size(C) (defaulting to returning C.size()), we
don't need to define our own now that C++17 is our minimum.

It seemed harmless to define it anyway for quite a while... but then a
few days ago, the GitHub Windows CI runners upgraded their version of
MSVS, and we started getting some very odd test failures that I was able
to trace to std::size somehow returning the wrong size in some cases,
and printf debugging revealed that the one we supplied wasn't even the
one being called.

I can't say I understand exactly what was going wrong. I was debugging
by repeatedly submitting small changes with debugging scaffolding to GH
to see how it works in a CI run, since I have no access to a local
Windows machine (at about 1/2 hour turnaround time for each iteration!).
Once I discovered that not supplying the redundant definition somehow
fixes the problem, I couldn't justify spending more of my weekend on
this to find out why. "Because MSVS" is a sufficient explanation for a
lot of weirdness in the computing world.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-03-02 09:51:36 -08:00
Larry Gritz a9c3dd63af ci: Improved clang-format CI task (#4647)
Old: Do a build with target 'clang-format', relying on our build system.
But that means that we need to do the cmake config step, and need a
bunch of dependencies set up so that the config doesn't fail.

New: Make a new run-clang-format.bash utility to issue the commands for
the right files. No "build" is requred, and the only dependencies we
need are the minimum it takes to run clang-format itself.

These changes reduce the approximate total elapsed time of a CI
clang-format job from nearly 7:00 to around 0:45.

Also, I noticed that we never had been clang-format testing the .cpp and
.h files in the testsuite itself. So enable that now, and commit the
small amount of reformatting that it identified.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-28 13:31:28 -08:00
Larry Gritz a7421600b8 ci: for docs workflow, lock down versions and speed up (#4646)
When test building the docs, lock down breathe and furo versions to
exactly what we use on RTD.

Also, to speed up the workflow: run on native Ubuntu rather than on an
ASWF container (eliminates needless container download), and make sure
that we don't waste time installing dependencies that we don't need.

These changes speed up the docs workflow from around 3:40 to around
2:00.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-27 18:22:10 -08:00
Larry Gritz 89e5c7fa72 admin: Set up .gitattributes file (#4648)
Starter purpose is giving hints to GitHub's language analysis.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-26 09:17:15 -08:00
Larry Gritz db9072e840 admin: Add ".vs" to .gitignore (#4645)
Prevents people from accidentally committing their Visual Studio
configuration files.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-25 13:18:48 -08:00
Larry Gritz 3d767284cb ICC profile reading improvements, especially for PSD (#4644)
The main thing here is that it turns out that when trying to parse the
ICC profiles from Photoshop PSD/PSB files, we weren't storing the
attributes in the correct way. Everything else, we shoved in both the
"common" and "composite" imagespecs, but we left ICC data out of the
composite spec.

While I'm at it, I made two other ICC related changes:

* Among the several formats with ICC profiles, we were inconsistent
about whether we report errors for corrupt ICC profiles and treat the
whole image as broken, or just ignore the errors entirely. Fixed in
various places to make a consistent policy of always checking the
errors, and reporting/terminating if the "imageinput:strict" global
attribute is true, allowing it to just ignore the broken ICC record if
that attribute is false.

* Found a spot in JPEG handling of ICC where we were dangerously
trusting of the sizes of things. Replace a risky memcpy with a safer
spancpy that can't overrun the buffer bounds when copying.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-24 11:04:34 -08:00
Mikael Sundell d87412f85a fix(sysutil): improve the implementation of Sysutil::put_in_background on macOS (#4640)
Replaces the system() call with posix_spawn() on macOS to preserve
environment variables. This is essential for Debug builds using
DYLD_IMAGE_SUFFIX=_debug to prevent Qt from loading mixed
configurations.

## Tests

Run the iv application in background mode on macOS without the -F flag,
using a Debug configuration. Previously, the system() call did not
inherit the parent environment variables, causing a mix of Debug and
Release versions of Qt to be loaded.

---------

Signed-off-by: Mikael Sundell <mikael.sundell@gmail.com>
2025-02-23 11:38:57 -08:00
Larry Gritz 122e6aea47 api: ImageSpec::scanline_bytes, tile_bytes, image_bytes (#4631)
Existing versions could return the expected bytes for a scanline, tile,
or image for either the native per-channel types, or the single
composite channel type.

The new flavor lets you pass in any data type and it tells you how many
bytes you'd need for a scanline, tile, or image if all channels were the
passed type. (As a special case, the answer for TypeUnknown is the
"native" size, same as `thing_bytes(true)`).

This is handy for computing how big your buffer needs to be to hold a
type-converted scanline or tile.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-19 16:00:02 -08:00
Larry Gritz b764c455e1 ci: Move away from soon-to-be-deprecated ubuntu-20.04 GHA runner (#4636)
In the process, port a more modern build_llvm.bash from osl.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-19 15:58:38 -08:00
zachlewis 19f50fe5d1 ci(wheels): Add numpy as a runtime requirement (#4638)
Adds "numpy" as a runtime requirement for the Python wheels.

Fixes #4637

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-02-19 15:58:17 -08:00
Larry Gritz aaa599b9d3 fix(rla): More robust to corrupted RLA files that could overrun buffers (#4624)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-14 15:35:04 -08:00
Larry Gritz 4065e6ffff fix(ico): More robust to corrupted ICO files (#4625)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-14 13:32:13 -08:00
zachlewis bfa48c82a8 fix(wheels): Ensure python-based builds use maj.min.patch SO versioning (#4634)
Always use patch-specific SO versioning for scikit-build-core-based
builds, even when OpenImageIO_SUPPORTED_RELEASE=ON.

Fixes #4621

Ensures that Python-based builds only bundle a single copy each of
libOpenImageIO and libOpenImageIO_Util shared libraries.

## Tests

Previously, `$ uv sync -v --reinstall
-Ccmake.define.OpenImageIO_SUPPORTED_RELEASE=1` would bundle both
.so.3.0 and .so.3.0.3 copies of libraries when installing to a local
virtual environment.

With this fix, only .so.3.0.3 copies of libraries are installed.

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-02-13 10:17:30 -08:00
Larry Gritz a440e4b7cb build: fix recently broken rpath to restore python wheel building (#4633)
Also, make the wheel workflow work on pushes when the branch name
contains the substring "python" or "wheel", and when any of the cmake
build files in src/cmake (which control building of dependencies,
among other things), even if none of the python bindings themselves
are touched. This means that if you suspect your work might cause a
wheel to break even though you're not modifying the python bindings
directly, you can ensure that the wheel workflow will run on CI simply
by naming your branch to contain one of those words.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-12 15:17:03 -08:00
Lydia Zheng 1fdc5d09e5 feat(oiiotool): oiiotool new expression eval tokens IS_CONSTANT, IS_BLACK (#4610)
Included two additional metadata boolean checks for constant and black
frame images, so that handling for those image cases are facilitated.

IS_CONSTANT and IS_BLACK return 1 when true, and 0 when false.

Signed-off-by: Lydia Zheng <lydiamzheng@gmail.com>
2025-02-10 22:58:04 -08:00
Larry Gritz f8d93807dc fix(ImageBuf): Fix bug in ImageBuf construction from ptr + neg strides (#4630)
There was a bug in span_from_buffer when strides were negative
(basically, we were subtracting, when adding was correct since those
strides were negative values).

Also added a negative stride test to imagebuf_test.cpp. Embarrassed that
we didn't already have this, since it would have caught the problem.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-08 19:14:50 -08:00
Larry Gritz 66f4ae9a38 cleanup: Get rid of some compiler symbols no longer needed (#4606)
The newer versions of the compilers we now use no longer need this.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-08 12:17:49 -08:00
vernalchen 3a9cf59b3d fix(exr): fill in OpenEXR lineOrder attribute when reading (#4628)
Fill in OpenEXR lineOrder attribute when parsing the header in
OpenEXRCoreInput::PartInfo::parse_header()

---------

Signed-off-by: vernalchen <shaochun.chen@autodesk.com>
2025-02-07 23:53:08 -08:00
Larry Gritz 9ac484e8d0 docs: Argparse documentation/comments typos (#4612)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-06 10:44:48 -08:00
Larry Gritz d5739a7fef oiiotool: better handling of wildcards that match no files (#4627)
When you use frame or view wildcards, for example:

    oiiotool foo.%04d.tif -o bar.%04d.exr

we noticed that if NO files matched, no iteration would occur. You would
get this output:

```
$ oiiotool foo.%04d.tif -o bar.%04d.exr
oiiotool WARNING : oiiotool produced no output. Did you forget -o?
```

But maybe this is not helpful and it should be some kind of error to ask
for a match and not get one? Or at least give a more clear explanation
of what happened.

This PR detects the case where there is no match of the wildcard at all,
warns about that, and then tries interpreting the command line literally
(no wildcard expansion). So now the output is

```
$ oiiotool foo.%04d.tif -o bar.%04d.exr
oiiotool WARNING : No frame number or views matched the wildcards
oiiotool ERROR: read : File does not exist: "foo.%04d.tif"
Full command line was:
> oiiotool foo.%04d.tif -o bar.%04d.exr
```

Closes #4623

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-06 10:43:16 -08:00
Larry Gritz 1b2ce1d895 fix(build): Fix recently broken rpath setting (#4618)
As part of the recent big python wheel merge, compiler.cmake got changed
in a subtle way in how it sets CMAKE_INSTALL_RPATH.

This broken iv for me on a Mac with dynamic libraries. Strangely (and
I'm too lazy to chase down exactly why), oiiotool seems fine. So this
was missed entirely by the CI, which never runs 'iv', since it's an
interactive app. (Note to self: we should find some way to at least
verify that it can execute as part of the testsuite.)

Anyway, I believe that this change adds the install lib area back to the
path, and it does seem to repair my ability to run iv on my end.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-05 19:35:42 -08:00
Larry Gritz c4873d57e7 fix(ImageBuf): IB::pixeltype() did not always return the right value (#4614)
The implementation of IB::pixeltype() was:

- Make sure at least the spec had been read (lazy read).
- If there are "local pixels", return the pixel type from the spec,
otherwise return the cache pixel type.

But there is a flaw in this logic: If only the metadata has been read
but not the pixels, the local pixels might not be allocated yet, but
also there is not a cache and no cached pixel type, so pixeltype() will
return UNKNOWN even though we do already know what type of pixels will
be stored when they are eventually read.

The correct logic is:

- Make sure at least the spec had been read (lazy read).
- If it's a cached image, return the cache pixel type, otherwise return
the pixel type from the spec (which will be correct because we
definitely have read the spec at this point).

Also, for legit cached images, ensure that cachedpixeltype is set upon
read_spec() and doesn't have to wait for a full read().

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-02 10:43:40 -08:00
Todica Ionut 38824fc34c Docs: Document Python Wheel completed in roadmap (#4620)
Signed-off-by: Todica Ionut <todicaionut2000111@gmail.com>
2025-02-02 10:02:50 -08:00
Larry Gritz 1ca8406115 ci: Run wheel workflow on certain pushes (#4617)
We were only running the wheel workflow on pushes of TAGS, but this
change also will run it when we push to release, and dev-3.* branches.

My usual release workflow is to first push the "release" branch, watch
for it to pass CI, then add the tag and push the tag and draft the
release. If a problem with the wheel workflow isn't discovered until
we've already pushed the tag, then a fix will require a new tag and new
release (we never re-tag a release). So this change will allow us to
catch any problems with the wheel worflow BEFORE we actually irrevocably
make the tag, since it's no big deal to add corrections to the branch
before tagging. It still won't upload the wheels until the tag itself is
pushed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-01 18:42:44 -08:00
zachlewis 72c84c8ac1 ci: Switch to using ARM-native linux runners (#4616)
Use the publicly-available ARM-native linux runners for CI checks and
building Python wheels

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-02-01 16:14:44 -08:00
Larry Gritz 55a6634809 cleanup: no longer need OIIO_INLINE_CONSTEXPR macro (#4607)
Our minimum C++ version allows `inline constexpr`, just use it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-02-01 10:27:54 -08:00
Larry Gritz f25eb77f3c ci: Unbreak the scorecard workflow (#4605)
* Fix syntax error, other minor touch-ups
* Don't run other workflows when only scorecard.yml changes

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-31 15:17:16 -08:00
Larry Gritz 4da247997b docs: Make sure the CHANGES-2.x.md makes it into the installation (#4611)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-31 15:06:53 -08:00
Larry Gritz 8de907eb3a feat(span.h): span_memcpy is a safer memcpy when you know the span boundaries (#4597)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-26 11:51:27 -08:00
Larry Gritz d47da7bac5 ci: Allow special branch names to prune CI jobs (#4604)
Quite often I find myself debugging code or CI specific to just one
platform. It makes for much longer iteration for a huge CI job that
reruns lots of tests that won't be affected by the changes I'm
experimenting with. Sometime I make a commit that places `if: 0` in
strategic places to exclude irrelevant batches of tests. But this is a
pain to add, and has to be removed again to re-enable the tests prior to
turning the experiment into a proper PR.

This PR, then, adds some logic to ci.yml that lets me do the same just
with special branch names, rather than needing to edit ci.yml. Any
branch you push containing the substring "windows-only" will not run any
Linux or MacOS CI tests. And the analogous behavior is added for
"macos-only" and "linux-only".

This shouldn't affect any CI jobs in which people are not purposely
using those special branch names. You should NOT use these special names
for branches from which you submit PRs, since obviously we want every PR
to validate on all CI combinations. But it is very helpful for topic
branches on your own fork as you are developing and iterating over many
CI runs but only need results from one platform.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-26 11:50:49 -08:00
Brecht Van Lommel 9979a27ee6 api: Restore OIIO_NAMESPACE_USING (#4603)
This got lost with the 2-level namespace changes in #4567, but is used
by e.g. OpenUSD. Might as well not break the API here.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2025-01-22 09:31:44 -08:00
Loïc Vital 2677d4cc12 feat(oiiotool): oiiotool --layersplit, new command to split layers (#4591)
Implement FR from #4546

Add a new `--layersplit` command to `oiiotool` to split an image into
its channel-name-based layers onto the stack.

The extracted layer names are then stored in the `oiio:subimagename`
metadata (in case it is needed for later use, e.g merging these "layers"
as sub-images), and the extracted channel names replace the old channel
names in the new images.

Example:
an image with channels `R, G, B, A, diffuse.R, diffuse.G, diffuse.B`
will be split into two images, the first one with channels `R, G, B, A`
and the second one named `diffuse` with channels `R, G, B`.

> Note: we did not implement the `--layertosi` command suggested in the
FR as it can already be done with a combination of `--layersplit` and
`--siappendall`

We add a test in the test suite that takes a "multi-layer" image, splits
the layers and merges them as sub-images. The final image should have 3
sub-images.

---------

Signed-off-by: Loïc Vital <mugulmotion@gmail.com>
2025-01-21 16:29:12 -08:00
280e1c7c98 feat(build): Python wheels workflow and build backend (#4428)
### Summary
This PR is the spiritual successor to #4011. It implements a
`scikit-build-core`-based python build-backend, making it possible to
use `pip install .` to build from source; and it adds a Github workflow
for building with `cibuildwheel` and publishing to pypi.org binary
distributions (bdists) of the Python module / extensions / CLI tools for
cpython 3.8-3.13, across major operating systems and architectures.

When you `pip install OpenImageIO`, pip attempts to retrieve an
OpenImageIO bdist from pypi.org for the host's platform / architecture /
Python interpreter. If it can't find something appropriate, pip will
attempt to build locally from the OpenImageIO source distribution
(sdist), downloading and temporarily installing cmake and ninja if
necessary.

### PEP-Compliant Packaging: `pyproject.toml`

The `pyproject.toml` file is organized in three parts:
1. **Package metadata**: standard attributes identifying and describing
the Python package, its run-time and build-time requirements,
entry-points to executable scripts, and so forth.
2. **scikit-build-core options**: governs how `pip install ...`
interacts with `cmake`.
3. **cibuildwheel options**: additional steps and considerations for
building, packaging, and testing relocatable wheel build artifacts in
isolated environments.

### Additions to `__ init __.py` 

Previously, we were using a custom OpenImageIO/__ init__.py file to help
Python-3.8+ on Windows load the shared libraries linked by the Python
module (i.e., the .dll files that live alongside oiiotool.exe under
$PATH).

This PR adds an additional method for loading the DLL path, necessitated
by differences between pip-based and traditional CMake-based installs.

It also adds a mechanism for invoking binary executables found in the
.../site-packages/OpenImageIO/bin directory. This provides a means for
exposing Python script "shims" for each CLI tool, installed to
platform-specific locations under $PATH, while keeping the actual
binaries in a static location relative to the dynamic libraries. Upshot
is, in `pyproject.toml`,
each item under `[project.scripts]` is turned into a Python script upon
installation that behaves indistinguishably to the end user to the CLI
binary executable of the same name.

### Relocatable Binary Distributions with `cibuildwheel` + `repairwheel`

[cibuildwheel](https://github.com/pypa/cibuildwheel) is a widely-used
tool for drastically streamlining the process of building, repairing,
and testing Python wheels across platforms, architectures, interpreters,
and interpreter versions.

Additionally, the cibuildwheel-based builds set CMAKE_BUILD_TYPE to
"MinSizeRel" to optimize for size (instead of speed) -- this seems to
shave ~1.5MB off each .whl's size, compared to "Release"

### "Wheels" Github workflow

I straight-up copied `.github/workflows/wheel.yml` from OpenColorIO and
made a few OIIO-specific modifications. When pushing a commit tagged
v3*, the workflow will invoke a platform-agnostic "build sdist" (source
distribution) task, followed by a series of tasks for building OIIO
wheels for cpython-3.8-3.13 on Windows, Linux (x86_64 + aarch64, new
libstdc++), and MacOS (x86_64 + arm64) and persisting build artifacts;
followed finally by a task for publishing the build artifacts to
pypi.org

Note: For the sake of simplicity and troubleshooting, I've made as few
changes to OpenColorIO's wheel.yml as I could get away with; but in the
future, we can also build wheels for the PyPy interpreter, and possibly
pyodide.

Note: A "trusted publisher" must be set up on pypi.org. See
https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/

### Other Changes

I made some minor adjustments to `pythonutils.cmake` and
`fancy_add_executable.cmake` that only affect scikit-build-core-based
installs:
- -- namely, on Linux and macOS, I'm setting the INSTALL_RPATH property
to point to the relative path to the dynamic libraries, for the Python
module and CLI tools, respectively. This helps ensure that pip-based
builds and installs from source (as opposed to installs from repaired,
pre-built wheels) yield relocatable, importable packages, without
needing to mess with $LD_LIBRARY_PATH etc.


## Tests

`cibuildwheel` tests if `oiiotool --buildinfo` runs. If that command
elicits code zero, it means the "oiiotool" Python script installed by
the wheel is able to `import OpenImageIO`; that the actual binary
executable `oiiotool` is properly packaged and exists in the expected
location (e.g., at `.../site-packages/OpenImageIO/bin`); and that all
runtime dependencies are found.

## Inspiration, Credit, Prior Art
- @aclark4life's and @JeanChristopheMorinPerso's efforts + direction +
discussion + advice. See
[#3249](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3249),
and
[#4011](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4011),
as well as JCM's
[python_wheels](https://github.com/JeanChristopheMorinPerso/oiio/tree/python_wheels)
and
[python_wheels_windows](https://github.com/JeanChristopheMorinPerso/oiio/tree/python_wheels_windows)
branches. This PR is an attempt to leverage OIIO-2.6+
self-building-dependency features with # 4011's minimalist and modern
approach to packaging.
- OpenColorIO -- I tried to copy as much as I could from @remia et al's
fantastic work with all things wheels-related. The __init __.py
modifications, the way we're wrapping the CLI tools, and the github
Wheels workflow are lifted almost-verbatim from OCIO. Insert pun about
reinventing the wheel here.
  - @joaovbs96's help and patience with testing stuff on Windows.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Joseph Goldstone <joseph.goldstone@mac.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Jeremy Retailleau <jeremy.retailleau@gmail.com>
Signed-off-by: zachlewis <zachlewis@users.noreply.github.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Anton Dukhovnikov <antond@wetafx.co.nz>
Co-authored-by: Basile Fraboni <basile.fraboni@gmail.com>
Co-authored-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Co-authored-by: Joseph Goldstone <joseph.goldstone@mac.com>
Co-authored-by: Darby Johnston <darbyjohnston@yahoo.com>
Co-authored-by: Jeremy Retailleau <buddly27@users.noreply.github.com>
Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com>
2025-01-21 09:19:35 -08:00
Anton Dukhovnikov 4bf301298d feat(raw): add black level and BPS metadata (#4601)
Adds attributes to the input's ImageSpec for the black level and bit depth
when the raw bayer buffer is requested.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-01-21 00:01:50 -08:00
Anton Dukhovnikov 6206364f1c fix(IBA): demosaic - fix roi channels (#4602)
Fixes a bug in demosaicing where the code ignores the ROI channels.
The old behaviour was to always decode into the first 3 channels.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-01-20 23:52:47 -08:00
Jesse Yurkovich a50e7c737b fix(pdf): Perform endian byteswap on correct buffer area for PSD RLE (#4600)
Perform the endian byteswap on the correct buffer area for PSD RLE
decoding. The original code used `dst` but that pointer is modified from
its original value as it progresses through decoding.

Fixes #4599 

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2025-01-19 14:32:44 -08:00
Larry Gritz e67dcd240a testing: Additional ref output for jpeg-corrupt test (#4595)
Found a version of a dependency with a slightly different error wording
that got reported back.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-18 11:17:23 -08:00
Larry Gritz da42ac2673 fix(build): Recent change broke when using non-Apple clang on Apple (#4596)
This fixes a problem introduced with #4582

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-15 15:28:27 -08:00
Larry Gritz fce86272c3 testing: at long last, set up a softimage reading test
Also some very minor code cleanup that was helpful in setting up the
test cases and getting better code coverage.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-15 12:28:43 -08:00
Larry Gritz d9fcbc98d6 paramlist.h: ParamValue as_span, as_cspan
Convenience methods that give a bounded span of the data that a PV holds.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-15 12:28:33 -08:00
Larry Gritz 3fbfd1048b ABI after namespace change
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-15 10:16:16 -08:00
Larry Gritz 889cf33b61 api: make a 2-level namespace scheme (#4567)
TL;DR: In main, change the enclosing namespace from `OpenImageIO_v3_1`
to a 2-level scheme: `OpenImageIO::v3_1`.  This can't be backported to
the current release for obvious reasons; it is a forward-looking
change only.

More ponderous explanation follows:

We have for some time had a single namespace that contains the
version, defaulting to `OpenImageIO_v3_0` in the current release, for
example.  A namespace alias, `OIIO`, always aliases the current
namespace, so client applications can just say `OIIO::foo` without
needing to change code for every minor release (let alone if a
build-time option sets up a custom namespace).

By bumping the namespace for every minor release, we make the symbol
names themselves enforce a rigid ABI compatibility test, so you can't
accidentally compile against one minor release and link against an
older minor release. This gives us the freedom to break the ABI (link
compatibility) for each minor release, without subtle user errors.
(Doing it wrong makes a total failure to link, which is hard to miss.)

But being able to introduce ABI changes annually by changing the
enclosing namespace comes at the cost of a *complete* ABI compatibility
break with every minor release. Even classes or functions that haven't
change at all will be incompatible by virtue of their changed symbol
names.

This is an unfortunate limitation, and in an ideal world, we would
like downstream users to be able to upgrade to a newer minor release
more painlessly, and confident that they could even relink or perhaps
compile with a request to use an old ABI.

I haven't fully worked out all the details, or even if this is going
to be worth the trouble, but I think that a change we can introduce
now that will allow more flexibiity in the future is to switch to a
2-level namespace scheme, for example, `OpenImageIO::v3_1` instead of
the current `OpenImageIO_v3_1`.

The reason this might be helpful in the future is that we can use
"inline" namespaces that default to finding things that are in, say,
OpenImageIO::v3_2 without needing to specify it explicitly, while
giving the ability to explicitly give an alternate inner versioned
namespace. I haven't implemented that part here, it's reserved for
future expansion (though I have experimented with it, it does work,
but I want to discuss separately whether or not to actually do it).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-15 10:14:48 -08:00
Larry Gritz 703a73ec16 ci(deps): Adjust some pugixml versions (#4594)
* Bump the 'latest' test to test the actual latest, 1.15.
* Be sure that the 'oldest' tests actually test the oldest we support,
1.8.
* Sprinkle around a couple other versions that we don't test currently.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-14 22:14:20 -08:00
Larry Gritz 2bae2adec5 ci(deps): Raise 'latest' tests to use new fmt 11.1.2 (#4593)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-14 21:17:48 -08:00
zachlewis cc83997dd4 feat: Disable loading Python DLLs from PATH by default on Windows (#4590)
Users can enable the legacy behavior by setting env var
`OIIO_PYTHON_LOAD_DLLS_FROM_PATH=1`.

This commit also changes the environment variable name from
`OIIO_LOAD_DLLS_FROM_PATH` to `OIIO_PYTHON_LOAD_DLLS_FROM_PATH` to match
the convention used by OCIO.

This PR addresses issue  #4519

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2025-01-14 15:40:52 -08:00
Anton Dukhovnikov dc409d80b9 [feat]IBA:demosaic add X-Trans demosaicing (#4579)
Implements X-Trans pattern demosaicing using a simple bilinear
algorithm. Adds the Xtrans pattern layout to the ImageBuf attributes in
the raw reader plugin.

I have implemented unit tests in imagebufalgo_test.cpp which cover all
permutations of the Bayer and X-Trans layouts, as the X-Trans pattern is
a bit too complicated to generate using oiiotool.

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2025-01-14 09:55:17 -08:00
Larry Gritz 3baab41354 ci: Fix Windows 2019 CI -- make python version match the runner (#4592)
For reasons that are unclear (maybe a change to which python versions
are installed where on the GH runners?) this seems to have broken within
the past couple days, in a way that did not correspond to any change we
made on the OIIO side.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-13 16:09:18 -08:00
Larry Gritz d50caee5fb build: Fix libraw definitions (again) (#4588)
Fixes #4586
Replaces #4587

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-08 09:26:14 -08:00
Larry Gritz 0ae1f07c88 build: fix build_cmake.bash script for aarch64, bump its default version (#4581)
* When the script was run on aarch64, it was actually hard-coded to
retrieve a version older than we currently require as a minimum. Use the
CMAKE_VERSION hint just like we do for x86_64.
* Bump the default version that this script makes to the latest, 3.31.3.
(This does not change OIIO's minimum required cmake version, it merely
changes the default if this hepler script that we use for CI is run
without any specific version requested.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-08 08:48:46 -08:00
Larry Gritz 424e396658 ci: Only pass build-steps the secrets it needs (#4576)
Safer than letting it inherit all secrets.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-08 08:43:35 -08:00
Larry Gritz 85ece697e8 testing: better testing coverage of null image reader/writer (#4578)
This improves the mediocre testing line coverage in nullimageio.cpp from
50% to 95%.

* Test writing
* Test reading of tiled and MIP-mapped null images
* Test setting and reading of attributes
* Simplify some code
* Along the way, identified and fixed a nullimage bug -- it was
answering that it supported "rectangles" but had no write_rectangle
method. Testing works!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-07 11:17:51 -08:00
Loïc Vital 79cf7bcb85 docs: fix typo in oiiotool's gradient fill argument (#4589)
Correct `botromright` typo in `oiiotool` documentation.

Signed-off-by: Loïc Vital <mugulmotion@gmail.com>
2025-01-07 08:32:51 -08:00
Larry Gritz c8b33ae2fe feat: Filesystem::getline() (#4569)
Convenience function to safely read one line of text from an open FILE*
and return it as a string.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-06 22:04:57 -08:00
Larry GritzandBrecht Van Lommel 3663310751 fix(png): alpha premultiplication adjustment and attribute (#4585)
See discussion
https://github.com/AcademySoftwareFoundation/OpenImageIO/discussions/4054
and PR
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4315

In PR 4315, we fixed PNG read/write to do the required premultiplication
in linear space (that is, linearize, multiply by alpha, then go back to
the sRGB or gamma space). Which we really believe is "correct." Except
that maybe there are a ton of incorrectly made PNG files out there
(maybe most of them?) where partial alpha pixels had their
premultiplication occur on the sRGB or gamma values directly.

In this patch, we partly revert, allowing both potential behaviors,
controlled by an attribute "png:linear_premult", which instructs the PNG
driver to do any premultiplication in linear space if it's set to
nonzero. It can be set globally (via `OIIO::attribute()`), as well as
set/overridden on any individual file by setting the attribute in the
configuration hints for an ImageInput or in the spec for an ImageOutput.

As presented in this patch, we're setting the default to 0, meaning that
by default we are reverting back to the old behavior of doing the
premultiply of partial alpha pixels on the direct values intead of in a
linear space. Applications or sites that are confident that any PNG
files they encounter are "correct" can set the attribute to do the
multiplication linearly.

I'm not 100% confident about the default, and so am very happy to
entertain arguments for keeping the default set to do the multiplication
in linear space.

I had to change an internal spin mutex to a recursive mutex in order to
address a latent misdesign that was made symptomatic by this change.
Basically, asking for an attribute inside an ImageInput::init could make
a deadlock because certain attribute queries (that catalogue the list of
plugins) might instantiate those plugins, thus causing their init
functions to run, leading to recursive dependence on the mutex that
guards attribute queries.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Brecht Van Lommel <brecht@blender.org>
2025-01-06 17:06:16 -08:00
Larry Gritz e964a6af11 ci: test and document support for WebP 1.5 and fmt 11.1 (#4574)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-03 17:09:00 -08:00
Larry Gritz f4acbf3021 testing: improve Ptex testing (#4573)
* Ptex testsuite entry had been accidentally disabled somewhat recently
when we switched to using Ptex exported cmake config instead of our own
find module, because the "found" variable changed from PTEX_FOUND to
Ptex_FOUND.
* Change the test to print stats, thus forcing the ptex test to read
pixels instead of just header info, which improves the testing coverage
of ptexinput.cpp.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-03 17:08:15 -08:00
Larry Gritz dc90fdd2d8 ci: Upgrade to newer actions (#4570)
* Upgrade upload-artifact action, old one is being deprecated.
* Update checkout and cache actions to latest.
* Fix workflow warning: save-always is not really an input to
  actions/cache.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-03 17:06:51 -08:00
Larry Gritz cc5a2cb2ee CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-01 15:09:50 -08:00
Larry Gritz 682825f9df Fix release-sign
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-01 12:05:29 -08:00
Larry Gritz 3bf32a7eeb admin: Sign release artifacts (#4580)
Approach copied from OpenEXR. Let's try it!

Fixes #4404

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2025-01-01 11:51:33 -08:00
Larry Gritz fd411a6e36 fix: various internal fixes to address Sonar and other warnings (#4577)
Chipping away at minor warnings and areas identified by static analysis
as potentially problematic or hard to analyze.

* benchmark.h: suppress warnings about uninitialized Benchmarker
members.
* dpxoutput.cpp: change some raw pointers to spans
* dead code removal (color_ocio.cpp, filesystem.cpp, sysutil.cpp)
* exclude build-scripts from static analysis
* some misc warning suppression

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-31 12:31:37 -08:00
Larry Gritz bff3377d36 fix: IPTC fields have length limits (#4568)
It escaped our notice before that the IPTC spec dictates length limits
for many fields. Getting this wrong can confuse some software, including
Photoshop, apparently.

This patch enforces length limits wherever we could figure them out from
the IPTC spec -- it will simply truncate those strings that are too long
before writing them to a binary IPTC tag.

For this reason, we also are ending the practice of automatically
translating several IPTC fields to and from what we figured were the
equivalent generic metadata names. This was perhaps a dubious practice
to begin with, but now the enforcement of length limits for IPTC (but
not the generic metadata) makes it even more frought. There is probably
nobody depending on this behavior (and maybe few OIIO users depending on
IPTC support at all?), so now anybody purposely using IPTC metadata is
fully responsible for setting it and dealing with any issues of whether
it's "out of sync" with any other metadata that OIIO stores in or reads
from a file.

Fixes #4342

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-27 16:07:01 -08:00
Larry Gritz 6b11c95e95 fix: some LoggedTimer instances lacked a variable name (#4571)
It was syntactically correct, but without an actual variable, there was
no RAII scope and so it destructs immediately, causing the timers to
capture 0 time.

Found by Sonar warnings.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-27 14:41:56 -08:00
Larry Gritz af252a1227 ci: fixups of analysis workflow (#4572)
* Fix missing secrets that accidentally disabled the analysis workflow a
few commits back. After splitting into reusable steps, we needed the
main analysis workflow to let the steps workflow inherit secrets.
* Run analysis on TOT dev branches.
* For analysis, only build OIIO as debug, not dependencies.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-27 13:28:51 -08:00
Larry Gritz 8839accabf ci: refactor using a single steps workflow (#4545)
The logic for the GHA steps was repeated across multiple workflows and
platforms. Consolidate it all into a common "ci-steps" workflow, and
have all the other workflows reference that when possible. This should
hopefully make maintenance of the CI scripts easier in the future, with
less redundancy of the step logic.

The only major place where we deviate is that we have a separeately
specified set of steps for the "old" VFX Platform 2021 and 2022 based
tests (because we need to specify different container arguments to it).

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-21 12:52:07 -08:00
Larry Gritz 57de4554d1 fix: more ICC protections against invalid tag sizes (#4565)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-20 11:06:52 -08:00
Larry Gritz 00d6910f62 docs: Minor fixes and typos (#4564)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-19 12:54:41 -08:00
Larry Gritz dcb38bd76c api: Add global attribute imageinput:strict (#4560)
We don't do anything with this at the present time, but this PR reserves
and documents this attribute for future use.

The intent is to be able to set whether we want image readers to try
being as tolerant as possible when reading a file with flaws (press on
and see if the rest of the file is ok?), or be more conservative and
abandon reading any file as soon as a corruption or invalid data is
encountered (because that might be a clue that the file is arbitrarily
corrupted or even maliciously constructed).

I documented it as defaulting to 0 (err on the side of being permissive
of bad input), with high-security applications being responsible for
setting it to 1. But it's open for debate if people think that a better
default is to be strict and let applications who want to be more
tolerant be responsible for accepting the risk and switching the mode.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-19 12:53:41 -08:00
Larry Gritz 34b29f3321 fix: broken pgm having memory access error (#4559)
Fixes #4552
Caught during fuzzing with address sanitizer.

The source of the problem was a corrupted/truncated pgm file. Several
minor modifications in this PR shore up various cascading errors that
followed. Not all were directly causal to the sanitizer trigger, in some
cases I fixed what appeared to be related areas.

* In imagebuf.cpp, any time we free the local pixel memory m_pixels,
also explicitly clear the m_bufspan that has a span representation of
the usable memory and its bounds.
* An extra check related to oiiotool --printstats to make sure that the
image is valid before passing along to stats collection.
* In pnminput.cpp, a better error message when we hit a premature end of
file.

With these fixes in place, we seem to get a graceful error message and
exit when running the POC that was provided with the bug report.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-09 16:02:40 -08:00
Larry Gritz 78927acce0 fix: broken pnm files with invalid resolution (#4561)
Fixes #4553

Caught during fuzzing with address sanitizer. The file appeared to have
a resolution so big it would not be able to satisfy the memory
allocation.

Solution: add the check_open to take an early abort if resolutions are
bigger than could possibly be valid.

Also have Strutil::stoi hande 32 bit overflow without UB overflow that
the sanitizer complains about (that was the other cascading error that
this same test case encountered in the sanitizer after the bad
allocation).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-06 11:48:26 -08:00
Larry Gritz d2077eb22a fix: Detect invalid ICC profile tags (#4557)
Affects jpeg, tiff, and other formats with embedded ICC profiles.
Corrupted/invalid tag offset and/or length values were causing us to
touch memory outside the memory allocated for the profile.

Fixes #4551

Not sure if this is wise or not, but for JPEGs, I also enabled some
previously commented-out code that has the effect of treating a file
with a verifiably corrupted/nonsensical ICC profile block as a failed
file. If people ever complain about this in the future, maybe we'll come
back and add some kind of global option that lets the app express how
tolerant OIIO readers should be about corruptions in files -- do you
assume that the whole file is bogus or malicious upon discovering the
first invalidity, or do you press on and hope you can get something else
useful from the pixels? Let's be cautious for now.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-05 14:37:10 -08:00
Don Olmstead 904df59ab7 build: Use target_compile_options (fixes a LibRaw build issue) (#4556)
When using pkgconfig the value of `<NAME>_CFLAGS_OTHER` can contain
compiler flags along with preprocessor definitions. If there is a
compiler flag and its passed to `target_compile_definitions` then it
will be treated as if it is a preprocessor definition.

Found a case where a statically compiled LibRaw with a statically
compiled Little-CMS caused `LibRaw_DEFINITIONS` to have `-pthread` in
its listing which was passed to the compiler as a definition,
`-D-pthread`. This caused a build failure with `auto-moc`.

Add an additional parameter for the `add_oiio_plugin` macro to take
`COMPILE_OPTIONS` and pass those to `target_compile_options` which can
differentiate between compiler flags and preprocessor definitions. Pass
`LibRaw_DEFINITIONS` to the CMake macro to prevent the above error.

Issue found while updating Little-CMS in
https://github.com/microsoft/vcpkg/pull/42187 and the change fixes the
build issue found there. This is an attempt to upstream it so the issue
is fixed.

Signed-off-by: Don Olmstead <don.j.olmstead@gmail.com>
2024-12-04 11:59:26 -08:00
Larry Gritz 019cc0db97 CHANGES
(Note that at this point, 3.1 doesn't yet contain anything that hasn't
been backported to 3.0.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-12-01 20:40:11 -08:00
Anton Dukhovnikov e6972b9b8a feat(IBA): IBA::scale() (#4541)
Implements IBA::scale, an algo which takes two images, one of which is
required to be a single channel image, each channel of the other image
gets multiplied by that single channel, per pixel.

Note that this is subtly different from IBA::mul(), which is a
channel-by-channel multiplication, and so doesn't have a provision for
allowing you to scale all channels of one image by the single channel of
a second image.

I have added tests for the C++ code, python code, oiiotool, and the
documentation examples


Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-12-01 12:01:20 -08:00
Aras Pranckevičius 05f5f59825 perf: faster utf8<->utf16 conversion on Windows (#4549)
OIIO 2.3.13 with PR #3307 changed
MultiByteToWideChar/WideCharToMultiByte usage to C++11 <codecvt>
functionality, but that has two issues:

1) it is *way* slower, primarily due to locale object access (on Visual
C++ STL implementation in VS2022 at least). Since primary use case of
these conversions is on Windows, maybe it is better to use a fast code
path.

2) whole of <codecvt> machinery is deprecated with C++17 accross the
board, and will be removed in C++26. I've kept the existing functions in
there since otherwise it would have been an API break, but really maybe
with OIIO 3.0 they should have been un-exposed. Too late now though :(

## Tests

Performance numbers: doing ImageInput::create() on 1138 files where they
are not images at all (so OIIO in turns tries all the input plugins on
them). Ryzen 5950X, VS2022, Windows:

- utf8_to_utf16 3851ms -> 21ms
- utf16_to_utf8 1055ms -> 4ms

Signed-off-by: Aras Pranckevicius <aras@nesnausk.org>
2024-12-01 11:38:17 -08:00
Aras Pranckevičius da475b0525 perf: jpeg2000 valid_file implementation, much faster than trying to open (#4548)
Primary cost of detecting whether a given file is valid jpeg2000 file is
the thread pool initialization and shutdown that `Jpeg2000Input::open`
does (the actual thread pool part is inside OpenJpeg code).

So add a dedicated `valid_file()` implementation that only needs to
check 12 bytes of the header. While at it, I changed already existing
`isJp2File()` to `is_jp2_header()` to better match naming conventions
used elsewhere, and instead of trying to handle both little and big
endian cases by manual repetition of two sets of magic integers, let's
do just byte comparisons with `memcmp` instead.

On my PC (Ryzen 5950X, SSD, Windows VS2022), doing
`ImageInput::create()` on 1138 files where they are not images at all
(so OIIO in turns tries all the input plugins on them):

- Before: **3.4 seconds** spent in `Jpeg2000Input::open` (1.9s
`opj_thread_pool_create`, 1.3s `opj_thread_pool_destroy`)
- After: **33 milliseconds** spent in `Jpeg2000Input::valid_file`

No new tests. I checked behavior on the official Jpeg2000 conformance
data set
(https://github.com/uclouvain/openjpeg-data/tree/master/input/conformance),
seems to work.


Signed-off-by: Aras Pranckevicius <aras@nesnausk.org>
2024-12-01 11:00:28 -08:00
Larry Gritz 9ee71c4522 fix(exr): Avoid integer overflow for large deep exr slice strides (#4542)
Fixes #4540

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-29 22:18:17 -08:00
Larry Gritz 0ca814a2a6 ci: Fix broken CI for ASWF 2021 and 2022 containers (#4543)
The background here takes some explaining...

The ASWF's prepared Docker containers that reproduce a CentOS7-based
environment corresponding to VFX Platform 2021 and 2022 years contain a
glibc that is too old to run a newer version of "node" -- which GitHub
Actions themselves use. The old one is no longer receiving support, and
GitHub finally changed the policy that was allowing its GHA runners to
still run the old version that worked with those ASWF containers. The
new node version that is happy on the GHA runners requires a glibc newer
than the one in the containers. So that breaks all our CI runs in 2021
and 2022 VFX Platform configurations.

See this thread, if you dare:

https://academysoftwarefdn.slack.com/archives/C0169RX7MMK/p1732574400981949

Anyway, Jean-Francois Panisset proposed and tested a fix, which lets us
continue working (for now) by downloading an old node implemenation
(which is happy with the old glibc) and installing it atop the
conainers, so it's this old one that the GH actions will use. It feels
like it's all held together by chewing gum and duct tape, but it
unbreaks our CI and hopefully it will keep working until all the studios
have switched fully to RHEL/Alma/Rocky 9.x and we no longer care about
testing on CentOS-7 based containers or supporting the VFX Platform
years that are too old to be relevant to the new OS that the studios are
using.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-29 08:46:57 -08:00
Larry Gritz ff0861f99a docs: code review guidelines and tips (#4532)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-24 18:29:58 -08:00
Larry Gritz a56cd8a5b4 ci: Don't rebuild docs in CI when only CMakeLists.txt changes (#4539)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-21 10:40:31 -08:00
Larry Gritz b94b10a1fb doc: First stab at an archiecture overview (#4530)
Having such a document is one of the remaining steps to getting our
OpenSSF Best Practices silver level badge.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-21 10:38:29 -08:00
Anton Dukhovnikov 75e70b8753 feat(IBA): IBA:demosaic add white balancing (#4499)
Adds white balancing functionality to IBA:demosaic


Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-11-18 11:28:41 -08:00
Larry Gritz 519a179c2b admin: Document how to make signed release tags (#4529)
Fixes #4403

Also updated some other language in the RELEASING.md document.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-17 15:24:01 -08:00
Larry Gritz 1c3d69421e doc: Quickstart guide (#4531)
Having such a document is one of the remaining steps to getting our
OpenSSF Best Practices silver level badge.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-17 15:23:44 -08:00
Larry Gritz c5c0339b27 fix(exr): allow an empty "name" metadata to be read (#4536)
Continuation of PR #4528. I forgot to change the spot in the OpenEXR
"core" API as well.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-15 13:16:02 -08:00
Larry Gritz d9845863ef build: Add hardening options (#4538)
Get rid of the FORTIFY options, which were too specific to one compiler
feature. Add OIIO_HARDENING that takes a level meaning:

- 0 : do nothing, not recommended.
- 1 : enable features that have no (or nearly no) performance impact,
recommended default for optimized, shipping code.
- 2 : enable features that trade off performance for security,
recommended for debugging or deploying in security-sensitive
environments.
- 3 : enable features that have a significant performance impact, only
recommended for debugging.

Default to 1 for optimized builds, 3 for debug builds (so will be
thoroughly tested by our sanitizer and other CI tests). Users that have
more stringent security requirements may choose to build with 2 even for
shipping code (they should benchmark to see if that is acceptable to
them).

These levels turn on a variety of compiler options that are recommended
for additional safety. We will add more as they are developed.

There are also some warning suppressions that needed to be added to code
in a few areas where it was unavoidable to use some constructs that
trigger the elevated safety checks.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-15 13:15:37 -08:00
Larry Gritz badeba0717 perf: oiiotool --line --text --point --box speedups (#4518)
These commands, which are intended to alter the top image on the stack,
were each allocating and copying an image unnecessarily for each
operation. By changing the implementation to the right calls that know
it doesn't need to make a copy (already a feature I'd implemented in the
OiiotoolOp helper class) greatly speeds them up.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-12 09:55:49 -08:00
Larry Gritz 6a044e9597 ci: increased the macos timeout slightly to fix spurious failures (#4526)
Slow Mac runners sometimes take too long and fail needlessly.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-12 09:55:00 -08:00
Larry Gritz 2132261637 docs: Update some old links to our new vanity URLs (#4533)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-11 12:57:42 -08:00
Larry Gritz 895f0906bc fix(exr): allow an empty "name" metadata to be read (#4528)
When the exr "name" metadata (used for the names of subimages/parts)
existed but was the empty string, we were treating it like it didn't
exist (and upon write substituted our own "subimageXY" name, as we are
wont to do for unnamed parts). But now we've seen multi-part exrs where
the name is "" (exists, but empty string) and we want a read-write cycle
to preserve that. Even though it's not a very sensible or helpful part
name, it's technically legal, so we should honor it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-09 13:00:20 -08:00
Lukas Stockner 24dcdf9bcc feat(jpeg): Support encoding/decoding arbitrary metadata as comments (#4430)
This is needed to port Blender's current JPEG IO code to using OIIO, but
is also a useful feature to have in general.

For reading, the code tries to parse comments as colon-separated
key-value pairs and sets metadata accordingly. For writing, this needs
to be explicitly enabled by setting jpeg:com_attributes to 1 in order to
avoid accidentally bloating files for existing applications.

Tests:

I've added a small (~10KB) JPEG file containing Blender metadata and a
basic test that parses it, checks that the metadata was read correctly,
writes it twice (once with and once without `jpeg:com_attributes`), and
then checks that those files are also parsed as expected.
In case you're wondering why the info for "no-attribs.jpg" still
contains one Blender attribute - that's because the first COM field is
still put into `ImageDescription` just like before, so even without
`jpeg:com_attributes` it ends up being written to the output file and
recognized during parsing.


---------

Signed-off-by: Lukas Stockner <lukas@lukasstockner.de>
2024-11-07 12:21:02 -08:00
Anton Dukhovnikov de51ee61be fix(raw): fix channel layout (#4516)
The function libraw_filter_to_str() converts the `imgdata.idata.filters`
field to human readable form, by mapping a few hardcoded values. I found
the issue by converting images with disabled demosaicing, which writes
the Bayer pattern into the ImageBuf metadata. The Panasonic GX9 didn't
have any pattern recognised; The Canon R5 was incorrectly recognised as
GMCY.

The `imgdata.idata.filters` actually contains a sequence of 2-bit
values, where each represents an index in a 4-character long string
`imgdata.idata.cdesc`. I have modified the code to extract the channels
from `imgdata.idata.cdesc` as expected.

I have also disabled the normalisation code, which I believe was
incorrect, and never executed due to the issue above.

The current tests pass, however, I'll start a discussion on the piece of
code I have concerns with.

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-11-06 14:21:36 -08:00
zachlewis 2f0caf7806 build: support static OCIO self-builds (#4517)
* Add build recipes for certain dependencies needed for linking static
OpenColorIO libs: expat, minizip-ng, pystring, and yaml-cpp

* Add SOURCE_SUBDIR option to `build_dependency_with_cmake` that mimics
the behavior of the FetchContent option of the same name
 
* Tweak OpenColorIO build recipe to always build static libraries by
default.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2024-11-06 14:19:58 -08:00
Larry Gritz 5592195531 docs: Clarify 'copy_image' example (#4522)
It was pointed out on Slack that this example was unclear as to what
should be passed to open().

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-06 14:15:40 -08:00
zachlewisandLarry Gritz ffb7276788 deps: Add build recipe for PNG (#4423)
As requested in #4387.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: zachlewis <zachlewis@users.noreply.github.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2024-11-06 14:13:43 -08:00
peterhorvath111 d1f198ce25 api: OIIO::getattribute queries for available font families and styles (#4523)
Add an API to query available fonts based on family and style name. The
API can be used to build a UI where users can select a font from a list.
They consist of new queries for `OIIO::getattribute()`:

- `string font_family_list`

  A semicolon-separated list of all the font family names that
  OpenImageIO can find. 

- `string font_style_list:family`

  A semicolon-separated list of all the font style names that
  belong to the given font family. 

- `string font_filename:family:style`

  The font file (with full path) that defines the given font
  family and style. 

Fixes #4503.


---------

Signed-off-by: peter.horvath <peter.horvath@autodesk.com>
2024-11-06 11:37:05 -08:00
Vlad (Kuzmin) Erium 3c3f7151bd perf: IBA::unsharp_mask() speed and memory optimization (#4513)
Replacing 3x IBA + Helper function that generate 4 fulls size image
buffers with single unsharp_mask_impl() that use parallel_image() to
compute unsharp:
src + contr * (((src - blur) < threshold) ? 0.0 : (src - blur))

Added two pass 1D convolution for a kernels higher than 3x3

## Tests

```
	ImageBuf sharped(input.spec());
	const int repeats = 50;

	std::cout << "Start sharpening\n";
	auto start = std::chrono::high_resolution_clock::now();

	for (int i = 0; i < repeats; i++)
	{
		//ok = ImageBufAlgo::unsharp_mask(sharped, input, "gaussian", 15.0f, 10.0f, 0.01f);
		ok = ImageBufAlgo::unsharp_mask(sharped, input, "gaussian", 5.0f, 2.0f, 0.05f);
		std::cout << ".";
	}

	std::cout << "\n";

	auto part1 = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> elapsed_part1 = part1 - start;
	std::cout << "Elapsed time: " << elapsed_part1.count() << " s\n";
```

both single threaded (one IB at time) and multithreaded (multiply IB at
time) show pretty good speedup:
~30-40% with less memory use.

for 5x5 gaussian kernels two pass mode should add at least 20% speedup.

(if someone can do independent benchmark, will be great. As soon as I
had a big differences on them depend on real or synthetic use)

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2024-11-06 11:24:35 -08:00
Loïc Vital 30f6a0a915 feat(jpeg): Support reading Ultra HDR images (#4484)
Initial feature request: https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4424

Add support in the `jpeg` plugin for reading Ultra HDR images using the reference codec `libultrahdr`: https://github.com/google/libultrahdr

In short, "ultra hdr" images are a clever extension of JPEG where the image file really is an old school JPEG file and will be interpreted correctly as such by old readers not aware of ultra hdr, but readers that are aware will see an extra piece of metadata that contains a gain map, that when applied to the base layer then yields an HDR image. Pretty clever approach!

Images used for testing during development:
https://github.com/MishaalRahmanGH/Ultra_HDR_Samples

---------

Signed-off-by: loicvital <mugulmotion@gmail.com>
2024-11-06 10:59:31 -08:00
Larry Gritz d8fe20e1af deps: Add new ref output for libheif updates (#4525)
The latest libheif patch release changed something very slightly that
requires us to update some saved reference output.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-11-04 17:05:53 -08:00
Larry Gritz f6c7e4fafb Update ABI reference commit
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-30 10:07:49 -07:00
Larry Gritz c1d3c805c1 CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-30 10:07:49 -07:00
Larry Gritz 7929c81619 perf: file read performance -- double reads, extra copies (#4507)
Doing some benchmarking and adding extra LoggedTimer instrumentation
(included in another PR), I discovered that quite frequently, the
in-memory flavor of ImageBuf was reading its image multiple times --
once upon construction, and then again upon later calls to read(), even
though the latter should have taken early outs when the read was
unnecessary.

So I put some additional mechanism for the IB to internally know if it
read the pixels from disk into the buffer, and more effectively make
calls to IB.read() be a no-op. To help facilitate this, I also clarified
in the docs that read() should not be used to move an already-read image
to a different subimage or MIP level or a different data type -- reset()
really should be used for that purpose. (I don't know that anybody ever
relied on read() to do reset's job, but assuming that they won't helps
eliminate some tricky cases.)

Also, I noticed that inside ImageInput::read_image(), depending on
whether or not a data type conversion is needed, it can either read
directly into the user's buffer, or must read the native data into a
temp buffer and subsequently do a copy-and-type-convert into the user's
buffer. The latter is obviously more expensive. The direct read approach
was used when the user asked for no type conversion (just to receive the
native data type in the file), but it neglected to take the same
shortcut if the user asked for an explicit type conversion, but it just
so happened that the requested type was the type in the file.

Additional changes:

The evaluation of whether the buffer was contiguous (for various
shortcuts) only applied to LOCALBUFFER style storage, not APPBUFFER.

Fixing these two problems dramatically speeds up some reads. A benchmark
I was looking at where it reads a 10k x 10k uint8 uncompressed TIFF file
into an ImageBuf while requesting uint8 data went from (timings on my
laptop):

    function                  calls    total
    IB::read                      2   0.505s  (avg   0.25s)
    II::read_image                2   0.478s  (avg   0.24s)

to:

    IB::read                      1   0.172s  (avg   0.17s)
    II::read_image                1   0.172s  (avg   0.17s)

So almost 3x faster. Most of which was due doing 2 reads instead of 1,
but still each individual read improved from 0.25s to 0.17s because of
the fix that lets us avoid the unnecessary buffer copies.

Grain of salt: this was a very large image, and it was stored
uncompressed (so NO decompression that can sometimes be a significant
amount of overhead), so you may not see this much improvement in real
world scenarios.

This is only scratching the surface, I believe there are lots of other
areas to optimize more carefully.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-29 11:47:02 -07:00
peterhorvath111 95d246d198 feat: Lookup font in text render based on family and style name (#4509)
Fixes #4502.

This PR lets you specify fonts (for `IBA::render_text()` or `oiiotool --text`)
by family and style name, rather than only by filename of the font file.

The implementation is to add `init_font_families()` function, that iterates
over the available font files, reads family and style name via the freetype
API and caches them. The function is called from `resolve_font()` on
demand.

Added a new test to the oiiotool-text folder, that loads a font by the
name "Droid Serif Bold".

---------

Signed-off-by: peter.horvath <peter.horvath@autodesk.com>
2024-10-29 11:45:34 -07:00
zachlewis c8e4ffeee1 deps: Add build recipe for WebP (#4422)
As requested in #4387.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
Signed-off-by: zachlewis <zachlewis@users.noreply.github.com>
2024-10-29 11:23:58 -07:00
Larry Gritz a4098cfc0e ci: Retire deprecated macos12 runner, try beta macos15 (#4514)
The GHA macos-12 runner is deprecated and soon to be retired. It's
already flaky and they're doing purposeful outages to remind people (the
cloud equivalent of turning the lights on and off right before the bar
closes).

We still want to test earlier MacOS-12 compatibility to match VFX
Reference Platform, so use the macos-13 runner as the minmum but set
MACOSX_DEPLOYMENT_TARGET=12.0 to test that configurations.

Also, the MacOS-15 runner is in beta, so add that to the mix. (Along the
way, that also verifies that we run fine against python 3.13.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-29 09:47:33 -07:00
Larry Gritz a19b2c53a8 api: Deprecate OIIO::string_view::c_str() (#4511)
Because it's not in std::string_view.

If you must use this functionality (with caution about when it is safe),
then use the freestanding `OIIO::c_str(OIIO::string_view)` function
instead.

I would like to include this warning in 3.0.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-27 21:57:31 -07:00
Larry Gritz 9f3e15f413 docs: fix typo in description of Strutil::parse_values (#4512)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-27 21:52:32 -07:00
peterhorvath111 2515270129 Update font enumeration (#4508)
Fixes #4504

The PR removes the code that looks for font folders based on a prefix
and suffix list. Instead, adds all known system font folders per each
platform. The global "font_searchpath" attribute, `OPENIMAGEIO_FONTS`
and `OpenImageIO_ROOT` environment variables are still searched as
before, such as fonts directories relative to the currently running
binary. However $HOME and $SystemRoot folders (with all previous
suffixes) are not searched anymore, thus this is a breaking change, and
the documentation might need to be updated accordingly.
The search order did not change. It's still "font_searchpath" attribute,
environment variables, system font folders, folders relative to binary.

---------

Signed-off-by: peter.horvath <peter.horvath@autodesk.com>
2024-10-27 10:09:15 -07:00
pfranz c7388bbdb5 docs: Convert ImageInput-unassociatedalpha examples from docs to tests (#4468)
Convert error checking C++ and Python examples from the "imageinput"
chapter into tests within the "docs-examples" testsuites
(https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3992).

I grabbed unpremut.tif from the output of another test.

--

Signed-off-by: Paul Franz <pfranz@laika.com>
2024-10-26 13:09:28 -07:00
Larry Gritz 7e7dc0e939 int: Additional timing logging for performance investigations (#4506)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-25 18:39:58 -07:00
Larry Gritz 8e78a3d931 fix: address fmt exceptions for left justification (#4510)
I don't understand why, but for certain combinations of gcc, fmt, etc.,
we were getting exceptions from fmt. I finally caught it in the act! It
seems related to formatting specs that looks like `{:-20s}`. Maybe this
used to be allowed but isn't officially supported? Anyway, left
justification is default anyway, so there's no point to the `-`.
Removing it makes fmt happy, no more exceptions.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-25 18:36:50 -07:00
peterhorvath111 6eb9538e9e fix: Windows newline shows invalid character in text render (#4501)
Newline in strings on Windows is encoded as '\r\n', that is currently
not handled by the text render code and so carriage return (\r) shows up
in the rendered text. As a fix we simply ignore this character.
We came across this issue while exporting user specified text from DCCs
to render on Windows.

I'm not sure how to make a proper test case for this. Current tests
specify a command as a string that is passed to oiiotool as arguments
and executed in the command line. But adding a newline to the text
breaks the command.

Signed-off-by: Peter Horvath <peter.horvath@autodesk.com>
Signed-off-by: peter.horvath <peter.horvath@autodesk.com>
2024-10-25 03:50:29 -07:00
peterhorvath111 0c24aadfd4 fix(IBA): fix incorrect vertical alignment in text render (#4500)
The `y` argument in `OIIO::ImageBufAlgo::render_text()` should represent
the top and bottom edge of the text if vertical alignment is set to
`TextAlignY::Top` and `TextAlignY::Bottom`. However currently the
rendered text is off. The current code adjusts y to point to the top of
the text box before rendering the text, but it has to be adjusted to
point to the baseline of the text.

Tests

There is a existing test case, testing vertical alignment, but the
reference image seems wrong and has now been updated. See the "Topleft"
and "Rightbot" texts.

| Current    | Fixed |
| -------- | ------- |
|
![image](https://github.com/user-attachments/assets/e9e135bf-21d1-43a9-ace9-05b0e99af084)
|
![image](https://github.com/user-attachments/assets/970dee6a-5337-4382-bcc2-16f474bba160)
|

Note: The testsuite contains a reference image for freetype v2.4.11
(aligned-freetype2.4.11.tif). I don't have that version built, and
haven't been able to update the image. I'm wondering if this is still
used or could be removed. I guess CI will tell.

---------

Signed-off-by: peter.horvath <peter.horvath@autodesk.com>
2024-10-25 03:49:21 -07:00
kaarrot 86c4e55cba build: BUILD_MISSING_DEPS - fix minor configuration options (#4493)
Address a few small issues encountered during CMake configuration step
and during build using Makefile `BUILD_MISSING_DEPS` option enabled.
- Mismatch between expected libraw versions specified in
`build_libraw.bash` 0.21.3 and `externalpackages.cmake` 0.20.0
- OpenEXR link error in libutil tests
- Update top level Makefile to accept `BUILD_MISSING_DEPS` as string
instead of bool. Pass the string option down to CMake

Verified build completes with no errors: `BUILD_MISSING_DEPS=all make`

Signed-off-by: kuba <kuba456@gmail.com>
2024-10-25 02:48:13 -07:00
Larry Gritz ff0b55799e build: Remove the enforced upper version limit for fmt (#4497)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-25 02:46:36 -07:00
jreichel-nvidia b54a80b706 build: search for libbz2 only if FFmpeg or FreeType is enabled. (#4505)
Detect libbz2 only if necessary, i.e., FFmpeg or FreeType is enabled.
This avoids an unnecessary dependency on libbz2 if these features are
disabled.

In particular, with vcpkg, OpenImageIO might pick up a dependency on
libbz2.so from the host system since bzip2 from vcpkg is not listed as a
dependency of OpenImageIO (if the FFmpeg and FreeImage features are
disabled, and bzip2 is not already installed for other reasons).

Signed-off-by: Joachim Reichel <43646584+jreichel-nvidia@users.noreply.github.com>
2024-10-25 02:44:50 -07:00
Larry Gritz 966b9679a8 fix(iinfo): iinfo was not reading MIP levels correctly (#4498)
A logical error was causing us to not correctly cycle through the
successive MIP levels. Somehow, we missed this all these years.

You can tell that there was something wrong all along by examining the
testsuite/iinfo test output (which we have updated here) -- in the
old/wrong one, the statistics "FiniteCount" suspiciously stayed the same
for all MIP levels, which is clearly wrong. Now you can see that it does
correctly reflect the reduced resolution of each MIP level.

This bug was limited to 'iinfo' itself. There wasn't any inherent
problem with reading MIP levels directly with ImageInput or ImageBuf.

The line with the bug has been unchanged for 14 years! We were trying to
be clever about not double-reading, except that the only context in
which this was called, that would never have happened anyway, so that
cleverness (which was incorrectly implemented) was unnecessary.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-23 16:54:27 -07:00
Larry Gritz 3b70f1d2d2 docs: typo
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-20 09:42:49 -07:00
Larry Gritz c3c6b1e01b ci: Limit when automatic docs building ci happens (#4496)
Times we DON'T need to test rebuilding the docs:

* When just the ci.yml workflow changes (like when we bump what versions
of dependencies ci tests use).
* When tests changes only by altering their run.py.

But DO try rebuilding docs:

* When cpp files change that are outside of src/, such as the cpp files
in the testsuite that are used to supply code snippets that appear in
the docs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-18 10:06:30 -07:00
Larry Gritz b93220e984 ci: Bump ABI reference commit for the start of 3.1
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-17 17:40:33 -07:00
Larry Gritz db9fe349d0 admin: Reset main to be development for an eventual 3.1 (#4495)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-16 09:34:35 -07:00
Larry Gritz c2b344bee7 Stage for v3.0.0.0-beta1
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-15 15:25:50 -07:00
Larry Gritz 5482644429 docs: Update to vanity URL for the docs (#4494)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-15 15:25:17 -07:00
Larry Gritz acdb049da1 ci: Bump ABI reference for 3.0 beta
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-15 12:03:17 -07:00
Larry Gritz 45e49979fc docs: Release notes for 3.0 (#4492)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-15 11:45:34 -07:00
Larry Gritz d36e615fe4 api(TS): Version TextureOptBatch like we did for TextureOpt (#4490)
I got part way through the OSL side changes to accommodate what we did
recently with TextureOpt and TextureOptBatch. Ugh, it's a lot harder
than
I thought and I don't know how to finish the job without postponing the
3.0 release even more, which is unacceptable at this point. So here I do
to TextureOptBatch to get out of this mess:

* "Version" TextureOptBatch like we did for TextureOpt (should have done
  that all along).
* Revert "v1" to the same byte-for-byte layout we used to have, which
involves using `int` for some fields as it implicitly did before,
because
  the new enum classes totally change the field sizes and struct layout.
* Sketch out in comments what v2 might look like, to more fully match
the
TextureOpt. The introduction of struct versioning means we can make that
  change for 3.1, it doesn't need to wait years for 4.0.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-15 10:10:24 -07:00
Larry Gritz 554c3dacde ci: Fix broken bleeding edge test (#4491)
It's failing to get Mesa packages for some reason. Disable Qt and OpenCV
on this one test to work around it for now.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-14 20:30:28 -07:00
Larry Gritz a4a759f875 api: Remove deprecations (#4488)
These are all things long marked as deprecated (often since before the
official launch of 2.0) that we've waited for 3.0 to finally remove. Now
is the time.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-12 19:05:15 -07:00
Larry Gritz e8a0e38e00 cleanup: Remove code disabled as of 3.0 (#4487)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-12 18:07:21 -07:00
Larry Gritz 5b962b6f77 api: TextureOpt refactor (#4485)
* Version the class for easier future expansion! Let's call it
`TextureOpt_v2` and we make a `using` alias so that the name
`TextureOpt` means this. We can then revise the struct in the future by
not losing link compatibility.

* The macro OIIO_TEXTUREOPT_VERSION (now 2) can be used to test which is
the current version.

* Get rid of TextureOpt-local enums by finally switching to the
freestanding ones in the Tex namespace. (We've wanted to do this for a
long time, but couldn't break compatibility.) Preserve API compatibility
for now with clever use of `static constexpr` and `using`.

* Make more efficient use of space in the TextureOpt by: field order
rearrangement to eliminate empty space, switching a couple of the enums
that needed only a few values to be `class enum xxx : uint8_t` so they
take only 1 byte instead of 4, switch `anisotropic` to be 16 bits (do we
really need an anisotropic ratio > 65535?), elimiate the time and
samples fields which have never been used (they were reserved for shadow
maps, which we never implemented).

I think this set of changes is minimally onerous to downstream projects
for the 3.0 release, while laying a path forward (via the versioning) to
allow future changes to the struct to happen with a lower pain
threshold.

I don't claim that this perfectly preserves downstream source
compatibility, but the fact that outside of these changes to
delcarations in texture.h, only 8 lines in the entire rest of the OIIO
codebase needed to change to accommodate them. So I think that the
impact downstream will be minimal. (OSL might be the exception, since
its LLVM code generation is exquisitely sensitive to the exact layout of
the TextureOpt struct, but I'm working on those changes, too.)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-11 17:55:44 -07:00
Larry Gritz bb4f20a5ea admin: Update SECURITY.md for 3.0 beta (#4486)
Proposed revision to security version policy post 3.0 branch.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-11 17:55:17 -07:00
Larry Gritz fa0507fc9d api: Change Strutil::format to default to std::format conventions (#4480)
This finally switches Strutil::format to use std::format conventions.
You can still access the old printf convention via
`Strutil::old::format()`, and can explicitly access the new convention
uniformly on both 2.x and 3.x via `Strutil::fmt::format()`.

It also removes a long-deprecated vformat function.

We've been waiting for 3.0 to make this non-back-compatible change.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-11 17:55:00 -07:00
Larry Gritz 33bb76547c Bump version to 3.0.0.0, prepare for beta (#4481)
A few minor changes were needed to keep a working build, due to things
long ago rigged to be disabled as soon as the version bumped.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-11 17:53:52 -07:00
Larry Gritz a946288db4 Color management nomenclature improvements (#4479)
A round of color management improvements (I hope).

We were pretty squirrelly about what "linear" meant. Get more exact. Now
we will treat "linear" as a legacy synonym for "lin_rec709" (sRGB
primaries, but linear response). Change file format readers to say
"lin_rec709" when they mean it, and not use the more generic alias
"linear".

"scene_linear", on the other hand, is the internal working color space
for math. Which concrete color space it is an alias for is determined by
the OCIO config in use.

Use "g18_rec709" and "g22_rec709" for rec709 + gamma 1.8 or 2.2,
respectvely.

A few new API calls help out: equivalent_colorspace(),
set_colorspace(spec,name), set_colorspace_rec709_gamma().

OpenEXR always tagged files as linear by default. It was too aggressive
about this, so with this PR, now it defaults to lin_rec709 only for
files that appear to be RGB and not have any other clues about the color
space.

Similarly, the raw reader was too eager to set the Exif:ColorSpace to
look like sRGB even when it wasn't.

Lots of reference outputs needed to be updated.

This is a potentially big behavior change. But I think it's for the
better.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-08 08:52:34 -07:00
Larry Gritz ff20241916 perf: Reduce compile time by trimming template expansion in IBA (#4476)
I was profiling the builds and saw that modules with lots of template
expansion dominate the compile time. For example,
imagebufalgo_pixelmath.cpp alone took 290s to compile on my 2020
MacbookPro (!), and imagebufalgo_addsub.cpp took 84 seconds.

This is all due to the combnatorics of expanding IBA templates via the
DISPATCH macros in imagebufalgo_util.h separately for every type that
the arguments can be. But I claim that most combinations are rarely if
ever used. I mean, how often does anybody need IBA::add() to add an int8
image to an int16 image? So this PR rewrites those macros to simplify
the cases as follows:

* The common pixel data types are float, half, unint8, and uint16.

* Specialized versions are fully expanded only when the result and input
images are one of these types. Images not of one of those types are
first automatically converted to float to make them reduce to a common
case. That makes uncommon pixel data types like (signed) int16 not
expand the template, but rather convert to and from float and use the
float specializations.

* For binary and ternary operations (those with 2 or 3 image inputs), if
the pixel types of the inputs doesn't match, we make sure they both are
converted to float. So, for example, we don't need a specialized version
that adds a half image to a uint16 image -- just convert them to float
and use the common case. But we do specalize if the two inputs are both
the same common case, such as adding two uint16 images.

* Assume that commonly, the result image will either be float, or will
be the same pixel data type as the inputs. Other combinations trigger
assignment to a temporary float IB, then copying with convertion to the
uncommon use-supplied result buffer.

* Additionally, we cut down on a little bit more templating by moving
some "deep" methods from the type-templated ImageBuf::Iterator to its
type-generic non-templated base class IteraterBase.

The net result of all this is an awful lot less template expansion. With
this in place, my laptop compiles imagebufalgo_pixelmath.cpp in 97s (vs
290 before) and imagebufalgo_addsub.cpp in 26s (from 84). It takes a big
bite out of all the iba files, and reduces project-wide compile time by
over 10%, around 30s out of 300 for a fresh, uncached, optimized build
with 16 threads.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-08 07:53:45 -07:00
Larry Gritz 704d0db42e CHANGES, etc.
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 21:46:57 -07:00
Larry Gritz 94f6c54989 build: add option for build profiling with clang -ftime-trace (#4475)
Document the process, too.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 16:38:33 -07:00
Larry Gritz 7a6b6932fc testing: Fixup after directory refactor of OpenImageIO-images (#4473)
I refactored the companion project full of testing images, putting all
the clutter in the main directory into a subdirectory for each file
type. These are the main OpenImageIO changes needed as a result.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 16:37:42 -07:00
Larry Gritz bbe91ad37f build: Raise CMake minimum to 3.18.2 (#4472)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 16:37:21 -07:00
Larry Gritz 9bf4356412 docs: Add documenting comments where missing in string_view and span (#4478)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 16:37:07 -07:00
Larry Gritz d031277579 docs: Various minor fixes (#4477)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-04 16:36:56 -07:00
Luc Touraille 33a772db30 build: Don't change CMAKE_XXX_OUTPUT_DIRECTORY when built as subdir (#4417)
When building OIIO as a subdirectory of a super-project (with
`add_subdirectory`), it is better to honor the output directories
specified by the parent project.

In our project, it was causing issues because OIIO libs were ending in a
different folder from USD plugins, which thereby failed to load
correctly in the build tree.

Signed-off-by: Luc Touraille <touraill@adobe.com>
2024-10-03 12:58:32 -07:00
Larry Gritz 1ba3d451c4 fix(openexr): modernize dwa compression level setting (#4434)
Starting with OpenEXR 3.1.3, the preferred API call for setting
DWAA/DWAB compression level has changed. We never changed the OIIO side.
Luckily, OpenEXR seems to have kept respecting the old API calls we were
making (passing as an attribute). But this modernizes the approach, now
that we don't have OpenEXR 2.x support to maintain.

But in the process, we also fixed a bug! Turns out we weren't
propagating the compression properly -- if the compression name
was plain "dwaa", we ignored any "openexr:dwaCompressionLevel"
attribute, effectively.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-03 12:52:21 -07:00
Bram Stolk 3f4285b936 testing: Add switch to imageinout_test for enabling floating point exceptions. (#4463)
Adds new feature: floating point exceptions, to imageinout_test binary.

Running `imageinout_test --enable-fpe` will run the test with FPEs enabled.

Currently it is catching a FP overflow in libjxl.
Once that is fixed, it may find other FPEs.

For now, this is a Linux-only feature.

```
$ ./imageinout_test --enable-fpe
```

Signed-off-by: Bram Stolk <b.stolk@gmail.com>
2024-10-03 08:17:22 -07:00
Danny Greenstein 1be693b211 docs: convert docs -> examples for image enhancement and restoration section (#4458)
Further work towards #3992

Signed-off-by: Daniel Greenstein <danny.gr@gmail.com>
2024-10-01 19:22:05 -07:00
Larry Gritz 765c8edfb0 ci: Make scrorecards workflow not fail constantly (#4471)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-01 19:17:47 -07:00
Larry Gritz ce70eb747a Fixup after PR 4470
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-01 15:18:15 -07:00
Larry Gritz db418827cc Fixup after PR 4470
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-01 15:12:36 -07:00
Larry Gritz 0a47039f49 docs: Move some docs around (#4470)
* Move RELEASING.md from the top directory to docs/dev
* Move 0.x and 1.x CHANGES documents from src/doc to docs
* A couple master->main renames that were MIA

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-01 10:43:16 -07:00
Todica Ionut 2d5017822c admin: Update OpenImageIO Roadmap (#4469)
Check off the successfully raised dependencies.

Signed-off-by: Todica Ionut <todicaionut2000111@gmail.com>
2024-10-01 08:00:12 -07:00
Larry Gritz 8f28abed1f ci:Test against OCIO 2.4 (#4467)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-10-01 07:57:47 -07:00
Larry Gritz 6b23d7a52a ci: Test against OpenEXR 3.3 and deal with its 4.0 bump (#4466)
OpenEXR 3.3 was just released and its main branch has bumped its
advertised version to 4.0 (the latter breaking our "bleeding edge" CI
test).

Raise our "latest releases" test to use 3.3.

Our "bleeding edge" test picking up the now-called-4.0 OpenEXR main
branch required some minor logic changes to not reject the version as
too new to be compatible.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-30 21:26:22 -07:00
Larry Gritz 260972944f ci: Streamline the old MacOS-12 CI test (#4465)
It's an old flavor not well supported by homebrew any longer, so what's
happening is that some of the dependency packages we ask to install have
to build from source, which means it takes a long long time.

By disabling OpenCV and Qt homebrew installation for it, we can make it
fast again. Neither the minimal OpenCV interop, nor osltoy (the only
thing that needs Qt) are exercised by the automated testsuite anyway, so
I don't think there's any loss of testing functionality in practice.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-30 14:54:32 -07:00
Ankit Sinha 8bfa9943ab feat(raw): raw reader - exposing max_raw_memory_mb (#4454)
PR is to address
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3881
feature request. The reported wanted to expose
`imgdata.rawparams.max_raw_memory_mb` as `raw:max_raw_memory_mb`

---------

Signed-off-by: Ankit Sinha <ankitsinha@netflixanimation.com>
2024-09-29 21:16:36 -07:00
Larry Gritz c1318c1573 build(deps): support fmt 11.0 (#4441)
Some behavior changed for fmt error conditions, an in a way that
requires us to remove a test, because there is no reproducible output
to compare against.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-29 21:13:08 -07:00
Bram Stolk 970153d30c fix(ImageInput): Initialize pixels of partial tile conversion buffer. (#4462)
When writing a partial tile, the unused pixels still go through float
conversion.

This means, that floating point operations are done on uninitialized
data.

This can easily lead to NaN and to floating point exceptions, if those
were to be enabled.

This change will set the shared buffer used for all partial tiles to all
zero pixels.

Tested by running valgrind before and after the change

FIXES: #4461

Signed-off-by: Bram Stolk <b.stolk@gmail.com>
2024-09-29 18:14:59 -07:00
Andy Chan 609999e7c9 feat(iv): add iv data and display windows overlay (#4443)
Adding data and display window overlay in iv.
Dashed line: Display window
Solid line: Data window

Off by default, select "Show display and data window borders" from the View menu.

---------

Signed-off-by: tkchanat <andychancse@gmail.com>
2024-09-29 07:51:33 -07:00
Larry Gritz a5dd2c3729 ci: Bump the ABI reference commit
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-28 16:00:52 -07:00
Basile Fraboni 14be11a71d api: IC/TS get_imagespec, imagespec, get_cache_dimensions (#4442)
First draft of front end changes for  issue #4436.

The end goal is to remove redundant ImageSpec from ImageCache internals (issue #4436).
But that necessarily changes some assumptions about what is accessible through the public
APIs for ImageCache and TextureSystem. This PR contains the API-side changes, but without
the internals overhaul that will come later.

* `get_imagespec()` and `imagespec()` lose their miplevel and native parameters.  We are
   now assuming now that there is no arbitrary metadata varying per-mip-level. Also, loss
   of native param means that it's always copying an ImageSpec that reflects the file.
* New `get_cache_dimensions()` is a lighter-weight function that can retrieve the limited
   items that really do vary between MIP levels, and may differ between the file and the
   in-cache pixels: resolution, tile size, pixel data format.
* Harmonize the order of parameters in the analogous functions exposed by IC and TS
  (they confusingly differed before).
* For now, API-backward-compatible wrappers for the old functions, which will eventually
  be deprecated and then removed.

---------

Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
2024-09-28 14:58:14 -07:00
Dharshan Vishwanatha 243b3b6855 int: Added check_open for PNG, JPEG, and EXR readers (#4452)
This PR is ment to address this feature request:
https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3974

I added `check_open` for these file format's ImageInput while following
each file specfication:
- PNG: https://www.w3.org/TR/png/#11IHDR
- JPEG:
https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#JFIF_APP0_marker_segment
- EXR:
https://openexr.com/en/latest/OpenEXRFileLayout.html#header-attributes-all-files

---------

Signed-off-by: Dharshan Vishwanatha <dharshanv1999@gmail.com>
2024-09-28 08:56:31 -07:00
Lydia Zheng 0391796682 docs: convert to test for ImageBufAlgo Partial Image Arithmetic (#4460)
cumentation to testsuite conversion for cpp and python for the
ImageBufAlgo Chapter, Section: Image Arithmetic up to the div function.

The PR also fixes a python testing image file reference in
..docs-examples-python/ref/out.txt, where reference images "simple.tif"
and "scanlines.tif" should have the docs-examples-cpp prefix (see
..docs-examples-python/run.py line 11 for details).

---------

Signed-off-by: Lydia Zheng <lydiamzheng@gmail.com>
2024-09-27 20:12:46 -07:00
Ziad Khouri 6e62fb4d55 docs: Convert ImageInput tiles examples from docs to tests (#4455)
Convert tiles C++ and Python examples from the "imageinput" chapter into
tests within the "docs-examples" testsuites
(https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3992).

---------

Signed-off-by: Ziad Khouri <ziad@caligra.com>
2024-09-27 18:48:24 -07:00
Larry Gritz 9133e01937 testing: Update test ref output for OpenColorIO 2.4 (#4459)
This fixes OIIO's CI "bleeding edge" test that broke when OCIO pushed
to their main the new config files that will be in OCIO 2.4. (Yay!)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-27 15:55:29 -07:00
pfranz d94d381bb3 docs: Convert ImageInput-errorchecking examples from docs to tests (#4456)
## Description

Convert error checking C++ and Python examples from the "imageinput"
chapter into tests within the "docs-examples" testsuites
(https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3992).


Signed-off-by: Paul Franz <pfranz@laika.com>
Signed-off-by: Paul Franz <paul@paulfranz.com>
2024-09-27 14:46:24 -07:00
Bram Stolk a7276c753e fix(iv): Initialize variables before we use them. (#4457)
This addresses:
```
==126424== Conditional jump or move depends on uninitialised value(s)
==126424==    at 0x16A24E: IvGL::mouseMoveEvent(QMouseEvent*) (src/iv/ivgl.cpp:1208)
==126424==    by 0x5FCD5F6: QWidget::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x5F843AF: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x5F7D2C6: QApplication::notify(QObject*, QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x6E35447: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Core.so.6.4.2)
==126424==    by 0x5F79D7D: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x5FDBAD6: ??? (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x5FDCE74: ??? (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x5F843AF: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6.4.2)
==126424==    by 0x6E35447: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Core.so.6.4.2)
==126424==    by 0x6762DE6: QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt6Gui.so.6.4.2)
==126424==    by 0x67AD5CB: QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib/x86_64-linux-gnu/libQt6Gui.so.6.4.2)
==126424==  Uninitialised value was created by a heap allocation
==126424==    at 0x4846FA3: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==126424==    by 0x11F509: ImageViewer::ImageViewer(bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (src/iv/imageviewer.cpp:140)
==126424==    by 0x17D248: main (src/iv/ivmain.cpp:127)
```


With this patch, this particular valgrind error goes away.

Tested by running valgrind on iv before and after change.


Signed-off-by: Bram Stolk <b.stolk@gmail.com>
2024-09-27 14:42:52 -07:00
Bram Stolk f875327dfa fix(pnm): Initialize m_pfm_flip before use to avoid UB. (#4446)
Fixes #4445

This avoids UB by initializing a variable.

## Tests

I ran valgrind after the fix: no longer issues error.

```
==77256== 
==77256== HEAP SUMMARY:
==77256==     in use at exit: 25,167,390 bytes in 8,232 blocks
==77256==   total heap usage: 183,524 allocs, 175,292 frees, 4,415,783,216 bytes allocated
==77256== 
==77256== LEAK SUMMARY:
==77256==    definitely lost: 0 bytes in 0 blocks
==77256==    indirectly lost: 0 bytes in 0 blocks
==77256==      possibly lost: 0 bytes in 0 blocks
==77256==    still reachable: 25,167,390 bytes in 8,232 blocks
==77256==         suppressed: 0 bytes in 0 blocks
==77256== Rerun with --leak-check=full to see details of leaked memory
==77256== 
==77256== For lists of detected and suppressed errors, rerun with: -s
==77256== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
```

---

Signed-off-by: Bram Stolk <b.stolk@gmail.com>
2024-09-27 04:03:49 -07:00
David Adler 3e4f2cc15d fix(iv): iv shows constant brown and GL error messages on start-up. (#4451)
This fixes a problem seen on RHEL 9.2 Linux when launching an image in
iv, eg:
  iv testsuite/texture-overscan/ref/out-exact.exr

The image displayed as a constant brown and the terminal showed:
  GL error create program 1281 - Invalid value
  GL error After attach vertex shader. 1281 - Invalid value

The fix is to initialize m_shader_program and m_vertex_shader in the
class constructor.


ERROR ANALYSIS:

The bug was introduced in 5fe44415 "feat(iv): OCIO color managed display
(#4031)".

Before that commit, create_shaders() initialized those members to 0
before they were used.

After that commit:

* uninitialized m_shader_program is passed to glDeleteProgram() (near
the top of create_shaders) ), causing the
"create program" warning (there isn't an print_error call after
glDeleteProgram so the error is reported as "create program").

* ununitialized m_vertex_shader is non-0 when checked by if
(!m_vertex_shader), causing the vertex shader not to be created and
causing the later call to glAttachShader() with uninitialized
m_vertex_shader to fail. That causes the second error message, and lack
of a vertex shader apparently causes the image to display as constant
brown.

Signed-off-by: David Adler <david1.pub@gmail.com>
2024-09-27 03:53:19 -07:00
Ziad Khouri e5ad995c9f docs/testing: Convert docs examples to tests in ImageInput chapter (#4444)
Convert scanline C++ and Python examples from the "imageinput" chapter
into tests within the "docs-examples" testsuites
(https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/3992).

---------

Signed-off-by: Ziad Khouri <ziad@caligra.com>
2024-09-26 19:08:03 -07:00
Anton Dukhovnikov e45a625626 fix(raw) check for nullptr in raw input plugin (#4448)
This adds a null pointer check in the raw input plugin when the user
requested raw bayer data for a file format which doesn't have it. With
this fix OIIO shows an error instead of crashing in such case.

This fixes the issue mentioned in the comments of #4361. The title issue
of #4361 has been resolved in LibRaw 0.22.0, so we can close that issue,
I guess.

This also fixes the crash on 5 out of 6 examples in #3115. The last one
is unrelated, and I don't have a good fix for that at this time (crash
due to the raw buffer having half resolution, with the pixel aspect
ratio of 0.5). Perhaps we could create a separate issue and close #3115.

I have not added any tests for this change specifically, as it is fairly
trivial.
I have started working on a more comprehensive test suite for the raw
plugin / rawtoaces, but it's not ready yet, and I'm not sure where it
should live at this stage.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-09-26 17:55:50 -07:00
Larry Gritz de6cb3e041 testing: add test ref for old fmt (#4450)
For old versions of fmt library, some error output was slightly
different. Address it with an additional acceptable reference
output for the oiiotool test.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-26 17:51:50 -07:00
Larry Gritz efb70b5195 ci: Update ABI reference commit
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-26 09:20:30 -07:00
Larry Gritz fe9f7f8451 perf(oiiotool): use pointer not static for internal color config (#4433)
Basically, this switches to creating the colorconfig that oiiotool uses
from statically constructed to build-on-demand, which should slightly
lower runtime overhead for oiiotool invocations that don't need to do
any color transformations.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-22 11:44:45 -07:00
Larry Gritz d950d03f77 api(IB)!: Add span based ImageBuf methods for getpixel/setpixel (#4426)
Next round of making safer interfaces. Primarily, this adds new
span-baesd versions of ImageBuf::get_pixels, set_pixels, setpixel,
getpixel, interppixel, interppixel_NDC, interppixel_bucibuc,
interppixel_bicubic_NDC.

The old ones took raw pointers and implied sizes -- these still exist
but are considered "unsafe" and aimed at experts and special cases. (If
a downstream project wants to be sure not to use them, they can define
symbol "OIIO_IMAGEBUF_DEPRECATE_RAW_PTR" before including imagebuf.h to
force deprecation warnings.)

The new additions instead take a span -- a combined pointer and length
that can be bounds-checked (in debug mode). I strongly encourage people
to use the new interface, as it forces the caller to think hard about
the exact region of memory that's ok to read from or write to, and then
for the OIIO side to honor that and enfoce/debug with bounds checks
against that if we add such plumbing.

Along the way, I added some interesting helper functions:

In span.h:
* `span_within()` checks that one byte span lies entirely within
another.
* `check_span()` checks if a pointer and length lies entirely within a
span.
* `OIIO_ALLOCA_SPAN` is a macro much like OIIO_ALLOCA, except what it
returns is a span rather than a raw pointer to the stack-allocated
region.

In imageio.h:
* `span_from_buffer()`/`cspan_from_bufffer()` : Given a raw pointer,
pixel data type (TypeDesc), and image dimensions and strides, returns a
byte stride describing the extent of memory that encompasses all pixels
laid out by that description.

I hope the switch to spans is not very onerous for people. I really
think that this will help us write more solid and deliberate code to
begin with, and when things do go wrong, the various debug-mode checks
and assertions that spans provide should help us more quickly identify
exactly where buffer overruns and the like occurred.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-22 11:44:21 -07:00
Larry Gritz bac80d9bbe ci: various minor bumps for the 'latest' dependencies (#4437)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-22 11:43:52 -07:00
Larry Gritz 639089af5f build: Add a build option for profiling (#4432)
Right now, the only option is gperftools, because that's what I happened
to be trying. But this can be expanded later.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-20 17:56:53 -07:00
Larry Gritz dc663b5d20 docs: IBA::st_warp was missing from the documentation (#4431)
Oops.

I didn't really have time to add an "example" right now. I hope to
return to beef this up (or that somebody else takes it on).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-20 17:01:13 -07:00
Larry Gritz 187cf72b89 admin: change docs and comments references master -> main (#4435)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-18 22:11:23 -07:00
Larry Gritz 9c7f5226ba test: Optimize running of oiiotool-demosaic test (#4429)
This test was running very slowly, taking too long in all circumstances,
but shockly causing GHA CI Mac runners to hit the test timeout
sometimes.

It turns out we were doing a lot of redundant work. There was no need to
make separate pattern and bayer images for every data type. Instead,
hoist the test image generation out of the loop and just make one
(float), then use `-i:type=<type>` to read it into an ImageBuf of the
appropriate data type.

This cuts the time for this test to run by about 3x.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-17 10:48:00 -07:00
zachlewis c658c8f1ee build: Add auto-build recipe for ZLIB (#4420)
Required for building redistributable python wheels on Windows Wheels
runners.

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2024-09-16 13:16:03 -07:00
Larry Gritz 89cc7dc794 docs: minor docs fixups to help with sphinx warnings and errors (#4427)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-15 14:23:04 -07:00
Larry Gritz a3c6453023 ci: Adjust ABI standard
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-14 11:08:03 -07:00
Larry Gritz 6aba6e99fd build: No need for OCIO search to use PREFER_CONFIG (#4425)
We no longer supply a FindOpenColorIO.cmake, so it makes no difference.
But it was getting in the way of a weird case where a wrapping project
wanted to supply one.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-14 10:35:20 -07:00
Larry Gritz ce82f61168 api: IOProxy const method adjustments (#4415)
With 3.0 approaching, it seems like the only time to make these changes
that I made note of a while back:

* It seems to me that `tell()` should be const because it isn't going to
modify or change the state of the IOProxy.

* It seems to me that `flush()` should NOT be const, because it probably
does change internal state.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-14 10:34:43 -07:00
Larry Gritz 37a814f725 api: Adjust IBA::perpixel_op function signature (#4409)
When I added perpixel_op recently, I didn't get the function signature
right. It only would work for plain old function pointers, and would not
work properly for "functors" or lambdas with capture. I should have used
function_view which can do a light-weight wrapper of all three, so now I
do. Also modified imagebufalgo_test to explicitly test all three forms
to be sure they work.

Also update function_view ever so slightly.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-14 10:34:07 -07:00
Anton Dukhovnikov c62dec6bbc fix(IBA): fix IBA::demosaic of non-float images (#4419)
Fixes the bug where IBA::demosaic only works with float images. 

Fixes#4416

I've extended the unit tests to run on float, half, uint16, uint8
images.


Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-09-12 10:16:12 -07:00
Larry Gritz fbc0042c6d test: Fix tests that were writing into ref (#4418)
openexr_copy and openexr-decreasingy

These recently added test were writing into the ref/ directory, which
they certainly should not do. Write into the build test area, compare to
what's in the ref area.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-11 08:09:52 -07:00
Jeremy Retailleau 856dc6fc06 docs: Convert more examples within the imagebufalgo chapter. (#4039)
Convert C++ and Python examples from the "Image transformations and data
movement" section of the "imagebufalgo" chapter into tests within the
"docs-examples" testsuites (related to issue #3992).

Update 'oiiotool' tabs to use a simple 'tab' instead of 'code-tab' to
prevent synchronized tab selection, which is inconsistent with the other
tabs using the 'literalinclude' directive.


---------

Signed-off-by: Jeremy Retailleau <jeremy.retailleau@gmail.com>
2024-09-10 17:38:14 -07:00
Larry Gritz e0a3fce203 ci: add a workflow that builds docs (#4413)
This allows somebody who is enhancing the docs to check the results
entirely through CI without having to set up the dependencies necessary
for docs on their end. (Perfect for Dev Days.) It also ensures that any
changes we make to the code base don't break the documentation somehow,
because now a successful docs build will be part of the CI.

Note that the docs building job leaves behind an artifact, which will be
a zip file of the directly containing the HTML docs, just like one would
find on RTD, so you can download that zip file and view the docs it made
to verify that everything looks right.

I made the docs builder a separate workflow, but I also changed some
things in the CI workflow for the sake of making them more similar.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-09 09:08:18 -07:00
Larry Gritz c1d0456012 ci: Bump the dependency versions for the 'latest' test to the actual latest (#4410)
Also some other minor simplifications.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-08 21:05:38 -07:00
Larry Gritz c0bf9701d4 api(IB): Add span-based constuctors to ImageBuf (#4401)
The flavor of ImageBuf that wraps caller-owned memory is constructed or
reset by merely passing a raw pointer and it assumes that the range of
memory implied by the strides is entirely safe to read from or write to.
And even if correct, there is not much within ImageBuf internals to
prevent bugs from buffer overruns.

This PR introduces a new constructor and reset() method to ImageBuf
where instead of taking a raw pointer, it takes a span describing the
extent of the safely addressible memory (and also an optional "pointer
to first pixel" within the buffer, which is necessary if you're using
negative strides or for some other reason are describing safe memory
that starts before the location of pixel 0). That span is stored in the
ImageBuf, and also it remembers if it was a cspan (which should indicate
a read-only IB) or a non-const span (which should wrap writable memory).

At this moment, I'm just adding this API and will start using and
documenting it as the perferred method, with the raw pointer versions
being regarded as unsafe for now (and maybe some day will be
deprecated?). But we're not yet using the span internally for safety
checks.

In the future, my intent is to gradually add safeguards to do bounds
checking against the span for IB operations that touch the wrapped
memory. Because we'll most likely bounds check only in debug mode, it
shouldn't ever impact performance, but it will make debugging,
sanitizer, and fuzz tests more robust to catch and zero in on buffer
overruns. I also like how it forces the caller, at the call site, to
think hard about exactly what range of memory the IB is wrapping, and
not merely pass a single pointer and hope it works out.

I also changed all ImageBuf ctrs and resets within the OIIO codebase to
use the new span-based versions.

This is part of an overall trend to migrate from raw pointer based API
calls to span-based API design as much as possible.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-08 18:22:41 -07:00
Larry Gritz f751f21359 api: Fold span_util.h contents into span.h (#4402)
span_util.h is relatively new. I'm honestly no longer sure why I thought
it was necessary to make a second file, but so little is in it that I
now believe its contents should be folded into span.h to keep all the
span-related definitions in once place. It's just not big enough to need
to be divided into several headers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-06 16:35:08 -07:00
Larry Gritz 56b7271a69 docs: Switch license name in docs (#4407)
The link points to the Apache 2.0 license, we just never changed the
label here.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-06 16:34:15 -07:00
Larry Gritz 68bd5db906 Bump version after developer preview tag
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-05 19:47:19 -07:00
Larry Gritz 0312717964 Update ABI reference commit / stage for developer preview v2.6.5.0
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-02 18:41:48 -07:00
Larry Gritz 1b839e5f78 CHANGES and bump version to 2.6.5.0
* Bump version to reflect recent ABI changes
* Bring CHANGES and CREDITS up to date

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-02 18:40:48 -07:00
Larry Gritz 8aac12c786 fix: Don't let fmtlib exceptions crash the app (#4400)
When fmt arguments don't match the format string, fmt will throw an
exception, or terminate if we disable exceptions (which we do). For
gcc11+, we tried intercepting these, but let's do it for all platforms,
and let's not terminate ourselves, but insted print and log the error.

But, oof, to do this properly, I needed to move some error recording
functionality from libOpenImageIO to libOpenImageIO_Util and make it
owned more properly by strutil.cpp, so that this all works even when
only using the util library. The logic isn't changing, it's just moving
over to the other library.

This all helps to address #4388

Unfortunately, the exception thrown by fmt doesn't tell us the bad
format string itself. That would have really allowed to probably zero
right in on it. But at least we know it's occurring, and one could put a
breakpoint on pvt::log_fmt_error to catch it in the act and see where
it's being called, revealing the bad line.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-02 09:09:41 -07:00
zachlewis 1d599d29e8 feat: implement support for OCIO NamedTransforms (#4393)
- ColorProcCacheKey: Update definition, signature, and usage to support
caching NamedTransform processor handles.
(Note: **ABI-breaking**)

- ColorConfig: add NamedTransform convenience functions:
`getNumNamedTransforms`, `getNamedTransformNameByIndex`,
`getNamedTransformNames`, `getNamedTransformAliases`

- ColorConfig: add `createNamedTransform` function returning new
ColorProcessorHandle

- Add `ImageBufAlgo::ocionamedtransform` functions

- oiiotool: add `--ocionamedtransform` operator

- python: add NamedTransform convenience function bindings

- python: add `ImageBufAlgo.ocionamedtransform(...)` bindings

- Update `oiiotool` and `python` documentation with examples


## Description

OCIO-2 config authors may define a set of stand-alone "source-agnostic"
`NamedTransforms`. Unlike the `colorconvert`, `ociodisplay`, and
`ociolook` IBAs, which explicitly convert _from_ a color space to
something else, the `ocionamedtransform` IBA behaves more like the
`ociofiletransform` IBA, where the transform itself can be applied
either in the forwards or inverse direction, and does not take into
consideration the input encoding or image state.

Quoting from the OCIO [NamedTransform
documentation](https://opencolorio.readthedocs.io/en/latest/guides/authoring/authoring.html#named-transforms):

> Sometimes it is helpful to include one or more transforms in a config
that are essentially stand-alone transforms that do not have a fixed
relationship to a reference space or a process space. An example would
be a “utility curve” transform where the intent is to simply apply a
LUT1D without any conversion to a reference space. In these cases, a
named_transforms section may be added to the config with one or more
named transforms. [...] This feature may be used to emulate older
methods of color management that ignored the RGB primaries and simply
applied one-dimensional transformations.

Notably, the built-in OCIO-2 Studio config
(`ocio://studio-config-latest`) contains NamedTransforms "sRGB - Curve"
and "Rec709 - Curve", which we could implement as drop-in replacements
for the existing `linear_to_sRGB`, `sRGB_to_linear`, `linear_to_Rec709`,
and `Rec709_to_linear` functions in `color.h` (unless those functions
are deprecated...).

There are several other applications for NamedTransforms as well. They
can be extremely useful as workflow-oriented transforms implemented at
various points in facility pipelines (e.g., for applying shot-specific
conversions, grades, gamut-compression, etc.); they can be used to
provide diagnostic transforms for visualizing "exposure zones", clipped
areas, NaNs, etc; for visually "tagging" problematic clips; for applying
parts of ACES Metadata Files parsed by OCIO's forthcoming AMF parser;
for conversion to non-RGB color models... all sorts of things.

## Tests

Tests are forthcoming. I've tested everything locally, but have not yet
implemented proper tests in the testsuite.

---------

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2024-09-02 09:06:57 -07:00
Larry Gritz 482f165955 refactor!: de-virtualize IC and TS (#4384)
Background: The ImageCache and TextureSystem had historically been
implemented as pure virtual abstract base classe defining an interface,
then a hidden concrete subclass. The flexibility this was intended to
provide was never really used; instead the imagined main client for the
flexibility, OSL, has a different mechanism for customizing the texture
system (via their RendererServices class). Meanwhile, this has made the
interfaces to IC and TS impossible to change without breaking the ABI.

So this PR does the following:

* ImageCache and TextureSytem are fullly de-virtualized, and are now
concrete classes, no hidden subclassing, no virtual methods. As such,
removing or changing existing methods will be an ABI break, but adding
new methods is not.

* Each now use a PIMPL idiom, where all the data and internal methods
are hidden from the public interface and do not affect the ABI.

* Roughly speaking, we added the PIMPL pointers and made the
ImageCacheImpl/TextureSystemImpl -- what used to be the hidden concrete
subclasses -- into the hidden PIMPL classes.

* Moved a lot of classes that used to be in a "pvt" namespace into the
main namespace. If they are opaque types not exposed in public headers
or as symbols exported from the library, it doesn't matter, so this just
removes some arbitrary clutter.

* Had to rearrange some of the recently added heapsize/footprint code,
moved some inline functions in the headers into methods of the classes,
defined in the cpp files.

This itself is a huge ABI change, so will only be merged into master, to
become part of the 3.0 release. This is not an API change, though! This
is all about the internals, and should not require any client software
to change a single line of code.

I may do further simplification or refactoring of this code in the
future, but that will all be smaller and have no further API/ABI changes
that break compatibility.

Although the structure of the class hierarchy has changed around, none
of the logic about how IC and TS actually *work* has changed, so there
should be no change in observable behavior.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-09-02 09:03:33 -07:00
Basile Fraboni 92bebd009a api!: add virtual heapsize() and footprint() to ImageInput and ImageOutput (#4323)
Second PR of two, following @lgritz and I discussions on memory tracking
in the OIIO::ImageCache.

- the memory tracking system from
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4322 is
not sufficient to track OIIO public objects that can be overriden.
- add virtual `heapsize()` method to ImageInput and ImageOutput that
return the total heap allocated memory held by the structure and its
members.
- [ ] **TODO**: override for every internal OIIO type (bmp, tiff, etc). 

Related PR from Larry :
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4317
First PR:
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4322

Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
2024-09-02 09:02:29 -07:00
Anton Dukhovnikov 101f9508e1 feat(raw): make the crop match in-camera JPEG (#4397)
Make the 'display window' match the default crop, which is applied to
in-camera JPEG.

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-08-31 16:59:36 -07:00
Larry Gritz a534a392cd dev: span utility improvements (#4398)
* Added as_bytes and as_writable_bytes that convert spans of arbitrary
type to spans of std::byte. (This mimics C++20 utilities of the same
name.)

* spancopy, spanset, spanzero: add parameter defaults for the common
case of wanting to do the operation on the whole span, also simplify the
bound-limiting logic in those functions a bit (but still performing
precisely the same task).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-31 11:06:19 -07:00
Larry Gritz f460da52e3 fix(iba): IBA::transpose() didn't set output image's format to input (#4391)
Because IBA::transpose changes resolution, it doesn't pass the input
image to IBAPrep(), and there was a special case there that always set
destination to float if there were no source images.

So change transpose to specifically request a format, to be the same as
the input image.

And that required a tweak to IBAPrep allowing us to specify such a thing
(there was already an option that meant "force it to float", but not the
general case of an arbitrary type).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-31 11:01:56 -07:00
Darby Johnston 1677f9e95b feat(ffmpeg): FFmpeg additional metadata (#4396)
This change adds additional FFmpeg metadata from the video and data
streams. These streams can hold the start timecode which is very useful
in OpenTimelineIO applications.

I also added `av_guess_frame_rate()` which might be more robust than
just checking `stream->avg_frame_rate`, but I can also create a separate
PR if it is better to break it up.

It doesn't look like there are any FFmpeg tests in `testsuite`?

I tested with the DPEL ALab trailer and some Netflix Open Content
movies, and was able to see the timecode metadata in the OIIO image
attributes.

---------

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
2024-08-31 10:29:04 -07:00
Larry Gritz f6a1279a18 fix(iba): Add missing version of warp (#4390)
It was documented and declared, but implementation was missing in
action.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-28 14:27:15 -07:00
Larry Gritz d6ff16fbb3 docs: clarify TextureSystem::create use of imagecache when shared=true (#4399)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-28 14:19:19 -07:00
Darby Johnston fb5f2bf322 build: Add proper detection of new FFmpeg versions (#4394)
Correctly detect new versions of FFmpeg (6.1 and 7.0). The FFmpeg versions page
was used for reference:
https://www.ffmpeg.org/download.html#releases

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
2024-08-26 17:57:52 -07:00
Anton Dukhovnikov 8699b965ed feat(iba): IBA::demosaic() for bayer pattern demosaicing (#4366)
Added IBA::demosaic().
Currently supports 4 Bayer pattern layouts, "RGGB", "GRBG", "GBRG", "BGGR", and 2 algorithms: "linear", "MHC".
Should be expandable in the future.

---------

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-08-26 16:09:47 -07:00
zachlewis 1cbde797d1 build(deps): Add libjpeg-turbo recipe (#4392)
Build and link missing libjpeg-turbo shared + static libs

Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
2024-08-26 15:56:14 -07:00
Larry Gritz 6b2d140f4e fix(png): bug in associateAlpha botched alpha=0 pixels (#4386)
In trying to avoid doing the color conversion pointlessly for pixels
with alpha=0, I accidentally also managed to skip the multiplication by
alpha for those pixels. Oops.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-21 10:14:31 -07:00
Larry Gritz fac55fa9e0 ptex: Store full metadata only at subimage 0, miplevel 0 for ptex files. (#4376)
Don't read or store full metadata on every MIP level for every face.
That can really add up! Ptex can only have one set of metadata, the
format itself doesn't allow it to vary from face to face.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-21 10:14:14 -07:00
Larry Gritz 956ce13d6d fix: Catch potential OCIO exception that we were missing (#4379)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-21 00:31:46 -07:00
Larry Gritz a47c073d59 docs: typo fix (#4385)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-20 19:17:16 -07:00
Larry Gritz 7faf944b1d int: Beef up some error messages (#4369)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 11:31:35 -07:00
Larry Gritz 55872131ad style: Turn on clang-format for ivmain.cpp (#4382)
It was disabled to make prettier formatting for getargs, but neglected
to turn it back on for the rest of the file.

I also changed a few old `<<` stream output to `print()`.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 11:31:20 -07:00
Joseph Goldstone ef5dd61678 cleanup: Fix typo where apostrophe was used for possessive of 'it' (#4383)
Nominally, fix four places where "it's" was used when "its" was
appropriate. Realistically, force the EasyCLA dialog so that I can get
an individual CLA in place, my employment with ARRI having terminated on
15 July of this year.

Signed-off-by: Joseph Goldstone <joseph.goldstone@mac.com>
2024-08-16 11:30:53 -07:00
Larry Gritz c9ced0e4a1 ci: Bump ABI standard in master
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 10:38:56 -07:00
Larry Gritz f30cdf9e21 Bump version to indicate ABI changes
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 10:28:31 -07:00
Larry Gritz c894d76ede api: use shared_ptr for ImageCache and TextureSystem (#4377)
Change IC::create() and TS::create() to return shared_ptr instead of a
raw pointer. This cleans up a lot of lingering lifetime management issue
of these classes. The switch to 3.0 is an opportunity to make breaking
changes to these APIs.

For the sake of downstream users, we define preprocessor symbols
OIIO_IMAGECACHE_CREATE_SHARED and OIIO_TEXTURESYSTEM_CREATE_SHARED to
signal that the new APIs are present. Some very minor changes may be
needed at the call site.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 08:45:41 -07:00
Larry Gritz 135e659301 build: Don't link libOpenImageIO against OpenCV (#4363)
Fully linking OpenCV against libOpenImageIO is burdensome for people
downstream, especially those who want a static version of
libOpenImageIO.

There were only three IBA functions that use OpenCV: to_OpenCV(),
from_OpenCV(), and capture_image(), and all three are fairly short. Move
them to a separate header, imagebufalgo_opencv.h, make them fully INLINE
(so they don't actually produce object code in libOpenImageIO, which
therefore does not need to link against OpenCV).

Applications wanting these three functions should include this header
and will be responsible themselves for ensuring that the include paths
and linkage of their application makes provisions for finding and using
OpenCV. All other applications don't need to deal with OpenCV dependency
at all.

Our own oiiotool (for --capture) and our python bindings still link
against OpenCV to support this functionality (again, still as an
optional dependency, enabled only if OpenCV is found at build time). But
downstream apps using libOpenImageIO and who do not themselves need our
OpenCV functioality now no longer need to link against OpenCV.

We have removed capture_image() from the Python bindings -- Python
scripts that need to capture live camera images can use OpenCV or any
other capture API of their choice without going through OIIO.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-16 08:44:28 -07:00
Vlad (Kuzmin) Erium 67d4f61e13 fix(windows): fix for setenv() on Windows (#4381)
Microsoft's runtime library doesn't support the standard setenv()
function. _putenv_s() should be used instead.

Without fix iv do not compiling:
`E:\GH\OpenImageIO\src\iv\ivmain.cpp(119,9): error C3861: 'setenv':
identifier not found [E:\GH\OpenImageIO\build\src\iv\iv.vcxproj]`

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2024-08-16 08:00:27 -07:00
Larry Gritz 611f98aaba build(deps): Raise libheif minimum to 1.11 (#4380)
This version dates from early 2021 (so still supporting back 3.5 years).

The reason for the bump is to simplify a bit on our part and avoid older
versions known to be broken or lacking certain features.

This is for master/2.6/3.0 only, will not be backported to 2.5, since we
never raise minimum dependencies in already-released branches.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-15 15:37:00 -07:00
Larry Gritz c9922412a1 build: CI sanitizer test improvements (#4374)
CI sanitizers in master have been failing lately. A different PR
addresses the root cause, but this patch contains some improvements I
made along the way while investigating it:

* CMake: Change the SANIIZE build variables to use set_cache, thus
allowing easier override by env variable.

* Bumped the CI sanitizer test to use the 2024 container and latest
compilers.

* Suppress UB warnings in STL function.h, where it's claiming undefined
behavior in the std::function guts called by ArgParse internals. Only
seen failing on my Mac, wasn't actually failing in the GHA CI. I'm
pretty sure it's a false positive.

* Also, only on my Mac building against OpenVDB 11, it found some UB in
OpenVDB, which I'm suppressing (I think it's also false positive).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-15 10:56:00 -07:00
Larry Gritz 03a680ddfd cleanup: Remove unused test output ref from old dependency versions (#4370)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-15 10:54:48 -07:00
Larry Gritz 80545a95fe fix(oiiotool): -i:ch=... didn't fix up alpha and z channels (#4373)
Fix a bug in oiiotool wherein `-i:ch=...` (input only a subset of
channels when reading from a file) was not adjusting the spec's
alpha_channel and z_channel -- that is, they still contained the OLD
channel numbers of those things, which not only could be wrong due to
the reordering, but they might be out of range of the new number of
channels.

Also a related fix in the TIFF reader, to fix a possible dereference of
an empty vector. This was being triggered by that out-of-range
alpha_channel. Maybe that can't happen anymore with the above bug fix,
but it still feels like the safer way to proceed.

This was all found by the sanitizers in CI -- and only recently, despite
this code having this bug for a long time. So yay for sanitizer CI!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-12 11:47:02 -07:00
Larry Gritz fb26ed86ed deps: Make OCIO 2.2+ a required dependency (#4367)
Make OCIO a hard dependency, at least version 2.2.

Revise and improve the OCIO "auto-build" scripts.

Remove OCIO 1.x testsuite reference output.

No longer need FindOpenColorIO.cmake module

As part of this, I split the CI "oldest/hobbled" test into two different
tests:

* oldest -- test against the oldest supported versions of all
dependencies.
* hobbled -- test against most optional dependencies missing and
optional features disabled.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-12 10:53:32 -07:00
Basile Fraboni af13eb9203 api: add pvt::heapsize() and pvt::footprint() methods and image cache memory tracking (#4322)
First PR of two, following @lgritz and I discussions on memory tracking
in the OIIO::ImageCache.
- Add two template methods and their specializations for types various
to help memory tracking:
```c++
// return the total heap allocated memory held by the object and its members
template<typename T> inline size_t heapsize(const T& t);
// return the total memory footprint including the size of the structure itself
template<typename T> inline size_t footprint(const T& t);
```
- Specialized for: ParamValue, ParamValueList, ImageSpec, ImageInput,
ImageOutput, std::vector, std::shared_ptr, std::unique_ptr,
oiio::intrusive_ptr, ImageCacheImpl related objects.
- New files: 
- `include/memory.h` : adds base and few types specialization of
heapsize and footprint.
- `libtexture/imagecache_memory_pvt.h` : adds specilializations for
ImageCacheImpl and related objects.
- `libtexture/imagecache_memory_print.h` : adds a helper function that
print a breakdown of the ImageCacheImpl total memory usage as well, as
well as per image format. Note: this is slow, but gives accurate memory
estimation.

Related PR from Larry :
https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4317

Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
2024-08-11 16:27:27 -07:00
Larry Gritz 64f829febd admin: Relicense code under Apache 2.0 (#3905)
Some more updates to the relicensing. At this point, less than 0.15% of the codebase remains under the original BSD-3-clause license.
2024-08-10 09:07:25 -07:00
Larry Gritz d249036302 api: move OIIO::pvt::error and log_time into the exposed OIIO namespace (#4362)
This is needed for the related OpenCV-related PR

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-07 11:58:59 -07:00
Anton Dukhovnikov 3cb2acf374 raw: expose additional white balancing hints (#4360)
The main purpose of this change is to make it possible to use OIIO for
reading raw files in rawtoaces instead of calling LibRaw directly. There
are the changes:
- add the missing hints needed to implement all combinations of
white-balancing methods and matrix methods provided by rawtoaces.
- add the DNG-specific attributes

The change adds this functionality:
- new "raw:user_black" hint to override the default black point
- new "raw:use_auto_wb" hint to force LibRaw to white balance by
averaging over the whole image.
- new "raw:grey_box" hint to make LibRaw to white balance by averaging
over the given rectange.
- new "raw:dng:XXX" attributes added to the output ImageBuf if the input
image is a DNG file. The attributes consist of 2 sets of [calibration
illuminant; calibration matrix, XYZ to camera RGB matrix]. Note, the
current DNG standard supports up to 3 calibration illuminants, but both
LibRaw and rawtoaces only use 2 currently.

I have manually tested all permutations of white-balancing modes and
matrix methods which are currently supported by raw to aces. The images
match up to a rounding error.

The current unit tests pass, but they only seem to use the default
conversion settings. We may want to extend those. I'm not clear on how
to do that, there are multiple reference images for different versions
of LibRaw, not sure if I will have to re-generate all of them. I intend
to make more changes to the raw plugin soon, may come back to updating
tests during/after that.

There are currently no tests using DNG files, so the new DNG-specific
attributes are not covered. The code relying on those in rawtoaces works
fine.

I have also updated the documentation to add the new hints, however, I
haven't been able to build the documentation.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-08-07 11:58:28 -07:00
Larry Gritz fb9d818b17 fix(png): round dpi resolution to nearest 0.1 (#4347)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-07 11:53:52 -07:00
Larry Gritz e031dc35fe feat(jpeg): output hint "jpeg:iptc" (#4346)
JPEG output configuration hint "jpeg:iptc" (default: 1), if set to 0,
will suppress IPTC block output to the file.

In the process, we changed the return type of utility function
encode_iptc_iim() to return true if anything was successfully encoded,
false otherwise.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-07 11:53:32 -07:00
Larry Gritz f578096ef7 int: Rename env OIIOTOOL_METADATA_HISTORY -> OPENIMAGEIO_METADATA_HISTORY (#4368)
It's not just in oiiotool. This seems clearer and adheres to the env
variable naming convention we chose.

Reminder: This controls whether command line history gets written to
output image metadata by default by oiiotool and maketx. We historically
did it, but recently stopped because of security concerns.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-07 11:52:46 -07:00
Larry Gritz e947e79548 feat(oiiotool): additional stack commands and --for improvement (#4348)
Additional stack manipulation commands:
* `--popbottom` discards the bottom-of-stack image
* `--stackreverse` reverses the order of the whole stack
* `--stackclear` fully empties the stack
* `--stackextract <index>` moves the indexed item from the stack (index
0 means the top) to the top.

Make `--for` work correctly in both directions:
* Correct behavior if `--for` has a negative step value.
* If the end value is less than the begin value and no step is supplied,
assume -1 (analogous to how we usually assueme step=1 under ordinary
circumstances).
* Error if step is 0 (presume it will make an infinite loop).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-08-07 11:52:01 -07:00
Anton Dukhovnikov 8a09888f19 fix(IB): copy/paste error in the ImageBuf iterator copy constructor (#4365)
Fixes a simple copy/paste error in a copy constructor where the y
coordinate gets initialised twice instead of y and z.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2024-08-01 15:31:31 -07:00
Larry Gritz a2f044a34c build: A few cmake cleanups and minor code rearrangements (#4359)
* Get rid of some obsolete cmake code.

* Movement (but no change) to some parts of CMakeLists.txt, primarily to
make it closer to the corresponding file in OSL to make it easy for me
to diff them and port innovations back and forth between them.

* Some typo/etc fixes

* Remove unused OIIO_UNUSED_OK macro that's been deprecated since 2.0,
and OIIO_CONSTEXPR and OIIO_CONSTEXPR14, neither of which have been
needed for years.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-28 22:22:01 -07:00
Larry Gritz ee99e8a91f docs: clarify that IBA::rotate params are pixel coordinates (#4358)
As suggested by Moritz Moeller

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-26 09:04:56 -07:00
Larry Gritz 08afc2c71f CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 22:27:38 -04:00
Larry Gritz 4ce19d93ed CHANGES update
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 22:09:42 -04:00
Larry Gritz 0f50bf95c9 build(deps): Raise giflib minimum to 5.0 (#4349)
Even that is quite old -- released in 2012! But it's the first version
that guaranteed thread safety for error reporting. So we're finally
making that our minimum and taking out the locking we did on our side.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 10:39:44 -07:00
Larry Gritz af51dbfdc1 deps: Raise libPNG minimum to 1.6.0 (#4355)
Raised from 1.5.13 (maybe? we never carefully checked) to 1.6.0 minimum,
which was released in 2013 (so absolutely nobody should be bothered by
this).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 10:38:33 -07:00
Larry Gritz 0fed401abf deps: Raise WebP minimum version to 1.1 (#4354)
This new version dates to 2020. Previously, we had supported
(purportedly) WebP 0.6.1, but we didn't test that configuration. By
bumping to 1.1 minimum, we can use WebP's own exported cmake config,
rather than maintaining a FindWebP.cmake mmodule on our side.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 10:37:44 -07:00
Larry Gritz 72daf8b7f2 deps: Raise OpenCV minimum to 4.0 (~2018) (#4353)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 10:36:48 -07:00
Larry Gritz 096cb1625f fix: sanitizer new warnings about signed/unsigned offsets in openexr (#4351)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-22 07:06:27 -07:00
Larry Gritz a8d06f390a build(deps): Raise ffmpeg minimum to 4.0 (released in 2018) (#4352)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-21 16:24:32 -07:00
Larry Gritz 10d6bffc5c docs: Add deprecation updates to the RELEASING checklist (#4345)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-21 11:59:26 -07:00
Larry Gritz 5439e0f3de Update ABI reference after recent deprecations
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-19 11:53:17 -04:00
Larry Gritz ed01d746dd feat(oiiotool): Expression eval improvements: BOTTOM, IMG[expression], check label/var names (#4334)
Improvements to expression evaluation of oiiotool command line arguments
surrounded by `{braces}`.

* Just like `TOP` refers to the top image on the stack, now `BOTTOM`
refers to the bottom image.
* Referring to images with `IMG[id]` previously worked if `id` was a
literal integer or an image label or an image filepath. But now it can
be any expression that evaluates to any of those things. So, for
example, you could say `{IMG[i].filename}` to get the filename of the
i-th image down the stack (where `i` is a variable), or
`{IMG[NIMAGES-2].width}` to get the x resolution of the 2nd-from-bottom
image on the stack.
* The `--label` and `--set` commands check that the name you use for an
image label or user variable follow the "C identifier" lexical rules:
must be alphanumeric + underscore, but not start with number. It was
previously possibly to do completely chaotic things like `--set 1 2`.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-19 08:32:06 -07:00
Larry Gritz 0d824b6435 api: imagebufalgo.h mark, warn, or remove various deprecations (#4344)
* The old versions (deprecated since 2.0) of IBA::compare() and
computePixelStats() that took a reference to the CompareResults or
PixelStats structure now have deprecation warnings. Use the versions
that return the structure instead.
* The deprecated (often since as far back as 2.0) versions of functions
that took raw pointers to color values now have deprecations warnings.
Use the versions that take `span<>` or `cspan<>` instead. These include
versions of: isConstantColor, isConstantChannel, isMonochrome,
isConstantChannel, colorconvert, fill, checker, add, sub, absdiff, mul,
div, mad, pow, channel_sum, channels, clamp, color_count,
color_range_check, render_text.
* The `histogram()` function that takes a reference to a result vector
(deprecated since 2.0 and previously warned) has been removed. Use the
version that returns the vector instead. The `histogram_draw()`
(deprecated since 2.0 and previously warned) has been removed and has no
replacement since it was always silly.
* The versions of ociodisplay that lacked an `inverse` parameter, which
were marked as deprecated since 2.5, now have deprecation warnings. Use
the version that takes an `inverse` bool.
* The OpenCV-related functions that take old-style IplImage pointers
(deprecated since 2.0) have been removed. Use the modern ones that use
cv::Mat.
* The pre-KWArgs versions of resize, warp, and fit now have deprecation
warnings. Use the versions that take KWArgs instead.
* IBA::type_merge, deprecated since 2.3, now has a deprecation warning.
Instead, use TypeDesc::basetype_merge().

All of the IBA functions with deprecation warnings are additionally
implemented inline, so that they can be easily removed later if
necessary without an ABI break at that time.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-16 18:15:41 -07:00
Larry Gritz 722c7f47dd security: Document CVE-2024-40630 resolution
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-16 15:05:10 -04:00
Curtis Black 5cc8860371 perf(TS): Reduce TS memory by slimming down internal LevelInfo size (#4337)
Reduces the memory footprint of the `LevelInfo` struct. Three changes
are here, in order of most to least impactful:

- Makes one `ImageSpec` optional, most of the time `spec` and
`nativespec` are the same, it appears they are only different when
autotile is enabled, this saves about 160 bytes.
- Uses `std::unique_ptr<float[]>` (8 bytes) instead of
`std::vector<float>` (24 bytes).
- Reorders members to remove excess padding.

We noticed this memory usage on scenes with per-face textures with
multiple mips per face. For a scene with 12.5 million mips, this saves
about 2GB.

Note, it would probably also be possible to remove the
`polecolorcomputed` member, instead relying on the `polecolor` pointer.
But since this bool occupies existing padding in the struct it wouldn't
save any memory currently.

---------

Signed-off-by: Curtis Black <curtis.w.black@gmail.com>
2024-07-16 07:54:18 -07:00
Larry Gritz 736d253659 api: imagebuf.h add deprecation warnings to deprecated things (#4341)
* Add deprecation warnings to the varieties of ImageBuf constructor and
`reset()` that don't take subimage and miplevel parameters. The
equivalent is to just pass `0` for both of those parameters. The warned
constructors have been marked as deprecated since OIIO 2.2.
* The misspelled `ImageBuf::make_writeable()` has been given deprecation
warnings. Since OIIO 2.2, the correct spelling is `make_writable`.
* The `ImageBuf::error()` method that uses printf-style formatting now
has deprecation warnings. Use `ImageBuf::errorfmt()` instead.
* The `ImageBuf::interppixel_NDC_full()` method, which has been marked
as deprecated since OIIO 1.5, now has deprecation warnings. Use
`interppixel_NDC()` instead.

Undeprecate the name+spec varieties of constructors. They were
documented as deprecated but warnings were never added. In doing this
set of changes, I realized that they were used for something useful
after all -- it makes it easy to remember the name of a new buffer
you're making not from a file, so you can later `write()` it without
needing to know the filename at that time. I also added a new
`set_name()` method to do it directly for times when you don't want to
rely on the constructor or want to change the name.

By the way, I'm being careful also to convert all the warned or marked
deprecated functions to inline, if at all possible, so that in the
future removing them will not be an ABI break.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-16 07:02:17 -07:00
Larry Gritz be110f655b feat(IB): Add ImageBuf::wrapmode_name, inverse of wrapmode_from_string (#4340)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-15 20:18:34 -07:00
Larry Gritz e9d3656936 make_texture: only write full metadata to the first mip level (#4320)
It's silly to copy the full metadata from the source (which could
include big things like ICC profiles) to EVERY level of a MIPmap.

This mostly applies to TIFF textures, since OpenEXR MIPmaps don't store
attributes separately for each MIP level anyway.

This can be disabled (that is, make it copy full metadata to all levels
of the MIPmap) by setting a new make_texture configuration hint,
"maketx:mipmap_metadata" to nonzero.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-15 07:39:40 -07:00
Larry Gritz a303f1a2b2 api: Make span::size() return size_t (#4332)
With 3.0 coming soon, it's time to break compatibility by switching
OIIO::span::size() to return an unsigned value, matching C++20
std::span.

The history is that when we first added OIIO::span, at that time, the
C++ draft proposal for std::span included a signed size() result, but by
the time it got finalized into C++20, it was changed to unsigned to
match all the other std containers, but it was too late for us to switch
without breaking API compatibility rather seriously.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-15 06:13:42 -07:00
Gerrard Tai d95d8476ce fix(heic): Correctly set imagespec size for heif images
Signed-off-by: Gerrard Tai <42868323+flyyee@users.noreply.github.com>
2024-07-15 09:09:19 -04:00
Larry Gritz fd0f9e1a30 api: Deprecations: missing_math.h, parmalist.h, parallel.h, strutil.h, sysutil.h, thread.h, tiffutils.h, ustring.h, type_traits.h (#4338)
* Remove long deprecated and empty header missing_math.h

* paramlist.h: Deprecate the old form of ParamValue constructors.

  People should be using the versions with strongly typed params, not
  raw bools.

* parallel.h: Remove deprecated parallel_for variants.

* strutil.h: Add deprecation warnings to old-style format.

* sysutil.h: Deprecate Sysutil::physical_concurrency.

  Also, I noticed that all the external declarations in this header were
  incorrectly OIIO_API but should have been OIIO_UTIL_API to reflect that
  they are in the OpenImageIO_Util library.

* thread.h: mark deprecated yield() and this_thread_is_in_pool().

* tiffutils.h: removed deprecated redundant functions.

* ustring.h: Remove deprecated ustringHash.

* type_traits.h: Remove deprecated OIIO::void_t, use std::void_t instead.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-13 15:15:07 -07:00
Larry Gritz 9dfbcf4506 api(texture.h): get rid of texture deprecations (#4339)
* Old version of TextureOptions we haven't used since OIIO 1.x.
* Texture methods that were based on the VaryingRef helper. These are
actually remnants of early OSL needs when it was more Reyes-like, BEFORE
we used LLVM!
* Get rid of the varyingref.h header, no longer needed by anything.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-13 12:41:47 -07:00
Larry Gritz 4999c7b15e api: various deprecations in array_view.h, benchmark.h, bit.h, color.h, errorhandler.h (#4335)
* array_view.h: Remove this long-deprecated header.
* benchmark.h: Attach DEPRECATED warning to external use of
benchmark.h's time_trial().
* bit.h: Remove bit_cast that's had deprecation warnings for several
releases, and add deprecation warnings to the old rotl32 and rotl64
* color.h: add deprecation warnings and make the deprecated things
inline so they can be removed later without an ABI break.
* errorhandler.h: remove deprecated old printf style methods

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-13 06:11:28 -07:00
Larry Gritz 277d864aba api(strutil.h): Strutil::string_is_identifier() (#4333)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-11 11:35:48 -07:00
Vlad (Kuzmin) Erium 4185ec9c3c feat(jpegxl): Initial Exif and XML metadata support for JPEG XL (#4310)
Initial Exif and XML metadata support for JPEG XL.
- EXIF - works and enabled by default
- XML - works and enabled by default
- IPTC - that part need some help. JPEG XL support XML based IPTC, but Ido not get what IPTC create an OIIO
- JBIG - not sure

new options:
- `jpegxl:use_boxes` - export EXIF, XMP, IPTC, JBIG
- `jpegxl:compress_boxes` - compress meta boxes (disabled for this moment by default)
- jpegxl:exif_box = 1 (enabled)
- jpegxl:xmp_box = 1 (enabled)
- jpegxl:jumb_box = 0 (disabled)
- jpegxl:iptc_box = 0 (disabled)

No tests yet, but if we have I can add.

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2024-07-11 11:31:36 -07:00
Larry Gritz 5e0b16784e api: consistent naming of OPENIMAGEIO_PLUGIN_PATH env variable (#4330)
The old name, OIIO_LIBRARY_PATH, was inconsistently named in two ways:

First, it was not clear that it was specific to searching for plugins,
and since it is related to the to the global attribute
"plugin_searchpath", I thought making it mention plugins specifically
would be more clear.

Second, I noticed that all of the publicly documented environment
variables that are "for users" started with OPENIMAGEIO_, except for
this one. There are a bunch of environment variables we check that begin
with OIIO_, but all but this one are intended for developers when
testing or debugging.

So I'm using a new name that is consistent with both principles.

Henceforth, the naming rule about environment variables is:

* `OPENIMAGEIO_FOO` for public interfaces, are fully documented and
intended for users/sites to use to customize behavior.

* `OIIO_FOO` for developers to use when testing and debugging, are
undocumented (except in the code itself), and are not considered part of
the public API/behavior of OpenImageIO -- their meaning may change, they
may disappear without warning, or they may only be functional for debug
builds.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-10 09:07:00 -07:00
Larry Gritz 69d6871d26 fix: Fix deprecation masking of virtual functions (#4329)
I should not have hidden virtual functions behind
OIIO_DISABLE_DEPRECATED checks. Never make the vtbl possibly vary for
clients of the library from the way we built it!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-08 23:30:02 -07:00
Jesse Yurkovich 961977ca80 fix: iv should enable the ImageCache (#4326)
Enable the ImageCache for the `iv` tool. It more or less expects it to
be present and certain features, like loading the Image's mip-levels,
requires the ImageCache to be used.
2024-07-08 22:29:23 -07:00
Larry Gritz 7c04af9be1 ci: deal with CentOS 7 EOL and disappearance of yum mirrors (#4325)
This was breaking CI for us. Hard break for icc/icx tests, since those
REQUIRED a yum install of the intel compilers. Softer undetected break
for all the ASWF <= 2022 containers based on CentOS 7, which were not
failing outright but were failing to install certain optional packages.

The solution (for now) is to configure yum to exclude the missing repo.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-07 15:55:50 -07:00
Larry Gritz 0b4e015a15 Fix GHA CI after they upgraded nodejs (#4324)
They upgraded to a version that requires a glibc newer than is in the
pre-2023 ASWF containers.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-06 21:24:35 -07:00
Larry Gritz dc451388eb admin: Document my git-cliff workflow for release notes (#4319)
For the last year or so, I have been using git-cliff to generate the
first draft of release notes. It gets me 90% of the way there for the
monthly patch releases, perhaps more like 30% (but a very good starting
point) for the big annual major releases.

In this PR, I document my process and check in the toml file that
provides the git cliff configuration that gets mostly what we need.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-06 07:35:46 -07:00
Larry Gritz 979e5f99f7 feat(iba): IBA::perpixel_op (#4299)
Inspired by a question by Vlad Erium, I have added a simpler way for C++
users of OIIO to construct IBA-like functions for simple unary and
binary operations on ImageBufs where each pixel is independent and based
only on the corresponding pixel of the input(s).

The user only needs to supply the contents of the inner loop, i.e. just
doing one pixel's work, and only needs to work for float values. All
format conversion, sizing and allocation of the destination buffer,
looping over pixels, and multithreading is automatic.

If the actual buffers in question are not float-based, conversions will
happen automatically, at about a 2x slowdown compared to everything
being in float all along, which seems reasonable for the extreme
simplicity, especially for use cases where the buffers are fairly likely
to be float anyway.

What you pass is a function or lambda that takes spans for the output
and input pixel values. Here's an example that adds two images channel
by channel, producing a sum image:

    // Assume ImageBuf A, B are the inputs, ImageBuf R is the output
    R = ImageBufAlgo::perpixel_op(A, B,
            [](span<float> r, cspan<float> a, cspan<float> b) {
                for (size_t c = 0, nc = size_t(r.size()); c < nc; ++c)
                    r[c] = a[c] + b[c];
                return true;
            });

This is exactly equivalent to calling

    R = ImageBufAlgo::add(A, B);

and for float IB's, it's just as fast.

To make the not-float case fast and not require the DISPATCH macro
magic, I needed to change the ImageBuf::Iterator just a bit to add
store() and load() method templates to the iterators, and add a field
that holds the buffer type. That might make a slight ABI tweak, so I am
thinking that I will make this for the upcoming OIIO 3.0, and not
backport to the release branch.

I think this is ready to introduce at this time, but I'm also studying
whether more varieties of this approach are needed, whether the
non-float case can be sped up even more, and whether some of the
existing IBA functions should switch to using this internally (good
candidates would be those that are almost always performed on float
buffers, but for which the heavy template expansion of the DISPATCH
approach to handling the full type zoo currently makes them very bloated
and expensive to compile, for very little real-world gain).

We should probably consider this to be experimental for a little while,
just in case the function signature for this changes as I think about it
more or add functionality.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-03 08:24:42 -07:00
Larry Gritz 5cdcdb3f13 refactor: Simplify openexr includes (#4304)
In master, since we have raised the minimum Imath/OpenEXR to 3.x, no
more 2.x, we no longer need generate our Imath.h and half.h from
templates, they can be turned into regular header files.

Additionally, define IMATH_HALF_NO_LOOKUP_TABLE in half.h before
including Imath/half.h, which ensures that the Imath code we include
converts float <-> half using actual inline code and not the lookup
table. This can reduce or sometimes eliminate the need to link agains
Imath only for the sake of accessing that lookup table.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 16:58:01 -07:00
Larry Gritz 4ef5f37c80 ci: Update ABI reference commit after known ABI-breaking merges and version bump
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 16:42:04 -07:00
Larry Gritz 7126290122 api: deprecation cleanup in imageio.h (#4312)
Track down and fix many places internal to OIIO where we were still
using deprecated API calls.

Add deprecation warnings to some things that have been nominally
deprecated, but weren't already tagged as such.

Guard deprecated things behind OIIO_DISABLE_DEPRECATED so that
downstream projects can hide them to help them find and change any use
of the deprecated calls, and behind !defined(OIIO_INTERNAL) so they are
hidden from the rest of the internals of our code base.

Make some of the deprecated things inline, so that their final removal
later doesn't constitute a link ABI compatibility change. (We do absorb
an ABI compatibility boundary with this PR, so I've bumped the version
number appropriately.) Move all the OIIO-namespace level deprecated
items to the end of imageio.h so they're as out of the way as possible.

A lot of the things that are still present here, just guarded by the
deprecation warnings, will be removed entirely before the final OIIO 3.0
release.

Please note some particular things in imageio that have been deprecated
for a while and that we expect to disappear entirely by 3.0:

* The old style `ImageInput::read_*` functions that don't take explicit
subimage and miplevel paramters, because they aren't thread-safe due to
their implied statefulness. You are expected to use the ones that take
those parameters and are stateless.

* The variety of seek_subimage that takes an `ImageSpec&` to fill in.

* Some obsolete varieties of ImageInput and ImageOutput create() static
methods.

* The `destroy` methods that are no longer needed (plain old `delete` is
fine).

* The various error-setting functions that use the old printf-like
formatting conventions. Use `errorfmt()` and friends that use the
std::format conventions.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 14:03:07 -07:00
jreichel-nvidia 24e82d0c9b fix(tiff): Fix TIFF export with EXIF data and I/O proxy (#4300)
TIFF export with EXIF metadata (e.g. oiio::ColorSpace) creates invalid
TIFF files in the presence of an I/O proxy ("TIFF directory is missing
required "ImageLength" field"). The reasons is that TIFFSetDirectory()
requires to read some of the previously written data, but neither
writer_readproc() nor the available proxy implementations support that.
Note that TIFF output does not yet use this new scheme for I/O proxy
that was used for many other plugins.

I think writer_readproc() should not take any shortcuts and just forward
the call to the I/O proxy.

Is there a reason why IOFile (in write mode) and IOVecOutput do not
allow to re-read written data? This looks like an artificial restriction
of the underlying resources. An alternative not modifiying these two
implementations would be to let the TIFF output use a variant of
IOVecOutput that allows re-reading and forward all data at the very end
to the passed-in proxy.

Is there some policy to add assertions in all methods that are not
supposed to be called? This would have helped here a lot to reduce the
test case.

I did not add an explicit test. I guess the proper way would be to
convert TIFF ouput to use the same I/O proxy scheme that is used by many
other plugins. Small repro case is attached.

[repro.cpp.txt](https://github.com/user-attachments/files/15886829/repro.cpp.txt)

---------

Signed-off-by: Joachim Reichel <43646584+jreichel-nvidia@users.noreply.github.com>
2024-07-02 14:02:15 -07:00
Larry Gritz e211302af0 Bump the version after tagging developer preview and anticipating ABI breakage
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 13:59:58 -07:00
Larry Gritz e75b096e75 CHANGES and stage a developer preview tag v2.6.2.0-dev
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 11:30:45 -07:00
Larry Gritz 028accf5cf docs: More CLA explanation and how-to links (#4318)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 09:17:41 -07:00
Larry Gritz 14a395b875 api: Add TypeDesc::Vector3i (#4316)
Like the existing Vector2i, but, you know, 3.

Along the way, fixed a bug in the way the Vector2i type is represented
as a string.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-07-02 09:15:49 -07:00
Larry Gritz 7c486a1121 api: deprecate things in typedesc.h (#4311)
Fully remove some things that have had deprecation warnings for a long,
long time (mostly since 1.x), so we think it can't possibly break
anyone.

Add deprecation warnings to some things that have been nominally
deprecated for some time. The build warnings will serve as final notice
that they will fully disappear by OIIO 3.0 release.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-29 22:39:55 -07:00
Larry Gritz 5876181b6e build: raise libtiff min to 4.0 + self-build for libtiff (and libdeflate) (#4296)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-29 22:04:17 -07:00
Jesse Yurkovich fbe4415e62 build: Avoid rebuilds due to processing of fmt headers (#4313)
This continues the adventure from #4082 where the processing of fmt
headers, both locally built and externally referenced, causes large
rebuilds to occur when making small or even zero changes between builds.

Since that previous PR is stuck I'll try again here.

This makes two sets of changes:
- Check if our generated files exist before writing to them (in the
externally referenced case)
- Use `copy_if_different` to prevent redundant copies from occuring, and
triggering timestamp updates (in the local build case)

Note that while this seems to fix the problem, the build is still not
"clean" wrt fmt processing. The following will be be seen when
triggering a build, with zero changes since the last build, within VS:
```
1>------ Build started: Project: ZERO_CHECK, Configuration: Debug x64 ------
1>1>Checking Build System
2>------ Build started: Project: fmt_internal_target, Configuration: Debug x64 ------
3>------ Build started: Project: CopyFiles, Configuration: Debug x64 ------

2>Generating ../../include/OpenImageIO/detail/fmt
2>Building Custom Rule C:/Users/jesse/source/oiio/src/include/CMakeLists.txt
2>Generating ../../include/OpenImageIO/detail/fmt/core.h, ../../include/OpenImageIO/detail/fmt/format-inl.h, ../../include/OpenImageIO/detail/fmt/format.h, ../../include/OpenImageIO/detail/fmt/ostream.h, ../../include/OpenImageIO/detail/fmt/printf.h, ../../include/OpenImageIO/detail/fmt/std.h, ../../include/OpenImageIO/detail/fmt/chrono.h
2>C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(254,5): warning MSB8065: Custom build for item "C:\Users\jesse\source\oiio\build\CMakeFiles\b19a1b09c2e7eaa53ca90801840dfdd0\fmt.rule" succeeded, but specified output "c:\users\jesse\source\oiio\build\include\openimageio\detail\fmt" has not been created. This may cause incremental build to work incorrectly.
2>C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(254,5): warning MSB8064: Custom build for item "C:\Users\jesse\source\oiio\build\CMakeFiles\b253238471e54ff57d14ae397110f40e\core.h.rule" succeeded, but specified dependency "c:\users\jesse\source\oiio\build\include\openimageio\detail\fmt" does not exist. This may cause incremental build to work incorrectly.

2>Done building project "fmt_internal_target.vcxproj".
4>------ Build started: Project: OpenImageIO_Util, Configuration: Debug x64 ------
```
Whatever it is, the VS generator doesn't much like the way we're
handling the processing but I don't know enough cmake-fu to ascertain
why that might be.


Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2024-06-29 14:39:43 -07:00
Larry Gritz 8ae48b2804 fix(png): Correctly read PNGs with partial alpha (#4315)
TL;DR: when turning unassociated alpha into associated for
gamma-corrected PNG images, we got the exponent wrong for the
linearization step, and when doing the same for sRGB images, we didn't
linearize at all.

WARNING: will change appearance of PNG files with partial alpha.

Details:

Ugh, two separate problems related to how we associate alpha (i.e.
premultiply the colors) for PNG pixels with partial alpha. The correct
thing to do is linearize the unassociated pixel value first, then
associate, then go back to the nonlinear space.

First problem: PNGs have three possible transfer functions: gamma
correction (with a particular gamma), no gamma correction / linear, and
explicitly sRGB. Guess what? We were neglecting the case of pngs tagged
as sRGB and not doing the linearize/delinearize round trip for those
images.

But if that's not enough, also for the gamma case, we were, ugh,
swapping the gamma and 1/gamma, resulting in those partial alpha pixels
ending up a whole lot darker than they should have been.

None of this affected most ordinary PNGs with no alpha channel, or where
alpha was 1.0. It only affected "edge" or "partially transparent" pixels
with 0 < alpha < 1. But it was definitely wrong before, for which I
apologize and hope you'll understand why those pixels are going to
change now (hopefully, always always for the better).

While I was at it, I also made the color space handling a little more
robust -- instead of just a straight string compare for color space
names, use the ColorConfig to check `equivalent`, which should make us a
lot more robust against aliases and whatnot.

Fixes #4314
Closes #4054

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-27 08:41:33 -07:00
Larry Gritz 1f0f0729c7 paramlist.h: Add ParamValueSpan::get_bool() (#4303)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-26 19:38:53 -07:00
Larry Gritz 0d83c8727a api: deprecations in fmath.h (#4309)
In several places, we still used OIIO versions of isnan/isinf/isfinite
and is_same. All of there for some time have been aliased to the std
versions (having our own was mostly a pre-C++11 artifact).  Also,
there are a couple obsolete function names (pow2roundup and
pow2rounddown were replaced with ceil2 and floor2 to match later
C++ standard names).

Change those OIIO::foo to std::foo or use the modern names
throughout the codebase, and hide the old declarations themselves
behind some guards that:

1. Will eliminate them completely as soon as the version is higher than
2.6.x.

2. Makes them invisible now internally to OIIO (so we aren't
accidentally using them ourselves), and to external projects (like OSL)
that define OIIO_DISABLE_DEPRECATED to hide deprecated things.

3. Add deprecation warnings if they are not hidden by the logic of (2)
above.

Before 3.0 release is final, we will truly remove them entirely, but
these staged warnings will help people with the transition.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-24 08:58:01 -07:00
Larry GritzandThiago Ize 92adbe0bf5 cleanup: simd.h deprecations (#4308)
Fully remove some things that have had deprecation warnings for a long,
long time (mostly since 1.x), so we think it can't possibly break
anyone.

Add deprecation warnings to some things that have been nominally
deprecated for some time. The build warnings will serve as final notice
that they will fully disappear by OIIO 3.0 release.

This is part of a series of small steps to fully deprecate a whole lot
of cruft between now and the 3.0 release.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Thiago Ize <ThiagoIze@users.noreply.github.com>
2024-06-23 09:29:03 -07:00
Jesse Yurkovich e4577d0b99 fix(psd): various PSD files fail to load correctly (#4302)
The primary issue seemed to be that the ChannelInfo width and height
were not filled in for some of the layers, notably the merged image data
layer in most(all?) cases.

A second issue was that there was incorrect nesting of the switch
statement in `read_channel_row`. The last 3 case statements were all
nested under the `if (!bigendian()) {` conditional from the 1st case.

Fixes #4298

## Tests

Use `iconvert` on all PSD files contained in the attached .zip.
Converting to both .exr and .png is a good test to ensure the data is
flowing out to those formats correctly.
[psd.zip](https://github.com/user-attachments/files/15905814/psd.zip)

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2024-06-22 15:16:40 -07:00
kaarrot 097e645f06 build: Add missing includes to libutil CMake target. (#4306)
This is the continuation of [4305
](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4305)(Add
extra step to Makefile config target to force CMake to rescan).
The error occurs when configuring with `make
OpenImageIO_BUILD_MISSING_DEPS=all` option which fails the build as
`libuitil` does not have `./dep/dist/include` on the path.
The original solution was to rerun cmake and let it rescan paths. This
step was only required to run once - after the initial CMake
configuration step. This kind off worked but I'm still unsure why. So
instead of that we can just add the missing location to CMakeLists.

Signed-off-by: kuba <kuba456@gmail.com>
2024-06-22 13:29:11 -07:00
Larry Gritz 9a020e8551 build: pybind11 raise min to 2.7 and make self-builder (#4297)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-21 21:32:28 -07:00
Larry Gritz c45f4d4e52 Rudimentary CUDA support infrastructure (#4293)
Build-time check for Cuda toolkit as optional dependency. This can be
explicitly disabled with OIIO_USE_CUDA=OFF (though currently, it
defaults to off, you have to turn it on at build time because this is
all still experimental). When this is enabled at build time, C++
preprocessor symbol OIIO_USE_CUDA will be defined within the OIIO
codebase.

OIIO global `attribute("gpu:device", "CUDA")` can be used to enable CUDA
functionality, which at this point doesn't do anything other than
initialize the CUDA device and find out information about it. Several
global `getattribute("cuda:*")` queries let you find out some
information about any device found.

I'm trying to keep a lot of the approaches fairly generic, so that the
interface won't need to change much to allow OpenCL or Metal or whatever
else comes along, though for now I'm trying to flesh out the
implementation mostly with CUDA.

oiiotool adds a new `--cuda` option, reserved for enabling CUDA
functionality. Currently the only way this is used is to print
information about the CUDA device in the `oiiotool --help` messages. An
example of that is:

```
$ oiiotool --cuda --help
oiiotool -- simple image processing operations
...

OIIO 2.6.2.0spi | Linux/x86_64
    Build compiler: gcc 9.3 | C++17/201703
    HW features enabled at build: sse2,sse3,ssse3,sse41,sse42
    CUDA 11.6.0 support enabled at build time
...
Running on 32 cores 187.3GB sse2,sse3,ssse3,sse41,sse42,avx,avx2,avx512f,
    avx512dq,avx512cd,avx512bw,avx512vl,fma,f16c,popcnt,rdrand
Compute hardware available: CUDA on Quadro RTX 6000, driver 12020,
    runtime 11060, compat 705, memory 23.6 GB
```

Note that at this point, we aren't actually *using* CUDA for anything.
This is just setting up some basics for future expansion. It's all
hidden in the pvt namespace for internal use only, and any of the
functions or nomenclature may change as we continue to add
functionality. I want to iterate on it a bit before it's in any way
exposed in public headers or interfaces.

I'm a big fan of introducing even big strategic changes in the form of a
series of MVP easy to review discrete steps. This step's only goals are:
(a) allowing the build system to find and link against the CUDA Toolkit;
(b) allowing runtime initialization and querying of a few basic facts
about the device found; (c) start noodling around just a bit with
function and attribute interfaces to gain a little experience that will
guide what we eventually want.

LONG TERM goals of this initiative include:

* A full TextureSystem work-alike that can be used from CUDA (and
possibly other compute device APIs) based renderers and with OSL's OptiX
back and, having an analogous (ideally identical) interface and as close
as possible to feature parity with CPU TextureSystem.

* Augment ImageBuf with the ability to store its images in GPU (or
unified) memory and for IBA functions to be able to operate on those
GPU-side buffers with GPU compute kernels, somewhat analogously to how
libraries like PyTorch provides optional GPU support for tensor
operations. (The hope is that this improves impage processing
performance, though it's possible that it'll turn out that typical OIIO
image processing workflows are so I/O dominated that there's not a lot
of potential upside. I think we'll have to try before we really find out
if it's going to be worth it.)

* Allow image reading/writing plugins (or other parts of OIIO
functionality) to leverage a GPU if available, and if there is something
productive they can do with it.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-21 21:31:27 -07:00
Curtis Black 348c16adac Simplify tile cache clearing. (#4292)
Simplifies the clearing of the tile cache so it no longer allocates a
vector of tile IDs prior to erasing them all.

---------

Signed-off-by: Curtis Black <curtis.w.black@gmail.com>
2024-06-21 10:31:32 -07:00
Larry Gritz 9c37711dc0 docs: Fixes to formatting and sphinx warnings (#4301)
Also, tell doxygen to use multiple threads.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-20 11:19:10 -07:00
Larry Gritz ea234b38ed build: Enhacements to the dependency report (#4294)
* List external dependencies found, as well as those not found.
* Sort and deduplicate the lists before printing.
* Print versions of everything

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-20 11:18:36 -07:00
Larry Gritz 1a1e6b1ff8 int(platform.h): In platform.h, define OIIO_DEVICE macro (#4290)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-17 07:47:21 -07:00
Larry Gritz 59b54587bf ci: new tets: oldest, hobbled, localbuilds (#4295)
Split the CI "oldest/hobbled" test into two different tests:

* oldest -- test against the oldest supported versions of all
dependencies.

* hobbled -- test against most optional dependencies missing and
optional feature disabled (including no SSE, no OCIO, etc.).

And add an additional test:

* local-builds -- a test that builds and uses every dependency that we
know how to build locally/automatically.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-16 11:55:50 -07:00
Larry Gritz d3c5d798f3 build: Raise freetype minimum to 2.10.0 and allow auto-build (#4283)
freetype 2.10.0 dates from 2019, so we're still supporting 5 years back.

Previously, we enforced no minimum, so we're not sure how far back it
would really work, but the earliest version we tested in CI was 2.8,
which dated from 2018.

Add a build_Freetype.bash for easy setup for CI (and other users).

Add build_freetype.cmake to allow automatic local builds if it can't
be found at build time.

CI many cases need to build freetype, because the old CentOS 7 era
freetype is now too old.

Remove some reference output that was only needed for older freetype.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-15 11:11:11 -07:00
Larry Gritz 8acc6bf891 build(deps): Raise Robin-map minimum to 1.2.0 (#4287)
Fixes #4050

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-12 18:18:04 -07:00
Larry Gritz e575f3b435 fix(iv): If OCIO env is not set or doesn't exist, have iv use built-in config (#4285)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-12 18:17:32 -07:00
Chris Hellmuth 762fe7b5c4 fix(ustring.h): Address ignored annotation nvcc warnings on explicitly-defaulted functions (#4291)
We're seeing nvcc compilation warnings like the following:
```
ustring.h(869): warning #20012-D: __device__ annotation is ignored on a function("operator=") that is explicitly defaulted on its first declaration
     __attribute__((host)) __attribute__((device)) 
```

According to nvidia's documentation
(https://docs.nvidia.com/cuda/archive/10.1/cuda-c-programming-guide/index.html#compiler-generated-functions),
functions that are explicitly-defaulted should not have execution space
specifiers like \_\_device\_\_ or \_\_host\_\_. Instead the compiler
will determine the annotations from the functions that invoke it.

This patch goes through the ustring and typedesc headers and removes
OIIO_HOSTDEVICE from all defaulted functions.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2024-06-12 15:02:14 -07:00
Larry Gritz 2bf029548b build: Upgrade to more modern python3 finding (#4288)
Latest versions of cmake are warning about FindPython being a deprecated
module, they recommend FindPython2 or FindPython3 instead. In master,
we're already python3 minimum, so go ahead and switch this to the modern
method.

This also seems to fully fix our recently broken CI on one of the Windows tests!

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-12 14:16:04 -07:00
Larry Gritz fd7d4210b9 fix: Improve error messages when a font is not found (#4284)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-10 14:28:02 -07:00
Larry Gritz a5157940c8 build: new system to build dependencies locally if needed (#4242)
High level TLDR:

* If checked_find_package doesn't find a dependency (or it is not an
  acceptable version), it looks for `src/cmake/build_<pkg>.cmake` and
  if that exists, includes it. It can do anything, but is expected to
  somehow provide the dependency so that a second find_package will
  find it and then proceed as if it were a system install.

* I've implemented these scripts so far for Imath, OpenEXR,
  OpenColorIO, fmt, and robin-map, that download, build, install the
  package in OIIO's build area. More to come later?

* This is really simple with a new build_dependency_with_cmake macro,
  much simpler than ExternalProject_Add, as I've seen it used
  elsewhere.

* Just look at any of the new build_blah.cmake files to see how simple
  it is for each new dependency we set up this way.

* By default, pre-installed packages it can find always take precedent
  over building locally. So if you have all the dependencies already
  installed, none of this should behave any differntly than before.
  But there are variables that let you override on a package by package
  basis, giving the option of never building locally, building locally
  if the package is missing, or forcing a local build to always happen.

----

Various details:

A bunch of cmake things (including checked_find_package) have been
moved into a new file, dependency_utils.cmake.

build_Imath.cmake, build_OpenColorIO.cmake, build_OpenEXR.cmake,
build_Robinmap.cmake, and build_fmt.cmake implement local builds of
those packages. They're very simple, and lean heavily on common
infrastructure of build_dependency_with_cmake, which also can be found
in dependency_utils.cmake.

Robinmap and fmt are extra simple because we use them as header-only
libraries.

For Imath and OpenEXR, I build them as static libraries, so they will
be incorporated into libOpenImageIO (and/or _Util) libraries to be
totally internal to them, there should be no symbols exposed outside
our libraries. This should mean that the resulting libOpenImageIO
should be perfectly safe to link in an application that also links
against OpenEXR, Imath, or OpenColorIO, even different versions
thereof, without any interference. Note that none of those packages
are used in our public APIs, only internally.

OpenColorIO was a little trickier. It builds its own dependencies as
static libraries that are internalized, but OCIO itself is a dynamic
library. So we end up having to make it part of our install, but I use
OCIO's build system to make a custom symbol namespace and a custom
library name, so it still should not interfere with any other OCIO
linked into the application.

We'll see how it goes for furture dependencies we want to add.  The
header only, static libraries incorporated and hidden, and dynamic
library but renamed and with custom namespace, are all techniques that
work well. I'm not sure I'd advocate doing local builds of any
dependency that we can't incorporate in one of these ways, but I guess
we'll cross that bridge when we get to it.

New option_utils.cmake has two handy new utilities: set_cache() is
much like the built-in set() when making a cache variable, and
set_option() is much like build-in option(). The biggest difference is
that both allow an environment variable of the same name, if it
exists, to supply the default value. This is something that cmake does
with many of its own controls, like CMAKE_BUILD_TYPE, but does not
make any provision for built-in set() or option() let users do it.

checked_find_package() has moved to dependency_utils.cmake, and has
been enhanced to take several new options, and also so that if the
enclosed find_package() fails and there is a
src/cmake/build_PKG.cmake, it will run it to build the dependency
itself in the build area. If that build_PKG sets a variable called
PKG_REFIND, it will try find_package again to find the one just built.

build_dependency_with_cmake() is given a git repo and tag, and
basically clones the repo, checks out the tag, configures, builds, and
installs it (all in our own build area).

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-10 14:25:27 -07:00
Larry Gritz 24f172a7e7 ci: For Windows CI, build only release of vcpkg packages (#4282)
This cuts down CI time, as before we were building both release and
debug versions of the packages.

The dependency building step of our CI typically took around 6.5-7
minutes previously, and with this patch, now typically is about 5
minutes and sometimes slightly less.

Thanks so much to @cedrik-fuoco who pointed me at this feature of vcpkg
which had eluded me for a long time!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-04 14:22:31 -07:00
Larry Gritz aad449f452 build: Some minor corrections to the new set utils (#4281)
A few minor fixes for things I noticed as I started to actually use
these new utilities in other branches I'm working on.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-04 14:20:25 -07:00
Larry Gritz 098b33ae3c fix: Typo in build_libtiff.bash (#4280)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-06-03 17:08:21 -07:00
Mel Massadian 81474b6544 fix: Update INSTALL.md for windows (#4279)
While making a CI to build python wheels for OIIO on windows I spotted a
few issues in the instructions, these edits made it work for me.

Small adjustment to expected paths for the manual instructions.

Signed-off-by: Mel Massadian <melmassadian@gmail.com>
2024-05-31 13:07:49 -07:00
Larry Gritz 6269efe960 ci: Avoid Ubuntu apt-get update that's killing the 24.04 runners (#4278)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-31 10:15:16 -07:00
Larry Gritz e0d0ae1b0e refactor: move most of imageio_pvt.h.in to just a regular .h (#4277)
This file imageio_pvt.h.in was used as the input template for CMake to
create imageio_pvt.h, doing a couple build variable substitutions along
the way. But this was inconvenient (because it doesn't look like a real
.h file to editors or clang-format) and it turns out that there were
only 2 lines that needed the substitution.

So in this patch, we split the file, making 99% of it just plain old
imageio_pvt.h that needs no rewriting, and the couple lines that need
variable substitions becomes buildopts.h.in and is included only from
the one source file that actually cares, imageio.cpp.

Other than cleaving those two definitions off to another header and some
file renaming, I haven't changed any of the other content of the
headers, so there should be no change in code the compiler sees or other
behavior.

The reformatting you see is because now that it's a legit .h file,
clang-format wants its way with it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-30 20:51:54 -07:00
Larry Gritz 7cfffaaef8 build: Partially revert #4193, the avoidance of add_blah wasn't necessary (#4273)
I misunderstood all along -- the add_compile_definitions,
add_compile_options, etc., aren't truly global, they are restricted to
targets in the same directory or below. They aren't really prone to
polluting "surrounding" projects when OIIO is used as a subproject.

So for simplicity, reverting that part and using the usual built-ins.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-29 10:09:30 -07:00
Larry Gritz 1313a2314d build: new set_utils.cmake for various handy "set()" wrappers (#4274)
New set_utils.cmake has some handy new utilities: set_cache() is much
like the built-in set() when making a cache variable, and set_option()
is much like build-in option(). The biggest difference is that both
allow an environment variable of the same name, if it exists, to supply
the default value. This is something that cmake does with many of its
own controls, like CMAKE_BUILD_TYPE, but does not make any provision for
built-in set() or option() let users do it.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-27 13:12:30 -07:00
Larry Gritz becf0f6953 fix(fmath.h): One more fast_exp fix (#4275)
In PR #4268, I accidentally changed the clause addressing what is
seemingly a bug with older MSVS. I'm just putting things back the way
they were. It's not a new change, just restoring this line closer to the
way it was about 3 commits back.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-26 13:39:46 -07:00
Larry Gritz ae8aa8f974 build: gcc-14 support, testing, CI (#4270)
* Switch runner type for bleeding edge, use gcc14 and python 3.12

* Various minor gcc-14 + C++20 + Python 3.12 fixes

Notable: gcc14 warns about std::atomic_load for share_ptr as deprecated,
since C++20 provides a true atomic shared pointer.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-22 11:09:58 -07:00
Larry Gritz a339c93bd0 build: Fix warning on windows (#4272)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-22 11:09:07 -07:00
Larry Gritz ce610f2725 fix(simd.h): fix longstanding probem with 16-wide bitcast for 8-wide HW (#4268)
We've been plagued on and off for a long time with spurious wrong
results in our SIMD versions of exp and log. It was really squirrelly,
came and went with changes to seemingly unrelated code, and had long
periods of time with no symptoms or ability to reproduce it. It just
started popping up again in CI in the dev-2.5 branch, consistently.

Today I think I finally tracked it down for real. I believe the problem
was actually in the SIMD bitcast_to_int and bitcast_to_float functions,
for the variety that was 8-wide when running on 4-wide hardware, and the
16-wide one when running on 8-wide (or less) hardware.

Background: When real 16-wide HW is not available, we define the 16-wide
vectors as an array of two 8-wide vectors. (Same for 8 vs 4, I'll spare
you explaining it all twice.) So most of the 16 wide functions boil down
to:

    vfloat16 op (vfloat16 arg, ...)
    {
    #if 16 wide HW is available
        return real_16_wide_intrinsic(arg);
    #else /* recursively define in terms of 8-wide halves */
        return vfloat16(op(arg.lo()), op(arg.hi()));
    #endif
    }

But for the bitcast operators, we did something different, a shade too
clever: we just did a pointer cast, dereference and return:

    vint16 bitcast_to_int (const vfloat16& x)
    {
    #if OIIO_SIMD_AVX >= 512
        return _mm512_castps_si512 (x.simd());
    #else
        return *(vint16 *)&x;
    #endif
    }

I believe that the problem is that this cast is undefined behavior for
the case where the vector x was broken into two halves, and by being in
the middle of a long code sequence of SIMD ops, the two halves happened
to be in registers at that moment. Basically, we are taking the address,
and it just doesn't seem to always understand that it needs to
materialize the whole thing in memory for the pointer cast to work
properly.

I removed the pointer cast and replaced with

    return vfloat16(bitcast_to_float(x.lo()), bitcast_to_float(x.hi()));

basically falling back on the usual recursive definition of 16-wide
operations to being in terms of 8-wide operations when 16-wide HW is not
available. This totally clears up the problem since we're no longer
potentially relying on needing the address of something that has no
address at that moment.

A couple other spots (andnot) also had dubious casts that I fixed in the
same way.

N.B.: The 16-wide cast from bool to int had to do something slightly
different, because it's represented differently and isn't a true
bitcast.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-21 21:46:18 -07:00
Larry Gritz 2ed2a47d4d test: Fix windows quoting for test (#4271)
We didn't notice before because our CI didn't test with OCIO on Windows.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-21 20:23:05 -07:00
Jesse Yurkovich 3b31ddd64e build: Add appropriate compiler defines and flags for SIMD with MSVC (#4266)
This should address the following 2 issues when using MSVC:
- MSVC does not set defines like `__SSE2__` or `__SSE4_2__` etc. we must
do that ourselves
- MSVC uses the `/arch` flag differently than other compilers and it
should be set only once

The ramifications of not having those defines set basically means that
OIIO won't notice any SIMD is possible.

For MSVC the /arch flag only controls which instruction set the compiler
may use when generating code "on its own". For example, the x64 compiler
by default will use SSE2 whenever possible when its generating code but
when using `/arch:AVX` it will produce AVX code as it sees fit. NOTE:
case matters here too! "avx" does not work but "AVX" does.

However, if the source code uses intrinsics, MSVC will happily use those
instead. In fact it's possible to use `avx512` intrinsics without
specifying any /arch flag at all and it will happily generate
corresponding avx512 code. This is much different than say GCC where, in
order to use intrinsics at all, you must specify the corresponding flags
allowing you to do so for the arch in question.

Fixes #4265

## Tests

Existing simd_test.cpp should be sufficient I think. In addition to
those, I've verified the below locally:

Currently: when using `-DUSE_SIMD="sse4.2,avx2"` to build, we get the
wrong `build:simd` flags:
`sse2`

After: using the same flags as above:
`sse2,sse3,ssse3,sse41,sse42,avx,avx2`

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2024-05-21 07:50:48 -07:00
Larry Gritz d0201ea1fa docs: Add missing documentation of ImageBuf locking methods (#4267)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-20 08:12:28 -07:00
Larry Gritz 4ff7643458 fix: Incorrectly formed debug output (#4269)
Format string didn't match the number of arguments.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-20 08:12:12 -07:00
Larry Gritz 41c894925b cleanup: change raw cerr stream output to print (#4258)
A small piece of the ongoing switch to std::format/print style text
output. This part is for error and debugging output when reading/writing
exr images.

I also switched conditional compilation to the DBG macro idiom that I've
used elsewhere, where it takes a combination of DEBUG compile and
setting of environment variable OIIO_DEBUG_OPENEXR to trigger the printf
style debugging (the first use case of this was in our color management
code, which I also modify slightly here to conform).

Also opportunistically simplify gcd declaration now that we're C++17
minimum.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-18 16:06:36 -07:00
jreichel-nvidia d868624a1d fix: Add proxy support for EXR multipart output (#4263) (#4264)
Add proxy support for EXR multipart output by taking the setup code from
the other open() overload and calling the constructor accepting a stream
instead of a filename.


---------

Signed-off-by: Joachim Reichel <43646584+jreichel-nvidia@users.noreply.github.com>
2024-05-16 09:06:01 -07:00
Larry Gritz feb58ace9e build: Add CMath target for the sake of static libtiff (#4261)
Recent libtiff versions export cmake configs that, if you built libtiff
as a static library, will reference targets it set up when it built, but
which are nonstandard names and won't exist when you build and consume
their config exports. Ugh!

Some can be swept under the rug by turning off some libtiff optional
dependencies, but I can't seem to get rid of a target CMath::CMath that
static libtiff target wants. It just points to the math library. So I'm
just setting that up so it will be found when we do the
find_package(tiff). Oh, the hoops we jump through for badly constructed
packges.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-14 15:48:27 -07:00
Larry Gritz f05ac2a799 testing: Add new heif test output (#4262)
Some weird combination of old libheif library gives a different
oiio:OriginalOrientation result. Need this ref because that's how it
behaves in that version (which I have to build against at work), but
it's not worth tracking down a "fix" because it's so old and works fine
on newer versions.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-14 15:48:08 -07:00
Larry Gritz d2f140dc9e refactor: oiiotool break out expression eval methods into separate file (#4256)
This is just a code move. There no changes to the code logic, though in
the process, I do change old "local" uses of eval_as_bool to the new
Strutil one.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-13 22:11:45 -07:00
Larry Gritz 8405e0f9ce fix: Improve IB::nsubimages and other related fixes (#4228)
Background: Some formats that support multi-image files know as soon as
they are opened and read the header what the total subimage count is.
Others (I'm looking at you, TIFF) can't know without reading each
subimage in succession until you hit the end of the file. Format readers
who can easily figure it out open first opening are supposed to set
attribute "oiio:subimages" to the number of subimages, or 0 / unset if
it can't be cheaply or immediately determined.

ImageBuf has a `nsubimages()` method that you'd think would give you the
right count, and it did when all IBs were read through the ImageCache
(which fully inventories the subimages of any file it reads). But when
OIIO 2.5 changed IB behavior to only be backed by IC when explicitly
requested, we effectively lost this functionality most of the time, and
instead returned 0 ("don't know yet"). This was confusing. And also
silly, because it reported 0 even for files whose formats don't permit
multiple images (so you know the count is 1).

This patch does the following:

* Changes the behavior and documentation of `ImageBuf::nsubimages()` to
the following return values:
- 1, for formats that are always a single subimage. (Or for ImageBufs
that are not direct reads of a file.)
- n>=1 for files that permit multiple subimages and the count is known.
- 0 for files that permit multiple subimages, but the count is not known
because it's one of the formats where it can't easily be determined upon
opening the file.
* Add a new ImageInput::supports("multiimage") that says if the input
file format permits multiple images, and ensure that it returns true for
all formats where this is the case.
* Ensure that formats permitting multiimage and can easily know the
count up front set the "oiio:subimages" attribute (not all did).
* Document in the built-in format section of the docs the formats that
are expected to set this attribute.

Fixes #4225

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-13 22:08:59 -07:00
Vlad (Kuzmin) Erium feb28fd264 jxl: JPEG-XL improvements (#4252)
## JpegXL Output plugin
* support for uint8/uint16/half/float
* "compression jpegxl:##" config hint sets compression type
* "jpegxl:distance"
* "jpegxl:effort"
* "jpegxl:photon_noise_iso"

## JpegXL Input plugin
* support for uint8/uint16/half/float

**Encode:**
```
oiiotools -v ^
-i DISP_16bit.tif -o DISP_16bit_tif.jxl ^
-i  DISP_8bit.tif -o DISP_8bit_tif.jxl ^
-i DISP_float.exr -o DISP_float_exr.jxl ^
-i DISP_half.exr -o DISP_half_exr.jxl
```

jxlinfo.exe -v output
```
JPEG XL image, 1440x1440, (possibly) lossless, 16-bit RGB
JPEG XL image, 1440x1440, (possibly) lossless, 8-bit RGB
JPEG XL image, 1440x1440, (possibly) lossless, 32-bit float (8 exponent bits) RGB
JPEG XL image, 1440x1440, (possibly) lossless, 16-bit float (5 exponent bits) RGB
```

**Decode**
```
oiiotool.exe -v ^
-i w:\DISP_16bit_tif.jxl -o w:\DISP_16bit_tif_jxl.tif ^
-i w:\DISP_8bit_tif.jxl -o w:\DISP_8bit_tif_jxl.tif ^
-i w:\DISP_float_exr.jxl -o w:\DISP_float_exr_jxl.exr ^
-i w:\DISP_half_exr.jxl -o w:\DISP_half_exr_jxl.exr
```

iinfo.exe output
```
DISP_16bit_tif_jxl.tif : 1440 x 1440, 3 channel, uint16 tiff
DISP_8bit_tif_jxl.tif : 1440 x 1440, 3 channel, uint8 tiff
DISP_float_exr_jxl.exr : 1440 x 1440, 3 channel, float openexr
DISP_half_exr_jxl.exr : 1440 x 1440, 3 channel, half openexr
```

TODO:
- [ ] EXIF and metadata
- [ ] Color spaces support
- [x] Encoding settings
- [ ] Decoding settings

## OIIO Tests
not yet


---------

Signed-off-by: ssh4net <libalias@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
2024-05-05 11:12:44 -07:00
Larry Gritz 6ba496f40f build: More warning elimination for clang18 (#4257)
This is a continuation of PR 4246, had one more spot where we needed to
disable warnings for unity builds involving clang18 and deprecated
unicode conversion functions.

There's some changes included to ci.yml and install_homebrew_deps.bash
that are part of work I did to make it easier for me to force it to use
clang-18 for certain tests while working on this.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-05 09:37:57 -07:00
Vlad (Kuzmin) Erium ed9d8d3570 pnm: Improvements to pnm plugin (#4253)
Fixes added:

- import/export support for 8/16 uint 32-float
- "pnm:bigendian" attribute reports/controls andianness
- "pnm:pfmflip" attribute (when set to 0) can disable the automatic vertical flip of pfm files (GIMP flips float PFM files by default, Photoshop does not)
- update in documentation

---------

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <shaamaan@gmail.com>
2024-05-04 10:14:28 -07:00
Larry Gritz 676fb5802f docs: Fix stray references to the old repo home (#4255)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-04 08:09:31 -07:00
Larry Gritz acc9605fb9 cleanup: more old style format deprecation (#4247)
Remove some long-ago deprecated printf-like error functions. Mark as
deprecated some other ones that we will remove when it gets closer to
3.0 release. I think these are the very last uses internally of the old
style that we want to remove.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-02 22:28:29 -07:00
Larry Gritz 90f78eb5ec CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-01 17:31:01 -07:00
Larry Gritz 559016f26b dev: Add Strutil::eval_as_bool (#4250)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-05-01 14:07:14 -07:00
Larry Gritz 69b91d36f8 fix: fix crash when no default fonts are found (#4249)
The nullptr at the end of default_font_name was left over from a time
that we iterated by going through array elements until we hit the
nullptr that signalled we had passed the last valid element. At some
point we switched to a range-for, which iterates over every element of
the array without needing an "end sentinel", and we should have
eliminated the nullptr but failed to do so.

Fixes #4248

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-29 19:15:01 -07:00
Larry Gritz 92701f7552 build: Disable clang18 warnings about deprecated unicode conversion (#4246)
clang/llvm 18 (and probably other compilers soon) has made noisy
warnings about the C++17-deprecated unicode conversions. Actually
replacing them enirely with something else is rather hairy, we will
tackle that later.

In the mean time, this patch seems to be the minimal change to disable
the warnings that should be totally easy to backport.

These seem to be the only changes necessary to make a clean build with
clang 18.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-27 11:40:41 -07:00
Brecht Van Lommel 9f62336e33 Don't use (DY)LD_LIBRARY_PATH as plugin search paths (#4245)
Only use the OIIO_LIBRARY_PATH environment variable by default.

Searching through such system paths has some risk loading plugins
installed for another purpose or that may be incompatible.

If the previous behavior is desired, applications can add these
environment variables to the plugin search path manually.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2024-04-25 23:34:56 -07:00
Larry Gritz 8d7f25b13b cleanup: convert more old errorf() to errorfmt() (#4231)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-23 13:22:32 -07:00
Larry Gritz 58127b7ddc security: Better documentation of past CVE fixes in SECURITY.md (#4238)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-23 13:22:03 -07:00
Larry Gritz a6239ead17 fix: Error retrieval safeguards for recycled objects (#4239)
The recent switch from boost thread_specific_ptr left a bug: if an
ImageInput (say) is deleted without the caller clearing its error state,
and then later another ImageInput is allocated and happens to get the
same address as the first one, it can "inherit" the unretrieved error
state left behind by the other.

Fix by  using a unique ID (initialized by an incrementing atomic
counter) to index the object in the per-thread error store.

I feel like we still don't have a foolproof replacement for the really
nice lifetime management that thread_specific_ptr was doing for us. One
could argue that unretrieved errors in an object are a "bug" in the
user's program, but unretrieved bugs currently just accumulate in the
map, even after the ImageInput is destroyed, until the thread terminates.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-21 17:28:02 -07:00
Peter Kovář 1c81e49e52 Fixed the sign compare causing build failure (#4240)
This is a trivial fix for build with warnings treated as errors.

Signed-off-by: Peter Kovář <peter.kovar@reflexion.tv>
2024-04-21 14:52:23 -07:00
Larry Gritz 9073b6c96c build!: Move OpenEXR/Imath minimum to 3.1 (#4223)
These are build-breaking changes that impose a new minimum OpenEXR/Imath
version supported of 3.1 or higher.

Needless to say, this will not be backported to any release branches,
which guarantee that they will never raise the minimum supported
versions of any dependencies. This is just for future OIIO. There is
already a "developer preview" branch dev-2.6.1 marking the last spot in
master in which the old dependencies are supported.

Fixes #4156

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-20 13:21:28 -07:00
Larry Gritz 19ad65ffdf security: change command line embedding for oiiotool & maketx output (#4237)
It was pointed out that oiiotool and maketx's habit of embedding their
exact command line arguments in the Software and ImageHistory metadata
of output images was potentially problematic in that it might
inadvertently leak important internal data (for example, file paths may
reveal secret projects, etc.).

This patch changes the behavior of oiiotool and maketx as follows:

* The default behavior is now to use `"OpenImageIO <version> <hash>"`
where `<hash>` is the SHA-1 hash of the command line arguments (which
allows you to tell if two files use the same command line args, but
doesn't let you know what they were).

* A new `--history` argument (or setting OIIOTOOL_METADATA_HISTORY env
variable to a nonzero integer) instead uses the full command line
arguments with no obfuscation. (This used to be the default behavior but
is now deemed unsafe.) When the env variable is in effect, a
`--no-history` argument explicitly disables it.

* For oiiotool, the existing `--nosoftwareattrib`, as before, causes the
Software and ImageHistory metadata to not be modified at all.

Here is an example of the behavior:

```
$ oiiotool tmp.tif -o tmp.exr && iinfo -v tmp.exr
tmp.exr :  640 x  480, 3 channel, half openexr
    channel list: R, G, B
    Software: "OpenImageIO 2.6.2.0dev : B897973B86EC13E3F1858AAE5E057EFCCF99889A"
    ...

$ oiiotool --history tmp.tif -o tmp.exr && iinfo -v tmp.exr
tmp.exr :  640 x  480, 3 channel, half openexr
    channel list: R, G, B
    Software: "OpenImageIO 2.6.2.0dev : oiiotool --history tmp.tif -o tmp.exr"
    Exif:ImageHistory: "oiiotool --history tmp.tif -o tmp.exr"
    ...
```

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-20 13:21:06 -07:00
Peter Kovář 27c3cfb2e7 feat: Add initial support to read R3D files (#4216)
This is an initial code for the RED Digital Cinema support.

CPU only so far.

See the RED section in the docs builtinplugins.rst for more details on what currently works and current limitations.

---------

Signed-off-by: Peter Kovář <peter.kovar@reflexion.tv>
2024-04-20 13:20:33 -07:00
Larry Gritz f481262233 fix(build): libOpenImageIO_Util does need DL libs, we removed it incorrectly (#4230)
Was broken by #4193

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-16 22:39:15 -07:00
Vic P 2eec082357 Fix building failed from source on Windows (#4235)
The instruction for building from source on Windows is incorrect and
causes building to fail. I fixed it.

Signed-off-by: Vic P <vic4key@gmail.com>
2024-04-16 12:35:09 -07:00
Larry Gritz 43a15b5aad fix: Typo in formatted output (#4229)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-15 16:10:00 -07:00
Larry Gritz f0c89626ed cleanup: Remove some long-deprecated things (#4234)
This is just the first step in many for removing deprecated things along
the way to a 3.0 release. I'm doing a little at a time.

I believe that here I'm only removing things that (a) have been
deprecated since 2.0 or earlier, (b) most or maybe all were marked with
OIIO_DEPRECATED and so should have been triggering warnings for a long
time if used downstream (thus, almost certainly nobody is using it), and
(c) are inline definitions, so this change should not appear to break
link ABIs.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-15 16:01:21 -07:00
Larry Gritz 58c8a112a5 build(deps): Remove the very last references to boost (#4233)
As Marie Kondo would say, Boost no longer sparks joy for us, so we take
one last look, thank it for its many years of service to our project,
and then send it on its way.

Fixes #4158

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-15 07:34:35 -07:00
Larry Gritz a4dafbd9f8 style: Fix clang-format problem caused by 4221 (#4232)
Oops, we let that slip by.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-14 20:38:31 -07:00
Christopher Kulla eef733c520 Remove boost thread_specific_ptr (#4221)
Remove the dependency on boost's thread_specific_ptr by using hashmap's
of static duration between the owning object and the target datatype.

After digging a bit into how boost's pointer works behind the scenes, it
is actually a very similar mechanism, with the lookup being into an
std::map. I don't have an easy way to measure performance here, but none
of these are on a hot path (with the possible exception of the
per_thread_info for the image cache, but this one can be managed
externally if you want the best performance.

---------

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2024-04-14 16:55:24 -07:00
Larry Gritz c76824bff0 fix(fmt.h): fix build break from recent fmt change (#4227)
We disable fmt execptions and force it to do one of our ASSERT's
instead. But fmt in their main branch recently added `[[noreturn]]`
annotations in a way that cause this to be compiler errors for our
overrides. Needed an extra std::terminate() call to guarantee the
noreturn promise.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-13 13:46:10 -07:00
Larry Gritz 4a89b8d0ee fix(TS): fix missing initialization in TextureOptBatch (#4226)
The doc comment said it should initialize, and the analogous structure
for scalar texturing, TextureOpt, initialized. Missed this one.

Fixes #4219

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-13 12:10:01 -07:00
Aaron Colwell 7f41a6a383 fix(openexr): Fix out-of-bounds reads when using OpenEXR decreasingY lineOrder. (#4215)
This change fixes out-of-bounds reads and incorrect scanline ordering
when OpenEXR's decreasingY lineOrder mode is used.

OpenEXR expects to process scanlines in decreasing order when the
decreasingY lineOrder option is enabled. This change fixes the code that
provides the chunks of scanlines to OpenEXR so that the proper scanlines
are available when it accesses the FrameBuffer OIIO created. The old
code was providing incorrect scanlines AND setting up the FrameBuffer
with incorrect pointers so out-of-bounds reads were occurring.

The key things to keep in mind are:
- Chunks of scanlines need to be sent to
OpenEXROutput::write_scanlines() from the bottom of the image to the top
when decreasingY is enabled. If the chunk's scanline range does not
contain the scanlines OpenEXR is expecting to fetch, then it can cause
out-of-bound reads because the wrong information is used to construct
the pointers for the Slices created when constructing a FrameBuffer.
- OpenEXROutput::write_scanlines() does its own chunking of scanlines
and this logic must also properly start from the bottom of the chunk
data passed into this function when decreasingY is enabled.
- The to_native_rectangle() call in OpenEXROutput::write_scanlines() may
return a pointer to m_scratch if a format conversion is needed. This
means the pointers passed to OpenEXR, in this situation, _WILL NOT_ be a
full frame buffer. This caused OpenEXR to do out-of-bounds reads because
the computations used to create the Slices were using the wrong scanline
number to adjust the pointer.
- The progress callback computation needed to be modified to handle
traversing scanlines in decreasing order.

I added an openexr-decreasingY test to verify that the code no longer
crashes because of the out-of-bound reads and it also verifies that the
decreasingY images match the increasingY images.

---------

Signed-off-by: Aaron Colwell <300262+acolwell@users.noreply.github.com>
2024-04-12 12:53:48 -07:00
kaarrot 0dd63f633a build: fix missing target_link_options for libraries
It seems that two targets `libOpenImageIO`, `libOpenImageIO_Util` were left out
during the [switch to target-based definitions]
(https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4193)
refactor and have no `-ftest-coverage -fprofile-arcs` options added in
the CODECOV=1 mode.

This was due to #4193 failing to propagate the link options to the dynamic libraries.

Adding the missing options resolves build errors.

Signed-off-by: kuba <kuba456@gmail.com>
2024-04-12 12:51:38 -07:00
Larry Gritz ab87887ba8 build: Remove boost::stacktrace (#4222)
To shed the boost dependency, we are disabling stacktrace for now. It's
not vital and probably not worth keeping boost just for that.

C++23 has std::stacktrace, so as compilers add support for this, we will
phase it back in.

We can also add it back if somebody has an alternate suggestion for a
3rd party solution that is a simply drop-in replacement, portable,
lightweight dependency, with compatible license. A good compromise might
be this one: https://github.com/jeremy-rifkin/cpptrace But I think what
I'm proposing is that we accept this PR first, get rid of boost, then we
can come back to looking at cpptrace as potentially a way to restore the
functionality prior to C++23.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-11 21:32:30 -07:00
Larry Gritz 96615f1c6a build!(deps): Raise minimum LibRaw to 0.20 (from 0.18) (#4217)
LibRaw 0.20 dates from mid-2020 and in any case, this version or newer
is necesary for use with C++17 which is our new minimum.

Bump the version built by build_scripts/build_LibRaw.bash to the latest.

Remove some old libraw testsuite output references that were only
applicable to the older versions.

This change will not be backported to release branches, the bump will
only be for OIIO 3.0 and later.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-10 12:49:26 -07:00
alexguirre f9113dfdca feat(dds): DDS support more DXGI formats (#4220)
Adds support for the following DXGI formats when using the DX10 extended
header on DDS files:
 - Compressed BCn and its sRGB variants.
 - BGRA8/BGRX8/RGBA8 and its sRGB variants.
 - RGB10A2.
 - R16.

On the sRGB formats, the attribute `oiio:ColorSpace` is also set to
`sRGB`.

Closes #4045.

Added new DDS test images to the OpenImageIO-images repo and updated the
testsuite expected output.
OpenImageIO-images PR:
https://github.com/AcademySoftwareFoundation/OpenImageIO-images/pull/7

Signed-off-by: Alejandro Aguirre <alexguirre.aa@gmail.com>
2024-04-10 12:47:41 -07:00
Larry Gritz e5058c1ccc build(deps): Raise OpenVDB minimum to 9.0 (#4218)
Soon we'll raise the minimum OpenEXR to 3.1, and OpenVDB 9.0 is the
first version to support that. And because OpenVDB has Imath types in
its public APIs, it's really hard to mix and match our using an
OpenEXR/Imath 3 internal to OIIO with an OpenVDB that uses an
OpenEXR/IlmBase 2.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-10 12:37:37 -07:00
Christopher Kulla 5472c84bf1 Replace uses of boost flat_map and flat_set with robin_map and robin_set (#4191)
A tiny bit more progress towards #4158.

None of the code was actually dependent on the fact that these
containers are sorted by key. Switching to the robin containers instead
removes one less use of boost in the project.

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2024-04-09 17:18:47 -07:00
Larry Gritz 8799aedabd build!: Move to Python 3.7 minimum (#4200)
These are build-breaking changes that impose a variety of new minimum
dependencies for the toolchain.

The new minimum Python version supported is now 3.7.

Get rid of 'from future' lines in python scripts in testsuite.

Remove python 2.7 specific ref images from testsuite.

Needless to say, this will not be backported to any release branches,
which guarantee that they will never raise the minimum supported
versions of any dependencies. This is just for future OIIO.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-05 07:50:46 -07:00
Larry Gritz cc36e2a5b2 ci: Update abi check after C++17 bump
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-04 22:03:14 -07:00
Larry Gritz e83cd7c449 build!: Move to C++17 minimum (#4199)
These are build-breaking changes that impose a variety of new minimum
dependencies for the toolchain.

C++17 is the new minimum. All hail C++17.

Bump minimum compiler versions to the respective releases of each one
that is requred to fully support C++17 for us. This means new minimum
changes of gcc 6.1 -> 9.3, clang 3.4 -> 5.0, icc 17 -> 19, and MSVS
v19.14 or higher now.

Remove CI tests for too-old platforms, and adjust some others that
needed particular components upgraded. We now will no longer attempt to
test on "VFX Platform 2019" or 2020. The 2021 platforms are the earliest
we claim to support (reflecting VFXP's guidance about trying to support
up to 3 years back).

By removing the old test cases, we're also removing the last platforms
that test Python 2.7. So while this PR isn't the one that officially
removes the last vestiges of Python 2, it does mean that once this is
merged, we will no longer be testing less than Python 3.7. (A separate
PR removing all Python 2 support will follow and presumably be merged
around the same time.)

With C++17 min, remove traces of boost::filesystem. We can rely on
std::filesystem now.

Clean up pre-C++17 macros in platform.h

Needless to say, this will not be backported to any release branches,
which guarantee that they will never raise the minimum supported
versions of any dependencies. This is just for future OIIO. I won't
merge this until after April 1, at which point I will also tag the last
spot in master that is known to work with C++14/gcc6.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-04 18:34:10 -07:00
EmilDohneandLarry Gritz fc5a454a9c feat(psd): Add support for 16- and 32-bit Photoshop file reads (#4208)
As mentioned in #4205, #3900 and
https://github.com/AcademySoftwareFoundation/OpenImageIO/discussions/3910#discussioncomment-8913737
OpenImageIO previously did not support reading of 16- and 32-bit files
beyond their merged image data section. I have now implemented this by:

1. Adding support for reading layer info from the "Lr16" and "Lr32"
Tagged Blocks as well as adding additional checks to the regular layer
info section
2. Implemented the Zip and ZipPrediction compression codec which is
required to read these files as that is photoshops preferred compression
codec for those bitdepths

Due to the way the Zip data is stored (per channel but not per scanline)
the current implementation reads the whole channel into a buffer which
is then memcpy'd from by calls to `read_native_scanline()`. The buffer
gets cleared on deletion of the `PSDInput` object

---------

Signed-off-by: EmilDohne <86836589+EmilDohne@users.noreply.github.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2024-04-02 09:59:29 -07:00
Larry Gritz 2ba88a7c11 ci: Fix broken Windows CI by building our own libtiff (#4214)
Windows CI was failing because it couldn't get a proper libtiff from
VcPkg, which in turn is because lzma is a dependency of the libtiff
build in VcPkg, and for the time being, it looks like VcPgk is failing
to get lzma which is part of the big xz debacle of 2024.

So work around for now by just building our own libtiff rather than
relying on VcPkg. Seems to work fine.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-01 18:20:10 -07:00
Larry Gritz 7a06ba38c3 Update ABI reference commit
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-01 14:55:38 -07:00
Larry Gritz 0caf97bc5f Bump master version number to prepare for more compat-breaking changes
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-04-01 12:46:10 -07:00
940 changed files with 78881 additions and 141708 deletions
+16
View File
@@ -0,0 +1,16 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Ignore skills that might be installed locally by a developer, to prevent
# cluttering the output of `git status` and prevent people from accidentally
# checking in locally installed skills.
skills/*
# But don't ignore the ones that belong to this project and are checked in. As
# we add skills that we intend to commit and make available to all project
# developers, they must be individually added here if they don't start with
# "oiio-".
!skills/oiio-*/
!skills/prepare-patch-release/
!skills/release-notes-update/
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env bash
# .agents/setup-agent — Set up AI coding tool integration for this repository.
#
# Creates the tool-specific symlinks and config files needed to use the shared
# resources in AGENTS.md and .agents/ with your preferred AI coding assistant.
# Run "setup-agent <tool>" once after cloning; re-running is always safe.
#
# The canonical project instructions live in AGENTS.md (root) and skills live
# in .agents/skills/<name>/SKILL.md. Everything tool-specific is either a
# symlink into those locations, or a thin wrapper that references them.
# Tool-specific directories (.claude/, .cursor/, etc.) are git-ignored so that
# each developer runs this script for the tool they actually use.
#
# ─────────────────────────────────────────────────────────────────────────────
# TOOL STRATEGIES (update this section when tool conventions change)
# ─────────────────────────────────────────────────────────────────────────────
#
# CLAUDE CODE
# Reads: .claude/CLAUDE.md (project) or CLAUDE.md (root) — NOT AGENTS.md natively.
# If Anthropic eventually adds native AGENTS.md support, the
# .claude/CLAUDE.md wrapper can be retired.
# Skills: .claude/skills/ (each subdirectory is a skill)
# Setup: Write .claude/CLAUDE.md containing "@AGENTS.md" (Claude's include
# syntax), symlink .claude/skills -> ../.agents/skills.
# Docs: https://docs.anthropic.com/en/docs/claude-code/memory
# https://docs.anthropic.com/en/docs/claude-code/skills
#
# OPENAI CODEX
# Reads: AGENTS.md natively — no wrapper needed.
# Skills: .agents/skills/ natively, and also .codex/skills/ as a fallback.
# Setup: Symlink .codex/skills -> ../.agents/skills so either path works.
# Docs: https://developers.openai.com/codex/guides/agents-md
# https://developers.openai.com/codex/skills
#
# CURSOR
# Reads: .cursor/rules/*.mdc files — does NOT read AGENTS.md natively.
# If Cursor adds native AGENTS.md support, the rules symlink can be
# retired.
# Skills: Cursor uses a different slash-command mechanism; .agents/skills/
# are not directly usable today, but the convention may change.
# Setup: Symlink .cursor/rules/project.mdc -> ../../AGENTS.md so Cursor
# picks up our instructions as a project rule.
# Docs: https://docs.cursor.com/context/rules-for-ai
# https://docs.cursor.com/cmdk/overview
#
# OPENCODE
# Reads: AGENTS.md natively — no wrapper needed.
# Skills: Documented to read .agents/skills/ natively, but in practice also
# requires .opencode/commands/<name>.md symlinks (as of 2025-05).
# Remove the per-command symlinks once opencode reliably finds
# .agents/skills/ on its own.
# Setup: Symlink .opencode/skills -> ../.agents/skills (future-proof),
# plus individual .opencode/commands/<name>.md -> skill SKILL.md
# files (current workaround).
# Docs: https://opencode.ai/docs/configuration
# https://opencode.ai/docs/skills
#
# GITHUB COPILOT
# Reads: AGENTS.md natively (VS Code Copilot ≥ 1.99 / GitHub Copilot Chat).
# Also reads .github/copilot-instructions.md as a fallback for older
# clients or non-VS Code surfaces.
# Skills: .agents/skills/ natively supported.
# Setup: Symlink .github/copilot-instructions.md -> ../AGENTS.md so older
# clients also receive our instructions. Remove once all Copilot
# surfaces reliably pick up AGENTS.md directly.
# Docs: https://code.visualstudio.com/docs/copilot/customization/custom-instructions
# https://docs.github.com/en/copilot/concepts/about-prompting-copilot
# https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SKILLS_DIR=".agents/skills"
SUPPORTED_TOOLS="claude codex cursor opencode copilot"
usage() {
cat <<EOF
Usage: .agents/setup-agent <tool|all|clear|list> [tool...]
Commands:
<tool> [...] Set up one or more tools
all Set up all supported tools
clear Remove all tool-specific setup created by this script
clear <tool> Remove setup for one specific tool
list List supported tools
Supported tools: $SUPPORTED_TOOLS
Examples:
.agents/setup-agent claude
.agents/setup-agent claude cursor
.agents/setup-agent all
.agents/setup-agent clear
.agents/setup-agent clear opencode
EOF
}
rel() { echo "${1#"$REPO_ROOT"/}"; }
# Create a symlink only if the path doesn't already exist.
# Silent if the link already points to the correct target.
safe_symlink() {
local link="$1" target="$2"
if [ -L "$link" ] && [ "$(readlink "$link")" = "$target" ]; then
return 0
elif [ -e "$link" ] || [ -L "$link" ]; then
echo " SKIP (already exists): $(rel "$link")"
return 0
fi
mkdir -p "$(dirname "$link")"
ln -s "$target" "$link"
echo " LINK: $(rel "$link") -> $target"
}
# Write a file only if the path doesn't already exist.
safe_write() {
local file="$1"
shift
local content="$*"
if [ -e "$file" ]; then
echo " SKIP (already exists): $(rel "$file")"
return 0
fi
mkdir -p "$(dirname "$file")"
printf '%s\n' "$content" > "$file"
echo " FILE: $(rel "$file")"
}
# Remove a symlink only if it still points to the expected target.
safe_remove_symlink() {
local link="$1" expected_target="$2"
[ ! -L "$link" ] && return 0
if [ "$(readlink "$link")" = "$expected_target" ]; then
rm "$link"
echo " REMOVED: $(rel "$link")"
else
echo " SKIP (modified, not removing): $(rel "$link")"
fi
}
# Remove a file only if its content still matches what we wrote.
safe_remove_file() {
local file="$1"
shift
local expected="$*"
[ ! -f "$file" ] || [ -L "$file" ] && return 0
if [ "$(cat "$file")" = "$expected" ]; then
rm "$file"
echo " REMOVED: $(rel "$file")"
else
echo " SKIP (modified, not removing): $(rel "$file")"
fi
}
try_rmdir() { rmdir "$1" 2>/dev/null && echo " RMDIR: $(rel "$1")" || true; }
#------------------------------------------------------------------------------
# Claude Code (.claude/)
#------------------------------------------------------------------------------
setup_claude() {
echo "Setting up Claude Code..."
safe_write "$REPO_ROOT/.claude/CLAUDE.md" "@AGENTS.md"
safe_symlink "$REPO_ROOT/.claude/skills" "../.agents/skills"
safe_write "$REPO_ROOT/.claude/.gitignore" "settings.local.json"
}
clear_claude() {
echo "Removing Claude Code setup..."
safe_remove_file "$REPO_ROOT/.claude/CLAUDE.md" "@AGENTS.md"
safe_remove_symlink "$REPO_ROOT/.claude/skills" "../.agents/skills"
safe_remove_file "$REPO_ROOT/.claude/.gitignore" "settings.local.json"
try_rmdir "$REPO_ROOT/.claude"
}
#------------------------------------------------------------------------------
# OpenAI Codex (.codex/)
#------------------------------------------------------------------------------
setup_codex() {
echo "Setting up OpenAI Codex..."
safe_symlink "$REPO_ROOT/.codex/skills" "../.agents/skills"
safe_write "$REPO_ROOT/.codex/.gitignore" "*.log"
}
clear_codex() {
echo "Removing OpenAI Codex setup..."
safe_remove_symlink "$REPO_ROOT/.codex/skills" "../.agents/skills"
safe_remove_file "$REPO_ROOT/.codex/.gitignore" "*.log"
try_rmdir "$REPO_ROOT/.codex"
}
#------------------------------------------------------------------------------
# Cursor (.cursor/)
#------------------------------------------------------------------------------
setup_cursor() {
echo "Setting up Cursor..."
safe_symlink "$REPO_ROOT/.cursor/rules/project.mdc" "../../AGENTS.md"
safe_write "$REPO_ROOT/.cursor/.gitignore" "$(printf 'composer/\nchat/')"
}
clear_cursor() {
echo "Removing Cursor setup..."
safe_remove_symlink "$REPO_ROOT/.cursor/rules/project.mdc" "../../AGENTS.md"
safe_remove_file "$REPO_ROOT/.cursor/.gitignore" "$(printf 'composer/\nchat/')"
try_rmdir "$REPO_ROOT/.cursor/rules"
try_rmdir "$REPO_ROOT/.cursor"
}
#------------------------------------------------------------------------------
# Opencode (.opencode/)
#------------------------------------------------------------------------------
OPENCODE_GITIGNORE="$(printf 'node_modules\npackage.json\npackage-lock.json\nbun.lock')"
setup_opencode() {
echo "Setting up Opencode..."
safe_symlink "$REPO_ROOT/.opencode/skills" "../.agents/skills"
safe_write "$REPO_ROOT/.opencode/.gitignore" "$OPENCODE_GITIGNORE"
# Individual command links (needed in practice despite docs implying otherwise)
for skill_dir in "$REPO_ROOT/$SKILLS_DIR"/*/; do
[ -d "$skill_dir" ] || continue
local skill_name
skill_name="$(basename "$skill_dir")"
safe_symlink "$REPO_ROOT/.opencode/commands/${skill_name}.md" \
"../../$SKILLS_DIR/${skill_name}/SKILL.md"
done
}
clear_opencode() {
echo "Removing Opencode setup..."
safe_remove_symlink "$REPO_ROOT/.opencode/skills" "../.agents/skills"
safe_remove_file "$REPO_ROOT/.opencode/.gitignore" "$OPENCODE_GITIGNORE"
for skill_dir in "$REPO_ROOT/$SKILLS_DIR"/*/; do
[ -d "$skill_dir" ] || continue
local skill_name
skill_name="$(basename "$skill_dir")"
safe_remove_symlink "$REPO_ROOT/.opencode/commands/${skill_name}.md" \
"../../$SKILLS_DIR/${skill_name}/SKILL.md"
done
try_rmdir "$REPO_ROOT/.opencode/commands"
try_rmdir "$REPO_ROOT/.opencode"
}
#------------------------------------------------------------------------------
# GitHub Copilot (.github/copilot-instructions.md)
# Copilot natively reads AGENTS.md, but also checks copilot-instructions.md.
#------------------------------------------------------------------------------
setup_copilot() {
echo "Setting up GitHub Copilot..."
safe_symlink "$REPO_ROOT/.github/copilot-instructions.md" "../AGENTS.md"
}
clear_copilot() {
echo "Removing GitHub Copilot setup..."
safe_remove_symlink "$REPO_ROOT/.github/copilot-instructions.md" "../AGENTS.md"
}
#------------------------------------------------------------------------------
# Dispatch
#------------------------------------------------------------------------------
run_tool() {
local action="$1" tool="$2"
case "$tool" in
claude) "${action}_claude" ;;
codex) "${action}_codex" ;;
cursor) "${action}_cursor" ;;
opencode) "${action}_opencode" ;;
copilot) "${action}_copilot" ;;
*)
echo "Unknown tool: $tool (supported: $SUPPORTED_TOOLS)" >&2
exit 1
;;
esac
}
[ $# -eq 0 ] && { usage; exit 0; }
case "$1" in
all)
for t in $SUPPORTED_TOOLS; do run_tool setup "$t"; done
;;
clear)
shift
if [ $# -eq 0 ]; then
for t in $SUPPORTED_TOOLS; do run_tool clear "$t"; done
else
for t in "$@"; do run_tool clear "$t"; done
fi
;;
list)
echo "Supported tools: $SUPPORTED_TOOLS"
;;
-h|--help|help)
usage
;;
*)
for t in "$@"; do run_tool setup "$t"; done
;;
esac
@@ -0,0 +1,104 @@
---
name: prepare-patch-release
description: Do all the tasks needed for a patch release of the project.
argument-hint: [new-version]
---
Do all the tasks needed for a patch release of the project. These patch
releases generally happen on the first day of every month.
Arguments: `$ARGUMENTS`
- First argument (optional): the version of the upcoming release we are
preparing. If omitted, find the most recent tag on this branch, and the
new version will update the third portion of the version. It might be
either a version number (like `3.1.4.0`) or a tag (like `v3.1.4.0`).
Hint: The numeric "version" is a four-part numeric deignation with the pattern
`MAJOR.MINOR.PATCH.TWEAK`. The "version tag" is usually the numeric version
with a "v" prepended, for example, `v3.1.4.0`.
## Steps and Checklist
- [ ] Determine the version of the new release.
- [ ] Update the main @CMakeLists.txt.
- [ ] Use the "release-notes-update" skill to update @CHANGES.md.
- [ ] Review the release notes to ensure that the changes do not deprecate any
API calls or break API or ABI backward-compatibility, or remove support
for any dependency or toolchain versions. If you think these rules are
being violated, ask for confirmation.
- [ ] Review @README.md for changes.
- [ ] Review @INSTALL.md for changes.
- [ ] Review @CREDITS.md for changes.
- [ ] Review @SECURITY.md for changes.
## Steps to determine the versions of the last and new releases.
1. **Determine the previous tag** if not provided by looking at the
most recent git tag in the current branch, and deducing the 4-part
version number from that.
2. The assumed new version for a patch release has the same major and minor
numbers, the patch number is incremented by one since the last tag, and the
tweak number is "0".
3. If no optional version was present in the arguments, use the assumed new
version.
4. If a version was supplied in the arguments, double check that it differs
from the last tag as explained above. If it does not, ask for verification
that the version requested is correct before proceeding.
## Steps to update CMakeLists.txt
1. In the main @CMakeLists.txt, alter the version to that of the new release,
if it isn't already the same.
2. For a patch release, ensure that `${PROJECT_NAME}_SUPPORTED_RELEASE` should
be set to ON. In main (not yet a supported release) it shold be OFF. If you
find these to not be as expected, ask for confirmation of whether to fix.
3. For a patch release, `PROJECT_VERSEION_RELEASE_TYPE` should be set to empty
(""). In main, it will typically be "dev", "beta", or other designations.
If you find these to not be as expected, ask for confirmation of whether to
fix.
## Reviewing README.md
If this release added support for any new image file formats, be sure that
README.md mentions them in its list of image formats supported.
## Reviewing INSTALL.md
If any of the new commits (as described in the release notes for this version)
appear to add dependencies, or add support for new versions of dependencies,
be sure that INSTALL.md is updated to include that dependency (if not already
listed among the required and optional dependencies), and reflects the latest
version that we claim to support.
Double check @externalpackages.cmake and ensure that any minimum required
versions of dependencies that cmake will enforce match the oldest versions
of those dependencies as documentd in INSTALL.md.
## Reviewing CREDITS.md
The @CREDITS.md file lists all known contributors to the project, sorted alpha
by first name. In cases where an author's actual name is unknown, we use the
GitHub userid.
Ensure that any authors referenced in the new release notes for the version we
are releasing are inserted in the credit list, if they are not already
present. You don't need to check older versions, we presume those have already
been included.
## Reviewing SECURITY.md
The @SECURITY.md file lists which versions are currently supported at what
levels, and lists all previously-fixed SVE's or security advisories. Be sure
to check this file in older branches (the last two releases, say), and if you
are preparing a patch release, also check in main and more recent (higher
numbered) releases for more recently modified SECURITY.md, and be sure that
this branch gets amended with any information that seems to have been updated
more recently in those other branches. Check whichever is newer of the local
and remote copy of that branch, since the local one may have had release notes
or its version in CMakeLists.txt updated, but not yet pushed to GitHub.
## Reference
- Full release procedures: `docs/dev/RELEASING.md`
- Steps for updating release notes: `release-notes-update/SKILL.md`
@@ -0,0 +1,246 @@
---
name: release-notes-update
description: Generate or update release notes for a patch, minor, or major release, or just to update main. Run git-cliff, organize and edit the output per project conventions, and insert into CHANGES.md.
argument-hint: [patch|minor|major|main] [prev-tag]
---
Generate release notes for an OpenImageIO release.
Arguments: `$ARGUMENTS`
- First argument (optional): release type — `patch` (default), `minor`, `major`, or `main`.
- Second argument (optional): previous release tag (e.g. `v3.1.2.0`). If omitted, find the most recent tag automatically. If the release type is `main`, instead of a tag, look for the last commit at which the CHANGES.md file was updated.
## Steps
1. **Determine the previous tag** if not provided:
```
git describe --tags --abbrev=0
```
or look at recent tags: `git tag --sort=-version:refname | head -10`.
However, if the "release type" is `main`, instead of a tag, just find
the commit at which CHANGES.md was last updated.
2. **Run git-cliff** to get raw commit data:
```
git cliff -c src/doc/cliff.toml <prev-tag>..HEAD > /tmp/cliff-out.md
```
Read `/tmp/cliff-out.md` to see the raw output.
3. **Required, do not skip:** Look up the GitHub user ID for each author (use
`gh pr view NNNN --repo AcademySoftwareFoundation/OpenImageIO --json
author` — the login is discernable from the posted PR, but not from the
local commit). Rewrite every git-cliff author credit from `(by First
Last)` to the combined form `(by @githubid / First Last)` before drafting
the formatted notes in step 5. This applies to patch, minor, major, and
main updates alike — the combined format is the standard for every
release type, not just an example in the patch skeleton. Only fall back to
a single form — `(by @githubid)` or `(by First Last)` — if the other half
genuinely cannot be found; don't skip the github lookup just because the
real name is already known from the local commit.
4. **Read CHANGES.md** to see the current top of the file and understand where to insert.
5. **Format the release notes** according to the release type:
### For patch releases:
Follow the skeleton in `docs/dev/Changes-skeleton-patch.md`:
```
Release X.Y.Z.W (Month DD, YYYY) -- compared to X.Y.Z.W-1
---------------------------------------------------------
- *category*: Description. [#NNNN](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/NNNN) (by @authorid / author-full-name)
```
Rules:
- **Remove** the section headings git-cliff generates; patch notes are a flat
list.
- **Add conventional commit prefixes** to any "uncategorized" entries (those
lacking a `feat:`, `fix:`, etc. prefix).
- **Reorder** entries logically: feature enhancements first, then bug fixes,
then build/CI fixes, then internal changes, then test improvements, then
docs/admin.
- **Omit** entries that are purely internal and too minor to matter to users.
Ask for confirmation about entries you propose to omit.
- Author credit is `(by @githubid / Full Name)` per step 3 above. Use just
`(by @githubid)` or `(by Full Name)` only if the other half truly can't be
found — don't drop the githubid merely because the name is already known.
- Omit the author if it is the project leader, Larry Gritz, unless he is not
the dominant author (at least 75% of commits) in this release.
- Keep entries to one line each. Be terse but informative.
- Use the format `*subsystem*:` for the category prefix (e.g., image file
format like `*exr*:`, utility like `*oiiotool*:`, class or API category like
`*IBA*:`, or topic category such as `*build*:`, `*ci*:`, `*docs*:`).
- We aim to make patch releases on the first day of each month. If we are
within a few days of a month end, list the date as the beginning of the
upcoming month. Ask for confirmation that this is the planned release date.
### For minor or major releases:
Follow the skeleton in `docs/dev/Changes-skeleton-major.md`. Sections:
```
Release X.Y.0.0 (Month, YYYY) -- compared to X.Y-1
--------------------------------------------------
### New minimum dependencies and compatibility changes:
### ⛰️ Major new features and public API changes:
* *New image file format support:*
* *oiiotool new features and major improvements*:
* *Command line utilities*:
* *API changes*
* Other notable new feature:
### 🚀 Performance improvements:
### 🐛 Fixes and feature enhancements:
### 🔧 Internals and developer goodies
### 🏗 Build/test/CI and platform ports:
* CMake build system and scripts:
* Dependency and platform support:
* Testing and Continuous integration (CI) systems:
### 📚 Notable documentation changes:
### 🏢 Project Administration
### 🤝 Contributors
```
Note that the section outline may already be present, in which case you
only need to fit items into the existing category outline.
Rules:
- Group commits into sections; within each section, cluster related items together.
- When needed, expand terse one-liners into enough prose that users understand what changed and why it matters.
- For `feat:` commits, make sure the feature is explained sufficiently — don't just copy the commit subject.
- For `api:` or `api!:` commits, clearly call out what changed in the public API.
- Include PR links and author attribution for every entry, in the combined
`(by @githubid / Full Name)` form from step 3.
- The notes should "tell the story" of the release, not just be a dump of commit subjects.
- We aim to make major/minor releases approximately in October 1 of each year. If the anticipted release date is already in the file, don't change it. If it is not present, ask for confirmation of the planned release date.
### For updating release notes in main:
Rules:
- Generally, follow the rules for "major/minor releases", except as noted in other items below.
- Don't apply a new skeleton of category listings unless they are not present for the upcoming release.
5. **Insert the formatted notes** into `CHANGES.md` in the appropriate place (as detailed below). Leave the existing content intact.
- When updating `main` or preparing a `major` or `minor` release, insert the updates in the top section for the upcoming major/minor release. Insert a new set of category sections only if it's not already present.
- When doing a `patch` release, insert the changes immediately above the last patch release of that branch, so that CHANGES.md lists releases in descending numerical (version) order.
- When porting a set of release notes from a release branch into main, or from an older (obsolete) release branch to the current release branch, insert it into the right place to maintain overall descending order.
6. **Double check that the notes are adequately descriptive.** (See more
detailed description of this step below.)
7. **Forward-port release notes from release branches if needed**
8. **Show a summary** of what was inserted and ask the user to review before finalizing.
## Forward-porting release notes
Release notes may have been generated independently in main, and release
branches. When updating one branch, we ensure that any changes from older
branches have been incorporated.
- When preparing `patch` release notes, check the CHANGES.md file in the
"dev-X.(Y-1)" branch for the previous minor release family to identify any
X.(Y-1).Z patch release notes that are not reflected in the current release
notes that we are updating.
- When updating `main` or doing a `major` or `minor` release, check the
CHANGES.md file in both the "dev-X.(Y-1)" and "dev-X.(Y-2)" branches.
Check whichever is newer of the local and remote copy of that branch, since
the local one may have had release notes or its version in CMakeLists.txt
updated, but not yet pushed to GitHub.
- If any patch releases are present in the older dev branches checked, insert
the release notes for those patch releases into the right positions in the
current release notes that we are updating.
- If a change is forward-ported in this manner and the same PR is an update in
the current set of changes we are updating as our main task, document that
in the current set of notes using the following convention: in the line of
the notes, the explanation of the version where it appears should reflect
the first version of all branches where it appeared, for example, `(3.2.0.0,
3.1.3.0, 3.0.8.0)` to indicate that the patch was added to each of those
versions. The versions should be listed in descending order.
## Useful abbreviations for category labels
| Abbrev | Meaning |
|--------|---------|
| IB | ImageBuf |
| IBA | ImageBufAlgo |
| IC | ImageCache |
| TS | TextureSystem |
| oiiotool | the oiiotool command |
| build | CMake/build system |
| deps | Changes to accommodate dependency or toolchain changes |
| ci | CI/GitHub Actions |
| docs | documentation |
| int | internal/refactor |
| test | testsuite or unit tests |
| HEADER.h | Developer utilities in a public header file |
## Combining PRs into single entries
To be more concise and easier to read, within a release's notes, related
PRs/commits can be combined into a single bullet-point line, which would look
like
```
- *category*: Combined Description. [#NNNN1](URL) (by author1) [#NNNN2](URL2) (by author2) [#NNNN2](URL2) (by author2)
```
if fully combined, or if explained one by one,
```
- *category*: Description 1 [#NNNN1](URL) (by author1), amendment 2, [#NNNN2](URL2) (by author2), amendment 3, [#NNNN3](URL3) (by author3)
```
Choose the fully combined or explained one by one based on which is more clear
to the reader.
If the authors are all the same, only have the author designation at the end.
Here are the cases where it's ok to combine commits in this way:
- If it is clear that multiple PRs are part of the same feature or fix,
consisting of an initial commit, and subsequent smaller changes or
continuations of the same topic.
- An initial commit, and a subsequent commit that is obviously a fix to a bug
in the initial commit.
- "CI" changes that all only add new cases to the test matrix.
- "CI" changes that all only fix spontaneous breakages in the GitHub runners.
- "Build" changes that are all just minor updates to versions of dependencies
that we support or test against.
Some more examples of combined commit messages:
```
- feat: Add GPS metadata functionality for TIFF [PR1](PR URL 1) [PR2](PR URL 2) [PR3](PR URL 3) (by author).
- ci: New CI variants for MSVS 2026 [PR1](PR URL 1) (by author1), VFX Platform 2027 [PR2](PR URL 2) (by author2).
- ci: Various fixes for unexpected changes to GitHub Actions runners [PR1](PR URL 1), [PR2](PR URL 2) (by author)
- build: Added support for gcc 15 [PR1](PR URL 1) (by author1), OpenEXR 3.5.1 [PR2](PR URL 2) (by author2), libtiff 4.8 [PR3](PR URL 3) (by author3).
```
Always ask for confirmation before combining commits in this manner. Confirm
separately for each proposed combination of a group of multiple original
commits into a single commit. Give the user the opportunity to revise the
combined description or request other changes for the grouping.
## Double check that the notes are adequately descriptive
For newly added items for this release, read the short descriptions provided
by git-cliff, double check them against the full commit messages to be sure
the one-line summary is adequate. If the summary is misleading, too brief and
leaving out the fact that an important thing was changed, or not adequately
capturing the scope of changes, feel free to propose an alternate wording that
will make it more clear to readers what changed as a result of the PR. Ask for
confirmation on these and explain why you felt the one-line description wasn't
enough.
One example of a case where this is needed is if the one line description
merely mentions a new image processing capability by name, but the full commit
message makes it clear that a new ImageBufAlgo API call was added, and also a
new oiiotool command line argument was added, and that couldn't all be
described in the one-line brief message of the commit.
## Reference
Full release procedures: `docs/dev/RELEASING.md`
Patch skeleton: `docs/dev/Changes-skeleton-patch.md`
Major skeleton: `docs/dev/Changes-skeleton-major.md`
Example good patch notes: https://github.com/AcademySoftwareFoundation/OpenImageIO/releases/tag/v3.0.0.0
Example good major/minor notes: https://github.com/AcademySoftwareFoundation/OpenImageIO/releases/tag/v3.1.6.1
+3
View File
@@ -40,3 +40,6 @@ d8810c5365ea88e2b1bce6155b7b495c18f2f9bc
# style: update our formatting standard to clang-format 17.0 and C++17 (#4096)
c618d45e13dcc382fb07a948be84b8074d1ed481
b88b82ffe9b3c4fcf04bf17bacc4ee77b2d1ed92
# style: Turn on clang-format for ivmain.cpp (#4382)
55872131ada91e0fa3b8bc4519e335b352d284df
+17
View File
@@ -0,0 +1,17 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Helpful documentation:
# - https://github.com/github-linguist/linguist/blob/main/docs/overrides.md
# - https://github.com/github-linguist/linguist/blob/main/docs/troubleshooting.md
*.h linguist-language=C++
src/libOpenImageIO/bluenoise.inc -linguist-detectable
# Image test fixtures are binary and must never be CRLF-converted on
# checkout. Some (e.g. tiny/corrupt HDR files) are mostly ASCII and would
# otherwise be misdetected as text, breaking byte-exact reader tests.
*.hdr binary
*.rgbe binary
+4 -1
View File
@@ -1,12 +1,15 @@
---
name: Bug report
about: I think I have identified a legit bug and can describe it.
title: "[BUG]"
title: "bug:"
labels: ''
assignees: ''
---
<!-- THESE ARE JUST SUGGESTIONS. FEEL FREE TO DELETE ALL OF THIS AND -->
<!-- WRITE YOUR OWN THOROUGH BUG REPORT. -->
**Describe the bug**
A clear and concise description of what the bug is. What happened, and
+4 -3
View File
@@ -1,16 +1,17 @@
---
name: Build problems
about: I'm having trouble building OIIO. Help!
title: "[BUILD]"
title: "build:"
labels: ''
assignees: ''
---
**PLEASE DO NOT REPORT BUILD TROUBLES AS GITHUB "ISSUES" UNLESS YOU ARE RALLY SURE IT'S A BUG**
**PLEASE DO NOT REPORT BUILD TROUBLES AS GITHUB "ISSUES" UNLESS YOU ARE REALLY SURE IT'S A BUG**
The best way to get help with your build problems is to ask a question on the
[oiio-dev developer mail list](https://lists.aswf.io/g/oiio-dev).
[oiio-dev developer mail list](https://lists.aswf.io/g/oiio-dev) or on the
[ASWF Slack](https://slack.aswf.io) `#openimageio` channel.
When you email about this, please attach one or both of the following:
1. The full verbose build log, which you can create like this:
+4 -1
View File
@@ -1,12 +1,15 @@
---
name: Feature request
about: I have a concrete idea about how to improve OpenImageIO.
title: "[FEATURE REQUEST]"
title: "feat:"
labels: ''
assignees: ''
---
<!-- THESE ARE JUST SUGGESTIONS. FEEL FREE TO DELETE ALL OF THIS AND -->
<!-- WRITE YOUR OWN THOROUGH FEATURE REQUEST. -->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+4 -4
View File
@@ -1,7 +1,7 @@
---
name: Question
about: How do I... I need help with...
title: "[HELP]"
title: "help:"
labels: ''
assignees: ''
@@ -18,10 +18,10 @@ But if you are just asking a question:
* Am I doing something wrong?
* I can't build OpenImageIO
For anything of this nature, the best way to get help using OpenImageIO is
to ask a question on the [oiio-dev developer mail list](https://lists.aswf.io/g/oiio-dev).
For anything of this nature, the best way to get help using OpenImageIO is to
ask a question on the [oiio-dev developer mail list](https://lists.aswf.io/g/oiio-dev) or the [ASWF Slack](https://slack.aswf.io) `#openimageio` channel.
The [documentation](https://openimageio.readthedocs.org)
The [documentation](https://docs.openimageio.org)
is pretty comprehensive, so please check there first; you may find the answer
more quickly than you can get your question answered on the mail list.
+35 -18
View File
@@ -1,32 +1,49 @@
<!-- This is just a guideline and set of reminders about what constitutes -->
<!-- a good PR. Feel free to delete all this matter and replace it with -->
<!-- your own detailed message about the PR, assuming you hit all the -->
<!-- important points made below. -->
## Description
------ :scissors: -------------------------------------------------------------------
YOU MAY DELETE ALL OF THIS IF YOU ALREADY HAVE A DESCRIPTIVE COMMIT MESSAGE!
This is just a template and set of reminders about what constitutes a good PR.
But please look over the checklist at the bottom.
If THIS TEXT is still in your PR description, we'll know you didn't read the
instructions!
### Description
<!-- Please provide a description of what this PR is meant to fix, and -->
<!-- how it works (if it's not going to be very clear from the code). -->
## Tests
### Tests
<!-- Did you / should you add a testsuite case (new test, or add to an -->
<!-- existing test) to verify that this works? -->
## Checklist:
### Checklist:
<!-- Put an 'x' in the boxes as you complete the checklist items -->
- [ ] I have read the [contribution guidelines](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/CONTRIBUTING.md).
- [ ] I have updated the documentation, if applicable.
- [ ] I have ensured that the change is tested somewhere in the testsuite
(adding new test cases if necessary).
- [ ] If I added or modified a C++ API call, I have also amended the
corresponding Python bindings (and if altering ImageBufAlgo functions, also
exposed the new functionality as oiiotool options).
- [ ] My code follows the prevailing code style of this project. If I haven't
already run clang-format before submitting, I definitely will look at the CI
test that runs clang-format and fix anything that it highlights as being
nonconforming.
- [ ] **I have read the guidelines** on [contributions](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/CONTRIBUTING.md) and [code review procedures](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/docs/dev/CodeReview.md).
- [ ] **I have read the [Policy on AI Coding Assistants](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/docs/dev/AI_Policy.md)**
and if I used AI coding assistants, I have an `Assisted-by: TOOL / MODEL`
line in the pull request description above.
- [ ] **I have updated the documentation** if my PR adds features or changes
behavior.
- [ ] **I am sure that this PR's changes are tested in the testsuite**.
- [ ] **I have run and passed the testsuite in CI** *before* submitting the
PR, by pushing the changes to my fork and seeing that the automated CI
passed there. (Exceptions: If most tests pass and you can't figure out why
the remaining ones fail, it's ok to submit the PR and ask for help. Or if
any failures seem entirely unrelated to your change; sometimes things break
on the GitHub runners.)
- [ ] **My code follows the prevailing code style of this project** and I
fixed any problems reported by the clang-format CI test.
- [ ] If I added or modified a public C++ API call, I have also amended the
corresponding Python bindings. If altering ImageBufAlgo functions, I also
exposed the new functionality as oiiotool options.
+59 -92
View File
@@ -11,15 +11,32 @@ on:
# Run unconditionally once weekly
# - cron: "0 0 * * 0"
push:
# Run on pushes only to master or if the branch name contains "analysis"
# Run on pushes only to main or if the branch name contains "analysis"
branches:
- main
- dev-3.0
- '*analysis*'
- '*sonar*'
paths:
- '**'
- '!**.md'
- '!**.rst'
- '!**/ci.yml'
- '!**/docs.yml'
- '!**/scorecard.yml'
- '!**/wheel.yml'
- '!**.properties'
- '!pyproject.toml'
- '!docs/**'
# Run analysis on PRs only if the branch name indicates that the purpose of
# the PR is related to the Sonar analysis. We don't run on every PR because
# the analysis run is very expensive and just isn't usually necessary.
pull_request:
branches:
- master
- '*analysis*'
- '*sonar*'
# Allow manual kicking off of the workflow from github.com
workflow_dispatch:
# Uncomment the following line if we want to run analysis on all PRs:
# pull_request:
permissions: read-all
@@ -35,109 +52,59 @@ jobs:
name: "SonarCloud Analysis"
# Exclude runs on forks, since only the main org has the SonarCloud
# account credentials.
if: github.repository == 'AcademySoftwareFoundation/OpenImageIO'
if: github.event.repository.fork == false
uses: ./.github/workflows/build-steps.yml
# Must let the called steps workflow inherit necessary secrets
secrets:
PASSED_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PASSED_SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
nametag: ${{ matrix.nametag || 'unnamed!' }}
runner: ${{ matrix.runner || 'ubuntu-latest' }}
container: ${{ matrix.container }}
cc_compiler: ${{ matrix.cc_compiler }}
cxx_compiler: ${{ matrix.cxx_compiler }}
cxx_std: ${{ matrix.cxx_std || '17' }}
build_type: ${{ matrix.build_type || 'Release' }}
depcmds: ${{ matrix.depcmds }}
extra_artifacts: ${{ matrix.extra_artifacts }}
fmt_ver: ${{ matrix.fmt_ver }}
opencolorio_ver: ${{ matrix.opencolorio_ver }}
openexr_ver: ${{ matrix.openexr_ver }}
pybind11_ver: ${{ matrix.pybind11_ver }}
python_ver: ${{ matrix.python_ver }}
setenvs: ${{ matrix.setenvs }}
simd: ${{ matrix.simd }}
skip_build: ${{ matrix.skip_build }}
skip_tests: ${{ matrix.skip_tests }}
abi_check: ${{ matrix.abi_check }}
build_docs: ${{ matrix.build_docs }}
generator: ${{ matrix.generator }}
ctest_args: ${{ matrix.ctest_args }}
ctest_test_timeout: ${{ matrix.ctest_test_timeout }}
coverage: ${{ matrix.coverage || '0' }}
sonar: ${{ matrix.sonar || '0' }}
strategy:
fail-fast: false
matrix:
include:
- desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.2
- desc: sonar gcc11/C++17 py311 exr3.2 ocio2.3
nametag: static-analysis-sonar
os: ubuntu-latest
container: aswf/ci-osl:2023-clang15
vfxyear: 2023
container: aswf/ci-oiio:2024.2
cxx_std: 17
python_ver: "3.10"
python_ver: "3.11"
simd: "avx2,f16c"
opencolorio_ver: v2.3.2
fmt_ver: 10.1.1
pybind11_ver: v2.10.0
pybind11_ver: v2.12.0
coverage: 1
# skip_tests: 1
sonar: 1
setenvs: export SONAR_SERVER_URL="https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR=/__w/OpenImageIO/OpenImageIO/bw_output
OIIO_CMAKE_BUILD_WRAPPER="build-wrapper-linux-x86-64 --out-dir /__w/OpenImageIO/OpenImageIO/bw_output"
CMAKE_BUILD_TYPE=Debug
OIIO_CMAKE_BUILD_TYPE=Debug
CMAKE_UNITY_BUILD=OFF
CODECOV=1
CTEST_TEST_TIMEOUT=1200
OIIO_CMAKE_FLAGS="-DOIIO_TEX_IMPLEMENT_VARYINGREF=OFF"
runs-on: ${{ matrix.os }}
container:
image: ${{ matrix.container }}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
USE_SIMD: ${{matrix.simd}}
FMT_VERSION: ${{matrix.fmt_ver}}
OPENEXR_VERSION: ${{matrix.openexr_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
# DEBUG_CI: 1
steps:
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
# on CI runs where we are producing artifacts that users might rely on.
# - name: Harden Runner
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
# with:
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: '0'
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "date=`date -u +'%Y-%m-%dT%H:%M:%SZ'`" >> $GITHUB_OUTPUT
- name: ccache
id: ccache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
with:
path: /tmp/ccache
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{github.job}}-
- name: Build setup
run: |
${{matrix.setenvs}}
src/build-scripts/ci-startup.bash
- name: Dependencies
run: |
${{matrix.depcmds}}
src/build-scripts/gh-installdeps.bash
- name: Install sonar-scanner and build-wrapper
if: matrix.sonar == '1'
uses: sonarsource/sonarcloud-github-c-cpp@e4882e1621ad2fb48dddfa48287411bed34789b1 # v2.0.2
- name: Build
run: src/build-scripts/ci-build.bash
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Code coverage
if: matrix.coverage == '1'
run: src/build-scripts/ci-coverage.bash
- name: Sonar-scanner
if: matrix.sonar == 1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
which sonar-scanner
ls -l /__w/OpenImageIO/OpenImageIO/bw_output
echo "BUILD_OUTPUT_DIR is " "${{ env.BUILD_WRAPPER_OUT_DIR }}"
find . -name "*.gcov" -print
# sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
time sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="$BUILD_WRAPPER_OUT_DIR" --define sonar.cfamily.gcov.reportsPath="_coverage" --define sonar.cfamily.threads="$PARALLEL"
# Consult https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-cli/ for more information and options
# - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
# if: failure()
# with:
# name: oiio-${{github.job}}-${{matrix.nametag}}
# path: |
# build/cmake-save
# build/testsuite/*/*.*
# !build/testsuite/oiio-images
# !build/testsuite/openexr-images
# !build/testsuite/fits-images
# !build/testsuite/j2kp4files_v1_5
+322
View File
@@ -0,0 +1,322 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
##########################################################################
# Common steps for all CI workflows
##########################################################################
name: CI Steps
on:
workflow_call:
# This inputs receive values via the "with:" section in ci_workflow.yml
inputs:
build:
type: string
runner:
type: string
container:
type: string
container_volumes:
type: string
default: '[]'
cc_compiler:
type: string
cxx_compiler:
type: string
cxx_std:
type: string
build_type:
type: string
depcmds:
type: string
extra_artifacts:
type: string
fmt_ver:
type: string
fmt_commit:
type: string
gcc_action_ver:
type: string
llvm_action_ver:
type: string
opencolorio_ver:
type: string
openexr_ver:
type: string
pybind11_ver:
type: string
python_action_ver:
type: string
python_ver:
type: string
setenvs:
type: string
simd:
type: string
skip_build:
type: string
skip_tests:
type: string
abi_check:
type: string
benchmark:
type: string
build_docs:
type: string
clang_format:
type: string
generator:
type: string
ctest_args:
type: string
ctest_test_timeout:
type: string
coverage:
type: string
sonar:
type: string
# Note: Remove old_node and everything that handles its being nonzero,
# when we branch for 3.2. We no longer have any CI jobs in main that
# need it, but we are not yet removing it, for the sake of not making
# this file diverge from the release branch quite yet, to make
# backporting CI fixes easy.
old_node:
type: string
default: 0
nametag:
type: string
required_deps:
type: string
optional_deps:
type: string
build_local_deps:
type: string
oiio_python_bindings_backend:
type: string
default: ''
secrets:
PASSED_GITHUB_TOKEN:
required: false
PASSED_SONAR_TOKEN:
required: false
permissions: read-all
jobs:
steps:
name: "${{inputs.cxx_compiler}} c++${{inputs.cxx_std}} py${{inputs.python_ver}}"
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
volumes: ${{ fromJson( inputs.container_volumes ) }}
options: -v /:/host/root ${{ (contains(inputs.runner, 'gpu') && '-e NVIDIA_DRIVER_CAPABILITIES=compute,graphics,utility --gpus all') || '-e A=x' }}
# Extra options:
# - Ensure the GPU runners have OptiX is visible in the container.
# - Mount the native filesystem under /host/root
env:
CXX: ${{inputs.cxx_compiler}}
CC: ${{inputs.cc_compiler}}
CMAKE_BUILD_TYPE: ${{inputs.build_type}}
CMAKE_CXX_STANDARD: ${{inputs.cxx_std}}
CMAKE_GENERATOR: ${{inputs.generator}}
CTEST_ARGS: ${{inputs.ctest_args}}
CTEST_TEST_TIMEOUT: ${{inputs.ctest_test_timeout}}
USE_SIMD: ${{inputs.simd}}
fmt_BUILD_VERSION: ${{inputs.fmt_ver}}
fmt_GIT_COMMIT: ${{inputs.fmt_commit}}
OPENCOLORIO_VERSION: ${{inputs.opencolorio_ver}}
OPENEXR_VERSION: ${{inputs.openexr_ver}}
PYBIND11_VERSION: ${{inputs.pybind11_ver}}
PYTHON_VERSION: ${{inputs.python_ver}}
ABI_CHECK: ${{inputs.abi_check}}
ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION: node16
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
# For CI, sometimes we want to require all dependencies to be present,
# except for a select few listed explicitly. This ensures that we don't
# accidentally have a situation in which we think we are building
# against and testing an optional dependency, but in fact are not.
OpenImageIO_REQUIRED_DEPS: ${{inputs.required_deps}}
OpenImageIO_OPTIONAL_DEPS: ${{inputs.optional_deps}}
OpenImageIO_BUILD_LOCAL_DEPS: ${{inputs.build_local_deps}}
SETENVS: ${{inputs.setenvs}}
DEPCMDS: ${{inputs.depcmds}}
OIIO_PYTHON_BINDINGS_BACKEND: ${{ inputs.oiio_python_bindings_backend }}
steps:
- name: install nodejs20glibc2.17
if: inputs.old_node == '1'
run: |
curl --silent https://unofficial-builds.nodejs.org/download/release/v20.18.1/node-v20.18.1-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217 -f -
- name: Checkout repo
if: inputs.old_node != '1'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Checkout repo-OLD
if: inputs.old_node == '1'
# Must use an old checkout action for old containers
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Build setup
shell: bash
run: |
eval "$SETENVS"
src/build-scripts/ci-startup.bash
- name: Prepare ccache timestamp
id: ccache_cache_keys
shell: bash
run: echo "date=`date -u +'%Y-%m-%dT%H:%M:%SZ'`" >> $GITHUB_OUTPUT
- name: ccache-restore
if: inputs.old_node != '1'
id: ccache-restore
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ${{ env.CCACHE_DIR }}
key: ${{inputs.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{inputs.nametag}}
- name: ccache-restore-OLD
if: inputs.old_node == '1'
id: ccache-restore-old
# Must use an old cache restore action for old containers
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.CCACHE_DIR }}
# path: ./ccache
key: ${{inputs.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{inputs.nametag}}
- name: Install gcc
if: inputs.gcc_action_ver != ''
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt-get update -y
sudo apt-get install -y g++-${{inputs.gcc_action_ver}}
- name: Install python
if: inputs.python_action_ver != ''
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ inputs.python_action_ver }}
- name: Install LLVM and Clang
if: inputs.llvm_action_ver != ''
uses: KyleMayes/install-llvm-action@ebc0426251bc40c7cd31162802432c68818ab8f0 # v2.0.9
with:
version: ${{ inputs.llvm_action_ver }}
- name: Dependencies
shell: bash
run: |
eval "$DEPCMDS"
if [[ "$RUNNER_OS" == "Linux" ]]; then
src/build-scripts/gh-installdeps.bash
elif [[ "$RUNNER_OS" == "macOS" ]]; then
src/build-scripts/install_homebrew_deps.bash
elif [[ "$RUNNER_OS" == "Windows" ]]; then
src/build-scripts/gh-win-installdeps.bash
fi
- name: Install sonar-scanner and build-wrapper
if: inputs.sonar == '1'
uses: sonarsource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 # v7.0.0
- name: Build
if: inputs.skip_build != '1'
shell: bash
run: src/build-scripts/ci-build.bash
- name: Check out ABI standard
if: inputs.abi_check != ''
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{inputs.abi_check}}
path: abi_standard
- name: Build ABI standard
if: inputs.abi_check != ''
shell: bash
run: |
mkdir -p abi_standard/build
pushd abi_standard
src/build-scripts/ci-build.bash
popd
- name: ccache-save
if: inputs.old_node != '1'
id: ccache-save
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ${{ env.CCACHE_DIR }}
key: ${{inputs.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
- name: ccache-save-OLD
if: inputs.old_node == '1'
id: ccache-save-old
# Must use an old cache action for old containers
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.CCACHE_DIR }}
key: ${{inputs.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
- name: Testsuite
if: inputs.skip_tests != '1'
shell: bash
run: src/build-scripts/ci-test.bash
- name: Benchmarks
if: inputs.benchmark == '1'
shell: bash
run: src/build-scripts/ci-benchmark.bash
- name: clang-format
if: inputs.clang_format == '1'
shell: bash
run: src/build-scripts/run-clang-format.bash
- name: Code coverage
if: inputs.coverage == '1'
run: src/build-scripts/ci-coverage.bash
- name: Sonar-scanner
if: inputs.sonar == '1'
env:
GITHUB_TOKEN: ${{ secrets.PASSED_GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.PASSED_SONAR_TOKEN }}
run: |
which sonar-scanner
ls -l /__w/OpenImageIO/OpenImageIO/bw_output
echo "BUILD_OUTPUT_DIR is ${BUILD_WRAPPER_OUT_DIR}"
find . -name "*.gcov" -print
# sonar-scanner --define sonar.cfamily.compile-commands="${BUILD_WRAPPER_OUT_DIR}/compile_commands.json"
time sonar-scanner --define sonar.host.url="${SONAR_SERVER_URL}" --define sonar.cfamily.compile-commands="$BUILD_WRAPPER_OUT_DIR/compile_commands.json" --define sonar.cfamily.gcov.reportsPath="_coverage" --define sonar.cfamily.threads="$PARALLEL"
# Consult https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-cli/ for more information and options
- name: Check ABI
if: inputs.abi_check != ''
shell: bash
run: |
src/build-scripts/ci-abicheck.bash ./build abi_standard/build libOpenImageIO libOpenImageIO_Util
- name: Build Docs
if: inputs.build_docs == '1'
shell: bash
run: |
cd src/doc
time make doxygen
time make sphinx
- name: Upload testsuite debugging artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: ${{ inputs.old_node != '1' && (failure() || inputs.build_docs == '1' || inputs.benchmark == '1' || inputs.abi_check != '') }}
with:
name: oiio-${{github.job}}-${{inputs.nametag}}
path: |
build/cmake-save
build/compat_reports
build/sphinx
build/benchmarks
build/testsuite/*/*.*
!build/testsuite/oiio-images
!build/testsuite/openexr-images
!build/testsuite/fits-images
!build/testsuite/j2kp4files_v1_5
${{ inputs.extra_artifacts }}
- name: Upload testsuite debugging artifacts-OLD
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ inputs.old_node == '1' && (failure() || inputs.build_docs == '1' || inputs.benchmark == '1' || inputs.abi_check != '') }}
with:
name: oiio-${{github.job}}-${{inputs.nametag}}
path: |
build/cmake-save
build/compat_reports
build/sphinx
build/benchmarks
build/testsuite/*/*.*
!build/testsuite/oiio-images
!build/testsuite/openexr-images
!build/testsuite/fits-images
!build/testsuite/j2kp4files_v1_5
${{ inputs.extra_artifacts }}
+641 -519
View File
File diff suppressed because it is too large Load Diff
+92
View File
@@ -0,0 +1,92 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
name: docs
on:
push:
# Skip jobs when only cpp files are changed. The materials for
# docs are all in md, rst, and .h files.
paths-ignore:
- '**/ci.yml'
- '**/analysis.yml'
- '**/scorecard.yml'
- '**/wheel.yml'
- '**.properties'
- 'src/**.cpp'
- '**.cmake'
- '**/CMakeLists.txt'
- '**/run.py'
- 'src/build-scripts/**'
- './*.md'
- 'pyproject.toml'
pull_request:
paths-ignore:
- '**/ci.yml'
- '**/analysis.yml'
- '**/scorecard.yml'
- '**/wheel.yml'
- '**.properties'
- 'src/**.cpp'
- '**.cmake'
- '**/CMakeLists.txt'
- '**/run.py'
- 'src/build-scripts/**'
- './*.md'
- 'pyproject.toml'
schedule:
# Full nightly build
- cron: "0 8 * * *"
workflow_dispatch:
# This allows manual triggering of the workflow from the web
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
docs:
name: "Docs / ${{matrix.desc}}"
if: ${{ github.event_name != 'schedule' || github.event.repository.fork == false }}
uses: ./.github/workflows/build-steps.yml
with:
nametag: ${{ matrix.nametag || 'unnamed!' }}
runner: ${{ matrix.runner || 'ubuntu-latest' }}
container: ${{ matrix.container }}
cc_compiler: ${{ matrix.cc_compiler }}
cxx_compiler: ${{ matrix.cxx_compiler }}
cxx_std: ${{ matrix.cxx_std || '17' }}
build_type: ${{ matrix.build_type || 'Release' }}
depcmds: ${{ matrix.depcmds }}
extra_artifacts: ${{ matrix.extra_artifacts }}
python_ver: ${{ matrix.python_ver }}
setenvs: ${{ matrix.setenvs }}
simd: ${{ matrix.simd }}
skip_build: ${{ matrix.skip_build }}
skip_tests: ${{ matrix.skip_tests }}
abi_check: ${{ matrix.abi_check }}
build_docs: ${{ matrix.build_docs }}
generator: ${{ matrix.generator }}
strategy:
fail-fast: false
matrix:
include:
- desc: docs
nametag: docslinux
runner: ubuntu-latest
cxx_std: 17
python_ver: "3.11"
build_docs: 1
skip_build: 1
skip_tests: 1
setenvs: export EXTRA_DEP_PACKAGES="doxygen sphinx-doc"
PIP_INSTALLS="sphinx breathe==4.34.0 sphinx-tabs furo==2022.6.21"
SKIP_SYSTEM_DEPS_INSTALL=1
USE_OPENCV=0 USE_FFMPEG=0 USE_FREETYPE=0
USE_LIBHEIF=0 QT_VERSION=0 PYBIND11_VERSION=0
+1 -1
View File
@@ -23,4 +23,4 @@ jobs:
slack_bot_token: ${{ secrets.SLACK_BOT_TOKEN }}
slack_channel: "#release-announcements"
project_logo: "https://artwork.aswf.io/projects/openimageio/icon/color/openimageio-icon-color.png"
uses: jmertic/slack-release-notifier@main
uses: jmertic/slack-release-notifier@35fad060af5559c24decdec0f701e6ba93566704 # circa Mar 2026
+67
View File
@@ -0,0 +1,67 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) Contributors to the OpenImageIO Project.
#
# Releases are signed via https://github.com/sigstore/sigstore-python.
# See https://docs.sigstore.dev for information about sigstore.
#
# This action creates a .tar.gz of the complete OpenImageIO source tree at
# the given release tag, signs it via sigstore, and uploads the
# .tar.gz and the associated .tar.gz.sigstore credential bundle.
#
# To verify a downloaded release at a given tag:
#
# % pip install sigstore
# % sigstore verify github --cert-identity https://github.com/AcademySoftwareFoundation/OpenImageIO/.github/workflows/release-sign.yml@refs/tags/<tag> OpenImageIO-<tag>.tar.gz
#
name: Sign Release
on:
release:
types: [published]
permissions:
contents: read
jobs:
release:
name: Sign & upload release artifacts
runs-on: ubuntu-latest
env:
TAG: ${{ github.ref_name }}
permissions:
contents: write
id-token: write
repository-projects: write
steps:
- name: Set Prefix
# The tag name begins with a 'v', e.g. "v3.0.3", but the prefix
# should omit the 'v', so the tarball "OpenImageIO-3.0.3.tar.gz"
# extracts files into "OpenImageIO-v3.0.3/...". This matches
# the GitHub release page autogenerated artifact conventions.
run: |
echo OPENIMAGEIO_PREFIX=OpenImageIO-${TAG//v}/ >> $GITHUB_ENV
echo OPENIMAGEIO_TARBALL=OpenImageIO-${TAG//v}.tar.gz >> $GITHUB_ENV
shell: bash
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create archive
run: git archive --format=tar.gz -o ${OPENIMAGEIO_TARBALL} --prefix ${OPENIMAGEIO_PREFIX} ${TAG}
- name: Sign archive with Sigstore
uses: sigstore/gh-action-sigstore-python@a5caf349bc536fbef3668a10ed7f5cd309a4b53d # v3.2.0
with:
inputs: ${{ env.OPENIMAGEIO_TARBALL }}
upload-signing-artifacts: false
release-signing-artifacts: false
- name: Upload release archive
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload ${TAG} ${OPENIMAGEIO_TARBALL} ${OPENIMAGEIO_TARBALL}.sigstore.json
+10 -11
View File
@@ -8,13 +8,12 @@ on:
# Only the default branch is supported.
branch_protection_rule:
push:
# Run on pushes to master, but only the main repo, not forks
branches: [ "master" ]
if: github.event.pull_request.head.repo.full_name == github.repository
# Run on pushes to main, but only the official repo, not forks
branches: [ "main" ]
pull_request:
# Only run on individual PRs if the workflow file itself is changed.
# Only run on individual PRs if the workflows changed
paths:
- .github/workflows/scorecard.yml
- '.github/workflows/**'
# Declare default permissions as read only.
permissions: read-all
@@ -28,7 +27,7 @@ concurrency:
jobs:
analysis:
name: Scorecards analysis
if: github.repository == 'AcademySoftwareFoundation/OpenImageIO'
if: github.event.repository.fork == false
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
@@ -40,13 +39,13 @@ jobs:
actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
@@ -65,7 +64,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif
@@ -73,6 +72,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
uses: github/codeql-action/upload-sarif@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
with:
sarif_file: results.sarif
+535
View File
@@ -0,0 +1,535 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright Contributors to the OpenImageIO Project.
#
# This workflow will run on under two independent conditions:
# 1) On the official AcademySoftwareFoundation repo, according to a nightly schedule.
# 2) On forks, when submitting a PR that modifies Python-related files.
name: Wheel
permissions:
contents: read
id-token: write
on:
push:
# Workflow run on tags for v3 only, or pre-tagged pushes of release, or
# dev-3.* branches. Also if the branch name itself contains the substrings
# 'wheel' or 'python'.
tags:
- v3.*
branches:
- release
- dev-3.*
- "*wheel*"
- "*python*"
pull_request:
# Workflow run on pull_request only when related files change, or when the
# branch name itself contains the substrings 'wheel' or 'python'.
paths:
- .github/workflows/wheel.yml
- pyproject.toml
- src/python/*.py
- src/python/*.h
- src/python/*.cpp
- src/cmake/*.cmake
schedule:
# Nightly build
- cron: "0 8 * * *"
workflow_dispatch:
# This allows manual triggering of the workflow from the web
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# Linux jobs run in Docker containers (manylinux), so the latest OS version
# is OK. macOS and Windows jobs need to be locked to specific virtual
# environment versions to mitigate issues from OS updates, and will require
# maintenance as OS versions are retired.
# ---------------------------------------------------------------------------
# Source Distribution
# ---------------------------------------------------------------------------
sdist:
name: Build SDist
runs-on: ubuntu-latest
if: |
github.event_name != 'schedule' || github.event.repository.fork == false
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Build SDist
run: pipx run build --sdist
- name: Check metadata
run: pipx run twine check dist/*
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-sdist
path: dist/*.tar.gz
# ---------------------------------------------------------------------------
# Linux Wheels
# ---------------------------------------------------------------------------
linux:
name: Build wheels on Linux
runs-on: ubuntu-latest
if: |
${{ github.event_name != 'schedule' || github.event.repository.fork == false }}
strategy:
fail-fast: false
matrix:
include:
# -------------------------------------------------------------------
# CPython 64 bits manylinux_2_28
# -------------------------------------------------------------------
- build: CPython 3.9 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp39-manylinux_x86_64
arch: x86_64
- build: CPython 3.10 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp310-manylinux_x86_64
arch: x86_64
- build: CPython 3.11 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp311-manylinux_x86_64
arch: x86_64
- build: CPython 3.12 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp312-manylinux_x86_64
arch: x86_64
- build: CPython 3.13 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp313-manylinux_x86_64
arch: x86_64
- build: CPython 3.14 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp314-manylinux_x86_64
arch: x86_64
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.9'
- name: ccache-restore
id: ccache-restore
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.manylinux}}-${{matrix.python}}
restore-keys: wheel-${{runner.os}}-${{matrix.manylinux}}-${{matrix.python}}
- name: Build wheels
# Note: the version of cibuildwheel should be kept in sync with src/python/stubs/CMakeLists.txt
uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0
env:
# pass GITHUB_ACTIONS through to the build container so that custom
# processes can tell they are running in CI.
CIBW_ENVIRONMENT_PASS_LINUX: GITHUB_ACTIONS
CIBW_BEFORE_ALL: "source src/build-scripts/build_ccache.bash && pwd && ext/dist/bin/ccache --max-size=200M && ext/dist/bin/ccache -sv && export CMAKE_C_COMPILER_LAUNCHER=/project/ext/dist/bin/ccache CMAKE_CXX_COMPILER_LAUNCHER=/project/ext/dist/bin/ccache"
CIBW_BEFORE_TEST: "ext/dist/bin/ccache -s"
CIBW_BUILD: ${{ matrix.python }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
CIBW_ENVIRONMENT: >
CCACHE_DIR=/host//home/runner/.ccache
CCACHE_COMPRESSION=yes
CCACHE_PREBUILT=1
CMAKE_BUILD_PARALLEL_LEVEL=4
CTEST_PARALLEL_LEVEL=4
SKBUILD_CMAKE_ARGS="-DLINKSTATIC=1"
SKBUILD_CMAKE_BUILD_TYPE="MinSizeRel"
SKBUILD_BUILD_DIR=/project/build
CXXFLAGS="-Wno-error=stringop-overflow -Wno-pragmas"
WebP_BUILD_VERSION="1.5.0"
WebP_GIT_COMMIT=a4d7a715337ded4451fec90ff8ce79728e04126c
# FIXME: Getting build problems when using WebP 1.6.0, so hold it back
# CMAKE_GENERATOR = "Ninja"
- name: ccache-save
id: ccache-save
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.manylinux}}-${{matrix.python}}
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-wheels-${{matrix.manylinux}}-${{ matrix.python }}-${{ matrix.manylinux }}
path: |
./wheelhouse/*.whl
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: stubs-${{ matrix.python }}-${{ matrix.manylinux }}
path: |
./wheelhouse/OpenImageIO/__init__.pyi
# if stub validation fails we want to upload the stubs for users to review.
# keep the python build in sync with the version specified in tool.cibuildwheel.overrides
# section of pyproject.toml
if: always() && contains(matrix.python, 'cp311-manylinux')
# ---------------------------------------------------------------------------
# Linux ARM Wheels
# ---------------------------------------------------------------------------
linux-arm:
name: Build wheels on Linux ARM
runs-on: ubuntu-24.04-arm
if: |
github.event_name != 'schedule' || github.event.repository.fork == false
strategy:
matrix:
include:
# -------------------------------------------------------------------
# CPython ARM 64 bits manylinux2014
# -------------------------------------------------------------------
- build: CPython 3.9 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp39-manylinux_aarch64
arch: aarch64
- build: CPython 3.10 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp310-manylinux_aarch64
arch: aarch64
- build: CPython 3.11 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp311-manylinux_aarch64
arch: aarch64
- build: CPython 3.12 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp312-manylinux_aarch64
arch: aarch64
- build: CPython 3.13 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp313-manylinux_aarch64
arch: aarch64
- build: CPython 3.14 ARM 64 bits manylinux_2_28
manylinux: manylinux_2_28
python: cp314-manylinux_aarch64
arch: aarch64
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.9'
- name: ccache-restore
id: ccache-restore
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
restore-keys: wheel-${{runner.os}}-${{matrix.python}}
- name: Build wheels
uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0
env:
CIBW_ENVIRONMENT_PASS_LINUX: GITHUB_ACTIONS
CIBW_BEFORE_ALL: "source src/build-scripts/build_ccache.bash && pwd && /project/ext/dist/bin/ccache --max-size=200M && /project/ext/dist/bin/ccache -sv && export CMAKE_C_COMPILER_LAUNCHER=/project/ext/dist/bin/ccache CMAKE_CXX_COMPILER_LAUNCHER=/project/ext/dist/bin/ccache"
CIBW_BEFORE_TEST: "ext/dist/bin/ccache -s"
CIBW_BUILD: ${{ matrix.python }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux }}
CIBW_ENVIRONMENT: >
CCACHE_DIR=/host//home/runner/.ccache
CCACHE_COMPRESSION=yes
CCACHE_PREBUILT=0
CMAKE_BUILD_PARALLEL_LEVEL=6
CTEST_PARALLEL_LEVEL=6
SKBUILD_CMAKE_ARGS="-DLINKSTATIC=1"
SKBUILD_CMAKE_BUILD_TYPE="MinSizeRel"
SKBUILD_BUILD_DIR=/project/build
CXXFLAGS="-Wno-error=stringop-overflow -Wno-pragmas"
WebP_BUILD_VERSION="1.5.0"
WebP_GIT_COMMIT=a4d7a715337ded4451fec90ff8ce79728e04126c
- name: ccache-save
id: ccache-save
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-wheels-${{ matrix.python }}-${{ matrix.manylinux }}
path: |
./wheelhouse/*.whl
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: stubs-${{ matrix.python }}-${{ matrix.manylinux }}
path: |
./wheelhouse/OpenImageIO/__init__.pyi
# if stub validation fails we want to upload the stubs for users to review.
# keep the python build in sync with the version specified in tool.cibuildwheel.overrides
# section of pyproject.toml
if: always() && contains(matrix.python, 'cp311-manylinux')
# ---------------------------------------------------------------------------
# macOS Wheels
# ---------------------------------------------------------------------------
macos:
name: Build wheels on macOS
runs-on: macos-15-intel
if: |
github.event_name != 'schedule' || github.event.repository.fork == false
strategy:
fail-fast: false
matrix:
include:
# -------------------------------------------------------------------
# CPython 64 bits
# -------------------------------------------------------------------
- build: CPython 3.9 64 bits
python: cp39-macosx_x86_64
arch: x86_64
- build: CPython 3.10 64 bits
python: cp310-macosx_x86_64
arch: x86_64
- build: CPython 3.11 64 bits
python: cp311-macosx_x86_64
arch: x86_64
- build: CPython 3.12 64 bits
python: cp312-macosx_x86_64
arch: x86_64
- build: CPython 3.13 64 bits
python: cp313-macosx_x86_64
arch: x86_64
- build: CPython 3.14 64 bits
python: cp314-macosx_x86_64
arch: x86_64
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.9'
- name: ccache-restore
id: ccache-restore
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
restore-keys: wheel-${{runner.os}}-${{matrix.python}}
- name: Install build tools
run: |
brew install ninja ccache || true
- name: Brew uninstall problematic dependencies
run: |
brew uninstall -f --ignore-dependencies openexr imath expat cmake || true
- name: Build wheels
uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0
env:
CIBW_BUILD: ${{ matrix.python }}
CIBW_ARCHS: ${{ matrix.arch }}
MACOSX_DEPLOYMENT_TARGET: 10.15
CMAKE_GENERATOR: "Unix Makefiles"
# TODO: Re-enable HEIF when we provide a build recipe that does
# not include GPL-licensed dynamic libraries.
USE_Libheif: 'OFF'
CMAKE_BUILD_PARALLEL_LEVEL: 6
CTEST_PARALLEL_LEVEL: 6
SKBUILD_BUILD_DIR: "/Users/runner/work/OpenImageIO/OpenImageIO/build"
CCACHE_DIR: /Users/runner/.ccache
CCACHE_COMPRESSION: yes
- name: ccache-save
id: ccache-save
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-wheels-${{ matrix.python }}
path: ./wheelhouse/*.whl
# ---------------------------------------------------------------------------
# macOS ARM Wheels
# ---------------------------------------------------------------------------
macos-arm:
name: Build wheels on macOS ARM
runs-on: macos-14
if: |
github.event_name != 'schedule' || github.event.repository.fork == false
strategy:
fail-fast: false
matrix:
include:
# -------------------------------------------------------------------
# CPython ARM 64 bits
# -------------------------------------------------------------------
- build: CPython 3.9 ARM 64 bits
python: cp39-macosx_arm64
arch: arm64
- build: CPython 3.10 ARM 64 bits
python: cp310-macosx_arm64
arch: arm64
- build: CPython 3.11 ARM 64 bits
python: cp311-macosx_arm64
arch: arm64
- build: CPython 3.12 ARM 64 bits
python: cp312-macosx_arm64
arch: arm64
- build: CPython 3.13 ARM 64 bits
python: cp313-macosx_arm64
arch: arm64
- build: CPython 3.14 ARM 64 bits
python: cp314-macosx_arm64
arch: arm64
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.9'
- name: ccache-restore
id: ccache-restore
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
restore-keys: wheel-${{runner.os}}-${{matrix.python}}
- name: Install build tools
run: |
brew install ninja ccache || true
- name: Build wheels
uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0
env:
CIBW_BUILD: ${{ matrix.python }}
CIBW_ARCHS: ${{ matrix.arch }}
CMAKE_GENERATOR: "Unix Makefiles"
CMAKE_BUILD_PARALLEL_LEVEL: 6
CTEST_PARALLEL_LEVEL: 6
SKBUILD_BUILD_DIR: "/Users/runner/work/OpenImageIO/OpenImageIO/build"
CCACHE_DIR: /Users/runner/.ccache
CCACHE_COMPRESSION: yes
- name: ccache-save
id: ccache-save
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.ccache
key: wheel-${{runner.os}}-${{matrix.python}}
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-wheels-${{ matrix.python }}
path: ./wheelhouse/*.whl
# ---------------------------------------------------------------------------
# Windows Wheels
# ---------------------------------------------------------------------------
windows:
name: Build wheels on Windows
runs-on: windows-2022
if: |
github.event_name != 'schedule' || github.event.repository.fork == false
strategy:
fail-fast: false
matrix:
include:
# -------------------------------------------------------------------
# CPython 64 bits
# -------------------------------------------------------------------
- build: CPython 3.9 64 bits
python: cp39-win_amd64
arch: AMD64
- build: CPython 3.10 64 bits
python: cp310-win_amd64
arch: AMD64
- build: CPython 3.11 64 bits
python: cp311-win_amd64
arch: AMD64
- build: CPython 3.12 64 bits
python: cp312-win_amd64
arch: AMD64
- build: CPython 3.13 64 bits
python: cp313-win_amd64
arch: AMD64
- build: CPython 3.14 64 bits
python: cp314-win_amd64
arch: AMD64
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.9'
- name: Build wheels
uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0
env:
CIBW_BUILD: ${{ matrix.python }}
CIBW_ARCHS: ${{ matrix.arch }}
CMAKE_POLICY_VERSION_MINIMUM: 3.5
CMAKE_BUILD_PARALLEL_LEVEL: 4
CTEST_PARALLEL_LEVEL: 4
SKBUILD_BUILD_DIR: "$HOME/OpenImageIO/OpenImageIO/build"
CCACHE_DIR: ~/.ccache
CCACHE_COMPRESSION: yes
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: cibw-wheels-${{ matrix.python }}
path: ./wheelhouse/*.whl
upload_pypi:
needs: [sdist, linux, linux-arm, macos, macos-arm, windows]
runs-on: ubuntu-latest
permissions:
id-token: write
if: github.event_name == 'push' && (startsWith(github.event.ref, 'refs/tags/v3.0.') || startsWith(github.event.ref, 'refs/tags/v3.1.')) && github.event.repository.fork == false
steps:
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
pattern: cibw-*
path: dist
merge-multiple: true
- uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
+17 -1
View File
@@ -4,13 +4,19 @@ branches/
build/
dist/
ext/
wheelhouse/
_coverage/
.python-version
.idea
.vs
.vscode
.cache
.cproject
.project
.DS_Store
*.pyc
_coverage/
/*.lock
gastest.o
# Exclude test files I tend to leave around at the top level. The leading
# slash ensures that files with these extensions within subdirectories are not
@@ -18,6 +24,16 @@ _coverage/
/*.exr
/*.tif
/*.jpg
/*.png
/*.jxl
/*.tx
/*.log
# AI coding tool directories — generated locally by .agents/setup-agent
.claude/
.codex/
.cursor/
.opencode/
.github/copilot-instructions.md
+182
View File
@@ -0,0 +1,182 @@
# OpenImageIO Agent Guide
This file provides guidance to coding assistants when working with code in
this repository.
## Project Overview
OpenImageIO (OIIO) is a C++17 library and toolset for reading, writing, and
manipulating image files across many formats, designed for VFX/animation/film
production. Part of the Academy Software Foundation (ASWF). Canonical repo:
http://github.com/AcademySoftwareFoundation/OpenImageIO
**Core libraries:**
- `libOpenImageIO` — Main library: ImageInput/ImageOutput (file I/O), ImageBuf/ImageBufAlgo (image processing), ImageCache/TextureSystem (texture mapping)
- `libOpenImageIO_Util` — Utility library (string_view, ustring, span, threading, filesystem, etc.)
**Command line tools**
- `oiiotool`: general image processing CLI
- `iinfo`: print info & metadata for an image file
- `iconvert`: simple format conversion
- `maketx`: convert images to tiled and MIP-mapped textures.
- `iv`: image viewer
## Repo map
- `src/include/OpenImageIO/` : Public API headers
- `src/libOpenImageIO/` : Core library (ImageBuf, ImageBufAlgo,
ImageInput/ImageOutput base classes)
- `src/libtexture/` : ImageCache, TextureSystem
- `src/libutil/` : Utility class implementations
- `src/<FORMAT>.imageio/` : Per-format ImageInput/ImageOutput plugins.
- `src/python/` : Python bindings using pybind11
- `src/<TOOL>` : CLI tools (oiiotool, iinfo, iconvert, maketx, iv)
- `testsuite/` : End-to-end/regression tests + reference outputs
- `src/cmake/`, `CMakeLists.txt` : Build system
- `.github/workflows/ci.yml` : GitHub Actions CI
- `src/build-scripts` Helper scripts used for build & CI
- `src/doc/` : User manual source (+ Doxygen comments in the public headers)
- `docs/dev/` : Developer documentation
- `docs/dev/Architecture.md` : Major subsystems overview
## Build and verification
Common build commands via the Makefile convenience wrapper:
```bash
make # configure, build, install (Release)
make debug # debug build
make clean # wipe build dir (needed when switching branches/modes)
make clang-format # format all source files
make test # full testsuite
make test TEST=<pattern> # subset matching regex
```
Or directly with cmake:
```bash
cmake -B build -S .
cmake --build build --target install
ctest --test-dir build -R <pattern> --output-on-failure
```
By default, builds into `./build` and installs into `./dist`.
## Testsuite notes
- Test output lands in `build/testsuite/<testname>/`; references in
`testsuite/<testname>/ref/`
- Read `testsuite/TESTSUITE-README.md` before updating references or
diagnosing failures
- For platform-specific diffs, add a variant ref (e.g. `out-win.txt`) rather
than overwriting
- Be conservative loosening image diff thresholds — use the minimum needed
- Check uploaded CI artifacts before changing references when local
reproduction is unclear
## Code formatting and file conventions
- `clang-format` enforced (`.clang-format`); CI rejects non-conforming code —
run `make clang-format` before committing
- Lines ~80 cols; ASCII only in code and comments; `#pragma once` for headers
- New files: standard copyright + SPDX notice
- `CamelCase` classes, `snake_case` locals, `ALL_CAPS` macros, `m_foo` private
members
- 3 blank lines between free functions/classes; 1 between class methods; max 1
blank line inside a function body
- `//` for regular comments; `///` Doxygen for public API
- If a file has a strong local style, imitate that.
## C++ guidelines
- Error handling: prefer `bool` returns, explicit status propagation, and
`errorfmt()`-style reporting — not exceptions — consistent with the
surrounding subsystem
- Preserve API, ABI, and behavior compatibility unless the task explicitly
requires a break
- For hot paths: no hidden allocation in inner loops or parallel regions;
precompute outside hot paths
- For kernel-style image work, use existing `ImageBufAlgo` and
`parallel_image` patterns before inventing a new execution model
## OIIO utility types (prefer over raw C++ equivalents)
Prefer C++17 `std` and Imath types except as noted below. Avoid introducing
new third-party dependencies without a strong reason.
- `OIIO::string_view` — non-owning string/`char*` (like `std::string_view`)
- `OIIO::span` / `OIIO::cspan` — non-owning contiguous data (like
`std::span`); use instead of pointer+length pairs
- `OIIO::image_span` — describes pixel buffer memory layout (pointer, sizes,
strides)
- `OIIO::Filesystem::*` — file/directory utilities (`filesystem.h`)
- `strutil.h` : string processing utilities
- `Strutil::format()` / `Strutil::print()` (= `OIIO::print()`) — string
formatting/output; **never** `printf` or `<<` streams
- `fmath.h` — fast/safe math, avoids NaN/Inf
- `simd.h` — SIMD helpers
- `unittest.h` — unit test macros
## Safe programming in C++
- Try to avoid passing raw pointers as function arguments.
- Use `std::unique_ptr` and `std::shared_ptr` rather than raw ownership when
new ownership must be expressed, but do not churn existing code just to
"modernize" it.
- Prefer `OIIO::string_view` when passing non-mutable strings or C-style
`char*` strings.
- Prefer `OIIO::span` rather than passing raw pointers + a separate length, or
passing a raw pointer with an implied (but not explicitly passed) length.
`OIIO::cspan` is a synonmym when the underlying data is const/non-mutable.
`OIIO::span<std::byte>` or `OIIO::cspan<std::byte>` can be used to represent
contiguous untyped data. These are our equivalent of C++ `std::span`.
- Prefer `OIIO::image_span` to describe the memory layout of multi-dimensional
pixel buffers (such as are used to describe where to read or write image
pixels), rather than passing raw pointers, sizes, and strides.
## Performance and determinism
- For hot image-processing code, avoid hidden allocation in inner loops or
parallel regions.
- Precompute setup work outside hot paths when practical.
- Keep data flow and ownership explicit.
- Preserve deterministic results where practical.
- Avoid unnecessary global state or synchronization.
- For kernel-style work, look for existing `ImageBufAlgo` and
`parallel_image` patterns before inventing a new execution model.
- Prefer incremental performance fixes backed by measurement or concrete
reasoning over speculative rewrites.
## Change impact checklist
- Bug fixes and behavior changes → add/update tests
- Public API changes → update Python bindings, docs, `CHANGES.md`
- `ImageBufAlgo` changes → consider oiiotool exposure, docs, Python, tests
- Format plugin changes → regression coverage for metadata, edge cases,
read/write
- CLI changes → update tests and help text
- Build/dependency changes → check CMake logic, CI, optional-feature coverage
## Commits and PRs
- Keep PRs narrow and easy to review.
- Prefix format: `type(subsystem): message` — subsystem is optional but helpful.
- Valid types: `fix:`, `feat:`, `perf:`, `api:`, `int:`, `build:`, `test:`,
`ci:`, `docs:`, `refactor:`, `style:`, `admin:`, `revert:`.
- Add a subsystem tag when it helps, e.g. `fix(exr):` or `perf(IBA):`.
- Write commit messages and PR descriptions that explain why the change is
needed, what behavior changes, and any non-obvious implementation choices.
## AI policy
Refer to `docs/dev/AI_Policy.md`.
See `docs/dev/AI_Policy.md`. Key rule: if AI assistance contributed materially
to a patch, the commit must include `Assisted-by: <TOOL> / <MODEL>`. The human
author is responsible for understanding, testing, and defending all changes.
## References
- `CONTRIBUTING.md` : general contribution guidelines and recap of coding
conventions.
-21
View File
@@ -1,21 +0,0 @@
OpenImageIO has been accepted to be an ASWF-administered project, by vote of
the ASWF Technical Advisory Council (TAC) on May 3, 2023.
At this time, the ASWF subdirectory contains *proposed* (and sometimes TBD/WIP
placeholders) project organization and policy documents that will be formally
adopted as the OpenImageIO project is formally turned over to ASWF and moved
to the AcademySoftwareFoundation GitHub account. Please file issues or PRs
or review comments against these documents to make any suggested changes while
we are revising the drafts.
Summary of the current state of documents:
| File | Status | Notes |
| ---- | ------ | ----- |
| CLA-corporate.md | Final | Standard ASWF corporate CLA, approved by the TSC. Will take effect when the repo moves. |
| CLA-individual.md | Final | Standard ASWF individual CLA, approved by the TSC. Will take effect when the repo moves. |
| CODE_OF_CONDUCT.md | Final | Links to the standard LF CoC, approved by the TSC and now in effect. |
| CONTRIBUTING.md | Preliminary | Modified version of our existing CONTRIBUTING guidelines, lightly amended to reflect the changes that will come along with moving the repo, the new CLA/DCO rules, etc.
| GOVERNANCE.md | Final | Approved by the TSC and now in effect. |
| project_intake.md | Ongoing | This is the latest ASWF project intake checklist. We will check off items as we get them done. |
| Technical-Charter.md | Final | Approved by the TSC. |
-242
View File
@@ -1,242 +0,0 @@
# Technical Charter (the "Charter") for OpenImageIO a Series of LF Projects, LLC
Adopted July 1, 2023 by unanimous vote of the TSC.
This Charter sets forth the responsibilities and procedures for technical
contribution to, and oversight of, the OpenImageIO open source project, which
has been established as OpenImageIO a Series of LF Projects, LLC (the
“Project”). LF Projects, LLC (“LF Projects”) is a Delaware series limited
liability company. All contributors (including committers, maintainers, and
other technical positions) and other participants in the Project
(collectively, “Collaborators”) must comply with the terms of this Charter.
### 1. Mission and Scope of the Project
* **a.** The mission of the Project is to develop software to read, write,
and manipulate image files of any image file format relevant to vfx /
animation via a format-agnostic API, with a feature set, scalability, and
robustness needed for production.
* **b.** The scope of the Project includes collaborative development under
the Project License (as defined herein) supporting the mission, including
documentation, testing, integration and the creation of other artifacts
that aid the development, deployment, operation or adoption of the open
source project.
### 2. Technical Steering Committee
* **a.** The Technical Steering Committee (the “TSC”) will be responsible
for all technical oversight of the open source Project.
* **b.** The TSC voting members are initially the Project’s Committers. At
the inception of the project, the Committers of the Project will be as set
forth within the “GOVERNANCE” file within the Project’s code repository.
The TSC may choose an alternative approach for determining the voting
members of the TSC, and any such alternative approach will be documented
in the GOVERNANCE file. Any meetings of the Technical Steering Committee
are intended to be open to the public, and can be conducted
electronically, via teleconference, or in person.
* **c.** TSC projects generally will involve Contributors and Committers.
The TSC may adopt or modify roles so long as the roles are documented in
the GOVERNANCE file. Unless otherwise documented:
- **i.** Contributors include anyone in the technical community that
contributes code, documentation, or other technical artifacts to the
Project;
- **ii.** Committers are Contributors who have earned the ability to
modify (“commit”) source code, documentation or other technical
artifacts in a project’s repository; and
- **iii.** A Contributor may become a Committer by a majority approval of
the existing Committers. A Committer may be removed by a majority
approval of the other existing Committers.
* **d.** Participation in the Project through becoming a Contributor and
Committer is open to anyone so long as they abide by the terms of this
Charter.
* **e.** The TSC may (1) establish work flow procedures for the submission,
approval, and closure/archiving of projects, (2) set requirements for the
promotion of Contributors to Committer status, as applicable, and (3)
amend, adjust, refine and/or eliminate the roles of Contributors, and
Committers, and create new roles, and publicly document any TSC roles, as
it sees fit.
* **f.** The TSC may elect a TSC Chair, who will preside over meetings of
the TSC and will serve until their resignation or replacement by the TSC.
The TSC Chair, or any other TSC member so designated by the TSC, will
serve as the primary communication contact between the Project and the
Academy Software Foundation, a directed fund of The Linux Foundation.
* **g.** Responsibilities: The TSC will be responsible for all aspects of
oversight relating to the Project, which may include:
- **i.** coordinating the technical direction of the Project;
- **ii.** approving project or system proposals (including, but not
limited to, incubation, deprecation, and changes to a sub-project’s
scope);
- **iii.** organizing sub-projects and removing sub-projects;
- **iv.** creating sub-committees or working groups to focus on
cross-project technical issues and requirements;
- **v.** appointing representatives to work with other open source or open
standards communities;
- **vi.** establishing community norms, workflows, issuing releases, and
security issue reporting policies;
- **vii.** approving and implementing policies and processes for
contributing (to be published in the CONTRIBUTING file) and coordinating
with the series manager of the Project (as provided for in the Series
Agreement, the “Series Manager”) to resolve matters or concerns that may
arise as set forth in Section 7 of this Charter;
- **viii.** discussions, seeking consensus, and where necessary, voting on
technical matters relating to the code base that affect multiple
projects; and
- **ix.** coordinating any marketing, events, or communications regarding
the Project.
### 3. TSC Voting
* **a.** While the Project aims to operate as a consensus-based community,
if any TSC decision requires a vote to move the Project forward, the
voting members of the TSC will vote on a one vote per voting member basis.
* **b.** Quorum for TSC meetings requires at least fifty percent of all
voting members of the TSC to be present. The TSC may continue to meet if
quorum is not met but will be prevented from making any decisions at the
meeting.
* **c.** Except as provided in Section 7.c. and 8.a, decisions by vote at a
meeting require a majority vote of those in attendance, provided quorum is
met. Decisions made by electronic vote without a meeting require a
majority vote of all voting members of the TSC.
* **d.** In the event a vote cannot be resolved by the TSC, any voting
member of the TSC may refer the matter to the Series Manager for
assistance in reaching a resolution.
### 4. Compliance with Policies
* **a.** This Charter is subject to the Series Agreement for the Project and
the Operating Agreement of LF Projects. Contributors will comply with the
policies of LF Projects as may be adopted and amended by LF Projects,
including, without limitation the policies listed at
https://lfprojects.org/policies/.
* **b.** The TSC may adopt a code of conduct (“CoC”) for the Project, which
is subject to approval by the Series Manager. In the event that a
Project-specific CoC has not been approved, the LF Projects Code of
Conduct listed at https://lfprojects.org/policies will apply for all
Collaborators in the Project.
* **c.** When amending or adopting any policy applicable to the Project, LF
Projects will publish such policy, as to be amended or adopted, on its web
site at least 30 days prior to such policy taking effect; provided,
however, that in the case of any amendment of the Trademark Policy or
Terms of Use of LF Projects, any such amendment is effective upon
publication on LF Project’s web site.
* **d.** All Collaborators must allow open participation from any individual
or organization meeting the requirements for contributing under this
Charter and any policies adopted for all Collaborators by the TSC,
regardless of competitive interests. Put another way, the Project
community must not seek to exclude any participant based on any criteria,
requirement, or reason other than those that are reasonable and applied on
a non-discriminatory basis to all Collaborators in the Project community.
* **e.** The Project will operate in a transparent, open, collaborative, and
ethical manner at all times. The output of all Project discussions,
proposals, timelines, decisions, and status should be made open and easily
visible to all. Any potential violations of this requirement should be
reported immediately to the Series Manager.
### 5. Community Assets
* **a.** LF Projects will hold title to all trade or service marks used by
the Project (“Project Trademarks”), whether based on common law or
registered rights. Project Trademarks will be transferred and assigned to
LF Projects to hold on behalf of the Project. Any use of any Project
Trademarks by Collaborators in the Project will be in accordance with the
license from LF Projects and inure to the benefit of LF Projects.
* **b.** The Project will, as permitted and in accordance with such license
from LF Projects, develop and own all Project GitHub and social media
accounts, and domain name registrations created by the Project community.
* **c.** Under no circumstances will LF Projects be expected or required to
undertake any action on behalf of the Project that is inconsistent with
the tax-exempt status or purpose, as applicable, of the Joint Development
Foundation or LF Projects, LLC.
### 6. General Rules and Operations.
* **a.**. The Project will:
- **i.** engage in the work of the Project in a professional manner
consistent with maintaining a cohesive community, while also maintaining
the goodwill and esteem of LF Projects, Joint Development Foundation and
other partner organizations in the open source community; and
- **ii.** respect the rights of all trademark owners, including any
branding and trademark usage guidelines.
### 7. Intellectual Property Policy
* **a.** Collaborators acknowledge that the copyright in all new
contributions will be retained by the copyright holder as independent
works of authorship and that no contributor or copyright holder will be
required to assign copyrights to the Project.
* **a.** Except as described in Section 7.c., all contributions to the
Project are subject to the following:
- **i.** All new inbound code contributions to the Project must be made
using the Apache License, Version 2.0 available at
http://www.apache.org/licenses/LICENSE-2.0 (the “Project License”).
- **ii.** All new inbound code contributions must also be accompanied by
(i) a Developer Certificate of Origin (http://developercertificate.org)
sign-off in the source code system that is submitted through a
TSC-approved contribution process which will bind the authorized
contributor and, if not self-employed, their employer to the applicable
license and (ii) a duly executed contribution license agreement in the
form approved by the TSC;
- **iii.** All outbound code will be made available under the Project
License.
- **iv.** Documentation will be received and made available by the Project
under the Creative Commons Attribution 4.0 International License
(available at http://creativecommons.org/licenses/by/4.0/).
- **v.** The Project may seek to integrate and contribute back to other
open source projects (“Upstream Projects”). In such cases, the Project
will conform to all license requirements of the Upstream Projects,
including dependencies, leveraged by the Project. Upstream Project code
contributions not stored within the Project’s main code repository will
comply with the contribution process and license terms for the
applicable Upstream Project.
* **c.** The TSC may approve the use of an alternative license or licenses
for inbound or outbound contributions on an exception basis. To request an
exception, please describe the contribution, the alternative open source
license(s), and the justification for using an alternative open source
license for the Project. License exceptions must be approved by a
two-thirds vote of the entire TSC.
* **d.** Contributed files should contain license information, such as SPDX
short form identifiers, indicating the open source license or licenses
pertaining to the file.
### 8. Amendments
* **a.** This charter may be amended by a two-thirds vote of the entire TSC
and is subject to approval by LF Projects.
-66
View File
@@ -1,66 +0,0 @@
# Project Intake checklist
This is a checklist for TSC's to review as part of the intake process. The TSC should review this entire list during the kickoff meeting. For anything outstanding, create an [issue](../issues) to track and link to it in the list
- Existing Project Governance
- [X] A [LICENSE.md](../LICENSE.md) file in every code repository, with the license chosen an OSI-approved license.
- [X] Any third-party components/dependencies included are listed along with thier licenses ( [THIRD-PARTY.md](../THIRD-PARTY.md) )
- [X] A [README.md](../README.md) file welcoming new community members to the project and explaining why the project is useful and how to get started.
- [X] A [CONTRIBUTING.md](../CONTRIBUTING.md) file explaining to other developers and your community of users how to contribute to the project. The file should explain what types of contributions are needed and how the process works, along with how to disclose security issues responsibly ( may also point to a [SECURITY.md](../SECURITY.md) file ).
- [ ] A [CODEOWNERS](../CODEOWNERS) or [COMMITTERS](../COMMITERS.csv) file to define individuals or teams that are responsible for code in a repository; document current project owners and current and emeritus committers.
- [X] A [CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md) file that sets the ground rules for participants’ behavior associated and helps to facilitate a friendly, welcoming environment. By default, projects should leverage the Linux Foundation Code of Conduct unless an alternate Code of Conduct was previously approved.
- [X] A [RELEASING.md](../RELEASING.md) file that provides documentation on the release methodology, cadence, criteria, etc.
- [X] A [GOVERNANCE.md](../GOVERNANCE.md) file that documents the project’s technical governance.
- [ ] A [SUPPORT.md](../SUPPORT.md) file to let users and developers know about ways to get help with your project.
- Infrastructure/Assets
- [X] Technical Charter Approved
- [X] License scan completed and no issues found
- [X] Code repository imported to ASWF GitHub organization or ownership of current GitHub organization given to `thelinuxfoundation` user
- [X] Developer Certificate of Origin past commit signoff done and DCO Probot enabled.
- [X] Issue/feature tracker established (JIRA, GitHub issues)
- [X] Mailing lists ( one of )
- [X] Setup new lists ( -dev@ and -tsc@ ) on [ASWF groups.io](https://lists.aswf.io) ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to setup )
- [X] (In progress) Move to [ASWF groups.io](https://lists.aswf.io) ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to transfer )
- [X] Slack ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to setup project channel on [ASWF Slack](https://slack.aswf.io) )
- [ ] Website
- [X] CI/build environment
- [X] Trademarks/mark ownership rights ( complete 'LF Projects - Form of Trademark and Account Assignment' - create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) - only needed if project using existing name )
- [X] Domain name ( create [issue with the LF IT staff](https://jira.linuxfoundation.org/plugins/servlet/theme/portal/2/group/19) to setup/transfer )
- [X] Zoom account access ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to get access to credentials )
- [X] (N/A) Social media accounts or other project accounts ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to transfer )
- [X] Logo(s) ( create [issue on artwork repo](https://github.com/AcademySoftwareFoundation/artwork/issues/new) to add in SVG and PNG format and color/black/white )
- New Project Governance
- [X] TSC members identified
- [X] First TSC meeting held
- [X] TSC meeting cadence set and added to project calendar
- [X] CLA Approved ( if used ) ( [CCLA](CLA-corporate.md) and [ICLA](CLA-individual.md) )
- Project charter ( [Technical-Charter.md](Technical-Charter.md) )
- [X] Approved by TSC
- [X] Filed ( create pull request against [foundation repo](https://github.com/AcademySoftwareFoundation/foundation) )
- [X] [Core Infrastructure Initiative Best Practices Badge](https://bestpractices.coreinfrastructure.org/) achieved as the 'Passing' level.
- Outreach
- [ ] New project announcement done ( create [issue on foundation repo](https://github.com/AcademySoftwareFoundation/foundation/issues/new) to trigger )
- [X] Project added to ASWF website and ASWF landscape
- Incubation Stage requirements
- [X] Have achieved and maintained a [OpenSSF Best Practices Badge at the passing level](https://bestpractices.coreinfrastructure.org/en/criteria).
- [X] Have had a successful license scan with any critical issues remedied.
- [X] Have a defined project mission and scope
- [ ] An overview of the project’s architecture and features defined.
- [ ] A project roadmap defined, which should address the following questions.
- What use cases are possible now?
- What does the next year look like in terms of additional features and use cases covered?
- [ ] Community and contributor growth assessment
- The current number of contributors and committers, and the number of different organizations contributing to the project.
- Demonstrate a sustained flow of commits / merged contributions
- A credible plan for developing a thriving user community, in particular expanding the number of committers and contributors?
- Outline of the plan for the project to complete the requirements for Adopted Stage
- [X] Obtain an affirmative vote of the TAC.
- Adopted Stage graduation requirements
- [ ] Demonstrate a substantial ongoing flow of commits and merged contributions, authored by a healthy number of diverse contributors.
- [ ] Demonstrable roadmap progress.
- [ ] A healthy number of public adopters that are identified within the project ( using an ADOPTERS file or showcased on the project’s website ).
- [ ] Have achieved and maintained an [OpenSSF Best Practices Badge at the gold level](https://bestpractices.coreinfrastructure.org/en/criteria/2).
- [ ] Have a technical lead appointed for voting representation of the project to the TAC.
- [ ] Be deemed by the TAC to add value to the mission of ASWF.
- [ ] 2/3 supermajority vote of the TAC
- [ ] Affirmative majority vote of the Governing Board
+1578 -5049
View File
File diff suppressed because it is too large Load Diff
+140 -65
View File
@@ -1,10 +1,10 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause and Apache-2.0
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
cmake_minimum_required (VERSION 3.15)
cmake_minimum_required (VERSION 3.18.2...4.0)
set (OpenImageIO_VERSION "2.6.1.0")
set (OpenImageIO_VERSION "3.2.0.2")
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)
@@ -24,7 +24,7 @@ set (PROJECT_VERSION_RELEASE_TYPE "dev" CACHE STRING
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
set (PROJECT_AUTHORS "Contributors to the OpenImageIO project")
option (${PROJECT_NAME}_SUPPORTED_RELEASE
"Set ON for supported release branch, OFF for master" OFF)
"Set ON for supported release branches, OFF for 'main'" OFF)
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
set (${PROJECT_NAME}_DEV_RELEASE OFF)
else ()
@@ -40,6 +40,17 @@ if (CMAKE_VERSION VERSION_LESS 3.21)
endif ()
endif ()
# Set up module path for our own cmake modules and add some essential ones
list (APPEND CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/src/cmake/modules"
"${PROJECT_SOURCE_DIR}/src/cmake")
# Utilities
include (colors)
include (set_utils)
include (check_is_enabled)
include (fancy_add_executable)
# If the user wants to use Conan to build dependencies, they will have done
# this prior to the cmake config:
# cd <build area>
@@ -76,9 +87,11 @@ message (STATUS "Build type = ${CMAKE_BUILD_TYPE}")
message (STATUS "Supported release = ${${PROJECT_NAME}_SUPPORTED_RELEASE}")
# Make the build area layout look a bit more like the final dist layout
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if (PROJECT_IS_TOP_LEVEL)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message (FATAL_ERROR "Not allowed to run in-source build!")
@@ -97,15 +110,16 @@ if (VERBOSE)
else ()
set (CMAKE_MESSAGE_LOG_LEVEL "STATUS" CACHE STRING "CMake log level to display")
endif ()
option (${PROJ_NAME}_BUILD_TOOLS "Build the command-line tools" ON)
option (${PROJ_NAME}_BUILD_TESTS "Build the unit tests" ON)
set_option (${PROJ_NAME}_BUILD_TOOLS "Build the command-line tools" ON)
set_option (${PROJ_NAME}_BUILD_TESTS "Build the unit tests" ON)
set_option (OIIO_USE_HWY "Enable experimental Google Highway SIMD optimizations (if Highway is available)" OFF VERBOSE)
set (OIIO_LIBNAME_SUFFIX "" CACHE STRING
"Optional name appended to ${PROJECT_NAME} libraries that are built")
option (BUILD_OIIOUTIL_ONLY "If ON, will build *only* libOpenImageIO_Util" OFF)
option (BUILD_DOCS "If ON, build documentation and man pages." ON)
option (INSTALL_DOCS "If ON, install documentation and man pages." ON)
option (INSTALL_FONTS "If ON, install default fonts" ON)
option (EMBEDPLUGINS "Embed format plugins in libOpenImageIO" ON)
set_option (BUILD_OIIOUTIL_ONLY "If ON, will build *only* libOpenImageIO_Util" OFF)
set_option (BUILD_DOCS "If ON, build documentation and man pages." ON)
set_option (INSTALL_DOCS "If ON, install documentation and man pages." ON)
set_option (INSTALL_FONTS "If ON, install default fonts" ON)
set_option (EMBEDPLUGINS "Embed format plugins in libOpenImageIO" ON)
set (PLUGIN_SEARCH_PATH "" CACHE STRING "Default plugin search path")
file (TO_NATIVE_PATH "${PLUGIN_SEARCH_PATH}" PLUGIN_SEARCH_PATH_NATIVE)
set (CMAKE_DEBUG_POSTFIX "_d" CACHE STRING "Library naming postfix for Debug builds")
@@ -119,45 +133,108 @@ message(STATUS "CMAKE_UNITY_BUILD_MODE = ${CMAKE_UNITY_BUILD_MODE}")
message(STATUS "CMAKE_UNITY_BUILD_BATCH_SIZE = ${CMAKE_UNITY_BUILD_BATCH_SIZE}")
option (OIIO_THREAD_ALLOW_DCLP "OIIO threads may use DCLP for speed" ON)
if (NOT OIIO_THREAD_ALLOW_DCLP)
add_compile_definitions (OIIO_THREAD_ALLOW_DCLP=0)
endif ()
set (TEX_BATCH_SIZE "" CACHE STRING "Force TextureSystem SIMD batch size (e.g. 16)")
option (OIIO_TEX_IMPLEMENT_VARYINGREF "Implement the deprecated batch texture functions taking VaryingRef params" ON)
# Set the default namespace
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
"Customized outer namespace base name (version will be added)")
option (${PROJ_NAME}_NAMESPACE_INCLUDE_PATCH
"Should the inner namespace include the patch number" ${${PROJECT_NAME}_DEV_RELEASE})
set (PROJ_NAMESPACE "${${PROJ_NAME}_NAMESPACE}")
set (PROJ_NAMESPACE_V "${PROJ_NAMESPACE}_v${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}")
if (${PROJ_NAME}_NAMESPACE_INCLUDE_PATCH)
set (PROJ_NAMESPACE_V "${PROJ_NAMESPACE_V}_${PROJECT_VERSION_PATCH}")
if (TEX_BATCH_SIZE)
add_compile_definitions (OIIO_TEXTURE_SIMD_BATCH_WIDTH=${TEX_BATCH_SIZE})
endif ()
message(STATUS "Setting Namespace to: ${PROJ_NAMESPACE_V}")
# If we're building this just for CI, define a symbol so the code can
# tell (and reduce complexity of some tests)
set_option (OIIO_CI "Set if this build is for our GHA CI" OFF)
if (OIIO_CI)
add_compile_definitions (OIIO_CI=1)
endif ()
# Namespace settings
#
# The "outer namespace" defaults to the project name, but it can be overridden
# to allow custom builds that put everything inside a unique namespace that
# can't conflict with default builds.
set (${PROJ_NAME}_OUTER_NAMESPACE ${PROJECT_NAME} CACHE STRING
"Customized outer namespace")
set (PROJ_NAMESPACE "${${PROJ_NAME}_OUTER_NAMESPACE}") # synonym
# There is also an inner namespace that is either vMAJ_MIN or vMAJ_MIN_PATCH,
# depending on the setting of ${PROJ_NAME}_INNER_NAMESPACE_INCLUDE_PATCH.
option (${PROJ_NAME}_INNER_NAMESPACE_INCLUDE_PATCH
"Should the inner namespace include the patch number" ${${PROJECT_NAME}_DEV_RELEASE})
if (${PROJ_NAME}_INNER_NAMESPACE_INCLUDE_PATCH)
set (PROJ_VERSION_NAMESPACE "v${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}_${PROJECT_VERSION_PATCH}")
else ()
set (PROJ_VERSION_NAMESPACE "v${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}")
endif ()
# PROJ_NAMESPACE_V combines the outer and inner namespaces into one symbol
set (PROJ_NAMESPACE_V "${PROJ_NAMESPACE}_${PROJ_VERSION_NAMESPACE}")
message(STATUS "Outer namespace PROJ_OUTER_NAMESPACE: ${PROJ_NAMESPACE}")
message(STATUS "Inner namespace PROJ_VERSION_NAMESPACE: ${PROJ_VERSION_NAMESPACE}")
message(STATUS "Joint namespace PROJ_NAMESPACE_V: ${PROJ_NAMESPACE_V}")
list (APPEND CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/src/cmake/modules"
"${PROJECT_SOURCE_DIR}/src/cmake")
# Define OIIO_INTERNAL symbol only when building OIIO itself, will not be
# defined for downstream projects using OIIO.
add_compile_definitions (OIIO_INTERNAL=1)
# If CMake variable OIIO_SITE is set, set compile symbol OIIO_SITE_sitename
if (OIIO_SITE)
add_compile_definitions (OIIO_SITE_${OIIO_SITE})
endif ()
include (GNUInstallDirs)
# Utilities
include (colors)
include (check_is_enabled)
include (checked_find_package)
include (fancy_add_executable)
# Utilities for build instructions of the format-reading plugins
include (add_oiio_plugin)
# All the C++ and compiler related options and adjustments
include (compiler)
# Dependency finding utilities and all dependency-related options
include (dependency_utils)
option (IGNORE_HOMEBREWED_DEPS "If ON, will ignore homebrew-installed dependencies" OFF)
if (IGNORE_HOMEBREWED_DEPS)
# Define the list of prefixes to ignore
set (HOMEBREW_PREFIXES
/opt/homebrew
/opt/homebrew/Cellar
/usr/local
/usr/local/Cellar
/usr/X11
/usr/X11R6
/opt/X11
)
message (STATUS "Ignoring Homebrew dependencies and adjusted environment and CMake variables accordingly.")
foreach (_cmake_var
CMAKE_SYSTEM_INCLUDE_PATH
CMAKE_SYSTEM_LIBRARY_PATH
CMAKE_PREFIX_PATH)
remove_prefixes_from_variable (CMAKE ${_cmake_var} "${HOMEBREW_PREFIXES}")
endforeach ()
# Adjust CMAKE_IGNORE_PATH
foreach (_prefix IN LISTS HOMEBREW_PREFIXES)
list (APPEND CMAKE_IGNORE_PATH
"${_prefix}"
"${_prefix}/lib"
"${_prefix}/bin"
"${_prefix}/include"
)
endforeach ()
message (STATUS "CMAKE_IGNORE_PATH: ${CMAKE_IGNORE_PATH}")
endif ()
# Utilities and options related to finding python and making python bindings
include (pythonutils)
# Dependency finding utilities and all dependency-related options
include (externalpackages)
include (cuda_macros)
# Include all our testing apparatus and utils, but not if it's a subproject
if (PROJECT_IS_TOP_LEVEL)
include (testing)
@@ -177,23 +254,6 @@ include_directories (
"${CMAKE_BINARY_DIR}/include/OpenImageIO"
)
# Define OIIO_INTERNAL symbol only when building OIIO itself, will not be
# defined for downstream projects using OIIO.
proj_add_compile_definitions (OIIO_INTERNAL=1)
if (NOT OIIO_THREAD_ALLOW_DCLP)
proj_add_compile_definitions (OIIO_THREAD_ALLOW_DCLP=0)
endif ()
if (TEX_BATCH_SIZE)
proj_add_compile_definitions (OIIO_TEXTURE_SIMD_BATCH_WIDTH=${TEX_BATCH_SIZE})
endif ()
if (NOT OIIO_TEX_IMPLEMENT_VARYINGREF)
proj_add_compile_definitions (OIIO_TEX_NO_IMPLEMENT_VARYINGREF=1)
endif ()
# Tell CMake to process the sub-directories
add_subdirectory (src/libutil)
@@ -207,13 +267,6 @@ set (format_plugin_libs "")
set (format_plugin_include_dirs "")
set (format_plugin_definitions "")
file (GLOB all_format_plugin_dirs src/*.imageio)
if ("${OIIO_SITE}" STREQUAL "SPI")
# SPI only -- because of a workaround for a very weird linkage issue
# specific to our system, we need to be sure libtiff is referenced first.
file (GLOB tiff_format_plugin_dir src/tiff.imageio)
list (REMOVE_ITEM all_format_plugin_dirs ${tiff_format_plugin_dir})
list (INSERT all_format_plugin_dirs 0 ${tiff_format_plugin_dir})
endif ()
if (EMBEDPLUGINS AND NOT BUILD_OIIOUTIL_ONLY)
foreach (plugin_dir ${all_format_plugin_dirs})
add_subdirectory (${plugin_dir})
@@ -224,6 +277,16 @@ if (NOT BUILD_OIIOUTIL_ONLY)
add_subdirectory (src/libOpenImageIO)
endif ()
# Disable building of certain tools when building Python wheels
if (SKBUILD)
set (ENABLE_iconvert OFF)
set (ENABLE_igrep OFF)
set (ENABLE_iinfo OFF)
set (ENABLE_testtex OFF)
set (ENABLE_iv OFF)
endif ()
if (OIIO_BUILD_TOOLS AND NOT BUILD_OIIOUTIL_ONLY)
add_subdirectory (src/iconvert)
add_subdirectory (src/idiff)
@@ -244,8 +307,23 @@ if (NOT EMBEDPLUGINS AND NOT BUILD_OIIOUTIL_ONLY)
endforeach ()
endif ()
if (USE_PYTHON AND Python_Development_FOUND AND NOT BUILD_OIIOUTIL_ONLY)
add_subdirectory (src/python)
if (WIN32)
set (_py_dev_found Python3_Development_FOUND)
else ()
set (_py_dev_found Python3_Development.Module_FOUND)
endif ()
if (USE_PYTHON AND ${_py_dev_found} AND NOT BUILD_OIIOUTIL_ONLY)
if (OIIO_BUILD_PYTHON_PYBIND11
OR OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "nanobind")
add_subdirectory (src/python)
endif ()
if (OIIO_BUILD_PYTHON_NANOBIND
AND OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "both")
add_subdirectory (src/python-nanobind)
endif ()
else ()
message (STATUS "Not building Python bindings: USE_PYTHON=${USE_PYTHON}, Python3_Development.Module_FOUND=${Python3_Development.Module_FOUND}")
endif ()
add_subdirectory (src/include)
@@ -259,11 +337,6 @@ if (NUKE_FOUND)
add_subdirectory (src/nuke/txWriter)
endif ()
# Last minute site-specific instructions, if they exist
if (OIIO_SITE AND EXISTS "${PROJECT_SOURCE_DIR}/site/${OIIO_SITE}/cmake/sitecustom.cmake")
include ("${PROJECT_SOURCE_DIR}/site/${OIIO_SITE}/cmake/sitecustom.cmake")
endif ()
# install pkgconfig file
if (NOT MSVC)
configure_file(src/build-scripts/OpenImageIO.pc.in "${CMAKE_BINARY_DIR}/OpenImageIO.pc" @ONLY)
@@ -320,3 +393,5 @@ endif ()
if (PROJECT_IS_TOP_LEVEL)
include (packaging)
endif ()
print_package_notfound_report ()
+4
View File
@@ -5,3 +5,7 @@ you can read in full [here](https://lfprojects.org/policies/code-of-conduct).
To report incidents or to appeal reports of incidents, send email to
the Manager of LF Projects at manager@lfprojects.org.
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+169 -47
View File
@@ -1,37 +1,33 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
Contributing to OpenImageIO
===========================
> NOTE: This is the proposed post-ASWF-move version of CONTRIBUTING. After the
> project is legally transferred and moved to the new repo, this file will
> replace the one at the project root.
>
> TO DO:
>
> - [X] Update the mail list sign-up page after the mail list moves.
> - [ ] Update the repo URL
> - [ ] Double check the security and info email addresses.
>
Code contributions to OpenImageIO are always welcome, and [nearly 200
people](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/CREDITS.md) have done
Code contributions to OpenImageIO are always welcome, and [nearly 250
people](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/CREDITS.md) have done
so over the years. Please review this document to get a briefing on our
process.
General Tips for Open Source Development
----------------------------------------
* GitHub's [Open Source Guides](https://opensource.guide/)
- Especially the guide on [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
Mail List and Slack
-------------------
Contributors should be reading the oiio-dev mail list:
* [oiio-dev](https://lists.aswf.io/g/oiio-dev)
For developers of the OpenImageIO code itself, or users who are really
interested in the OIIO internals. This is where we mostly discuss the code
(including bug reports), but are also happy to answer user questions about
use or working of OIIO.
use or working of OIIO. You can sign up for the mail list on your own using the link above.
You can sign up for the mail list on your own using the link above.
The [ASWF Slack](https://slack.aswf.io/) has an `openimageio` channel. Sign up
* [ASWF Slack](https://slack.aswf.io/) has an `openimageio` channel. Sign up
for the Slack on your own, then under "channels", select "browse channels" and
you should see the openimageio channel (among those of the other projects and
working groups).
@@ -55,7 +51,7 @@ enhancements: https://github.com/AcademySoftwareFoundation/OpenImageIO/issues
**If you are merely asking a question ("how do I...")**, please do not file an
issue, but instead ask the question on the [oiio-dev mailing
list](https://lists.aswf.io/g/oiio-dev).
list](https://lists.aswf.io/g/oiio-dev) or on the Slack channel.
If you are submitting a bug report, please be sure to note which version of
OIIO you are using, on what platform (OS/version, which compiler you used,
@@ -72,10 +68,44 @@ following your instructions. Please quote the exact error message you
received. If you are having trouble building, please post the full cmake
output of a fresh VERBOSE=1 build.
Suspected security vulnerabilities should be reported by the same process.
[SECURITY.md](SECURITY.md) details our security policies and lists prior security advisories. True exploitable security vulnerabilities
that should be fixed before disclosure should be reported by filing a GitHub
[security advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/new).
If that is not possible, it is also fine to email your report to
security@openimageio.org. Only the project administrators have access to these
reports. For problems that you don't think are really exploitable
vulnerabilities, you are encouraged to just file a regular issue, as described
above.
If confidentiality precludes a public question or issue for any reason, you
may contact us privately at [security@openimageio.org](security@openimageio.org).
Policy on AI Tools
------------------
Please read our [Policy on AI Coding Assistants](docs/dev/AI_Policy.md)
before contributing or participating in the project in any way mediated by
"AI" assistants.
High-level summary:
- Human must always be in the loop, and is the responsible party for
the contents of a PR (including fully understanding and being able
to explain, defend, and modify it in response to review comments).
- Interact with the project and community yourself, not by agent.
- Disclose what tools you used and how. At a minimum, we require an
"Assisted-by: TOOL/MODEL" line in the commit comments and PR description.
- Don't waste maintainer's time with low quality PRs.
Please do read the whole [Policy on AI Coding Assistants](docs/dev/AI_Policy.md)
for all the details.
The repository supports several AI coding assistants (Claude Code, Cursor,
GitHub Copilot, OpenAI Codex, Opencode). After cloning, run the setup script
for whichever tool(s) you use:
```
.agents/setup-agent claude # or: cursor, codex, opencode, copilot, all
```
See [docs/dev/Agentic_Coding.md](docs/dev/Agentic_Coding.md) for details.
Contributor License Agreement (CLA) and Intellectual Property
@@ -87,26 +117,39 @@ safety, as it prevents any possible future disputes between code authors and
their employers or anyone else who might think they might own the IP output of
the author.
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/ASWF/CLA-corporate.md) :
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/ASWF/CLA-corporate.md) :
If you are writing the code as part of your job, or if there is any
possibility that your employers might think they own any intellectual
property you create. This needs to be executed by someone who has
signatory power for the company.
* [Individual CLA](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/ASWF/CLA-individual.md) :
* [Individual CLA](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/ASWF/CLA-individual.md) :
If you are an individual writing the code on your own time, using your own
equipment, and you're SURE you are the sole owner of any intellectual
property you contribute.
The easiest way to sign CLAs is digitally [using EasyCLA](https://corporate.v1.easycla.lfx.linuxfoundation.org).
Please note that it is extremely common (nearly ubiquitous in the US and
Canada, and maybe other places) for full-time employees of technology and
entertainment companies to have IP clauses in their employment agreement (in
that pile of paperwork you sign on your first day of work and then promptly
forget about) that give the company rights to any code you write, even on your
own time. The OpenImageIO project expects you to know and follow the rules of
your employer and to have them sign a corporate CLA if necessary.
The easiest way to sign CLAs is digitally [using
EasyCLA](https://corporate.v1.easycla.lfx.linuxfoundation.org). There are
detailed step-by-step instructions about using the EasyCLA system for
[corporate CLAs](https://docs.linuxfoundation.org/lfx/easycla/v2-current/contributors/corporate-contributor)
and [individual CLAs](https://docs.linuxfoundation.org/lfx/easycla/v2-current/contributors/individual-contributor#github).
Companies who prefer not to use the online tools may sign, scan, and email
the executed copy to manager@lfprojects.org.
The CLA allows a company to name a "CLA Manager" (who does not need
signatory power) who has the ability to use the online system to add or
delete individual employees of the company who are authorized to submit pull
requests, without needing to get an executive to amend and sign the
agreement each time.
The corporate CLA allows a company to name a "CLA Manager" (who does not need
signatory power) who has the ability to use the online system to add or delete
individual employees of the company who are authorized to submit pull
requests, without needing to get an executive to amend and sign the agreement
each time.
Please note that these CLAs are based on the Apache 2.0 CLAs, and differ
minimally, only as much as was required to correctly describe the EasyCLA
@@ -134,6 +177,84 @@ leverage this [command line tool](https://github.com/coderanger/dco) for
automatically adding the signoff message on commits.
Commit messages
---------------
### Summary heuristic
Look at the commit history of the project to get a sense of the style and
level of detail that is expected in commit messages.
### General guidelines and expectations
The first line of the commit message should be a short (less than 80
characters) summary of the change, prefixed with the general nature of the
change (see below).
The rest of the commit message should be a more detailed explanation of the
changes. Some commits are self-explanatory and don't need more than the
summary line. Others may need a more detailed explanation. Hallmarks of
a good commit message include:
* An explanation of why the change is necessary and what you hope to
accomplish with it.
* A description of any major user- or developer-facing changes that people
should be aware of: changes in APIs or behaviors, new features, etc.
* An explanation of any tricky implementation details or design decisions that
might not be immediately obvious to someone reading the code.
* Guideposts for somebody reviewing the code to understand the rationale and
have any supporting background information to fully understanding the code
changes.
Remember that at some point in the future, a developer unfamiliar with your
change (maybe you, long after you've forgotten the details) might need to
understand or fix your patch. Keep that person in mind as your audience and
strive to write a commit message that explains the context in a way that saves
them time and effort. Be the hero in the story of their future debugging
effort!
### Using "conventional commits" prefixes
We strive to follow the recommendations known as [conventional
commits](https://www.conventionalcommits.org/), which means that we would like
merged commit messages to have their first line start with one of the
following prefixes:
- `feat:` new features
- `fix:` bug fixes
- `perf:` performance improvements
- `api:` changes to the public APIs
- `int:` changes to code internals that don't affect the public API
- `build:` changes to the build system
- `test:` changes to the test suite or unit tests
- `ci:` changes to the CI system
- `docs:` changes to the documentation
- `refactor:` code refactoring
- `style:` formatting or other stylistic non-functional changes to the code
- `admin:` project administration or policy changes
- `revert:` reverting a previous commit
Obviously, some (if not most) PRs may qualify for more than one of these
categories (for example, a new feature may also introduce a new API call, add
tests, and include new documentation). If that is the case, use your best
judgment to pick the category that best captures the essence or most important
aspect of the change. When ambiguous, consider the list above to be a priority
ranking (e.g., a change that fixes a bug and adds a new test should be listed
under `fix:`, because that appears first in the list).
It is also encouraged, when it makes sense to do so, to put a subcategory in
parenthesis after the prefix, like `fix(exr):` or `feat(IBA):`. It's ok to use
obvious abbreviations for major classes or subsections: IB=ImageBuf,
IBA=ImageBufAlgo, IC=ImageCache, TS=TextureSystem, etc. If there is no clear
single format or class that is the man focus of the patch, then you can omit
the subcategory.
API or ABI-breaking changes should additionally be marked with an exclamation
point at the end of the prefix, like `feat!:` or `api!:` to make it easily
identifiable as a breaking change from the first line of the commit message.
Pull Requests and Code Review
-----------------------------
@@ -143,38 +264,41 @@ The best way to submit changes is via GitHub Pull Request. GitHub has a
All code must be formally reviewed before being merged into the official
repository. The protocol is like this:
1. Get a GitHub account, fork OpenImageIO/oiio to create your own repository
on GitHub, and then clone it to get a repository on your local machine.
1. Get a GitHub account, fork AcademySoftwareFoundation/OpenImageIO to create
your own repository on GitHub, and then clone it to get a repository on your
local machine.
1. Edit, compile, and test your changes. Run clang-format (see the
2. Edit, compile, and test your changes. Run clang-format (see the
instructions on coding style below).
1. Push your changes to your fork (each unrelated pull request to a separate
3. Push your changes to your fork (each unrelated pull request to a separate
"topic branch", please).
1. Make a "pull request" on GitHub for your patch.
4. Make a "pull request" on GitHub for your patch.
2. If your patch will induce a major compatibility break, or has a design
5. If your patch will induce a major compatibility break, or has a design
component that deserves extended discussion or debate among the wider OIIO
community, then it may be prudent to email oiio-dev pointing everybody to
the pull request URL and discussing any issues you think are important.
1. All pull requests automatically launch CI jobs on GitHub Actions to
6. All pull requests automatically launch CI jobs on GitHub Actions to
ensure that the build completes and that the tests suite runs correctly, for
a variety of platform, compiler, library, and flag combinations. The status
of the CI tests for your PR will be displayed on the GitHub PR page. We will
not accept PRs that don't build cleanly or pass the existing testsuite.
1. The reviewer will look over the code and critique on the "comments" area.
7. The reviewer will look over the code and critique on the "comments" area.
Reviewers may ask for changes, explain problems they found, congratulate the
author on a clever solution, etc. But until somebody says "LGTM" (looks good
to me), the code should not be committed. Sometimes this takes a few rounds
of give and take. Please don't take it hard if your first try is not
accepted. It happens to all of us.
1. After approval, one of the senior developers (with commit approval to the
official main repository) will merge your fixes into the master branch.
8. After approval, one of the senior developers (with commit approval to the
official main repository) will merge your fixes into the main branch.
Please see the [Code Review](docs/dev/CodeReview.md) document for more
explanaton of the code review process.
Coding Style
------------
@@ -255,9 +379,9 @@ capitalize new words: `class CustomerList;` In general, local variables
should start with lower case. Macros should be `ALL_CAPS`, if used at all.
If your class is extremely similar to, or modeled after, something in the
standard library, Boost, or something else we interoperate with, it's ok to
standard library, or something else we interoperate with, it's ok to
use their naming conventions. For example, very general utility classes and
templates (the kind of thing you would normally find in std or boost) should
templates (the kind of thing you would normally find in std) should
be lower case with underscores separating words, as they would be if they
were standards.
@@ -290,10 +414,8 @@ Namespaces: yes, use them!
### Third-party libraries
Prefer C++11 `std` rather than Boost, where both can do the same task.
Feel free to use Boost classes you already see in the code base, but don't
use any Boost you don't see us already using, without first checking with
the project leader.
Prefer C++17 `std` rather than other libraries, where both can do the same
task.
Please do use Imath vector, matrix, and utility classes where applicable.
Don't write your own vector or matrix code!
+67 -1
View File
@@ -4,10 +4,16 @@ by first name.
If you know of somebody that I missed or have corrections, please email:
lg@openimageio.org
* Aamir Raza
* Aaron Colwell
* Adam Mains
* Akihiro Yamasaki
* Alan Jones
* Alejandro Conty
* Alejandro Aguirre
* Aleksandr Motsjonov
* Alex Fuller
* Alex Guirre
* Alex Hughes
* Alex Schworer
* Alexander Kuleshov
@@ -19,10 +25,16 @@ lg@openimageio.org
* Aman Shah
* Ananth Garre
* Anders Langlands
* Andy Chan
* Anthony Roberts
* AngryLoki
* Angus Davis
* Ankit Sinha
* Anton Dukhovnikov
* Anthony Nemoff
* Aras Pranckevičius
* Arkady Shapkin
* Basile Fraboni
* Basileios Anastasatos
* Bastien Montagne
* Ben De Luca
@@ -31,26 +43,39 @@ lg@openimageio.org
* Blair Tennessy
* Blazej Floch
* Brad Smith
* Bram Stolk
* Brecht Van Lommel
* Brent Davis
* Brian Hall
* Brice Gros
* Campbell Barton
* Carine Touraille
* Carl Rand
* Cassian Andrei
* Chad Dombrova
* Changlin Hsieh
* Chaitanya Sharma
* Chris Crosetto
* Chris Foster
* Chris Hellmuth
* Chris Kulla
* Chris Whalen
* Christoph Willing
* Cliff Stein
* Clément Champetier
* Cliff Stein
* Connie Chang
* Curtis Black
* D-Spirits
* Dalai Felinto
* Dan Wexler
* Daniel Dresser
* Daniel Flehner Heen
* Daniel Wyatt
* Danielle Imogu
* Danny Greenstein
* Darby Johnston
* Dharshan Vishwanatha
* David Adler
* David Aguilar
* David Gordon
* Deepak Gopinath
@@ -58,22 +83,27 @@ lg@openimageio.org
* Dieter De Baets
* Dinko Galetik
* Dominik Bartkiewicz
* Dominik Wójt
* Don Olmstead
* Duncan Chan
* Dustin Rodrigues
* Edgar Velazquez-Armendariz
* Eloi Du Bois
* Elvic Liang
* Emil Dohne
* Fabien Castan
* Fabien Servant
* Fredrik Averpil
* Frédéric Devernay
* Gaurav Bansal
* Gerrard Tai
* Gerdya
* Ghislain Antony Vaillant
* Gonzalo Garramuño
* Gregor Mueckl
* Grégoire De Lillo
* Guillaume Chatelet
* Hannah Gulka
* Hanspeter Niederstrasser
* Harry Mallon
* Heiko Becker
@@ -82,18 +112,23 @@ lg@openimageio.org
* Imarz
* Irena Damsky
* Ismael Cortes
* Jackson Sun
* Jan Hettenkofer
* Jan Honsbrok
* Jens Lindgren
* Jep Hill
* Jeph Alapat
* Jeremy Retailleau
* Jeremy Rose
* Jeremy Selan
* Jesse Yurkovich
* Jim Hourihan
* Joachim Reichel
* Johannes Unterguggenberger
* John Burnett
* John Fea
* John Haddon
* Jonathan Brown
* Jonathan Hearn
* Jonathan Scruggs
* Joris Nijs
@@ -101,6 +136,7 @@ lg@openimageio.org
* Julien Enche
* Justin Israel
* Justina Mikonyte
* Kaarrot
* Kazuki Takahashi
* Kevin Brightwell
* Kimball Thurston
@@ -110,17 +146,22 @@ lg@openimageio.org
* LazyDodo
* Leonid Onokhov
* Leszek Godlewski
* Li Ji
* Lucas Panian
* Lucille Caillaud
* Lukas Schrangl
* Lukasz Maliszewski
* Luke Emrose
* Lumina Wang
* Luna Kim
* Lydia Zheng
* M Joonas Pihlaja
* Malcolm Humphreys
* Manuel Gamito
* Manuel Leonhardt
* Marcos Fajardo
* Marie Fetiveau
* Marta Feriani
* Mariusz Szczepanczyk
* Mark Boorer
* Mark Visser
@@ -128,6 +169,8 @@ lg@openimageio.org
* Matteo F. Vescovi
* Matthew E. Levine
* Max Liani
* Maxwell Iverson
* Mel Massadian
* Merwan Achibet
* Michael Cho
* Michael Oliver
@@ -145,15 +188,21 @@ lg@openimageio.org
* Noah Rahm (designer of our logo!)
* Northon Patrick
* Nuno Cardoso
* Oktay Comu
* Ole Gulbrandsen
* omcaif
* Ott Tinn
* Pascal Lecocq
* Patrick Hodoul
* Patrick Piché
* Paul Franz
* Paul Melis
* Paul Molodowitch
* Pavan Madduri
* Pavel Karneliuk
* Pete Larabell
* Peter Horvath
* Peter Kovář
* Philip Nemec
* Pino Toscano
* Povilas Kanapickas
@@ -166,18 +215,23 @@ lg@openimageio.org
* Robert Matusewicz
* Roeland Schoukens
* Roman Zulak
* Rui Chen
* Rui Li
* Russell Greene
* Ryen
* Saket Jalan
* Sam Richards
* Samuel Nicholas
* Scott Milner
* Scott Wilson
* Sebastian Elsner
* SebTV
* Seifeddine Dridi
* Sergey Sharybin
* Sergio Rojas
* Shane Ambler
* Shane Smith
* Shashvat K. Singh
* Simon Boorer
* Solomon Boulos
* SRHMorris
@@ -185,15 +239,21 @@ lg@openimageio.org
* Stefan Stavrev
* Thiago Ize
* Thomas Dinges
* Thomas Klausner
* Thomas Mansencal
* Till Dechent
* Tim D. Smith
* Tim Grant
* Todica Ionut
* Tom Knowles
* Troy James Sobotka
* Valery Angelique
* Vanessa Valderrama
* Vic P
* Vinod Khare
* Vishal Agrawal
* Vitor Franchi
* Vlad (Kuzmin) Erium
* Wayne Arnold
* Will Rosecrans
* William Krick
@@ -201,4 +261,10 @@ lg@openimageio.org
* Xo Wang
* Yang Yang
* Yann Lanthony
* Zach Lewis
* Ziad Khouri
* zomgrolf
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+13 -10
View File
@@ -27,9 +27,9 @@ beyond the legal forms.
### How to Become a Contributor
* Review the coding standards and [contributing
guidelines](../CONTRIBUTING.md) to ensure your contribution is in line with
the project's coding and styling guidelines.
* Review the coding standards and [contributing guidelines](CONTRIBUTING.md)
to ensure your contribution is in line with the project's coding and styling
guidelines.
* Sign the Individual CLA, or if you are employed by an organization that
might have any claim to IP you create, have your organization sign the
@@ -79,8 +79,9 @@ request that the TSC restore them to active Committer status.
## Technical Steering Committee
The Technical Steering Committee (TSC) has final authority over this project.
As defined in the project charter, in addition to committer activities, TSC
responsibilities also include, but are not limited to:
As defined in the project [technical charter](https://github.com/AcademySoftwareFoundation/foundation/blob/main/project_charters/openimageio_charter.pdf), in
addition to committer activities, TSC responsibilities also include, but are
not limited to:
* Coordinating technical direction of the Project.
@@ -130,13 +131,12 @@ represents the project at all ASWF TAC meetings.
Current voting members of the TSC are:
* **Chair and TAC representative**: Daniel Greenstein - Sony Pictures Imageworks (possibly interim?)
* **Chair and TAC representative**: Daniel Greenstein - Sony Pictures Imageworks
* **Chief Architect**: Larry Gritz - Sony Pictures Imageworks
* Anton Dukhovnikov - Wētā Digital / Unity
* Jesse Yurkovich - Blender
* Joseph Goldstone - ARRI
* Lewis Wakeland - Disney TV Animation
* Luke Emrose - Animal Logic (interim?)
* Luke Emrose - Animal Logic
* Martin Davies - LAIKA
* Robin Rowe - Heroic Robots
* Thiago Ize - Autodesk
@@ -181,8 +181,8 @@ her absence. Meetings may also be streamed online where appropriate;
connection details will be posted to the oiio-dev mail list in advance of the
scheduled meeting.
The biweekly TSC meetings can be found on the [ASWF Calendar](https://www.aswf.io/meeting-calendar),
just click on the OpenImageIO meeting entries to get the Zoom link.
The biweekly TSC meetings can be found on the [ASWF Calendar](https://calendar.openimageio.org),
just click on the OpenImageIO TSC meeting entries to get the Zoom link.
Items are added to the TSC agenda which are considered contentious or are
modifications of governance, contribution policy, TSC membership, or release
@@ -213,3 +213,6 @@ Due to the challenges of scheduling a global meeting with participants in
several time zones, the TSC will seek to resolve as many agenda items as
possible outside of meetings on the public mailing list or through GitHub
issues, discussions, and pull requests.
Meeting notes (usually very brief) can be found at: https://docs.google.com/document/d/1quSh1K5U2jUDi3cB1eX84i9Y2p7r58w1fZMXM8rnH-w/
+184 -109
View File
@@ -14,72 +14,81 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
### Required dependencies -- OIIO will not build at all without these
* C++14 or higher (also builds with C++17, and C++20)
* C++17 or higher (also builds with C++20, C++23, and C++26)
* The default build mode is C++17. This can be controlled by via the
CMake configuration flag: `-DCMAKE_CXX_STANDARD=14`, etc.
* ADVISORY: We expect that OIIO 2.6 in 2024 will require C++17 or higher.
* Compilers: gcc 6.1 - 13.1, clang 3.4 - 17, MSVS 2017 - 2019,
Intel icc 17+, Intel OneAPI C++ compiler 2022+.
* **CMake >= 3.15** (tested through 3.28)
* **OpenEXR/Imath >= 2.4** (recommended: 3.1 or higher; tested through 3.2
and main) (ADVISORY: We expect that OIIO 2.6 in 2024 will require OpenEXR >= 3.1)
* libTIFF >= 3.9 (recommended: 4.0+; tested through 4.6)
* libjpeg >= 8 (tested through jpeg9e), or **libjpeg-turbo >= 2.1** (tested
through 3.0)
* Boost >= 1.53 (recommended: at least 1.66; tested through 1.84)
* **[fmtlib](https://github.com/fmtlib/fmt) >= 7.0** (tested through 10.1).
If not found at build time, this will be automatically downloaded unless
the build sets `-DBUILD_MISSING_FMT=OFF`.
CMake configuration flag: `-DCMAKE_CXX_STANDARD=20`, etc.
* Note that no matter which version you compile with internally,
OIIO's public APIs only require C++17 features.
* Compilers: gcc 9.3 - 15.2, clang 10 - 22, MSVS 2017 - 2026 (v19.14
and up), Intel OneAPI C++ compiler 2022+.
* CMake >= 3.18.2 (tested through 4.3)
* Imath >= 3.1 (tested through 3.2 and main)
* OpenEXR >= 3.1 (tested through 3.4 and main)
* libTIFF >= 4.0 (tested through 4.7 and master)
* OpenColorIO >= 2.3 (tested through 2.5 and main)
* libjpeg >= 8 (tested through jpeg9e), or libjpeg-turbo >= 2.1 (tested
through 3.1)
* zlib >= 1.2.7 (tested through 1.3.2)
* **[fmtlib](https://github.com/fmtlib/fmt) >= 9.0** (tested through 12.2 and master).
If not found at build time, this will be automatically downloaded and built.
* [Robin-map](https://github.com/Tessil/robin-map) (unknown minimum, tested
through 1.4, which is the recommended version). If not found at build time,
this will be automatically downloaded and built.
### Optional dependencies -- features may be disabled if not found
* If you are building the `iv` viewer (which will be disabled if any of
these are not found):
* Qt5 >= 5.6 (tested through 5.15) or Qt6 (tested through 6.6)
* Qt5 >= 5.6 (tested through 5.15) or Qt6 (tested through 6.11)
* OpenGL
* If you are building the Python bindings or running the testsuite:
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10, 3.11)
* pybind11 >= 2.4.2 (Tested through 2.11. Note that pybind11 v2.10+ does
not support Python < 3.6.)
* NumPy
* Python >= 3.9 (tested through 3.13).
* pybind11 >= 2.7 (tested through 3.0)
* NumPy (tested through 2.4.4)
* If you enable the optional nanobind (WIP) backend for source/CMake
builds (`OIIO_PYTHON_BINDINGS_BACKEND` is `nanobind` or `both`):
* nanobind discoverable by CMake, or installed in the active Python
environment so `python -m nanobind --cmake_dir` works
* If you want support for PNG files:
* libPNG >= 1.6.0 (tested though 1.6.56)
* If you want support for camera "RAW" formats:
* LibRaw >= 0.18 (tested though 0.21.2; if
building with C++17 or higher, LibRaw >= 0.20 is necessary)
* LibRaw >= 0.20 (tested though 0.22.0 and master)
* If you want support for a wide variety of video formats:
* ffmpeg >= 3.0 (tested through 6.1)
* ffmpeg >= 4.0 (tested through 8.1)
* If you want support for jpeg 2000 images:
* OpenJpeg >= 2.0 (tested through 2.5; we recommend 2.4 or higher
* OpenJpeg >= 2.0 (tested through 2.5.4; we recommend 2.4 or higher
for multithreading support)
* If you want support for OpenVDB files:
* OpenVDB >= 5.0 (tested through 11.0). Note that using OpenVDB >= 10.0
requires that you compile OIIO with C++17 or higher.
* OpenVDB >= 9.0 (tested through 13.0).
* If you want to use TBB as the thread pool:
* TBB >= 2018 (tested through 2021 and OneTBB)
* If you want support for converting to and from OpenCV data structures,
or for capturing images from a camera:
* OpenCV 3.x, or 4.x (tested through 4.9)
* OpenCV 4.x or 5.x (tested through 5.0)
* If you want support for GIF images:
* giflib >= 4.1 (tested through 5.2; 5.0+ is strongly recommended for
stability and thread safety)
* giflib >= 5.0 (tested through 6.1.2)
* If you want support for HEIF/HEIC or AVIF images:
* libheif >= 1.3 (1.7 required for AVIF support, 1.16 required for
correct orientation support, tested through 1.17.6)
* libheif >= 1.11 (1.16 required for correct orientation support and
1.17 required for monochrome HEIC support; tested through 1.22.0)
* libheif must be built with an AV1 encoder/decoder for AVIF support.
* Avoid libheif 1.10 on Mac, it is very broken. Libheif 1.11+ is fine.
* If you want support for DICOM medical image files:
* DCMTK >= 3.6.1 (tested through 3.6.8)
* DCMTK >= 3.6.1 (tested through 3.7.0)
* If you want support for WebP images:
* WebP >= 0.6.1 (tested through 1.3.2)
* If you want support for OpenColorIO color transformations:
* OpenColorIO >= 1.1 (tested through 2.3; 2.0+ is recommended)
* WebP >= 1.1 (tested through 1.6)
* If you want support for Ptex:
* Ptex >= 2.3.1 (probably works for older; tested through 2.4.2)
* Ptex >= 2.3.1 (probably works for older; tested through 2.5)
* If you want to be able to do font rendering into images:
* Freetype (minimum unknown, tested 2.8 through 2.13)
* Freetype >= 2.10.0 (tested through 2.14)
* If you want to be able to read "ultra-HDR" embedded in JPEG files:
* libultrahdr >= 1.3 (tested through 1.4)
* If you want support for JPEG XL images:
* libjxl >= 0.10.1 (tested through 0.12.0)
* If you want support for j2c files:
* OpenJPH >= 0.21.2 (tested through 0.30)
* We use PugiXML for XML parsing. There is a version embedded in the OIIO
tree, but if you want to use an external, system-installed version (as
may be required by some software distributions with policies against
embedding other projects), then just build with `-DUSE_EXTERNAL_PUGIXML=1`.
Any PugiXML >= 1.8 should be fine (we have tested through 1.14).
Any PugiXML >= 1.11 should be fine (we have tested through 1.16).
@@ -154,6 +163,12 @@ Make wrapper (`make PkgName_ROOT=...`).
`USE_PYTHON=0` : Omits building the Python bindings.
`OIIO_PYTHON_BINDINGS_BACKEND=pybind11|nanobind|both` : Select which Python
binding backend(s) to configure for source/CMake builds. `both` keeps the
existing pybind11 module and also builds the nanobind (WIP) module. The
Python packaging path driven by `pyproject.toml` still targets the production
pybind11 bindings today.
`OIIO_BUILD_TESTS=0` : Omits building tests (you probably don't need them
unless you are a developer of OIIO or want to verify that your build
passes all tests).
@@ -182,11 +197,11 @@ Building OpenImageIO on Linux or OS X
The following dependencies must be installed to build the core of
OpenImageIO:
* Boost
* libjpeg
* libtiff
* libpng
* OpenEXR.
* Imath
* OpenEXR
These can be installed using the standard package managers on your system.
Optionally, to build the image viewing tools, you will need Qt and OpenGL.
@@ -235,19 +250,21 @@ Make targets you should know about:
Additionally, a few helpful modifiers alter some build-time options:
| Target | Command |
| ------------------------- | ---------------------------------------------- |
| make VERBOSE=1 ... | Show all compilation commands |
| make STOP_ON_WARNING=0 | Do not stop building if compiler warns |
| make EMBEDPLUGINS=0 ... | Don't compile the plugins into libOpenImageIO |
| make USE_OPENGL=0 ... | Skip anything that needs OpenGL |
| make USE_QT=0 ... | Skip anything that needs Qt |
| make MYCC=xx MYCXX=yy ... | Use custom compilers |
| make USE_PYTHON=0 ... | Don't build the Python binding |
| make BUILD_SHARED_LIBS=0 | Build static library instead of shared |
| make LINKSTATIC=1 ... | Link with static external libraries when possible |
| make SOVERSION=nn ... | Include the specified major version number in the shared object metadata |
| make NAMESPACE=name | Wrap everything in another namespace |
| Target | Command |
| ----------------------------- | ------------------------------------------------------------------------- |
| make VERBOSE=1 ... | Show all compilation commands |
| make STOP_ON_WARNING=0 | Do not stop building if compiler warns |
| make EMBEDPLUGINS=0 ... | Don't compile the plugins into libOpenImageIO |
| make USE_OPENGL=0 ... | Skip anything that needs OpenGL |
| make USE_QT=0 ... | Skip anything that needs Qt |
| make MYCC=xx MYCXX=yy ... | Use custom compilers |
| make USE_PYTHON=0 ... | Don't build the Python binding |
| make OIIO_PYTHON_BINDINGS_BACKEND=both ... | For source/CMake builds, build the existing pybind11 bindings and the nanobind (WIP) module |
| make BUILD_SHARED_LIBS=0 | Build static library instead of shared |
| make IGNORE_HOMEBREWED_DEPS=1 | Ignore homebrew-managed dependencies |
| make LINKSTATIC=1 ... | Link with static external libraries when possible |
| make SOVERSION=nn ... | Include the specified major version number in the shared object metadata |
| make NAMESPACE=name | Wrap everything in another namespace |
The command 'make help' will list all possible options.
@@ -278,68 +295,71 @@ Building on Windows
You will need to have Git, CMake and Visual Studio installed.
The minimal set of dependencies for OIIO is: Boost, zlib, libTIFF, OpenEXR, and libjpeg or libjpeg-turbo. If you have them built somewhere then you skip
the section below, and will only have to point OIIO build process so their locations.
The minimal set of dependencies for OIIO is: zlib, libTIFF, Imath, OpenEXR,
OpenColorIO, and libjpeg or libjpeg-turbo. If you have them built somewhere
then if you set the environment variable `CMAKE_PREFIX_PATH` to include those
areas so CMake will find them, the OpenImageIO build will find those pre-built
packages and use them. If you don't have them build, or are unsure, the
`OpenImageIO_BUILD_MISSING_DEPS=all` CMake option will cause the build process
to download the sources of those dependencies, build them, and use them.
* Boost: get the boost source archive, extract into `{BOOST_ROOT}`.
```
cd {BOOST_ROOT}
bootstrap
b2
```
* zlib: this will build it, and then delete the non-static library, so they don't get picked up:
```
cd {ZLIB_ROOT}
git clone https://github.com/madler/zlib .
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=.
cmake --build build --config Release --target install
del build\lib\zlib.lib
```
* libTIFF:
```
cd {TIFF_ROOT}
git clone https://gitlab.com/libtiff/libtiff.git .
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=.
cmake --build build --target install
```
* libjpeg-turbo:
```
cd {JPEG_ROOT}
git clone https://github.com/libjpeg-turbo/libjpeg-turbo .
mkdir build
cd build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=.
cmake --build build --config Release --target install
```
* OpenEXR: you'll have to point it to your `{ZLIB_ROOT}` location from the above. If copy-pasting the multi-line command (with lines ending in `^`) into
cmd.exe prompt, make sure to copy all the lines at once.
```
cd {EXR_ROOT}
git clone https://github.com/AcademySoftwareFoundation/openexr .
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=dist ^
-DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DOPENEXR_BUILD_TOOLS=OFF ^
-DOPENEXR_INSTALL_TOOLS=OFF -DOPENEXR_INSTALL_EXAMPLES=OFF ^
-DZLIB_ROOT={ZLIB_ROOT}\build
cmake --build build --target install --config Release
```
To build OpenImageIO, you first need to clone the OIIO repository
and check out the desired branch or tag:
Now get the OIIO source and do one-time CMake configuration step. Replace `{*_ROOT}` below with folders where you have put the 3rd party
dependencies.
```
cd {OIIO_ROOT}
git clone https://github.com/AcademySoftwareFoundation/OpenImageIO .
cmake -S . -B build -DVERBOSE=ON -DCMAKE_BUILD_TYPE=Release ^
-DBoost_USE_STATIC_LIBS=ON -DBoost_NO_WARN_NEW_VERSIONS=ON -DBoost_ROOT={BOOST_ROOT} ^
-DZLIB_ROOT={ZLIB_ROOT}\build ^
-DTIFF_ROOT={TIFF_ROOT}\build ^
-DOpenEXR_ROOT={EXR_ROOT}\build\dist ^
-DImath_DIR={EXR_ROOT}\build\dist\lib\cmake\Imath ^
-DJPEG_ROOT={JPEG_ROOT}\build ^
-DUSE_PYTHON=0 -DUSE_QT=0 -DBUILD_SHARED_LIBS=0 -DLINKSTATIC=1
git checkout release
```
This will produce `{OIIO_ROOT}/build/OpenImageIO.sln` that can be opened in Visual Studio IDE. Note that the solution will be
only for the Intel x64 architecture only; and will only target "min-spec" (SSE2) SIMD instruction set.
OIIO_ROOT is the directory where you want to place the OIIO source code.
Note the `git checkout release` line. There are a few choices here:
- `release` - always will be the latest stable supported release, which is the
recommended choice for most users.
- `v3.0.3.0` - a specific release version, which is the recommended choice for
most users who want to use a specific version of OIIO. Note that this is
just an example, and by the time you are reading these instructions, it will
likely be out of date. Adjust the version number to match the one you want.
Note that `release` is a shortcut for the latest stable release, if you
aren't sure which version you want.
- `main` - the latest development version, which may be unstable, but is
probably what you want if you are a developer and are working on new
contributions to OIIO.
Next, you need to do the "cmake configure" step:
```
cmake -S . -B build -DOpenImageIO_BUILD_MISSING_DEPS=all ^
-DBUILD_SHARED_LIBS=0 -DLINKSTATIC=1
```
If that command succeeds, you can either do the full build and install
from the command line, or open the generated Visual Studio solution.
Note that you can speed up the build by disabling certain components if you
know you won't need them: Adding `-DUSE_PYTHON=0` to the command above will
skip building the Python bindings, `-DUSE_QT=0` will disable looking for and
using Qt (needed only for the `iv` viewer), and `-DOIIO_BUILD_TESTS=0` will
skip building certain unit tests (which you only need if you want to OIIO's
tests).
If you just want a one-step build/install from the command line, you can run:
```
cmake --build build --target install --config Release
```
and that will build the package and install it into the `{OIIO_ROOT/dist`
area. (If you instead wanted the install to end up elsewhere, the easiest way
is on the earlier config step, to add the option
`-DCMAKE_INSTALL_PREFIX=somewhere_else`.)
On the other hand, if you would prefer to open the generated Visual Studio
solution, the "cmake configure" will have produced
`{OIIO_ROOT}/build/OpenImageIO.sln` that can be opened in Visual Studio IDE.
Note that the solution will be only for the Intel x64 architecture only; and
will only target "min-spec" (SSE2) SIMD instruction set.
Optional packages that OIIO can use (e.g. libpng, Qt) can be build and pointed to OIIO build process in a similar way.
@@ -366,6 +386,57 @@ produce a dynamic-linked version.
3. Execute the PowerShell command from where vcpkg is located in directory. ``vcpkg install openimageio``
**Note: Importing the OpenImageIO Python Module**
As of OpenImageIO 3.0.3.0, the default DLL-loading behavior for Python 3.8+ has changed.
If you've built OIIO from source and ``import OpenImageIO`` is throwing a ModuleNotFound exception, revert to the legacy DLL-loading behavior by setting environment variable
``OPENIMAGEIO_PYTHON_LOAD_DLLS_FROM_PATH=1``.
Python-based Builds and Installs
--------------------------------
**Installing from prebuilt binary distributions**
If you're only interested in the Python module and the CLI tools, you can install with `pip` or `uv`:
> ```pip install OpenImageIO```
**Building and installing from source**
If you have a C++ compiler installed, you can also use the Python build-backend to compile and install
from source by navigating to the root of the repository and running: ```pip install .```
This will download and install CMake and Ninja if necessary, and invoke the CMake build system; which,
in turn, will build missing dependencies, compile OIIO, and install the Python module, the libraries,
the headers, and the CLI tools to a platform-specific, Python-specific location.
See the [scikit-build-core docs](https://scikit-build-core.readthedocs.io/en/latest/configuration.html#configuring-cmake-arguments-and-defines)
for more information on customizing and overriding build-tool options and CMake arguments.
This repo contains python type stubs which are generated from `pybind11` signatures.
The workflow for releasing new stubs is as follows:
- Install [`uv`](https://docs.astral.sh/uv/getting-started/installation/) and `docker`
- Run `make pystubs` locally to generate updated stubs in `src/python/stubs/__init__.pyi`
- Run `make test-pystubs` locally to use mypy to test the stubs against the code in
the python testsuite.
- Commit the new stubs and push to Github
- In CI, the stubs will be included in the wheels built by `cibuildwheel`, as defined in `.github/wheel.yml`
- In CI, one of the `cibuildwheel` Github actions will rebuild the stubs to a
temp location and verify that they match what has been committed to the repo.
This step ensures that if changes to the C++ source code and bindings results
in a change to the stubs, developers are notified of the need to regenerate
the stubs, so that changes can be reviewed and the rules in `generate_stubs.py`
can be updated, if necessary.
Note that if you can't (or don't want to) build the stubs locally, you can
download an artifact containing the wheel and `__init__.pyi` file from any job
that fails the stub validation.
Test Images
-----------
@@ -389,3 +460,7 @@ You do not need any of these packages in order to build or use
OpenImageIO. But if you are going to contribute to OpenImageIO
development, you probably want them, since it is required for executing
OpenImageIO's test suite (when you run "make test").
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
-27
View File
@@ -1,27 +0,0 @@
Copyright (c) 2008-present by Contributors to the OpenImageIO project.
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+18 -21
View File
@@ -79,10 +79,6 @@ ifneq (${OPENEXR_ROOT},)
MY_CMAKE_FLAGS += -DOPENEXR_ROOT:STRING=${OPENEXR_ROOT}
endif
ifneq (${ILMBASE_ROOT},)
MY_CMAKE_FLAGS += -DILMBASE_ROOT:STRING=${ILMBASE_ROOT}
endif
ifneq (${NUKE_VERSION},)
MY_CMAKE_FLAGS += -DNUKE_VERSION:STRING=${NUKE_VERSION}
endif
@@ -163,7 +159,7 @@ MY_CMAKE_FLAGS += -DTEX_BATCH_SIZE:STRING="${TEX_BATCH_SIZE}"
endif
ifneq (${TEST},)
TEST_FLAGS += -R ${TEST}
TEST_FLAGS += -R '${TEST}'
endif
ifneq (${USE_CCACHE},)
@@ -184,10 +180,6 @@ ifeq (${CODECOV},1)
MY_CMAKE_FLAGS += -DCODECOV:BOOL=${CODECOV}
endif
ifneq (${SANITIZE},)
MY_CMAKE_FLAGS += -DSANITIZE=${SANITIZE}
endif
ifneq (${CLANG_TIDY},)
MY_CMAKE_FLAGS += -DCLANG_TIDY:BOOL=1
endif
@@ -210,11 +202,6 @@ ifneq (${CLANG_FORMAT_EXCLUDES},)
MY_CMAKE_FLAGS += -DCLANG_FORMAT_EXCLUDES:STRING=${CLANG_FORMAT_EXCLUDES}
endif
ifneq (${BUILD_MISSING_DEPS},)
MY_CMAKE_FLAGS += -DBUILD_MISSING_DEPS:BOOL=${BUILD_MISSING_DEPS}
endif
#$(info MY_CMAKE_FLAGS = ${MY_CMAKE_FLAGS})
#$(info MY_MAKE_FLAGS = ${MY_MAKE_FLAGS})
@@ -256,6 +243,18 @@ build: config
${CMAKE} --build . --config ${CMAKE_BUILD_TYPE} \
)
# generate python stubs and add them to the repo
pystubs: config
@ ( cd ${build_dir} ; \
${CMAKE} --build . --config ${CMAKE_BUILD_TYPE} --target pystubs \
)
# run mypy on python tests to confirm the stubs are working
test-pystubs: pystubs
@ ( uv export --quiet --no-dev --no-build --no-emit-project --no-hashes -o ${build_dir}/requirements.txt ; \
uvx --with-requirements ${build_dir}/requirements.txt mypy==1.15.0 \
)
# 'make install' builds everthing and installs it in 'dist'.
# Suppress pointless output from docs installation.
install: build
@@ -294,7 +293,7 @@ test: build
@ ${CMAKE} -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests ${TEST_FLAGS}..."
@ ( cd ${build_dir} ; \
PYTHONPATH=${PWD}/${build_dir}/lib/python/site-packages \
ctest -E broken ${TEST_FLAGS} \
ctest ${TEST_FLAGS} \
)
@ ( if [[ "${CODECOV}" == "1" ]] ; then \
cd ${build_dir} ; \
@@ -356,7 +355,7 @@ help:
@echo " VERBOSE=1 Show all compilation commands"
@echo " STOP_ON_WARNING=0 Do not stop building if compiler warns"
@echo " MYCC=xx MYCXX=yy Use custom compilers"
@echo " CMAKE_CXX_STANDARD=14 C++ standard to build with (default is 17)"
@echo " CMAKE_CXX_STANDARD=20 C++ standard to build with (default is 17)"
@echo " USE_LIBCPLUSPLUS=1 For clang, use libc++"
@echo " GLIBCXX_USE_CXX11_ABI=1 For gcc, use the new string ABI"
@echo " EXTRA_CPP_ARGS= Additional args to the C++ command"
@@ -364,7 +363,7 @@ help:
@echo " USE_CCACHE=0 Disable ccache (even if available)"
@echo " UNITY=BATCH Do a 'Unity' build (BATCH or GROUP or nothing)"
@echo " CODECOV=1 Enable code coverage tests"
@echo " SANITIZE=name1,... Enable sanitizers (address, leak, thread)"
@echo " SANITIZE=name1,... Enable sanitizers (address, leak, thread, undefined)"
@echo " CLANG_TIDY=1 Run clang-tidy on all source (can be modified"
@echo " by CLANG_TIDY_ARGS=... and CLANG_TIDY_FIX=1"
@echo " CLANG_FORMAT_INCLUDES=... CLANG_FORMAT_EXCLUDES=..."
@@ -383,16 +382,15 @@ help:
@echo " LibRaw OpenColorIO OpenCV OpenGL OpenJpeg OpenVDB"
@echo " PTex R3DSDK TBB TIFF Webp"
@echo " Finding and Using Dependencies:"
@echo " BOOST_ROOT=path Custom Boost installation"
@echo " OPENEXR_ROOT=path Custom OpenEXR installation"
@echo " ILMBASE_ROOT=path Custom IlmBase installation"
@echo " USE_EXTERNAL_PUGIXML=1 Use the system PugiXML, not the one in OIIO"
@echo " USE_QT=0 Skip anything that needs Qt"
@echo " USE_PYTHON=0 Don't build the Python binding"
@echo " PYTHON_VERSION=2.6 Specify the Python version"
@echo " PYTHON_VERSION=3.9 Specify the Python version"
@echo " USE_NUKE=0 Don't build Nuke plugins"
@echo " Nuke_ROOT=path Custom Nuke installation"
@echo " NUKE_VERSION=ver Custom Nuke version"
@echo " IGNORE_HOMEBREWED_DEPS=1 Don't use dependencies installed by Homebrew"
@echo " OIIO build-time options:"
@echo " INSTALL_PREFIX=path Set installation prefix (default: ./${INSTALL_PREFIX})"
@echo " NAMESPACE=name Override namespace base name (default: OpenImageIO)"
@@ -405,7 +403,6 @@ help:
@echo " 0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
@echo " avx, avx2, avx512f)"
@echo " TEX_BATCH_SIZE=16 Override TextureSystem SIMD batch size"
@echo " BUILD_MISSING_DEPS=1 Try to download/build missing dependencies"
@echo " make test, extra options:"
@echo " TEST=regex Run only tests matching the regex"
@echo ""
+36 -17
View File
@@ -4,7 +4,7 @@
<img src="ASWF/logos/openimageio-horizontal-gradient.png">
</p>
[![License](https://img.shields.io/badge/license-Apache2.0-blue.svg?style=flat-square)](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/LICENSE.md)
[![License](https://img.shields.io/badge/license-Apache2.0-blue.svg?style=flat-square)](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/LICENSE.md)
[![CI](https://github.com/AcademySoftwareFoundation/OpenImageIO/actions/workflows/ci.yml/badge.svg)](https://github.com/AcademySoftwareFoundation/OpenImageIO/actions/workflows/ci.yml)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2694/badge)](https://bestpractices.coreinfrastructure.org/projects/2694)
[![latest packaged version(s)](https://repology.org/badge/latest-versions/openimageio.svg)](https://repology.org/project/openimageio/versions)
@@ -80,7 +80,7 @@ For original code, we use the [Apache-2.0 license](LICENSE.md), and for
documentation, the [Creative Commons Attribution 4.0 Unported
License](http://creativecommons.org/licenses/by/4.0/). In 2023 we asked
historical users to [relicense](RELICENSING.md) from the original BSD-3-clause
license to Apache-2.0, and over 99.75% of lines of code have been relicensed
license to Apache-2.0, and over 99.86% of lines of code have been relicensed
to Apache-2.0. A small amount of code incorporated into this repository from
other projects are covered by compatible [third-party open source
licenses](THIRD-PARTY.md).
@@ -88,7 +88,7 @@ licenses](THIRD-PARTY.md).
The OpenImageIO project is part of the [Academy Software
Foundation](https://www.aswf.io/), a part of the Linux Foundation formed in
collaboration with the Academy of Motion Picture Arts and Sciences. The
[Technical Charter](aswf/Technical-Charter.md) and [Project
[technical charter](https://github.com/AcademySoftwareFoundation/foundation/blob/main/project_charters/openimageio_charter.pdf) and [Project
Governance](GOVERNANCE.md) explain how the project is run, who makes
decisions, etc. Please be aware of our [Code of Conduct](CODE_OF_CONDUCT.md).
@@ -96,11 +96,17 @@ decisions, etc. Please be aware of our [Code of Conduct](CODE_OF_CONDUCT.md).
💁 User Documentation
---------------------
[OpenImageIO Documentation on ReadTheDocs](https://openimageio.readthedocs.io/)
[OpenImageIO Documentation](https://docs.openimageio.org)
is the best place to start if you are interested in how to use OpenImageIO,
its APIs, its component programs (once they are built). There is also a [PDF
version](https://readthedocs.org/projects/openimageio/downloads/pdf/latest/).
Additional resources:
- [User quick start](docs/QuickStart.md) is a quick example of using
OpenImageIO in Python, C++, and the command line.
- [Releases](https://github.com/AcademySoftwareFoundation/OpenImageIO/releases) -- see this for the latest release notes, also found in the [CHANGES.md](CHANGES.md) file.
👷 Building and installing OpenImageIO
--------------------------------------
@@ -118,35 +124,48 @@ it and potentially be able to answer your question quickly (more so than a GH
"issue"). For quick questions, you could also try the [ASWF
Slack](https://slack.aswf.io) `#openimageio` channel.
Bugs, build problems, and discovered vulnerabilities that you are relatively
certain is a legit problem in the code, and **for which you can give clear
instructions for how to reproduce**, should be [reported as
A bug or build problem that you are relatively certain is a legit problem in
the code, and **for which you can give clear instructions for how to
reproduce**, should be [reported as
issues](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues).
To report a security vulnerability that is serious enough that it should not
be discussed publicly until a patch is ready, please file a GitHub [security
advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/new).
If confidentiality precludes a public question or issue, you may contact us
privately at [info@openimageio.org](info@openimageio.org), or for
security-related issues [security@openimageio.org](security@openimageio.org).
privately at [info@openimageio.org](mailto:info@openimageio.org), or for
security-related issues [security@openimageio.org](mailto:security@openimageio.org).
🔧 Contributing and developer documentation
-------------------------------------------
OpenImageIO welcomes code contributions, and [nearly 200 people](CREDITS.md)
OpenImageIO welcomes code contributions, and [nearly 250 people](CREDITS.md)
have done so over the years. We take code contributions via the usual GitHub
pull request (PR) mechanism.
* [Architecture overview](docs/dev/Architecture.md) is a high-level
description of the major classes and their relationships.
* [CONTRIBUTING](CONTRIBUTING.md) has detailed instructions about the
development process.
* [AI Policy](docs/dev/AI_Policy.md) decribes our policies on AI coding
assistance tools.
* [ROADMAP](docs/ROADMAP.md) is a high-level overview of the current
development priorities for the next annual release, expected in September,
2024.
* [RELEASING](RELEASING.md) explains our policies and procedures for making
releases. We have a major, possibly-compatibility-breaking, release annually
in September/October, and minor bug fix and safe feature addition release at
the beginning of every month.
development priorities for the next annual release.
* [RELEASING](docs/dev/RELEASING.md) explains our policies and procedures for
making releases. We have a major, possibly-compatibility-breaking, release
annually in September/October, and minor bug fix and safe feature addition
release at the beginning of every month.
* [Building the docs](src/doc/Building_the_docs.md) has instructions for
building the documentation locally, which may be helpful if you are editing
the documentation in nontrivial ways and want to preview the appearance.
* Other developer documentation is in the [docs/dev](docs/dev) directory.
* You may also have luck learning a bit about the organization and
architecture of the project by reading the [DeepWiki Analysis of
OpenImageIO](https://deepwiki.com/AcademySoftwareFoundation/OpenImageIO).
But take it with a grain of salt -- like any LLM-generated summary, there
may be inaccuracies lurking.
☎️ Communications channels and additional resources
@@ -157,5 +176,5 @@ pull request (PR) mechanism.
* [Developer mail list](https://lists.aswf.io/g/oiio-dev)
* [ASWF Slack](https://slack.aswf.io) (look for the `#openimageio` channel)
* Biweekly Technical Steering Committee (TSC) Zoom meetings are on the [ASWF
Calendar](https://www.aswf.io/meeting-calendar/) (click on the OpenImageIO
Calendar](https://calendar.openimageio.org) (click on the OpenImageIO
meeting entries, every second Monday, to get the Zoom link, anyone may join)
+14 -3
View File
@@ -1,8 +1,15 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
New code entering the OpenImageIO repository from July 1 2023 onward is
subject to the [Apache 2.0 license](LICENSE.md).
Code dating from earlier than July 1 2023 was contributed under the [BSD
3-clause license](LICENSE-BSD-3-Clause.md), unless relicensed below.
3-clause license](https://opensource.org/license/bsd-3-clause), unless
relicensed below.
Stragglers who haven't relicensed yet, it's never too late, just sign onto the
PR: https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3905
The following copyright holders agree that all of their contributions
originally submitted to this project under the 3-Clause BSD License are hereby
@@ -137,9 +144,13 @@ the Developer Certificate of Origin, version 1.1:
- Damien Courtois (ix-dcourtois)
- Carl Rand (crand)
- Gregor Mückl (gmueckl)
- Jep Hill (jephill)
- John Haddon (johnhaddon)
...
**Prior authors, please submit a PR against this file that adds your name
above. If, at the time of your prior contributions, you were employed by a
**Prior authors, please follow the directions for adding your name to
[this PR](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3905).
If, at the time of your prior contributions, you were employed by a
company who would have owned your IP output, then please have someone from
that company who is authorized to do so submit a PR to add their company’s
name to the list under the statement in this file.**
+123 -10
View File
@@ -7,19 +7,132 @@ security vulnerabilities.
| Version / branch | Supported |
| ----------------- | ---------------------------------------------------- |
| master | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
| 2.5.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
| 2.4.x | :warning: Only receives occasional critical fixes, upon request, only if they can be easily backported. |
| <= 2.3.x | :x: No longer receiving patches of any kind. |
| main | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
| 3.1.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
| 3.0.x | :warning: Important fixes that can be easily backported without breaking ABI compatibility. New tagged releases as needed, and becoming less frequent over time. |
| <= 2.5.x | :x: No longer receiving patches of any kind. |
## Reporting a Vulnerability
If you think you've found a potential vulnerability in OpenImageIO, please
report it by emailing security@openimageio.org. Only the project administrators
have access to these messages. Include detailed steps to reproduce the issue,
and any other information that could aid an investigation. Our policy is to
respond to vulnerability reports within 14 days.
report it to the maintainers. Include detailed steps to reproduce the issue,
and any other information that could aid an investigation.
Our policy is to address critical security vulnerabilities rapidly and post
patches as quickly as possible.
The best way to report a vulnerability is to file a GitHub [security
advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/new).
If that is not possible, it is also fine to email your report to
security@openimageio.org. Only the project administrators have access to these
reports.
Our policy is to respond to vulnerability reports within 14 days, and to
address critical security vulnerabilities rapidly and post patches quickly,
usually at the next scheduled patch release at the beginning of every month.
For especially severe vulnerabilities, or when a flaw is believed to be
exploited in the wild, we will try to make a special patch release as soon as
possible.
## What do we consider a vulnerability?
A true vulnerability, by our definition, requires the following:
- It allows arbitrary code execution, privilege escalation, exfiltration of
secrets beyond network boundaries, destruction of data or equipment, or
similarly serious outcome.
- It can be plausibly exploited by an untrusted party through normal product
inputs (for example, a maliciously crafted input image).
We would like to hear about these through the confidential GitHub
vulnerability reporting mechanism described above.
The following are examples of problems that we DO NOT consider
vulnerabilities:
- A crash or program termination that does not directly present the
opportunity for further exploits. This includes hardening assertions that
terminate the program rather than allow undefined behavior.
- Out-of-memory errors, as long as the program terminates in a reasonable
amount of time. (But if a tiny crafted input can make it loop infinitely or
spin for minutes, then it might qualify as a DOS vulnerability. Use your
best judgment.)
- Misuse or incorrect use of the APIs. We consider all programs directly using
OIIO's APIs to be trusted.
- Flaws whose root cause lies in a dependency. These should be reported and
fixed upstream; the upstream project owns the CVE when one is warranted.
Please do not use the GitHub vulnerability reporting mechanism for these, and
instead file ordinary Issues and PRs. We do not support requesting a CVE for
these kinds of problems.
Users operating in an environment in which it might encounter untrusted inputs
that could be malicious, and are be running in a situation where real damage
could occur are expected to:
- Enable all the OpenImageIO build-time options for safety checks, hardening,
etc. A problem that only occurs when these are disabled is not considered a
vulnerability.
- Ensure that all the dependencies OIIO builds against are on their latest
patched versions, and not rely on the OS distribution default, or even
OIIO's own "dependency auto-build" scripts. A problem that depends on
having anything but the lastest dependencies is not an OIIO vulnerbility.
## Other security features
### Signed tags
Starting with OpenImageIO 3.0, we cryptographically sign release tags.
To verify a tag, you can use the `git tag -v` command, which will check
the signature against the public key that is included in the repository.
For example,
```bash
git tag -v v3.0.0.3
```
## Outstanding Security Issues
None known
## History of CVE Fixes
Most recent fixes listed first, more or less:
- CVE-2026-63638: Cineon invalid bit depth heap out-of-bounds write [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-9hxv-jvgr-3x8g) / [Fix: PR #5283](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5283) (fixed in 3.1.16.0)
- CVE-2026-63635: PSD RawColor invalid color mode causes global out-of-bounds read and allocation DoS [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-3c8w-9xvm-r6gf) / [Fix: PR #5282](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5282) (fixed in 3.1.16.0)
- CVE-2026-63635: PSD RawColor invalid color mode causes global out-of-bounds read and allocation DoS [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-3c8w-9xvm-r6gf) / [Fix: PR #5282, 3.1.16.0](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5282) (fixed in 3.1.16.0)
- CVE-2026-63422 OpenEXR plugin partial edge tile heap out-of-bounds write [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-xh5r-whph-qmc5) / [Fix: PR #5295](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5295) (fixed in 3.1.16.0)
- CVE-2026-63420: PSD RawColor indexed image out-of-bounds read in `interleave_row` [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-x877-h4xx-5m5j) / [Fix: PR #5307](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5307) (fixed in 3.1.16.0)
- CVE-2026-63419: OpenImageIO IFF ZBUFFER tile read writes past caller tile buffer [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-w6wc-gcf4-5pj2) / [Fix: PR #5268](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5268) (fixed in 3.1.16.0)
- CVE-2026-59956: Heap-buffer-overread in IffInput::readimg() when ZBUFFER flag is set [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-hjfv-gvxc-qgvh) / [Fix: PR #5251](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5251) (fixed in 3.0.20.0, 3.1.15.0)
- CVE-2026-59181: Stack buffer overflow in OpenImageIO Cineon reader via unchecked numberOfElements [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-xh8r-vmqq-56pp) / [Fix: PR #5250](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5250) (fixed in 3.0.20.0, 3.1.15.0)
- CVE-2026-59156: Unbounded recursion in FITS header parser leads to stack overflow [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-xvwr-x6ch-v2fq) / [Fix: PR #5248](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5248) (fixed in 3.0.20.0, >= 3.1.15.0)
- CVE-2026-50291: Segmentation Fault in BmpInput::read_native_scanline / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-q3c7-3225-66h7) / [Fix: PR #5030](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5030) (Fixed in 3.0.16.0, 3.1.11.0)
- CVE-2026-43909: Signed integer overflow in SwapRGBABytes loop index leads to out-of-bounds read/write in DPX ABGR decoder / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-g267-j53j-5258) / [Fix: PR5170](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5170) (Fixed in 3.0.18.1, 3.1.13.1)
- CVE-2026-43908: Signed integer overflow in ConvertCbYCrYToRGB leads to heap out-of-bounds write in DPX 4:2:2 decoder / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-2jr5-q49v-3858) / [Fix: PR5170](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5170) (Fixed in 3.0.18.1, 3.1.13.1)
- CVE-2026-43907: Integer overflow in QueryRGBBufferSizeInternal leads to heap out-of-bounds write in DPX decoder (kCbYCr and kABGR) / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-cq46-hp4h-cvfr) / [Fix: PR5170](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5170) (Fixed in 3.0.18.1, 3.1.13.1)
- CVE-2026-43996: Integer wraparound in bounds check of decode_pixel leads to out-of-bounds read in TGA paletted image decoder / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-mq8j-73c4-cr55) / [Fix: PR5165](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5165) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2026-43906: HEIF Heap overflow / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-gmrp-x952-3m66) / [Fix: PR5166](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5166) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2026-43905: JPEG2000 (OpenJPH) signed integer overflow in buffer allocation / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-pj45-cf3g-28gq) / [Fix: PR5143](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5143) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2026-43904: Softimage PIC RLE decoder heap buffer overflow — longCount not clamped to image width / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-4499-j545-7q33) / [Fix: PR5142](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5142) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2026-43903: SGI RLE decoder heap buffer overflow — OIIO_DASSERT bounds checks are no-ops in release builds / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-jg3q-vm3q-2j35) / [#5141](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5141) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2026-7582: DDS Image ddsinput.cpp out-of-bounds write / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-5pm7-8r3j-2x67). [Fix: #5131](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/5131) (Fixed in 3.2.0.1, 3.1.13.0, 3.0.18.0)
- CVE-2024-55194: Broken pgm had memory access error leading to heap overflow / [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-583r-43f7-cw8w) / [#4559](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4559) (Fixed in 3.0.2.0, 3.1.4.0)
- CVE-2024-40630: Fixed incorrect image size for certain HEIC files.
[advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-jjm9-9m4m-c8p2) (Fixed in 2.5.13.1)
- CVE-2023-42295: Fix signed integer overflow when computing total number of pixels while reading BMP files. [#3948](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3948) (by xiaoxiaoafeifei) (Fixed in 2.5.3.0/2.6.0.1)
- CVE-2023-36183: Heap-buffer-overflow while reading ICO files [#3872](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3872) (by xiaoxiaoafeifei)
- TALOS-2023-1709 / CVE-2023-24472: Race condition in TIFF reader. [#3772](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3772) (2.5.1.0/2.4.8.1)
- TALOS-2023-1707 / CVE-2023-24473, TALOS-2023-1708 / CVE-2023-22845: Guard against corrupted Targa. [#3768](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3768) (2.5.1.0/2.4.8.1)
- TALOS-2022-1654 / CVE-2022-43596, TALOS-2022-1655 / CVE-2022-43597 CVE-2022-43598, TALOS-2022-1656 / CVE-2022-43599 CVE-2022-43600 CVE-2022-43601 CVE-2022-43602: Fix possible IFF write errors [#3676](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3676) (2.4.6/2.5.0.0)
- TALOS-2022-1653 / CVE-2022-43594: Fix possible errors when writing BMP files. [#3673](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3673) (by lgritz) (2.4.6/2.5.0.0)
- TALOS-2022-1651 / CVE-2022-43592, TALOS-2022-1652 / CVE-2022-4359: Fix possible DPX write errors. [#3672](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3672) (2.4.6/2.5.0.0)
- TALOS-2022-1657 / CVE-2022-43603: Zfile write safety. [#3670](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3670) (2.4.6/2.5.0.0)
- TALOS-2022-1633 / CVE-2022-41639, TALOS-2022-1643 / CVE-2022-41988: Guard TIFF against buffer overflow for certain CMYK files. [#3632](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3632) (2.4.5/2.5.0.0)
- TALOS-2022-1626, CVE-2022-41794: PSD files protect against corrupted embedded thumbnails. [#3629](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3629) (2.4.5/2.5.0.0)
- TALOS-2022-1627, CVE-2022-41977: Guard TIFF reads against corrupt files with buffer overflows. [#3628](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3628) (2.4.5/2.5.0.0)
- TALOS-2022-1626 / CVE-2022-41794, TALOS-2022-1632 / CVE-2022-41684, TALOS-2022-1636 / CVE-2022-41837: Exif (all formats that support it, TIFF/JPEG/PSD) fix bugs where corrupted Exif blocks could overrun memory. [#3627](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3627) (2.4.5/2.5.0.0)
- TALOS-2022-1634 / CVE-2022-41838, TALOS-2022-1635 / CVE-2022-41999: Fix DDS reading crashes for cubemap files when a cube face was not present, and check for invalid bits per pixel. [#3625](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3625) (2.4.5/2.5.0.0) #3625 (2.4.5/2.5.0.0)
- TALOS-2022-1629, CVE-2022-36354: RLA potential buffer overrun. [#3624](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3624) (2.4.5/2.5.0.0)
- TALOS-2022-1628, CVE-2022-41981: Targa file string overflow safety. [#3622](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3622) (2.4.5/2.5.0.0)
- TALOS-2022-1630, CVE-2022-38143: Protect against corrupt pixel coordinates while reading BMP files. [#3620](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/3620) (by lgritz) (Fixed in 2.4.5/2.5.0.0)
<!-- - CVE-xxx: description [advisory](https://github.com/AcademySoftwareFoundation/OpenImageIO/security/advisories/GHSA-yyy) / [Fix: PR #nnnn](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/nnnn)
-->
+7 -4
View File
@@ -9,15 +9,15 @@ In no particular order:
-------------------------------------------------------------------------
BSD 3-Clause License
BSD 3-Clause License (https://opensource.org/license/bsd-3-clause)
SPDX-License-Identifier: BSD-3-Clause
* OpenImageIO prior to July 1, 2023
Code that was contributed to OpenImageIO prior to July 1 2023, and has not
yet been [relicensed](RELICENSING.md), was contributed under the [BSD
3-clause license](LICENSE-BSD.md). Currently, this is less than 2% of the
codebase (by lines of code).
yet been [relicensed](RELICENSING.md), was contributed under the BSD
3-clause license. Currently, less than 0.15% of the codebase (by lines of
code) remains under this license.
* Gelato, Copyright (c) 2004 by NVIDIA Corp.
@@ -179,6 +179,9 @@ SPDX-License-Identifier: Apache-2.0
This is licensed under the Apache 2.0 license with LLVM Exceptions.
https://llvm.org/docs/DeveloperPolicy.html#open-source-licensing-terms
* ninjatracing.py utility for build profiling is Apache-2.0 licensed
and comes from https://github.com/nico/ninjatracing.
Copyright 2018 Nico Weber.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+4 -1
View File
@@ -1,9 +1,12 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
[requires]
zlib/1.2.11
libtiff/4.0.9
libpng/1.6.37
openexr/2.4.0
boost/1.70.0
libjpeg/9c
libjpeg-turbo/2.0.2
giflib/5.1.4
@@ -1,6 +1,6 @@
These are all the release notes for versions 0.1 (Sept 2008) - 0.10 (Feb 2012).
For the full release notes of all versions, see:
[CHANGES](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/CHANGES.md).
[CHANGES](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/CHANGES.md).
Release 0.10.5 (20 Feb 2012)
@@ -679,3 +679,7 @@ Initial developer release 0.1 (1 Sep 2008):
* maketx
* API docs for ImageInput, ImageOutput, writing plugins
* Linux and OSX
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
@@ -1,7 +1,7 @@
These are all the release notes for versions 1.0 (Feb 2012) - 1.8 (Dec 2018).
For 0.x releases, see [CHANGES-0.x.md](CHANGES-0.x.md).
For the full release notes of all versions, see:
[CHANGES](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/master/CHANGES.md).
[CHANGES](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/CHANGES.md).
Release 1.8.17 (1 Dec 2018) -- compared to 1.8.16
@@ -4037,3 +4037,9 @@ Developer goodies:
* testtex improvements: --wrap
For older release notes, see:
* [CHANGES-0.x](https://github.com/AcademySoftwareFoundation/OpenImageIO/blob/main/docs/CHANGES-0.x.md).
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+5143
View File
File diff suppressed because it is too large Load Diff
+286
View File
@@ -0,0 +1,286 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
OpenImageIO 3.0 Deprecations
============================
For minor or patch releases, we try very hard to never fully remove
functionality that will force downstream applications using OpenImageIO to
change their source code. However, for major releases (e.g., 2.x -> 3.0),
which only occur once every several years, we allow removal of functionality.
OpenImageIO v3.0 is a major release that includes removal of many
long-deprecated API facets. This document lists the deprecations and removals.
NOTE: This is an in-progress document. Some things currently only warning
about being deprecated will be removed in the final 3.0 release.
### Glossary
- "Marked as deprecated" means that we consider an API facet to be obsolete,
and document it as such in the comments or documentation (or remove it from
the documentation).
- "Deprecation warning" means that a deprecated function is tagged with
attributes that should cause a compiler warning if the function is used. The
warning can be disabled by the downstream project, but it is recommended
that you fix the code to use the new API before it is permanently removed.
- "Removed" means that the deprecated API facet has been removed from the
library completely.
---
---
## argparse.h
* Several long-deprecated old method names now will give deprecation warnings
if used. Most notable are `parse()` (you should use `parse_args()` instead)
and `usage()` (use `print_help()` instead).
## array_view.h
* This header has been eliminated. It originally had the template `array_view`,
which many years ago was renamed `span<>` and lives in span.h, and since then
the array_view.h header has merely made an alias.
## bit.h
* The `bit_cast` template, which was deprecated and warned since 2.5, has been
removed. It was confusing because C++23 has a `std::bit_cast` that used the
reverse order of arguments. Users should instead use `std::bit_cast` (if
C++23) or the equivalent `OIIO::bitcast`.
* The `rotl32` and `rotl64` functions which have been marked as deprecated
since 2.1 now have deprecation warnings. Use `rotl` instead.
## benchmark.h
* The full `time_trial()` function now has deprecation warnings. Users should
generally use the `Benchmrker` class instead.
* The abbreviated `time_trial()` function (that lacks a `repeats` parameter
has been removed.
## color.h
* `ColorConfig::error()` now has a deprecation warning. Use
`ColorConfig::has_error()` instead.
* The versions of `createDisplayTransform()` that lack an `inverse` parameter
now have deprecation warnings. Use the version that takes an `inverse` bool.
## dassert.h
* Poorly named `ASSERT`, `DASSERT`, and `ASSERTMSG` macros have been removed.
They were deprecated since 2.1, since they could easily clash with macros
from other projects. Please instead use the `OIIO_ASSERT`, `OIIO_DASSERT`,
and `OIIO_ASSERT_MSG` macros.
## errorhandler.h
* All of the old methods that did printf-style formatting have been deprecated
(info/infof, warning/warningf, error/errorf, severe/severef,
message/messagef, debug/debugf). Instead, use infofmt, warningfmt, errorfmt,
severefmt, messagefmt, debugfmt, respectively, which all use the std::format
notation.
## imagebuf.h
* Add deprecation warnings to the varieties of ImageBuf constructor and
`reset()` that don't take subimage and miplevel parameters, which have been
marked as deprecated since OIIO 2.2. The equivalent is to just pass `0` for
both of those parameters.
* The misspelled `ImageBuf::make_writeable()` has been given deprecation
warnings. Since OIIO 2.2, we have used the correct spelling,
`make_writable`.
* The `ImageBuf::error()` method that uses printf-style formatting conventions
now has deprecation warnings. Use `ImageBuf::errorfmt()` instead.
* The `ImageBuf::interppixel_NDC_full()` method, which has been marked as
deprecated since OIIO 1.5, now has deprecation warnings. Use
`interppixel_NDC()` instead.
## imageio.h
* The global OIIO::attribute query "opencv_version" has been removed. The
libOpenImageIO library itself no longer has OpenCV as a dependency or links
against it. (However, the IBA functions involving OpenCV still exist and are
defined in `imagebufalgo_opencv.h` as inline functions, so it is up to the
application calling these API functions to find and link against OpenCV.)
* The old varieties of ImageInput::read_scanlines, read_tiles, and read_image
that did not take `subimage` and `miplevel` parameters, and were not
thread-safe, have been removed. These have been marked as deprecated since
OIIO 2.0.
* The type aliases ImageIOParameter and ImageIOParameterList, which have been
marked as deprecated since OIIO 2.0, have been removed. Use ParamValue and
ParamValueList instead.
* The utility functions convert_image and parallel_convert_image (the variety
that took alpha_channel and z_channel arguments) that have been deprecated
since OIIO 2.0 have been removed.
## imagebuf.h
* The style of ImageBuf constructor that "wraps" a caller-owned memory buffer
now has a new, preferred, version that takes a `span<>` or `cspan<>` instead
of a raw pointer. The old versions is considered deprecated.
* New span-based versions of get_pixels, set_pixels, setpixel, getpixel,
interppixel, interppixel_NDC, interppixel_bicubic, interppixel_bicubic_NDC.
These are preferred over the old versions that took raw pointers.
## imagebufalgo.h
* The old versions (deprecated since 2.0) of IBA::compare() and
computePixelStats() that took a reference to the CompareResults or
PixelStats structure now have deprecation warnings. Use the versions that
return the structure instead.
* The deprecated (often since as far back as 2.0) versions of functions that
took raw pointers to color values now have deprecations warnings. Use the
versions that take `span<>` or `cspan<>` instead. These include versions of:
isConstantColor, isConstantChannel, isMonochrome, isConstantChannel,
colorconvert, fill, checker, add, sub, absdiff, mul, div, mad, pow,
channel_sum, channels, clamp, color_count, color_range_check, render_text.
* The `histogram()` function that takes a reference to a result vector
(deprecated since 2.0 and previously warned) has been removed. Use the
version that returns the vector instead. The `histogram_draw()` (deprecated
since 2.0 and previously warned) has been removed and has no replacement
since it was always silly.
* The versions of ociodisplay that lacked an `inverse` parameter, which were
marked as deprecated since 2.5, now have deprecation warnings. Use the
version that takes an `inverse` bool.
* The OpenCV-related functions that take old-style IplImage pointers
(deprecated since 2.0) have been removed. Use the modern ones that use
cv::Mat.
* The pre-KWArgs versions of resize, warp, and fit now have deprecation
warnings. Use the versions that take KWArgs instead.
* The OpenCV-related functions `to_OpenCV()`, `from_OpenCV()`, and
`capture_image()` have moved to the `imagebufalgo_opencv.h` header.
## imagebufalgo_util.h
* IBA::type_merge, deprecated since 2.3, now has a deprecation warning.
Instead, use TypeDesc::basetype_merge().
## imagecache.h
* `ImageCache::create()` now returns a `std::shared_ptr<ImageCache>` instead
of a raw pointer.
## missingmath.h
* This header has been removed entirely. It has was originally needed for
pre-C++11 MSVS, but has been unused since OIIO 2.0 (other than transitively
including fmath.h).
## paramlist.h
* Removed some ParamValue constructor variants that have been deprecated since
OIIO 2.4. The removed variants took an optional `bool` parameter indicating
whether the value was copied. If you need to override the usual copy
behavior, please use the newer variety of constructors that instead use a
"strong" type where you pass `ParamValue:Copy(bool)`.
## parallel.h
* Removed several varieties of `parallel_for` functions where the task
functions took a thread ID argument in addition to the range, which have
been considered deprecated since OIIO 2.3. Please use task functions that do
not take a thread ID parameter.
## platform.h
* Removed macros `OIIO_CONSTEXPR`, `OIIO_CONSTEXPR14`, and
`OIIO_CONSTEXPR_OR_CONST` and deprecated `OIIO_CONSTEXPR17` (use regular C++
`constexpr` in place of all of these). Removed macro `OIIO_NOEXCEPT` (use
C++ `noexcept`).
* Removed macro `OIIO_UNUSED_OK`, which had been deprecated since 2.0. Marked
`OIIO_MAYBE_UNUSED` as deprecated as well, now that C++17 is the minimum,
there's no reason not to directly use the C++ attribute `[[maybe_unused]]`.
## simd.h
* The old (OIIO 1.x) type names float3, float4, float8, int4, int8, mask4,
bool4, bool8 have been removed. Use the new vbool4, vint4, vfloat4, etc.
* The old rotl32 functions have been removed. They had been deprecated since
OIIO 2.1. Please use `rotl()` intead.
* The old floori functions have been removed. They had been deprecated since
OIIO 1.8. Please use ifloor() instead.
* The old OIIO_SIMD_HAS_FLOAT8 macro has been removed. It was deprecated since
OIIO 1.8.
## string_view.h
* The string_view::c_str() method has been marked as deprecated, since
it is not present in C++17 std::string_view. If you must use this
functionality (with caution about when it is safe), then use the
freestanding OIIO::c_str(string_view) function instead.
## strutil.h
* The default behavior of `Strutil::format()` has been changed to use the
`std::format` conventions. If you want the old behavior, use
`Strutil::old::format()` instead.
* Added deprecation warnings to all the old (printf-convention) string
`format()` function.
## texture.h
* `TextureSystem::create()` now returns a `std::shared_ptr<TextureSystem>`
instead of a raw pointer.
* Removed stochastic-related tokens from the MipMode and InterpMode enums.
These were originally experimental but never removed.
* Removed the `bias` field from the TextureOpt structure. This was originally
there for the sake of shadow maps, but was never used because we never
implemented shadow maps in OIIO's TextureSystem.
* Removed the TextureOptions, which hasn't been used since OIIO 1.x. We
switched to the alternate TextureOpt structure in OIIO 2.0.
* Fully removed the long-deprecated methods of TextureSystem that operated
on batches using the VaryingRef class. These were replaced by alternatives
a long time ago.
## thread.h
* `OIIO::yield()` now has a deprecation warning, having been marked as
deprecatd since OIIO 2.4. Use `std::this_thread::yield()`.
## tiffutils.h
* Removed the version of decode_exif that takes a pointer and length
(deprecated since 1.8). Use the version that takes a `string_view`, or the
one that takes a `cspan<uint8_t>`.
## type_traits.h
* Removed the `OIIO::void_t` template, which now should be replaced with
`std::void_t`.
## ustring.h
* Removed old `ustringHash` (which was just an alias for `std::hash<ustring>`,
which should be used instead).
## varyingref.h
* This header has been removed completely, since we no longer use the classes
it defines.
## python bindings
* The `ImageBufAlgo.capture_image()` function has been removed from the
Python bindings. Python scripts that wish to capture images from live
cameras should use OpenCV or other capture APIs of choice and then
pass the results to OIIO to construct an ImageBuf.
* Static type names within the `TypeDesc` class (such as `TypeDesc.TypeFloat`)
have been removed after being considered deprecated since OIIO 1.8. Use the
names in the overall OpenImageIO namespace instead.
* Older versions of `ImageBufAlgo.fit()` have been removed. Use the newer
function signatures.
* Older versions of `ImageInput::read_native_deep_scanlines()` and
`read_native_deep_tiles()` have been removed. They had been deprecated
since OIIO 2.0.
## maketx
* The `--noresize` option has been removed. It was deprecated since OIIO 2.0,
when it became the default behavior.
* The `--stats` option has been removed. It was deprecated since OIIO 1.6,
when it was renamed `--runstats`.
+98
View File
@@ -0,0 +1,98 @@
OpenImageIO Usage Quick Start
=============================
> [!NOTE]
> For information about how to *install* or *build* OpenImageIO, please see
> the [INSTALL guide](../INSTALL.md). This "Usage Quick Start" guide is
> intended to help you get started using OpenImageIO once you have it
> installed.
To illustrate how to do a simple common image operation -- reading a TIFF file
and writing it back as an OpenEXR file, with all necessary conversions -- we
will show how this can be accomplished through several different OpenImageIO
APIs and programs.
In all cases, we will assume we have a file called `input.tif` and we wish to
convert it to `output.exr`.
### Using `oiiotool` command-line utility
```bash
$ oiiotool input.tif -o output.exr
```
### High-level ImageBuf API
In C++:
```cpp
#include <OpenImageIO/imagebuf.h>
void main()
{
OIIO::ImageBuf image("input.tif");
image.write("output.exr");
}
```
In Python:
```python
import OpenImageIO as oiio
image = oiio.ImageBuf("input.tif")
image.write("output.exr")
```
### Low level ImageInput/ImageOutput API
In C++:
```cpp
#include <OpenImageIO/imageio.h>
#include <cstddef>
#include <memory>
void main()
{
auto input = oiio.ImageInput.open("input.tif")
OIIO::ImageSpec spec = input.spec()
size_t nbytes = spec.image_bytes();
std::unique_ptr<std::byte[]> pixels = new std::byte[nbytes];
input->read_image(0, 0, 0, spec.nchanels, OIIO::TypeUnknown, pixels.get());
input->close();
auto output = oiio.ImageOutput.create("output.exr");
output->open("output.exr", spec);
output->write_image(TypeUnknown, pixels.get());
output->close();
}
```
In Python:
```python
import OpenImageIO as oiio
input = oiio.ImageInput.open("input.tif")
spec = input.spec()
pixels = input.read_image()
# Note: read_image will return a NumPy multi-dimensional array holding
# all the pixel values of the image.
output = oiio.ImageOutput.create("output.exr")
output.open("output.exr", spec)
output.write_image(pixels)
# Note: write_image expects a NumPy multi-dimensional array holding
# all the pixel values of the image.
```
### Next Steps
This is just a simple example to give you a flavor of the different major
interfaces. For more advanced usage, you may want to explore the
[documentation](https://docs.openimageio.org).
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+17 -16
View File
@@ -32,26 +32,27 @@ here](https://github.com/AcademySoftwareFoundation/OpenImageIO/discussions/4151)
See the [Dependency proposal wiki page](https://github.com/AcademySoftwareFoundation/OpenImageIO/discussions/4151)
* [ ] Big required upgrades with potentially widespread impact on the code base
- [ ] C++17 [#4155](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4155)
- [ ] Python 3.7 [#4157](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4157)
- [ ] OpenEXR/Imath 3.1 [#4156](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4156)
* [x] Big required upgrades with potentially widespread impact on the code base
- [x] C++17 [#4155](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4155)
- [x] Python 3.7 [#4157](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4157)
- [x] OpenEXR/Imath 3.1 [#4156](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4156)
* [ ] Miscellaneous optional upgrades whose changes will be very localized
* [x] Miscellaneous optional upgrades whose changes will be very localized
This isn't a complete list, nor do we need to do all of these, but the
highest priorities are:
- [ ] CMake 3.18 (from 3.15). Or possibly newer if there's a good reason? (3.19 or 3.20 are also reasonable.)
- [ ] OpenColorIO 2.0, or possibly 2.1 (from 1.1). Open for debate: should it be a required dependency rather than optional?
- [ ] fmt 8.0 (from 7.0), which has many improvements.
- [ ] GIFlib 5.0 (from 4.0), which adds thread safety.
- [ ] libheif 1.11 (from 1.3), which supports many additional features of that format.
- [ ] WebP 1.2 (from 0.6) which lets us use their exported CMake configs and retire FindWebP.cmake.
- [ ] pybind11 2.6 or 2.7 (from 2.4).
- [X] CMake 3.18 (from 3.15). [#4472](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4472)
- [x] OpenColorIO 2.2, and make it required. [#4367](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4367)
- [ ] fmt 8.0 (from 7.0), which has many improvements. CANCELLED: fmt 8.0+
does not work with the old icc compiler.
- [x] GIFlib 5.0 (from 4.0), which adds thread safety. [#4349](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4349)
- [x] libheif 1.11 (from 1.3), which supports many additional features of that format. [#4380](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4380)
- [x] WebP 1.2 (from 0.6) which lets us use their exported CMake configs and retire FindWebP.cmake. [#4354](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4354)
- [x] pybind11 2.6 or 2.7 (from 2.4). [#4297](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4297)
- [ ] [#4156](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4156) Eliminate the last few places where we use Boost and eliminate it as a dependency.
- [x] [#4158](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4158) Eliminate the last few places where we use Boost and eliminate it as a dependency.
<br>
@@ -86,8 +87,8 @@ major release:
Regardless of OCIO availability, version, or contents of any configs, have universal support for the [canonical color spaces](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/documents/Specification/MaterialX.Specification.md#color-spaces-and-color-management-systems) that seem to be the common consensus of ACES, MaterialX, and USD.
- [ ] Preliminary Rust bindings for most of the OpenImageIO APIs.
- [ ] Python wheel construction so `pip install openimageio` will be an easy way
for users to install the whole banana.
- [x] Python wheel construction so `pip install openimageio` will be an easy way
for users to install the whole banana. [#4428](https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/4428)
If there is something you think should be on the roadmap for the next major
release but is not, please open an issue or discussion to propose it, or
@@ -97,6 +98,6 @@ bring it up at a TSC meeting, or on the mail list or Slack channel.
## Parking
Here is where we will put things that definitely should be on the roadmap, but
that need not be completed in time for the fall 2024 release of OIIO 3.0.
that need not be completed in time for the fall 2026 release of OIIO 3.2.
...
+14
View File
@@ -0,0 +1,14 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Ignore temporary specs that may be ephemeral or local to an individual
# developer, to prevent cluttering the output of `git status` and prevent
# people from accidentally checking in specs that are only meant for them.
specs/*
# But don't ignore the ones that belong to this project and are checked in. As
# we add specs that we intend to commit and make available to all project
# developers, they must be individually added here.
# !specs/example
+170
View File
@@ -0,0 +1,170 @@
Policy on AI Coding Assistants
==============================
- Initial policy merged 23-Mar-2026
Use of "AI coding assistants" is permitted on this project, with the following
guidelines and principles.
Summary of our core values:
- Human must always be in the loop, and is the responsible party for
the contents of a PR (including fully understanding and being able
to explain, defend, and modify it in response to review comments).
- Interact with the project and community yourself, not by agent.
- Disclose what tools you used and how. At a minimum, we require an
"Assisted-by: TOOL/MODEL" line in the commit comments and PR description.
- Don't waste maintainer's time with low quality PRs.
The long version:
### Human authorship and interaction with the project
**The human making a PR is considered the author** and is fully responsible
for the code they submit.
**No PRs should be submitted, reviewed/merged, or deployed without a human
fully in the loop.** You may use agents locally to help you write code (and
docs, tests, etc.), but you may not use agents to autonomously interact with
the project community. Submit your own PRs, write your own discussion
comments, respond to community members in your own words, approve or reject
code in review using your own brain.
Code autonomously submitted without an identifiable human author and
responsible party will be immediately closed, and the account associated with
the submission may be banned from future project participation.
**DO NOT "vibe code."** This term refers to a pure prompt-to-behavior cycle
where the human accepts un-inspected code based on the program behavior alone.
We don't want this. Code that must be maintained by the project should be
truly understood. Project code is ideally the result of discussion / pair
programming between the author and assistant, but even if the machine is doing
most of the work, all code should be approved and fully understood by the
author prior to PR submission.
### Professionalism and quality
**The usual high quality level of PRs should be maintained regardless of tools
used.** This includes not only code, but also the design, testing, PR
preparation, and the author's ability to explain and defend the code and
respond to questions and requests for changes. We never want to hear "but the
AI..." as an excuse for anything.
**PRs should always be [reviewed](CodeReview.md) and approved by someone other
than their author if at all possible.** This is especially true of code with
machine-generated components, because of the additional risk that the
submitter/operator may not fully understand what they did not write
themselves. This is part of the reason for AI tool disclosure -- to ensure
that another pair of eyes is on it. AI code review may be requested for
additional input, but the AI cannot give "approval", nor merge code itself.
Even when using a coding assistant to write the code, you are strongly
encouraged to write your own PR description, in your own words, if for no
other reason than to force yourself to understand the code well enough to
describe it to others.
### Disclosure
**Disclosure is required.** Patches that were written with the aid of AI
coding assistants must have, at a minimum, the following line in the commit
comment and PR description body:
Assisted-by: TOOL / MODEL
Ideally, to the extent practical, the PR description should also have a brief
description of how the tool was used, including the gist of key prompts or
summarizing the direction of the dialog. A full log is not necessary; a short
summary will do.
There are several reasons for this disclosure/documentation, even though it
will sometimes be inconvenient:
- Reproducibility: We want even automated work to be reproducible by others in
principle, just like a scientific paper.
- Education: We want to actively teach each other what tools, prompts, or
methods are successful at making high quality results for the project.
- Metrics: We would like the ability to look back and compare assisted vs
non-assisted code for things like defect rate (how often were new bugs
introduced or commits needed to be reverted), whether people are more likely
to write comprehensive tests when using assistants, etc.
- Compliance: Many key users and developers are in companies where they need
to disclose how AI tools were used in their work, and in other software that
they use. Let's make it easy for them.
- Insurance: Should future legal decisions radically change the IP status of
AI-generated code, or if particular models are implicated in copyright
violations, we want a way to find out which contributions might need to be
revisited in order to bring the project back into compliance.
### Intellectual Property
Regardless of how the code came to be -- from your head alone, from a friend,
from Stack Overflow, from a blog post, from reading other code bases, or from
a coding assistant -- we expect the terms of the
[DCO](https://developercertificate.org/) and CLA to apply, and for the author
to take reasonable care that code is not copied from a source with an
incompatible license.
You may find that your confidence about complying with the DCO+CLA depends on:
- If you provided a detailed specification and how much you edited or guided
the results yourself.
- Whether you are modifying or extending existing code versus writing large
amounts of entirely new code.
- The degree to which the generated code seems to fit into our structure and
idiomatic style, and therefore seems unlikely to be copied from elsewhere.
- Whether your tool has guardrails to prevent answers that are too similar to
existing code, for example as claimed by [Claude](https://privacy.claude.com/en/articles/10023638-why-am-i-receiving-an-output-blocked-by-content-filtering-policy-error) and [Copilot](https://docs.github.com/en/copilot/how-tos/manage-your-account/).
### Extractive submissions
**Maintainer time and attention are precious commodities**, and use of coding
assistants is not an excuse to submit poor PRs or to externalize costs onto
maintainers/reviewers (such as responsibility for understanding, testing, or
fixing PRs that the human author does not have a full understanding of).
Maintainers are free to take counter-measures against submitters of sub-par
PRs, or other violations of this policy, up to and including banning habitual
abusers from future participation in the project.
**We discourage use of AI tools to fix GitHub issues labeled as "good first
issue" or for "Dev Days" work.** Cultivating and educating new contributors is
important, and as such, we do not want people to swoop in and use automated
tools to trivially solve tasks that were curated specifically for somebody to
actually learn from. We expect each developer to implement at most one "good
first issue" per Dev Days occasion, and we encourage you to solve the problem
with your own brain to maximize the learning experience.
### Exceptions
This AI tool use policy is not meant to encompass cases such as:
- "Smart auto-complete", spell-checking, grammar checking, or other uses that
aren't really contributing substantively to authorship.
- Use of LLMs to explain code or learn about the codebase, answer basic
programming questions, help with background research, or audit the code
for bugs that are subsequently confirmed and fixed by people.
- Language translation for non-fluent English speakers or other accessibility
accommodations.
- Trivial or de-minimis fixes such as fixing a typo, obviously wrong variable
use, etc.
- Reviewing your own code for mistakes prior to submitting a PR (as long as it
isn't making the fixes for you).
### Creative contributions -- out of scope
This project repository contains code for tools, and their documentation. We
don't really directly host any artistically creative work here, so we have not
addressed additional policy issues that might come up in such a context.
If you are representing a different project that is using this document for
guidance or inspiration for your own policies, please be aware that you may
have needs that are not covered by these policies but deserve well-crafted
guidance.
### References and inspiration
Our policy has been informed and inspired by the following efforts in other communities:
- [LLVM AI Tool Policy](https://llvm.org/docs/AIToolPolicy.html)
- [Fedora Project policy on AI-assisted contributions](https://communityblog.fedoraproject.org/council-policy-proposal-policy-on-ai-assisted-contributions/)
- [Linux Foundation policy on Generative AI](https://www.linuxfoundation.org/legal/generative-ai)
- [Rust policy on rejecting burdensome PRs](https://github.com/rust-lang/compiler-team/issues/893)
- The METR paper [Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity](https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/)
- [GitHub Blog: Rethinking open source mentorship in the AI era](https://github.blog/open-source/maintainers/rethinking-open-source-mentorship-in-the-ai-era/)
+57
View File
@@ -0,0 +1,57 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
# Agentic coding / coding assistants
Please start by reading [our policy on using "AI" coding
assistsants](AI_Policy.md).
## Multi-tool setup
We aim to allow people to use whatever agentic or coding assistant tools they
want. The repository ships with a setup script that configures tool-specific
files locally for whichever assistant(s) you use.
### Generic: `AGENTS.md` and `.agents/`
As much as possible, we use identical instructions and files across all coding
assistants.
`AGENTS.md` is the main file providing overall repo-specific instructions and
context to agents. Many coding agents already read this file directly; for
those that don't, the setup script creates the necessary links or wrappers.
`.agents/skills/` is where shared skill files live. Many tools find skills
here automatically; for those that need them elsewhere, the setup script
creates the appropriate links.
### Running the setup script
After cloning, run `.agents/setup-agent <tool>` for the tool(s) you use:
```
.agents/setup-agent claude # Claude Code
.agents/setup-agent cursor # Cursor
.agents/setup-agent codex # OpenAI Codex
.agents/setup-agent opencode # Opencode
.agents/setup-agent copilot # GitHub Copilot
.agents/setup-agent all # all of the above
```
The script is idempotent — running it multiple times is safe. To undo:
```
.agents/setup-agent clear # remove all tool setup
.agents/setup-agent clear claude # remove setup for one tool
```
Tool-specific directories (`.claude/`, `.cursor/`, `.codex/`, `.opencode/`,
`.github/copilot-instructions.md`) are created locally only and are listed in
`.gitignore`. Each developer runs the script for the tool they use; nothing
tool-specific is committed to the repository.
The script header contains per-tool documentation (what each tool reads
natively, what requires setup, and links to relevant docs) — consult it when
adding support for a new tool or updating the strategy for an existing one.
+207
View File
@@ -0,0 +1,207 @@
OpenImageIO's Architecture
==========================
```mermaid
block-beta
columns 3
Apps
style Apps fill:#0000,stroke:#0000
cmd["oiiotool, iinfo, maketx, ..."]:2
Classes["Image and caching\nclasses"]
style Classes fill:#0000,stroke:#0000
block:IB
style IB fill:#0000,stroke:#0000
columns 1
ImageBufAlgo ImageBuf
end
block:ICTA
style ICTA fill:#0000,stroke:#0000
columns 1
TextureSystem ImageCache
end
file["File reading/writing\nclasses"]:1
style file fill:#0000,stroke:#0000
ImageInput ImageOutput
plugins["File format\nimplementations"]
style plugins fill:#0000,stroke:#0000;
block:formats:2
style formats fill:#0000,stroke:#0000
columns auto
TIFF OpenEXR JPEG DPX etc["..."]
style etc fill:#0000,stroke:#0000
end
```
## Core level / file abstraction: ImageInput and ImageOutput
At the heart of OpenImageIO are the `ImageInput` and `ImageOutput` classes,
which are the abstract interfaces for reading and writing image files using a
simple file-format-agnostic API. These classes provide a file-oriented
abstraction, with operations such as opening an image file, reading the
resolution and other metadata about the image in the file, reading or writing
scanlines or tiles to/from caller-provided memory, and closing the file.
All the details of the individual file formats and how the data is arranged or
stored in the file are hidden by these classes. Furthermore, when reading or
writing scanlines or tiles, the caller-side memory can use any of several
different common data types (sometimes called "data formats" or "formats" in
OIIO) such as `float`, `half`, 8 or 16 bit integers, etc. The `ImageInput` and
`ImageOutput` classes will automatically convert the data to or from the
format stored in the file.
This level of abstraction imposes some conceptual constraints on the
presentation of the image data, for the sake of simplification, so that every
application doesn't need to consider every possible combination of choices
that all the different file formats might make. For example, on the
"application side" of the `ImageInput` and `ImageOutput` classes, all images
have pixels that are 8- 16- or 32-bit int (signed or unsigned), 16- 32- or
64-bit float. If the pixel data in the file uses another data type, or a
number of bits per channel that is not 8, 16, or 32, those details are hidden
from the application. There are many other such simplifications.
## Low level: File format implementations
If the `ImageInput` and `ImageOutput` present the *interface* for reading and
writing image files, the implementations of each individual file format are
implemented in the file format plugins. (We call them "plugins" because it's
possible to organize them as an extensible list of dynamically loaded modules,
but all the common file formats have their plugins compiled into the
OpenImageIO library itself, so are not dynamically loaded and not generally
experienced as "plugins" in the usual sense.)
Each file format plugin consists of a concrete subclass of `ImageInput`, and
usually `ImageOutput`. Most format plugins are capable of both reading and
writing the file format, but some of them only include the reading portion.
## Higher level / Image abstraction: ImageBuf and ImageBufAlgo
For many applications, you just want to manipulate whole images, without
worrying about the details of opening and closing files, reading and writing
of individual scanlines or tiles, or how and where the pixel data is stored.
The `ImageBuf` class provides such an interface. It is a higher-level
abstraction that encapsulates an entire image.
For an ImageBuf that is meant to read an image file, it is simply told the
name of the file, and it will handle all the details of how and when to open,
close, and read the file, including handling all the combinations of tiles,
scanlines, and so on. Similarly, an ImageBuf can be written to an image file
on disk simply by providing the filename and telling it to `write()`, without
needing to specify any scanline-by-scanline instructions. The internal
implementation of ImageBuf uses ImageInput and ImageOutput to read and write
the image data from and to files, and so can read or write any file format for
which there is an ImageInput or ImageOutput plugin available.
ImageBuf typically owns the memory holding its pixel data and is responsible
for allocating and freeing it. Thus, file reads and writes are to/from this
internal memory, as opposed to ImageInput and ImageOutput, which must be
supplied with memory by the caller as the source or destination of the pixel
data. (That said, there is also a way to make an ImageBuf "wrap" memory owned
by the application rather than allocate internally.)
In addition to restricting the pixel data types to a limited set, ImageBuf
further imposes the simplification that all color channels are stored in the
same data type. This is a simplification that is not present in the ImageInput
and ImageOutput classes, which can handle files where different channels are
stored in different data types. For such a file, the ImageBuf will "promote"
all the channels of an image to a single same data type (usually the "widest"
or "most precise" used by any of its channels).
If `ImageBuf` is the in-memory representation of an entire image, then
`ImageBufAlgo` is a collection of algorithms that operate on `ImageBuf`
objects. These algorithms include simple operations like copying, resizing,
and compositing images, as well as more complex operations like color
conversions, resizing, filtering, etc.
Some performance-critical `ImageBufAlgo` implementations have SIMD-accelerated
paths using Google Highway. For implementation details and guidance for adding
new kernels, see `docs/dev/ImageBufAlgo_Highway.md`.
## Image caching: TextureSystem and ImageCache
There are situations where ImageBuf is still not the right abstraction,
and you have so many images -- potentially tens of thousands of images
totalling multiple terabytes of pixel data -- that they can't possibly
be held in memory at once. This is actually a typical case for a
high-quality film renderer, where the renderer needs to be able to
access a texture data set of that size range.
In such cases, you want to handle both the pixel memory and the set of
open files as a *pool* centrally managed. This is done by the
`ImageCache` class. In short, it manages two central caches:
- A pool of image files currently held open, with a limit on the number of
files that can be open at once (typically hundreds to thousands). When the
limit is reached, a file that has not been accessed recently is closed to
make room for a new file to be opened.
- A pool of pixel memory, organized into image *tiles*, with a limit on the
total amount of tile memory to be used (typically a small number of GB).
Accesses to pixel values check if the tile is in the cache, in which case no
read from disk is necessary. If pixel access requires a tile not currently
in the cache and the tile memory limit is reached, a tile that has not been
accessed recently is evicted from the cache to make room for the new tile.
The TextureSystem is a level of abstraction above the ImageCache that further
adds the ability to do texture lookups with texture filtering, MIP-mapping,
and other features typical of texture mapping in a renderer.
## Command line applications
OpenImageIO has several command line utilities that use various combinations
of ImageBuf, ImageInput, and ImageOutput.
`oiiotool` is the most important of these (and technically can do everything
that the other tools can do, and more). It is a general-purpose image
manipulation tool that can read and write images, apply various image
operations, and write the results to disk.
Other command line tools include `iinfo` (which prints out information about
an image file), `iconvert` (which converts between different file formats),
and `maketx` (which generates tiled mipmaps in an efficient arrangement for
texture mapping in a renderer).
## Language Bindings
The main APIs, and the underlying implementation, are in C++ (currently
using C++17 features).
A Python binding is provided, currently using the pybind11 library to
generate the Python bindings for each C++ class or function.
There is an effort underway to eventually provide a Rust binding.
## Helper classes
Several image-related auxiliary classes are used by the public APIs of the
image- and file-oriented classes described above. The most important ones are:
- `ImageSpec` stores the specification for an image: its resolution, pixel data
type, number of channels (as well as their names and individual data types),
pixel and display windows, and all other metadata from the image file.
- `ParamValueList` is used to store a list of of name/value pairs (each
individual name+value is a `ParamValue`), such as arbitrary image metadata.
- `ROI` describes a region of interest: the x, y, z, and channel range of
pixels on which to perform some operation.
Additionally, there are many small utility classes that are not about images
per se, but also are used by the public interfaces of our main image classes.
A few of them that you will see commonly used are:
- `string_view` is a non-owning reference to a string (of any of several
types, or partial substrings thereof), akin to `std::string_view` in C++17.
- `span` is a non-owning reference to a contiguous sequence of objects, akin
to `std::span` in C++20.
- `ustring` is a string class where the characters are stored in an internal
shared pool of strings, so all ustrings that have the same character
sequence point to the same character memory. In addition to saving memory,
this makes string assignment and equality comparison as inexpensive as
integer operations.
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+51
View File
@@ -0,0 +1,51 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
# Build profiling
These are instructions for profiling the build process of OpenImageIO --
useful for figuring out where the build process is spending its time, and
where it might be optimized.
## Profiling module compilation with clang -ftime-trace
These instructions are based on the following references:
- general instructions: https://www.superfunc.zone/posts/001-speeding-up-c-builds/
- ninjatracing.py script: https://github.com/nico/ninjatracing
- Background info: https://aras-p.info/blog/2019/01/16/time-trace-timeline-flame-chart-profiler-for-Clang/
The steps are as follows, and they require the use of clang, ninja, and
the chrome browser:
1. Build with clang using the `-ftime-trace`, flag which is set when you use
the OIIO build option -DOIIO_BUILD_PROFILE=1. You MUST use clang, as this
is a clang-specific feature, and you must use the ninja builder (use CMake
arguments `-G ninja`). This must be a *fresh* build, not an incremental
build (or the results will only reflect the incrementally build parts).
This will result in a file, build/.ninja_log, containing timings from
the build process.
2. Prepare the output using the `ninjatracing.py` script as follows:
```
python3 src/build-scripts/ninjatracing.py -a build/.ninja_log > top_level.json
```
3. Running the Chrome browser, visit the URL `chrome://tracing`, and LOAD that
json file created in the previous step. This will display a timeline of the
build process, showing which thread, in what order, and how long each
module took to compile.
4. For even more detail on what's happening within the compilation of each
module, you can use the `-e` flag to expand the output:
```
python3 src/build-scripts/ninjatracing.py -a -e -g 50000 build/.ninja_log > expanded.json
```
Loading this in Chrome's tracing view, as above, will show a full flame
chart of the build process, showing the time spent in the different
functional parts of the compiler and which functions of OIIO it is
compiling or which templates are being instantiated.
+48
View File
@@ -0,0 +1,48 @@
Release 3.0 (Fall 2024) -- compared to 2.5
-------------------------------------------------
### New minimum dependencies and compatibility changes:
* *Blah*: Raise minimum to 1.2...
### ⛰️ Major new features and public API changes:
* *New feature*: item
* *New image file format support:*
- Format1 explanation
- Format2 explanation
* *oiiotool*:
- item
* *ImageBuf/ImageBufAlgo*:
- item
* *Other categories or subsystems as needed*:
### 🚀 Performance improvements:
- *subsystem*: item
### 🐛 Fixes and feature enhancements:
* *subsystem*: item
* *oiiotool*: item
* *ImageBuf/ImageBufAlgo*:
- item
* *ImageCache/TextureSystem*:
- item
* *format*:
- item
### 🔧 Internals and developer goodies
- *int*: item
- *header.h*: developer item
### 🏗 Build/test/CI and platform ports:
* CMake build system and scripts:
- item
* Testing and Continuous integration (CI) systems:
- *test*: item
- *ci*: item
* Platform support:
- *win*: item
### 📚 Notable documentation changes:
- *docs*: item
### 🏢 Project Administration
- *admin*: item
+4
View File
@@ -0,0 +1,4 @@
Release 1.2.3.4 (Month DD, YYYY) -- compared to 1.2.3.3
-------------------------------------------------------
- *category*: Description [#1234](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1234) (by someuser)
+194
View File
@@ -0,0 +1,194 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
Code Review Procedures
======================
### Why do we code review?
Code review is a process where someone other than the author of a patch
examines the proposed changes and approves or critiques them. The main
benefits are to:
- Encourage submitters to ensure that their changes are well thought out,
tested, and documented so that their intent and wisdom will be clear to
others.
- Directly find shortcomings in or suggest improvements to the proposed
changes, and ensure that the changes are consistent with the project's best
practices.
- Minimize the amount of the code base that has only been seen or is only
understood by one person.
- Improve security and robustness of the code base by assuring that at least
two people (submitter and reviewer) agree that every patch is reasonable and
safe.
### Reviewer guidelines -- what you should be looking for
Code review is not difficult, and it doesn't require you to be a senior
developer or a domain expert. Even if you don't particularly understand that
region of the code and are not a domain expert in the feature being changed,
you can still provide a helpful second pair of eyes to look for obvious red
flags and give an adequate review:
- This may seem too obvious to say explicitly, but a big part of review is
just looking at the PR and seeing that it doesn't appear to deface,
purposely/obviously break, or introduce malware into the project.
- Does the explanation of the PR make logical sense and appear to match (as
near as you can tell) the changes in the code? Does it seem sensible, even
if you don't understand all the details?
- Does the test pass all of our existing CI tests? (If it does, at least we
are reasonably sure it doesn't break commonly used features.)
- Is there any evidence that the changes have been tested? Ideally, something
already in, or added to the testsuite by this PR, exercises the new or
altered code. (Though sometimes a patch addresses an edge case that's very
hard to reproduce in the testsuite, and you have to rely on the submitter's
word and the sensibility of their explanation.)
- Not required, but nice if we can get it: You're an expert in the part of
the code being changed, and you agree that this is the best way to achieve
an improvement.
- Any objections should be explained in detail and invite counter-arguments
from the author or other onlookers. A reviewer should never close a PR
unless it fails to conform to even the basic requirements of any submitted
PR, or if enough time has passed that it's clear that the PR has been
abandoned by its author. It's ok to ultimately say "no" to a PR that can't
be salvaged, but that should be the result of a dialogue.
Obviously, you also want any review comments you give to be constructive and
helpful. If you don't understand something, ask for clarification. If you
think something is wrong, suggest a fix if you know how to fix it. If you
think something is missing, suggest what you think should be added. Follow the
expected kind and constructive tone of the project's community.
### Submitter guidelines -- how to encourage good reviews and timely merges
A few tips for submitters to help ensure that your PRs get reviewed and merged
in a timely manner and are respectful of the reviewers' time and effort:
- Aim for small PRs that do a specific thing in a clear way. It is better to
implement a large change with a series of PRs that each take a small,
obvious step forward, than to have one huge PR that makes changes so
extensive that nobody quite knows how to evaluate it.
- Make sure your PR commit summary message clearly explains the why and how of
your changes. You want someone to read that and judge whether it's a
sensible approach, know what to look for in the code, and have their
examination of the code make them say "yes, I see, of course, great, just as
I expected!"
- Make sure your PR includes a test (if not covered by existing tests).
- Make sure your PR fully passes our CI tests.
- Make sure your PR modifies the documentation as necessary if it adds new
features, changes any public APIs, or alters behavior of existing features.
- If your PR alters the C++ API, make sure that the changes are also reflected
in the Python bindings and any other language bindings we support.
- If your PR adds to or alters any ImageBufAlgo function, make sure you have
exposed those changes with appropriate `oiiotool` commands as well.
### Code review procedures -- in the ideal case
In the best of circumstances, the code review process should be as follows for
**EVERY** pull request:
- At least one reviewer critiques and eventually (possibly after changes are
made) approves the pull request. Reviewers, by definition, are not the same
person as the author.
- Reviewers should indicate their approval by clicking the "Approve" button in
GitHub, or by adding a comment that says "LGTM" (looks good to me).
- If possible, reviewers should have some familiarity with the code being
changed (though for a large code base, this is not always possible).
- At least a few work days should elapse between posting the PR and merging
it, even if an approving review is received immediately. This is to allow
additional reviewers or dissenting voices to get a chance to weigh in.
- If the reviewer has suggestions for improvement, it's the original author
who should make the changes and push them to the PR, or at the very least,
the author should okay any changes made by the reviewer before a merge
occurs (if at all practical).
Not all patches need the highest level of scrutiny. Reviews can be cursory and
quick, and merges performed without additional delay, in some common low-risk
circumstances:
- The patch fixes broken CI, taking the project from a verifiably broken state
to passing all of our CI builds and tests.
- The changes are only to documentation, comments, or other non-code files,
and so cannot break the build or introduce new bugs.
- The code changes are trivial and are obviously correct. (This is a judgment
call, but if the author or reviewer or both are among the project's senior
developers, they don't need to performatively pretend that they aren't sure
it's a good patch.)
- The changes are to *localized* and *low risk* code, that even if wrong,
would only have the potential to break individual non-critical features or
rarely-used code paths.
Conversely, some patches are so important or risky that if possible, they
should be reviewed by multiple people, preferably from different stakeholder
institutions than the author, and ensure that the approval is made with a
detailed understanding of the issues. In these cases, it may also be worth
bringing up the issue up at a TSC meeting to ensure the attention of many
stakeholders. These include:
- *New directions*: Addition of major new features, new strategic initiatives,
or changes to APIs that introduce new idioms or usage patterns should give
ample time for all stakeholders to provide feedback. In such cases, it may
be worth having the PR open for comments for weeks, not just days.
- *Risky changes*: Changes to core classes or code that could subtly break
many things if not done right, or introduce performance regressions to
critical cases.
- *Compatibility breaks*: changes that propose to break backward API
compatibility with existing code or data files, or that change the required
toolchain or dependencies needed to build the project.
- *Security*: Changes that could introduce security vulnerabilities, or that
fix tricky security issues where the best fix is not obvious.
### Code review compromises -- because things are rarely ideal
We would love to have many senior reviewers constantly watching for PRs, doing
thorough reviews immediately, and following the above guidelines without
exception. Wouldn't that be great! But in reality, we have to compromise,
hurry, or cut corners, or nothing would ever get done. Some of these
compromises are understandable and acceptable if they aren't happening too
often.
- Lack of reviews: If no reviews are forthcoming after a couple days, a "are
there any objections?" comment may be added to the PR, and if no objections
are raised within another few days, the PR may be merged by the author if
they are a senior developer on the project. This is a fact of life, but
should be minimized (with a rigor proportional to where the patch falls on
the "low risk / high risk" scale described above). If this is done, you
should leave an additional comment explaining why it was merged without
review and inviting people to submit post-merge comments if they
subsequently spot something that can be improved.
- Time-critical patches: urgent security fixes, broken CI or builds, critical
bugs affecting major stakeholders who are waiting for a repaired release,
fixes that are blocking other work or preventing other PRs from advancing.
In such cases, it is understandable for senior developers to try to speed up
the process of getting the changes integrated (though the very nature of
their criticality also indicates that it's worth getting a review if at all
possible).
- Failing tests: Sometimes a PR must be merged despite failing CI tests.
Usually this is for one of two reasons: (1) spurious CI failures are known
to be occurring at that time and are unrelated to the PR; (2) the PR is part
of a series of patches that are only expected to fully pass CI when the last
piece is completed.
These changes are understandable, but we still are striving to reduce their
frequency. It is the responsibility of the senior developers, TSC members, and
major stakeholders to be monitoring the incoming PRs and helping with reviews
as much as possible, to ensure that review exceptions are rare.
### Code review pathologies -- things to avoid
These are anti-patterns that generally are indications of an unhealthy open
source project:
* An author merging their own PR without any review comments that indicate
meaningful scrutiny or approval from another party, and without giving
adequate warning that a merge will occur if no reviews are received.
* PRs languishing for weeks or months without any review or merge.
* PRs that don't adequately test their changes (basically crossing your
fingers and hoping it works).
* PRs that are merged despite failing CI that might be related or, if
unrelated, that might be masking problems with the PR being evaluated.
Again, sometimes these things happen out of necessity to keep the project
moving forward under constrained development resources. But we strive as much
as possible to ensure that they are rare exceptions.
+264
View File
@@ -0,0 +1,264 @@
ImageBufAlgo Highway (hwy) Implementation Guide
==============================================
This document explains how OpenImageIO uses Google Highway (hwy) to accelerate
selected `ImageBufAlgo` operations, and how to add or modify kernels in a way
that preserves OIIO semantics while keeping the code maintainable.
This is a developer-facing document about the implementation structure in
`src/libOpenImageIO/`. It does not describe the public API behavior of the
algorithms.
Goals and non-goals
-------------------
Goals:
- Make the hwy-backed code paths easy to read and easy to extend.
- Centralize repetitive boilerplate (type conversion, tails, ROI pointer math).
- Preserve OIIO's numeric semantics (normalized integer model).
- Keep scalar fallbacks as the source of truth for tricky layout cases.
Non-goals:
- Explain Highway itself. Refer to the upstream Highway documentation.
- Guarantee that every ImageBufAlgo op has a hwy implementation.
Where the code lives
--------------------
Core helpers:
- `src/libOpenImageIO/imagebufalgo_hwy_pvt.h`
Typical hwy call sites:
- `src/libOpenImageIO/imagebufalgo_addsub.cpp`
- `src/libOpenImageIO/imagebufalgo_muldiv.cpp`
- `src/libOpenImageIO/imagebufalgo_mad.cpp`
- `src/libOpenImageIO/imagebufalgo_pixelmath.cpp`
- `src/libOpenImageIO/imagebufalgo_xform.cpp` (some ops are hwy-accelerated)
Enabling and gating the hwy path
-------------------------------
The hwy path is only used when:
- Highway usage is enabled at runtime (`OIIO::pvt::enable_hwy`).
- The relevant `ImageBuf` objects have local pixel storage (`localpixels()` is
non-null), meaning the data is in process memory rather than accessed through
an `ImageCache` tile abstraction.
- The operation can be safely expressed as contiguous streams of pixels/channels
for the hot path, or the code falls back to a scalar implementation for
strided/non-contiguous layouts.
The common gating pattern looks like:
- In a typed `*_impl` dispatcher: check `OIIO::pvt::enable_hwy` and `localpixels`
and then call a `*_impl_hwy` function; otherwise call `*_impl_scalar`.
Important: the hwy path is an optimization. Correctness must not depend on hwy.
OIIO numeric semantics: why we promote to float
----------------------------------------------
OIIO treats integer image pixels as normalized values:
- Unsigned integers represent [0, 1].
- Signed integers represent approximately [-1, 1] with clamping for INT_MIN.
Therefore, most pixel math must be performed in float (or double) space, even
when the stored data is integer. This is why the hwy layer uses the
"LoadPromote/Operate/DemoteStore" pattern.
For additional discussion (and pitfalls of saturating integer arithmetic), see:
- `HIGHWAY_SATURATING_ANALYSIS.md`
The core pattern: LoadPromote -> RunHwy* -> DemoteStore
-------------------------------------------------------
The helper header `imagebufalgo_hwy_pvt.h` defines the reusable building blocks:
1) Computation type selection
- `SimdMathType<T>` selects `float` for most types, and `double` only when
the destination type is `double`.
Rationale:
- Float math is significantly faster on many targets.
- For OIIO, integer images are normalized to [0,1] (or ~[-1,1]), so float
precision is sufficient for typical image processing workloads.
2) Load and promote (with normalization)
- `LoadPromote(d, ptr)` and `LoadPromoteN(d, ptr, count)` load values and
normalize integer ranges into the computation space.
Rationale:
- Consolidates all normalization and conversion logic in one place.
- Prevents subtle drift where each operation re-implements integer scaling.
- Ensures tail handling ("N" variants) is correct and consistent.
3) Demote and store (with denormalization/clamp/round)
- `DemoteStore(d, ptr, v)` and `DemoteStoreN(d, ptr, v, count)` reverse the
normalization and store results in the destination pixel type.
Rationale:
- Centralizes rounding and clamping behavior for all destination types.
- Ensures output matches OIIO scalar semantics.
4) Generic kernel runners (streaming arrays)
- `RunHwyUnaryCmd`, `RunHwyCmd` (binary), `RunHwyTernaryCmd`
- These are the primary entry points for most hwy kernels.
Rationale:
- Encapsulates lane iteration and tail processing once.
- The call sites only provide the per-lane math lambda, not the boilerplate.
Native integer runners: when they are valid
-------------------------------------------
Some operations are "scale-invariant" under OIIO's normalized integer model.
For example, for unsigned integer add:
- `(a/max + b/max)` in float space, then clamped to [0,1], then scaled by max
matches saturated integer add `SaturatedAdd(a, b)` for the same bit depth.
For those cases, `imagebufalgo_hwy_pvt.h` provides:
- `RunHwyUnaryNativeInt<T>`
- `RunHwyBinaryNativeInt<T>`
These should only be used when all of the following are true:
- The operation is known to be scale-invariant under the normalization model.
- Input and output types are the same integral type.
- The operation does not depend on mixed types or float-range behavior.
Rationale:
- Avoids promotion/demotion overhead and can be materially faster.
- Must be opt-in and explicit, because many operations are NOT compatible with
raw integer arithmetic (e.g. multiplication, division, pow).
Local pixel pointer helpers: reducing boilerplate safely
-------------------------------------------------------
Most hwy call sites need repeated pointer and stride computations:
- Pixel size in bytes.
- Scanline size in bytes.
- Base pointer to local pixels.
- Per-row pointer for a given ROI and scanline.
- Per-pixel pointer for non-contiguous fallbacks.
To centralize that, `imagebufalgo_hwy_pvt.h` defines:
- `HwyPixels(ImageBuf&)` and `HwyPixels(const ImageBuf&)`
returning a small view (`HwyLocalPixelsView`) with:
- base pointer (`std::byte*` / `const std::byte*`)
- `pixel_bytes`, `scanline_bytes`
- `xbegin`, `ybegin`, `nchannels`
- `RoiNChannels(roi)` for `roi.chend - roi.chbegin`
- `ChannelsContiguous<T>(view, nchannels)`:
true only when the pixel stride exactly equals `nchannels * sizeof(T)`
- `PixelBase(view, x, y)`, `ChannelPtr<T>(view, x, y, ch)`
- `RoiRowPtr<T>(view, y, roi)` for the start of the ROI row at `roi.xbegin` and
`roi.chbegin`.
Rationale:
- Avoids duplicating fragile byte-offset math across many ops.
- Makes it visually obvious what the code is doing: "get row pointer" vs
"compute offset by hand."
- Makes non-contiguous fallback paths less error-prone by reusing the same
pointer computations.
Important: these helpers are only valid for `ImageBuf` instances with local
pixels (`localpixels()` non-null). The call sites must check that before using
them.
Contiguous fast path vs non-contiguous fallback
-----------------------------------------------
Most operations implement two paths:
1) Contiguous fast path:
- Used when pixels are tightly packed for the ROI's channel range.
- The operation is executed as a 1D stream of length:
`roi.width() * (roi.chend - roi.chbegin)`
- Uses `RunHwy*Cmd` (or native-int runner) and benefits from:
- fewer branches
- fewer pointer computations
- auto tail handling
2) Non-contiguous fallback:
- Used when pixels have padding, unusual strides, or channel subsets that do
not form a dense stream.
- Typically loops pixel-by-pixel and channel-by-channel.
- May still use the `ChannelPtr` helpers to compute correct addresses.
Rationale:
- The contiguous path is where SIMD delivers large gains.
- Trying to SIMD-optimize arbitrary strided layouts often increases complexity
and risk for marginal benefit. Keeping a scalar fallback preserves
correctness and maintainability.
How to add a new hwy kernel
---------------------------
Step 1: Choose the kernel shape
- Unary: `R = f(A)` -> use `RunHwyUnaryCmd`
- Binary: `R = f(A, B)` -> use `RunHwyCmd`
- Ternary: `R = f(A, B, C)` -> use `RunHwyTernaryCmd`
Step 2: Decide if a native-int fast path is valid
- Only for scale-invariant ops and same-type integral inputs/outputs.
- Use `RunHwyUnaryNativeInt` / `RunHwyBinaryNativeInt` when safe.
- Otherwise, always use the promote/demote runners.
Step 3: Implement the hwy body with a contig check
Typical structure inside `*_impl_hwy`:
- Acquire views once:
- `auto Rv = HwyPixels(R);`
- `auto Av = HwyPixels(A);` etc.
- In the parallel callback:
- compute `nchannels = RoiNChannels(roi)`
- compute `contig = ChannelsContiguous<...>(...)` for each image
- for each scanline y:
- `Rtype* r_row = RoiRowPtr<Rtype>(Rv, y, roi);`
- `const Atype* a_row = RoiRowPtr<Atype>(Av, y, roi);` etc.
- if contig: call `RunHwy*` with `n = roi.width() * nchannels`
- else: fall back per pixel, per channel
Step 4: Keep the scalar path as the reference
- The scalar implementation should remain correct for all layouts and types.
- The hwy path should match scalar results for supported cases.
Design rationale summary
------------------------
This design intentionally separates concerns:
- Type conversion and normalization are centralized (`LoadPromote`,
`DemoteStore`).
- SIMD lane iteration and tail handling are centralized (`RunHwy*` runners).
- Image address computations are centralized (`HwyPixels`, `RoiRowPtr`,
`ChannelPtr`).
- Operation-specific code is reduced to short lambdas expressing the math.
This makes the hwy layer:
- Easier to maintain: fewer places to fix bugs when semantics change.
- Easier to extend: adding an op mostly means writing the math lambda and the
dispatch glue.
- Safer: correctness for unusual layouts remains in scalar fallbacks.
Notes on `half`
---------------
The hwy conversion helpers handle `half` by converting through
`hwy::float16_t`. This currently assumes the underlying `half` representation
is compatible with how Highway loads/stores 16-bit floats.
If this assumption is revisited in the future, it should be changed as a
separate, explicit correctness/performance project.
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
+199 -73
View File
@@ -10,17 +10,18 @@
Our release numbers are of the form `MAJOR.MINOR.PATCH.TWEAK`, and we follow
an almost-semantic-versioning scheme.
MAJOR changes are those that break backward-compatibility of the public APIs,
MAJOR releases are those that break backward-compatibility of the public APIs,
requiring existing application code to change their source code where it calls
OIIO API functions in order to compile and work correctly.
MINOR changes guarantee API backward-compatibility with prior releases that
MINOR releases guarantee API backward-compatibility with prior releases that
have the same major number, but can introduce ABI or link incompatibilities.
Applications using OIIO need to be recompiled to move to a new minor release,
but should not need to change their source code. Minor releases are allowed
to drop support for sufficiently old compilers and dependencies.
but should not need to change their source code (except, of course, to take
advantage of new features). Minor releases are allowed to drop support for
sufficiently old compilers and dependencies.
PATCH changes guarantee both API and ABI/link backward-compatibility with
PATCH releases guarantee both API and ABI/link backward-compatibility with
prior releases that have the same minor number. Features and new public API
calls may be added (thus deviating from strict semantic versioning), but only
if they preserve ABI/link compatibility. This means that standalone functions
@@ -32,7 +33,7 @@ guarantee that any compilers or dependencies supported for the first release
of a minor series will continue to be supported for all patches to that minor
series.
TWEAK changes are restricted to critical bug fixes or build breaks that do
TWEAK releases are restricted to critical bug fixes or build breaks that do
not alter public APIs in any way.
### Cadence of releases
@@ -51,27 +52,27 @@ Tweak (fully forward and backward compatible) releases are not regularly
scheduled, and only happen sporadically, when a critical fix is needed in
between scheduled patch releases.
### Things are different in "master"
### Things are different in "main"
The "master" branch is where ongoing development occurs without any
The "main" branch is where ongoing development occurs without any
compatibility guarantees. We don't always know if the next year's release from
master will turn out to be major (API breaking) or minor (only ABI breaking).
main will turn out to be major (API breaking) or minor (only ABI breaking).
Some studios or products need the most up-to-date enhancements, and thus tend
to build OIIO from the "master" branch rather than using tagged releases. For
these users, we try to set version numbers and occasionally tag in master, to
send a signal about which points in master seem safe to rely on various
to build OIIO from the "main" branch rather than using tagged releases. For
these users, we try to set version numbers and occasionally tag in main, to
send a signal about which points in main seem safe to rely on various
compatibility levels. However, the rules are slightly different than we use
for releases.
In the "master" branch:
In the "main" branch:
- TWEAK changes within "master" only guarantee ABI back-compatibility, but may
- TWEAK tags within "main" only guarantee ABI back-compatibility, but may
have additions or non-bug-fix behavior changes (akin to patch releases
within a release branch).
- PATCH changes within "master" are allowed to break ABI or API (changes that
would require minor or major releases, if they were not in "master").
- Beware of unmarked breaks in compatibility of commits in master that are
- PATCH tags within "main" are allowed to break ABI or API (changes that
would require minor or major releases, if they were not in "main").
- Beware of unmarked breaks in compatibility of commits in main that are
in between developer preview tags.
@@ -83,10 +84,10 @@ In the "master" branch:
(and thus the branch markers will move over time). Branch names obey the
following conventions:
- `master` is the area for arbitrary changes intended for the next year's
- `main` is the area for arbitrary changes intended for the next year's
major or minor release.
- `dev-1.2` are the areas for staging additions to the next month's patch
release for the designated minor version series.
- `dev-1.2` are the areas for staging additions that will become the next
tweak or patch release for the minor version series.
- `release` is a special branch marker that is always set to the latest tag of
the currently supported, stable release family. People can count on
"release" always being the latest stable release, whatever that may be at
@@ -101,7 +102,7 @@ conventions:
- `v1.2.3.4-alpha`, `v1.2.3.4-beta`, or `v1.2.3.4-RC1` are pre-releases for an
upcoming public stable release, at the alpha, beta, or release candidate
stages, respectively.
- `v1.2.3.4-dev` is a "developer preview" within "master." It is not an official
- `v1.2.3.4-dev` is a "developer preview" within "main." It is not an official
supported release, and while the numbering may indicate compatibility versus
other recent developer previews, they should not be assumed to be compatible
with any prior official stable releases.
@@ -118,7 +119,7 @@ in general should be ignored by anyone who didn't make the tag or branch.
### Soft freeze for monthly tweak releases:
We freely backport *safe*, non-ABI-breaking changes by cherry-picking them
from master to the supported branch continually throughout most of the month.
from main to the supported branch continually throughout most of the month.
In the seven days before the new month, we do a "soft freeze" where only
important bug fixes are backported. Hold on to any other patches you wish to
@@ -133,18 +134,18 @@ project during this soft freeze.
By mid-June (about 1-2 months before the beta of a new annual big release),
you should branch and mark it as an alpha.
At the tip of "master", create a new branch named `dev-MAJOR.MINOR` that will
At the tip of "main", create a new branch named `dev-MAJOR.MINOR` that will
be the staging area for the next release.
Customarily, at that point we add a commit to master (but not to the new
dev-MAJ.MIN branch) that bumps master's version to the next minor level, to
avoid any confusion between builds from master versus what will be the next
release branch. This starts the divergence between master and the release
Customarily, at that point we add a commit to main (but not to the new
dev-MAJ.MIN branch) that bumps main's version to the next minor level, to
avoid any confusion between builds from main versus what will be the next
release branch. This starts the divergence between main and the release
branch, and henceforth, any big or compatibility-breaking changes will only be
committed to master and not backported to the release branch. (Though we are
committed to main and not backported to the release branch. (Though we are
loose about this rule during the alpha period and allow continued breaking
changes in the alpha, but by the time we call it beta, we allow no more
breaking changes.) Also at this stage, the master branch's CHANGES.md should
breaking changes.) Also at this stage, the main branch's CHANGES.md should
have a heading added at the top for the *next* version.
@@ -155,7 +156,34 @@ have a heading added at the top for the *next* version.
pages), and that the [INSTALL.md](../INSTALL.md) file correctly documents
the version ranges that we expect to work and that we actively test.
2. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
2. Update deprecations: Deprecations tend to happen in stages, spread over a
few releases, taking steps forward depending on what kind of release is
occurring:
- Tweak releases (a.b.c.d -> a.b.c.D+1): should not introduce new
deprecations.
- Monthly patch releases (a.b.c.d -> a.b.C+1.0): advertise that a function
is deprecated in its comments, documentation, and release notes. Remember
that these releases are not allowed to break ABI/link compatibility.
- Annual minor releases (a.b.c.d -> a.B+1.0.0): functions previously
marked/documented as deprecated should receive deprecation warnings by
adding `OIIO_DEPRECATED` macros to function or class declarations where
possible, if that has not already been done. Use good judgment about
whether to add these warnings, or postpone to a later release, based on
the amount of disruption that they will likely cause, and how important
it is to rapidly discourage people from using the deprecated function.
For a minor release, we don't allow backwards-incompatible API changes,
so only *remove* a function if there is another function that will accept
the same call signature in the source code. It's allowed to break ABI for
minor releases, so it's ok/encouraged to make a deprecated function from
linked to inline, for example (which might allow it to be removed later
without an ABI change).
- Major releases (a.b.c.d -> A+1.0.0.0): API compatibility breaks are
allowed here, so this is the time to completely remove any functions that
have already had a full minor release where they had been given
deprecation warning macros.
3. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
all the new features and fixes. Looking at the notes from older releases
should provide a good example of what we're aiming for.
@@ -168,7 +196,7 @@ have a heading added at the top for the *next* version.
internals and developer goodies, testing/CI/ports, etc.) and ordered for
readability and relevance.
3. Ensure docs are up to date:
4. Ensure docs are up to date:
- [README.md](README.md): Actually read it! Make sure it all seems
accurate and up to date.
@@ -178,28 +206,28 @@ have a heading added at the top for the *next* version.
sure new contributors are listed.
- [SECURITY.md](SECURITY.md): Make sure it accurately reflects the
status of which branches get updates.
- Skim the [user documentation](https://openimageio.readthedocs.io/) to
- Skim the [user documentation](https://docs.openimageio.org) to
ensure it's building correctly and doesn't have any obvious errors,
especially the parts that describe new features.
4. Make sure the the top-level CMakeLists.txt file is updated:
5. Make sure the the top-level CMakeLists.txt file is updated:
- The `OpenImageIO_VERSION` should be correct.
- The `PROJECT_VERSION_RELEASE_TYPE` variable should be set to "alpha" or
"beta" if appropriate, "RC" for release candidate, or empty string `""`
for most supported releases, and "dev" only for the master branch or
for most supported releases, and "dev" only for the main branch or
developer previews.
- The `${PROJECT_NAME}_SUPPORTED_RELEASE` variable should be `ON` for any
release branch, `OFF` for master.
release branch, `OFF` for main.
5. In the https://github.com/AcademySoftwareFoundation/OpenImageIO-images project, create a branch
6. In the https://github.com/AcademySoftwareFoundation/OpenImageIO-images project, create a branch
`dev-x.y` for the major/minor branch, and in the main oiio repo, update
src/build-scripts/install_test_images.bash to specify `-b dev-x.y` in the
checkout of oiio-images to ensure CI tests are against the set of test
images corresponding to that major/minor release (just in the branch, not
in master!).
in main!).
6. Make sure everything passes the usual CI workflow. Also check the daily or
7. Make sure everything passes the usual CI workflow. Also check the daily or
weekly "analysis" workflows to make sure there aren't any important
warnings that should be fixed.
@@ -236,24 +264,40 @@ truly critical bugs or build breaks that users will encounter.
The following are the steps for making the release:
1. Edit the top-level CMakeLists.txt to remove any RC designation
(i.e., `PROJECT_VERSION_RELEASE_TYPE` should be set to `""`).
1. Double check the top-level CMakeLists.txt to ensure the right version
number and type of version designation (i.e.,
`PROJECT_VERSION_RELEASE_TYPE` should be set appropriately).
2. Edit CHANGES.md to reflect the correct date of the release and ensure it
includes any last-minute changes that were made during beta or release
candidate stages.
candidate stages. Please see the section "Generating release notes" below.
3. Push it to **your** GitHub, make sure it passes CI.
3. Push it to **your** GitHub fork, make sure it passes CI.
4. Tag the release: `git tag v1.2.3.4` (no more beta, RC, or dev suffix).
4. Tag the release with a signed tag:
$ git tag -s v1.2.3.4 # add a signed tag
$ git tag -v v1.2.3.4 # verify the tag
Be sure that the tag also reflects if it's an alpha (v1.2.3.4-alpha),
beta (v1.2.3.4-beta), release candidate (v1.2.3.4-RC1), or developer
preview (v1.2.3.4-dev). If it's a final release, just use the plain
version number (v1.2.3.4).
Note that the tag signing requires you to have a GPG key set up and
associated with your GitHub account. Please see [GitHub's signed tagging instructions](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-tags) for more information.
If you get errors messages "gpg: signing failed: Inappropriate ioctl for device", then the solution is to first:
$ export GPG_TTY=$(tty)
5. If this will now be the recommended stable release, move the `release`
branch marker to the same position.
6. Push it to GitHub: `git push OpenImageIO release --tags`
(This example assumes "OpenImageIO" is the name of the remote for the
GitHub `OpenImageIO/oiio` repo.)
GitHub `AcademySoftwareFoundation/OpenImageIO` repo.)
7. Draft a release on GitHub: On https://github.com/AcademySoftwareFoundation/OpenImageIO/releases
select "Draft a new release." Choose the new tag you just pushed. Make the
@@ -268,26 +312,25 @@ The following are the steps for making the release:
For a monthly patch release:
> We have tagged v1.2.3.4 as the latest production release and moved the
> We have tagged v3.1.0.0 as the latest production release and moved the
> "release" branch marker to that point. This is guaranteed to be API,
> ABI, and link back-compatible with prior 1.2 releases. Release notes
> are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
> ABI, and link back-compatible with prior 3.1 releases. Release notes
> can be found at *LINK TO THE GITHUB RELEASE PAGE.*
For an annual major/minor release:
> OpenImageIO version 1.2 has been released! Officially tagged as
> "v1.2.3.4", we have also moved the "release" branch tag to this
> position. Henceforth, 1.2 is the supported production release family.
> The API is now frozen -- we promise that subsequent 1.2.x releases
> OpenImageIO version 3.1 has been released! Officially tagged as
> "v3.1.0.0", we have also moved the "release" branch tag to this
> position. Henceforth, 3.1 is the supported production release family.
> The API is now frozen -- we promise that subsequent 3.1.x releases
> (which should happen monthly) will not break back-compatibility of API,
> ABI, or linkage, compared to this release. Please note that this release
> is *not* ABI or link compatible with 1.1 or older releases.
> is *not* ABI or link compatible with 3.0 or older releases.
>
> Release notes for 1.2 outlining all the changes since last year's
> release are below.
> Release notes for 3.1 outlining all the changes since last year's
> release can be found at *LINK TO THE GITHUB RELEASE PAGE.*
> (Optionally, you can include a brief summary of the most important
> changes in this email.)
>
> Please note that a few of the build and runtime dependencies have
> changed their minimum supported versions. (List here any important
@@ -301,35 +344,35 @@ The following are the steps for making the release:
> backward-compatible with prior versions, warn about that here.)
>
> Enjoy, and please report any problems. We will continue to make patch
> releases to the 1.2 family roughly monthly, which will contain bug fixes
> releases to the 3.1 family roughly monthly, which will contain bug fixes
> and non-breaking enhancements.
>
> The older 1.1 series of releases is now considered obsolete. We will
> continue for now to make 1.1 patch releases, but over time, these will
> The older 3.0 series of releases is now considered obsolete. We will
> continue for now to make 3.0 patch releases, but over time, these will
> become less frequent and be reserved for only the most critical bug
> fixes.
>
> The "master" branch is now progressing toward an eventual 1.3 release next
> summer. As usual, you are welcome to use master for real work, but we do
> The "main" branch is now progressing toward an eventual 3.2 release next
> fall. As usual, you are welcome to use main for real work, but we do
> not make any compatibility guarantees and don't guarantee continuing API
> compatibility in master.
> compatibility within main.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> (Paste the full set of 3.1 changes here, just copy the appropriate
> part of CHANGES.md)
For a beta leading up to the annual major/minor release:
> OpenImageIO version 1.2 is now in beta, tagged as "v1.2.3.4-beta". We
> OpenImageIO version 3.1 is now in beta, tagged as "v3.1.0.0-beta". We
> will try very hard not to make any further API or ABI changes between
> now and the final release (unless it is absolutely necessary to fix
> an important problem identified during beta testing). The final 1.2
> an important problem identified during beta testing). The final 3.1
> release is scheduled for [DATE GOES HERE], so please try building and
> testing the beta so we are sure to find any problems.
>
> Release notes for 1.2 outlining all the changes since last year's
> Release notes for 3.1 outlining all the changes since last year's
> release are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> (Paste the full set of 3.1 changes here, just copy the appropriate
> part of CHANGES.md)
@@ -340,11 +383,11 @@ Odds and ends to do after the tag is pushed and the announcements are sent:
- Re-read RELEASING.md and ensure that the instructions match what you
have done. Update as necessary.
- Go to [readthedocs.org](https://openimageio.readthedocs.io/), and ensure
that the new release is built, visible, and is the default release shown
(specified in the Admin section). I tend to keep the latest patch of each
minor release available for reference indefinitely, but hide the docs for
earlier patch releases within that minor release series.
- Go to [OIIO's docs hosted on readthedocs.org](https://docs.openimageio.org),
and ensure that the new release is built, visible, and is the default
release shown (specified in the Admin section). I tend to keep the latest
patch of each minor release available for reference indefinitely, but hide
the docs for earlier patch releases within that minor release series.
- Edit the top-level CMakeList.txt to update the version to the *next*
anticipated release on the branch, in order to ensure that anybody building
@@ -353,3 +396,86 @@ Odds and ends to do after the tag is pushed and the announcements are sent:
(blank) heading for the next patch or release.
## Generating release notes
We strongly encourage the use of "conventional commit" prefixes in commit
messages. See [CONTRIBUTING.md](CONTRIBUTING.md#commit-messages) for details.
Many PRs are submitted (even by the author of this section you are now
reading!) without the conventional commit prefix. The person who approves and
merges the commit should take responsibility during the merge process to edit
the commit message to add the appropriate prefix (and for that matter, to edit
any part of the commit message for clarity). But at the end of the day, if we
end up with some commits lacking a conventional commit prefix, it's no big
deal -- we can fix it all up by hand when we make the release notes. But
having CC prefixes in as many commit messages possible helps make the release
notes process be simpler and more automated.
We have been using the [git-cliff](https://github.com/orhun/git-cliff) tool
as the starting point for release notes. The command we use is:
git cliff -c src/doc/cliff.toml v3.1.2.3..HEAD > cliff.out.md
where v3.1.2.3 in this example is the tag of the last release. You could also
use commit hashes to denote the range of changes you want to document.
**For monthly patch releases**
We have found that the git-cliff output is most of what we need for the patch
releases, and can be copied into the CHANGES.md file with only some minor
editing needed. The template for the patch release notes can be found in
[Changes-skeleton-patch.md](docs/dev/Changes-skeleton-patch.md).
* Get rid of the headings that git-cliff generates. We don't use the headings
for the patch releases.
* Add prefixes to any commits that don't have them (they will be marked as
"uncategorized" by git-cliff), and feel free to change any of the existing
prefixes that you think are wrong or could be improved for clarity.
* Rearrange the order of the entries to be logical and readable. I prefer the
order: feature enhancements, bug fixes, build system fixes that might impact
users, internal changes, test improvements, documentation and administrative
changes.
* For patch releases, feel free to omit any entries that you think are not
user-facing and are too minor to be worth mentioning in the release notes.
Strive to keep the release notes just long enough for users to know if the
patch contains any fixes relevant to them, but short enough to be read at a
glance and without extraneous detail.
Here is an example of well-constructed monthly patch release notes:
https://github.com/AcademySoftwareFoundation/OpenImageIO/releases/tag/v2.5.12.0
**For annual major/minor releases**
For major releases, the git-cliff output is just a starting point and need
significant editing to get the detail and quality level we expect for our
major releases. A simple bullet list of commits is not sufficient -- we aim
for a prose-based description of important changes that "tell the story" of
the year's work and will be thoroughly understood by our stakeholders who need
to understand what has changed.
* Copy all the headings from [Changes-skeleton-major.md](docs/dev/Changes-skeleton-major.md)
or the previous year's release notes to get the skeleton of the major and
minor headers that you fit everything into. Note that it mostly corresponds
to sections of the git-cliff output, but with a more carefully constructed
hierarchy of categories.
* Add prefixes to any commits that don't have them (they will be marked as
"uncategorized" by git-cliff), and feel free to change any of the existing
prefixes that you think are wrong or could be improved for clarity.
* Rearrange the git-cliff output into the hierarchy of our preferred major
release notes organization. Within each section and subsection, group
similar changes together. The chronological order of the commits isn't as
important as clearly explaining what changed over the course of the year.
* The git-cliff output is a good starting point for populating the notes with
every PR, plus automatically adding a reference and link to the PR and the
name of the author of the patch.
* Look with a skeptical eye at the one-line bullet points from git-cliff (i.e,
from the first line of each PR's commit message). Often, they are too terse
or tend to [bury the lede](https://www.dictionary.com/e/slang/bury-the-lede/).
Expand into as much explanation is necessary for users who need to know
about the change or feature to know whether it is relevant and have some
idea what to do or that they should look at the relevant PRs for more
detail.
Here is an example of well-constructed annual major release notes:
https://github.com/AcademySoftwareFoundation/OpenImageIO/releases/tag/v2.5.4.0
+167
View File
@@ -0,0 +1,167 @@
# See docs at https://cibuildwheel.pypa.io/en/stable/options
# for description of all the options in this file.
[project]
name = "OpenImageIO"
# The build backend ascertains the version from the CMakeLists.txt file.
dynamic = ["version"]
description = "Reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API, aimed at VFX applications."
authors = [
{name = "Larry Gritz", email = "lg@larrygritz.com"},
{name = "OpenImageIO Contributors", email = "oiio-dev@lists.aswf.io"}
]
maintainers = [
{name = "OpenImageIO Contributors", email="oiio-dev@lists.aswf.io"},
]
readme = "README.md"
license = {text = "Apache-2.0"}
classifiers = [
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"License :: OSI Approved :: Apache Software License",
"Topic :: Multimedia :: Graphics",
"Topic :: Multimedia :: Video",
"Topic :: Multimedia :: Video :: Display",
"Topic :: Software Development :: Libraries :: Python Modules",
]
requires-python = ">= 3.9"
dependencies = [
"numpy>=2.0,<3",
]
[project.urls]
Homepage = "https://openimageio.org/"
Source = "https://github.com/AcademySoftwareFoundation/OpenImageIO"
Documentation = "https://docs.openimageio.org"
Issues = "https://github.com/AcademySoftwareFoundation/OpenImageIO/issues"
[project.scripts]
# Use the convention below to expose CLI tools as Python scripts.
idiff = "OpenImageIO:_command_line"
maketx = "OpenImageIO:_command_line"
oiiotool = "OpenImageIO:_command_line"
[build-system]
build-backend = "scikit_build_core.build"
requires = [
"scikit-build-core>=0.10.6,<1",
"pybind11>=2.13,<4",
]
[tool.scikit-build]
build.verbose = true
# Exclude unnecessary directories from the source distribution.
sdist.exclude = [".github", "testsuite", "ASWF", "docs"]
# Pin minimum scikit-build-core to that specified in build-system.requires.
minimum-version = "build-system.requires"
# Pin minimum CMake version to that specified in CMakeLists.txt.
cmake.version = "CMakeLists.txt"
wheel.license-files = ["LICENSE.md", "THIRD-PARTY.md"]
# Make sure the package is structured as expected.
wheel.install-dir = "OpenImageIO"
# Only install the user and fonts components.
install.components = ["user", "fonts"]
[tool.scikit-build.cmake.define]
# Build missing dependencies. See src/cmake for details.
OpenImageIO_BUILD_MISSING_DEPS = "all"
# Don't build tests. Dramatically improves build time.
OIIO_BUILD_TESTS = "0"
# Prefer linking static dependencies when possible.
LINKSTATIC = "1"
# Standardize the install directory for libraries, as expected by
# other parts of the wheels build process.
CMAKE_INSTALL_LIBDIR = "lib"
# Dynamically set the package version metadata by pasrsing CMakeLists.txt.
[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.regex"
input = "CMakeLists.txt"
regex = 'set \(OpenImageIO_VERSION "(?P<value>[0-9a-z.]+)"\)'
# On macOS, ensure dependencies are only built for the target architecture.
[[tool.scikit-build.overrides]]
if.platform-system = "darwin"
if.platform-machine = "arm64"
inherit.cmake.define = "append"
cmake.define.CMAKE_OSX_ARCHITECTURES = "arm64"
cmake.define.CMAKE_OSX_DEPLOYMENT_TARGET = "11"
[[tool.scikit-build.overrides]]
if.platform-system = "darwin"
if.platform-machine = "x86_64"
inherit.cmake.define = "append"
cmake.define.CMAKE_OSX_ARCHITECTURES = "x86_64"
cmake.define.CMAKE_OSX_DEPLOYMENT_TARGET = "10.15"
[tool.cibuildwheel]
build-verbosity = 1
skip = [
# Skip 32-bit builds
"*-win32",
"*-manylinux_i686",
# Building with musl seems to work, but the repair-wheel step seems to fail...
# This may be a bug in repairwheel (or auditwheel)?
"*musllinux*",
# Skip free-threading builds
"cp3??t-*",
]
test-command = "oiiotool --buildinfo"
[tool.cibuildwheel.macos.environment]
CC = "/usr/bin/clang"
CXX = "/usr/bin/clang++"
SKBUILD_CMAKE_ARGS = "-DLINKSTATIC=1; -DIGNORE_HOMEBREWED_DEPS=1"
# Optimize for size (not speed).
SKBUILD_CMAKE_BUILD_TYPE = "MinSizeRel"
[tool.cibuildwheel.linux.environment]
SKBUILD_CMAKE_ARGS = "-DLINKSTATIC=1"
# Suppress warnings that cause linux cibuildwheel build to fail
CXXFLAGS = "-Wno-error=stringop-overflow -Wno-pragmas"
SKBUILD_CMAKE_BUILD_TYPE = "MinSizeRel"
# FIXME: Getting build problems when using WebP 1.6.0, so hold it back
WebP_BUILD_VERSION = "1.5.0"
[tool.cibuildwheel.windows.environment]
SKBUILD_CMAKE_BUILD_TYPE = "MinSizeRel"
# Temporarily disabled test below. The CI stub generation seems broken, and
# is failing CI every time. Just turn off this check until we can figure out
# why it is broken.
# ----
# [[tool.cibuildwheel.overrides]]
# # Trigger the build & validation of the python stubs for certain platforms.
# # The test command acts as a kind of "post-build" callback where it's possible
# # for the stub-generator to import the freshly-built wheel.
# # There are two entry-points which are designed to call generate_stubs.py through
# # this test command:
# # - `make pystubs` is called during local development to generate the
# # stubs and copy them into the git repo to be committed and reviewed.
# # - in CI, the cibuildwheel action is used to validate that the stubs match what
# # has been committed to the repo.
# test-requires = "mypy~=1.15.0 stubgenlib~=0.1.0"
# # Note: the python version here must be kept in sync with src/python/stubs/CMakeLists.txt
# select = "cp311-manylinux_*64"
# inherit.test-command = "append"
# test-command = [
# "python {project}/src/python/stubs/generate_stubs.py --out-path '/output' --validate-path '{project}/src/python/stubs/OpenImageIO/__init__.pyi'",
# ]
# ----
[tool.mypy]
files = [
"testsuite/python-*/src/",
]
mypy_path = [
"src/python/stubs",
]
check_untyped_defs = true
+2 -3
View File
@@ -6,7 +6,7 @@ sonar.host.url=https://sonarcloud.io
# Required metadata
sonar.organization=academysoftwarefoundation
sonar.projectName=OpenImageIO
sonar.projectVersion=2.6
sonar.projectVersion=3.1
sonar.projectKey=AcademySoftwareFoundation_OpenImageIO
# Project links
@@ -17,11 +17,10 @@ sonar.links.issue=https://github.com/AcademySoftwareFoundation/OpenImageIO/issue
# Source properties
sonar.sources=src
sonar.exclusions=src/doc/**,src/include/OpenImageIO/detail/pugixml/**,src/libutil/stb_sprintf.h,src/libutil/xxhash.cpp,src/include/OpenImageIO/detail/farmhash.h,src/libutil/farmhash.cpp
sonar.exclusions=src/doc/**,src/build-scripts/**,src/include/OpenImageIO/detail/pugixml/**,src/libutil/stb_sprintf.h,src/libutil/xxhash.cpp,src/include/OpenImageIO/detail/farmhash.h,src/libutil/farmhash.cpp
sonar.sourceEncoding=UTF-8
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=/__w/OpenImageIO/OpenImageIO/bw_output
sonar.cfamily.gcov.reportsPath=_coverage
sonar.coverage.exclusions=src/iv/**,src/include/OpenImageIO/detail/pugixml/**,src/include/OpenImageIO/detail/fmt/**,src/libOpenImageIO/kissfft.hh
+50 -21
View File
@@ -5,6 +5,7 @@
#include <cstdio>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
#include "bmp_pvt.h"
@@ -185,20 +186,14 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
const int height = (m_dib_header.height >= 0) ? m_dib_header.height
: -m_dib_header.height;
m_spec = ImageSpec(m_dib_header.width, height, nchannels, TypeDesc::UINT8);
if (!check_open(m_spec, { 0, 1 << 16, 0, 1 << 16, 0, 1, 0, 4 }))
return false;
if (m_dib_header.hres > 0 && m_dib_header.vres > 0) {
m_spec.attribute("XResolution", (int)m_dib_header.hres);
m_spec.attribute("YResolution", (int)m_dib_header.vres);
m_spec.attribute("ResolutionUnit", "m");
}
if (m_spec.width < 1 || m_spec.height < 1 || m_spec.nchannels < 1
|| m_spec.image_bytes() < 1
|| m_spec.image_pixels() > std::numeric_limits<uint32_t>::max()) {
errorfmt(
"Invalid image size {} x {} ({} chans, {}), is likely corrupted",
m_spec.width, m_spec.height, m_spec.nchannels, m_spec.format);
close();
return false;
}
// Compute channel shifts & masks (only relevant for 16bpp case)
if (m_dib_header.red_mask == 0 || m_dib_header.green_mask == 0
@@ -258,10 +253,17 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
case WINDOWS_V5: m_spec.attribute("bmp:version", 5); break;
}
if (m_dib_header.cpalete && !m_colortable.size()) {
errorfmt(
"BMP error: bad BPP ({}) for palette image -- presumed corrupt file",
m_dib_header.bpp);
return false;
}
// Default presumption is that a BMP file is meant to look reasonable on a
// display, so assume it's sRGB. This is not really correct -- see the
// comments below.
m_spec.attribute("oiio:ColorSpace", "sRGB");
m_spec.attribute("oiio:ColorSpace", "srgb_rec709_scene");
#if 0
if (m_dib_header.size >= WINDOWS_V4
&& m_dib_header.cs_type == CSType::CalibratedRGB) {
@@ -301,8 +303,8 @@ BmpInput::read_rle_image()
m_uncompressed.clear();
m_uncompressed.resize(m_spec.image_pixels());
// Note: the clear+resize zeroes out the buffer
bool ok = true;
int y = 0, x = 0;
bool ok = true;
int64_t y = 0, x = 0;
while (ok) {
// Strutil::print("currently at {},{}\n", x, y);
unsigned char rle_pair[2];
@@ -390,14 +392,31 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
size_t scanline_bytes = m_spec.scanline_bytes();
uint8_t* mscanline = (uint8_t*)data;
if (m_dib_header.compression == RLE4_COMPRESSION
|| m_dib_header.compression == RLE8_COMPRESSION) {
for (int x = 0; x < m_spec.width; ++x) {
int p = m_uncompressed[(m_spec.height - 1 - y) * m_spec.width + x];
auto& c = colortable(p);
mscanline[3 * x] = c.r;
mscanline[3 * x + 1] = c.g;
mscanline[3 * x + 2] = c.b;
if ((m_dib_header.compression == RLE4_COMPRESSION
|| m_dib_header.compression == RLE8_COMPRESSION)
&& m_colortable.size()) {
if (m_spec.nchannels == 1) {
OIIO_CONTRACT_ASSERT(m_allgray);
for (int x = 0; x < m_spec.width; ++x) {
int p
= m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
+ x];
auto& c = colortable(p);
mscanline[x] = c.r;
// For the "all gray" case, rgb are equal and we're filling in
// a 1-channel data buffer.
}
} else {
OIIO_CONTRACT_ASSERT(m_spec.nchannels == 3);
for (int x = 0; x < m_spec.width; ++x) {
int p
= m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
+ x];
auto& c = colortable(p);
mscanline[3 * x] = c.r;
mscanline[3 * x + 1] = c.g;
mscanline[3 * x + 2] = c.b;
}
}
return true;
}
@@ -406,9 +425,19 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
if (m_dib_header.height >= 0)
y = m_spec.height - y - 1;
const int64_t scanline_off = y * m_padded_scanline_size;
const int64_t scanline_pos = int64_t(m_bmp_header.offset) + scanline_off;
// A corrupt header can place the scanline outside the file. The IOProxy
// will reject such a read, but validate the position explicitly so we
// fail cleanly instead of relying on a bad seek being caught downstream.
if (m_padded_scanline_size < 0 || scanline_pos < 0
|| scanline_pos + m_padded_scanline_size > int64_t(ioproxy()->size())) {
errorfmt("Invalid scanline position in BMP file");
return false;
}
fscanline.resize(m_padded_scanline_size);
ioseek(m_bmp_header.offset + scanline_off);
ioseek(scanline_pos);
if (!ioread(fscanline.data(), m_padded_scanline_size)) {
return false; // Read failed
}
+2 -36
View File
@@ -5,6 +5,7 @@
#include <cstdio>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/strutil.h>
@@ -26,9 +27,6 @@ public:
bool close(void) override;
bool write_scanline(int y, int z, TypeDesc format, const void* data,
stride_t xstride) override;
bool write_tile(int x, int y, int z, TypeDesc format, const void* data,
stride_t xstride, stride_t ystride,
stride_t zstride) override;
private:
int64_t m_padded_scanline_size;
@@ -37,7 +35,6 @@ private:
bmp_pvt::DibInformationHeader m_dib_header;
int64_t m_image_start;
unsigned int m_dither;
std::vector<unsigned char> m_tilebuffer;
std::vector<unsigned char> m_scratch;
std::vector<unsigned char> m_buf; // more tmp space for write_scanline
@@ -109,11 +106,6 @@ BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
m_image_start = iotell();
// If user asked for tiles -- which this format doesn't support, emulate
// it by buffering the whole image.
if (m_spec.tile_width && m_spec.tile_height)
m_tilebuffer.resize(m_spec.image_bytes());
return true;
}
@@ -156,23 +148,6 @@ BmpOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
}
bool
BmpOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
stride_t xstride, stride_t ystride, stride_t zstride)
{
if (!ioproxy_opened()) {
errorfmt("write_tile called but file is not open.");
return false;
}
// Emulate tiles by buffering the whole image
return copy_tile_to_image_buffer(x, y, z, format, data, xstride, ystride,
zstride, m_tilebuffer.data());
}
bool
BmpOutput::close(void)
{
@@ -181,17 +156,8 @@ BmpOutput::close(void)
return true;
}
bool ok = true;
if (m_spec.tile_width && m_tilebuffer.size()) {
// Handle tile emulation -- output the buffered pixels
OIIO_DASSERT(m_tilebuffer.size());
ok &= write_scanlines(m_spec.y, m_spec.y + m_spec.height, 0,
m_spec.format, m_tilebuffer.data());
std::vector<unsigned char>().swap(m_tilebuffer);
}
init();
return ok;
return true;
}
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Utility script to download and build Freetype
#
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Exit the whole script if any command fails.
set -ex
# Repo and branch/tag/commit of Freetype to download if we don't have it yet
FREETYPE_REPO=${FREETYPE_REPO:=https://github.com/freetype/freetype.git}
FREETYPE_VERSION=${FREETYPE_VERSION:=VER-2-14-1}
# Where to put Freetype repo source (default to the ext area)
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
FREETYPE_SRC_DIR=${FREETYPE_SRC_DIR:=${LOCAL_DEPS_DIR}/Freetype}
FREETYPE_BUILD_DIR=${FREETYPE_BUILD_DIR:=${FREETYPE_SRC_DIR}/build}
FREETYPE_INSTALL_DIR=${FREETYPE_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
FREETYPE_BUILD_TYPE=${FREETYPE_BUILD_TYPE:=Release}
# Fix for freetype breaking against cmake 4.0 because of too-old cmake min.
# Remove when freetype is fixed to declare its own minimum high enough.
export CMAKE_POLICY_VERSION_MINIMUM=3.5
pwd
echo "Freetype install dir will be: ${FREETYPE_INSTALL_DIR}"
mkdir -p ./ext
pushd ./ext
# Clone Freetype project from GitHub and build
if [[ ! -e ${FREETYPE_SRC_DIR} ]] ; then
echo "git clone ${FREETYPE_REPO} ${FREETYPE_SRC_DIR}"
git clone ${FREETYPE_REPO} ${FREETYPE_SRC_DIR}
fi
cd ${FREETYPE_SRC_DIR}
echo "git checkout ${FREETYPE_VERSION} --force"
git checkout ${FREETYPE_VERSION} --force
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -S . -B ${FREETYPE_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=${FREETYPE_BUILD_TYPE} \
-DBUILD_SHARED_LIBS=${FREETYPE_BUILD_SHARED_LIBS:-ON} \
-DCMAKE_INSTALL_PREFIX=${FREETYPE_INSTALL_DIR} \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
${FREETYPE_CONFIG_OPTS}
time cmake --build ${FREETYPE_BUILD_DIR} --config ${FREETYPE_BUILD_TYPE} --target install
fi
# ls -R ${FREETYPE_INSTALL_DIR}
popd
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export Freetype_ROOT=$FREETYPE_INSTALL_DIR
+7 -1
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of OpenJPEG to download if we don't have it yet
OPENJPEG_REPO=${OPENJPEG_REPO:=https://github.com/uclouvain/openjpeg.git}
OPENJPEG_VERSION=${OPENJPEG_VERSION:=v2.4.0}
OPENJPEG_VERSION=${OPENJPEG_VERSION:=v2.5.4}
# Where to put OpenJPEG repo source (default to the ext area)
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -20,6 +20,10 @@ OPENJPEG_BUILD_DIR=${OPENJPEG_BUILD_DIR:=${OPENJPEG_SRC_DIR}/build}
OPENJPEG_INSTALL_DIR=${OPENJPEG_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
#OPENJPEG_CONFIG_OPTS=${OPENJPEG_CONFIG_OPTS:=}
# Fix for openjpeg breaking against cmake 4.0 because of too-old cmake min.
# Remove when openjpeg is fixed to declare its own minimum high enough.
export CMAKE_POLICY_VERSION_MINIMUM=3.5
pwd
echo "OpenJPEG install dir will be: ${OPENJPEG_INSTALL_DIR}"
@@ -41,6 +45,8 @@ if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${OPENJPEG_INSTALL_DIR} \
-DBUILD_CODEC=OFF \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DBUILD_SHARED_LIBS=${OPENJPEG_BUILD_SHARED_LIBS:-ON} \
${OPENJPEG_CONFIG_OPTS}
time cmake --build ${OPENJPEG_BUILD_DIR} --config Release --target install
fi
+1
View File
@@ -33,6 +33,7 @@ git checkout ${PTEX_VERSION} --force
time cmake -S . -B ${PTEX_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PTEX_INSTALL_DIR} \
-DCMAKE_CXX_STANDARD=17 \
${PTEX_CONFIG_OPTS}
time cmake --build ${PTEX_BUILD_DIR} --config Release --target install
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Utility script to download or build ccacheccache
#
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Exit the whole script if any command fails.
set -ex
echo "Building ccache"
uname
ARCH=`uname -m`
echo "HOME=$HOME"
echo "PWD=$PWD"
echo "ARCH=$ARCH"
CCACHE_PREBUILT=${CCACHE_PREBUILT:=1}
# Repo and branch/tag/commit of ccache to download if we don't have it yet
CCACHE_REPO=${CCACHE_REPO:=https://github.com/ccache/ccache}
CCACHE_VERSION=${CCACHE_VERSION:=4.12}
CCACHE_TAG=${CCACHE_TAG:=v${CCACHE_VERSION}}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
# Where to put ccache repo source (default to the ext area)
CCACHE_SRC_DIR=${CCACHE_SRC_DIR:=${LOCAL_DEPS_DIR}/ccache}
# Temp build area (default to a build/ subdir under source)
CCACHE_BUILD_DIR=${CCACHE_BUILD_DIR:=${CCACHE_SRC_DIR}/build}
# Install area for ccache (default to ext/dist)
CCACHE_INSTALL_DIR=${CCACHE_INSTALL_DIR:=${PWD}/ext/dist}
CCACHE_CONFIG_OPTS=${CCACHE_CONFIG_OPTS:=}
# if [[ `uname` == "Linux" && `uname -m` == "x86_64" ]] ; then
if [[ `uname` == "Linux" ]] ; then
mkdir -p ${CCACHE_SRC_DIR}
pushd ${CCACHE_SRC_DIR}
if [[ "$CCACHE_PREBUILT" != "0" ]] ; then
#
# Try to download -- had trouble with this on runners
#
CCACHE_DESCRIPTOR="ccache-${CCACHE_VERSION}-linux-x86_64"
curl --location "${CCACHE_REPO}/releases/download/${CCACHE_TAG}/${CCACHE_DESCRIPTOR}.tar.xz" -o ccache.tar.xz
tar xJvf ccache.tar.xz
mkdir -p ${CCACHE_INSTALL_DIR}/bin
cp ${CCACHE_SRC_DIR}/${CCACHE_DESCRIPTOR}/ccache ${CCACHE_INSTALL_DIR}/bin
else
# Clone ccache project from GitHub and build
if [[ ! -e ${CCACHE_SRC_DIR}/.git ]] ; then
echo "git clone ${CCACHE_REPO} ${CCACHE_SRC_DIR}"
git clone ${CCACHE_REPO} ${CCACHE_SRC_DIR}
fi
echo "git checkout ${CCACHE_TAG} --force"
git checkout ${CCACHE_TAG} --force
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -S . -B ${CCACHE_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${CCACHE_INSTALL_DIR} \
-DENABLE_TESTING=OFF -DENABLE_DOCUMENTATION=OFF \
${CCACHE_CONFIG_OPTS}
time cmake --build ${CCACHE_BUILD_DIR} --config Release --target install
fi
fi
popd
ls ${CCACHE_INSTALL_DIR}
ls ${CCACHE_INSTALL_DIR}/bin
echo "CCACHE_INSTALL_DIR=$CCACHE_INSTALL_DIR"
echo "CCACHE_DIR=$CCACHE_DIR"
mkdir -p $CCACHE_DIR
ls $CCACHE_DIR || true
export PATH=${CCACHE_INSTALL_DIR}/bin:$PATH
${CCACHE_INSTALL_DIR}/bin/ccache -sv
fi
+3 -3
View File
@@ -12,7 +12,7 @@ set -ex
echo "Building cmake"
uname
CMAKE_VERSION=${CMAKE_VERSION:=3.18.5}
CMAKE_VERSION=${CMAKE_VERSION:=3.31.3}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
CMAKE_INSTALL_DIR=${CMAKE_INSTALL_DIR:=${LOCAL_DEPS_DIR}/cmake}
@@ -25,8 +25,8 @@ fi
if [[ `uname` == "Linux" && `uname -m` == "aarch64" ]] ; then
mkdir -p ${CMAKE_INSTALL_DIR} || true
curl --location https://anaconda.org/conda-forge/cmake/3.17.0/download/linux-aarch64/cmake-3.17.0-h28c56e5_0.tar.bz2 -o cmake-3.17.0-h28c56e5_0.tar.bz2
tar -xjf cmake-3.17.0-h28c56e5_0.tar.bz2 -C ${CMAKE_INSTALL_DIR}
curl --location "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-aarch64.sh" -o "cmake.sh"
sh cmake.sh --skip-license --prefix=${CMAKE_INSTALL_DIR}
export PATH=${CMAKE_INSTALL_DIR}/bin:$PATH
# In case we ever need to build from scratch:
+1 -1
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of libjpeg-turbo to download if we don't have it yet
LIBJPEGTURBO_REPO=${LIBJPEGTURBO_REPO:=https://github.com/libjpeg-turbo/libjpeg-turbo.git}
LIBJPEGTURBO_VERSION=${LIBJPEGTURBO_VERSION:=3.0.0}
LIBJPEGTURBO_VERSION=${LIBJPEGTURBO_VERSION:=3.1.2}
# Where to put libjpeg-turbo repo source (default to the ext area)
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
+2 -2
View File
@@ -10,8 +10,8 @@
set -ex
# Repo and branch/tag/commit of libpng to download if we don't have it yet
LIBPNG_REPO=${LIBPNG_REPO:=https://github.com/glennrp/libpng.git}
LIBPNG_VERSION=${LIBPNG_VERSION:=v1.6.35}
LIBPNG_REPO=${LIBPNG_REPO:=https://github.com/pnggroup/libpng.git}
LIBPNG_VERSION=${LIBPNG_VERSION:=v1.6.50}
# Where to put libpng repo source (default to the ext area)
LIBPNG_SRC_DIR=${LIBPNG_SRC_DIR:=${PWD}/ext/libpng}
+1 -1
View File
@@ -11,7 +11,7 @@ set -ex
# Which LibRaw to retrieve, how to build it
LIBRAW_REPO=${LIBRAW_REPO:=https://github.com/LibRaw/LibRaw.git}
LIBRAW_VERSION=${LIBRAW_VERSION:=0.20.2}
LIBRAW_VERSION=${LIBRAW_VERSION:=0.21.5}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
+5 -2
View File
@@ -13,9 +13,9 @@ LIBTIFF_REPO=${LIBTIFF_REPO:=https://gitlab.com/libtiff/libtiff.git}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
LIBTIFF_BUILD_DIR=${LIBTIFF_BUILD_DIR:=${LOCAL_DEPS_DIR}/libtiff}
LIBTIFF_INSTALL_DIR=${LIBTIFF_INSTALL_DIR:=${PWD}/ext/dist}
LIBTIFF_VERSION=${LIBTIFF_VERSION:=v4.3.0}
LIBTIFF_VERSION=${LIBTIFF_VERSION:=v4.7.1}
LIBTIFF_BUILD_TYPE=${LIBTIFF_BUILD_TYPE:=Release}
if [[ `uname` == `Linux` ]] ; then
if [[ `uname` == "Linux" ]] ; then
LIBTIFF_CXX_FLAGS=${LIBTIFF_CXX_FLAGS:="-O3 -Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
fi
LIBTIFF_BUILDOPTS="${LIBTIFF_BUILDOPTS}"
@@ -42,6 +42,8 @@ if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
-DCMAKE_INSTALL_PREFIX=${LIBTIFF_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${LIBTIFF_CXX_FLAGS}" \
-DBUILD_SHARED_LIBS=${LIBTIFF_BUILD_SHARED_LIBS:-ON} \
-Dtiff-tools=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dtiff-contrib=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dtiff-tests=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dtiff-docs=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dlibdeflate=ON \
@@ -59,5 +61,6 @@ popd
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export LIBTIFF_ROOT=$LIBTIFF_INSTALL_DIR
export Tiff_ROOT=$LIBTIFF_INSTALL_DIR
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${LIBTIFF_INSTALL_DIR}/lib
+22 -8
View File
@@ -12,10 +12,11 @@ set -ex
echo "Building LLVM"
uname
: ${LLVM_VERSION:=18.1.8}
: ${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
mkdir -p $LLVM_INSTALL_DIR || true
if [[ `uname` == "Linux" ]] ; then
: ${LLVM_VERSION:=13.0.0}
: ${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
: ${LLVM_DISTRO_NAME:=ubuntu-18.04}
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
echo LLVMTAR = $LLVMTAR
@@ -23,11 +24,24 @@ if [[ `uname` == "Linux" ]] ; then
ls -l $LLVMTAR
tar xf $LLVMTAR
rm -f $LLVMTAR
echo "Installed LLVM ${LLVM_VERSION} in ${LLVM_INSTALL_DIR}"
mkdir -p $LLVM_INSTALL_DIR && true
mv clang+llvm*/* $LLVM_INSTALL_DIR
export LLVM_DIRECTORY=$LLVM_INSTALL_DIR
export PATH=${LLVM_INSTALL_DIR}/bin:$PATH
export LLVM_ROOT=${LLVM_INSTALL_DIR}
# ls -a $LLVM_DIRECTORY
elif [[ `uname -s` == "Windows" || "${RUNNER_OS}" == "Windows" ]] ; then
echo "Installing Windows LLVM"
: ${LLVM_DISTRO_NAME:=ubuntu-18.04}
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-pc-windows-msvc.tar.xz
echo LLVMTAR = $LLVMTAR
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
ls -l $LLVMTAR
tar xf $LLVMTAR
rm -f $LLVMTAR
mv clang+llvm*/* $LLVM_INSTALL_DIR
else
echo Bad uname `uname`
fi
echo "Installed LLVM ${LLVM_VERSION} in ${LLVM_INSTALL_DIR}"
ls -a $LLVM_INSTALL_DIR || true
ls -a $LLVM_INSTALL_DIR/* || true
export LLVM_DIRECTORY=$LLVM_INSTALL_DIR
export PATH=${LLVM_INSTALL_DIR}/bin:$PATH
export LLVM_ROOT=${LLVM_INSTALL_DIR}
+6 -3
View File
@@ -11,7 +11,7 @@ set -ex
# Which OCIO to retrieve, how to build it
OPENCOLORIO_REPO=${OPENCOLORIO_REPO:=https://github.com/AcademySoftwareFoundation/OpenColorIO.git}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.2.1}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.4.2}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -19,7 +19,6 @@ OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_SOURCE_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
OPENCOLORIO_BUILD_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO-build}
OPENCOLORIO_INSTALL_DIR=${OPENCOLORIO_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
OPENCOLORIO_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE:=Release}
OPENCOLORIO_CXX_FLAGS=${OPENCOLORIO_CXX_FLAGS:="-Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
# Just need libs:
OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
-DOCIO_BUILD_DOCS=OFF -DOCIO_BUILD_TESTS=OFF \
@@ -27,6 +26,11 @@ OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
-DOCIO_BUILD_PYTHON=OFF -DOCIO_BUILD_PYGLUE=OFF \
-DOCIO_BUILD_JAVA=OFF \
-DBUILD_SHARED_LIBS=${OPENCOLORIO_BUILD_SHARED_LIBS:=ON}"
# Fix yaml-cpp which breaks against cmake 4.0 because of too-old cmake min.
# Remove when yaml-cpp is fixed to declare its own minimum high enough.
export CMAKE_POLICY_VERSION_MINIMUM=3.5
BASEDIR=`pwd`
pwd
echo "OpenColorIO install dir will be: ${OPENCOLORIO_INSTALL_DIR}"
@@ -46,7 +50,6 @@ git checkout ${OPENCOLORIO_VERSION} --force
time cmake -S . -B ${OPENCOLORIO_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${OPENCOLORIO_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${OPENCOLORIO_CXX_FLAGS}" \
${OPENCOLORIO_BUILDOPTS}
time cmake --build ${OPENCOLORIO_BUILD_DIR} --config Release --target install
popd
+5 -7
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Utility script to download and build OpenEXR & IlmBase
# Utility script to download and build OpenEXR & Imath
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
@@ -11,7 +11,7 @@ set -ex
# Which OpenEXR to retrieve, how to build it
OPENEXR_REPO=${OPENEXR_REPO:=https://github.com/AcademySoftwareFoundation/openexr.git}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.9}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.3.5}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -29,7 +29,7 @@ echo "OpenEXR build dir will be: ${OPENEXR_BUILD_DIR}"
echo "OpenEXR install dir will be: ${OPENEXR_INSTALL_DIR}"
echo "OpenEXR Build type is ${OPENEXR_BUILD_TYPE}"
# Clone OpenEXR project (including IlmBase) from GitHub and build
# Clone OpenEXR project (including Imath) from GitHub and build
if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
echo "git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}"
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
@@ -43,10 +43,9 @@ cmake -S . -B ${OPENEXR_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DBUILD_SHARED_LIBS=${OpenEXR_LOCAL_BUILD_SHARED_LIBS:=ON} \
-DOPENEXR_BUILD_UTILS=0 \
-DBUILD_TESTING=0 \
-DPYILMBASE_ENABLE=0 \
-DOPENEXR_VIEWERS_ENABLE=0 \
-DINSTALL_OPENEXR_EXAMPLES=0 \
-DOPENEXR_INSTALL_EXAMPLES=0 \
@@ -61,9 +60,8 @@ popd
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export ILMBASE_ROOT=$OPENEXR_INSTALL_DIR
export OpenEXR_ROOT=$OPENEXR_INSTALL_DIR
export OPENEXR_ROOT=$OPENEXR_INSTALL_DIR
export ILMBASE_LIBRARY_DIR=$OPENEXR_INSTALL_DIR/lib
export OPENEXR_LIBRARY_DIR=$OPENEXR_INSTALL_DIR/lib
export LD_LIBRARY_PATH=$OPENEXR_ROOT/lib:$LD_LIBRARY_PATH
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Utility script to download and build openjph
#
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Exit the whole script if any command fails.
set -ex
# Repo and branch/tag/commit of openjph to download if we don't have it yet
OPENJPH_REPO=${OPENJPH_REPO:=https://github.com/aous72/OpenJPH.git}
OPENJPH_VERSION=${OPENJPH_VERSION:=0.30.1}
# Where to put openjph repo source (default to the ext area)
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
OPENJPH_SRC_DIR=${OPENJPH_SRC_DIR:=${LOCAL_DEPS_DIR}/openjph}
OPENJPH_BUILD_DIR=${OPENJPH_BUILD_DIR:=${OPENJPH_SRC_DIR}/build}
OPENJPH_INSTALL_DIR=${OPENJPH_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
OPENJPH_BUILD_TYPE=${OPENJPH_BUILD_TYPE:=${CMAKE_BUILD_TYPE:-Release}}
#OPENJPH_CONFIG_OPTS=${OPENJPH_CONFIG_OPTS:=}
pwd
echo "openjph install dir will be: ${OPENJPH_INSTALL_DIR}"
mkdir -p ./ext
pushd ./ext
# Clone openjph project from GitHub and build
if [[ ! -e ${OPENJPH_SRC_DIR} ]] ; then
echo "git clone ${OPENJPH_REPO} ${OPENJPH_SRC_DIR}"
git clone ${OPENJPH_REPO} ${OPENJPH_SRC_DIR}
fi
cd ${OPENJPH_SRC_DIR}
echo "git checkout ${OPENJPH_VERSION} --force"
git checkout ${OPENJPH_VERSION} --force
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -S . -B ${OPENJPH_BUILD_DIR} -DCMAKE_BUILD_TYPE=${OPENJPH_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${OPENJPH_INSTALL_DIR} \
-DOJPH_BUILD_EXECUTABLES=OFF \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DBUILD_SHARED_LIBS=${OPENJPH_BUILD_SHARED_LIBS:-ON} \
${OPENJPH_CONFIG_OPTS}
time cmake --build ${OPENJPH_BUILD_DIR} --target install
fi
# ls -R ${OPENJPH_INSTALL_DIR}
popd
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export openjph_ROOT=$OPENJPH_INSTALL_DIR
+1 -1
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of pugixml to download if we don't have it yet
PUGIXML_REPO=${PUGIXML_REPO:=https://github.com/zeux/pugixml.git}
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.11.4}
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.16}
# Where to put pugixml repo source (default to the ext area)
PUGIXML_SRC_DIR=${PUGIXML_SRC_DIR:=${PWD}/ext/pugixml}
+5 -1
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of pybind11 to download if we don't have it yet
PYBIND11_REPO=${PYBIND11_REPO:=https://github.com/pybind/pybind11.git}
PYBIND11_VERSION=${PYBIND11_VERSION:=v2.8.1}
PYBIND11_VERSION=${PYBIND11_VERSION:=v3.0.1}
# Where to put pybind11 repo source (default to the ext area)
PYBIND11_SRC_DIR=${PYBIND11_SRC_DIR:=${PWD}/ext/pybind11}
@@ -22,6 +22,10 @@ LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
PYBIND11_INSTALL_DIR=${PYBIND11_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
#PYBIND11_BUILD_OPTS=${PYBIND11_BUILD_OPTS:=}
# Fix for pybind11 breaking against cmake 4.0 because of too-old cmake min.
# Remove when pybind11 is fixed to declare its own minimum high enough.
export CMAKE_POLICY_VERSION_MINIMUM=3.5
if [[ "${PYTHON_VERSION}" != "" ]] ; then
PYBIND11_BUILD_OPTS+=" -DPYBIND11_PYTHON_VERSION=${PYTHON_VERSION}"
fi
+2 -2
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of webp to download if we don't have it yet
WEBP_REPO=${WEBP_REPO:=https://github.com/webmproject/libwebp.git}
WEBP_VERSION=${WEBP_VERSION:=v1.1.0}
WEBP_VERSION=${WEBP_VERSION:=v1.6.0}
# Where to put webp repo source (default to the ext area)
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -47,7 +47,7 @@ if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
-DWEBP_BUILD_GIF2WEBPx=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_SHARED_LIBS=${WEBP_BUILD_SHARED_LIBS:-ON} \
${WEBP_CONFIG_OPTS}
time cmake --build ${WEBP_BUILD_DIR} --target install
fi
+4
View File
@@ -21,6 +21,10 @@ ZLIB_BUILD_DIR=${ZLIB_BUILD_DIR:=${ZLIB_SRC_DIR}/build}
ZLIB_INSTALL_DIR=${ZLIB_INSTALL_DIR:=${PWD}/ext/dist}
#ZLIB_CONFIG_OPTS=${ZLIB_CONFIG_OPTS:=}
# Fix zlib which breaks against cmake 4.0 because of too-old cmake min.
# Remove when zlib is fixed to declare its own minimum high enough.
export CMAKE_POLICY_VERSION_MINIMUM=3.5
pwd
echo "zlib install dir will be: ${ZLIB_INSTALL_DIR}"
+1 -1
View File
@@ -41,6 +41,7 @@ for lib in $LIBS ; do
fgrep "Binary compatibility:" ${lib}-abi-results.txt
echo -e "\x1b[33;0m"
done
cp -r compat_reports ${BUILDDIR_NEW}/compat_reports || true
#
# If the "Binary compatibility" summary results say anything other than 100%,
@@ -48,7 +49,6 @@ done
#
for lib in $LIBS ; do
if [[ `fgrep "Binary compatibility:" ${lib}-abi-results.txt | grep -v 100\%` != "" ]] ; then
cp -r compat_reports ${BUILDDIR_NEW}/compat_reports
exit 1
fi
done
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
BUILD_BIN_DIR=build/bin
if [[ "${RUNNER_OS}" == "Windows" ]] ; then
BUILD_BIN_DIR+=/${CMAKE_BUILD_TYPE}
fi
ls build
ls $BUILD_BIN_DIR
mkdir -p build/benchmarks
for t in image_span_test span_test ; do
echo
echo
echo "$t"
echo "========================================================"
OpenImageIO_CI=0 ${BUILD_BIN_DIR}/$t | tee build/benchmarks/$t.out
# Note: set OpenImageIO_CI=0 to avoid CI-specific automatic reduction of
# the number of trials and iterations.
echo "========================================================"
echo "========================================================"
echo
done
+14 -5
View File
@@ -12,13 +12,21 @@ OIIO_CMAKE_FLAGS="$MY_CMAKE_FLAGS $OIIO_CMAKE_FLAGS"
export OIIO_SRC_DIR=${OIIO_SRC_DIR:=$PWD}
export OIIO_BUILD_DIR=${OIIO_BUILD_DIR:=${OIIO_SRC_DIR}/build}
export OIIO_INSTALL_DIR=${OIIO_INSTALL_DIR:=${OIIO_SRC_DIR}/dist}
export OIIO_CMAKE_BUILD_TYPE=${OIIO_CMAKE_BUILD_TYPE:=${CMAKE_BUILD_TYPE:=Release}}
# Allow OIIO_specific overrides for CC, CXX
if [[ "$OIIO_CC" != "" ]] ; then
CC=$OIIO_CC
fi
if [[ "$OIIO_CXX" != "" ]] ; then
CXX=$OIIO_CXX
fi
if [[ "$USE_SIMD" != "" ]] ; then
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
fi
if [[ -n "$FMT_VERSION" ]] ; then
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DBUILD_FMT_VERSION=$FMT_VERSION"
if [[ -n "${OIIO_PYTHON_BINDINGS_BACKEND:-}" ]] ; then
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DOIIO_PYTHON_BINDINGS_BACKEND=${OIIO_PYTHON_BINDINGS_BACKEND}"
fi
if [[ -n "$CODECOV" ]] ; then
@@ -32,18 +40,18 @@ fi
# pushd $OIIO_BUILD_DIR
cmake -S $OIIO_SRC_DIR -B $OIIO_BUILD_DIR -G "$CMAKE_GENERATOR" \
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
-DCMAKE_BUILD_TYPE="${OIIO_CMAKE_BUILD_TYPE}" \
-DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH" \
-DCMAKE_INSTALL_PREFIX="$OpenImageIO_ROOT" \
-DPYTHON_VERSION="$PYTHON_VERSION" \
-DCMAKE_INSTALL_LIBDIR="$OpenImageIO_ROOT/lib" \
-DCMAKE_INSTALL_LIBDIR="lib" \
-DCMAKE_CXX_STANDARD="$CMAKE_CXX_STANDARD" \
-DOIIO_DOWNLOAD_MISSING_TESTDATA=ON \
-DEXTRA_CPP_ARGS="${OIIO_EXTRA_CPP_ARGS}" \
$OIIO_CMAKE_FLAGS -DVERBOSE=1
# Save a copy of the generated files for debugging broken CI builds.
mkdir ${OIIO_BUILD_DIR}/cmake-save || /bin/true
mkdir ${OIIO_BUILD_DIR}/cmake-save || true
cp -r ${OIIO_BUILD_DIR}/CMake* ${OIIO_BUILD_DIR}/*.cmake ${OIIO_BUILD_DIR}/cmake-save
: ${BUILDTARGET:=install}
@@ -53,6 +61,7 @@ if [[ "$BUILDTARGET" != "none" ]] ; then
echo "Using build wrapper '${OIIO_CMAKE_BUILD_WRAPPER}'"
fi
time ${OIIO_CMAKE_BUILD_WRAPPER} cmake --build ${OIIO_BUILD_DIR} --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
ccache --show-stats || true
fi
# popd
@@ -0,0 +1,6 @@
# CI-only: nanobind for CMake (`python -m nanobind --cmake_dir`). Used on Linux
# (gh-installdeps) and Windows (gh-win-installdeps) with pip --require-hashes.
# macOS CI uses `brew install nanobind` instead (install_homebrew_deps.bash).
# When bumping pip pin: https://pypi.org/pypi/nanobind/<ver>/json → wheel sha256.
nanobind==2.12.0 \
--hash=sha256:a10d3d88e691dcdf22696f9acd893fda3c5a05635763aea238829d274fcad480
+15 -9
View File
@@ -12,9 +12,13 @@
export PATH=/usr/local/bin/_ccache:/usr/lib/ccache:$PATH
export USE_CCACHE=${USE_CCACHE:=1}
export CCACHE_CPP2=
export CCACHE_DIR=/tmp/ccache
if [[ "${RUNNER_OS}" == "macOS" ]] ; then
export CCACHE_DIR=$HOME/.ccache
export CCACHE_DIR=$HOME/.ccache
export CCACHE_COMPRESSION=yes
if [[ "$(which ccache)" != "" ]] ; then
# Try to coax dependency building into also using ccache
export CMAKE_CXX_COMPILER_LAUNCHER="ccache"
export CMAKE_C_COMPILER_LAUNCHER="ccache"
ccache -z
fi
mkdir -p $CCACHE_DIR
@@ -27,17 +31,16 @@ export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
export ASAN_OPTIONS=print_suppressions=0
export UBSAN_OPTIONS=suppressions=$PWD/src/build-scripts/ubsan-suppressions.txt
export PYTHON_VERSION=${PYTHON_VERSION:="2.7"}
export PYTHON_VERSION=${PYTHON_VERSION:="3.7"}
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
export BUILD_MISSING_DEPS=${BUILD_MISSING_DEPS:=1}
export COMPILER=${COMPILER:=gcc}
export CC=${CC:=gcc}
export CXX=${CXX:=g++}
export OpenImageIO_CI=true
export OpenImageIO_CI=1
export USE_NINJA=${USE_NINJA:=1}
export CMAKE_GENERATOR=${CMAKE_GENERATOR:=Ninja}
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:=Release}
export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=14}
export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=17}
export LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=$HOME/ext}
export PATH=${LOCAL_DEPS_DIR}/dist/bin:$PATH
@@ -45,9 +48,11 @@ export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib64:$LD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$DYLD_LIBRARY_PATH
# export OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio"
export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1}
# For CI, default to building missing dependencies automatically
export OpenImageIO_BUILD_MISSING_DEPS=${OpenImageIO_BUILD_MISSING_DEPS:=all}
# Sonar
export BUILD_WRAPPER_OUT_DIR="${PWD}/bw_output"
export BW_OUTPUT_DIR="${PWD}/bw_output"
@@ -70,7 +75,8 @@ fi
export PAR_MAKEFLAGS=-j${PARALLEL}
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:=${PARALLEL}}
export CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL:=${PARALLEL}}
export OIIO_USE_CUDA=1
export CUDAToolkit_ROOT=/usr/local/cuda
mkdir -p build dist
+5 -1
View File
@@ -19,7 +19,7 @@ fi
# debugging info in the CI logs.
#
echo ; echo "Results of oiiotool --version:"
$OpenImageIO_ROOT/bin/oiiotool --version || true
$OpenImageIO_ROOT/bin/oiiotool --version
echo ; echo "Results of oiiotool brief help:"
$OpenImageIO_ROOT/bin/oiiotool || true
echo ; echo "Results of oiiotool full --help:"
@@ -34,6 +34,10 @@ $OpenImageIO_ROOT/bin/oiiotool --unittest --list-formats --threads 0 \
echo ; echo "Try unknown command:"
$OpenImageIO_ROOT/bin/oiiotool -q --unknown || true
if [[ `uname -s` == "Linux" ]] ; then
echo ; echo "ldd oiiotool:"
ldd $OpenImageIO_ROOT/bin/oiiotool
fi
#
# Full test suite
+104 -74
View File
@@ -8,59 +8,72 @@
set -ex
# Make extra space on the runners
df -h .
time rm -rf /usr/local/lib/android /host/root/usr/local/lib/android &
sleep 3
# rather than block, delete in background, but give it a few secs to start
# clearing things out before moving on.
# Other candidates, if we need it: /usr/share/dotnet /usr/local/.ghcup
#
# Install system packages when those are acceptable for dependencies.
#
if [[ "$ASWF_ORG" != "" ]] ; then
# Using ASWF CentOS container
# Using ASWF container
#ls /etc/yum.repos.d
sudo yum install -y giflib giflib-devel && true
# This will show how much space is taken by each installed package, sorted
# by size in KB.
# rpm -qa --queryformat '%10{size} - %-25{name} \t %{version}\n' | sort -n
# I would like this to free space by removing packages we don't need.
# BUT IT DOESN'T, because uninstalling a package just ends is visibility
# to the runtime, it doesn't remove it from the static container image
# that's taking up the disk space. So this is pointless. But leaving it
# here to remind myself not to waste time trying it again.
# time sudo yum remove -y nsight-compute-2022.3.0 libcublas-devel-11-8 libcublas-11-8 libcusparse-devel-11-8 libnpp-devel-11-8 libnpp-11-8 libcurand-devel-11-8 libcurand-11-8 || true
# time sudo yum remove -y nsight-compute-2024.3.1 libcublas-devel-12-6 libcublas-12-6 libcusparse-devel-12-6 libnpp-devel-12-6 libnpp-12-6 libcurand-devel-12-6 libcurand-12-6 || true
# time sudo dnf upgrade --refresh || true
if [[ "${DO_RPMFUSION_REPO:-0}" != "0" ]] ; then
time sudo dnf install --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm -y || true
fi
if [[ "$ASWF_VFXPLATFORM_VERSION" == "2022" ]] ; then
# CentOS 7 based containers need the now-nonexistent centos repo to be
# excluded or all the subsequent yum install commands will fail.
yum-config-manager --disable centos-sclo-rh || true
sed -i 's,^mirrorlist=,#,; s,^#baseurl=http://mirror\.centos\.org/centos/$releasever,baseurl=https://vault.centos.org/7.9.2009,' /etc/yum.repos.d/CentOS-Base.repo
fi
# time time sudo yum install -y giflib giflib-devel || true
if [[ "${USE_OPENCV}" != "0" ]] ; then
sudo yum install -y opencv opencv-devel && true
time sudo yum install -y opencv opencv-devel || true
fi
if [[ "${USE_FFMPEG}" != "0" ]] ; then
sudo yum install -y ffmpeg ffmpeg-devel && true
time sudo dnf install -y ffmpeg ffmpeg-devel || true
fi
if [[ "${USE_FREETYPE:-1}" != "0" ]] ; then
time sudo yum install -y freetype freetype-devel || true
fi
if [[ "${USE_LIBRAW:-0}" != "0" ]] ; then
time sudo yum install -y LibRaw LibRaw-devel || true
fi
if [[ "${EXTRA_DEP_PACKAGES}" != "" ]] ; then
time sudo yum install -y ${EXTRA_DEP_PACKAGES}
time sudo yum install -y ${EXTRA_DEP_PACKAGES} || true
fi
if [[ "${PIP_INSTALLS}" != "" ]] ; then
time pip3 install ${PIP_INSTALLS} || true
fi
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
mkdir conan
pushd conan
# Simple way to conan install just one package:
# conan install clang/${CONAN_LLVM_VERSION}@aswftesting/ci_common1 -g deploy -g virtualenv
# But the below method can accommodate multiple requirements:
echo "[imports]" >> conanfile.txt
echo "., * -> ." >> conanfile.txt
echo "[requires]" >> conanfile.txt
echo "clang/${CONAN_LLVM_VERSION}@aswftesting/ci_common1" >> conanfile.txt
time conan install .
echo "--ls--"
ls -R .
export PATH=$PWD/bin:$PATH
export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
export LLVM_ROOT=$PWD
popd
fi
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
# Lock down icc to 2022.1 because newer versions hosted on the Intel
# repo require a glibc too new for the ASWF CentOS7-based containers
# we run CI on.
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0.x86_64
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
elif [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
# Lock down icx to 2023.1 because newer versions hosted on the Intel
# repo require a libstd++ too new for the ASWF containers we run CI on
# because their default install of gcc 9 based toolchain.
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2023.1.0.x86_64
# sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
# If we needed to lock down to a particular version, we could:
# sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2023.1.0.x86_64
set +e; source /opt/intel/oneapi/setvars.sh; set -e
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
icpx --version
@@ -69,23 +82,27 @@ if [[ "$ASWF_ORG" != "" ]] ; then
else
# Using native Ubuntu runner
time sudo apt-get update
if [[ "${SKIP_APT_GET_UPDATE}" != "1" ]] ; then
time sudo apt-get update
fi
time sudo apt-get -q install -y \
git cmake ninja-build ccache g++ \
libboost-dev libboost-thread-dev libboost-filesystem-dev \
libilmbase-dev libopenexr-dev \
libtiff-dev libgif-dev libpng-dev
if [[ "${SKIP_SYSTEM_DEPS_INSTALL}" != "1" ]] ; then
time sudo apt-get -q install -y \
time sudo apt-get -q install -y --fix-missing \
git cmake ninja-build ccache g++ \
libtiff-dev libgif-dev libpng-dev libjpeg-dev \
libraw-dev libwebp-dev \
libavcodec-dev libavformat-dev libswscale-dev libavutil-dev \
dcmtk libopenvdb-dev \
libfreetype6-dev \
locales wget \
libopencolorio-dev \
libtbb-dev \
libopencv-dev
libdeflate-dev bzip2
# Iffy ones get the "|| true" treatment so failure is ok
time sudo apt-get -q install -y --fix-missing \
libjxl-dev || true
fi
if [[ "${USE_OPENCV}" != "0" ]] && [[ "${INSTALL_OPENCV}" != "0" ]] ; then
sudo apt-get -q install -y --fix-missing libopencv-dev || true
fi
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
time sudo apt-get -q install -y \
@@ -97,15 +114,12 @@ else
time sudo apt-get -q install -y ${EXTRA_DEP_PACKAGES}
fi
# Nonstandard python versions
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
time sudo apt-get -q install -y python3.9-dev python3-numpy
pip3 --version
pip3 install numpy
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
time sudo apt-get -q install -y python-dev python-numpy
else
pip3 install numpy
if [[ "${USE_PYTHON}" != "0" ]] ; then
time sudo apt-get -q install -y python3-numpy
fi
: ${PIP_SUFFIX:=}
if [[ "${PIP_INSTALLS}" != "" ]] ; then
time pip3${PIP_SUFFIX} install ${PIP_INSTALLS}
fi
if [[ "$USE_LIBHEIF" != "0" ]] ; then
@@ -116,29 +130,17 @@ else
libheif-plugin-x265 libheif-dev || true
fi
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
if [[ "$CXX" == "g++-6" ]] ; then
time sudo apt-get install -y g++-6
elif [[ "$CXX" == "g++-7" ]] ; then
time sudo apt-get install -y g++-7
elif [[ "$CXX" == "g++-8" ]] ; then
time sudo apt-get install -y g++-8
elif [[ "$CXX" == "g++-9" ]] ; then
time sudo apt-get install -y g++-9
elif [[ "$CXX" == "g++-10" ]] ; then
time sudo apt-get install -y g++-10
elif [[ "$CXX" == "g++-11" ]] ; then
time sudo apt-get install -y g++-11
elif [[ "$CXX" == "g++-12" ]] ; then
time sudo apt-get install -y g++-12
if [[ "${USE_FFMPEG}" != "0" ]] ; then
time sudo apt-get -q install -y ffmpeg || true
fi
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$USE_ICX" != "" ]] ; then
time sudo apt-get -q install -y wget
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
time sudo apt-get update
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
fi
@@ -155,7 +157,7 @@ cmake --version
# If we're using clang to compile on native Ubuntu, we need to install it.
# If on an ASWF CentOS docker container, it already is installed.
#
if [[ ("$CXX" == "clang++" && "$ASWF_ORG" == "") || "$LLVM_VERSION" != "" ]] ; then
if [[ "$LLVM_VERSION" != "" ]] ; then
source src/build-scripts/build_llvm.bash
fi
@@ -165,7 +167,9 @@ fi
# Packages we need to build from scratch.
#
source src/build-scripts/build_pybind11.bash
if [[ "$PYBIND11_VERSION" != "0" ]] ; then
source src/build-scripts/build_pybind11.bash
fi
if [[ "$OPENEXR_VERSION" != "" ]] ; then
source src/build-scripts/build_openexr.bash
@@ -183,6 +187,10 @@ if [[ "$LIBRAW_VERSION" != "" ]] ; then
source src/build-scripts/build_libraw.bash
fi
if [[ "$OPENJPH_VERSION" != "" ]] ; then
source src/build-scripts/build_openjph.bash
fi
if [[ "$OPENJPEG_VERSION" != "" ]] ; then
source src/build-scripts/build_OpenJPEG.bash
fi
@@ -208,6 +216,14 @@ if [[ "$LIBJPEGTURBO_VERSION" != "" ]] ; then
source src/build-scripts/build_libjpeg-turbo.bash
fi
if [[ "$FREETYPE_VERSION" != "" ]] ; then
source src/build-scripts/build_Freetype.bash
fi
if [[ "$LIBPNG_VERSION" != "" ]] ; then
source src/build-scripts/build_libpng.bash
fi
if [[ "$USE_ICC" != "" ]] ; then
# We used gcc for the prior dependency builds, but use icc for OIIO itself
echo "which icpc:" $(which icpc)
@@ -215,5 +231,19 @@ if [[ "$USE_ICC" != "" ]] ; then
export CC=icc
fi
df -h .
df -h /host/root || true
# nanobind's CMake config is discovered via `python -m nanobind --cmake_dir`.
# Version + wheel hash: src/build-scripts/ci-requirements-nanobind.txt (CodeQL / supply chain).
if [[ "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "both" || "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "nanobind" ]] ; then
_oiio_nanobind_requirements_file="$PWD/src/build-scripts/ci-requirements-nanobind.txt"
if [[ "$ASWF_ORG" != "" ]] ; then
time pip3 install -r "$_oiio_nanobind_requirements_file" --require-hashes || true
else
time pip3${PIP_SUFFIX} install -r "$_oiio_nanobind_requirements_file" --require-hashes
fi
fi
# Save the env for use by other stages
src/build-scripts/save-env.bash
+50 -97
View File
@@ -4,19 +4,18 @@
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# DEP_DIR="$PWD/ext/dist"
DEP_DIR="$PWD/dist/$PLATFORM"
mkdir -p "$DEP_DIR"
mkdir -p ext && true
mkdir -p ext
INT_DIR="build/$PLATFORM"
VCPKG_INSTALLATION_ROOT=/c/vcpkg
export CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH:=.}
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;$DEP_DIR"
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;$VCPKG_INSTALLATION_ROOT/installed/x64-windows"
export PATH="$PATH:$DEP_DIR/bin:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/bin:/bin:$PWD/ext/dist/bin:$PWD/ext/dist/lib"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/bin:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/bin"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/lib"
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;$VCPKG_INSTALLATION_ROOT/installed/x64-windows-release"
export PATH="$PATH:$DEP_DIR/bin:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/installed/x64-windows-release/bin:/bin:$PWD/ext/dist/bin:$PWD/ext/dist/lib"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/bin:$VCPKG_INSTALLATION_ROOT/installed/x64-windows-release/bin"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/installed/x64-windows-release/lib"
# export MY_CMAKE_FLAGS="$MY_CMAKE_FLAGS -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
# export OPENEXR_CMAKE_FLAGS="$OPENEXR_CMAKE_FLAGS -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
@@ -25,95 +24,46 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/i
#ls -l "C:/Program Files (x86)/Microsoft Visual Studio" && true
if [[ "$PYTHON_VERSION" == "3.6" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.6.8/x64"
elif [[ "$PYTHON_VERSION" == "3.7" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.7.9/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.7.9/x64/python.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
elif [[ "$PYTHON_VERSION" == "3.9" ]] ; then
if [[ "$PYTHON_VERSION" == "3.9" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.9.13/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.9.13/x64/python3.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
elif [[ "$PYTHON_VERSION" == "3.12" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.12.10/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.12.10/x64/python3.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
elif [[ "$PYTHON_VERSION" == "3.14" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.14.3/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.14.3/x64/python3.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
fi
pip install numpy
if [[ "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "both" || "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "nanobind" ]] ; then
_oiio_nanobind_requirements_file="$PWD/src/build-scripts/ci-requirements-nanobind.txt"
"${Python_EXECUTABLE:-python}" -m pip install -r "$_oiio_nanobind_requirements_file" --require-hashes
fi
########################################################################
# Dependency method #1: Use vcpkg (disabled)
#
# Currently we are not using this, but here it is for reference:
#
echo "All pre-installed VCPkg installs:"
vcpkg list
echo "---------------"
# In case we need vcpkg, example:
# echo "All pre-installed VCPkg installs:"
# vcpkg list
# echo "---------------"
# vcpkg update
#
time vcpkg install boost-container:x64-windows
time vcpkg install boost-filesystem:x64-windows
time vcpkg install boost-math:x64-windows
time vcpkg install boost-stacktrace:x64-windows
time vcpkg install boost-system:x64-windows
time vcpkg install boost-thread:x64-windows
#vcpkg install libdeflate:x64-windows
#vcpkg install zlib:x64-windows
vcpkg install tiff:x64-windows
# vcpkg install libpng:x64-windows
# vcpkg install giflib:x64-windows
vcpkg install freetype:x64-windows
# # vcpkg install openexr:x64-windows
vcpkg install libjpeg-turbo:x64-windows
#
# vcpkg install libraw:x64-windows
# vcpkg install openjpeg:x64-windows
# # vcpkg install ffmpeg:x64-windows # takes FOREVER!
# # vcpkg install webp:x64-windows # No such vcpkg package?a
#
# #echo "$VCPKG_INSTALLATION_ROOT"
# #ls "$VCPKG_INSTALLATION_ROOT"
# #echo "$VCPKG_INSTALLATION_ROOT/installed/x64-windows"
# #ls "$VCPKG_INSTALLATION_ROOT/installed/x64-windows"
# #echo "$VCPKG_INSTALLATION_ROOT/installed/x64-windows/lib"
# #ls "$VCPKG_INSTALLATION_ROOT/installed/x64-windows/lib"
# #echo "$VCPKG_INSTALLATION_ROOT/installed/x64-windows/bin"
# #ls "$VCPKG_INSTALLATION_ROOT/installed/x64-windows/bin"
#
# # export PATH="$PATH:$DEP_DIR/bin:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/bin"
# export PATH="$DEP_DIR/lib:$DEP_DIR/bin:$PATH:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/lib"
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH:$VCPKG_INSTALLATION_ROOT/installed/x64-windows"
# export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$VCPKG_INSTALLATION_ROOT/installed/x64-windows/lib:$DEP_DIR/lib:$DEP_DIR/bin"
#
echo "All VCPkg installs:"
vcpkg list
#
########################################################################
# vcpkg install libdeflate:x64-windows-release
# export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH:$VCPKG_INSTALLATION_ROOT/installed/x64-windows-release"
#echo "All VCPkg installs:"
#vcpkg list
########################################################################
# Dependency method #2: Build from source ourselves
#
#
# src/build-scripts/build_zlib.bash
# export ZLIB_ROOT=$PWD/ext/dist
if [[ "$LIBTIFF_VERSION" != "" ]] ; then
source src/build-scripts/build_libtiff.bash
fi
# src/build-scripts/build_libpng.bash
# export PNG_ROOT=$PWD/ext/dist
# We're currently getting libtiff from vcpkg
#src/build-scripts/build_libtiff.bash
#export TIFF_ROOT=$PWD/ext/dist
# We're currently getting jpeg from vcpkg
# LIBJPEGTURBO_CONFIG_OPTS=-DWITH_SIMD=OFF
# # ^^ because we're too lazy to build nasm
# src/build-scripts/build_libjpeg-turbo.bash
# export JPEGTurbo_ROOT=$PWD/ext/dist
source src/build-scripts/build_pybind11.bash
#export pybind11_ROOT=$PWD/ext/dist
if [[ "$PYBIND11_VERSION" != "0" ]] ; then
source src/build-scripts/build_pybind11.bash
fi
# curl --location https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.2.1-win64-dev.zip -o ffmpeg-dev.zip
@@ -123,24 +73,27 @@ source src/build-scripts/build_pybind11.bash
echo "CMAKE_PREFIX_PATH = $CMAKE_PREFIX_PATH"
OPENEXR_CXX_FLAGS=" /W1 /EHsc /DWIN32=1 "
#OPENEXR_BUILD_TYPE=$CMAKE_BUILD_TYPE
OPENEXR_INSTALL_DIR=$DEP_DIR
source src/build-scripts/build_openexr.bash
export PATH="$OPENEXR_INSTALL_DIR/bin:$OPENEXR_INSTALL_DIR/lib:$PATH"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PATH
# the above line is admittedly sketchy
if [[ "$OPENEXR_VERSION" != "" ]] ; then
OPENEXR_CXX_FLAGS=" /W1 /EHsc /DWIN32=1 "
OPENEXR_INSTALL_DIR=$DEP_DIR
source src/build-scripts/build_openexr.bash
export PATH="$OPENEXR_INSTALL_DIR/bin:$OPENEXR_INSTALL_DIR/lib:$PATH"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PATH
# the above line is admittedly sketchy
fi
cp $DEP_DIR/lib/*.lib $DEP_DIR/bin
cp $DEP_DIR/bin/*.dll $DEP_DIR/lib
echo "OPENCOLORIO_VERSION='${OPENCOLORIO_VERSION}'"
if [[ "$OPENCOLORIO_VERSION" != "" ]] ; then
OPENCOLORIO_INSTALL_DIR=$DEP_DIR
source src/build-scripts/build_opencolorio.bash
export PATH="$OPENCOLORIO_INSTALL_DIR/bin:$OPENCOLORIO_INSTALL_DIR/lib:$PATH"
fi
cp $DEP_DIR/lib/*.lib $DEP_DIR/bin || true
cp $DEP_DIR/bin/*.dll $DEP_DIR/lib || true
echo "DEP_DIR $DEP_DIR :"
ls -R -l "$DEP_DIR"
# source src/build-scripts/build_openexr.bash
# export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;$ILMBASE_ROOT;$OPENEXR_ROOT"
# source src/build-scripts/build_opencolorio.bash
# Save the env for use by other stages
src/build-scripts/save-env.bash
+40 -30
View File
@@ -19,49 +19,59 @@ if [[ `which brew` == "" ]] ; then
exit 1
fi
set -ex
#brew update >/dev/null
if [[ "${DO_BREW_UPDATE:=0}" != "0" ]] ; then
brew update >/dev/null
fi
echo ""
echo "Before my brew installs:"
brew list --versions
# All cases except for clang-format target, we need the dependencies.
brew install --display-times -q gcc ccache cmake ninja boost || true
brew link --overwrite gcc
brew install --display-times -q python@${PYTHON_VERSION} || true
brew unlink python@3.8 || true
brew unlink python@3.9 || true
brew unlink python@3.10 || true
brew link --overwrite --force python@${PYTHON_VERSION} || true
#brew upgrade --display-times -q cmake || true
#brew install --display-times -q libtiff
brew install --display-times -q imath openexr opencolorio
#brew install --display-times -q libpng giflib webp
brew install --display-times -q jpeg-turbo openjpeg
brew install --display-times -q freetype libraw dcmtk pybind11 numpy || true
brew install --display-times -q ffmpeg libheif ptex || true
brew install --display-times -q tbb || true
brew install --display-times -q openvdb || true
if [[ "${USE_OPENCV}" != "0" ]] ; then
brew install --display-times -q opencv || true
fi
if [[ "${USE_QT}" != "0" ]] ; then
brew install --display-times -q qt${QT_VERSION}
if [[ "$OIIO_BREW_INSTALL_PACKAGES" == "" ]] ; then
OIIO_BREW_INSTALL_PACKAGES=" \
ccache \
dcmtk \
expat \
ffmpeg \
imath \
jpeg-xl \
libheif \
libraw \
libultrahdr \
numpy \
opencolorio \
openexr \
openjpeg \
ptex \
pybind11 \
robin-map \
tbb \
"
if [[ "${USE_OPENCV:=}" != "0" ]] && [[ "${INSTALL_OPENCV:=1}" != "0" ]] ; then
OIIO_BREW_INSTALL_PACKAGES+=" opencv"
fi
if [[ "${USE_OPENVDB:=1}" != "0" ]] && [[ "${INSTALL_OPENVDB:=1}" != "0" ]] ; then
OIIO_BREW_INSTALL_PACKAGES+=" openvdb"
fi
if [[ "${USE_QT:=1}" != "0" ]] && [[ "${INSTALL_QT:=1}" != "0" ]] ; then
OIIO_BREW_INSTALL_PACKAGES+=" qt${QT_VERSION}"
fi
if [[ "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "both" || "${OIIO_PYTHON_BINDINGS_BACKEND:-}" == "nanobind" ]] ; then
OIIO_BREW_INSTALL_PACKAGES+=" nanobind"
fi
fi
brew install --display-times -q $OIIO_BREW_INSTALL_PACKAGES $OIIO_BREW_EXTRA_INSTALL_PACKAGES || true
echo ""
echo "After brew installs:"
brew list --versions
# Needed on some systems
pip${PYTHON_VERSION} install numpy
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export PATH=/usr/local/opt/qt5/bin:$PATH
export PATH=/usr/local/opt/python/libexec/bin:$PATH
export PYTHONPATH=/usr/local/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
#export PATH=/usr/local/opt/llvm/bin:$PATH
export PATH=${HOMEBREW_PREFIX}/opt/qt5/bin:$PATH
export PATH=${HOMEBREW_PREFIX}/opt/python/libexec/bin:$PATH
export PYTHONPATH=${HOMEBREW_PREFIX}/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
# Save the env for use by other stages
src/build-scripts/save-env.bash
+190
View File
@@ -0,0 +1,190 @@
#!/usr/bin/env python3
# Copyright 2018 Nico Weber
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Converts one (or several) .ninja_log files into chrome's about:tracing format.
If clang -ftime-trace .json files are found adjacent to generated files they
are embedded.
Usage:
ninja -C $BUILDDIR
ninjatracing $BUILDDIR/.ninja_log > trace.json
"""
import json
import os
import optparse
import re
import sys
class Target:
"""Represents a single line read for a .ninja_log file. Start and end times
are milliseconds."""
def __init__(self, start, end):
self.start = int(start)
self.end = int(end)
self.targets = []
def read_targets(log, show_all):
"""Reads all targets from .ninja_log file |log_file|, sorted by start
time"""
header = log.readline()
m = re.search(r'^# ninja log v(\d+)\n$', header)
assert m, "unrecognized ninja log version %r" % header
version = int(m.group(1))
assert 5 <= version <= 6, "unsupported ninja log version %d" % version
if version == 6:
# Skip header line
next(log)
targets = {}
last_end_seen = 0
for line in log:
if line.startswith('#'):
continue
start, end, _, name, cmdhash = line.strip().split('\t') # Ignore restat.
if not show_all and int(end) < last_end_seen:
# An earlier time stamp means that this step is the first in a new
# build, possibly an incremental build. Throw away the previous data
# so that this new build will be displayed independently.
targets = {}
last_end_seen = int(end)
targets.setdefault(cmdhash, Target(start, end)).targets.append(name)
return sorted(targets.values(), key=lambda job: job.end, reverse=True)
class Threads:
"""Tries to reconstruct the parallelism from a .ninja_log"""
def __init__(self):
self.workers = [] # Maps thread id to time that thread is occupied for.
def alloc(self, target):
"""Places target in an available thread, or adds a new thread."""
for worker in range(len(self.workers)):
if self.workers[worker] >= target.end:
self.workers[worker] = target.start
return worker
self.workers.append(target.start)
return len(self.workers) - 1
def read_events(trace, options):
"""Reads all events from time-trace json file |trace|."""
trace_data = json.load(trace)
def include_event(event, options):
"""Only include events if they are complete events, are longer than
granularity, and are not totals."""
return ((event['ph'] == 'X') and
(event['dur'] >= options['granularity']) and
(not event['name'].startswith('Total')))
return [x for x in trace_data['traceEvents'] if include_event(x, options)]
def trace_to_dicts(target, trace, options, pid, tid):
"""Read a file-like object |trace| containing -ftime-trace data and yields
about:tracing dict per eligible event in that log."""
ninja_time = (target.end - target.start) * 1000
for event in read_events(trace, options):
# Check if any event duration is greater than the duration from ninja.
if event['dur'] > ninja_time:
print("Inconsistent timing found (clang time > ninja time). Please"
" ensure that timings are from consistent builds.")
sys.exit(1)
# Set tid and pid from ninja log.
event['pid'] = pid
event['tid'] = tid
# Offset trace time stamp by ninja start time.
event['ts'] += (target.start * 1000)
yield event
def embed_time_trace(ninja_log_dir, target, pid, tid, options):
"""Produce time trace output for the specified ninja target. Expects
time-trace file to be in .json file named based on .o file."""
for t in target.targets:
o_path = os.path.join(ninja_log_dir, t)
json_trace_path = os.path.splitext(o_path)[0] + '.json'
try:
with open(json_trace_path, 'r') as trace:
for time_trace_event in trace_to_dicts(target, trace, options,
pid, tid):
yield time_trace_event
except IOError:
pass
def log_to_dicts(log, pid, options):
"""Reads a file-like object |log| containing a .ninja_log, and yields one
about:tracing dict per command found in the log."""
threads = Threads()
for target in read_targets(log, options['showall']):
tid = threads.alloc(target)
yield {
'name': '%0s' % ', '.join(target.targets), 'cat': 'targets',
'ph': 'X', 'ts': (target.start * 1000),
'dur': ((target.end - target.start) * 1000),
'pid': pid, 'tid': tid, 'args': {},
}
if options.get('embed_time_trace', False):
# Add time-trace information into the ninja trace.
try:
ninja_log_dir = os.path.dirname(log.name)
except AttributeError:
continue
for time_trace in embed_time_trace(ninja_log_dir, target, pid,
tid, options):
yield time_trace
def main(argv):
usage = __doc__
parser = optparse.OptionParser(usage)
parser.add_option('-a', '--showall', action='store_true', dest='showall',
default=False,
help='report on last build step for all outputs. Default '
'is to report just on the last (possibly incremental) '
'build')
parser.add_option('-g', '--granularity', type='int', default=50000,
dest='granularity',
help='minimum length time-trace event to embed in '
'microseconds. Default: %default')
parser.add_option('-e', '--embed-time-trace', action='store_true',
default=False, dest='embed_time_trace',
help='embed clang -ftime-trace json file found adjacent '
'to a target file')
(options, args) = parser.parse_args()
if len(args) == 0:
print('Must specify at least one .ninja_log file')
parser.print_help()
return 1
entries = []
for pid, log_file in enumerate(args):
with open(log_file, 'r') as log:
entries += list(log_to_dicts(log, pid, vars(options)))
json.dump(entries, sys.stdout)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
# Important: set -ex causes this whole script to terminate with error if
# any command in it fails. This is crucial for CI tests.
set -ex
CLANG_FORMAT_EXE=${CLANG_FORMAT_EXE:="clang-format"}
echo "Running " `which clang-format` " version " `${CLANG_FORMAT_EXE} --version`
files=`find ./{src,testsuite} \( -name '*.h' -o -name '*.cpp' \) -print \
| grep -Ev 'pugixml|SHA1|farmhash.cpp|libdpx|libcineon|bcdec.h|gif.h|stb_sprintf.h'`
${CLANG_FORMAT_EXE} -i -style=file $files
git diff --color
THEDIFF=`git diff`
if [[ "$THEDIFF" != "" ]] ; then
echo "git diff was not empty. Failing clang-format check."
exit 1
fi
+2
View File
@@ -0,0 +1,2 @@
vptr:function.h
vptr:openvdb::v11_0
+48
View File
@@ -0,0 +1,48 @@
#include <winver.h>
#define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
#define VER_FILEVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.0\0"
#define VER_PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
#define VER_PRODUCTVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@\0"
#ifndef DEBUG
#define VER_DEBUG 0
#else
#define VER_DEBUG VS_FF_DEBUG
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS (VER_DEBUG)
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "OpenImageIO"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "OpenImageIO"
VALUE "ProductName", "OpenImageIO"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
/* The following line should only be modified for localized versions. */
/* It consists of any number of WORD,WORD pairs, with each pair */
/* describing a language,codepage combination supported by the file. */
/* */
/* For example, a file might have values "0x409,1252" indicating that it */
/* supports English language (0x409) in the Windows ANSI codepage (1252). */
VALUE "Translation", 0x409, 1252
END
END
+39 -11
View File
@@ -41,6 +41,7 @@ private:
m_stream = nullptr;
}
m_userBuf.clear();
m_cin.SetInStream(nullptr);
}
/// Helper function - retrieve string for libcineon descriptor
@@ -89,12 +90,35 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
return false;
}
int nchannels = m_cin.header.NumberOfElements();
if (nchannels < 1 || nchannels > 8) {
errorfmt("Invalid number of channels {} (must be 1-8)", nchannels);
close();
return false;
}
// create imagespec
TypeDesc typedesc;
int maxbits = 0;
for (int i = 0; i < m_cin.header.NumberOfElements(); i++) {
if (maxbits < m_cin.header.BitDepth(i))
maxbits = m_cin.header.BitDepth(i);
for (int i = 0; i < nchannels; i++) {
int b(m_cin.header.BitDepth(i));
// libcineon's ComponentDataSize/ComponentByteCount only know how to
// handle these bit depths; anything else asserts (or worse, in a
// non-debug build) deep inside the vendored library. Reject bogus
// values here so we can give a proper error instead.
switch (b) {
case 8:
case 10:
case 12:
case 16:
case 32:
case 64: break;
default:
errorfmt("Invalid bitdepth in channel {}: {} bits", i, b);
close();
return false;
}
maxbits = std::max(maxbits, b);
}
switch ((maxbits + 7) / 8) {
case 1: typedesc = TypeDesc::UINT8; break;
@@ -103,8 +127,13 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
case 4: typedesc = TypeDesc::UINT32; break;
default: errorfmt("Unsupported bit depth {}", maxbits); return false;
}
m_spec = ImageSpec(m_cin.header.Width(), m_cin.header.Height(),
m_cin.header.NumberOfElements(), typedesc);
m_spec = ImageSpec(m_cin.header.Width(), m_cin.header.Height(), nchannels,
typedesc);
if (!check_open(m_spec, { 0, 1 << 30, 0, 1 << 30, 0, 1, 0, 8 })) {
return false;
}
// fill channel names
m_spec.channelnames.clear();
int gscount = 0, rcount = 0, gcount = 0, bcount = 0;
@@ -119,7 +148,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
break;
case cineon::kPrintingDensityRed:
case cineon::kRec709Red:
if (++gscount > 1) {
if (++rcount > 1) {
std::string ch = Strutil::fmt::format("R{}", rcount);
m_spec.channelnames.push_back(ch);
} else
@@ -169,7 +198,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
// This is not very smart, but it seems that as a practical matter,
// all Cineon files are log. So ignore the gamma field and just set
// the color space to KodakLog.
m_spec.attribute("oiio:ColorSpace", "KodakLog");
m_spec.set_colorspace("KodakLog");
#else
// image linearity
// FIXME: making this more robust would require the per-channel transfer
@@ -177,19 +206,18 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
switch (m_cin.header.ImageDescriptor(0)) {
case cineon::kRec709Red:
case cineon::kRec709Green:
case cineon::kRec709Blue: m_spec.attribute("oiio:ColorSpace", "Rec709");
case cineon::kRec709Blue: m_spec.set_colorspace("Rec709");
default:
// either grayscale or printing density
if (!std::isinf(m_cin.header.Gamma()) && m_cin.header.Gamma() != 0.0f)
// actual gamma value is read later on
m_spec.attribute("oiio:ColorSpace",
Strutil::fmt::format("Gamma{:.2g}", g));
set_colorspace_rec709_gamma(m_spec, float(m_cin.header.Gamma()));
break;
}
// gamma exponent
if (!std::isinf(m_cin.header.Gamma()) && m_cin.header.Gamma() != 0.0f)
m_spec.attribute("oiio:Gamma", (float)m_cin.header.Gamma());
set_colorspace_rec709_gamma(m_spec, float(m_cin.header.Gamma()));
#endif
// general metadata
+4 -12
View File
@@ -8,20 +8,11 @@ include(CMakeFindDependencyMacro)
# add here all the find_dependency() whenever switching to config based dependencies
if (NOT @OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH@ AND NOT OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH)
if (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 3.0)
find_dependency(Imath @Imath_VERSION@
HINTS @Imath_DIR@)
elseif (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 2.4 AND @FOUND_OPENEXR_WITH_CONFIG@)
find_dependency(IlmBase @OpenEXR_VERSION@
HINTS @IlmBase_DIR@ @OpenEXR_DIR@)
find_dependency(OpenEXR @OpenEXR_VERSION@
HINTS @OpenEXR_DIR@)
find_dependency(ZLIB @ZLIB_VERSION@) # Because OpenEXR doesn't do it
find_dependency(Threads) # Because OpenEXR doesn't do it
endif ()
find_dependency(Imath @Imath_VERSION@
HINTS @Imath_DIR@)
endif ()
if (NOT @OIIO_USING_FMT_LOCAL@ AND NOT @INTERNALIZE_FMT@)
if (NOT @fmt_LOCAL_BUILD@ AND (NOT @OIIO_INTERNALIZE_FMT@ OR @OIIO_USE_COMPILED_FMT@))
find_dependency(fmt)
endif ()
@@ -30,6 +21,7 @@ if (NOT @BUILD_SHARED_LIBS@)
# INTERFACE_LINK_LIBRARIES. If the project does not know about PNG target, it will cause
# configuration error about unknown targets being linked in.
find_dependency(TIFF)
find_dependency(OpenColorIO)
if (@JPEG_FOUND@)
find_dependency(JPEG)
endif()
+14 -6
View File
@@ -11,15 +11,17 @@
# [ NAME targetname ... ]
# [ SRC source1 ... ]
# [ INCLUDE_DIRS include_dir1 ... ]
# [ LINK_DIRECTORIES link_dir1 ... ]
# [ LINK_LIBRARIES external_lib1 ... ]
# [ DEFINITIONS -DFOO=bar ... ])
# [ COMPILE_OPTIONS -Wflag ... ]
# [ DEFINITIONS FOO=bar ... ])
#
# The plugin name can be specified with NAME, otherwise is inferred from the
# subdirectory name. The source files of the binary can be specified with
# SRC, otherwise are inferred to be all the .cpp files within the
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, and
# private LINK_LIBRARIES may also be specified. The source is automatically
# linked against OpenImageIO.
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, private
# LINK_DIRECTORIES, and private LINK_LIBRARIES may also be specified.
# The source is automatically linked against OpenImageIO.
#
# The plugin may be disabled individually using any of the usual
# check_is_enabled() conventions (e.g. -DENABLE_<format>=OFF).
@@ -34,7 +36,7 @@
# be handed off too the setup of the later OpenImageIO target.
#
macro (add_oiio_plugin)
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_LIBRARIES;DEFINITIONS" ${ARGN})
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_DIRECTORIES;LINK_LIBRARIES;COMPILE_OPTIONS;DEFINITIONS" ${ARGN})
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
get_filename_component (_plugin_name ${CMAKE_CURRENT_SOURCE_DIR} NAME_WE)
if (NOT _plugin_NAME)
@@ -61,7 +63,9 @@ macro (add_oiio_plugin)
endforeach ()
set (libOpenImageIO_srcs "${_plugin_all_source}" PARENT_SCOPE)
set (format_plugin_definitions ${format_plugin_definitions} ${_plugin_DEFINITIONS} PARENT_SCOPE)
set (format_plugin_compile_options ${format_plugin_compile_options} ${_plugin_COMPILE_OPTIONS} PARENT_SCOPE)
set (format_plugin_include_dirs ${format_plugin_include_dirs} ${_plugin_INCLUDE_DIRS} PARENT_SCOPE)
set (format_plugin_lib_dirs ${format_plugin_lib_dirs} ${_plugin_LINK_DIRECTORIES} PARENT_SCOPE)
set (format_plugin_libs ${format_plugin_libs} ${_plugin_LINK_LIBRARIES} PARENT_SCOPE)
else ()
# # Get the name of the current directory and use it as the target name.
@@ -70,7 +74,11 @@ macro (add_oiio_plugin)
target_compile_definitions (${_plugin_NAME} PRIVATE
${_plugin_DEFINITIONS}
OpenImageIO_EXPORTS)
target_include_directories (${_plugin_NAME} PRIVATE ${_plugin_INCLUDE_DIRS})
target_compile_options (${_plugin_NAME} PRIVATE ${_plugin_COMPILE_OPTIONS})
target_include_directories (${_plugin_NAME} BEFORE PRIVATE ${_plugin_INCLUDE_DIRS})
if (_plugin_LINK_DIRECTORIES)
target_link_directories (${_plugin_NAME} PRIVATE ${_plugin_LINK_DIRECTORIES})
endif ()
target_link_libraries (${_plugin_NAME} PUBLIC OpenImageIO
PRIVATE ${_plugin_LINK_LIBRARIES})
set_target_properties (${_plugin_NAME} PROPERTIES PREFIX "" FOLDER "Plugins")
+52
View File
@@ -0,0 +1,52 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# Freetype by hand!
######################################################################
set_cache (Freetype_BUILD_VERSION 2.14.1 "Freetype version for local builds")
set (Freetype_GIT_REPOSITORY "https://github.com/freetype/freetype")
set (Freetype_GIT_TAG "VER-2-14-1")
set (Freetype_GIT_COMMIT "526ec5c47b9ebccc4754c85ac0c0cdf7c85a5e9b")
set_cache (Freetype_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should a local Freetype build, if necessary, build shared libraries" ADVANCED)
# We would prefer to build a static Freetype, but haven't figured out how to make
# it all work with the static dependencies, it just makes things complicated
# downstream.
string (MAKE_C_IDENTIFIER ${Freetype_BUILD_VERSION} Freetype_VERSION_IDENT)
# Conditionally disable support for PNG-compressed OpenType embedded bitmaps on MacOS
# https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/4423#issuecomment-2455217897
if ( APPLE )
set (_freetype_EXTRA_CMAKE_ARGS -DFT_DISABLE_PNG=ON )
endif ()
build_dependency_with_cmake(Freetype
VERSION ${Freetype_BUILD_VERSION}
GIT_REPOSITORY ${Freetype_GIT_REPOSITORY}
GIT_TAG ${Freetype_GIT_TAG}
GIT_COMMIT ${Freetype_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_SHARED_LIBS=${Freetype_BUILD_SHARED_LIBS}
-D CMAKE_POSITION_INDEPENDENT_CODE=ON
-D CMAKE_INSTALL_LIBDIR=lib
${_freetype_EXTRA_CMAKE_ARGS}
# Fix for freetype breaking against cmake 4.0.
# Remove when freetype is fixed to declare its own minimum high enough.
-D CMAKE_POLICY_VERSION_MINIMUM=3.5
)
# Set some things up that we'll need for a subsequent find_package to work
set (Freetype_ROOT ${Freetype_LOCAL_INSTALL_DIR})
# Signal to caller that we need to find again at the installed location
set (Freetype_REFIND TRUE)
set (Freetype_REFIND_ARGS CONFIG)
if (Freetype_BUILD_SHARED_LIBS)
install_local_dependency_libs (Freetype Freetype)
endif ()
+41
View File
@@ -0,0 +1,41 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# GIF/GIFLIB
# The original library does not have a CMake build system, so we
# provide our own CMakeLists.txt template to build it.
# See build_GIF_CMakeLists.txt for details.
######################################################################
set_cache (GIF_BUILD_VERSION "5.2.1" "GIFLIB version for local builds")
super_set (GIF_BUILD_GIT_REPOSITORY "https://git.code.sf.net/p/giflib/code")
super_set (GIF_BUILD_GIT_TAG "${GIF_BUILD_VERSION}")
super_set (GIF_BUILD_GIT_COMMIT "52b62de83d5facbbbde042b85bf3f61182e3bebd")
set_cache (GIF_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should execute a local GIFLIB build; if necessary, build shared libraries" ADVANCED)
string (MAKE_C_IDENTIFIER ${GIF_BUILD_VERSION} GIF_VERSION_IDENT)
set (GIF_CMAKELISTS_TEMPLATE_PATH "${CMAKE_CURRENT_LIST_DIR}/build_GIF_CMakeLists.txt")
build_dependency_with_cmake(GIF
VERSION ${GIF_BUILD_VERSION}
GIT_REPOSITORY ${GIF_BUILD_GIT_REPOSITORY}
GIT_TAG ${GIF_BUILD_GIT_TAG}
GIT_COMMIT ${GIF_BUILD_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_SHARED_LIBS=${GIF_BUILD_SHARED_LIBS}
)
unset(GIF_CMAKELISTS_TEMPLATE_PATH)
# Set some things up that we'll need for a subsequent find_package to work
set (GIF_ROOT ${GIF_LOCAL_INSTALL_DIR})
# Signal to caller that we need to find again at the installed location
find_package (GIF ${GIF_BUILD_VERSION} EXACT CONFIG REQUIRED)
if (GIF_BUILD_SHARED_LIBS)
install_local_dependency_libs (GIF GIF)
endif ()
+280
View File
@@ -0,0 +1,280 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# CMakeLists.txt for GIF/GIFLIB
# GIFLib repository doesn't have a cmakelists.txt included.
# So when we clone the repository on build_GIF.cmake, we also want to
# add this file as a "CMakeLists.txt" into the repository. This way
# we can run it the same way with other libraries, following the same
# logic as the build_with_cmake_macro
# Windows compatibility: Source code includes unistd.h, which is not available
# on Windows systems. We patch source files to use appropriate Windows
# alternatives and use these patched files (in GIF-build) instead of
# the originals (GIF)
######################################################################
cmake_minimum_required (VERSION @CMAKE_MINIMUM_REQUIRED_VERSION@)
project(GIF VERSION @GIF_BUILD_VERSION@ LANGUAGES C)
# Options
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(BUILD_UTILS "Build utility programs" OFF)
# Set MSVC specific flags and runtime
if(MSVC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
# Let runtime library be set by CMAKE_MSVC_RUNTIME_LIBRARY from command line
if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
if(BUILD_SHARED_LIBS)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif()
# Ensure proper DLL export/import
if(BUILD_SHARED_LIBS)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
endif()
# replace #includes unistd to use windows equivalent
if(WIN32)
file(GLOB_RECURSE ORIGINAL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
foreach(HEADER ${ORIGINAL_HEADERS})
# Compute output path in build dir
file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${HEADER}")
set(OUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${REL_PATH}")
# Make sure directory exists
get_filename_component(OUT_DIR ${OUT_HEADER} DIRECTORY)
file(MAKE_DIRECTORY ${OUT_DIR})
# Read header
file(READ ${HEADER} CONTENTS)
# Add #ifdef guards to unistd.h
if(CONTENTS MATCHES "#include <unistd.h>")
string(REPLACE "#include <unistd.h>" "#ifdef _WIN32\n#include <io.h>\n#else\n#include <unistd.h>\n#endif" CONTENTS "${CONTENTS}")
endif()
# Write patched header
file(WRITE ${OUT_HEADER} "${CONTENTS}")
# Add patched directory to include path
include_directories(${CMAKE_CURRENT_BINARY_DIR})
endforeach()
endif()
# Set output directories
if(MSVC)
# For MSVC, we want Debug and Release in separate directories
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin/${OUTPUTCONFIG})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib/${OUTPUTCONFIG})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib/${OUTPUTCONFIG})
endforeach()
else()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
# Core library source files
if (WIN32)
# Use patched files from build directory
set(GIF_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/dgif_lib.c
${CMAKE_CURRENT_BINARY_DIR}/egif_lib.c
${CMAKE_CURRENT_BINARY_DIR}/gif_err.c
${CMAKE_CURRENT_BINARY_DIR}/gif_hash.c
${CMAKE_CURRENT_BINARY_DIR}/gifalloc.c
${CMAKE_CURRENT_BINARY_DIR}/openbsd-reallocarray.c
${CMAKE_CURRENT_BINARY_DIR}/quantize.c
)
else()
# Use original files on non-Windows platforms
set(GIF_SOURCES
dgif_lib.c
egif_lib.c
gif_err.c
gif_hash.c
gifalloc.c
openbsd-reallocarray.c
quantize.c
)
endif()
# Define the GIF library
if(BUILD_SHARED_LIBS)
add_library(GIF SHARED ${GIF_SOURCES})
if (MSVC)
# Add export definitions for Windows DLL
target_compile_definitions(GIF
PRIVATE -DGIF_EXPORTS
PUBLIC -DGIF_DLL
)
endif()
else()
add_library(GIF STATIC ${GIF_SOURCES})
endif()
# Create an alias target since we want to refer to it as GIF::GIF
add_library(GIF::GIF ALIAS GIF)
# Set library properties
set_target_properties(GIF PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME "GIF"
# Ensure PIC just in case we need to link it into a shared library
POSITION_INDEPENDENT_CODE ON
)
# Add include path for GIFLIB
if(WIN32)
target_include_directories(GIF
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
else()
target_include_directories(GIF
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
endif()
# Utility programs common source files
if(WIN32)
# Use patched files from build directory
set(UTILS_COMMON_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/getarg.c
${CMAKE_CURRENT_BINARY_DIR}/qprintf.c
${CMAKE_CURRENT_BINARY_DIR}/gif_font.c
)
else()
# Use original files on non-Windows platforms
set(UTILS_COMMON_SOURCES
getarg.c
qprintf.c
gif_font.c
)
endif()
# Define utility programs
set(UTILS
gif2rgb
gifbuild
gifbg
gifclrmp
gifcolor
gifecho
giffilter
giffix
gifhisto
gifinto
gifsponge
giftext
giftool #note: this requires getopt.c, which is not available on Windows
gifwedge
)
# Build utilities if enabled
if(BUILD_UTILS)
foreach(UTIL ${UTILS})
add_executable(${UTIL} ${UTIL}.c ${UTILS_COMMON_SOURCES})
target_link_libraries(${UTIL} PRIVATE GIF m)
# Set utility output properties
set_target_properties(${UTIL} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}"
PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
endforeach()
endif()
# Installation
include(GNUInstallDirs)
install(TARGETS GIF
EXPORT GIFTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# Install headers
if(WIN32)
# Install patched headers from build directory
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/gif_lib.h
${CMAKE_CURRENT_BINARY_DIR}/gif_hash.h
${CMAKE_CURRENT_BINARY_DIR}/gif_lib_private.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
else()
# Install original headers on non-Windows platforms
install(FILES
gif_lib.h
gif_hash.h
gif_lib_private.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()
# Install utilities
if(BUILD_UTILS)
install(TARGETS ${UTILS}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()
# Export targets
install(EXPORT GIFTargets
FILE GIFTargets.cmake
NAMESPACE GIF::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/GIF
)
# Create and install config files
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/GIFConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
# since we don't have a GIFConfig.cmake file in the source tree, we want to create
# one and install it
set(GIF_CONFIG_IN "
@PACKAGE_INIT@
include(\${CMAKE_CURRENT_LIST_DIR}/GIFTargets.cmake)
check_required_components(GIF)
")
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/GIFConfig.cmake.in" "${GIF_CONFIG_IN}")
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/GIFConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/GIFConfig.cmake"
INSTALL_DESTINATION lib/cmake/GIF
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/GIFConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/GIFConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/GIF
)
+49
View File
@@ -0,0 +1,49 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# Imath by hand!
######################################################################
set_cache (Imath_BUILD_VERSION 3.1.10 "Imath version for local builds")
set (Imath_GIT_REPOSITORY "https://github.com/AcademySoftwareFoundation/Imath")
set (Imath_GIT_TAG "v${Imath_BUILD_VERSION}")
set (Imath_GIT_COMMIT "9fe5ed213cd99237976f2eb48b8bf86e112d90fa")
set_cache (Imath_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should a local Imath build, if necessary, build shared libraries" ADVANCED)
string (MAKE_C_IDENTIFIER ${Imath_BUILD_VERSION} Imath_VERSION_IDENT)
build_dependency_with_cmake(Imath
VERSION ${Imath_BUILD_VERSION}
GIT_REPOSITORY ${Imath_GIT_REPOSITORY}
GIT_TAG ${Imath_GIT_TAG}
GIT_COMMIT ${Imath_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_SHARED_LIBS=${Imath_BUILD_SHARED_LIBS}
# Don't built unnecessary parts of Imath
-D BUILD_TESTING=OFF
-D IMATH_BUILD_EXAMPLES=OFF
-D IMATH_BUILD_PYTHON=OFF
-D IMATH_BUILD_TESTING=OFF
-D IMATH_BUILD_TOOLS=OFF
-D IMATH_INSTALL_DOCS=OFF
-D IMATH_INSTALL_PKG_CONFIG=OFF
-D IMATH_INSTALL_TOOLS=OFF
# Give the library a custom name and symbol namespace so it can't
# conflict with any others in the system or linked into the same app.
# not needed -D IMATH_NAMESPACE_CUSTOM=1
# not needed -D IMATH_INTERNAL_NAMESPACE=${PROJ_NAMESPACE_V}_Imath_${Imath_VERSION_IDENT}
-D IMATH_LIB_SUFFIX=_v${Imath_VERSION_IDENT}_${PROJ_NAMESPACE_V}
)
# Signal to caller that we need to find again at the installed location
set (Imath_REFIND TRUE)
set (Imath_REFIND_ARGS CONFIG)
set (Imath_REFIND_VERSION ${Imath_BUILD_VERSION})
if (Imath_BUILD_SHARED_LIBS)
install_local_dependency_libs (Imath Imath)
endif ()
+73
View File
@@ -0,0 +1,73 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# OpenColorIO by hand!
######################################################################
set_cache (OpenColorIO_BUILD_VERSION 2.5.1 "OpenColorIO version for local builds")
set (OpenColorIO_GIT_REPOSITORY "https://github.com/AcademySoftwareFoundation/OpenColorIO")
set (OpenColorIO_GIT_TAG "v${OpenColorIO_BUILD_VERSION}")
set (OpenColorIO_GIT_COMMIT "004f80009653fa322c1133ba2c57b8ed526599c9")
set_cache (OpenColorIO_BUILD_SHARED_LIBS OFF
DOC "Should a local OpenColorIO build, if necessary, build shared libraries" ADVANCED)
# We would prefer to build a static OCIO, but haven't figured out how to make
# it all work with the static dependencies, it just makes things complicated
# downstream.
# Clear variables from the failed find_package
unset (OPENCOLORIO_LIBRARY)
unset (OPENCOLORIO_INCLUDE_DIR)
unset (FIND_PACKAGE_MESSAGE_DETAILS_OpenColorIO)
unset (OPENCOLORIO_VERSION_MAJOR)
unset (OPENCOLORIO_VERSION_MINOR)
unset (OpenColorIO_DIR)
checked_find_package(pystring VERSION_MIN 1.1.3)
checked_find_package(expat REQUIRED VERSION_MIN 2.6)
checked_find_package(yaml-cpp REQUIRED VERSION_MIN 0.8.0)
checked_find_package(minizip-ng REQUIRED VERSION_MIN 4.0.10)
string (MAKE_C_IDENTIFIER ${OpenColorIO_BUILD_VERSION} OpenColorIO_VERSION_IDENT)
build_dependency_with_cmake(OpenColorIO
VERSION ${OpenColorIO_BUILD_VERSION}
GIT_REPOSITORY ${OpenColorIO_GIT_REPOSITORY}
GIT_TAG ${OpenColorIO_GIT_TAG}
GIT_COMMIT ${OpenColorIO_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_SHARED_LIBS=${OpenColorIO_BUILD_SHARED_LIBS}
-D CMAKE_POSITION_INDEPENDENT_CODE=ON
-D CMAKE_INSTALL_LIBDIR=lib
# Don't built unnecessary parts of OCIO
-D OCIO_BUILD_APPS=OFF
-D OCIO_BUILD_GPU_TESTS=OFF
-D OCIO_BUILD_PYTHON=OFF
-D OCIO_BUILD_TESTS=OFF
-D OCIO_USE_OIIO_FOR_APPS=OFF
-D OCIO_INSTALL_DOCS=OFF
# Make OCIO build all its dependencies statically
-D OCIO_INSTALL_EXT_PACKAGES=MISSING
# Give the library a custom name and symbol namespace so it can't
# conflict with any others in the system or linked into the same app.
# -D OCIO_NAMESPACE=${OpenColorIO_VERSION_IDENT}_${PROJ_NAME}
-D OCIO_LIBNAME_SUFFIX=_v${OpenColorIO_VERSION_IDENT}_${PROJ_NAME}
# Fix for yaml-cpp breaking against cmake 4.0.
# Remove when yaml-cpp is fixed to declare its own minimum high enough.
-D CMAKE_POLICY_VERSION_MINIMUM=3.5
)
# Set some things up that we'll need for a subsequent find_package to work
set (OpenColorIO_ROOT ${OpenColorIO_LOCAL_INSTALL_DIR})
set (OpenColorIO_DIR ${OpenColorIO_LOCAL_INSTALL_DIR})
# Signal to caller that we need to find again at the installed location
# set (OpenColorIO_REFIND TRUE)
# set (OpenColorIO_REFIND_ARGS CONFIG)
find_package (OpenColorIO ${OpenColorIO_BUILD_VERSION} EXACT CONFIG REQUIRED)
find_package(pystring REQUIRED)
if (OpenColorIO_BUILD_SHARED_LIBS)
install_local_dependency_libs (OpenColorIO OpenColorIO)
endif ()
+55
View File
@@ -0,0 +1,55 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
set_cache (OpenEXR_BUILD_VERSION 3.3.5 "OpenEXR version for local builds")
set (OpenEXR_GIT_REPOSITORY "https://github.com/AcademySoftwareFoundation/OpenEXR")
set (OpenEXR_GIT_TAG "v${OpenEXR_BUILD_VERSION}")
set (OpenEXR_GIT_COMMIT "6661cb40c6fa8d332f142e660e25ac96675c15bd")
set_cache (OpenEXR_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should a local OpenEXR build, if necessary, build shared libraries" ADVANCED)
string (MAKE_C_IDENTIFIER ${OpenEXR_BUILD_VERSION} OpenEXR_VERSION_IDENT)
build_dependency_with_cmake(OpenEXR
VERSION ${OpenEXR_BUILD_VERSION}
GIT_REPOSITORY ${OpenEXR_GIT_REPOSITORY}
GIT_TAG ${OpenEXR_GIT_TAG}
GIT_COMMIT ${OpenEXR_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_SHARED_LIBS=${OpenEXR_BUILD_SHARED_LIBS}
-D OPENEXR_FORCE_INTERNAL_DEFLATE=ON
# Don't built unnecessary parts of OpenEXR
-D BUILD_TESTING=OFF
-D BUILD_WEBSITE=OFF
-D OPENEXR_BUILD_EXAMPLES=OFF
-D OPENEXR_BUILD_PYTHON=OFF
-D OPENEXR_BUILD_SHARED_LIBS=OFF
-D OPENEXR_BUILD_TOOLS=OFF
-D OPENEXR_BUILD_WEBSITE=OFF
-D OPENEXR_INSTALL_DOCS=OFF
-D OPENEXR_INSTALL_PKG_CONFIG=OFF
-D OPENEXR_INSTALL_TOOLS=OFF
# Give the library a custom name and symbol namespace so it can't
# conflict with any others in the system or linked into the same app.
-D OPENEXR_NAMESPACE_CUSTOM=1
-D ILMTHREAD_NAMESPACE_CUSTOM=1
-D IEX_NAMESPACE_CUSTOM=1
-D OPENEXR_INTERNAL_IMF_NAMESPACE=${PROJ_NAMESPACE_V}_Imf_${OpenEXR_VERSION_IDENT}
-D ILMTHREAD_INTERNAL_NAMESPACE=${PROJ_NAMESPACE_V}_IlmThread_${OpenEXR_VERSION_IDENT}
-D Iex_INTERNAL_NAMESPACE=${PROJ_NAMESPACE_V}_Iex_${OpenEXR_VERSION_IDENT}
-D OPENEXR_LIB_SUFFIX=_v${OpenEXR_VERSION_IDENT}_${PROJ_NAMESPACE_V}
)
# Signal to caller that we need to find again at the installed location
set (OpenEXR_REFIND TRUE)
set (OpenEXR_REFIND_ARGS CONFIG)
set (OpenEXR_REFIND_VERSION ${OpenEXR_BUILD_VERSION})
if (OpenEXR_BUILD_SHARED_LIBS)
install_local_dependency_libs (OpenEXR OpenEXR)
install_local_dependency_libs (OpenEXR IlmThread)
install_local_dependency_libs (OpenEXR Iex)
endif ()
+38
View File
@@ -0,0 +1,38 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/Academ SoftwareFoundation/OpenImageIO
set_cache (OpenJPEG_BUILD_VERSION 2.5.4 "OpenJPEG version for local builds")
set (OpenJPEG_GIT_REPOSITORY "https://github.com/uclouvain/openjpeg.git")
set (OpenJPEG_GIT_TAG "v${OpenJPEG_BUILD_VERSION}")
set_cache (OpenJPEG_GIT_COMMIT "6c4a29b00211eb0430fa0e5e890f1ce5c80f409f"
"commit hash to verify tag against")
set_cache (OpenJPEG_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should a local OpenJPEG build, if necessary, build shared libraries" ADVANCED)
string (MAKE_C_IDENTIFIER ${OpenJPEG_BUILD_VERSION} OpenJPEG_VERSION_IDENT)
build_dependency_with_cmake(OpenJPEG
VERSION ${OpenJPEG_BUILD_VERSION}
GIT_REPOSITORY ${OpenJPEG_GIT_REPOSITORY}
GIT_TAG ${OpenJPEG_GIT_TAG}
GIT_COMMIT ${OpenJPEG_GIT_COMMIT}
CMAKE_ARGS
-D BUILD_CODEC=OFF
-D CMAKE_POSITION_INDEPENDENT_CODE=ON
)
# Set some things up that we'll need for a subsequent find_package to work
set (OpenJPEG_ROOT ${OpenJPEG_LOCAL_INSTALL_DIR})
set (OpenJPEG_VERSION ${OpenJPEG_BUILD_VERSION})
set (OPENJPEG_VERSION ${OpenJPEG_BUILD_VERSION})
# Signal to caller that we need to find again at the installed location
set (OpenJPEG_REFIND TRUE)
set (OpenJPEG_REFIND_ARGS CONFIG)
set_invert (OpenJPEG_LINKSTATIC ${OpenJPEG_BUILD_SHARED_LIBS})
if (OpenJPEG_BUILD_SHARED_LIBS)
install_local_dependency_libs (OpenJPEG openjp2)
endif ()
+85
View File
@@ -0,0 +1,85 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# PNG by hand!
######################################################################
set_cache (PNG_BUILD_VERSION 1.6.50 "PNG version for local builds")
super_set (PNG_BUILD_GIT_REPOSITORY "https://github.com/pnggroup/libpng")
super_set (PNG_BUILD_GIT_TAG "v${PNG_BUILD_VERSION}")
super_set (PNG_BUILD_GIT_COMMIT "2b978915d82377df13fcbb1fb56660195ded868a")
super_set (PNG_BUILD_EXTRA_CMAKE_ARGS "")
set_cache (PNG_BUILD_SHARED_LIBS OFF
DOC "Should execute a local PNG build, if necessary, build shared libraries" ADVANCED)
set_option (PNG_BUILD_USE_CUSTOM_PREFIX "Use custom namespace prefix for libpng" OFF)
if (PNG_BUILD_USE_CUSTOM_PREFIX)
list (APPEND PNG_BUILD_EXTRA_CMAKE_ARGS -D PNG_PREFIX=oiio)
endif ()
string (MAKE_C_IDENTIFIER ${PNG_BUILD_VERSION} PNG_VERSION_IDENT)
unset (PNG_FOUND)
unset (PNG_LIBRARY)
unset (PNG_LIBRARY_RELEASE)
unset (PNG_LIBRARY_DEBUG)
unset (PNG_LIBRARIES)
unset (PNG_INCLUDE_DIRS)
unset (PNG_INCLUDE_DIR)
unset (PNG_PNG_INCLUDE_DIR)
unset (PNG_VERSION_STRING)
unset (PNG_DEFINITIONS)
unset (PNG_VERSION)
build_dependency_with_cmake (PNG
VERSION ${PNG_BUILD_VERSION}
GIT_REPOSITORY ${PNG_BUILD_GIT_REPOSITORY}
GIT_TAG ${PNG_BUILD_GIT_TAG}
GIT_COMMIT ${PNG_BUILD_GIT_COMMIT}
CMAKE_ARGS
-D PNG_SHARED=${PNG_BUILD_SHARED_LIBS}
-D PNG_STATIC=ON
-D PNG_EXECUTABLES=OFF
-D PNG_TESTS=OFF
-D PNG_TOOLS=OFF
-D PNG_FRAMEWORK=OFF
-D CMAKE_POSITION_INDEPENDENT_CODE=ON
-D CMAKE_INSTALL_LIBDIR=lib
${PNG_BUILD_EXTRA_CMAKE_ARGS}
)
set (PNG_REFIND FALSE)
set (PNG_REFIND_VERSION ${PNG_BUILD_VERSION})
set (PNG_REFIND_ARGS EXACT REQUIRED)
set (PNG_FIND_VERSION_EXACT ON)
unset (PNG_FOUND)
unset (PNG_LIBRARY)
unset (PNG_LIBRARY_RELEASE)
unset (PNG_LIBRARY_DEBUG)
unset (PNG_LIBRARIES)
unset (PNG_INCLUDE_DIRS)
unset (PNG_INCLUDE_DIR)
unset (PNG_PNG_INCLUDE_DIR)
unset (PNG_VERSION_STRING)
unset (PNG_DEFINITIONS)
unset (PNG_VERSION)
if (PNG_BUILD_VERSION VERSION_GREATER 1.6.43)
list (APPEND PNG_REFIND_ARGS CONFIG)
endif ()
find_package(PNG ${PNG_REFIND_VERSION} ${PNG_REFIND_ARGS}
HINTS
${PNG_LOCAL_INSTALL_DIR}/lib/cmake/PNG
${PNG_LOCAL_INSTALL_DIR}
NO_DEFAULT_PATH
)
set (PNG_INCLUDE_DIRS ${PNG_LOCAL_INSTALL_DIR}/include)
include_directories(BEFORE ${PNG_INCLUDE_DIRS})
if (PNG_BUILD_SHARED_LIBS)
install_local_dependency_libs (PNG png)
endif ()
+31
View File
@@ -0,0 +1,31 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO
######################################################################
# Robinmap by hand!
######################################################################
set_cache (Robinmap_BUILD_VERSION 1.4.0 "Robinmap version for local builds")
set (Robinmap_GIT_REPOSITORY "https://github.com/Tessil/robin-map")
set (Robinmap_GIT_TAG "v${Robinmap_BUILD_VERSION}")
set_cache (Robinmap_GIT_COMMIT "4ec1bf19c6a96125ea22062f38c2cf5b958e448e"
"commit hash to verify tag against")
build_dependency_with_cmake(Robinmap
VERSION ${Robinmap_BUILD_VERSION}
GIT_REPOSITORY ${Robinmap_GIT_REPOSITORY}
GIT_TAG ${Robinmap_GIT_TAG}
GIT_COMMIT ${Robinmap_GIT_COMMIT}
CMAKE_ARGS
# Fix for pybind11 breaking against cmake 4.0.
# Remove when pybind11 is fixed to declare its own minimum high enough.
-D CMAKE_POLICY_VERSION_MINIMUM=3.5
)
# Set some things up that we'll need for a subsequent find_package to work
set (Robinmap_ROOT ${Robinmap_INSTALL_DIR})
# Signal to caller that we need to find again at the installed location
set (Robinmap_REFIND TRUE)
set (Robinmap_VERSION ${Robinmap_BUILD_VERSION})

Some files were not shown because too many files have changed in this diff Show More