import sys
import Image
from array import array

from GDprep import dump, rgb555, encode

font8x8 = array('B', open('font8x8').read())
hh = open("../font8x8.h", "w")
dump(hh, "font8x8", font8x8);



def rotations(im):
    nf = 4
    (w,h) = im.size
    frames = Image.new(im.mode, (w,h*nf))
    for i in range(nf):
        frames.paste(im.rotate(i*90/nf, Image.LINEAR) , (0,h*i))
    return frames

def tile(im):
    (w,h) = im.size
    n = Image.new(im.mode, (16, (w/16) * h))
    i = 0   # tile counter
    for y in range(0, h, 16):
        for x in range(0, w, 16):
            n.paste(im.crop((x,y,x+16,y+16)), (0, 16 * i))
            i += 1
    return n

if 1:
    im = Image.open("liberator64.png")
    im = rotations(im)
    # Get the alpha band
    if im.mode == "RGBA":
        alpha = im.split()[3]
        mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
        # Convert the image into P mode but only use 255 colors in the palette out of 256
        im.paste((0,0,0), mask)
        im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=15)
        # Set all pixel values below 128 to 255,
        # and the rest to 0
        # Paste the color of index 255 and use alpha as a mask
        im.paste(15, mask)
        transparent = 15
    else:
        im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
        transparent = None

im.save("preview.png")
lut = im.resize((256,1))
lut.putdata(range(256))
palstr = lut.convert("RGB").tostring()
rgbs = zip(*(array('B', palstr[i::3]) for i in range(3)))
rgb_555 = [(((r / 8) << 10) | ((g / 8) << 5) | (b / 8)) for (r,g,b) in rgbs]
if transparent is not None:
    rgb_555[transparent] |= 0x8000

hh = open("../liberator.h", "w")
dump(hh, "liberator_palette", array('H', rgb_555))


locs = {}
packdata = []
for frame in range(4):
    for y in range(4):
        for x in range(4):
            xx = 16 * x
            yy = 64 * frame + 16 * y
            pixels = array('B', im.crop((xx,yy,xx+16,yy+16)).tostring())
            if set(pixels) == set([15]):
                locs[(frame,x,y)] = None
            else:
                locs[(frame,x,y)] = len(packdata)
                packdata.append(pixels)
if len(packdata) & 1:
    packdata.append(array('B', [0]*256))
doubledata = []
for i in range(0, len(packdata), 2):
    lo = packdata[i]
    hi = packdata[i + 1]
    doubledata += [((h << 4) + l) for (h, l) in zip(hi, lo)]
dump(hh, "liberator_image", array('B', doubledata));

print >>hh, """static void draw_liberator(int spr, int x, int y, byte anim, byte image, byte palette, byte rot)
{
  GD.__wstart(0x3000 + (spr << 2));"""

for frame in range(4):
    print >>hh, "if (anim == %d) {" % frame
    for y in range(4):
        for x in range(4):
            loc = locs[(frame, x, y)]
            if loc is None:
                print >>hh, "GD.xsprite(0, 400, 0, 0, 0, 0, 0);" 
            else:
                index = loc / 2
                subindex = loc % 2
                print >>hh, "GD.xsprite(x, y, %d, %d, image + %d, %d, rot);" % (-32 + x * 16, -32 + y * 16, index, 4 + (subindex << 1))
    print >>hh, "}"
print >>hh, """ GD.__end();
}
"""

for fn in ["bg", "Wood32", "stone_wall_texture", "sprites256", "platformer"]:
    bg = Image.open("%s.png" % fn).convert("RGB")
    (picdata, chrdata, paldata) = encode(bg)
    print fn, len(chrdata) / 16
    hh = open("../%s.h" % fn, "w")
    dump(hh, "%s_pic" % fn, picdata)
    dump(hh, "%s_chr" % fn, chrdata)
    dump(hh, "%s_pal" % fn, paldata)

