LibGfx/JPEGXL: Support images with the have_crop option in FrameHeader

This commit only allows us to read these values. The decoder will still
output the image as if no cropping was requested.
This commit is contained in:
Lucas CHOLLET 2023-08-10 15:48:49 -04:00 committed by Andreas Kling
parent a9620d8784
commit 70e4d3a9b6
Notes: sideshowbarker 2024-07-17 16:23:55 +09:00

View file

@ -681,6 +681,10 @@ struct FrameHeader {
u8 lf_level {};
bool have_crop { false };
i32 x0 {};
i32 y0 {};
u32 width {};
u32 height {};
BlendingInfo blending_info {};
FixedArray<BlendingInfo> ec_blending_info {};
@ -701,7 +705,9 @@ static int operator&(FrameHeader::Flags first, FrameHeader::Flags second)
return static_cast<int>(first) & static_cast<int>(second);
}
static ErrorOr<FrameHeader> read_frame_header(LittleEndianInputBitStream& stream, ImageMetadata const& metadata)
static ErrorOr<FrameHeader> read_frame_header(LittleEndianInputBitStream& stream,
SizeHeader size_header,
ImageMetadata const& metadata)
{
FrameHeader frame_header;
bool const all_default = TRY(stream.read_bit());
@ -744,15 +750,29 @@ static ErrorOr<FrameHeader> read_frame_header(LittleEndianInputBitStream& stream
if (frame_header.frame_type != FrameHeader::FrameType::kLFFrame)
frame_header.have_crop = TRY(stream.read_bit());
if (frame_header.have_crop)
TODO();
if (frame_header.have_crop) {
auto const read_crop_dimension = [&]() -> ErrorOr<u32> {
return U32(TRY(stream.read_bits(8)), 256 + TRY(stream.read_bits(11)), 2304 + TRY(stream.read_bits(14)), 18688 + TRY(stream.read_bits(30)));
};
if (frame_header.frame_type != FrameHeader::FrameType::kReferenceOnly) {
frame_header.x0 = unpack_signed(TRY(read_crop_dimension()));
frame_header.y0 = unpack_signed(TRY(read_crop_dimension()));
}
frame_header.width = TRY(read_crop_dimension());
frame_header.height = TRY(read_crop_dimension());
}
bool const normal_frame = frame_header.frame_type == FrameHeader::FrameType::kRegularFrame
|| frame_header.frame_type == FrameHeader::FrameType::kSkipProgressive;
// FIXME: also consider "cropped" image of the dimension of the frame
VERIFY(!frame_header.have_crop);
bool const full_frame = !frame_header.have_crop;
// Let full_frame be true if and only if have_crop is false or if the frame area given
// by width and height and offsets x0 and y0 completely covers the image area.
bool const cover_image_area = frame_header.x0 <= 0 && frame_header.y0 <= 0
&& (frame_header.width + frame_header.x0 >= size_header.width)
&& (frame_header.height + frame_header.y0 == size_header.height);
bool const full_frame = !frame_header.have_crop || cover_image_area;
if (normal_frame) {
frame_header.blending_info = TRY(read_blending_info(stream, metadata, full_frame));
@ -2304,13 +2324,14 @@ static ErrorOr<Frame> read_frame(LittleEndianInputBitStream& stream,
Frame frame;
frame.frame_header = TRY(read_frame_header(stream, metadata));
frame.frame_header = TRY(read_frame_header(stream, size_header, metadata));
if (!frame.frame_header.have_crop) {
frame.width = size_header.width;
frame.height = size_header.height;
} else {
TODO();
frame.width = frame.frame_header.width;
frame.height = frame.frame_header.height;
}
if (frame.frame_header.upsampling > 1) {