aboutsummaryrefslogtreecommitdiff
path: root/tools/img2sprite.py
blob: 6463e0cb9475964ff5d919dd081be8335d4a6230 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python

__version__ = "1.0"

import sys
from argparse import ArgumentParser
from PIL import Image

DEF_W = 8
DEF_H = 16

def encode_byte(a, b):
    return (a & 1) << 7 | (b & 1) << 6 \
            | (a & 4) << 3 | (b & 4) << 2 \
            | (a & 2) << 2 | (b & 2) << 1 \
            | (a & 8) >> 2 | (b & 8) >> 3

def main():

    parser = ArgumentParser(description="Image cpcrslib sprite",
                            epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
                            )

    parser.add_argument("--version", action="version", version="%(prog)s "  + __version__)
    parser.add_argument("-i", "--id", dest="id", default="sprite", type=str,
                        help="variable name (default: sprite)")
    parser.add_argument("--width", dest="w", default=DEF_W, type=int,
                        help="sprite width (default: %s)" % DEF_W)
    parser.add_argument("--height", dest="h", default=DEF_H, type=int,
                        help="sprite height (default: %s)" % DEF_H)
    parser.add_argument("--transparent-color", dest="tc", default=None, type=int,
                        help="palette index for the transparent color (default: None)")
    parser.add_argument("-d", "--dimension", dest="dim", action="store_true",
                        help="include the sprite dimensions in the output")
    parser.add_argument("-b", "--binary", dest="binary", action="store_true",
                        help="output binary instead of C code")


    parser.add_argument("image", help="image to convert", nargs="?")

    args = parser.parse_args()

    if not args.image:
        parser.error("required parameter: image")

    if args.tc:
        try:
            args.tc = int(args.tc)
            if args.tc < 0 or args.tc > 15:
                    raise ValueError()
        except ValueError:
            parser.error("--transparent-color expects an integer in [0, 15]")

    try:
        image = Image.open(args.image)
    except IOError:
        parser.error("failed to open the image")

    if image.mode != "P":
        parser.error("not an indexed image (no palette)")

    (w, h) = image.size

    if w % args.w or h % args.h:
        parser.error("%s size is not multiple of the image size" % args.image)

    data = image.getdata()

    out = []
    for x in range(0, w, args.w):
        frame = []
        for y in range(h): # FIXME: different heights!
            if args.dim:
                out.extend([args.w // 2, args.h])
            for i in range(0, args.w, 2):
                a = data[x + i + (y * w)]
                b = data[x + i + 1 + (y * w)]

                if args.tc is not None:
                    mask_a = mask_b = 0
                    if a == args.tc:
                        mask_a = 0xf
                        a = 0
                    if b == args.tc:
                        mask_b = 0xf
                        b = 0
                    frame.append(encode_byte(mask_a, mask_b))

                frame.append(encode_byte(a, b))
        out.append(frame)

    if args.binary:
        for frame in out:
            sys.stdout.write(bytearray(frame))
        return

    frames = len(out)

    data_out = ""
    for block in out:
        if data_out:
            data_out += ",\n"
        data_out += "{"
        for part in range(0, len(block), 4):
            if data_out and data_out[-1] != "{":
                data_out += ",\n"
            data_out += ', '.join(["0x%02x" % b for b in block[part: part + 4]])
        data_out += "}"

    print("/* %sx%s (frames: %s, mask: %s, dim: %s) */" % (args.w, args.h, frames, args.tc is not None, args.dim))
    print("const unsigned char %s[%d][%d] = {\n%s\n};\n" % (args.id, len(out), len(out[0]), data_out))

if __name__ == "__main__":
    main()