Skip to content

Commit 7775b2f

Browse files
authored
Merge branch 'AcademySoftwareFoundation:main' into CUDA
2 parents ee11629 + ae04b6e commit 7775b2f

File tree

26 files changed

+440
-28
lines changed

26 files changed

+440
-28
lines changed

.github/workflows/build-steps.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ jobs:
9595
container:
9696
image: ${{ inputs.container }}
9797
volumes: ${{ fromJson( inputs.container_volumes ) }}
98+
options: -v /:/host/root ${{ (contains(inputs.runner, 'gpu') && '-e NVIDIA_DRIVER_CAPABILITIES=compute,graphics,utility --gpus all') || '-e A=x' }}
99+
# Extra options:
100+
# - Ensure the GPU runners have OptiX is visible in the container.
101+
# - Mount the native filesystem under /host/root
98102
env:
99103
CXX: ${{inputs.cxx_compiler}}
100104
CC: ${{inputs.cc_compiler}}

src/build-scripts/gh-installdeps.bash

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77

88

99
set -ex
10-
df -h
10+
11+
# Make extra space on the runners
12+
df -h .
13+
time rm -rf /usr/local/lib/android /host/root/usr/local/lib/android &
14+
sleep 3
15+
# rather than block, delete in background, but give it a few secs to start
16+
# clearing things out before moving on.
17+
# Other candidates, if we need it: /usr/share/dotnet /usr/local/.ghcup
1118

1219

1320
#
@@ -219,7 +226,8 @@ if [[ "$USE_ICC" != "" ]] ; then
219226
export CC=icc
220227
fi
221228

222-
df -h
229+
df -h .
230+
df -h /host/root || true
223231

224232
# Save the env for use by other stages
225233
src/build-scripts/save-env.bash

src/doc/pythonbindings.rst

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3888,6 +3888,73 @@ sections) work with deep inputs::
38883888
38893889
|
38903890
3891+
.. _sec-pythoncolorconfig:
3892+
3893+
3894+
ColorConfig
3895+
===========
3896+
3897+
The `ColorConfig` class that represents the set of color transformations that
3898+
are allowed.
3899+
3900+
If OpenColorIO is enabled at build time, this configuration is loaded at
3901+
runtime, allowing the user to have complete control of all color transformation
3902+
math. See the
3903+
`OpenColorIO documentation <https://opencolorio.readthedocs.io>`_ for details.
3904+
3905+
If OpenColorIO is not enabled at build time, a generic color configuration
3906+
is provided for minimal color support.
3907+
3908+
..
3909+
TODO: The documentation for this class is incomplete.
3910+
3911+
.. py:method:: get_cicp (colorspace)
3912+
3913+
Find CICP code corresponding to the colorspace.
3914+
Return a sequence of 4 ints, or None if not found.
3915+
3916+
Example:
3917+
3918+
.. code-block:: python
3919+
3920+
colorconfig = oiio.ColorConfig()
3921+
cicp = colorconfig.get_cicp("pq_rec2020_display")
3922+
if cicp:
3923+
primaries, transfer, matrix, color_range = cicp
3924+
3925+
This function was added in OpenImageIO 3.1.
3926+
3927+
3928+
.. py:method:: get_color_interop_id (colorspace)
3929+
3930+
Find color interop ID for the given colorspace.
3931+
Returns empty string if not found.
3932+
3933+
Example:
3934+
3935+
.. code-block:: python
3936+
3937+
colorconfig = oiio.ColorConfig()
3938+
interop_id = colorconfig.get_color_interop_id("Rec.2100-PQ - Display")
3939+
3940+
This function was added in OpenImageIO 3.1.
3941+
3942+
3943+
.. py:method:: get_color_interop_id (cicp)
3944+
3945+
Find color interop ID corresponding to the CICP code.
3946+
Returns empty string if not found.
3947+
3948+
Example:
3949+
3950+
.. code-block:: python
3951+
3952+
colorconfig = oiio.ColorConfig()
3953+
interop_id = colorconfig.get_color_interop_id([9, 16, 9, 1])
3954+
3955+
This function was added in OpenImageIO 3.1.
3956+
3957+
38913958
.. _sec-pythonmiscapi:
38923959
38933960
Miscellaneous Utilities

