summaryrefslogtreecommitdiff
path: root/tools/rle_encode.py
blob: c8c2de6c8bd3e0f5e36160e1b32b48a08118fe9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3

import argparse
import sys
from PIL import Image

def encode(im):
    pixels = im.load()

    rle = []
    rl = 0
    px = 0

    for y in range(im.height):
        for x in range(im.width):
            newpx = pixels[x, y]
            if newpx == px:
                if rl < 255:
                    rl += 1
                else:
                    # Handle overflow
                    rle.append(255)
                    rle.append(0)
                    rl = 1
                continue

            # Start a new run
            rle.append(rl)
            rl = 1
            px = newpx
    # Handle the final run
    rle.append(rl)

    return (im.width, im.height, bytes(rle))

def render_c(image, fname):
    print(f'// 1-bit RLE, generated from {fname}, {len(image[2])} bytes')
    print('static const uint8_t rle[] = {\n ', end='')
    i = 0
    for rl in image[2]:
        print(f' {hex(rl)},', end='')

        i += 1
        if i == 12:
            print('\n ', end='')
            i = 0

    print('\n};')

def decode_to_ascii(image):
    (sx, sy, rle) = image
    data = bytearray(2*sx)
    dp = 0
    black = ord('#')
    white = ord(' ')
    color = black

    for rl in rle:
        while rl:
            data[dp] = color
            data[dp+1] = color
            dp += 2
            rl -= 1

            if dp >= (2*sx):
                print(data.decode('utf-8'))
                dp = 0

        if color == black:
            color = white
        else:
            color = black

    # Check the image is the correct length
    assert(dp == 0)



parser = argparse.ArgumentParser(description='RLE encoder tool.')
parser.add_argument('files', nargs='+',
                    help='files to be encoded')
parser.add_argument('--ascii', action='store_true',
                    help='Run the resulting image(s) through an ascii art decoder')
parser.add_argument('--c', action='store_true',
                    help='Render the output as C instead of python')
args = parser.parse_args()

for fname in args.files:
    image = encode(Image.open(fname))

    if args.c:
        render_c(image, fname)
    else:
        print(f'# 1-bit RLE, generated from {fname}, {len(image[2])} bytes')
        print(f'rle = {image}')

    if args.ascii:
        print()
        decode_to_ascii(image)