#!/usr/bin/env python import os import re import struct from collections import defaultdict from PIL import Image ushrtmax = (1<<16)-1 def encode0(im): return ''.join([chr(i) for i in list(im.getdata())]) # greedy RLE # for each pixel, test which encoding manages to encode most data, then apply # that encoding and look at the next pixel after the encoded chunk def encode1(im): pixels = im.load() w,h = im.size result = [] # these function return a tuple of the compressed string and the amount of # pixels compressed def rle_comp(x,y): # find all pixels after the first one with the same color color = pixels[x,y] if color == 0xff: # this color can't be run length encoded return raw_comp(x,y) else: count = 1 for x in range(x+1,w): if pixels[x,y] == color and count < 255: count += 1 else: break return (struct.pack(" rawl: r += rlec x += rlel else: r += rawc x += rawl result.append(r) return result def encode23chunk(s,e,pixels,y): r = '' if pixels[s,y] < 8: colors = pixels[s,y] count = 1 else: colors = [pixels[s,y]] count = 0 for x in range(s+1,e): color = pixels[x,y] if count > 0: # rle was started if color == colors and count < 32: # same color again, increase count count+=1 else: # either new color or maximum length reached, so write current one r+=struct.pack(" 31: # new rle color, or maximum length reached so write current non rle r+=struct.pack(" 0: # write rle r+=struct.pack(">5)+1)<<5 rm = lm+w im = im.crop((lm,tm,rm,bm)) if im.mode != 'P': print "input images must have a palette" return False cursig =(t,p,fw,fh,im.getpalette(),fmt) if not sig: sig = cursig else: if sig != cursig: print "sigs must match - got:" print sig print cursig return False if len(fn) > 9: print "filename can't be longer than 9 bytes" return False data = fmtencoders[fmt](im) infiles[bid].append((im,t,p,j,fn,lm,tm,fmt,data)) if len(infiles) == 0: print "no input files detected" return False # check if j values for all bids are correct and sort them in j order in the process for bid in infiles: infiles[bid].sort(key=lambda t: t[3]) for k,(_,_,_,j,_,_,_,_,_) in enumerate(infiles[bid]): if k != j: print "incorrect j value %d for bid %d should be %d"%(j,bid,k) t,p,fw,fh,pal,fmt = cursig outname = os.path.join(outdir,p)+".def" print "writing to %s"%outname outf = open(outname, "w+") # write the header # full width and height are not used and not the same for all frames # in some defs, so just putting the last known value outf.write(struct.pack(" ushrtmax: print "exceeding max ushort value: %d"%offs return False lineoffs.append(offs) acc += len(d) outf.write(struct.pack("<%dH"%h, *lineoffs)) outf.write(struct.pack(" ushrtmax: print "exceeding max ushort value: %d"%offs return False lineoffs.append(offs) acc += len(e) outf.write(struct.pack("<"+"H"*(w/32)*h, *lineoffs)) for d in data: # line for e in d: # 32 pixel block outf.write(e) return True if __name__ == '__main__': import sys if len(sys.argv) != 3: print "usage: %s indir outdir"%sys.argv[0] exit(1) ret = makedef(sys.argv[1], sys.argv[2]) exit(0 if ret else 1)