Repository: SerenityOS/serenity
File: Userland/Libraries/LibGfx/ImageFormats/JPEGXLLoader.cpp (C++)

Code before:
    // representation of this blending before the final rendering (in m_bitmap)
    Optional<Image> m_image;

    Vector<Frame> m_frames;

    SizeHeader m_header;
    ImageMetadata m_metadata;

    ByteBuffer m_icc_profile;
};

JPEGXLImageDecoderPlugin::JPEGXLImageDecoderPlugin(NonnullOwnPtr<FixedMemoryStream> stream)
{
    m_context = make<JPEGXLLoadingContext>(move(stream));
}

JPEGXLImageDecoderPlugin::~JPEGXLImageDecoderPlugin() = default;

IntSize JPEGXLImageDecoderPlugin::size()
{
    return m_context->size();
}

bool JPEGXLImageDecoderPlugin::sniff(ReadonlyBytes data)
{
    bool is_raw_codestream = data.size() > 2
        && data.data()[0] == 0xFF
        && data.data()[1] == 0x0A;

    // 18181-2: 9.1  JPEG XL Signature box (JXL␣)
    static constexpr Array signature = to_array<u8>({
        // clang-format off
        0x00, 0x00, 0x00, 0x0C,
        0x4A, 0x58, 0x4C, 0x20,
        0x0D, 0x0A, 0x87, 0x0A,
        // clang-format on
    });
    bool is_container = data.size() > 12 && data.trim(12) == signature;
    return is_raw_codestream || is_container;
}

ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGXLImageDecoderPlugin::create(ReadonlyBytes data)
{
    auto stream = TRY(try_make<FixedMemoryStream>(data));
    auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEGXLImageDecoderPlugin(move(stream))));
    TRY(plugin->m_context->decode_image_header());
    return plugin;
}

bool JPEGXLImageDecoderPlugin::is_animated()
{

Review comment (bug):
Shouldn't this be part of the next commit? Else we'll allow boxed jxls at this commit but then fail to load them.

Code after:

    // 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;

    Vector<Frame> m_frames;

    SizeHeader m_header;
    ImageMetadata m_metadata;

    ByteBuffer m_icc_profile;
};

JPEGXLImageDecoderPlugin::JPEGXLImageDecoderPlugin(Optional<Vector<u8>>&& jxlc_content, NonnullOwnPtr<FixedMemoryStream> stream)
    : m_context(make<JPEGXLLoadingContext>(move(stream)))
    , m_jxlc_content(move(jxlc_content))
{
}

JPEGXLImageDecoderPlugin::~JPEGXLImageDecoderPlugin() = default;

IntSize JPEGXLImageDecoderPlugin::size()
{
    return m_context->size();
}

static bool is_raw_codestream(ReadonlyBytes data)
{
    return data.starts_with(to_array<u8>({ 0xFF, 0x0A }));
}

bool JPEGXLImageDecoderPlugin::sniff(ReadonlyBytes data)
{
    // 18181-2: 9.1  JPEG XL Signature box (JXL␣)
    static constexpr Array signature = to_array<u8>({
        // clang-format off
        0x00, 0x00, 0x00, 0x0C,
        0x4A, 0x58, 0x4C, 0x20,
        0x0D, 0x0A, 0x87, 0x0A,
        // clang-format on
    });
    bool is_container = data.starts_with(signature);
    return is_raw_codestream(data) || is_container;
}

static ErrorOr<Vector<u8>> extract_codestream_from_container(NonnullOwnPtr<FixedMemoryStream> input)
{
    auto box_reader = TRY(ISOBMFF::Reader::create(move(input)));
    auto box_list = TRY(box_reader.read_entire_file());

    for (auto& box : box_list) {