Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 29 additions & 1 deletion src/jpegxl.imageio/jxlinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <cassert>
#include <cstdio>

#include <OpenImageIO/color.h>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
Expand Down Expand Up @@ -54,7 +55,6 @@ class JxlInput final : public ImageInput {
std::string m_filename;
int m_next_scanline; // Which scanline is the next to read?
uint32_t m_channels;
JxlColorEncoding m_color_encoding;
JxlDecoderPtr m_decoder;
JxlResizableParallelRunnerPtr m_runner;
std::unique_ptr<ImageSpec> m_config; // Saved copy of configuration spec
Expand Down Expand Up @@ -224,6 +224,8 @@ JxlInput::open(const std::string& name, ImageSpec& newspec)
JxlDataType jxl_data_type;
TypeDesc m_data_type;
uint32_t bits = 0;
JxlColorEncoding color_encoding {};
bool have_color_encoding = false;

for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(m_decoder.get());
Expand Down Expand Up @@ -300,6 +302,16 @@ JxlInput::open(const std::string& name, ImageSpec& newspec)
errorfmt("JxlDecoderGetColorAsICCProfile failed\n");
return false;
}

// Get the color encoding of the pixel data
// This will return JXL_DEC_ERR for a valid file without color
// encoding information, so don't report an error.
if (JXL_DEC_SUCCESS
== JxlDecoderGetColorAsEncodedProfile(
m_decoder.get(), JXL_COLOR_PROFILE_TARGET_DATA,
&color_encoding)) {
have_color_encoding = true;
}
} else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
DBG std::cout << "JXL_DEC_NEED_IMAGE_OUT_BUFFER\n";

Expand Down Expand Up @@ -348,6 +360,7 @@ JxlInput::open(const std::string& name, ImageSpec& newspec)

m_spec = ImageSpec(info.xsize, info.ysize, m_channels, m_data_type);

// Read ICC profile
if (m_icc_profile.size() && m_icc_profile.data()) {
m_spec.attribute("ICCProfile",
TypeDesc(TypeDesc::UINT8, m_icc_profile.size()),
Expand All @@ -365,6 +378,21 @@ JxlInput::open(const std::string& name, ImageSpec& newspec)
}
}

// Read CICP from color encoding. Custom primaries, custom white point and
// arbitrary gamma not supported currently.
if (have_color_encoding && color_encoding.primaries != JXL_PRIMARIES_CUSTOM
&& color_encoding.white_point != JXL_WHITE_POINT_CUSTOM
&& color_encoding.transfer_function != JXL_TRANSFER_FUNCTION_GAMMA) {
const int cicp[4] = { color_encoding.primaries,
color_encoding.transfer_function, 0 /* RGB */,
1 /* Full range */ };
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);
}

newspec = m_spec;
return true;
}
Expand Down
56 changes: 56 additions & 0 deletions src/jpegxl.imageio/jxloutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstdio>
#include <vector>

#include <OpenImageIO/color.h>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
Expand Down Expand Up @@ -538,6 +539,8 @@ JxlOutput::save_image(const void* data)
return false;
}

bool wrote_colorspace = false;

// Write the ICC profile, if available
const ParamValue* icc_profile_parameter = m_spec.find_attribute(
"ICCProfile");
Expand All @@ -551,6 +554,59 @@ JxlOutput::save_image(const void* data)
length)) {
errorfmt("JxlEncoderSetICCProfile failed\n");
}
wrote_colorspace = true;
}
}

// Write CICP
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>()
: (!wrote_colorspace) ? colorconfig.get_cicp(colorspace)
: cspan<int>();
if (!cicp.empty()) {
// JXL only has a subset of CICP, only write if supported. Custom
// primaries and white point are not currently used but could help
// support more CICP codes.
JxlColorEncoding color_encoding {};
color_encoding.primaries = JxlPrimaries(cicp[0]);
color_encoding.transfer_function = JxlTransferFunction(cicp[1]);
color_encoding.color_space = JXL_COLOR_SPACE_RGB;

bool supported_primaries = false;
bool supported_transfer = false;

switch (color_encoding.primaries) {
case JXL_PRIMARIES_SRGB:
case JXL_PRIMARIES_2100:
case JXL_PRIMARIES_P3:
supported_primaries = true;
color_encoding.white_point = JXL_WHITE_POINT_D65;
break;
case JXL_PRIMARIES_CUSTOM: // Not an actual CICP code in JXL
break;
}

switch (color_encoding.transfer_function) {
case JXL_TRANSFER_FUNCTION_709:
case JXL_TRANSFER_FUNCTION_UNKNOWN:
case JXL_TRANSFER_FUNCTION_LINEAR:
case JXL_TRANSFER_FUNCTION_SRGB:
case JXL_TRANSFER_FUNCTION_PQ:
case JXL_TRANSFER_FUNCTION_DCI:
case JXL_TRANSFER_FUNCTION_HLG: supported_transfer = true; break;
case JXL_TRANSFER_FUNCTION_GAMMA: // Not an actual CICP code
break;
}

if (supported_primaries && supported_transfer) {
if (JXL_ENC_SUCCESS
!= JxlEncoderSetColorEncoding(m_encoder.get(),
&color_encoding)) {
errorfmt("JxlEncoderSetColorEncoding failed\n");
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions testsuite/jxl/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,26 @@ tahoe-icc.jxl : 128 x 96, 3 channel, uint8 jpegxl
ICCProfile:profile_size: 560
ICCProfile:profile_version: "2.1.0"
ICCProfile:rendering_intent: "Perceptual"
Reading tahoe-cicp-pq.jxl
tahoe-cicp-pq.jxl : 128 x 96, 3 channel, uint8 jpegxl
SHA-1: 069F1A3E5567349C2D34E535B29913029EF1B09C
channel list: R, G, B
CICP: 9, 16, 0, 1
ICCProfile: 0, 0, 16, 248, 106, 120, 108, 32, 4, 64, 0, 0, 109, 110, 116, 114, ... [4344 x uint8]
ICCProfile:attributes: "Reflective, Glossy, Positive, Color"
ICCProfile:cmm_type: 1786276896
ICCProfile:color_space: "RGB"
ICCProfile:copyright: "CC0"
ICCProfile:creation_date: "2019:12:01 00:00:00"
ICCProfile:creator_signature: "6a786c20"
ICCProfile:device_class: "Display device profile"
ICCProfile:flags: "Not Embedded, Independent"
ICCProfile:manufacturer: "0"
ICCProfile:model: "0"
ICCProfile:platform_signature: "Apple Computer, Inc."
ICCProfile:profile_connection_space: "CIELAB"
ICCProfile:profile_description: "RGB_D65_202_Per_PeQ"
ICCProfile:profile_size: 4344
ICCProfile:profile_version: "4.4.0"
ICCProfile:rendering_intent: "Perceptual"
oiio:ColorSpace: "pq_rec2020_display"
3 changes: 3 additions & 0 deletions testsuite/jxl/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
command += info_command ("tahoe-icc.jxl", safematch=True)
command += oiiotool ("tahoe-icc.jxl --iccwrite test-jxl.icc")

command += oiiotool ("../common/tahoe-tiny.tif --cicp \"9,16,9,1\" -o tahoe-cicp-pq.jxl")
command += info_command ("tahoe-cicp-pq.jxl", safematch=True)

outputs = [
"test-jxl.icc",
"out.txt"
Expand Down
Loading