Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa521922c9 | ||
|
+3 |
92db29b9e7 |
@@ -77,6 +77,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2023
|
||||
install-ext-packages: MISSING
|
||||
- build: 11
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
@@ -89,6 +90,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2023
|
||||
install-ext-packages: ALL
|
||||
- build: 10
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
@@ -101,6 +103,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2023
|
||||
install-ext-packages: ALL
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2022 (Python 3.9)
|
||||
# -------------------------------------------------------------------
|
||||
@@ -116,6 +119,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2022
|
||||
install-ext-packages: ALL
|
||||
- build: 8
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
@@ -128,6 +132,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2022
|
||||
install-ext-packages: MISSING
|
||||
- build: 7
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
@@ -140,6 +145,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2022
|
||||
install-ext-packages: ALL
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2021 (Python 3.7)
|
||||
# -------------------------------------------------------------------
|
||||
@@ -155,6 +161,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2021
|
||||
install-ext-packages: MISSING
|
||||
- build: 5
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
@@ -167,6 +174,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2021
|
||||
install-ext-packages: ALL
|
||||
- build: 4
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
@@ -179,6 +187,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2021
|
||||
install-ext-packages: ALL
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2020 (Python 3.7)
|
||||
# -------------------------------------------------------------------
|
||||
@@ -194,6 +203,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2020
|
||||
install-ext-packages: MISSING
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'OFF'
|
||||
@@ -206,6 +216,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2020
|
||||
install-ext-packages: ALL
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
@@ -218,6 +229,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2020
|
||||
install-ext-packages: ALL
|
||||
env:
|
||||
CXX: ${{ matrix.cxx-compiler }}
|
||||
CC: ${{ matrix.cc-compiler }}
|
||||
@@ -245,7 +257,7 @@ jobs:
|
||||
-DOCIO_BUILD_GPU_TESTS=OFF \
|
||||
-DOCIO_USE_SIMD=${{ matrix.use-simd }} \
|
||||
-DOCIO_USE_OIIO_FOR_APPS=${{ matrix.use-oiio }} \
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=ALL \
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=${{ matrix.install-ext-packages }} \
|
||||
-DOCIO_WARNING_AS_ERROR=ON \
|
||||
-DPython_EXECUTABLE=$(which python)
|
||||
working-directory: _build
|
||||
@@ -527,7 +539,10 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install docs env
|
||||
run: share/ci/scripts/windows/install_docs_env.sh
|
||||
run: |
|
||||
DOXYGEN_PATH=$GITHUB_WORKSPACE/doxygen
|
||||
share/ci/scripts/windows/install_docs_env.sh "$DOXYGEN_PATH"
|
||||
echo "$DOXYGEN_PATH" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
if: matrix.build-docs == 'ON'
|
||||
- name: Install tests env
|
||||
|
||||
@@ -54,6 +54,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2022
|
||||
use-oiio: 'ON'
|
||||
- build: 2
|
||||
build-docs: 'OFF'
|
||||
build-openfx: 'OFF'
|
||||
@@ -62,6 +63,7 @@ jobs:
|
||||
cc-compiler: gcc
|
||||
compiler-desc: GCC
|
||||
vfx-cy: 2021
|
||||
use-oiio: 'OFF'
|
||||
# -------------------------------------------------------------------
|
||||
# Clang
|
||||
# -------------------------------------------------------------------
|
||||
@@ -73,6 +75,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2022
|
||||
use-oiio: 'OFF'
|
||||
- build: 4
|
||||
build-docs: 'ON'
|
||||
build-openfx: 'ON'
|
||||
@@ -81,6 +84,7 @@ jobs:
|
||||
cc-compiler: clang
|
||||
compiler-desc: Clang
|
||||
vfx-cy: 2021
|
||||
use-oiio: 'ON'
|
||||
env:
|
||||
CXX: ${{ matrix.cxx-compiler }}
|
||||
CC: ${{ matrix.cc-compiler }}
|
||||
@@ -132,7 +136,7 @@ jobs:
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=NONE \
|
||||
-DOCIO_WARNING_AS_ERROR=OFF \
|
||||
-DPython_EXECUTABLE=$(which python) \
|
||||
-DOCIO_USE_OIIO_CMAKE_CONFIG=ON
|
||||
-DOCIO_USE_OIIO_FOR_APPS=${{ matrix.use-oiio }}
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -176,11 +180,13 @@ jobs:
|
||||
build-openfx: 'ON'
|
||||
cxx-standard: 17
|
||||
python-version: '3.11'
|
||||
use-oiio: 'ON'
|
||||
- build: 2
|
||||
build-docs: 'ON'
|
||||
build-openfx: 'ON'
|
||||
cxx-standard: 14
|
||||
python-version: '3.9'
|
||||
use-oiio: 'OFF'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
@@ -235,7 +241,7 @@ jobs:
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=NONE \
|
||||
-DOCIO_WARNING_AS_ERROR=OFF \
|
||||
-DPython_EXECUTABLE=$(which python) \
|
||||
-DOCIO_USE_OIIO_CMAKE_CONFIG=ON
|
||||
-DOCIO_USE_OIIO_FOR_APPS=${{ matrix.use-oiio }}
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -279,11 +285,13 @@ jobs:
|
||||
build-openfx: 'ON'
|
||||
cxx-standard: 17
|
||||
python-version: '3.11'
|
||||
use-oiio: 'ON'
|
||||
- build: 2
|
||||
build-docs: 'ON'
|
||||
build-openfx: 'ON'
|
||||
cxx-standard: 14
|
||||
python-version: '3.9'
|
||||
use-oiio: 'OFF'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
@@ -292,7 +300,10 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install docs env
|
||||
run: share/ci/scripts/windows/install_docs_env.sh
|
||||
run: |
|
||||
DOXYGEN_PATH=$GITHUB_WORKSPACE/doxygen
|
||||
share/ci/scripts/windows/install_docs_env.sh "$DOXYGEN_PATH"
|
||||
echo "$DOXYGEN_PATH" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
if: matrix.build-docs == 'ON'
|
||||
- name: Install tests env
|
||||
@@ -359,7 +370,7 @@ jobs:
|
||||
-DOCIO_WARNING_AS_ERROR=OFF \
|
||||
-DPython_EXECUTABLE=$(which python) \
|
||||
-DOCIO_BUILD_PYTHON=OFF \
|
||||
-DOCIO_USE_OIIO_CMAKE_CONFIG=ON
|
||||
-DOCIO_USE_OIIO_FOR_APPS=${{ matrix.use-oiio }}
|
||||
shell: bash
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
|
||||
@@ -16,8 +16,6 @@ on:
|
||||
tags-ignore:
|
||||
- v0.*
|
||||
- v1.*
|
||||
paths:
|
||||
- .github/workflows/gpu_workflow.yml
|
||||
|
||||
jobs:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
-DOCIO_BUILD_OPENFX=ON \
|
||||
-DOCIO_BUILD_GPU_TESTS=OFF \
|
||||
-DOCIO_BUILD_PYTHON=${{ matrix.build-python}} \
|
||||
-DOCIO_USE_SSE=ON \
|
||||
-DOCIO_USE_SIMD=ON \
|
||||
-DOCIO_USE_OIIO_FOR_APPS=OFF \
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=ALL \
|
||||
-DOCIO_WARNING_AS_ERROR=ON \
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
-DOCIO_BUILD_OPENFX=ON \
|
||||
-DOCIO_BUILD_GPU_TESTS=OFF \
|
||||
-DOCIO_BUILD_PYTHON=${{ matrix.build-python}} \
|
||||
-DOCIO_USE_SSE=ON \
|
||||
-DOCIO_USE_SIMD=ON \
|
||||
-DOCIO_USE_OIIO_FOR_APPS=OFF \
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=ALL \
|
||||
-DOCIO_WARNING_AS_ERROR=ON \
|
||||
@@ -333,7 +333,7 @@ jobs:
|
||||
-DOCIO_BUILD_OPENFX=ON \
|
||||
-DOCIO_BUILD_GPU_TESTS=OFF \
|
||||
-DOCIO_BUILD_PYTHON=${{ matrix.build-python}} \
|
||||
-DOCIO_USE_SSE=ON \
|
||||
-DOCIO_USE_SIMD=ON \
|
||||
-DOCIO_USE_OIIO_FOR_APPS=OFF \
|
||||
-DOCIO_INSTALL_EXT_PACKAGES=ALL \
|
||||
-DOCIO_WARNING_AS_ERROR=ON \
|
||||
|
||||
@@ -78,41 +78,86 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
# -------------------------------------------------------------------
|
||||
# CPython 64 bits
|
||||
# CPython 64 bits manylinux_2_28
|
||||
# -------------------------------------------------------------------
|
||||
- build: CPython 3.7 64 bits
|
||||
- build: CPython 3.7 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp37-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.8 64 bits
|
||||
- build: CPython 3.8 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp38-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.9 64 bits
|
||||
- build: CPython 3.9 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp39-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.10 64 bits
|
||||
- build: CPython 3.10 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp310-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.11 64 bits
|
||||
- build: CPython 3.11 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp311-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.12 64 bits manylinux_2_28
|
||||
manylinux: manylinux_2_28
|
||||
python: cp312-manylinux*
|
||||
arch: x86_64
|
||||
# -------------------------------------------------------------------
|
||||
# CPython ARM 64 bits
|
||||
# CPython 64 bits manylinux2014
|
||||
# -------------------------------------------------------------------
|
||||
- build: CPython 3.7 ARM 64 bits
|
||||
- build: CPython 3.7 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp37-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.8 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp38-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.9 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp39-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.10 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp310-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.11 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp311-manylinux*
|
||||
arch: x86_64
|
||||
- build: CPython 3.12 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp312-manylinux*
|
||||
arch: x86_64
|
||||
# -------------------------------------------------------------------
|
||||
# CPython ARM 64 bits manylinux2014
|
||||
# -------------------------------------------------------------------
|
||||
- build: CPython 3.7 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp37-manylinux*
|
||||
arch: aarch64
|
||||
- build: CPython 3.8 ARM 64 bits
|
||||
- build: CPython 3.8 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp38-manylinux*
|
||||
arch: aarch64
|
||||
- build: CPython 3.9 ARM 64 bits
|
||||
- build: CPython 3.9 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp39-manylinux*
|
||||
arch: aarch64
|
||||
- build: CPython 3.10 ARM 64 bits
|
||||
- build: CPython 3.10 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp310-manylinux*
|
||||
arch: aarch64
|
||||
- build: CPython 3.11 ARM 64 bits
|
||||
- build: CPython 3.11 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp311-manylinux*
|
||||
arch: aarch64
|
||||
- build: CPython 3.12 ARM 64 bits manylinux2014
|
||||
manylinux: manylinux2014
|
||||
python: cp312-manylinux*
|
||||
arch: aarch64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -128,10 +173,12 @@ jobs:
|
||||
platforms: all
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.13.1
|
||||
uses: pypa/cibuildwheel@v2.16.2
|
||||
env:
|
||||
CIBW_BUILD: ${{ matrix.python }}
|
||||
CIBW_ARCHS: ${{ matrix.arch }}
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux }}
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -143,7 +190,7 @@ jobs:
|
||||
|
||||
macos:
|
||||
name: Build wheels on macOS
|
||||
runs-on: macos-11
|
||||
runs-on: macos-12
|
||||
# Don't run on OCIO forks
|
||||
if: |
|
||||
github.event_name != 'schedule' ||
|
||||
@@ -169,6 +216,9 @@ jobs:
|
||||
- build: CPython 3.11 64 bits
|
||||
python: cp311-*
|
||||
arch: x86_64
|
||||
- build: CPython 3.12 64 bits
|
||||
python: cp312-*
|
||||
arch: x86_64
|
||||
# -------------------------------------------------------------------
|
||||
# CPython ARM 64 bits
|
||||
# -------------------------------------------------------------------
|
||||
@@ -184,6 +234,9 @@ jobs:
|
||||
- build: CPython 3.11 ARM 64 bits
|
||||
python: cp311-*
|
||||
arch: arm64
|
||||
- build: CPython 3.12 ARM 64 bits
|
||||
python: cp312-*
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -194,7 +247,7 @@ jobs:
|
||||
python-version: '3.8'
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.13.1
|
||||
uses: pypa/cibuildwheel@v2.16.2
|
||||
env:
|
||||
CIBW_BUILD: ${{ matrix.python }}
|
||||
CIBW_ARCHS: ${{ matrix.arch }}
|
||||
@@ -209,7 +262,7 @@ jobs:
|
||||
|
||||
windows:
|
||||
name: Build wheels on Windows
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2022
|
||||
# Don't run on OCIO forks
|
||||
if: |
|
||||
github.event_name != 'schedule' ||
|
||||
@@ -235,6 +288,9 @@ jobs:
|
||||
- build: CPython 3.11 64 bits
|
||||
python: cp311-*
|
||||
arch: AMD64
|
||||
- build: CPython 3.12 64 bits
|
||||
python: cp312-*
|
||||
arch: AMD64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -245,7 +301,7 @@ jobs:
|
||||
python-version: '3.8'
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.13.1
|
||||
uses: pypa/cibuildwheel@v2.16.2
|
||||
env:
|
||||
CIBW_BUILD: ${{ matrix.python }}
|
||||
CIBW_ARCHS: ${{ matrix.arch }}
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
|
||||
This file documents releases up to 1.1.1. For a description of version 2.0 and later
|
||||
please refer to the Releases page on GitHub:
|
||||
|
||||
https://github.com/AcademySoftwareFoundation/OpenColorIO/releases
|
||||
|
||||
and for more details please see the release notes in latest documentation pages:
|
||||
|
||||
https://opencolorio.readthedocs.io/en/latest/releases/_index.html#releases
|
||||
|
||||
**Version 1.1.1 (April 2 2019):**
|
||||
* Added optional compatibility for building apps with OpenImageIO 1.9+
|
||||
* Added USE_SSE checks to fix Linux build failure
|
||||
|
||||
+5
-2
@@ -29,7 +29,7 @@ endif()
|
||||
# Project definition.
|
||||
|
||||
project(OpenColorIO
|
||||
VERSION 2.3.0
|
||||
VERSION 2.3.2
|
||||
DESCRIPTION "OpenColorIO (OCIO) is a complete color management solution"
|
||||
HOMEPAGE_URL https://github.com/AcademySoftwareFoundation/OpenColorIO
|
||||
LANGUAGES CXX C)
|
||||
@@ -180,8 +180,11 @@ option(OCIO_USE_OIIO_FOR_APPS "Request OIIO to build apps (ociolutimage, ociocon
|
||||
|
||||
|
||||
if (NOT APPLE)
|
||||
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(AMD64|IA64|EM64T|X86|x86_64|i386|i686)")
|
||||
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(AMD64|IA64|EM64T|x86_64|X86|i386|i686)")
|
||||
# Intel-based architecture (not APPLE)
|
||||
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(X86|i386|i686)")
|
||||
set(OCIO_ARCH_X86_32 1)
|
||||
endif()
|
||||
set(OCIO_ARCH_X86 1)
|
||||
set(OCIO_BUILD_ENABLE_OPTIMIZATIONS_SSE ON)
|
||||
set(OCIO_BUILD_ENABLE_OPTIMIZATIONS_AVX ON)
|
||||
|
||||
+1
-1
@@ -243,7 +243,7 @@ expected to validate the behavior of every part of OCIO:
|
||||
* Any change to existing functionality should have tests added if they
|
||||
don't already exist.
|
||||
|
||||
The test should should be run, via ``ctest``, before submitting a pull request.
|
||||
The test should be run, via ``ctest``, before submitting a pull request.
|
||||
|
||||
## Versioning Policy
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Houdini, Silhouette FX, and
|
||||
[others](https://opencolorio.org/#supported_apps).
|
||||
|
||||
OpenColorIO is free and open source software ([LICENSE](LICENSE)), and
|
||||
one of several projects actvively sponsored by the ASWF
|
||||
one of several projects actively sponsored by the ASWF
|
||||
([Academy Software Foundation](https://www.aswf.io/)).
|
||||
|
||||
OpenColorIO Project Mission
|
||||
@@ -50,12 +50,12 @@ content creation applications and pipelines.
|
||||
|
||||
OpenColorIO aims to:
|
||||
|
||||
* be stable, secure, and thouroughly tested on Linux, macOS, and Windows
|
||||
* be stable, secure, and thoroughly tested on Linux, macOS, and Windows
|
||||
* be performant on modern CPUs and GPUs
|
||||
* be simple, scalable, and well documented
|
||||
* be compatible with critical color and imaging standards
|
||||
* provide lossless color processing wherever possible
|
||||
* maintain config backwards compatability across major versions
|
||||
* maintain config backwards compatibility across major versions
|
||||
* have every new feature carefully reviewed by leaders from the motion picture,
|
||||
VFX, animation, and video game industries
|
||||
* have a healthy and active community
|
||||
@@ -65,13 +65,14 @@ OpenColorIO Project Governance
|
||||
------------------------------
|
||||
|
||||
OpenColorIO is governed by the Academy Software Foundation (ASWF). See
|
||||
[GOVERNANCE.md](GOVERNANCE.md) for detailed infomation about how the project
|
||||
[GOVERNANCE.md](GOVERNANCE.md) for detailed information about how the project
|
||||
operates.
|
||||
|
||||
Web Resources
|
||||
-------------
|
||||
|
||||
* Website: <http://opencolorio.org>
|
||||
* Documentation: <https://opencolorio.readthedocs.io/en/latest/>
|
||||
* Mailing lists:
|
||||
* Developer: <ocio-dev@lists.aswf.io>
|
||||
* User: <ocio-user@lists.aswf.io>
|
||||
@@ -99,6 +100,11 @@ The following reference implementations are provided:
|
||||
* Other
|
||||
* nuke-default
|
||||
|
||||
Sources for the newer builtin ACES configuration files can be found in the releases section of the
|
||||
[OpenColorIO-Config-ACES](https://github.com/AcademySoftwareFoundation/OpenColorIO-Config-ACES)
|
||||
repository.
|
||||
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
|
||||
@@ -2456,6 +2456,10 @@ public:
|
||||
*/
|
||||
bool hasChannelCrosstalk() const;
|
||||
|
||||
/**
|
||||
* Returns a hash string generated by hashing the cachedIDs of the (unoptimized) list of ops
|
||||
* contained in the Processor. (This forms part of the key used by the config's processor cache.)
|
||||
*/
|
||||
const char * getCacheID() const;
|
||||
|
||||
/**
|
||||
|
||||
@@ -760,7 +760,7 @@ extern OCIOEXPORT const char * OCIO_INACTIVE_COLORSPACES_ENVVAR;
|
||||
* The envvar 'OCIO_OPTIMIZATION_FLAGS' provides a way to force a given optimization level.
|
||||
* Remove the variable or set the value to empty to not use it. Set the value of the variable
|
||||
* to the desired optimization level as either an integer or hexadecimal value.
|
||||
* Ex: OCIO_OPTIMIZATION_FLAGS="20479" or "0x4FFF" for OPTIMIZATION_LOSSLESS.
|
||||
* Ex: OCIO_OPTIMIZATION_FLAGS="144457667" or "0x89c3fc3" for OPTIMIZATION_LOSSLESS.
|
||||
*/
|
||||
extern OCIOEXPORT const char * OCIO_OPTIMIZATION_FLAGS_ENVVAR;
|
||||
|
||||
|
||||
+6
-6
@@ -4,7 +4,10 @@ requires = [
|
||||
"wheel",
|
||||
"cmake>=3.13",
|
||||
"ninja; sys_platform != 'win32' and platform_machine != 'arm64'",
|
||||
# Documentation requirements
|
||||
# Documentation requirements (see docs/requirements.txt for details)
|
||||
"urllib3<2",
|
||||
"docutils>=0.18.1",
|
||||
"sphinx<=7.1.2",
|
||||
"six",
|
||||
"testresources",
|
||||
"recommonmark",
|
||||
@@ -23,10 +26,6 @@ test-command = [
|
||||
"ociocheck"
|
||||
]
|
||||
|
||||
manylinux-x86_64-image = "manylinux2014"
|
||||
manylinux-i686-image = "manylinux2014"
|
||||
manylinux-aarch64-image = "manylinux2014"
|
||||
|
||||
[tool.cibuildwheel.linux]
|
||||
before-build = "share/ci/scripts/linux/yum/install_docs_env.sh"
|
||||
|
||||
@@ -34,4 +33,5 @@ before-build = "share/ci/scripts/linux/yum/install_docs_env.sh"
|
||||
before-build = "share/ci/scripts/macos/install_docs_env.sh"
|
||||
|
||||
[tool.cibuildwheel.windows]
|
||||
before-build = "bash -c share/ci/scripts/windows/install_docs_env.sh"
|
||||
environment = { PATH="$GITHUB_WORKSPACE/doxygen;$PATH" }
|
||||
before-build = 'bash -c "share/ci/scripts/windows/install_docs_env.sh $GITHUB_WORKSPACE/doxygen"'
|
||||
|
||||
@@ -12,6 +12,7 @@ classifiers =
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
Programming Language :: Python :: 3.11
|
||||
Programming Language :: Python :: 3.12
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
Programming Language :: C++
|
||||
description = OpenColorIO (OCIO) is a complete color management solution geared towards motion picture production with an emphasis on visual effects and computer animation.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
set -ex
|
||||
|
||||
HERE=$(dirname $0)
|
||||
DOXYGEN_LOCATION="$1"
|
||||
|
||||
bash $HERE/install_doxygen.sh latest
|
||||
bash $HERE/install_doxygen.sh "$DOXYGEN_LOCATION"
|
||||
pip install -r $HERE/../../../../docs/requirements.txt
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
|
||||
set -ex
|
||||
|
||||
DOXYGEN_VERSION="$1"
|
||||
DOXYGEN_LOCATION="$1"
|
||||
|
||||
if [ "$DOXYGEN_VERSION" == "latest" ]; then
|
||||
choco install doxygen.install
|
||||
else
|
||||
choco install doxygen.install --version=${DOXYGEN_VERSION}
|
||||
fi
|
||||
# Utility to parse JSON object.
|
||||
choco install jq
|
||||
|
||||
# Get the URL of the latest zip package for Doxygen.
|
||||
url=$(curl -s 'https://api.github.com/repos/doxygen/doxygen/releases/latest' | jq -r '.assets[] | select(.name | test("doxygen-.*windows.x64.bin.zip")) | .browser_download_url')
|
||||
|
||||
# Download the zip.
|
||||
mkdir $DOXYGEN_LOCATION
|
||||
cd $DOXYGEN_LOCATION
|
||||
powershell 'iwr -URI '$url' -OutFile doxygen.zip'
|
||||
|
||||
# Unzip the file into $DOXYGEN_LOCATION.
|
||||
unzip -o doxygen.zip
|
||||
@@ -216,7 +216,7 @@ macro (ocio_handle_dependency dep_name)
|
||||
endif()
|
||||
|
||||
if(ocio_dep_REQUIRED)
|
||||
if(NOT ${dep_name}_FOUND AND NOT ocio_dep_VERSION)
|
||||
if(NOT ${dep_name}_FOUND)
|
||||
message(SEND_ERROR "${ColorError}${dep_name} is required, will abort at the end.${ColorReset}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# minizip-ng_LIBRARY - minizip-ng library to link to
|
||||
# minizip-ng_INCLUDE_DIR - Where to find mz.h and other headers
|
||||
# minizip-ng_VERSION - The version of the library
|
||||
# minizip-ng_COMPAT - Whether minizip-ng MZ_COMPAT was used or not
|
||||
#
|
||||
# Global targets defined by this module:
|
||||
# MINIZIP::minizip-ng - IMPORTED target, if found
|
||||
@@ -114,7 +115,9 @@ if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
include/minizip-ng
|
||||
include/minizip
|
||||
minizip-ng/include
|
||||
minizip/include
|
||||
)
|
||||
|
||||
# Minizip-ng uses prefix "lib" on all platform by default.
|
||||
@@ -202,4 +205,16 @@ if(_minizip-ng_TARGET_CREATE)
|
||||
mark_as_advanced(minizip-ng_INCLUDE_DIR minizip-ng_LIBRARY minizip-ng_VERSION)
|
||||
|
||||
target_link_libraries(MINIZIP::minizip-ng INTERFACE ZLIB::ZLIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
### Detect compatibility mode ###
|
||||
|
||||
set(minizip-ng_COMPAT FALSE)
|
||||
if(minizip-ng_INCLUDE_DIR)
|
||||
list(GET minizip-ng_INCLUDE_DIR 0 _minizip-ng_INCLUDE_DIR)
|
||||
if(EXISTS "${_minizip-ng_INCLUDE_DIR}/mz_compat.h")
|
||||
set(minizip-ng_COMPAT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
mark_as_advanced(minizip-ng_COMPAT)
|
||||
|
||||
@@ -28,11 +28,12 @@ if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
# Find include directory
|
||||
find_path(pystring_INCLUDE_DIR
|
||||
NAMES
|
||||
pystring/pystring.h
|
||||
pystring.h
|
||||
HINTS
|
||||
${pystring_ROOT}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
include/pystring
|
||||
pystring/include
|
||||
)
|
||||
|
||||
|
||||
@@ -10,10 +10,9 @@
|
||||
# yaml-cpp_VERSION - Library's version
|
||||
#
|
||||
# Global targets defined by this module:
|
||||
# yaml-cpp
|
||||
# yaml-cpp::yaml-cpp
|
||||
#
|
||||
# For compatibility with the upstream CMake package, the following variables and targets are defined:
|
||||
# yaml-cpp::yaml-cpp - Alias of the yaml-cpp target
|
||||
# YAML_CPP_LIBRARIES - Libraries to link against yaml-cpp
|
||||
# YAML_CPP_INCLUDE_DIR - Include directory
|
||||
#
|
||||
@@ -41,16 +40,26 @@ if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
|
||||
set(BUILD_TYPE_DEBUG ON)
|
||||
endif()
|
||||
|
||||
if(yaml-cpp_FIND_QUIETLY)
|
||||
set(quiet QUIET)
|
||||
endif()
|
||||
|
||||
if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
set(_yaml-cpp_REQUIRED_VARS yaml-cpp_LIBRARY)
|
||||
|
||||
# Search for yaml-cpp-config.cmake
|
||||
if(NOT DEFINED yaml-cpp_ROOT)
|
||||
# Search for yaml-cpp-config.cmake
|
||||
find_package(yaml-cpp ${yaml-cpp_FIND_VERSION} CONFIG QUIET)
|
||||
find_package(yaml-cpp ${yaml-cpp_FIND_VERSION} CONFIG ${quiet})
|
||||
endif()
|
||||
|
||||
if(yaml-cpp_FOUND)
|
||||
get_target_property(yaml-cpp_LIBRARY yaml-cpp LOCATION)
|
||||
# Alias target for yaml-cpp < 0.8 compatibility
|
||||
if(TARGET yaml-cpp AND NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||
endif()
|
||||
|
||||
get_target_property(yaml-cpp_INCLUDE_DIR yaml-cpp::yaml-cpp INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(yaml-cpp_LIBRARY yaml-cpp::yaml-cpp LOCATION)
|
||||
else()
|
||||
|
||||
# As yaml-cpp-config.cmake search fails, search an installed library
|
||||
@@ -59,14 +68,14 @@ if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
list(APPEND _yaml-cpp_REQUIRED_VARS yaml-cpp_INCLUDE_DIR yaml-cpp_VERSION)
|
||||
|
||||
# Search for yaml-cpp.pc
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_yaml-cpp QUIET "yaml-cpp>=${yaml-cpp_FIND_VERSION}")
|
||||
find_package(PkgConfig ${quiet})
|
||||
pkg_check_modules(PC_yaml-cpp ${quiet} "yaml-cpp>=${yaml-cpp_FIND_VERSION}")
|
||||
|
||||
# Try to detect the version installed, if any.
|
||||
if(NOT PC_yaml-cpp_FOUND)
|
||||
pkg_search_module(PC_yaml-cpp QUIET "yaml-cpp")
|
||||
pkg_search_module(PC_yaml-cpp ${quiet} "yaml-cpp")
|
||||
endif()
|
||||
|
||||
|
||||
# Find include directory
|
||||
find_path(yaml-cpp_INCLUDE_DIR
|
||||
NAMES
|
||||
@@ -91,7 +100,7 @@ if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
# Prefer static lib names
|
||||
set(_yaml-cpp_STATIC_LIB_NAMES
|
||||
"${CMAKE_STATIC_LIBRARY_PREFIX}yaml-cpp${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
|
||||
# Starting from 0.7.0, all platforms uses the suffix "d" for debug.
|
||||
# See https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt#L141
|
||||
if(BUILD_TYPE_DEBUG)
|
||||
@@ -127,42 +136,37 @@ if(NOT OCIO_INSTALL_EXT_PACKAGES STREQUAL ALL)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(yaml-cpp
|
||||
REQUIRED_VARS
|
||||
REQUIRED_VARS
|
||||
${_yaml-cpp_REQUIRED_VARS}
|
||||
VERSION_VAR
|
||||
yaml-cpp_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
### Create target
|
||||
|
||||
if(yaml-cpp_FOUND AND NOT TARGET yaml-cpp)
|
||||
add_library(yaml-cpp UNKNOWN IMPORTED GLOBAL)
|
||||
set(_yaml-cpp_TARGET_CREATE TRUE)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
### Configure target ###
|
||||
|
||||
if(_yaml-cpp_TARGET_CREATE)
|
||||
set_target_properties(yaml-cpp PROPERTIES
|
||||
IMPORTED_LOCATION ${yaml-cpp_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${yaml-cpp_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
mark_as_advanced(yaml-cpp_INCLUDE_DIR yaml-cpp_LIBRARY yaml-cpp_VERSION)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
### Set variables for compatibility ###
|
||||
### Create target
|
||||
|
||||
if(TARGET yaml-cpp AND NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||
endif()
|
||||
if (yaml-cpp_FOUND AND NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(yaml-cpp::yaml-cpp PROPERTIES
|
||||
IMPORTED_LOCATION ${yaml-cpp_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${yaml-cpp_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if(yaml-cpp_INCLUDE_DIR)
|
||||
set(YAML_CPP_INCLUDE_DIR "${yaml-cpp_INCLUDE_DIR}")
|
||||
endif()
|
||||
# Required because Installyaml-cpp.cmake creates `yaml-cpp::yaml-cpp`
|
||||
# as an alias, and aliases get resolved in exported targets, causing the
|
||||
# find_dependency(yaml-cpp) call in OpenColorIOConfig.cmake to fail.
|
||||
# This can be removed once Installyaml-cpp.cmake targets yaml-cpp 0.8.
|
||||
if (NOT TARGET yaml-cpp)
|
||||
add_library(yaml-cpp ALIAS yaml-cpp::yaml-cpp)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(YAML_CPP_LIBRARIES yaml-cpp::yaml-cpp)
|
||||
if (yaml-cpp_FOUND)
|
||||
# TODO: Remove this variable and use the `yaml-cpp::yaml-cpp` target
|
||||
# directly when the minimum version of yaml-cpp is updated to 0.8.
|
||||
get_target_property(YAML_CPP_INCLUDE_DIR yaml-cpp::yaml-cpp INCLUDE_DIRECTORIES)
|
||||
set(YAML_CPP_LIBRARIES yaml-cpp::yaml-cpp)
|
||||
endif ()
|
||||
|
||||
@@ -110,7 +110,7 @@ if(NOT OpenEXR_FOUND AND OCIO_INSTALL_EXT_PACKAGES AND NOT OCIO_INSTALL_EXT_PACK
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DBUILD_TESTING=OFF
|
||||
-DOPENEXR_INSTALL_EXAMPLES=OFF
|
||||
-DOPENEXR_INSTALL_TOOLS=OFF
|
||||
-DOPENEXR_BUILD_TOOLS=OFF
|
||||
# Try to use in-source built Imath first, if available.
|
||||
-DCMAKE_PREFIX_PATH=${_EXT_DIST_ROOT}
|
||||
)
|
||||
|
||||
@@ -38,7 +38,7 @@ if(NOT pystring_FOUND AND OCIO_INSTALL_EXT_PACKAGES AND NOT OCIO_INSTALL_EXT_PAC
|
||||
else()
|
||||
set(pystring_VERSION ${pystring_FIND_VERSION})
|
||||
endif()
|
||||
set(pystring_INCLUDE_DIR "${_EXT_DIST_ROOT}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(pystring_INCLUDE_DIR "${_EXT_DIST_ROOT}/${CMAKE_INSTALL_INCLUDEDIR}/pystring")
|
||||
|
||||
set(pystring_LIBRARY
|
||||
"${_EXT_DIST_ROOT}/${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}pystring${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
###############################################################################
|
||||
### Create target (if previous 'find_package' call hasn't) ###
|
||||
|
||||
if(NOT TARGET yaml-cpp)
|
||||
add_library(yaml-cpp UNKNOWN IMPORTED GLOBAL)
|
||||
if(NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp UNKNOWN IMPORTED GLOBAL)
|
||||
set(_yaml-cpp_TARGET_CREATE TRUE)
|
||||
endif()
|
||||
|
||||
@@ -138,7 +138,7 @@ if(NOT yaml-cpp_FOUND AND OCIO_INSTALL_EXT_PACKAGES AND NOT OCIO_INSTALL_EXT_PAC
|
||||
--parallel
|
||||
)
|
||||
|
||||
add_dependencies(yaml-cpp yaml-cpp_install)
|
||||
add_dependencies(yaml-cpp::yaml-cpp yaml-cpp_install)
|
||||
if(OCIO_VERBOSE)
|
||||
message(STATUS "Installing yaml-cpp: ${yaml-cpp_LIBRARY} (version \"${yaml-cpp_VERSION}\")")
|
||||
endif()
|
||||
@@ -149,7 +149,7 @@ endif()
|
||||
### Configure target ###
|
||||
|
||||
if(_yaml-cpp_TARGET_CREATE)
|
||||
set_target_properties(yaml-cpp PROPERTIES
|
||||
set_target_properties(yaml-cpp::yaml-cpp PROPERTIES
|
||||
IMPORTED_LOCATION ${yaml-cpp_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${yaml-cpp_INCLUDE_DIR}
|
||||
)
|
||||
@@ -157,15 +157,5 @@ if(_yaml-cpp_TARGET_CREATE)
|
||||
mark_as_advanced(yaml-cpp_INCLUDE_DIR yaml-cpp_LIBRARY yaml-cpp_VERSION)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
### Set variables for compatibility ###
|
||||
|
||||
if(TARGET yaml-cpp AND NOT TARGET yaml-cpp::yaml-cpp)
|
||||
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||
endif()
|
||||
|
||||
if(yaml-cpp_INCLUDE_DIR)
|
||||
set(YAML_CPP_INCLUDE_DIR "${yaml-cpp_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
set(YAML_CPP_INCLUDE_DIR "${yaml-cpp_INCLUDE_DIR}")
|
||||
set(YAML_CPP_LIBRARIES yaml-cpp::yaml-cpp)
|
||||
|
||||
@@ -59,7 +59,7 @@ else()
|
||||
message(STATUS "Performing Test COMPILER_SUPPORTS_SSE2 - Failed")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "${_cmake_cxx_flags_orig}")
|
||||
set(CMAKE_CXX_FLAGS "${_cmake_cxx_flags_orig}")
|
||||
unset(_cmake_cxx_flags_orig)
|
||||
|
||||
if(__universal_build)
|
||||
|
||||
@@ -13,7 +13,7 @@ endif()
|
||||
|
||||
# MSVC doesn't have flags
|
||||
if(USE_GCC OR USE_CLANG)
|
||||
set(CMAKE_CXX_FLAGS "-w -msse3")
|
||||
set(CMAKE_CXX_FLAGS "-w -mssse3")
|
||||
endif()
|
||||
|
||||
if (APPLE AND __universal_build)
|
||||
|
||||
@@ -107,8 +107,8 @@ if(USE_GCC OR USE_CLANG)
|
||||
endif()
|
||||
|
||||
if(OCIO_ENABLE_SANITIZER)
|
||||
set(PLATFORM_COMPILE_OPTIONS "${PLATFORM_COMPILE_OPTIONS};-fno-omit-frame-pointer;-fsanitize=address")
|
||||
set(PLATFORM_LINK_OPTIONS "${PLATFORM_LINK_OPTIONS};-fsanitize=address")
|
||||
set(PLATFORM_COMPILE_OPTIONS "${PLATFORM_COMPILE_OPTIONS};-fno-omit-frame-pointer;-fsanitize=address;-fsanitize=undefined")
|
||||
set(PLATFORM_LINK_OPTIONS "${PLATFORM_LINK_OPTIONS};-fsanitize=address;-fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#if OCIO_USE_AVX
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
#include "BitDepthUtils.h"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#if OCIO_USE_AVX2
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
#include "BitDepthUtils.h"
|
||||
|
||||
@@ -389,7 +389,7 @@ elseif(APPLE)
|
||||
|
||||
|
||||
# Check for minizip first since our Findminizip module sets minizip-ng_LIBRARY.
|
||||
if (minizip_LIBRARY)
|
||||
if (minizip_LIBRARY OR minizip-ng_COMPAT)
|
||||
get_filename_component(_minizip-ng_LIBDIR "${minizip_LIBRARY}" DIRECTORY)
|
||||
set(_minizip-ng_NAME "minizip")
|
||||
elseif(minizip-ng_LIBRARY)
|
||||
|
||||
@@ -50,6 +50,13 @@ static inline void cpuid(int index, int *data)
|
||||
{
|
||||
#if _MSC_VER
|
||||
__cpuid(data, index);
|
||||
#elif OCIO_ARCH_X86_32
|
||||
__asm__ volatile (
|
||||
"mov %%ebx, %%esi \n\t"
|
||||
"cpuid \n\t"
|
||||
"xchg %%ebx, %%esi"
|
||||
: "=a" (data[0]), "=S" (data[1]), "=c" (data[2]), "=d" (data[3])
|
||||
: "0" (index), "2"(0));
|
||||
#else
|
||||
__asm__ volatile (
|
||||
"mov %%rbx, %%rsi \n\t"
|
||||
@@ -100,10 +107,10 @@ CPUInfo::CPUInfo()
|
||||
flags |= X86_CPU_FLAG_SSE42;
|
||||
|
||||
/* Check OSXSAVE and AVX bits */
|
||||
if (info.reg.ecx & 0x18000000)
|
||||
if ((info.reg.ecx & 0x18000000) == 0x18000000)
|
||||
{
|
||||
xcr = xgetbv();
|
||||
if(xcr & 0x6) {
|
||||
if((xcr & 0x6) == 0x6) {
|
||||
flags |= X86_CPU_FLAG_AVX;
|
||||
|
||||
if(info.reg.ecx & 0x20000000) {
|
||||
@@ -122,7 +129,7 @@ CPUInfo::CPUInfo()
|
||||
|
||||
/* OPMASK/ZMM state */
|
||||
if ((xcr & 0xe0) == 0xe0) {
|
||||
if ((flags & X86_CPU_FLAG_AVX2) && (info.reg.ebx & 0xd0030000))
|
||||
if ((flags & X86_CPU_FLAG_AVX2) && ((info.reg.ebx & 0xd0030000) == 0xd0030000))
|
||||
flags |= X86_CPU_FLAG_AVX512;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
|
||||
#cmakedefine01 OCIO_ARCH_X86
|
||||
#cmakedefine01 OCIO_ARCH_X86_32
|
||||
|
||||
// Relevant only for arm64 architecture.
|
||||
#if defined(__aarch64__)
|
||||
#cmakedefine01 OCIO_USE_SSE2NEON
|
||||
#else
|
||||
#define OCIO_USE_SSE2NEON 0
|
||||
#endif
|
||||
|
||||
// On the Apple platform, a universal build is created for both x86_64 and arm64 architectures.
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <regex>
|
||||
#include <functional>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "builtinconfigs/BuiltinConfigRegistry.h"
|
||||
@@ -34,7 +36,6 @@
|
||||
#include "Platform.h"
|
||||
#include "PrivateTypes.h"
|
||||
#include "Processor.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
#include "utils/StringUtils.h"
|
||||
#include "ViewingRules.h"
|
||||
@@ -435,7 +436,7 @@ public:
|
||||
{
|
||||
m_viewTransforms.push_back(vt->createEditableCopy());
|
||||
}
|
||||
|
||||
m_defaultViewTransform = rhs.m_defaultViewTransform;
|
||||
m_defaultLumaCoefs = rhs.m_defaultLumaCoefs;
|
||||
m_strictParsing = rhs.m_strictParsing;
|
||||
|
||||
@@ -2821,6 +2822,23 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe
|
||||
auto procToReference = config.getImpl()->getProcessorWithoutCaching(
|
||||
config, t, TRANSFORM_DIR_FORWARD
|
||||
);
|
||||
|
||||
// TODO: It could be useful to try and avoid evaluating points through ops that are
|
||||
// expensive but highly unlikely to be linear (with inverse Lut3D being the prime example).
|
||||
// There are some heuristics that are used in ConfigUtils.cpp that are intended to filter
|
||||
// out color spaces from consideration before a processor is even calculated. However,
|
||||
// those are not entirely appropriate here since one could imagine wanting to know if a
|
||||
// color space involving a FileTransform (an ASC CDL being a good example) is linear.
|
||||
// Likewise, one might want to know whether a color space involving a Look or ColorSpace
|
||||
// Transform is linear (both of those are filtered out by the ConfigUtils heuristics).
|
||||
// It seems like the right approach here is to go ahead and build the processor and
|
||||
// thereby convert File/Look/ColorSpace Transforms into ops. But currently there is
|
||||
// no method on the Processor class to know if it contains a Lut3D. There is the
|
||||
// ProcessorMetadata files list, though that is not as precise. For example, it would
|
||||
// not say if a CLF or CTF file contains a Lut3D or just a matrix. Probably the best
|
||||
// solution would be to have each op sub-class provide an isLinear method and then
|
||||
// surface that on the Processor class, iterating over each op in the Processor.
|
||||
|
||||
auto optCPUProc = procToReference->getOptimizedCPUProcessor(OPTIMIZATION_NONE);
|
||||
optCPUProc->apply(desc, descDst);
|
||||
|
||||
@@ -4100,6 +4118,10 @@ void Config::addLook(const ConstLookRcPtr & look)
|
||||
if(StringUtils::Lower(getImpl()->m_looksList[i]->getName()) == namelower)
|
||||
{
|
||||
getImpl()->m_looksList[i] = look->createEditableCopy();
|
||||
|
||||
AutoMutex lock(getImpl()->m_cacheidMutex);
|
||||
getImpl()->resetCacheIDs();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -4715,20 +4737,29 @@ ConstProcessorRcPtr Config::GetProcessorFromConfigs(const ConstContextRcPtr & sr
|
||||
"the source color space.");
|
||||
}
|
||||
|
||||
const char* csName = dstConfig->getDisplayViewColorSpaceName(dstDisplay, dstView);
|
||||
const char* displayColorSpaceName = View::UseDisplayName(csName) ? dstDisplay : csName;
|
||||
ConstColorSpaceRcPtr displayColorSpace = dstConfig->getColorSpace(displayColorSpaceName);
|
||||
if (!displayColorSpace)
|
||||
{
|
||||
throw Exception("Can't create the processor for the destination config: "
|
||||
"display color space not found.");
|
||||
}
|
||||
|
||||
auto p2 = dstConfig->getProcessor(dstContext, dstInterchangeName, dstDisplay, dstView, direction);
|
||||
if (!p2)
|
||||
{
|
||||
throw Exception("Can't create the processor for the destination config "
|
||||
"and the destination color space.");
|
||||
"and the destination display view transform.");
|
||||
}
|
||||
|
||||
ProcessorRcPtr processor = Processor::Create();
|
||||
processor->getImpl()->setProcessorCacheFlags(srcConfig->getImpl()->m_cacheFlags);
|
||||
|
||||
// If the source color spaces is a data space, its corresponding processor
|
||||
// If either of the color spaces are data spaces, its corresponding processor
|
||||
// will be empty, but need to make sure the entire result is also empty to
|
||||
// better match the semantics of how data spaces are handled.
|
||||
if (!srcColorSpace->isData())
|
||||
if (!srcColorSpace->isData() && !displayColorSpace->isData())
|
||||
{
|
||||
if (direction == TRANSFORM_DIR_INVERSE)
|
||||
{
|
||||
|
||||
+203
-37
@@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright Contributors to the OpenColorIO Project.
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include "ConfigUtils.h"
|
||||
#include "MathUtils.h"
|
||||
#include "utils/StringUtils.h"
|
||||
@@ -165,7 +167,7 @@ bool GetInterchangeRolesForColorSpaceConversion(const char ** srcInterchangeCSNa
|
||||
|
||||
// Return true if the color space name or its aliases contains sRGB (case-insensitive).
|
||||
//
|
||||
bool containsSRGB(ConstColorSpaceRcPtr & cs)
|
||||
bool containsSRGB(const ConstColorSpaceRcPtr & cs)
|
||||
{
|
||||
std::string name = StringUtils::Lower(cs->getName());
|
||||
if (StringUtils::Find(name, "srgb") != std::string::npos)
|
||||
@@ -223,10 +225,31 @@ const char * getRefSpaceName(const ConstConfigRcPtr & cfg)
|
||||
return "";
|
||||
}
|
||||
|
||||
// Find the first scene-referred color space with isdata: true.
|
||||
//
|
||||
const char * getDataSpaceName(const ConstConfigRcPtr & cfg)
|
||||
{
|
||||
int nbCs = cfg->getNumColorSpaces(SEARCH_REFERENCE_SPACE_SCENE, COLORSPACE_ALL);
|
||||
|
||||
for (int i = 0; i < nbCs; i++)
|
||||
{
|
||||
const char * csname = cfg->getColorSpaceNameByIndex(SEARCH_REFERENCE_SPACE_SCENE,
|
||||
COLORSPACE_ALL,
|
||||
i);
|
||||
ConstColorSpaceRcPtr cs = cfg->getColorSpace(csname);
|
||||
|
||||
if (cs->isData())
|
||||
{
|
||||
return csname;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// Return false if the supplied Processor modifies any of the supplied float values
|
||||
// by more than the supplied absolute tolerance amount.
|
||||
//
|
||||
bool isIdentityTransform(ConstProcessorRcPtr proc,
|
||||
bool isIdentityTransform(const ConstProcessorRcPtr & proc,
|
||||
std::vector<float> & RGBAvals,
|
||||
float absTolerance)
|
||||
{
|
||||
@@ -249,28 +272,143 @@ bool isIdentityTransform(ConstProcessorRcPtr proc,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper to avoid color spaces that are without transforms or are data spaces.
|
||||
// Determine whether a Processor contains a MatrixTransform with off-diagonal coefficients.
|
||||
//
|
||||
bool hasNoTransform(const ConstColorSpaceRcPtr & cs)
|
||||
bool hasNonTrivialMatrixTransform(const ConstProcessorRcPtr & proc)
|
||||
{
|
||||
GroupTransformRcPtr gt = proc->createGroupTransform();
|
||||
// The result of createGroupTransform only contains transforms that correspond to ops,
|
||||
// in other words, there are no complex transforms such as File, Builtin, or ColorSpace,
|
||||
// and the only GroupTransform is the enclosing one.
|
||||
for (int i = 0; i < gt->getNumTransforms(); ++i)
|
||||
{
|
||||
ConstTransformRcPtr transform = gt->getTransform(i);
|
||||
if (transform->getTransformType() == TRANSFORM_TYPE_MATRIX)
|
||||
{
|
||||
// Check that there is a significant off-diagonal coefficient in the matrix.
|
||||
// This is to avoid matrices that are not actual color primary conversions,
|
||||
// for example, the scale and offset that are sometimes prepended to a Lut1D.
|
||||
ConstMatrixTransformRcPtr mtx = DynamicPtrCast<const MatrixTransform>(transform);
|
||||
double values[16];
|
||||
mtx->getMatrix(values);
|
||||
for (int j = 0; j < 3 ; ++j) // only checking rgb, not alpha
|
||||
{
|
||||
for (int k = 0; k < 3 ; ++k) // only checking rgb, not alpha
|
||||
{
|
||||
if (j != k)
|
||||
{
|
||||
if (std::abs(values[j * 4 + k]) > 0.1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine if the transform contains a type that is inappropriate for the heuristics.
|
||||
//
|
||||
bool containsBlockedTransform(const ConstTransformRcPtr & transform)
|
||||
{
|
||||
// If it's a GroupTransform, need to recurse into it to check the contents.
|
||||
if (transform->getTransformType() == TRANSFORM_TYPE_GROUP)
|
||||
{
|
||||
ConstGroupTransformRcPtr gt = DynamicPtrCast<const GroupTransform>(transform);
|
||||
for (int i = 0; i < gt->getNumTransforms(); ++i)
|
||||
{
|
||||
ConstTransformRcPtr tr = gt->getTransform(i);
|
||||
if (containsBlockedTransform(tr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent FileTransforms from being used, except for spi1d and spimtx since these
|
||||
// may be used with OCIO v1 configs to implement the type of color spaces the heuristics
|
||||
// are designed to look for. (E.g. The sRGB Texture space in the legacy ACES configs.)
|
||||
else if (transform->getTransformType() == TRANSFORM_TYPE_FILE)
|
||||
{
|
||||
ConstFileTransformRcPtr ft = DynamicPtrCast<const FileTransform>(transform);
|
||||
std::string filepath = ft->getSrc();
|
||||
std::string root, extension;
|
||||
pystring::os::path::splitext(root, extension, filepath);
|
||||
extension = StringUtils::Lower(extension);
|
||||
if (extension != ".spi1d" && extension != ".spimtx")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent transforms that may be hiding a FileTransform.
|
||||
else if (transform->getTransformType() == TRANSFORM_TYPE_COLORSPACE
|
||||
|| transform->getTransformType() == TRANSFORM_TYPE_DISPLAY_VIEW
|
||||
|| transform->getTransformType() == TRANSFORM_TYPE_LOOK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Putting this here since Lut3D is the main type of transform to avoid,
|
||||
// however given that the input transform comes directly from a color space
|
||||
// and has not been converted to a processor yet, it should never actually
|
||||
// have a transform of this type (it would still be a FileTransform).
|
||||
else if (transform->getTransformType() == TRANSFORM_TYPE_LUT3D)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look at the to_ref/from_ref transforms in the color space and exclude color spaces
|
||||
// that are probably not what the heuristics are looking for and could be prohibitively
|
||||
// expensive to fully check.
|
||||
//
|
||||
// Because this check is done before a processor is built, it is inexpensive but it may
|
||||
// be inaccurate. In other words, it's possible that this check will exclude some
|
||||
// reasonable color spaces, but that's better than trying to invert 3d-LUTs, etc.
|
||||
//
|
||||
// cs -- Color space object to check.
|
||||
// refSpaceType -- Exclude if the color space is not of the same reference space type.
|
||||
// blockRefSpaces -- Exclude the color space if it does not have any transforms.
|
||||
//
|
||||
bool excludeColorSpaceFromHeuristics(const ConstColorSpaceRcPtr & cs,
|
||||
ReferenceSpaceType refSpaceType,
|
||||
bool blockRefSpaces)
|
||||
{
|
||||
if (cs->isData())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ConstTransformRcPtr srcTransform = cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
|
||||
if (!srcTransform)
|
||||
|
||||
if (cs->getReferenceSpaceType() != refSpaceType)
|
||||
{
|
||||
srcTransform = cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
|
||||
if (srcTransform)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ConstTransformRcPtr transform = cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
|
||||
if (transform)
|
||||
{
|
||||
// The to_ref transform is what the heuristics try to use first, so if that
|
||||
// does not contain problematic transforms, it's ok to proceed without checking
|
||||
// the from_ref transform.
|
||||
|
||||
return containsBlockedTransform(transform);
|
||||
}
|
||||
|
||||
// There is no to_ref transform, check if the from_ref is present.
|
||||
transform = cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
|
||||
if (transform)
|
||||
{
|
||||
return containsBlockedTransform(transform);
|
||||
}
|
||||
// Color space contains no transforms (it's a reference space).
|
||||
else
|
||||
{
|
||||
return blockRefSpaces;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the supplied color space against a set of color spaces in the built-in config.
|
||||
@@ -288,17 +426,6 @@ int getReferenceSpaceFromLinearSpace(const ConstConfigRcPtr & srcConfig,
|
||||
const ConstColorSpaceRcPtr & cs,
|
||||
const ConstConfigRcPtr & builtinConfig)
|
||||
{
|
||||
// Currently only handling scene-referred spaces in the heuristics.
|
||||
if (cs->getReferenceSpaceType() == REFERENCE_SPACE_DISPLAY)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Don't check spaces without transforms / data spaces.
|
||||
if (hasNoTransform(cs))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define a set of (somewhat arbitrary) RGB values to test whether the combined transform is
|
||||
// enough of an identity.
|
||||
std::vector<float> vals = { 0.7f, 0.4f, 0.02f, 0.f,
|
||||
@@ -353,14 +480,9 @@ int getReferenceSpaceFromLinearSpace(const ConstConfigRcPtr & srcConfig,
|
||||
//
|
||||
int getReferenceSpaceFromSRGBSpace(const ConstConfigRcPtr & srcConfig,
|
||||
const char * srcRefName,
|
||||
const ConstColorSpaceRcPtr cs,
|
||||
const ConstColorSpaceRcPtr & cs,
|
||||
const ConstConfigRcPtr & builtinConfig)
|
||||
{
|
||||
// Currently only handling scene-referred spaces in the heuristics.
|
||||
if (cs->getReferenceSpaceType() == REFERENCE_SPACE_DISPLAY)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Get a transform in the to-reference direction.
|
||||
ConstTransformRcPtr toRefTransform;
|
||||
ConstTransformRcPtr ctransform = cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
|
||||
@@ -405,6 +527,18 @@ int getReferenceSpaceFromSRGBSpace(const ConstConfigRcPtr & srcConfig,
|
||||
|
||||
ConstProcessorRcPtr proc = srcConfig->getProcessor(toRefTransform, TRANSFORM_DIR_FORWARD);
|
||||
|
||||
// Ensure that the color space is not only an sRGB curve, it needs to have a color matrix
|
||||
// too or else the last step below could succeed by pairing the built-in sRGB space with
|
||||
// a linear space that cancels out the matrix in the built-in sRGB space.
|
||||
// NB: This is being done after the getProcessor call rather than simply looking at
|
||||
// the raw color space transform contents since once it becomes a processor, the complex
|
||||
// transforms (e.g. File, ColorSpace, Builtins) that could be hiding a matrix are
|
||||
// converted into ops.
|
||||
if (!hasNonTrivialMatrixTransform(proc))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ConstCPUProcessorRcPtr cpu = proc->getOptimizedCPUProcessor(OPTIMIZATION_NONE);
|
||||
// Convert the non-linear values to linear.
|
||||
cpu->apply(desc, descDst);
|
||||
@@ -422,6 +556,7 @@ int getReferenceSpaceFromSRGBSpace(const ConstConfigRcPtr & srcConfig,
|
||||
out[i] = 1.055f * std::pow(out[i], 1.f / 2.4f) - 0.055f;
|
||||
}
|
||||
// Compare against the original source values.
|
||||
// (This assumes equal channel sRGB values remain so in the reference space of src config.)
|
||||
if (!EqualWithAbsError(vals[i], out[i], 1e-3f))
|
||||
{
|
||||
return -1;
|
||||
@@ -442,6 +577,8 @@ int getReferenceSpaceFromSRGBSpace(const ConstConfigRcPtr & srcConfig,
|
||||
// sRGB texture space. If the result is an identity, then that tells what the source config
|
||||
// reference space is.
|
||||
|
||||
// At this point, cs has the expected non-linearity and a non-trivial matrix to its reference space.
|
||||
// Now try to identify the matrix.
|
||||
for (int i = 0; i < getNumberOfbuiltinLinearSpaces(); i++)
|
||||
{
|
||||
ConstProcessorRcPtr proc = Config::GetProcessorFromConfigs(srcConfig,
|
||||
@@ -511,7 +648,7 @@ void IdentifyInterchangeSpace(const char ** srcInterchange,
|
||||
|
||||
// Identify the name of a reference space in the source config.
|
||||
*srcInterchange = getRefSpaceName(srcConfig);
|
||||
if (!*srcInterchange)
|
||||
if (!**srcInterchange)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "The supplied config does not have a color space for the reference.";
|
||||
@@ -531,8 +668,16 @@ void IdentifyInterchangeSpace(const char ** srcInterchange,
|
||||
for (int i = 0; i < nbCs; i++)
|
||||
{
|
||||
ConstColorSpaceRcPtr cs = srcConfig->getColorSpace(srcConfig->getColorSpaceNameByIndex(i));
|
||||
|
||||
if (containsSRGB(cs))
|
||||
{
|
||||
// Exclude color spaces that may be too expensive to test or otherwise inappropriate.
|
||||
// Currently only handling scene-referred spaces in the heuristics.
|
||||
if (excludeColorSpaceFromHeuristics(cs, REFERENCE_SPACE_SCENE, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
refColorSpacePrimsIndex = getReferenceSpaceFromSRGBSpace(srcConfig,
|
||||
*srcInterchange,
|
||||
cs,
|
||||
@@ -549,6 +694,14 @@ void IdentifyInterchangeSpace(const char ** srcInterchange,
|
||||
for (int i = 0; i < nbCs; i++)
|
||||
{
|
||||
ConstColorSpaceRcPtr cs = srcConfig->getColorSpace(srcConfig->getColorSpaceNameByIndex(i));
|
||||
|
||||
// Exclude color spaces that may be too expensive to test or otherwise inappropriate.
|
||||
// Currently only handling scene-referred spaces in the heuristics.
|
||||
if (excludeColorSpaceFromHeuristics(cs, REFERENCE_SPACE_SCENE, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (srcConfig->isColorSpaceLinear(cs->getName(), REFERENCE_SPACE_SCENE))
|
||||
{
|
||||
refColorSpacePrimsIndex = getReferenceSpaceFromLinearSpace(srcConfig,
|
||||
@@ -602,6 +755,18 @@ const char * IdentifyBuiltinColorSpace(const ConstConfigRcPtr & srcConfig,
|
||||
throw Exception(os.str().c_str());
|
||||
}
|
||||
|
||||
if (builtinColorSpace->isData())
|
||||
{
|
||||
const char * dataName = getDataSpaceName(srcConfig);
|
||||
if (!*dataName)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "The requested space is a data space but the supplied config does not have a data space.";
|
||||
throw Exception(os.str().c_str());
|
||||
}
|
||||
return dataName;
|
||||
}
|
||||
|
||||
ReferenceSpaceType builtinRefSpaceType = builtinColorSpace->getReferenceSpaceType();
|
||||
|
||||
// Identify interchange spaces. Passing an empty string for the source color space
|
||||
@@ -633,8 +798,8 @@ const char * IdentifyBuiltinColorSpace(const ConstConfigRcPtr & srcConfig,
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
1.f, 1.f, 1.f, 0.f };
|
||||
|
||||
// Loop over each non-data color space in the source config and test if the conversion to
|
||||
// the specified space in the built-in config is an identity.
|
||||
// Loop over the active, non-excluded, color spaces in the source config and test if the
|
||||
// conversion to the specified space in the built-in config is an identity.
|
||||
//
|
||||
// Note that there is a possibility that both the source and built-in sides of the
|
||||
// transform could be an identity (e.g., if the user asks for ACES2065-1 and that is
|
||||
@@ -646,7 +811,8 @@ const char * IdentifyBuiltinColorSpace(const ConstConfigRcPtr & srcConfig,
|
||||
for (int i = 0; i < nbCs; i++)
|
||||
{
|
||||
ConstColorSpaceRcPtr cs = srcConfig->getColorSpace(srcConfig->getColorSpaceNameByIndex(i));
|
||||
if (cs->isData() || (cs->getReferenceSpaceType() != builtinRefSpaceType))
|
||||
|
||||
if (excludeColorSpaceFromHeuristics(cs, builtinRefSpaceType, false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "ContextVariableUtils.h"
|
||||
@@ -15,7 +17,6 @@
|
||||
#include "OCIOZArchive.h"
|
||||
#include "PathUtils.h"
|
||||
#include "PrivateTypes.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "utils/StringUtils.h"
|
||||
|
||||
namespace OCIO_NAMESPACE
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <cstring>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Display.h"
|
||||
@@ -19,7 +21,6 @@
|
||||
#include "ParseUtils.h"
|
||||
#include "PathUtils.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "utils/StringUtils.h"
|
||||
#include "ViewingRules.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
@@ -4737,9 +4738,9 @@ inline void save(YAML::Emitter & out, const Config & config)
|
||||
out << YAML::Newline;
|
||||
out << YAML::Newline;
|
||||
|
||||
if (configMajorVersion >= 2)
|
||||
if (configMajorVersion >= 2 || config.getNumEnvironmentVars() > 0)
|
||||
{
|
||||
// Print the environment even if empty.
|
||||
// For v2 configs, write the environment section, even if empty.
|
||||
out << YAML::Key << "environment";
|
||||
out << YAML::Value << YAML::BeginMap;
|
||||
for(int i = 0; i < config.getNumEnvironmentVars(); ++i)
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
#include <set>
|
||||
#include <limits>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Mutex.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "utils/StringUtils.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
|
||||
@@ -24,7 +26,6 @@
|
||||
#include "mz_strm_mem.h"
|
||||
#include "mz_strm_os.h"
|
||||
#include "mz_strm_split.h"
|
||||
#include "mz_strm_zlib.h"
|
||||
#include "mz_zip.h"
|
||||
#include "mz_zip_rw.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Logging.h"
|
||||
@@ -20,7 +22,6 @@
|
||||
#include "ops/lut1d/Lut1DOp.h"
|
||||
#include "ops/lut3d/Lut3DOp.h"
|
||||
#include "ops/range/RangeOp.h"
|
||||
#include "pystring/pystring.h"
|
||||
|
||||
namespace OCIO_NAMESPACE
|
||||
{
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Mutex.h"
|
||||
#include "PathUtils.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "utils/StringUtils.h"
|
||||
#include "OCIOZArchive.h"
|
||||
|
||||
@@ -218,4 +219,3 @@ int ParseColorSpaceFromString(const Config & config, const char * str)
|
||||
}
|
||||
|
||||
} // namespace OCIO_NAMESPACE
|
||||
|
||||
|
||||
+35
-5
@@ -18,8 +18,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
#include "BitDepthUtils.h"
|
||||
|
||||
@@ -76,6 +74,8 @@ static inline void sse2RGBATranspose_4x4(__m128 row0, __m128 row1, __m128 row2,
|
||||
out_a = _mm_movehl_ps(tmp3, tmp1);
|
||||
}
|
||||
|
||||
#if !OCIO_USE_SSE2NEON
|
||||
|
||||
static inline __m128i sse2_blendv(__m128i a, __m128i b, __m128i mask)
|
||||
{
|
||||
return _mm_xor_si128(_mm_and_si128(_mm_xor_si128(a, b), mask), a);
|
||||
@@ -164,6 +164,8 @@ static inline __m128 sse2_cvtph_ps(__m128i a)
|
||||
return _mm_or_ps(o, sign);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Note Packing functions perform no 0.0 - 1.0 normalization
|
||||
// but perform 0 - max value clamping for integer formats
|
||||
template<BitDepth BD> struct SSE2RGBAPack {};
|
||||
@@ -290,21 +292,48 @@ struct SSE2RGBAPack<BIT_DEPTH_F16>
|
||||
__m128i rgba_00_01 = _mm_loadu_si128((const __m128i*)(in + 0));
|
||||
__m128i rgba_02_03 = _mm_loadu_si128((const __m128i*)(in + 8));
|
||||
|
||||
#if OCIO_USE_SSE2NEON
|
||||
// use neon hardware support for f16 to f32
|
||||
__m128 rgba0 = vreinterpretq_m128_f32(
|
||||
vcvt_f32_f16(vget_low_f16(vreinterpretq_f16_s64(vreinterpretq_s64_m128i(rgba_00_01))))
|
||||
);
|
||||
__m128 rgba1 = vreinterpretq_m128_f32(
|
||||
vcvt_f32_f16(vget_high_f16(vreinterpretq_f16_s64(vreinterpretq_s64_m128i(rgba_00_01))))
|
||||
);
|
||||
__m128 rgba2 = vreinterpretq_m128_f32(
|
||||
vcvt_f32_f16(vget_low_f16(vreinterpretq_f16_s64(vreinterpretq_s64_m128i(rgba_02_03))))
|
||||
);
|
||||
__m128 rgba3 = vreinterpretq_m128_f32(
|
||||
vcvt_f32_f16(vget_high_f16(vreinterpretq_f16_s64(vreinterpretq_s64_m128i(rgba_02_03))))
|
||||
);
|
||||
#else
|
||||
__m128 rgba0 = sse2_cvtph_ps(rgba_00_01);
|
||||
__m128 rgba1 = sse2_cvtph_ps(_mm_shuffle_epi32(rgba_00_01, _MM_SHUFFLE(1,0,3,2)));
|
||||
__m128 rgba2 = sse2_cvtph_ps(rgba_02_03);
|
||||
__m128 rgba3 = sse2_cvtph_ps(_mm_shuffle_epi32(rgba_02_03, _MM_SHUFFLE(1,0,3,2)));
|
||||
|
||||
#endif
|
||||
sse2RGBATranspose_4x4(rgba0, rgba1, rgba2, rgba3, r, g, b, a);
|
||||
}
|
||||
|
||||
static inline void Store(half *out, __m128 r, __m128 g, __m128 b, __m128 a)
|
||||
{
|
||||
__m128 rgba0, rgba1, rgba2, rgba3;
|
||||
__m128i rgba;
|
||||
|
||||
sse2RGBATranspose_4x4(r, g, b, a, rgba0, rgba1, rgba2, rgba3);
|
||||
|
||||
#if OCIO_USE_SSE2NEON
|
||||
// use neon hardware support for f32 to f16
|
||||
float16x8_t rgba;
|
||||
float16x4_t rgba00_01 = vcvt_f16_f32(vreinterpretq_f32_m128(rgba0));
|
||||
float16x4_t rgba03_03 = vcvt_f16_f32(vreinterpretq_f32_m128(rgba1));
|
||||
float16x4_t rgba04_05 = vcvt_f16_f32(vreinterpretq_f32_m128(rgba2));
|
||||
float16x4_t rgba06_07 = vcvt_f16_f32(vreinterpretq_f32_m128(rgba3));
|
||||
rgba = vcombine_f16(rgba00_01, rgba03_03);
|
||||
vst1q_f16((float16_t *)(out+0), rgba);
|
||||
|
||||
rgba = vcombine_f16(rgba04_05, rgba06_07);
|
||||
vst1q_f16((float16_t *)(out+8), rgba);
|
||||
#else
|
||||
__m128i rgba;
|
||||
__m128i rgba00_01 = sse2_cvtps_ph(rgba0);
|
||||
__m128i rgba02_03 = sse2_cvtps_ph(rgba1);
|
||||
__m128i rgba04_05 = sse2_cvtps_ph(rgba2);
|
||||
@@ -315,6 +344,7 @@ struct SSE2RGBAPack<BIT_DEPTH_F16>
|
||||
|
||||
rgba = _mm_xor_si128(rgba04_05, _mm_shuffle_epi32(rgba06_07, _MM_SHUFFLE(1,0,3,2)));
|
||||
_mm_storeu_si128((__m128i*)(out+8), rgba);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ void LocalFileFormat::buildFileOps(OpRcPtrVec & ops,
|
||||
{
|
||||
// Use 0 for empty string.
|
||||
int cccindex=0;
|
||||
if (StringToInt(&cccindex, cccid.c_str(), true))
|
||||
if (cccid.empty() || StringToInt(&cccindex, cccid.c_str(), true))
|
||||
{
|
||||
int maxindex = ((int)cachedFile->m_transformVec.size())-1;
|
||||
if (cccindex<0 || cccindex>maxindex)
|
||||
|
||||
@@ -247,7 +247,7 @@ LocalFileFormat::buildFileOps(OpRcPtrVec & ops,
|
||||
{
|
||||
// Use 0 for empty string.
|
||||
int cccindex=0;
|
||||
if (StringToInt(&cccindex, cccid.c_str(), true))
|
||||
if (cccid.empty() || StringToInt(&cccindex, cccid.c_str(), true))
|
||||
{
|
||||
int maxindex = ((int)cachedFile->m_transformVec.size())-1;
|
||||
if (cccindex<0 || cccindex>maxindex)
|
||||
@@ -274,7 +274,7 @@ LocalFileFormat::buildFileOps(OpRcPtrVec & ops,
|
||||
if (!success)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "You must specify a valid cccid to load from the ccc file";
|
||||
os << "You must specify a valid cccid to load from the cdl file";
|
||||
os << " (either by name or index). id='" << cccid << "' ";
|
||||
os << "is not found in the file, and is not parsable as an ";
|
||||
os << "integer index.";
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "expat.h"
|
||||
@@ -23,7 +25,6 @@
|
||||
#include "OpBuilders.h"
|
||||
#include "ops/noop/NoOps.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "TransformBuilder.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
#include "utils/StringUtils.h"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "BitDepthUtils.h"
|
||||
@@ -16,7 +18,6 @@
|
||||
#include "ops/lut1d/Lut1DOp.h"
|
||||
#include "ops/lut3d/Lut3DOp.h"
|
||||
#include "ParseUtils.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "Platform.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
#include "utils/StringUtils.h"
|
||||
@@ -771,4 +772,3 @@ FileFormat * CreateFileFormatDiscreet1DL()
|
||||
}
|
||||
|
||||
} // namespace OCIO_NAMESPACE
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Logging.h"
|
||||
@@ -15,7 +17,6 @@
|
||||
#include "ops/matrix/MatrixOp.h"
|
||||
#include "ops/range/RangeOp.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "expat.h"
|
||||
@@ -13,7 +15,6 @@
|
||||
#include "ops/lut3d/Lut3DOp.h"
|
||||
#include "ParseUtils.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "transforms/FileTransform.h"
|
||||
#include "utils/StringUtils.h"
|
||||
#include "utils/NumberUtils.h"
|
||||
@@ -579,4 +580,3 @@ FileFormat * CreateFileFormatIridasLook()
|
||||
}
|
||||
|
||||
} // namespace OCIO_NAMESPACE
|
||||
|
||||
|
||||
@@ -24,13 +24,23 @@ namespace {
|
||||
|
||||
static inline __m128 fmadd_ps_sse2(__m128 a, __m128 b, __m128 c)
|
||||
{
|
||||
#if OCIO_USE_SSE2NEON
|
||||
return vreinterpretq_m128_f32(
|
||||
vfmaq_f32(vreinterpretq_f32_m128(c), vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))
|
||||
);
|
||||
#else
|
||||
return _mm_add_ps(_mm_mul_ps(a, b), c);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline __m128 floor_ps_sse2(__m128 v)
|
||||
{
|
||||
#if OCIO_USE_SSE2NEON
|
||||
return _mm_floor_ps(v);
|
||||
#else
|
||||
// NOTE: using truncate cvtt
|
||||
return _mm_cvtepi32_ps(_mm_cvttps_epi32(v));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,18 +38,32 @@ struct rgbavec_sse2 {
|
||||
|
||||
static inline __m128 floor_ps_sse2(__m128 v)
|
||||
{
|
||||
#if OCIO_USE_SSE2NEON
|
||||
return _mm_floor_ps(v);
|
||||
#else
|
||||
// NOTE: using truncate cvtt
|
||||
return _mm_cvtepi32_ps(_mm_cvttps_epi32(v));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline __m128 blendv_ps_sse2(__m128 a, __m128 b, __m128 mask)
|
||||
{
|
||||
#if OCIO_USE_SSE2NEON
|
||||
return _mm_blendv_ps(a, b, mask);
|
||||
#else
|
||||
return _mm_xor_ps(_mm_and_ps(_mm_xor_ps(a, b), mask), a);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline __m128 fmadd_ps_sse2(__m128 a, __m128 b, __m128 c)
|
||||
{
|
||||
#if OCIO_USE_SSE2NEON
|
||||
return vreinterpretq_m128_f32(
|
||||
vfmaq_f32(vreinterpretq_f32_m128(c), vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))
|
||||
);
|
||||
#else
|
||||
return _mm_add_ps(_mm_mul_ps(a, b), c);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline rgbavec_sse2 interp_tetrahedral_sse2(const Lut3DContextSSE2 &ctx, __m128 r, __m128 g, __m128 b, __m128 a)
|
||||
|
||||
@@ -184,7 +184,7 @@ void BuildColorSpaceOps(OpRcPtrVec & ops,
|
||||
|
||||
if (!src)
|
||||
{
|
||||
srcNamedTransform = config.getNamedTransform(srcName.c_str());
|
||||
srcNamedTransform = config.getNamedTransform( context->resolveStringVar(srcName.c_str()) );
|
||||
if (!srcNamedTransform)
|
||||
{
|
||||
ThrowMissingCS(srcName.c_str());
|
||||
@@ -192,7 +192,7 @@ void BuildColorSpaceOps(OpRcPtrVec & ops,
|
||||
}
|
||||
if (!dst)
|
||||
{
|
||||
dstNamedTransform = config.getNamedTransform(dstName.c_str());
|
||||
dstNamedTransform = config.getNamedTransform( context->resolveStringVar(dstName.c_str()) );
|
||||
if (!dstNamedTransform)
|
||||
{
|
||||
ThrowMissingCS(dstName.c_str());
|
||||
@@ -393,6 +393,31 @@ void BuildReferenceConversionOps(OpRcPtrVec & ops,
|
||||
}
|
||||
}
|
||||
|
||||
bool CollectContextVariables(const Config & config,
|
||||
const Context & context,
|
||||
ConstNamedTransformRcPtr & nt,
|
||||
ContextRcPtr & usedContextVars)
|
||||
{
|
||||
bool foundContextVars = false;
|
||||
|
||||
if (nt)
|
||||
{
|
||||
ConstTransformRcPtr to = nt->getTransform(TRANSFORM_DIR_FORWARD);
|
||||
if (to && CollectContextVariables(config, context, to, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
|
||||
ConstTransformRcPtr from = nt->getTransform(TRANSFORM_DIR_INVERSE);
|
||||
if (from && CollectContextVariables(config, context, from, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
}
|
||||
|
||||
return foundContextVars;
|
||||
}
|
||||
|
||||
bool CollectContextVariables(const Config & config,
|
||||
const Context & context,
|
||||
ConstColorSpaceRcPtr & cs,
|
||||
@@ -441,15 +466,37 @@ bool CollectContextVariables(const Config & config,
|
||||
}
|
||||
|
||||
ConstColorSpaceRcPtr src = config.getColorSpace(srcName.c_str());
|
||||
if (CollectContextVariables(config, context, src, usedContextVars))
|
||||
if (src)
|
||||
{
|
||||
foundContextVars = true;
|
||||
if (CollectContextVariables(config, context, src, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstNamedTransformRcPtr nt_src = config.getNamedTransform(srcName.c_str());
|
||||
if (CollectContextVariables(config, context, nt_src, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
}
|
||||
|
||||
ConstColorSpaceRcPtr dst = config.getColorSpace(dstName.c_str());
|
||||
if (CollectContextVariables(config, context, dst, usedContextVars))
|
||||
if (dst)
|
||||
{
|
||||
foundContextVars = true;
|
||||
if (CollectContextVariables(config, context, dst, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstNamedTransformRcPtr nt_dst = config.getNamedTransform(dstName.c_str());
|
||||
if (CollectContextVariables(config, context, nt_dst, usedContextVars))
|
||||
{
|
||||
foundContextVars = true;
|
||||
}
|
||||
}
|
||||
|
||||
return foundContextVars;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
#include <pystring.h>
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "Caching.h"
|
||||
@@ -19,7 +21,6 @@
|
||||
#include "ops/noop/NoOps.h"
|
||||
#include "PathUtils.h"
|
||||
#include "Platform.h"
|
||||
#include "pystring/pystring.h"
|
||||
#include "utils/StringUtils.h"
|
||||
|
||||
namespace OCIO_NAMESPACE
|
||||
|
||||
+134
-47
@@ -50,12 +50,16 @@ public:
|
||||
void setGPU(OCIO::ConstGPUProcessorRcPtr gpu)
|
||||
{
|
||||
m_gpu = gpu;
|
||||
m_oglApp = OCIO::OglApp::CreateOglApp("ociochecklut", 256, 20);
|
||||
|
||||
if (m_verbose)
|
||||
if (!m_oglApp)
|
||||
{
|
||||
m_oglApp->printGLInfo();
|
||||
m_oglApp = OCIO::OglApp::CreateOglApp("ociochecklut", 256, 20);
|
||||
|
||||
if (m_verbose)
|
||||
{
|
||||
m_oglApp->printGLInfo();
|
||||
}
|
||||
}
|
||||
|
||||
m_oglApp->setPrintShader(m_verbose);
|
||||
float image[4]{ 0.f, 0.f, 0.f, 0.f };
|
||||
m_oglApp->initImage(1, 1, OCIO::OglApp::COMPONENTS_RGBA, image);
|
||||
@@ -191,6 +195,7 @@ int main (int argc, const char* argv[])
|
||||
bool usegpu = false;
|
||||
bool usegpuLegacy = false;
|
||||
bool outputgpuInfo = false;
|
||||
bool stepInfo = false;
|
||||
|
||||
ArgParse ap;
|
||||
ap.options("ociochecklut -- check any LUT file and optionally convert a pixel\n\n"
|
||||
@@ -199,6 +204,7 @@ int main (int argc, const char* argv[])
|
||||
"<SEPARATOR>", "Options:",
|
||||
"-t", &test, "Test a set a predefined RGB values",
|
||||
"-v", &verbose, "Verbose",
|
||||
"-s", &stepInfo, "Print the output after each step in a multi - transform LUT",
|
||||
"--help", &help, "Print help message",
|
||||
"--inv", &invlut, "Apply LUT in inverse direction",
|
||||
"--gpu", &usegpu, "Use GPU instead of CPU",
|
||||
@@ -346,7 +352,7 @@ int main (int argc, const char* argv[])
|
||||
0.f, 1.f, 0.f,
|
||||
0.f, 0.f, 1.f };
|
||||
|
||||
if (verbose)
|
||||
if (verbose || stepInfo)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -357,59 +363,140 @@ int main (int argc, const char* argv[])
|
||||
{
|
||||
std::vector<float> pixel = { input[curPix], input[curPix+1], input[curPix+2],
|
||||
comp == 3 ? 0.0f : input[curPix + 3] };
|
||||
try
|
||||
{
|
||||
proc.apply(pixel);
|
||||
}
|
||||
catch (const OCIO::Exception & e)
|
||||
{
|
||||
std::cerr << "ERROR: Processing pixel: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "ERROR: Unknown error encountered while processing pixel." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Print to string so that in & out values can be aligned if needed.
|
||||
|
||||
std::vector<std::string> out;
|
||||
ToString(out, pixel, 0, comp);
|
||||
|
||||
if (verbose)
|
||||
if (stepInfo)
|
||||
{
|
||||
std::vector<std::string> in;
|
||||
ToString(in, input, curPix, comp);
|
||||
|
||||
std::cout << "Input [R G B";
|
||||
if (comp == 4)
|
||||
// Process each step in a multi - transform LUT
|
||||
try
|
||||
{
|
||||
std::cout << " A";
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(in, out, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
// Create GroupTransform so that each can be processed one at a time.
|
||||
auto processor = config->getProcessor(t);
|
||||
auto transform = processor->createGroupTransform();
|
||||
std::vector<float> inputPixel = pixel;
|
||||
std::vector<float> outputPixel = pixel;
|
||||
const auto numTransforms = transform->getNumTransforms();
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Output [R G B";
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " A";
|
||||
for (int i = 0; i < numTransforms; ++i)
|
||||
{
|
||||
auto transformStep = transform->getTransform(i);
|
||||
auto processorStep = config->getProcessor(transformStep);
|
||||
|
||||
if (usegpu || usegpuLegacy)
|
||||
{
|
||||
proc.setGPU(usegpuLegacy ? processorStep->getOptimizedLegacyGPUProcessor(OCIO::OPTIMIZATION_DEFAULT, 32)
|
||||
: processorStep->getDefaultGPUProcessor());
|
||||
}
|
||||
else
|
||||
{
|
||||
proc.setCPU(processorStep->getDefaultCPUProcessor());
|
||||
}
|
||||
|
||||
// Process the pixel
|
||||
proc.apply(outputPixel);
|
||||
|
||||
// Print the input/output pixel
|
||||
std::vector<std::string> in;
|
||||
ToString(in, inputPixel, 0, comp);
|
||||
|
||||
std::vector<std::string> out;
|
||||
ToString(out, outputPixel, 0, comp);
|
||||
|
||||
std::cout << "\n" << *(transform->getTransform(i)) << std::endl;
|
||||
std::cout << "Input [R G B";
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " A";
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(in, out, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
std::cout << "Output [R G B";
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " A";
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(out, in, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
inputPixel = outputPixel;
|
||||
}
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(out, in, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
catch (const OCIO::Exception& exception)
|
||||
{
|
||||
std::cerr << "ERROR: " << exception.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "ERROR: Unknown error encountered while processing single step operator." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
curPix += comp;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << out[0] << " " << out[1] << " " << out[2];
|
||||
if (comp == 4)
|
||||
// Process in a single step
|
||||
try
|
||||
{
|
||||
std::cout << " " << out[3];
|
||||
proc.apply(pixel);
|
||||
}
|
||||
catch (const OCIO::Exception& e)
|
||||
{
|
||||
std::cerr << "ERROR: Processing pixel: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "ERROR: Unknown error encountered while processing pixel." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Print to string so that in & out values can be aligned if needed.
|
||||
|
||||
std::vector<std::string> out;
|
||||
ToString(out, pixel, 0, comp);
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
curPix += comp;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
std::vector<std::string> in;
|
||||
ToString(in, input, curPix, comp);
|
||||
|
||||
std::cout << "Input [R G B";
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " A";
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(in, out, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
std::cout << "Output [R G B";
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " A";
|
||||
}
|
||||
std::cout << "]: [";
|
||||
PrintAlignedVec(out, in, comp);
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << out[0] << " " << out[1] << " " << out[2];
|
||||
if (comp == 4)
|
||||
{
|
||||
std::cout << " " << out[3];
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
curPix += comp;
|
||||
}
|
||||
}
|
||||
else if (test)
|
||||
{
|
||||
|
||||
@@ -41,10 +41,10 @@ Dependencies
|
||||
|
||||
* PyOpenColorIO
|
||||
* [OpenImageIO (Python bindings)](https://github.com/OpenImageIO/oiio)
|
||||
* [Imath (Python bindings)](https://github.com/AcademySoftwareFoundation/Imath)
|
||||
* ``pip install -r requirements.txt``
|
||||
* [numpy](https://pypi.org/project/numpy/)
|
||||
* [Pygments](https://pypi.org/project/Pygments/)
|
||||
* [PyOpenGL](https://pypi.org/project/PyOpenGL/)
|
||||
* [PySide2](https://pypi.org/project/PySide2/)
|
||||
* [PySide6](https://pypi.org/project/PySide6/)
|
||||
* [QtAwesome](https://pypi.org/project/QtAwesome/)
|
||||
* [imageio](https://pypi.org/project/imageio/)
|
||||
@@ -7,7 +7,7 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets, QtOpenGL
|
||||
from PySide6 import QtCore, QtGui, QtWidgets, QtOpenGL
|
||||
|
||||
import ocioview.log_handlers # Import to initialize logging
|
||||
from ocioview.main_window import OCIOView
|
||||
@@ -30,12 +30,11 @@ if __name__ == "__main__":
|
||||
sys.excepthook = excepthook
|
||||
|
||||
# OpenGL core profile needed on macOS to access programmatic pipeline
|
||||
gl_format = QtOpenGL.QGLFormat()
|
||||
gl_format.setProfile(QtOpenGL.QGLFormat.CoreProfile)
|
||||
gl_format.setSampleBuffers(True)
|
||||
gl_format = QtGui.QSurfaceFormat()
|
||||
gl_format.setProfile(QtGui.QSurfaceFormat.CoreProfile)
|
||||
gl_format.setSwapInterval(1)
|
||||
gl_format.setVersion(4, 0)
|
||||
QtOpenGL.QGLFormat.setDefaultFormat(gl_format)
|
||||
QtGui.QSurfaceFormat.setDefaultFormat(gl_format)
|
||||
|
||||
# Create app
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from .items import (
|
||||
ColorSpaceEdit,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
|
||||
# Root application directory
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from pygments.formatters import HtmlFormatter
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..message_router import MessageRouter
|
||||
from ..utils import get_glyph_icon, processor_to_shader_html
|
||||
@@ -40,9 +40,9 @@ class CodeInspector(QtWidgets.QWidget):
|
||||
|
||||
html_css = HtmlFormatter(style="material").get_style_defs()
|
||||
# Update line number colors to match palette
|
||||
html_css = html_css.replace("#263238", palette.color(palette.Base).name())
|
||||
html_css = html_css.replace("#263238", palette.color(palette.ColorRole.Base).name())
|
||||
html_css = html_css.replace(
|
||||
"#37474F", palette.color(palette.Text).darker(150).name()
|
||||
"#37474F", palette.color(palette.ColorRole.Text).darker(150).name()
|
||||
)
|
||||
|
||||
# Widgets
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import Optional
|
||||
import numpy as np
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..constants import R_COLOR, G_COLOR, B_COLOR, GRAY_COLOR
|
||||
from ..message_router import MessageRouter
|
||||
@@ -17,11 +17,22 @@ from ..widgets import EnumComboBox, FloatEditArray, IntEdit
|
||||
|
||||
|
||||
class SampleType(enum.Enum):
|
||||
"""Enum of curve sampling types for representing OCIO transforms."""
|
||||
|
||||
LINEAR = "linear"
|
||||
"""Linear scale."""
|
||||
|
||||
LOG = "log"
|
||||
"""Log scale with a user-defined base."""
|
||||
|
||||
|
||||
class CurveInspector(QtWidgets.QWidget):
|
||||
"""
|
||||
Widget for inspecting OCIO transform tone curves, which updates
|
||||
asynchronously when visible, to reduce unnecessary background
|
||||
processing.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def label(cls) -> str:
|
||||
return "Curve"
|
||||
@@ -43,11 +54,11 @@ class CurveInspector(QtWidgets.QWidget):
|
||||
self.input_range_edit.setToolTip(self.input_range_label.toolTip())
|
||||
self.input_range_edit.value_changed.connect(self._on_input_range_changed)
|
||||
|
||||
self.sample_size_label = get_glyph_icon("ph.line-segments", as_widget=True)
|
||||
self.sample_size_label.setToolTip("Sample size")
|
||||
self.sample_size_edit = IntEdit(default=CurveView.SAMPLE_SIZE_DEFAULT)
|
||||
self.sample_size_edit.setToolTip(self.sample_size_label.toolTip())
|
||||
self.sample_size_edit.value_changed.connect(self._on_sample_size_changed)
|
||||
self.sample_count_label = get_glyph_icon("ph.line-segments", as_widget=True)
|
||||
self.sample_count_label.setToolTip("Sample count")
|
||||
self.sample_count_edit = IntEdit(default=CurveView.SAMPLE_COUNT_DEFAULT)
|
||||
self.sample_count_edit.setToolTip(self.sample_count_label.toolTip())
|
||||
self.sample_count_edit.value_changed.connect(self._on_sample_count_changed)
|
||||
|
||||
self.sample_type_label = get_glyph_icon("mdi6.function-variant", as_widget=True)
|
||||
self.sample_type_label.setToolTip("Sample type")
|
||||
@@ -70,16 +81,16 @@ class CurveInspector(QtWidgets.QWidget):
|
||||
option_layout = QtWidgets.QHBoxLayout()
|
||||
option_layout.addWidget(self.input_range_label)
|
||||
option_layout.addWidget(self.input_range_edit)
|
||||
option_layout.setStretch(1, 2)
|
||||
option_layout.addWidget(self.sample_size_label)
|
||||
option_layout.addWidget(self.sample_size_edit)
|
||||
option_layout.setStretch(3, 1)
|
||||
option_layout.setStretch(1, 3)
|
||||
option_layout.addWidget(self.sample_count_label)
|
||||
option_layout.addWidget(self.sample_count_edit)
|
||||
option_layout.setStretch(3, 2)
|
||||
option_layout.addWidget(self.sample_type_label)
|
||||
option_layout.addWidget(self.sample_type_combo)
|
||||
option_layout.setStretch(5, 1)
|
||||
option_layout.setStretch(5, 3)
|
||||
option_layout.addWidget(self.log_base_label)
|
||||
option_layout.addWidget(self.log_base_edit)
|
||||
option_layout.setStretch(7, 1)
|
||||
option_layout.setStretch(7, 2)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
layout.addLayout(option_layout)
|
||||
@@ -88,83 +99,137 @@ class CurveInspector(QtWidgets.QWidget):
|
||||
self.setLayout(layout)
|
||||
|
||||
def reset(self) -> None:
|
||||
"""Clear rendered curves."""
|
||||
self.view.reset()
|
||||
|
||||
@QtCore.Slot(str, float)
|
||||
def _on_input_range_changed(self, label: str, value: float) -> None:
|
||||
"""
|
||||
Triggered when the user changes the input range, which defines
|
||||
the input values to be sampled through the transform.
|
||||
|
||||
:param label: Float edit label
|
||||
:param value: Float edit value
|
||||
"""
|
||||
self.view.set_input_range(
|
||||
self.input_range_edit.component_value("min"),
|
||||
self.input_range_edit.component_value("max"),
|
||||
)
|
||||
|
||||
@QtCore.Slot(int)
|
||||
def _on_sample_size_changed(self, sample_size: int) -> None:
|
||||
if sample_size >= CurveView.SAMPLE_SIZE_MIN:
|
||||
self.view.set_sample_size(sample_size)
|
||||
def _on_sample_count_changed(self, sample_count: int) -> None:
|
||||
"""
|
||||
Triggered when the user changes the number of samples to be
|
||||
processed within the input range through the transform.
|
||||
|
||||
:param sample_count: Number of samples. Typically, a power of 2
|
||||
number.
|
||||
"""
|
||||
if sample_count >= CurveView.SAMPLE_COUNT_MIN:
|
||||
self.view.set_sample_count(sample_count)
|
||||
else:
|
||||
with SignalsBlocked(self.sample_size_edit):
|
||||
self.sample_size_edit.set_value(CurveView.SAMPLE_SIZE_MIN)
|
||||
self.view.set_sample_size(CurveView.SAMPLE_SIZE_MIN)
|
||||
with SignalsBlocked(self.sample_count_edit):
|
||||
self.sample_count_edit.set_value(CurveView.SAMPLE_COUNT_MIN)
|
||||
self.view.set_sample_count(CurveView.SAMPLE_COUNT_MIN)
|
||||
|
||||
@QtCore.Slot(int)
|
||||
def _on_sample_type_changed(self, index: int) -> None:
|
||||
"""
|
||||
Triggered when the user changes the sample type, which defines
|
||||
how samples are distributed within the input range.
|
||||
|
||||
:param index: Curve type index
|
||||
"""
|
||||
sample_type = self.sample_type_combo.member()
|
||||
self.log_base_edit.setEnabled(sample_type == SampleType.LOG)
|
||||
self.view.set_sample_type(sample_type)
|
||||
|
||||
@QtCore.Slot(int)
|
||||
def _on_log_base_changed(self, log_base: int) -> None:
|
||||
"""
|
||||
Triggered when the user changes the base for the log sample
|
||||
type.
|
||||
|
||||
:param log_base: Log scale base
|
||||
"""
|
||||
self.view.set_log_base(log_base)
|
||||
|
||||
|
||||
class CurveView(QtWidgets.QGraphicsView):
|
||||
"""
|
||||
Widget for rendering OCIO transform tone curves.
|
||||
"""
|
||||
|
||||
SAMPLE_SIZE_MIN = 2**8
|
||||
SAMPLE_SIZE_DEFAULT = 2**10
|
||||
SAMPLE_COUNT_MIN = 2**8
|
||||
SAMPLE_COUNT_DEFAULT = 2**10
|
||||
INPUT_MIN_DEFAULT = 0.0
|
||||
INPUT_MAX_DEFAULT = 1.0
|
||||
LOG_BASE_DEFAULT = 2
|
||||
CURVE_SCALE = 100
|
||||
FONT_HEIGHT = 4
|
||||
|
||||
# The curve viewer only shows 5 digit decimal precision, so this should work fine
|
||||
# as a minimum when input min is 0.
|
||||
LOG_EPSILON = 1e-5
|
||||
LOG_BASE_DEFAULT = 2
|
||||
EPSILON = 1e-5
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
input_min: float = INPUT_MIN_DEFAULT,
|
||||
input_max: float = INPUT_MAX_DEFAULT,
|
||||
sample_size: int = SAMPLE_SIZE_DEFAULT,
|
||||
sample_count: int = SAMPLE_COUNT_DEFAULT,
|
||||
sample_type: SampleType = SampleType.LINEAR,
|
||||
log_base: int = LOG_BASE_DEFAULT,
|
||||
parent: Optional[QtWidgets.QWidget] = None,
|
||||
):
|
||||
"""
|
||||
:param input_min: Input range minimum value
|
||||
:param input_max: Input range maximum value
|
||||
:param sample_count: Number of samples in the input range,
|
||||
which will typically be a power of 2 value.
|
||||
:param sample_type: Sample scale/distribution type
|
||||
:param log_base: Log scale base when sample_type is
|
||||
`SampleType.LOG`.
|
||||
"""
|
||||
super().__init__(parent=parent)
|
||||
self.setRenderHint(QtGui.QPainter.Antialiasing, True)
|
||||
self.setViewportUpdateMode(QtWidgets.QGraphicsView.FullViewportUpdate)
|
||||
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.setMouseTracking(True)
|
||||
self.scale(1, -1)
|
||||
self.scale(1, -1) # Flip to make origin the bottom-left corner
|
||||
|
||||
# Input range
|
||||
if input_max <= input_min:
|
||||
input_min = self.INPUT_MIN_DEFAULT
|
||||
input_max = self.INPUT_MAX_DEFAULT
|
||||
|
||||
self._log_base = max(2, log_base)
|
||||
self._input_min = input_min
|
||||
self._input_max = input_max
|
||||
self._sample_size = max(self.SAMPLE_SIZE_MIN, sample_size)
|
||||
|
||||
# Sample characteristics
|
||||
self._sample_count = max(self.SAMPLE_COUNT_MIN, sample_count)
|
||||
self._sample_type = sample_type
|
||||
self._log_base = max(2, log_base)
|
||||
|
||||
# Cached sample data
|
||||
self._sample_ellipse: Optional[QtWidgets.QGraphicsEllipseItem] = None
|
||||
self._sample_text: Optional[QtWidgets.QGraphicsTextItem] = None
|
||||
self._sample_rect: Optional[QtCore.QRectF] = None
|
||||
self._samples_x_lin: np.ndarray = None
|
||||
self._samples_x_log: np.ndarray = None
|
||||
self._sample_y_min: float = self._input_min
|
||||
self._sample_y_max: float = self._input_max
|
||||
|
||||
self._samples: dict[str, np.ndarray] = {}
|
||||
self._nearest_samples: dict[str, tuple[float, float, float]] = {}
|
||||
|
||||
self._x_lin: np.ndarray = np.array([], dtype=np.float32)
|
||||
self._x_log: np.ndarray = np.array([], dtype=np.float32)
|
||||
self._x_min: float = self._input_min
|
||||
self._x_max: float = self._input_max
|
||||
self._y_min: float = self._input_min
|
||||
self._y_max: float = self._input_max
|
||||
|
||||
# Cached curve data
|
||||
self._curve_init = False
|
||||
self._curve_tf = QtGui.QTransform()
|
||||
self._curve_tf_inv = QtGui.QTransform()
|
||||
self._curve_paths: dict[str, QtGui.QPainterPath] = {}
|
||||
self._curve_items: dict[str, QtWidgets.QGraphicsPathItem] = {}
|
||||
self._curve_rect = QtCore.QRectF(
|
||||
@@ -173,10 +238,11 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
self._input_max - self._input_min,
|
||||
self._input_max - self._input_min,
|
||||
)
|
||||
self._nearest_samples: dict[str, tuple[float, float, float]] = {}
|
||||
self._prev_cpu_proc = None
|
||||
self._curve_init = False
|
||||
|
||||
# Cached processor from which the OCIO transform is derived
|
||||
self._prev_cpu_proc = None
|
||||
|
||||
# Graphics scene
|
||||
self._scene = QtWidgets.QGraphicsScene()
|
||||
self.setScene(self._scene)
|
||||
|
||||
@@ -200,8 +266,8 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
msg_router.set_cpu_processor_updates_allowed(False)
|
||||
|
||||
def resizeEvent(self, event: QtGui.QResizeEvent) -> None:
|
||||
"""Re-fit graph on resize, to always be centered."""
|
||||
super().resizeEvent(event)
|
||||
|
||||
self._fit()
|
||||
|
||||
def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
@@ -213,37 +279,52 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
|
||||
self._nearest_samples.clear()
|
||||
|
||||
pos = self.mapToScene(event.pos()) / self.CURVE_SCALE
|
||||
pos = self._curve_tf_inv.map(self.mapToScene(event.pos()))
|
||||
pos_arr = np.array([pos.x(), pos.y()], dtype=np.float32)
|
||||
|
||||
for color_name, samples in self._samples.items():
|
||||
all_dist = np.linalg.norm(samples - pos_arr, axis=2)
|
||||
all_dist = np.linalg.norm(samples - pos_arr, axis=1)
|
||||
nearest_dist_index = np.argmin(all_dist)
|
||||
self._nearest_samples[color_name] = (
|
||||
(
|
||||
self._samples_x_lin[nearest_dist_index]
|
||||
self._x_lin[nearest_dist_index]
|
||||
if self._sample_type == SampleType.LINEAR
|
||||
else self._samples_x_log[nearest_dist_index]
|
||||
else self._x_log[nearest_dist_index]
|
||||
),
|
||||
samples[0][nearest_dist_index][0],
|
||||
samples[0][nearest_dist_index][1],
|
||||
samples[nearest_dist_index][0],
|
||||
samples[nearest_dist_index][1],
|
||||
)
|
||||
|
||||
self._invalidate()
|
||||
|
||||
def wheelEvent(self, event: QtGui.QWheelEvent) -> None:
|
||||
"""
|
||||
Ignore wheel events to prevent scrolling around graphics scene.
|
||||
"""
|
||||
event.ignore()
|
||||
|
||||
def reset(self) -> None:
|
||||
"""Clear all curves."""
|
||||
self._samples.clear()
|
||||
self._curve_items.clear()
|
||||
self._curve_paths.clear()
|
||||
self._nearest_samples.clear()
|
||||
self._prev_cpu_proc = None
|
||||
|
||||
self._curve_init = False
|
||||
self._curve_paths.clear()
|
||||
self._curve_items.clear()
|
||||
|
||||
self._prev_cpu_proc = None
|
||||
|
||||
self._scene.clear()
|
||||
self._invalidate()
|
||||
|
||||
def set_input_range(self, input_min: float, input_max: float) -> None:
|
||||
"""
|
||||
Set the input range, which defines the input values to be
|
||||
sampled through the transform.
|
||||
|
||||
:param input_min: Input range minimum value
|
||||
:param input_max: Input range maximum value
|
||||
"""
|
||||
if (
|
||||
input_min != self._input_min or input_max != self._input_max
|
||||
) and input_max > input_min:
|
||||
@@ -252,31 +333,62 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
self._update_curves()
|
||||
|
||||
def set_input_min(self, input_min: float) -> None:
|
||||
"""
|
||||
Set the input minimum, which defines the lowest value to be
|
||||
sampled through the transform.
|
||||
|
||||
:param input_min: Input range minimum value
|
||||
"""
|
||||
if input_min != self._input_min and input_min < self._input_max:
|
||||
self._input_min = input_min
|
||||
self._update_curves()
|
||||
|
||||
def set_input_max(self, input_max: float) -> None:
|
||||
"""
|
||||
Set the input maximum, which defines the highest value to be
|
||||
sampled through the transform.
|
||||
|
||||
:param input_max: Input range minimum value
|
||||
"""
|
||||
if input_max != self._input_max and input_max > self._input_min:
|
||||
self._input_max = input_max
|
||||
self._update_curves()
|
||||
|
||||
def set_sample_size(self, sample_size: int) -> None:
|
||||
if sample_size != self._sample_size and sample_size >= self.SAMPLE_SIZE_MIN:
|
||||
self._sample_size = sample_size
|
||||
def set_sample_count(self, sample_count: int) -> None:
|
||||
"""
|
||||
Set the number of samples to be processed within the input
|
||||
range through the transform.
|
||||
|
||||
:param sample_count: Number of samples. Typically, a power of 2
|
||||
number.
|
||||
"""
|
||||
if sample_count != self._sample_count and sample_count >= self.SAMPLE_COUNT_MIN:
|
||||
self._sample_count = sample_count
|
||||
self._update_curves()
|
||||
|
||||
def set_sample_type(self, sample_type: SampleType) -> None:
|
||||
"""
|
||||
Set the sample type, which defines how samples are distributed
|
||||
within the input range.
|
||||
|
||||
:param sample_type: Curve type index
|
||||
"""
|
||||
if sample_type != self._sample_type:
|
||||
self._sample_type = sample_type
|
||||
self._update_curves()
|
||||
|
||||
def set_log_base(self, log_base: int) -> None:
|
||||
"""
|
||||
Set the base for the log sample type.
|
||||
|
||||
:param log_base: Log scale base
|
||||
"""
|
||||
if log_base != self._log_base and log_base >= 2:
|
||||
self._log_base = log_base
|
||||
self._update_curves()
|
||||
|
||||
def drawBackground(self, painter: QtGui.QPainter, rect: QtCore.QRectF) -> None:
|
||||
"""Draw curve grid and axis values."""
|
||||
# Flood fill background
|
||||
painter.setPen(QtCore.Qt.NoPen)
|
||||
painter.setBrush(QtCore.Qt.black)
|
||||
@@ -285,101 +397,41 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
if not self._curve_init:
|
||||
return
|
||||
|
||||
# Calculate grid rect
|
||||
curve_t, curve_b, curve_l, curve_r = (
|
||||
self._curve_rect.top(),
|
||||
self._curve_rect.bottom(),
|
||||
self._curve_rect.left(),
|
||||
self._curve_rect.right(),
|
||||
)
|
||||
|
||||
# Round to nearest 10 for grid bounds
|
||||
grid_t = curve_t // 10 * 10
|
||||
if grid_t > math.ceil(curve_t):
|
||||
grid_t -= 10
|
||||
grid_b = curve_b // 10 * 10
|
||||
if grid_b < math.floor(curve_b):
|
||||
grid_b += 10
|
||||
grid_l = curve_l // 10 * 10
|
||||
if grid_l > math.ceil(curve_l):
|
||||
grid_l -= 10
|
||||
grid_r = curve_r // 10 * 10
|
||||
if grid_r < math.floor(curve_r):
|
||||
grid_r += 10
|
||||
font = painter.font()
|
||||
font.setPixelSize(self.FONT_HEIGHT)
|
||||
painter.setFont(font)
|
||||
|
||||
text_pen = QtGui.QPen(GRAY_COLOR)
|
||||
|
||||
grid_pen = QtGui.QPen(GRAY_COLOR.darker(200))
|
||||
grid_pen.setWidthF(0)
|
||||
|
||||
font = painter.font()
|
||||
font.setPixelSize(self.FONT_HEIGHT)
|
||||
|
||||
painter.setPen(grid_pen)
|
||||
painter.setBrush(QtCore.Qt.NoBrush)
|
||||
painter.setFont(font)
|
||||
|
||||
# Calculate samples to display
|
||||
sample_step = math.ceil(self._sample_size / 10.0)
|
||||
min_x = max_x = min_y = max_y = None
|
||||
|
||||
if self._sample_type == SampleType.LINEAR:
|
||||
sample_x_values = self._samples_x_lin
|
||||
else: # SampleType.LOG
|
||||
sample_x_values = self._samples_x_log
|
||||
|
||||
sample_y_data = []
|
||||
for i, sample_y in enumerate(
|
||||
np.linspace(self._sample_y_min, self._sample_y_max, 11, dtype=np.float32)
|
||||
):
|
||||
pos_y = sample_y * self.CURVE_SCALE
|
||||
sample_y_data.append((pos_y, sample_y))
|
||||
|
||||
if min_y is None or pos_y < min_y:
|
||||
min_y = pos_y
|
||||
if max_y is None or pos_y > max_y:
|
||||
max_y = pos_y
|
||||
|
||||
sample_x_data = []
|
||||
for i, sample_x in enumerate(sample_x_values):
|
||||
if not (i % sample_step == 0 or i == self._sample_size - 1):
|
||||
continue
|
||||
|
||||
pos_x = self._samples_x_lin[i] * self.CURVE_SCALE
|
||||
sample_x_data.append((pos_x, sample_x))
|
||||
|
||||
if min_x is None or pos_x < min_x:
|
||||
min_x = pos_x
|
||||
if max_x is None or pos_x > max_x:
|
||||
max_x = pos_x
|
||||
|
||||
if min_x is None:
|
||||
min_x = grid_l
|
||||
if max_x is None:
|
||||
max_x = grid_r
|
||||
if min_y is None:
|
||||
min_y = grid_t
|
||||
if max_x is None:
|
||||
max_y = grid_b
|
||||
|
||||
self._sample_rect = QtCore.QRectF(
|
||||
max_x + 5, min_y, 40, len(self._curve_items) * 20
|
||||
)
|
||||
# Draw grid border
|
||||
painter.drawRect(self._curve_rect)
|
||||
|
||||
# Draw grid rows
|
||||
y_text_origin = QtGui.QTextOption(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
y_text_origin.setWrapMode(QtGui.QTextOption.NoWrap)
|
||||
|
||||
for pos_y, sample_y in sample_y_data:
|
||||
painter.setPen(grid_pen)
|
||||
painter.drawLine(QtCore.QLineF(min_x, pos_y, max_x, pos_y))
|
||||
for i, y in enumerate(
|
||||
np.linspace(self._y_min, self._y_max, 11, dtype=np.float32)
|
||||
):
|
||||
p1 = self._curve_tf.map(QtCore.QPointF(self._x_min, y))
|
||||
p2 = self._curve_tf.map(QtCore.QPointF(self._x_max, y))
|
||||
|
||||
if pos_y > grid_t:
|
||||
label_value = round(sample_y, 2)
|
||||
if self._y_min < y < self._y_max:
|
||||
painter.setPen(grid_pen)
|
||||
painter.drawLine(QtCore.QLineF(p1, p2))
|
||||
|
||||
if y > self._y_min:
|
||||
label_value = round(y, 2)
|
||||
if label_value == 0.0:
|
||||
label_value = abs(label_value)
|
||||
|
||||
painter.save()
|
||||
painter.translate(QtCore.QPointF(min_x, pos_y))
|
||||
painter.translate(p1)
|
||||
painter.scale(1, -1)
|
||||
painter.setPen(text_pen)
|
||||
painter.drawText(
|
||||
@@ -391,28 +443,39 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
x_text_origin = QtGui.QTextOption(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||
x_text_origin.setWrapMode(QtGui.QTextOption.NoWrap)
|
||||
|
||||
for pos_x, sample_x in sample_x_data:
|
||||
painter.setPen(grid_pen)
|
||||
painter.drawLine(QtCore.QLineF(pos_x, min_y, pos_x, max_y))
|
||||
sample_step = math.ceil(self._sample_count / 10.0)
|
||||
|
||||
if pos_x > grid_l:
|
||||
for i, x in enumerate(self._x_lin):
|
||||
if not (i % sample_step == 0 or i == self._sample_count - 1):
|
||||
continue
|
||||
|
||||
p1 = self._curve_tf.map(QtCore.QPointF(x, self._y_min))
|
||||
p2 = self._curve_tf.map(QtCore.QPointF(x, self._y_max))
|
||||
|
||||
if self._x_min < x < self._x_max:
|
||||
painter.setPen(grid_pen)
|
||||
painter.drawLine(QtCore.QLineF(p1, p2))
|
||||
|
||||
if x > self._x_min:
|
||||
label_value = round(
|
||||
sample_x, 5 if self._sample_type == SampleType.LOG else 2
|
||||
x if self._sample_type == SampleType.LINEAR else self._x_log[i],
|
||||
2 if self._sample_type == SampleType.LINEAR else 5,
|
||||
)
|
||||
if label_value == 0.0:
|
||||
label_value = abs(label_value)
|
||||
|
||||
painter.save()
|
||||
painter.translate(QtCore.QPointF(pos_x, min_y))
|
||||
painter.translate(p1)
|
||||
painter.scale(1, -1)
|
||||
painter.rotate(90)
|
||||
painter.setPen(text_pen)
|
||||
painter.drawText(
|
||||
QtCore.QRect(2.5 + 1, -10, 40, 20), str(label_value), x_text_origin
|
||||
QtCore.QRectF(2.5 + 1, -10, 40, 20), str(label_value), x_text_origin
|
||||
)
|
||||
painter.restore()
|
||||
|
||||
def drawForeground(self, painter: QtGui.QPainter, rect: QtCore.QRectF) -> None:
|
||||
"""Draw nearest sample point and coordinates."""
|
||||
if not self._curve_init:
|
||||
return
|
||||
|
||||
@@ -436,16 +499,18 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
painter.setBrush(QtGui.QColor(color_name))
|
||||
|
||||
painter.drawEllipse(
|
||||
QtCore.QPointF(
|
||||
nearest_sample[1] * self.CURVE_SCALE,
|
||||
nearest_sample[2] * self.CURVE_SCALE,
|
||||
self._curve_tf.map(
|
||||
QtCore.QPointF(
|
||||
nearest_sample[1],
|
||||
nearest_sample[2],
|
||||
)
|
||||
),
|
||||
1.25,
|
||||
1.25,
|
||||
1.5,
|
||||
1.5,
|
||||
)
|
||||
|
||||
# Draw sample values
|
||||
if sample_l is not None:
|
||||
# Draw sample values
|
||||
painter.setBrush(QtCore.Qt.NoBrush)
|
||||
|
||||
x_label_value = f"{nearest_sample[0]:.05f}"
|
||||
@@ -461,27 +526,56 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
|
||||
if color_name == GRAY_COLOR.name():
|
||||
palette = self.palette()
|
||||
painter.setPen(palette.color(palette.Text))
|
||||
painter.setPen(palette.color(palette.ColorRole.Text))
|
||||
else:
|
||||
painter.setPen(QtGui.QColor(color_name))
|
||||
|
||||
painter.drawText(
|
||||
QtCore.QRectF(5, -20, 35, 10), x_label_value, text_origin
|
||||
)
|
||||
painter.drawText(
|
||||
QtCore.QRectF(5, -10, 35, 10), y_label_value, text_origin
|
||||
)
|
||||
|
||||
painter.restore()
|
||||
|
||||
def _invalidate(self) -> None:
|
||||
"""Force repaint of visible region of graphics scene."""
|
||||
self._scene.invalidate(QtCore.QRectF(self.visibleRegion().boundingRect()))
|
||||
|
||||
def _update_curves(self) -> None:
|
||||
"""
|
||||
Update X-axis samples and rebuild curves from any cached
|
||||
processor.
|
||||
"""
|
||||
self._update_x_samples()
|
||||
if self._prev_cpu_proc is not None:
|
||||
self._on_cpu_processor_ready(self._prev_cpu_proc)
|
||||
|
||||
def _update_x_samples(self):
|
||||
"""
|
||||
Update linear and log X-axis samples from input and sample
|
||||
parameters.
|
||||
"""
|
||||
self._x_lin = np.linspace(
|
||||
self._input_min, self._input_max, self._sample_count, dtype=np.float32
|
||||
)
|
||||
|
||||
log_min = math.log(max(self.EPSILON, self._input_min))
|
||||
log_max = max(log_min + 0.00001, math.log(self._input_max, self._log_base))
|
||||
self._x_log = np.logspace(
|
||||
log_min, log_max, self._sample_count, base=self._log_base, dtype=np.float32
|
||||
)
|
||||
|
||||
self._x_min = self._x_lin.min()
|
||||
self._x_max = self._x_lin.max()
|
||||
|
||||
def _fit(self) -> None:
|
||||
"""Fit and center graph."""
|
||||
if not self._curve_init:
|
||||
return
|
||||
|
||||
# Use font metrics to calculate text padding, based on estimated maximum
|
||||
# number lengths.
|
||||
font = self.font()
|
||||
font.setPixelSize(self.FONT_HEIGHT)
|
||||
fm = QtGui.QFontMetrics(font)
|
||||
@@ -503,29 +597,15 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
|
||||
fit_rect = self._curve_rect.adjusted(-pad_l, -pad_t, pad_r, pad_b)
|
||||
|
||||
# Fit and center on calculated rectangle
|
||||
self.fitInView(fit_rect, QtCore.Qt.KeepAspectRatio)
|
||||
self.centerOn(fit_rect.center())
|
||||
self.update()
|
||||
|
||||
def _invalidate(self) -> None:
|
||||
self._scene.invalidate(QtCore.QRectF(self.visibleRegion().boundingRect()))
|
||||
|
||||
def _update_x_samples(self):
|
||||
self._samples_x_lin = np.linspace(
|
||||
self._input_min, self._input_max, self._sample_size, dtype=np.float32
|
||||
)
|
||||
self._samples_x_log = np.logspace(
|
||||
math.log(max(self.LOG_EPSILON, self._input_min)),
|
||||
math.log(max(self.LOG_EPSILON, self._input_max)),
|
||||
self._sample_size,
|
||||
base=self._log_base,
|
||||
dtype=np.float32,
|
||||
)
|
||||
|
||||
@QtCore.Slot(ocio.CPUProcessor)
|
||||
def _on_cpu_processor_ready(self, cpu_proc: ocio.CPUProcessor) -> None:
|
||||
"""
|
||||
Update curves from OCIO CPU processor.
|
||||
Update curves from sampled OCIO CPU processor.
|
||||
|
||||
:param cpu_proc: CPU processor of currently viewed transform
|
||||
"""
|
||||
@@ -535,12 +615,12 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
|
||||
# Get input samples
|
||||
if self._sample_type == SampleType.LOG:
|
||||
samples = self._samples_x_log
|
||||
x_samples = self._x_log
|
||||
else: # LINEAR
|
||||
samples = self._samples_x_lin
|
||||
x_samples = self._x_lin
|
||||
|
||||
# Interleave samples per channel
|
||||
rgb_samples = np.repeat(samples, 3)
|
||||
rgb_samples = np.repeat(x_samples, 3)
|
||||
|
||||
# Apply processor to samples
|
||||
cpu_proc.applyRGB(rgb_samples)
|
||||
@@ -550,28 +630,21 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
g_samples = rgb_samples[1::3]
|
||||
b_samples = rgb_samples[2::3]
|
||||
|
||||
# Build painter path from sample data
|
||||
if np.array_equal(r_samples, g_samples) and np.array_equal(
|
||||
r_samples, b_samples
|
||||
# Collect sample pairs and min/max Y sample values
|
||||
if np.allclose(r_samples, g_samples, atol=self.EPSILON) and np.allclose(
|
||||
r_samples, b_samples, atol=self.EPSILON
|
||||
):
|
||||
palette = self.palette()
|
||||
color_name = palette.color(palette.Text).name()
|
||||
color_name = palette.color(palette.ColorRole.Text).name()
|
||||
|
||||
self._samples[color_name] = np.dstack((self._samples_x_lin, r_samples))
|
||||
self._sample_y_min = r_samples.min()
|
||||
self._sample_y_max = r_samples.max()
|
||||
self._samples[color_name] = np.stack((self._x_lin, r_samples), axis=-1)
|
||||
|
||||
curve = QtGui.QPainterPath(
|
||||
QtCore.QPointF(self._samples_x_lin[0], r_samples[0])
|
||||
)
|
||||
curve.reserve(samples.size)
|
||||
for i in range(1, samples.size):
|
||||
curve.lineTo(QtCore.QPointF(self._samples_x_lin[i], r_samples[i]))
|
||||
self._curve_paths[color_name] = curve
|
||||
self._y_min = r_samples.min()
|
||||
self._y_max = r_samples.max()
|
||||
|
||||
else:
|
||||
sample_y_min = None
|
||||
sample_y_max = None
|
||||
y_min = None
|
||||
y_max = None
|
||||
|
||||
for i, (color, channel_samples) in enumerate(
|
||||
[
|
||||
@@ -582,43 +655,71 @@ class CurveView(QtWidgets.QGraphicsView):
|
||||
):
|
||||
color_name = color.name()
|
||||
|
||||
self._samples[color_name] = np.dstack(
|
||||
(self._samples_x_lin, channel_samples)
|
||||
self._samples[color_name] = np.stack(
|
||||
(self._x_lin, channel_samples), axis=-1
|
||||
)
|
||||
|
||||
channel_sample_y_min = channel_samples.min()
|
||||
if sample_y_min is None or channel_sample_y_min < sample_y_min:
|
||||
sample_y_min = channel_sample_y_min
|
||||
channel_sample_y_max = channel_samples.max()
|
||||
if sample_y_max is None or channel_sample_y_max > sample_y_max:
|
||||
sample_y_max = channel_sample_y_max
|
||||
channel_y_min = channel_samples.min()
|
||||
if y_min is None or channel_y_min < y_min:
|
||||
y_min = channel_y_min
|
||||
channel_y_max = channel_samples.max()
|
||||
if y_max is None or channel_y_max > y_max:
|
||||
y_max = channel_y_max
|
||||
|
||||
curve = QtGui.QPainterPath(
|
||||
QtCore.QPointF(self._samples_x_lin[0], channel_samples[0])
|
||||
self._y_min = y_min
|
||||
self._y_max = y_max
|
||||
|
||||
# Transform to scale/translate curve so that it fits in a square and
|
||||
# has its origin at (0, 0).
|
||||
curve_tf = QtGui.QTransform()
|
||||
curve_tf.translate(-self._x_min, -self._y_min)
|
||||
curve_tf.scale(
|
||||
self.CURVE_SCALE / (self._x_max - self._x_min),
|
||||
self.CURVE_SCALE / (self._y_max - self._y_min),
|
||||
)
|
||||
self._curve_tf = curve_tf
|
||||
self._curve_tf_inv, ok = curve_tf.inverted()
|
||||
|
||||
# Curve square
|
||||
self._curve_rect = QtCore.QRectF(
|
||||
self._curve_tf.map(QtCore.QPointF(self._x_min, self._y_min)),
|
||||
self._curve_tf.map(QtCore.QPointF(self._x_max, self._y_max)),
|
||||
)
|
||||
|
||||
# Sample box rect
|
||||
self._sample_rect = QtCore.QRectF(
|
||||
self._curve_rect.right() + 5,
|
||||
self._curve_rect.top(),
|
||||
40,
|
||||
len(self._samples) * 20,
|
||||
)
|
||||
|
||||
# Build painter paths that fit in square from sample data
|
||||
for color_name, channel_samples in self._samples.items():
|
||||
curve = QtGui.QPainterPath(
|
||||
self._curve_tf.map(
|
||||
QtCore.QPointF(channel_samples[0][0], channel_samples[0][1])
|
||||
)
|
||||
curve.reserve(samples.size)
|
||||
for j in range(1, samples.size):
|
||||
curve.lineTo(
|
||||
QtCore.QPointF(self._samples_x_lin[j], channel_samples[j])
|
||||
)
|
||||
curve.reserve(channel_samples.shape[0])
|
||||
for i in range(1, channel_samples.shape[0]):
|
||||
curve.lineTo(
|
||||
self._curve_tf.map(
|
||||
QtCore.QPointF(channel_samples[i][0], channel_samples[i][1])
|
||||
)
|
||||
self._curve_paths[color_name] = curve
|
||||
|
||||
self._sample_y_min = sample_y_min
|
||||
self._sample_y_max = sample_y_max
|
||||
)
|
||||
self._curve_paths[color_name] = curve
|
||||
|
||||
# Add curve(s) to scene
|
||||
self._curve_rect = QtCore.QRectF()
|
||||
for color_name, curve in self._curve_paths.items():
|
||||
pen = QtGui.QPen()
|
||||
pen.setColor(QtGui.QColor(color_name))
|
||||
pen.setWidthF(0)
|
||||
pen.setWidthF(0.5)
|
||||
|
||||
curve_item = self._scene.addPath(
|
||||
curve, pen, QtGui.QBrush(QtCore.Qt.NoBrush)
|
||||
)
|
||||
curve_item.setScale(self.CURVE_SCALE)
|
||||
self._curve_items[color_name] = curve_item
|
||||
self._curve_rect = self._curve_rect.united(curve_item.sceneBoundingRect())
|
||||
|
||||
self._curve_init = True
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..log_handlers import set_logging_level
|
||||
from ..message_router import MessageRouter
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from .inspect.curve_inspector import CurveInspector
|
||||
from .inspect import LogInspector, CodeInspector
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..widgets import ItemModelListWidget
|
||||
from ..utils import get_glyph_icon
|
||||
|
||||
@@ -5,7 +5,7 @@ from dataclasses import dataclass
|
||||
from typing import Any, Callable, Optional, Type
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..undo import ConfigSnapshotUndoCommand
|
||||
@@ -87,7 +87,7 @@ class BaseActiveDisplayViewModel(BaseConfigItemModel):
|
||||
|
||||
def _get_undo_command_type(
|
||||
self, column_desc: ColumnDesc
|
||||
) -> Type[QtWidgets.QUndoCommand]:
|
||||
) -> Type[QtGui.QUndoCommand]:
|
||||
if column_desc == self.ACTIVE:
|
||||
# Changing check state of the ACTIVE column has side effects related to
|
||||
# display/view order, so a config snapshot is needed to revert the change.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
import PyOpenColorIO as ocio
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
|
||||
@@ -5,7 +5,7 @@ import copy
|
||||
from typing import Any, Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..ref_space_manager import ReferenceSpaceManager
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..constants import MARGIN_WIDTH
|
||||
from ..transform_manager import TransformManager
|
||||
@@ -47,7 +47,7 @@ class BaseConfigItemParamEdit(QtWidgets.QWidget):
|
||||
|
||||
if self.__has_transforms__:
|
||||
self.__has_tabs__ = True
|
||||
no_tf_color = palette.color(palette.Disabled, palette.Text)
|
||||
no_tf_color = palette.color(palette.ColorGroup.Disabled, palette.ColorRole.Text)
|
||||
self._from_ref_icon = get_glyph_icon("mdi6.layers-plus")
|
||||
self._no_from_ref_icon = get_glyph_icon(
|
||||
"mdi6.layers-plus", color=no_tf_color
|
||||
|
||||
@@ -6,7 +6,7 @@ from dataclasses import dataclass
|
||||
from typing import Any, Optional, Type, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..transform_manager import TransformManager, TransformAgent
|
||||
@@ -587,7 +587,7 @@ class BaseConfigItemModel(QtCore.QAbstractTableModel):
|
||||
|
||||
def _get_undo_command_type(
|
||||
self, column_desc: ColumnDesc
|
||||
) -> Type[QtWidgets.QUndoCommand]:
|
||||
) -> Type[QtGui.QUndoCommand]:
|
||||
"""
|
||||
Support overriding the undo command type used to
|
||||
track data changes, per column.
|
||||
|
||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtWidgets
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
from ..constants import RGB
|
||||
from ..widgets import (
|
||||
|
||||
@@ -5,7 +5,7 @@ import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
import PyOpenColorIO as ocio
|
||||
|
||||
from .config_item_model import ColumnDesc, BaseConfigItemModel
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..widgets import CallbackComboBox
|
||||
@@ -34,7 +34,6 @@ class ColorSpaceDelegate(QtWidgets.QStyledItemDelegate):
|
||||
editor = CallbackComboBox(
|
||||
get_items=ConfigCache.get_color_space_names, editable=True, parent=parent
|
||||
)
|
||||
editor.setAutoCompletion(True)
|
||||
editor.completer().setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
|
||||
return editor
|
||||
|
||||
@@ -119,7 +118,6 @@ class RoleDelegate(QtWidgets.QStyledItemDelegate):
|
||||
raise NotImplementedError
|
||||
|
||||
widget = CallbackComboBox(get_items=get_items, editable=True, parent=parent)
|
||||
widget.setAutoCompletion(True)
|
||||
widget.completer().setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
|
||||
return widget
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from dataclasses import dataclass, field
|
||||
from typing import Any, Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import next_name
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..utils import get_glyph_icon
|
||||
from .active_display_view_edit import ActiveDisplayViewEdit
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import get_glyph_icon
|
||||
|
||||
@@ -6,7 +6,7 @@ from dataclasses import dataclass, field
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..undo import ConfigSnapshotUndoCommand
|
||||
|
||||
@@ -5,7 +5,7 @@ from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtWidgets
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..widgets import CallbackComboBox, TextEdit
|
||||
|
||||
@@ -5,7 +5,7 @@ import copy
|
||||
from typing import Any, Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..ref_space_manager import ReferenceSpaceManager
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import get_glyph_icon
|
||||
|
||||
@@ -5,7 +5,7 @@ import copy
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import get_glyph_icon
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtGui, QtWidgets
|
||||
from PySide6 import QtGui, QtWidgets
|
||||
|
||||
from ..widgets import ItemModelTableWidget
|
||||
from .delegates import RoleDelegate
|
||||
|
||||
@@ -5,7 +5,7 @@ from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from .config_item_model import ColumnDesc, BaseConfigItemModel
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from ..utils import get_glyph_icon
|
||||
from .file_rule_edit import FileRuleEdit
|
||||
|
||||
@@ -5,7 +5,7 @@ from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtWidgets
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..widgets import CallbackComboBox, LineEdit
|
||||
|
||||
@@ -6,7 +6,7 @@ from dataclasses import dataclass, field
|
||||
from typing import Any, Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from .config_item_model import ColumnDesc, BaseConfigItemModel
|
||||
|
||||
@@ -5,7 +5,7 @@ from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..transform_manager import TransformManager
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..ref_space_manager import ReferenceSpaceManager
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
from PySide6 import QtWidgets
|
||||
import PyOpenColorIO as ocio
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
|
||||
@@ -5,7 +5,7 @@ import copy
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import get_enum_member, get_glyph_icon
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import get_glyph_icon
|
||||
|
||||
@@ -7,7 +7,7 @@ from dataclasses import dataclass, field
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..undo import ConfigSnapshotUndoCommand
|
||||
|
||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from .config_cache import ConfigCache
|
||||
from .config_dock import ConfigDock
|
||||
|
||||
@@ -10,7 +10,7 @@ from typing import Any, Optional
|
||||
from queue import Empty, SimpleQueue
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from .utils import config_to_html, processor_to_ctf_html, processor_to_shader_html
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright Contributors to the OpenColorIO Project.
|
||||
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
|
||||
settings = QtCore.QSettings(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide2 import QtGui, QtWidgets
|
||||
from PySide6 import QtGui, QtWidgets
|
||||
|
||||
from .constants import (
|
||||
BORDER_COLOR_ROLE,
|
||||
|
||||
@@ -7,7 +7,7 @@ from functools import partial
|
||||
from typing import Callable, Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtGui
|
||||
from PySide6 import QtCore, QtGui
|
||||
|
||||
from .utils import get_glyph_icon
|
||||
|
||||
@@ -99,12 +99,15 @@ class TransformManager:
|
||||
tf_agent.item_tf_changed.connect(partial(cls._on_item_tf_changed, slot))
|
||||
cls._tf_subscriptions[slot] = tf_subscription
|
||||
|
||||
# Trigger immediate update to subscribers
|
||||
# Inform menu subscribers of the menu change
|
||||
cls._update_menu_items()
|
||||
cls._on_item_tf_changed(
|
||||
slot,
|
||||
*item_model.get_item_transforms(item_name),
|
||||
)
|
||||
|
||||
# Inform init subscribers of the new subscription
|
||||
for init_callback in cls._tf_subscribers.get(-1, []):
|
||||
init_callback(slot)
|
||||
|
||||
# Trigger immediate update to subscribers of this slot
|
||||
cls._on_item_tf_changed(slot, *item_model.get_item_transforms(item_name))
|
||||
|
||||
# Repaint views for previous and new model
|
||||
if prev_item_model is not None:
|
||||
@@ -206,10 +209,27 @@ class TransformManager:
|
||||
menu_callback(cls.get_subscription_menu_items())
|
||||
|
||||
@classmethod
|
||||
def subscribe_to_transforms(cls, slot: int, tf_callback: Callable) -> None:
|
||||
def subscribe_to_transform_subscription_init(cls, init_callback: Callable) -> None:
|
||||
"""
|
||||
Subscribe to transform and item name updates at the given slot
|
||||
number.
|
||||
Subscribe to transform subscription initialization on all slots.
|
||||
|
||||
:param init_callback: Transform subscription initialization
|
||||
callback, which will be called whenever a new transform
|
||||
subscription is initialized with the subscription slot
|
||||
number.
|
||||
"""
|
||||
cls._tf_subscribers[-1].append(init_callback)
|
||||
|
||||
# Trigger immediate update to init subscriber if a transform subscription
|
||||
# exists.
|
||||
for slot, tf_subscription in cls._tf_subscriptions.items():
|
||||
init_callback(slot)
|
||||
break
|
||||
|
||||
@classmethod
|
||||
def subscribe_to_transforms_at(cls, slot: int, tf_callback: Callable) -> None:
|
||||
"""
|
||||
Subscribe to transform updates at the given slot number.
|
||||
|
||||
:param slot: Subscription slot number
|
||||
:param tf_callback: Transform callback, which will be called
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..widgets import EnumComboBox, FloatEdit, FloatEditArray
|
||||
from .transform_edit import BaseTransformEdit
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..widgets import ComboBox
|
||||
from .transform_edit import BaseTransformEdit
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..constants import RGB
|
||||
from ..widgets import EnumComboBox, FloatEdit, FloatEditArray
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..widgets import CheckBox, CallbackComboBox
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..config_cache import ConfigCache
|
||||
from ..utils import SignalsBlocked
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..constants import RGBA
|
||||
from ..widgets import EnumComboBox, FloatEditArray
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..constants import RGBA
|
||||
from ..widgets import EnumComboBox, FloatEditArray
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..widgets import EnumComboBox, FloatEdit
|
||||
from .transform_edit import BaseTransformEdit
|
||||
|
||||
@@ -5,7 +5,7 @@ import os
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore
|
||||
from PySide6 import QtCore
|
||||
|
||||
from ..widgets import EnumComboBox, LineEdit
|
||||
from .transform_edit import BaseTransformEdit
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import PyOpenColorIO as ocio
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from ..widgets import EnumComboBox, FloatEditArray, ExpandingStackedWidget
|
||||
from .transform_edit import BaseTransformEdit
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user