src/ffmpeg.imageio/ffmpeginput.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ receive_frame(AVCodecContext* avctx, AVFrame* picture, AVPacket* avpkt)
7171

7272

7373

74+
#include <OpenImageIO/color.h>
7475
#include <OpenImageIO/imageio.h>
7576
#include <iostream>
7677
#include <mutex>
@@ -549,6 +550,11 @@ FFmpegInput::open(const std::string& name, ImageSpec& spec)
549550
m_codec_context->colorspace,
550551
m_codec_context->color_range == AVCOL_RANGE_MPEG ? 0 : 1 };
551552
m_spec.attribute("CICP", TypeDesc(TypeDesc::INT, 4), cicp);
553+
const ColorConfig& colorconfig(ColorConfig::default_colorconfig());
554+
string_view interop_id = colorconfig.get_color_interop_id(cicp);
555+
if (!interop_id.empty())
556+
m_spec.attribute("oiio:ColorSpace", interop_id);
557+
552558
m_nsubimages = m_frames;
553559
spec = m_spec;
554560
m_filename = name;

src/heif.imageio/heifinput.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// https://github.com/AcademySoftwareFoundation/OpenImageIO
44

5+
#include <OpenImageIO/color.h>
56
#include <OpenImageIO/filesystem.h>
67
#include <OpenImageIO/fmath.h>
78
#include <OpenImageIO/imageio.h>
@@ -292,6 +293,11 @@ HeifInput::seek_subimage(int subimage, int miplevel)
292293
int(nclx->matrix_coefficients),
293294
int(nclx->full_range_flag ? 1 : 0) };
294295
m_spec.attribute("CICP", TypeDesc(TypeDesc::INT, 4), cicp);
296+
const ColorConfig& colorconfig(
297+
ColorConfig::default_colorconfig());
298+
string_view interop_id = colorconfig.get_color_interop_id(cicp);
299+
if (!interop_id.empty())
300+
m_spec.attribute("oiio:ColorSpace", interop_id);
295301
}
296302
heif_nclx_color_profile_free(nclx);
297303
}

src/heif.imageio/heifoutput.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// https://github.com/AcademySoftwareFoundation/OpenImageIO
44

55

