diff --git a/AK/Debug.h.in b/AK/Debug.h.in index 4d0a3c5d68..edd3e8d297 100644 --- a/AK/Debug.h.in +++ b/AK/Debug.h.in @@ -234,6 +234,10 @@ # cmakedefine01 ITEM_RECTS_DEBUG #endif +#ifndef JBIG2_DEBUG +# cmakedefine01 JBIG2_DEBUG +#endif + #ifndef JOB_DEBUG # cmakedefine01 JOB_DEBUG #endif diff --git a/Base/res/apps/ImageViewer.af b/Base/res/apps/ImageViewer.af index 480b508b6e..e6ec0b1adf 100644 --- a/Base/res/apps/ImageViewer.af +++ b/Base/res/apps/ImageViewer.af @@ -4,4 +4,4 @@ Executable=/bin/ImageViewer Category=Gra&phics [Launcher] -FileTypes=bmp,dds,gif,ico,iff,jpeg,jpg,jxl,lbm,pbm,pgm,png,ppm,qoi,tga,tiff,tif,tvg +FileTypes=bmp,dds,gif,ico,iff,jb2,jbig2,jpeg,jpg,jxl,lbm,pbm,pgm,png,ppm,qoi,tga,tiff,tif,tvg diff --git a/Meta/CMake/all_the_debug_macros.cmake b/Meta/CMake/all_the_debug_macros.cmake index 4964079df3..b446533404 100644 --- a/Meta/CMake/all_the_debug_macros.cmake +++ b/Meta/CMake/all_the_debug_macros.cmake @@ -89,6 +89,7 @@ set(IRQ_DEBUG ON) set(ISO9660_DEBUG ON) set(ISO9660_VERY_DEBUG ON) set(ITEM_RECTS_DEBUG ON) +set(JBIG2_DEBUG ON) set(JOB_DEBUG ON) set(JPEG_DEBUG ON) set(JS_BYTECODE_DEBUG ON) diff --git a/Meta/gn/secondary/AK/BUILD.gn b/Meta/gn/secondary/AK/BUILD.gn index 7b498930be..86986055c5 100644 --- a/Meta/gn/secondary/AK/BUILD.gn +++ b/Meta/gn/secondary/AK/BUILD.gn @@ -291,6 +291,7 @@ write_cmake_config("ak_debug_gen") { "IMAP_PARSER_DEBUG=", "ITEM_RECTS_DEBUG=", "JOB_DEBUG=", + "JBIG2_DEBUG=", "JPEG_DEBUG=", "JS_BYTECODE_DEBUG=", "JS_MODULE_DEBUG=", diff --git a/Meta/gn/secondary/Userland/Libraries/LibGfx/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibGfx/BUILD.gn index 4e2954fbe3..b390184d0e 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibGfx/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibGfx/BUILD.gn @@ -74,6 +74,7 @@ shared_library("LibGfx") { "ImageFormats/ISOBMFF/Boxes.cpp", "ImageFormats/ISOBMFF/Reader.cpp", "ImageFormats/ImageDecoder.cpp", + "ImageFormats/JBIG2Loader.cpp", "ImageFormats/JPEGLoader.cpp", "ImageFormats/JPEGWriter.cpp", "ImageFormats/JPEGXLLoader.cpp", diff --git a/Userland/Libraries/LibCore/MimeData.cpp b/Userland/Libraries/LibCore/MimeData.cpp index b60af36fec..75ba279e84 100644 --- a/Userland/Libraries/LibCore/MimeData.cpp +++ b/Userland/Libraries/LibCore/MimeData.cpp @@ -124,6 +124,7 @@ static Array const s_registered_mime_type = { MimeType { .name = "image/webp"sv, .common_extensions = { ".webp"sv }, .description = "WebP image data"sv, .magic_bytes = Vector { 'W', 'E', 'B', 'P' }, .offset = 8 }, MimeType { .name = "image/x-icon"sv, .common_extensions = { ".ico"sv }, .description = "ICO image data"sv }, MimeType { .name = "image/x-ilbm"sv, .common_extensions = { ".iff"sv, ".lbm"sv }, .description = "Interleaved bitmap image data"sv, .magic_bytes = Vector { 0x46, 0x4F, 0x52, 0x4F } }, + MimeType { .name = "image/x-jbig2"sv, .common_extensions = { ".jbig2"sv, ".jb2"sv }, .description = "JBIG2 image data"sv, .magic_bytes = Vector { 0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A } }, MimeType { .name = "image/x-portable-arbitrarymap"sv, .common_extensions = { ".pam"sv }, .description = "PAM image data"sv, .magic_bytes = Vector { 0x50, 0x37, 0x0A } }, MimeType { .name = "image/x-portable-bitmap"sv, .common_extensions = { ".pbm"sv }, .description = "PBM image data"sv, .magic_bytes = Vector { 0x50, 0x31, 0x0A } }, MimeType { .name = "image/x-portable-graymap"sv, .common_extensions = { ".pgm"sv }, .description = "PGM image data"sv, .magic_bytes = Vector { 0x50, 0x32, 0x0A } }, diff --git a/Userland/Libraries/LibGUI/FileTypeFilter.h b/Userland/Libraries/LibGUI/FileTypeFilter.h index 4d4b93079f..3f8dd33a2e 100644 --- a/Userland/Libraries/LibGUI/FileTypeFilter.h +++ b/Userland/Libraries/LibGUI/FileTypeFilter.h @@ -25,7 +25,7 @@ struct FileTypeFilter { static FileTypeFilter image_files() { - return FileTypeFilter { "Image Files", Vector { "png", "gif", "bmp", "dip", "pam", "pbm", "pgm", "ppm", "ico", "iff", "jpeg", "jpg", "jxl", "dds", "qoi", "tif", "tiff", "webp", "tvg" } }; + return FileTypeFilter { "Image Files", Vector { "png", "gif", "bmp", "dip", "pam", "pbm", "pgm", "ppm", "ico", "iff", "jb2", "jbig2", "jpeg", "jpg", "jxl", "dds", "qoi", "tif", "tiff", "webp", "tvg" } }; } }; diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 109233a0eb..3650b68831 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/Userland/Libraries/LibGfx/Bitmap.h @@ -16,26 +16,28 @@ #include #include -#define ENUMERATE_IMAGE_FORMATS \ - __ENUMERATE_IMAGE_FORMAT(bmp, ".bmp") \ - __ENUMERATE_IMAGE_FORMAT(dds, ".dds") \ - __ENUMERATE_IMAGE_FORMAT(gif, ".gif") \ - __ENUMERATE_IMAGE_FORMAT(ico, ".ico") \ - __ENUMERATE_IMAGE_FORMAT(iff, ".iff") \ - __ENUMERATE_IMAGE_FORMAT(jpeg, ".jpeg") \ - __ENUMERATE_IMAGE_FORMAT(jpeg, ".jpg") \ - __ENUMERATE_IMAGE_FORMAT(jxl, ".jxl") \ - __ENUMERATE_IMAGE_FORMAT(iff, ".lbm") \ - __ENUMERATE_IMAGE_FORMAT(pam, ".pam") \ - __ENUMERATE_IMAGE_FORMAT(pbm, ".pbm") \ - __ENUMERATE_IMAGE_FORMAT(pgm, ".pgm") \ - __ENUMERATE_IMAGE_FORMAT(png, ".png") \ - __ENUMERATE_IMAGE_FORMAT(ppm, ".ppm") \ - __ENUMERATE_IMAGE_FORMAT(qoi, ".qoi") \ - __ENUMERATE_IMAGE_FORMAT(tga, ".tga") \ - __ENUMERATE_IMAGE_FORMAT(tiff, ".tif") \ - __ENUMERATE_IMAGE_FORMAT(tiff, ".tiff") \ - __ENUMERATE_IMAGE_FORMAT(tvg, ".tvg") \ +#define ENUMERATE_IMAGE_FORMATS \ + __ENUMERATE_IMAGE_FORMAT(bmp, ".bmp") \ + __ENUMERATE_IMAGE_FORMAT(dds, ".dds") \ + __ENUMERATE_IMAGE_FORMAT(gif, ".gif") \ + __ENUMERATE_IMAGE_FORMAT(ico, ".ico") \ + __ENUMERATE_IMAGE_FORMAT(iff, ".iff") \ + __ENUMERATE_IMAGE_FORMAT(jpeg, ".jb2") \ + __ENUMERATE_IMAGE_FORMAT(jpeg, ".jbig2") \ + __ENUMERATE_IMAGE_FORMAT(jpeg, ".jpeg") \ + __ENUMERATE_IMAGE_FORMAT(jpeg, ".jpg") \ + __ENUMERATE_IMAGE_FORMAT(jxl, ".jxl") \ + __ENUMERATE_IMAGE_FORMAT(iff, ".lbm") \ + __ENUMERATE_IMAGE_FORMAT(pam, ".pam") \ + __ENUMERATE_IMAGE_FORMAT(pbm, ".pbm") \ + __ENUMERATE_IMAGE_FORMAT(pgm, ".pgm") \ + __ENUMERATE_IMAGE_FORMAT(png, ".png") \ + __ENUMERATE_IMAGE_FORMAT(ppm, ".ppm") \ + __ENUMERATE_IMAGE_FORMAT(qoi, ".qoi") \ + __ENUMERATE_IMAGE_FORMAT(tga, ".tga") \ + __ENUMERATE_IMAGE_FORMAT(tiff, ".tif") \ + __ENUMERATE_IMAGE_FORMAT(tiff, ".tiff") \ + __ENUMERATE_IMAGE_FORMAT(tvg, ".tvg") \ __ENUMERATE_IMAGE_FORMAT(tvg, ".webp") namespace Gfx { diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index 3f454ef2ef..4b300ae800 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -47,6 +47,7 @@ set(SOURCES ImageFormats/ImageDecoder.cpp ImageFormats/ISOBMFF/Boxes.cpp ImageFormats/ISOBMFF/Reader.cpp + ImageFormats/JBIG2Loader.cpp ImageFormats/JPEGLoader.cpp ImageFormats/JPEGXLLoader.cpp ImageFormats/JPEGWriter.cpp diff --git a/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp b/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp index 813471c6b2..de0977ce37 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ static ErrorOr> probe_and_sniff_for_appropriate_plugi { GIFImageDecoderPlugin::sniff, GIFImageDecoderPlugin::create }, { ICOImageDecoderPlugin::sniff, ICOImageDecoderPlugin::create }, { ILBMImageDecoderPlugin::sniff, ILBMImageDecoderPlugin::create }, + { JBIG2ImageDecoderPlugin::sniff, JBIG2ImageDecoderPlugin::create }, { JPEGImageDecoderPlugin::sniff, JPEGImageDecoderPlugin::create }, { JPEGXLImageDecoderPlugin::sniff, JPEGXLImageDecoderPlugin::create }, { PAMImageDecoderPlugin::sniff, PAMImageDecoderPlugin::create }, diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp new file mode 100644 index 0000000000..bad5393a61 --- /dev/null +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024, Nico Weber + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +// Spec: ITU-T_T_88__08_2018.pdf in the zip file here: +// https://www.itu.int/rec/T-REC-T.88-201808-I + +namespace Gfx { + +bool JBIG2ImageDecoderPlugin::sniff(ReadonlyBytes data) +{ + // JBIG2 spec, Annex D, D.4.1 ID string + u8 id_string[] = { 0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A }; + return data.starts_with(id_string); +} + +ErrorOr> JBIG2ImageDecoderPlugin::create(ReadonlyBytes) +{ + return Error::from_string_view("FIXME: Draw the rest of the owl"sv); +} + +} diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.h b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.h new file mode 100644 index 0000000000..6faf4f3e59 --- /dev/null +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024, Nico Weber + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Gfx { + +struct JBIG2LoadingContext; + +class JBIG2ImageDecoderPlugin : public ImageDecoderPlugin { +public: + static bool sniff(ReadonlyBytes); + static ErrorOr> create(ReadonlyBytes); + + virtual ~JBIG2ImageDecoderPlugin() override = default; +}; + +}