qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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);