From b2a559ddb075fbdf75fe3642b5d296616a675665 Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Fri, 28 Jul 2023 22:09:55 -0400 Subject: [PATCH] LibGfx/JPEGXL: Create `Image` with the correct number of channel As a quick and dirty implementation, we used to assume that the final image was always composed of three channels of the same size. However, JPEG XL has support for more than three channels and extra channels can have a smaller size. With this patch, we now create the image with the correct number of channel and with their respective sizes. --- .../LibGfx/ImageFormats/JPEGXLLoader.cpp | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGXLLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGXLLoader.cpp index 52c514380d..a6864b58a2 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGXLLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGXLLoader.cpp @@ -398,6 +398,18 @@ struct ImageMetadata { Array up2_weight = s_d_up2; Array up4_weight = s_d_up4; Array up8_weight = s_d_up8; + + u16 number_of_color_channels() const + { + if (!xyb_encoded && colour_encoding.colour_space == ColourEncoding::ColourSpace::kGrey) + return 1; + return 3; + } + + u16 number_of_channels() const + { + return number_of_color_channels() + num_extra_channels; + } }; static ErrorOr read_metadata_header(LittleEndianInputBitStream& stream) @@ -1169,14 +1181,18 @@ private: class Image { public: - static ErrorOr create(IntSize size) + static ErrorOr create(IntSize size, ImageMetadata const& metadata) { Image image {}; - // FIXME: Don't assume three channels and a fixed size - TRY(image.m_channels.try_append(TRY(Channel::create(size.width(), size.height())))); - TRY(image.m_channels.try_append(TRY(Channel::create(size.width(), size.height())))); - TRY(image.m_channels.try_append(TRY(Channel::create(size.width(), size.height())))); + for (u16 i = 0; i < metadata.number_of_channels(); ++i) { + if (i < metadata.number_of_color_channels()) { + TRY(image.m_channels.try_append(TRY(Channel::create(size.width(), size.height())))); + } else { + auto const dim_shift = metadata.ec_info[i - metadata.number_of_color_channels()].dim_shift; + TRY(image.m_channels.try_append(TRY(Channel::create(size.width() >> dim_shift, size.height() >> dim_shift)))); + } + } return image; } @@ -1629,7 +1645,7 @@ static ErrorOr read_frame(LittleEndianInputBitStream& stream, frame.toc = TRY(read_toc(stream, frame.frame_header, frame.num_groups, frame.num_lf_groups)); - image = TRY(Image::create({ frame.width, frame.height })); + image = TRY(Image::create({ frame.width, frame.height }, metadata)); frame.lf_global = TRY(read_lf_global(stream, image, frame.frame_header, metadata, entropy_decoder));