Skip to content

Commit 0e5c5a5

Browse files
feat(jpeg-xl): ICC read and write for JPEG-XL files (issue 4649) (#4905)
This PR addresses [4649](#4649) implementing ICC read and write support for JPEG-XL. Fixes #4969 The jxl testsuite directory was added with tests. --------- Signed-off-by: Shane Smith <[email protected]>
1 parent 46ce8ee commit 0e5c5a5

File tree

6 files changed

+73
-0
lines changed

6 files changed

+73
-0
lines changed

src/cmake/testing.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ macro (oiio_add_all_tests)
284284
FOUNDVAR OPENJPEG_FOUND
285285
IMAGEDIR j2kp4files_v1_5
286286
URL http://www.itu.int/net/ITU-T/sigdb/speimage/ImageForm-s.aspx?val=10100803)
287+
oiio_add_tests (jxl
288+
FOUNDVAR JXL_FOUND)
287289
set (all_openexr_tests
288290
openexr-suite openexr-multires openexr-chroma openexr-decreasingy
289291
openexr-v2 openexr-window perchannel oiiotool-deep)

src/jpegxl.imageio/jxlinput.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <OpenImageIO/imageio.h>
2222
#include <OpenImageIO/tiffutils.h>
2323

24+
#include <jxl/color_encoding.h>
2425
#include <jxl/decode.h>
2526
#include <jxl/decode_cxx.h>
2627
#include <jxl/resizable_parallel_runner_cxx.h>
@@ -53,6 +54,7 @@ class JxlInput final : public ImageInput {
5354
std::string m_filename;
5455
int m_next_scanline; // Which scanline is the next to read?
5556
uint32_t m_channels;
57+
JxlColorEncoding m_color_encoding;
5658
JxlDecoderPtr m_decoder;
5759
JxlResizableParallelRunnerPtr m_runner;
5860
std::unique_ptr<ImageSpec> m_config; // Saved copy of configuration spec
@@ -346,6 +348,23 @@ JxlInput::open(const std::string& name, ImageSpec& newspec)
346348

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

351+
if (m_icc_profile.size() && m_icc_profile.data()) {
352+
m_spec.attribute("ICCProfile",
353+
TypeDesc(TypeDesc::UINT8, m_icc_profile.size()),
354+
m_icc_profile.data());
355+
std::string errormsg;
356+
357+
bool ok = decode_icc_profile(cspan<uint8_t>(m_icc_profile.data(),
358+
m_icc_profile.size()),
359+
m_spec, errormsg);
360+
361+
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
362+
errorfmt("Possible corrupt file, could not decode ICC profile: {}\n",
363+
errormsg);
364+
return false;
365+
}
366+
}
367+
349368
newspec = m_spec;
350369
return true;
351370
}

src/jpegxl.imageio/jxloutput.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,21 @@ JxlOutput::save_image(const void* data)
538538
return false;
539539
}
540540

541+
// Write the ICC profile, if available
542+
const ParamValue* icc_profile_parameter = m_spec.find_attribute(
543+
"ICCProfile");
544+
if (icc_profile_parameter != nullptr) {
545+
unsigned char* icc_profile
546+
= (unsigned char*)icc_profile_parameter->data();
547+
uint32_t length = icc_profile_parameter->type().size();
548+
if (icc_profile && length) {
549+
if (JXL_ENC_SUCCESS
550+
!= JxlEncoderSetICCProfile(m_encoder.get(), icc_profile,
551+
length)) {
552+
errorfmt("JxlEncoderSetICCProfile failed\n");
553+
}
554+
}
555+
}
541556

542557
// No more image frames nor metadata boxes to add
543558
DBG std::cout << "calling JxlEncoderCloseInput()\n";

testsuite/jxl/ref/out.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Reading tahoe-icc.jxl
2+
tahoe-icc.jxl : 128 x 96, 3 channel, uint8 jpegxl
3+
SHA-1: 069F1A3E5567349C2D34E535B29913029EF1B09C
4+
channel list: R, G, B
5+
ICCProfile: 0, 0, 2, 48, 65, 68, 66, 69, 2, 16, 0, 0, 109, 110, 116, 114, ... [560 x uint8]
6+
ICCProfile:attributes: "Reflective, Glossy, Positive, Color"
7+
ICCProfile:cmm_type: 1094992453
8+
ICCProfile:color_space: "RGB"
9+
ICCProfile:copyright: "Copyright 1999 Adobe Systems Incorporated"
10+
ICCProfile:creation_date: "1999:06:03 00:00:00"
11+
ICCProfile:creator_signature: "41444245"
12+
ICCProfile:device_class: "Display device profile"
13+
ICCProfile:flags: "Not Embedded, Independent"
14+
ICCProfile:manufacturer: "6e6f6e65"
15+
ICCProfile:model: "0"
16+
ICCProfile:platform_signature: "Apple Computer, Inc."
17+
ICCProfile:profile_connection_space: "XYZ"
18+
ICCProfile:profile_description: "Adobe RGB (1998)"
19+
ICCProfile:profile_size: 560
20+
ICCProfile:profile_version: "2.1.0"
21+
ICCProfile:rendering_intent: "Perceptual"

testsuite/jxl/ref/test-jxl.icc

560 Bytes
Binary file not shown.

testsuite/jxl/run.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright Contributors to the OpenImageIO project.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# https://github.com/AcademySoftwareFoundation/OpenImageIO
6+
7+
8+
# Test adding and extracting ICC profiles
9+
command += oiiotool ("../common/tahoe-tiny.tif --iccread ref/test-jxl.icc -o tahoe-icc.jxl")
10+
command += info_command ("tahoe-icc.jxl", safematch=True)
11+
command += oiiotool ("tahoe-icc.jxl --iccwrite test-jxl.icc")
12+
13+
outputs = [
14+
"test-jxl.icc",
15+
"out.txt"
16+
]

0 commit comments

Comments
 (0)