From 05180c8070e5f792e665e93cb260122ba3fb754f Mon Sep 17 00:00:00 2001 From: whowechina Date: Sat, 15 Jun 2024 15:31:59 +0800 Subject: [PATCH] gfx tools for image and anima compression --- firmware/tools/anima_conv.c | 105 ++++++++----------------- firmware/tools/image_conv.c | 151 ++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+), 72 deletions(-) create mode 100644 firmware/tools/image_conv.c diff --git a/firmware/tools/anima_conv.c b/firmware/tools/anima_conv.c index 144ddbd..7009f87 100644 --- a/firmware/tools/anima_conv.c +++ b/firmware/tools/anima_conv.c @@ -1,5 +1,6 @@ /* - * Image compression tool + * Anima compression tool for AIC Pico + * WHowe * 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 #include #include -#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"); diff --git a/firmware/tools/image_conv.c b/firmware/tools/image_conv.c new file mode 100644 index 0000000..abec91e --- /dev/null +++ b/firmware/tools/image_conv.c @@ -0,0 +1,151 @@ +/* Image compression tool for AIC Pico + * WHowe + * 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 +#include +#include +#include +#include +#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; +}