Skip to content

Instantly share code, notes, and snippets.

@PJB3005
Last active February 2, 2018 21:08
Show Gist options
  • Save PJB3005/b707d9da4926e0f7bd746ffc8e79988c to your computer and use it in GitHub Desktop.
Save PJB3005/b707d9da4926e0f7bd746ffc8e79988c to your computer and use it in GitHub Desktop.
Shifts the hue of states in a BYOND DMI.
#!/usr/bin/env python3
import argparse
import colorsys
from pathlib import Path
from byond.DMI import DMI
from byond.DMI.State import State as DMIState
from PIL import Image
def main() -> None:
parser = argparse.ArgumentParser(description="Hue shifts one or more states in a DMI, copying them into a new state(s) with a postfix. Preserves animations.")
parser.add_argument("filename", type=Path, help="The DMI to open and modify.")
parser.add_argument("shiftamount", type=float, help="The amount to shift the hue, in degrees.")
parser.add_argument("prefix", help="The prefix to apply to each copied state.")
parser.add_argument("statenames", nargs="+", help="The names of the states to hue shift.")
args = parser.parse_args()
dmi = DMI(args.filename)
dmi.loadAll()
for statename in args.statenames:
if statename not in dmi.states:
print(f"State not in DMI: {statename}! Skipping.")
continue
shift_state(dmi, statename, args.shiftamount, args.prefix)
def shift_state(dmi: DMI, statename: str, amount: float, prefix: str) -> None:
state = dmi.states[statename]
newstate = clone_state(state, prefix + state.name)
for icon in newstate.icons:
shift_image(icon, amount)
dmi.states[newstate.name] = newstate
dmi.save(dmi.filename)
def shift_image(image: Image.Image, amount: float) -> None:
pixels = image.load()
for x in range(image.width):
for y in range(image.height):
r, g, b, a = pixels[x, y]
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
h = (h + amount/360.0) % 1.0
r, g, b = colorsys.hsv_to_rgb(h, s, v)
pixels[x, y] = (int(r * 255), int(g * 255), int(b * 255), a)
def clone_state(state: DMIState, new_name: str) -> DMIState:
newstate = DMIState(new_name)
newstate.hotspot = state.hotspot
newstate.frames = state.frames
newstate.dirs = state.dirs
newstate.movement = state.movement
newstate.loop = state.loop
newstate.rewind = state.rewind
newstate.delay = state.delay[:]
newstate.positions = state.positions[:]
newstate.icons = [None] * len(state.icons)
for index, icon in enumerate(state.icons):
icon.save("wat.png")
newstate.icons[index] = icon.copy()
return newstate
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment