blob: b7d1fbc5a7215710197c9b7bcecb1767f020b191 [file]
#!/usr/bin/env python
"""
Convert PNG (stdin) to the raw 565 format used on the Kobo devices.
On the 2013-era Kobo devices, the screen is 800x600 so this size
input PNG works best. Note: image top-left is screen top-right.
"""
# The raw format stores the pixels sequentially in top-left
# reading order; each pixel is a 16-bit word packed into bytes
# little-endian; the word stores (from high to low) 5 bits of
# Red, 6 bits of Green, 5 bits of Blue:
# 15 11 10 5 4 0
# +-------+---------+-------+
# | Red | Green | Blue |
# +-------+---------+-------+
# 15 8 7 0
# \ / \ /
# byte N+1 byte N
import png
class Kobo565:
@staticmethod
def from_array(array):
return Kobo565(array)
def __init__(self, array):
self.array = array
def save(self, file):
import struct
close = lambda: None
if not hasattr(file, 'write'):
file = open(file, 'wb')
close = file.close
try:
for row in self.array:
for r, g, b in row:
w = (r << 11) + (g << 5) + (b)
file.write(struct.pack('<H', w))
finally:
close()
def quads(i):
"""
[a, b, c, d, e, f, g, h, ...] -> [(a, b, c, d), (e, f, g, h)]
"""
return zip(*[iter(i)]*4)
def conv565(r, g, b, a):
"""
Convert to a triple in the range: (0 to 31, 0 to 63, 0 to 31).
"""
return (r >> 3, g >> 2, b >> 3)
def main():
import sys
outname = None
arg = sys.argv[1:]
while arg:
if arg[0] == '-o':
outname = arg[1]
arg = arg[2:]
elif arg[0] == '--':
arg = arg[1:]
break
elif arg[0].startswith('-'):
raise Exception("Unknown option %r" % arg[0])
else:
break
w, h, pixels, info = png.Reader(file=sys.stdin).asRGBA()
a565 = [[conv565(*t) for t in quads(row)] for row in pixels]
image = Kobo565.from_array(a565)
if outname is None:
image.save(sys.stdout)
else:
image.save(outname)
if __name__ == '__main__':
main()