Compare commits

..
356 Commits
Author SHA1 Message Date
Larry Gritz e181aadac5 build: Test ABI compliance (#3983, #3988)
This patch adds a new test to the CI matrix: verifying that we do not
break the ABI during releases.

Basically, in addition to building the current checkout, it also builds
a checkout of the designated "ABI standard" (generally, the first
non-beta release of a major version), then generates ABI dumps of both
versions and runs the ABI compliance checker using the tools from
https://github.com/lvc

Making two builds sounds expensive, but both builds are rigged to be
minimal, since only the main two libraries are needed for ABI checks (we
can turn off the binary tools, unit tests, python bindings, and support
for many formats), and of course the test suite need not run. So
actually, it's less expensive than most of the test matrix entries, and
it helps ensure that we don't accidentally break ABI when we don't mean
to.

I'm not sure how many false positives we'll have. We might need to
adjust the methodology slightly as we gain experience with this.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-16 21:58:34 -07:00
Jesse Yurkovich 082b360122 fix(png): Write out proper tiff header version in png EXIF blobs (#3984)
When writing out EXIF headers in PNG files, the `tiff_version` field
wasn't handling endianness properly.

This lead to some tools like `exiv2` refusing to process the file at
all[1]

[1] https://github.com/Exiv2/exiv2/issues/2745

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-09-16 16:32:48 -07:00
Larry Gritz 8d37a81f83 feat(python): Implement ImageCache.get_imagespec() (#3982)
This C++ method of ImageCache was never exposed previously.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-16 16:31:39 -07:00
Larry Gritz 49459df4b8 docs: Prototype docs examples doubling as tests (#3977)
New theory of code examples in the docs: every one should live in the
testsuite somewhere, and merely be included by reference in the docs.
This ensures that every code example works, stays current with the
evolution of the APIs, and never breaks. It also beefs up our test cases
for more thorough code overage in the testsuite.

I've done this with just two examples here, but hopefully it serves as
an example for others to -- bit by bit -- convert all the other code
examples in the docs into tests in a similar manner.

Doing this for any one example is a perfect "good first issue," since
it's bite sized and can easily be done in a day, it doesn't require any
knowledge of deep OIIO internals, and in the process it also teaches you
something about how both the docs and the testsuite are set up.

A few notes:

* I'm structuring it (for now?) as two testsuite entry for each chapter
of the documentation (one for C++ and one for Python).

* Note how I can have many code snippets in a test source file, and use
the Sphinx `:start-after:` and `:end-before:` modifiers of
`literalinclude` to clip particular subsections of the file, using
special comment markers in the code.

While I was there, I also fixed some typos I noticed in the text of the
chapter, oops.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-16 16:31:24 -07:00
Larry Gritz a0162813fd fix(ustring): fix Cuda warnings (#3978)
To my eyes, these two constructors look like they should be treated as
doing exactly the same thing:

    MyType()
        : mymember(...)
    { }

and

    MyType()
    {
       mymember = ...;
    }

But nvcc in Cuda mode says no, if the constructor is constexpr, the
former is okey dokey, but latter gives a warning. Fine, Cuda, whatver
you say.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-08 13:41:02 -07:00
Jesse Yurkovich 7c4634ce64 Remove unnecessary headers from strutil.cpp causing build trouble (#3976)
While testing out the 2.5 beta for use in Blender, I hit an odd build
error[1] apparently related to include order. Apparently `windows.h`
should be included before `shellapi.h`[2]. Swapping the order does fix
things, however, it turns out neither is used in this particular file so
just remove them both. Unsure why we didn't see it until now.

[1]
```
20>[9/146] Building CXX object src\libutil\CMakeFiles\OpenImageIO_Util.dir\strutil.cpp.obj
20>FAILED: src/libutil/CMakeFiles/OpenImageIO_Util.dir/strutil.cpp.obj

20>cl : Command line warning D9002: ignoring unknown option '/arch:sse2'
20>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\shellapi.h(68): error C2146: syntax error: missing ';' before identifier 'DECLSPEC_IMPORT'
20>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\shellapi.h(79): error C2065: 'HDROP': undeclared identifier
20>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\shellapi.h(82): error C2086: 'int EXTERN_C': redefinition
20>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\shellapi.h(68): note: see declaration of 'EXTERN_C'
```
[2] 

https://stackoverflow.com/questions/2953704/vs2010-lots-of-errors-when-including-standard-libraries

https://social.msdn.microsoft.com/forums/vstudio/en-us/ed93ae48-969a-4280-8fd5-ef57a332022b/problems-with-shellexecute-and-shellapih?forum=vcgeneral

## Checklist:

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

- [X] I have read the [contribution
guidelines](https://github.com/OpenImageIO/oiio/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).
- [X] 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.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-09-08 12:42:31 -07:00
Larry Gritz 1383491c9b Stage for 2.5.3.0-beta1
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-04 19:58:10 -07:00
Larry Gritz a4a6113ac5 CHANGES and stage for 2.5 beta 1
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-04 17:47:56 -07:00
Larry Gritz 4c36a07d1d build: Bump fmt minimum 7.0, fix fmt+gcc bugs (#3973)
Bump fmt minimum to 7.0 for OIIO 2.5. fmt 7.0 is 3 years old, so let's
stop doing extra work to support 6.x. It's not that we depend on newer
features per se, but I'd like to no longer need separate reference
output for some tests whose formatting behavior changed slightly between
6.x and 7.0.

Rig CI to properly test "latest" and "bleeding edge" fmt. It turns out
we had not yet been testing 10.1 or keeping up with their master.

In the process, I discovered that the combo of fmt >= 10.1 and gcc >= 11
results in a mangled AVX math heisenbug, symptomatic in our simd_test. I
struggled with this on and off for many days, having great difficulty
reproducing (though it does fail every time and deterministically, I
just can't seem to narrow it to a smaller example). It only happens with
gcc, only gcc >= 11, only when we use FMT_EXCEPTIONS=0 to disable true
exceptions in fmt. The change happens specifically at fmt commit 9a034b0
(midway between 10.0 and 10.1), which changes the definition of
FMT_THROW when exceptions are disabled. Why this should affect SIMD math
is a total mystery, and currently I am suspecting either a gcc compiler
error or that it's exposing undefined behavior. I found that redefining
FMT_THROW on our side to something innocuous is a good workaround. If I
no longer disable fmt exceptions, that also makes it work, but I don't
know what that might break for us or downstream.

My report of this to the fmt project is
[here](https://github.com/fmtlib/fmt/issues/3620), maybe they'll uncover
the true cause.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-04 17:41:03 -07:00
Larry Gritz 4da1679757 admin: update project intake checklist
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-04 16:31:36 -07:00
Larry Gritz 7f6861505b ci: Bump 'latest release' test to OpenEXR/Imath 3.2 and OCIO 2.3 (#3971)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-31 22:26:35 -07:00
Larry Gritz 8e1c7701d0 feat(ImageBuf): auto print uncaught IB errors (#3949)
Advanced users know to check error returns and retrieve errors.

New users often just try OIIO calls with no error checks when they don't
get behavior they want, ask questions to the dev team. We hypothesize
that if they only saw the text of the error messages that they never
retrieved, they could probably self-diagnose many of their problems.

This patch makes an ImageBuf, when it is destryed, print any pending
error messages that were never retrieved. It happens by default, but can
be disabled by setting the new global attribute
"imagebuf:print_uncaught_errors" to 0 (it defaults to 1).

This doesn't cover everything, but for ImageBuf and ImageBufAlgo, maybe
it will help some users? It could annoy advanced users who intend to not
retrieve error messages (why?) but still don't want this printed. But
that's who the new attribute is for.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-31 17:09:37 -07:00
Larry Gritz 0246a1bc8b build: Fix broken libheif < 1.13 (#3970)
Typo introduced in #3894 broke our ability to build against libheif <
1.13. A conditional compilation that should have kicked in for >=1.16
was mistakenly written as 1.6.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-31 17:09:00 -07:00
Larry Gritz 436ab6eff2 fix: normalize cleanup (#3963)
* Add documentation for oiiotool --normalize

* Add tests for oiiotool --normalize

* Revamp existing normalize tests in testsuite/python-imagebofalgo: Get
rid of old test images and refs, because their values were already
normalized, so was probably not testing the math. Make new tests that
are much smaller, 3x3 images that contain specific (non-normalized)
values to verify they all get normalized corectly. They'll run a lot
faster, too.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-31 09:14:47 -07:00
Larry Gritz fd8e64a660 feat(api): ImageInput::open_check (#3967)
Not unlike the ImageOutput::open_check we added a few months back, this
creates an ImageInput utility function that centralizes a number of
validation checks. Currently, this is primarily a check on allowed
resolution and total size, aimed at making a guess at files that are
corrupted or malicious.

Also adds a new `supports("noimage")` query.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-30 10:04:39 -07:00
Larry Gritz b008158500 admin: Relicense code under Apache 2.0 (#3966)
This is Update 4, the original PR is ongoing and we will continue to
update as additional people relicense.

Per PR #3905 (https://github.com/OpenImageIO/oiio/pull/3905), update the
RELICENSING document with the names of people and companies who have
signed on to the relicensing thus far, and update the SPDX license
notices on source files whose extant authorship (per 'git blame')
comprises only authors who have relicensed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-29 21:54:42 -07:00
Larry Gritz 554dd02134 Admin: Add Jesse Yurkovich to the TSC (#3937)
Proposal from Thiago to add Jesse Yurkovich, representing Blender, to
the TSC.

Vote passed by majority of TSC members voting yes on the PR itself.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-27 21:58:55 -07:00
Larry Gritz 83c885309c build(win): Fix windows.h pre-definitions (#3965)
* Avoid possible double define of NOMINMAX in platform.h
* Move other Windows symbol definitions into the cmake file instead of
  repeating them in certain .cpp files.

Fixes #3964

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-27 20:31:32 -07:00
b445bc64a4 feat(IBA): IBA::normalize() - Normalize 3D vectors (i.e., divide by their length) textures. (#3945)
Normalize 3D vectors (i.e., divide by their length) textures.

inCenter and outCenter define 0.0 coordinate in input and output 
3D vectors encodings (e.g. 0.0f for [-1,1] or 0.5f for [0,1] encoding).
 
scale defines the scale factor to apply to the normalized vectors 
(i.e. 1.0f for a full range normalization, 0.5f for 0.0-1.0 range
encoding).

Default values are for [-1,1] encoding and full range normalization.

Functions required 3 or 4 channels. If destination have no alpha
channel,
but source have, alpha channel will be dropped.

## Tests

```
int main(int argc, const char* argv[])
{
    ImageBuf input(argv[1]);
    ImageBuf output;

    bool ok = ImageBufAlgo::normalize(output, input, 0.0f, 0.0f, 1.0f);
    if (ok)
    {
		ok = output.write(argv[2]);
    }
    else {
        std::cerr << "Could not normalize image: " << argv[1] << std::endl;
        return -1;
    }
    return 0;
}
```

---------

Signed-off-by: ssh4net <libalias@gmail.com>
Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
Signed-off-by: Vlad Erium <libalias@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Anton Dukhovnikov <131838425+antond-weta@users.noreply.github.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-08-25 18:35:18 -07:00
Jesse Yurkovich a5c7a0c942 fix(dds): Fix div by 0 during DXT4 DDS load (#3959)
Fixes #3950

Fix the div-by-0 when handling unassociated alpha during a DXT4 DDS
load. The code mirrors what other formats do by first checking to see if
the alpha value is not 0 before continuing.

Added the 218-byte file from the bug to the local test suite.

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-08-24 20:46:59 -07:00
Mikael Sundell 38aed29bb0 build: Added check for Boost_NO_BOOST_CMAKE, ignore if already set (#3961)
Enable set of Boost_NO_BOOST_CMAKE through make using
MY_CMAKE_FLAGS=-DBoost_NO_BOOST_CMAKE:BOOL=OFF.

Signed-off-by: Mikael Sundell <mikael.sundell@gmail.com>
2023-08-24 13:06:56 -07:00
Jesse Yurkovich afe81598ca Fix(rla): Invalid read from an empty vector during RLA load (#3960)
The incoming length of the RLE data could be 0. In this case we would
attempt to take the address of the 1st element of an empty vector.

Added a new 1004-byte file to the local test suite.

Fixes #3951

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-08-24 09:30:06 -07:00
Jesse Yurkovich cdc82185f1 cleanup: Fix typo in debug output (#3956)
Fixes a typo in the debug output triggered during the image plugin
search sequence.


Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-08-24 09:25:09 -07:00
Larry Gritz 56c734a675 exr: Re-enable openexr core default when recent enough (#3942)
We had disabled the use of the "openexr core" library by default, even
for OpenEXR versions that nominally support it, when it was discovered
that it stil didn't support the DWA compression types.

That has finally been added to the OpenEXR trunk as well as the OpenEXR
3.1.10 release. When we are building against a sufficiently new OpenEXR
to fully support all the compression types for exr core, then re-enable
it by default.

Bump the "latest" CI tests to OpenEXR 3.1.11.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-23 13:33:02 -07:00
Larry Gritz 8f423c9975 fix: various protections against corrupted files (#3954)
Fixes #3952

Several interrelated fixes to guard against corrupted files:

* Extend the `limits:imagesize_MB` sanity check to Targa files to
address #3952 specifically, and check in that failing example file into
the testsuite. (N.B.: Only a couple readers use this, TIFF and now
Targa. it should be extended to the others. Mackerel!)

* Improve the error message used for the above, both for Targa and TIFF.

* For low-memory situations, perhaps the default of 32GB is too large.
Make the default be the minimum of 32GB and 1/2 the size of physical
memory on the machine. (An app that legit expects humongous files is
expected to raise the limit appropriately.)

* The generic "Read error: hit end of file" we sometimes issued from
`ImageInput::ioread()` was hard to discern which reader it came from, in
cases where the file extension was absent or misleading and a succession
of files were tried. By changing this error message to say which format
reader triggered the error, it might make these errors easier to track
down in the future. This also changed the reference output of a few test
involving truncated or corrupted files.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-23 13:32:09 -07:00
Larry Gritz 0fca55569d ci: Make more robust timer_test (#3953)
On overloaded VMs, the timer_test is ureliable and fails spuriously too
often.

Two strategies in this patch, hope some combination does the trick:

1. Increase the absolute error allowed for the timing tests when doing
CI runs.

2. Add just a bit more relative error (via a new unit test macro,
OIIO_CHECK_EQUAL_THRESH_REL).

Hopefully this will cut down on CI failures for unit_timer test case.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-21 14:59:26 -07:00
ShootfastandLarry Gritz 9909b4b109 build: Silence gcc new/delete warnings for texturesys (#3944)
Disable GCC warnings around mismatched new/delete for shared_texturesys
creation


Signed-off-by: Shootfast <markboo99@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-08-21 11:03:32 -07:00
Larry Gritz 629b205da4 dev(ustring.h): string literal operator for ustring and ustringhash (#3939)
* Add string literal operators for ustring and ustringhash so you can
write: ``` "foo"_us "bar"_ush ``` Note that on Cuda (but not on the
host), this ustringhash construction is constexpr.

* Add a new `ustringhash(const char*, size_t)` constructor, which is
also constexpr on the device side.

* Mark the existing `ustringhash(string_view)` constructor as constexpr
on the device side.

We can mark those things as constexpr on the device side because on the
Cuda side, the implementation only takes the hash (which is constexpr),
and does not actually add a ustring to the table (which cannot be
constexpr). To make such declarations easy, add a new macro to
platform.h, `OIIO_DEVICE_CONSTEXPR` which is constexpr for the device,
merely inline for the host.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-20 18:03:59 -07:00
xiaoxiaoafeifei 15750af31a fix(bmp): fix signed integer overflow when computing total number of pixels (#3948)
fix #3947: runtime error: signed integer overflow in file
src/bmp.imageio/bmpinput.cpp:302
2023-08-20 10:26:19 -07:00
Larry Gritz c7f8169d73 admin: Update pull request and issue templates (#3946)
The most important fix is to remove links to the old CLAs and update
references to the mail list to the new one.

Also spruced up some language while I was there, hopefully to coax out
improved PRs and Issues.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-20 10:12:08 -07:00
Anton Dukhovnikov e3f666500b build: suppress Xcode warnings (#3940)
When building the code with Xcode ("cmake -G Xcode"), there are 1000+
warnings about implicit 64 to 32 bit conversion.
This change adds a compile option to suppress such warnings when
generating an Xcode project.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
2023-08-11 07:39:55 -07:00
Larry Gritz 81a1c221bb admin: Relicense code under Apache 2.0 (#3938)
This is Update 3, the original PR is ongoing and we will continue to
update as additional people relicense.

Per PR #3905 (https://github.com/OpenImageIO/oiio/pull/3905), update the
RELICENSING document with the names of people and companies who have
signed on to the relicensing thus far, and update the SPDX license
notices on source files whose extant authorship (per 'git blame')
comprises only authors who have relicensed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-03 21:01:32 -07:00
NicolasandLarry Gritz 1bb1ca591a fix: utf-8 text rendering (#3935)
Text rendering doesn't work with utf-8... 

I can't render chinese, arabic... or special chars as éèûîà...

It seems that the string function to convert utf-8 to unicode is quiet
simple.

Fixes #3933 

[Note]: OpenImageIO is used in the [gpx2video
project](https://github.com/progweb/gpx2video).

---------

Signed-off-by: Nicolas VIVIEN <nicolas@vivien.fr>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-08-03 10:46:16 -07:00
Larry Gritz 9e42bd1228 Docs: Make sure README has links for slack and meetings (#3936)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-31 22:17:02 -07:00
Larry Gritz 6e603475a8 api: extend TypeDesc and ParamType to represent ustringhash (#3915)
I think it will be handy to be able to have ParamValue contain
ustringhashes and have a TypeDesc that can describe it explicitly.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-30 16:47:01 -07:00
Larry Gritz 353e0222d5 build(deps): Raise OpenEXR minimum from 2.3 to 2.4 (#3928)
This will not be backported to the release branch, it's only for OIIO
2.5 and later.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-29 13:37:41 -07:00
Larry Gritz 81cb1a433c build(deps): Raise minimum libraw to 0.18 (#3921)
Rationale:

* LibRaw 0.18 was released in last 2016, so we are stil supporting all
libraw from up to 6 years back.
* LibRaw 0.18 is necessary for ACES, plus it improves a lot of metadata
handling.
* LibRaw 0.20 is the minimum that can be used when compiling with C++17,
and we will almost certainly move to C++17 as a minimum in OIIO 2.6, so
it seems like LibRaw 0.18 is reasonable minimum for the upcmoming 2.5.

Remove some cruft that's no longer necessary if we drop support for
0.15-0.17.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-29 11:34:36 -07:00
Larry Gritz 004cbb0238 build(deps): Raise minimum CMake dependency from 3.12 to 3.15 (#3924)
This bump brings access to the following interesting features (not a
comprehensive list):

- 3.13  Nov 21, 2018 

    - -B, -S let you specify source and build directories without the "cd" dance
    - target_link_options() 
    - ctest --progress / CTEST_PROGRESS_OUTPUT

- 3.14  Mar 14, 2019 

    - cmake --build now supports -v/--verbose 
    - file(CREATE_LINK ) 
    - FindGIF now has imported targets

- 3.15  Jul 17, 2019 

    - env CMAKE_GENERATOR can be used instead of -G 
    - when using --build, the --target can now list multiple targets (and also can be `-t`)
    - --install can be used separately without running through the whole build
    - message() now supports NOTICE, VERBOSE, DEBUG and TRACE. 
    - CMAKE_FIND_PACKAGE_PREFER_CONFIG variable 
    - Enable C++20 for Apple Clang

Make sure all CI cases have a new enough cmake

Use GIF targets, now enabled with CMake 3.14

Use message(VERBOSE ...) feature to simplify lots of `if` blocks.

Clean up code for older cmake versions

Note that this will NOT be backported to the current release branch,
but it will be part of the upcoming 2.5 family of reseases.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-29 11:00:24 -07:00
Jesse Yurkovich c97826c144 fix(python): Fix arithmetic overflow in oiio_bufinfo (Python interop) (#3931)
When an incoming 1-dimensional, buffer-like, object was used in Python,
the corresponding check inside OIIO would overflow if its length
exceeded a signed 32bit value.

An error similar to `Pixel data array error: Python array shape is
[2304000000] but expecting h=24000, w=24000, ch=4` would be raised.

I modified a few similar calculations and tried to follow the
predominant pattern already used.

Tested using the following snippet which would previously fail:
```
import OpenImageIO as oiio
import numpy as np

filename = "t:/foo.png"
xres = 24000
yres = 24000
channels = 4  # RGB
pixels = np.zeros(xres * yres * channels, dtype=np.uint8)

spec = oiio.ImageSpec(xres, yres, channels, "uint8")
image = oiio.ImageOutput.create(filename)
image.open(filename, spec)
if not image.write_image(pixels):
    print("error = ", image.geterror())
image.close()
```

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-07-29 09:50:16 -07:00
Larry Gritz 3dd4951fe2 build: bump build_openexr and build_opencolorio defaults to latest versions (#3920)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-29 09:45:40 -07:00
Larry Gritz d65eb6597b admin: Relicense code under Apache 2.0 (#3926)
Per PR #3905 (https://github.com/OpenImageIO/oiio/pull/3905), update the
RELICENSING document with the names of people and companies who have
signed on to the relicensing thus far, and update the SPDX license
notices on source files whose extant authorship (per 'git blame')
comprises only authors who have relicensed.

This is part 2, the original PR is ongoing and we will continue to
update as additional people relicense.

Signed-off-by: Larry Gritz <lg@larrygritz.com>

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-28 22:49:34 -07:00
Larry Gritz 88c10a91cb docs: Put logo on the main readme (#3927)
Add some logo images in ASWF/logos for handy use.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-27 17:00:17 -07:00
Larry Gritz 712a73818f ci: Lock down icx version (#3929)
Intel's servers have again updated the default icx that you get when you
install from their yum repository, and the new one seems incompatible
with our libstdc++ toolchain. So lock down on 2023.1.0 for now so that
our CI can pass.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-27 09:15:05 -07:00
Larry Gritz b205899131 refactor: Convert iconvert.cpp stream io and sprintf to modern (#3925)
Also fix a typo

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-24 19:04:56 -07:00
Curtis BlackandLarry Gritz d757bffca5 perf(TS): Remove redundant instructions from tile hash (#3898)
Optimises the code in the tile hash function. During a render this
function is called billions of times so this small improvement adds up,
in some test scenes it reduces total render time by an average of about
2%.

See https://godbolt.org/z/jMzz4PTce for the exact details. A summary
would be:

- Reduced instruction count from 75 to 61, this is due to the redundant
  add and shift operations that can be implicitely handled by taking
  advantage of the member layout in the class.
- Halves the number of memory fetch instructions because all accesses
  are now 64-bit.
- Removes branching instructions and extra memory indirection inside
  `ustring::hash()`.

There is a slight change in behaviour, which is that the hash is now
computed from the `m_file` pointer rather than from
`m_file->filename().hash()`, so runtime reproducibility is lost. However
the performance gain seems worth it.

Signed-off-by: Curtis Black <curtis.w.black@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-07-24 18:06:45 -07:00
jasonbaumeister 9fd9fbfdc2 feat(ico): Add IOProxy support to ICOInput (#3919)
This updates ICOInput to use the IOProxy model so it can read from files
or the IOMemReader

Signed-off-by: Jason Baumeister <jason@jasonbaumeister.com>
2023-07-22 19:16:27 -07:00
jasonbaumeister 88d354e068 fix(psd): CMYK PSD files should copy alpha (#3918)
During the CMYK to RGB conversion in PSDInput, the alpha channel was
never copied to the RGBA output. Converting a PSD to JPEG worked because
it ignored all the 0 alpha values, but converting to WebP would result
in a fully transparent image.

I added a cmyk-with-alpha.psd test to the psd-colormodes test to check
this

Signed-off-by: Jason Baumeister <jason@jasonbaumeister.com>
2023-07-22 12:21:56 -07:00
Larry Gritz e297a3ba0d ci: Test against pybind11 v2.11 (#3912)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-22 11:52:30 -07:00
D-Spirits e203bd6d27 Admin: Add DevilishSpirits to RELICENSING.md (#3922)
For the relicensing request in #3905 and signed with my personal PGP
key.
2023-07-22 10:43:54 -07:00
Larry Gritz 780fe682c9 build: Fix broken OIIO_NO_NEON definition (#3911)
Clean up the `#if` tests that disable Intel SIMD when not on Intel
architectures, which incorrectly disabled ARM NEON when on ARM.

Fixes #3909

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-16 21:44:28 -07:00
Jesse Y b1f5265642 docs: Update ImageInput docs to not use deprecated APIs (#3907)
Update the ImageInput documentation to not use the deprecated
`read_image` APIs.

Based on the discussion in #3902

---------

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
2023-07-15 12:30:32 -07:00
Larry Gritz b257b8e6a0 admin: Relicense code under Apache 2.0 (#3914)
Per PR #3905 (https://github.com/OpenImageIO/oiio/pull/3905), update the
RELICENSING document with the names of people and companies who have
signed on to the relicensing thus far, and update the SPDX license
notices on source files whose extant authorship (per 'git blame')
comprises only authors who have relicensed.

This is part 1, the original PR is ongoing and we will continue to
update as additional people relicense.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-15 12:28:45 -07:00
Benjamin Buch 3c86a882cd build: Find OpenEXR equally well with our FindOpenEXR and exr's exported config file (#3862)
If OpenEXR is found by cmake config file, OpenEXR_VERSION is set instead of OPENEXR_VERSION

Signed-off-by: Benjamin Buch <benjamin.buch@technoteam.de>
2023-07-13 17:59:12 -07:00
Benjamin Buch a27b55a867 build: Fix WebP linking if CMAKE_FIND_PACKAGE_PREFER_CONFIG is ON (#3863)
Our own FindWebP.cmake was setting up targets that didn't
match the capitalization of the cmake configs that come with WebP itself.

Signed-off-by: Benjamin Buch <benjamin.buch@technoteam.de>
2023-07-13 16:59:50 -07:00
Larry Gritz 0aee3bb863 admin: Mark more files that LG has contributed to as 'and Apache-2.0' (#3906)
This batch is for files that LG (relicensed!) has contributed, in
addition to >2 other authors. Also add appropriate license notices to
some that had no posted license before due to oversight.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-10 15:06:46 -07:00
Larry Gritz 944c2034c8 docs: Document CVE
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-08 20:33:01 -04:00
Larry Gritz 3e1a6d5540 admin: Copyright and license notice updates (#3904)
* Add copyright/license notices to some mixed-authorship files that
lacked them before (all related to tests)
* Get rid of the pointless year in many copyright notices (change to the
current LF recommended wording)

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-06 06:44:42 -04:00
Larry Gritz eda748ef0e admin: update licensing (#3903)
Since LG has re-licensed all his old code under Apache-2.0, we can
change the license notice from BSD to Apache-2.0 for all files in which
LG is the only extant author. Also change all files that LG co-authored
with other people to specify "BSD-3-Clause and Apache-2.0".

Some files (mostly test scripts) had no license notice, so in those
cases, we added one.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-05 21:32:04 -04:00
Larry Gritz 42c629ffef admin: Change open source license to Apache 2.0 (#3899)
By majority vote of the TSC, we are changing OpenImageIO's main
incoming/outgoing open source license from BSD-3-Clause to Apache-2.0.
New code submitted from July 1, 2023 will be contributed under the
Apache 2.0 license.

Old code submitted prior to July 1 2023 is under the original BSD
3-clause license, unless relicensed per the process described in the new
RELICENSING.md file. We hope to get the vast majority of the code base
relicensed quickly and we will document which set of files contain a
mixture of licenses.

Instructions to everybody reading this:

* If you are contributing code under the authorization of an employer,
please let them know we are changing to Apache 2.0 and make sure that
you are authorized to make all future contributions to under that
license.

* If you made prior contributions to OpenImageIO over the years and are
willing to relicense your code under the Apache 2.0 license, please
submit a PR adding your name to the list in RELICENSING.md. If you were
working for a company that might own your IP output at the time you made
those contributions, please also ask somebody there (who has the
authority to do so) to submit a PR adding the company name as well,
indicating that they are re-submitting all of the old contributions
under the new license.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-01 11:59:56 -07:00
Larry Gritz 692b7899d7 admin: Remove old CLAs that are no longer in effect
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-01 11:58:42 -07:00
Larry Gritz f3eaebc8b8 admin: Add charter and other ASWF documents to the repo (#3850)
By unanimous vote of the OpenImageIO TSC, as of July 1, 2023, we
adopt the technical charter, Code of Conduct, new CLAs, and GOVERNANCE
document.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-01 11:55:22 -07:00
Larry Gritz 3fd70cfd35 fix(strutil.h): ensure proper constexpr of string hashing (#3901)
The underlying farmhash algorithm (which is the basis for
Strutil::strhash, and thus ustring's hash representation) turned out to
not be properly constexpr under certain circumstances and needed to be
expressed a different way to be fully constexpr on all platforms and for
all strings.

New implementation suggested by Alex Wells.

Also, make sure string_view ctr from char* can be constexpr, even for
C++14. This is related for the sake of the strhash calls that, when
taking string literals, actually choose the variety that accepts a
string_view.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-30 22:01:18 -07:00
Larry Gritz d18c7e27f2 ci: Get rid of long-unused install_test_images.bash (#3895)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-29 22:56:00 -07:00
Larry Gritz 77975c6ae2 testing: Fix missing simd test due to copy paste typo (#3896)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-29 22:55:38 -07:00
Larry Gritz a8291872c7 docs: Document use of the DCO which is now required for all PRs (#3897)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-25 21:25:57 -07:00
Larry Gritz 87a1e49b2d docs: Add repology badge to README and package versions to INSTALL (#3893)
repology has a handy tool that will show all the package distros
and which version of openimageio they supply.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-24 21:11:21 -07:00
Larry Gritz 20d2927224 ci: Simplify build_llvm.bash script (#3892)
* Remove leftover logic from when we used TravisCI.
* Pick a default for LLVM_DISTRO_NAME so it works when the script is run
standalone when not on GitHub Actions CI. (But it's still really only
meant to run on x86 Ubuntu, and not designed for anything useful outside
of our CI.)
* Eliminate all the complexity with old LLVM versions -- in practice,
our CI only uses this to download fairly modern clang versions.

Fixes #3891

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-24 21:10:36 -07:00
Larry Gritz 150af5a36e ci: Fix broken heif dependency and test (#3894)
The strukturag repo for libheif recently upgraded the version it was
serving from 1.14 to 1.16, and that caused our tests to fail because (a)
some of the codec support has been moved to plugins that are loaded at
runtime and those are now distributed in packages we need to install
separately; (b) you must call heif_init() or it won't know about the
optional plugins.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-24 21:07:34 -07:00
Larry Gritz ca4a245aec docs(raw): Fix explanation of raw:Exposure config hint (#3889)
Fixes #3888

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-17 13:05:55 -07:00
Larry Gritz 612bbbd0d0 fix(IBA): Improve error message for IBA::ocio functions (#3887)
If colorconvert, ociolook, ociodisplay, ociofiletransform fail
because OCIO support is not enabled, make sure the error message
makes that clear.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-16 18:52:34 -07:00
Fabien Servant @ TCS bdf31de0c3 fix(exif): Convert paramvalue string to integer when needed (#3886)
Make sure we can input exif tags as strings containing numbers when
number are required.

E.G. if my input is "Orientation"=>"8", i would like the jpeg output to
contains the value 8 for the exif tag orientation.
2023-06-16 13:41:13 -07:00
Larry Gritz a3d9900bab fix(exr): correction to dwa vs zip logic when outputting OpenEXR (#3884)
PR #2147, addressing issue #1844, is related to an apparent OpenEXR bug
wherein single channel tiled images where the tile dimensions were not a
power of 2 and >= 16 would not work properly with dwa compression. We
work around the problem by automatically substituting zip compression in
those cases. But it was implemented with a subtle bug, forgetting that
tile_size == 0 for untiled images, and thus we were silently switching
from dwa to zip compression for all *untiled* single channel images of
any size (which presumably were never problematic). This patch fixes the
test so we are not changing the compression for the untiled files.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 11:39:14 -07:00
Larry Gritz fd33ab67c1 fix(jpeg2000): better pixel type promotion logic (#3878)
J2K output was defaulting to UINT8 when asked to output an unsupported
type. It should have been UINT16 to try to minimize the amount of
precision loss.

Fixes #3876

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 10:59:24 -07:00
Larry Gritz 7d9a19b5d9 admin: Update mail list URL (#3880)
Everybody please go to https://lists.aswf.io/g/oiio-dev and sign up for
the new mail list as soon as possible. The old list is on its last legs
and having trouble, let's get this done.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-13 14:58:32 -07:00
Ray Molenkamp 577f10858a fix(api): Add shutdown method (#3882)
This change adds a `shutdown()` method to the API that can be used to
perform shutdown of the thread-pool(s) (or other clean-up activities).
Applications that utilize OpenImageIO are advised to call it before exiting their
main function to prevent possible deadlocks during application shutdown
(see #3851)

This change also updates the documentation and all oiio-tools to call
the new `shutdown` method.

This is the final change for fixing #3851
2023-06-13 14:14:19 -07:00
Ray Molenkamp 2abd946ea5 fix: Wait for terminated threads to join in thread_pool::Impl::resize (#3879)
Part of solving #3851.

When decreasing the number of threads in `thread_pool::Impl::resize` it
was possible for the threads marked for termination to still be fully
alive at process exit time if the call to `resize` and the exit of the
main function were close enough to each other.

This change makes `resize` wait for the threads to actually join
guaranteeing the threads have been shut down in a orderly manner when
the `resize` function exits.
2023-06-12 16:39:19 -07:00
Larry Gritz c9f0c93f73 New function: default_thread_pool_shutdown() (#2382)
This cleanly terminates all worker threads of the default thread pool
by resizing the pool to 0 threads... but only if the pool has been
created in the first place. Note that the alternate idiom

    default_thread_pool()->resize(0);

seems like it should accomplish the same thing, but in fact will start
by creating a pool and its threads, if it has not done so before, only
to immediately terminate them.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-12 16:37:07 -07:00
Larry Gritz 407e14ec3f ci: Add test with new aswf containers for VFX Platform 2023 (#3875)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-12 09:47:58 -07:00
Larry Gritz f95ff86e43 build: Fix fmt vs gcc warning that had version typo (#3874)
The comment was right, but the test seems to have had a typo we didn't
catch in review.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-12 09:47:40 -07:00
Larry Gritz 8da473e254 fix(psd): Prevent simultaneous psd thumbnail reads from clashing (#3877)
When reading a PSD file, if it contains a thumbnail, we read it from the
in-memory blob with a combination of an IOMemReader and an ImageBuf.
But... we always named it "thumbnail.jpg" without considering that
multiple simultaneous PSD files reading identically named images (but
which are in fact different) could cause a weird kind of clashing in any
underlying use of ImageCache!

The simple fix is to use ordinary ImageInput approach to reading the
thumbnail from the IOMemReader, but just store it in the ImageBuf.

Fixes #3824

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-12 09:47:04 -07:00
xiaoxiaoafeifei aad99bad9a fix(ico): heap-buffer-overflow (#3872)
heap-buffer-overflow in function ICOInput::readimg 

fixes #3871
2023-06-08 21:48:12 -07:00
Larry Gritz 1cd0d0a9df build: Fix use of OIIO_LOCAL_DEPS_PATH (#3865)
We set it, but we didn't use it where it was intended.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-08 19:05:42 -07:00
Larry Gritz e56eab4b36 fix(simd.h): Fix sense of hiding deprecated type names (#3870)
I got the test backwards, and it was incorrectly hiding the definition
for the default case of OIIO_DISABLE_DEPRECATED == 0.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-08 17:42:29 -07:00
Jesse Y 109f0bdba0 docs: Many fixes to python code examples (#3869)
A variety of minor documentation fixups:
- Use Python 3 style 'print' statements consistently everywhere (some
snippets had a mix of both)
- Correct the usage of `ImageSpec::channels` that should be
`ImageSpec::nchannels`
- Template syntax errors in two C++ snippets
- Document the new default for `max_memory_MB`
2023-06-07 23:25:57 -07:00
Ziggy Cross 116a1f1a25 ImageInput and ImageOutput docs updated to Python 3. (#3866)
## Description

Fixes #3846 by updating Python examples.

Current code examples for
[ImageInput](https://openimageio.readthedocs.io/en/latest/imageinput.html)
and
[ImageOutput](https://openimageio.readthedocs.io/en/latest/imageoutput.html)
raise a SyntaxError in Python 3:
```python
File "<cwd>\main.py", line 13
    return
    ^^^^^^
SyntaxError: 'return' outside function
```

It seems these code examples might be for Python 2.7. Perhaps it would
be worth creating an extra tab instead of replacing the old code?

## Tests

Tested on Python 3.11, no issues.

## Checklist:

- [x] I have read the [contribution
guidelines](https://github.com/OpenImageIO/oiio/blob/master/CONTRIBUTING.md).
- [ ] If this is more extensive than a small change to existing code, I
  have previously submitted a Contributor License Agreement

([individual](https://github.com/OpenImageIO/oiio/blob/master/src/doc/CLA-INDIVIDUAL),
and if there is any way my
  employers might think my programming belongs to them, then also

[corporate](https://github.com/OpenImageIO/oiio/blob/master/src/doc/CLA-CORPORATE)).
- [x] 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).
- [x] My code follows the prevailing code style of this project.
2023-06-07 23:02:25 +00:00
Larry Gritz cfaccc1609 CHANGES and stage for 2.5.2.0 developer preview
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-06 12:27:28 -07:00
Larry Gritz f40f9800c8 feat(oiiotool): oiiotool --parallel-frames (#3849)
Background info: oiiotool multithreads *within* any individual image
operation (such as `--over`), but a series of operations comprising the
oiiotool command are done serially -- each command finishes before the
next starts. And similarly, for multi-frame operations using frame
ranges, frame number wildcards, or view wildcards, the set of commands
for each frame runs to completion before the next begins. For complex
oiiotool commands, especially when running over frame ranges, this is
not a particularly efficient way of parallelizing, since any serialized
operation (which often includes the expensive writing of the result
image from each frame to disk) can substantially serialize the entire
run.

This PR adds a new oiiotool --parallel-frames option that assumes all
frames in the range can be computed independently and in any order, and
can therefore be run in parallel. As long as there are a similar number
(or more) of frames versus cores, and you have enough RAM to handle that
many image pipelines at once, this is a more efficient way of
parallelizing the operations than multithreading individual image
processing operations.

Benchmarking: On my 32-core workstation, I tried the following oiiotool
command, contrived but representative of a reasonable oiiotool command
complexity that might be a production task:

oiiotool --runstats -v --frames 1-100 tmp/noise.exr -cut
2880x1620+960+540 -resize 1920x1080 -colorconvert lin_srgb srgb -d uint8
-o "tmp/test.#.tif"

The noise.exr file was a previously created 4k x 3channel 'half' exr
image. The command loads the file, cuts out a 3k section of it, resizes
that to HD res, does a color space transformation, then outputs as an 8
bit TIFF file, for each of 100 sequential frames.

    threads   real time    user  sys      peak memory
    1         4:44         4:23  0:21     122 MB
    2         2:58         4:24  0:29     122 MB
    4         1:40         4:36  0:29     122 MB
    8         1:10         5:00  0:30     127 MB
    16        0:56         5:28  0:37     131 MB
    all(32)   0:55         8:12  0:54     127 MB

    parallel  0:25         8:13  1:04     3.4 GB

Here we can see the diminishing returns of using multiple threads within
each frame, where for low thread counts we are improving steadily, but
we pretty much peak at 16 threads, seeing virtually no further gain at
32, and maxing out at about 5x the single threaded performance. This is
due to serialization of the I/O and increasingly bumping into various
locking at higher thread levels.

However, using `--parallel-frames` gives us another doubling of total
throughput (giving us a total of 11.3x speedup versus single threaded),
though at the expense of 28x the memory use! That memory explosion is
acceptable in this case, even 3.4 GB is really nothing on a modern
machine, but we can imagine that other possible oiiotool command lines
might be more memory intensive and having dozens of frame pipelines
computing simultaneously would have problematic memory use. So use this
feature carefully and with purpose, always checking that your own
workflows experience sufficient speedup and don't use more memory than
you have available.
2023-06-06 09:30:15 -07:00
Larry Gritz ee3dc556b8 fix(exr): try to improve exr thread pool weirdness (#3864)
There's some code I put in not long ago to automatically call exr's
thread pool setNumThreads(0) upon exit, as an attempt to work around
some exr thread pool deadlock conditions. But... we've seen some
weirdness from this workaround as well, so try to limit its application
by not bothering when using OpenEXR >= 3.1.8 (at which point we believe
the exr side bug was fixed) and also to do so only on Windows.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-06 09:25:59 -07:00
Larry Gritz 13e1e802c0 feat(OpenCV): Improve OpenCV support -- errors, version, half (#3853)
Various improvements to OpenCV support:

* IBA::from_OpenCV and to_OpenCV now set error messages for every type
of failure they encounter, instead of returning false with no
explanation. For from_OpenCV, the error message can be retrieved from
the ImageBuf returned; for to_OpenCV, the error message can be retrieved
from the global OIIO::geterror(). Several assertions were removed,
instead relying on error return codes and messages.

* Add global OIIO attribute "opencv_version" which allows you to find
out what version of OpenCV OIIO was built against, which was previously
impossible to know without seeing the build-time status messages. This
can be retrieved via

      OIIO::get_int_attribute("opencv_version")

  and also you can find out from the command line with

      oiiotool --echo "{getattribute(opencv_version)}"

The return value is an integer encoded as `10000*major + 100*minor +
patch`, and it will return 0 if no OpenCV support was enabled when
OpenImageIO was built.

* For OpenCV >= 4.0, to_OpenCV can now correctly construct a 'half'
matrix. For OpenCV 3.x, we turn it into a float matrix as before, since
CV_16F was only supported starting in 4.0.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-02 10:20:51 -07:00
Larry Gritz cb6475c0dd docs: Update CONTRIBUTING and SECURITY (#3852)
Just a routine update of these files as I proofread them in light of the
move to ASWF. This patch is addressing the "old" project, there will be
further ASWF-specific edits for changes that will take effect after the
project is fully moved.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-01 23:58:53 -07:00
Loïc Vital eaa2c2ae37 fix(jpeg): fix density calculation for jpeg output (#3861)
In `jpegoutput.cpp` when computing the density fields the relationship
between `XRes`, `YRes` and `aspect` is `aspect = XRes / YRes`.

However this relationship was not respected in one specific case, when
`aspect >= 1.0` and `XRes` and `YRes` are not set.

This PR solves this problem by enforcing the correct relationship.

Related to: https://github.com/OpenImageIO/oiio/issues/2822
2023-06-01 22:03:23 -07:00
Larry Gritz e47e501eb0 ci: Fix package name for icc (#3860)
The Intel yum repo renamed this package a couple weeks ago, and it broke
our CI. Update to the new name.

Adjust fmt use to solve icc warning.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-01 07:31:29 -07:00
Loïc Vital cf2b7d7995 fix(raw): raw input fix user_flip usage (#3858)
When reading a raw image, setting the `user_flip` to 1 meant ignoring
the `flip` value (to avoid buffer rotation from LibRaw).

However the value 1 for the `user_flip` is **not neutral**: values lie
between 0 and 7 (see
https://www.libraw.org/docs/API-datastruct-eng.html#libraw_image_sizes_t),
and 1 corresponds to a horizontal mirror (in my understanding of the
source code).

The proposed fix is to use 0 as `user_flip` value for ignoring the
`flip` value.

This modification invalidates the changes made in this PR:
https://github.com/OpenImageIO/oiio/pull/3847.
Therefore, flip to orientation conversion has been adapted to match
exactly LibRaw's documentation, which handles only rotations (+90, +180,
-90 degrees).

The previous PR was only tested on images of landscape and human faces,
hence the mirroring issue remained unnoticed.
When reading images containing text however the problem is clearly
visible.
This PR fixes this mirroring issue on the following 4 orientations: 0,
+90, +180 and -90 degrees rotation.
Other orientations could not be tested as they don't seem to ever appear
on raw images datasets.
2023-05-31 09:01:37 -07:00
Larry Gritz b3d9c8c4ed build(Mac): Fixes for latest xcode on MacOS 13.3 Ventura (#3854)
I found that this was needed after weekend OS update of my laptop.

Also added MacOS-13 CI test.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-29 08:44:46 -07:00
Larry Gritz 6f7db0775e refactor(oiiotool): Get rid of the global Oiiotool singleton. (#3848)
Make all oiiotool actions take ot as a parameter.

This is a necessary first step to being able to parallelize over frame
ranges.

Also finally convert the last of the `int argc, const char**argv` idioms
to `cspan<const char*>`.
2023-05-23 23:08:34 -07:00
Loïc Vital 5ca9ffea7a fix(raw): fix LibRaw flip to Exif orientation conversion (#3847)
When reading a raw image while having a `user_flip` set to 1, we set the
orientation Exif tag to LibRaw's flip value (so that LibRaw doesn't
rotate and/or mirror the buffer but the image still gets displayed
correctly).

However LibRaw's convention for flip values differ from Exif orientation
values: https://www.libraw.org/comment/5176#comment-5176.

In this PR we fix this issue by converting LibRaw flip values to Exif
orientation values. This conversion is based on:
- https://www.libraw.org/comment/5178#comment-5178 (conversion proposed
by LibRaw's maintainer)
-
https://github.com/LibRaw/LibRaw/blob/6fffd414bfda63dfef2276ae07f7ca36660b8888/src/write/file_write.cpp#L22
(LibRaw's function for applying the flip).

Tested on:
- CR2 images with flip values 1, 5 and 6
- ARW images with flip values 1 and 5
(unfortunately I could not find any image covering other flip values).

Since the conversion is `[1, 2, 3, 4, 5, 6, 7, 8] -> [1, 2, 4, 3, 5, 8,
6, 7]`, the only test that came out with different results before and
after the change is the one with flip value 6:
in that case, the image orientation got corrected by the fix.
2023-05-19 18:43:56 -07:00
Jesse Y 1f6d137434 feat(ImageInput): Implement valid_file(IOProxy) overloads for DDS, PSD, and WEBP (#3831)
Following up #3826, this implements efficient `valid_file` support for
DDS, DPX, PSD, HDR, and WEBP.

The quick magic/signature checks were abstracted into small helper
functions where necessary to eliminate duplicate code.

For WEBP, some redundant checks were also removed and there's also a fix
for a `uint64_t` vs `size_t` check which would have caused issues on
32-bit builds.

The PSD changes exposed an issue with array attributes. During a normal
ImageInput create+open sequence, an ImageInput may be opened then closed
and then opened again.

Array attributes are not cleared as part of close and so their contents
will be doubled up next time they are read into the existing `m_spec`.
This PR does not fix that general problem but now that PSD has a proper
valid_file which doesn't do an open, the array attributes are now
correct:

```
This PR
2023-05-06T02:32:05.8774584Z -    photoshop:ColorMode: 3
2023-05-06T02:32:05.8774888Z -    photoshop:ICCProfile: "sRGB IEC61966-2.1"
2023-05-06T02:32:05.8775194Z -    photoshop:LayerName: 1, 2, 3
2023-05-06T02:32:05.8775436Z -    photoshop:LayerText: 1, 2, 3

vs. the current
2023-05-06T02:32:05.8775725Z +    photoshop:ColorMode: 3, 3
2023-05-06T02:32:05.8776023Z +    photoshop:ICCProfile: "sRGB IEC61966-2.1"
2023-05-06T02:32:05.8776494Z +    photoshop:LayerName: 1, 2, 3, 1, 2, 3
2023-05-06T02:32:05.8776746Z +    photoshop:LayerText: 1, 2, 3, 1, 2, 3
```
2023-05-17 14:23:51 -07:00
xiaoxiaoafeifei e5733a0607 fix: prevent heap-buffer-overflow in file src/gif.imageio/gifinput.cpp, line 368 (#3841)
Fixes #3840
2023-05-17 14:20:52 -07:00
Larry Gritz 23b0e2beae fix(int): prevent possible deadlock when reaading files with wrong extensions (#3845)
Make pvt::imageio_mutex be a recursive_mutex

Fixes #3842
2023-05-17 09:14:06 -07:00
Larry Gritz c8c8ea5cac docs(internal): Add links for dds format documentation 2023-05-16 12:15:54 -07:00
Larry Gritz dce61b3c5b fix(oiiotool): don't propagate unsupported channels (#3838)
Fixes #3837

oiiotool already attempted to trim extra channels when outputting to a
format that can't support it. It correctly handled the two common cases:

* More than 4 channels for formats that don't have
`supports("nchannels")` will drop after the first 4 channels.
* More than 3 channels for formats that don't have `supports("alpha")`
will drop after the first 3 channels.

But this omits an interesting (but rare) corner case: a 4 channel file
where the last channel is NOT alpha, and the output file supports an
alpha channel but not arbitrary channels. A concrete example might be an
input file that is exr with channels R, G, B, Z, writing to a PNG file
(which can support RGB or RGBA). We wouldn't want to write what appears
to be an RGBA file if that last channel isn't really alpha.

Also, noticed that oiiotool --chnames didn't properly clear the
alpha_channel and z_channel flags, which is important if the new channel
lists drop one of those channels.
2023-05-14 15:00:29 -07:00
Larry Gritz f27a974c34 build(deps): fmt 10.0 support (#3836)
fmt 10.0 was recently released, and it breaks a lot for us because they
have fully removed legacy support for automatically being able to format
anything that has an iostream `<<` operator. This facility was deprecatd
in 8.1 but could be re-enabled with FMT_DEPRECATED_OSTREAM, but even
that was removed in 10.0.

So this means that we had to write several explicit format handlers for
some types for use with format() and print().

Also, they are even more strict with sprintf/printf which don't honor
the custom formatters as far as I can tell, so in several cases I also
switched those to the std::format/print style.

Fixes #3835
2023-05-14 00:50:06 -07:00
Larry Gritz 81e4bd2fa7 build(cmake): Fix incorrect variable name to control symbol visibility (#3834)
As Fabrice Macagno points out on the mail list, we weren't setting the
correct variable name CMAKE_CXX_VISIBILITY_PRESET.

Fixing this -- and finally hiding all the symbols correctly -- uncovered
an instance where testtex was relying on some classes that should have
been hidden in libOpenImageIO. For symbol visibility reasons, move the
functionality of testtex's test_hash() function to be in TextureSystem
itself. This is a much cleaner separation.
2023-05-14 00:49:42 -07:00
Larry Gritz 4250d71093 cleanup: root out deprecated simd type names; OIIO_DISABLE_DEPRECATED (#3830)
We have some OIIO 1.x era type aliases float4, int4, etc., for the
simd types that have long since been renamed vfloat4, vint4, etc.
Hide those aliases when buiding OIIO itself, to be sure we aren't
inadvertently using them. And indeed, in one spot, we were! (Fix it.)

Introuce a new preprocessor symbol, `OIIO_DISABLE_DEPRECATED`, which
if set to an encoded version number (such as 20100 for version 2.1) by
a downstream package, indicates that we are permitted to hide
declarations that were considered deprecated from that version
on. This is an aid to downstream projects who wish to enforce that
they are not inadvertently using any deprecated OIIO calls which may
disappear in a future release.

So back to the deprecated simd names: Also hide them if
`OIIO_DISABLE_DEPRECATED` is defined to exclude things that were
deprecated as of OIIO 1.9+, which apparently is when we changed this
definition.
2023-05-14 00:49:02 -07:00
Larry Gritz 5152be9a57 ci: Fix warnings (#3833)
I'm honestly not sure why some GHA CI jobs suddenly started warning
about this in the past day or so. Something must have updated on their
end. But switching to the safer Strutil equivalents fixes it.
2023-05-09 14:29:53 -07:00
Ray Molenkamp 0a39c2c993 Fix: Build error with MSVC (#3832)
`ssize_t` is a posix type, msvc seemingly doesn't know about leading to
a build error with MSVC 2019

usage elsewhere in this files used the `py::ssize_t` type, which seems
to fix this
2023-05-08 11:54:26 -07:00
Ray Molenkamp a02327df53 Fix: Build error with MSVC (#3832)
`ssize_t` is a posix type, msvc seemingly doesn't know about leading to
a build error with MSVC 2019

usage elsewhere in this files used the `py::ssize_t` type, which seems
to fix this
2023-05-08 11:53:15 -07:00
Larry Gritz e1dcef1453 Add a helpful link to the comments 2023-05-08 10:57:46 -07:00
Larry Gritz 617eeed554 Improve make_texture for very large images (#3829)
`make_texture()` already took a configuration option "maketx:forcefloat"
(defaults to 1), which if set to 0 disables the conversion to a float
buffer for intermediate computation.

For `oiiotool -otex`, there was no way to specify this. This patch
allows it to be disabled with the new optional modifier
`-otex:forcefloat=0`.

Also, in make_texture, this option only controlled the initial
conversion of the whole buffer to float, but the downsized levels all
were float either way. This patch now uses the forcefloat config option
to also control the buffers used for downsizing.

Disabling forcefloat like this has a speed penalty (the downsizing math
on float buffers is faster than going in and out of float for every
indvidual value) and loses some precision in the process of repeatedly
downsizing to generate the MIP levels. But it can sure save a lot of
memory if you have a ginormous uint8 image and want to avod the 4x
balooning of memory. I don't recommend disabling forcefloat except for
images that can't fit into memory for the texture creation without it.
But when this is the right hammer to use, it can be the difference
between being able to create the texture, or not.

Some other improvements:

* `oiiotool -otex` wasn't outputting ANY status output during texture
output as maketx does, and for that matter, -v and -debug were not being
influencing the behavior of make_texture at all despite it having such
support. So fix to pass down the right flags. Now there are proper
verbose status and debug messages when requested.

* Eliminate useless call to is_monochrome by calling it only when the
previously-computed pixel stats indicate that the average value of all
the channels is the same (if they don't have the same average, there's
no way the pixel-by-pixel values will be the same in all channels for
all pixels). This saves an extra traversal of all the pixel memory
during texture creation.

* Use synchronized/flushed status messages so users can see them as they
are issued for very long maketx tasks. This also included some
conversion from old iostream stuff to fmt-based print.

* For verbose/debug, more fine-grained timing for make_texture, in
particular, print the time spent downsizing and writing each MIP level.
2023-05-08 10:06:36 -07:00
Larry Gritz 32a361ab3e build: Disable new warning for fmt headers in gcc13 (#3827)
Working toward clean build with the new gcc 13.1. This isn't the whole
story, but it is one thing necessary.
2023-05-04 21:28:42 -07:00
Larry Gritz 4917cd2fc8 One more revision to synchronized Strutil::print (#3828)
This is a continuation/fix for #3825
2023-05-04 21:27:13 -07:00
Jesse Y a1d8dbcecd api(ImageInput)!: Add an ImageInput::valid_file(IOProxy) overload (#3826)
ABI-BREAKING CHANGE!

Every format that has an existing `valid_file(std::string)`
implementation, and which supports an
ioproxy, now also has a `valid_file(IOProxy)` implementation for
completeness.

The existing std::string overloads have been implemented in terms of the
IOProxy overload where
possible to cut down on the boilerplate. This is done at the base of the
hierarchy in ImageInput.

The remaining formats that support ioproxy, but do not currently have a
`valid_file` method, will be
submitted in a follow-up PR as the additional logic required for those
will require closer review.
2023-05-03 16:22:58 -07:00
Larry Gritz 23819a86d8 cleanup(strutil): use forward properly for sync::print(). (#3825) 2023-05-01 19:12:33 -07:00
Larry Gritz 9e7e040a37 fix(psd): Improve memory efficiency of PSD read (#3807)
The PSD reader was written 12 years ago by a GSOC student and has
changed little since. The following is not a knock on that student, who
clearly did a good job if his code has survived mostly unomdified for
over a decade. In chasing down problems with handling extremely large
psd files, I've noticed some oddities and inefficiencies that need
fixing. It's not an emergency, so I'll handle it in pieces.

The item addressed by this patch is memory usage and thread concurrency.
It turns out that the reader allocates memory for the scanline reads as
it goes... and basically keeps it in the ImageInput until it's
destroyed, even though it will never actually be used again. I guess
it's just trying to save the next allocation if it reads the same
scanline again or on the next subimage? But this means that if you read
a really big psd image, it's basically doubling the memory use -- it
reads one copy into the user's buffer, but also holds on to this extra
copy for no reason. Also, a bunch of the decoding helper functions
implicitly use this memory, which means we lock a mutex for the duration
of read_native_scanline (which in theory should not be necessary since
all I/O is happening through thread-safe IOProxy calls).

So this patch does the following:

1. Remove both this retained scanline memory as well as some other
scratch memory from the ImageInput, and make it allocated and freed
local to read_native_scanline.

2. Change all the helper methods that used it implicitly so that they
are passed buffers to use. In many cases these have been changed to
`const` methods and in a few cases to `static`, making it much easier to
assure ourselves that they don't modify (or sometimes use at all)
anything in the PSDInput to do their task.

3. The result of these changes means that read_native_scanline doen't
need to modify any of the data methods of the class (though it does use,
without modifcation, some things set up in the course of open). Because
it's now non-mutable, we can also remove the mutex, now allowing
multiple threads to read scanlines from the same file simultaneously
without blocking each other.

4. Some other miscellaneous cleanup, including that some scratch memory
was allocated as std::string (!), whereas it should really be a
`vector<unsigned char>` or `unique_ptr<unsigned char>`, and also
changing some computations from double to float.

There is still some more work to do after this is merged. In particular,
I think now that scanline read is stateless / non-mutable with respect
to the PSDInput object, this is a candidate for adding a multi-scanline
read_native_scanlines method (replacing the default implementation of
looping and calling read_native_scanline serially for each scanline),
which should also be able to read multiple scanlines with some overhead
and allocations done once per block, and with blocks of scanlines
running in parallel using the thread pool. This should be a huge
efficiency gain when reading psd files. But it will wait until the next
patch.
2023-04-30 22:57:04 -07:00
Larry Gritz b64356b3af feat(oiiotool): expression eval NIMAGES gives current stack depth (#3822)
Based on a suggestion Matt Chaput on the oiio-dev mail list.
2023-04-30 10:41:49 -07:00
Edoardo DominiciandEdoardo Dominici c231dfb70a Fix float128 compilation of NVPTX backend for LLVM (#3823)
The latest version of libfmt began using the `__float128` type but this
is [not supported in the NVPTX backend for
LLVM](https://discourse.llvm.org/t/compiling-cuda-code-fails/61240/13).
A way to detect this particular platform seems to be to check both
`__CUDA_ARCH__` and `__clang__`.
I am not disabling it entirely on any CUDA target because NVCC 10+
understands `_float128` and generates instructions for it when tested on
godbolt.

Following up from https://github.com/OpenImageIO/oiio/issues/3809.

Co-authored-by: Edoardo Dominici <edoardod@sy1wse0003.al.com.au>
2023-04-27 19:24:01 -07:00
Larry Gritz 571a16717f test: Change the few symbolic links to copies to help Windows (#3818)
Windows isn't smart about symbolic links. There were a few places in the
testsuite where we used symlinks to essentially de-duplicate test
reference images that were expected to be identical. But then the
resulting archive you get when you ask GitHub for a zip file of the
whole repo (which some people download to get OIIO source rather than
git clone) can't be unzipped correctly on Windows (at least not by
cmake's unzip command).

OK, so just change those links to full copies.

Fixes #3811
2023-04-25 17:04:06 -07:00
Larry Gritz 4b6f54dc16 test: Don't run exr core version of openexr-compression testsuite (#3819)
Because it's broken in exr core!
2023-04-25 13:45:23 -07:00
Jesse Y e88e4e4b93 build: Fix incorrect branch name when cloning openexr-images for the tests (#3814)
The `openexr-images` repo was never updated after the default branch was
renamed to `main`. This will fix the following silent errors in CI:
```
Cloning into '/__w/oiio/oiio/build/testsuite/openexr-images'...
warning: Could not find remote branch master to clone.
fatal: Remote branch master not found in upstream origin
```

Additionally, the cmake attempted to symbolically link local repos like
`oiio-images` if they were found. Unfortunately this type of link will
fail unless running as admin on Windows (which is rare) and the
COPY_ON_ERROR directive did _not_ work here (cmake 3.24; weird;
sigh...). The output will now look something like the following:
```
-- Linking oiio-images from C:/Users/jesse/source/oiio-images
-- Link result failed to create symbolic link 'C:/Users/jesse/source/oiio/build/testsuite/oiio-images': A required privilege is not held by the client.
-- Copying oiio-images from C:/Users/jesse/source/oiio-images
```
2023-04-24 22:10:09 -07:00
AdamMainsTL bd4bbaf9cc Support HIF extension (#3813)
I've come across some unsupported files from Canon cameras that have a
.hif extension. These are HEIC/HEIF files with a slightly changed
extension. I have no idea why Canon decided to do this. Without any
changes I am able to open the images, probably because it checks the
header, but I am unable to write to paths with a hif extension.

Some random articles/forum posts mentioning the HIF format in relation
to Canon cameras:
https://www.cameralabs.com/jpeg-vs-heif-canon-hif-comparison/
https://www.dpreview.com/forums/thread/4558661

https://www.reddit.com/r/canon/comments/kjc6xl/new_eos_r6_owner_here_photo_files_show_up_as_hif/
2023-04-24 07:57:03 -07:00
Larry Gritz 54badeeb7c build: ffmpeg 6.0 support (#3812)
It seems to work fine with the new 6.0 with no code modifications, other
than our cmake build misidentifying the version.
2023-04-22 08:30:56 -07:00
Larry Gritz eb2ceba5ed fix: Controlled shutdown of IlmThread pool in all apps in which we use it. (#3805)
We know that there are some corner cases on Windows when it can be
unsafe to exit because the Ilm thread pool (which is used implicitly by
OpenEXR) hangs. The exact conditions that cause this are not well
understood.

Some time back, in PR 3582, we added an explicit shutdown in oiiotool
right before we exit, to alleviate the problem. But this doesn't help
for other apps like idiff, nor for apps that use libOpenImageIO and
aren't aware of the problem, so wouldn't know to do this.

This patch changes to a different strategy: In set_exr_threads(), which
will always be called any time we use openexr files, use `std::atexit()`
to ensure that when the program terminates -- any program using
OpenImageIO in cases when openexr was used -- we set the IlmThread
global thread pool size to 0 to shut it down cleanly. Hopefully, that
will cover even more cases where this OpenEXR bug might be tickled.
2023-04-22 08:30:24 -07:00
Larry Gritz 21ee2d225e CHANGES 2023-04-20 10:51:33 -07:00
Larry Gritz 22a8196c8f Refactor simd.h to disable Intel inrinsics when not on Intel (#3810)
Especially when compiling for Cuda.

Fixes #3809
2023-04-19 09:39:50 -07:00
Brad Smith efe2fe07c9 Fix building on OpenBSD (#3808) 2023-04-19 00:21:28 +00:00
Larry Gritz b2c11c33a4 fix(psd): Handle very wide images (#3806)
When decoding RLE data, some arguments to decompress_packbits() were
inexplicably declared uint16_t (they were passed uint32_t arguments, and
I honestly don't know why we didn't get a warning all along). This
prevented us from correctly reading PSD images whose width was more than
64k, which I suppose are rare enough that it's not hard to understand
why this went unreported for so long.

But anyway, just changing those parameters to uint32_t does the trick.
2023-04-17 08:53:24 -07:00
Eric Mehl f5f6d692cf Fix fast_exp2 with MSVC and sse4.2 (#3804)
I ran into the problem described in #2929 and did a little digging to
see if I could find the source of the bad color conversions. I tracked
it down to `fast_exp2()`
https://github.com/OpenImageIO/oiio/blob/a77e36250fadfb4c391688eb1df4b3dd88d5e367/src/include/OpenImageIO/fmath.h#L2050-L2080

and in particular the return statement on L2071. In the process of
trying to figure out what part of that return statement was going awry,
I found that separating the bitcasts to separate variables as in this
PR, the problem went away. All testing was done with the `color_test`
added in #3023.

It also succeeded when adding various `std::cout` lines to check what
the values of each computation were, so it does sound like a compiler
optimization that does or does not get triggered is the problem.

Unfortunately I don't know why it's not failing on the CI builds, I
double checked to make sure I'm using the same settings and flags. I
also tested on two different machines and get the same failures, and
success with this patch, on both.

One strange wrinkle is that even without this patch, color conversions
worked fine when using AVX2 for the SIMD mode.

Summary :
Previous results (without this patch)

- USE_SIMD=0 - PASS
- USE_SIMD=SSE4.2 - FAIL
- USE_SIMD=AVX - FAIL
- USE_SIMD=AVX2 - PASS

With this patch
- USE_SIMD=0 - PASS
- USE_SIMD=SSE4.2 - PASS
- USE_SIMD=AVX - PASS
- USE_SIMD=AVX2 - PASS

Visual Studio 2019 versions 16.11.32228.343, 16.11.33328.57 and
16.11.33423.256(same as current Github build runners) in RelWithDebInfo
mode.
2023-04-15 08:35:12 -07:00
Larry Gritz 3332c78f5e refactor: refactor font search (#3803)
Chris Gloor points out that after my latest change, the "font_dir_list"
got loaded with every directory underneath that it discovered through
that one level of recursion. Not harmful, but very cluttered. My
original intention was for font_dir_list to only have the search path
directories.

So this prompted me to do a bigger refactor to fix that up and clean up
some other things. Now all the searching is done once when it builds up
the initial inventory the first time a font is needed, no more potential
directory searching or touching non-essential files for each font-using
operation.
2023-04-14 09:33:51 -07:00
Larry Gritz a77e36250f test: Add another ref output for tiff-misc, for differing libitff error message 2023-04-13 11:27:18 -07:00
Larry Gritz 1db505e28e fix: Add one level of recursion to font search (#3802)
Not long ago, we removed recursion from the font searching, for
performance reasons. But now I see at there are some systems where none
of the font directories likely in the searchpath have any of the font
files directly there, but instead they are in subdirectories one level
further down.

To compromise, then, I'm adding ONE level of recurson to our font
search. If you need to search deeper than that, you should directly add
the paths to the OPENIMAGEIO_FONTS searchpath.
2023-04-13 07:49:10 -07:00
Larry Gritz 0a9f055edb fix(python): improve error messages of bad python array sizes (#3801)
For cases of calls like `ImageOutput.write_image(array)`, this improves
the error messages when the array dimensions don't match the size of the
image we're writing, in two ways:

1. For the case of 2D images where the dims don't match, print what the
array shape actually is and what was expected. That's more helpful than
just saying "can't figure out array shape" and printing the number of
dimensions (but not the shape).

2. A mistake caused a number of error messages to be substituted by a
cryptic "can't handle numpy array with noncontiguous channels", but that
was only supposed to be for one particular case; fix that.
2023-04-13 04:31:39 +00:00
Larry Gritz 1a6bfd0716 fix(raw): handle raw 1-channel raw images (#3798)
Fixes #3797
2023-04-11 16:27:40 -07:00
Larry Gritz 72bdba80b1 Revert PR 3788 -- switch "openexr:core" attrib back to 0 default (#3799)
We are not ready to throw the switch quite yet, because the exr core
library still cannot read dwaa/dwab compressed images. It's only safe
to use if you are sure you will not encounter those files.

I feel really stupid for not catching this earlier. Inadequate testing!

Add a new "openexr-compression" test that writes one of every compression
methods available to openexr and ensures it can be read back. We have to
disable it for openexr:core=1 because it will fail on the dwa cases.
2023-04-09 18:39:49 +00:00
Larry Gritz 78eff533c6 CHANGES update 2023-04-02 17:22:47 -07:00
Larry Gritz 3287b8e46a Document that OIIO builds fine with clang 16 2023-03-31 19:07:08 -07:00
Tom Knowles 541f87b249 fix(maketx): Add support for CDFs of bumpslopes channels (#3793)
Currently, if you run oiiotool with --bumpslopes and --cdf at the same time (or -obump:cdf=1), the CDF is only produced for the first four (of six) channels. The techniques described in Burley (2019) actually do apply reasonably to the squared derivative channels, so it's useful to allow all six channels to have CDFs here.

maketx and oiiotool-maketx tests updated with new relevant tests.
2023-03-31 13:59:16 -07:00
Larry Gritz e3929659dc CI: bump 'latest versions' test to the newest openexr release (#3796) 2023-03-30 23:04:18 -07:00
johnfeaandTuomas Tonteri d1a11a9316 Make project compile with clang 11.0.1-2 in Mac (#3795)
Co-authored-by: Tuomas Tonteri <e90@tuomastonteri.fi>
2023-03-30 23:03:23 -07:00
Massimo Paladin cb0db7c276 Remove SonarCloud cache setup as it is now offered by default (#3792)
No need to configure the cache anymore,
SonarCloud now has automatic analysis caching. See:
https://docs.sonarcloud.io/advanced-setup/languages/c-c-objective-c/#analysis-cache.

Also, the filesystem cache was not persisted.
2023-03-27 15:21:51 -07:00
Larry Gritz 67065cbcef perf(exr): change to using exr-core for reading by default (#3788)
When we build against OpenEXR >= 3.1, default to using the new
"exrcore" APIs unless disabled at build time with
`-DOIIO_USE_EXR_C_API=OFF` or at runtime through the global openexr:core
attribute.
2023-03-17 00:18:30 -07:00
Larry Gritz f25ff39537 Disable writing TIFF with jpeg compression (#3791)
TIFF output using JPEG compression seems unreliable, and after several
hours trying to chase it down, I'm not making much progress.  As far
as I can tell, this has always (or at least for a long time) been
broken, and nobody noticed, which is strong circumstantial evidence
that it's not something people need or is trying to use, and therefore
it doesn't seem like a good use of more time to fix a feature that
no one uses.

So I'm hiding all the TIFF output with jpeg compression support behind
`#if` guards and disabling them for now. This will cause requests to
use jpeg compression for TIFF output to just revert to the default zip
compression.

Reading TIFF files that are jpeg-compressed seems fine, this doesn't
disable our ability to read the files, just to produce them.

It is also worth noting: It's one thing to write an actual .jpg file
as *final* output for web display, viewing, or other "terminal" uses.
But JPEG-compressed image data should never ever be used as input to
further image computation operations, since each read/write/read cycle
with jpeg compression can lead to further data loss.  So I think for
this reason also, this patch should help avoid the temptation or
inadvertent ability to use this lossy compression method when writing
TIFFs.
2023-03-17 00:18:07 -07:00
Larry Gritz 34f01aa793 Add benchmarking of ways to concatenate strings. (#3787)
Upshot: when you are doing a straight-up concatenation, `concat(a, b)`
is about 2x faster than `format("{}{}", a, b)`.
2023-03-12 11:09:25 -07:00
Larry Gritz 412a1e16db fix: unique_ptr type mismatch caught by sanitizer (#3790) 2023-03-12 00:51:43 -08:00
Larry Gritz 4ce7365212 fix(gif): gif.h array overrun (#3789) 2023-03-12 02:56:03 +00:00
Larry Gritz 14995e39dd docs: edit INSTALL to correctly reflect changed dependencies lately
There were still some bolded (indicating newly changed) dependency
minimums that actually were bumped in 2.4 or even 2.3 and should have
already been unbolded.
2023-03-11 15:48:41 -08:00
Larry Gritz f1fa0537fb ci: updates to runners, dependencies (#3786)
* Don't use deprecated ubuntu-18.04 runner. Switch to running on
  ubuntu-20.04, but use docker containers that supply ubundu-18.04.

* Bump 'latest' version of openexr, webp, pugixml.
2023-03-11 12:04:12 -08:00
Larry Gritz 44a17dcdfa fix(IC/TS): Avoid deadlock situations with file handle cache (#3784)
There turns out to be a way to get wedged into a mutual deadlock on
the file handle cache, with how get_texture_info on a udim pattern
checks to see if the attribute requested is present and equally valued
in all constituent files of the udim set. This hits the handle set
pretty hard, and if multiple threads are hammering the same sets and
rapidly cycling textures out of the cache, there can be trouble, it
seems.

Remedies in this patch:

* When it's trying to close files because the number of handles is too
  high, we already had it so that if we only exceeded the max_files
  limit by a little bit, we would simply try to get the lock, and
  abandon the attempt if somebody else is holding it, but if we are
  quite a bit over, then stay and wait for the lock to be released.

  In this patch, we make the that default behavior -- if we are over
  the limit and need to free some handles, simply try to get the lock,
  and if somebody else is holding it, leave it all up to them and
  return immediately. The pros of this are (a) snappier response by
  never waiting at this point, and (b) removing the possibility of a
  deadlock, because if you can't acquire the lock, you just move
  on. But the con is that lots of threads adding new files may run
  faster than the one thread who has the file and is trying to release
  files, so it's possible that the number of handles will exceed the
  limit by a wider margin now, but hopefully only momentarily.  (But
  note that this can be overridden with a new ImageCache attribute
  "max_open_files_strict", which if set to nonzero revert to the old
  behavior. At least for now, in case I am neglecting to understand
  some bad consequence of this change.)

* The recursive_mutex controlling access to the ImageInput in each
  tile cache record is changed to a recursive_timed_mutex, and when
  closing a handle by calling release(), instead of an unconditional
  lock, try acquiring a lock for 100ms. If it fails to do so, it may
  be in a possible deadlock, so just give up and move on. The only
  consequence is that maybe that handle isn't freed after all. It will
  then move on to the next one, not the end of the world, but at least
  it can't get stuck there.

* In find_file, eliminate the call to check_max_files -- it's not
  needed here, since it's also called by open(), which is the only
  time that new file handles might be opened. We just don't also need
  it again simply because we're adding a file to the cache.
2023-03-10 23:01:10 -08:00
Fabien Castan 8e9b334a25 rawinput: fix typo on CameraElevationAngle (#3783) 2023-03-07 13:20:26 -08:00
Larry Gritz 15965ad8ad Update INSTALL.md to document the latest dependency support 2023-03-01 09:51:37 -08:00
Larry Gritz 1c5b4f40d7 api(ustringhash): make a public explicit ustringhash ctr from hash value (#3778) 2023-02-28 00:38:15 +00:00
Larry Gritz 0e2374e0bd Qt6 compatibility (#3779) 2023-02-27 16:37:30 -08:00
jreichel-nvidia 2ac5797422 Add cmake option to disable the stacktrace functionality. (#3777)
Setting the cmake option OIIO_DISABLE_BOOST_STACKTRACE to ON disables the use of
Boost stacktrace at compile time. This avoids dependencies on helper libraries
like dbgeng.dll.
2023-02-21 08:49:02 -08:00
Russell Greene a58e145e09 use check_cxx_source_compiles instead (#3774) 2023-02-13 21:50:09 +00:00
Larry Gritz f8db9f38d1 fix: race condition in TIFF reader (#3772)
* test: Add a corrupted test file

* fix(IC): upon tile read error, mark the file as broken

The idea is to keep fruitlessly reading from a corrupted file.

* fix: race condition in TIFF reader

TIFFInput::read_native_tiles had a very subtle race condition.  There
is a section where it has a task_set of decompression tasks that are
sent to the thread queue.  When the method ends, the task_set goes out
of scope, and its destructor will wait for all the remaining tasks to
finish. All fine, right? Except that other variables in the function
include unique_ptr's with allocated memory that the tasks need.  So
what can happen is that if the compiler generates the code such that
the destructor of the unique_ptr happens before the destructor of the
task_set, the memory that the unique_ptr held may be deallocated
before some of the tasks still running in threads have finished.

In practice, we seem only to hit this race condition for particular
cases involving corrupted files, because the early `return` seems
quite likely to run those destructors before all the threads are done,
but it was possible to encounter it for valid files as well, if the
timing is just right. Shocking that we never had it reported.

The solution is just to have an explitit tasks.wait(), which will
block until all the tasks have finished before hitting the actual end
of the method and letting the other destructors to run. And for the
"early return" case, change it to a break so that we go through the
wait call at the end.

I believe that this fix addresses TALOS-2023-1709 / CVE-2023-24472.
2023-02-13 05:30:36 +00:00
Larry Gritz fa9dadea72 fix(fits): Make sure to close if open fails to find right magic number (#3771)
There are two ways to fail the FITS magic number check: fail to read
the bytes, or the bytes don't match the magic number. It seemed
suspicious that we call close() for the latter but not the
former. Combine them into a single error response (they had the same
message, anyway).

Also, make sure FitsInput::init() fully clears some other data
structures.  Oversight?

I don't know if any of these things are real bugs, but they look
sloppy and potentially problematic, so fixing them up.
2023-02-12 22:04:23 +00:00
angusdavisadobeandLarry Gritz 9cb000f178 improve thread safety for concurrent tiff loads (#3767)
* Make lookups of const unordered_maps thread-safe

* added back deleted end brace

* clang-format

---------

Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-02-10 20:31:24 +00:00
Larry Gritz 86aea43007 fix: ImageOutput::check_open error conditions (#3769)
For non-0-origin images, we were checking the resolution range
incorrectly (`>=` vs `>`).

Also were printing the error message with the wrong notation, should
have shown a half-open range as `[beg,end)` and not `(beg,end]`.
2023-02-09 18:15:59 -08:00
Larry Gritz 759fcd392d fix(targa): guard against corrupted tga files (#3768)
* Be more careful constructing strings from what we read in the header;
  corrupted files may make them not be zero-terminated.
  Fixes TALOS-2023-1707 / CVE-2023-24473

* Watch out for pixels with palette indices that exceed the size we
  allocated for the palette.
  Fixes TALOS-2023-1708 / CVE-2023-22845

* Check alpha_type for valid range.
2023-02-09 13:32:31 -08:00
Larry Gritz 2a6f2c84b3 test: Better testing of python IBA functions (#3766)
Add a shim that can run both the "returns an IB" and "modifies an IB"
version of each IBA function for better test coverage.
2023-02-06 10:35:08 -08:00
Larry Gritz 9325069dd4 Fix formatting from PR 3764 2023-02-04 21:55:04 -08:00
Larry Gritz 271f911984 feat(TS): Add color management to texture lookups (#3761)
This isn't 100% final -- I'm sure there are some corner cases I
missed, maybe things that will eventually need some performance work,
but enough works and passes tests that I'm confident in the API and so
I want to get this merged and we can iterate on internals later.

The use case is as follows: User or shader knows that a particular
texture is in something other than the default working color space,
this is not necessarily apparent from the file itself and so cannot be
fully automatic, but it is presumed that it can be communicated in the
texture call. We aim to be efficient, fully converting each tile upon
input. Note that we are sweeping under the rug the fact that a
non-default color space lookup is not mathematically correct with
respect to the MIP-map downsizing math if that was not considered at
texture creation time. But by converting texels as they are read,
rather than the shader itself trying to do a color transformation on
the final texture result, at least we are doing the right math for the
filtering within and among MIP levels.

The new interface consists of communicating the presumed working color
space, finding the colortransform ID of a given from/to (with the "to"
defaulting to the working space, if not specified), and then on each
texture call, supplying that colortransform ID as one of the settings
in TextureOpt (or TextureOptBatch).

The outline of changes are as follows:

* BREAKING CHANGE: TextureOpt and TextureOptBatch now contain an
  additional int `colortransformid`. The default, 0, is the old (and,
  frankly, preferred) behavior. Nonzero values indicate that we want
  the texels to go through a color transformation as the tiles are
  read into the cache.

* BREAKING CHANGE: New public methods have been added to TextureSystem
  `get_colortransform_id(fromspace, tospace)` that return a transform
  ID given the from and to color spaces (ustring or ustringhash). This
  is the value that goes in the TextureOpt to request a color
  transformation on the pixels as they are read.

* BREAKING CHANGE: IC::get_image_handle / TS::get_texture_handle now
  take an additional optinal parameter that is a TextureOpt*. This is
  currently unused, but is reserved for possible future use and/or for
  alternate TextureSystem implementations that choose a different
  implementation strategy wherein an entirely different TextureHandle
  may correspond to each color transformation. That's not how I've
  done it here, but it's a valid approach (and maybe one we'll switch
  to in the future). We presume that it's ill-defined to ask for a
  handle with one explicit color transformation, then use that handle
  with a TextureOpt that implies a different color
  transformation. Using those consistently ensure that either TS
  strategy will work equally well.

* New TextureSystem attribute "colorspace" gives the working color
  space name (defaulting to "scene_linear"), and "colorconfig" can
  optionally point to a color config file (though this is not yet
  functional -- it just uses the default color config).

* Internally, the tile cache hash has been adjusted so that the same
  tile in the disk file will appear as a separate tile in the cache
  for each color transform that is applied to it. Thus, there is no
  conflict if some different texture calls ask for different color
  space interpretations of the same texture file. (That said, it's not
  recommended to be throwing color spaces around willy nilly -- it
  still takes multiple cache entries, plus extra color conversion math
  as the tiles are read in.)

* A new preprocessor symbol OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE in
  texture.h allows client software can easily tell if this is a
  version new enough to support color management and has the additional
  fields in the texture option structures.

Because there are breaking changes here to ABI, this is destined only
for master (future 2.5) and will not be backported to OIIO 2.4.
2023-02-04 14:53:30 -08:00
Larry Gritz f2a10108b3 fix(ImageCache): Avoid bad IC stats when no files were read (#3765) 2023-02-04 14:51:48 -08:00
jreichel-nvidiaandJoachim Reichel a8b93f0ccc Initialize OpenEXROutput::m_levelmode() in init(). (#3764)
Avoids conditional jump on uninitialised values in close().

Co-authored-by: Joachim Reichel <joachim.reichel@posteo.de>
2023-02-04 14:51:17 -08:00
Latios96 3b34231a3a Fix unresolved external symbol for MSVS 2017 (#3762) (#3763)
If char16_t is used as template argument, this leads to an unresolved symbol for MSVS 2017.
Use int16_t instead of char16_t in this case
2023-02-02 15:22:33 -08:00
Larry Gritz e2e5eba95d Update ref image 2023-01-26 15:09:48 -08:00
Larry Gritz 963b46a3d9 iff: Temporarily address breakage with optional IOProxy revert (#3760)
When we recently added IOProxy support to the Maya iff file reader in
PR 3647, something broke for certain (but not all) iff files, and I
have productions stumbling over this.

It's proving tricky to track down and I have shows needing a fix
immediatly, so this change sets up a CMake variable
ENABLE_RLA_IOPROXY, default to ON, but when set to OFF, it switches
back to the old "no proxy" versions of the iff reader.

Disabling this will get me out of my current emergency -- at the cost
of not having IOProxy for iff, which I don't need at this moment
anyway -- and give me some breathing room to fix the problem for real,
at which point I will re-remove the old code.
2023-01-26 13:52:26 -08:00
Larry Gritz e59397ad7c Add ColorConfig::getColorSpaceIndex -- look up index by name (#3758) 2023-01-22 23:33:00 -08:00
Larry Gritz 91a2bc4814 Minor IBA python binding internal refactor: vecresize utility (#3757)
There's a recurring idiom spread all over the python bindings for
ImageBufAlgo, which I encapsulate in a new local helper template
vecresize(). This ensures that the logic is identical in all the
places it's used, and also improves our coverage analysis (because it
was tricky to make tests that exercise the uninitialized-handling
cases separately for each of the many different places the idiom was
used).
2023-01-22 12:56:06 -08:00
Larry Gritz 4f180d13f8 Improve OCIO (especially 2.2) support and better testing (#3755)
Tweak the heuristics for trying to determine which arbitrary-named
color spaces are equivalent to certain known common names.

For OCIO 2.2+, some of this is easier and more reliable by using the
new built-in color spaces -- for example, we can transform a set of
sentinel colors from an arbitrary cs into the known built-in acescg,
or lin_srgb, etc., and if the values don't change, we know that cs
*is* the canonical one, even if named something weird.

But one problem is that for older OCIO, the built-in config is not
present, so if you have a color space named, I dunno, "linear", it's
hard to know what that is. Is it what we now call lin_srgb? Is it
ACEScg?  Something else? So the hack is: first, we try to identify a
space that we think is sRGB (almost all configs have something called
"srgb", because everybody needs it, and we take it at face value that
if they call a cs "srgb", it's the real "srgb", fools who use the name
for something else get what they deserve). We transform the sentinel
colors from the srgb into the cs we are interrogating, and if they
match what we expect to see from an srgb->lin_srgb transformation,
then guess what -- the unknown color space must be lin_srgb!

We may, in the future, expand this to deduce other spaces. But this is
a start.

There are other changes I made here to make this whole process much
less expensive than it had been getting, there was some redundant
work, and some work that only was useful for 2.2 or only useful for <=
2.1, so I only do those in the right circumstances now.

Also along for the ride: improve test coverage for maketx features of
colorconvert, unpremult, attrib, attrib.
2023-01-21 15:22:18 -08:00
Larry Gritz b311d51e3d Fix CHANGES typo 2023-01-20 09:10:32 -08:00
Larry Gritz 3fc4293a42 Update CVE designations in CHANGES 2023-01-19 13:38:38 -08:00
Larry Gritz 59f54c80b2 Spend less wasted time zeroing out ImageBuf (#3754)
Examining some timings and function call counts, I saw that a typical
oiiotool command was spending a surprising amount of time in
ImageBufAlgo::zero(), not just more runtime overall, but also calling
it many more times than I thought it should.  For example,

    oiiotool -create 4096x4096 3 -colorconvert srgb acescg

called ImageBufAlgo::zero()... 4 times, totaling as much time as the
colorconvert operation.

The idiom used in `IBA::op(dst, src, ...)` which initializes the `dst`
IB if it's not already initialized will call the IB constructor that
zeros out its contents (so you don't have every new IB full of garbage
pixel values). But for IBA functions, this is almost never necessary,
since the IBA function itself will tend to overwrite all pixel values.
Not always, of course -- since IBA functions let you restrict the
spatial area or channel range -- but in the cases where the
destination starts out uninitialized and is allocated to exactly mtch
the ROI, I *think* you can count on the calling IBA function filling
in all those values.

So I changed IBAPrep() to call the IB constructor that says not to
zero out the pixels.

Just in case we ever need the ability, I made a new flag value that
lets you call IBAPrep and tell it, yes, do zero out any newly
allocated buffers. But we pass the testsuite without needing that flag
anywhere, so I think we're ok.

Also, the --create command itself would make new buffers (with the
implied zeroing), and then explicitly zero it again!

So after these changes, the oiiotool example command line above only
calls IBA::zero() ONCE (correctly, in the initial new image --create
makes), eliminating three redundant calls.

I also hypothesized that each call to zero was taking too much time,
because underneath it was calling IBA::fill which laboriously walked
through the IB with iterators and copying a fixed pixel value that
happened to contain 0 values. So I rewrote a special case where if the
buffer had contiguous strides, it would just use memset instead.
Surprisingly, it was not appreciably faster, and I'm guessing that the
memory bandwidth necessary to touch every pixel in a 4k buffer is the
limiting factor, and the other pixel-by-pixel iterator diddling was
inconsequential compared to waiting for the memory bus. I'm still
going to leave this "optimization" in, even though it was barely
measurable for the case I was trying.
2023-01-17 23:26:37 -08:00
Larry Gritz 0a8311b885 Simplify oiiotool --resize recent changes (#3752)
No need for separate :offset= modifier, the :to= can already be
used for this purpose.
2023-01-17 23:26:04 -08:00
Larry Gritz 7e0ed37e97 Minor Timer and LoggedTimer class tweaks (#3753)
Timer:

* Fix goof where m_printdtr was a bool but was tested for equality to
  an enum. It happened to work like that, but only coincidentally.

* Add another enum value that allows a debugging message to be printed
  upon construction of the timer, in addition to its destruction.

* Switch from printf style to std::print style formatting of the
  debugging messages.

LoggedTimer:

* Modify to allow modifying the call count.  This turns out to be
  helpful for times when one logged function calls another logged
  function (like if a special case is broken out) and they both log to
  the same timer -- it makes it look like just one invocation instead
  of two.
2023-01-17 23:25:49 -08:00
Larry Gritz fd05534d44 Expanded functionality of oiiotool --resize (#3751)
Currently, --resize takes a single argument giving an "image geometry"
(like "640x480") that designates the size of the result image, and the
rescaling specifically maps the "full size" (a.k.a. display window) of
the input image to the output.

This experimental change extends --resize to accept additional new
optional modifiers:

- ":from=<geom>" Overrides the default of the full window of the
  source.

- ":to=<geom>" Overrides the default of the full window of the
  destination.

- ":offset=+x+y" Adds an additional offset transformation to the
  destination.

- ":edgeclamp=<0|1>" Turns on and off some special edge sample
  clamping to try to reduce certain ringing artifacts. (Experimental.)

Unlike the output resolution, which like all image sizes must be an
integer resolution, the overrides on the source and destination
windows and the offset is allowed to be floating point, that is,
allowing for fractional pixel sizes or offsets.

The from and to windows do not restrict the boundaries of pixels
computed, but rather, simply define the transformational mapping
between the two images: the transformation will be chosen such that
the float-valued coordinates of the source image correspond exactly to
the float-valued coordintes within the destination image. In both
cases, coordinates refer to the true continuous coordinates in the
image plane, with (0.0, 0.0) being the "upper left" corner, and pixel
centers being at half-unit positions such as (ipixel+0.5, jpixel+0.5).

For example,

    oiiotool in.exr -resize:from=100x50.3+50+20 1000x503 -o out.exr

creates a 1000x503 pixel image where the full output image is a
resized version of the 100x50.3 pixel window starting at coordinates
(50,20) in the input image.

This is mostly implemented (when it doesn't end up equivalent to the
old style resize) in terms of the existing IBA::warp() function. I needed
to add a new variety of warp() to avoid some artifacts, but I do this
tentatively and so currently do not expose it as part of the public API.
I want to gain some experience with the oiiotool usage by the users who
requested this, then will return later to exactly how it should be
exposed directly as IBA functions.
2023-01-12 15:57:35 -08:00
Larry Gritz c2781d7a8d TIFF: refine logic for setting PhotometricInterpretation on output (#3746)
Some background: TIFF allows for pixel values to be encoded in some
alternative color spaces, like YCbCr, CIELAB, etc., and this is
indicated by the TIFF PhotometricInterpretation tag. Since in practice
we almost never encounter these encodings in the wild, and they
require a lot of custom code to handle (for example, YCbCr also comes
along with the ability to subsample the chroma, and options for
different placements of the subsampled positions, yuck), for most of
these cases we just lean on libtiff's ability to convert the whole
thing to RGBA for us, and so in that case, we return to the user the
pixels as RGBA, and set the "tiff:ColorSpace" metadata just as an
advisory to indicate how it had been encoded in the file. But we don't
support writing any of those. (One exception is that we do allow
reading and writing of CMYK files.)

OK, but now what about a case where the app already has the data in
one of these spaces (such as YCrCb; and let's ignore the whole
subsampling miasma and assume we don't want to support that), and all
we want to do is write that data to a TIFF file -- without any kind of
data conversion -- but to set the TIFF tags properly to indicate that
the data in the file is what we know it to be?

A related special case of this is: what if we have a TIFF file that
has YCbCr data but neglected to mark it as such (I'm staring daggers
at a certain widely used compositing package right now), and to fix
this, we want to use OIIO to just copy the file and set the right tags?

It turns out that in the status quo, it is surprisingly difficult to
do this. There is just nothing in our existing TIFF output code that
will write any of those photometric tags for those spaces, and no way
to communicate that this is what we desire.

Whew. Now here's what this patch does:

* If the "oiio:ColorSpace" attribute (our usual way to indicate
  presumed color space of the pixel data) says that the pixels are
  already in one of those color spaces (specifically, "YCbCr",
  "CIELAB", "ICCLAB", "ITULAB", "LOGL", "LOGLUV"), then we set the
  PhotometricInterpretation tag as such in the TIFF file that we
  write.

* We still DO NOT interpret that as a request to convert pixel data
  from any other space into this one. In other words, the TIFF output
  does not convert color spaces (except for RGB <-> CMYK); this merely
  lets us output a file that correctly says the data are what the app
  thinks they are.

* A bunch of minor refactoring was necessary because of some unobvious
  coupling and order dependencies. For example, the sgilog compression
  techniques MUST be used with the LOGLUV color space, and vice versa.
  You have to know how both should be set before checking that they
  are compatible, and if they are not, adjust something that it's not
  too late to change.

So the punchline at the end is that if you had a TIFF file that has
YCbCr encoded pixels, but for some reason it's marked as ordinary RGB,
you can fix it as follows:

    oiiotool ycbcr_disguised_as_rgb.tif --iscolorspace YCbCb -o real_ycbcr.tif
2023-01-12 14:32:11 -08:00
Larry Gritz b6b6230a1b Bump version after recent developer preview tag 2023-01-12 14:29:27 -08:00
Brecht Van Lommel dfb086e130 Fix wrong oiio:UnassociatedAlpha spec for PSD files (#3750)
Refactoring in #1641 incorrectly caused this to be set on the last layer
rather than the composite image as before. Now set it on the composite
image and every layer, as all of them use unassociated alpha.
2023-01-09 11:18:33 -08:00
Larry Gritz 496b374e9c Testing: improve testing of maketx (#3748)
* Tests for maketx -u, --attrib, --sattrib, --cdf

* maketx was documeted to take --cdf as a simple flag, but was
  incorrectly implemented as requiring a (pointless) nonzero argument.
  Fix it and hope nobody was depending on the undocumented behavior.

* maketx -v arg never had any effect. Add it back.
2023-01-08 19:19:00 -08:00
Larry Gritz 1f2e6b9990 Comment out parts of libcineon that are not used by OIIO (#3747) 2023-01-08 18:34:06 -08:00
Larry Gritz 1026d7b18d Clarify comments in documentation of IBA::make_texture 2023-01-08 14:22:23 -08:00
Larry Gritz b4dad279a9 Additional testing and improved code coverage (and minor fixes) (#3745)
* Better Typedesc testing of 'tostring' with fmt style formatting
  commands, and fix a bug that uncovered.

* Refine 'make CODECOV=1' behavior

* Beef up python-imagecache test to test getpixels, more attribute,
  invalidate.

* Better testing of python IB construction from numpy array.

* testtex: Use correct guard to avoid compiling unused code for
  coverage analysis testtex: get rid of unused 3d warp code.

* Add texture-threadtimes test

* Eliminate redundant code in exroutput.c by implementing
  write_scanline using write_scanlines.
2023-01-08 14:17:43 -08:00
Joris NijsandJoris Nijs 8cfa5f90b5 Add EXIF write support to PNG output. (#3736)
* Add Exif write support to PNG output.

Stores any Exif data from the given ImageSpec into the PNG eXIf chunk.

* add test for writing Exif data in png

* add test reference output for libpng versions not supporting the eXIf chunk.

* Update testsuite/png/ref/out-libpng15.txt

Co-authored-by: Joris Nijs <joris.nijs@esko.com>
2023-01-08 11:46:12 -08:00
Larry Gritz 6acaac4d08 Docs: minor improvments in description of ociodisplay and others 2023-01-08 10:16:59 -08:00
Larry Gritz ff1f577c08 ImageSpec:set_colorspace() (#3734)
Sets color space metadata. While conceptually, the main job is to call
`attribute("oiio:ColorSpace",name)`, this is a central spot to add
logic that adjusts or removes other contradictory metadata.
2023-01-07 23:49:18 -08:00
Larry Gritz 43c13ae9c8 Docs: for rtd, upgrade sphinx/breathe versions, use furo theme (#3737)
I think this looks better.

Also a few minor tweaks to typos and misquotes.
2023-01-07 23:46:29 -08:00
Larry Gritz da51cd9167 Revert #3728, that was ill advised (#3740)
Note that these intrinsics don't seem to be available for gcc.
They are available on clang, but are defined in terms of the memcpy
trick. But in Intel, they seem to actually help.
2023-01-07 23:45:21 -08:00
Larry Gritz 89c5802990 CI: Lock down to older icc so it's not broken (#3744)
The new 2023 one on the Intel site seems to require a glibc too new to
be compatible with the one on the ASWF CentOS-7 based containers, so
has been breaking our CI for a couple weeks.
2023-01-07 17:41:43 -08:00
Larry Gritz a3843e2597 CHANGES 2023-01-04 19:01:07 -08:00
Larry Gritz 16948f64a2 Testing: get rid of testtex's datatime query, for test consistency (#3741) 2023-01-04 19:00:25 -08:00
Larry Gritz 1b9ce86821 Update ref image 2023-01-04 14:51:38 -08:00
Larry Gritz d5be2d16cb CMake config should not include a find of fmt if it's internalized (#3739) 2023-01-03 18:11:47 -08:00
Larry Gritz dad63699ed CI: Temporarily lock fmt to 9.1.0 because its master seems broken (#3738)
Investigate later. For now, this is necessary for us to pass CI.
2023-01-03 17:06:04 -08:00
Larry Gritz c023ec6004 Update ref output 2023-01-03 14:34:36 -08:00
Larry Gritz d5670ff858 Move ARM_NEON definition and fix possible double define (#3735)
It should not have been set in platform.h (inside the cpuid function!)
in the first place. And apparently, though this was ok for Windows ARM,
on Mac ARM it's an error because that symbol is already defined.
So only redefine it if it's currently undefined. And move the whole
check and definition into simd.h where all the other ARM_NEON stuff
lives.
2023-01-03 11:36:35 -08:00
Larry Gritz 3b8807df85 Fix date 2023-01-01 09:51:26 -08:00
Larry Gritz c3a15ed84e CHANGES 2023-01-01 00:01:26 -08:00
Larry Gritz 0b9e9d7ed7 Add testing for maketx --lightprobe, fix bugs (#3732)
We never had a test for `maketx --lightprobe`, so add it to
testsuite/maketx.

Immediately discovered that it only worked correctly for float images,
fails for half or other types. Fix.
2022-12-30 09:51:20 -08:00
Larry Gritz f70834521c Fix long-broken ref images for texture-icwrite test (#3733) 2022-12-30 09:50:43 -08:00
Larry Gritz edaa7a2ac1 pbm: Fix for incorrect inverting (#3731)
We didn't have thorough tests of pbm/pgm/ppm files, add some.
That immediately uncovered a problem with pbp files.

By spec, pbm (1 bit) files use 1 to mean black, 0 for white.
Confusing, because pgm (grey) and ppm (rgb) use 0 for black.
2022-12-30 09:50:09 -08:00
Larry Gritz 9aabd4366d CI/Testing: many improvements for testing and code coverage (#3730)
* When checking code coverage, don't abort for failed tests
* Rejigger imagebufalgo_test a bit for better IBA test coverage
* Test zover
* Have testsuite/oiiotool-fixnan test with deep images
* Add to the extisting --fixnan tests a test for 'error' mode.
* Make testsuite/oiiotool-color test all colormap names
* Test 2D filters in filter_test
* Exclude python scripts in src/doc from coverage analysis
* Remove redundant attribute-seting code from the python internals
* Remove unused python_array_code function
* Exclude some imported code from coverage testing
* Re-enable and improve coverage testing from 'make CODECOV=1'
* Exclude unused/unexposed parts of xxhash.cpp from compilation
2022-12-28 11:44:56 -08:00
Larry Gritz ec2fb0005a Remove useless bitcast specializations (#3728)
Turns out the clang/gcc intrinsics themselves compile to the same
memcpy idiom that I was using for the general case. So there is no
need for the clutter of the specialization.
2022-12-28 11:44:37 -08:00
Larry Gritz e1db762b58 platform.h: set up macros for detecting MSVS 2019 and 2022 (#3727) 2022-12-28 11:44:02 -08:00
Larry Gritz 93727ff83b typedesc.h: Extend TypeDescFromC template to the full set of pixel types (#3726) 2022-12-28 11:43:44 -08:00
Larry Gritz 46f31d5a53 tiff updates for libtiff 4.5 (#3719)
libtiff 4.5 was just released, so confirm that we build against it,
update the "latest versions" CI test to use 4.5.

More careful sorting out of libtiff version numbers for conditional
compilation.

Get rid of some ancient tiff version guards that are related to
libtiff versions that are older than we currently support.

When building against libiff 4.5, use the new open calls that allow
per-file error handlers, which is better than the old global error
handlers for thread safety of multiple threads reading from the same
ImageInput if there are errors.

Convert error messages to std::format form.
2022-12-27 21:28:34 -08:00
Larry Gritz 070790ef73 Fix typos 2022-12-26 15:27:58 -08:00
Larry Gritz 003a1f15ae Retroactively fix release notes to document TALOS-2022-1631/CVE-2022-41649 2022-12-24 15:45:17 -08:00
Larry Gritz 5c43dfebe4 IBAprep should not zero out deep images when creating dst (#3724) 2022-12-24 14:27:34 -08:00
Larry Gritz 8f6de9b512 CHANGES 2022-12-24 14:24:22 -08:00
Larry Gritz 5518be34c0 Fix static analysis warning about array extent 2022-12-24 12:13:43 -08:00
Larry Gritz 188efa55af oiiotool --pdiff: test, be sure to count it as making output (#3723)
We had no testsuite exercise of --pdiff, add it.

Along the way, I saw tha we were getting the "you didn't have any
output" warning when using pdiff, so fix that.

And some other minor changes: formatted output update, some other
tightening up of things.

A little bit of jiggling the contents of XYZtoLAB_color to work around
what I think is a compiler error with icx -- it was generating NaNs
for reasons I was unable to understand or fix, but not if I rearranged
the code slightly. All the other compilers and versions had correct
behavior.
2022-12-23 19:38:32 -08:00
Larry Gritz 726c51181a ARM: Fix signed/unsigned simd mismatch in vbool4::load (#3722)
Fixes #3721

Please read the comments in #3721. This is the "local" fix for the
build break due to the type mismatch. It is a band-aid. And it may be
the best solution for the 2.4 branch if we don't want to potentially
break ABIs by changing the definition of any public types.

Still pending is to examine the issue of whether it was a mistake to
define vbool4 storage for neon as uint32x4_t or if we should change it
to int32x4_t to better match the non-simd reference implementation.
After debating that (and identifying somebody with access to an
ARM-based machine to test the solution for us), we may return to
tackle this more fundamental change.
2022-12-22 16:30:52 -08:00
Larry Gritz 48f2b1bf92 ustring.h: cuda guards (#3718)
Hide from Cuda some things that can't possibly work in Cuda.
2022-12-20 15:09:07 -08:00
Larry Gritz 2317a6b681 Add testsuite coverage of igrep utility (#3715)
Add exception safety in igrep test.
2022-12-18 15:34:19 -08:00
Larry Gritz 109164e012 Add a test of the 'term' pseudo-output (#3714)
A few minor fixe to the term code, add a "term:filename" optional hint
to redirect output rather than go to stdout, and also change to the
new std::format notation for output.
2022-12-18 14:45:57 -08:00
Larry Gritz 9c910144aa OpenColorIO improvements, especially for 2.2 (#3707)
* OpenColorIO improvements, especially for 2.2

* When OIIO builds against OCIO >= 2.2, in the event that there is no
  config supplied (e.g., specified by env `$OCIO`), use he new
  build-in "cg" config to supply a basic set of color spaces and
  transformations. Yay for OCIO 2.2 and its built-in configs!

* New OIIO-understood aliases (regardless of whether they were in the
  config or not): "scene_linear", "srgb", "lin_srgb", and "ACEScg".
  It will do its best to know which, if any, supported color spaces
  are equivalent to these, even if arbitrarily named. For OCIO >= 2.2,
  some trickery is employed to use the new features that can convert
  to built-in config color spaces, transforming several colors in this
  manner and seeing if it gets what would be expected for various
  canonical color spaces.

* `oiiotool --help` now a much abbreviated set of color information
  (just the OCIO version, and the config, and a hint about how to get
  more info).

* A new command `oiiotool --colorconfiginfo` prints the FULL
  inventory of color management information, which now has been
  expanded to reveal the aliases of each color space, print the roles,
  and generally spruce up the output to be much more readable (though
  longer) for large configs.

* New methods for our ColorConfig class:

  - `resolve(name)` turns the name, which could be a color space, an
    alias, a role, or an OIIO-understood universal name (like "sRGB")
    into a canonical color space name.
  - `equivalent(name1,name2)` returns whether or not the two names
    refer, ultimately, to equivalent color spaces (to the best of its
    ability to figure out).

* Some minor changes (including additional `const` qualifiers)
  on the ColorConfig class.

* Make testsuite tests use the built-in OCIO config if OCIO 2.2+ is
  found.

* Build sonar against ocio2.2 so we are primarily testing the new
  code paths.

* For OCIO >= 2.2, because we can count on the built-in configs,
  conditionally compile a bunch of hard-coded color transforms.  These
  will eventually disappear completely, someday, when OCIO 2.2 is the
  minimum supported version.

I think the behavior should all be largely unchanged when running
OIIO in a facility that has a proper OCIO config pointed to by the
`$OCIO` env variable and using color space names contained therein. So
studio users will (I hope) see no changes. For users that have no
OCIO config, or that are writing software that they want to work
reasonably well for common cases no matter what config they encounter
at runtime, this should give more helpful and consistent behavior when
OCIO 2.2+ is used (which I now strongly recommend for anybody not
constrained to 2.1 for compatibility reasons.

But because of the risk and the possible behavioral changes, this is
all currently envisioned as OIIO 2.5 features, and I am not planning
to backport it to the 2.4 release branch. Additionally, a lot has
changed and I expect some additional tweaking and identification of
edge cases I may have missed.

* docs, etc
2022-12-18 11:53:40 -08:00
Larry Gritz 82a4b089c7 IOProxy read/write error handling improvements (#3712)
IOMemReader::pread catch out-of-range read positions.

Fixes #3711

Along the way, I noticed that the system pread & pwrite return a
ssize_t rather than a size_t as our IOProxy methods do, so I need to
catch the negative value returns that they use to indicate errors.
2022-12-18 11:52:58 -08:00
Larry Gritz c59529a9a1 hashes.cpp: remove or exclude from compilation unused functions (#3713)
Remove the xxhash stuff from hashes.cpp -- it long ago moved to
xxhash.cpp. Also, comment out the bjhash implementations that OIIO
itself doesn't use or expose publicly, since there's no point
compiling it (or having it count against us in coverage analysis).
2022-12-18 11:52:37 -08:00
Larry Gritz 55fa36062d Build: Suppress warnings about deprecated std::codecvt_utf8_utf16 (#3710)
Another fix for the latest Apple clang, continuing #3709 (I missed
these other spots).
2022-12-16 11:14:52 -08:00
Larry Gritz 8efd666c21 Build: Suppress warnings about deprecated std::codecvt_utf8_utf16 on Apple clang (#3709) 2022-12-15 18:09:49 -08:00
Larry Gritz 1449b46500 CI: Fix iinfo test so it works on windows (#3706) 2022-12-11 15:57:18 -08:00
Larry Gritz ed3dc51c55 Excise the last instances of unsafe sprintf (#3705) 2022-12-11 12:05:52 -08:00
Larry Gritz 494236c1fc Remove useless test in hdrinput (#3704) 2022-12-11 12:05:24 -08:00
Larry Gritz 327eb03790 BMP: set colorspace to sRGB (#3701)
Seems like a reasonable assumption for BMP files.  It's not strictly
correct -- there are header fields on V4 and V5 BMP files that
communicate color primaries and gamma, but honestly, I do not have any
idea if anybody uses them or whether they're more misleading than
helpful. For now, assuming that a BMP file is meant for output on
an sRGB display seems like it's likely to be true.
2022-12-09 22:18:59 -08:00
Michael Oliver 4001c95ac7 build_openexr.bash: bump default version to 3.1.5 (#3703)
bump to 3.1.5 for vfxreferenceplatform cy2022
2022-12-09 22:18:20 -08:00
Larry Gritz 99b0f37ac6 CI: Fix broken Mac CI with proper numpy install (#3702)
Something changing in homebrew caused CI on the macos11 test case to
fail, starting a few days ago. This fixes.
2022-12-08 11:46:27 -08:00
Larry Gritz 78ee5e05ea texture3d testing, fixes, refactoring, coverage (#3699)
* More extensive testing of texture3d: handle vs filename, subimages,
  >4 channels, closest sample interpolation.

* Fixes for tex3d > 4 chan that turned out to be broken.

* Some rearrangement for the >4 channel case

* Refactor and simplify accum3d_sample_bilinear so multiple data types
  all use the same templated code path.

* This all reduces the amount of untested code in OIIO by another 0.4%.
2022-12-07 21:29:02 -08:00
Larry Gritz dc5bffcf3f Build: fmt external version flexibility (#3598)
* Build: fmt external version flexibility

The current default behavior is to
1. Check if there's already a copy of fmt found.
2. If not (or if BUILD_FMT_FORCE is ON), download it locally.
3. Copy the relevant fmt .h files as part of the OIIO install in
   OpenImageIO_ROOT/include/OpenImageIO/detail/fmt

This patch adds a new INTERNALIZE_FMT option, which defaults to ON,
whch is the old behavior. But if set to OFF at build time, the fmt
headers will NOT be copied into OIIO's install area (instead, it will
have dummy files that in turn include the real ones).

Set INTERNALIZE_FMT to OFF if you are really sure you want users of
OIIO to use the system install of fmt and not have OIIO install a new
copy.

When an externalized fmt is used, also make sure our exported cmake
config files cause the downstream user to find fmt and pass on the
dependency properly (necessary because strutil.h actually requires
properly including fmt headers).

Eliminate extraneous include_directories of fmt

Bump the auto-download version of fmtlib to 9.1
2022-12-04 12:50:23 -08:00
Larry Gritz 3641834a11 Centralize ImageOutput validity checks (#3686)
Many ImageOutput::open implementations start out with various validity
checks -- such as whether the ImageSpec requests a resolution, number
of channels, or other features simply not allowed by that file format.
This is not only repetitive, but which checks are done by each file
type is somewhat haphazard, error-prone, hard to get full test
coverage (must we separately test each possible failure case for every
file format?), and the error messages are not always consistent across
formats. Frankly, most of the format writers assume that the caller
has a full understanding of supports() and will never send requests
for features that are unsupported.

This PR proposes adding a utility method ImageOutput::check_open(),
which performs all validity checks on the ImageSpec that can be
deduced from supports(). The various ImageOutput::open()
implementations may call this function and avoid having to replicate
(or forget) all the checks done in other output formats.  This is a
protected method that is used by ImageOutput implementations
internally, but has no use for client-side code.

I've implemented check_open, and also used it here for all the output
formats. If this seems ok to everyone, I also plan to do an analogous
helper for ImageInput common validity checks (which will be an even
bigger reduction of redundant code and greatly increase the safety
against corrupted or nonsensical input files).

Along the way I also instituted a new supports() query: "noimage".
That is to indicate a file for which it is permitted to have a pixel
data window consisting of 0 pixels (i.e. an "image" that is only a
container for metadata). Currently, FITS is the only format we support
that allows this, though it's something we occasionally talk about for
OpenEXR. Allowing an explicit way for formats to say they allow no
pixels is what allows check_open to issue error messages for all the
other formats if it is passed zero-sized width, height, depth, or
nchannels.
2022-12-04 09:59:20 -08:00
Larry Gritz 92e488a3b7 Testing; better tests of environment mapping, minor fixes (#3694)
Would you believe we never had a testsuite test for environment
mapping?  Well, it wasn't totally untested, in the sense that OSL
testsuite had one, and obviously it's used in production all the
time. But OIIO's testsuite didn't have any tests of
TextureSystem::environmemt(). We now remedy that.

* Add testsuite/texture-env, contains several environment tests,
  including handles vs filenames, subimage selection, different interp
  and mip modes, ask for >4 channels.

* New CMake build option OIIO_TEX_IMPLEMENT_VARYINGREF can be used for
  testing to disable implementation of the old 1.x style of batch
  texture calls.  We don't use them, they are deprecated. This option
  give us a way to exclude them from code analysis, because we really
  don't care.

* Fix bug with >4 channels for environment batch shading!

* Avoid unnecessary spec lookup in TileID constructor.

* Avoid building testtex test_hash during code coverage -- it is an
  extremely specialized test, not run in the testsuite, it shouldn't
  really count againt good code coverage.
2022-12-04 09:55:23 -08:00
Larry Gritz fabce2ac33 Fix broken version designation in docs (#3698) 2022-12-03 21:51:11 -08:00
Larry Gritz a707c2a534 Fix docs typo 2022-12-02 16:43:31 -08:00
Larry Gritz ecb807262e CI: test against latest webp, and deal with its master->main repo change (#3695)
Also be more robust to the libheif and libde265 repos being
occasionally down.
2022-12-01 14:39:05 -08:00
Larry Gritz 8b5ace53a9 make_texture: allow existing DateTime to remain (#3692)
When creating a texture, the old logic was to set the file metadata
"DateTime" to the current time, unless update mode was used, in which
case it was set to the file's write timestamp of the input file.

But that made it impossible to explicitly set that metadata, and also
a big PITA for testing because it meant the metadata of any written
texture would be the time of its writing, and so appear different
every time.

This change alters the logic: update mode still sets DateTime to the
last update time of the input file, as before; other cases will only
set DateTime if it isn't already set, but not alter it if the input
carries that metadata already.
2022-11-29 22:49:02 -08:00
Larry Gritz 4037671a31 Refactor common parts out of iinfo and oiiotool printinfo, testing (#3688)
* There was lots of duplicated code between iinfo and `oiiotool -info`.
  Refactor much of that into a new src/libOpenImageIO/printinfo.cpp.
  These are internal functions, no change to public API.
* Test iinfo --hash, --stats, and with nonzero origin and full size
* Test iinfo and oiiotool --dumpdata of deep image
* Test iinfo for subimages, mips, -f, -s
* Some conversion to new print instead of printf

There is probably more such refactoring to do later, I did the easy
parts for now and that's a start.
2022-11-25 18:48:05 -08:00
Gerdya 1aa2cf6edf Some fixes for compilation with MSVC for Windows ARM64 (#3690) 2022-11-25 16:31:12 -08:00
Larry Gritz 6aac5b182a span minor improvements (#3685)
* Make sure the cspan alias also allows the Extent template argument.

* Add a custom formatter for {fmt} to print spans, like we did for
  Imath types.
2022-11-24 11:38:15 -08:00
Larry Gritz 44ff29deb7 oiiotool --dumpdata : fix channel name output (#3687)
We weren't copying the full spec, so didn't get the channel names.
2022-11-20 22:50:53 -08:00
Larry Gritz f782db69e3 oiiotool --point fix problem when there's no alpha (#3684)
We were over-allocating the color vector, and that was throwing off
the operation of IBA::render_point for cases where the image had no
alpha channel.
2022-11-20 22:50:26 -08:00
Larry Gritz c0bbf873f2 Catch possible exception, identified by static analysis (#3681) 2022-11-19 08:43:50 -08:00
Larry Gritz e4b5fa4ea7 DPXColorConverter.cpp: exclude unused portions (#3682)
Many parts of this imported file are unused by OIIO. `#if 0` them away,
so they aren't part of static analysis or code coverage.
2022-11-19 08:43:35 -08:00
Larry Gritz ce03d56d8e PSD reading: don't reject padded thumbnails (#3677)
When reading PSD file, if reading the thumbnail doesn't pass basic
sanity checks, we consider that a hard error reading the file.  One
check that we do is to make sure that our computation of the byte
width of the uncompressed thumbnail (`bpp/8 * width`) matches what the
file says the `widthbytes` is.

BUT... it seems that it might round up to an even (or maybe 4-multiple?)
of columns, presumably for scanline alignment reasons. And so we were
considering whole PDF files unreadable if they fell into this case.

This PR primarily loosens the test to allow some padding up to a
multiple of 4.

Fixes #3658
2022-11-18 07:30:49 -08:00
Larry Gritz 209c1bfd46 IFF output safety (#3676)
* Maya IFF documentation says IFF file has max resolution of 8192, and
  our implementation only allows writing RGB and RGBA, so check these
  limits when an IFF file is opened for output.

* Make sure scratch space allocates enough for tile padding.

* Check for non-zero image origin coordinates (which are not allowed
  in IFF files).

* Change some 16-bit loop variables to uint32_t to avoid possible
  overflow.

Fixes TALOS-2022-1654, TALOS-2022-1655, TALOS-2022-1656
2022-11-18 07:29:51 -08:00
Larry Gritz 9ccbc43f38 Try to squash warning in gcc 12.1 + C++20 (#3679) 2022-11-17 22:41:13 -08:00
wayne-arnold-adsk ae1031044f Avoid sanitizer warning unsigned integer overflow (#3678)
/Volumes/DATA/local/S/Maya_master_CI_sanitizer/build/RelWithDebInfo/src/Components/ExternalLibraries/OpenImageIO/install/include/OpenImageIO/string_view.h:252:43: runtime error: unsigned integer overflow: 0 - 17 cannot be represented in type 'unsigned long'
    #0 0x10d0adf61 in OpenImageIOMaya_v2_4::basic_string_view<char, std::__1::char_traits<char> >::compare(OpenImageIOMaya_v2_4::basic_string_view<char, std::__1::char_traits<char> >) const string_view.h:252
2022-11-17 15:08:51 -08:00
Larry Gritz 4b22cf4452 BMP output safety (#3673)
In open(), check for non-zero image offsets, which is not supported by
BMP, and issue an error if found. If the spec passed in has nonzero
spec.y, other code in the write functions would fail because they
assumed spec.y == 0 and could therefore access memory incorrectly.

More generally, also put checks in the write functions that issue
errors and take early outs if they find that they are called on a
BMPOutput that is not currently open, for example if open() fails but
the user doesn't check the return codes and proceeds to call the write
functions anyway.

This addresses TALOS-2022-1653 / CVE-2022-43594-CVE-2022-43595
2022-11-16 12:07:21 -08:00
Larry Gritz 32946e54e5 DPX output: fix write errors (#3672)
There was a subtle error where we had a reference to an ImageSpec for
one of the subimages, confusingly called m_spec, which we altered, but
then didn't make the same change to the this->m_spec, and in a later
spot we referenced the `m_spec` meaning the one in `this`. This could
lead to a crash.

Fix, but not only that, also rename to avoid the confusion. `spec0` is the
alias we us for the spec for subimage 0, and `spec_s` is the alias we
use when referencing subimage S, and we really never use m_spec
anymore to avoid any confusion. This should make it easier to reason
about this code in the future and avoid these kinds of mistakes.

A second error resulted from the situation where a failure in open()
would return before one or both of m_buf or m_tilebuf were allocated.
If the return status of open() were ignored and the caller
subsequently attempted calls to write_scanline or write_tile, invalid
memory could be accessed. Fix this with a variety of guards not only
based on the allocation status of these buffers, but also issuing
errors (and exiting early) from write_scanline or write_tile if they
are called on an ImageInput that is not in fact open.

Addresses TALOS-2022-1651 / CVE-2022-43592 and 
TALOS-2022-1652 / CVE-2022-43593
2022-11-16 10:53:23 -08:00
Larry Gritz 1605a4a961 Fix formatting 2022-11-16 10:39:52 -08:00
Fabien Servant @ TCS f7c4023487 [raw] update exif orientation with raw flip if user flip is set (#3669) 2022-11-16 10:38:05 -08:00
Larry Gritz d5d9146f32 PSD: Fix thumbnail extraction for PSD files (#3668)
Fixes #3660

In investigating this issue, I also noticed that now that IOProxy
support can be relied on, the old code that in the psd reader that
directly fumbles with libjpeg is not needed and can be replaced by
just a couple of lines to make an ImageBuf read from an IOProxy.

And it fixes the bug, too. So I'm not even going to try to figure
out what was going wrong with the old code.
2022-11-15 18:41:14 -08:00
Larry Gritz aba8470c91 DPX input: Comment out assertions (#3674)
We shouldn't abort here, we should return and handle the error better
(which we do).
2022-11-15 08:01:24 -08:00
Larry Gritz b48f0650a4 Zfile write safety (#3670)
When writing a zfile, anything that causes open() to fail will leave
m_tilebuffer at 0 size. Subsequent calls to write_tiles, and also
to close (which cleans up unwritten parts of the buffer at the end)
did not check for this condition and would access out of bounds memory.

While I was in there, I converted the zfile.cpp error messages to the
new formatting convention.

Fixes TALOS-2022-1657
2022-11-14 19:21:40 -08:00
Larry Gritz d7ecbbb100 ImageBuf+IOProxy vs ImageCache subtle fixes (#3666)
I uncovered a very subtle problem that can happen with the interaction
between ImageBuf, using an IOProxy, and the underlying ImageCache.
Remember that when using an IOProxy, it is critical that the lifetime
of the proxy outlasts any ImageInput, ImageBuf, or ImageCache that was
told about it.

Consider the following code:

    IOProxy proxy(...);   // temporary proxy in this local scope
    ImageBuf A ("foo.exr", 0, 0, proxy);

We've set up an ImageBuf that will read from an IOProxy.  Behind the
scenes, it made an ImageCache entry that remembers the IOProxy, as it
has to, since it needs to use that proxy for subsequent reads.
Now we read the image, and we use the `force=true` parameter to
force an immediate read of the file:

    A.read (0, 0, true);

It reads from the proxy. But the IB and the underlying entry in the IC
still know about the proxy. But in the user's mind, they have fully
read the image, will never read from it again, so of course (they
think) it is safe to close or destroy the proxy, knowing that they
made it last past its use:

    proxy.close();

But -- oops! -- the cache entry still has a pointer to the proxy, and
even though it won't need to read from it again, it still will access
it, close it, etc., but the user's proxy may by that point be out of
scope.

This is *technically* not a "bug" in the sense that it is the user who
violated the contract by closing or destroying the proxy before its
last use by anything they passed it to. But in context, it's very easy
to be confused by this -- the user thinks that the only observer of
the proxy is the ImageBuf, and they're done using the ImageBuf at that
point, but because they don't explicitly mention an ImageCache, they
don't realize that the ImageBuf passed the proxy reference along to
the underlying IC that could be backing any ImageBuf.

It's the user's fault in some sense, but let's just say that we have
given them an "attractive nuisance."

That's a long bit of background explanation, but I wanted to force
myself to explain it clearly and make sure it was spelled out in the
commit comments. Now here is the fix:

* When IB::read does an immediate forced read involving an IOProxy,
  after the read is complete, tell the cache to invalidate the entry
  for the file so that it no longer retains a pointer to the proxy.

* When an IB itself is destroyed or cleared, if it used an IOProxy,
  also invalidate the IC entry for that file.

* Unrelated cleanup: avoid a redundant invalidate call in init_spec().
2022-11-14 19:20:11 -08:00
Larry Gritz 04fc83edeb OpenColorIO 2.2 support -- preliminaries (#3662)
* Make it so that when we build against OCIO 2.2, it is possible to
  specify the built-in configs. The logic had previously precluded
  this, because at one point it checks to see if the passed config or
  contents of env $OCIO was an existing file. Now you can set OCIO to
  "ocio://default", for example, and it will be used by OIIO.

* Expose getAliases (I think that has been there for a while but we
  didn't expose in in our ColorConfig wrapper).

* Expose isColorSpaceLinear (new to OCIO 2.2)

* New OIIO global getattribute query: "opencolorio_version" returns the
  human-readable version string (such as "2.2.0").

* Some miscellaneous other cleanup in color_ocio.cpp

* Change in color methodology for test suite: Previously, for every
  call to oiiotool in the testsuite, we passed a `--colorconfig`
  argument to oiiotool pointing it to the sample colorconfig that we
  ship in the testsuite. Here, I'm changing it so that the cmake setup
  for tests sets the OCIO env variable for all tests, so no explicit
  --colorconfig is necessary, and thus you won't see a path to the
  config in any of the test output files if they need to echo the
  command line arguments (and you'll see several test outputs altered
  in this way). This is a prelude to later changes that will use the
  built-in configs themselves for tests, when available.

More interesting changes coming in subsequent PRs.
2022-11-14 19:19:40 -08:00
Larry Gritz c31b10007b CI: No longer add the ppa:ubuntu-toolchain-r/test repository (#3671)
Lately, it has been experiencing intermittent availability problems
that causes our CI to fail while setting up dependencies.

What happens if we don't use the problematic ubuntu-toolchain-r at all?

Nothing, it seems. So eliminate it.

I think that once upon a time, it was necessary to add this repo to
get certain new packages? But maybe they are mainstream enough now
that it's not necessary to add this repo? In any case, it doesn't seem
to hurt anything, it's one less moving part that can't fail if it's
not there.
2022-11-14 14:09:44 -08:00
Larry Gritz 30ea4ebdfa Expose OIIO::Strutil::print in the main OIIO namespace (#3667)
We use this all the time in our internals, and I'm tired of having to
write Strutil::print. Too verbose. By putting it in the main OIIO
namespace, OIIO internals can reference as simply print(), and
external users now have a choice of saying Strutil::print() or
OIIO::print().
2022-11-14 08:00:37 -08:00
Larry Gritz 72bc675885 IOMemReader ctr should take const buffer pointer (#3665)
The ctr is inline, so I don't think it breaks backwards link
compatibility to make this change, so I do intend to backport it.
2022-11-14 08:00:07 -08:00
Larry Gritz 6da2b6ef48 Fix type mismatch warning in JPEG code (#3664)
Fixes #3663
2022-11-12 08:33:42 -08:00
Larry Gritz d9f326f18e ociodisplay gets an inverse control (#3650)
Fixes #3648
2022-11-09 22:13:31 -08:00
Larry Gritz 1278f60e7a CMake: Adjust how version overrides work (#3653)
Kai Pastor (dg0yt) made an important observation that the way I
recently made OpenImageIO_VERSION be a cache variable might lead to
unexpeted behavior by inadvertently retaining a version number upon
recompiles if the cache itself was not cleared, and this can happen
unexpectedly even when the user isn't trying to override the version.

This patch changs the behavior as follows:

You must use the special `-DOpenImageIO_VERSION_OVERRIDE=...` to
override the version.

  * if you do so, you are playing with fire and get what you deserve
    if you misuse it or change branches and don't remember to clear
    the cache.

If you do a normal build (without _trying_ to override the version),

  * you will get the real version number because it IS NOT cached
  * if you switch branches, you'll always get the right version number
  * ...but switching branches without clearing the cache can still, as
    always, have other subtle behavior differences versus doing a
    truly fresh build from scratch.

So in short, it still allows a way to override the version if you
really want to, but if you are not trying to do that, you can no
longer get yourself inadvertently into unexpected trouble.
2022-11-09 22:12:49 -08:00
Larry Gritz e03b7b38b4 Testing; Imagecache better testing coverage and some stats improvements (#3654)
* testtex: better control over temp file creation

* Additional texture tests to improve coverage of udim generation,
  and deadling with cache limits.

* Better ImageCache unit tests for perthread create/destroy and
  individual tile retrieval. Fix a bug in get_tile for nonexistant
  subimage or miplevel.

* Dead code removal: ImageCacheFile::udim_to_concrete() and
  find_file_no_add(), which were no longer called anywhere.

* IC stats: fix messed up 'slowest' list ordering when there are broken files

* IC stats: when stats level is high, enable printing of some stats that
  we previously skipped over when they were "uninteresting" (e.g., too
  little time spent on something, no problematic files, etc).

* IC testing: test a variety of get_pixels error conditions

* IC testing: more tests of IC::imagespec() and get_imagespec(), incluing
  error conditions.

* More get_texture_info query testing

* Minor bug fix for int-to-float data conversion in get_image_info

* Test IC query for resolution[3]

* Test IC::reset_stats()

* Fix ImageCache::reset_stats in cases where threads ended
2022-11-06 14:16:11 -08:00
Larry Gritz 8b8952d964 Additional Strutil tests (#3655)
Better coverage of edge cases for escape_chars/unescape_chars, stoi
hex conversion, strtod, stod, freestanding c_str(), parse_nested
failure cases, base64_encode, debug.
2022-11-06 11:45:53 -08:00
Larry Gritz 989bf367ec IOProxy support for IFF files (#3647) 2022-11-04 20:00:56 -07:00
Larry Gritz ab93bfa6c0 Filesystem::is_executable and find_program (#3638)
Also cull some cruft that no longer is used for OIIO >= 2.4
2022-11-04 20:00:41 -07:00
Larry Gritz 404015ef26 Fix ColorConfig::getColorSpaceDataType null ptr deref when no OCIO config is found (#3652) 2022-11-04 20:00:16 -07:00
Larry Gritz efd27a9dfb CMake: use of ${PROJECT_NAME} must be after call to project() (#3651) 2022-11-04 16:43:30 -07:00
Larry Gritz 78aaf34d3a oiiotool testing and minor subimage/miplevel fixes (#3649)
* Add casual tests of oiiotool with no args (print brief usage message)
  and when an unknown command.

* Also changed the meaning of -q (quiet mode) to be more quiet -- in
  particular, not to print the full help message for errors when quiet
  mode is used, only print the error.

* oiiotool test sequence errors.

* Test (and fix) --selectmip and --subimage with out of range indices
2022-11-02 21:52:29 -07:00
Larry Gritz f099e19d94 RLA IOProxy support (#3642)
Also take the opportunity to do some std::format style conversion.
2022-11-01 22:01:58 -07:00
Larry Gritz 7d53464069 CI: Test against OpenColorIO 2.2 (#3644) 2022-11-01 22:01:09 -07:00
Larry Gritz 9c706409f1 IOProxy support for SGI files and fix important bug (#3641)
Add IOProxy support.
Fixes #3623

Along the way, noticed an important bug at line 209 of this change --
the header "imagename" field should be fully zeroed out even if there
is no ImageDescription metadata!
2022-11-01 18:31:48 -07:00
Larry Gritz 88152a6a10 CI: adjust when workflows are run to cut needless CI runs (#3645)
Changes:

* Scorecards and analysis -- allow newly launched job to cancel
  running old job from the same PR.

* Scorecard only runs on main repo, no need to run on forks.

* Nightly CI only runs on main repo, no need to run on forks.
2022-11-01 08:49:11 -07:00
Larry Gritz 1beeb27dae Analysis: more test related fixes to try to increase code coverage (#3643)
* Test oiiotool control flow syntax mistakes
* Test oiiotool --set with array of strings
* oiiotool: better adjust_geometry unit testing

Helper utility additions:

* oiiotool --no-error-exit

  `--no-error-exit` causes an error to not exit immediately, but
  rather to try its best to continue execuing command line
  operations. Use with caution! This is mainly for unit tests and
  debugging.

  `--unittest` also turns this on automatically, so that tests that
  are probing failures don't cause an exit.

* unittest.h: If OIIO_UNIT_TEST_QUIET_SUCCESS is defined, don't print
  anything extra for unit test success
2022-11-01 08:48:49 -07:00
Larry Gritz 52846a5253 Squash some alignment problems caught by ubsan (#3646) 2022-11-01 07:21:26 -07:00
Larry Gritz 76610138e9 oiiotool: --printinfo improvements to fix mem vs file ambiguities (#3639)
It surprised me a little to realize that --printinfo prints the
current spec of the top image (I mean, duh), but that may not match
what you'd get with `oiiotool -info -v`, which prints the data about
each file as it's read from disk, inasmuch as the "current" spec
reflects the in-memory representation. So, for example, it might say
the image is float, because oiiotool tends to store everything
in-memory as float, rather than uint8 of the disk file.

So these changes help fix this oddity and other ambiguities I realized
follow:

* Give --printinfo an optional modifier `:native=1` that will print
  the native (from the original file) info, if that's what you need,
  rather than the up-to-the-moment in-memory data.

* Also add --printinfo optional modifiers `:verbose=` and `:stats=`.

* Expression substitution gets some new names it knows: "nativeformat"
  is the data type in the file, versus "format" which I now see would
  return the in-memory version; METANATIVE and METANDATIVEBRIEF, which
  are the native versions of META and METABRIEF.
2022-10-31 21:46:03 -07:00
Larry Gritz ab694d0322 maketexture: Ensure proper setting of some metadata (#3634)
Make extra sure to clear the oiio:ConstantColor, oiio:AverageColor,
and oio:SHA-1 metadata when writing textures, if those things are not
going to be set.
2022-10-31 21:45:34 -07:00
Larry Gritz 0674f8de7b Refactor font searching and add font getattribute queries (#3633)
* Add OIIO::getattribute() queries for "font_list", "font_file_list",
  and "font_dir_list", which are, respectively, the lists of fonts
  that were found, the list of font files (full paths), and the list
  of directories it searched.  All return a single string that is a
  semicolon-separated list of the items.

* As a consequence of the new attributes, if you are curious to see
  the full inventory of fonts it can find, you can just query the
  attribute:

      oiiotool --echo "{getattribute(font_list)}"

* Some refactoring of the font inventory process (in
  imagebufalgo_draw.cpp) was necessary to achieve this.

* We now search for ".ttc" (TrueType collection) files, which we didn't
  notice before.

* We now search explicitly in share/fonts/OpenImageIO, which we
  neglected to do before, but found those fonts because we searched
  /share/fonts recursively.  In exchange, we now do not search the
  directories recursively, because that seems unwise for performance
  reasons.

* We pass the full testsuite, but it's possible that this
  change may fail to find fonts that were previously found because of
  the recusion. If that is the case, you should fix it by explicitly
  adding the deep directories with fonts to the search path specified
  in the environment variable `$OPENIMAGEIO_FONTS`.
2022-10-31 21:45:19 -07:00
Larry Gritz 53d2e5db1d Analysis: Add tests to improve code coverage of oiiotool (#3637)
* Unit test adjust_geometry
* Tests of --set for various implicit and explicit types not
  previously covered in the testsuite
* Comment out Oiiotool:get_position, which seems to be unused
* Exercise --iconfig for explicit types
* Add test for --origin and --originoffset
* Add test for --ociodisplay
* Add test for --unmip and --selectmip
2022-10-30 12:47:08 -07:00
Larry Gritz af4b6f1da6 Strutil: trimmed_whitespace (#3636)
It's similar to trim_whitespace, but returns the trimmed result, rather
than operating in-place on a `string_view&`.

Also add unit testing of trim_whitespace and trimmed_whitespace
2022-10-29 10:24:45 -07:00
Larry Gritz c5ef0f2e50 Strutil read_text_from_command, and limit size of read_text_file (#3635)
* Add an optional size parameter to read_text_file to limit the
  maximum size that will be allocated and read (default to a limit of
  16MB).

* New read_text_from_command, similar use to read_text_file, but reads
  from the console output of a shell command.
2022-10-29 10:24:26 -07:00
Larry Gritz 78441fa29a TIFF: guard against buffer overflow for certain CMYK files (#3632) 2022-10-23 19:11:41 -07:00
Larry Gritz 92db3f5d35 PSD: protect against corrupted embedded thumbnails (#3629) 2022-10-23 13:08:23 -07:00
Larry Gritz acfb6a9e28 TIFF: guard against corrupt files with buffer overflows (#3628)
Along the way, improve the runtest.py script by giving the
info_command() fuction the same silent, concat, and failureok
parameters that the oiiotool() function has. (This lets individual
tests assemble iinfo command lines with a little more flexibility.)
2022-10-23 13:08:12 -07:00
Larry Gritz e44400feac DDS: fix crashes and add tests (#3625)
* In the case of DDS cubemap files where a cube face was not present,
  we were filling m_buf with 0 bytes before allocating it.

* Add check for invalid bits per pixel.

* Add regression test for another bug that was perviously fixed in
  2.4.3.
2022-10-23 13:07:58 -07:00
Larry Gritz 884dfd6b7c Fix EXIF bugs where corrupted exif blocks could overrun memory (#3627)
In one case, we actually had a check for this, but an assignment to an
int made the nonsensical offset appear negative, and we only tested
whether the necessary offset it was bigger than the buffer size.
Keeping it as (unsigned) size_t makes the test work as intended.

In another case, there were several places where we never checked that
we were staying within the exif block, and here we address this by
changing the utility decode_ifd so instead of passing it a pointer to
the ifd, it passes the offset (the pointer turned out to always be
inside the buffer) so it can check the extent for subsequent accesses.

Also some fixes related to squashing undefined behavior sanitizer
cases.
2022-10-22 12:32:46 -07:00
Larry Gritz a37aa72f93 RLA: fix potential buffer overrun (#3624) 2022-10-22 12:32:21 -07:00
Larry Gritz 737b317394 Custom fmt formatter for ustringhash prints the string, not the hash (#3614)
Also, change `operator<<` to output the string, not the hash itself.
These changes help push us more toward the original intent of
ustringhash being a drop-in replacement for ustring, any time it's
more desirable to be using around the hashes rather than the pointers.
2022-10-22 09:02:15 -07:00
Larry Gritz 51705b7fba Improve oiiotool test coverage (#3626)
* oiiotool tests for expressions var() and getattribute()

* Make sure we test oiiotool IMG[] expressions and several specific
  special attributes to retrieve.

* Add coverage of oiiotool --keyword and --clear-keywords
2022-10-22 09:01:30 -07:00
Larry Gritz 19121dc4f0 Targa: String overflow safety (#3622)
Added utility functions safe_string_view and safe_string to strutil.h.
2022-10-21 08:15:40 -07:00
Larry Gritz 5fa8d996bd BMP: protect against corrupt pixel coordinates (#3620)
When reading the image (which can have signals to jump around in the
array), we checked for out-of-bounds x coordinate, but not y, and some
corrupted files could overrun buffers as a result.
2022-10-21 08:15:28 -07:00
Larry Gritz f6b2a13473 CI: eliminate xxhash and farmhash code from coverage analysis (#3621)
Because we're not the originators of the code and we use only a tiny
subset of what's in those files.
2022-10-21 00:17:42 -07:00
Larry Gritz 1196815fd1 oiiotool: New metadata expression syntax (#3619)
The existing syntax `TOP.name`, if the name wasn't found, produced
an error.

This PR adds another syntax: `TOP[name]` which is identical if the
named metadata is found. But if not found, this syntax just evaluates
to the empty string, with no error.
2022-10-21 00:10:25 -07:00
Aras Pranckevičius 3a9d3faab5 Docs: write Windows build instructions (#3602)
I recently wrote down how to build OIIO from source for myself (https://gist.github.com/aras-p/6497703c9b52f67761e6191343e43f7b), and maybe a slightly cleaned up version would be good to put into actual docs.
2022-10-20 08:20:33 -07:00
Larry Gritz 4be5ca093d Fix missing getattribute of limits:channels and limits:imagesize_MB (#3617)
I think it was just inadvertently left out when these were first added.
2022-10-20 08:20:00 -07:00
Larry Gritz c51349a0d6 Testing: optimize oiiotool-control test (#3618)
This test was taking almost 30 seconds to run, without a lot of images
being read or written. Turns out it was just a large number of separte
oiiotool invocations, and the overhead of all those shells and
programs launched adds up. Most of them were just firing up oiiotool
for the sake of doing an `--echo` to print things. A little bit of
restructuring to make fewer oiiotool invocations (each one doing a
bunch of echo commands, each testing a different thing) cuts the time
for the whole test by 50%.

I also made the runtest.py script allow certain test debugging by
letting a test set the `wrapper_cmd`, and if so, will prepend every
oiio utility launch with it. For example, a test could say
`wrapper_cmd='time'` to time every command.
2022-10-20 08:19:31 -07:00
Larry Gritz 90dfdb1720 oiiotool: Add unit tests, minor internals utility refactoring (#3616)
Add a hidden --unittest command to oiiotool, only functional for Debug
builds, which enables additional testing of internal utility funcions
and other things that are difficult to fully exercise in the testsuite
from normal oiiotool commands (could be done, but would take tons of
additional tests to get into particular deep edge cases).

Prototype by adding unit tests for scan_box. More will be added later
now that the mechanism exists.

Simplify string_to_dataformat

Make sure to use --list-formats and --runstats during testing.
2022-10-19 09:29:14 -07:00
Larry Gritz 71b4cffcaa Testing: eliminate redundant code in Python IBA bindings (#3615)
Also add a test for sub(imagebuf,tuple) that we didn't have before.
2022-10-19 07:43:23 -07:00
Larry Gritz 7f28d3f3f1 Ensure that ustring hashes are 64 bits (#3606)
ustring::hash() and the representation of ustringhash were size_t,
which might be 32 bits on some platforms. But we really would prefer
ustrings hash to 64 bits, to greatly reduce the chance of hash
collisions.

* Add strhash64() which is like strhash() but guaranteed to be a 64
  bit value (returning uint64_t instead of size_t -- though note that
  these are the same on 64 bit CPUs).

* ustring::hash() and ustringhash::rep_t are now uint64_t.

* Note that std::hash(ustring) and std::hash(ustringhash) are still
  size_t, per the C++ definition of std::hash. So ustring::hash() may
  have more bits than std::hash(ustring) on 32 bit platforms.

This will NOT be backported to the release branch, since it changes
ABI on 32 bit platforms.
2022-10-18 16:04:52 -07:00
Larry Gritz 2e663455ee Add a test that forces stats to be computed (#3612)
Increases code coverage for dynamic analysis and coverage metrics.
2022-10-18 00:26:16 -07:00
Larry Gritz a7d0346cb0 Testing: testsuite/iinfo -- make it compute stats, use MIPmaps (#3613)
Better coverage of the functionality of iinfo
2022-10-18 00:25:58 -07:00
Larry Gritz c5cd76a395 Testing: update cineon test image 2022-10-17 11:04:12 -07:00
Larry Gritz 575fcb3c13 Fix exr core test options (#3610) 2022-10-17 00:20:53 -07:00
Larry Gritz c653ab0052 CI: Sonar analysis should exclude stb_sprintf.h (#3609)
It's not really "our code", and we use very little of that file, so
it's not helpful to include it in coverage or other analysis.
2022-10-16 22:32:14 -07:00
Larry Gritz 5532d49387 Testing: make a test specifically for iinfo (#3605)
Believe it or not, iinfo was never run in the testsuite before this!
2022-10-16 21:37:31 -07:00
Larry Gritz 1875a9b884 Test fixes (#3608)
* We mis-named color_test, and that caused it to never get run!

* imagespeed_test is meant for benchmarking only, run by hand.
  We don't make a testsuite test, so don't even build the source
  (which would never be counted for code coverage because it doesn't
  run) during CI.
2022-10-16 20:58:20 -07:00
Larry Gritz a432a35e34 Improve cineon build and test (#3607)
* Add a test for cineon -- we never directly tested it before

* Don't compile code used only for writing. We don't supporting
  writing cineon, so there is no point compiling the cineon module
  used only for writing.

* And of course, once cineon was in the testsuite, we immediately
  found a problem via the sanitizers! So fix buffer overflows when
  reading FilmEdgeCode in Cineon.  (And clean up the equally sloppy,
  though not technically buggy, code in DPX as well.)
2022-10-16 19:26:50 -07:00
Larry Gritz 7a510254c6 Testing: test both openexr old and core versions (#3604)
On any one platform, our testsuite was only testing the old C++ and
the new C core exr implementations.

Rig it to run the openexr-oriented tests twice -- once in each state
(when using OpenEXR new enough to support the core library).

Doing this cleanly required adding SUFFIX and ENVIRONMENT optional
parameters to the oiio_add_tests utility macro. Once that was added,
the texture batch testing could be implemented that way as well,
removing a bunch of hackier special purpose code.
2022-10-16 19:21:36 -07:00
Larry Gritz e471c7ea49 Static analysis related fixes (#3603)
* Protect against 0-sized allocation
* Exception safety in IffOutput destructor
* Using sonar.coverage.exclusions as a better way to exclude files
  from coverage analysis
* Null pointer safety
2022-10-15 18:13:28 -07:00
Aras Pranckevičius 5320f79968 SIMD: extend NEON implementation coverage, and include neon in oiio_simd_caps (#3599)
* Use hardware float<->half conversion (similar to F16C on Intel)
* Use hardware sqrt
* Use horizontal adds in more places ("reduce_add")
* Equivalents of _mm_movemask_ps for NEON in vbool4
* Other smaller bits & bobs

Testing on Apple M1 Max, Release build, notable simd_test Mvals/sec
changes:

vfloat4
* load from half[]: 2457 -> 5890
* store to half[]: 1041 -> 6074
* simd sqrt: 2151 -> 6075

vfloat8
* load from half[]: 2433 -> 10367
* store to half[]: 1235 -> 11192
* reduce_add: 7377 -> 11971

vfloat16
* load from half[]: 2672 -> 14505
* store to half[]: 1322 -> 12558
* reduce_add: 7123 -> 11858
* operator<:  3345 -> 7500 (similar with other compare ops)

vint4
* blend: 4403 -> 5007
* blend0: 5187 -> 6076
* rotl: 1775 -> 2932

vint8
* load from int[]: 9415 -> 12152

vint16
* operator<<: 4656 -> 5865 (similar for >>, srl)
* rotl : 4042 -> 5137

vbool4
* reduce_and: 875 -> 1361
* reduce_or: 985 -> 1373
2022-10-12 17:35:27 -07:00
Larry Gritz bbd48ca172 ustring hashing improvements (#3577)
I realized that the recently added ustringhash class is confusingly
similar to the (obscure, barely used, mostly forgotten) ustringHash
functor. But also ustringHash doesn't need to exist, because it's
equivalent to `std::hash<ustring>`, if we define it. So now we do define
it, and also `std::hash<ustringhash>`, and deprecate ustringHash, to
be removed entirely for 3.0.

Also, add a ustring ctr from ustringhash (explicit only for now),
and `operator<` for ustringhash.

And add from_hash(size_t) method to ustringhash, analogous to
ustring::from_hash().

Modernize a few places we still used `(void)` to just `()`.

Give ustring and ustringhash a `using rep_t =`
rep_t is the type of the underlying representation (const char* for
ustring, size_t for ustringhash).

Modernize some typedef into using.

Make `==` and `!=(ustringhash, const char*)` be constexpr for C++ >= 17
2022-10-12 11:31:02 -07:00
Aras Pranckevičius c721423cdd Windows: stop including <windows.h> from public OIIO headers (#3597)
Including windows.h leads to a lot of possibly common names being
"taken", mostly by preprocessor defines. Some of these are possible
to turn off (like "max" and "min" by defining "NOMINMAX" before
including <windows.h>). But many others are not possible to turn off,
e.g. "near" and "far" just get defined to nothing, preventing from using
variables named like that.

Additionally, includes have a cost, and while <windows.h>, being a C
header does not have expensive language constructs that would slow down
compilation a lot, it's still something close to 100k lines of
preprocessed code to wade through.

Now, only the OIIO implementation .cpp files that actually need
<windows.h> include it (all of them under "libutil").

There were two exceptions:
1) thread.h pause() implementation uses YieldProcessor() macro when on
  a Windows system. Replaced it with manually "re-implemented"
  things that YieldProcessor expands to. Right now made the
  implementation for all 4 platforms that Windows normally supports
  (x64, x86, arm, arm64); the latter two OIIO does not support though
  when on Windows so it's untested.
2) timer.h Timer::now() inline function used QueryPerformanceCounter
  and LARGE_INTEGER. These are quite hard to somehow "forward-declare"
  or similar, without resulting in duplicate type definitions. So on
  Windows I moved the now() function to be non-inline.
2022-10-12 11:28:51 -07:00
Aras Pranckevičius babbd98081 Windows: fewer windows.h includes from platform.h (#3596)
In particular, defining NOGDI before including <windows.h> achieves
several things amongh others:
- No longer causes ERROR symbol to be defined to 0. ERROR being defined
  prevents using e.g. google/glog library, since it wants ERROR to mean
  something else.
- No longer defines some possibly widely used names e.g. GetObject.
2022-10-11 07:59:19 -07:00
Aras Pranckevičius afaaf6d10d BMP: fix reading 16bpp images (#2808) (#3592)
16 bit per pixel (e.g. 555, 565, 444) formats probably have never
worked. One part of the code was assuming 5 bits in the mask, another
was shifting by 4 bits, and the 16-bit pixel fetch code was reading just
one byte.
2022-10-07 20:55:16 -07:00
jreichel-nvidiaandJoachim Reichel 3e3fba67c0 Fix PSD import on ARM. (#3589)
The code assumes "char" is "signed char" (as on x86), but on ARM "char" is
"unsigned char".

Co-authored-by: Joachim Reichel <joachim.reichel@posteo.de>
2022-10-07 12:26:48 -07:00
Aras Pranckevičius f60205ab50 oiiotool: work around static destruction order issue (#3295) (#3591)
In some cases (at least on Windows, with static linking) the oiiotool
main returns zero, but the full process returns 3 error code due to
abort() being called. And that is called because a global shared
image cache is already destroyed, but the image references from another
global (Oiiotool itself) try to use it, get a call into a "pure virtual
function" stub that is put by MSVC C runtime into a destroyed object
vtable, and that ends up in an abort().

Work around that by making sure various member variables holding
ImageRecRef are cleared before main() finishes and global destructors
are called.
2022-10-07 12:15:23 -07:00
Aras Pranckevičius 4a4f50eda8 HDR: speed up reading by around 4x (#3590)
Most of the cost in HDR file reading was converting from RGBE to floats,
inside ldexpf(), which at least on Windows/VS2022 spends most of the
time inside _ctrlfp(). But we only have 256 possible exponents in total,
so just use a precomputed table.

On my PC (Windows 10, VS2022, Ryzen 5950X) this change gets file read
time for an 8x resolution .HDR image from 1.10s down to 0.27s
2022-10-07 09:08:00 -07:00
Aras Pranckevičius a285a5d1ed HDR: fix read performance regression (#3585) (#3588)
HDR code overhaul to support IOProxy (#3218) changed all reads into
a `pread()` with explicit file position tracking. Turns out, that is
quite a larger overhead compared to simple sequential reads; even more
so on Windows.

On my PC (Windows 10, VS2022, Ryzen 5950X) this change gets file read
time for an 8x resolution .HDR image (with RLE compression) from
8.28s back to 1.10s just like it was in OIIO 2.3.

On Windows the extra cost when using pread() is a bit more extra mutex
locks, but the real cost is in enventual ReadFile; looks like any seek
operations make it take some sort of "way slower" path with various
callbacks and whatnot inside the kernel.

---

Note repoduced from discussion #3588 from LG: 

Switching from IOProxy::pread to using IOProxy::seek + IOProxy::read makes the IOProxy stateful and not thread-safe without an external lock (which this HdrInput has, so it's not going to break anything), precluding any future removal of the locks from read_native_scanline to make the whole ImageInput able to read concurrently. That's probably not important for this file format, but for others (especially crucial those usable as texture), it would be desirable to rely on those stateless pread calls and remove the lock from the ImageInput.

I think this patch is fine. We don't expect a lot of concurrent reads from hdr like we do for tiff and openexr that we use extensively for highly threaded on-demand reading of texture. It fixes the recent performance regression, and it doesn't really cost us concurrency because we already had the lock in HdrInput. But in general, we want to prefer eschewing read/seek and using pread instead, so we can expect maximum concurrency from multiple threads using an ImageInput (as we do in ImageCache/TextureSystem).

So I believe that a revised and more complete diagnosis is that the problem isn't the pread vs read per se, but that for RLE-compressed images we were calling pread separately for every 4 bytes! The calls to read are faster simply because they are buffered (in FILE) and require fewer OS system calls. But the real sin is that we call it way too many times.

I think that the rle case could go back to pread if we want, but do just one pread per scanline (rather than one per pixel value run), asking for the maximum amount that will be needed to read the scanline for the worst case rle representation (it's ok if it's the end of the file, pread will just read up to the end and return the true number of bytes read). In other words, we'd be doing the buffering ourselves.

But anyway, the real misdesign of this HDR reader is ancient, and consists of doing many many tiny reads. Even the buffered fread would be sped up a lot by not doing it separately for every 2-4 bytes of the file. I don't know if it's worth fixing for this format. Depends on whether anybody really needs to maximize its performance or expects multiple threads reading the same hdr file to be fully concurrent.
2022-10-07 09:07:28 -07:00
Larry Gritz 3c32812296 CI/build: build_libtiff.bash should be sure to build shared library (#3586)
Something changed in libtiff master and it doesn't build shared libs
by default, breaking our "bleeding edge" CI test. So when we build it,
be sure to ask for it. It can be overridden in build_libtiff by
invoking it with env variable `LIBTIFF_BUILD_SHARED_LIBS=OFF`.
2022-10-06 13:39:26 -07:00
Larry Gritz b89fa9d0d6 DDS: honor ImageInput thread policy (#3584) 2022-10-05 23:57:14 -07:00
Aras Pranckevičius 60800746bf DDS: optimize loading of compressed images (3-5x) (#3583)
Comparing the time it takes to load DXT/BCn compressed DDS images via
OIIO, I noticed that it's several times slower than in another codebase
(Blender). So I started profiling, and fixing some low hanging fruit.

- After decoding a BCn block (always 4x4 pixels), it was written into
  destination image using quite many branches in the innermost loop.
  Now it still takes care of not writing outside of a destination image
  that might not be multiple-of-4 in size, just with way fewer branches.
- BCn decompression is multi-threaded via parallel_for_chunked, using
  at least 8 block rows per job (i.e. 32 pixel rows). This is
  similar to internal multi-threading done by EXR or TIF readers.
- Avoid one case of std::vector resize (which clears memory) followed
  by immediate overwriting of that buffer with bytes read from the file.
  Switched to using unique_ptr for that array, similar to how other
  input plugins do it.

Performance data: I'm timing how long it takes to do "iinfo --hash" on
24 DDS files, each 4096x4096 in size. Quite a lot of time there is taken
by just the SHA hash calculation which is not related to loading, so
also have timing info for just DDSInput::read_native_scanline where
all the actual DDS loading/decoding happens.

Timings on PC (Windows 10, VS2022 Release build), AMD Ryzen 5950X.
- BC1: total 3.68s -> 2.76s, read_native_scanline 1.54s -> 0.59s
- BC3: total 3.74s -> 2.84s, read_native_scanline 1.83s -> 0.66s
- BC4: total 1.26s -> 0.82s, read_native_scanline 0.74s -> 0.24s
- BC5: total 2.29s -> 1.57s, read_native_scanline 1.31s -> 0.46s
- BC6: total 7.50s -> 4.30s, read_native_scanline 4.67s -> 1.60s
- BC7: total 6.18s -> 3.09s, read_native_scanline 4.34s -> 0.84s

Possible future optimization: implement DDSInput::read_native_scanlines,
that could avoid one extra temporary memory buffer copy. This extra
buffer clear & eventual copy from it into final user destination pixels
is non-trivial cost from profiling. But it's also quite involved
to handle all the possible edge cases (e.g. user requests scanlines
not on 4-pixel row boundaries); the code would have to do similar
juggling as EXR reader does to handle "not on chunk boundaries" reads.
It could potentially also interplay with DDS cubemap/volume texture
reading ("tiled") code paths, for which there is no test coverage at all
right now. Maybe for some other day.
2022-10-05 21:00:49 -07:00
Larry Gritz fe48013d04 oiiotool protect against OpenEXR thread deadlock on Windows (#3582)
Suggested by SideFX: explicitly shut down the OpenEXR thread pool
before exiting oiiotool, because sometimes on Windows it seems to hang
otherwise. A better solution is probably possible on the OpenEXR side,
but I don't know what it would be. (And in any case, we'd still need
to do this be be well behaved when using OpenEXR versions earlier than
where a fix might land.)

Solution tracked down by Edward Lam.
2022-10-05 16:05:48 -07:00
Aras Pranckevičius 4ee35351f1 DDS: alpha/luminance format fixes, add & enable more tests (#3581)
* DDS: fixes for A8, L8, A8L8 formats

While developing #3573 at one time I had them working properly, but then
while fixing the address sanitizer failure for 3-channel formats I
botched them again. Note to self: never again do a "yeah I'll add tests
later", since if I had all of them running all the time this would
not have happened. 🤦

* DDS: extend test coverage for more formats & channel size cases

With more test images recently added (https://github.com/OpenImageIO/oiio/pull/3459),
start using them for DDS tests. This covers now:
- Alpha, Luminance and Alpha+Luminance formats,
- RGB formats with rarer channel sizes (rgb10 a2, r3g3b2),
- Several "broken" DDS file cases
- Removed usage of sample-DXT1 since it is well covered by others.
2022-10-05 16:03:39 -07:00
Larry Gritz caf15b6b73 Remove incorrect OIIO_API from inline method declaration (#3578)
This was causing build issues on MinGW.
2022-10-04 17:02:09 -07:00
Larry Gritz e64b2cb425 Revise RELEASING to explain updating oiio-images branch (#3580) 2022-10-04 17:00:58 -07:00
Larry Gritz 33c0181843 Build/security: Try FORTIFY_SOURCE (#3575)
Add a new build-time cmake cache variable: FORTIFY_SOURCE

Default to empty, but can be set to 1, 2, or 3, corresponding to
setting the _FORTIFY_SOURCE macro available in recent versions of
clang and gcc. (I'm not sure exactly which minimum compiler version is
needed for each fortification level, except that for level 3, gcc must
be 12+.)

Fortification involves replacing several "unsafe" memory-related
functions such as memcpy, memset, strcpy, etc, with special versions
that do bounds checking, aided by some compiler smarts for
understanding the likely bounds of different buffers. If I understand
correctly, at level 2 it can figure out bounds of constant-sized
arrays, and at level 3 it can figure out certain dynamic cases as
well.

There are two use cases for this:

1. For our own CI, this is yet another bit of static and dynamic
anslysis to enable (currently, just in the gcc12 test) to possibly
catch bugs.

2. Users who are building OIIO to deploy it in security-sensitive
environment may wish to build with some fortification level enabled to
help prevent certain memory errors or security issues, understanding
that it may slightly impact performance.
2022-10-03 21:08:26 -07:00
Aras Pranckevičius 5dd9feeade DDS: various improvements (#3573)
- If a DDS pixel format header contains "this is a normal map" flag
  set, then handle that properly (#3525):
  - For a DXT5, this means it's a "DXT5nm" format. Normal X & Y
    components are in green and alpha channel respectively. Compute Z
    component from those, and the result is a 3-channel tangent space
    normal map.
  - For ATI2/BC5 format that also has a "normal map" flag set, compute
    the Z component automatically too, and result is a 3-channel image.
    However a bunch of ATI2/BC5 normal maps out there in the wild do
    not have that bit set, so also have a global "dds:bc5normal"
    attribute to optionally turn this on.
- Fix support of R10G10B10A2 format - was producing garbage data due to
  code assumption that truncation down to 8 bits never needs to happen.
- Fix bit expansion ("too dark") of very low-bit formats, e.g. R3G3B2.
  Code was simply shifting the bits, instead of properly repeating
  the high bits into new low bit positions (i.e. a 3-bit "111" needs
  to become an 8-bit "11111111" and not a "11100000").
- Support "RXGB" (DXT5, with red & alpha swapped) as well as "BC4U"
  and "BC5U" formats (the latter two are just BC4 and BC5, produced by
  some older tools).
- Support alpha-only (e.g. A8) formats.

All this mostly prompted by doing DDS improvements in Blender, and
wanting to get Cycles renderer (which uses OIIO) to the same feature
parity. See https://developer.blender.org/T101405 and
https://developer.blender.org/D16087.
2022-10-02 09:21:46 -07:00
Larry Gritz 490d51bc96 CI: improvements and minor refactoring (#3570)
* Refactor the clang-format job to be part of the aswf batch of jobs
  rather than separate (reduces redundant logic in the workflow file).
* Give proper names to distinguish the two Mac jobs' artifacts for
  broken builds and their caches.
* Revise scorecard workflow triggers: no need to run weekly, and run
  on push only to the main repo, no reason to run on forks.
2022-09-29 17:56:57 -07:00
Aras Pranckevičius 3ffb4ae7e8 Build: enable parallel compilation when using visual studio (#3571)
Cmake-generated visual studio project files were using just one CPU core for all the compilation, which is not terribly fast. Add the `/MP` option so that it compiles separate .cpp files in parallel. On my (16 core, 32 thread) machine this makes a Release build of OpenImageIO.lib go from 136 sec down to 30 sec.
2022-09-28 12:25:47 -07:00
Larry Gritz 53aa8a1674 Update one more ref image after recent raw change (#3572)
Also remove three raw test reference output files that we apparently
no longer use (corresponding to platform + libraw combinations that
aren't in our current set of CI configurations).
2022-09-28 12:25:34 -07:00
Larry Gritz 09d3464c9d Remove long deprecated/nonfunctional C API headers (#3567)
This was an experiment that was added to master at one point but
removed before we branched for a release. But we forgot to remove a
few headers. Removing them now is not a compatibility break, since we
never shipped a supported release that contained the library that
implemented the functions declared in these headers.
2022-09-27 14:38:37 -07:00
Larry Gritz fcc45717fa Use undefined behavior sanitizer (ubsan) as part of CI (#3565)
In addition to address and leak sanitizers, also turn on the undefined
behavior sanitizer in our CI run. We can do it in the same job as
asan/lsan.

Some things that come along for the ride, including fixes for things
that ubsan uncovered:

* src/build-scripts/ubsan-suppressions.txt can hold suppression list
  (though we don't have any now, it just sets up the space for it for
  future needs).

* Split the "targa" test so that the parts that directly need the OIIO
  python module (which are all related to thumbnails) are now in
  "targa-thumbnails" test. That has to be disabled for the sanitizers,
  since we can't arrange for python to b linked to the sanitizer
  libraries.

* Found vint4::store has a potentially unaligned integer store.

* Found Strutil::concat is not necessarily safe if either of the
  strings are empty.
2022-09-27 12:11:47 -07:00
Larry GritzandVincent Demoulinv 893eead5a8 Update ref output after recent raw change and clang-format (#3569)
This is an addendum to #3561 to fix reference output

Co-authored-by: Vincent Demoulinv <vincent.demoulin@technicolor.com>
2022-09-27 12:09:03 -07:00
demoulinvanddemoulinv 9c6c9192f1 Add color metadata from libraw. (#3561)
2 vectors, pre_mul and cam_mul.
2 matrices, cam_xyz[4][3] and rgb_cam[3][4], delivered as 1D tab.

Co-authored-by: demoulinv <vincent.demoulin@technicolor.com>
2022-09-27 11:14:25 -07:00
Larry Gritz 03ee387c05 Reinstate missing (obsolete) parallel_for_chunked_2D variant (#3566)
This was part of a set of obsolete calls where we recently removed the
implementations, but for link compatibility, made matching shim calls
and wrap the modern versions. But I missed one case.
2022-09-26 22:09:35 -07:00
Larry Gritz d5973882d8 Add RELEASING.md to document our release procedures (#3564)
Adapted from the similar document I wrote for OSL.

This serves both as a checklist for me to make sure I don't miss any
steps during a release, but also so that other people could take over
release procedures if necessary or desired.

I also rearranged the order of some lines in CMakeLists.txt for
clarity (but did not change the logic).
2022-09-26 11:07:18 -07:00
Larry Gritz ebea33b0c2 CHANGES and docs fixes 2022-09-24 11:36:45 -07:00
Larry Gritz b085899021 Update ref output after recent python chage 2022-09-24 11:36:45 -07:00
Larry Gritz 9c45ba9cf1 Changes to take care of new clang 15 warnings (#3563) 2022-09-22 22:56:41 -07:00
Larry Gritz 9b41418941 IC and TS getattributetype() (#3559)
ImageSpec and ParamValueList have had (since 2.1) a getattributetype()
method, which simply returns the TypeDesc of the named attribute, or
TypeUnknown if no such attribute exits. This goes along well with the
related getattribute() and attribute() family of methods.

The getattribute() method was not present in ImageCache and
TextureSystem, despite their having very similar
getattribute()/attribute() interfaces.

A recent issue made me realize that in the Python bindings, the IC and
TS bindings for `getattribute(name)` did not work properly, always
returning None, and *required* you to use the full
`getattribute(name,type)` variety where you have to supply -- and
already know -- the type. This isn't especially Pythonic, where you
should just be able to ask by name and get a polymorphic result. And
when I went to look at how to repair this, it was going to be very
awkward without getattributetype(), but trivial with it.

So this patch sets up getattributetype() for both IC and TS, and
exposes them to both C++ and Python APIs, and also fully fixes the
getattribute() so that it works properly with the name only.

Unfortunately, because getattributename is a new virtual method, it
changes the vtable, breaking the ABI, and thus cannot be backported to
any supported release that makes ABI compatibility promises.
2022-09-22 22:56:11 -07:00
Povilas Kanapickas b22260bd19 Fix build on iOS by not using std::system() (#3562)
iOS and similar Apple platforms only support executing single process
per app. Calling std::system() there fails at compile time.
2022-09-22 22:52:48 -07:00
Povilas Kanapickas d779a32814 Build: Fix cross-compiling on Android failing due to -latomic check (#3560)
Currently when cross-compiling for Android build fails due to usage of
TRY_RUN(). In the particular case it tries to figure out whether atomics
can be used without the libatomic library.

Fortunately we don't need this check because on Android NDK atomics are
built-in and libatomic.so is not present. Only static dummy libatomic.a
exists for compatibility with -latomic flag.
2022-09-19 18:02:42 -07:00
Larry Gritz 80374c0128 Python internals: support int8[] metadata and ICCProfile, refactor (#3556)
This patch allows ParamValue, ParamValueList, and ImageSpec to support
attribute/getattribute of metadata consisting of uint8[] arrays, which
is how we store certain binary blobs or raw byte arrays.  We translate
this to Python as a numpy array of type uint8 (dtype='B').

This fixes a limitation where it was not possible to directly retrieve
or set the "ICCProfile" metadata (which is stored as a uint8 array)
from the Python APIs, as you could easily do from the C++ APIs.

In the process, I found similar bits of code in several different
places, in various states of incompleteness. I refactored to make a
single make_pyobject() utility and then used that call in place of
several other redundant pieces of functionality.
2022-09-19 10:56:07 -07:00
Povilas Kanapickas 96f420b26d cmake: Find TBB dependency in Config.cmake.in when building static (#3557)
TBB::tbb is added as a library dependency via TARGET_NAME_IF_EXISTS.
Therefore if an executable links OpenImageIO static library without the
executable itself depending on TBB, then TBB will not be linked in and
result in link time errors.
2022-09-17 22:41:56 -07:00
Larry Gritz a2e7ec714f Python: add ability to getattribute of int64 and uint64 data (#3555)
Just a couple missing pieces were preventing getattribute() from
retrieving attributes that were stored as int64 or uint64. That
doesn't come up very often, but one place is retrieving certain
statistics that use 64 bit counters. (This comes up in ImageCache,
among other places.)

While we're at it, there was no existing test dedicated to the python
binding of ImageCache. So to add these getattribute calls, I made one.

There is an important caveat about ImageCache.getattribute(): In this
process, I discovered that the flavor of IC.getattribute(name) where
you only pass the name is BROKEN, and will always return None. You
MUST use the form where you pass the type, like

    x = ic.getattribute("foo", "int")

This is unfortunate and not very Pythonic, but it is the workaround
for now. I will addess getting the name-only form working in a
separate PR.

Closes #3537
2022-09-16 15:23:36 -07:00
Larry Gritz acbd1f3c9f Extract metadata from embedded ICC profiles. (#3554)
For a while, we have found embedded ICC profiles in TIFF, JPEG,
JPEG-2000, PNG, and PSD (PhotoShop) files and store them in the
metadata as a byte array with the name "ICCProfile".

With this patch, we further add the facility of parsing the binary ICC
profile data to extract a number of other fields that we add to the
ImageSpec metadata so that "oiiotool -info -v" or "iinfo 'v"
will print this info.

Important caveat: You can read this for informational purposes, but
changing it (e.g. with spec.attribute()) does not change the contents
of the ICCProfile byte array, which is still the canonical ground
truth of the profile. You have to replace the "ICCProfile" byte array
to actually change the profile.
2022-09-15 16:48:14 -07:00
Larry Gritz 9aeece7a53 Strutil utf conversion improvements (#3553)
* Add `Strutil::utf16_to_utf8(const std::u16string& utf16str)`.
  This is subtly different from our existing utf16_to_utf8() that
  takes a std::wstring, because wchar_t is not the same on all
  platforms.  If it really and truly is utf16-in-char16_t, you need
  this and can't use the utf-in-wchar_t which may be 32 bit chars.

* Add `Strutil::utf8_to_utf16wstring()` (identical to the old
  utr8_to_utf16) to make it more self-documenting as returning a
  utf16-encoded wstring and NOT a u16string. Note that wchar_t is not
  necessarily char16_t on all platforms (it is on Windows, but it's 32
  bits on Linux).

* Deprecate the ambiguously named `utf8_to_utf16()` for OIIO >= 2.5 and
  remove it for OIIO >= 3.0.
2022-09-13 21:46:45 -07:00
Povilas Kanapickas 71a329672e cmake: Add library dependencies in Config.cmake.in when building static (#3552)
This fixes builds in projects that compile OpenImageIO as static
libraries and don't themselves depend on the image libraries used by
OpenImageIO such as PNG, JPEG or TIFF.

When OpenImageIO is built as a static library its targets have e.g.
PNG::PNG among INTERFACE_LINK_LIBRARIES. If the including project does
not itself depend on PNG, the following error would be observed:

Target "<...>" links to target "PNG::PNG" but the target was not found.
Perhaps a find_package() call is missing for an IMPORTED target, or an
ALIAS target is missing?
2022-09-13 21:36:04 -07:00
Larry Gritz a22ed46940 Slight change to avoid gcc12 warning (#3551) 2022-09-13 13:38:36 -07:00
Larry Gritz 0d9f098dbb Build: Make the version number be a cmake cache variable (#3549)
Rather than specify the version in the usual project() statement,

    project (OpenImageIO VERSION 2.5.0.0 ...)

this patch decouples it

    set (OpenImageIO_VERSION "2.5.0.0" CACHE STRING "Version")
    project (OpenImageIO VERSION ${OpenImageIO_VERSION} ...)

thus allowing the possibility of overriding the version number at
build confuguration time (`cmake -DOpenImageIO_VERSION=3.1.4.1`).

This should be used with extreme caution. Probably never used by most
people. I don't need to describe all the ways that things can go
sideways if you make your build of x.y.z.w actually be arbitrarily
different from the x.y.z.w that everyone else uses and that is
documented.

That said, there are two scenarios I have in mind for which this
ability is very useful:

1. Sometimes, we add or deprecate API features "in advance" by having
   an `#if` enable or disable code based on the version, essentially
   putting in place changes that can't be enabled yet because they
   would break compatibility rules, but we want to integrate the code
   now and have it become active upon reaching a particular future
   version in which that incompatibility will be allowed. The version
   number override makes it easy to test this by quickly doing a build
   "as if" we had already bumped the version number to see what will
   happen when we actually do.

2. Every once in a while we need to do an internal build that, to
   conform to version compatibility rules, needs to appear to still be
   part of a past version family. This lets individual sites play some
   games with version number overrides rather than have to create new
   branches and tags for certain one-off internal releases.
2022-09-13 09:43:09 -07:00
Larry Gritz 0ff1bf34f9 oiiotool --iccread and --iccwrite (#3550)
--iccread reads a named file and directly adds its contents as the
"ICCProfile" metadata of the top image (as a byte array).

--iccwrite takes the "ICCProfile" metadata of the top image and
writes it to a named file.
2022-09-13 09:42:38 -07:00
Larry Gritz a028a11a0b CI: Re-enable sanitizer tests (#3545)
Oops, at some point, something about the way we set up the CI test
that runs the sanitizers, and ever since then (embarrassingly, perhaps
as much as a couple years ago), the "sanitizer" test has not in fact
been running the sanitizers. Here we fix that up, get sanitizers
running again.
2022-09-07 21:31:43 -07:00
Larry Gritz 99adfb43a8 PNG fixes (#3544)
* Minor png refactoring to fix some memory leaks for broken png files.

* Remove unused string variable from read_info() and simplify the
  surrounding "if"

* Split png test into png and png-damaged, because I just can't seem
  to squash some very minor memory leaks for broken png files, I think
  it's not worth worrying about and I'll just exclude the broken case
  from testing for the address sanitizer.
2022-09-07 13:08:45 -07:00
Johannes Unterguggenberger cd4ca3bae4 Fixes a warning from an unsuitable format specifier (#3540)
Changed the assert  to use format specifier %d and casting the size to an int.
2022-09-07 13:00:40 -07:00
Larry Gritz 73f958341e PNG: fix memory leak when error takes early exit (#3543)
Found by leak sanitizer.
2022-09-06 22:16:01 -07:00
Larry Gritz 23235c9851 Fix heap overflow in DDS input (#3542)
Reading uncompressed scanlines would copy 4 bytes from each pixel into
an int and then decode the bits, incrementing where it was reading
from by Bpp bytes each time.  But when Bpp == 3, the last pixel of
every row would therefore read an extra byte past the end of the heap
storage. Allocation padding would in practice keep it from crashing,
and that meaningless extra byte was not used in the decode because it
knew it only needed the first 3 of the integer. But found by address
sanitizer!
2022-09-06 22:15:13 -07:00
Larry Gritz c85b5d7768 Targa internals: fix incorrect unique_ptr declaration (#3541) 2022-09-05 21:29:39 -07:00
Larry Gritz c23cda28a5 This is now the branch that leads to 2.5 (#3539) 2022-09-01 12:19:20 -07:00
269 changed files with 8954 additions and 3786 deletions
+2 -1
View File
@@ -40,7 +40,7 @@ jobs:
fail-fast: false
matrix:
include:
- desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.1
- desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.2
nametag: static-analysis-sonar
os: ubuntu-latest
vfxyear: 2022
@@ -62,6 +62,7 @@ jobs:
CODECOV=1
CTEST_TEST_TIMEOUT=1200
OIIO_CMAKE_FLAGS="-DOIIO_TEX_IMPLEMENT_VARYINGREF=OFF"
OPENCOLORIO_VERSION=v2.2.0
runs-on: ${{ matrix.os }}
container:
+54 -16
View File
@@ -30,17 +30,18 @@ jobs:
fail-fast: false
matrix:
include:
- desc: gcc6/C++14 py2.7 boost1.66 exr2.3 ocio1.1
- desc: gcc6/C++14 py2.7 boost1.66 exr2.4 ocio1.1
nametag: linux-vfx2019
os: ubuntu-latest
container: aswf/ci-osl:2019
vfxyear: 2019
cxx_std: 14
openexr_ver: v2.4.3
python_ver: 2.7
simd: sse4.2
fmt_ver: 6.1.2
fmt_ver: 7.0.1
pybind11_ver: v2.4.2
setenvs: export PUGIXML_VERSION=v1.9
setenvs: export PUGIXML_VERSION=v1.9 CMAKE_VERSION=3.15.5
- desc: gcc6/C++14 py3.7 boost1.70 exr2.4 ocio1.1
nametag: linux-vfx2020
os: ubuntu-latest
@@ -95,7 +96,7 @@ jobs:
cxx_std: 17
python_ver: 3.9
simd: "avx2,f16c"
fmt_ver: 8.1.1
fmt_ver: 9.1.0
pybind11_ver: v2.8.1
- desc: icc/C++17 py3.9 boost1.76 exr3.1 ocio2.1 qt5.15
nametag: linux-vfx2022-icc
@@ -137,7 +138,7 @@ jobs:
OIIO_CMAKE_FLAGS="-DSANITIZE=address,undefined -DUSE_PYTHON=0"
CMAKE_BUILD_TYPE=Debug
CTEST_TEST_TIMEOUT=1200
CTEST_EXCLUSIONS="broken|cmake-consumer|png-damaged"
CTEST_EXCLUSIONS="broken|png-damaged"
- desc: gcc11/C++17 py3.10 boost1.80 exr3.1 ocio2.2
nametag: linux-vfx2023
os: ubuntu-latest
@@ -146,9 +147,9 @@ jobs:
cxx_std: 17
python_ver: "3.10"
simd: "avx2,f16c"
fmt_ver: 9.1.0
fmt_ver: 10.1.1
pybind11_ver: v2.10.0
- desc: oldest/hobbled gcc6.3/C++14 py2.7 boost-1.66 exr-2.3 no-sse no-ocio
- desc: oldest/hobbled gcc6.3/C++14 py2.7 boost-1.66 exr-2.4 no-sse no-ocio
# Oldest versions of the dependencies that we can muster, and various
# things disabled (no SSE, OCIO, or OpenCV, don't embed plugins).
nametag: linux-oldest
@@ -156,17 +157,18 @@ jobs:
container: aswf/ci-osl:2019
vfxyear: 2019
cxx_std: 14
fmt_ver: 6.1.2
openexr_ver: v2.3.0
fmt_ver: 7.0.1
openexr_ver: v2.4.0
pybind11_ver: v2.4.2
python_ver: 2.7
simd: 0
setenvs: export EMBEDPLUGINS=0
PTEX_VERSION=v2.3.1
CMAKE_VERSION=3.15.5
PTEX_VERSION=v2.3.2
WEBP_VERSION=v1.0.0
USE_JPEGTURBO=0
USE_OPENCOLORIO=0
USE_OPENCV=0
WEBP_VERSION=v1.0.0
depcmds: sudo rm -rf /usr/local/include/OpenEXR
# Test formatting. This test entry doesn't do a full build, it
@@ -184,6 +186,26 @@ jobs:
setenvs: export BUILDTARGET=clang-format
OIIO_CMAKE_FLAGS=-DUSE_PYTHON=0
# Test ABI stability. `abi_check` is the version or commit that we
# believe is the current standard against which we don't want to
# break the ABI. Basically, we will build that version as well as
# the current one, and compare the resulting libraries.
- desc: abi check
nametag: linux-vfx2023
os: ubuntu-latest
container: aswftesting/ci-osl:2023-clang15
vfxyear: 2023
cxx_std: 17
python_ver: "3.10"
simd: "avx2,f16c"
fmt_ver: 10.1.1
pybind11_ver: v2.10.0
skip_tests: 1
abi_check: v2.5.3.0-beta1
setenvs: export OIIO_CMAKE_FLAGS="-DOIIO_BUILD_TOOLS=0 -DOIIO_BUILD_TESTS=0 -DUSE_PYTHON=0"
USE_OPENCV=0 USE_FFMPEG=0 USE_PYTHON=0
CMAKE_BUILD_TYPE=RelWithDebInfo
runs-on: ${{ matrix.os }}
container:
image: ${{ matrix.container }}
@@ -196,6 +218,7 @@ jobs:
OPENEXR_VERSION: ${{matrix.openexr_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
ABI_CHECK: ${{matrix.abi_check}}
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
@@ -228,12 +251,30 @@ jobs:
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Check out ABI standard
if: matrix.abi_check != ''
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
ref: ${{matrix.abi_check}}
path: abi_standard
- name: Build ABI standard
if: matrix.abi_check != ''
run: |
mkdir -p abi_standard/build
pushd abi_standard
src/build-scripts/ci-build.bash
popd
- name: Check ABI
if: matrix.abi_check != ''
run: |
src/build-scripts/ci-abicheck.bash ./build abi_standard/build libOpenImageIO libOpenImageIO_Util
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: oiio-${{github.job}}-${{matrix.nametag}}
path: |
build/cmake-save
build/compat_reports
build/testsuite/*/*.*
!build/testsuite/oiio-images
!build/testsuite/openexr-images
@@ -261,7 +302,6 @@ jobs:
setenvs: export LIBRAW_VERSION=0.20.2
LIBTIFF_VERSION=v4.5.0
OPENCOLORIO_VERSION=v2.3.0
OPENIMAGEIO_OPTIONS="openexr:core=1"
OPENJPEG_VERSION=v2.4.0
PTEX_VERSION=v2.4.0
PUGIXML_VERSION=v1.13
@@ -282,7 +322,6 @@ jobs:
setenvs: export LIBRAW_VERSION=master
LIBTIFF_VERSION=master
OPENCOLORIO_VERSION=main
OPENIMAGEIO_OPTIONS="openexr:core=1"
OPENJPEG_VERSION=master
PTEX_VERSION=main
PUGIXML_VERSION=master
@@ -296,14 +335,13 @@ jobs:
cxx_compiler: clang++
cc_compiler: clang
cxx_std: 20
fmt_ver: 9.0.0
openexr_ver: v3.1.5
fmt_ver: 10.1.1
openexr_ver: v3.1.11
pybind11_ver: v2.9.2
python_ver: 3.8
simd: avx2,f16c
setenvs: export LLVM_VERSION=14.0.0
OPENCOLORIO_VERSION=v2.1.2
OPENIMAGEIO_OPTIONS="openexr:core=1"
USE_OPENVDB=0
# The installed OpenVDB has a TLS conflict with Python 3.8
- desc: debug gcc7/C++14, sse4.2, exr2.4
+2 -2
View File
@@ -14,7 +14,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- [ ] 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
- [ ] **(Awaiting scan from LF)** License scan completed and no issues found
- [X] License scan completed and no issues found
- [ ] 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)
@@ -36,7 +36,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- [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
- [ ] Filed ( create pull request against [foundation repo](https://github.com/AcademySoftwareFoundation/foundation) )
- [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 )
+648 -45
View File
@@ -1,5 +1,622 @@
Release 2.4.16.0 (1 Oct? 2023) -- compared to 2.4.15.0
-------------------------------------------------------
Release 2.5 (Fall 2023) -- compared to 2.4
-------------------------------------------------
Beta 1: 2023-09-04
### New minimum dependencies and compatibility changes:
* CMake: minimum needed to build OpenImageIO has been raised from 3.12 to
3.15. [#3924](https://github.com/OpenImageIO/oiio/pull/3924) (2.5.2.1)
* LibRaw: minimum has ben raised from 0.15 to 0.18.
[#3921](https://github.com/OpenImageIO/oiio/pull/3921) (2.5.2.1)
* The new OpenEXR minimum is 2.4 (raised from 2.3).
[#3928](https://github.com/OpenImageIO/oiio/pull/3928) (2.5.2.1)
* The new `fmt` library minimum is 7.0 (raised from 6.1)
[#3973](https://github.com/OpenImageIO/oiio/pull/3973) (2.5.3.0)
### ⛰️ New features and public API changes:
* TextureSystem color management: [#3761](https://github.com/OpenImageIO/oiio/pull/3761) (2.5.1.0)
- TextureOpt and TextureOptBatch have a new field, `colortransformid`,
which supplies an integer ID for a requested color space transformation
to be applied as texture tiles are read. The default value 0 means no
transformation because the texture is presumed to be in the working
color space (this is the old behavior, and most performant). Tiles from
the same texture file but using different color transformations are
allowed and will not interfere with each other in the cache.
- New `TextureSystem::get_colortransform_id(from, to)` maps from/to named
color spaces to a color transform ID that can be passed to texture
lookup calls.
- `ImageCache::get_image_handle` and `TextureSystem::get_texture_handle`
now take an optional `TextureOpt*` parameter that can supply additional
constraints (such as color transformation) that TS/IC implementations
may wish to split into separate handles. This is currently not used, but
is reserved so that the API doesn't need to be changed if we use it in
the future.
- texture.h defines symbol `OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE` that
can be tested for existence to know if the new fields are in the
TextureOpt structure.
* Extensive support for OpenColorIO 2.2 functionality and improved color
management:
- When building against OCIO 2.2, you can specify/use the new "built-in"
configs, including using `ocio://default`, which will automatically be
usd if no config is specified and the `$OCIO` variable is not set #3662
#3707 (2.5.0.0)
- OIIO tries to find and honor the common color space aliases
"scene_linear", "srgb", "lin_srgb", and "ACEScg". When building against
OCIO 2.2+, it will know which of any config's color spaces are
equivalent to these, even if they are named something totally different,
thanks to the magic of OCIO 2.2 built-in configs. For older OCIO (2.1 or
older), it is less robust and may have to make best guesses based on the
name of the color spaces it finds. #3707 (2.5.0.0)
- New ColorConfig methods: `getAliases()` #3662; `isColorSpaceLinear()`
#3662; `resolve(name)` turns any color space name, alias, role, or OIIO
name (like "sRGB") into a canonical color space name;
`equivalent(n1,n2)` returns true if it can tell that the two names
refer, ultimately, to equivalent color spaces #3707 (2.5.0.0)
- New `ImageSpec::set_colorspace()` method is a more thorough way to set
the color space data than simply setting the "oiio:ColorSpace" metadata
(though it also does that). #3734 (2.5.0.1)
- Improve OIIO's ability to guess which of the config's color space names
are aliases for common spaces such as srgb, lin_srgb, and acescg (quite
robustly if using OCIO >= 2.2, even for totally nonstandard names in the
config). #3755 (2.5.0.1)
- New `ColorConfig::getColorSpaceIndex()` looks up a color space index by
its name, alias, or role. #3758 (2.5.0.1)
* oiiotool new commands and features:
- New `--iccread` and `--iccwrite` add an ICC profile from an external
file to the metadata of an image, or extract the ICC profile metadata
and save it as a separate file. #3550 (2.5.0.0)
- New `--parallel-frames` parallelizes execution over a frame range rather
than over regions within each image operation. This should be used with
caution, as it will give incorrect results for an oiiotool command line
involving a frame range where the iterations have a data dependency on
each other and must be executed in order. But in cases where the order
of frame processing doesn't matter and there are many more frames in the
sequence than cores, you can get a substantial performance improvement
using this flag. [#3849](https://github.com/OpenImageIO/oiio/pull/3849) (2.5.2.0)
- New `--no-error-exit` causes an error to not exit immediately, but
rather to try to execute the remaining command line operations. This is
intended primarily for unit tests and debugging. #3643 (2.5.0.0)
- New `--colorconfiginfo` prints the full inventory of color management
information, including color space aliases, roles, and with improved
readability of output for larger configs. #3707 (2.5.0.0)
- The `--resize` command takes new optional `:from=`, `:to=`, and
`:edgeclamp=` modifiers to give more general and fine control over the
specific correspondence between display windows in the input image and
resized destination image (including allowing partial pixel offsets).
#3751 #3752 (2.5.0.1)
- New expression substitution additions:
- New syntax for retrieving metadata `{TOP[foo]}` is similar to the
existing `{TOP.foo}`, if there is no `foo` metadata found, the
former evaluates to an empty string, whereas the latter is an error.
#3619 (2.4.5/2.5.0.0)
- `{NIMAGES}` gives current stack depth
[#3822](https://github.com/OpenImageIO/oiio/pull/3822) (2.5.2.0)
- `{nativeformat}` is the pixel data format of the file, whereas the
existing `format` has always returned the data type used in memory.
Also, `METANATIVE` and `METANATIVEBRIEF` are the full metadata
keywords for native file metadata, comapred to the previously
existing `META` and `METABRIEF` which we now clarify reflect the
in-memory representation. #3639 (2.5.0.0)
- `--ociodisplay` now takes an optional `:inverse=1` modifier. #3650
(2.5.0.0)
- New `-otex` optional modifier `forcefloat=0` can improve memory use for
enormous texture conversion.
[#3829](https://github.com/OpenImageIO/oiio/pull/3829) (2.5.2.0)
- `--printinfo` now takes new optional modifiers: `:native=1` ensures
that the metadata printed is of the file, not changed by the way the
image is stored in memory (for example, it may have been converted to
a more convenient in-memory data type); `:verbose=1` prints verbose
stats even if `-v` is not used; `:stats=1` prints full pixel stats,
even if `--stats` is not used. #3639 (2.5.0.0)
- New `--normalize` mormalizes image that represent 3D vectors (i.e.,
divide by their length) textures. This is helpful for normal maps.
[#3945](https://github.com/OpenImageIO/oiio/pull/3945) (by Vlad (Kuzmin) Erium) (2.5.3.0)
* ImageBufAlgo additions:
- A new flavor of `ociodisplay()` now contains an inverse parameter.
#3650 (2.5.0.0)
- New `normalize()` normalizes image that represent 3D vectors (i.e.,
divide by their length) textures. This is helpful for normal maps.
[#3945](https://github.com/OpenImageIO/oiio/pull/3945) (by Vlad (Kuzmin)
Erium) [#3963](https://github.com/OpenImageIO/oiio/pull/3963) (2.5.3.0)
* ImageInput / ImageOutput
- New `ImageOutput::check_open()` method can be used by format writers
authors to centralize certain validity tests so they don't need to be
implemented separately for each file type. This is not meant to be
called by client application code, only by format writer authors. #3686
(2.5.0.0)
- Add an `ImageInput::valid_file(IOProxy)` overload
[#3826](https://github.com/OpenImageIO/oiio/pull/3826) (by Jesse Y)
(2.5.2.0) and implement its overloads for DDS, PSD, and WEBP
[#3831](https://github.com/OpenImageIO/oiio/pull/3831) (by Jesse Y)
(2.5.2.0)
- New `ImageOutput::check_open()` and `ImageInput::open_check()` can be
used by format reader/writer authors to centralize certain validity
tests so they don't need to be implemented separately for each file
type. This is not meant to be called by client application code, only by
format reader/writer authors.
[#3686](https://github.com/OpenImageIO/oiio/pull/3686) (2.5.0.0)
[#3967](https://github.com/OpenImageIO/oiio/pull/3967) (2.5.3.0)
- *ImageInput*: Add an ImageInput::valid_file(IOProxy) overload
[#3826](https://github.com/OpenImageIO/oiio/pull/3826) (by Jesse Y) (2.5.2.0)
- *ImageInput*: Implement valid_file(IOProxy) overloads for DDS, PSD, and
WEBP [#3831](https://github.com/OpenImageIO/oiio/pull/3831) (by Jesse
Y) (2.5.2.0)
* New top-level `namespace OIIO` functions:
- `OIIO::shutdown()` method [#3882](https://github.com/OpenImageIO/oiio/pull/3882) (by Ray Molenkamp)
- `OIIO::default_thread_pool_shutdown()` [#2382](https://github.com/OpenImageIO/oiio/pull/2382)
- `OIIO::print()` exposes `Strutil::print()` in the main OIIO namespace.
#3667 (2.4.6/2.5.0.0)
* OIIO::getattribute() new queries:
- `font_list`, `font_file_list`, `font_dir_list` return, respectively, the
list of fonts that OIIO found, the list of full paths to font files, and
the list of directories searched for fonts. All return a single string
that is a semicolon-separated list of the items. #3633 (2.5.0.0)
- `opencolorio_version` returns the human-readable (e.g. "2.2.0") version
of OpenColorIO that is being used. #3662 (2.5.0.0)
* IOProxy support for additional file formats: SGI #3641, RLA #3642, IFF #3647
(2.5.0.0), ICO input [#3919](https://github.com/OpenImageIO/oiio/pull/3919)
(by jasonbaumeister) (2.5.2.0)
* Remove long deprecated/nonfunctional C API headers [#3567](https://github.com/OpenImageIO/oiio/pull/3567)
### 🚀 Performance improvements:
- Fixed some ImageBuf and IBA internals to avoid unnecessary/redundant zeroing
out of newly allocated buffer memory. #3754 (2.5.0.1)
- *oiiotool*: `--parallel-frames` parallelizes execution over a frame
range rather than over regions within each image operation.
[#3849](https://github.com/OpenImageIO/oiio/pull/3849) (2.5.2.0)
- *psd*: Improve memory efficiency of PSD read
[#3807](https://github.com/OpenImageIO/oiio/pull/3807) (2.5.2.0)
- Improvements to performance and memory when making very large textures
[#3829](https://github.com/OpenImageIO/oiio/pull/3829) (2.5.2.0)
- OpenEXR: Change to using exr-core for reading by default [#3788](https://github.com/OpenImageIO/oiio/pull/3788)
- TextureSystem: Improve texture lookup performance by remove redundant
instructions from tile hash [#3898](https://github.com/OpenImageIO/oiio/pull/3898) (by Curtis Black) (2.5.2.0)
### 🐛 Fixes and feature enhancements:
* ImageInput: fix typo in debug output [#3956](https://github.com/OpenImageIO/oiio/pull/3956) (by Jesse Yurkovich)
* Python bindings:
- Add ability to `getattribute()` of int64 and uint64 data [#3555](https://github.com/OpenImageIO/oiio/pull/3555) (2.5.0.0)
- Fixed ability to add and retrieve `uint8[]` metadata, which on the
python side will be numpy arrays of type uint8 (dtype='B'). This is
important for being able to set and retrieve "ICCProfile" metadata.
#3556 (2.5.0.0)
- Eliminate redundant code in Python IBA bindings [#3615](https://github.com/OpenImageIO/oiio/pull/3615)
- Improve error messages for when passing incorrect python array sizes.
#3801 (2.5.1.0)
- Fix arithmetic overflow in oiio_bufinfo (Python interop) [#3931](https://github.com/OpenImageIO/oiio/pull/3931) (by Jesse Yurkovich) (2.5.2.0)
* ImageBuf improvements:
- Fixes to subtle bugs when ImageBuf is used with IOProxy. #3666
(2.4.6/2.5.0.0)
- Auto print uncaught ImageBuf errors. When an IB is destroyed, any errors
that were never retrieved via `geterror()` will be printed, to aid users
who would not notice the errors otherwise.
[#3949](https://github.com/OpenImageIO/oiio/pull/3949) (2.5.3.0)
* ImageBufAlgo improvements:
- IBAPrep should not zero out deep images when creating a new destination
image. #3724 (2.5.0.0/2.4.8.0)
- Improve error message for IBA::ocio functions [#3887](https://github.com/OpenImageIO/oiio/pull/3887)
- UTF-8 text rendering fixes [#3935](https://github.com/OpenImageIO/oiio/pull/3935)
(by Nicolas) (2.5.3.0)
* make_texture() / maketx / TextureSystem / ImageCache:
- Ensure proper setting of certain metadata when using a texture as a
source to build another texture. #3634 (2.4.5/2.5.0.0)
- Minor improvements in statistics printing for IC. #3654 (2.5.0.0)
- When creating a texture, don't overwrite an existing DateTime metadata
in the source file. #3692 (2.5.0.0)
- Fix environment mapping in batch mode when >4 channels are requested in
a lookup. #3694 (2.5.0.0)
- Fixed `maketx --lightprobe`, which never worked properly for images
that weren't `float` pixel data type. #3732 (2.5.0.0/2.4.7.0)
- Fix bad handling of `maketx --cdf`, which was trying to take an extra
command line argument that it didn't need. #3748 (2.5.0.1)
- Improve IC statistics appearance by omitting certain meaningless stats
when no files were read by the IC/TS. #3765 (2.4.9.0/2.5.0.1)
- Fixes that avoid deadlock situations on the file handle cache in certain
scenarios with very high thread contention. #3784 (2.4.10.0/2.5.0.3)
- maketx and oiiotool --otex: Add support for CDFs of bumpslopes channels.
Previously, if you used both --bumpslopes and --cdf at the same time,
the CDFs were not produced for all channels. #3793 (by Tom Knowles) (2.4.10.0/2.5.1.0)
* oiiotool improvements:
- When `-q` (quiet mode) is used, and when an error occurs, only print the
error message and not the full help message. #3649 (2.5.0.0)
- Fix problems with `--point` when there is no alpha channel. #3684
(2.4.6/2.5.0.0)
- `--dumpdata` fix channel name output. #3687 (2.4.6/2.5.0.0)
- `--help` now prints a much abbreviated color management section (just the
OCIO version and config file). Use the new `--colorconfiginfo` argument
to print the full color management information, which is both more
readable and more detailed than what `--help` used to print. #3707
(2.5.0.0)
- Don't propagate unsupported channels
[#3838](https://github.com/OpenImageIO/oiio/pull/3838) (2.5.2.0)
- *refactor*: Get rid of the global Oiiotool singleton.
[#3848](https://github.com/OpenImageIO/oiio/pull/3848) (2.5.2.0)
- *oiiotool*: Work around static destruction order issue #3295 [#3591](https://github.com/OpenImageIO/oiio/pull/3591) (by Aras Pranckevičius)
* ICC Profiles found in JPEG, JPEG-2000, PSN, PSD, and TIFF files are now
examined and several key fields are extracted as separate metadata. #3554
(2.5.0.0)
* Various protections against corrupted files [#3954](https://github.com/OpenImageIO/oiio/pull/3954) (2.5.3.0)
* BMP:
- Fix reading 16bpp images. [#3592](https://github.com/OpenImageIO/oiio/pull/3592) (by Aras Pranckevičius) (2.4.5/2.5.0.0)
- Protect against corrupt pixel coordinates. (TALOS-2022-1630,
CVE-2022-38143) [#3620](https://github.com/OpenImageIO/oiio/pull/3620) (2.4.5/2.5.0.0)
- Fix possible write errors, fixes TALOS-2022-1653 / CVE-2022-43594,
CVE-2022-43595. #3673 (2.4.6/2.5.0.0)
- Mark color space as sRGB, which seems likely to be true of any BMP
files anybody encounters. #3701 (2.5.0.0)
- Fix signed integer overflow when computing total number of pixels
[#3948](https://github.com/OpenImageIO/oiio/pull/3948) (by xiaoxiaoafeifei) (2.5.3.0)
* DDS:
- Fix heap overflow in DDS input. #3542 (2.5.0.0)
- Improved support for DTX5, ATI2/BC5 normal maps, R10G10B10A2
format, RXGB, BC4U, BC5U, A8, improved low bit expansion to 8 bits.
[#3573](https://github.com/OpenImageIO/oiio/pull/3573)
(by Aras Pranckevičius)(2.4.4.2/2.5.0.0)
- Fix alpha/luminance files, better testing. [#3581](https://github.com/OpenImageIO/oiio/pull/3581) (by Aras Pranckevičius) (2.4.5/2.5.0.0)
- Optimize loading of compressed images, improves 3-5x. [#3583](https://github.com/OpenImageIO/oiio/pull/3583) (by Aras Pranckevičius) #3584
(2.4.5/2.5.0.0)
- Honor ImageInput thread policy [#3584](https://github.com/OpenImageIO/oiio/pull/3584)
- Fix crashes for cubemap files when a cube face was not present, and
check for invalid bits per pixel. (TALOS-2022-1634, CVE-2022-41838)
(TALOS-2022-1635, CVE-2022-41999) [#3625](https://github.com/OpenImageIO/oiio/pull/3625) (2.4.5/2.5.0.0)
(TALOS-2022-1635, CVE-2022-41999) #3625 (2.4.5/2.5.0.0)
- Fix divide-by-0 during DXT4 DDS load [#3959](https://github.com/OpenImageIO/oiio/pull/3959) (by Jesse Yurkovich) (2.5.3.0)
* DPX:
- Fix possible write errors, fixes TALOS-2022-1651 / CVE-2022-43592 and
TALOS-2022-1652 / CVE-2022-43593. #3672 (2.4.6/2.5.0.0)
* FITS:
- Ensure that the file is closed if open fails to find the right magic
number. #3771 (2.5.1.0)
* GIF:
- Fix potential array overrun when writing GIF files. #3789
(2.4.10.0/2.5.1.0)
- Prevent heap-buffer-overflow
[#3841](https://github.com/OpenImageIO/oiio/pull/3841) (2.5.2.0) (by
xiaoxiaoafeifei)
* HEIC:
- Support the ".hif" extension, which seems to be used by some Canon
cameras instead of .heif.
[#3813](https://github.com/OpenImageIO/oiio/pull/3813)(by AdamMainsTL)
* HDR:
- Fix a 8x (!) read performance regression for HDR files that was
introduced in OIIO in 2.4. On top of that, speed up by another 4x beyond
what we ever did before by speeding up the RGBE->float conversion.
[#3588](https://github.com/OpenImageIO/oiio/pull/3588) [#3590](https://github.com/OpenImageIO/oiio/pull/3590)
(by Aras Pranckevičius) (2.4.5/2.5.0.0)
* ICO:
- Heap-buffer-overflow [#3872](https://github.com/OpenImageIO/oiio/pull/3872) (by xiaoxiaoafeifei) Fixes CVE-2023-36183.
* IFF:
- Protect against 0-sized allocations. #3603 (2.5.0.0)
- IOProxy support. #3647 (2.4.6/2.5.0.0)
FIXME Temporarily disable IOProxy support to avoid bugs in #3760
(2.5.0.1)
- Fix possible write errors, fixes 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 #3676
(2.4.6/2.5.0.0)
- Catch possible exception, identified by static analysis [#3681](https://github.com/OpenImageIO/oiio/pull/3681)
* JPEG
- *jpeg*: Fix density calculation for jpeg output
[#3861](https://github.com/OpenImageIO/oiio/pull/3861) (2.5.2.0) (by
Loïc Vital)
* JPEG2000:
- Better pixel type promotion logic [#3878](https://github.com/OpenImageIO/oiio/pull/3878) (2.5.2.0)
* OpenEXR:
- Fix potential use of uninitialized value when closing. #3764 (2.5.0.1)
- Try to improve exr thread pool weirdness
[#3864](https://github.com/OpenImageIO/oiio/pull/3864) (2.5.2.0)
- Controlled shutdown of IlmThread pool in all apps in which we use it.
[#3805](https://github.com/OpenImageIO/oiio/pull/3805) (2.5.2.0)
- Correction to dwa vs zip logic when outputting OpenEXR [#3884](https://github.com/OpenImageIO/oiio/pull/3884) (2.5.2.0)
- Enable openexr core library by default when recent enough
[#3942](https://github.com/OpenImageIO/oiio/pull/3942) (2.5.3.0)
* PBM:
- Fix accidental inversion for 1-bit bitmap pbm files. [#3731](https://github.com/OpenImageIO/oiio/pull/3731)
(2.5.0.0/2.4.8.0)
* PNG:
- Fix memory leaks for error conditions. #3543 #3544 (2.5.0.0)
- Add EXIF write support to PNG output. [#3736](https://github.com/OpenImageIO/oiio/pull/3736) (by Joris Nijs) (2.5.0.1)
* PSD:
- Fix a PSD read error on ARM architecture. #3589 (2.4.5/2.5.0.0)
- Protect against corrupted embedded thumbnails. (TALOS-2022-1626,
CVE-2022-41794) #3629 (2.4.5/2.5.0.0)
- Fix thumbnail extraction. #3668 (2.4.6/2.5.0.0)
- When reading, don't reject padded thumbnails. #3677 (2.4.6/2.5.0.0)
- Fix wrong "oiio:UnassociatedAlpha" metadata. #3750 (2.5.0.1)
- Handle very wide images with more than 64k resolution in either
direction. #3806 (2.5.1.0/2.4.11)
- Improve memory efficiency of PSD read [#3807](https://github.com/OpenImageIO/oiio/pull/3807) (2.5.2.0)
- Prevent simultaneous psd thumbnail reads from clashing [#3877](https://github.com/OpenImageIO/oiio/pull/3877)
- CMYK PSD files now copy alpha correctly [#3918](https://github.com/OpenImageIO/oiio/pull/3918) (by jasonbaumeister) (2.5.2.0)
* RAW:
- Add color metadata: pre_mul, cam_mul, cam_xyz, rgb_cam. #3561 #3569
#3572 (2.5.0.0)
- Update Exif orientation if user flip is set. #3669 (2.4.6/2.5.0.0)
- Correctly handle 1-channel raw images. #3798 (2.5.1.0/2.4.11.0)
- Fix LibRaw flip to Exif orientation conversion
[#3847](https://github.com/OpenImageIO/oiio/pull/3847)
[#3858](https://github.com/OpenImageIO/oiio/pull/3858) (2.5.2.0) (by
Loïc Vital)
* RLA:
- Fix potential buffer overrun. (TALOS-2022-1629, CVE-2022-36354) #3624
(2.4.5/2.5.0.0)
- IOProxy support. #3642 (2.5.0.0)
- Fix possible invalid read from an empty vector during RLA load
[#3960](https://github.com/OpenImageIO/oiio/pull/3960) (by Jesse Yurkovich) (2.5.3.0)
* SGI:
- IOProxy support. #3641 (2.5.0.0)
* Targa:
- Fix incorrect unique_ptr allocation. #3541 (2.5.0.0)
- Fix string overflow safety. (TALOS-2022-1628, CVE-2022-41981)
[#3622](https://github.com/OpenImageIO/oiio/pull/3622) (2.4.5/2.5.0.0)
- Guard against corrupted tga files Fixes TALOS-2023-1707 /
CVE-2023-24473, TALOS-2023-1708 / CVE-2023-22845. #3768 (2.5.1.0/2.4.8.1)
* TIFF:
- Guard against corrupt files with buffer overflows. (TALOS-2022-1627,
CVE-2022-41977) [#3628](https://github.com/OpenImageIO/oiio/pull/3628) (2.4.5/2.5.0.0)
- Guard against buffer overflow for certain CMYK files. (TALOS-2022-1633,
CVE-2022-41639) (TALOS-2022-1643, CVE-2022-41988)
[#3632](https://github.com/OpenImageIO/oiio/pull/3632) (2.4.5/2.5.0.0)
- While building against the new libtiff 4.5, use its new per-tiff error
handlers to ensure better thread safety. #3719 (2.5.0.0/2.4.8.0)
- Better logic for making TIFF PhotometricInterpretation tag and
oiio:ColorSpace metadata correspond to each other correctly for TIFF
files. [#3746](https://github.com/OpenImageIO/oiio/pull/3746) (2.5.0.1)
- Fix: race condition in TIFF reader, fixes TALOS-2023-1709 /
CVE-2023-24472. #3772 (2.5.1.0/2.4.8.1)
- Disable writing TIFF files with JPEG compression -- it never worked
properly and we can't seem to fix it. The fact that nobody noticed that
it never worked is taken as evidence that nobody needs it. If asked for,
it just uses the default ZIP compression instead. The TIFF reader can
still read JPEG-compressed TIFF files just fine, it's only writing that
appears problematic. #3791 (2.5.0.4)
* Zfile:
- Zfile write safety, fixes TALOS-2022-1657 / CVE-2022-43603. #3670
(2.4.6/2.5.0.0)
* Exif (all formats that support it, TIFF/JPEG/PSD):
- Fix EXIF bugs where corrupted exif blocks could overrun memory.
(TALOS-2022-1626, CVE-2022-41794) (TALOS-2022-1632, CVE-2022-41684)
(TALOS-2022-1636 CVE-2022-41837) #3627 (2.4.5/2.5.0.0)
- Fix typo that prevented us from correctly naming Exif
"CameraElevationAngle" metadata.
[#3783](https://github.com/OpenImageIO/oiio/pull/3783) (by Fabien
Castan) (2.4.10.0/2.5.1.0)
- Convert paramvalue string to integer when needed [#3886](https://github.com/OpenImageIO/oiio/pull/3886) (by Fabien Servant @ TCS) (2.5.2.0)
- Squash some alignment problems caught by ubsan [#3646](https://github.com/OpenImageIO/oiio/pull/3646)
* Fix missing OIIO::getattribute support for `limits:channels` and
`limits:imagesize_MB`. #3617 (2.4.5/2.5.0.0)
* IBA::render_text and `oiiotool --text` now can find ".ttc" font files. #3633
(2.5.0.0)
* Fix ImageOutput::check_open error conditions. #3769 (2.5.1.0)
* Fix thread safety issue when reading ICC profiles from multiple files
simultaneously. This could affect any files with ICC profiles. #3767
(2.5.1.0)
* Improve searching for fonts for the text rendering functionality. #3802
#3803 (2.5.1.0)
* Improve OpenCV support -- errors, version, half
[#3853](https://github.com/OpenImageIO/oiio/pull/3853) (2.5.2.0)
* Prevent possible deadlock when reading files with wrong extensions
[#3845](https://github.com/OpenImageIO/oiio/pull/3845)
* Wait for terminated threads to join in thread_pool::Impl::resize [#3879](https://github.com/OpenImageIO/oiio/pull/3879) (by Ray Molenkamp)
### 🔧 Internals and developer goodies
* filesystem.h:
- Add an optional size parameter to `read_text_file()` to limit the
maximum size that will be allocated and read (default to a limit of
16MB). New `read_text_from_command()` is similar to `read_text_file`,
but reads from the console output of a shell command. #3635 (2.5.0.0)
- New `Filesystem::is_executable()` and `find_program()`. #3638
(2.4.6/2.5.0.0)
- Change IOMemReader constructor to take a const buffer pointer. #3665
(2.4.6/2.5.0.0)
- IOMemReader::pread now detects and correctly handles out-of-range
read positions. #3712 (2.4.7/2.5.0.0)
* fmath.h:
- Fix a wrong result with `fast_exp2()` with MSVS and sse4.2.
[#3804](https://github.com/OpenImageIO/oiio/pull/3804) (by Eric Mehl)
(2.5.1.0/2.4.11)
* platform.h:
- New macros for detecting MSVS 2019 and 2022. #3727 (2.5.0.0/2.4.8.0)
* simd.h:
- Fixes to ensure safe compilation for Cuda. #3810 (2.5.1.0/2.4.11)
- Fix sense of hiding deprecated type names [#3870](https://github.com/OpenImageIO/oiio/pull/3870) (2.5.2.0)
- Fix broken OIIO_NO_NEON definition [#3911](https://github.com/OpenImageIO/oiio/pull/3911)
* span.h:
- `cspan<>` template now allows for Extent template argument (as `span<>`
already did). #3685 (2.5.0.0)
- New custom fmt formatter can print spans. #3685 (2.5.0.0)
* string_view.h:
- Avoid sanitizer warning unsigned integer overflow [#3678](https://github.com/OpenImageIO/oiio/pull/3678)(by wayne-arnold-adsk)
* strutil.h:
- Add a new flavor of `utf16_to_utf8()` to convert between std::u16string
and std::string (UTF-8 encoded). Note the contrast between this and the
existing flavor that takes a `std::wstring` with UTF-16 encoding
(`std::wchar/wstring` is not guaranteed to 16 bits on all platforms, but
`u16char/u16string` is). #3553 (2.5.0.0)
- New `trimmed_whitspace()`. [#3636](https://github.com/OpenImageIO/oiio/pull/3636) (2.4.5/2.5.0.0)
- Use std::forward properly for sync::print().
[#3825](https://github.com/OpenImageIO/oiio/pull/3825) (2.5.2.0)
- Ensure proper constexpr of string hashing [#3901](https://github.com/OpenImageIO/oiio/pull/3901)
* timer.h:
- Minor improvements to Timer and LoggedTimer classes. #3753 (2.5.0.1)
* tiffutils.h:
- `decode_icc_profile` extracts several fields from an ICC profile binary
blob and adds them as metadata to an ImageSpec. #3554 (2.5.0.0)
* typedesc.h:
- Extend TypeDescFromC template to the full set of pixel types. #3726
(2.5.0.0/2.4.8.0)
* ustring.h:
- Make `std::hash` work for ustring, add `operator<` for ustringhash, add
`from_hash()` to ustringhash, make ustringhash `==` and `!=` be
constexpr for C++17 and beyond. #3577 (2.4.5/2.5.0.0)
- Custom fmt formatter for ustringhash that prints the string rather than
the hash. #3614 (2.4.5/2.5.0.0)
- Ensure that ustring hashes are always 64 bits, even on 32-bit
architectures. #3606 (2.5.0.0)
- Ensure safe use of this header from Cuda. #3718 (2.4.7/2.5.0.0)
- ustringhash: Make an explicit constructor from a hash value.
[#3778](https://github.com/OpenImageIO/oiio/pull/3778) (2.4.9.0/2.5.1.0)
- String literal operator for ustring and ustringhash
[#3939](https://github.com/OpenImageIO/oiio/pull/3939) (2.5.3.0)
* Safety: excise the last instances of unsafe sprintf. #3705 (2.5.0.0)
* Root out stray uses of deprecated simd type names; `OIIO_DISABLE_DEPRECATED`
[#3830](https://github.com/OpenImageIO/oiio/pull/3830) (2.5.2.0)
* Convert iconvert.cpp stream io and sprintf to modern [#3925](https://github.com/OpenImageIO/oiio/pull/3925)
### 🏗 Build/test/CI and platform ports:
* CMake build system and scripts:
- It is now possible to `-DOpenImageIO_VERSION` to override the version
number being built (use with extreme caution). #3549 #3653 (2.5.0.0)
- Perform parallel builds with MSVS. #3571 (2.5.0.0)
- New CMake cache variable `FORTIFY_SOURCE`, if enabled, builds with the
specified gcc `_FORTIFY_SOURCE` option defined. This may be desirable
for people deploying OIIO in security-sensitive environments. #3575
(2.4.5/2.5.0.0)
- CMake config should not include a find of fmt if it's internalized.
#3739 (2.4.7.1/2.5.0.0)
- New CMake cache variable `OIIO_DISABLE_BOOST_STACKTRACE` to disable the
stacktrace functionality for users who want to avoid the Boost
stacktrace library. #3777 (by jreichel-nvidia) (2.4.9.0/2.5.1.0)
- Check need for libatomic with check_cxx_source_compiles instead of the
more expensive check_cxx_source_runs. #3774 (2.4.9.0/2.5.1.0)
- Fix incorrect CMake variable name to control symbol visibility
[#3834](https://github.com/OpenImageIO/oiio/pull/3834) (2.5.2.0)
- Make sure use of `${PROJECT_NAME}` doesn't occur before the call to
`project()`. [#3651](https://github.com/OpenImageIO/oiio/pull/3651)
- Fix use of OIIO_LOCAL_DEPS_PATH [#3865](https://github.com/OpenImageIO/oiio/pull/3865)
- Added check for Boost_NO_BOOST_CMAKE, ignore if already set
[#3961](https://github.com/OpenImageIO/oiio/pull/3961) (by Mikael Sundell) (2.5.3.0)
* Dependency version support:
- Support for OpenColorIO 2.2. #3644 (2.5.0.0)
- New CMake option `INTERNALIZE_FMT` (default ON), if set to OFF, will
force OIIO clients to use the system fmt library and will not copy the
necessary fmt headers into the OIIO include area. #3598 (2.4.7/2.5.0.0)
- build_libtiff.bash changed to build shared library by default. #3586
(2.5.0.0)
- build_openexr.bash changed to build v3.1.5 by default. #3703 (by Michael Oliver) (2.5.0.0)
- Qt6 support for iv. #3779 (2.4.9.0/2.5.1.0)
- Fmt 10.0 support [#3836](https://github.com/OpenImageIO/oiio/pull/3836) (2.5.2.0)
- FFmpeg 6.0 support [#3812](https://github.com/OpenImageIO/oiio/pull/3812) (2.5.2.0)
- Disable new warning for fmt headers in gcc13
[#3827](https://github.com/OpenImageIO/oiio/pull/3827) (2.5.2.0)
- Raise minimum CMake dependency from 3.12 to 3.15 [#3924](https://github.com/OpenImageIO/oiio/pull/3924) (2.5.2.0)
- Raise minimum libraw to 0.18 [#3921](https://github.com/OpenImageIO/oiio/pull/3921) (2.5.2.0)
- Raise OpenEXR minimum from 2.3 to 2.4 [#3928](https://github.com/OpenImageIO/oiio/pull/3928) (2.5.2.0)
- Fix WebP linking if CMAKE_FIND_PACKAGE_PREFER_CONFIG is ON [#3863](https://github.com/OpenImageIO/oiio/pull/3863) (by Benjamin Buch)
- Find OpenEXR equally well with our FindOpenEXR and exr's exported config
file [#3862](https://github.com/OpenImageIO/oiio/pull/3862) (by Benjamin
Buch)
- Fix fmt vs gcc warning that had version typo [#3874](https://github.com/OpenImageIO/oiio/pull/3874)
- Fix broken libheif < 1.13 [#3970](https://github.com/OpenImageIO/oiio/pull/3970) (2.5.3.0)
* Testing and Continuous integration (CI) systems:
- Restored sanitizer tests which had been inadvertently disabled. #3545
(2.5.0.0)
- Added tests for undefined behavior sanitizer. #3565 (2.5.0.0)
- Added tests or improved test coverage for Cineon files #3607, iinfo
#3605 #3613 #3688 #3706, texture statistics #3612, oiiotool unit tests
#3616, oiiotool expression substitution #3636, various oiiotool #3626
#3637 #3643 #3649, oiiotool control flow #3643, oiiotool sequence errors
and selecting out of range subimages or mip levels #3649, Strutil
functionality #3655, ImageCache #3654, environment mapping #3694,
texture3d #3699, term output #3714, igrep #3715, oiiotool --pdiff #3723,
zover, fixnan for deep images, 2D filters #3730, pbm files #3731, maketx
--lightprobe #3732 (2.5.0.0), TypeDesc::tostring, python ImageCache and
ImageBuf #3745, maketx #3748 (2.5.0.1), ImageBufAlgo python functions
#3766 (2.5.1.0), etc. #3745
- Make testsuite/oiiotool-control run much faster by combining commands
into fewer oiiotool invocations (speeds up testsuite) #3618 (2.5.0.0)
- CI color related tests use the OCIO buit-in configs, when OCIO 2.2+ is
available. #3662 (2.5.0.0)
- Fix compiler warnings [#3833](https://github.com/OpenImageIO/oiio/pull/3833) (2.5.2.0)
- Fix package name for icc [#3860](https://github.com/OpenImageIO/oiio/pull/3860) (2.5.2.0)
- Change the few symbolic links to copies to help Windows
[#3818](https://github.com/OpenImageIO/oiio/pull/3818) (2.5.2.0)
- Fix incorrect branch name when cloning openexr-images for the tests
[#3814](https://github.com/OpenImageIO/oiio/pull/3814) (2.5.2.0) (by
Jesse Y)
- Sonar analysis should exclude stb_sprintf.h [#3609](https://github.com/OpenImageIO/oiio/pull/3609)
- Eliminate xxhash and farmhash code from coverage analysis [#3621](https://github.com/OpenImageIO/oiio/pull/3621)
- No longer add the ppa:ubuntu-toolchain-r/test repository [#3671](https://github.com/OpenImageIO/oiio/pull/3671)
- Test against latest webp, and deal with its master->main repo change [#3695](https://github.com/OpenImageIO/oiio/pull/3695)
- Fix broken Mac CI with proper numpy install [#3702](https://github.com/OpenImageIO/oiio/pull/3702)
- Lock down to older icc so it's not broken [#3744](https://github.com/OpenImageIO/oiio/pull/3744)
- Updates to runners, dependencies [#3786](https://github.com/OpenImageIO/oiio/pull/3786)
- Bump 'latest versions' test to the newest openexr release [#3796](https://github.com/OpenImageIO/oiio/pull/3796)
- Fix broken heif dependency and test [#3894](https://github.com/OpenImageIO/oiio/pull/3894)
- Add test with new aswf containers for VFX Platform 2023 [#3875](https://github.com/OpenImageIO/oiio/pull/3875)
- Simplify build_llvm.bash script [#3892](https://github.com/OpenImageIO/oiio/pull/3892)
- Get rid of long-unused install_test_images.bash [#3895](https://github.com/OpenImageIO/oiio/pull/3895)
- Test against pybind11 v2.11 [#3912](https://github.com/OpenImageIO/oiio/pull/3912)
- Lock down icx version [#3929](https://github.com/OpenImageIO/oiio/pull/3929)
- Fix missing simd test due to copy paste typo [#3896](https://github.com/OpenImageIO/oiio/pull/3896)
- Bump build_openexr and build_opencolorio defaults to latest versions [#3920](https://github.com/OpenImageIO/oiio/pull/3920)
- Test both openexr old and core versions [#3604](https://github.com/OpenImageIO/oiio/pull/3604)
- Add benchmarking of strutil.h ways to concatenate strings. [#3787](https://github.com/OpenImageIO/oiio/pull/3787)
- Make timer_test more robust [#3953](https://github.com/OpenImageIO/oiio/pull/3953) (2.5.3.0)
* Platform support:
- Windows: protect against OpenEXR thread deadlock on shutdown. #3582
(2.4.5/2.5.0.0)
- Windows: Work around a static destruction order issue. #3591
(2.4.5/2.5.0.0)
- Windows: define `NOGDI` to keep the inclusion of windows.h from adding
as many unneeded symbols. [#3596](https://github.com/OpenImageIO/oiio/pull/3596) (by Aras Pranckevičius) (2.4.5/2.5.0.0)
- Windows: Stop including Windows.h from public OIIO headers. [#3597](https://github.com/OpenImageIO/oiio/pull/3597) (by Aras Pranckevičius) (2.5.0.0)
- Windows: Fix windows.h pre-definitions
[#3965](https://github.com/OpenImageIO/oiio/pull/3965) (2.5.3.0)
- Windows on ARM64 build fixes. #3690 (2.4.6/2.5.0.0)
- Windows: Fix unresolved external symbol for MSVS 2017.
[#3763](https://github.com/OpenImageIO/oiio/pull/3763) (by Latios96) (2.5.0.1)
- Windows: Fix build error with MSVC [#3832](https://github.com/OpenImageIO/oiio/pull/3832) (by Ray Molenkamp) (2.5.2.0)
- MinGW: fix incorrect symbol visibility issue for ImageBuf iterators. #3578
- Mac: Suppress warnings about deprecated std::codecvt on newest Apple
clang. #3709 #3710 (2.4.7/2.5.0.0)
- Mac: Fixes to make a clean build using Apple Clang 11.0.
[#3795](https://github.com/OpenImageIO/oiio/pull/3795) (by johnfea) (2.4.10.0/2.5.1.0)
- Mac: Fixes for latest xcode on MacOS 13.3 Ventura [#3854](https://github.com/OpenImageIO/oiio/pull/3854) (2.5.2.0)
- Mac: Suppress Xcode warnings [#3940](https://github.com/OpenImageIO/oiio/pull/3940) (by Anton Dukhovnikov) (2.5.3.0)
#3722 (2.4.7/2.5.0.0)
- Mac: Fixes for latest xcode on MacOS 13.3 Ventura [#3854](https://github.com/OpenImageIO/oiio/pull/3854) (2.5.2.0)
- Fixes to make a clean build on Mac using Apple Clang 11.0.
- ARM: Fix signed/unsigned mismatch compiler errors in vbool4 methods.
- ARM: improve SIMD operations for ARM NEON. #3599 (2.4.5/2.5.0.0)
- ARM: Fix signed/unsigned mismatch compiler errors in vbool4 methods.
- ARM Mac: Fix build break. #3735 (2.5.0.0/2.4.7.1)
- Fixes to build properly on OpenBSD. [#3808](https://github.com/OpenImageIO/oiio/pull/3808) (by Brad Smith) (2.5.1.0/2.4.11)
- Squash warning in gcc 12.1 + C++20 [#3679](https://github.com/OpenImageIO/oiio/pull/3679)
- Work around problems with fmt library + NVPTX relating to unknown
float128 type. [#3823](https://github.com/OpenImageIO/oiio/pull/3823)
(by Edoardo Dominici)
- Silence gcc new/delete warnings for texturesys [#3944](https://github.com/OpenImageIO/oiio/pull/3944) (by Shootfast) (2.5.3.0)
### 📚 Notable documentation changes:
- Docs: Better Windows build instructions in INSTALL.md. [#3602](https://github.com/OpenImageIO/oiio/pull/3602) (by Aras Pranckevičius) (2.4.5/2.5.0.0)
- ImageInput and ImageOutput docs updated to Python 3. [#3866](https://github.com/OpenImageIO/oiio/pull/3866) (by Ziggy Cross)
- Fix explanation of raw:Exposure config hint [#3889](https://github.com/OpenImageIO/oiio/pull/3889)
- Many fixes to python code examples [#3869](https://github.com/OpenImageIO/oiio/pull/3869) (by Jesse Y)
- Update ImageInput docs to not use deprecated APIs [#3907](https://github.com/OpenImageIO/oiio/pull/3907) (by Jesse Y)
### 🏢 Project Administration
- Added RELEASING.md documenting our versioning and release procedures #3564
#3580
- Update CONTRIBUTING and SECURITY [#3852](https://github.com/OpenImageIO/oiio/pull/3852) (2.5.2.0)
- Update mail list to https://lists.aswf.io/g/oiio-dev [#3880](https://github.com/OpenImageIO/oiio/pull/3880)
- Add charter and other ASWF documents to the repo [#3850](https://github.com/OpenImageIO/oiio/pull/3850)
- Document use of the DCO which is now required for all PRs [#3897](https://github.com/OpenImageIO/oiio/pull/3897)
- Put logo on the main readme [#3927](https://github.com/OpenImageIO/oiio/pull/3927)
- Remove old CLAs that are no longer in effect
- Change open source license to Apache 2.0. #3899, #3903, #3904, #3906,
#3914, #3922, #3926, #3938, #3966.
- Make sure README has links for slack and meetings [#3936](https://github.com/OpenImageIO/oiio/pull/3936)
- Update pull request and issue templates [#3946](https://github.com/OpenImageIO/oiio/pull/3946)
- Add Jesse Yurkovich to the TSC [#3937](https://github.com/OpenImageIO/oiio/pull/3937)
Release 2.4.15.0 (1 Sep 2023) -- compared to 2.4.14.0
@@ -44,29 +661,27 @@ Release 2.4.14.0 (1 Aug 2023) -- compared to 2.4.13.0
Release 2.4.13.0 (1 July 2023) -- compared to 2.4.12.0
-------------------------------------------------------
- *OpenCV*: Improve OpenCV support -- errors, version, half [#3853](https://github.com/OpenImageIO/oiio/pull/3853)
- *IBA*: Improve error message for IBA::ocio functions [#3887](https://github.com/OpenImageIO/oiio/pull/3887)
- *exif*: Convert paramvalue string to integer when needed [#3886](https://github.com/OpenImageIO/oiio/pull/3886) (by Fabien Servant @ TCS)
- *exr*: Correction to dwa vs zip logic when outputting OpenEXR [#3884](https://github.com/OpenImageIO/oiio/pull/3884)
- *OpenCV*: Improve OpenCV support -- errors, version, half [#3853](https://github.com/OpenImageIO/oiio/pull/3853)
- *IBA*: Improve error message for IBA::ocio functions [#3887](https://github.com/OpenImageIO/oiio/pull/3887)
- *exif*: Convert paramvalue string to integer when needed [#3886](https://github.com/OpenImageIO/oiio/pull/3886) (by Fabien Servant @ TCS)
- *exr*: Correction to dwa vs zip logic when outputting OpenEXR [#3884](https://github.com/OpenImageIO/oiio/pull/3884)
- *ico*: Heap-buffer-overflow [#3872](https://github.com/OpenImageIO/oiio/pull/3872) (by xiaoxiaoafeifei) Fixes CVE-2023-36183.
- *jpeg*: Fix density calculation for jpeg output [#3861](https://github.com/OpenImageIO/oiio/pull/3861) (by Loïc Vital)
- *jpeg2000*: Better pixel type promotion logic [#3878](https://github.com/OpenImageIO/oiio/pull/3878)
- *psd*: Prevent simultaneous psd thumbnail reads from clashing [#3877](https://github.com/OpenImageIO/oiio/pull/3877)
- *strutil.h*: Ensure proper constexpr of string hashing [#3901](https://github.com/OpenImageIO/oiio/pull/3901)
- *jpeg*: Fix density calculation for jpeg output [#3861](https://github.com/OpenImageIO/oiio/pull/3861) (by Loïc Vital)
- *jpeg2000*: Better pixel type promotion logic [#3878](https://github.com/OpenImageIO/oiio/pull/3878)
- *psd*: Prevent simultaneous psd thumbnail reads from clashing [#3877](https://github.com/OpenImageIO/oiio/pull/3877)
- *strutil.h*: Ensure proper constexpr of string hashing [#3901](https://github.com/OpenImageIO/oiio/pull/3901)
- *build* Fix use of OIIO_LOCAL_DEPS_PATH [#3865](https://github.com/OpenImageIO/oiio/pull/3865)
- *build* Fix fmt vs gcc warning that had version typo [#3874](https://github.com/OpenImageIO/oiio/pull/3874)
- *ci*: Add test with new aswf containers for VFX Platform 2023 [#3875](https://github.com/OpenImageIO/oiio/pull/3875)
- *ci*: Fix broken heif dependency and test [#3894](https://github.com/OpenImageIO/oiio/pull/3894)
- *ci*: Simplify build_llvm.bash script [#3892](https://github.com/OpenImageIO/oiio/pull/3892)
- *build* Fix fmt vs gcc warning that had version typo [#3874](https://github.com/OpenImageIO/oiio/pull/3874)
- *ci*: Add test with new aswf containers for VFX Platform 2023 [#3875](https://github.com/OpenImageIO/oiio/pull/3875)
- *ci*: Fix broken heif dependency and test [#3894](https://github.com/OpenImageIO/oiio/pull/3894)
- *ci*: Simplify build_llvm.bash script [#3892](https://github.com/OpenImageIO/oiio/pull/3892)
- *tests*: Fix missing simd test due to copy paste typo [#3896](https://github.com/OpenImageIO/oiio/pull/3896)
- *docs*: Update CONTRIBUTING and SECURITY [#3852](https://github.com/OpenImageIO/oiio/pull/3852)
- *docs*: Update CONTRIBUTING and SECURITY [#3852](https://github.com/OpenImageIO/oiio/pull/3852)
- *docs*: ImageInput and ImageOutput docs updated to Python 3. [#3866](https://github.com/OpenImageIO/oiio/pull/3866) (by Ziggy Cross)
- *docs*: Many fixes to python code examples [#3869](https://github.com/OpenImageIO/oiio/pull/3869) (by Jesse Y)
- *docs*: Update mail list URL [#3880](https://github.com/OpenImageIO/oiio/pull/3880)
- *docs*: Fix explanation of raw:Exposure config hint [#3889](https://github.com/OpenImageIO/oiio/pull/3889)
- *docs*: Document use of the DCO which is now required for all PRs [#3897](https://github.com/OpenImageIO/oiio/pull/3897)
- *docs*: Many fixes to python code examples [#3869](https://github.com/OpenImageIO/oiio/pull/3869) (by Jesse Y)
- *docs*: Update mail list URL [#3880](https://github.com/OpenImageIO/oiio/pull/3880)
- *docs*: Fix explanation of raw:Exposure config hint [#3889](https://github.com/OpenImageIO/oiio/pull/3889)
- *docs*: Document use of the DCO which is now required for all PRs [#3897](https://github.com/OpenImageIO/oiio/pull/3897)
Release 2.4.12.0 (1 June 2023) -- compared to 2.4.11.1
------------------------------------------------------
@@ -83,7 +698,6 @@ Release 2.4.12.0 (1 June 2023) -- compared to 2.4.11.1
- *ci*: Fix warnings [#3833](https://github.com/OpenImageIO/oiio/pull/3833)
- *ci*: Fix package name for icc [#3860](https://github.com/OpenImageIO/oiio/pull/3860)
Release 2.4.11.1 (14 May 2023) -- compared to 2.4.11.0
------------------------------------------------------
- *build*: Fmt 10.0 support [#3836](https://github.com/OpenImageIO/oiio/pull/3836)
@@ -95,7 +709,7 @@ Release 2.4.11.0 (1 May 2023) -- compared to 2.4.10.0
* Python: Improve error messages when passing wrong python array sizes. #3801
* Raw: handle 1-channel raw images. #3798
* HEIC: Support the ".hif" extension, which seems to be used by some Canon
cameras instead of .heif. #3813
cameras instead of .heif. [#3813](https://github.com/OpenImageIO/oiio/pull/3813)(by AdamMainsTL)
* PSD: Fix problems reading images with width > 64k pixels. #3806
* Windows/fmath: Work around MSVS bug(?) that generated wrong code for
fast_exp2. #3804
@@ -104,7 +718,7 @@ Release 2.4.11.0 (1 May 2023) -- compared to 2.4.10.0
(including Cuda compiles). #3814
* Build: Fix building against new ffmpeg 6.0. #3812
* Build: Work around problems with fmt library + NVPTX relating to unknown
float128 type. #3823
float128 type. [#3823](https://github.com/OpenImageIO/oiio/pull/3823) (by Edoardo Dominici)
* CI/test: Fix incorrect branch name when cloning openexr-images for the
testsuite. #3814
* Test: Use copies instead of symlinks in a couple spots to help on Windows.
@@ -172,7 +786,6 @@ Release 2.4.8.0 (1 Feb 2023) -- compared to 2.4.7.1
* Docs: Fix old release notes to document all CVEs addressed in certain
prior releases.
Release 2.4.7.1 (3 Jan 2023) -- compared to 2.4.7.0
----------------------------------------------------
* Fix build break for Mac ARM. #3735
@@ -216,9 +829,10 @@ Release 2.4.6 (1 Dec 2022) -- compared to 2.4.5.0
* IFF files: Add IOProxy support. #3647
* IFF: Fix possible write errors, fixes 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 #3676
CVE-2022-43599 CVE-2022-43600 CVE-2022-43601 CVE-2022-43602
[#3676](https://github.com/OpenImageIO/oiio/pull/3676)
* PSD: Fix thumbnail extraction. #3668
* PSD: when reading, don't reject padded thumbnails. #3677
* PSD: when reading, don't reject padded thumbnails. [#3677](https://github.com/OpenImageIO/oiio/pull/3677)
* Raw: Update Exif orientation if user flip is set. #3669
* Zfile write safety, fixes TALOS-2022-1657 / CVE-2022-43603. #3670
* filesystem.h: new `Filesystem::is_executable()` and `find_program()`. #3638
@@ -321,7 +935,7 @@ New major features and public API changes:
headers (relying on the accidental fact of other OIIO headers
transitively including them), you may need to adjust your includes.
#3301 #3332 (2.4.0.2) #3406 #3474 (2.4.2)
- New `V3fParam`, `M33fParam`, and `M44Param` (defined in vecparam.h) are
- New `V3fParam`, `M33fParam`, and `M44fParam` (defined in vecparam.h) are
used just for parameter passing in public APIs, instead of Imath::V3f,
M33f, or M44f, in order to more fully hide Imath types from our public
interfaces. These are only parameter-passing classes, and are not useful
@@ -460,7 +1074,7 @@ New major features and public API changes:
"GammaCorrectedX.Y"). #3202 (2.4.0)
* `oiioversion.h` now defines symbols `OIIO_USING_IMATH_VERSION_MAJOR` and
`OIIO_USING_IMATH_VERSION_MINOR` that reveal which Imath version was used
internally to OIIO when it was build (which may be different than the
internally to OIIO when it was built (which may be different than the
version found when the downstream app is being compiled). #3305 (2.4.0.1)
* Most of the major APIs (including ImageInput, ImageOutput, and ImageBuf)
that took a std::string or string_view to indicate a filename (assumed to
@@ -864,7 +1478,7 @@ Developer goodies / internals:
representation is the hash, rather than the unique string pointer. #3436
(2.4.2)
* vecparam.h:
- New `V3fParam`, `M33fParam`, and `M44Param` (defined in vecparam.h) are
- New `V3fParam`, `M33fParam`, and `M44fParam` (defined in vecparam.h) are
used just for parameter passing in public APIs, instead of Imath::V3f,
M33f, or M44f, in order to more fully hide Imath types from our public
interfaces. These are only parameter-passing classes, and are not useful
@@ -936,7 +1550,7 @@ Build/test system improvements and platform ports:
components to the path. #3487 (2.4.2.1)
- On MacOS, do not force MACOS_RPATH on. #3523 (2.4.2.2)
- Improvements to the generated cmake config files when building static
libraries. #3552 #3557 (2.4.4.0)
libraries. #3552 #3557 (by Povilas Kanapickas) (2.4.4.0)
* Dependency version support:
- When using C++17, use std::gcd instead of boost. #3076 (2.4.0)
- When using C++17, use `inline constexpr` instead of certain statics.
@@ -961,6 +1575,7 @@ Build/test system improvements and platform ports:
- Fixes for ffmpeg 5.1 detection. #3516 (2.3.19.0/2.4.2.2)
- Support for gcc 12.1. #3480 (2.4.2.1) #3551 (2.4.4.0)
- Support building with clang 15.0. #3563 (2.4.4.0)
- Try FORTIFY_SOURCE [#3575](https://github.com/OpenImageIO/oiio/pull/3575)
* Testing and Continuous integration (CI) systems:
- Properly test against all the versions of VFX Platform 2022. #3074
(2.4.0)
@@ -1000,8 +1615,8 @@ Build/test system improvements and platform ports:
- Improved simd.h support for armv7 and aarch32. #3361 (2.4.1.0/2.3.14)
- Suppress MacOS wasnings about OpenGL deprecation. #3380 (2.4.1.0/2.3.14)
- Fix MSVS/Windows errors. #3382 (2.4.1.1)
- Fix cross-compiling on Android failing due to `-latomic` check. #3560
(2.4.4.0)
- Fix cross-compiling on Android failing due to `-latomic` check.
[#3560](https://github.com/OpenImageIO/oiio/pull/3560) (by Povilas Kanapickas) (2.4.4.0)
- Fix building on iOS. #3562 (2.4.4.0)
Notable documentation changes:
@@ -1023,18 +1638,6 @@ Notable documentation changes:
Release 2.3.21 (1 Nov 2022) -- compared to 2.3.20
--------------------------------------------------
* oiiotool: protect against OpenEXR thread deadlock on Windows. #3582
* oiiotool: work around static destruction order issue. #3591
* Fix PSD import on ARM. #3589
* Docs: write Windows build instructions in INSTALL.md. #3602
* RLA: fix potential buffer overrun. (TALOS-2022-1629, CVE-2022-36354) #3624
* TIFF: guard against corrupt files with buffer overflows. (TALOS-2022-1627,
CVE-2022-41977) #3628
* TIFF: guard against buffer overflow for certain CMYK files.
(TALOS-2022-1633, CVE-2022-41639) (TALOS-2022-1643, CVE-2022-41988) #3632
Release 2.3.20 (1 Oct 2022) -- compared to 2.3.19
-------------------------------------------------
* Fixes to compile with gcc 12. #3551
+4 -4
View File
@@ -2,9 +2,9 @@
# SPDX-License-Identifier: BSD-3-Clause and Apache-2.0
# https://github.com/OpenImageIO/oiio
cmake_minimum_required (VERSION 3.12)
cmake_minimum_required (VERSION 3.15)
set (OpenImageIO_VERSION "2.4.16.0")
set (OpenImageIO_VERSION "2.5.3.0")
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)
@@ -19,7 +19,7 @@ project (OpenImageIO VERSION ${OpenImageIO_VERSION}
set (PROJ_NAME OIIO) # short name, caps
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
string (TOUPPER ${PROJ_NAME} PROJ_NAME_UPPER) # short name upper case
set (PROJECT_VERSION_RELEASE_TYPE "" CACHE STRING
set (PROJECT_VERSION_RELEASE_TYPE "beta" CACHE STRING
"Build type, for example: dev, beta2, RC1 (empty string for normal release)")
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
set (PROJECT_AUTHORS "Contributors to the OpenImageIO project")
@@ -305,7 +305,7 @@ install (EXPORT OIIO_EXPORTED_TARGETS
NAMESPACE ${PROJECT_NAME}::)
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING AND ${PROJ_NAME}_BUILD_TESTS)
oiio_setup_test_data()
oiio_add_all_tests()
endif ()
-1
View File
@@ -90,7 +90,6 @@ lg@openimageio.org
* Jeremy Rose
* Jeremy Selan
* Jim Hourihan
* Joachim Reichel
* Johannes Unterguggenberger
* John Burnett
* John Fea
+30 -31
View File
@@ -14,20 +14,22 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
### Required dependencies -- OIIO will not build at all without these
* C++14 (also builds with C++17, and C++20)
* C++14 or higher (also builds with C++17, and C++20)
* The default build mode is C++14. This can be controlled by via the
CMake configuration flag: `-DCMAKE_CXX_STANDARD=17`, etc.
* ADVISORY: We expect that OIIO 2.6 in 2024 will require C++17 or higher.
* Compilers: gcc 6.1 - 12.1, clang 3.4 - 16, MSVS 2017 - 2019,
Intel icc 17+, **Intel OneAPI C++ compiler 2022+**.
* CMake >= 3.12 (tested through 3.26)
* **OpenEXR/Imath >= 2.3** (recommended: 2.4 or higher; tested through 3.2 and main)
Intel icc 17+, Intel OneAPI C++ compiler 2022+.
* **CMake >= 3.15** (tested through 3.27)
* **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.5)
* libjpeg >= 8, or libjpeg-turbo >= 1.1 (tested through jpeg9d and jpeg-turbo
2.1)
* Boost >= 1.53 (recommended: at least 1.66; tested through 1.81)
* [fmtlib](https://github.com/fmtlib/fmt) >= 6.1.2 (tested through 10.0). If
not found at build time, this will be automatically downloaded unless the
build sets `-DBUILD_MISSING_FMT=OFF`.
* **[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`.
### Optional dependencies -- features may be disabled if not found
* If you are building the `iv` viewer (which will be disabled if any of
@@ -40,8 +42,7 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
not support Python < 3.6.)
* NumPy
* If you want support for camera "RAW" formats:
* LibRaw >= 0.15 (tested 0.15 - 0.21.1; LibRaw >= 0.18 is necessary for
ACES support and much better recognition of camera metadata; if
* LibRaw >= 0.18 (tested though 0.21.1; if
building with C++17 or higher, LibRaw >= 0.20 is necessary)
* If you want support for a wide variety of video formats:
* ffmpeg >= 3.0 (tested through 6.0)
@@ -123,6 +124,9 @@ build options), maybe one of these packages managers will do it for you:
If these work for you and it's all you need, bingo! You are done.
You may find this guide to versions carried by distributions helpful:
[![OpenImageIO packaging status](https://repology.org/badge/vertical-allrepos/openimageio.svg?exclude_unsupported=1&columns=3&exclude_sources=modules,site&header=OpenImageIO%20packaging%20status)](https://repology.org/project/openimageio/versions)
Building from source
@@ -248,9 +252,8 @@ The command 'make help' will list all possible options.
You can also ignore the top level Makefile wrapper, and instead use
CMake directly:
mkdir build
cd build
cmake ..
cmake -B build -S .
cmake --build build --target install
If the compile stops because of warnings, try again with
@@ -259,8 +262,9 @@ If the compile stops because of warnings, try again with
or, if you are using CMake directly,
cd build
cmake -DSTOP_ON_WARNING=0 ..
rm -rf build
cmake -B build -S . -DSTOP_ON_WARNING=0
cmake --build build --target install
@@ -285,19 +289,16 @@ the section below, and will only have to point OIIO build process so their locat
```
cd {ZLIB_ROOT}
git clone https://github.com/madler/zlib .
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --config Release --target install
del lib\zlib.lib
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 .
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --target install
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=.
cmake --build build --target install
```
* libjpeg-turbo:
```
@@ -305,19 +306,19 @@ the section below, and will only have to point OIIO build process so their locat
git clone https://github.com/libjpeg-turbo/libjpeg-turbo .
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --config Release --target install
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 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=dist ^
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 . --target install --config Release
-DZLIB_ROOT={ZLIB_ROOT}\build
cmake --build build --target install --config Release
```
Now get the OIIO source and do one-time CMake configuration step. Replace `{*_ROOT}` below with folders where you have put the 3rd party
@@ -325,16 +326,14 @@ dependencies.
```
cd {OIIO_ROOT}
git clone https://github.com/OpenImageIO/oiio .
mkdir build
cd build
cmake -DVERBOSE=ON -DCMAKE_BUILD_TYPE=Release ^
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 ..
-DUSE_PYTHON=0 -DUSE_QT=0 -DBUILD_SHARED_LIBS=0 -DLINKSTATIC=1
```
This will produce `{OIIO_ROOT}/build/OpenImageIO.sln` that can be opened in Visual Studio IDE. Note that the solution will be
+1
View File
@@ -5,6 +5,7 @@
[![License](https://img.shields.io/badge/license-Apache2.0-blue.svg?style=flat-square)](https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md)
[![CI](https://github.com/OpenImageIO/oiio/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenImageIO/oiio/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)
Introduction
+4
View File
@@ -222,6 +222,10 @@ else ifeq (${platform}, macosx)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
USE_LIBCPLUSPLUS := 0
else ifeq (${COMPILER}, gcc13)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13
USE_LIBCPLUSPLUS := 0
else ifeq (${COMPILER},clang13)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@13/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@13/bin/clang++
-3
View File
@@ -19,7 +19,4 @@ sonar.cfamily.build-wrapper-output=build/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
sonar.cfamily.cache.enabled=true
sonar.cfamily.cache.path=/tmp/sonarcache
sonar.verbose=false
+6 -4
View File
@@ -23,7 +23,7 @@ public:
{
return feature == "ioproxy";
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
@@ -94,11 +94,13 @@ OIIO_PLUGIN_EXPORTS_END
bool
BmpInput::valid_file(const std::string& filename) const
BmpInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;
bmp_pvt::BmpFileHeader header;
Filesystem::IOFile file(filename, Filesystem::IOProxy::Read);
return file.opened() && header.read_header(&file) && header.isBmp();
return header.read_header(ioproxy) && header.isBmp();
}
+2 -18
View File
@@ -81,27 +81,11 @@ BmpOutput::supports(string_view feature) const
bool
BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
if (mode != Create) {
errorfmt("{} does not support subimages or MIP levels", format_name());
if (!check_open(mode, spec, { 0, 65535, 0, 65535, 0, 1, 0, 4 },
uint64_t(OpenChecks::Disallow2Channel)))
return false;
}
// saving 'name' and 'spec' for later use
m_filename = name;
m_spec = spec;
if (m_spec.nchannels != 1 && m_spec.nchannels != 3
&& m_spec.nchannels != 4) {
errorfmt("{} does not support {}-channel images\n", format_name(),
m_spec.nchannels);
return false;
}
if (m_spec.x || m_spec.y || m_spec.z) {
errorfmt("{} does not support images with non-zero image origin offset",
format_name());
return false;
}
// Only support 8 bit channels for now.
m_spec.set_format(TypeDesc::UINT8);
+4 -6
View File
@@ -36,15 +36,13 @@ cd ${OPENJPEG_SRC_DIR}
echo "git checkout ${OPENJPEG_VERSION} --force"
git checkout ${OPENJPEG_VERSION} --force
mkdir -p ${OPENJPEG_BUILD_DIR} && true
cd ${OPENJPEG_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${OPENJPEG_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${OPENJPEG_INSTALL_DIR} \
-DBUILD_CODEC=OFF \
${OPENJPEG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
${OPENJPEG_CONFIG_OPTS}
time cmake --build ${OPENJPEG_BUILD_DIR} --config Release --target install
fi
# ls -R ${OPENJPEG_INSTALL_DIR}
+3 -5
View File
@@ -31,12 +31,10 @@ cd ${PTEX_SRC_DIR}
echo "git checkout ${PTEX_VERSION} --force"
git checkout ${PTEX_VERSION} --force
mkdir -p ${PTEX_BUILD_DIR}
cd ${PTEX_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${PTEX_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PTEX_INSTALL_DIR} \
${PTEX_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
${PTEX_CONFIG_OPTS}
time cmake --build ${PTEX_BUILD_DIR} --config Release --target install
# ls -R ${PTEX_INSTALL_DIR}
popd
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Utility script to download and build abi checking tools
#
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/OpenImageIO/oiio
# Exit the whole script if any command fails.
set -ex
# Where to install the final results
: ${LOCAL_DEPS_DIR:=${PWD}/ext}
: ${ABITOOLS_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
mkdir -p ${LOCAL_DEPS_DIR}
pushd ${LOCAL_DEPS_DIR}
git clone https://github.com/lvc/vtable-dumper
pushd vtable-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
git clone https://github.com/lvc/abi-dumper
pushd abi-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
git clone https://github.com/lvc/abi-compliance-checker
pushd abi-compliance-checker ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
popd
# ls -R ${LOCAL_DEPS_DIR}
export PATH=${PATH}:${ABITOOLS_INSTALL_DIR}/bin
+1 -1
View File
@@ -12,7 +12,7 @@ set -ex
echo "Building cmake"
uname
CMAKE_VERSION=${CMAKE_VERSION:=3.12.4}
CMAKE_VERSION=${CMAKE_VERSION:=3.18.5}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
CMAKE_INSTALL_DIR=${CMAKE_INSTALL_DIR:=${LOCAL_DEPS_DIR}/cmake}
+3 -6
View File
@@ -36,14 +36,11 @@ cd ${LIBJPEGTURBO_SRC_DIR}
echo "git checkout ${LIBJPEGTURBO_VERSION} --force"
git checkout ${LIBJPEGTURBO_VERSION} --force
mkdir -p ${LIBJPEGTURBO_BUILD_DIR}
cd ${LIBJPEGTURBO_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${LIBJPEGTURBO_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBJPEGTURBO_INSTALL_DIR} \
${LIBJPEGTURBO_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
${LIBJPEGTURBO_CONFIG_OPTS}
time cmake --build ${LIBJPEGTURBO_BUILD_DIR} --config Release --target install
fi
# ls -R ${LIBJPEGTURBO_INSTALL_DIR}
+3 -6
View File
@@ -38,16 +38,13 @@ cd ${LIBPNG_SRC_DIR}
echo "git checkout ${LIBPNG_VERSION} --force"
git checkout ${LIBPNG_VERSION} --force
mkdir -p ${LIBPNG_BUILD_DIR}
cd ${LIBPNG_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${LIBPNG_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBPNG_INSTALL_DIR} \
-DPNG_EXECUTABLES=OFF \
-DPNG_TESTS=OFF \
${LIBPNG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
${LIBPNG_CONFIG_OPTS}
time cmake --build ${LIBPNG_BUILD_DIR} --config Release --target install
fi
# ls -R ${LIBPNG_INSTALL_DIR}
+7 -6
View File
@@ -36,16 +36,17 @@ cd libtiff
echo "git checkout ${LIBTIFF_VERSION} --force"
git checkout ${LIBTIFF_VERSION} --force
mkdir -p build
cd build
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=${LIBTIFF_BUILD_TYPE} \
time cmake -S . -B build \
-DCMAKE_BUILD_TYPE=${LIBTIFF_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${LIBTIFF_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${LIBTIFF_CXX_FLAGS}" \
-DBUILD_SHARED_LIBS=${LIBTIFF_BUILD_SHARED_LIBS:-ON} \
${LIBTIFF_BUILDOPTS} ..
time cmake --build . --target install
-Dtiff-tests=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dtiff-docs=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dlibdeflate=ON \
${LIBTIFF_BUILDOPTS}
time cmake --build build --target install
fi
popd
+5 -5
View File
@@ -18,6 +18,7 @@ LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
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 \
@@ -42,13 +43,12 @@ cd ${OPENCOLORIO_SOURCE_DIR}
echo "git checkout ${OPENCOLORIO_VERSION} --force"
git checkout ${OPENCOLORIO_VERSION} --force
mkdir -p ${OPENCOLORIO_BUILD_DIR}
cd ${OPENCOLORIO_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
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} ${OPENCOLORIO_SOURCE_DIR}
time cmake --build . --config Release --target install
${OPENCOLORIO_BUILDOPTS}
time cmake --build ${OPENCOLORIO_BUILD_DIR} --config Release --target install
popd
# ls -R ${OPENCOLORIO_INSTALL_DIR}
+15 -32
View File
@@ -36,42 +36,25 @@ if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
fi
mkdir -p ${OPENEXR_INSTALL_DIR} && true
mkdir -p ${OPENEXR_BUILD_DIR} && true
pushd ${OPENEXR_SOURCE_DIR}
git checkout ${OPENEXR_VERSION} --force
if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
# Simplified setup for 2.3+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DOPENEXR_BUILD_UTILS=0 \
-DOPENEXR_BUILD_TESTS=0 \
-DOPENEXR_BUILD_PYTHON_LIBS=0 \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
else
# Simplified setup for 2.4+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DOPENEXR_BUILD_UTILS=0 \
-DBUILD_TESTING=0 \
-DPYILMBASE_ENABLE=0 \
-DOPENEXR_VIEWERS_ENABLE=0 \
-DINSTALL_OPENEXR_EXAMPLES=0 \
-DOPENEXR_INSTALL_EXAMPLES=0 \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
fi
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}" \
-DOPENEXR_BUILD_UTILS=0 \
-DBUILD_TESTING=0 \
-DPYILMBASE_ENABLE=0 \
-DOPENEXR_VIEWERS_ENABLE=0 \
-DINSTALL_OPENEXR_EXAMPLES=0 \
-DOPENEXR_INSTALL_EXAMPLES=0 \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS}
time cmake --build ${OPENEXR_BUILD_DIR} --target install --config ${OPENEXR_BUILD_TYPE}
popd
+2 -5
View File
@@ -38,16 +38,13 @@ cd ${PUGIXML_SRC_DIR}
echo "git checkout ${PUGIXML_VERSION} --force"
git checkout ${PUGIXML_VERSION} --force
mkdir -p ${PUGIXML_BUILD_DIR}
cd ${PUGIXML_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${PUGIXML_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF \
${PUGIXML_BUILD_OPTS} ..
time cmake --build . --config Release --target install
time cmake --build ${PUGIXML_BUILD_DIR} --config Release --target install
fi
# ls -R ${PUGIXML_INSTALL_DIR}
+3 -6
View File
@@ -42,15 +42,12 @@ cd ${PYBIND11_SRC_DIR}
echo "git checkout ${PYBIND11_VERSION} --force"
git checkout ${PYBIND11_VERSION} --force
mkdir -p ${PYBIND11_BUILD_DIR}
cd ${PYBIND11_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${PYBIND11_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PYBIND11_INSTALL_DIR} \
-DPYBIND11_TEST=OFF \
${PYBIND11_BUILD_OPTS} ..
time cmake --build . --config Release --target install
${PYBIND11_BUILD_OPTS}
time cmake --build ${PYBIND11_BUILD_DIR} --config Release --target install
fi
# ls -R ${PYBIND11_INSTALL_DIR}
+3 -6
View File
@@ -37,11 +37,8 @@ cd ${WEBP_SRC_DIR}
echo "git checkout ${WEBP_VERSION} --force"
git checkout ${WEBP_VERSION} --force
mkdir -p ${WEBP_BUILD_DIR}
cd ${WEBP_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=${WEBP_BUILD_TYPE} \
time cmake -S . -B ${WEBP_BUILD_DIR} -DCMAKE_BUILD_TYPE=${WEBP_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${WEBP_INSTALL_DIR} \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
@@ -51,8 +48,8 @@ if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=ON \
${WEBP_CONFIG_OPTS} ..
time cmake --build . --target install
${WEBP_CONFIG_OPTS}
time cmake --build ${WEBP_BUILD_DIR} --target install
fi
+3 -7
View File
@@ -37,15 +37,11 @@ cd ${ZLIB_SRC_DIR}
echo "git checkout ${ZLIB_VERSION} --force"
git checkout ${ZLIB_VERSION} --force
mkdir -p ${ZLIB_BUILD_DIR} && true
cd ${ZLIB_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${ZLIB_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR} \
${ZLIB_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
${ZLIB_CONFIG_OPTS}
time cmake --build ${ZLIB_BUILD_DIR} --config Release --target install
fi
# ls -R ${ZLIB_INSTALL_DIR}
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/OpenImageIO/oiio
# Important: set -ex causes this whole script to terminate with error if
# any command in it fails. This is crucial for CI tests.
set -e
# Arguments to this script are:
# BUILDDIR_NEW BUILDDIR_OLD LIBRARIES...
BUILDDIR_NEW=$1
shift
BUILDDIR_OLD=$1
shift
LIBS=$*
#
# First, create ABI dumps from both builds
#
ABI_ARGS="-bin-only -skip-cxx -public-headers $PWD/dist/include/OpenImageIO "
echo "ABI_CHECK: PWD=${PWD} "
ls -l $BUILDDIR_NEW
ls -l $BUILDDIR_OLD
for dir in $BUILDDIR_NEW $BUILDDIR_OLD ; do
for lib in $LIBS ; do
abi-dumper $ABI_ARGS ${dir}/lib/${lib}.so -o ${dir}/abi-${lib}.dump
done
done
echo "Saved ABI dumps"
#
# Run the ABI compliance checker, saving the outputs to files
#
for lib in $LIBS ; do
abi-compliance-checker -l $lib -old $BUILDDIR_OLD/abi-$lib.dump -new $BUILDDIR_NEW/abi-$lib.dump | tee ${lib}-abi-results.txt || true
echo -e "\x1b[33;1m"
echo -e "$lib"
fgrep "Binary compatibility:" ${lib}-abi-results.txt
echo -e "\x1b[33;0m"
done
#
# If the "Binary compatibility" summary results say anything other than 100%,
# we fail!
#
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
+4 -6
View File
@@ -27,8 +27,7 @@ if [[ ${GITHUB_ACTIONS} == true ]] ; then
OIIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=${CMAKE_UNITY_BUILD:=ON} -DCMAKE_UNITY_BUILD_MODE=${CMAKE_UNITY_BUILD_MODE:=BATCH}"
fi
pushd build
cmake .. -G "$CMAKE_GENERATOR" \
cmake -S . -B build -G "$CMAKE_GENERATOR" \
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
-DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH" \
-DCMAKE_INSTALL_PREFIX="$OpenImageIO_ROOT" \
@@ -40,15 +39,14 @@ cmake .. -G "$CMAKE_GENERATOR" \
$OIIO_CMAKE_FLAGS -DVERBOSE=1
# Save a copy of the generated files for debugging broken CI builds.
mkdir cmake-save || /bin/true
cp -r CMake* *.cmake cmake-save
mkdir build/cmake-save || /bin/true
cp -r build/CMake* build/*.cmake build/cmake-save
: ${BUILDTARGET:=install}
if [[ "$BUILDTARGET" != "none" ]] ; then
echo "Parallel build ${CMAKE_BUILD_PARALLEL_LEVEL} of target ${BUILDTARGET}"
time ${OIIO_CMAKE_BUILD_WRAPPER} cmake --build . --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
time ${OIIO_CMAKE_BUILD_WRAPPER} cmake --build build --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
fi
popd
if [[ "${DEBUG_CI:=0}" != "0" ]] ; then
echo "PATH=$PATH"
+1 -1
View File
@@ -50,7 +50,7 @@ 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 OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio"
export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1}
mkdir -p build dist
+2
View File
@@ -24,6 +24,8 @@ echo ; echo "Results of oiiotool brief help:"
$OpenImageIO_ROOT/bin/oiiotool || true
echo ; echo "Results of oiiotool full --help:"
$OpenImageIO_ROOT/bin/oiiotool --help || true
echo ; echo "Results of oiiotool --colorconfiginfo:"
$OpenImageIO_ROOT/bin/oiiotool --colorconfiginfo
echo ; echo "Results of oiiotool with no args (should get short help message):"
$OpenImageIO_ROOT/bin/oiiotool || true
echo ; echo "Run unit tests and simple stats:"
+13 -2
View File
@@ -18,8 +18,12 @@ if [[ "$ASWF_ORG" != "" ]] ; then
#ls /etc/yum.repos.d
sudo yum install -y giflib giflib-devel && true
sudo yum install -y opencv opencv-devel && true
sudo yum install -y ffmpeg ffmpeg-devel && true
if [[ "${USE_OPENCV}" != "0" ]] ; then
sudo yum install -y opencv opencv-devel && true
fi
if [[ "${USE_FFMPEG}" != "0" ]] ; then
sudo yum install -y ffmpeg ffmpeg-devel && true
fi
if [[ "${EXTRA_DEP_PACKAGES}" != "" ]] ; then
time sudo yum install -y ${EXTRA_DEP_PACKAGES}
fi
@@ -138,6 +142,9 @@ else
fi
if [[ "$CMAKE_VERSION" != "" ]] ; then
source src/build-scripts/build_cmake.bash
fi
cmake --version
@@ -190,6 +197,10 @@ if [[ "$PTEX_VERSION" != "" ]] ; then
source src/build-scripts/build_Ptex.bash
fi
if [[ "$ABI_CHECK" != "" ]] ; then
source src/build-scripts/build_abi_tools.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)
@@ -1,22 +0,0 @@
#!/usr/bin/env bash
if [[ ! -e ../oiio-images ]] ; then
git clone https://github.com/OpenImageIO/oiio-images.git -b RB-2.4 --depth 1 ../oiio-images
# NOTE: on release branches, this should include `-b RB-x.y`` so that
# updates to the master oiio-images don't break tests in release branches.
fi
# if [[ ! -e ../libtiffpic ]] ; then
# curl -o pics-3.8.0.tar.gz https://download.osgeo.org/libtiff/pics-3.8.0.tar.gz
# tar xf pics-3.8.0.tar.gz -C ..
# fi
if [[ ! -e ../openexr-images ]] ; then
git clone https://github.com/openexr/openexr-images.git --depth 1 ../openexr-images
fi
# if [[ ! -e ../bmpsuite ]] ; then
# mkdir ../bmpsuite
# curl -o bmpsuite.zip http://entropymine.com/jason/bmpsuite/bmpsuite.zip
# unzip bmpsuite.zip -d ../bmpsuite
# fi
+20 -41
View File
@@ -15,13 +15,11 @@
###########################################################################
# Print some basic status about the system and compiler
#
if (VERBOSE)
message (STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
message (STATUS "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
message (STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
endif ()
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
message (VERBOSE "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
message (VERBOSE "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
message (VERBOSE "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
###########################################################################
@@ -44,9 +42,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
execute_process (COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (VERBOSE)
message (STATUS "Using gcc ${GCC_VERSION} as the compiler")
endif ()
message (VERBOSE "Using gcc ${GCC_VERSION} as the compiler")
else ()
set (GCC_VERSION 0)
endif ()
@@ -63,26 +59,18 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
set (CMAKE_CXX_COMPILER_ID "AppleClang")
set (CMAKE_COMPILER_IS_APPLECLANG 1)
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" APPLECLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
set (CMAKE_COMPILER_IS_INTELCLANG 1)
string (REGEX MATCH "[0-9]+(\\.[0-9]+)+" INTELCLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
else ()
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
endif ()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set (CMAKE_COMPILER_IS_INTEL 1)
if (VERBOSE)
message (STATUS "Using Intel as the compiler")
endif ()
message (VERBOSE "Using Intel as the compiler")
endif ()
@@ -121,11 +109,11 @@ endif ()
# give more fine-grained control for hiding symbols, because sometimes
# dependent libraries may not be well behaved and need extra hiding.
#
set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
set (CMAKE_CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
set (CMAKE_C_VISIBILITY_PRESET ${CMAKE_CXX_VISIBILITY_PRESET})
if (${CMAKE_CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
@@ -191,6 +179,7 @@ endif ()
if (MSVC)
# Microsoft specific options
add_compile_options (/W1)
add_compile_options (/MP)
add_definitions (-D_CRT_SECURE_NO_DEPRECATE)
add_definitions (-D_CRT_SECURE_NO_WARNINGS)
add_definitions (-D_CRT_NONSTDC_NO_WARNINGS)
@@ -314,9 +303,7 @@ if (NOT USE_SIMD STREQUAL "")
else ()
string (REPLACE "," ";" SIMD_FEATURE_LIST ${USE_SIMD})
foreach (feature ${SIMD_FEATURE_LIST})
if (VERBOSE)
message (STATUS "SIMD feature: ${feature}")
endif ()
message (VERBOSE "SIMD feature: ${feature}")
if (MSVC OR CMAKE_COMPILER_IS_INTEL)
set (SIMD_COMPILE_FLAGS ${SIMD_COMPILE_FLAGS} "/arch:${feature}")
else ()
@@ -371,9 +358,7 @@ if (NOT MSVC AND NOT APPLE AND NOT ANDROID)
message (FATAL_ERROR "Compiler needs libatomic, but not found")
endif ()
else ()
if (VERBOSE)
message (STATUS "Compiler supports std::atomic, no libatomic necessary")
endif ()
message (VERBOSE "Compiler supports std::atomic, no libatomic necessary")
endif ()
endif ()
@@ -476,10 +461,8 @@ if (CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES "clang-tidy"
DOC "Path to clang-tidy executable")
message (STATUS "CLANG_TIDY_EXE ${CLANG_TIDY_EXE}")
if (CLANG_TIDY_EXE AND NOT ${CMAKE_VERSION} VERSION_LESS 3.6)
set (CMAKE_CXX_CLANG_TIDY
"${CLANG_TIDY_EXE}"
)
if (CLANG_TIDY_EXE)
set (CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}")
if (CLANG_TIDY_ARGS)
list (APPEND CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_ARGS})
endif ()
@@ -573,9 +556,7 @@ else ()
set (SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
CACHE STRING "Set the SO version for dynamic libraries")
endif ()
if (VERBOSE)
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
endif ()
message(VERBOSE "Setting SOVERSION to: ${SOVERSION}")
###########################################################################
@@ -637,9 +618,7 @@ else ()
# add the automatically determined parts of the RPATH that
# point to directories outside the build tree to the install RPATH
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if (VERBOSE)
message (STATUS "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
endif ()
message (VERBOSE "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
endif ()
+16 -13
View File
@@ -99,8 +99,8 @@ checked_find_package (TIFF REQUIRED
# IlmBase & OpenEXR
checked_find_package (OpenEXR REQUIRED
VERSION_MIN 2.3
RECOMMEND_MIN 2.4
VERSION_MIN 2.4
RECOMMEND_MIN 3.1
PRINT IMATH_INCLUDES OPENEXR_INCLUDES)
# Force Imath includes to be before everything else to ensure that we have
# the right Imath/OpenEXR version, not some older version in the system
@@ -123,18 +123,14 @@ set (OPENIMAGEIO_IMATH_TARGETS
# For OpenEXR >= 2.4/2.5 with reliable exported targets
$<TARGET_NAME_IF_EXISTS:IlmBase::Imath>
$<TARGET_NAME_IF_EXISTS:IlmBase::Half>
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex>
# For OpenEXR <= 2.3:
${ILMBASE_LIBRARIES} )
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex> )
set (OPENIMAGEIO_OPENEXR_TARGETS
# For OpenEXR/Imath 3.x:
$<TARGET_NAME_IF_EXISTS:OpenEXR::OpenEXR>
# For OpenEXR >= 2.4/2.5 with reliable exported targets
$<TARGET_NAME_IF_EXISTS:OpenEXR::IlmImf>
$<TARGET_NAME_IF_EXISTS:IlmBase::IlmThread>
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex>
# For OpenEXR <= 2.3:
${OPENEXR_LIBRARIES} )
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex> )
set (OPENIMAGEIO_IMATH_DEPENDENCY_VISIBILITY "PUBLIC" CACHE STRING
"Should we expose Imath library dependency as PUBLIC or PRIVATE")
set (OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH OFF CACHE BOOL
@@ -183,9 +179,16 @@ checked_find_package (OpenColorIO
DEFINITIONS -DUSE_OCIO=1 -DUSE_OPENCOLORIO=1
# PREFER_CONFIG
)
if (NOT OpenColorIO_FOUND)
if (OpenColorIO_FOUND)
option (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS
"For deveoper debugging/testing ONLY! Disable OCIO 2.2 builtin configs." OFF)
if (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}")
add_compile_definitions(OIIO_DISABLE_BUILTIN_OCIO_CONFIGS)
endif ()
else ()
set (OpenColorIO_FOUND 0)
endif ()
checked_find_package (OpenCV 3.0
DEFINITIONS -DUSE_OPENCV=1)
@@ -212,8 +215,7 @@ if (APPLE AND LIBHEIF_VERSION VERSION_GREATER_EQUAL 1.10 AND LIBHEIF_VERSION VER
endif ()
checked_find_package (LibRaw
RECOMMEND_MIN 0.18
RECOMMEND_MIN_REASON "for ACES support and better camera metadata"
VERSION_MIN 0.18
PRINT LibRaw_r_LIBRARIES)
if (LibRaw_FOUND AND LibRaw_VERSION VERSION_LESS 0.20 AND CMAKE_CXX_STANDARD VERSION_GREATER_EQUAL 17)
message (STATUS "${ColorYellow}WARNING When building for C++17, LibRaw should be 0.20 or higher (found ${LibRaw_VERSION}). You may get errors, depending on the compiler.${ColorReset}")
@@ -315,7 +317,7 @@ endmacro()
option (BUILD_FMT_FORCE "Force local download/build of fmt even if installed" OFF)
option (BUILD_MISSING_FMT "Local download/build of fmt if not installed" ON)
option (INTERNALIZE_FMT "Copy fmt headers into <install>/include/OpenImageIO/detail/fmt" ON)
set (BUILD_FMT_VERSION "9.0.0" CACHE STRING "Preferred fmtlib/fmt version, when downloading/building our own")
set (BUILD_FMT_VERSION "10.0.0" CACHE STRING "Preferred fmtlib/fmt version, when downloading/building our own")
macro (find_or_download_fmt)
# If we weren't told to force our own download/build of fmt, look
@@ -348,7 +350,8 @@ macro (find_or_download_fmt)
else ()
set (OIIO_USING_FMT_LOCAL FALSE)
endif ()
checked_find_package (fmt REQUIRED)
checked_find_package (fmt REQUIRED
VERSION_MIN 7.0)
endmacro()
find_or_download_fmt()
+1 -3
View File
@@ -55,9 +55,7 @@ macro (fancy_add_executable)
if (CMAKE_UNITY_BUILD AND UNITY_BUILD_MODE STREQUAL GROUP)
set_source_files_properties(${_target_SRC} PROPERTIES
UNITY_GROUP ${_target_NAME})
if (VERBOSE)
message (STATUS "Unity group ${_target_NAME} = ${_target_SRC}")
endif ()
message (VERBOSE "Unity group ${_target_NAME} = ${_target_SRC}")
endif ()
if (_target_NAME_INSTALL_enabled)
install_targets (${_target_NAME})
+4 -164
View File
@@ -1,5 +1,5 @@
# 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/OpenImageIO/oiio
# Module to find OpenEXR and Imath.
@@ -7,7 +7,7 @@
# I'm afraid this is a mess, due to needing to support a wide range of
# OpenEXR versions.
#
# For OpenEXR & Imath 3.0, this will establish the following imported
# For OpenEXR & Imath 3.x, this will establish the following imported
# targets:
#
# Imath::Imath
@@ -24,14 +24,12 @@
# IlmBase::IlmThread
# OpenEXR::IlmImf
#
# For all versions -- but for OpenEXR < 2.4 the only thing this sets --
# are the following CMake variables:
# For all version, the following CMake variables:
#
# OPENEXR_FOUND true, if found
# OPENEXR_INCLUDES directory where OpenEXR headers are found
# OPENEXR_LIBRARIES libraries for OpenEXR + IlmBase
# OPENEXR_VERSION OpenEXR version (accurate for >= 2.0.0,
# otherwise will just guess 1.6.1)
# OPENEXR_VERSION OpenEXR version
# IMATH_INCLUDES directory where Imath headers are found
# ILMBASE_INCLUDES directory where IlmBase headers are found
# ILMBASE_LIBRARIES libraries just IlmBase
@@ -111,162 +109,4 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
string(REGEX REPLACE "include/OpenEXR$" "include" IMATH_INCLUDES "${IMATH_INCLUDES}")
string(REGEX REPLACE "include/OpenEXR$" "include" OPENEXR_INCLUDES "${OPENEXR_INCLUDES}")
else ()
# OpenEXR 2.x older versions without a config or whose configs we don't
# trust.
set (FOUND_OPENEXR_WITH_CONFIG 0)
# Other standard issue macros
include (FindPackageHandleStandardArgs)
include (SelectLibraryConfigurations)
find_package (ZLIB REQUIRED)
# Link with pthreads if required
find_package (Threads)
if (CMAKE_USE_PTHREADS_INIT)
set (ILMBASE_PTHREADS ${CMAKE_THREAD_LIBS_INIT})
endif ()
# Attempt to find OpenEXR with pkgconfig
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
if (NOT Ilmbase_ROOT AND NOT ILMBASE_ROOT
AND NOT DEFINED ENV{Ilmbase_ROOT} AND NOT DEFINED ENV{ILMBASE_ROOT})
pkg_check_modules(_ILMBASE QUIET IlmBase>=2.0.0)
endif ()
if (NOT OpenEXR_ROOT AND NOT OPENEXR_ROOT
AND NOT DEFINED ENV{OpenEXR_ROOT} AND NOT DEFINED ENV{OPENEXR_ROOT})
pkg_check_modules(_OPENEXR QUIET OpenEXR>=2.0.0)
endif ()
endif (PKG_CONFIG_FOUND)
# List of likely places to find the headers -- note priority override of
# ${OPENEXR_ROOT}/include.
# ILMBASE is needed in case ilmbase an openexr are installed in separate
# directories, like NixOS does
set (GENERIC_INCLUDE_PATHS
${OPENEXR_ROOT}/include
$ENV{OPENEXR_ROOT}/include
${ILMBASE_ROOT}/include
$ENV{ILMBASE_ROOT}/include
${_ILMBASE_INCLUDEDIR}
${_OPENEXR_INCLUDEDIR}
/usr/local/include
/usr/include
/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
/sw/include
/opt/local/include )
# Find the include file locations.
find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h
HINTS ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}
${GENERIC_INCLUDE_PATHS} )
find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
HINTS ${OPENEXR_INCLUDE_DIR}
${GENERIC_INCLUDE_PATHS} )
# Try to figure out version number
if (DEFINED _OPENEXR_VERSION AND NOT "${_OPENEXR_VERSION}" STREQUAL "")
set (OPENEXR_VERSION "${_OPENEXR_VERSION}")
set (OpenEXR_VERSION "${_OPENEXR_VERSION}")
string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OpenEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OpenEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
elseif (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
# Must be at least 2.0
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_STRING .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" OpenEXR_VERSION ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MAJOR .*$")
string (REGEX MATCHALL "[0-9]+" OpenEXR_VERSION_MAJOR ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MINOR .*$")
string (REGEX MATCHALL "[0-9]+" OpenEXR_VERSION_MINOR ${TMP})
else ()
# Assume an old one, predates 2.x that had versions
set (OPENEXR_VERSION 1.6.1)
set (OpenEXR_VERSION 1.6.1)
set (OpenEXR_VERSION_MAJOR 1)
set (OpenEXR_VERSION_MINOR 6)
endif ()
# List of likely places to find the libraries -- note priority override of
# ${OPENEXR_ROOT}/lib.
set (GENERIC_LIBRARY_PATHS
${OPENEXR_ROOT}/lib
${ILMBASE_ROOT}/lib
${OPENEXR_INCLUDE_PATH}/../lib
${ILMBASE_INCLUDE_PATH}/../lib
${_ILMBASE_LIBDIR}
${_OPENEXR_LIBDIR}
/usr/local/lib
/usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/usr/lib
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/sw/lib
/opt/local/lib
$ENV{PROGRAM_FILES}/OpenEXR/lib/static )
# message (STATUS "Generic lib paths: ${GENERIC_LIBRARY_PATHS}")
# Handle request for static libs by altering CMAKE_FIND_LIBRARY_SUFFIXES.
# We will restore it at the end of this file.
set (_openexr_orig_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
if (OpenEXR_USE_STATIC_LIBS)
if (WIN32)
set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else ()
set (CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif ()
endif ()
# Look for the libraries themselves, for all the components.
# This is complicated because the OpenEXR libraries may or may not be
# built with version numbers embedded.
set (_openexr_components IlmThread IlmImf Imath Iex Half)
foreach (COMPONENT ${_openexr_components})
string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
# First try with the version embedded
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY
NAMES ${COMPONENT}-${OpenEXR_VERSION_MAJOR}_${OpenEXR_VERSION_MINOR}
${COMPONENT}
${COMPONENT}-${OpenEXR_VERSION_MAJOR}_${OpenEXR_VERSION_MINOR}_d
${COMPONENT}_d
HINTS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
${GENERIC_LIBRARY_PATHS} )
endforeach ()
find_package_handle_standard_args (OpenEXR
REQUIRED_VARS ILMBASE_INCLUDE_PATH OPENEXR_INCLUDE_PATH
OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY
OPENEXR_IEX_LIBRARY OPENEXR_HALF_LIBRARY
)
if (OPENEXR_FOUND)
set (OPENEXR_VERSION_MAJOR ${OpenEXR_VERSION_MAJOR})
set (OPENEXR_VERSION_MINOR ${OpenEXR_VERSION_MINOR})
set (Imath_VERSION_MAJOR ${OpenEXR_VERSION_MAJOR})
set (Imath_VERSION_MINOR ${OpenEXR_VERSION_MINOR})
set (ILMBASE_FOUND TRUE)
set (ILMBASE_INCLUDES ${ILMBASE_INCLUDE_PATH})
set (IMATH_INCLUDES ${ILMBASE_INCLUDE_PATH})
set (OPENEXR_INCLUDES ${OPENEXR_INCLUDE_PATH})
set (ILMBASE_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
set (IMATH_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
set (OPENEXR_INCLUDE_DIR ${OPENEXR_INCLUDE_PATH})
set (ILMBASE_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ILMBASE_PTHREADS} CACHE STRING "The libraries needed to use IlmBase")
set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${ILMBASE_LIBRARIES} ${ZLIB_LIBRARIES} CACHE STRING "The libraries needed to use OpenEXR")
set (FINDOPENEXR_FALLBACK TRUE)
endif ()
mark_as_advanced(
OPENEXR_ILMIMF_LIBRARY
OPENEXR_IMATH_LIBRARY
OPENEXR_IEX_LIBRARY
OPENEXR_HALF_LIBRARY
OPENEXR_VERSION)
# Restore the original CMAKE_FIND_LIBRARY_SUFFIXES
set (CMAKE_FIND_LIBRARY_SUFFIXES ${_openexr_orig_suffixes})
endif ()
+1 -3
View File
@@ -16,9 +16,7 @@ find_package (pugixml CONFIG)
if (TARGET pugixml::pugixml)
# New pugixml (>= 1.11) has nice config files we can rely on and makes a
# pugixml::pugixml target.
if (VERBOSE)
message (STATUS "Found CONFIG for pugixml (>=1.11)")
endif ()
message (VERBOSE "Found CONFIG for pugixml (>=1.11)")
set (PUGIXML_FOUND true)
set (pugixml_FOUND true)
+4 -8
View File
@@ -52,11 +52,9 @@ macro (find_python)
if (NOT DEFINED PYTHON_SITE_DIR)
set (PYTHON_SITE_DIR "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_FOUND}/site-packages/OpenImageIO")
endif ()
if (VERBOSE)
message (STATUS " Python site packages dir ${PYTHON_SITE_DIR}")
message (STATUS " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
message (STATUS " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
endif ()
message (VERBOSE " Python site packages dir ${PYTHON_SITE_DIR}")
message (VERBOSE " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
message (VERBOSE " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
endmacro()
@@ -114,9 +112,7 @@ macro (setup_python_module)
# This is only needed for SpComp2
if (PYLIB_INCLUDE_SONAME)
if (VERBOSE)
message(STATUS "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
endif ()
message(VERBOSE "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
set_target_properties(${target_name} PROPERTIES
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
SOVERSION ${SOVERSION} )
+22 -17
View File
@@ -69,7 +69,8 @@ macro (oiio_add_tests)
set (_test_disabled 1)
endif ()
endforeach ()
if (0 AND OpenColorIO_VERSION VERSION_GREATER_EQUAL 2.2)
if (OpenColorIO_VERSION VERSION_GREATER_EQUAL 2.2
AND NOT (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}"))
# For OCIO 2.2+, have the testsuite use the default built-in config
list (APPEND _ats_ENVIRONMENT "OCIO=ocio://default"
"OIIO_TESTSUITE_OCIOCONFIG=ocio://default")
@@ -124,9 +125,7 @@ macro (oiio_add_tests)
endif()
endforeach ()
if (VERBOSE)
message (STATUS "TESTS: ${_ats_UNPARSED_ARGUMENTS}")
endif ()
message (VERBOSE "TESTS: ${_ats_UNPARSED_ARGUMENTS}")
endif ()
endmacro ()
@@ -140,6 +139,7 @@ macro (oiio_add_all_tests)
# Freestanding tests:
oiio_add_tests (
cmake-consumer
docs-examples-cpp
iinfo igrep
nonwhole-tiles
oiiotool
@@ -185,6 +185,7 @@ macro (oiio_add_all_tests)
texture-stats
texture-threadtimes
texture-env
texture-colorspace
)
oiio_add_tests (${all_texture_tests})
# Duplicate texture tests with batch mode
@@ -208,6 +209,7 @@ macro (oiio_add_all_tests)
# libraries to run correctly.
if (USE_PYTHON AND NOT BUILD_OIIOUTIL_ONLY AND NOT SANITIZE)
oiio_add_tests (
docs-examples-python
python-colorconfig
python-deep
python-imagebuf
@@ -274,12 +276,18 @@ macro (oiio_add_all_tests)
set (all_openexr_tests
openexr-suite openexr-multires openexr-chroma
openexr-v2 openexr-window perchannel oiiotool-deep)
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.1.10)
# OpenEXR 3.1.10 is the first release where the exr core library
# properly supported all compression types (DWA in particular).
list (APPEND all_openexr_tests openexr-compression)
endif ()
# Run all OpenEXR tests without core library
oiio_add_tests (${all_openexr_tests}
ENVIRONMENT OPENIMAGEIO_OPTIONS=openexr:core=0
IMAGEDIR openexr-images
URL http://github.com/AcademySoftwareFoundation/openexr-images)
# For OpenEXR >= 3.1, be sure to test with the core option on
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.1)
# For OpenEXR >= 3.1, be sure to test with the core option on
oiio_add_tests (${all_openexr_tests}
SUFFIX ".core"
ENVIRONMENT OPENIMAGEIO_OPTIONS=openexr:core=1
@@ -360,18 +368,15 @@ function (oiio_get_test_data name)
if (IS_DIRECTORY "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
AND NOT EXISTS "${CMAKE_BINARY_DIR}/testsuite/${name}")
set (_ogtd_LINK_RESULT "")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
# Just make a link if we can
message (STATUS "Linking ${name} from ${OIIO_LOCAL_TESTDATA_ROOT}/${name}")
file (CREATE_LINK "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
"${CMAKE_BINARY_DIR}/testsuite/${name}"
SYMBOLIC RESULT _ogtd_LINK_RESULT)
# Note: Using 'COPY_ON_ERROR' in the above command should have prevented the need to
# have the manual fall-back below. However, there's been at least one case where a user
# noticed that copying did not happen if creating the link failed (CMake 3.24). We can
# adjust this in the future if CMake behavior improves.
message (STATUS "Link result ${_ogtd_LINK_RESULT}")
endif ()
message (STATUS "Linking ${name} from ${OIIO_LOCAL_TESTDATA_ROOT}/${name}")
file (CREATE_LINK "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
"${CMAKE_BINARY_DIR}/testsuite/${name}"
SYMBOLIC RESULT _ogtd_LINK_RESULT)
# Note: Using 'COPY_ON_ERROR' in the above command should have prevented the need to
# have the manual fall-back below. However, there's been at least one case where a user
# noticed that copying did not happen if creating the link failed (CMake 3.24). We can
# adjust this in the future if CMake behavior improves.
message (VERBOSE "Link result ${_ogtd_LINK_RESULT}")
if (NOT _ogtd_LINK_RESULT EQUAL 0)
# Older cmake or failure to link -- copy
message (STATUS "Copying ${name} from ${OIIO_LOCAL_TESTDATA_ROOT}/${name}")
+4
View File
@@ -5,6 +5,10 @@
#pragma once
// Some documentation for the DDS format:
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-reference
OIIO_PLUGIN_NAMESPACE_BEGIN
+25 -1
View File
@@ -37,6 +37,7 @@ public:
{
return feature == "ioproxy";
}
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& spec,
const ImageSpec& config) override;
@@ -101,6 +102,8 @@ private:
/// Helper function: performs the actual pixel decoding.
bool internal_readimg(unsigned char* dst, int w, int h, int d);
static bool validate_signature(uint32_t signature);
};
static TypeDesc::BASETYPE
@@ -316,6 +319,27 @@ OIIO_PLUGIN_EXPORTS_END
bool
DDSInput::validate_signature(uint32_t signature)
{
return signature == DDS_MAKE4CC('D', 'D', 'S', ' ');
}
bool
DDSInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;
uint32_t magic {};
const size_t numRead = ioproxy->pread(&magic, sizeof(magic), 0);
return numRead == sizeof(magic) && validate_signature(magic);
}
bool
DDSInput::open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config)
@@ -379,7 +403,7 @@ DDSInput::open(const std::string& name, ImageSpec& newspec)
// sanity checks - valid 4CC, correct struct sizes and flags which should
// be always present, regardless of the image type, size etc., also check
// for impossible flag combinations
if (m_dds.fourCC != DDS_MAKE4CC('D', 'D', 'S', ' ') || m_dds.size != 124
if (!validate_signature(m_dds.fourCC) || m_dds.size != 124
|| m_dds.fmt.size != 32 || !(m_dds.caps.flags1 & DDS_CAPS1_TEXTURE)
|| !(m_dds.flags & DDS_CAPS) || !(m_dds.flags & DDS_PIXELFORMAT)
|| (m_dds.caps.flags2 & DDS_CAPS2_VOLUME
+98 -40
View File
@@ -168,6 +168,8 @@ Z component of a normal map. This applies to images using DXT5 compression
and images using BC5/ATI2 compression (normal X & Y components are in
red & green channels).
**Attributes**
.. list-table::
:widths: 30 10 65
:header-rows: 1
@@ -215,27 +217,9 @@ When the attribute value is set to non-zero (default is zero), any input
image using BC5/ATI2 compression format is assumed to be a normal map,
even if pixel format "normal map" flag is not set.
**Configuration settings for DDS output**
When opening an DDS ImageOutput, the following special metadata tokens
control aspects of the writing itself:
.. list-table::
:widths: 30 10 65
:header-rows: 1
* - Output Configuration Attribute
- Type
- Meaning
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by writing to a memory buffer.
**Custom I/O Overrides**
DDS supports the "custom I/O" feature via the
DDS input supports the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
@@ -326,15 +310,15 @@ control aspects of the writing itself:
will keep unaltered pixel values (versus the default OIIO behavior
of automatically converting from RGB to the designated color space
as the pixels are written).
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by writing to memory rather than the file system.
* - ``oiio:dither``
- int
- If nonzero and outputting UINT8 values in the file from a source of
higher bit depth, will add a small amount of random dither to combat
the appearance of banding.
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by writing to memory rather than the file system.
**Custom I/O Overrides**
@@ -647,7 +631,7 @@ control aspects of the writing itself:
**Custom I/O Overrides**
GIF supports the "custom I/O" feature via the
GIF input and output support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
@@ -682,6 +666,7 @@ applications and to distribute HDR environment maps. But newer formats with
native HDR support, such as OpenEXR, are vastly superior and should be
preferred except when legacy file access is required.
**Attributes**
.. list-table::
:widths: 30 10 65
@@ -695,7 +680,8 @@ preferred except when legacy file access is required.
- encodes the orientation (see Section :ref:`sec-metadata-orientation`)
* - ``oiio:ColorSpace``
- string
- Color space (see Section :ref:`sec-metadata-color`).
- Color space (see Section :ref:`sec-metadata-color`). We currently
assume that any RGBE files encountered are linear with sRGB primaries.
* - ``oiio:Gamma``
- float
- the gamma correction specified in the RGBE header (if it's gamma corrected).
@@ -738,7 +724,7 @@ control aspects of the writing itself:
**Custom I/O Overrides**
HDR supports the "custom I/O" feature via the
HDR input and output support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
@@ -884,6 +870,8 @@ IFF
IFF files are used by Autodesk Maya and use the file extension :file:`.iff`.
**Attributes**
.. list-table::
:widths: 30 10 65
:header-rows: 1
@@ -1062,7 +1050,7 @@ control aspects of the writing itself:
**Custom I/O Overrides**
JPEG supports the "custom I/O" feature
JPEG input and output support the "custom I/O" feature
via the `ImageInput::set_ioproxy()` method and the special
``"oiio:ioproxy"`` attributes (see Section :ref:`sec-imageinput-ioproxy`).
@@ -1478,6 +1466,8 @@ coordinate mapping. Layers may be scalar (1 channel) or vector (3 channel)
fields, and the voxel data are always `float`. OpenVDB files always
report as tiled, using the leaf dimension size.
**Attributes**
.. list-table::
:widths: 30 10 65
:header-rows: 1
@@ -1785,7 +1775,7 @@ Lab or duotone modes.
**Custom I/O Overrides**
PSD supports the "custom I/O" feature via the special ``"oiio:ioproxy"``
PSD output supports the "custom I/O" feature via the special ``"oiio:ioproxy"``
attributes (see Sections :ref:`sec-imageoutput-ioproxy` and
:ref:`sec-imageinput-ioproxy`) as well as the `set_ioproxy()` methods.
@@ -1806,6 +1796,7 @@ Ptex files, but the TextureSystem doesn't properly filter across face
boundaries when using it as a texture. OpenImageIO currently does not write
Ptex files at all.
**Attributes**
.. list-table::
:widths: 30 10 65
@@ -2024,6 +2015,24 @@ software developed at Wavefront. RLA files commonly use the file extension
- float
- the gamma correction value (if specified).
**Configuration settings for RLA input**
When opening a RLA ImageInput with a *configuration* (see
Section :ref:`sec-input-with-config`), the following special configuration
options are supported:
.. list-table::
:widths: 30 10 65
:header-rows: 1
* - Input Configuration Attribute
- Type
- Meaning
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by reading from memory rather than the file system.
**Configuration settings for RLA output**
When opening a RLA ImageOutput, the following special metadata tokens
@@ -2041,6 +2050,17 @@ control aspects of the writing itself:
- If nonzero and outputting UINT8 values in the file from a source of
higher bit depth, will add a small amount of random dither to combat
the appearance of banding.
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by reading from memory rather than the file system.
**Custom I/O Overrides**
RLA input and output support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
**Limitations**
@@ -2081,6 +2101,24 @@ otherwise: no support for tiles, no MIPmaps, no multi-subimage, only 8- and
- string
- Image name.
**Configuration settings for SGI input**
When opening a SGI ImageInput with a *configuration* (see
Section :ref:`sec-input-with-config`), the following special configuration
options are supported:
.. list-table::
:widths: 30 10 65
:header-rows: 1
* - Input Configuration Attribute
- Type
- Meaning
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by reading from memory rather than the file system.
**Configuration settings for SGI output**
When opening an SGI ImageOutput, the following special metadata tokens
@@ -2098,8 +2136,19 @@ control aspects of the writing itself:
- If nonzero and outputting UINT8 values in the file from a source of
higher bit depth, will add a small amount of random dither to combat
the appearance of banding.
* - ``oiio:ioproxy``
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by reading from memory rather than the file system.
**Custom I/O Overrides**
SGI input and output support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
|
.. _sec-bundledplugins-pic:
@@ -2115,6 +2164,8 @@ The Softimage PIC format is sometimes used for legacy apps, but has little
merit otherwise, so currently OpenImageIO only reads Softimage files and is
unable to write them.
**Attributes**
.. list-table::
:widths: 30 10 65
:header-rows: 1
@@ -2259,7 +2310,7 @@ control aspects of the writing itself:
**Custom I/O Overrides**
DDS supports the "custom I/O" feature via the
Targa input and output support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.
@@ -2445,9 +2496,13 @@ aspects of the writing itself:
TIFF files despite their being legal.
* - ``tiff:ColorSpace``
- string
- Requests that the file be saved with a non-RGB color spaces. Choices
are ``RGB``, ``CMYK``. (``YCbCr``, ``CIELAB``, ``ICCLAB``,
``ITULAB`` are not yet supported.)
- Requests that the RGB image be converted and saved in the TIFF file in
a non-RGB color space. Choices are ``RGB``, ``CMYK``. (Note that
``YCbCr``, ``CIELAB``, ``ICCLAB``, ``ITULAB`` are not yet supported
for convertion. However, if the `oiio:ColorSpace` is one of those,
meaning that the image data is presumed to already be in that
space, the TIFF PhotometricInterpretation tag will be set to convey
this information.)
* - ``tiff:zipquality``
- int
- A time-vs-space knob for ``zip`` compression, ranging from 1-9
@@ -2475,18 +2530,17 @@ aspects of the writing itself:
**TIFF compression modes**
The full list of possible TIFF compression mode values are as
follows ($ ^*$ indicates that OpenImageIO can write that format, and is not
part of the format name):
follows.
``none`` $ ^*$
``lzw`` $ ^*$
``zip`` $ ^*$
``none`` :sup:`*`
``lzw`` :sup:`*`
``zip`` :sup:`*`
``ccitt_t4``
``ccitt_t6``
``ccittfax3``
``ccittfax4``
``ccittrle2``
``ccittrle`` $ ^*$
``ccittrle`` :sup:`*`
``dcs``
``isojbig``
``IT8BL``
@@ -2494,11 +2548,11 @@ part of the format name):
``IT8LW``
``IT8MP``
``jp2000``
``jpeg`` $ ^*$
``jpeg`` :sup:`*`
``lzma``
``next``
``ojpeg``
``packbits`` $ ^*$
``packbits`` :sup:`*`
``pixarfilm``
``pixarlog``
``sgilog24``
@@ -2507,6 +2561,10 @@ part of the format name):
``T85``
``thunderscan``
:sup:`*` indicates that OpenImageIO can write that format, and is not
part of the format name. The compression types without the asterisk are
supported for reading but not for writing.
**Custom I/O Overrides**
TIFF input and output support the "custom I/O" feature
+7
View File
@@ -286,6 +286,13 @@ just exist in the OIIO namespace as general utilities. (See
.. doxygenfunction:: get_extension_map
.. _sec-startupshutdown:
Startup and Shutdown
==========================================
.. doxygenfunction:: shutdown
|
+46 -75
View File
@@ -18,42 +18,19 @@ to a file:
.. tabs::
.. code-tab:: c++
.. tab:: C++
.. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imageoutput.cpp
:language: c++
:start-after: BEGIN-imageoutput-simple
:end-before: END-imageoutput-simple
#include <OpenImageIO/imageio.h>
using namespace OIIO;
...
.. tab:: Python
const char *filename = "foo.jpg";
const int xres = 640, yres = 480;
const int channels = 3; // RGB
unsigned char pixels[xres * yres * channels];
.. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imageoutput.py
:language: py
:start-after: BEGIN-imageoutput-simple
:end-before: END-imageoutput-simple
std::unique_ptr<ImageOutput> out = ImageOutput::create (filename);
if (! out)
return;
ImageSpec spec (xres, yres, channels, TypeDesc::UINT8);
out->open (filename, spec);
out->write_image (TypeDesc::UINT8, pixels);
out->close ();
.. code-tab:: py
import OpenImageIO as oiio
import numpy as np
filename = "foo.jpg"
xres = 640
yres = 480
channels = 3 # RGB
pixels = np.zeros((yres, xres, channels), dtype=np.uint8)
out = oiio.ImageOutput.create (filename)
if out:
spec = oiio.ImageSpec(xres, yres, channels, 'uint8')
out.open (filename, spec)
out.write_image (pixels)
out.close ()
This little bit of code does a surprising amount of useful work:
@@ -73,7 +50,7 @@ This little bit of code does a surprising amount of useful work:
out = ImageOutput.create (filename)
* Open the file, write the correct headers, and in all other important ways
prepare a file with the given dimensions (640 x 480), number of color
prepare a file with the given dimensions (320 x 240), number of color
channels (3), and data format (unsigned 8-bit integer).
.. tabs::
@@ -172,33 +149,26 @@ time, one tile at a time, or by individual rectangles.
Writing individual scanlines
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Individual scanlines may be written using the ``writescanline()`` API call:
Individual scanlines may be written using the ``write_scanline()`` API call:
.. tabs::
.. code-tab:: c++
.. tab:: C++
.. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imageoutput.cpp
:language: c++
:start-after: BEGIN-imageoutput-scanlines
:end-before: END-imageoutput-scanlines
:dedent: 4
unsigned char scanline[xres*channels];
out->open (filename, spec);
int z = 0; // Always zero for 2D images
for (int y = 0; y < yres; ++y) {
... generate data in scanline[0..xres*channels-1] ...
out->write_scanline (y, z, TypeDesc::UINT8, scanline);
}
out->close ();
.. tab:: Python
.. code-tab:: py
.. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imageoutput.py
:language: py
:start-after: BEGIN-imageoutput-scanlines
:end-before: END-imageoutput-scanlines
:dedent: 8
out.open (filename, spec)
z = 0 # Always zero for 2D images
for y in range(yres) :
# generate data in scanline[0..xres*channels-1] ...
scanline = ...
out.write_scanline (y, z, scanline)
}
out.close ()
The first two arguments to ``writescanline()`` specify which scanline is
The first two arguments to ``write_scanline()`` specify which scanline is
being written by its vertical (*y*) scanline number (beginning with 0)
and, for volume images, its slice (*z*) number (the slice number should
be 0 for 2D non-volume images). This is followed by a `TypeDesc`
@@ -212,7 +182,7 @@ All ``ImageOutput`` implementations will accept scanlines in strict order
any). See Section :ref:`sec-imageoutput-random-access-pixels` for details
on out-of-order or repeated scanlines.
The full description of the ``writescanline()`` function may be found
The full description of the ``write_scanline()`` function may be found
in Section :ref:`sec-imageoutput-class-reference`.
Writing individual tiles
@@ -220,7 +190,7 @@ Writing individual tiles
Not all image formats (and therefore not all ``ImageOutput``
implementations) support tiled images. If the format does not support
tiles, then ``writetile()`` will fail. An application using OpenImageIO
tiles, then ``write_tile()`` will fail. An application using OpenImageIO
should gracefully handle the case that tiled output is not available for
the chosen format.
@@ -297,7 +267,7 @@ individual plugin.
out.write_tile (x, y, z, tile)
out.close ()
The first three arguments to ``writetile()`` specify which tile is being
The first three arguments to ``write_tile()`` specify which tile is being
written by the pixel coordinates of any pixel contained in the tile: *x*
(column), *y* (scanline), and *z* (slice, which should always be 0 for 2D
non-volume images). This is followed by a `TypeDesc` describing the data
@@ -311,7 +281,7 @@ All ``ImageOutput`` implementations that support tiles will accept tiles in
strict order of increasing *y* rows, and within each row, increasing *x*
column, without missing any tiles. See
The full description of the ``writetile()`` function may be found
The full description of the ``write_tile()`` function may be found
in Section :ref:`sec-imageoutput-class-reference`.
Writing arbitrary rectangles
@@ -451,15 +421,15 @@ do not attempt to remap values, and do not clamp (except to their full
floating-point range).
It is not required that the pixel data passed to ``writeimage()``,
``writescanline()``, ``writetile()``, or ``write_rectangle()`` actually be
It is not required that the pixel data passed to ``write_image()``,
``write_scanline()``, ``write_tile()``, or ``write_rectangle()`` actually be
in the same data type as that requested as the native pixel data type of the
file. You can fully mix and match data you pass to the various "write"
routines and OpenImageIO will automatically convert from the internal format
to the native file format. For example, the following code will open a TIFF
file that stores pixel data as 16-bit unsigned integers (values ranging from
0 to 65535), compute internal pixel values as floating-point values, with
``writeimage()`` performing the conversion automatically:
``write_image()`` performing the conversion automatically:
.. tabs::
@@ -484,7 +454,7 @@ file that stores pixel data as 16-bit unsigned integers (values ranging from
out.write_image (pixels)
Note that ``writescanline()``, ``writetile()``, and ``write_rectangle()``
Note that ``write_scanline()``, ``write_tile()``, and ``write_rectangle()``
have a parameter that works in a corresponding manner.
@@ -507,13 +477,13 @@ passed to the "write" functions are *contiguous*, that is:
* for 3D volumetric images, the first pixel of slice *z* immediately
follows the last pixel of of slice ``z-1``.
Please note that this implies that data passed to ``writetile()`` be
Please note that this implies that data passed to ``write_tile()`` be
contiguous in the shape of a single tile (not just an offset into a whole
image worth of pixels), and that data passed to ``write_rectangle()`` be
contiguous in the dimensions of the rectangle.
The ``writescanline()`` function takes an optional ``xstride`` argument, and
the ``writeimage()``, ``writetile()``, and ``write_rectangle()`` functions
The ``write_scanline()`` function takes an optional ``xstride`` argument, and
the ``write_image()``, ``write_tile()``, and ``write_rectangle()`` functions
take optional ``xstride``, ``ystride``, and ``zstride`` values that describe
the distance, in *bytes*, between successive pixel columns, rows, and
slices, respectively, of the data you are passing. For any of these values
@@ -910,25 +880,26 @@ The color space hints only describe color channels. You should always pass
alpha, depth, or other non-color channels with linear values.
Here is a simple example of setting up the ``ImageSpec`` when you know that
the pixel values you are writing are linear:
the pixel values you are writing are in your default linear scene-referred
color space:
.. tabs::
.. code-tab:: c++
ImageSpec spec (width, length, channels, format);
spec.attribute ("oiio:ColorSpace", "Linear");
spec.attribute ("oiio:ColorSpace", "scene_linear");
.. code-tab:: py
spec = ImageSpec(width, length, channels, format)
spec.attribute ("oiio:ColorSpace", "Linear")
spec.attribute ("oiio:ColorSpace", "scene_linear")
If a particular ``ImageOutput`` implementation is required (by the rules of
the file format it writes) to have pixels in a particular color space,
the file format it writes) to have pixels in a fixed color space,
then it should try to convert the color values of your image to the right color
space if it is not already in that space. For example, JPEG images
must be in sRGB space, so if you declare your pixels to be ``"Linear"``,
must be in sRGB space, so if you declare your pixels to be ``"scene_linear"``,
the JPEG ``ImageOutput`` will convert to sRGB.
If you leave the ``"oiio:ColorSpace"`` unset, the values will not be
@@ -1151,8 +1122,8 @@ specification of the subimages at the time you first open the file.
out.write_image (pixels[s])
out.close ()
In both of these examples, we have used ``writeimage()``, but of course
``writescanline()``, ``writetile()``, and ``write_rectangle()`` work as you
In both of these examples, we have used ``write_image()``, but of course
``write_scanline()``, ``write_tile()``, and ``write_rectangle()`` work as you
would expect, on the current subimage.
@@ -1277,8 +1248,8 @@ used for texture mapping):
out.close ()
In this example, we have used ``writeimage()``, but of course
``writescanline()``, ``writetile()``, and ``write_rectangle()`` work as you
In this example, we have used ``write_image()``, but of course
``write_scanline()``, ``write_tile()``, and ``write_rectangle()`` work as you
would expect, on the current MIP level.
+155 -19
View File
@@ -136,18 +136,23 @@ contents of an expression may be any of:
`ImageDescription`, or `width`)
* `filename` : the name of the file (e.g., `foo.tif`)
* `file_extension` : the extension of the file (e.g., `tif`)
* `geom` : the pixel data size in the form `640x480+0+0`)
* `full_geom` : the "full" or "display" size)
* `geom` : the pixel data size in the form `640x480+0+0`)
* `nativeformat` : the pixel data type from the file.
* `MINCOLOR` : the minimum value of each channel over the entire image
(channels are comma-separated)
* `MAXCOLOR` : the maximum value of each channel over the entire image
(channels are comma-separated)
* `AVGCOLOR` : the average pixel value of the image (channels are
comma-separated)
* `METABRIEF` : a string containing the brief one-line description that
would be printed with `oiiotool -info`.
* `META` : a multi-line string containing the full metadata that would
be printed with `oiiotool -info -v`.
* `META` : a multi-line string containing the full metadata of the image,
similar to what would be printed with `oiiotool -info -v`.
* `METABRIEF` : a string containing the brief one-line description,
similar to what would be printed that with `oiiotool -info`.
* `METANATIVE` : like `META`, but for the "native" original information from
when the file was read from disk.
* `METANATIVEBRIEF` : like `METABRIEF`, but for the "native" original
information from when the file was read from disk.
* `STATS` : a multi-line string containing the image statistics that would
be printed with `oiiotool -stats`.
@@ -1068,6 +1073,30 @@ output each one to a different file, with names `sub0001.tif`,
frame (rather than the default behavior of exiting immediately and not
even attempting the other frames in the range).
.. option:: --parallel-frames
When iterating over a frame range or views, if this option is used, the
frames will run *concurrently* and not necessarily in any deterministic
order.
Running the range of frames in parallel is helpful in cases where (a)
there are enough frames in the range to make it be better to parallelize
over the range rather than within each operation (rule of thumb: you
should probably have at least as many frames to process as cores
available); (b) it doesn't matter what order the frames are processed in
(e.g., no frames have a dependency on the computed results of earlier
frames); and (c) you have enough memory and I/O bandwidth to handle all
the parallel jobs (probably equal to the number of cores).
Without the `--parallel-frames` option, the frame range will be executed
in increasing numerical order and each frame in the range will run to
completion before the next one starts. Multithreading will be used for the
individual operations done to each frame. This mode is less efficient if
you have more frames than cores available, but it is guaranteed to be safe
even if there are order or data dependencies between your frames, and it
This feature was added to OpenImageIO 2.5.1.
.. option:: --wildcardoff, --wildcardon
These *positional* options turn off (or on) numeric wildcard expansion
@@ -1376,7 +1405,7 @@ Writing images
`:type=` *name*
Set the pixel data type (like `-d`) for this output image (e.g.,
`:uint8`, `uint16`, `half`, `float`, etc.).
`uint8`, `uint16`, `half`, `float`, etc.).
`:bits=` *int*
Set the bits per pixel (if nonstandard for the datatype) for this
output image.
@@ -1666,11 +1695,40 @@ Writing images
.. option:: --printinfo
Prints information and all metadata about the current image.
Prints information and all metadata about the current (top) image. This
behavior is similar to invoking oiiotool with :option:`--info -v`, but it
applies immediately to the current top image, even if it is a "computed"
image (whereas :option:`--info` only applies to images as they are read
from disk).
Optional appended modifiers include:
- `:allsubimages=` *int*
If nonzero, stats will be printed about all subimages of the current
image. (The default is given by whether or not the `-a` option was
used.)
- `:native=1`
Print metadata reflecting the "native" image as it was originally
read from disk. This may have a data type, tile size, or other
items that differ from the current in-memory representation of
the image.
- `:stats=1`
Print statistics about the image (much like the :option:`--stats`
command).
- `:verbose=0`
Overrides the default verbosity (1, on) with a less verbose output.
.. option:: --printstats
Prints detailed statistical information about the current image.
Prints detailed statistical information about the current image. This
behavior is similar to invoking oiiotool with :option:`--stats`, but it
applies immediately to the current top image, even if it is a "computed"
image (whereas :option:`--stats` only applies to images as they are read
from disk).
Optional appended modifiers include:
@@ -1686,8 +1744,8 @@ Writing images
- `:allsubimages=` *int*
If nonzero, stats will be printed about all subimages of the current
image. (The default is zero, meaning that stats will only be printed for
the first subimage of the current image.)
image. (The default is given by whether or not the `-a` option was
used.)
.. option:: --colorcount r1,g1,b1,...:r2,g2,b2,...:...
@@ -2499,6 +2557,38 @@ current top image.
Include/exclude subimages (see :ref:`sec-oiiotool-subimage-modifier`).
.. option:: --normalize
Normalize the top image. Assuming the first three channels represent a 3D
vector, divide each pixel by its length to make it unit length. This
function assumes a 3-channel image that represents a 3-vector, or a
4-channel image that represents a 3-vector plus an alpha value. If an
alpha channel is present, its value is merely copied, and is not part of
the normalization computation.
Optional appended modifiers include:
`:incenter=` *float*
The pixel value that corresponds to a 0.0 vector value for the input.
(default: 0.0)
`:outcenter=` *float*
The pixel value that corresponds to a 0.0 vector value for the output.
(default: 0.0)
`:scale=` *float*
The desired length of the output vectors. (default: 1.0)
Example::
# Normalize a floating point image containing vector values:
oiiotool xyzvectors.exr --normalize -o normalized.exr
# Normalize an unsigned integer image where [-1,1] vector values
# are encoded on [0,1] for both input and output:
oiiotool xyzvectors.tif --normalize:incenter=0.5:outcenter=0.5:scale=0.5 -o normalized.tif
.. option:: --noise
Alter the top image to introduce noise, with the option `:type=`
@@ -3140,11 +3230,29 @@ current top image.
*wscale% x hscale%*
if `width` or `height` is 0, that dimension will be
automatically computed so as to preserve the original aspect ratio.
If `width` or `height` is 0, that dimension will be automatically computed
so as to preserve the original aspect ratio.
By default, the scaling that occurs is to map the *full/display* window
area of the input image to the full/display window of the output image
(determined by the `size` argument). However, a more general warping
can be specified using any of the `:from=`, `:to=`, or `:offset=`
optional modifiers. (These modifiers were added in OpenmageIO 2.5.)
Optional appended modifiers include:
`:from=` *size*
The region (specified in any of the same forms as the *size* argument,
with decimal / partial pixel sizes and offsets allowed) of the source
image that defines the transformational mapping. This defaults to the
full/display window of the source image.
`:to=` *size*
The region (specified in any of the same forms as the *size* argument,
with decimal / partial pixel sizes and offsets allowed) of the
destination image that defines the transformational mapping. This
defaults to the full/display window of the destination image.
`:filter=` *name*
Filter name. The default is `blackman-harris` when increasing
resolution, `lanczos3` when decreasing resolution.
@@ -3155,6 +3263,11 @@ current top image.
`--rangeexpand`, which can reduce visible ringing artifacts when a
filter with negative lobes is used on a very high-contrast HDR image.
`:edgeclamp=` *bool*
If nonzero, clamp the image to the edge pixels before filtering.
This might help with certain edge ringing situations. The default is
0 (off).
`:subimages=` *indices-or-names*
Include/exclude subimages (see :ref:`sec-oiiotool-subimage-modifier`).
@@ -3165,6 +3278,15 @@ current top image.
--resize 300% # increase resolution to 1920x1440
--resize 400x0 # new resolution will be 400x300
# Create a 1024x768 image that is a resized and shifted version
# of the original, where the upper left 100x100 section of the
# original maps to a 200x200 region starting at the 50,50
# coordinates of the new image.
--resize:from=100x100:to=200x200+50+50 1024x768
# Resize to 320x240, but with an additional 1/2 pixel shift in
# each direction.
--resize:offset=+0.5+0.5 320x240
.. option:: --fit <size>
@@ -3976,7 +4098,23 @@ versa).
If you ask for :program:`oiiotool` help (`oiiotool --help`), at the very
bottom you will see the list of all color spaces, looks, and displays that
:program:`oiiotool` knows about.
:program:`oiiotool` knows about. That information (including even more detail)
will be printed with the command `oiiotool --colorconfiginfo`.
.. option:: --colorconfiginfo
Print to the console extensive information about the color management
configuration, including the list of all known color spaces (and their
aliases), looks, displays (and their views), as well as which version
of OpenColorIO is being used, and the path to the configuration file.
This command was added in OIIO 2.4.6.
.. option:: --colorconfig <filename>
Instruct :program:`oiiotool` to read an OCIO configuration from a custom
location. Without this, the default is to use the `$OCIO` environment
variable as a guide for the location of the configuration file.
.. option:: --iscolorspace <colorspace>
@@ -3985,12 +4123,6 @@ bottom you will see the list of all color spaces, looks, and displays that
it only changes :program:`oiiotool`'s understanding of what color space
those those pixels are in.
.. option:: --colorconfig <filename>
Instruct :program:`oiiotool` to read an OCIO configuration from a custom
location. Without this, the default is to use the `$OCIO` environment
variable as a guide for the location of the configuration file.
.. option:: --colorconvert <fromspace> <tospace>
Replace the current image with a new image whose pixels are transformed
@@ -4160,6 +4292,10 @@ bottom you will see the list of all color spaces, looks, and displays that
is 0, meaning the color transformation not will be automatically
bracketed by divide-by-alpha / mult-by-alpha operations.
`inverse=` *val* :
If *val* is nonzero, inverts the color transformation.
`:subimages=` *indices-or-names*
Include/exclude subimages (see :ref:`sec-oiiotool-subimage-modifier`).
+3 -3
View File
@@ -3552,7 +3552,7 @@ Color manipulation
.. code-block:: python
Src = ImageBuf ("tahoe.jpg")
Dst = ImageBufAlgo.colorconvert (Src, "sRGB", "linear")
Dst = ImageBufAlgo.colorconvert (Src, "sRGB", "scene_linear")
@@ -3592,8 +3592,8 @@ Color manipulation
.. py:method:: ImageBuf ImageBufAlgo.ociodisplay (src, display, view, fromspace="", looks="", unpremult=True, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
bool ImageBufAlgo.ociodisplay (dst, src, display, view, fromspace="", looks="", unpremult=True, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
.. py:method:: ImageBuf ImageBufAlgo.ociodisplay (src, display, view, fromspace="", looks="", unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
bool ImageBufAlgo.ociodisplay (dst, src, display, view, fromspace="", looks="", unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
Apply an OpenColorIO "display" transform to the pixel values.
+10 -4
View File
@@ -141,12 +141,18 @@ Color information
The name of the color space of the color channels. Values include:
- `"Linear"` : Color pixel values are known to be scene-linear and
using facility-default color primaries (presumed sRGB/Rec709 color
primaries if otherwise unknown.
- `"scene_linear"` : Color pixel values are known to be scene-linear and
using facility-default color primaries as defined by the OpenColorIO
configuration. Note that `"linear"` is treated as a synonym. (Note: when
no color config is found, this are presumed to use sRGB/Rec709 color
primaries when built against OpenColorIO 2.1 or earlier, or when no OCIO
support is available, but is presumed to be ACEScg when built against
OCIO 2.2 or higher and using its built-in config.)
- `"lin_srgb"` : Color pixel values are known to be linear and
using sRGB/Rec709 color primaries.
- `"sRGB"` : Using standard sRGB response and primaries.
- `"Rec709"` : Using standard Rec709 response and primaries.
- `"ACES"` : ACES color space encoding.
- `"ACEScg"` : ACEScg color space encoding.
- `"AdobeRGB"` : Adobe RGB color space.
- `"KodakLog"` : Kodak logarithmic color space.
- `"GammaX.Y"` : Color values have been gamma corrected
+7 -13
View File
@@ -12,6 +12,7 @@
// But that seems not to be actively maintained.
#include "libdpx/DPX.h"
#include "libdpx/DPXColorConverter.h"
#include "libdpx/DPXHeader.h"
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/strutil.h>
@@ -29,7 +30,7 @@ public:
{
return (feature == "ioproxy");
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
@@ -107,21 +108,14 @@ OIIO_PLUGIN_EXPORTS_END
bool
DPXInput::valid_file(const std::string& filename) const
DPXInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
Filesystem::IOProxy* io
= new Filesystem::IOFile(filename, Filesystem::IOProxy::Mode::Read);
std::unique_ptr<Filesystem::IOProxy> io_uptr(io);
if (!io || io->mode() != Filesystem::IOProxy::Mode::Read)
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;
std::unique_ptr<InStream> stream_uptr(new InStream(io));
if (!stream_uptr)
return false;
dpx::Reader dpx;
dpx.SetInStream(stream_uptr.get());
return dpx.ReadHeader(); // IOFile is automatically closed when destructed
dpx::U32 magic {};
const size_t numRead = ioproxy->pread(&magic, sizeof(magic), 0);
return numRead == sizeof(magic) && dpx::Header::ValidMagicCookie(magic);
}
+19 -33
View File
@@ -142,8 +142,8 @@ bool
DPXOutput::open(const std::string& name, int subimages, const ImageSpec* specs)
{
if (subimages > MAX_DPX_IMAGE_ELEMENTS) {
errorf("DPX does not support more than %d subimages",
MAX_DPX_IMAGE_ELEMENTS);
errorfmt("DPX does not support more than {} subimages",
MAX_DPX_IMAGE_ELEMENTS);
return false;
};
m_subimages_to_write = subimages;
@@ -158,14 +158,7 @@ bool
DPXOutput::open(const std::string& name, const ImageSpec& userspec,
OpenMode mode)
{
if (mode == Create) {
m_subimage = 0;
if (m_subimage_specs.size() < 1) {
m_subimage_specs.resize(1);
m_subimage_specs[0] = userspec;
m_subimages_to_write = 1;
}
} else if (mode == AppendSubimage) {
if (mode == AppendSubimage) {
if (!is_opened()) {
errorfmt("open() with AppendSubimage called but file is not open.");
return false;
@@ -174,28 +167,35 @@ DPXOutput::open(const std::string& name, const ImageSpec& userspec,
write_buffer();
++m_subimage;
if (m_subimage >= m_subimages_to_write) {
errorf("Exceeded the pre-declared number of subimages (%d)",
m_subimages_to_write);
errorfmt("Exceeded the pre-declared number of subimages ({})",
m_subimages_to_write);
return false;
}
return prep_subimage(m_subimage, true);
// Nothing else to do, the header taken care of when we opened with
// Create.
} else if (mode == AppendMIPLevel) {
errorf("DPX does not support MIP-maps");
return false;
}
// From here out, all the heavy lifting is done for Create
OIIO_DASSERT(mode == Create);
if (is_opened())
close(); // Close any already-opened file
ioproxy_retrieve_from_config(userspec);
if (!check_open(mode, userspec, { 0, 1 << 20, 0, 1 << 20, 0, 1, 0, 256 }))
return false;
// From here out, all the heavy lifting is done for Create
OIIO_DASSERT(mode == Create);
ioproxy_retrieve_from_config(m_spec);
if (!ioproxy_use_or_open(name))
return false;
m_subimage = 0;
if (m_subimage_specs.empty()) {
m_subimage_specs.resize(1);
m_subimage_specs[0] = m_spec;
m_subimages_to_write = 1;
}
m_stream = new OutStream(ioproxy());
m_dpx.SetOutStream(m_stream);
m_dpx.Start();
@@ -203,20 +203,6 @@ DPXOutput::open(const std::string& name, const ImageSpec& userspec,
ImageSpec& spec0(m_subimage_specs[m_subimage]); // alias the spec
// Check for things this format doesn't support
if (spec0.width < 1 || spec0.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
spec0.width, spec0.height);
return false;
}
if (spec0.depth < 1)
spec0.depth = 1;
else if (spec0.depth > 1) {
errorf("DPX does not support volume images (depth > 1)");
return false;
}
// some metadata
std::string software = spec0.get_string_attribute("Software", "");
std::string project = spec0.get_string_attribute("DocumentName", "");
+4 -2
View File
@@ -44,8 +44,10 @@ public:
int supports(string_view feature) const override
{
return (feature == "arbitrary_metadata"
|| feature == "exif" // Because of arbitrary_metadata
|| feature == "iptc"); // Because of arbitrary_metadata
|| feature == "exif" // Because of arbitrary_metadata
|| feature == "iptc" // Because of arbitrary_metadata
|| feature == "noimage" // allow metadata only, no pixels
);
}
bool valid_file(const std::string& filename) const override;
bool open(const std::string& name, ImageSpec& spec) override;
+7 -14
View File
@@ -31,7 +31,7 @@ FitsOutput::supports(string_view feature) const
{
return (feature == "multiimage" || feature == "alpha"
|| feature == "nchannels" || feature == "random_access"
|| feature == "arbitrary_metadata"
|| feature == "noimage" || feature == "arbitrary_metadata"
|| feature == "exif" // Because of arbitrary_metadata
|| feature == "iptc"); // Because of arbitrary_metadata
}
@@ -41,14 +41,12 @@ FitsOutput::supports(string_view feature) const
bool
FitsOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
if (mode == AppendMIPLevel) {
errorf("%s does not support MIP levels", format_name());
close();
if (!check_open(mode, spec, { 0, 1 << 30, 0, 1 << 30, 0, 1, 0, 1 << 10 }))
return false;
}
// saving 'name' and 'spec' for later use
m_filename = name;
m_spec = spec;
if (m_spec.format == TypeDesc::UNKNOWN) // if unknown, default to float
m_spec.set_format(TypeDesc::FLOAT);
// FITS only supports signed short and int pixels
@@ -60,12 +58,7 @@ FitsOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
// checking if the file exists and can be opened in WRITE mode
m_fd = Filesystem::fopen(m_filename, mode == AppendSubimage ? "r+b" : "wb");
if (!m_fd) {
errorf("Could not open \"%s\"", m_filename);
return false;
}
if (m_spec.depth != 1) {
errorf("Volume FITS files not supported");
errorfmt("Could not open \"{}\"", m_filename);
return false;
}
@@ -92,7 +85,7 @@ FitsOutput::write_scanline(int y, int /*z*/, TypeDesc format, const void* data,
if (m_spec.width == 0 && m_spec.height == 0)
return true;
if (y > m_spec.height) {
errorf("Attempt to write too many scanlines to %s", m_filename);
errorfmt("Attempt to write too many scanlines to {}", m_filename);
close();
return false;
}
@@ -224,7 +217,7 @@ FitsOutput::create_fits_header(void)
size_t byte_count = fwrite(&header[0], 1, header.size(), m_fd);
if (byte_count != header.size()) {
// FIXME Bad Write
errorf("Bad header write (err %d)", byte_count);
errorfmt("Bad header write (err {})", byte_count);
}
}
+1 -2
View File
@@ -4,8 +4,7 @@
if (GIF_FOUND)
add_oiio_plugin (gifinput.cpp gifoutput.cpp
INCLUDE_DIRS ${GIF_INCLUDE_DIRS}
LINK_LIBRARIES ${GIF_LIBRARIES}
LINK_LIBRARIES GIF::GIF
DEFINITIONS "-DUSE_GIF")
else()
message (WARNING "GIF plugin will not be built")
+9 -25
View File
@@ -97,7 +97,7 @@ private:
ioproxy_clear();
}
bool start_subimage();
bool start_subimage(const ImageSpec& spec);
bool finish_subimage();
};
@@ -126,7 +126,7 @@ GIFOutput::open(const std::string& name, const ImageSpec& newspec,
}
if (mode == AppendMIPLevel) {
errorf("%s does not support MIP levels", format_name());
errorfmt("{} does not support MIP levels", format_name());
return false;
}
@@ -134,8 +134,7 @@ GIFOutput::open(const std::string& name, const ImageSpec& newspec,
if (m_pending_write)
finish_subimage();
++m_subimage;
m_spec = newspec;
return start_subimage();
return start_subimage(newspec);
}
OIIO_ASSERT_MSG(0, "Unknown open mode %d", int(mode));
@@ -148,7 +147,7 @@ bool
GIFOutput::open(const std::string& name, int subimages, const ImageSpec* specs)
{
if (subimages < 1) {
errorf("%s does not support %d subimages.", format_name(), subimages);
errorfmt("{} does not support {} subimages.", format_name(), subimages);
return false;
}
@@ -156,7 +155,6 @@ GIFOutput::open(const std::string& name, int subimages, const ImageSpec* specs)
m_subimage = 0;
m_nsubimages = subimages;
m_subimagespecs.assign(specs, specs + subimages);
m_spec = specs[0];
float fps = m_spec.get_float_attribute("FramesPerSecond", 1.0f);
m_delay = (fps == 0.0f ? 0 : (int)(100.0f / fps));
@@ -164,7 +162,7 @@ GIFOutput::open(const std::string& name, int subimages, const ImageSpec* specs)
if (!ioproxy_use_or_open(name))
return false;
return start_subimage();
return start_subimage(specs[0]);
}
@@ -184,25 +182,11 @@ GIFOutput::close()
bool
GIFOutput::start_subimage()
GIFOutput::start_subimage(const ImageSpec& spec)
{
// Check for things this format doesn't support
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
if (!check_open(Create, spec, { 0, 65535, 0, 65535, 0, 1, 0, 4 },
uint64_t(OpenChecks::Disallow1or2Channel)))
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
if (m_spec.nchannels != 3 && m_spec.nchannels != 4) {
errorf("%s does not support %d-channel images", format_name(),
m_spec.nchannels);
return false;
}
m_spec.set_format(TypeDesc::UINT8); // GIF is only 8 bit
@@ -212,7 +196,7 @@ GIFOutput::start_subimage()
m_spec.height, m_delay, 8 /*bit depth*/,
true /*dither*/);
if (!ok) {
errorf("Could not open \"%s\"", m_filename);
errorfmt("Could not open \"{}\"", m_filename);
return false;
}
}
+18 -6
View File
@@ -41,6 +41,7 @@ public:
{
return feature == "ioproxy";
}
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& spec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
@@ -202,6 +203,19 @@ rgbe2float(float& red, float& green, float& blue, unsigned char rgbe[4])
bool
HdrInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;
char magic[2] {};
const size_t numRead = ioproxy->pread(magic, sizeof(magic), 0);
return numRead == sizeof(magic) && memcmp(magic, "#?", sizeof(magic)) == 0;
}
bool
HdrInput::open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config)
@@ -277,7 +291,10 @@ HdrInput::RGBE_ReadHeader()
if (!line.size())
return false;
m_spec.attribute("oiio:ColorSpace", "linear"); // presume linear
m_spec.attribute("oiio:ColorSpace", "lin_srgb");
// presume linear w/ srgb primaries -- seems like the safest assumption
// for this old file format.
bool found_FORMAT_line = false;
for (int nlines = 0; nlines < 100 /* safety */; ++nlines) {
if (line.size() == 0 || line[0] == '\n') // stop at blank line
@@ -493,11 +510,6 @@ HdrInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
bool
HdrInput::close()
{
// if (m_io_local) {
// // If we allocated our own ioproxy, close it.
// ioproxy_clear();
// }
init(); // Reset to initial state
return true;
}
+2 -24
View File
@@ -204,33 +204,11 @@ bool
HdrOutput::open(const std::string& name, const ImageSpec& newspec,
OpenMode mode)
{
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
if (!check_open(mode, newspec, { 0, 1 << 20, 0, 1 << 20, 0, 1, 0, 3 },
uint64_t(OpenChecks::Disallow1or2Channel)))
return false;
}
// Save spec for later use
m_spec = newspec;
// HDR always behaves like floating point
m_spec.set_format(TypeDesc::FLOAT);
// Check for things HDR can't support
if (m_spec.nchannels != 3) {
errorf("HDR can only support 3-channel images");
return false;
}
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
m_spec.set_format(TypeDesc::FLOAT); // Native rgbe is float32 only
ioproxy_retrieve_from_config(m_spec);
+9 -32
View File
@@ -19,7 +19,7 @@ public:
const char* format_name(void) const override { return "heif"; }
int supports(string_view feature) const override
{
return feature == "alpha" || feature == "exif";
return feature == "alpha" || feature == "exif" || feature == "tiles";
}
bool open(const std::string& name, const ImageSpec& spec,
OpenMode mode) override;
@@ -95,34 +95,11 @@ bool
HeifOutput::open(const std::string& name, const ImageSpec& newspec,
OpenMode mode)
{
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
if (!check_open(mode, newspec, { 0, 1 << 20, 0, 1 << 20, 0, 1, 0, 4 },
uint64_t(OpenChecks::Disallow2Channel)))
return false;
}
m_filename = name;
// Save spec for later used
m_spec = newspec;
// heif always behaves like floating point
m_spec.set_format(TypeDesc::FLOAT);
// Check for things heif can't support
if (m_spec.nchannels != 1 && m_spec.nchannels != 3
&& m_spec.nchannels != 4) {
errorf("heif can only support 1-, 3- or 4-channel images");
return false;
}
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
m_spec.set_format(TypeUInt8); // Only uint8 for now
@@ -149,11 +126,11 @@ HeifOutput::open(const std::string& name, const ImageSpec& newspec,
#endif
} catch (const heif::Error& err) {
std::string e = err.get_message();
errorf("%s", e.empty() ? "unknown exception" : e.c_str());
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
return false;
} catch (const std::exception& err) {
std::string e = err.what();
errorf("%s", e.empty() ? "unknown exception" : e.c_str());
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
return false;
}
@@ -231,13 +208,13 @@ HeifOutput::close()
} catch (const heif::Error& err) {
#ifdef DEBUG
std::string e = err.get_message();
Strutil::printf("%s", e.empty() ? "unknown exception" : e.c_str());
Strutil::print("{}", e.empty() ? "unknown exception" : e.c_str());
#endif
}
m_ctx->set_primary_image(m_ihandle);
Filesystem::IOFile ioproxy(m_filename, Filesystem::IOProxy::Write);
if (ioproxy.mode() != Filesystem::IOProxy::Write) {
errorf("Could not open \"%s\"", m_filename);
errorfmt("Could not open \"{}\"", m_filename);
ok = false;
} else {
MyHeifWriter writer(&ioproxy);
@@ -245,11 +222,11 @@ HeifOutput::close()
}
} catch (const heif::Error& err) {
std::string e = err.get_message();
errorf("%s", e.empty() ? "unknown exception" : e.c_str());
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
return false;
} catch (const std::exception& err) {
std::string e = err.what();
errorf("%s", e.empty() ? "unknown exception" : e.c_str());
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
return false;
}
+11 -29
View File
@@ -76,7 +76,7 @@ private:
{
size_t n = ::fwrite(buf, itemsize, nitems, m_file);
if (n != nitems)
errorf("Write error");
errorfmt("Write error");
return n == nitems;
}
@@ -87,7 +87,7 @@ private:
{
size_t n = ::fread(buf, itemsize, nitems, m_file);
if (n != nitems)
errorf("Read error");
errorfmt("Read error");
return n == nitems;
}
};
@@ -127,33 +127,14 @@ bool
ICOOutput::open(const std::string& name, const ImageSpec& userspec,
OpenMode mode)
{
if (mode == AppendMIPLevel) {
errorf("%s does not support MIP levels", format_name());
close(); // Close any already-opened file
if (!check_open(mode, userspec, { 0, 256, 0, 256, 0, 1, 0, 4 }))
return false;
}
close(); // Close any already-opened file
m_spec = userspec; // Stash the spec
if (m_spec.format == TypeDesc::UNKNOWN) // if unknown, default to 8 bits
m_spec.set_format(TypeDesc::UINT8);
// Check for things this format doesn't support
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
return false;
} else if (m_spec.width > 256 || m_spec.height > 256) {
errorf("Image resolution must be at most 256x256, you asked for %d x %d",
m_spec.width, m_spec.height);
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
// check if the client wants this subimage written as PNG
// also force PNG if image size is 256 because ico_header->width and height
// are 8-bit
@@ -165,7 +146,7 @@ ICOOutput::open(const std::string& name, const ImageSpec& userspec,
std::string s = PNG_pvt::create_write_struct(m_png, m_info,
m_color_type, m_spec);
if (s.length()) {
errorf("%s", s);
errorfmt("{}", s);
return false;
}
} else {
@@ -176,7 +157,8 @@ ICOOutput::open(const std::string& name, const ImageSpec& userspec,
case 3: m_color_type = PNG_COLOR_TYPE_RGB; break;
case 4: m_color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
default:
errorf("ICO only supports 1-4 channels, not %d", m_spec.nchannels);
errorfmt("ICO only supports 1-4 channels, not {}",
m_spec.nchannels);
return false;
}
@@ -203,7 +185,7 @@ ICOOutput::open(const std::string& name, const ImageSpec& userspec,
m_file = Filesystem::fopen(name, mode == AppendSubimage ? "r+b" : "wb");
if (!m_file) {
errorf("Could not open \"%s\"", name);
errorfmt("Could not open \"{}\"", name);
return false;
}
@@ -236,7 +218,7 @@ ICOOutput::open(const std::string& name, const ImageSpec& userspec,
<< ico.type << " count = " << ico.count << "\n";*/
if (ico.reserved != 0 || ico.type != 1) {
errorf("File failed ICO header check");
errorfmt("File failed ICO header check");
return false;
}
@@ -448,7 +430,7 @@ ICOOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
if (m_want_png) {
if (!PNG_pvt::write_row(m_png, (png_byte*)data)) {
errorf("PNG library error");
errorfmt("PNG library error");
return false;
}
} else {
+50 -46
View File
@@ -6,7 +6,6 @@
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
@@ -16,11 +15,12 @@
#include <OpenImageIO/imagebuf.h>
#include <OpenImageIO/imagecache.h>
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/strutil.h>
#include <OpenImageIO/sysutil.h>
using namespace OIIO;
using OIIO::Strutil::print;
static std::string uninitialized = "uninitialized \001 HHRU dfvAS: efjl";
static std::string dataformatname = "";
@@ -97,13 +97,13 @@ getargs(int argc, char* argv[])
"--sRGB", &sRGB, "This file is in sRGB color space",
"--separate", &separate, "Force planarconfig separate",
"--contig", &contig, "Force planarconfig contig",
"--no-clobber", &noclobber, "Do no overwrite existing files",
"--no-clobber", &noclobber, "Do not overwrite existing files",
//FIXME "-z", &zfile, "Treat input as a depth file",
//FIXME "-c %s", &channellist, "Restrict/shuffle channels",
nullptr);
// clang-format on
if (ap.parse(argc, (const char**)argv) < 0) {
std::cerr << ap.geterror() << std::endl;
print(stderr, "{}\n", ap.geterror());
ap.usage();
ap.abort();
return_code = EXIT_FAILURE;
@@ -117,23 +117,25 @@ getargs(int argc, char* argv[])
}
if (filenames.size() != 2 && !inplace) {
std::cerr
<< "iconvert: Must have both an input and output filename specified.\n";
print(
stderr,
"iconvert: Must have both an input and output filename specified.\n");
ap.usage();
ap.abort();
return_code = EXIT_FAILURE;
return;
}
if (filenames.size() == 0 && inplace) {
std::cerr << "iconvert: Must have at least one filename\n";
print(stderr, "iconvert: Must have at least one filename\n");
ap.usage();
ap.abort();
return_code = EXIT_FAILURE;
return;
}
if (((int)rotcw + (int)rotccw + (int)rot180 + (orientation > 0)) > 1) {
std::cerr
<< "iconvert: more than one of --rotcw, --rotccw, --rot180, --orientation\n";
print(
stderr,
"iconvert: more than one of --rotcw, --rotccw, --rot180, --orientation\n");
ap.usage();
ap.abort();
return_code = EXIT_FAILURE;
@@ -312,14 +314,15 @@ static bool
convert_file(const std::string& in_filename, const std::string& out_filename)
{
if (noclobber && Filesystem::exists(out_filename)) {
std::cerr << "iconvert ERROR: Output file already exists \""
<< out_filename << "\"\n";
print(stderr, "iconvert ERROR: Output file already exists \"{}\"\n",
out_filename);
return false;
}
if (verbose)
std::cout << "Converting " << in_filename << " to " << out_filename
<< "\n";
if (verbose) {
print("Converting {} to {}\n", in_filename, out_filename);
fflush(stdout);
}
std::string tempname = out_filename;
if (tempname == in_filename) {
@@ -330,11 +333,10 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
auto in = ImageInput::open(in_filename);
if (!in) {
std::string err = geterror();
std::cerr << "iconvert ERROR: "
<< (err.length() ? err
: Strutil::sprintf("Could not open \"%s\"",
in_filename))
<< "\n";
print(stderr, "iconvert ERROR: {}\n",
(err.length() ? err
: Strutil::fmt::format("Could not open \"{}\"",
in_filename)));
return false;
}
ImageSpec inspec = in->spec();
@@ -343,9 +345,10 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
// Find an ImageIO plugin that can open the output file, and open it
auto out = ImageOutput::create(tempname);
if (!out) {
std::cerr
<< "iconvert ERROR: Could not find an ImageIO plugin to write \""
<< out_filename << "\" : " << geterror() << "\n";
print(
stderr,
"iconvert ERROR: Could not find an ImageIO plugin to write \"{}\": {}\n",
out_filename, geterror());
return false;
}
@@ -375,9 +378,10 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
for (int subimage = 0; ok && in->seek_subimage(subimage, 0, inspec);
++subimage) {
if (subimage > 0 && !out->supports("multiimage")) {
std::cerr << "iconvert WARNING: " << out->format_name()
<< " does not support multiple subimages.\n";
std::cerr << "\tOnly the first subimage has been copied.\n";
print(stderr,
"iconvert WARNING: {} does not support multiple subimages.\n"
"\tOnly the first subimage has been copied.\n",
out->format_name());
break; // we're done
}
@@ -396,16 +400,17 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
mode = ImageOutput::AppendSubimage; // use if we must
if (!mip_to_subimage_warning
&& strcmp(out->format_name(), "tiff")) {
std::cerr << "iconvert WARNING: " << out->format_name()
<< " does not support MIPmaps.\n";
std::cerr
<< "\tStoring the MIPmap levels in subimages.\n";
print(stderr,
"iconvert WARNING: {} does not support MIPmaps.\n"
"\tStoring the MIPmap levels in subimages.\n",
out->format_name());
}
mip_to_subimage_warning = true;
} else {
std::cerr << "iconvert WARNING: " << out->format_name()
<< " does not support MIPmaps.\n";
std::cerr << "\tOnly the first level has been copied.\n";
print(stderr,
"iconvert WARNING: {} does not support MIPmaps.\n"
"\tOnly the first level has been copied.\n",
out->format_name());
break; // on to the next subimage
}
ok = out->open(tempname.c_str(), outspec, mode);
@@ -424,12 +429,11 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
}
if (!ok) {
std::string err = out->geterror();
std::cerr << "iconvert ERROR: "
<< (err.length()
? err
: Strutil::sprintf("Could not open \"%s\"",
out_filename))
<< "\n";
print(stderr, "iconvert ERROR: {}\n",
(err.length()
? err
: Strutil::fmt::format("Could not open \"{}\"",
out_filename)));
ok = false;
break;
}
@@ -448,9 +452,9 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
if (!nocopy) {
ok = out->copy_image(in.get());
if (!ok)
std::cerr << "iconvert ERROR copying \"" << in_filename
<< "\" to \"" << out_filename << "\" :\n\t"
<< out->geterror() << "\n";
print(stderr,
"iconvert ERROR copying \"{}\" to \"{}\" :\n\t{}\n",
in_filename, out_filename, out->geterror());
} else {
// Need to do it by hand for some reason. Future expansion in which
// only a subset of channels are copied, or some such.
@@ -458,13 +462,13 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
ok = in->read_image(subimage, miplevel, 0, outspec.nchannels,
outspec.format, &pixels[0]);
if (!ok) {
std::cerr << "iconvert ERROR reading \"" << in_filename
<< "\" : " << in->geterror() << "\n";
print(stderr, "iconvert ERROR reading \"{}\": {}\n",
in_filename, in->geterror());
} else {
ok = out->write_image(outspec.format, &pixels[0]);
if (!ok)
std::cerr << "iconvert ERROR writing \"" << out_filename
<< "\" : " << out->geterror() << "\n";
print(stderr, "iconvert ERROR writing \"{}\": {}\n",
out_filename, out->geterror());
}
}
@@ -522,6 +526,6 @@ main(int argc, char* argv[])
} else {
ok = convert_file(filenames[0], filenames[1]);
}
shutdown();
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
+1
View File
@@ -399,5 +399,6 @@ main(int argc, char* argv[])
imagecache->invalidate_all(true);
ImageCache::destroy(imagecache);
shutdown();
return ret;
}
+6 -1
View File
@@ -2,4 +2,9 @@
# SPDX-License-Identifier: Apache-2.0
# https://github.com/OpenImageIO/oiio
add_oiio_plugin (iffinput.cpp iffoutput.cpp)
option (ENABLE_RLA_IOPROXY "(Temporarily) turn this off to switch back to the old pre-IOProxy RLA implementation to address a bug." ON)
if (ENABLE_RLA_IOPROXY)
add_oiio_plugin (iffinput.cpp iffoutput.cpp)
else ()
add_oiio_plugin (noproxy-iffinput.cpp noproxy-iffoutput.cpp noproxy-iff_pvt.cpp)
endif ()
+4 -1
View File
@@ -87,6 +87,9 @@ private:
return read_type_len(name, len) && read_str(val, len);
}
// Read a 4-byte type code (no endian swap), and if that succeeds (beware
// of EOF or other errors), then also read a 32 bit size (subject to
// endian swap).
bool read_typesize(uint8_t type[4], uint32_t& size)
{
return ioread(type, 1, 4) && read(&size);
@@ -181,7 +184,7 @@ IffInput::open(const std::string& name, ImageSpec& spec)
m_spec.full_height = m_iff_header.height;
// tiles
if (m_iff_header.tile_width > 0 || m_iff_header.tile_height > 0) {
if (m_iff_header.tile_width > 0 && m_iff_header.tile_height > 0) {
m_spec.tile_width = m_iff_header.tile_width;
m_spec.tile_height = m_iff_header.tile_height;
// only 1 subimage for IFF
+8 -17
View File
@@ -143,33 +143,24 @@ IffOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
// RGBA <size> tile pixels
// ...
if (mode != Create) {
errorfmt("{} does not support subimages or MIP levels", format_name());
return false;
}
// saving 'name' and 'spec' for later use
m_filename = name;
m_spec = spec;
// Maya docs say 8k is the limit
if (m_spec.width < 1 || m_spec.width > 8192 || m_spec.height < 1
|| m_spec.height > 8192) {
errorfmt("Image resolution {} x {} is not valid for an IFF file",
m_spec.width, m_spec.height);
if (!check_open(mode, spec, { 0, 8192, 0, 8192, 0, 1, 0, 4 }))
return false;
}
// Maya docs say 8k is the limit
// tiles always
m_spec.tile_width = tile_width();
m_spec.tile_height = tile_height();
m_spec.tile_depth = 1;
// This implementation only supports writing RGB and RGBA images as IFF
if (m_spec.nchannels < 3 || m_spec.nchannels > 4) {
errorfmt("Cannot write IFF file with {} channels", m_spec.nchannels);
return false;
}
// tiles
m_spec.tile_width = tile_width();
m_spec.tile_height = tile_height();
m_spec.tile_depth = 1;
uint64_t xtiles = tile_width_size(m_spec.width);
uint64_t ytiles = tile_height_size(m_spec.height);
if (xtiles * ytiles >= (1 << 16)) { // The format can't store it!
+332
View File
@@ -0,0 +1,332 @@
// Copyright Contributors to the OpenImageIO project.
// SPDX-License-Identifier: Apache-2.0
// https://github.com/OpenImageIO/oiio
#include "noproxy-iff_pvt.h"
#include <OpenImageIO/dassert.h>
OIIO_PLUGIN_NAMESPACE_BEGIN
using namespace iff_pvt;
#define STRINGIZE2(a) #a
#define STRINGIZE(a) STRINGIZE2(a)
bool
IffFileHeader::read_header(FILE* fd, std::string& err)
{
uint8_t type[4];
uint32_t size;
uint32_t chunksize;
uint32_t tbhdsize;
uint32_t flags;
uint16_t bytes;
uint16_t prnum;
uint16_t prden;
// read FOR4 <size> CIMG.
err.clear();
for (;;) {
// get type and length
if (!read_typesize(fd, type, size)) {
err = "could not read type/size @ L" STRINGIZE(__LINE__);
return false;
}
chunksize = align_size(size, 4);
if (type[0] == 'F' && type[1] == 'O' && type[2] == 'R'
&& type[3] == '4') {
// get type
if (!fread(&type, 1, sizeof(type), fd)) {
err = "could not read FDR4 type @ L" STRINGIZE(__LINE__);
return false;
}
// check if CIMG
if (type[0] == 'C' && type[1] == 'I' && type[2] == 'M'
&& type[3] == 'G') {
// read TBHD.
for (;;) {
if (!read_typesize(fd, type, size)) {
err = "could not read CIMG length @ L" STRINGIZE(
__LINE__);
return false;
}
chunksize = align_size(size, 4);
if (type[0] == 'T' && type[1] == 'B' && type[2] == 'H'
&& type[3] == 'D') {
tbhdsize = size;
// test if table header size is correct
if (tbhdsize != 24 && tbhdsize != 32) {
err = "bad table header @ L" STRINGIZE(__LINE__);
return false; // bad table header
}
// get width and height
if (!read(fd, width) || !read(fd, height)
|| !read(fd, prnum) || !read(fd, prden)
|| !read(fd, flags) || !read(fd, bytes)
|| !read(fd, tiles) || !read(fd, compression)) {
err = "@ L" STRINGIZE(__LINE__);
return false;
}
// get xy
if (tbhdsize == 32) {
if (!read(fd, x) || !read(fd, y)) {
err = "could not get xy @ L" STRINGIZE(
__LINE__);
return false;
}
} else {
x = 0;
y = 0;
}
// tiles
if (tiles == 0) {
err = "non-tiles not supported @ L" STRINGIZE(
__LINE__);
return false;
} // non-tiles not supported
// 0 no compression
// 1 RLE compression
// 2 QRL (not supported)
// 3 QR4 (not supported)
if (compression > 1) {
err = "only RLE compression is supported @ L" STRINGIZE(
__LINE__);
return false;
}
// test format.
if (flags & RGBA) {
// test if black is set
OIIO_DASSERT(!(flags & BLACK));
// test for RGB channels.
if (flags & RGB)
pixel_channels = 3;
// test for alpha channel
if (flags & ALPHA)
pixel_channels++;
// test pixel bits
pixel_bits = bytes ? 16 : 8;
}
// Z format.
else if (flags & ZBUFFER) {
pixel_channels = 1;
pixel_bits = 32; // 32bit
// NOTE: Z_F32 support - not supported
OIIO_DASSERT(bytes == 0);
}
// read AUTH, DATE or FOR4
for (;;) {
// get type
if (!read_typesize(fd, type, size)) {
err = "could not read type/size @ L" STRINGIZE(
__LINE__);
return false;
}
chunksize = align_size(size, 4);
if (type[0] == 'A' && type[1] == 'U'
&& type[2] == 'T' && type[3] == 'H') {
std::vector<char> str(chunksize);
if (!fread(&str[0], 1, chunksize, fd)) {
err = "could not read author @ L" STRINGIZE(
__LINE__);
return false;
}
author = std::string(&str[0], size);
} else if (type[0] == 'D' && type[1] == 'A'
&& type[2] == 'T' && type[3] == 'E') {
std::vector<char> str(chunksize);
if (!fread(&str[0], 1, chunksize, fd)) {
err = "could not read date @ L" STRINGIZE(
__LINE__);
return false;
}
date = std::string(&str[0], size);
} else if (type[0] == 'F' && type[1] == 'O'
&& type[2] == 'R' && type[3] == '4') {
if (!fread(&type, 1, sizeof(type), fd)) {
err = "could not read FOR4 type @ L" STRINGIZE(
__LINE__);
return false;
}
// check if CIMG
if (type[0] == 'T' && type[1] == 'B'
&& type[2] == 'M' && type[3] == 'P') {
// tbmp position for later user in in
// read_native_tile
tbmp_start = ftell(fd);
// read first RGBA block to detect tile size.
for (unsigned int t = 0; t < tiles; t++) {
if (!read_typesize(fd, type, size)) {
err = "xxx @ L" STRINGIZE(__LINE__);
return false;
}
chunksize = align_size(size, 4);
// check if RGBA
if (type[0] == 'R' && type[1] == 'G'
&& type[2] == 'B'
&& type[3] == 'A') {
// get tile coordinates.
uint16_t xmin, xmax, ymin, ymax;
if (!read(fd, xmin)
|| !read(fd, ymin)
|| !read(fd, xmax)
|| !read(fd, ymax)) {
err = "xxx @ L" STRINGIZE(
__LINE__);
return false;
}
// check tile
if (xmin > xmax || ymin > ymax
|| xmax >= width
|| ymax >= height) {
err = "tile min/max nonsensical @ L" STRINGIZE(
__LINE__);
return false;
}
// set tile width and height
tile_width = xmax - xmin + 1;
tile_height = ymax - ymin + 1;
// done, return
return true;
}
// skip to the next block.
if (fseek(fd, chunksize, SEEK_CUR)) {
err = "could not fseek @ L" STRINGIZE(
__LINE__);
return false;
}
}
} else {
// skip to the next block.
if (fseek(fd, chunksize, SEEK_CUR)) {
err = "could not fseek @ L" STRINGIZE(
__LINE__);
return false;
}
}
} else {
// skip to the next block.
if (fseek(fd, chunksize, SEEK_CUR)) {
err = "could not fseek @ L" STRINGIZE(
__LINE__);
return false;
}
}
}
// TBHD done, break
break;
}
// skip to the next block.
if (fseek(fd, chunksize, SEEK_CUR)) {
err = "could not fseek @ L" STRINGIZE(__LINE__);
return false;
}
}
}
}
// skip to the next block.
if (fseek(fd, chunksize, SEEK_CUR)) {
err = "could not fseek @ L" STRINGIZE(__LINE__);
return false;
}
}
err = "unknown error, ended early @ L" STRINGIZE(__LINE__);
return false;
}
bool
IffOutput::write_header(IffFileHeader& header)
{
// write 'FOR4' type, with 0 length for now (to reserve it)
if (!(write_str("FOR4") && write_int(0)))
return false;
// write 'CIMG' type
if (!write_str("CIMG"))
return false;
// write 'TBHD' type
if (!write_str("TBHD"))
return false;
// 'TBHD' length, 32 bytes
if (!write_int(32))
return false;
if (!write_int(header.width) || !write_int(header.height))
return false;
// write prnum and prden (pixel aspect ratio? -- FIXME)
if (!write_short(1) || !write_short(1)) //NOSONAR
return false;
// write flags and channels
if (!write_int(header.pixel_channels == 3 ? RGB : RGBA)
|| !write_short(header.pixel_bits == 8 ? 0 : 1)
|| !write_short(header.tiles))
return false;
// write compression
// 0 no compression
// 1 RLE compression
// 2 QRL (not supported)
// 3 QR4 (not supported)
if (!write_int(header.compression))
return false;
// write x and y
if (!write_int(header.x) || !write_int(header.y))
return false;
// Write metadata
write_meta_string("AUTH", header.author);
write_meta_string("DATE", header.date);
// for4 position for later user in close
header.for4_start = ftell(m_fd);
// write 'FOR4' type, with 0 length to reserve it for now
if (!write_str("FOR4") || !write_int(0))
return false;
// write 'TBMP' type
if (!write_str("TBMP"))
return false;
return true;
}
OIIO_PLUGIN_NAMESPACE_END
+303
View File
@@ -0,0 +1,303 @@
// Copyright Contributors to the OpenImageIO project.
// SPDX-License-Identifier: Apache-2.0
// https://github.com/OpenImageIO/oiio
#pragma once
// Format reference: Affine Toolkit (Thomas E. Burge), riff.h and riff.c
// Autodesk Maya documentation, ilib.h
#include <cstdio>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
#include "imageio_pvt.h"
OIIO_PLUGIN_NAMESPACE_BEGIN
namespace iff_pvt {
// compression numbers
const uint32_t NONE = 0;
const uint32_t RLE = 1;
const uint32_t QRL = 2;
const uint32_t QR4 = 3;
const uint32_t RGB = 0x00000001;
const uint32_t ALPHA = 0x00000002;
const uint32_t RGBA = RGB | ALPHA;
const uint32_t ZBUFFER = 0x00000004;
const uint32_t BLACK = 0x00000010;
// store information about IFF file
class IffFileHeader {
public:
// reads information about IFF file
bool read_header(FILE* fd, std::string& err);
// header information
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t compression;
uint8_t pixel_bits;
uint8_t pixel_channels;
uint16_t tiles;
uint16_t tile_width;
uint16_t tile_height;
// author string
std::string author;
// date string
std::string date;
// tbmp start
uint32_t tbmp_start;
// for4 start
uint32_t for4_start;
private:
// Read a uint32_t, swap endian if necessary
bool read(FILE* fd, uint32_t& data)
{
bool ok = (fread(&data, 1, sizeof(data), fd) == sizeof(data));
if (littleendian())
swap_endian(&data);
return ok;
}
// Read a uint16_t, swap endian if necessary
bool read(FILE* fd, uint16_t& data)
{
bool ok = (fread(&data, 1, sizeof(data), fd) == sizeof(data));
if (littleendian())
swap_endian(&data);
return ok;
}
// Read a 4-byte code (no endian swap), and if that succeeds (beware of EOF or
// other errors), then also read a 32 bit size (subject to endian swap).
bool read_typesize(FILE* fd, uint8_t type[4], uint32_t& size)
{
return (fread(type, 1, 4, fd) == 4) && read(fd, size);
}
};
// align size
inline uint32_t
align_size(uint32_t size, uint32_t alignment)
{
uint32_t mod = size % alignment;
if (mod) {
mod = alignment - mod;
size += mod;
}
return size;
}
// tile width
inline const int&
tile_width()
{
static int tile_w = 64;
return tile_w;
}
// tile height
inline const int&
tile_height()
{
static int tile_h = 64;
return tile_h;
}
// tile width size
inline uint32_t
tile_width_size(uint32_t width)
{
uint32_t tw = tile_width();
return (width + tw - 1) / tw;
}
// tile height size
inline uint32_t
tile_height_size(uint32_t height)
{
uint32_t th = tile_height();
return (height + th - 1) / th;
}
} // namespace iff_pvt
class IffInput final : public ImageInput {
public:
IffInput() { init(); }
~IffInput() override
{
try {
close();
} catch (const std::exception& e) {
OIIO::pvt::errorfmt("{}", e.what());
}
}
const char* format_name(void) const override { return "iff"; }
bool open(const std::string& name, ImageSpec& spec) override;
bool close(void) override;
bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
bool read_native_tile(int subimage, int miplevel, int x, int y, int z,
void* data) override;
private:
FILE* m_fd;
std::string m_filename;
iff_pvt::IffFileHeader m_iff_header;
std::vector<uint8_t> m_buf;
uint32_t m_tbmp_start;
// init to initialize state
void init(void)
{
m_fd = NULL;
m_filename.clear();
m_buf.clear();
}
// helper to read an image
bool readimg(void);
// helper to uncompress a rle channel
size_t uncompress_rle_channel(const uint8_t* in, uint8_t* out, int size);
bool read_short(uint16_t& val)
{
bool ok = fread(&val, sizeof(val), 1, m_fd);
if (littleendian())
swap_endian(&val);
return ok;
}
bool read_int(uint32_t& val)
{
bool ok = fread(&val, sizeof(val), 1, m_fd);
if (littleendian())
swap_endian(&val);
return ok;
}
bool read_str(std::string& val, uint32_t len, uint32_t round = 4)
{
const uint32_t big = 1024;
char strbuf[big];
len = std::min(len, big);
bool ok = fread(strbuf, len, 1, m_fd);
val.assign(strbuf, len);
for (uint32_t pad = len % round; pad; --pad)
fgetc(m_fd);
return ok;
}
bool read_type_len(std::string& type, uint32_t& len)
{
return read_str(type, 4) && read_int(len);
}
bool read_meta_string(std::string& name, std::string& val)
{
uint32_t len = 0;
return read_type_len(name, len) && read_str(val, len);
}
};
class IffOutput final : public ImageOutput {
public:
IffOutput() { init(); }
~IffOutput() override
{
try {
close();
} catch (const std::exception& e) {
OIIO::pvt::errorfmt("{}", e.what());
}
}
const char* format_name(void) const override { return "iff"; }
int supports(string_view feature) const override;
bool open(const std::string& name, const ImageSpec& spec,
OpenMode mode) override;
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:
FILE* m_fd;
std::string m_filename;
iff_pvt::IffFileHeader m_iff_header;
std::vector<uint8_t> m_buf;
unsigned int m_dither;
std::vector<uint8_t> scratch;
void init(void)
{
m_fd = NULL;
m_filename.clear();
}
// writes information about iff file to give file
bool write_header(iff_pvt::IffFileHeader& header);
bool write_short(uint16_t val)
{
if (littleendian())
swap_endian(&val);
return fwrite(&val, sizeof(val), 1, m_fd);
}
bool write_int(uint32_t val)
{
if (littleendian())
swap_endian(&val);
return fwrite(&val, sizeof(val), 1, m_fd);
}
bool write_str(string_view val, size_t round = 4)
{
bool ok = fwrite(val.data(), val.size(), 1, m_fd);
for (size_t i = val.size(); i < round_to_multiple(val.size(), round);
++i)
ok &= (fputc(' ', m_fd) != EOF);
return ok;
}
bool write_meta_string(string_view name, string_view val,
bool write_if_empty = false)
{
if (val.empty() && !write_if_empty)
return true;
return write_str(name) && write_int(int(val.size()))
&& (val.size() == 0 || write_str(val));
}
// helper to compress verbatim
void compress_verbatim(const uint8_t*& in, uint8_t*& out, int size);
// helper to compress duplicate
void compress_duplicate(const uint8_t*& in, uint8_t*& out, int size);
// helper to compress a rle channel
size_t compress_rle_channel(const uint8_t* in, uint8_t* out, int size);
};
OIIO_PLUGIN_NAMESPACE_END
+488
View File
@@ -0,0 +1,488 @@
// Copyright Contributors to the OpenImageIO project.
// SPDX-License-Identifier: Apache-2.0
// https://github.com/OpenImageIO/oiio
#include "noproxy-iff_pvt.h"
#include <cmath>
OIIO_PLUGIN_NAMESPACE_BEGIN
using namespace iff_pvt;
// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT int iff_imageio_version = OIIO_PLUGIN_VERSION;
OIIO_EXPORT const char*
iff_imageio_library_version()
{
return nullptr;
}
OIIO_EXPORT ImageInput*
iff_input_imageio_create()
{
return new IffInput;
}
OIIO_EXPORT const char* iff_input_extensions[] = { "iff", "z", nullptr };
OIIO_PLUGIN_EXPORTS_END
bool
IffInput::open(const std::string& name, ImageSpec& spec)
{
// Autodesk Maya documentation:
// "Maya Image File Format - IFF
//
// Maya supports images in the Interchange File Format (IFF).
// IFF is a generic structured file access mechanism, and is not only
// limited to images.
//
// The openimageio IFF implementation deals specifically with Maya IFF
// images with it's data blocks structured as follows:
//
// Header:
// FOR4 <size> CIMG
// TBHD <size> flags, width, height, compression ...
// AUTH <size> attribute ...
// DATE <size> attribute ...
// FOR4 <size> TBMP
// Tiles:
// RGBA <size> tile pixels
// RGBA <size> tile pixels
// RGBA <size> tile pixels
// ...
// saving 'name' for later use
m_filename = name;
m_fd = Filesystem::fopen(m_filename, "rb");
if (!m_fd) {
errorf("Could not open file \"%s\"", name);
return false;
}
// we read header of the file that we think is IFF file
std::string err;
if (!m_iff_header.read_header(m_fd, err)) {
errorf("\"%s\": could not read iff header (%s)", m_filename,
err.size() ? err : std::string("unknown"));
close();
return false;
}
// image specification
m_spec = ImageSpec(m_iff_header.width, m_iff_header.height,
m_iff_header.pixel_channels,
m_iff_header.pixel_bits == 8 ? TypeDesc::UINT8
: TypeDesc::UINT16);
// set x, y
m_spec.x = m_iff_header.x;
m_spec.y = m_iff_header.y;
// set full width, height
m_spec.full_width = m_iff_header.width;
m_spec.full_height = m_iff_header.height;
// tiles
if (m_iff_header.tile_width > 0 || m_iff_header.tile_height > 0) {
m_spec.tile_width = m_iff_header.tile_width;
m_spec.tile_height = m_iff_header.tile_height;
// only 1 subimage for IFF
m_spec.tile_depth = 1;
} else {
errorf("\"%s\": wrong tile size", m_filename);
close();
return false;
}
// attributes
// compression
if (m_iff_header.compression == iff_pvt::RLE) {
m_spec.attribute("compression", "rle");
}
// author
if (m_iff_header.author.size()) {
m_spec.attribute("Artist", m_iff_header.author);
}
// date
if (m_iff_header.date.size()) {
m_spec.attribute("DateTime", m_iff_header.date);
}
// file pointer is set to the beginning of tbmp data
// we save this position - it will be helpful in read_native_tile
m_tbmp_start = m_iff_header.tbmp_start;
spec = m_spec;
return true;
}
bool
IffInput::read_native_scanline(int /*subimage*/, int /*miplevel*/, int /*y*/,
int /*z*/, void* /*data*/)
{
// scanline not used for Maya IFF, uses tiles instead.
return false;
}
bool
IffInput::read_native_tile(int subimage, int miplevel, int x, int y, int /*z*/,
void* data)
{
lock_guard lock(*this);
if (!seek_subimage(subimage, miplevel))
return false;
if (m_buf.empty())
readimg();
// tile size
int w = m_spec.width;
int tw = std::min(x + m_spec.tile_width, m_spec.width) - x;
int th = std::min(y + m_spec.tile_height, m_spec.height) - y;
// tile data
int oy = 0;
for (int iy = y; iy < y + th; iy++) {
// in
uint8_t* in_p = &m_buf[0] + (iy * w + x) * m_spec.pixel_bytes();
// out
uint8_t* out_p = (uint8_t*)data
+ (oy * m_spec.tile_width) * m_spec.pixel_bytes();
// copy
memcpy(out_p, in_p, tw * m_spec.pixel_bytes());
oy++;
}
return true;
}
bool inline IffInput::close(void)
{
if (m_fd) {
fclose(m_fd);
m_fd = NULL;
}
init();
return true;
}
bool
IffInput::readimg()
{
uint8_t type[4];
uint32_t size;
uint32_t chunksize;
// seek pos
// set position tile may be called randomly
fseek(m_fd, m_tbmp_start, SEEK_SET);
// resize buffer
m_buf.resize(m_spec.image_bytes());
for (unsigned int t = 0; t < m_iff_header.tiles;) {
// get type
if (!fread(&type, 1, sizeof(type), m_fd) ||
// get length
!fread(&size, 1, sizeof(size), m_fd))
return false;
if (littleendian())
swap_endian(&size);
chunksize = align_size(size, 4);
// check if RGBA
if (type[0] == 'R' && type[1] == 'G' && type[2] == 'B'
&& type[3] == 'A') {
// get tile coordinates.
uint16_t xmin, xmax, ymin, ymax;
if (!fread(&xmin, 1, sizeof(xmin), m_fd)
|| !fread(&ymin, 1, sizeof(ymin), m_fd)
|| !fread(&xmax, 1, sizeof(xmax), m_fd)
|| !fread(&ymax, 1, sizeof(ymax), m_fd))
return false;
// swap endianness
if (littleendian()) {
swap_endian(&xmin);
swap_endian(&ymin);
swap_endian(&xmax);
swap_endian(&ymax);
}
// get tile width/height
uint32_t tw = xmax - xmin + 1;
uint32_t th = ymax - ymin + 1;
// get image size
// skip coordinates, uint16_t (2) * 4 = 8
uint32_t image_size = chunksize - 8;
// check tile
if (xmin > xmax || ymin > ymax || xmax >= m_spec.width
|| ymax >= m_spec.height || !tw || !th) {
return false;
}
// tile compress
bool tile_compress = false;
// if tile compression fails to be less than image data stored
// uncompressed the tile is written uncompressed
// set channels
uint8_t channels = m_iff_header.pixel_channels;
// set tile size
uint32_t tile_size = tw * th * channels * m_spec.channel_bytes()
+ 8;
// test if compressed
// we use the non aligned size
if (tile_size > size) {
tile_compress = true;
}
// handle 8-bit data.
if (m_iff_header.pixel_bits == 8) {
std::vector<uint8_t> scratch;
// set bytes.
scratch.resize(image_size);
if (!fread(&scratch[0], 1, scratch.size(), m_fd))
return false;
// set tile data
uint8_t* p = static_cast<uint8_t*>(&scratch[0]);
// tile compress.
if (tile_compress) {
// map BGR(A) to RGB(A)
for (int c = (channels * m_spec.channel_bytes()) - 1;
c >= 0; --c) {
std::vector<uint8_t> in(tw * th);
uint8_t* in_p = &in[0];
// uncompress and increment
p += uncompress_rle_channel(p, in_p, tw * th);
// set tile
for (uint16_t py = ymin; py <= ymax; py++) {
uint8_t* out_dy = static_cast<uint8_t*>(&m_buf[0])
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
uint8_t* out_p
= out_dy + px * m_spec.pixel_bytes() + c;
*out_p++ = *in_p++;
}
}
}
} else {
int sy = 0;
for (uint16_t py = ymin; py <= ymax; py++) {
uint8_t* out_dy = static_cast<uint8_t*>(&m_buf[0])
+ (py * m_spec.width + xmin)
* m_spec.pixel_bytes();
// set tile
int sx = 0;
for (uint16_t px = xmin; px <= xmax; px++) {
uint8_t* in_p
= p + (sy * tw + sx) * m_spec.pixel_bytes();
// map BGR(A) to RGB(A)
for (int c = channels - 1; c >= 0; --c) {
uint8_t* out_p = in_p
+ (c * m_spec.channel_bytes());
*out_dy++ = *out_p;
}
sx++;
}
sy++;
}
}
}
// handle 16-bit data.
else if (m_iff_header.pixel_bits == 16) {
std::vector<uint8_t> scratch;
// set bytes.
scratch.resize(image_size);
if (!fread(&scratch[0], 1, scratch.size(), m_fd))
return false;
// set tile data
uint8_t* p = static_cast<uint8_t*>(&scratch[0]);
if (tile_compress) {
// set map
std::vector<uint8_t> map;
if (littleendian()) {
int rgb16[] = { 0, 2, 4, 1, 3, 5 };
int rgba16[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
if (m_iff_header.pixel_channels == 3) {
map = std::vector<uint8_t>(rgb16, &rgb16[6]);
} else {
map = std::vector<uint8_t>(rgba16, &rgba16[8]);
}
} else {
int rgb16[] = { 1, 3, 5, 0, 2, 4 };
int rgba16[] = { 1, 3, 5, 7, 0, 2, 4, 6 };
if (m_iff_header.pixel_channels == 3) {
map = std::vector<uint8_t>(rgb16, &rgb16[6]);
} else {
map = std::vector<uint8_t>(rgba16, &rgba16[8]);
}
}
// map BGR(A)BGR(A) to RRGGBB(AA)
for (int c = (channels * m_spec.channel_bytes()) - 1;
c >= 0; --c) {
int mc = map[c];
std::vector<uint8_t> in(tw * th);
uint8_t* in_p = &in[0];
// uncompress and increment
p += uncompress_rle_channel(p, in_p, tw * th);
// set tile
for (uint16_t py = ymin; py <= ymax; py++) {
uint8_t* out_dy = static_cast<uint8_t*>(&m_buf[0])
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
uint8_t* out_p
= out_dy + px * m_spec.pixel_bytes() + mc;
*out_p++ = *in_p++;
}
}
}
} else {
int sy = 0;
for (uint16_t py = ymin; py <= ymax; py++) {
uint8_t* out_dy = static_cast<uint8_t*>(&m_buf[0])
+ (py * m_spec.width + xmin)
* m_spec.pixel_bytes();
// set scanline, make copy easier
std::vector<uint16_t> scanline(tw
* m_spec.pixel_bytes());
uint16_t* sl_p = &scanline[0];
// set tile
int sx = 0;
for (uint16_t px = xmin; px <= xmax; px++) {
uint8_t* in_p
= p + (sy * tw + sx) * m_spec.pixel_bytes();
// map BGR(A) to RGB(A)
for (int c = channels - 1; c >= 0; --c) {
uint16_t pixel;
uint8_t* out_p = in_p
+ (c * m_spec.channel_bytes());
memcpy(&pixel, out_p, 2);
// swap endianness
if (littleendian()) {
swap_endian(&pixel);
}
*sl_p++ = pixel;
}
sx++;
}
// copy data
memcpy(out_dy, &scanline[0], tw * m_spec.pixel_bytes());
sy++;
}
}
} else {
errorf("\"%s\": unsupported number of bits per pixel for tile",
m_filename);
return false;
}
// tile
t++;
} else {
// skip to the next block
if (fseek(m_fd, chunksize, SEEK_CUR))
return false;
}
}
// flip buffer to make read_native_tile easier,
// from tga.imageio:
int bytespp = m_spec.pixel_bytes();
std::vector<unsigned char> flip(m_spec.width * bytespp);
unsigned char *src, *dst, *tmp = &flip[0];
for (int y = 0; y < m_spec.height / 2; y++) {
src = &m_buf[(m_spec.height - y - 1) * m_spec.width * bytespp];
dst = &m_buf[y * m_spec.width * bytespp];
memcpy(tmp, src, m_spec.width * bytespp);
memcpy(src, dst, m_spec.width * bytespp);
memcpy(dst, tmp, m_spec.width * bytespp);
}
return true;
}
size_t
IffInput::uncompress_rle_channel(const uint8_t* in, uint8_t* out, int size)
{
const uint8_t* const _in = in;
const uint8_t* const end = out + size;
while (out < end) {
// information.
const uint8_t count = (*in & 0x7f) + 1;
const bool run = (*in & 0x80) ? true : false;
++in;
// find runs
if (!run) {
// verbatim
for (int i = 0; i < count; i++)
*out++ = *in++;
} else {
// duplicate
const uint8_t p = *in++;
for (int i = 0; i < count; i++)
*out++ = p;
}
}
const size_t r = in - _in;
return r;
}
OIIO_PLUGIN_NAMESPACE_END
+600
View File
@@ -0,0 +1,600 @@
// Copyright Contributors to the OpenImageIO project.
// SPDX-License-Identifier: Apache-2.0
// https://github.com/OpenImageIO/oiio
#include "noproxy-iff_pvt.h"
OIIO_PLUGIN_NAMESPACE_BEGIN
using namespace iff_pvt;
// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT ImageOutput*
iff_output_imageio_create()
{
return new IffOutput;
}
OIIO_EXPORT const char* iff_output_extensions[] = { "iff", "z", nullptr };
OIIO_PLUGIN_EXPORTS_END
int
IffOutput::supports(string_view feature) const
{
return (feature == "tiles" || feature == "alpha" || feature == "nchannels");
}
bool
IffOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
// Autodesk Maya documentation:
// "Maya Image File Format - IFF
//
// Maya supports images in the Interchange File Format (IFF).
// IFF is a generic structured file access mechanism, and is not only
// limited to images.
//
// The openimageio IFF implementation deals specifically with Maya IFF
// images with it's data blocks structured as follows:
//
// Header:
// FOR4 <size> CIMG
// TBHD <size> flags, width, height, compression ...
// AUTH <size> attribute ...
// DATE <size> attribute ...
// FOR4 <size> TBMP
// Tiles:
// RGBA <size> tile pixels
// RGBA <size> tile pixels
// RGBA <size> tile pixels
// ...
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
return false;
}
close(); // Close any already-opened file
// saving 'name' and 'spec' for later use
m_filename = name;
m_spec = spec;
// tiles
m_spec.tile_width = tile_width();
m_spec.tile_height = tile_height();
m_spec.tile_depth = 1;
m_fd = Filesystem::fopen(m_filename, "wb");
if (!m_fd) {
errorf("Could not open \"%s\"", m_filename);
return false;
}
// IFF image files only supports UINT8 and UINT16. If something
// else was requested, revert to the one most likely to be readable
// by any IFF reader: UINT8
if (m_spec.format != TypeDesc::UINT8 && m_spec.format != TypeDesc::UINT16)
m_spec.set_format(TypeDesc::UINT8);
m_dither = (m_spec.format == TypeDesc::UINT8)
? m_spec.get_int_attribute("oiio:dither", 0)
: 0;
// check if the client wants the image to be run length encoded
// currently only RGB RLE compression is supported, we default to RLE
// as Maya does not handle non-compressed IFF's very well.
m_iff_header.compression
= (m_spec.get_string_attribute("compression") == "none") ? NONE : RLE;
uint64_t xtiles = tile_width_size(m_spec.width);
uint64_t ytiles = tile_height_size(m_spec.height);
if (xtiles * ytiles >= (1 << 16)) { // The format can't store it!
errorf(
"Too high a resolution (%dx%d), exceeds maximum of 64k tiles in the image\n",
m_spec.width, m_spec.height);
close();
return false;
}
// we write the header of the file
m_iff_header.x = m_spec.x;
m_iff_header.y = m_spec.y;
m_iff_header.width = m_spec.width;
m_iff_header.height = m_spec.height;
m_iff_header.tiles = xtiles * ytiles;
m_iff_header.pixel_bits = m_spec.format == TypeDesc::UINT8 ? 8 : 16;
m_iff_header.pixel_channels = m_spec.nchannels;
m_iff_header.author = m_spec.get_string_attribute("Artist");
m_iff_header.date = m_spec.get_string_attribute("DateTime");
if (!write_header(m_iff_header)) {
errorf("\"%s\": could not write iff header", m_filename);
close();
return false;
}
m_buf.resize(m_spec.image_bytes());
return true;
}
bool
IffOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
stride_t xstride)
{
// scanline not used for Maya IFF, uses tiles instead.
// Emulate by copying the scanline to the buffer we're accumulating.
std::vector<unsigned char> scratch;
data = to_native_scanline(format, data, xstride, scratch, m_dither, y, z);
size_t scanlinesize = spec().scanline_bytes(true);
size_t offset = scanlinesize * (y - spec().y)
+ scanlinesize * spec().height * (z - spec().z);
memcpy(&m_buf[offset], data, scanlinesize);
return false;
}
bool
IffOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
stride_t xstride, stride_t ystride, stride_t zstride)
{
// auto stride
m_spec.auto_stride(xstride, ystride, zstride, format, spec().nchannels,
spec().tile_width, spec().tile_height);
// native tile
data = to_native_tile(format, data, xstride, ystride, zstride, scratch,
m_dither, x, y, z);
x -= m_spec.x; // Account for offset, so x,y are file relative, not
y -= m_spec.y; // image relative
// tile size
int w = m_spec.width;
int tw = std::min(x + m_spec.tile_width, m_spec.width) - x;
int th = std::min(y + m_spec.tile_height, m_spec.height) - y;
// tile data
int iy = 0;
for (int oy = y; oy < y + th; oy++) {
// in
uint8_t* in_p = (uint8_t*)data
+ (iy * m_spec.tile_width) * m_spec.pixel_bytes();
// out
uint8_t* out_p = &m_buf[0] + (oy * w + x) * m_spec.pixel_bytes();
// copy
memcpy(out_p, in_p, tw * m_spec.pixel_bytes());
iy++;
}
return true;
}
inline bool
IffOutput::close(void)
{
if (m_fd && m_buf.size()) {
// flip buffer to make write tile easier,
// from tga.imageio:
int bytespp = m_spec.pixel_bytes();
std::vector<unsigned char> flip(m_spec.width * bytespp);
unsigned char *src, *dst, *tmp = &flip[0];
for (int y = 0; y < m_spec.height / 2; y++) {
src = &m_buf[(m_spec.height - y - 1) * m_spec.width * bytespp];
dst = &m_buf[y * m_spec.width * bytespp];
memcpy(tmp, src, m_spec.width * bytespp);
memcpy(src, dst, m_spec.width * bytespp);
memcpy(dst, tmp, m_spec.width * bytespp);
}
// write y-tiles
for (uint32_t ty = 0; ty < tile_height_size(m_spec.height); ty++) {
// write x-tiles
for (uint32_t tx = 0; tx < tile_width_size(m_spec.width); tx++) {
// channels
uint8_t channels = m_iff_header.pixel_channels;
// set tile coordinates
uint16_t xmin, xmax, ymin, ymax;
// set xmin and xmax
xmin = tx * tile_width();
xmax = std::min(xmin + tile_width(), m_spec.width) - 1;
// set ymin and ymax
ymin = ty * tile_height();
ymax = std::min(ymin + tile_height(), m_spec.height) - 1;
// set width and height
uint32_t tw = xmax - xmin + 1;
uint32_t th = ymax - ymin + 1;
// write 'RGBA' type
std::string tmpstr = "RGBA";
if (!fwrite(tmpstr.c_str(), tmpstr.length(), 1, m_fd))
return false;
// length.
uint32_t length = tw * th * m_spec.pixel_bytes();
// tile length.
uint32_t tile_length = length;
// align.
length = align_size(length, 4);
// append xmin, xmax, ymin and ymax.
length += 8;
// tile compression.
bool tile_compress = (m_iff_header.compression == RLE);
// set bytes.
std::vector<uint8_t> scratch;
scratch.resize(tile_length);
uint8_t* out_p = static_cast<uint8_t*>(&scratch[0]);
// handle 8-bit data
if (m_spec.format == TypeDesc::UINT8) {
if (tile_compress) {
uint32_t index = 0, size = 0;
std::vector<uint8_t> tmp;
// set bytes.
tmp.resize(tile_length * 2);
// map: RGB(A) to BGRA
for (int c = (channels * m_spec.channel_bytes()) - 1;
c >= 0; --c) {
std::vector<uint8_t> in(tw * th);
uint8_t* in_p = &in[0];
// set tile
for (uint16_t py = ymin; py <= ymax; py++) {
const uint8_t* in_dy
= &m_buf[0]
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
// get pixel
uint8_t pixel;
const uint8_t* in_dx
= in_dy + px * m_spec.pixel_bytes() + c;
memcpy(&pixel, in_dx, 1);
// set pixel
*in_p++ = pixel;
}
}
// compress rle channel
size = compress_rle_channel(&in[0], &tmp[0] + index,
tw * th);
index += size;
}
// if size exceeds tile length write uncompressed
if (index < tile_length) {
memcpy(&scratch[0], &tmp[0], index);
// set tile length
tile_length = index;
// append xmin, xmax, ymin and ymax
length = index + 8;
// set length
uint32_t align = align_size(length, 4);
if (align > length) {
out_p = &scratch[0] + index;
// Pad.
for (uint32_t i = 0; i < align - length; i++) {
*out_p++ = '\0';
tile_length++;
}
}
} else {
tile_compress = false;
}
}
if (!tile_compress) {
for (uint16_t py = ymin; py <= ymax; py++) {
const uint8_t* in_dy = &m_buf[0]
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
// Map: RGB(A)8 RGBA to BGRA
for (int c = channels - 1; c >= 0; --c) {
// get pixel
uint8_t pixel;
const uint8_t* in_dx
= in_dy + px * m_spec.pixel_bytes()
+ c * m_spec.channel_bytes();
memcpy(&pixel, in_dx, 1);
// set pixel
*out_p++ = pixel;
}
}
}
}
}
// handle 16-bit data
else if (m_spec.format == TypeDesc::UINT16) {
if (tile_compress) {
uint32_t index = 0, size = 0;
std::vector<uint8_t> tmp;
// set bytes.
tmp.resize(tile_length * 2);
// set map
std::vector<uint8_t> map;
if (littleendian()) {
int rgb16[] = { 0, 2, 4, 1, 3, 5 };
int rgba16[] = { 0, 2, 4, 7, 1, 3, 5, 6 };
if (m_iff_header.pixel_channels == 3) {
map = std::vector<uint8_t>(rgb16, &rgb16[6]);
} else {
map = std::vector<uint8_t>(rgba16, &rgba16[8]);
}
} else {
int rgb16[] = { 1, 3, 5, 0, 2, 4 };
int rgba16[] = { 1, 3, 5, 7, 0, 2, 4, 6 };
if (m_iff_header.pixel_channels == 3) {
map = std::vector<uint8_t>(rgb16, &rgb16[6]);
} else {
map = std::vector<uint8_t>(rgba16, &rgba16[8]);
}
}
// map: RRGGBB(AA) to BGR(A)BGR(A)
for (int c = (channels * m_spec.channel_bytes()) - 1;
c >= 0; --c) {
int mc = map[c];
std::vector<uint8_t> in(tw * th);
uint8_t* in_p = &in[0];
// set tile
for (uint16_t py = ymin; py <= ymax; py++) {
const uint8_t* in_dy
= &m_buf[0]
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
// get pixel
uint8_t pixel;
const uint8_t* in_dx
= in_dy + px * m_spec.pixel_bytes()
+ mc;
memcpy(&pixel, in_dx, 1);
// set pixel.
*in_p++ = pixel;
}
}
// compress rle channel
size = compress_rle_channel(&in[0], &tmp[0] + index,
tw * th);
index += size;
}
// if size exceeds tile length write uncompressed
if (index < tile_length) {
memcpy(&scratch[0], &tmp[0], index);
// set tile length
tile_length = index;
// append xmin, xmax, ymin and ymax
length = index + 8;
// set length
uint32_t align = align_size(length, 4);
if (align > length) {
out_p = &scratch[0] + index;
// Pad.
for (uint32_t i = 0; i < align - length; i++) {
*out_p++ = '\0';
tile_length++;
}
}
} else {
tile_compress = false;
}
}
if (!tile_compress) {
for (uint16_t py = ymin; py <= ymax; py++) {
const uint8_t* in_dy = &m_buf[0]
+ (py * m_spec.width)
* m_spec.pixel_bytes();
for (uint16_t px = xmin; px <= xmax; px++) {
// map: RGB(A) to BGRA
for (int c = channels - 1; c >= 0; --c) {
uint16_t pixel;
const uint8_t* in_dx
= in_dy + px * m_spec.pixel_bytes()
+ c * m_spec.channel_bytes();
memcpy(&pixel, in_dx, 2);
if (littleendian()) {
swap_endian(&pixel);
}
// set pixel
*out_p++ = pixel & 0xff;
*out_p++ = pixel >> 8;
}
}
}
}
}
// write 'RGBA' length
if (littleendian())
swap_endian(&length);
if (!fwrite(&length, sizeof(length), 1, m_fd))
return false;
// write xmin, xmax, ymin and ymax
if (littleendian()) {
swap_endian(&xmin);
swap_endian(&ymin);
swap_endian(&xmax);
swap_endian(&ymax);
}
if (!fwrite(&xmin, sizeof(xmin), 1, m_fd)
|| !fwrite(&ymin, sizeof(ymin), 1, m_fd)
|| !fwrite(&xmax, sizeof(xmax), 1, m_fd)
|| !fwrite(&ymax, sizeof(ymax), 1, m_fd))
return false;
// write tile
if (!fwrite(&scratch[0], tile_length, 1, m_fd))
return false;
}
}
// set sizes
uint32_t pos, tmppos;
pos = ftell(m_fd);
uint32_t p0 = pos - 8;
uint32_t p1 = p0 - m_iff_header.for4_start;
// set pos
tmppos = 4;
fseek(m_fd, tmppos, SEEK_SET);
// write FOR4 <size> CIMG
if (littleendian()) {
swap_endian(&p0);
}
if (!fwrite(&p0, sizeof(p0), 1, m_fd))
return false;
// set pos
tmppos = m_iff_header.for4_start + 4;
fseek(m_fd, tmppos, SEEK_SET);
// write FOR4 <size> TBMP
if (littleendian()) {
swap_endian(&p1);
}
if (!fwrite(&p1, sizeof(p1), 1, m_fd))
return false;
m_buf.resize(0);
m_buf.shrink_to_fit();
}
if (m_fd) {
// close the stream
fclose(m_fd);
m_fd = NULL;
}
return true;
}
void
IffOutput::compress_verbatim(const uint8_t*& in, uint8_t*& out, int size)
{
int count = 1;
unsigned char byte = 0;
// two in a row or count
for (; count < size; ++count) {
if (in[count - 1] == in[count]) {
if (byte == in[count - 1]) {
count -= 2;
break;
}
}
byte = in[count - 1];
}
// copy
*out++ = count - 1;
memcpy(out, in, count);
out += count;
in += count;
}
void
IffOutput::compress_duplicate(const uint8_t*& in, uint8_t*& out, int size)
{
int count = 1;
for (; count < size; ++count) {
if (in[count - 1] != in[count])
break;
}
const bool run = count > 1;
const int length = run ? 1 : count;
// copy
*out++ = ((count - 1) & 0x7f) | (run << 7);
*out = *in;
out += length;
in += count;
}
size_t
IffOutput::compress_rle_channel(const uint8_t* in, uint8_t* out, int size)
{
const uint8_t* const _out = out;
const uint8_t* const end = in + size;
while (in < end) {
// find runs
const int max = std::min(0x7f + 1, static_cast<int>(end - in));
if (max > 0) {
if (in < (end - 1) && in[0] == in[1]) {
// compress duplicate
compress_duplicate(in, out, max);
} else {
// compress verbatim
compress_verbatim(in, out, max);
}
}
}
const size_t r = out - _out;
return r;
}
OIIO_PLUGIN_NAMESPACE_END
+6 -2
View File
@@ -181,13 +181,17 @@ main(int argc, const char* argv[])
flag = std::regex_constants::extended;
if (ap["i"].get<int>())
flag |= std::regex_constants::icase;
bool ok = true;
try {
std::regex re(pattern, flag);
for (auto&& s : filenames)
grep_file(s, re);
} catch (const std::regex_error& e) {
std::cerr << "igrep: " << e.what() << "\n";
return EXIT_FAILURE;
ok = false;
}
return 0;
shutdown();
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
+1
View File
@@ -487,5 +487,6 @@ main(int argc, const char* argv[])
if (sum)
print("Total size: {}\n", Strutil::memformat(totalsize));
shutdown();
return returncode;
}
+47 -8
View File
@@ -94,7 +94,7 @@ public:
/// This routine will return the error string (and by default, clear any
/// error flags). If no error has occurred since the last time
/// geterror() was called, it will return an empty string.
std::string geterror(bool clear = true);
std::string geterror(bool clear = true) const;
/// Get the number of ColorSpace(s) defined in this configuration
int getNumColorSpaces() const;
@@ -102,6 +102,12 @@ public:
/// Query the name of the specified ColorSpace.
const char* getColorSpaceNameByIndex(int index) const;
/// Given a color space name, return the index of an equivalent color
/// space, or -1 if not found. It will first look for an exact match of
/// the name, but if not found, will match a color space that is
/// "equivalent" to the named color space.
int getColorSpaceIndex(string_view name) const;
/// Get the name of the color space representing the named role,
/// or NULL if none could be identified.
const char* getColorSpaceNameByRole(string_view role) const;
@@ -168,7 +174,7 @@ public:
/// inverse==true, request the inverse transformation. The
/// context_key and context_value can optionally be used to establish
/// extra key/value pairs in the OCIO context if they are comma-
/// separated lists of ontext keys and values, respectively.
/// separated lists of context keys and values, respectively.
///
/// The handle is actually a shared_ptr, so when you're done with a
/// ColorProcess, just discard it. ColorProcessor(s) remain valid even
@@ -252,14 +258,26 @@ public:
ColorProcessorHandle
createDisplayTransform(string_view display, string_view view,
string_view inputColorSpace, string_view looks = "",
string_view context_key = "",
bool inverse = false, string_view context_key = "",
string_view context_value = "") const;
ColorProcessorHandle
createDisplayTransform(ustring display, ustring view,
ustring inputColorSpace, ustring looks = ustring(),
bool inverse = false,
ustring context_key = ustring(),
ustring context_value = ustring()) const;
// OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)")
ColorProcessorHandle
createDisplayTransform(string_view display, string_view view,
string_view inputColorSpace, string_view looks,
string_view context_key,
string_view context_value = "") const;
// OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)")
ColorProcessorHandle createDisplayTransform(
ustring display, ustring view, ustring inputColorSpace, ustring looks,
ustring context_key, ustring context_value = ustring()) const;
/// Construct a processor to perform color transforms determined by an
/// OpenColorIO FileTransform. It is possible that this will return an
/// empty handle if the FileTransform doesn't exist or is not allowed.
@@ -297,6 +315,15 @@ public:
/// is found.
string_view parseColorSpaceFromString(string_view str) const;
/// Turn the name, which could be a color space, an alias, a role, or
/// an OIIO-understood universal name (like "sRGB") into a canonical
/// color space name. If the name is not recognized, return "".
string_view resolve(string_view name) const;
/// Are the two color space names/aliases/roles equivalent?
bool equivalent(string_view color_space,
string_view other_color_space) const;
/// Return a filename or other identifier for the config we're using.
std::string configname() const;
@@ -313,6 +340,13 @@ public:
/// OCIO support is available.
static int OpenColorIO_version_hex();
/// Return a default ColorConfig, which is a singleton that will be
/// created the first time it is needed. It will be initialized with the
/// OCIO environment variable, if it exists, or the OCIO built-in config
/// (for OCIO >= 2.2). If neither of those is possible, it will be
/// initialized with a built-in minimal config.
static const ColorConfig& default_colorconfig();
private:
ColorConfig(const ColorConfig&) = delete;
ColorConfig& operator=(const ColorConfig&) = delete;
@@ -324,7 +358,8 @@ private:
/// Utility -- convert sRGB value to linear
/// Utility -- convert sRGB value to linear transfer function, without
/// any change in color primaries.
/// http://en.wikipedia.org/wiki/SRGB
inline float
sRGB_to_linear(float x)
@@ -344,7 +379,8 @@ sRGB_to_linear(const simd::vfloat4& x)
}
#endif
/// Utility -- convert linear value to sRGB
/// Utility -- convert linear value to sRGB transfer function, without
/// any change in color primaries.
inline float
linear_to_sRGB(float x)
{
@@ -354,7 +390,8 @@ linear_to_sRGB(float x)
#ifndef __CUDA_ARCH__
/// Utility -- convert linear value to sRGB
/// Utility -- convert linear value to sRGB transfer function, without
/// any change in color primaries.
inline simd::vfloat4
linear_to_sRGB(const simd::vfloat4& x)
{
@@ -365,7 +402,8 @@ linear_to_sRGB(const simd::vfloat4& x)
#endif
/// Utility -- convert Rec709 value to linear
/// Utility -- convert Rec709 value to linear transfer function, without
/// any change in color primaries.
/// http://en.wikipedia.org/wiki/Rec._709
inline float
Rec709_to_linear(float x)
@@ -376,7 +414,8 @@ Rec709_to_linear(float x)
return powf((x + 0.099f) * (1.0f / 1.099f), (1.0f / 0.45f));
}
/// Utility -- convert linear value to Rec709
/// Utility -- convert linear value to Rec709 transfer function, without
/// any change in color primaries.
inline float
linear_to_Rec709(float x)
{
+3
View File
@@ -51,6 +51,9 @@ OIIO_PRAGMA_WARNING_PUSH
#if OIIO_GNUC_VERSION >= 70000
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#if OIIO_GNUC_VERSION >= 130000
# pragma GCC diagnostic ignored "-Wdangling-reference"
#endif
#if OIIO_INTEL_LLVM_COMPILER
# pragma GCC diagnostic ignored "-Wtautological-constant-compare"
#endif
+13 -2
View File
@@ -247,8 +247,19 @@ OIIO_UTIL_API int open (string_view path, int flags);
/// Read the entire contents of the named text file (as a UTF-8 encoded
/// filename) and place it in str, returning true on success, false on
/// failure.
OIIO_UTIL_API bool read_text_file (string_view filename, std::string &str);
/// failure. The optional size parameter gives the maximum amount to read
/// (for memory safety) and defaults to 16MB. Set size to 0 for no limit
/// (use at your own risk).
OIIO_UTIL_API bool read_text_file(string_view filename, std::string &str,
size_t size = (1UL << 24));
/// Run a command line process and capture its console output in `str`,
/// returning true on success, false on failure. The optional size parameter
/// gives the maximum amount to read (for memory safety) and defaults to 16MB.
/// Set size to 0 for no limit (use at your own risk).
OIIO_UTIL_API bool read_text_from_command(string_view command,
std::string &str,
size_t size = (1UL << 24));
/// Write the entire contents of the string `str` to the named file (UTF-8
/// encoded), overwriting any prior contents of the file (if it existed),
+1 -2
View File
@@ -789,8 +789,7 @@ OIIO_FORCEINLINE OIIO_HOSTDEVICE OUT_TYPE bit_cast (const IN_TYPE& in) {
#if defined(__x86_64__) && !defined(__CUDA_ARCH__) && \
(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) \
|| OIIO_CLANG_VERSION >= 100000 || OIIO_APPLE_CLANG_VERSION >= 130000 \
|| OIIO_GCC_VERSION >= 90300)
|| OIIO_CLANG_VERSION >= 100000 || OIIO_APPLE_CLANG_VERSION >= 130000)
// On x86/x86_64 for certain compilers we can use Intel CPU intrinsics for
// some common bitcast cases that might be even more understandable to the
// compiler and generate better code without its getting confused about the
+5
View File
@@ -80,7 +80,12 @@ inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed=1771)
uint64_t v;
while (pos != end) {
// This appears to be a false positive which only affects GCC.
// https://godbolt.org/z/5q7Y7ndfb
OIIO_PRAGMA_WARNING_PUSH
OIIO_GCC_ONLY_PRAGMA(GCC diagnostic ignored "-Wmaybe-uninitialized")
v = *pos++;
OIIO_PRAGMA_WARNING_PUSH
h ^= mix(v);
h *= m;
}
+85 -10
View File
@@ -679,6 +679,9 @@ bool OIIO_API resize (ImageBuf &dst, const ImageBuf &src, Filter2D *filter,
/// For "deep" images, this function returns copies the closest source pixel
/// needed, rather than attempting to interpolate deep pixels (regardless of
/// the value of `interpolate`).
///
/// @see ImageBufAlgo::resize()
ImageBuf OIIO_API resample (const ImageBuf &src, bool interpolate = true,
ROI roi={}, int nthreads=0);
/// Write to an existing image `dst` (allocating if it is uninitialized).
@@ -790,6 +793,27 @@ bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, M33fParam M,
const Filter2D *filter, bool recompute_roi = false,
ImageBuf::WrapMode wrap = ImageBuf::WrapDefault,
ROI roi = {}, int nthreads=0);
#ifdef OIIO_INTERNAL /* experimental -- not part of public API yet */
ImageBuf OIIO_API warp (const ImageBuf &src, M33fParam M,
string_view filtername,
float filterwidth, bool recompute_roi,
ImageBuf::WrapMode wrap, bool edgeclamp,
ROI roi={}, int nthreads=0);
ImageBuf OIIO_API warp (const ImageBuf &src, M33fParam M,
const Filter2D *filter, bool recompute_roi,
ImageBuf::WrapMode wrap, bool edgeclamp,
ROI roi = {}, int nthreads=0);
bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, M33fParam M,
string_view filtername,
float filterwidth, bool recompute_roi,
ImageBuf::WrapMode wrap, bool edgeclamp,
ROI roi={}, int nthreads=0);
bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, M33fParam M,
const Filter2D *filter, bool recompute_roi,
ImageBuf::WrapMode wrap, bool edgeclamp,
ROI roi = {}, int nthreads=0);
#endif // OIIO_INTERNAL
/// @}
@@ -1004,6 +1028,38 @@ ImageBuf OIIO_API pow (const ImageBuf &A, cspan<float> B,
bool OIIO_API pow (ImageBuf &dst, const ImageBuf &A, cspan<float> B,
ROI roi={}, int nthreads=0);
/// Normalize a 3D vector texture (i.e., divide each pixel by its length).
/// This function assumes a 3-channel image that represents a 3-vector, or a
/// 4-channel image that represents a 3-vector plus an alpha value. If an
/// alpha channel is present, its value is merely copied, and is not part of
/// the normalization computation. If the destination has no alpha channel but
/// the sources do, the alpha channel will be dropped.
///
/// `inCenter` and `outCenter` define the pixel value that corresponds to a
/// 0.0 vector value for input and output, respectively. `scale` defines the
/// scale factor to apply to the normalized vectors.
///
/// Thus, if the input image encodes vector components into [0,1] range pixel
/// values so that a pixel value 0.5 indicates a 0-length vector, then you
/// should use `inCenter=0.5`, whereas if they are already using the full
/// range (0.0 is encoded as 0.0), then you want `inCenter=0.0`. Similarly, if
/// you want the output normalized vectors to be in the range [0,1], use
/// `outCenter=0.5` and `scale=0.5`, but if you want them to be in the range
/// [-1,1], use `outCenter=0.0` and `scale=1.0` (this probably will only work
/// if you intend to write the results in `float` or `half` format).
///
/// Expressed another way, the computation is conceptually:
///
/// out = outCenter + scale * (in - inCenter) / length(in - inCenter)
///
bool OIIO_API normalize(ImageBuf& dst, const ImageBuf& A, float inCenter=0.0f,
float outCenter=0.0f, float scale=1.0f,
ROI roi={}, int nthreads=0);
ImageBuf OIIO_API normalize(const ImageBuf& A, float inCenter=0.0f,
float outCenter=0.0, float scale=1.0f,
ROI roi={}, int nthreads=0);
/// Converts a multi-channel image into a one-channel image via a weighted
/// sum of channels:
@@ -1827,7 +1883,7 @@ bool OIIO_API erode (ImageBuf &dst, const ImageBuf &src,
ImageBuf OIIO_API colorconvert (const ImageBuf &src,
string_view fromspace, string_view tospace, bool unpremult=true,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Transform using a ColorProcessor, returning an ImageBuf result.
@@ -1838,7 +1894,7 @@ ImageBuf OIIO_API colorconvert (const ImageBuf &src,
bool OIIO_API colorconvert (ImageBuf &dst, const ImageBuf &src,
string_view fromspace, string_view tospace, bool unpremult=true,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Transform using a ColorProcessor, storing reults into an existing ImageBuf.
@@ -1928,14 +1984,14 @@ ImageBuf OIIO_API ociolook (const ImageBuf &src, string_view looks,
string_view fromspace, string_view tospace,
bool unpremult=true, bool inverse=false,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Write to an existing image `dst` (allocating if it is uninitialized).
bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, string_view looks,
string_view fromspace, string_view tospace,
bool unpremult=true, bool inverse=false,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
@@ -1983,19 +2039,38 @@ bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, string_view looks,
ImageBuf OIIO_API ociodisplay (const ImageBuf &src,
string_view display, string_view view,
string_view fromspace="", string_view looks="",
bool unpremult=true,
bool unpremult=true, bool inverse=false,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Write to an existing image `dst` (allocating if it is uninitialized).
bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src,
string_view display, string_view view,
string_view fromspace="", string_view looks="",
bool unpremult=true,
bool unpremult=true, bool inverse=false,
string_view context_key="", string_view context_value="",
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
#ifndef OIIO_DOXYGEN
// OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)")
ImageBuf OIIO_API ociodisplay (const ImageBuf &src,
string_view display, string_view view,
string_view fromspace, string_view looks,
bool unpremult,
string_view context_key, string_view context_value="",
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
// OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)")
bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src,
string_view display, string_view view,
string_view fromspace, string_view looks,
bool unpremult,
string_view context_key, string_view context_value="",
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
#endif
/// Return the pixels of `src` within the ROI, applying an OpenColorIO
/// "file" transform. In-place operations (`dst` == `src`) are supported.
@@ -2023,13 +2098,13 @@ bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src,
ImageBuf OIIO_API ociofiletransform (const ImageBuf &src,
string_view name,
bool unpremult=true, bool inverse=false,
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Write to an existing image `dst` (allocating if it is uninitialized).
bool OIIO_API ociofiletransform (ImageBuf &dst, const ImageBuf &src,
string_view name,
bool unpremult=true, bool inverse=false,
ColorConfig *colorconfig=nullptr,
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
@@ -134,6 +134,11 @@ IBAprep(ROI& roi, ImageBuf* dst, const ImageBuf* A, int prepflags)
{
return IBAprep(roi, dst, A, NULL, NULL, NULL, prepflags);
}
inline bool
IBAprep(ROI& roi, ImageBuf* dst, int prepflags)
{
return IBAprep(roi, dst, nullptr, nullptr, nullptr, nullptr, prepflags);
}
// clang-format off
@@ -155,6 +160,7 @@ enum IBAprep_flags {
IBAprep_MINIMIZE_NCHANNELS = 1<<14, // Multi-inputs get min(nchannels)
IBAprep_REQUIRE_MATCHING_CHANNELS = 1<<15, // Channel names must match
IBAprep_MERGE_METADATA = 1 << 16, // Merge all inputs' metadata
IBAprep_FILL_ZERO_ALLOC = 1 << 17, // Fill with 0 if we alloc space
};
+22 -10
View File
@@ -28,6 +28,9 @@
OIIO_NAMESPACE_BEGIN
// Forward declaration
class TextureOpt;
namespace pvt {
// Forward declaration
class ImageCacheImpl;
@@ -222,6 +225,11 @@ public:
/// enabled, this reduces the number of file opens, at the
/// expense of not being able to open files if their format do
/// not actually match their filename extension). Default: 0
/// - `string colorspace` :
/// The working colorspace of the texture system. Default: none.
/// - `string colorconfig` :
/// Name of the OCIO config to use. Default: "" (meaning to use
/// the default color config).
///
/// - `string options`
/// This catch-all is simply a comma-separated list of
@@ -473,18 +481,22 @@ public:
/// internals.
typedef pvt::ImageCacheFile ImageHandle;
/// Retrieve an opaque handle for fast image lookups. The filename is
/// presumed to be UTF-8 encoded. The opaque `pointer thread_info` is
/// thread-specific information returned by `get_perthread_info()`.
/// Return NULL if something has gone horribly wrong.
virtual ImageHandle* get_image_handle (ustring filename,
Perthread *thread_info=NULL) = 0;
/// Retrieve an opaque handle for fast texture lookups, or nullptr upon
/// failure. The filename is presumed to be UTF-8 encoded. The `options`,
/// if not null, may be used to create a separate handle for certain
/// texture option choices. (Currently unused, but reserved for the future
/// or for alternate IC implementations.) The opaque pointer `thread_info`
/// is thread-specific information returned by `get_perthread_info()`.
virtual ImageHandle* get_image_handle(ustring filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) = 0;
/// Get an ImageHandle using a UTF-16 encoded wstring filename.
ImageHandle* get_image_handle (const std::wstring& filename,
Perthread *thread_info=NULL) {
return get_image_handle (ustring(Strutil::utf16_to_utf8(filename)),
thread_info);
ImageHandle* get_image_handle(const std::wstring& filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) {
return get_image_handle(ustring(Strutil::utf16_to_utf8(filename)),
thread_info, options);
}
/// Return true if the image handle (previously returned by
+203 -10
View File
@@ -1003,6 +1003,10 @@ public:
/// Does this format reader support retrieving a reduced
/// resolution copy of the image via the `thumbnail()` method?
///
/// - `"noimage"` :
/// Does this format allow 0x0 sized images, i.e. an image file
/// with metadata only and no pixels?
///
/// This list of queries may be extended in future releases. Since this
/// can be done simply by recognizing new query strings, and does not
/// require any new API entry points, addition of support for new
@@ -1025,11 +1029,24 @@ public:
/// `true` upon success, or `false` upon failure.
virtual bool valid_file (const std::string& filename) const;
/// Check valid vile using a UTF-16 encoded wstring filename.
/// Check valid file using a UTF-16 encoded wstring filename.
bool valid_file (const std::wstring& filename) const {
return valid_file(Strutil::utf16_to_utf8(filename));
}
/// Return true if the `ioproxy` represents a file of the type for this
/// ImageInput. The implementation will try to determine this as
/// efficiently as possible, in most cases much less expensively than
/// doing a full `open()`. Note that there can be false positives: a
/// file can appear to be of the right type (i.e., `valid_file()`
/// returning `true`) but still fail a subsequent call to `open()`, such
/// as if the contents of the file are truncated, nonsensical, or
/// otherwise corrupted.
///
/// @returns
/// `true` upon success, or `false` upon failure.
virtual bool valid_file (Filesystem::IOProxy* ioproxy) const;
/// Opens the file with given name and seek to the first subimage in the
/// file. Various file attributes are put in `newspec` and a copy
/// is also saved internally to the `ImageInput` (retrievable via
@@ -1805,6 +1822,53 @@ protected:
/// Helper: retrieve the current position of the proxy, akin to ftell.
int64_t iotell() const;
/// Helper: convenience boilerplate for several checks and operations that
/// every implementation of ImageInput::open() will need to do. Failure is
/// presumed to indicate a file that is corrupt (or perhaps maliciously
/// crafted) and no further reading should be attempted.
///
/// @param spec
/// The ImageSpec that we are validating.
///
/// @param range
/// An ROI that describes the allowable pixel coordinates and channel
/// indices as half-open intervals. For example, the default value
/// `{0, 65535, 0, 65535, 0, 1, 0, 4}` means that pixel coordinates
/// must be non-negative and the width and height be representable by
/// a uint16 value, up to 4 channels are allowed, and volumes are not
/// permitted (z coordinate may only be 0). File formats that can
/// handle larger resolutions, or volumes, or >4 channels must
/// override these limits!
///
/// @param flags
/// A bitfield flag (bits defined by `enum OpenChecks`) that can
/// indicate additional checks to perform, or checks that should be
/// skipped.
///
/// @returns
/// Return `true` if the spec is valid and passes all checks,
/// otherwise return `false` and make appropriate calls to
/// this->errorfmt() to record the errors.
///
/// Checks performed include:
///
/// * Whether the resolution and channel count are within the range
/// implied by `range`.
/// * Whether the channel count is within the `"limit:channels"` OIIO
/// attribute.
/// * The total uncompressed pixel data size is expected to be within the
/// `"limit:imagesize_MB"` OIIO attribute.
///
bool check_open (const ImageSpec &spec,
ROI range = {0, 65535, 0, 65535, 0, 1, 0, 4},
uint64_t flags = 0);
/// Bit field definitions for the `flags` argument to `check_open()`.
enum class OpenChecks : uint64_t {
Defaults = 0,
// Reserved for future use
};
/// @}
private:
@@ -2019,6 +2083,10 @@ public:
/// thumbnail must be supplied immediately after `open()`, prior
/// to any of the `write_*()` calls.)
///
/// - `"noimage"` :
/// Does this format allow 0x0 sized images, i.e. an image file
/// with metadata only and no pixels?
///
/// This list of queries may be extended in future releases. Since this
/// can be done simply by recognizing new query strings, and does not
/// require any new API entry points, addition of support for new
@@ -2490,6 +2558,102 @@ public:
typedef ImageOutput* (*Creator)();
protected:
/// @{
/// @name Helper functions for ImageOutput implementations.
///
/// This set of utility functions are not meant to be called by user code.
/// They are protected methods of ImageOutput, and are used internally by
/// the ImageOutput implementation to help it properly implement support
/// of IOProxy.
///
/// Helper: convenience boilerplate for several checks and operations that
/// every implementation of ImageOutput::open() will need to do.
///
/// 1. Check if the open `mode` is one allowed by `supports("multiimage")`
/// and `supports("mipmap")`.
/// 2. Copy the passed spec to the internal m_spec.
/// 3. Do all possible validity checks based on `supports()` (for example,
/// is the request to write volumetric data but the format writer
/// doesn't support it).
///
/// Returns true if ok, false if the open request can't be satisfied (and
/// makes appropriate calls to this->errorfmt() to record the errors).
///
/// Having a central helper method for this is beneficial:
///
/// * Less repeated code in the many open() implementations, which also
/// means less opportunity for bugs.
/// * Ensures that all image writers perform the full set of possible
/// validity checks.
/// * Ensures that error messages are consistent across all writers and
/// can be improved in a single location.
/// * Better code coverage for testing, because the error handling that is
/// done centrally means we don't need to separately test every possible
/// error condition in every writer.
///
/// @param mode
/// The mode in which the file is to be opened (`Create`,
/// `AppendSubimage`, or `AppendMIPLevel`).
///
/// @param spec
/// The ImageSpec that we are validating.
///
/// @param range
/// An ROI that describes the allowable pixel coordinates and channel
/// indices as half-open intervals. For example, the default value
/// `{0, 65535, 0, 65535, 0, 1, 0, 4}` means that pixel coordinates
/// must be non-negative and the width and height be representable by
/// a uint16 value, up to 4 channels are allowed, and volumes are not
/// permitted (z coordinate may only be 0). File formats that can
/// handle larger resolutions, or volumes, or >4 channels must
/// override these limits!
///
/// @param flags
/// A bitfield flag (bits defined by `enum OpenChecks`) that can
/// indicate additional checks to perform, or checks that should be
/// skipped.
///
/// @returns
/// Return `true` if the spec is valid and passes all checks,
/// otherwise return `false` and make appropriate calls to
/// this->errorfmt() to record the errors.
///
/// Checks performed include:
///
/// * Whether the open `mode` is one allowed by `supports("multiimage")`
/// and `supports("mipmap")`.
/// * Whether the resolution and channel count is within the range
/// implied by `range`. If `spec.depth < 1`, it will be set to 1.
/// * Whether the request for volumes or deep images can be accommodated
/// by the format (according to its `supports()` queries).
/// * If per-channel data types are supplied (and not all the same), but
/// but the file format does not not `supports("channelformats")`. If
/// `spec.channelformats` is used but all formats are equal, then
/// the `channelformats` vector will be cleared and only `spec.format`
/// will be used.
/// * If any of the "full" size fields are negative or zero, they will be
/// set to the corresponding pixel data size fields.
/// * Whether the pixel origin offset (`spec.x`, `spec.y`, `spec.z`) is
/// allowed to be non-zero (according to `supports("origin")` or
/// negative (`supports("negativeorigin")`) -- if it is not allowed,
/// it is an error if flags includes `Strict`, otherwise it will simply
/// be adjusted to 0.
/// * Whether the `extra_attribs` contains a request to use an IOProxy,
/// but the format writer does not report `supports("ioproxy")`.
bool check_open(OpenMode mode, const ImageSpec &spec,
ROI range = {0, 65535, 0, 65535, 0, 1, 0, 4},
uint64_t flags = 0);
/// Bit field definitions for the `flags` argument to `check_open()`.
enum class OpenChecks : uint64_t {
Defaults = 0,
Disallow1Channel = 1,
Disallow2Channel = 2,
Disallow1or2Channel = Disallow1Channel | Disallow2Channel,
Strict = (uint64_t(1) << 32)
};
/// Helper routines used by write_* implementations: convert data (in
/// the given format and stride) to the "native" format of the file
/// (described by the 'spec' member variable), in contiguous order. This
@@ -2545,13 +2709,15 @@ protected:
void *image_buffer,
TypeDesc buf_format = TypeDesc::UNKNOWN);
/// @}
/// @{
/// @name IOProxy aids for ImageInput implementations.
/// @name IOProxy aids for ImageOutput implementations.
///
/// This set of utility functions are not meant to be called by user code.
/// They are protected methods of ImageInput, and are used internally by
/// the ImageInput implementation to help it properly implement support of
/// IOProxy.
/// They are protected methods of ImageOutput, and are used internally by
/// the ImageOutput implementation to help it properly implement support
/// of IOProxy.
///
/// Get the IOProxy being used underneath.
@@ -2590,8 +2756,8 @@ protected:
/// Helper: retrieve the current position of the proxy, akin to ftell.
int64_t iotell() const;
// Write a formatted string to the output proxy. Return true on success,
// false upon failure and issue an error message.
/// Write a formatted string to the output proxy. Return true on success,
/// false upon failure and issue an error message.
template<typename Str, typename... Args>
inline bool iowritefmt(const Str& fmt, Args&&... args)
{
@@ -2619,6 +2785,13 @@ private:
// Utility functions
/// `OIIO::shutdown` prepares OpenImageIO for shutdown. Before exiting an
/// application that utilizes OpenImageIO the `OIIO::shutdown` function must be
/// called, which will perform shutdown of any running thread-pools. Failing
/// to call `OIIO::shutdown` could lead to a sporadic dead-lock during
/// application shutdown on certain platforms such as Windows.
OIIO_API void shutdown ();
/// Returns a numeric value for the version of OpenImageIO, 10000 for each
/// major version, 100 for each minor version, 1 for each patch. For
/// example, OpenImageIO 1.2.3 would return a value of 10203. One example of
@@ -2789,7 +2962,7 @@ OIIO_API std::string geterror(bool clear = true);
/// you should raise this limit. Setting the limit to 0 means having no
/// limit.
///
/// - `int log_times`
/// - `int log_times` (0)
///
/// When the `"log_times"` attribute is nonzero, `ImageBufAlgo` functions
/// are instrumented to record the number of times they were called and
@@ -2807,6 +2980,20 @@ OIIO_API std::string geterror(bool clear = true);
/// the log information. When the `log_times` attribute is disabled,
/// there is no additional performance cost.
///
/// - `imagebuf:print_uncaught_errors` (1)
///
/// If nonzero, an `ImageBuf` upon destruction will print any error messages
/// that were never retrieved by its `geterror()` method. While this may
/// seem chaotic, we are presuming that any well-written library or
/// application will proactively check error codes and retrieve errors, so
/// will never print anything upon destruction. But for less sophisticated
/// applications (or users), this is very useful for forcing display of
/// error messages so that users can see relevant errors even if they never
/// check them explicitly, thus self-diagnose their troubles before asking
/// the project dev deam for help. Advanced users who for some reason desire
/// to neither retrieve errors themselves nor have them printed in this
/// manner can disable the behavior by setting this attribute to 0.
///
OIIO_API bool attribute(string_view name, TypeDesc type, const void* val);
/// Shortcut attribute() for setting a single integer.
@@ -2863,8 +3050,14 @@ inline bool attribute (string_view name, string_view val) {
///
/// "tiff:LIBTIFF 4.0.4;gif:gif_lib 4.2.3;openexr:OpenEXR 2.2.0"
///
/// - string "timing_report"
/// A string containing the report of all the log_times.
/// - `string font_list`
/// - `string font_file_list`
/// - `string font_dir_list`
///
/// A semicolon-separated list of, respectively, all the fonts that
/// OpenImageIO can find, all the font files that OpenImageIO can find (with
/// full paths), and all the directories that OpenImageIO will search for
/// fonts. (Added in OpenImageIO 2.5)
///
/// - `string opencolorio_version`
///
+23
View File
@@ -88,6 +88,29 @@
OIIO_VERSION_MINOR, OIIO_VERSION_PATCH, \
OIIO_VERSION_TWEAK, "")
// OIIO_DISABLE_DEPRECATED encodes the version for which any declarations that
// were deprecated as of that version may be hidden from view of software
// including the OIIO headers. For example, if a downstream project says
//
// #define OIIO_DISABLE_DEPRECATED OIIO_MAKE_VERSION(2,2,0)
//
// before including any OpenImageIO header, then we will do our best to make
// it a compile-time error if they try to use anything that was deprecated
// in or before version 2.2.0. This is viewed as equivalent to the downstream
// package considering their minimum OIIO to be 2.2 and they want to be sure
// they aren't using any features that are slated for deprecation. The
// default, 0, will not try to hide any deprecated features.
//
// To clarify, if version 2.2 is the first to deprecate a certain definition,
// then it is considered good practice to guard it like this:
//
// #if OIIO_DISABLE_DEPRECATED < OIIO_MAKE_VERSION(2,2,0)
// ... deprecated definition here ...
// #endif
//
#ifndef OIIO_DISABLE_DEPRECATED
# define OIIO_DISABLE_DEPRECATED 0
#endif
// Establish the name spaces
namespace @PROJ_NAMESPACE_V@ { }
+5
View File
@@ -110,6 +110,11 @@ public:
: ParamValue(_name, ustring(value))
{
}
ParamValue(string_view _name, ustringhash value) noexcept
{
init_noclear(ustring(_name), TypeDesc::USTRINGHASH, 1, &value,
Copy(true));
}
// Set from string -- parse
ParamValue(string_view _name, TypeDesc type, string_view value);
+5 -19
View File
@@ -38,29 +38,15 @@
# include <malloc.h> // for alloca
#endif
#if defined(_WIN32)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef VC_EXTRALEAN
# define VC_EXTRALEAN
# endif
# ifndef NOMINMAX
# define NOMINMAX
# endif
# ifndef NOGDI
# define NOGDI
# endif
# include <windows.h>
#endif
#ifdef _MSC_VER
# include <intrin.h>
#endif
//Avoid min and max being defined
#if defined(_WIN32)
#define NOMINMAX
// Avoid min and max being defined for any subsequent include of windows.h
#ifdef _WIN32
# ifndef NOMINMAX
# define NOMINMAX
# endif
#endif
#include <OpenImageIO/oiioversion.h>
+6
View File
@@ -25,6 +25,7 @@
/// Additional web resources:
/// http://www.codersnotes.com/notes/maths-lib-2016/
/// https://www.agner.org/optimize/
/// https://www.corsix.org/content/converting-fp32-to-fp16
// clang-format off
@@ -292,7 +293,11 @@ class vbool16;
class vint16;
class vfloat16;
#if OIIO_DISABLE_DEPRECATED < OIIO_MAKE_VERSION(1,9,0) && !defined(OIIO_INTERNAL)
// Deprecated names -- remove these in 1.9
// These are removed from visibility for the OIIO codebase itself, or for any
// downstream project that defines OIIO_DISABLE_DEPRECATED to exclude
// declarations deprecated as of version 1.9 or later.
typedef vbool4 mask4; // old name
typedef vbool4 bool4;
typedef vbool8 bool8;
@@ -301,6 +306,7 @@ typedef vint8 int8;
typedef vfloat3 float3;
typedef vfloat4 float4;
typedef vfloat8 float8;
#endif
} // namespace simd
+26 -10
View File
@@ -127,11 +127,7 @@ template<typename Str, typename... Args>
OIIO_NODISCARD
inline std::string format(const Str& fmt, Args&&... args)
{
#if FMT_VERSION >= 70000
return ::fmt::vformat(fmt, ::fmt::make_format_args(args...));
#else
return ::fmt::format(fmt, args...);
#endif
}
} // namespace fmt
@@ -371,26 +367,46 @@ std::string OIIO_UTIL_API wordwrap (string_view src, int columns = 80,
/// Our favorite "string" hash of a length of bytes. Currently, it is just
/// a wrapper for an inlined, constexpr (if C++ >= 14), Cuda-safe farmhash.
/// It returns a size_t, so will be a 64 bit hash on 64-bit platforms, but
/// a 32 bit hash on 32-bit platforms.
inline constexpr size_t
strhash (size_t len, const char *s)
strhash(size_t len, const char *s)
{
return OIIO::farmhash::inlined::Hash(s, len);
}
/// A guaranteed 64-bit string hash on all platforms.
inline constexpr uint64_t
strhash64(size_t len, const char *s)
{
return OIIO::farmhash::inlined::Hash64(s, len);
}
/// Hash a string_view. This is OIIO's default favorite string hasher.
/// Currently, it uses farmhash, is constexpr (for C++14), and works in
/// Cuda. This is rigged, though, so that empty strings hash always hash to
/// 0 (that isn't what a raw farmhash would give you, but it's a useful
/// property, especially for trivial initialization).
/// Currently, it uses farmhash, is constexpr (for C++14), and works in Cuda.
/// This is rigged, though, so that empty strings hash always hash to 0 (that
/// isn't what a raw farmhash would give you, but it's a useful property,
/// especially for trivial initialization). It returns a size_t, so will be a
/// 64 bit hash on 64-bit platforms, but a 32 bit hash on 32-bit platforms.
inline constexpr size_t
strhash (string_view s)
strhash(string_view s)
{
return s.length() ? strhash(s.length(), s.data()) : 0;
}
/// Hash a string_view, guaranteed 64 bits (even on 32 bit platforms).
inline constexpr uint64_t
strhash64(string_view s)
{
return s.length() ? strhash64(s.length(), s.data()) : 0;
}
/// Case-insensitive comparison of strings. For speed, this always uses a
/// static locale that doesn't require a mutex. Caveat: the case-sensivive
/// `==` of string_view's is about 20x faster than this case-insensitive
+35 -13
View File
@@ -20,6 +20,7 @@
// Define symbols that let client applications determine if newly added
// features are supported.
#define OIIO_TEXTURESYSTEM_SUPPORTS_CLOSE 1
#define OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE 1
// Is the getattributetype() method present? (Added in 2.5)
#define OIIO_TEXTURESYSTEM_SUPPORTS_GETATTRIBUTETYPE 1
@@ -232,6 +233,7 @@ public:
fill(0.0f), missingcolor(nullptr),
time(0.0f), rnd(-1.0f), samples(1),
rwrap(WrapDefault), rblur(0.0f), rwidth(1.0f),
colortransformid(0),
envlayout(0)
{ }
@@ -264,6 +266,8 @@ public:
float rblur; ///< Blur amount in the r direction
float rwidth; ///< Multiplier for derivatives in r direction
int colortransformid; ///< Color space id of the texture
/// Utility: Return the Wrap enum corresponding to a wrap name:
/// "default", "black", "clamp", "periodic", "mirror".
static Wrap decode_wrapmode(const char* name)
@@ -313,9 +317,7 @@ public:
alignas(Tex::BatchAlign) float twidth[Tex::BatchWidth];
alignas(Tex::BatchAlign) float rwidth[Tex::BatchWidth];
// Note: rblur,rwidth only used for volumetric lookups
#if OIIO_VERSION_GREATER_EQUAL(2,4,0)
alignas(Tex::BatchAlign) float rnd[Tex::BatchWidth];
#endif
// Options that must be the same for all points we're texturing at once
int firstchannel = 0; ///< First channel of the lookup
@@ -330,6 +332,7 @@ public:
int conservative_filter = 1; ///< True: over-blur rather than alias
float fill = 0.0f; ///< Fill value for missing channels
const float *missingcolor = nullptr; ///< Color for missing texture
int colortransformid = 0; ///< Color space id of the texture
private:
// Options set INTERNALLY by libtexture after the options are passed
@@ -554,6 +557,10 @@ public:
/// - `int max_errors_per_file` :
/// Limits how many errors to issue for each file. (default:
/// 100)
/// - `string colorspace` :
/// The working colorspace of the texture system.
/// - `string colorconfig` :
/// Name of the OCIO config to use (default: "").
///
/// Texture-specific settings:
/// - `matrix44 worldtocommon` / `matrix44 commontoworld` :
@@ -791,16 +798,20 @@ public:
class TextureHandle;
/// Retrieve an opaque handle for fast texture lookups. The filename is
/// presumed to be UTF-8 encoded. The opaque pointer `thread_info` is
/// thread-specific information returned by `get_perthread_info()`.
/// Return nullptr if something has gone horribly wrong.
virtual TextureHandle* get_texture_handle (ustring filename,
Perthread *thread_info=nullptr) = 0;
/// presumed to be UTF-8 encoded. The `options`, if not null, may be used
/// to create a separate handle for certain texture option choices
/// (currently: the colorspace). The opaque pointer `thread_info` is
/// thread-specific information returned by `get_perthread_info()`. Return
/// nullptr if something has gone horribly wrong.
virtual TextureHandle* get_texture_handle(ustring filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) = 0;
/// Get a TextureHandle using a UTF-16 encoded wstring filename.
TextureHandle* get_texture_handle (const std::wstring& filename,
Perthread *thread_info=nullptr) {
return get_texture_handle (ustring(Strutil::utf16_to_utf8(filename)),
thread_info);
TextureHandle* get_texture_handle(const std::wstring& filename,
Perthread* thread_info = nullptr,
const TextureOpt* options = nullptr) {
return get_texture_handle(ustring(Strutil::utf16_to_utf8(filename)),
thread_info, options);
}
/// Return true if the texture handle (previously returned by
@@ -813,6 +824,14 @@ public:
/// This method was added in OpenImageIO 2.3.
virtual ustring filename_from_handle(TextureHandle* handle) = 0;
/// Retrieve an id for a color transformation by name. This ID can be used
/// as the value for TextureOpt::colortransformid. The returned value will
/// be -1 if either color space is unknown, and 0 for a null
/// transformation.
virtual int get_colortransform_id(ustring fromspace,
ustring tospace) const = 0;
virtual int get_colortransform_id(ustringhash fromspace,
ustringhash tospace) const = 0;
/// @}
/// @{
@@ -1750,8 +1769,8 @@ public:
/// `filenames` will be sized to `ntiles * nvtiles` and filled with the
/// the names of the concrete files comprising the atlas, with an empty
/// ustring corresponding to any unpopulated tiles (the UDIM set is
/// allowed to be sparse). The filename list is indexed as `utile + vtile
/// * nvtiles`.
/// allowed to be sparse). The filename list is indexed as
/// `utile + vtile * nvtiles`.
///
/// This method was added in OpenImageIO 2.3.
virtual void inventory_udim(ustring udimpattern,
@@ -1833,6 +1852,9 @@ public:
virtual ~TextureSystem () { }
// For testing -- do not use
static void unit_test_hash();
protected:
// User code should never directly construct or destruct a TextureSystem.
// Always use TextureSystem::create() and TextureSystem::destroy().
+24 -8
View File
@@ -112,11 +112,19 @@ pause(int delay) noexcept
#elif defined(_MSC_VER)
for (int i = 0; i < delay; ++i) {
# if defined(_WIN64)
YieldProcessor();
# else
// A reimplementation of winnt.h YieldProcessor,
// to avoid including windows headers.
#if defined(_M_AMD64)
_mm_pause();
#elif defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64)
__dmb(_ARM64_BARRIER_ISHST);
__yield();
#elif defined(_M_ARM)
__dmb(_ARM_BARRIER_ISHST);
__yield();
#else
_asm pause
# endif /* _WIN64 */
#endif
}
#else
@@ -762,10 +770,18 @@ private:
/// Return a reference to the "default" shared thread pool. In almost all
/// ordinary circumstances, you should use this exclusively to get a
/// single shared thread pool, since creating multiple thread pools
/// could result in hilariously over-threading your application.
OIIO_UTIL_API thread_pool* default_thread_pool ();
/// ordinary circumstances, you should use this exclusively to get a single
/// shared thread pool, since creating multiple thread pools could result in
/// hilariously over-threading your application. Note that this call may
/// (safely, and only once) trigger creation of the thread pool and its
/// worker threads if it has not yet been created.
OIIO_UTIL_API thread_pool* default_thread_pool();
/// If a thread pool has been created, this call will safely terminate its
/// worker threads. This should presumably be called by an application
/// immediately before it exists, when it is confident the thread pool will
/// no longer be needed.
OIIO_UTIL_API void default_thread_pool_shutdown();
+22 -18
View File
@@ -21,7 +21,6 @@
#include <OpenImageIO/strutil.h>
#ifdef _WIN32
//# include <windows.h> // Already done by platform.h
#elif defined(__APPLE__)
# include <mach/mach_time.h>
#else
@@ -64,27 +63,32 @@ class OIIO_UTIL_API Timer {
public:
typedef int64_t ticks_t;
enum StartNowVal { DontStartNow, StartNow };
enum PrintDtrVal { DontPrintDtr, PrintDtr };
enum PrintDtrVal { DontPrintDtr, PrintDtr, PrintCtrDtr };
/// Constructor -- reset at zero, and start timing unless optional
/// 'startnow' argument is false.
Timer(StartNowVal startnow = StartNow, PrintDtrVal printdtr = DontPrintDtr,
Timer(StartNowVal startnow, PrintDtrVal printdtr = DontPrintDtr,
const char* name = NULL)
: m_ticking(false)
, m_printdtr(printdtr == PrintDtr)
, m_printdtr(printdtr == PrintDtr || printdtr == PrintCtrDtr)
, m_starttime(0)
, m_elapsed_ticks(0)
, m_name(name)
{
if (startnow == StartNow)
if (startnow == StartNow) {
start();
if (printdtr == PrintCtrDtr) {
Strutil::print("Starting timer {}\n", (m_name ? m_name : ""),
seconds(ticks()));
}
}
}
/// Constructor -- reset at zero, and start timing unless optional
/// 'startnow' argument is false.
Timer(bool startnow)
Timer(bool startnow = true)
: m_ticking(false)
, m_printdtr(DontPrintDtr)
, m_printdtr(false)
, m_starttime(0)
, m_elapsed_ticks(0)
, m_name(NULL)
@@ -96,9 +100,9 @@ public:
/// Destructor.
~Timer()
{
if (m_printdtr == PrintDtr)
Strutil::printf("Timer %s: %gs\n", (m_name ? m_name : ""),
seconds(ticks()));
if (m_printdtr)
Strutil::print("Timer {}: {:g}s\n", (m_name ? m_name : ""),
seconds(ticks()));
}
/// Start (or restart) ticking, if we are not currently.
@@ -199,23 +203,23 @@ private:
/// Platform-dependent grab of current time, expressed as ticks_t.
///
ticks_t now(void) const
{
#ifdef _WIN32
LARGE_INTEGER n;
QueryPerformanceCounter(&n); // From MSDN web site
return n.QuadPart;
#elif defined(__APPLE__)
; // a non-inline function on Windows
#else
{
# if defined(__APPLE__)
return mach_absolute_time();
#elif OIIO_TIMER_LINUX_USE_clock_gettime
# elif OIIO_TIMER_LINUX_USE_clock_gettime
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return int64_t(t.tv_sec) * int64_t(1000000000) + t.tv_nsec;
#else
# else
struct timeval t;
gettimeofday(&t, NULL);
return int64_t(t.tv_sec) * int64_t(1000000) + t.tv_usec;
#endif
# endif
}
#endif
/// Difference between two times, expressed in (platform-dependent)
/// ticks.
+7
View File
@@ -83,6 +83,7 @@ struct OIIO_UTIL_API TypeDesc {
DOUBLE, ///< 64-bit IEEE floating point values, (C/C++ `double`).
STRING, ///< Character string.
PTR, ///< A pointer value.
USTRINGHASH, ///< The hash of a ustring
LASTBASE
};
@@ -404,6 +405,7 @@ OIIO_INLINE_CONSTEXPR TypeDesc TypeTimeCode (TypeDesc::UINT, TypeDesc::SCALAR, T
OIIO_INLINE_CONSTEXPR TypeDesc TypeKeyCode (TypeDesc::INT, TypeDesc::SCALAR, TypeDesc::KEYCODE, 7);
OIIO_INLINE_CONSTEXPR TypeDesc TypeRational(TypeDesc::INT, TypeDesc::VEC2, TypeDesc::RATIONAL);
OIIO_INLINE_CONSTEXPR TypeDesc TypePointer(TypeDesc::PTR);
OIIO_INLINE_CONSTEXPR TypeDesc TypeUstringhash(TypeDesc::USTRINGHASH);
@@ -485,6 +487,10 @@ template<> struct TypeDescFromC<Imath::Box3i> { static const constexpr TypeDesc
#endif
class ustringhash; // forward declaration
/// A template mechanism for getting C type of TypeDesc::BASETYPE.
///
template<int b> struct CType {};
@@ -501,6 +507,7 @@ template<> struct CType<(int)TypeDesc::HALF> { typedef half type; };
#endif
template<> struct CType<(int)TypeDesc::FLOAT> { typedef float type; };
template<> struct CType<(int)TypeDesc::DOUBLE> { typedef double type; };
template<> struct CType<(int)TypeDesc::USTRINGHASH> { typedef ustringhash type; };
+18 -17
View File
@@ -127,6 +127,7 @@ class OIIO_UTIL_API ustring {
public:
using rep_t = const char*; ///< The underlying representation type
using value_type = char;
using hash_t = uint64_t; ///< The hash type
using pointer = value_type*;
using reference = value_type&;
using const_reference = const value_type&;
@@ -314,7 +315,7 @@ public:
}
/// Return a hashed version of the string
size_t hash() const noexcept
hash_t hash() const noexcept
{
if (!m_chars)
return 0;
@@ -741,7 +742,7 @@ public:
/// ustring() if there is no registered ustring with that hash. Note that
/// if there are multiple ustrings with the same hash, this will return
/// the first one it finds in the table.
OIIO_NODISCARD static ustring from_hash(size_t hash);
OIIO_NODISCARD static ustring from_hash(hash_t hash);
private:
// Individual ustring internal representation -- the unique characters.
@@ -755,12 +756,12 @@ public:
// if you know the rep, the chars are at (char *)(rep+1), and if you
// know the chars, the rep is at ((TableRep *)chars - 1).
struct TableRep {
size_t hashed; // precomputed Hash value
hash_t hashed; // precomputed Hash value
std::string str; // String representation
size_t length; // Length of the string; must be right before cap
size_t dummy_capacity; // Dummy field! must be right before refcount
int dummy_refcount; // Dummy field! must be right before chars
TableRep(string_view strref, size_t hash);
TableRep(string_view strref, hash_t hash);
~TableRep();
const char* c_str() const noexcept { return (const char*)(this + 1); }
};
@@ -789,7 +790,8 @@ private:
///
class OIIO_UTIL_API ustringhash {
public:
using rep_t = size_t; ///< The underlying representation type
using rep_t = ustring::hash_t; ///< The underlying representation type
using hash_t = ustring::hash_t; ///< The hash type
// Default constructor
OIIO_HOSTDEVICE constexpr ustringhash() noexcept
@@ -853,7 +855,7 @@ public:
/// Construct from a raw hash value. Beware: results are undefined if it's
/// not the valid hash of a ustring.
OIIO_HOSTDEVICE explicit constexpr ustringhash(size_t hash) noexcept
OIIO_HOSTDEVICE explicit constexpr ustringhash(hash_t hash) noexcept
: m_hash(hash)
{
}
@@ -909,7 +911,7 @@ public:
#endif
/// Return a hashed version of the string
OIIO_HOSTDEVICE constexpr size_t hash() const noexcept { return m_hash; }
OIIO_HOSTDEVICE constexpr hash_t hash() const noexcept { return m_hash; }
#ifndef __CUDA_ARCH__
/// Return the number of characters in the string.
@@ -986,8 +988,8 @@ public:
#endif
/// Return the ustringhash corresponding to the given hash. Caveat emptor:
/// results are undefined if it's not the hash value of a ustring.
OIIO_NODISCARD static constexpr ustringhash from_hash(size_t hash)
/// results are undefined if it's not the valid hash of a ustring.
OIIO_NODISCARD static constexpr ustringhash from_hash(hash_t hash)
{
ustringhash u;
u.m_hash = hash;
@@ -1003,8 +1005,8 @@ private:
static_assert(sizeof(ustringhash) == sizeof(size_t),
"ustringhash should be the same size as a size_t");
static_assert(sizeof(ustringhash) == sizeof(uint64_t),
"ustringhash should be the same size as a uint64_t");
static_assert(sizeof(ustring) == sizeof(const char*),
"ustring should be the same size as a const char*");
@@ -1049,10 +1051,6 @@ OIIO_DEVICE_CONSTEXPR ustringhash operator""_ush(const char* str,
/// Deprecated -- This is too easy to confuse with the ustringhash class. And
/// also it is unnecessary if you use std::hash<ustring>. This will be removed
/// in OIIO 3.0.
# if OIIO_VERSION_GREATER_EQUAL(2, 6, 0)
OIIO_DEPRECATED("Use std::hash<ustring> instead of ustringHash")
# endif
using ustringHash = std::hash<ustring>;
#endif
@@ -1138,7 +1136,10 @@ OIIO_NAMESPACE_END
namespace std { // not necessary in C++17, then we can just say std::hash
// std::hash specialization for ustring
template<> struct hash<OIIO::ustring> {
std::size_t operator()(OIIO::ustring u) const noexcept { return u.hash(); }
std::size_t operator()(OIIO::ustring u) const noexcept
{
return static_cast<std::size_t>(u.hash());
}
};
@@ -1147,7 +1148,7 @@ template<> struct hash<OIIO::ustringhash> {
OIIO_HOSTDEVICE constexpr std::size_t
operator()(OIIO::ustringhash u) const noexcept
{
return u.hash();
return static_cast<std::size_t>(u.hash());
}
};
} // namespace std
+1 -1
View File
@@ -127,6 +127,6 @@ main(int argc, char* argv[])
std::cout << "\n";
std::cout << imagecache->getstats(1 + verbose) << "\n";
}
shutdown();
return r;
}
+2 -6
View File
@@ -62,10 +62,8 @@ public:
{
return (feature == "exif" || feature == "iptc" || feature == "ioproxy");
}
bool valid_file(const std::string& filename) const override
{
return valid_file(filename, nullptr);
}
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& spec) override;
bool open(const std::string& name, ImageSpec& spec,
const ImageSpec& config) override;
@@ -119,8 +117,6 @@ private:
bool read_icc_profile(j_decompress_ptr cinfo, ImageSpec& spec);
bool valid_file(const std::string& filename, Filesystem::IOProxy* io) const;
void close_file() { init(); }
friend class JpgOutput;
+7 -17
View File
@@ -138,26 +138,16 @@ JpgInput::jpegerror(my_error_ptr /*myerr*/, bool fatal)
bool
JpgInput::valid_file(const std::string& filename, Filesystem::IOProxy* io) const
JpgInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
// Check magic number to assure this is a JPEG file
uint8_t magic[2] = { 0, 0 };
bool ok = true;
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Read)
return false;
if (io) {
ok = (io->pread(magic, sizeof(magic), 0) == sizeof(magic));
} else {
FILE* fd = Filesystem::fopen(filename, "rb");
if (!fd)
return false;
ok = (::fread(magic, sizeof(magic), 1, fd) == 1);
fclose(fd);
}
if (magic[0] != JPEG_MAGIC1 || magic[1] != JPEG_MAGIC2) {
ok = false;
}
return ok;
uint8_t magic[2] {};
const size_t numRead = ioproxy->pread(magic, sizeof(magic), 0);
return numRead == sizeof(magic) && magic[0] == JPEG_MAGIC1
&& magic[1] == JPEG_MAGIC2;
}
+6 -17
View File
@@ -121,27 +121,16 @@ bool
JpgOutput::open(const std::string& name, const ImageSpec& newspec,
OpenMode mode)
{
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
return false;
}
// Save name and spec for later use
m_filename = name;
m_spec = newspec;
// Check for things this format doesn't support
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
if (!check_open(mode, newspec,
{ 0, JPEG_MAX_DIMENSION, 0, JPEG_MAX_DIMENSION, 0, 1, 0,
256 }))
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
// NOTE: we appear to let a large number of channels be allowed, but
// that's only because we robustly truncate to only RGB no matter what we
// are handed.
ioproxy_retrieve_from_config(m_spec);
if (!ioproxy_use_or_open(name))
+3 -25
View File
@@ -33,7 +33,7 @@ public:
const char* format_name(void) const override { return "jpeg2000"; }
int supports(string_view feature) const override
{
return feature == "alpha" || feature == "ioproxy";
return feature == "alpha" || feature == "ioproxy" || feature == "tiles";
// FIXME: we should support Exif/IPTC, but currently don't.
}
bool open(const std::string& name, const ImageSpec& spec,
@@ -150,33 +150,11 @@ bool
Jpeg2000Output::open(const std::string& name, const ImageSpec& spec,
OpenMode mode)
{
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
if (!check_open(mode, spec, { 0, 1 << 20, 0, 1 << 20, 0, 1, 0, 4 },
uint64_t(OpenChecks::Disallow2Channel)))
return false;
}
m_filename = name;
m_spec = spec;
// Check for things this format doesn't support
if (m_spec.width < 1 || m_spec.height < 1) {
errorf("Image resolution must be at least 1x1, you asked for %d x %d",
m_spec.width, m_spec.height);
return false;
}
if (m_spec.depth < 1)
m_spec.depth = 1;
if (m_spec.depth > 1) {
errorf("%s does not support volume images (depth > 1)", format_name());
return false;
}
if (m_spec.nchannels != 1 && m_spec.nchannels != 3
&& m_spec.nchannels != 4) {
errorf("%s does not support %d-channel images\n", format_name(),
m_spec.nchannels);
return false;
}
// If not uint8 or uint16, default to uint16
if (m_spec.format != TypeDesc::UINT8 && m_spec.format != TypeDesc::UINT16)
+14 -2
View File
@@ -103,6 +103,18 @@ if (EMBEDPLUGINS)
endforeach ()
endif ()
# Enable default use of OpenEXR core library for versions of the library
# new enough to support DWA compression in exrcore.
if (OPENEXR_VERSION VERSION_GREATER_EQUAL 3.1.10)
target_compile_definitions(OpenImageIO
PRIVATE OIIO_OPENEXR_CORE_DEFAULT=1)
message (STATUS "OpenEXR core library will be used by default")
else ()
target_compile_definitions(OpenImageIO
PRIVATE OIIO_OPENEXR_CORE_DEFAULT=0)
message (STATUS "OpenEXR core library will not be used by default")
endif ()
# Source groups for libutil and libtexture
source_group ("libutil" REGULAR_EXPRESSION ".+/libutil/.+")
source_group ("libtexture" REGULAR_EXPRESSION ".+/libtexture/.+")
@@ -216,7 +228,7 @@ install_targets (OpenImageIO)
# Testing
if (OIIO_BUILD_TESTS)
if (OIIO_BUILD_TESTS AND BUILD_TESTING)
add_executable (color_test color_test.cpp)
target_link_libraries (color_test PRIVATE OpenImageIO)
@@ -260,4 +272,4 @@ if (OIIO_BUILD_TESTS)
set_target_properties (compute_test PROPERTIES FOLDER "Unit Tests")
add_test (unit_compute ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/compute_test)
endif (OIIO_BUILD_TESTS)
endif ()
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1302,6 +1302,8 @@ encode_exif(const ImageSpec& spec, std::vector<char>& blob,
TIFFHeader head;
head.tiff_magic = (endianreq == endian::little) ? 0x4949 : 0x4d4d;
head.tiff_version = 42;
if (endianreq != endian::native)
swap_endian(&head.tiff_version);
// N.B. need to swap_endian head.tiff_diroff below, once we know the sizes
append(blob, head);
+10
View File
@@ -485,6 +485,16 @@ ImageBufImpl::~ImageBufImpl()
// else init_spec requested the system-wide shared cache, which
// does not need to be destroyed.
clear();
// Upon destruction, print uncaught errors to help users who don't know
// how to properly check for errors.
if (!m_err.empty() /* Note: safe becausethis is the dtr */
&& pvt::imagebuf_print_uncaught_errors) {
OIIO::print(
"An ImageBuf was destroyed with a pending error message that was never\n"
"retrieved via ImageBuf::geterror(). This was the error message:\n{}\n",
m_err);
}
}
+12
View File
@@ -501,6 +501,16 @@ test_write_over()
static void
test_uncaught_error()
{
ImageBuf buf;
buf.error("Boo!");
// buf exists scope and is destroyed without anybody retrieving the error.
}
int
main(int /*argc*/, char* /*argv*/[])
{
@@ -534,6 +544,8 @@ main(int /*argc*/, char* /*argv*/[])
test_write_over();
test_uncaught_error();
Filesystem::remove("A_imagebuf_test.tif");
return unit_test_failures;
}
+3 -1
View File
@@ -254,7 +254,9 @@ ImageBufAlgo::IBAprep(ROI& roi, ImageBuf* dst, const ImageBuf* A,
}
}
dst->reset(spec);
dst->reset(spec, (prepflags & IBAprep_FILL_ZERO_ALLOC)
? InitializePixels::Yes
: InitializePixels::No);
// If we just allocated more channels than the caller will write,
// clear the extra channels.
+188 -88
View File
@@ -5,6 +5,8 @@
#include <algorithm>
#include <cmath>
#include <limits>
#include <set>
#include <unordered_map>
#include <OpenImageIO/half.h>
@@ -185,6 +187,22 @@ ImageBufAlgo::zero(ImageBuf& dst, ROI roi, int nthreads)
pvt::LoggedTimer logtime("IBA::zero");
if (!IBAprep(roi, &dst))
return false;
OIIO_ASSERT(dst.localpixels());
if (dst.contiguous() && roi == dst.roi() && !dst.deep()) {
// Special case: we're zeroing out an entire contiguous buffer -- safe
// to use use memset.
ImageBufAlgo::parallel_image(roi, nthreads, [=, &dst](ROI roi) {
auto size = dst.spec().pixel_bytes() * imagesize_t(roi.width());
for (int z = roi.zbegin; z < roi.zend; ++z) {
for (int y = roi.ybegin; y < roi.yend; ++y) {
memset(dst.pixeladdr(roi.xbegin, y, z), 0, size);
}
}
});
return true;
}
// More general case -- fall back on fill_const
float* zero = OIIO_ALLOCA(float, roi.chend);
memset(zero, 0, roi.chend * sizeof(float));
bool ok;
@@ -707,14 +725,165 @@ ImageBufAlgo::bluenoise_image()
static std::vector<std::string> font_search_dirs;
static std::vector<std::string> all_font_files;
static std::vector<std::string> all_fonts;
static std::unordered_map<std::string, std::string> font_file_map;
static std::mutex font_search_mutex;
static bool fonts_are_enumerated = false;
static const char* font_dir_prefix_envvars[]
= { "OPENIMAGEIO_FONTS", "HOME", "SystemRoot", "OpenImageIO_ROOT" };
static const char* font_dir_prefixes[]
= { "/Library/Fonts", "/System/Library/Fonts",
"C:/Windows", "/usr",
"/usr/local", "/opt/local" };
static const char* font_dir_suffixes[]
= { "fonts", "Fonts", "Library/Fonts",
"share/fonts", "share/Fonts", "share/fonts/OpenImageIO" };
static const char* default_font_name[] = { "DroidSans", "cour", "Courier New",
"FreeMono", nullptr };
// static const char* font_extensions[] = { "", ".ttf", ".ttc", ".pfa", ".pfb" };
// Add one dir to font_search_dirs, if the dir exists.
static void
fontpath_add_one_dir(string_view dir, int recursion = 0)
{
if (dir.size() && Filesystem::is_directory(dir)) {
font_search_dirs.emplace_back(dir);
if (recursion) {
std::vector<std::string> files;
if (Filesystem::get_directory_entries(dir, files, false)) {
for (auto&& subdir : files)
fontpath_add_one_dir(subdir, recursion - 1);
}
}
}
}
// Add all the dirs in a searchpath to font_search_dirs.
static void
fontpath_add_from_searchpath(string_view searchpath)
{
if (searchpath.size()) {
for (auto& dir : Filesystem::searchpath_split(searchpath, true)) {
fontpath_add_one_dir(dir);
for (auto s : font_dir_suffixes)
fontpath_add_one_dir(Strutil::fmt::format("{}/{}", dir, s));
}
}
}
// Add dir/{common_font_subdirs} to font_search_dirs.
static void
fontpath_add_from_dir(const std::string& dir)
{
if (dir.size() && Filesystem::is_directory(dir)) {
fontpath_add_one_dir(dir);
for (auto s : font_dir_suffixes)
fontpath_add_one_dir(Strutil::fmt::format("{}/{}", dir, s));
}
}
static void
enumerate_fonts()
{
std::lock_guard<std::mutex> lock(font_search_mutex);
if (fonts_are_enumerated)
return; // already done
// Find all the existing dirs from the font search path to populate
// font_search_dirs.
fontpath_add_from_searchpath(pvt::font_searchpath);
for (auto s : font_dir_prefix_envvars)
fontpath_add_from_searchpath(Sysutil::getenv(s));
for (auto s : font_dir_prefixes)
fontpath_add_from_dir(s);
std::string this_program = OIIO::Sysutil::this_program_path();
if (this_program.size()) {
std::string path = Filesystem::parent_path(this_program);
path = Filesystem::parent_path(path);
fontpath_add_from_dir(path);
}
// Get list of directories one level deeper than the font_search_dirs
auto dirs = font_search_dirs;
for (auto& dir : font_search_dirs) {
std::vector<std::string> filenames;
Filesystem::get_directory_entries(dir, filenames, false);
for (auto& f : filenames)
if (f.size() && Filesystem::is_directory(f))
dirs.push_back(f);
}
// Look for all the font files in dirs, populate font_file_set and font_set
std::set<std::string> font_set;
std::set<std::string> font_file_set;
for (auto& dir : dirs) {
std::vector<std::string> filenames;
Filesystem::get_directory_entries(dir, filenames, false);
for (auto& f : filenames) {
if (Strutil::iends_with(f, ".ttf") || Strutil::iends_with(f, ".ttc")
|| Strutil::iends_with(f, ".pfa")
|| Strutil::iends_with(f, ".pfb")) {
std::string fontname
= Filesystem::replace_extension(Filesystem::filename(f),
"");
font_file_set.insert(f);
font_set.insert(fontname);
if (font_file_map.find(fontname) == font_file_map.end())
font_file_map[fontname] = f;
}
}
}
for (auto& f : font_file_set)
all_font_files.push_back(f);
for (auto& f : font_set)
all_fonts.push_back(f);
// Don't need to do that again
fonts_are_enumerated = true;
}
const std::vector<std::string>&
pvt::font_dirs()
{
enumerate_fonts();
return font_search_dirs;
}
const std::vector<std::string>&
pvt::font_file_list()
{
enumerate_fonts();
return all_font_files;
}
const std::vector<std::string>&
pvt::font_list()
{
enumerate_fonts();
return all_fonts;
}
#ifdef USE_FREETYPE
namespace { // anon
static mutex ft_mutex;
static FT_Library ft_library = NULL;
static bool ft_broken = false;
static std::vector<std::string> font_search_dirs;
static const char* default_font_name[] = { "DroidSans", "cour", "Courier New",
"FreeMono", nullptr };
// Helper: given unicode and a font face, compute its size
static ROI
@@ -748,43 +917,6 @@ text_size_from_unicode(cspan<uint32_t> utext, FT_Face face, int fontsize)
}
// Add one dir to font_search_dirs, if the dir exists.
static void
fontpath_add_one_dir(string_view dir)
{
if (dir.size() && Filesystem::is_directory(dir))
font_search_dirs.emplace_back(dir);
}
// Add all the dirs in a searchpath to font_search_dirs.
static void
fontpath_add_from_searchpath(string_view searchpath)
{
if (searchpath.size()) {
std::vector<std::string> user_font_dirs;
Filesystem::searchpath_split(searchpath, user_font_dirs, true);
for (auto& dir : user_font_dirs)
fontpath_add_one_dir(dir);
}
}
// Add dir/{common_font_subdirs} to font_search_dirs.
static void
fontpath_add_from_dir(const std::string& dir)
{
if (dir.size() && Filesystem::is_directory(dir)) {
fontpath_add_one_dir(dir + "/fonts");
fontpath_add_one_dir(dir + "/Fonts");
fontpath_add_one_dir(dir + "/Library/Fonts");
fontpath_add_one_dir(dir + "/share/fonts");
fontpath_add_one_dir(dir + "/share/Fonts");
}
}
// Given font name, resolve it to an existing font filename.
// If found, return true and put the resolved filename in result.
// If not found, return false and put an error message in result.
@@ -807,66 +939,34 @@ resolve_font(string_view font_, std::string& result)
}
}
// A set of likely directories for fonts to live, across several systems.
// Fill out the list of search dirs if not yet done.
if (font_search_dirs.size() == 0) {
fontpath_add_from_searchpath(pvt::font_searchpath);
fontpath_add_from_searchpath(Sysutil::getenv("OPENIMAGEIO_FONTS"));
fontpath_add_from_dir(Sysutil::getenv("HOME"));
fontpath_add_from_dir(Sysutil::getenv("SystemRoot"));
fontpath_add_from_dir(Sysutil::getenv("OpenImageIO_ROOT"));
fontpath_add_from_dir(
Sysutil::getenv("OPENIMAGEIO_ROOT_DIR")); // DEPRECATED(1.9)
fontpath_add_from_dir(
Sysutil::getenv("OPENIMAGEIOHOME")); // DEPRECATED(1.9)
fontpath_add_from_dir("/Library");
fontpath_add_from_dir("C:/Windows");
fontpath_add_from_dir("/usr");
fontpath_add_from_dir("/usr/local");
fontpath_add_from_dir("/opt/local");
std::string this_program = OIIO::Sysutil::this_program_path();
if (this_program.size()) {
std::string path = Filesystem::parent_path(this_program);
path = Filesystem::parent_path(path);
fontpath_add_from_dir(path);
}
}
// Try to find the font. Experiment with several extensions
// Try to find the font.
enumerate_fonts();
std::string font = font_;
if (font.empty()) {
// nothing specified -- look for something to use as a default.
for (int j = 0; default_font_name[j] && font.empty(); ++j) {
static const char* extensions[] = { "", ".ttf", ".pfa", ".pfb",
NULL };
for (int i = 0; font.empty() && extensions[i]; ++i)
font = Filesystem::searchpath_find(
std::string(default_font_name[j]) + extensions[i],
font_search_dirs, true, true);
for (auto fontname : default_font_name) {
auto f = font_file_map.find(fontname);
if (f != font_file_map.end()) {
font = f->second;
break;
}
}
if (font.empty()) {
result = "Could not set default font face";
return false;
}
} else if (Filesystem::is_regular(font)) {
// directly specified a filename -- use it
} else {
}
if (!Filesystem::is_regular(font)) {
// A font name was specified but it's not a full path, look for it
std::string f;
static const char* extensions[] = { "", ".ttf", ".pfa", ".pfb", NULL };
for (int i = 0; f.empty() && extensions[i]; ++i)
f = Filesystem::searchpath_find(font + extensions[i],
font_search_dirs, true, true);
if (f.empty()) {
result = Strutil::sprintf("Could not set font face to \"%s\"",
font);
return false;
}
font = f;
auto f = font_file_map.find(font);
if (f != font_file_map.end())
font = f->second;
else
font = std::string();
}
if (!Filesystem::is_regular(font)) {
result = Strutil::sprintf("Could not find font \"%s\"", font);
result = Strutil::fmt::format("Could not find font \"{}\"", font);
return false;
}
@@ -433,6 +433,71 @@ ImageBufAlgo::pow(const ImageBuf& A, cspan<float> b, ROI roi, int nthreads)
return result;
}
template<class Rtype>
static bool
normalize_impl(ImageBuf& R, const ImageBuf& A, float inCenter, float outCenter,
float scale, ROI roi, int nthreads)
{
ImageBufAlgo::parallel_image(roi, nthreads, [&](ROI roi) {
ImageBuf::ConstIterator<Rtype> a(A, roi);
for (ImageBuf::Iterator<Rtype> r(R, roi); !r.done(); ++r, ++a) {
float x = a[0] - inCenter;
float y = a[1] - inCenter;
float z = a[2] - inCenter;
float length = std::sqrt(x * x + y * y + z * z);
float s = (length > 0.0f) ? scale / length : 0.0f;
r[0] = x * s + outCenter;
r[1] = y * s + outCenter;
r[2] = z * s + outCenter;
if (R.spec().nchannels == 4) {
r[3] = a[3];
}
}
});
return true;
}
bool
ImageBufAlgo::normalize(ImageBuf& dst, const ImageBuf& src, float inCenter,
float outCenter, float scale, ROI roi, int nthreads)
{
if (!ImageBufAlgo::IBAprep(roi, &dst, &src))
return false;
if (src.spec().nchannels != 3 && src.spec().nchannels != 4) {
src.errorfmt("normalize can only handle 3- or 4-channel images");
return false;
}
if (src.spec().nchannels < dst.spec().nchannels) {
dst.errorfmt(
"destination buffer can`t have more channels than the source");
return false;
}
bool ok;
OIIO_DISPATCH_COMMON_TYPES(ok, "normalize", normalize_impl,
dst.spec().format, dst, src, inCenter, outCenter,
scale, roi, nthreads);
return ok;
}
ImageBuf
ImageBufAlgo::normalize(const ImageBuf& A, float inCenter, float outCenter,
float scale, ROI roi, int nthreads)
{
ImageBuf result;
bool ok = ImageBufAlgo::normalize(result, A, inCenter, outCenter, scale,
roi, nthreads);
if (!ok && !result.has_error())
result.errorfmt("normalize error");
return result;
}
template<class D, class S>
+24
View File
@@ -20,6 +20,7 @@
#include <OpenImageIO/argparse.h>
#include <OpenImageIO/benchmark.h>
#include <OpenImageIO/color.h>
#include <OpenImageIO/imagebuf.h>
#include <OpenImageIO/imagebufalgo.h>
#include <OpenImageIO/imagebufalgo_util.h>
@@ -1112,6 +1113,28 @@ test_opencv()
void
test_color_management()
{
ColorConfig config;
// Test the IBA::colorconvert version that works on a color at a time
{
auto processor = config.createColorProcessor("lin_srgb", "srgb");
float rgb[3] = { 0.5f, 0.5f, 0.5f };
ImageBufAlgo::colorconvert(rgb, processor.get(), false);
OIIO_CHECK_EQUAL_THRESH(rgb[1], 0.735356983052449f, 1.0e-5);
}
{
auto processor = config.createColorProcessor("lin_srgb", "srgb");
float rgb[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
ImageBufAlgo::colorconvert(rgb, processor.get(), true);
OIIO_CHECK_EQUAL_THRESH(rgb[1], 0.735356983052449f, 1.0e-5);
}
}
static void
test_yee()
{
@@ -1168,6 +1191,7 @@ main(int argc, char** argv)
test_IBAprep();
test_validate_st_warp_checks();
test_opencv();
test_color_management();
test_yee();
benchmark_parallel_image(64, iterations * 64);

Some files were not shown because too many files have changed in this diff Show More