6+
#include <OpenImageIO/color.h>
67
#include <OpenImageIO/filesystem.h>
78
#include <OpenImageIO/fmath.h>
89
#include <OpenImageIO/imageio.h>
@@ -249,10 +250,13 @@ HeifOutput::close()
249250
std::unique_ptr<heif_color_profile_nclx,
250251
void (*)(heif_color_profile_nclx*)>
251252
nclx(heif_nclx_color_profile_alloc(), heif_nclx_color_profile_free);
252-
const ParamValue* p = m_spec.find_attribute("CICP",
253-
TypeDesc(TypeDesc::INT, 4));
254-
if (p) {
255-
const int* cicp = static_cast<const int*>(p->data());
253+
const ColorConfig& colorconfig(ColorConfig::default_colorconfig());
254+
const ParamValue* p = m_spec.find_attribute("CICP",
255+
TypeDesc(TypeDesc::INT, 4));
256+
string_view colorspace = m_spec.get_string_attribute("oiio:ColorSpace");
257+
cspan<int> cicp = (p) ? p->as_cspan<int>()
258+
: colorconfig.get_cicp(colorspace);
259+
if (!cicp.empty()) {
256260
nclx->color_primaries = heif_color_primaries(cicp[0]);
257261
nclx->transfer_characteristics = heif_transfer_characteristics(
258262
cicp[1]);

src/include/OpenImageIO/color.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,24 @@ class OIIO_API ColorConfig {
402402
bool equivalent(string_view color_space,
403403
string_view other_color_space) const;
404404

405+
/// Find CICP code corresponding to the colorspace.
406+
/// Return a cspan of 4 ints, or an empty span if not found.
407+
///
408+
/// @version 3.1
409+
cspan<int> get_cicp(string_view colorspace) const;
410+
411+
/// Find color interop ID for the given colorspace.
412+
/// Returns empty string if not found.
413+
///
414+
/// @version 3.1
415+
string_view get_color_interop_id(string_view colorspace) const;
416+
417+
/// Find color interop ID corresponding to the CICP code.
418+
/// Returns empty string if not found.
419+
///
420+
/// @version 3.1
421+
string_view get_color_interop_id(const int cicp[4]) const;
422+
405423
/// Return a filename or other identifier for the config we're using.
406424
std::string configname() const;
407425

src/libOpenImageIO/color_ocio.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,173 @@ ColorConfig::parseColorSpaceFromString(string_view str) const
19971997
}
19981998

19991999

2000+
//////////////////////////////////////////////////////////////////////////
2001+
//
2002+
// Color Interop ID
2003+
2004+
namespace {
2005+
enum class CICPPrimaries : int {
2006+
Rec709 = 1,
2007+
Rec2020 = 9,
2008+
XYZD65 = 10,
2009+
P3D65 = 12,
2010+
};
2011+
2012+
enum class CICPTransfer : int {
2013+
BT709 = 1,
2014+
Gamma22 = 4,
2015+
Linear = 8,
2016+
sRGB = 13,
2017+
PQ = 16,
2018+
Gamma26 = 17,
2019+
HLG = 18,
2020+
};
2021+
2022+
enum class CICPMatrix : int {
2023+
RGB = 0,
2024+
BT709 = 1,
2025+
Unspecified = 2,
2026+
Rec2020_NCL = 9,
2027+
Rec2020_CL = 10,
2028+
};
2029+
2030+
enum class CICPRange : int {
2031+
Narrow = 0,
2032+
Full = 1,
2033+
};
2034+
2035+
struct ColorInteropID {
2036+
constexpr ColorInteropID(const char* interop_id)
2037+
: interop_id(interop_id)
2038+
, cicp({ 0, 0, 0, 0 })
2039+
, has_cicp(false)
2040+
{
2041+
}
2042+
2043+
constexpr ColorInteropID(const char* interop_id, CICPPrimaries primaries,
2044+
CICPTransfer transfer, CICPMatrix matrix)
2045+
: interop_id(interop_id)
2046+
, cicp({ int(primaries), int(transfer), int(matrix),
2047+
int(CICPRange::Full) })
2048+
, has_cicp(true)
2049+
{
2050+
}
2051+
2052+
const char* interop_id;
2053+
std::array<int, 4> cicp;
2054+
bool has_cicp;
2055+
};
2056+
2057+
// Mapping between color interop ID and CICP, based on Color Interop Forum
2058+
// recommendations.
2059+
constexpr ColorInteropID color_interop_ids[] = {
2060+
// Scene referred interop IDs first so they are the default in automatic
2061+
// conversion from CICP to interop ID. Some are not display color spaces
2062+
// at all, but can be represented by CICP anyway.
2063+
{ "lin_ap1_scene" },
2064+
{ "lin_ap0_scene" },
2065+
{ "lin_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::Linear,
2066+
CICPMatrix::BT709 },
2067+
{ "lin_p3d65_scene", CICPPrimaries::P3D65, CICPTransfer::Linear,
2068+
CICPMatrix::BT709 },
2069+
{ "lin_rec2020_scene", CICPPrimaries::Rec2020, CICPTransfer::Linear,
2070+
CICPMatrix::Rec2020_CL },
2071+
{ "lin_adobergb_scene" },
2072+
{ "lin_ciexyzd65_scene", CICPPrimaries::XYZD65, CICPTransfer::Linear,
2073+
CICPMatrix::Unspecified },
2074+
{ "srgb_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::sRGB,
2075+
CICPMatrix::BT709 },
2076+
{ "g22_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::Gamma22,
2077+
CICPMatrix::BT709 },
2078+
{ "g18_rec709_scene" },
2079+
{ "srgb_ap1_scene" },
2080+
{ "g22_ap1_scene" },
2081+
{ "srgb_p3d65_scene", CICPPrimaries::P3D65, CICPTransfer::sRGB,
2082+
CICPMatrix::BT709 },
2083+
{ "g22_adobergb_scene" },
2084+
{ "data" },
2085+
{ "unknown" },
2086+
2087+
// Display referred interop IDs.
2088+
{ "srgb_rec709_display", CICPPrimaries::Rec709, CICPTransfer::sRGB,
2089+
CICPMatrix::BT709 },
2090+
{ "g24_rec709_display", CICPPrimaries::Rec709, CICPTransfer::BT709,
2091+
CICPMatrix::BT709 },
2092+
{ "srgb_p3d65_display", CICPPrimaries::P3D65, CICPTransfer::sRGB,
2093+
CICPMatrix::BT709 },
2094+
{ "srgbe_p3d65_display", CICPPrimaries::P3D65, CICPTransfer::sRGB,
2095+
CICPMatrix::BT709 },
2096+
{ "pq_p3d65_display", CICPPrimaries::P3D65, CICPTransfer::PQ,
2097+
CICPMatrix::Rec2020_NCL },
2098+
{ "pq_rec2020_display", CICPPrimaries::Rec2020, CICPTransfer::PQ,
2099+
CICPMatrix::Rec2020_NCL },
2100+
{ "hlg_rec2020_display", CICPPrimaries::Rec2020, CICPTransfer::HLG,
2101+
CICPMatrix::Rec2020_NCL },
2102+
// No CICP mapping to keep previous behavior unchanged, as Gamma 2.2
2103+
// display is more likely meant to be written as sRGB. On read the
2104+
// scene referred interop ID will be used.
2105+
{ "g22_rec709_display",
2106+
/* CICPPrimaries::Rec709, CICPTransfer::Gamma22, CICPMatrix::BT709 */ },
2107+
// No CICP code for Adobe RGB primaries.
2108+
{ "g22_adobergb_display" },
2109+
{ "g26_p3d65_display", CICPPrimaries::P3D65, CICPTransfer::Gamma26,
2110+
CICPMatrix::BT709 },
2111+
{ "g26_xyzd65_display", CICPPrimaries::XYZD65, CICPTransfer::Gamma26,
2112+
CICPMatrix::Unspecified },
2113+
{ "pq_xyzd65_display", CICPPrimaries::XYZD65, CICPTransfer::PQ,
2114+
CICPMatrix::Unspecified },
2115+
};
2116+
} // namespace
2117+
2118+
string_view
2119+
ColorConfig::get_color_interop_id(string_view colorspace) const
2120+
{
2121+
if (colorspace.empty())
2122+
return "";
2123+
#if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 5, 0)
2124+
if (getImpl()->config_ && !disable_ocio) {
2125+
OCIO::ConstColorSpaceRcPtr c = getImpl()->config_->getColorSpace(
2126+
std::string(resolve(colorspace)).c_str());
2127+
const char* interop_id = (c) ? c->getInteropID() : nullptr;
2128+
if (interop_id) {
2129+
return interop_id;
2130+
}
2131+
}
2132+
#endif
2133+
for (const ColorInteropID& interop : color_interop_ids) {
2134+
if (equivalent(colorspace, interop.interop_id)) {
2135+
return interop.interop_id;
2136+
}
2137+
}
2138+
return "";
2139+
}
2140+
2141+
string_view
2142+
ColorConfig::get_color_interop_id(const int cicp[4]) const
2143+
{
2144+
for (const ColorInteropID& interop : color_interop_ids) {
2145+
if (interop.has_cicp && interop.cicp[0] == cicp[0]
2146+
&& interop.cicp[1] == cicp[1]) {
2147+
return interop.interop_id;
2148+
}
2149+
}
2150+
return "";
2151+
}
2152+
2153+
cspan<int>
2154+
ColorConfig::get_cicp(string_view colorspace) const
2155+
{
2156+
string_view interop_id = get_color_interop_id(colorspace);
2157+
if (!interop_id.empty()) {
2158+
for (const ColorInteropID& interop : color_interop_ids) {
2159+
if (interop.has_cicp && interop_id == interop.interop_id) {
2160+
return interop.cicp;
2161+
}
2162+
}
2163+
}
2164+
return cspan<int>();
2165+
}
2166+
20002167

20012168
//////////////////////////////////////////////////////////////////////////
20022169
//

src/libutil/filesystem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,15 @@ Filesystem::path_is_absolute(string_view path, bool dot_is_absolute)
330330
bool
331331
Filesystem::exists(string_view path) noexcept
332332
{
333+
#ifdef _WIN32
334+
// filesystem::exists is slow on Windows for network paths, so use the
335+
// WinAPI directly
336+
return INVALID_FILE_ATTRIBUTES
337+
!= GetFileAttributesW(Strutil::utf8_to_utf16wstring(path).c_str());
338+
#else
333339
error_code ec;
334340
return filesystem::exists(u8path(path), ec);
341+
#endif
335342
}
336343

337344

0 commit comments

Comments
 (0)