mirror of
https://github.com/whowechina/aic_pico.git
synced 2024-11-13 17:30:52 +01:00
Generic RLE compression for images
This commit is contained in:
parent
a047d16a76
commit
29f6dc3e5b
@ -1,5 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "st7789.h"
|
#include "st7789.h"
|
||||||
|
#include "rle.h"
|
||||||
#include "anima.h"
|
#include "anima.h"
|
||||||
|
|
||||||
const uint16_t white_pallete[16] = {
|
const uint16_t white_pallete[16] = {
|
||||||
@ -54,10 +56,12 @@ void anima_draw(const anima_t *ani, int x, int y, int frame, const uint16_t pall
|
|||||||
uint16_t height = ani->height;
|
uint16_t height = ani->height;
|
||||||
frame = frame % ani->frames;
|
frame = frame % ani->frames;
|
||||||
|
|
||||||
decode_start(ani->data + ani->index[frame]);
|
rle_t rle;
|
||||||
|
rle_x_init(&rle, ani->data + ani->index[frame], ani->size, 0);
|
||||||
|
|
||||||
for (int j = 0; j < height; j++) {
|
for (int j = 0; j < height; j++) {
|
||||||
for (int i = 0; i < width / 2; i++) {
|
for (int i = 0; i < width / 2; i++) {
|
||||||
uint8_t value = decode_byte();
|
uint8_t value = rle_x_get_uint8(&rle);
|
||||||
st7789_pixel_raw(x + i * 2, y + j, pallete[value >> 4]);
|
st7789_pixel_raw(x + i * 2, y + j, pallete[value >> 4]);
|
||||||
st7789_pixel_raw(x + i * 2 + 1, y + j, pallete[value & 0x0f]);
|
st7789_pixel_raw(x + i * 2 + 1, y + j, pallete[value & 0x0f]);
|
||||||
}
|
}
|
||||||
@ -70,10 +74,11 @@ void anima_mix(const anima_t *ani, int x, int y, int frame, uint16_t color)
|
|||||||
uint16_t height = ani->height;
|
uint16_t height = ani->height;
|
||||||
frame = frame % ani->frames;
|
frame = frame % ani->frames;
|
||||||
|
|
||||||
decode_start(ani->data + ani->index[frame]);
|
rle_t rle;
|
||||||
|
rle_x_init(&rle, ani->data + ani->index[frame], ani->size, 0);
|
||||||
for (int j = 0; j < height; j++) {
|
for (int j = 0; j < height; j++) {
|
||||||
for (int i = 0; i < width / 2; i++) {
|
for (int i = 0; i < width / 2; i++) {
|
||||||
uint8_t value = decode_byte();
|
uint8_t value = rle_x_get_uint8(&rle);
|
||||||
st7789_pixel(x + i * 2, y + j, color, value >> 4 << 4);
|
st7789_pixel(x + i * 2, y + j, color, value >> 4 << 4);
|
||||||
st7789_pixel(x + i * 2 + 1, y + j, color, (value & 0x0f) << 4);
|
st7789_pixel(x + i * 2 + 1, y + j, color, (value & 0x0f) << 4);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ typedef struct {
|
|||||||
uint16_t width;
|
uint16_t width;
|
||||||
uint16_t height;
|
uint16_t height;
|
||||||
uint32_t frames;
|
uint32_t frames;
|
||||||
|
uint32_t size;
|
||||||
const uint32_t *index;
|
const uint32_t *index;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
} anima_t;
|
} anima_t;
|
||||||
|
File diff suppressed because it is too large
Load Diff
132
firmware/src/rle.c
Normal file
132
firmware/src/rle.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/* Run Length Encoding (RLE) Codec
|
||||||
|
* WHowe <github.com/whowechina>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rle.h"
|
||||||
|
|
||||||
|
void rle_init(rle_t *rle, const void *input, size_t size)
|
||||||
|
{
|
||||||
|
rle->src = input;
|
||||||
|
rle->size = size;
|
||||||
|
rle->pos = 0;
|
||||||
|
rle->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rle_x_init(rle_t *rle, const void *input, size_t size, uint32_t x)
|
||||||
|
{
|
||||||
|
rle->x = x;
|
||||||
|
rle_init(rle, input, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rle_eof(rle_t *rle)
|
||||||
|
{
|
||||||
|
return (!rle->counter) && (rle->pos >= rle->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RLE_GET_TEMPLATE(type, condition) \
|
||||||
|
if (rle->counter) { \
|
||||||
|
rle->counter--; \
|
||||||
|
} else if (rle->pos < rle->size) { \
|
||||||
|
rle->value = ((const type *)rle->src)[rle->pos++]; \
|
||||||
|
if (condition) { \
|
||||||
|
rle->counter = ((const type *)rle->src)[rle->pos++]; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return rle->value;
|
||||||
|
|
||||||
|
#define RLE_GET(type) RLE_GET_TEMPLATE(type, true)
|
||||||
|
#define RLE_GET_X(type) RLE_GET_TEMPLATE(type, rle->value == rle->x)
|
||||||
|
|
||||||
|
uint8_t rle_get_uint8(rle_t *rle)
|
||||||
|
{
|
||||||
|
RLE_GET(uint8_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t rle_get_uint16(rle_t *rle)
|
||||||
|
{
|
||||||
|
RLE_GET(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rle_x_get_uint8(rle_t *rle)
|
||||||
|
{
|
||||||
|
RLE_GET_X(uint8_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t rle_x_get_uint16(rle_t *rle)
|
||||||
|
{
|
||||||
|
RLE_GET_X(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PUSH_DATA(data) \
|
||||||
|
output[pos++] = data;
|
||||||
|
|
||||||
|
#define BEGIN_COUNT \
|
||||||
|
value = input[i]; \
|
||||||
|
PUSH_DATA(value); \
|
||||||
|
num = 0; \
|
||||||
|
counting = true;
|
||||||
|
|
||||||
|
#define END_COUNT \
|
||||||
|
PUSH_DATA(num); \
|
||||||
|
counting = false;
|
||||||
|
|
||||||
|
#define RLE_ENCODE_TEMPLATE(type, max, condition) \
|
||||||
|
size_t pos = 0; \
|
||||||
|
bool counting = false; \
|
||||||
|
uint32_t value; \
|
||||||
|
uint32_t num; \
|
||||||
|
for (size_t i = 0; i < size; i++) { \
|
||||||
|
if (!counting) { \
|
||||||
|
if (condition) { \
|
||||||
|
BEGIN_COUNT; \
|
||||||
|
} else { \
|
||||||
|
PUSH_DATA(input[i]); \
|
||||||
|
} \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (input[i] == value) { \
|
||||||
|
num++; \
|
||||||
|
if (num >= max) { \
|
||||||
|
END_COUNT; \
|
||||||
|
} \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (counting) { \
|
||||||
|
END_COUNT; \
|
||||||
|
if (condition) { \
|
||||||
|
BEGIN_COUNT; \
|
||||||
|
} else { \
|
||||||
|
PUSH_DATA(input[i]); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (counting) { \
|
||||||
|
END_COUNT; \
|
||||||
|
} \
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
#define RLE_ENCODE(type, max) RLE_ENCODE_TEMPLATE(type, max, true)
|
||||||
|
#define RLE_X_ENCODE(type, max, x) RLE_ENCODE_TEMPLATE(type, max, input[i] == x)
|
||||||
|
|
||||||
|
size_t rle_encode_uint8(uint8_t *output, const uint8_t *input, size_t size)
|
||||||
|
{
|
||||||
|
RLE_ENCODE(uint8_t, UINT8_MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rle_encode_uint16(uint16_t *output, const uint16_t *input, size_t size)
|
||||||
|
{
|
||||||
|
RLE_ENCODE(uint16_t, UINT16_MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rle_x_encode_uint8(uint8_t *output, const uint8_t *input, size_t size, uint32_t x)
|
||||||
|
{
|
||||||
|
RLE_X_ENCODE(uint8_t, UINT8_MAX, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rle_x_encode_uint16(uint16_t *output, const uint16_t *input, size_t size, uint32_t x)
|
||||||
|
{
|
||||||
|
RLE_X_ENCODE(uint16_t, UINT16_MAX, x)
|
||||||
|
}
|
40
firmware/src/rle.h
Normal file
40
firmware/src/rle.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Run Length Encoding (RLE) Codec
|
||||||
|
* WHowe <github.com/whowechina>
|
||||||
|
*
|
||||||
|
* RLE is regular, RLE_X only encodes a special value
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RLE_H
|
||||||
|
#define RLE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const void *src;
|
||||||
|
size_t size;
|
||||||
|
int pos;
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t value;
|
||||||
|
uint32_t counter;
|
||||||
|
} rle_t;
|
||||||
|
|
||||||
|
void rle_init(rle_t *rle, const void *input, size_t size);
|
||||||
|
void rle_x_init(rle_t *rle, const void *input, size_t size, uint32_t x);
|
||||||
|
|
||||||
|
bool rle_eof(rle_t *rle);
|
||||||
|
|
||||||
|
uint8_t rle_get_uint8(rle_t *rle);
|
||||||
|
uint16_t rle_get_uint16(rle_t *rle);
|
||||||
|
|
||||||
|
uint8_t rle_x_get_uint8(rle_t *rle);
|
||||||
|
uint16_t rle_x_get_uint16(rle_t *rle);
|
||||||
|
|
||||||
|
/* No protection, make sure output is large enough */
|
||||||
|
size_t rle_encode_uint8(uint8_t *output, const uint8_t *input, size_t size);
|
||||||
|
size_t rle_encode_uint16(uint16_t *output, const uint16_t *input, size_t size);
|
||||||
|
|
||||||
|
size_t rle_x_encode_uint8(uint8_t *output, const uint8_t *input, size_t size, uint32_t x);
|
||||||
|
size_t rle_x_encode_uint16(uint16_t *output, const uint16_t *input, size_t size, uint32_t x);
|
||||||
|
|
||||||
|
#endif
|
11423
firmware/src/star_ani.h
11423
firmware/src/star_ani.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user