You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.1 KiB
129 lines
3.1 KiB
4 years ago
|
#!/usr/bin/env python3
|
||
|
#
|
||
|
# (c) Copyright 2018 by Coinkite Inc. This file is part of Coldcard <coldcardwallet.com>
|
||
|
# and is covered by GPLv3 license found in COPYING.
|
||
|
#
|
||
|
import os, sys, pdb
|
||
|
from PIL import Image, ImageOps
|
||
|
import zlib
|
||
|
|
||
|
def read_text(fname):
|
||
|
|
||
|
w = 0
|
||
|
rows = []
|
||
|
Z = b'\0'
|
||
|
F = b'\xff'
|
||
|
|
||
|
# do not trim whitespace; perhaps it is spacing data
|
||
|
|
||
|
for ln in open(fname, 'rt').readlines():
|
||
|
ln = ln.rstrip('\n')
|
||
|
r = b''.join(F if i != ' ' else Z for i in ln)
|
||
|
w = max(w, len(r))
|
||
|
rows.append(r)
|
||
|
|
||
|
raw = b''
|
||
|
for r in rows:
|
||
|
r += Z*(w - len(r))
|
||
|
raw += r
|
||
|
|
||
|
return Image.frombytes('L', (w, len(rows)), raw).convert('1')
|
||
|
|
||
|
def read_img(fn):
|
||
|
img = Image.open(fn)
|
||
|
w,h = img.size
|
||
|
|
||
|
img = img.convert('L')
|
||
|
# fix colour issues: assume minority colour is white (1)
|
||
|
histo = img.histogram()
|
||
|
assert len(histo) == 256, repr(histo)
|
||
|
assert len(set(histo)) == 3, "Too many colours: "+repr(histo)
|
||
|
|
||
|
# if histo[-1] > histo[0]:
|
||
|
img = ImageOps.invert(img)
|
||
|
|
||
|
return img.convert('1', dither=False)
|
||
|
|
||
|
def compress(n, wbits=-9):
|
||
|
z = zlib.compressobj(wbits=wbits)
|
||
|
rv = z.compress(n)
|
||
|
rv += z.flush(zlib.Z_FINISH)
|
||
|
return rv
|
||
|
|
||
|
def crunch(n):
|
||
|
# try them all... not finding any difference tho.
|
||
|
a = [(wb,compress(n, wb)) for wb in range(-9, -15, -1)]
|
||
|
|
||
|
a.sort(key=lambda i: (-len(i[1]), -i[0]))
|
||
|
|
||
|
#print(' / '.join("%d => %d" % (wb,len(d)) for wb,d in a))
|
||
|
|
||
|
return a[0]
|
||
|
|
||
|
|
||
|
def doit(outfname, fnames):
|
||
|
|
||
|
assert fnames, "need some files"
|
||
|
|
||
|
fp = open(outfname, 'wt')
|
||
|
|
||
|
fp.write("""\
|
||
|
# SPDX-FileCopyrightText: 2020 Foundation Devices, Inc. <hello@foundationdevices.com>
|
||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
#
|
||
|
# SPDX-FileCopyrightText: 2018 Coinkite, Inc. <coldcardwallet.com>
|
||
|
# SPDX-License-Identifier: GPL-3.0-only
|
||
|
#
|
||
|
# autogenerated; don't edit
|
||
|
#
|
||
|
class Graphics:
|
||
|
# (w,h, w_bytes, wbits, data)
|
||
|
|
||
|
""")
|
||
|
|
||
|
from io import StringIO
|
||
|
for fn in fnames:
|
||
|
if fn.endswith('.txt'):
|
||
|
img = read_text(fn)
|
||
|
else:
|
||
|
img = read_img(fn)
|
||
|
|
||
|
assert img.mode == '1'
|
||
|
#img.show()
|
||
|
|
||
|
varname = fn.split('.')[0].replace('-', '_')
|
||
|
|
||
|
w,h = img.size
|
||
|
raw = img.tobytes()
|
||
|
str = StringIO()
|
||
|
i=0
|
||
|
print('w={}, h={} len(raw)={}'.format(w, h, len(raw)))
|
||
|
str.write('{')
|
||
|
str.write(os.linesep)
|
||
|
for y in range(h):
|
||
|
str.write('{')
|
||
|
for x in range(w//8):
|
||
|
b = raw[(y * w//8) + x]
|
||
|
str.write('0x{:02x}{} '.format(b, ',' if x < w-1 else ''))
|
||
|
str.write('},\\n')
|
||
|
str.write('}\\n')
|
||
|
|
||
|
wbits, comp = crunch(raw)
|
||
|
|
||
|
if 0:
|
||
|
# is compression better?
|
||
|
is_comp = len(comp)+8 < len(raw)
|
||
|
else:
|
||
|
# disable; taking too much runtime memory
|
||
|
is_comp = False
|
||
|
|
||
|
print(" %s = (%d, %d, %d, %s, %r)\n" % (varname, w, h, ((w+7)//8),
|
||
|
wbits if is_comp else 0, str.getvalue() if not is_comp else comp), file=fp)
|
||
|
|
||
|
print("done: '%s' (%d x %d)" % (varname, w, h))
|
||
|
|
||
|
fp.write("\n# EOF\n")
|
||
|
|
||
|
if 1:
|
||
|
doit('graphics.py', sys.argv[1:])
|