Mercurial > repos > ghero
diff tiles2img.py @ 3:97ec271a513f
Bunch of changes
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 02 Sep 2013 21:22:47 -0700 |
parents | |
children | 3148b6389042 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tiles2img.py Mon Sep 02 21:22:47 2013 -0700 @@ -0,0 +1,229 @@ +#!/usr/bin/env python +from PIL import Image + +def gchannel(Val): + return (Val >> 4) & 0xE + +threshold = 127 + +def get_color_info(pixels, rng, threshold, exclude={}): + gencolors = {} + A = 255 + for idx in rng: + color = pixels[idx] + if len(color) == 4: + (R, G, B, A) = color + else: + (R, G, B) = color + if A > threshold: + gcolor = (gchannel(R), gchannel(G), gchannel(B)) + if not gcolor in exclude: + if gcolor in gencolors: + gencolors[gcolor] += 1 + else: + gencolors[gcolor] = 1 + glist = [(gencolors[color], color) for color in gencolors] + glist.sort() + glist.reverse() + return glist + +def totiles(im, palette): + pass + +def make_palette(im, trans_thresh, max_global, max_line): + pixels = im.getdata() + (width, height) = im.size + colors = get_color_info(pixels, xrange(0, height * width), trans_thresh) + glob_pal = {} + for idx in xrange(0, min(max_global, len(colors))): + (count, color) = colors[idx] + glob_pal[color] = idx + line_pals = [] + if max_global < len(colors): + for line in xrange(0, height): + linestart = line * width + linecolors = get_color_info(pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal) + line_pal = {} + for idx in xrange(0, min(max_line, len(linecolors))): + (count, color) = linecolors[idx] + line_pal[color] = idx + line_pals.append(line_pal) + return (glob_pal, line_pals) + +def color_dist(a, b): + (ra, ga, ba) = a + (rb, gb, bb) = b + return abs(ra-rb)**2 + abs(ga-gb)**2 + abs(ba-bb)**2 + +def trans_image(im, trans_thresh, pal): + (global_pal, line_pals) = pal + pixels = im.getdata() + (width, height) = im.size + gpixels = [] + A = 255 + x = 0 + y = 0 + for pixel in pixels: + if x == width: + x = 0 + y += 1 + if width % 8: + for i in xrange(0, 8-(width%8)): + gpixels.append(0) + if len(pixel) == 4: + (R, G, B, A) = pixel + else: + (R, G, B) = pixel + if A > trans_thresh: + gpixel = (gchannel(R), gchannel(G), gchannel(B)) + if gpixel in global_pal: + gpixels.append(global_pal[gpixel]) + elif gpixel in line_pals[y]: + gpixels.append(line_pals[y][gpixel] + len(global_pal)) + else: + bestdist = color_dist((0,0,0), (15, 15, 15)) + bestpal = 0 + for cur in global_pal: + curdist = color_dist(gpixel, cur) + if curdist < bestdist: + bestdist = curdist + bestpal = global_pal[cur] + for cur in line_pals[y]: + curdist = color_dist(gpixel, cur) + if curdist < bestdist: + bestdist = curdist + bestpal = line_pals[y][cur] + gpixels.append(bestpal) + else: + gpixels.append(0) + x += 1 + if width % 8: + for i in xrange(0, 8-(width%8)): + gpixels.append(0) + width += 8-(width%8) + if height % 8: + for y in xrange(0, 8-(height%8)): + for x in xrange(0, width): + gpixels.append(0) + height += 8-(height%8) + + return (width, height, gpixels) + +def appendword(b, word): + b.append(word >> 8) + b.append(word & 0xff) + +def to_tiles(palpix): + (width, height, pixels) = palpix + b = bytearray() + cwidth = width/8 + cheight = height/8 + words = len(pixels)/4 + appendword(b, words) + appendword(b, cwidth) + appendword(b, cheight) + + for cy in xrange(0, cheight): + ystart = cy*8*width + for cx in xrange(0, cwidth): + startoff = (cx*8) + ystart + for row in xrange(0, 8): + rowoff = startoff + row*width + for bytecol in xrange(0, 4): + boff = bytecol * 2 + rowoff + #print 'boff:', boff, 'len(pixels)', len(pixels), 'cx', cx, 'cy', cy, 'cwidth', cwidth, 'cheight', cheight + #print 'pixels[boff]:', pixels[boff] + b.append(pixels[boff] << 4 | pixels[boff+1]) + return b + +def add_pal_entries(tiles, pal): + (global_pal, line_pals) = pal + pal_list = [()] * len(global_pal) + for entry in global_pal: + pal_list[global_pal[entry]] = entry + for entry in pal_list: + (R, G, B) = entry + tiles.append(B) + tiles.append(G << 4 | R) + for line in line_pals: + pal_list = [()] * len(line) + for entry in line: + pal_list[line[entry]] = entry + for entry in pal_list: + (R, G, B) = entry + tiles.append(B) + tiles.append(G << 4 | R) + +def getcolor(tiles, fixedpal, linepals, width, x, y): + celly = y/8 + cellx = x/8 + resty = y%8 + restx = x%8 + cellwidth = width / 8 + offset = celly * 32 * cellwidth + resty * 4 + cellx * 32 + restx / 2 + if restx & 1: + palidx = tiles[offset] & 0xF + else: + palidx = (tiles[offset] >> 4) & 0xF + if palidx < len(fixedpal): + return fixedpal[palidx] + return linepals[y][palidx - len(fixedpal)] + +def to_pixels(tiles, im): + (_, width, height), tiles, (fixedpal, linepals) = tiles + for y in xrange(0, height): + for x in xrange(0, width): + color = getcolor(tiles, fixedpal, linepals, width, x, y) + im.putpixel((x,y), color) + return im + +def expand_pal(pal): + def expand_pal_int(pal): + return ((pal << 4) & 0xE0, pal & 0xE0, (pal >> 4) & 0xE0) + fixedpal, linepals = pal + fixedpal = [expand_pal_int(color) for color in fixedpal] + linepals = [[expand_pal_int(color) for color in linepal] for linepal in linepals] + return (fixedpal, linepals) + +def open_tiles(name): + from struct import unpack, unpack_from + f = open(name, 'rb') + header = f.read(6) + words,width,height = unpack('>HHH', header) + width *= 8 + height *= 8 + meta = (words, width, height) + pixels = bytearray(f.read(words * 2)) + numfixed = 12 + numdynamic = 4 + fixedpalb = f.read(numfixed*2) + fixedpal = [] + for offset in xrange(0, numfixed*2, 2): + color, = unpack_from('>H', fixedpalb, offset) + fixedpal.append(color) + linepals = [] + linepalsize = numdynamic * height * 2 + linepalb = f.read(linepalsize) + for baseoffset in xrange(0, linepalsize, numdynamic * 2): + linepal = [] + for offset in xrange(baseoffset, baseoffset + numdynamic * 2, 2): + color, = unpack_from('>H', linepalb, offset) + linepal.append(color) + linepals.append(linepal) + return (meta, pixels, (fixedpal, linepals)) + +def main(argv): + if len(argv) < 3: + print "Not enough arguments" + return + fname = argv[1] + tiles = open_tiles(fname) + im = Image.new('RGB', (tiles[0][1], tiles[0][2])) + tiles = (tiles[0], tiles[1], expand_pal(tiles[2])) + to_pixels(tiles, im) + out = open(argv[2], 'wb') + im.save(out) + +if __name__ == '__main__': + import sys + main(sys.argv)