|
from PIL import Image |
|
import random, sys, getopt, os |
|
|
|
from hamcrest import none |
|
|
|
DEEP = 20 |
|
SHALLOW = 20 |
|
SHOW_INPUTPNG = False |
|
|
|
def writeMtl(opng, omtl): |
|
with open(omtl, "w") as w: |
|
w.write('''newmtl palette |
|
illum 1 |
|
Ka 0.000 0.000 0.000 |
|
Kd 1.000 1.000 1.000 |
|
Ks 0.000 0.000 0.000 |
|
map_Kd {}\n'''.format(opng)) |
|
|
|
def loadPng(ipng): |
|
if ipng is None: |
|
rgbas = [] |
|
for x in range(256): |
|
rgbas.append((255, 255, 255, 255)) |
|
return rgbas |
|
if not os.path.isfile(ipng): |
|
print("{} not found".format(ipng)) |
|
sys.exit(1) |
|
image = Image.open(ipng) |
|
pixels = image.load() |
|
rgbas = [] |
|
for x in range(image.size[0]): |
|
rgbas.append(pixels[x, 0]) |
|
return rgbas |
|
|
|
def generatePng(ipng, opng, omtl, type_, replace): |
|
irgbas = loadPng(ipng) |
|
oimg = Image.new('RGBA', (256, 1), (0, 0, 0, 0)) |
|
|
|
if replace is not None: |
|
frgba = str2rgba(replace[0]) |
|
trgba = str2rgba(replace[1]) |
|
for i in range(oimg.size[0]): |
|
rgba = tuple(irgbas[i]) |
|
if rgba[0] == frgba[0] and rgba[1] == frgba[1] and rgba[2] == frgba[2]: |
|
oimg.putpixel((i, 0), (trgba[0], trgba[1], trgba[2], rgba[3])) |
|
else: |
|
oimg.putpixel((i, 0), rgba) |
|
else: |
|
if type_ == "random": |
|
for i in range(oimg.size[0]): |
|
oimg.putpixel((i, 0), (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), 255)) |
|
elif type_ == "deeper": |
|
for i in range(oimg.size[0]): |
|
rgba = tuple(max(0, x - DEEP) for x in irgbas[i]) |
|
oimg.putpixel((i, 0), rgba) |
|
elif type_ == "shallower": |
|
for i in range(oimg.size[0]): |
|
rgba = tuple(min(255, x + SHALLOW) for x in irgbas[i]) |
|
oimg.putpixel((i, 0), rgba) |
|
else: |
|
usage() |
|
sys.exit(1) |
|
|
|
oimg.save(opng) |
|
writeMtl(opng, omtl) |
|
|
|
def usage(): |
|
print("Usage: python3 script.py -i <inputpng> -o <outputpng> -m <outputmtl> -t <type>(default random) -r <fromcolor> <tocolor>(hex start with 0x) -s(show inputpng)") |
|
print("Example1: python3 script.py -i monu1.vox.png -o monu1.vox.png -m monu1.vox.mtl -t random") |
|
print("Example2: python3 script.py -i monu1.vox.png -o monu1.vox.png -m monu1.vox.mtl -r 0x839aa9 0xff0000") |
|
print("type: random, deeper, shallower") |
|
|
|
def str2rgba(s): |
|
if s[0:2] != "0x": |
|
return None |
|
s = s[2:] |
|
if len(s) != 6: |
|
return None |
|
try: |
|
r = int(s[0:2], 16) |
|
g = int(s[2:4], 16) |
|
b = int(s[4:6], 16) |
|
except ValueError: |
|
return None |
|
return (r, g, b, 255) |
|
|
|
def rgba2str(rgba): |
|
return "0x{:02x}{:02x}{:02x}".format(rgba[0], rgba[1], rgba[2]) |
|
|
|
if __name__ == "__main__": |
|
try: |
|
opts, args = getopt.getopt(sys.argv[1:],"hi:o:m:t:rs",["ipng=","opng=","omtl=","type=","replace=","showpng="]) |
|
except getopt.GetoptError: |
|
print(getopt.GetoptError) |
|
usage() |
|
sys.exit(2) |
|
ipng, opng, omtl, type_, replace = None, None, None, None, None |
|
for opt, arg in opts: |
|
if opt == "-h": |
|
usage() |
|
sys.exit() |
|
elif opt in ("-s", "--showpng"): |
|
SHOW_INPUTPNG = True |
|
elif opt in ("-i", "--ipng"): |
|
ipng = arg |
|
elif opt in ("-o", "--opng"): |
|
opng = arg |
|
elif opt in ("-t", "--type"): |
|
type_ = arg |
|
elif opt in ("-m", "--omtl"): |
|
omtl = arg |
|
elif opt in ("-r", "--replace"): |
|
replace = args |
|
if SHOW_INPUTPNG: # show input png |
|
rgbas, lcnt = loadPng(ipng), 8 |
|
for i, rgba in enumerate(rgbas): |
|
print(rgba2str(rgba), end=" ") |
|
if i % lcnt == lcnt - 1: |
|
print("") |
|
sys.exit(0) |
|
if opng is None or omtl is None: |
|
print("[ERROR] Please specify outputpng and outputmtl") |
|
usage() |
|
sys.exit() |
|
if replace is not None and len(replace) != 2: |
|
print("[ERROR] Please specify replace") |
|
usage() |
|
sys.exit() |
|
if replace is not None and (str2rgba(replace[0]) is None or str2rgba(replace[1]) is None): |
|
print("[ERROR] Please specify replace with hex") |
|
usage() |
|
sys.exit() |
|
|
|
if type_ is None: type_ = "random" |
|
generatePng(ipng, opng, omtl, type_, replace) |