convert to and from RGBA images instead of palette based ones
This commit is contained in:
parent
6c2557dec8
commit
7c5377d29b
5 changed files with 110 additions and 53 deletions
27
common.py
27
common.py
|
@ -1,27 +0,0 @@
|
|||
import crcmod
|
||||
import colorsys
|
||||
|
||||
from PIL import ImageFont
|
||||
|
||||
font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", 34)
|
||||
|
||||
def sanitize_filename(fname):
|
||||
# find the first character outside range [32-126]
|
||||
for i,c in enumerate(fname):
|
||||
if ord(c) < 32 or ord(c) > 126:
|
||||
break
|
||||
return fname[:i]
|
||||
|
||||
def get_complement(r,g,b):
|
||||
r = r/255.0
|
||||
g = g/255.0
|
||||
b = b/255.0
|
||||
h,l,s = colorsys.rgb_to_hls(r, g, b)
|
||||
if h > 0.5:
|
||||
h -= 0.5
|
||||
else:
|
||||
h += 0.5
|
||||
r,g,b = colorsys.hls_to_rgb(h, l, s)
|
||||
return int(r*255), int(g*255), int(b*255)
|
||||
|
||||
crc24_func = crcmod.mkCrcFun(0x1864CFBL) # polynomial from libgcrypt
|
|
@ -25,13 +25,7 @@ from PIL import Image, ImageDraw
|
|||
from collections import defaultdict
|
||||
import os
|
||||
import json
|
||||
from common import crc24_func, font, sanitize_filename
|
||||
|
||||
def get_color(fname):
|
||||
crc = crc24_func(fname)
|
||||
# values 0-7 must not be used as they might represent transparency
|
||||
# so we are left with 248 values
|
||||
return 8+crc%248
|
||||
import numpy as np
|
||||
|
||||
def extract_def(infile,outdir):
|
||||
f = open(infile)
|
||||
|
@ -176,14 +170,33 @@ def extract_def(infile,outdir):
|
|||
else:
|
||||
print "unknown format: %d"%fmt
|
||||
return False
|
||||
im = Image.fromstring('P', (w,h),pixeldata)
|
||||
imp = Image.fromstring('P', (w,h),pixeldata)
|
||||
imp.putpalette(palette)
|
||||
# convert to RGBA
|
||||
imrgb = imp.convert("RGBA")
|
||||
# replace special colors
|
||||
# 0 -> (0,0,0,0) = full transparency
|
||||
# 1 -> (0,0,0,0x40) = shadow border
|
||||
# 2 -> ???
|
||||
# 3 -> ???
|
||||
# 4 -> (0,0,0,0x80) = shadow body
|
||||
# 5 -> (0,0,0,0) = selection highlight, treat as full transparency
|
||||
# 6 -> (0,0,0,0x80) = shadow body below selection, treat as shadow body
|
||||
# 7 -> (0,0,0,0x40) = shadow border below selection, treat as shadow border
|
||||
pixrgb = np.array(imrgb)
|
||||
pixp = np.array(imp)
|
||||
pixrgb[pixp == 0] = (0,0,0,0)
|
||||
pixrgb[pixp == 1] = (0,0,0,0x40)
|
||||
pixrgb[pixp == 4] = (0,0,0,0x80)
|
||||
pixrgb[pixp == 5] = (0,0,0,0)
|
||||
pixrgb[pixp == 6] = (0,0,0,0x80)
|
||||
pixrgb[pixp == 7] = (0,0,0,0x40)
|
||||
imrgb = Image.fromarray(pixrgb)
|
||||
im = Image.new('RGBA', (fw,fh), (0,0,0,0))
|
||||
im.paste(imrgb,(lm,tm))
|
||||
else: # either width or height is zero
|
||||
im = None
|
||||
imo = Image.new('P', (fw,fh))
|
||||
imo.putpalette(palette)
|
||||
if im:
|
||||
imo.paste(im,(lm,tm))
|
||||
imo.save(outname)
|
||||
im = Image.new('RGBA', (fw,fh), (0,0,0,0))
|
||||
im.save(outname)
|
||||
out_json["sequences"].append({"group":bid,"frames":frames})
|
||||
with open(os.path.join(outdir,"%s.json"%bn),"w+") as o:
|
||||
json.dump(out_json,o,indent=4)
|
||||
|
|
11
definfo.py
11
definfo.py
|
@ -19,7 +19,12 @@
|
|||
import struct
|
||||
from collections import defaultdict
|
||||
|
||||
from common import sanitize_filename
|
||||
def sanitize_filename(fname):
|
||||
# find the first character outside range [32-126]
|
||||
for i,c in enumerate(fname):
|
||||
if ord(c) < 32 or ord(c) > 126:
|
||||
break
|
||||
return fname[:i]
|
||||
|
||||
def main(infile):
|
||||
f = open(infile)
|
||||
|
@ -28,8 +33,8 @@ def main(infile):
|
|||
palette = []
|
||||
for i in range(256):
|
||||
r,g,b = struct.unpack("<BBB", f.read(3))
|
||||
palette.extend((r,g,b))
|
||||
print palette
|
||||
palette.append((r,g,b))
|
||||
print "palette: %s"%(' '.join(["#%02x%02x%02x"%(r,g,b) for r,g,b in palette]))
|
||||
offsets = defaultdict(list)
|
||||
for i in range(blocks):
|
||||
bid,entries,x_,y_ = struct.unpack("<IIII", f.read(16))
|
||||
|
|
|
@ -21,8 +21,6 @@ import struct
|
|||
import os
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from common import crc24_func, get_complement, font
|
||||
|
||||
def is_pcx(data):
|
||||
size,width,height = struct.unpack("<III",data[:12])
|
||||
return size == width*height or size == width*height*3
|
||||
|
|
82
makedef.py
82
makedef.py
|
@ -21,6 +21,8 @@ import struct
|
|||
import json
|
||||
from collections import defaultdict
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
ushrtmax = (1<<16)-1
|
||||
|
||||
def encode0(im):
|
||||
|
@ -172,6 +174,9 @@ def makedef(infile, outdir):
|
|||
p = os.path.splitext(p)[0].lower()
|
||||
d = os.path.dirname(infile)
|
||||
|
||||
outname = os.path.join(outdir,p)+".def"
|
||||
print "writing to %s"%outname
|
||||
|
||||
# sanity checks and fill infiles dict
|
||||
for seq in in_json["sequences"]:
|
||||
bid = seq["group"]
|
||||
|
@ -192,10 +197,13 @@ def makedef(infile, outdir):
|
|||
w = (((w-1)>>5)+1)<<5
|
||||
rm = lm+w
|
||||
im = im.crop((lm,tm,rm,bm))
|
||||
if im.mode != 'P':
|
||||
print "input images must have a palette"
|
||||
if im.mode == 'P':
|
||||
cursig =(fw,fh,im.getpalette())
|
||||
elif im.mode == 'RGBA':
|
||||
cursig =(fw,fh,None)
|
||||
else:
|
||||
print "input images must be rgba or palette based"
|
||||
return False
|
||||
cursig =(fw,fh,im.getpalette())
|
||||
if not sig:
|
||||
sig = cursig
|
||||
else:
|
||||
|
@ -204,16 +212,76 @@ def makedef(infile, outdir):
|
|||
print sig
|
||||
print cursig
|
||||
return False
|
||||
data,size = fmtencoders[fmt](im)
|
||||
infiles[bid].append((w,h,lm,tm,data,size))
|
||||
infiles[bid].append((lm,tm,im))
|
||||
|
||||
if len(infiles) == 0:
|
||||
print "no input files detected"
|
||||
return False
|
||||
|
||||
fw,fh,pal = cursig
|
||||
outname = os.path.join(outdir,p)+".def"
|
||||
print "writing to %s"%outname
|
||||
numframes = sum(len(l) for l in infiles.values())
|
||||
|
||||
# input images were RGB, find a good common palette
|
||||
if not pal:
|
||||
# create a concatenation of all images to create a good common palette
|
||||
concatim = Image.new("RGB",(fw,fh*numframes))
|
||||
num = 0
|
||||
for _,l in infiles.items():
|
||||
for _,_,im in l:
|
||||
concatim.paste(im, (0,fh*num))
|
||||
num+=1
|
||||
# convert that concatenation to a palette image to obtain a good common palette
|
||||
concatim = concatim.convert("P", dither=None, colors=248, palette=Image.ADAPTIVE)
|
||||
# concatenate the 248 colors to the 8 special ones
|
||||
pal = [0x00, 0xff, 0xff, # full transparency
|
||||
0xff, 0x96, 0xff, # shadow border
|
||||
0xff, 0x64, 0xff, # ???
|
||||
0xff, 0x32, 0xff, # ???
|
||||
0xff, 0x00, 0xff, # shadow body
|
||||
0xff, 0xff, 0x00, # selection highlight
|
||||
0xb4, 0x00, 0xff, # shadow body below selection
|
||||
0x00, 0xff, 0x00, # shadow border below selection
|
||||
] + concatim.getpalette()[:744]
|
||||
# convert RGBA images to P images with the common palette
|
||||
for bid,l in infiles.items():
|
||||
newl = []
|
||||
for lm,tm,im in l:
|
||||
w,h = im.size
|
||||
if w == 0 or h == 0:
|
||||
imp = None
|
||||
else:
|
||||
# must convert to RGB first for quantize() to work
|
||||
imrgb = im.convert("RGB")
|
||||
imp = imrgb.quantize(palette=concatim)
|
||||
# now shift the colors by 8
|
||||
pix = np.array(imp)
|
||||
pix += 8
|
||||
imp = Image.fromarray(pix)
|
||||
# now replace full transparency in the original RGBA image with index 0
|
||||
pixrgba = np.array(im)
|
||||
alpha = pixrgba[:,:,3]
|
||||
pix[alpha == 0] = 0
|
||||
# now replace any half-transpareny with shadow body (index 4)
|
||||
pix[(alpha > 0) & (alpha < 0xff)] = 4
|
||||
# TODO: calculate shadow border
|
||||
# now put the palette with the special colors
|
||||
imp.putpalette(pal)
|
||||
newl.append((lm,tm,imp))
|
||||
infiles[bid] = newl
|
||||
|
||||
# encode all images according to the required format
|
||||
for bid,l in infiles.items():
|
||||
newl = []
|
||||
for lm,tm,im in l:
|
||||
if im:
|
||||
w,h = im.size
|
||||
data,size = fmtencoders[fmt](im)
|
||||
else:
|
||||
w,h = 0,0
|
||||
data,size = '',0
|
||||
newl.append((w,h,lm,tm,data,size))
|
||||
infiles[bid] = newl
|
||||
|
||||
outf = open(outname, "w+")
|
||||
|
||||
# write the header
|
||||
|
|
Loading…
Reference in a new issue