Giter Club home page Giter Club logo

squeez-o's Introduction

squeez-o

OLED bitmap compression for deflating QMK-compatible graphics

How does it work?

This tool compresses a 128x32 pixel bitmap generated with img2cpp by marking null bytes (0x0) and non-null bytes using a single bit in a smaller byte array. It works best when the image has lots of whitespace. The compressed images stop being smaller than the input images when the overhead (64 bytes for each 512 byte input) is greater than the savings. Most bitmap images break even or better, but it's worth checking the statistics after running the tool to make sure the savings are worth the effort.

What's the point?

One of the most popular NIBBLE keymaps was too large to enable VIA on. The frames had a lot of whitespace and compressing them seemed like a good idea. The firmware-side decompression algorithm is simple, takes up only a few bytes of flash, and fast enough that it doesn't slow down the matrix scan. After compressing the 7 original frames, there is over 1kB of free flash remaining for other cool firmware features, or the addition of extra frames for longer animations.

Usage

Generate a 128x32 byte array using img2cpp (black background, plain bytes, Vertical - 1 bit per pixel) and save only the raw bytes to input_bytes.tmp. Optionally, users may save the raw bytes to another file of their choosing and use the -f flag followed by their file name when running the program. Run python3 squeez-o.py and copy the output block_list and block_maps into your keymap or keyboard code. For projects with multiple animations, do this for each frame.

Within the keyboard firmware, use the example decompression algorithm in decompress.c to decompress the compressed frames and write to the OLED display.

Running on the included input_bytes.tmp file yields this output:

// Compressed oled data structure
// This must be included ONCE along with the compressed data
typedef struct {
    const uint16_t data_len;
    const char* block_map;
    const char* block_list;
} compressed_oled_frame_t;

static const char PROGMEM frame_map[] = { 
    0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
    0x00, 0x00, 0x00, 0x00
};
static const char PROGMEM frame_list[] = { 
    0x80, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe,
    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x03, 0x03, 0x01, 0x1f, 0xbf, 0x9f, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xc0, 0xc0, 0xc0,
    0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
    0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x0c, 0x3f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f
};
static const compressed_oled_frame_t PROGMEM frame = {512, frame_map, frame_list};
// Input was 512 bytes, deflated block list is now 158 bytes + 64 bytes overhead
// Space savings: 56.64%

Which can be used within QMK by calling oled_write_compressed_P(frame);

Examples

For more info, take a look at the bongo cat keymap.

squeez-o's People

Contributors

jaygreco avatar lancewilhelm avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.