11#include " jxl_codec.h"
2- #include < inttypes.h>
2+ #include " jxl/decode_cxx.h"
3+ #include " jxl/encode_cxx.h"
4+ #include " jxl/types.h"
35#include < climits>
6+ #include < cstdlib>
7+ #include < inttypes.h>
8+ #include < jxl/encode.h>
49#include < memory>
510#include < stdexcept>
611#include < vector>
7- #include " fast_lossless.h"
8- #include " jxl/decode_cxx.h"
9- #include " jxl/encode_cxx.h"
10- #include " jxl/resizable_parallel_runner_cxx.h"
11- #include " jxl/thread_parallel_runner_cxx.h"
1212
1313/*
1414 * JXLEncoder
1515 */
1616
17- template class libench ::JXLEncoder<0 >;
17+ template class libench ::JXLEncoder<1 >;
1818template class libench ::JXLEncoder<2 >;
19+ template class libench ::JXLEncoder<3 >;
1920
20- template <int E>
21- libench::JXLEncoder<E>::JXLEncoder(){};
21+ template <int E> libench::JXLEncoder<E>::JXLEncoder(){};
2222
23- template <int E>
24- libench::JXLEncoder<E>::~JXLEncoder () {
23+ template <int E> libench::JXLEncoder<E>::~JXLEncoder () {
2524 free (this ->cb_ .codestream );
2625};
2726
28- template <int E>
29- libench::CodestreamContext libench::JXLEncoder<E>::encodeRGB8(const ImageContext &image) {
30- free (this ->cb_ .codestream );
27+ template <int E, bool rgba>
28+ static size_t JxlEncode (void *image_data, size_t width, size_t height,
29+ uint8_t **encoded) {
30+ auto enc = JxlEncoderMake (/* memory_manager=*/ nullptr );
31+
32+ JxlPixelFormat pixel_format = {rgba ? 4 : 3 , JXL_TYPE_UINT8,
33+ JXL_NATIVE_ENDIAN, 0 };
34+
35+ JxlBasicInfo basic_info;
36+ JxlEncoderInitBasicInfo (&basic_info);
37+ basic_info.xsize = width;
38+ basic_info.ysize = height;
39+ basic_info.bits_per_sample = 8 ;
40+ basic_info.exponent_bits_per_sample = 0 ;
41+ basic_info.uses_original_profile = JXL_TRUE;
42+ if (rgba) {
43+ basic_info.alpha_bits = 8 ;
44+ basic_info.num_extra_channels = 1 ;
45+ }
46+ if (JXL_ENC_SUCCESS != JxlEncoderSetBasicInfo (enc.get (), &basic_info)) {
47+ throw std::runtime_error (" JxlEncoderSetBasicInfo failed\n " );
48+ }
3149
32- this ->cb_ .size = FastLosslessEncode (image.planes8 [0 ], image.width , image.width * 3 , image.height , 3 , 8 , E,
33- &this ->cb_ .codestream );
50+ JxlColorEncoding color_encoding = {};
51+ JxlColorEncodingSetToSRGB (&color_encoding, false );
52+ if (JXL_ENC_SUCCESS !=
53+ JxlEncoderSetColorEncoding (enc.get (), &color_encoding)) {
54+ throw std::runtime_error (" JxlEncoderSetColorEncoding failed\n " );
55+ }
3456
35- return this ->cb_ ;
57+ JxlEncoderFrameSettings *frame_settings =
58+ JxlEncoderFrameSettingsCreate (enc.get (), nullptr );
59+
60+ if (JXL_ENC_SUCCESS != JxlEncoderSetFrameLossless (frame_settings, JXL_TRUE)) {
61+ throw std::runtime_error (" JxlEncoderSetFrameLossless failed\n " );
62+ }
63+
64+ if (JXL_ENC_SUCCESS != JxlEncoderFrameSettingsSetOption (
65+ frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, E)) {
66+ throw std::runtime_error (" JxlEncoderFrameSettingsSetOption failed\n " );
67+ }
68+
69+ if (JXL_ENC_SUCCESS !=
70+ JxlEncoderAddImageFrame (frame_settings, &pixel_format,
71+ static_cast <const void *>(image_data),
72+ pixel_format.num_channels * width * height)) {
73+ throw std::runtime_error (" JxlEncoderAddImageFrame failed\n " );
74+ }
75+ JxlEncoderCloseInput (enc.get ());
76+
77+ size_t size = pixel_format.num_channels * width * height;
78+ *encoded = (uint8_t *)malloc (size);
79+ uint8_t *next_out = *encoded;
80+ size_t avail_out = size - (next_out - *encoded);
81+ JxlEncoderStatus process_result = JXL_ENC_NEED_MORE_OUTPUT;
82+ while (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
83+ process_result = JxlEncoderProcessOutput (enc.get (), &next_out, &avail_out);
84+ if (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
85+ size_t offset = next_out - *encoded;
86+ size *= 2 ;
87+ *encoded = (uint8_t *)realloc (*encoded, size);
88+ next_out = *encoded + offset;
89+ avail_out = size - offset;
90+ }
91+ }
92+ if (JXL_ENC_SUCCESS != process_result) {
93+ throw std::runtime_error (" JxlEncoderProcessOutput failed\n " );
94+ }
95+
96+ return next_out - *encoded;
3697}
3798
3899template <int E>
39- libench::CodestreamContext libench::JXLEncoder<E>::encodeRGBA8(const ImageContext &image) {
100+ libench::CodestreamContext
101+ libench::JXLEncoder<E>::encodeRGB8(const ImageContext &image) {
40102 free (this ->cb_ .codestream );
103+ cb_.size = JxlEncode<E, false >(image.planes8 [0 ], image.width , image.height ,
104+ &cb_.codestream );
105+ return this ->cb_ ;
106+ }
41107
42- this ->cb_ .size = FastLosslessEncode (image.planes8 [0 ], image.width , image.width * 4 , image.height , 4 , 8 , E,
43- &this ->cb_ .codestream );
44-
108+ template <int E>
109+ libench::CodestreamContext
110+ libench::JXLEncoder<E>::encodeRGBA8(const ImageContext &image) {
111+ free (this ->cb_ .codestream );
112+ cb_.size = JxlEncode<E, true >(image.planes8 [0 ], image.width , image.height ,
113+ &cb_.codestream );
45114 return this ->cb_ ;
46115}
47116
@@ -51,21 +120,22 @@ libench::CodestreamContext libench::JXLEncoder<E>::encodeRGBA8(const ImageContex
51120
52121libench::JXLDecoder::JXLDecoder (){};
53122
54- libench::ImageContext libench::JXLDecoder::decodeRGB8 (const CodestreamContext& cs) {
123+ libench::ImageContext
124+ libench::JXLDecoder::decodeRGB8 (const CodestreamContext &cs) {
55125 return this ->decode8 (cs, 3 );
56126}
57127
58- libench::ImageContext libench::JXLDecoder::decodeRGBA8 (const CodestreamContext& cs) {
128+ libench::ImageContext
129+ libench::JXLDecoder::decodeRGBA8 (const CodestreamContext &cs) {
59130 return this ->decode8 (cs, 4 );
60131}
61132
62- libench::ImageContext libench::JXLDecoder::decode8 (const CodestreamContext& cs, uint8_t num_comps) {
133+ libench::ImageContext libench::JXLDecoder::decode8 (const CodestreamContext &cs,
134+ uint8_t num_comps) {
63135 libench::ImageContext image;
64136
65- image.format = num_comps == 3 ? libench::ImageFormat::RGB8 : libench::ImageFormat::RGBA8;
66-
67- // Multi-threaded parallel runner.
68- auto runner = JxlResizableParallelRunnerMake (nullptr );
137+ image.format =
138+ num_comps == 3 ? libench::ImageFormat::RGB8 : libench::ImageFormat::RGBA8;
69139
70140 auto dec = JxlDecoderMake (nullptr );
71141 if (JXL_DEC_SUCCESS !=
@@ -75,12 +145,6 @@ libench::ImageContext libench::JXLDecoder::decode8(const CodestreamContext& cs,
75145 throw std::runtime_error (" JxlDecoderSubscribeEvents failed\n " );
76146 }
77147
78- if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner (dec.get (),
79- JxlResizableParallelRunner,
80- runner.get ())) {
81- throw std::runtime_error (" JxlDecoderSetParallelRunner failed\n " );
82- }
83-
84148 JxlBasicInfo info;
85149 JxlPixelFormat format = {num_comps, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 0 };
86150
@@ -100,21 +164,17 @@ libench::ImageContext libench::JXLDecoder::decode8(const CodestreamContext& cs,
100164 }
101165 image.width = info.xsize ;
102166 image.height = info.ysize ;
103- JxlResizableParallelRunnerSetThreads (
104- runner.get (),
105- JxlResizableParallelRunnerSuggestThreads (info.xsize , info.ysize ));
106167 } else if (status == JXL_DEC_COLOR_ENCODING) {
107168 // Get the ICC color profile of the pixel data (but ignore it)
108169 size_t icc_size;
109170 if (JXL_DEC_SUCCESS !=
110- JxlDecoderGetICCProfileSize (
111- dec. get (), &format, JXL_COLOR_PROFILE_TARGET_DATA, &icc_size)) {
171+ JxlDecoderGetICCProfileSize (dec. get (), JXL_COLOR_PROFILE_TARGET_DATA,
172+ &icc_size)) {
112173 throw std::runtime_error (" JxlDecoderGetICCProfileSize failed\n " );
113174 }
114175 std::vector<uint8_t > icc_profile (icc_size);
115176 if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile (
116- dec.get (), &format,
117- JXL_COLOR_PROFILE_TARGET_DATA,
177+ dec.get (), JXL_COLOR_PROFILE_TARGET_DATA,
118178 icc_profile.data (), icc_profile.size ())) {
119179 throw std::runtime_error (" JxlDecoderGetColorAsICCProfile failed\n " );
120180 }
@@ -128,7 +188,7 @@ libench::ImageContext libench::JXLDecoder::decode8(const CodestreamContext& cs,
128188 throw std::runtime_error (" Invalid out buffer size" );
129189 }
130190 this ->pixels_ .resize (image.height * image.width * num_comps);
131- void * pixels_buffer = (void *)this ->pixels_ .data ();
191+ void * pixels_buffer = (void *)this ->pixels_ .data ();
132192 size_t pixels_buffer_size = this ->pixels_ .size () * sizeof (float );
133193 if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer (dec.get (), &format,
134194 pixels_buffer,
0 commit comments