mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
151 lines
3.4 KiB
C
151 lines
3.4 KiB
C
#pragma once
|
|
|
|
#ifndef MINI_QOI_H
|
|
#define MINI_QOI_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#define MQOI_RGB_HASH(px) ((px.r * 3 + px.g * 5 + px.b * 7) & 0b00111111)
|
|
#define MQOI_RGBA_HASH(px) ((px.r * 3 + px.g * 5 + px.b * 7 + px.a * 11) & 0b00111111)
|
|
|
|
#define MQOI_HEADER_SIZE (14)
|
|
|
|
#define MQOI_MASK_OP_2B (0b11000000)
|
|
#define MQOI_MASK_OP_8B (0b11111111)
|
|
|
|
#define MQOI_MASK_OP_LUMA_DG (0b00111111)
|
|
#define MQOI_MASK_OP_RUN (0b00111111)
|
|
|
|
// basic types
|
|
|
|
typedef enum
|
|
{
|
|
MQOI_DESC_OK = 0, // The descriptor is valid
|
|
MQOI_DESC_INVALID_MAGIC, // The magic value isn't correct
|
|
MQOI_DESC_INVALID_CHANNELS, // The channel number isn't valid
|
|
MQOI_DESC_INVALID_COLORSPACE, // The colorspace isn't valid
|
|
} mqoi_desc_err_t;
|
|
|
|
typedef enum
|
|
{
|
|
MQOI_OP2_INDEX = (0b00 << 6),
|
|
MQOI_OP2_DIFF = (0b01 << 6),
|
|
MQOI_OP2_LUMA = (0b10 << 6),
|
|
MQOI_OP2_RUN = (0b11 << 6),
|
|
MQOI_OP8_RUN_RGB = (0b11111110),
|
|
MQOI_OP8_RUN_RGBA = (0b11111111),
|
|
} mqoi_op_t;
|
|
|
|
typedef enum
|
|
{
|
|
MQOI_CHANNELS_RGB = 3,
|
|
MQOI_CHANNELS_RGBA,
|
|
} mqoi_channels_t;
|
|
|
|
typedef enum
|
|
{
|
|
MQOI_COLORSPACE_SRGB = 0,
|
|
MQOI_COLORSPACE_LINEAR = 1,
|
|
} mqoi_colorspace_t;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t r, g, b;
|
|
};
|
|
uint8_t value[3];
|
|
} mqoi_rgb_t;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t r, g, b, a;
|
|
};
|
|
uint8_t value[4];
|
|
} mqoi_rgba_t;
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t head;
|
|
|
|
uint8_t magic[4];
|
|
uint8_t width[4]; // big-endian width
|
|
uint8_t height[4]; // big-endian height
|
|
uint8_t channels;
|
|
uint8_t colorspace;
|
|
} mqoi_desc_t;
|
|
|
|
// ==== chunks ====
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t head;
|
|
union
|
|
{
|
|
mqoi_rgb_t rgb;
|
|
mqoi_rgba_t rgba;
|
|
uint8_t drdb;
|
|
};
|
|
};
|
|
uint8_t value[5];
|
|
} mqoi_chunk_t;
|
|
|
|
// ==== codecs ====
|
|
|
|
typedef struct
|
|
{
|
|
mqoi_rgba_t hashtable[64];
|
|
mqoi_rgba_t prev_px;
|
|
mqoi_chunk_t working_chunk;
|
|
uint8_t working_chunk_size;
|
|
} mqoi_enc_t;
|
|
|
|
typedef struct
|
|
{
|
|
mqoi_rgba_t hashtable[64];
|
|
mqoi_rgba_t prev_px;
|
|
mqoi_chunk_t curr_chunk;
|
|
uint8_t curr_chunk_head : 4;
|
|
uint8_t curr_chunk_size : 4;
|
|
uint32_t pix_left;
|
|
} mqoi_dec_t;
|
|
|
|
// ==== mqoi_desc_t ====
|
|
|
|
void mqoi_desc_init(mqoi_desc_t *desc);
|
|
void mqoi_desc_push(mqoi_desc_t *desc, uint8_t byte);
|
|
uint8_t *mqoi_desc_pop(mqoi_desc_t *desc);
|
|
uint8_t mqoi_desc_verify(mqoi_desc_t *desc, uint32_t *w, uint32_t *h);
|
|
bool mqoi_desc_done(const mqoi_desc_t *desc);
|
|
|
|
/* the encoder is still WIP
|
|
void mqoi_enc_init(mqoi_enc_t * enc);
|
|
void mqoi_enc_push(mqoi_enc_t * enc, mqoi_rgba_t * pix)
|
|
mqoi_chunk_t * mqoi_enc_pop(mqoi_enc_t * enc, uint8_t * size);
|
|
*/
|
|
|
|
// ==== mqoi_dec_t ====
|
|
|
|
void mqoi_dec_init(mqoi_dec_t *dec, uint32_t n_pix);
|
|
void mqoi_dec_push(mqoi_dec_t *dec, uint8_t byte);
|
|
uint8_t mqoi_dec_take(mqoi_dec_t *dec, const uint8_t *bytes);
|
|
mqoi_rgba_t *mqoi_dec_pop(mqoi_dec_t *dec);
|
|
bool mqoi_dec_done(const mqoi_dec_t *dec);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|