def extents(im): """ find pixel extents of im, as a box """ w,h = im.size cols = [set(imbytes(im.crop((i, 0, i + 1, im.size[1])))) != set([0]) for i in range(w)] rows = [set(imbytes(im.crop((0, i, im.size[0], i + 1)))) != set([0]) for i in range(h)] if not True in cols: return (0, 0, 0, 0) else: x0 = cols.index(True) y0 = rows.index(True) while not cols[-1]: cols.pop() while not rows[-1]: rows.pop() return (x0, y0, len(cols), len(rows))
def extents(im): """ find pixel extents of im, as a box """ w, h = im.size cols = [ set(imbytes(im.crop((i, 0, i + 1, im.size[1])))) != set([0]) for i in range(w) ] rows = [ set(imbytes(im.crop((0, i, im.size[0], i + 1)))) != set([0]) for i in range(h) ] if not True in cols: return (0, 0, 0, 0) else: x0 = cols.index(True) y0 = rows.index(True) while not cols[-1]: cols.pop() while not rows[-1]: rows.pop() return (x0, y0, len(cols), len(rows))
def stretch(im): d = imbytes(im) # print min(d), max(d) r = max(d) - min(d) return im.point(lambda x: (x - min(d)) * 255 // r)
def convert(im, dither=False, fmt=ARGB1555): """ Convert PIL image to GD2 format, optionally dithering""" im = im.convert({ARGB1555: "RGBA", L1: "L", L2: "L", L4: "L", L8: "L", RGB332: "RGB", ARGB2: "RGBA", ARGB4: "RGBA", RGB565: "RGB", PALETTED: "RGB"}[fmt]) imdata = [] colorfmts = {ARGB1555: (1, 5, 5, 5), RGB332: (0, 3, 3, 2), ARGB2: (2, 2, 2, 2), ARGB4: (4, 4, 4, 4), RGB565: (0, 5, 6, 5)} if dither: rnd = random.Random() rnd.seed(0) if fmt in colorfmts: im = im.convert("RGBA") (asz, rsz, gsz, bsz) = colorfmts[fmt] totalsz = sum((asz, rsz, gsz, bsz)) assert totalsz in (8, 16) for y in range(im.size[1]): for x in range(im.size[0]): (r, g, b, a) = im.getpixel((x, y)) if dither: a = min(255, a + rnd.randrange(256 >> asz)) r = min(255, r + rnd.randrange(256 >> rsz)) g = min(255, g + rnd.randrange(256 >> gsz)) b = min(255, b + rnd.randrange(256 >> bsz)) binary = ((a >> (8 - asz)) << (bsz + gsz + rsz)) | ((r >> (8 - rsz)) << (gsz + bsz)) | ((g >> (8 - gsz)) << bsz) | (b >> (8 - bsz)) imdata.append(binary) fmtchr = {8: 'B', 16: 'H'}[totalsz] data = array.array('B', array.array(fmtchr, imdata).tostring()) elif fmt == PALETTED: im = im.convert("P", palette=Image.ADAPTIVE) lut = im.resize((256, 1)) lut.putdata(range(256)) palstr = lut.convert("RGBA").tobytes() rgba = zip(*(array.array('B', palstr[i::4]) for i in range(4))) data = imbytes(im) elif fmt == L8: data = imbytes(im) elif fmt == L4: b0 = imbytes(im)[::2] b1 = imbytes(im)[1::2] def to15(c): if dither: dc = min(255, c + rnd.randrange(16)) else: dc = c return int((15 * dc / 255)) data = array.array('B', [(16 * to15(l) + to15(r)) for (l, r) in zip(b0, b1)]) elif fmt == L2: b0 = imbytes(im)[::4] b1 = imbytes(im)[1::4] b2 = imbytes(im)[2::4] b3 = imbytes(im)[3::4] def to3(c): if dither: dc = min(255, c + rnd.randrange(64)) else: dc = c return int((3 * dc / 255)) data = array.array('B', [(64 * to3(a) + 16 * to3(b) + 4 * to3(c) + to3(d)) for (a, b, c, d) in zip(b0, b1, b2, b3)]) elif fmt == L1: if dither: im = im.convert("1", dither=Image.FLOYDSTEINBERG) else: im = im.convert("1", dither=Image.NONE) data = imbytes(im) else: assert 0, "Bad format {!r}".format(fmt) return im.size, data
def convert(im, dither=False, fmt=ARGB1555): """ Convert PIL image to GD2 format, optionally dithering""" im = im.convert({ ARGB1555: "RGBA", L1: "L", L2: "L", L4: "L", L8: "L", RGB332: "RGB", ARGB2: "RGBA", ARGB4: "RGBA", RGB565: "RGB", PALETTED: "RGB" }[fmt]) imdata = [] colorfmts = { ARGB1555: (1, 5, 5, 5), RGB332: (0, 3, 3, 2), ARGB2: (2, 2, 2, 2), ARGB4: (4, 4, 4, 4), RGB565: (0, 5, 6, 5) } if dither: rnd = random.Random() rnd.seed(0) if fmt in colorfmts: im = im.convert("RGBA") (asz, rsz, gsz, bsz) = colorfmts[fmt] totalsz = sum((asz, rsz, gsz, bsz)) assert totalsz in (8, 16) for y in range(im.size[1]): for x in range(im.size[0]): (r, g, b, a) = im.getpixel((x, y)) if dither: a = min(255, a + rnd.randrange(256 >> asz)) r = min(255, r + rnd.randrange(256 >> rsz)) g = min(255, g + rnd.randrange(256 >> gsz)) b = min(255, b + rnd.randrange(256 >> bsz)) binary = ((a >> (8 - asz)) << (bsz + gsz + rsz)) | ( (r >> (8 - rsz)) << (gsz + bsz)) | ((g >> (8 - gsz)) << bsz) | (b >> (8 - bsz)) imdata.append(binary) fmtchr = {8: 'B', 16: 'H'}[totalsz] imd = array.array(fmtchr, imdata) if PYTHON2: data = array.array('B', imd.tostring()) else: data = array.array('B', imd.tobytes()) elif fmt == PALETTED: im = im.convert("P", palette=Image.ADAPTIVE) lut = im.resize((256, 1)) lut.putdata(range(256)) palstr = lut.convert("RGBA").tobytes() rgba = zip(*(array.array('B', palstr[i::4]) for i in range(4))) data = imbytes(im) elif fmt == L8: data = imbytes(im) elif fmt == L4: b0 = imbytes(im)[::2] b1 = imbytes(im)[1::2] def to15(c): if dither: dc = min(255, c + rnd.randrange(16)) else: dc = c return int((15 * dc / 255)) data = array.array('B', [(16 * to15(l) + to15(r)) for (l, r) in zip(b0, b1)]) elif fmt == L2: b0 = imbytes(im)[::4] b1 = imbytes(im)[1::4] b2 = imbytes(im)[2::4] b3 = imbytes(im)[3::4] def to3(c): if dither: dc = min(255, c + rnd.randrange(64)) else: dc = c return int((3 * dc / 255)) data = array.array('B', [(64 * to3(a) + 16 * to3(b) + 4 * to3(c) + to3(d)) for (a, b, c, d) in zip(b0, b1, b2, b3)]) elif fmt == L1: if dither: im = im.convert("1", dither=Image.FLOYDSTEINBERG) else: im = im.convert("1", dither=Image.NONE) data = imbytes(im) else: assert 0, "Bad format {!r}".format(fmt) return im.size, data