dreamcast/tools/bump_convert.py

116 lines
2.6 KiB
Python

from PIL import Image
import sys
import math
from decimal import Decimal
from math import acos, asin, pi, isnan
import struct
im = Image.open(sys.argv[1])
im = im.convert("RGB")
out = Image.new("RGB", im.size)
width, height = im.size
def mul(a, b):
return (a[0] * b[0], a[1] * b[1], a[2] * b[2])
def dot(a, b):
x, y, z = mul(a, b)
return x + y + z
def magnitude(v):
return math.sqrt(dot(v, v));
def remap(value, l1, h1, l2, h2):
if (value == 255):
value = 256
d = Decimal
mul = (d(h2) - d(l2)) / (d(h1) - d(l1))
output = d(l2) + (d(value) - d(l1)) * mul
if output == 0:
output = 0.0000000001
return float(output)
def remap_normal(x, y, z):
vec = (
remap(x, 0, 256, -1, 1),
remap(y, 0, 256, -1, 1),
remap(z, 0, 256, 1, -1),
)
div = 1.0 / magnitude(vec)
return vec
tests = [
((0,0,-1), (128,128,255)),
((1,1,0), (255,255,128)),
((1,0,0), (255,128,128)),
((0,1,0), (128,255,128)),
((-1,0,0), (0,128,128)),
((0,-1,0), (128,0,128)),
((-1,-1,0), (0,0,128)),
]
for xyz, rgb in tests:
rx, ry, rz = remap_normal(*rgb)
if abs(rx - 0) < 0.01:
rx = 0
if abs(ry - 0) < 0.01:
ry = 0
if abs(rz - 0) < 0.01:
rz = 0
r = (rx, ry, rz)
#print(r, xyz)
#assert r == xyz, (r, xyz)
x_vec = (1, 0, 0)
buf_out = [0] * width * height
for v in range(height):
for u in range(width):
px = im.getpixel((u, v))
x, y, z = remap_normal(*px)
#assert z >= 0, (x, y, z)
pos_xy = (x, y, 0)
r = 0
if pos_xy[0] != 0 and pos_xy[1] != 0:
mag = (magnitude(x_vec) * magnitude(pos_xy))
assert mag != 0, mag
d = dot(x_vec, pos_xy)
if d == 0:
print(pos_xy)
r = acos(d / mag)
if pos_xy[1] < 0:
r = 2 * pi - r
assert not isnan(r)
zz = (-z) if z < 0 else 0
s = asin(zz)
#s = zz * pi / 2
assert r >= 0 and r <= pi * 2, r
assert s >= 0 and s <= pi / 2, (z, zz, s)
if u >= 163 and u <= 165:
if v >= 334 and v <= 336:
print((u, v), (px[2]), z, s)
r_255 = int(remap(r, 0, pi * 2, 0, 255))
s_255 = int(remap(s, 0, pi / 2, 0, 255))
assert r_255 >= 0 and r_255 <= 255, r_255
assert s_255 >= 0 and s_255 <= 255, s_255
buf_out[(v * width) + u] = (s_255 << 8) | (r_255 << 0)
#int((px[0] * px[1]) / 255)
out.putpixel((u, v), (0, s_255, 0))
out.save("test.png")
with open(sys.argv[2], 'wb') as f:
for v in buf_out:
f.write(struct.pack("<H", v))