Skip to content

Instantly share code, notes, and snippets.

@chsbuffer
Last active November 8, 2022 20:42
Show Gist options
  • Save chsbuffer/d9ebb1141cb94b51c478bf52e245a8cf to your computer and use it in GitHub Desktop.
Save chsbuffer/d9ebb1141cb94b51c478bf52e245a8cf to your computer and use it in GitHub Desktop.
Terraria Mobile Unity 2DTexture merge _A.png _P.png
from PIL import Image
import numpy as np
import os
from multiprocessing import Pool
import multiprocessing
from functools import partial
from numpy.core.multiarray import array
"""
# _P
Pixel data
# _A
Alpha data
override if exists
# regular image
can be split into blocks
blocks indexed from up to down, right to left
210
543
876
pixel color = _P[block index][pixel alpha value]
"""
"""
change applied to img
"""
def draw(img, pimg, aimg=None):
override_alpha = aimg is not None
width, height = img.size
colors = np.array(pimg)
_, blocks = pimg.size
# block colums
block_cols = int(np.sqrt(blocks))
# block width
block_w = width // block_cols
# block rows
block_rows = int(np.ceil(height / block_w))
# block-colors index
block_i = 0
for b_row in range(block_rows):
for b_col in reversed(range(block_cols)):
b_colors = colors[block_i]
if block_i < colors.shape[0] - 1:
block_i += 1
# block coord (left up)
bx = b_col * block_w
by = b_row * block_w
# inside block coord
for x in range(block_w):
px = bx + x
if px >= width:
continue
for y in range(block_w):
py = by + y
if py >= height:
continue
d = img.getpixel((px, py))[3]
r, g, b, a = b_colors[d]
if override_alpha:
a = aimg.getpixel((px, py))[3]
img.putpixel((px, py), (r, g, b, a))
def merge(pfile, save=True, show=False, clean=True, destDir=None):
# cut _P.png
name = os.path.basename(pfile)[:-6]
dir = os.path.dirname(pfile)
file = os.path.join(dir, f"{name}.png")
afile = os.path.join(dir, f"{name}_A.png")
aimg = None
if os.path.exists(afile):
aimg = Image.open(afile)
with Image.open(pfile) as pimg:
with Image.open(file) as img:
draw(img, pimg, aimg)
if save:
if destDir is not None:
file = os.path.join(destDir, f"{name}.png")
img.save(file)
if show:
img.show()
if aimg is not None:
aimg.close()
if clean:
os.remove(pfile)
if os.path.exists(afile):
os.remove(afile)
def get_files(path):
return [os.path.join(path, f) for f in os.listdir(path) if f.endswith("_P.png")]
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.abspath(__file__)))
with Pool(multiprocessing.cpu_count()) as pool:
pool.map(
partial(merge, save=True, show=False, clean=False, destDir="test_out"),
get_files("test"),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment