Started from buttom go to the sky
This commit is contained in:
parent
96215449bd
commit
f811e55dea
4781 changed files with 10121 additions and 1743 deletions
305
stdme/include/me/img/qoi.h
Normal file
305
stdme/include/me/img/qoi.h
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* qoi.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/12/24 17:39:36 by maiboyer #+# #+# */
|
||||
/* Updated: 2023/12/25 18:35:05 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
/*
|
||||
|
||||
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
QOI - The "Quite OK Image" format for fast, lossless image compression
|
||||
|
||||
-- About
|
||||
|
||||
QOI encodes and decodes images in a lossless format. Compared to stb_image and
|
||||
stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
|
||||
20% better compression.
|
||||
|
||||
|
||||
-- Synopsis
|
||||
|
||||
// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this
|
||||
// library to create the implementation.
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
|
||||
// Encode and store an RGBA buffer to the file system. The t_qoi_desc describes
|
||||
// the input pixel data.
|
||||
qoi_write("image_new.qoi", rgba_pixels, &(t_qoi_desc){
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
.channels = 4,
|
||||
.colorspace = QOI_SRGB
|
||||
});
|
||||
|
||||
// Load and decode a QOI image from the file system t_i32o a 32bbp RGBA buffer.
|
||||
// The t_qoi_desc struct will be filled with the width, height,
|
||||
number of channels
|
||||
// and colorspace read from the file header.
|
||||
t_qoi_desc desc;
|
||||
void *rgba_pixels = qoi_read("image.qoi", &desc, 4);
|
||||
|
||||
|
||||
|
||||
-- Documentation
|
||||
|
||||
This library provides the following functions;
|
||||
- qoi_read -- read and decode a QOI file
|
||||
- qoi_decode -- decode the raw bytes of a QOI image from memory
|
||||
- qoi_write -- encode and write a QOI file
|
||||
- qoi_encode -- encode an rgba buffer t_i32o a QOI image in memory
|
||||
|
||||
See the function declaration below for the signature and more information.
|
||||
|
||||
If you don't want/need the qoi_read and qoi_write functions, you can define
|
||||
QOI_NO_STDIO before including this library.
|
||||
|
||||
This library uses malloc() and free(). To supply your own malloc implementation
|
||||
you can define QOI_MALLOC and QOI_FREE before including this library.
|
||||
|
||||
This library uses memset() to zero-initialize the index. To supply your own
|
||||
implementation you can define QOI_ZEROARR before including this library.
|
||||
|
||||
|
||||
-- Data Format
|
||||
|
||||
A QOI file has a 14 byte header, followed by any number of data "chunks" and an
|
||||
8-byte end marker.
|
||||
|
||||
struct qoi_header_t {
|
||||
char magic[4]; // magic bytes "qoif"
|
||||
ut_i3232_t width; // image width in pixels (BE)
|
||||
ut_i3232_t height; // sprite.height in pixels (BE)
|
||||
ut_i328_t channels; // 3 = RGB, 4 = RGBA
|
||||
ut_i328_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels
|
||||
linear
|
||||
};
|
||||
|
||||
Images are encoded row by row, left to right, top to bottom. The decoder and
|
||||
encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
|
||||
image is complete when all pixels specified by width * height have been covered.
|
||||
|
||||
Pixels are encoded as
|
||||
- a run of the previous pixel
|
||||
- an index t_i32o an array of previously seen pixels
|
||||
- a difference to the previous pixel value in r,g,b
|
||||
- full r,g,b or r,g,b,a values
|
||||
|
||||
The color channels are assumed to not be premultiplied with the alpha channel
|
||||
("un-premultiplied alpha").
|
||||
|
||||
A running array[64] (zero-initialized) of previously seen pixel values is
|
||||
mat_i32ained by the encoder and decoder. Each pixel that is seen by the encoder
|
||||
and decoder is put t_i32o this array at the position formed by a hash function
|
||||
of the color value. In the encoder, if the pixel value at the index matches the
|
||||
current pixel, this index position is written to the stream as QOI_OP_INDEX.
|
||||
The hash function for the index is:
|
||||
|
||||
index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
|
||||
|
||||
Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
|
||||
bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
|
||||
values encoded in these data bits have the most significant bit on the left.
|
||||
|
||||
The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
|
||||
presence of an 8-bit tag first.
|
||||
|
||||
The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte.
|
||||
|
||||
|
||||
The possible chunks are:
|
||||
|
||||
|
||||
.- QOI_OP_INDEX ----------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------|
|
||||
| 0 0 | index |
|
||||
`-------------------------`
|
||||
2-bit tag b00
|
||||
6-bit index t_i32o the color index array: 0..63
|
||||
|
||||
A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the
|
||||
same index. QOI_OP_RUN should be used instead.
|
||||
|
||||
|
||||
.- QOI_OP_DIFF -----------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----+-----+-----|
|
||||
| 0 1 | dr | dg | db |
|
||||
`-------------------------`
|
||||
2-bit tag b01
|
||||
2-bit red channel difference from the previous pixel between -2..1
|
||||
2-bit green channel difference from the previous pixel between -2..1
|
||||
2-bit blue channel difference from the previous pixel between -2..1
|
||||
|
||||
The difference to the current channel values are using a wraparound operation,
|
||||
so "1 - 2" will result in 255, while "255 + 1" will result in 0.
|
||||
|
||||
Values are stored as unsigned t_i32egers with a bias of 2. E.g. -2 is stored as
|
||||
0 (b00). 1 is stored as 3 (b11).
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_LUMA -------------------------------------.
|
||||
| Byte[0] | Byte[1] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------+-------------+-----------|
|
||||
| 1 0 | green diff | dr - dg | db - dg |
|
||||
`---------------------------------------------------`
|
||||
2-bit tag b10
|
||||
6-bit green channel difference from the previous pixel -32..31
|
||||
4-bit red channel difference minus green channel difference -8..7
|
||||
4-bit blue channel difference minus green channel difference -8..7
|
||||
|
||||
The green channel is used to indicate the general direction of change and is
|
||||
encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
|
||||
of the green channel difference and are encoded in 4 bits. I.e.:
|
||||
dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
|
||||
db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
|
||||
|
||||
The difference to the current channel values are using a wraparound operation,
|
||||
so "10 - 13" will result in 253, while "250 + 7" will result in 1.
|
||||
|
||||
Values are stored as unsigned t_i32egers with a bias of 32 for the green channel
|
||||
and a bias of 8 for the red and blue channel.
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_RUN ------------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------|
|
||||
| 1 1 | run |
|
||||
`-------------------------`
|
||||
2-bit tag b11
|
||||
6-bit run-length repeating the previous pixel: 1..62
|
||||
|
||||
The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
|
||||
(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
|
||||
QOI_OP_RGBA tags.
|
||||
|
||||
|
||||
.- QOI_OP_RGB ------------------------------------------.
|
||||
| Byte[0] | Byte[1] | Byte[2] | Byte[3] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||
|-------------------------+---------+---------+---------|
|
||||
| 1 1 1 1 1 1 1 0 | red | green | blue |
|
||||
`-------------------------------------------------------`
|
||||
8-bit tag b11111110
|
||||
8-bit red channel value
|
||||
8-bit green channel value
|
||||
8-bit blue channel value
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_RGBA ---------------------------------------------------.
|
||||
| Byte[0] | Byte[1] | Byte[2] | Byte[3] | Byte[4] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||
|-------------------------+---------+---------+---------+---------|
|
||||
| 1 1 1 1 1 1 1 1 | red | green | blue | alpha |
|
||||
`-----------------------------------------------------------------`
|
||||
8-bit tag b11111111
|
||||
8-bit red channel value
|
||||
8-bit green channel value
|
||||
8-bit blue channel value
|
||||
8-bit alpha channel value
|
||||
|
||||
*/
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Header - Public functions */
|
||||
|
||||
#ifndef QOI_H
|
||||
# define QOI_H
|
||||
|
||||
# include "me/mem/mem_alloc.h"
|
||||
# include "me/mem/mem_set_zero.h"
|
||||
# include "me/types.h"
|
||||
/* A pot_i32er to a t_qoi_desc struct has to be supplied to all of qoi's
|
||||
functions. It describes either the input format (for qoi_write and qoi_encode),
|
||||
or is filled with the description read from the file header (for qoi_read and
|
||||
qoi_decode).
|
||||
|
||||
The colorspace in this t_qoi_desc is an enum where
|
||||
0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
|
||||
1 = all channels are linear
|
||||
You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
|
||||
informative. It will be saved to the file header, but does not affect
|
||||
how chunks are en-/decoded. */
|
||||
|
||||
# define QOI_SRGB 0
|
||||
# define QOI_LINEAR 1
|
||||
|
||||
typedef struct s_t_qoi_desc
|
||||
{
|
||||
t_u32 width;
|
||||
t_u32 height;
|
||||
t_u8 channels;
|
||||
t_u8 colorspace;
|
||||
} t_qoi_desc;
|
||||
|
||||
# ifndef QOI_NO_STDIO
|
||||
|
||||
/* Encode raw RGB or RGBA pixels t_i32o a QOI image and write it to the file
|
||||
system. The t_qoi_desc struct must be filled with the image width, height,
|
||||
number of channels (3 = RGB, 4 = RGBA) and the colorspace.
|
||||
|
||||
The function returns 0 on failure (invalid parameters, or fopen or malloc
|
||||
failed) or the number of bytes written on success. */
|
||||
|
||||
t_i32 qoi_write(t_const_str filename, const void *data,
|
||||
const t_qoi_desc *desc);
|
||||
|
||||
/* Read and decode a QOI image from the file system. If channels is 0, the
|
||||
number of channels from the file header is used. If channels is 3 or 4 the
|
||||
output format will be forced t_i32o this number of channels.
|
||||
|
||||
The function either returns NULL on failure (invalid data, or malloc or fopen
|
||||
failed) or a pot_i32er to the decoded pixels. On success, the t_qoi_desc struct
|
||||
will be filled with the description from the file header.
|
||||
|
||||
The returned pixel data should be free()d after use. */
|
||||
|
||||
void *qoi_read(t_const_str filename, t_qoi_desc *desc,
|
||||
t_i32 channels);
|
||||
|
||||
# endif /* QOI_NO_STDIO */
|
||||
|
||||
/* Encode raw RGB or RGBA pixels t_i32o a QOI image in memory.
|
||||
|
||||
The function either returns NULL on failure (invalid parameters or malloc
|
||||
failed) or a pot_i32er to the encoded data on success. On success the out_len
|
||||
is set to the size in bytes of the encoded data.
|
||||
|
||||
The returned qoi data should be free()d after use. */
|
||||
|
||||
void *qoi_encode(const void *data, const t_qoi_desc *desc,
|
||||
t_i32 *out_len);
|
||||
|
||||
/* Decode a QOI image from memory.
|
||||
|
||||
The function either returns NULL on failure (invalid parameters or malloc
|
||||
failed) or a pot_i32er to the decoded pixels. On success, the t_qoi_desc struct
|
||||
is filled with the description from the file header.
|
||||
|
||||
The returned pixel data should be free()d after use. */
|
||||
|
||||
void *qoi_decode(const void *data, t_i32 size, t_qoi_desc *desc,
|
||||
t_i32 channels);
|
||||
|
||||
#endif /* QOI_H */
|
||||
86
stdme/include/me/img/qoi/qoi_decode.h
Normal file
86
stdme/include/me/img/qoi/qoi_decode.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* qoi_decode.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/12/25 22:33:19 by maiboyer #+# #+# */
|
||||
/* Updated: 2023/12/25 22:58:27 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef QOI_DECODE_H
|
||||
# define QOI_DECODE_H
|
||||
|
||||
# include "me/img/qoi.h"
|
||||
# include "me/img/qoi/qoi_utils.h"
|
||||
|
||||
typedef struct s_decode_vals
|
||||
{
|
||||
t_i32 px_len;
|
||||
t_i32 chunks_len;
|
||||
t_i32 px_pos;
|
||||
t_i32 p;
|
||||
t_i32 run;
|
||||
t_i32 b1;
|
||||
t_i32 b2;
|
||||
t_i32 vg;
|
||||
t_u32 header_magic;
|
||||
t_qoi_rgba index[64];
|
||||
t_qoi_rgba px;
|
||||
|
||||
} t_decode_vals;
|
||||
|
||||
static inline void qoi_op_luma_decode(t_decode_vals *vals, const t_u8 *bytes)
|
||||
{
|
||||
vals->b2 = bytes[vals->p++];
|
||||
vals->vg = (vals->b1 & 0x3f) - 32;
|
||||
vals->px.rgba.r += vals->vg - 8 + ((vals->b2 >> 4) & 0x0f);
|
||||
vals->px.rgba.g += vals->vg;
|
||||
vals->px.rgba.b += vals->vg - 8 + (vals->b2 & 0x0f);
|
||||
}
|
||||
|
||||
static inline void qoi_op_diff_decode(t_decode_vals *vals, const t_u8 *bytes)
|
||||
{
|
||||
(void)(bytes);
|
||||
vals->px.rgba.r += ((vals->b1 >> 4) & 0x03) - 2;
|
||||
vals->px.rgba.g += ((vals->b1 >> 2) & 0x03) - 2;
|
||||
vals->px.rgba.b += (vals->b1 & 0x03) - 2;
|
||||
}
|
||||
|
||||
static inline void qoi_op_rgba_decode(t_decode_vals *vals, const t_u8 *bytes)
|
||||
{
|
||||
vals->px.rgba.r = bytes[vals->p++];
|
||||
vals->px.rgba.g = bytes[vals->p++];
|
||||
vals->px.rgba.b = bytes[vals->p++];
|
||||
vals->px.rgba.a = bytes[vals->p++];
|
||||
}
|
||||
|
||||
static inline void qoi_op_rgb_decode(t_decode_vals *vals, const t_u8 *bytes)
|
||||
{
|
||||
vals->px.rgba.r = bytes[vals->p++];
|
||||
vals->px.rgba.g = bytes[vals->p++];
|
||||
vals->px.rgba.b = bytes[vals->p++];
|
||||
}
|
||||
|
||||
static inline void qoi_decode_inner_inner(t_decode_vals *vals, \
|
||||
const t_u8 *bytes)
|
||||
{
|
||||
vals->b1 = bytes[vals->p++];
|
||||
if (vals->b1 == QOI_OP_RGB)
|
||||
qoi_op_rgb_decode(vals, bytes);
|
||||
else if (vals->b1 == QOI_OP_RGBA)
|
||||
qoi_op_rgba_decode(vals, bytes);
|
||||
else if ((vals->b1 & QOI_MASK_2) == QOI_OP_INDEX)
|
||||
vals->px = vals->index[vals->b1];
|
||||
else if ((vals->b1 & QOI_MASK_2) == QOI_OP_DIFF)
|
||||
qoi_op_diff_decode(vals, bytes);
|
||||
else if ((vals->b1 & QOI_MASK_2) == QOI_OP_LUMA)
|
||||
qoi_op_luma_decode(vals, bytes);
|
||||
else if ((vals->b1 & QOI_MASK_2) == QOI_OP_RUN)
|
||||
vals->run = (vals->b1 & 0x3f);
|
||||
vals->index[qoi_color_hash(vals->px) % 64] = vals->px;
|
||||
}
|
||||
|
||||
#endif /* QOI_DECODE_H */
|
||||
155
stdme/include/me/img/qoi/qoi_encode.h
Normal file
155
stdme/include/me/img/qoi/qoi_encode.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* qoi_encode.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/12/25 22:36:06 by maiboyer #+# #+# */
|
||||
/* Updated: 2023/12/25 22:56:36 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef QOI_ENCODE_H
|
||||
# define QOI_ENCODE_H
|
||||
|
||||
# include "me/img/qoi.h"
|
||||
# include "me/img/qoi/qoi_utils.h"
|
||||
|
||||
typedef struct s_encode_vals
|
||||
{
|
||||
t_i32 i;
|
||||
t_i32 max_size;
|
||||
t_i32 p;
|
||||
t_i32 run;
|
||||
t_i32 px_len;
|
||||
t_i32 px_end;
|
||||
t_i32 px_pos;
|
||||
t_i32 channels;
|
||||
t_i32 index_pos;
|
||||
t_qoi_rgba index[64];
|
||||
t_qoi_rgba px;
|
||||
t_qoi_rgba px_prev;
|
||||
} t_encode_vals;
|
||||
|
||||
typedef struct s_v
|
||||
{
|
||||
t_i8 r;
|
||||
t_i8 g;
|
||||
t_i8 b;
|
||||
t_i8 g_r;
|
||||
t_i8 g_b;
|
||||
} t_v;
|
||||
|
||||
static inline void qoi_encode_if_thingy1(t_encode_vals *vals,
|
||||
t_v *v, t_u8 *bytes)
|
||||
{
|
||||
v->r = vals->px.rgba.r - vals->px_prev.rgba.r;
|
||||
v->g = vals->px.rgba.g - vals->px_prev.rgba.g;
|
||||
v->b = vals->px.rgba.b - vals->px_prev.rgba.b;
|
||||
v->g_r = v->r - v->g;
|
||||
v->g_b = v->b - v->g;
|
||||
if (v->r > -3 && v->r < 2 && v->g > -3 && v->g < 2 && v->b > -3
|
||||
&& v->b < 2)
|
||||
bytes[vals->p++] = QOI_OP_DIFF | (v->r + 2) << 4 | (v->g
|
||||
+ 2) << 2 | (v->b + 2);
|
||||
else if (v->g_r > -9 && v->g_r < 8 && v->g > -33 && v->g < 32
|
||||
&& v->g_b > -9 && v->g_b < 8)
|
||||
{
|
||||
bytes[vals->p++] = QOI_OP_LUMA | (v->g + 32);
|
||||
bytes[vals->p++] = (v->g_r + 8) << 4 | (v->g_b + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes[vals->p++] = QOI_OP_RGB;
|
||||
bytes[vals->p++] = vals->px.rgba.r;
|
||||
bytes[vals->p++] = vals->px.rgba.g;
|
||||
bytes[vals->p++] = vals->px.rgba.b;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qoi_encode_inner_inner_inner(t_encode_vals *vals,
|
||||
t_v *v, t_u8 *bytes)
|
||||
{
|
||||
if (vals->run > 0)
|
||||
{
|
||||
bytes[vals->p++] = QOI_OP_RUN | (vals->run - 1);
|
||||
vals->run = 0;
|
||||
}
|
||||
vals->index_pos = qoi_color_hash(vals->px) % 64;
|
||||
if (vals->index[vals->index_pos].v == vals->px.v)
|
||||
bytes[vals->p++] = QOI_OP_INDEX | vals->index_pos;
|
||||
else
|
||||
{
|
||||
vals->index[vals->index_pos] = vals->px;
|
||||
if (vals->px.rgba.a == vals->px_prev.rgba.a)
|
||||
qoi_encode_if_thingy1(vals, v, bytes);
|
||||
else
|
||||
{
|
||||
bytes[vals->p++] = QOI_OP_RGBA;
|
||||
bytes[vals->p++] = vals->px.rgba.r;
|
||||
bytes[vals->p++] = vals->px.rgba.g;
|
||||
bytes[vals->p++] = vals->px.rgba.b;
|
||||
bytes[vals->p++] = vals->px.rgba.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qoi_encode_inner_inner(t_encode_vals *vals,
|
||||
const t_u8 *pixels, t_u8 *bytes)
|
||||
{
|
||||
t_v v;
|
||||
|
||||
v = (t_v){0};
|
||||
while (vals->px_pos < vals->px_len)
|
||||
{
|
||||
vals->px.rgba.r = pixels[vals->px_pos + 0];
|
||||
vals->px.rgba.g = pixels[vals->px_pos + 1];
|
||||
vals->px.rgba.b = pixels[vals->px_pos + 2];
|
||||
if (vals->channels == 4)
|
||||
vals->px.rgba.a = pixels[vals->px_pos + 3];
|
||||
if (vals->px.v == vals->px_prev.v)
|
||||
{
|
||||
vals->run++;
|
||||
if (vals->run == 62 || vals->px_pos == vals->px_end)
|
||||
{
|
||||
bytes[vals->p++] = QOI_OP_RUN | (vals->run - 1);
|
||||
vals->run = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
qoi_encode_inner_inner_inner(vals, &v, bytes);
|
||||
vals->px_prev = vals->px;
|
||||
vals->px_pos += vals->channels;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *qoi_encode_inner(t_encode_vals *vals,
|
||||
const t_qoi_desc *desc,
|
||||
const t_u8 *pixels, t_i32 *out_len)
|
||||
{
|
||||
t_u8 *bytes;
|
||||
|
||||
bytes = (t_u8 *)mem_alloc(vals->max_size);
|
||||
if (!bytes)
|
||||
return (NULL);
|
||||
qoi_write_32(bytes, &vals->p, QOI_MAGIC);
|
||||
qoi_write_32(bytes, &vals->p, desc->width);
|
||||
qoi_write_32(bytes, &vals->p, desc->height);
|
||||
bytes[vals->p++] = desc->channels;
|
||||
bytes[vals->p++] = desc->colorspace;
|
||||
mem_set_zero(vals->index, sizeof(vals->index));
|
||||
vals->px_prev.rgba.a = 255;
|
||||
vals->px = vals->px_prev;
|
||||
vals->px_len = desc->width * desc->height * desc->channels;
|
||||
vals->px_end = vals->px_len - desc->channels;
|
||||
vals->channels = desc->channels;
|
||||
qoi_encode_inner_inner(vals, pixels, bytes);
|
||||
vals->i = 0;
|
||||
while (vals->i < (t_i32) sizeof(t_u8[8]))
|
||||
bytes[vals->p++] = ((t_u8[8]){0, 0, 0, 0, 0, 0, 0, 1})[vals->i++];
|
||||
*out_len = vals->p;
|
||||
return (bytes);
|
||||
}
|
||||
|
||||
#endif /* QOI_ENCODE_H */
|
||||
56
stdme/include/me/img/qoi/qoi_utils.h
Normal file
56
stdme/include/me/img/qoi/qoi_utils.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* qoi_utils.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/12/24 18:59:56 by maiboyer #+# #+# */
|
||||
/* Updated: 2023/12/25 22:33:07 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef QOI_UTILS_H
|
||||
# define QOI_UTILS_H
|
||||
|
||||
# include "me/img/qoi.h"
|
||||
# include "me/types.h"
|
||||
|
||||
# define QOI_OP_INDEX 0x00 /* 00xxxxxx */
|
||||
# define QOI_OP_DIFF 0x40 /* 01xxxxxx */
|
||||
# define QOI_OP_LUMA 0x80 /* 10xxxxxx */
|
||||
# define QOI_OP_RUN 0xc0 /* 11xxxxxx */
|
||||
# define QOI_OP_RGB 0xfe /* 11111110 */
|
||||
# define QOI_OP_RGBA 0xff /* 11111111 */
|
||||
# define QOI_MASK_2 0xc0 /* 11000000 */
|
||||
# define QOI_MAGIC 0x716f6966u
|
||||
//(((t_u32)'q') << 24 | ((t_u32)'o') << 16 | ((t_u32)'i') << 8 | ((t_u32)'f'))
|
||||
# define QOI_HEADER_SIZE 14
|
||||
/* 2GB is the max file size that this implementation can safely handle. We guard
|
||||
against anything larger than that, assuming the worst case with 5 bytes per
|
||||
pixel, rounded down to a nice clean value. 400 million pixels ought to be
|
||||
enough for anybody. */
|
||||
# define QOI_PIXELS_MAX 400000000u
|
||||
|
||||
typedef union u_qoi_rgba
|
||||
{
|
||||
struct s_qoi_rgba
|
||||
{
|
||||
t_u8 r;
|
||||
t_u8 g;
|
||||
t_u8 b;
|
||||
t_u8 a;
|
||||
} rgba;
|
||||
t_u32 v;
|
||||
} t_qoi_rgba;
|
||||
|
||||
void qoi_write_32(t_u8 *bytes, t_i32 *p, t_u32 v);
|
||||
|
||||
t_u32 qoi_read_32(const t_u8 *bytes, t_i32 *p);
|
||||
|
||||
static inline t_u32 qoi_color_hash(t_qoi_rgba c)
|
||||
{
|
||||
return (c.rgba.r * 3 + c.rgba.g * 5 + c.rgba.b * 7 + c.rgba.a * 11);
|
||||
}
|
||||
|
||||
#endif /* QOI_UTILS_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue