Last active
December 19, 2015 23:43
-
-
Save sjlongland/8a0b90d850fc857610e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gd | |
import argparse | |
from sys import stdout | |
parser = argparse.ArgumentParser( | |
description='Extract bits from the border colour of each tile', | |
formatter_class=argparse.RawTextHelpFormatter) | |
parser.add_argument('--image', help='Image file to parse') | |
parser.add_argument('--invert', help='Invert the bits', | |
action='store_const', default=False, const=True) | |
parser.add_argument('--binary', help='Write binary', | |
action='store_const', default=False, const=True) | |
parser.add_argument('--bits', help='Number of bits per grouping', | |
type=int, default=8) | |
parser.add_argument('--output', help='Output file') | |
parser.add_argument('--tile-w', type=int, default=12, | |
help='Width of FEZ tile') | |
parser.add_argument('--tile-h', type=int, default=12, | |
help='Height of FEZ tile') | |
parser.add_argument('--offset-x', type=int, default=1, | |
help='X co-ordinate of first tile') | |
parser.add_argument('--offset-y', type=int, default=1, | |
help='Y co-ordinate of first tile') | |
parser.add_argument('--direction', default='rd', | |
help='''Order of traversal, one of: | |
- rd ("right then down": Start top-left, scan to bottom-right, | |
horizontally) | |
- ld ("left then down": Start top-right, scan to bottom-left, | |
horizontally) | |
- ru ("right then up": Start bottom-left, scan to top-right, | |
horizontally) | |
- lu ("left then up": Start bottom-right, scan to top-left, | |
horizontally) | |
- dr ("down then right": Start top-left, scan to bottom-right, | |
vertically) | |
- dl ("down then left": Start top-right, scan to bottom-left, | |
vertically) | |
- ur ("up then right": Start bottom-left, scan to top-right, | |
vertically) | |
- ul ("up then left": Start bottom-right, scan to top-left, | |
vertically)''') | |
args = parser.parse_args() | |
img = gd.image(args.image) | |
if args.output is not None: | |
out = file(args.output,'w') | |
else: | |
out = stdout | |
# Compute number of tiles | |
(p_width, p_height) = img.size() | |
width = (p_width - args.offset_x) // args.tile_w | |
height = (p_height - args.offset_y) // args.tile_h | |
tile_pos = lambda x, y : (((x*args.tile_w) + args.offset_x), \ | |
((y*args.tile_h) + args.offset_y)) | |
# Enumerate a list of co-ordinates to read. | |
if args.direction[0] in ('d','u'): | |
v_dir = args.direction[0] | |
h_dir = args.direction[1] | |
hv_dir = 'v' | |
elif args.direction[0] in ('l','r'): | |
h_dir = args.direction[0] | |
v_dir = args.direction[1] | |
hv_dir = 'h' | |
else: | |
raise ValueError('Invalid direction %r' % args.direction) | |
x_posn = range(0, width) | |
y_posn = range(0, height) | |
if h_dir == 'l': | |
x_posn.reverse() | |
if v_dir == 'u': | |
y_posn.reverse() | |
if hv_dir == 'v': | |
coordinates = [tile_pos(x,y) for x in x_posn for y in y_posn] | |
else: | |
coordinates = [tile_pos(x,y) for y in y_posn for x in x_posn] | |
# Inversion logic | |
if args.invert: | |
read_bit = lambda p : not bool(p) | |
else: | |
read_bit = lambda p : bool(p) | |
# Traverse the image, collect bits. | |
bits = args.bits | |
byte = 0 | |
for c in coordinates: | |
p = img.getPixel(c) | |
bit = read_bit(img.getPixel(c)) | |
if args.binary: | |
byte <<= 1 | |
if bit: | |
byte |= 1 | |
else: | |
if bit: | |
out.write('1') | |
else: | |
out.write('0') | |
bits -= 1 | |
if bits <= 0: | |
bits = args.bits | |
if args.binary: | |
out.write(chr(byte)) | |
byte = 0 | |
else: | |
out.write('\n') | |
if bits != args.bits: | |
if args.binary: | |
out.write(chr(byte)) | |
else: | |
out.write('\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment