From 3d909e812cb1abf8b2d53f7eedd5005001fb64ab Mon Sep 17 00:00:00 2001 From: dxan29a <29759390+dxan29a@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:31:54 -0700 Subject: [PATCH] Add pattern for JXL --- README.md | 1 + patterns/jxl.hexpat | 140 ++++++++++++++++++++++++ tests/patterns/test_data/jxl.hexpat.jxl | Bin 0 -> 82136 bytes 3 files changed, 141 insertions(+) create mode 100644 patterns/jxl.hexpat create mode 100644 tests/patterns/test_data/jxl.hexpat.jxl diff --git a/README.md b/README.md index 23047823..54f2a341 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | ISO | `application/x-iso9660-image` | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system | | Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files | | JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format | +| JPEG XL | `patterns/jxl.hexpat` | [`patterns/jxl.hexpat`](patterns/jxl.hexpat) | JPEG XL(JXL) image format | | LOC | | [`patterns/loc.hexpat`](patterns/loc.hexpat) | Minecraft Legacy Console Edition Language file | | Lua 5.1 | | [`patterns/lua51.hexpat`](patterns/lua51.hexpat) | Lua 5.1 bytecode | | Lua 5.2 | | [`patterns/lua52.hexpat`](patterns/lua52.hexpat) | Lua 5.2 bytecode | diff --git a/patterns/jxl.hexpat b/patterns/jxl.hexpat new file mode 100644 index 00000000..0cc7c60b --- /dev/null +++ b/patterns/jxl.hexpat @@ -0,0 +1,140 @@ +#pragma author dxan29a +#pragma description JPEG XL Container Format + +import std.io; +import std.mem; +#pragma endian big +#pragma MIME image/jxl + +enum Type : u32 { + SIGNATURE = 0x4A584C20, // JXL + FILETYPE = 0x66747970, // ftyp + LEVEL = 0x6A786C6C, // jxll + JUMBF = 0x6A756D62, // jumb + EXIF = 0x45786966, // Exif + XML = 0x786D6C20, // xml + BROTILCOMPRESSED = 0x62726F62, // brob + FRAMEIDX = 0x6A786C69, // jxlu + CODESTREAM = 0x6A786C63, // jxlc + PARTIALCODESTREAM = 0x6A786C70, // jxlp + BITSTREAMRECONSTRUCTION = 0x6A627264, // jbrd + GAINMAPIMAGE = 0x6872676D // hrgm +}; + +struct Header { + u32 LBox; + u64 lbox = LBox; + Type box_type; + if (LBox == 1) { + u64 XLBox; + u64xlbox = XLBox; + } else { + u64 xlbox = 0; + } +}; + +struct Signature { + u32 validation; +}; + +struct FileType { + u8 JXL_JXL[12]; +}; + +struct Level { + u8 Level; +}; + +struct Jumbf { + if (lbox == 1) { + u8 JumbfBoxes[xlbox - 16]; + } else { + u8 JumbfBoxes[lbox - 8]; + } +}; + +struct Exif { + u32 tiff_header_offset; + if (lbox == 1) { + u8 ExifPayload[xlbox - 16 - sizeof(tiff_header_offset)]; + } else { + u8 ExifPayload[lbox - 8 - sizeof(tiff_header_offset)]; + } +}; + +struct XML { + if (lbox == 1) { + u8 XMLdata[xlbox - 16 - sizeof(tiff_header_offset)]; + } else { + u8 XMLdata[lbox - 8 - sizeof(tiff_header_offset)]; + } +}; + +struct PartialCodeStream { + u32 Index; + if (lbox == 1) { + u8 CodeStream[xlbox - 16 - sizeof(Index)]; + } else { + u8 CodeStream[lbox - 8 - sizeof(Index)]; + } +}; + +struct BrotilCompressed { + u32 PayloadTypes; + if (lbox == 1) { + u8 RemainingBytes[xlbox - 16 - sizeof(PayloadTypes)]; + } else { + u8 RemainingBytes[lbox - 8 - sizeof(PayloadTypes)]; + } +}; + +struct FrameIndex { + if (lbox == 1) { + u8 RemainingBytes[xlbox - 16]; + } else { + u8 RemainingBytes[lbox - 8]; + } +}; + +struct BitStreamReconstruction { + if (lbox == 1) { + u8 RemainingBytes[xlbox - 16]; + } else { + u8 RemainingBytes[lbox - 8]; + } +}; + +struct GainMapImage { + if (lbox == 1) { + u8 GainMapImage[xlbox - 16]; + } else { + u8 GainMapImage[lbox - 8]; + } +}; + +struct UnknownBox { + if (lbox == 1) { + u8 remaining_bytes[xlbox - 16]; + } else { + u8 remaining_bytes[lbox - 8]; + } +}; + +struct Box { + Header header; + match (header.box_type) { + (Type::SIGNATURE): Signature signature; + (Type::FILETYPE): FileType filetype; + (Type::LEVEL): Level level; + (Type::JUMBF): Jumbf jumbf; + (Type::EXIF): Exif exif; + (Type::PARTIALCODESTREAM): PartialCodeStream partial_codestream; + (Type::FRAMEIDX): FrameIndex frame_index; + (Type::BROTILCOMPRESSED): BrotilCompressed brotil_compressed; + (Type::BITSTREAMRECONSTRUCTION): BitStreamReconstruction bitstream_reconstruction; + (Type::GAINMAPIMAGE): GainMapImage gain_map_image;; + (_): UnknownBox unknown_box; + } +}; + +Box boxes[while(!std::mem::eof())] @ 0x00; \ No newline at end of file diff --git a/tests/patterns/test_data/jxl.hexpat.jxl b/tests/patterns/test_data/jxl.hexpat.jxl new file mode 100644 index 0000000000000000000000000000000000000000..65b69e1afa7c08878ace709018d3610ad39c0489 GIT binary patch literal 82136 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 Q9?oUqJU46=uOK4-3lCxVI{*Lx literal 0 HcmV?d00001