mirror of
https://github.com/whowechina/aic_pico.git
synced 2024-11-12 00:40:47 +01:00
gfx tools for image and anima compression
This commit is contained in:
parent
6004507e03
commit
05180c8070
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Image compression tool
|
||||
* Anima compression tool for AIC Pico
|
||||
* WHowe <github.com/whowechina>
|
||||
* From 8bit grayscale to 4bit grayscale and zero-run-length encoding
|
||||
* Input: ani_data[], ani_width, ani_height
|
||||
* Frame count is calculated from ani_data size and frame size (ani_width * ani_height)
|
||||
@ -9,92 +10,52 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../src/glow.h"
|
||||
#include "../src/rle.h"
|
||||
#include "../src/gfx.h"
|
||||
|
||||
const char *name = "glow";
|
||||
//#include "../src/glow.h"
|
||||
|
||||
static int col = 0;
|
||||
|
||||
static void line_begin()
|
||||
{
|
||||
col = 0;
|
||||
}
|
||||
|
||||
static void out_byte(uint8_t byte)
|
||||
{
|
||||
if (col == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
printf(" 0x%02x,", byte);
|
||||
col = (col + 1) % 16;
|
||||
}
|
||||
|
||||
static int zero_count = 0;
|
||||
|
||||
static int out_zero()
|
||||
{
|
||||
if (!zero_count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_byte(0);
|
||||
out_byte(zero_count);
|
||||
zero_count = 0;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int encode_byte(uint8_t byte)
|
||||
{
|
||||
if (byte == 0) {
|
||||
zero_count++;
|
||||
}
|
||||
|
||||
int written = 0;
|
||||
|
||||
if ((byte != 0) || (zero_count == 255)) {
|
||||
written += out_zero();
|
||||
}
|
||||
|
||||
if (byte != 0) {
|
||||
out_byte(byte);
|
||||
written++;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static int encode_finish()
|
||||
{
|
||||
return out_zero();
|
||||
}
|
||||
const char *name = "glow.h";
|
||||
|
||||
static inline uint8_t gs8bto4b(const uint8_t bytes[2])
|
||||
{
|
||||
return (bytes[0] & 0xf0) | (bytes[1] >> 4);
|
||||
}
|
||||
|
||||
static int out_frame(int frame, int frame_size)
|
||||
static uint8_t output[1*1024*1024];
|
||||
static uint8_t frame_buffer[1*1024*1024];
|
||||
|
||||
static void print_frame(int frame, int size)
|
||||
{
|
||||
const uint8_t *frame_data = ani_data + frame * frame_size;
|
||||
printf("\n // frame %d", frame);
|
||||
line_begin();
|
||||
int written = 0;
|
||||
for (int i = 0; i < frame_size / 2; i++) {
|
||||
written += encode_byte(gs8bto4b(frame_data + i * 2));
|
||||
printf("\n Frame %d: %d bytes", frame + 1, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if ((i & 15) == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
printf(" 0x%02x,", output[i]);
|
||||
}
|
||||
written += encode_finish();
|
||||
return written;
|
||||
}
|
||||
|
||||
static int encode_frame(int frame, int frame_size)
|
||||
{
|
||||
const uint8_t *frame_data = ani_data + frame * ani_width * ani_height;
|
||||
for (int i = 0; i < frame_size / 2; i++) {
|
||||
frame_buffer[i] = gs8bto4b(frame_data + i * 2);
|
||||
}
|
||||
int size = rle_x_encode_uint8(output, frame_buffer, frame_size / 2, 0);
|
||||
print_frame(frame, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
const char *headlines =
|
||||
"/* Generated by anima_conv.c, 4 bit per pixel, zero run-length compressed. */\n\n"
|
||||
"#include \"anima.h\"\n\n";
|
||||
"/* Generated by anima_conv.c, 4 bit per pixel, RLE X=0 compressed. */\n\n"
|
||||
"#include \"gfx.h\"\n\n";
|
||||
|
||||
|
||||
static const int frame_size = ani_width * ani_height;
|
||||
static const int frame_count = sizeof(ani_data) / frame_size;
|
||||
int main()
|
||||
{
|
||||
int frame_size = ani_width * ani_height;
|
||||
int frame_count = sizeof(ani_data) / frame_size;
|
||||
int frame_index[frame_count];
|
||||
|
||||
printf("%s", headlines);
|
||||
@ -102,7 +63,7 @@ int main()
|
||||
int sum = 0;
|
||||
for (int frame = 0; frame < frame_count; frame++) {
|
||||
frame_index[frame] = sum;
|
||||
sum += out_frame(frame, frame_size);
|
||||
sum += encode_frame(frame, frame_size);
|
||||
}
|
||||
printf("\n};\n\n");
|
||||
|
||||
|
151
firmware/tools/image_conv.c
Normal file
151
firmware/tools/image_conv.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* Image compression tool for AIC Pico
|
||||
* WHowe <github.com/whowechina>
|
||||
* RLE or RLE X can be used.
|
||||
* ENCODE and ENCODE_X are for compression.
|
||||
* ENCODE_PAL converts a 256-color pallete) from 32bit RGBA to RGB565A8.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "../src/rle.h"
|
||||
#include "../src/images.h"
|
||||
|
||||
uint16_t buf[2*1024*1024];
|
||||
uint8_t *output8 = (uint8_t *)buf;
|
||||
uint16_t *output16 = (uint16_t *)buf;
|
||||
|
||||
void test_rle_x()
|
||||
{
|
||||
uint8_t input[] = { 1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 5, 7, 0};
|
||||
|
||||
printf("Input: ");
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", input[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
int size = rle_x_encode_uint8(output8, input, sizeof(input), 1);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", output8[i]);
|
||||
}
|
||||
printf("\nDecode:");
|
||||
rle_decoder_t rle;
|
||||
rle_init(&rle, &(rle_src_t){ output8, size, RLE_RLE_X, 1 });
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", rle_get_uint8(&rle));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
size = rle_x_encode_uint8(output8, input, sizeof(input), 3);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", output8[i]);
|
||||
}
|
||||
printf("\nDecode:");
|
||||
rle_init(&rle, &(rle_src_t){ output8, size, RLE_RLE_X, 3 });
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", rle_get_uint8(&rle));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
size = rle_x_encode_uint8(output8, input, sizeof(input), 4);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", output8[i]);
|
||||
}
|
||||
printf("\nDecode:");
|
||||
rle_init(&rle, &(rle_src_t){ output8, size, RLE_RLE_X, 4 });
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", rle_get_uint8(&rle));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
size = rle_x_encode_uint8(output8, input, sizeof(input), 0);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", output8[i]);
|
||||
}
|
||||
printf("\nDecode:");
|
||||
rle_init(&rle, &(rle_src_t){ output8, size, RLE_RLE_X, 0 });
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", rle_get_uint8(&rle));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
size = rle_x_encode_uint8(output8, input, sizeof(input), 8);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", output8[i]);
|
||||
}
|
||||
printf("\nDecode:");
|
||||
rle_init(&rle, &(rle_src_t){ output8, size, RLE_RLE_X, 8 });
|
||||
for (int i = 0; i < sizeof(input); i++) {
|
||||
printf("%d ", rle_get_uint8(&rle));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_array(size_t size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i % 16 == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
printf(" 0x%02x,", output8[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Work only for arrays */
|
||||
#define DO_ENCODE(bits, input, print) \
|
||||
do { \
|
||||
size_t size = sizeof(input); \
|
||||
size_t len = rle_encode_uint##bits(output##bits, (const uint##bits##_t *)input, size); \
|
||||
printf(" // %s (%zd -> RLE %zd)", #input, size * bits / 8, len * bits / 8); \
|
||||
print ? print_array(len * bits / 8) : printf("\n"); \
|
||||
} while (0);
|
||||
|
||||
/* Work only for arrays */
|
||||
#define DO_ENCODE_X(bits, input, x, print) \
|
||||
do { \
|
||||
size_t size = sizeof(input); \
|
||||
size_t len = rle_x_encode_uint##bits(output##bits, (const uint##bits##_t *)input, size, x); \
|
||||
printf(" // %s (%zd -> RLE(%x) %zd)", #input, size * bits / 8, x, len * bits / 8); \
|
||||
print ? print_array(len * bits / 8) : printf("\n"); \
|
||||
} while (0);
|
||||
|
||||
#define ENCODE(bits, input) DO_ENCODE(bits, input, true)
|
||||
#define ENCODE_X(bits, input, x) DO_ENCODE_X(bits, input, x, true)
|
||||
#define TEST_ENCODE(bits, input) DO_ENCODE(bits, input, false)
|
||||
#define TEST_ENCODE_X(bits, input, x) DO_ENCODE_X(bits, input, x, false)
|
||||
|
||||
void encode_pallette(const uint8_t pallete[256 * 4])
|
||||
{
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (i % 4 == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
const uint8_t *color = pallete + i * 4;
|
||||
uint8_t r = color[0];
|
||||
uint8_t g = color[1];
|
||||
uint8_t b = color[2];
|
||||
uint8_t a = color[3];
|
||||
uint16_t rgb565 = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11);
|
||||
|
||||
printf(" 0x%06x,", (a << 16) | rgb565);
|
||||
}
|
||||
}
|
||||
|
||||
#define ENCODE_PAL(pallete) \
|
||||
if (sizeof(pallete) != 256 * 4) { \
|
||||
printf(" // Error\n"); \
|
||||
} else { \
|
||||
printf(" // %s Pallete (RGB565A8*256)", #pallete); \
|
||||
encode_pallette(pallete); \
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ENCODE(8, bana_logo_pixels);
|
||||
ENCODE_PAL(bana_logo_pal);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user