mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:32:45 +00:00 
			
		
		
		
	LibGfx: Add the start of a JBIG2 loader
JBIG2 is infamous for two things: 1. It's used in xerox scanners were it falsifies scanned numbers: https://www.dkriesel.com/en/blog/2013/0802_xerox-workcentres_are_switching_written_numbers_when_scanning 2. It was allegedly used in an iOS zero day, in a very cool way: https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html Needless to say, we need support for it in Serenity. (...because it's used in PDF files.) This adds all the scaffolding, but no actual implementation yet. It's enough for `file` to print the mime type of .jb2 files, but `image` can't do anything with the files yet.
This commit is contained in:
		
							parent
							
								
									d7ad134ae5
								
							
						
					
					
						commit
						58838db445
					
				
					 12 changed files with 86 additions and 22 deletions
				
			
		|  | @ -234,6 +234,10 @@ | |||
| #    cmakedefine01 ITEM_RECTS_DEBUG | ||||
| #endif | ||||
| 
 | ||||
| #ifndef JBIG2_DEBUG | ||||
| #    cmakedefine01 JBIG2_DEBUG | ||||
| #endif | ||||
| 
 | ||||
| #ifndef JOB_DEBUG | ||||
| #    cmakedefine01 JOB_DEBUG | ||||
| #endif | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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=", | ||||
|  |  | |||
|  | @ -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", | ||||
|  |  | |||
|  | @ -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<u8> { '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<u8> { 0x46, 0x4F, 0x52, 0x4F } }, | ||||
|     MimeType { .name = "image/x-jbig2"sv, .common_extensions = { ".jbig2"sv, ".jb2"sv }, .description = "JBIG2 image data"sv, .magic_bytes = Vector<u8> { 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<u8> { 0x50, 0x37, 0x0A } }, | ||||
|     MimeType { .name = "image/x-portable-bitmap"sv, .common_extensions = { ".pbm"sv }, .description = "PBM image data"sv, .magic_bytes = Vector<u8> { 0x50, 0x31, 0x0A } }, | ||||
|     MimeType { .name = "image/x-portable-graymap"sv, .common_extensions = { ".pgm"sv }, .description = "PGM image data"sv, .magic_bytes = Vector<u8> { 0x50, 0x32, 0x0A } }, | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ struct FileTypeFilter { | |||
| 
 | ||||
|     static FileTypeFilter image_files() | ||||
|     { | ||||
|         return FileTypeFilter { "Image Files", Vector<ByteString> { "png", "gif", "bmp", "dip", "pam", "pbm", "pgm", "ppm", "ico", "iff", "jpeg", "jpg", "jxl", "dds", "qoi", "tif", "tiff", "webp", "tvg" } }; | ||||
|         return FileTypeFilter { "Image Files", Vector<ByteString> { "png", "gif", "bmp", "dip", "pam", "pbm", "pgm", "ppm", "ico", "iff", "jb2", "jbig2", "jpeg", "jpg", "jxl", "dds", "qoi", "tif", "tiff", "webp", "tvg" } }; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,26 +16,28 @@ | |||
| #include <LibGfx/Forward.h> | ||||
| #include <LibGfx/Rect.h> | ||||
| 
 | ||||
| #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 { | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| #include <LibGfx/ImageFormats/ICOLoader.h> | ||||
| #include <LibGfx/ImageFormats/ILBMLoader.h> | ||||
| #include <LibGfx/ImageFormats/ImageDecoder.h> | ||||
| #include <LibGfx/ImageFormats/JBIG2Loader.h> | ||||
| #include <LibGfx/ImageFormats/JPEGLoader.h> | ||||
| #include <LibGfx/ImageFormats/JPEGXLLoader.h> | ||||
| #include <LibGfx/ImageFormats/PAMLoader.h> | ||||
|  | @ -39,6 +40,7 @@ static ErrorOr<OwnPtr<ImageDecoderPlugin>> 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 }, | ||||
|  |  | |||
							
								
								
									
										26
									
								
								Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2024, Nico Weber <thakis@chromium.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include <LibGfx/ImageFormats/JBIG2Loader.h> | ||||
| 
 | ||||
| // 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<NonnullOwnPtr<ImageDecoderPlugin>> JBIG2ImageDecoderPlugin::create(ReadonlyBytes) | ||||
| { | ||||
|     return Error::from_string_view("FIXME: Draw the rest of the owl"sv); | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										25
									
								
								Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2024, Nico Weber <thakis@chromium.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/MemoryStream.h> | ||||
| #include <AK/OwnPtr.h> | ||||
| #include <LibGfx/ImageFormats/ImageDecoder.h> | ||||
| 
 | ||||
| namespace Gfx { | ||||
| 
 | ||||
| struct JBIG2LoadingContext; | ||||
| 
 | ||||
| class JBIG2ImageDecoderPlugin : public ImageDecoderPlugin { | ||||
| public: | ||||
|     static bool sniff(ReadonlyBytes); | ||||
|     static ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> create(ReadonlyBytes); | ||||
| 
 | ||||
|     virtual ~JBIG2ImageDecoderPlugin() override = default; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nico Weber
						Nico Weber