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

Code before:
        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(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) {
        if (box->box_type() == ISOBMFF::BoxType::JPEGXLCodestreamBox) {
            auto& codestream_box = *reinterpret_cast<ISOBMFF::JPEGXLCodestreamBox*>(box.ptr());
            return move(codestream_box.codestream);
        }
    }

    return Error::from_string_literal("JPEGXLLoader: No jxlc box found");
}

ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGXLImageDecoderPlugin::create(ReadonlyBytes data)
{
    auto stream = TRY(try_make<FixedMemoryStream>(data));
    Optional<Vector<u8>> jxlc_content;
    if (!is_raw_codestream(data)) {
        jxlc_content = TRY(extract_codestream_from_container(move(stream)));
        stream = TRY(try_make<FixedMemoryStream>(jxlc_content->span()));
    }
    auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEGXLImageDecoderPlugin(move(jxlc_content), move(stream))));
    TRY(plugin->m_context->decode_image_header());
    return plugin;
}

bool JPEGXLImageDecoderPlugin::is_animated()
{
    return false;
}

size_t JPEGXLImageDecoderPlugin::loop_count()
{
    return 0;
}

size_t JPEGXLImageDecoderPlugin::frame_count()
{
    return 1;
}


Review comment (suggestion):
This is alright for now if you want to keep it that way, but at least in jpeg2000 "boxed" is the common, normal case, and raw codestream is the special case. So over there (cf `decode_jpeg2000_header` in JPEG2000Loader.cpp) I treat raw streams as the special case, not the boxed stream.

(Maybe you'll want to do more with boxes in the future, and then having that all in the if will be awkward.)

Code after:
        // 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) {
        if (box->box_type() == ISOBMFF::BoxType::JPEGXLCodestreamBox) {
            auto& codestream_box = *reinterpret_cast<ISOBMFF::JPEGXLCodestreamBox*>(box.ptr());
            return move(codestream_box.codestream);
        }
    }

    return Error::from_string_literal("JPEGXLLoader: No jxlc box found");
}

ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGXLImageDecoderPlugin::create(ReadonlyBytes data)
{
    auto stream = TRY(try_make<FixedMemoryStream>(data));
    Optional<Vector<u8>> jxlc_content;
    if (!is_raw_codestream(data)) {
        jxlc_content = TRY(extract_codestream_from_container(move(stream)));
        stream = TRY(try_make<FixedMemoryStream>(jxlc_content->span()));
    }
    auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEGXLImageDecoderPlugin(move(jxlc_content), move(stream))));
    TRY(plugin->m_context->decode_image_header());
    return plugin;
}

bool JPEGXLImageDecoderPlugin::is_animated()
{
    return false;
}

size_t JPEGXLImageDecoderPlugin::loop_count()
{
    return 0;
}

size_t JPEGXLImageDecoderPlugin::frame_count()
{
    return 1;
}

size_t JPEGXLImageDecoderPlugin::first_animated_frame_index()
{