LibGfx/JPEGXL: Add support for cropped images

Due to the way JPEG XL encodes its lossless images, it is sometimes
interesting to embed a large image and crop the result at the end. This
patch adds the functionality to crop a frame.

Note that JPEG XL supports image composition (almost like layers in
image editing software programs) and I tried to make these changes be
a step toward image composing. It's a small step as we are still unable
to read multiple frames, and we only support the `kReplace` blending
mode.
This commit is contained in:
Lucas CHOLLET 2023-08-11 13:16:43 -04:00 committed by Andreas Kling
parent 49c55447d9
commit ea85c99a01
Notes: sideshowbarker 2024-07-17 01:21:02 +09:00

View File

@ -1681,6 +1681,37 @@ public:
return image;
}
void blend_into(Image& image, FrameHeader const& frame_header) const
{
// FIXME: We should use ec_blending_info when appropriate
if (frame_header.blending_info.mode != BlendingInfo::BlendMode::kReplace)
TODO();
for (u16 i = 0; i < m_channels.size(); ++i) {
auto const& input_channel = m_channels[i];
auto& output_channel = image.channels()[i];
for (u32 y = 0; y < input_channel.height(); ++y) {
auto const corrected_y = static_cast<i64>(y) + frame_header.y0;
if (corrected_y < 0)
continue;
if (corrected_y >= output_channel.height())
break;
for (u32 x = 0; x < input_channel.width(); ++x) {
auto const corrected_x = static_cast<i64>(x) + frame_header.x0;
if (corrected_x < 0)
continue;
if (corrected_x >= output_channel.width())
break;
output_channel.set(corrected_x, corrected_y, input_channel.get(x, y));
}
}
};
}
ErrorOr<NonnullRefPtr<Bitmap>> to_bitmap(ImageMetadata& metadata) const
{
// FIXME: which channel size should we use?
@ -2560,7 +2591,10 @@ public:
TRY(render_extra_channels(frame.image, m_metadata));
m_bitmap = TRY(frame.image.to_bitmap(m_metadata));
if (!m_image.has_value())
m_image = TRY(Image::create({ m_header.width, m_header.height }, m_metadata));
frame.image.blend_into(*m_image, frame.frame_header);
return {};
}
@ -2580,6 +2614,9 @@ public:
TRY(decode_frame());
m_bitmap = TRY(m_image->to_bitmap(m_metadata));
m_image.clear();
return {};
}();
@ -2616,6 +2653,10 @@ private:
LittleEndianInputBitStream m_stream;
RefPtr<Gfx::Bitmap> m_bitmap;
// JPEG XL images can be composed of multiples sub-images, this variable is an internal
// representation of this blending before the final rendering (in m_bitmap)
Optional<Image> m_image;
Optional<EntropyDecoder> m_entropy_decoder {};
SizeHeader m_header;