mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Add json support for glb files (#412)
* patterns: Add json support for glb files This makes it possible to separate display the different buffer views, accessors and images (even visualizing them). Unfortunately the data within the JSON gets sometimes corrupted and this is the reason, why it parses the JSON multiple times at some places. * Use original style and only single json variable * patterns: Reuse json from global variable in gltf * patterns: Check component type in gltf only once * patterns: Fix gltf pattern and add formatting Removes the duplicate definition of `component_type_t` and also removes the need to pass the `component_type` to `stride_type_t`.
This commit is contained in:
@@ -22,13 +22,18 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma author H. Utku Maden
|
#pragma author H. Utku Maden, xZise
|
||||||
#pragma description GL Transmission Format binary 3D model (.glb)
|
#pragma description GL Transmission Format binary 3D model (.glb)
|
||||||
#pragma MIME model/gltf-binary
|
#pragma MIME model/gltf-binary
|
||||||
|
#pragma magic [67 6C 54 46] @ 0x00
|
||||||
|
|
||||||
import std.mem;
|
import std.mem;
|
||||||
import std.io;
|
import std.io;
|
||||||
import type.magic;
|
import type.magic;
|
||||||
|
import std.core;
|
||||||
|
#ifdef __IMHEX__
|
||||||
|
import hex.type.json;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The glTF magic section.
|
* @brief The glTF magic section.
|
||||||
@@ -53,7 +58,15 @@ enum gltf_chunk_type_t : u32 {
|
|||||||
struct gltf_chunk_t {
|
struct gltf_chunk_t {
|
||||||
u32 length; /**< Length of this chunk. */
|
u32 length; /**< Length of this chunk. */
|
||||||
gltf_chunk_type_t type [[format("gltf_format")]]; /**< Type of the chunk. JSON or BIN expected. */
|
gltf_chunk_type_t type [[format("gltf_format")]]; /**< Type of the chunk. JSON or BIN expected. */
|
||||||
u8 string[length]; /**< The chunk data. */
|
#ifndef __IMHEX__
|
||||||
|
u8 data[length]; /**< The chunk data. */
|
||||||
|
#endif
|
||||||
|
#ifdef __IMHEX__
|
||||||
|
match (type) {
|
||||||
|
(gltf_chunk_type_t::JSON): hex::type::Json<length> json;
|
||||||
|
(gltf_chunk_type_t::BIN): u8 data[length];
|
||||||
|
} /**< The chunk data. */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
fn gltf_format(gltf_chunk_type_t x)
|
fn gltf_format(gltf_chunk_type_t x)
|
||||||
@@ -64,7 +77,162 @@ fn gltf_format(gltf_chunk_type_t x)
|
|||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
gltf_magic_t magic @ 0x00;
|
struct stride_type_t<InnerType, auto Stride> {
|
||||||
gltf_chunk_t chunks[while(!std::mem::eof())] @ $;
|
InnerType value [[inline]];
|
||||||
|
if (Stride > 0) {
|
||||||
|
padding[Stride - sizeof(value)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::assert_warn(std::mem::size() == magic.length, "file size mismatch");
|
enum component_types_t : u64 {
|
||||||
|
BYTE = 5120,
|
||||||
|
UNSIGNED_BYTE = 5121,
|
||||||
|
SHORT = 5122,
|
||||||
|
UNSIGNED_SHORT = 5123,
|
||||||
|
UNSIGNED_INT = 5125,
|
||||||
|
FLOAT = 5126,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn component_type_format(component_types_t component_type)
|
||||||
|
{
|
||||||
|
if (component_type == component_types_t::BYTE) return "s8";
|
||||||
|
else if (component_type == component_types_t::UNSIGNED_BYTE) return "u8";
|
||||||
|
else if (component_type == component_types_t::SHORT) return "s16";
|
||||||
|
else if (component_type == component_types_t::UNSIGNED_SHORT) return "u16";
|
||||||
|
else if (component_type == component_types_t::UNSIGNED_INT) return "u32";
|
||||||
|
else if (component_type == component_types_t::FLOAT) return "float";
|
||||||
|
|
||||||
|
return std::format("{}", component_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct component_type_t<auto component_type> {
|
||||||
|
match (component_type) {
|
||||||
|
(component_types_t::BYTE): s8 value;
|
||||||
|
(component_types_t::UNSIGNED_BYTE): u8 value;
|
||||||
|
(component_types_t::SHORT): s16 value;
|
||||||
|
(component_types_t::UNSIGNED_SHORT): u16 value;
|
||||||
|
(component_types_t::UNSIGNED_INT): u32 value;
|
||||||
|
(component_types_t::FLOAT): float value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct scalar_t<auto component_type> {
|
||||||
|
component_type_t<component_type> scalar [[inline]];
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct vec2_t<auto component_type> {
|
||||||
|
component_type_t<component_type> x;
|
||||||
|
component_type_t<component_type> y;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct vec3_t<auto component_type> {
|
||||||
|
component_type_t<component_type> x;
|
||||||
|
component_type_t<component_type> y;
|
||||||
|
component_type_t<component_type> z;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct vec4_t<auto component_type> {
|
||||||
|
component_type_t<component_type> x;
|
||||||
|
component_type_t<component_type> y;
|
||||||
|
component_type_t<component_type> z;
|
||||||
|
component_type_t<component_type> w;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct mat2_t<auto component_type> {
|
||||||
|
component_type_t<component_type> a11, a21;
|
||||||
|
component_type_t<component_type> a12, a22;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct mat3_t<auto component_type> {
|
||||||
|
component_type_t<component_type> a11, a21, a31;
|
||||||
|
component_type_t<component_type> a12, a22, a32;
|
||||||
|
component_type_t<component_type> a13, a23, a33;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct mat4_t<auto component_type> {
|
||||||
|
component_type_t<component_type> a11, a21, a31, a41;
|
||||||
|
component_type_t<component_type> a12, a22, a32, a42;
|
||||||
|
component_type_t<component_type> a13, a23, a33, a43;
|
||||||
|
component_type_t<component_type> a14, a24, a34, a44;
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
fn mem_cnt(auto value) {
|
||||||
|
return std::core::member_count(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn has_mem(auto value, str member) {
|
||||||
|
return std::core::has_member(value, member);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct accessor_t {
|
||||||
|
u64 accessor_index = std::core::array_index();
|
||||||
|
u64 view_index = glb.json_chunk.json.accessors[accessor_index].bufferView [[export]];
|
||||||
|
u64 view_offset = glb.json_chunk.json.bufferViews[view_index].byteOffset [[export]];
|
||||||
|
if (has_mem(glb.json_chunk.json.bufferViews[view_index], "byteStride")) {
|
||||||
|
u64 byte_stride = glb.json_chunk.json.bufferViews[view_index].byteStride [[export]];
|
||||||
|
} else {
|
||||||
|
u64 byte_stride = 0 [[export]];
|
||||||
|
}
|
||||||
|
if (has_mem(glb.json_chunk.json.accessors[accessor_index], "byteOffset")) {
|
||||||
|
u64 accessor_offset = glb.json_chunk.json.accessors[accessor_index].byteOffset [[export]];
|
||||||
|
} else {
|
||||||
|
u64 accessor_offset = 0 [[export]];
|
||||||
|
}
|
||||||
|
view_offset = view_offset + accessor_offset;
|
||||||
|
u64 count_elements = glb.json_chunk.json.accessors[accessor_index].count;
|
||||||
|
component_types_t component_type = glb.json_chunk.json.accessors[accessor_index].componentType [[export]];
|
||||||
|
str element_type = glb.json_chunk.json.accessors[accessor_index].type [[export]];
|
||||||
|
|
||||||
|
match (element_type) {
|
||||||
|
("SCALAR"): stride_type_t<scalar_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("VEC2"): stride_type_t<vec2_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("VEC3"): stride_type_t<vec3_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("VEC4"): stride_type_t<vec4_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("MAT2"): stride_type_t<mat2_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("MAT3"): stride_type_t<mat3_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
("MAT4"): stride_type_t<mat4_t<parent.component_type>, byte_stride> content[count_elements] @ view_offset + addressof(glb.chunks[0].data);
|
||||||
|
}
|
||||||
|
} [[format("accessor_format")]];
|
||||||
|
|
||||||
|
fn accessor_format(accessor_t accessor) {
|
||||||
|
return std::format("{}<{}>[{}]", accessor.element_type, accessor.component_type, accessor.count_elements);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image_buffer_t {
|
||||||
|
u64 image_index = std::core::array_index();
|
||||||
|
u64 buffer_view_index = glb.json_chunk.json.images[image_index].bufferView;
|
||||||
|
u64 byte_offset = glb.json_chunk.json.bufferViews[buffer_view_index].byteOffset;
|
||||||
|
u64 byte_length = glb.json_chunk.json.bufferViews[buffer_view_index].byteLength;
|
||||||
|
u8 image[byte_length] @ addressof(glb.chunks[0].data) + byte_offset;
|
||||||
|
} [[hex::visualize("image", image)]];
|
||||||
|
|
||||||
|
struct buffer_view_t {
|
||||||
|
u64 buffer_view_index = std::core::array_index();
|
||||||
|
u64 byte_offset = glb.json_chunk.json.bufferViews[buffer_view_index].byteOffset;
|
||||||
|
u64 byte_length = glb.json_chunk.json.bufferViews[buffer_view_index].byteLength;
|
||||||
|
u8 data[byte_length] @ addressof(glb.chunks[0].data) + byte_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct glb_file_t {
|
||||||
|
gltf_magic_t magic;
|
||||||
|
gltf_chunk_t json_chunk;
|
||||||
|
gltf_chunk_t chunks[while(!std::mem::eof())];
|
||||||
|
|
||||||
|
std::assert_warn(std::mem::size() == magic.length, "file size mismatch");
|
||||||
|
};
|
||||||
|
|
||||||
|
glb_file_t glb @ 0x00;
|
||||||
|
|
||||||
|
#ifdef __IMHEX__
|
||||||
|
struct glb_objects_t {
|
||||||
|
if (std::core::member_count(glb.chunks) == 1) {
|
||||||
|
if (has_mem(glb.json_chunk.json, "images")) {
|
||||||
|
image_buffer_t images[mem_cnt(glb.json_chunk.json.images)];
|
||||||
|
}
|
||||||
|
buffer_view_t buffer_views[mem_cnt(glb.json_chunk.json.bufferViews)];
|
||||||
|
accessor_t accessors[mem_cnt(glb.json_chunk.json.accessors)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
glb_objects_t objects @ 0x00;
|
||||||
|
#endif
|
||||||
@@ -214,6 +214,11 @@ struct Chunks {
|
|||||||
chunk_t iend_chunk [[comment("Image End Chunk")]];
|
chunk_t iend_chunk [[comment("Image End Chunk")]];
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 visualizer[std::mem::size()] @ 0x00 [[sealed, hex::visualize("image", this)]];
|
struct Png {
|
||||||
header_t header @ 0x00 [[comment("PNG file signature"), name("Signature")]];
|
header_t header [[comment("PNG file signature"), name("Signature")]];
|
||||||
Chunks chunks @ 0x08 [[name("Chunks")]];
|
Chunks chunks [[name("Chunks")]];
|
||||||
|
u128 length = $ - addressof(this);
|
||||||
|
u8 visualizer[length] @ addressof(this) [[sealed, hex::visualize("image", this), no_unique_address]];
|
||||||
|
};
|
||||||
|
|
||||||
|
Png png @ 0x00;
|
||||||
224
patterns/png2.hexpat
Normal file
224
patterns/png2.hexpat
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
#pragma description PNG image
|
||||||
|
|
||||||
|
#pragma MIME image/png
|
||||||
|
#pragma endian big
|
||||||
|
|
||||||
|
import std.mem;
|
||||||
|
|
||||||
|
struct header_t {
|
||||||
|
u8 highBitByte;
|
||||||
|
char signature[3];
|
||||||
|
char dosLineEnding[2];
|
||||||
|
char dosEOF;
|
||||||
|
char unixLineEnding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct actl_t {
|
||||||
|
u32 frames [[comment("Total № of frames in animation")]];
|
||||||
|
u32 plays [[comment("№ of times animation will loop")]];
|
||||||
|
} [[comment("Animation control chunk"), name("acTL")]];
|
||||||
|
|
||||||
|
enum ColorType: u8 {
|
||||||
|
Grayscale = 0x0,
|
||||||
|
RGBTriple = 0x2,
|
||||||
|
Palette,
|
||||||
|
GrayscaleAlpha,
|
||||||
|
RGBA = 0x6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Interlacing: u8 {
|
||||||
|
None,
|
||||||
|
Adam7
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ihdr_t {
|
||||||
|
u32 width [[comment("Image width")]];
|
||||||
|
u32 height [[comment("Image height")]];
|
||||||
|
u8 bit_depth;
|
||||||
|
ColorType color_type [[comment("PNG Image Type")]];
|
||||||
|
u8 compression_method [[comment("Only 0x0 = zlib supported by most")]];
|
||||||
|
u8 filter_method [[comment("Only 0x0 = adaptive supported by most")]];
|
||||||
|
Interlacing interlacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sRGB: u8 {
|
||||||
|
Perceptual = 0x0,
|
||||||
|
RelativeColorimetric,
|
||||||
|
Saturation,
|
||||||
|
AbsoluteColorimetric
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Unit: u8 {
|
||||||
|
Unknown,
|
||||||
|
Meter
|
||||||
|
};
|
||||||
|
|
||||||
|
struct phys_t {
|
||||||
|
u32 ppu_x [[comment("Pixels per unit, X axis")]];
|
||||||
|
u32 ppu_y [[comment("Pixels per unit, Y axis")]];
|
||||||
|
Unit unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BlendOp: u8 {
|
||||||
|
Source = 0x0,
|
||||||
|
Over
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DisposeOp: u8 {
|
||||||
|
None = 0x0,
|
||||||
|
Background,
|
||||||
|
Previous
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fctl_t {
|
||||||
|
u32 sequence_no [[comment("Sequence №")]];
|
||||||
|
u32 width [[comment("Frame width")]];
|
||||||
|
u32 height;
|
||||||
|
u32 xoff;
|
||||||
|
u32 yoff;
|
||||||
|
u16 delay_num;
|
||||||
|
u16 delay_den;
|
||||||
|
DisposeOp dispose_op;
|
||||||
|
BlendOp blend_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fdat_t {
|
||||||
|
u32 sequence_no;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn text_len() {
|
||||||
|
u64 len = parent.parent.length - ($ - addressof(parent.keyword));
|
||||||
|
return len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct itxt_t {
|
||||||
|
char keyword[];
|
||||||
|
u8 compression_flag;
|
||||||
|
u8 compression_method;
|
||||||
|
char language_tag[];
|
||||||
|
char translated_keyword[];
|
||||||
|
char text[text_len()];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ztxt_t {
|
||||||
|
char keyword[];
|
||||||
|
u8 compression_method;
|
||||||
|
char text[text_len()];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct text_t {
|
||||||
|
char keyword[];
|
||||||
|
char text[text_len()];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iccp_t {
|
||||||
|
char keyword[];
|
||||||
|
u8 compression_method;
|
||||||
|
u8 compressed_profile[text_len()];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct palette_entry_t {
|
||||||
|
u24 color;
|
||||||
|
} [[inline]];
|
||||||
|
|
||||||
|
struct chrm_t {
|
||||||
|
u32 white_point_x;
|
||||||
|
u32 white_point_y;
|
||||||
|
u32 red_x;
|
||||||
|
u32 red_y;
|
||||||
|
u32 green_x;
|
||||||
|
u32 green_y;
|
||||||
|
u32 blue_x;
|
||||||
|
u32 blue_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct time_t {
|
||||||
|
u16 year;
|
||||||
|
u8 month;
|
||||||
|
u8 day;
|
||||||
|
u8 hour;
|
||||||
|
u8 minute;
|
||||||
|
u8 second;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chunk_t {
|
||||||
|
u32 length [[color("17BECF")]];
|
||||||
|
char name[4];
|
||||||
|
|
||||||
|
#define IHDR_k "IHDR"
|
||||||
|
#define PLTE_k "PLTE"
|
||||||
|
#define sRGB_k "sRGB"
|
||||||
|
#define pHYs_k "pHYs"
|
||||||
|
#define iTXt_k "iTXt"
|
||||||
|
#define tEXt_k "tEXt"
|
||||||
|
#define zTXt_k "zTXt"
|
||||||
|
#define IDAT_k "IDAT"
|
||||||
|
#define IEND_k "IEND"
|
||||||
|
#define gAMA_k "gAMA"
|
||||||
|
#define iCCP_k "iCCP"
|
||||||
|
#define acTL_k "acTL"
|
||||||
|
#define fdAT_k "fdAT"
|
||||||
|
#define fcTL_k "fcTL"
|
||||||
|
#define cHRM_k "cHRM"
|
||||||
|
#define tIME_k "tIME"
|
||||||
|
|
||||||
|
if (name == IHDR_k) {
|
||||||
|
ihdr_t ihdr [[comment("Image Header chunk"), name("IHDR")]];
|
||||||
|
} else if (name == PLTE_k) {
|
||||||
|
palette_entry_t entries[length / 3];
|
||||||
|
} else if (name == sRGB_k) {
|
||||||
|
sRGB srgb;
|
||||||
|
} else if (name == pHYs_k) {
|
||||||
|
phys_t phys;
|
||||||
|
} else if (name == acTL_k) {
|
||||||
|
actl_t actl [[comment("Animation control chunk")]];
|
||||||
|
} else if (name == fcTL_k) {
|
||||||
|
fctl_t fctl [[comment("Frame control chunk")]];
|
||||||
|
} else if (name == iTXt_k) {
|
||||||
|
itxt_t text;
|
||||||
|
} else if (name == gAMA_k) {
|
||||||
|
u32 gamma [[name("image gamma"), comment("4 byte unsigned integer representing gamma times 100000")]];
|
||||||
|
} else if (name == iCCP_k) {
|
||||||
|
iccp_t iccp;
|
||||||
|
} else if (name == tEXt_k) {
|
||||||
|
text_t text;
|
||||||
|
} else if (name == zTXt_k) {
|
||||||
|
ztxt_t text;
|
||||||
|
} else if (name == iCCP_k) {
|
||||||
|
iccp_t iccp;
|
||||||
|
} else if (name == fdAT_k) {
|
||||||
|
fdat_t fdat [[comment("Frame data chunk")]];
|
||||||
|
u8 data[length-sizeof(u32)];
|
||||||
|
} else if (name == cHRM_k) {
|
||||||
|
chrm_t chrm;
|
||||||
|
} else if (name == tIME_k) {
|
||||||
|
time_t time;
|
||||||
|
} else {
|
||||||
|
u8 data[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 crc;
|
||||||
|
} [[name(chunkValueName(this))]];
|
||||||
|
|
||||||
|
fn chunkValueName(ref chunk_t chunk) {
|
||||||
|
return chunk.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chunk_set {
|
||||||
|
chunk_t chunks[while(builtin::std::mem::read_string($ + 4, 4) != "IEND")] [[inline]];
|
||||||
|
} [[inline]];
|
||||||
|
|
||||||
|
struct Chunks {
|
||||||
|
chunk_t ihdr_chunk [[comment("PNG Header chunk")]];
|
||||||
|
chunk_set set [[comment("PNG Chunks"), name("Chunks"), inline]];
|
||||||
|
chunk_t iend_chunk [[comment("Image End Chunk")]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Png {
|
||||||
|
header_t header [[comment("PNG file signature"), name("Signature")]];
|
||||||
|
Chunks chunks [[name("Chunks")]];
|
||||||
|
u128 length = $ - addressof(this);
|
||||||
|
u8 visualizer[length] @ addressof(this) [[sealed, hex::visualize("image", this), no_unique_address]];
|
||||||
|
};
|
||||||
|
|
||||||
|
Png png @ 0x00;
|
||||||
Reference in New Issue
Block a user