diff --git a/Userland/Libraries/LibCore/MimeData.cpp b/Userland/Libraries/LibCore/MimeData.cpp index 0ac8c695763..ff7068ba5ed 100644 --- a/Userland/Libraries/LibCore/MimeData.cpp +++ b/Userland/Libraries/LibCore/MimeData.cpp @@ -115,6 +115,7 @@ static Array const s_registered_mime_type = { MimeType { .name = "image/bmp"sv, .common_extensions = { ".bmp"sv }, .description = "BMP image data"sv, .magic_bytes = Vector { 'B', 'M' } }, MimeType { .name = "image/gif"sv, .common_extensions = { ".gif"sv }, .description = "GIF image data"sv, .magic_bytes = Vector { 'G', 'I', 'F', '8', '7', 'a' } }, MimeType { .name = "image/gif"sv, .common_extensions = { ".gif"sv }, .description = "GIF image data"sv, .magic_bytes = Vector { 'G', 'I', 'F', '8', '9', 'a' } }, + MimeType { .name = "image/j2c"sv, .common_extensions = { ".j2c"sv, ".j2k"sv }, .description = "JPEG2000 image data codestream"sv, .magic_bytes = Vector { 0xFF, 0x4F, 0xFF, 0x51 } }, MimeType { .name = "image/jp2"sv, .common_extensions = { ".jp2"sv, ".jpf"sv, ".jpx"sv }, .description = "JPEG2000 image data"sv, .magic_bytes = Vector { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A } }, MimeType { .name = "image/jpeg"sv, .common_extensions = { ".jpg"sv, ".jpeg"sv }, .description = "JPEG image data"sv, .magic_bytes = Vector { 0xFF, 0xD8, 0xFF } }, MimeType { .name = "image/jxl"sv, .common_extensions = { ".jxl"sv }, .description = "JPEG XL image data"sv, .magic_bytes = Vector { 0xFF, 0x0A } }, diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEG2000Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEG2000Loader.cpp index 87fea74f8cc..4da0d1b91db 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEG2000Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEG2000Loader.cpp @@ -29,9 +29,8 @@ namespace Gfx { // or in a JP2 file, which is a container format based on boxes similar to ISOBMFF. // This is the marker for the codestream version. We don't support this yet. -// If we add support, add a second `"image/jp2"` line to MimeData.cpp for this magic number. // T.800 Annex A, Codestream syntax, A.2 Information in the marker segments and A.3 Construction of the codestream -[[maybe_unused]] static constexpr u8 marker_id_string[] = { 0xFF, 0x4F, 0xFF, 0x51 }; +static constexpr u8 marker_id_string[] = { 0xFF, 0x4F, 0xFF, 0x51 }; // This is the marker for the box version. // T.800 Annex I, JP2 file format syntax, I.5.1 JPEG 2000 Signature box @@ -717,6 +716,13 @@ static ErrorOr decode_jpeg2000_header(JPEG2000LoadingContext& context, Rea if (!JPEG2000ImageDecoderPlugin::sniff(data)) return Error::from_string_literal("JPEG2000LoadingContext: Invalid JPEG2000 header"); + if (data.starts_with(marker_id_string)) { + context.codestream_data = data; + TRY(parse_codestream_main_header(context)); + context.size = { context.siz.width, context.siz.height }; + return {}; + } + auto reader = TRY(Gfx::ISOBMFF::Reader::create(TRY(try_make(data)))); context.boxes = TRY(reader.read_entire_file()); @@ -914,7 +920,7 @@ ErrorOr TagTree::read_value(u32 x, u32 y, Function()> const& bool JPEG2000ImageDecoderPlugin::sniff(ReadonlyBytes data) { - return data.starts_with(jp2_id_string); + return data.starts_with(jp2_id_string) || data.starts_with(marker_id_string); } JPEG2000ImageDecoderPlugin::JPEG2000ImageDecoderPlugin()