non-256 faceSize fixes
This commit is contained in:
parent
7dfc5dcefa
commit
4cb46ca102
3 changed files with 58 additions and 19 deletions
|
@ -1,6 +1,6 @@
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from .cli import Paths
|
from .cli import Paths, ExpressionDefaults
|
||||||
|
|
||||||
|
|
||||||
def fetch_image(servantid: str, imageid: str):
|
def fetch_image(servantid: str, imageid: str):
|
||||||
|
@ -39,4 +39,9 @@ def fetch_data(servantid: str):
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
return { str(spritesheet["id"]): (spritesheet["faceX"], spritesheet["faceY"]) for spritesheet in data["mstSvtScript"] }
|
return {
|
||||||
|
str(spritesheet["id"]): {
|
||||||
|
"faceSize": spritesheet["extendData"].get("faceSize", ExpressionDefaults.faceSize),
|
||||||
|
"position": (spritesheet["faceX"], spritesheet["faceY"])
|
||||||
|
} for spritesheet in data["mstSvtScript"]
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,5 @@ class Paths:
|
||||||
if _args.output:
|
if _args.output:
|
||||||
OUTPUT = pathlib.Path(_args.output)
|
OUTPUT = pathlib.Path(_args.output)
|
||||||
|
|
||||||
class Expressions:
|
class ExpressionDefaults:
|
||||||
height = 256
|
faceSize = 256
|
||||||
width = 256
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import math
|
||||||
import pathlib
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -6,7 +7,7 @@ from PIL import Image
|
||||||
from tqdm.contrib import itertools as tqdm_itertools
|
from tqdm.contrib import itertools as tqdm_itertools
|
||||||
|
|
||||||
from .atlas import fetch_data, fetch_image
|
from .atlas import fetch_data, fetch_image
|
||||||
from .cli import Expressions, Paths
|
from .cli import ExpressionDefaults, Paths
|
||||||
|
|
||||||
|
|
||||||
def welcome():
|
def welcome():
|
||||||
|
@ -35,10 +36,10 @@ def run():
|
||||||
|
|
||||||
path = Paths.IMAGES / servantid
|
path = Paths.IMAGES / servantid
|
||||||
for f in path.iterdir():
|
for f in path.iterdir():
|
||||||
process_sprite(f, sprites[f.stem], servantid)
|
process_sprite(f, sprites[f.stem]["position"], sprites[f.stem]["faceSize"], servantid)
|
||||||
print(f"Files have been saved at: {(Paths.OUTPUT / servantid).absolute()}")
|
print(f"Files have been saved at: {(Paths.OUTPUT / servantid).absolute()}")
|
||||||
|
|
||||||
def process_sprite(filepath: pathlib.Path, position: tuple, servantid: str):
|
def process_sprite(filepath: pathlib.Path, position: tuple, faceSize: int, servantid: str):
|
||||||
im = Image.open(filepath)
|
im = Image.open(filepath)
|
||||||
width, height = im.size
|
width, height = im.size
|
||||||
|
|
||||||
|
@ -46,13 +47,47 @@ def process_sprite(filepath: pathlib.Path, position: tuple, servantid: str):
|
||||||
save_sprite(main_sprite, servantid, filepath.stem)
|
save_sprite(main_sprite, servantid, filepath.stem)
|
||||||
expressions = im.crop((0, 768, width, height))
|
expressions = im.crop((0, 768, width, height))
|
||||||
|
|
||||||
_, expressionheight = expressions.size
|
expressionwidth, expressionheight = expressions.size
|
||||||
rows = expressionheight // Expressions.height
|
rows = expressionheight // faceSize
|
||||||
|
expressions_p_row = expressionwidth // faceSize
|
||||||
|
|
||||||
for x, y in tqdm_itertools.product(range(0, rows), range(0, 4, 1), ascii="-="):
|
exp_per_row = 4
|
||||||
img = generate_sprite(main_sprite, expressions, x, y, position)
|
|
||||||
|
if faceSize != ExpressionDefaults.faceSize:
|
||||||
|
w, h = expressions.size
|
||||||
|
composites = []
|
||||||
|
|
||||||
|
per_composite = (1280 - ExpressionDefaults.faceSize) // faceSize
|
||||||
|
exp_per_row = per_composite
|
||||||
|
|
||||||
|
offset = (faceSize * ExpressionDefaults.faceSize) / 1280
|
||||||
|
composite_count = math.ceil((h - 1280) / (offset + faceSize * per_composite)) + 1
|
||||||
|
|
||||||
|
expressions = expressions.crop((0, 256, w, h))
|
||||||
|
floating_offset = 0
|
||||||
|
for count in range(0, composite_count + 1):
|
||||||
|
composites.append((
|
||||||
|
0,
|
||||||
|
3 * count * faceSize + floating_offset,
|
||||||
|
w,
|
||||||
|
(3 * count + 3) * faceSize + floating_offset - 1
|
||||||
|
))
|
||||||
|
floating_offset += offset
|
||||||
|
|
||||||
|
overrides = Image.new("RGBA", (w, faceSize * composite_count * 3), (255, 0, 0, 0))
|
||||||
|
for idx, c in enumerate(composites):
|
||||||
|
crop = expressions.crop(c)
|
||||||
|
pos = (
|
||||||
|
0,
|
||||||
|
idx * 3 * faceSize,
|
||||||
|
)
|
||||||
|
overrides.paste(crop, pos, crop)
|
||||||
|
expressions = overrides.copy()
|
||||||
|
|
||||||
|
for x, y in tqdm_itertools.product(range(0, rows), range(0, expressions_p_row, 1), ascii="-="):
|
||||||
|
img = generate_sprite(main_sprite, expressions, x, y, position, faceSize)
|
||||||
if img is not None:
|
if img is not None:
|
||||||
save_sprite(img, servantid, filepath.stem, (x, y))
|
save_sprite(img, servantid, filepath.stem, (x, y, exp_per_row))
|
||||||
|
|
||||||
def is_empty(img: Image.Image):
|
def is_empty(img: Image.Image):
|
||||||
data = np.asarray(img.crop((96, 96, 160, 160)).convert('LA'))
|
data = np.asarray(img.crop((96, 96, 160, 160)).convert('LA'))
|
||||||
|
@ -62,12 +97,12 @@ def is_empty(img: Image.Image):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def generate_sprite(sprite: Image.Image, expressions: Image.Image, row: int, col: int, position: tuple) -> Image.Image | None:
|
def generate_sprite(sprite: Image.Image, expressions: Image.Image, row: int, col: int, position: tuple, faceSize: int) -> Image.Image | None:
|
||||||
area = (
|
area = (
|
||||||
col * Expressions.width,
|
col * faceSize,
|
||||||
row * Expressions.height,
|
row * faceSize,
|
||||||
(col + 1) * Expressions.width - 1,
|
(col + 1) * faceSize - 1,
|
||||||
(row + 1) * Expressions.height - 1
|
(row + 1) * faceSize - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
expression = expressions.crop(area)
|
expression = expressions.crop(area)
|
||||||
|
@ -82,7 +117,7 @@ def save_sprite(image: Image.Image, folder: str, name: str, rowcol: tuple | None
|
||||||
savefolder = Paths.OUTPUT / folder
|
savefolder = Paths.OUTPUT / folder
|
||||||
if not savefolder.is_dir():
|
if not savefolder.is_dir():
|
||||||
savefolder.mkdir()
|
savefolder.mkdir()
|
||||||
postfix = f"_{rowcol[0] * 4 + rowcol[1] + 1}" if rowcol is not None else "_0"
|
postfix = f"_{rowcol[0] * rowcol[2] + rowcol[1] + 1}" if rowcol is not None else "_0"
|
||||||
outfile = savefolder / f"{name}{postfix}.png"
|
outfile = savefolder / f"{name}{postfix}.png"
|
||||||
with open(outfile, 'wb') as file:
|
with open(outfile, 'wb') as file:
|
||||||
image.save(file)
|
image.save(file)
|
||||||
|
|
Loading…
Reference in a new issue