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
|
#!/usr/bin/env python
"""
Convert Kobo RGB 565 (stdin) to PNG (stdout).
Assumes an 800x600 pixel input (compatible with 2013-era Kobo devices)
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 struct
import png
class Kobo565:
@staticmethod
def make_array(fil):
"""Convert RAW file *fil* to a 2D array."""
w = 800
h = 600
for i in range(h):
row = []
s = fil.read(w*2)
pixels = struct.unpack('<800H', s)
for p in pixels:
r = p >> 11
g = (p >> 5) & 0x3f
b = p & 0x1f
r = (r * 255) / 31.0
g = (g * 255) / 63.0
b = (b * 255) / 31.0
row.extend([int(round(x)) for x in [r, g, b]])
yield row
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
array = Kobo565.make_array(sys.stdin)
image = png.from_array(array, 'RGB', info=dict(height=600))
if outname is None:
image.save(sys.stdout)
else:
image.save(outname)
if __name__ == '__main__':
main()
|