mirror of
https://github.com/daniel5151/ANESE.git
synced 2025-04-02 10:32:00 -04:00
116 lines
3.9 KiB
Python
Executable file
116 lines
3.9 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# Bitmap to NES CHR converter using Python Imaging Library
|
|
# Copyright 2010 Damian Yerrick
|
|
#
|
|
# Copying and distribution of this file, with or without
|
|
# modification, are permitted in any medium without royalty
|
|
# provided the copyright notice and this notice are preserved.
|
|
# This file is offered as-is, without any warranty.
|
|
#
|
|
from __future__ import with_statement
|
|
from PIL import Image
|
|
from time import sleep
|
|
|
|
def formatTilePlanar(tile, nPlanes):
|
|
import array
|
|
if (tile.size != (8, 8)):
|
|
return None
|
|
pixels = iter(tile.getdata())
|
|
outplanes = [array.array('B')
|
|
for i in range(nPlanes)]
|
|
for y in range(8):
|
|
slivers = [0 for i in range(nPlanes)]
|
|
for x in range(8):
|
|
px = pixels.next()
|
|
for i in range(nPlanes):
|
|
slivers[i] = slivers[i] << 1
|
|
if px & 0x01:
|
|
slivers[i] = slivers[i] | 1
|
|
px >>= 1
|
|
for i in range(nPlanes):
|
|
outplanes[i].append(slivers[i])
|
|
out = "".join(plane.tostring() for plane in outplanes)
|
|
return out
|
|
|
|
def parse_argv(argv):
|
|
from optparse import OptionParser
|
|
parser = OptionParser(usage="usage: %prog [options] [-i] INFILE [-o] OUTFILE")
|
|
parser.add_option("-i", "--image", dest="infilename",
|
|
help="read image from INFILE", metavar="INFILE")
|
|
parser.add_option("-o", "--output", dest="outfilename",
|
|
help="write CHR data to OUTFILE", metavar="OUTFILE")
|
|
parser.add_option("-W", "--tile-width", dest="tileWidth",
|
|
help="set width of metatiles", metavar="HEIGHT",
|
|
type="int", default=8)
|
|
parser.add_option("-H", "--tile-height", dest="tileHeight",
|
|
help="set height of metatiles", metavar="HEIGHT",
|
|
type="int", default=8)
|
|
(options, args) = parser.parse_args(argv[1:])
|
|
|
|
tileWidth = int(options.tileWidth)
|
|
if tileWidth <= 0:
|
|
raise ValueError("tile width '%d' must be positive" % tileWidth)
|
|
|
|
tileHeight = int(options.tileHeight)
|
|
if tileHeight <= 0:
|
|
raise ValueError("tile height '%d' must be positive" % tileHeight)
|
|
|
|
# Fill unfilled roles with positional arguments
|
|
argsreader = iter(args)
|
|
try:
|
|
infilename = options.infilename
|
|
if infilename is None:
|
|
infilename = argsreader.next()
|
|
outfilename = options.infilename
|
|
if outfilename is None:
|
|
outfilename = argsreader.next()
|
|
except StopIteration:
|
|
raise ValueError("not enough filenames")
|
|
try:
|
|
argsreader.next()
|
|
raise ValueError("too many filenames")
|
|
except StopIteration:
|
|
pass
|
|
|
|
return (infilename, outfilename, tileWidth, tileHeight)
|
|
|
|
argvTestingMode = True
|
|
|
|
def main(argv=None):
|
|
if argv is None:
|
|
import sys
|
|
import os
|
|
argv = sys.argv
|
|
print argv
|
|
if (argvTestingMode and len(argv) < 2
|
|
and sys.stdin.isatty() and sys.stdout.isatty()):
|
|
argv.extend(raw_input('args:').split())
|
|
try:
|
|
(infilename, outfilename, tileWidth, tileHeight) = parse_argv(argv)
|
|
except StandardError, e:
|
|
import sys
|
|
sys.stderr.write("%s: %s\n" % (argv[0], str(e)))
|
|
sys.exit(1)
|
|
|
|
print "loading", infilename
|
|
im = Image.open(infilename)
|
|
im.load()
|
|
(w, h) = im.size
|
|
|
|
out = []
|
|
for mt_y in range(0, h, tileHeight):
|
|
for mt_x in range(0, w, tileWidth):
|
|
metatile = im.crop((mt_x, mt_y,
|
|
mt_x + tileWidth, mt_y + tileHeight))
|
|
for tile_y in range(0, tileHeight, 8):
|
|
for tile_x in range(0, tileWidth, 8):
|
|
tile = metatile.crop((tile_x, tile_y,
|
|
tile_x + 8, tile_y + 8))
|
|
data = formatTilePlanar(tile, 2)
|
|
out.append(data)
|
|
with open(outfilename, 'wb') as outfp:
|
|
outfp.writelines(out)
|
|
|
|
if __name__=='__main__':
|
|
main()
|