Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/bmp.imageio/bmpinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>

#include "imageio_pvt.h"

#include "bmp_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN
Expand Down Expand Up @@ -262,7 +264,8 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
// Default presumption is that a BMP file is meant to look reasonable on a
// display, so assume it's sRGB. This is not really correct -- see the
// comments below.
m_spec.attribute("oiio:ColorSpace", "srgb_rec709_scene");
const bool erase_other_attributes = false;
pvt::set_colorspace_srgb(m_spec, erase_other_attributes);
#if 0
if (m_dib_header.size >= WINDOWS_V4
&& m_dib_header.cs_type == CSType::CalibratedRGB) {
Expand Down
21 changes: 11 additions & 10 deletions src/dds.imageio/ddsinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <OpenImageIO/parallel.h>
#include <OpenImageIO/typedesc.h>

#include "imageio_pvt.h"

#include "dds_pvt.h"
#define BCDEC_IMPLEMENTATION
#include "bcdec.h"
Expand Down Expand Up @@ -828,7 +830,7 @@ DDSInput::seek_subimage(int subimage, int miplevel)
if (bpp != 0)
m_spec.attribute("oiio:BitsPerSample", bpp);

const char* colorspace = nullptr;
bool is_srgb = false;

if (m_dds.fmt.fourCC == DDS_4CC_DX10) {
switch (m_dx10.dxgiFormat) {
Expand All @@ -838,18 +840,17 @@ DDSInput::seek_subimage(int subimage, int miplevel)
case DDS_FORMAT_BC7_UNORM_SRGB:
case DDS_FORMAT_R8G8B8A8_UNORM_SRGB:
case DDS_FORMAT_B8G8R8A8_UNORM_SRGB:
case DDS_FORMAT_B8G8R8X8_UNORM_SRGB:
colorspace = "srgb_rec709_scene";
break;
case DDS_FORMAT_B8G8R8X8_UNORM_SRGB: is_srgb = true; break;
}
}

// linear color space for HDR-ish images
if (colorspace == nullptr
&& (basetype == TypeDesc::HALF || basetype == TypeDesc::FLOAT))
colorspace = "lin_rec709_scene";

m_spec.set_colorspace(colorspace);
if (is_srgb) {
pvt::set_colorspace_srgb(m_spec);
} else if (!is_srgb
&& (basetype == TypeDesc::HALF || basetype == TypeDesc::FLOAT)) {
// linear color space for HDR-ish images
m_spec.set_colorspace("lin_rec709_scene");
}

m_spec.default_channel_names();
// Special case: if a 2-channel DDS RG or YA?
Expand Down
6 changes: 4 additions & 2 deletions src/doc/stdmetadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,11 @@ Color information
- `"lin_ap1_scene"`, `"ACEScg"` : ACEScg color space encoding.
- `"lin_ap0_scene"` : ACES2065-1, the recommended ACES space for
interchange and archiving.
- `"srgb_rec709_scene"` : Using standard (piecewise) sRGB response and
- `"srgb_rec709_display"` : Using standard (piecewise) sRGB response and
primaries. The token `"sRGB"` is treated as a synonym.
- `"g22_rec709_scene"` : Rec709/sRGB primaries, but using a response curve
- `"srgb_rec709_scene"` : Same response and primaries as
`"srgb_rec709_display"` but for scene referred images.
- `"g22_rec709_display"` : Rec709/sRGB primaries, but using a response curve
corresponding to gamma 2.2.

Additionally, `"scene_linear"` is a role that is appropriate for color
Expand Down
4 changes: 3 additions & 1 deletion src/dpx.imageio/dpxinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <OpenImageIO/strutil.h>
#include <OpenImageIO/typedesc.h>

#include "imageio_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN


Expand Down Expand Up @@ -314,7 +316,7 @@ DPXInput::seek_subimage(int subimage, int miplevel)
switch (m_dpx.header.Transfer(subimage)) {
case dpx::kLinear: m_spec.set_colorspace("lin_rec709_scene"); break;
case dpx::kLogarithmic: m_spec.set_colorspace("KodakLog"); break;
case dpx::kITUR709: m_spec.set_colorspace("srgb_rec709_scene"); break;
case dpx::kITUR709: pvt::set_colorspace_srgb(m_spec); break;
case dpx::kUserDefined:
if (!std::isnan(m_dpx.header.Gamma()) && m_dpx.header.Gamma() != 0) {
set_colorspace_rec709_gamma(m_spec, float(m_dpx.header.Gamma()));
Expand Down
18 changes: 8 additions & 10 deletions src/dpx.imageio/dpxoutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <OpenImageIO/strutil.h>
#include <OpenImageIO/typedesc.h>

#include "imageio_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN


Expand Down Expand Up @@ -436,18 +438,14 @@ DPXOutput::prep_subimage(int s, bool allocate)
m_desc = get_image_descriptor();

// transfer function
const ColorConfig& colorconfig = ColorConfig::default_colorconfig();
std::string colorspace = spec_s.get_string_attribute("oiio:ColorSpace", "");
if (colorconfig.equivalent(colorspace, "lin_rec709_scene"))
m_transfer = dpx::kLinear;
else if (colorconfig.equivalent(colorspace, "srgb_rec709_scene"))
const float gamma = pvt::get_colorspace_rec709_gamma(spec_s);
if (pvt::is_colorspace_srgb(spec_s, false))
m_transfer = dpx::kITUR709;
else if (colorconfig.equivalent(colorspace, "g22_rec709_scene")
|| colorconfig.equivalent(colorspace, "g24_rec709_scene")
|| colorconfig.equivalent(colorspace, "g18_rec709_scene")
|| Strutil::istarts_with(colorspace, "Gamma"))
else if (gamma == 1.0f)
m_transfer = dpx::kLinear;
else if (gamma != 0.0f)
m_transfer = dpx::kUserDefined;
else if (colorconfig.equivalent(colorspace, "KodakLog"))
else if (spec_s.get_string_attribute("oiio:ColorSpace") == "KodakLog")
m_transfer = dpx::kLogarithmic;
else {
std::string dpxtransfer = spec_s.get_string_attribute("dpx:Transfer",
Expand Down
7 changes: 2 additions & 5 deletions src/ffmpeg.imageio/ffmpeginput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ receive_frame(AVCodecContext* avctx, AVFrame* picture, AVPacket* avpkt)



#include "imageio_pvt.h"
#include <OpenImageIO/color.h>
#include <OpenImageIO/imageio.h>
#include <iostream>
Expand Down Expand Up @@ -549,11 +550,7 @@ FFmpegInput::open(const std::string& name, ImageSpec& spec)
= { m_codec_context->color_primaries, m_codec_context->color_trc,
m_codec_context->colorspace,
m_codec_context->color_range == AVCOL_RANGE_MPEG ? 0 : 1 };
m_spec.attribute("CICP", TypeDesc(TypeDesc::INT, 4), cicp);
const ColorConfig& colorconfig(ColorConfig::default_colorconfig());
string_view interop_id = colorconfig.get_color_interop_id(cicp);
if (!interop_id.empty())
m_spec.attribute("oiio:ColorSpace", interop_id);
pvt::set_colorspace_cicp(m_spec, cicp);

m_nsubimages = m_frames;
spec = m_spec;
Expand Down
4 changes: 3 additions & 1 deletion src/gif.imageio/gifinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/thread.h>

#include "imageio_pvt.h"

// GIFLIB:
// http://giflib.sourceforge.net/
// Format description:
Expand Down Expand Up @@ -259,7 +261,7 @@ GIFInput::read_subimage_metadata(ImageSpec& newspec)
newspec.nchannels = 4;
newspec.default_channel_names();
newspec.alpha_channel = 4;
newspec.set_colorspace("srgb_rec709_scene");
pvt::set_colorspace_srgb(newspec);

m_previous_disposal_method = m_disposal_method;
m_disposal_method = DISPOSAL_UNSPECIFIED;
Expand Down
11 changes: 4 additions & 7 deletions src/heif.imageio/heifinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <OpenImageIO/platform.h>
#include <OpenImageIO/tiffutils.h>

#include "imageio_pvt.h"

#include <libheif/heif_cxx.h>

#define MAKE_LIBHEIF_VERSION(a, b, c, d) \
Expand Down Expand Up @@ -273,7 +275,7 @@ HeifInput::seek_subimage(int subimage, int miplevel)
if (m_bitdepth > 8) {
m_spec.attribute("oiio:BitsPerSample", m_bitdepth);
}
m_spec.set_colorspace("srgb_rec709_scene");
pvt::set_colorspace_srgb(m_spec);

#if LIBHEIF_HAVE_VERSION(1, 9, 0)
// Read CICP. Have to use the C API to get it from the image handle,
Expand All @@ -292,12 +294,7 @@ HeifInput::seek_subimage(int subimage, int miplevel)
int(nclx->transfer_characteristics),
int(nclx->matrix_coefficients),
int(nclx->full_range_flag ? 1 : 0) };
m_spec.attribute("CICP", TypeDesc(TypeDesc::INT, 4), cicp);
const ColorConfig& colorconfig(
ColorConfig::default_colorconfig());
string_view interop_id = colorconfig.get_color_interop_id(cicp);
if (!interop_id.empty())
m_spec.attribute("oiio:ColorSpace", interop_id);
pvt::set_colorspace_cicp(m_spec, cicp);
}
heif_nclx_color_profile_free(nclx);
}
Expand Down
9 changes: 3 additions & 6 deletions src/heif.imageio/heifoutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <OpenImageIO/platform.h>
#include <OpenImageIO/tiffutils.h>

#include "imageio_pvt.h"

#include <libheif/heif_cxx.h>

#define MAKE_LIBHEIF_VERSION(a, b, c, d) \
Expand Down Expand Up @@ -250,12 +252,7 @@ HeifOutput::close()
std::unique_ptr<heif_color_profile_nclx,
void (*)(heif_color_profile_nclx*)>
nclx(heif_nclx_color_profile_alloc(), heif_nclx_color_profile_free);
const ColorConfig& colorconfig(ColorConfig::default_colorconfig());
const ParamValue* p = m_spec.find_attribute("CICP",
TypeDesc(TypeDesc::INT, 4));
string_view colorspace = m_spec.get_string_attribute("oiio:ColorSpace");
cspan<int> cicp = (p) ? p->as_cspan<int>()
: colorconfig.get_cicp(colorspace);
cspan<int> cicp = pvt::get_colorspace_cicp(m_spec);
if (!cicp.empty()) {
nclx->color_primaries = heif_color_primaries(cicp[0]);
nclx->transfer_characteristics = heif_transfer_characteristics(
Expand Down
4 changes: 3 additions & 1 deletion src/iconvert/iconvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <OpenImageIO/strutil.h>
#include <OpenImageIO/sysutil.h>

#include "imageio_pvt.h"


using namespace OIIO;

Expand Down Expand Up @@ -224,7 +226,7 @@ adjust_spec(ImageInput* in, ImageOutput* out, const ImageSpec& inspec,
if (gammaval != 1.0f)
outspec.attribute("oiio:Gamma", gammaval);
if (sRGB) {
outspec.set_colorspace("srgb_rec709_scene");
pvt::set_colorspace_srgb(outspec);
if (!strcmp(in->format_name(), "jpeg")
|| outspec.find_attribute("Exif:ColorSpace"))
outspec.attribute("Exif:ColorSpace", 1);
Expand Down
6 changes: 5 additions & 1 deletion src/include/OpenImageIO/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,14 @@ class OIIO_API ColorConfig {
string_view get_color_interop_id(string_view colorspace) const;

/// Find color interop ID corresponding to the CICP code.
/// If prefer_image_state is set to "scene", prefer returning a scene
/// referred interop ID over a display referred interop ID if both exist.
/// Returns empty string if not found.
///
/// @version 3.1
string_view get_color_interop_id(const int cicp[4]) const;
string_view
get_color_interop_id(const int cicp[4],
string_view prefer_image_state = "display") const;

/// Return a filename or other identifier for the config we're using.
std::string configname() const;
Expand Down
12 changes: 11 additions & 1 deletion src/include/OpenImageIO/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -3843,6 +3843,17 @@ OIIO_API std::string geterror(bool clear = true);
/// For more information, please see OpenImageIO's documentation on the
/// built-in PNG format support.
///
/// - `string color:prefer_image_state` ("display")
///
/// When the color space of an image file is ambiguous and can be
/// interpreted as either a display referred or scene referred, by default
/// the `oiio:ColorSpace` attribute will be set to a display color space
/// like `srgb_rec709_display`.
///
/// By setting the preferred image state to "scene", the corresponding
/// scene referred color space like `srgb_rec709_scene` will be chosen
/// instead. For textures in particular this can be a better default guess.
///
/// - `int limits:channels` (1024)
///
/// When nonzero, the maximum number of color channels in an image. Image
Expand Down Expand Up @@ -4198,7 +4209,6 @@ OIIO_API void set_colorspace(ImageSpec& spec, string_view name);
/// @version 3.0
OIIO_API void set_colorspace_rec709_gamma(ImageSpec& spec, float gamma);


/// Are the two named color spaces equivalent, based on the default color
/// config in effect?
///
Expand Down
38 changes: 38 additions & 0 deletions src/include/imageio_pvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,44 @@ parallel_convert_from_float(const float* src, void* dst, size_t nvals,
OIIO_API bool
check_texture_metadata_sanity(ImageSpec& spec);

/// Set oiio:ColorSpace to the default sRGB colorspace, which may be display
/// or scene referred depending on configuration.
///
/// If erase_other_attributes is true, other potentially conflicting attributes
/// are erased.
OIIO_API void
set_colorspace_srgb(ImageSpec& spec, bool erase_other_attributes = true);

/// Returns true if for the purpose of interop, the spec's metadata
/// specifies a color space that should be encoded as sRGB.
///
/// If default_to_srgb is true, the colorspace will be assumed to
/// be sRGB if no colorspace was specified in the spec.
OIIO_API bool
is_colorspace_srgb(const ImageSpec& spec, bool default_to_srgb = true);

/// If the spec's metadata specifies a color space with Rec709 primaries and
/// gamma transfer function, return the gamma value. If not, return zero.
OIIO_API float
get_colorspace_rec709_gamma(const ImageSpec& spec);

// Returns ICC profile from the spec's metadata, either from an ICCProfile
// attribute or from the colorspace if from_colorspace is true.
// Returns an empty vector if not found.
OIIO_API std::vector<uint8_t>
get_colorspace_icc_profile(const ImageSpec& spec, bool from_colorspace = true);

// Set CICP attribute in the spec's metadata, and set oiio:ColorSpace
// along with it if there is a corresponding known colorspace.
OIIO_API void
set_colorspace_cicp(ImageSpec& spec, const int cicp[4]);

// Returns CICP from the spec's metadata, either from a CICP attribute
// or from the colorspace if from_colorspace is true.
// Returns an empty span if not found.
OIIO_API cspan<int>
get_colorspace_cicp(const ImageSpec& spec, bool from_colorspace = true);

/// Get the timing report from log_time entries.
OIIO_API std::string
timing_report();
Expand Down
Loading
Loading