def pal555(im, ncol = 255):
    if im.mode == "RGBA":
        alpha = im.split()[3]
        mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
        # Convert the image into P mode but only use 255 colors in the palette out of 256
        im.paste((0,0,0), mask)
        im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=ncol)
        # Set all pixel values below 128 to 255,
        # and the rest to 0
        # Paste the color of index 255 and use alpha as a mask
        im.paste(ncol, mask)
        transparent = ncol
    else:
        im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=ncol)
        transparent = None
    # Return the RGB555 palette used by im
    lut = im.resize((256,1))
    lut.putdata(range(256))
    palstr = lut.convert("RGB").tostring()
    rgbs = zip(*(array('B', palstr[i::3]) for i in range(3)))
    rgb555 = [(((r / 8) << 10) | ((g / 8) << 5) | (b / 8)) for (r,g,b) in rgbs]
    if transparent:
        rgb555[transparent] = 0x8000
    return (im, rgb555)

for (fn, ncol) in [("r", 15), ("lena", 255), ("sphere", 255), ("digits", 256), ("pickups2", 255)]:
    im = Image.open("%s.png" % fn)
    im.load()
    (im, pal) = pal555(im, ncol)
    hh = open("../%s.h" % fn, "w")
    dump(hh, "%s_img" % fn, tile(im))
    dump(hh, "%s_pal" % fn, array('H', pal))
open("lena", "w").write((pal555(Image.open("lena.png"), 256)[0]).tostring())

def alphamask(alpha):
    mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
    return mask

if 0:
    im = Image.open("Staunton32.png")

    larger = Image.new("RGBA", (im.size[0], im.size[1] + 16))
    larger.paste(im, (0,0))
    alpha = larger.split()[3]
    mask = alphamask(alpha)
    larger.paste((0,0,0), (0,0), mask)
    larger = larger.convert("RGB").convert('P', palette=Image.ADAPTIVE, colors=255)

    lut = larger.resize((16,16))
    lut.putdata(range(256))

    larger = Image.merge("RGBA", larger.convert("RGB").split() + (alpha,))
    larger.paste(lut, (0, im.size[1]))
    larger.save("Staunton32pal.png")

def rgbs(im):
    str = im.convert("RGB").tostring()
    return zip(*(array('B', str[i::3]) for i in range(3)))

def rgbas(im):
    str = im.convert("RGBA").tostring()
    return zip(*(array('B', str[i::4]) for i in range(4)))

def lutdata(palette):
    lst = [rgb555(*p) for p in palette]
    return array('H', [0x8000] + lst[:255])

hh = open("../staunton.h", "w")

im = Image.open("Staunton32pal.png")
w,h = im.size
lut = im.crop((0, h - 16, 16, h))
whitepalette = rgbs(lut)
dump(hh, "staunton_white", lutdata(whitepalette))

blk = Image.open("Staunton32blk.png")
lut = blk.crop((0, h - 16, 16, h))
dump(hh, "staunton_black", lutdata(rgbs(lut)))

body = tile(im.crop((0, 0, w, h - 16)))
def lookup(pal, pixel):
    (r,g,b,a) = pixel
    if a < 128:
        return 0
    else:
        return 1 + pal.index((r,g,b))

dump(hh, "staunton_img", array('B', [lookup(whitepalette, p) for p in rgbas(body)]))

if 0:
    import ImageFont
    import ImageDraw

    font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-bitstream-vera/VeraMono.ttf", 27);
    im = Image.new("L", (640,480))
    draw = ImageDraw.Draw(im)
    for i,ch in enumerate("0123456789:"):
        sz = draw.textsize(ch, font=font)
        print ch, sz
        draw.text((0 + 16 * i, 0), ch, font=font, fill=255)
    im.save("preview.png")

im = Image.open("font16.png")
(im, pal) = pal555(im, 4)
hh = open("../font16.h", "w")
dump(hh, "font16_pal", array('H', pal[:4]))
packed = array('B', [0] * (16 * 256))

# dump(hh, "font16_img", tile(im))
