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
|
from collections import defaultdict
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from common import crc24_func, font, sanitize_filename
|
import numpy as np
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def extract_def(infile,outdir):
|
def extract_def(infile,outdir):
|
||||||
f = open(infile)
|
f = open(infile)
|
||||||
|
@ -176,14 +170,33 @@ def extract_def(infile,outdir):
|
||||||
else:
|
else:
|
||||||
print "unknown format: %d"%fmt
|
print "unknown format: %d"%fmt
|
||||||
return False
|
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
|
else: # either width or height is zero
|
||||||
im = None
|
im = Image.new('RGBA', (fw,fh), (0,0,0,0))
|
||||||
imo = Image.new('P', (fw,fh))
|
im.save(outname)
|
||||||
imo.putpalette(palette)
|
|
||||||
if im:
|
|
||||||
imo.paste(im,(lm,tm))
|
|
||||||
imo.save(outname)
|
|
||||||
out_json["sequences"].append({"group":bid,"frames":frames})
|
out_json["sequences"].append({"group":bid,"frames":frames})
|
||||||
with open(os.path.join(outdir,"%s.json"%bn),"w+") as o:
|
with open(os.path.join(outdir,"%s.json"%bn),"w+") as o:
|
||||||
json.dump(out_json,o,indent=4)
|
json.dump(out_json,o,indent=4)
|
||||||
|
|
11
definfo.py
11
definfo.py
|
@ -19,7 +19,12 @@
|
||||||
import struct
|
import struct
|
||||||
from collections import defaultdict
|
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):
|
def main(infile):
|
||||||
f = open(infile)
|
f = open(infile)
|
||||||
|
@ -28,8 +33,8 @@ def main(infile):
|
||||||
palette = []
|
palette = []
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
r,g,b = struct.unpack("<BBB", f.read(3))
|
r,g,b = struct.unpack("<BBB", f.read(3))
|
||||||
palette.extend((r,g,b))
|
palette.append((r,g,b))
|
||||||
print palette
|
print "palette: %s"%(' '.join(["#%02x%02x%02x"%(r,g,b) for r,g,b in palette]))
|
||||||
offsets = defaultdict(list)
|
offsets = defaultdict(list)
|
||||||
for i in range(blocks):
|
for i in range(blocks):
|
||||||
bid,entries,x_,y_ = struct.unpack("<IIII", f.read(16))
|
bid,entries,x_,y_ = struct.unpack("<IIII", f.read(16))
|
||||||
|
|
|
@ -21,8 +21,6 @@ import struct
|
||||||
import os
|
import os
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
from common import crc24_func, get_complement, font
|
|
||||||
|
|
||||||
def is_pcx(data):
|
def is_pcx(data):
|
||||||
size,width,height = struct.unpack("<III",data[:12])
|
size,width,height = struct.unpack("<III",data[:12])
|
||||||
return size == width*height or size == width*height*3
|
return size == width*height or size == width*height*3
|
||||||
|
|
82
makedef.py
82
makedef.py
|
@ -21,6 +21,8 @@ import struct
|
||||||
import json
|
import json
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
ushrtmax = (1<<16)-1
|
ushrtmax = (1<<16)-1
|
||||||
|
|
||||||
def encode0(im):
|
def encode0(im):
|
||||||
|
@ -172,6 +174,9 @@ def makedef(infile, outdir):
|
||||||
p = os.path.splitext(p)[0].lower()
|
p = os.path.splitext(p)[0].lower()
|
||||||
d = os.path.dirname(infile)
|
d = os.path.dirname(infile)
|
||||||
|
|
||||||
|
outname = os.path.join(outdir,p)+".def"
|
||||||
|
print "writing to %s"%outname
|
||||||
|
|
||||||
# sanity checks and fill infiles dict
|
# sanity checks and fill infiles dict
|
||||||
for seq in in_json["sequences"]:
|
for seq in in_json["sequences"]:
|
||||||
bid = seq["group"]
|
bid = seq["group"]
|
||||||
|
@ -192,10 +197,13 @@ def makedef(infile, outdir):
|
||||||
w = (((w-1)>>5)+1)<<5
|
w = (((w-1)>>5)+1)<<5
|
||||||
rm = lm+w
|
rm = lm+w
|
||||||
im = im.crop((lm,tm,rm,bm))
|
im = im.crop((lm,tm,rm,bm))
|
||||||
if im.mode != 'P':
|
if im.mode == 'P':
|
||||||
print "input images must have a palette"
|
|
||||||
return False
|
|
||||||
cursig =(fw,fh,im.getpalette())
|
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
|
||||||
if not sig:
|
if not sig:
|
||||||
sig = cursig
|
sig = cursig
|
||||||
else:
|
else:
|
||||||
|
@ -204,16 +212,76 @@ def makedef(infile, outdir):
|
||||||
print sig
|
print sig
|
||||||
print cursig
|
print cursig
|
||||||
return False
|
return False
|
||||||
data,size = fmtencoders[fmt](im)
|
infiles[bid].append((lm,tm,im))
|
||||||
infiles[bid].append((w,h,lm,tm,data,size))
|
|
||||||
|
|
||||||
if len(infiles) == 0:
|
if len(infiles) == 0:
|
||||||
print "no input files detected"
|
print "no input files detected"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
fw,fh,pal = cursig
|
fw,fh,pal = cursig
|
||||||
outname = os.path.join(outdir,p)+".def"
|
numframes = sum(len(l) for l in infiles.values())
|
||||||
print "writing to %s"%outname
|
|
||||||
|
# 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+")
|
outf = open(outname, "w+")
|
||||||
|
|
||||||
# write the header
|
# write the header
|
||||||
|
|
Loading…
Reference in a new issue