qgf.h (6719B)
1 // Copyright 2021 Nick Brassel (@tzarc) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #pragma once 5 6 // Quantum Graphics File "QGF" File Format. 7 // See https://docs.qmk.fm/#/quantum_painter_qgf for more information. 8 9 #include <stdint.h> 10 #include <stdbool.h> 11 12 #include "compiler_support.h" 13 #include "qp_stream.h" 14 #include "qp_internal.h" 15 16 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 // QGF structures 18 19 ///////////////////////////////////////// 20 // Common block header 21 22 typedef struct PACKED qgf_block_header_v1_t { 23 uint8_t type_id; // See each respective block type below. 24 uint8_t neg_type_id; // Negated type ID, used for detecting parsing errors. 25 uint32_t length : 24; // 24-bit blob length, allowing for block sizes of a maximum of 16MB. 26 } qgf_block_header_v1_t; 27 28 STATIC_ASSERT(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF"); 29 30 ///////////////////////////////////////// 31 // Graphics descriptor 32 33 #define QGF_GRAPHICS_DESCRIPTOR_TYPEID 0x00 34 35 typedef struct PACKED qgf_graphics_descriptor_v1_t { 36 qgf_block_header_v1_t header; // = { .type_id = 0x00, .neg_type_id = (~0x00), .length = 18 } 37 uint32_t magic : 24; // constant, equal to 0x464751 ("QGF") 38 uint8_t qgf_version; // constant, equal to 0x01 39 uint32_t total_file_size; // total size of the entire file, starting at offset zero 40 uint32_t neg_total_file_size; // negated value of total_file_size 41 uint16_t image_width; // in pixels 42 uint16_t image_height; // in pixels 43 uint16_t frame_count; // minimum of 1 44 } qgf_graphics_descriptor_v1_t; 45 46 STATIC_ASSERT(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF"); 47 48 #define QGF_MAGIC 0x464751 49 50 ///////////////////////////////////////// 51 // Frame offset descriptor 52 53 #define QGF_FRAME_OFFSET_DESCRIPTOR_TYPEID 0x01 54 55 typedef struct PACKED qgf_frame_offsets_v1_t { 56 qgf_block_header_v1_t header; // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = (N * sizeof(uint32_t)) } 57 uint32_t offset[0]; // '0' signifies that this struct is immediately followed by the frame offsets 58 } qgf_frame_offsets_v1_t; 59 60 STATIC_ASSERT(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); 61 62 ///////////////////////////////////////// 63 // Frame descriptor 64 65 #define QGF_FRAME_DESCRIPTOR_TYPEID 0x02 66 67 typedef struct PACKED qgf_frame_v1_t { 68 qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = 6 } 69 qp_image_format_t format : 8; // Frame format, see qp_internal_formats.h. 70 uint8_t flags; // Frame flags, see below. 71 painter_compression_t compression_scheme : 8; // Compression scheme, see qp.h. 72 uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented) 73 uint16_t delay; // frame delay time for animations (in units of milliseconds) 74 } qgf_frame_v1_t; 75 76 STATIC_ASSERT(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF"); 77 78 #define QGF_FRAME_FLAG_DELTA 0x02 79 #define QGF_FRAME_FLAG_TRANSPARENT 0x01 80 81 ///////////////////////////////////////// 82 // Frame palette descriptor 83 84 #define QGF_FRAME_PALETTE_DESCRIPTOR_TYPEID 0x03 85 86 typedef struct PACKED qgf_palette_entry_v1_t { 87 uint8_t h; // hue component: `[0,360)` degrees is mapped to `[0,255]` uint8_t. 88 uint8_t s; // saturation component: `[0,1]` is mapped to `[0,255]` uint8_t. 89 uint8_t v; // value component: `[0,1]` is mapped to `[0,255]` uint8_t. 90 } qgf_palette_entry_v1_t; 91 92 STATIC_ASSERT(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size"); 93 94 typedef struct PACKED qgf_palette_v1_t { 95 qgf_block_header_v1_t header; // = { .type_id = 0x03, .neg_type_id = (~0x03), .length = (N * 3 * sizeof(uint8_t)) } 96 qgf_palette_entry_v1_t hsv[0]; // N * hsv, where N is the number of palette entries depending on the frame format in the descriptor 97 } qgf_palette_v1_t; 98 99 STATIC_ASSERT(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); 100 101 ///////////////////////////////////////// 102 // Frame delta descriptor 103 104 #define QGF_FRAME_DELTA_DESCRIPTOR_TYPEID 0x04 105 106 typedef struct PACKED qgf_delta_v1_t { 107 qgf_block_header_v1_t header; // = { .type_id = 0x04, .neg_type_id = (~0x04), .length = 8 } 108 uint16_t left; // The left pixel location to draw the delta image 109 uint16_t top; // The top pixel location to draw the delta image 110 uint16_t right; // The right pixel location to to draw the delta image 111 uint16_t bottom; // The bottom pixel location to to draw the delta image 112 } qgf_delta_v1_t; 113 114 STATIC_ASSERT(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF"); 115 116 ///////////////////////////////////////// 117 // Frame data descriptor 118 119 #define QGF_FRAME_DATA_DESCRIPTOR_TYPEID 0x05 120 121 typedef struct PACKED qgf_data_v1_t { 122 qgf_block_header_v1_t header; // = { .type_id = 0x05, .neg_type_id = (~0x05), .length = N } 123 uint8_t data[0]; // 0 signifies that this struct is immediately followed by the length of data specified in the header 124 } qgf_data_v1_t; 125 126 STATIC_ASSERT(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); 127 128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 129 // QGF API 130 131 uint32_t qgf_get_total_size(qp_stream_t *stream); 132 bool qgf_validate_stream(qp_stream_t *stream); 133 bool qgf_validate_block_header(qgf_block_header_v1_t *desc, uint8_t expected_typeid, int32_t expected_length); 134 bool qgf_read_graphics_descriptor(qp_stream_t *stream, uint16_t *image_width, uint16_t *image_height, uint16_t *frame_count, uint32_t *total_bytes); 135 bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette, bool *is_panel_native); 136 void qgf_seek_to_frame_descriptor(qp_stream_t *stream, uint16_t frame_number); 137 bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay);