Skip to content
This repository was archived by the owner on Nov 6, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rsi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .rsi import Rsi
from .state import State
from .state import State, rsi_state_diff

__all__ = [ "Rsi", "State" ]
__all__ = [ "Rsi", "State", "rsi_state_diff" ]
18 changes: 17 additions & 1 deletion rsi/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import argparse
from pathlib import Path
from typing import Optional
from rsi import Rsi
from rsi import Rsi, rsi_state_diff


def main() -> int:
Expand All @@ -24,6 +24,11 @@ def main() -> int:
_new_rsi.add_argument("-l", "--license", action="store", help="The license of this RSI file, as valid SPDX License Identifier (Google it).", nargs="?")
_new_rsi.add_argument("--dont-make-parent-dirs", action="store_true", help="Do not create parent directories if they do not exist, instead throw an error.", dest="no_parents")

_image_diff = subparser.add_parser("diff", help="Will output the image differences between 2 rsi state images.")
_image_diff.add_argument("source", help="The image to compare against the target. Supports multiple frames.", type=Path)
_image_diff.add_argument("target", help="The base image to be compared against. Single frame only.", type=Path)
_image_diff.add_argument("output", help="Filepath to output the result to.", type=Path)

args = parser.parse_args()

if args.command == "from_dmi":
Expand All @@ -33,6 +38,10 @@ def main() -> int:
if args.command == "new":
return new_rsi(args.rsi, args.dimensions, args.copyright, args.license, not args.no_parents)

if args.command == "diff":
image_diff(args.source, args.target, args.output)
return 0

print("No command specified!")
return 1

Expand Down Expand Up @@ -73,3 +82,10 @@ def new_rsi(loc: Path,
rsi.write(loc, make_parents)

return 0


def image_diff(source: Path,
target: Path,
output: Path) -> None:

rsi_state_diff(source, target, output)
49 changes: 49 additions & 0 deletions rsi/state.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import List, Tuple, Dict, Any
from PIL import Image
from pathlib import Path


class State(object):
def __init__(self,
Expand All @@ -13,3 +15,50 @@ def __init__(self,

self.delays = [[] for i in range(self.directions)] # type: List[List[float]]
self.icons = [[] for i in range(self.directions)] # type: List[List[Image.Image]]


def rsi_state_diff(source: Path, target: Path, output: Path) -> None:
"""
Gets the pixels in the source image that aren't in the target image and outputs to the output image.
This does NOT get the color difference between the 2 pixels.
Can also account for multiple frames.
This whole thing is very .rsi specialized so it's not recommended to use this for other types of image operations.
:param output:
:param target:
:param source:
:return:
"""

source_image: Image = Image.open(source).convert("RGB")
target_image: Image = Image.open(target).convert("RGB")

if source_image.size < target_image.size:
raise Exception("Source image must be larger than or equal to target size")

# I must be dumb but PIL doesn't seem to have a native tool for getting image diffs
# there is an "ImageChops.difference" but that gets the actual color difference rather than different pixels
diff = Image.new(mode="RGBA", size=source_image.size)
frame_size = target_image.size

# source can have or 1 more frames but target must have 1 frame only
for column in range(int(source_image.size[0] / frame_size[0])):
for row in range(int(source_image.size[1] / frame_size[1])):
for x in range(frame_size[0]):
for y in range(frame_size[1]):
offset_x = x + column * frame_size[0]
offset_y = y + row * frame_size[1]
source_color = source_image.getpixel((offset_x, offset_y))

# if source is already transparent then just skip
if source_color == (0, 0, 0):
continue

target_color = target_image.getpixel((x, y))

if source_color == target_color:
diff.putpixel((offset_x, offset_y), (0, 0, 0, 0))
continue

diff.putpixel((offset_x, offset_y), source_color)

diff.save(output)