56#define QOI_ALLOW_MEM_ALLOC 1
57#define QOI_ALLOW_MEM_FREE 1
59#if QOI_ALLOW_MEM_ALLOC
68#define QOI_TAG_MASK 0x3F
71#define QOI_OP_RGB 0xFE
73#define QOI_OP_RGBA 0xFF
75#define QOI_OP_INDEX 0x00
77#define QOI_OP_DIFF 0x40
79#define QOI_OP_LUMA 0x80
81#define QOI_OP_RUN 0xC0
88static const uint8_t
QOI_MAGIC[4] = {
'q',
'o',
'i',
'f'};
91static const uint8_t
QOI_PADDING[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
124 uint32_t concatenated_pixel_values;
144 uint32_t buffer_offset;
149 uint32_t pixel_offset;
151 uint32_t pixels_written;
188#if QOI_ALLOW_MEM_ALLOC
204static inline void qoi_enc_diff(
qoi_enc_t *enc, uint8_t red_diff, uint8_t green_diff, uint8_t blue_diff);
213 uint8_t* bytes = (uint8_t*)&value;
214 uint32_t be_value = (uint32_t) (
231 bytes[0] = (value >> 24);
232 bytes[1] = (value >> 16);
233 bytes[2] = (value >> 8);
236 return *((uint32_t*)bytes);
264 pixel->
green = green;
277 pixel->
green = green;
279 pixel->
alpha = alpha;
286 if (pixel == NULL)
return;
295 return (pixel.
red * 3 + pixel.
green * 5 + pixel.
blue * 7 + pixel.
alpha * 11) % 64;
303 if (desc == NULL)
return false;
344 if (dest == NULL || desc == NULL)
return;
346 uint8_t *
byte = (uint8_t*)dest;
349 *(uint32_t*)
byte = *(uint32_t*)
QOI_MAGIC;
353 uint32_t* dimension_ptr = (uint32_t*)&
byte[4];
404 (uint8_t)(red_diff + 2) << 4 |
405 (uint8_t)(green_diff + 2) << 2 |
406 (uint8_t)(blue_diff + 2);
449 cur_pixel.
alpha = 255;
490 int8_t red_diff, green_diff, blue_diff;
497 dr_dg = red_diff - green_diff;
498 db_dg = blue_diff - green_diff;
501 red_diff >= -2 && red_diff <= 1 &&
502 green_diff >= -2 && green_diff <= 1 &&
503 blue_diff >= -2 && blue_diff <= 1
510 dr_dg >= -8 && dr_dg <= 7 &&
511 green_diff >= -32 && green_diff <= 31 &&
512 db_dg >= -8 && db_dg <= 7
539 if (enc == NULL || desc == NULL)
return false;
541 for (uint8_t element = 0; element < 64; element++) {
561#if QOI_ALLOW_MEM_ALLOC
578 if (enc == NULL || newBuffer == NULL || len == 0)
return false;
580 #if QOI_ALLOW_MEM_ALLOC
581 if (shouldFreePrevBuffer ==
true && enc->
enc_buffer)
600#if QOI_ALLOW_MEM_ALLOC
603 if (enc == NULL || len == 0)
return false;
605 uint8_t *newBuffer = (uint8_t*)malloc(len *
sizeof(uint8_t));;
607 if (newBuffer == NULL)
612 if (shouldFreePrevBuffer ==
true && enc->
enc_buffer) {
626#if QOI_ALLOW_MEM_ALLOC
633 goto qoi_enc_free_buffer_skip;
642qoi_enc_free_buffer_skip:
652 if (enc == NULL)
return false;
static void qoi_enc_rgba(qoi_enc_t *enc, qoi_pixel_t px)
Place the RGBA information into the QOI file.
static uint32_t qoi_get_be32(uint32_t value)
Extract a 32-bit big endian integer regardless of endianness.
#define QOI_OP_RGB
11111110: Followed by 3 bytes of RGB data, representing the color of the pixel. This is used when the...
void qoi_set_pixel_rgba(qoi_pixel_t *pixel, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
Sets the RGBA pixel by a certain pixel value including an transparency alpha value.
#define QOI_OP_INDEX
00xxxxxx: Use the color at the index xx in the color index array.
bool qoi_desc_init(qoi_desc_t *desc)
Initalize the QOI desciptor to the default values.
void write_qoi_header(qoi_desc_t *desc, void *dest)
Writes the QOI metadata information to the file.
void qoi_set_dimensions(qoi_desc_t *desc, uint32_t width, uint32_t height)
Sets the image dimensions of an image for QOI descriptor.
bool read_qoi_header(qoi_desc_t *desc, void *data)
static void qoi_enc_luma(qoi_enc_t *enc, uint8_t green_diff, uint8_t dr_dg, uint8_t db_dg)
Place the luma values into the QOI opcode.
void qoi_set_pixel_rgb(qoi_pixel_t *pixel, uint8_t red, uint8_t green, uint8_t blue)
Sets the RGB pixel by a certain pixel value.
static const uint8_t QOI_MAGIC[4]
QOI magic number.
#define QOI_OP_RGBA
11111110: Followed by 3 bytes of RGB data and 1 byte of alpha data, representing the color of the pix...
static const uint8_t QOI_PADDING[8]
QOI end of file padding bytes.
static void qoi_enc_diff(qoi_enc_t *enc, uint8_t red_diff, uint8_t green_diff, uint8_t blue_diff)
Place the differences between color values into the QOI opcode.
void qoi_encode_chunk(qoi_desc_t *desc, qoi_enc_t *enc, void *qoi_pixel_bytes)
Encode pixel data into QOI opcodes.
static bool qoi_cmp_pixel(qoi_pixel_t pixel1, qoi_pixel_t pixel2, const uint8_t channels)
Compares two pixels for the same color.
static void qoi_enc_run(qoi_enc_t *enc)
Place the run length of a pixel color information into the QOI opcode.
bool qoi_enc_init(qoi_desc_t *desc, qoi_enc_t *enc)
Initalize the QOI encoder to the default state.
void qoi_initalize_pixel(qoi_pixel_t *pixel)
Initalizes the pixels to the default state.
void qoi_set_channels(qoi_desc_t *desc, uint8_t channels)
Sets the amount of channels of an image for QOI descriptor.
#define QOI_OP_LUMA
10xxxxxx: The color is represented by a luminance value and two chroma values.
static int32_t qoi_get_index_position(qoi_pixel_t pixel)
Hashing function for pixels: up to 64 possible hash values.
#define QOI_OP_DIFF
01xxxxxx: The color is the same as the previous pixel, with each channel optionally modified by a sma...
bool qoi_enc_set_buffer(qoi_enc_t *enc, void *newBuffer, uint32_t len, bool shouldFreePrevBuffer)
Sets a buffer for the QOI encoder, automatically free if free buffer flag is set.
bool qoi_enc_reset_buffer(qoi_enc_t *enc)
Resets the buffer of the QOI encoder to the default state.
bool qoi_enc_alloc_buffer(qoi_enc_t *enc, uint32_t data_len, bool shouldFreePrevBuffer)
Allocates a buffer for the QOI encoder.
static void qoi_enc_index(qoi_enc_t *enc, uint8_t index_pos)
Place the index position of the buffer into the QOI file.
bool qoi_enc_free_buffer(qoi_enc_t *enc)
Frees the buffer allocated for the QOI encoder.
#define QOI_OP_RUN
11xxxxxx: The color is the same as the previous pixel, and this run continues for xx pixels.
static void qoi_enc_rgb(qoi_enc_t *enc, qoi_pixel_t px)
Place the RGB information into the QOI file.
static uint32_t qoi_to_be32(uint32_t value)
Write a 32-bit big endian integer regardless of endianness.
void qoi_set_colorspace(qoi_desc_t *desc, uint8_t colorspace)
Sets the colorspace of an image for QOI descriptor.
QOI descriptor as read by the header of a QOI file.
uint8_t channels
The number of channels in the image, which is either 3 for RGB or 4 for RGBA.
uint32_t width
The width of the image in pixels, stored in big endian format.
uint32_t height
The height of the image in pixels, stored in big endian format.
uint8_t colorspace
The color space of the image, which is either 0 for sRGB with linear alpha or 1 for linear RGB.
uint32_t buffer_offset
The offset of the buffer to write the next encoded data to.
uint8_t * enc_buffer
The buffer to store the encoded QOI data before writing to the file.
uint32_t buffer_len
The total length of the buffer.
uint32_t len
The total length of the pixel data to encode (width * height).
uint8_t run
The run length of the current pixel value being encoded.
qoi_pixel_t prev_pixel
The previous pixel value is used to compare with the current pixel value to determine which QOI opcod...
uint32_t pixels_written
The total number of pixels encoded so far.
qoi_pixel_t pix_buffer[64]
The total number of pixels in the image to encode.
QOI pixel structure for storing the color values of a pixel in both individual channels and as a conc...
uint8_t blue
The blue value of the pixel.
uint32_t concatenated_pixel_values
The concatenated pixel values in a single 32-bit integer for easy comparison of pixels as a single va...
uint8_t green
The green value of the pixel.
uint8_t alpha
The alpha value of the pixel, which represents the transparency of the pixel. A value of 0 means the ...
uint8_t red
The red value of the pixel.