qgf.h 6.5 KB

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