Skip to content

Commit 034796c

Browse files
committed
Renormalize line endings to LF
1 parent 64f69a1 commit 034796c

9 files changed

+381
-375
lines changed

.editorconfig

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
root = true
2-
3-
[*]
4-
end_of_line = lf
5-
insert_final_newline = true
6-
charset = utf-8
7-
indent_style = space
8-
indent_size = 2
9-
10-
[*.py]
11-
indent_size = 4
12-
13-
[*.ui]
14-
indent_size = 1
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
charset = utf-8
7+
indent_style = space
8+
indent_size = 2
9+
10+
[*.py]
11+
indent_size = 4
12+
13+
[*.ui]
14+
indent_size = 1

.gitattributes

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Normalize EOF
2+
* autocrlf=false
3+
* eol=lf
4+
# Set linguist-language to support comments syntax highlight
5+
pyrightconfig*.json linguist-language=jsonc
6+
.vscode/*.json linguist-language=jsonc

docs/2.0.0_gif.gif

-296 Bytes
Loading

docs/mask_example_image.png

-1 Bytes
Loading

res/btn_donateCC_LG.png

-1 Bytes
Loading

res/icon.ico

-1 Bytes
Binary file not shown.

res/splash.png

-1 Bytes
Loading

src/AutoSplitImage.py

+165-165
Original file line numberDiff line numberDiff line change
@@ -1,165 +1,165 @@
1-
import os
2-
from enum import IntEnum, auto
3-
from math import sqrt
4-
from typing import TYPE_CHECKING
5-
6-
import cv2
7-
import numpy as np
8-
from cv2.typing import MatLike
9-
10-
import error_messages
11-
from compare import check_if_image_has_transparency, get_comparison_method_by_index
12-
from utils import BGR_CHANNEL_COUNT, MAXBYTE, ColorChannel, ImageShape, is_valid_image
13-
14-
if TYPE_CHECKING:
15-
from AutoSplit import AutoSplit
16-
17-
18-
# Resize to these width and height so that FPS performance increases
19-
COMPARISON_RESIZE_WIDTH = 320
20-
COMPARISON_RESIZE_HEIGHT = 240
21-
COMPARISON_RESIZE = (COMPARISON_RESIZE_WIDTH, COMPARISON_RESIZE_HEIGHT)
22-
COMPARISON_RESIZE_AREA = COMPARISON_RESIZE_WIDTH * COMPARISON_RESIZE_HEIGHT
23-
MASK_LOWER_BOUND = np.array([0, 0, 0, 1], dtype="uint8")
24-
MASK_UPPER_BOUND = np.array([MAXBYTE, MAXBYTE, MAXBYTE, MAXBYTE], dtype="uint8")
25-
START_KEYWORD = "start_auto_splitter"
26-
RESET_KEYWORD = "reset"
27-
28-
29-
class ImageType(IntEnum):
30-
SPLIT = auto()
31-
RESET = auto()
32-
START = auto()
33-
34-
35-
class AutoSplitImage:
36-
path: str
37-
filename: str
38-
flags: int
39-
loops: int
40-
image_type: ImageType
41-
byte_array: MatLike | None = None
42-
mask: MatLike | None = None
43-
# This value is internal, check for mask instead
44-
_has_transparency = False
45-
# These values should be overriden by some Defaults if None. Use getters instead
46-
__delay_time: float | None = None
47-
__comparison_method: int | None = None
48-
__pause_time: float | None = None
49-
__similarity_threshold: float | None = None
50-
51-
def get_delay_time(self, default: "AutoSplit | int"):
52-
"""Get image's delay time or fallback to the default value from spinbox."""
53-
if self.__delay_time is not None:
54-
return self.__delay_time
55-
if isinstance(default, int):
56-
return default
57-
return default.settings_dict["default_delay_time"]
58-
59-
def __get_comparison_method_index(self, default: "AutoSplit | int"):
60-
"""Get image's comparison or fallback to the default value from combobox."""
61-
if self.__comparison_method is not None:
62-
return self.__comparison_method
63-
if isinstance(default, int):
64-
return default
65-
return default.settings_dict["default_comparison_method"]
66-
67-
def get_pause_time(self, default: "AutoSplit | float"):
68-
"""Get image's pause time or fallback to the default value from spinbox."""
69-
if self.__pause_time is not None:
70-
return self.__pause_time
71-
if isinstance(default, (float, int)):
72-
return default
73-
return default.settings_dict["default_pause_time"]
74-
75-
def get_similarity_threshold(self, default: "AutoSplit | float"):
76-
"""Get image's similarity threshold or fallback to the default value from spinbox."""
77-
if self.__similarity_threshold is not None:
78-
return self.__similarity_threshold
79-
if isinstance(default, (float, int)):
80-
return default
81-
return default.settings_dict["default_similarity_threshold"]
82-
83-
def __init__(self, path: str):
84-
self.path = path
85-
self.filename = os.path.split(path)[-1].lower()
86-
self.flags = flags_from_filename(self.filename)
87-
self.loops = loop_from_filename(self.filename)
88-
self.__delay_time = delay_time_from_filename(self.filename)
89-
self.__comparison_method = comparison_method_from_filename(self.filename)
90-
self.__pause_time = pause_from_filename(self.filename)
91-
self.__similarity_threshold = threshold_from_filename(self.filename)
92-
self.__read_image_bytes(path)
93-
94-
if START_KEYWORD in self.filename:
95-
self.image_type = ImageType.START
96-
elif RESET_KEYWORD in self.filename:
97-
self.image_type = ImageType.RESET
98-
else:
99-
self.image_type = ImageType.SPLIT
100-
101-
def __read_image_bytes(self, path: str):
102-
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
103-
if not is_valid_image(image):
104-
self.byte_array = None
105-
error_messages.image_type(path)
106-
return
107-
108-
self._has_transparency = check_if_image_has_transparency(image)
109-
# If image has transparency, create a mask
110-
if self._has_transparency:
111-
# Adaptively determine the target size according to
112-
# the number of nonzero elements in the alpha channel of the split image.
113-
# This may result in images bigger than COMPARISON_RESIZE if there's plenty of transparency.
114-
# Which wouldn't incur any performance loss in methods where masked regions are ignored.
115-
scale = min(1, sqrt(COMPARISON_RESIZE_AREA / cv2.countNonZero(image[:, :, ColorChannel.Alpha])))
116-
117-
image = cv2.resize(
118-
image,
119-
dsize=None,
120-
fx=scale,
121-
fy=scale,
122-
interpolation=cv2.INTER_NEAREST,
123-
)
124-
125-
# Mask based on adaptively resized, nearest neighbor interpolated split image
126-
self.mask = cv2.inRange(image, MASK_LOWER_BOUND, MASK_UPPER_BOUND)
127-
else:
128-
image = cv2.resize(image, COMPARISON_RESIZE, interpolation=cv2.INTER_NEAREST)
129-
# Add Alpha channel if missing
130-
if image.shape[ImageShape.Channels] == BGR_CHANNEL_COUNT:
131-
image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
132-
133-
self.byte_array = image
134-
135-
def check_flag(self, flag: int):
136-
return self.flags & flag == flag
137-
138-
def compare_with_capture(
139-
self,
140-
default: "AutoSplit | int",
141-
capture: MatLike | None,
142-
):
143-
"""Compare image with capture using image's comparison method. Falls back to combobox."""
144-
if not is_valid_image(self.byte_array) or not is_valid_image(capture):
145-
return 0.0
146-
resized_capture = cv2.resize(capture, self.byte_array.shape[1::-1])
147-
148-
return get_comparison_method_by_index(
149-
self.__get_comparison_method_index(default),
150-
)(
151-
self.byte_array,
152-
resized_capture,
153-
self.mask,
154-
)
155-
156-
157-
if True:
158-
from split_parser import (
159-
comparison_method_from_filename,
160-
delay_time_from_filename,
161-
flags_from_filename,
162-
loop_from_filename,
163-
pause_from_filename,
164-
threshold_from_filename,
165-
)
1+
import os
2+
from enum import IntEnum, auto
3+
from math import sqrt
4+
from typing import TYPE_CHECKING
5+
6+
import cv2
7+
import numpy as np
8+
from cv2.typing import MatLike
9+
10+
import error_messages
11+
from compare import check_if_image_has_transparency, get_comparison_method_by_index
12+
from utils import BGR_CHANNEL_COUNT, MAXBYTE, ColorChannel, ImageShape, is_valid_image
13+
14+
if TYPE_CHECKING:
15+
from AutoSplit import AutoSplit
16+
17+
18+
# Resize to these width and height so that FPS performance increases
19+
COMPARISON_RESIZE_WIDTH = 320
20+
COMPARISON_RESIZE_HEIGHT = 240
21+
COMPARISON_RESIZE = (COMPARISON_RESIZE_WIDTH, COMPARISON_RESIZE_HEIGHT)
22+
COMPARISON_RESIZE_AREA = COMPARISON_RESIZE_WIDTH * COMPARISON_RESIZE_HEIGHT
23+
MASK_LOWER_BOUND = np.array([0, 0, 0, 1], dtype="uint8")
24+
MASK_UPPER_BOUND = np.array([MAXBYTE, MAXBYTE, MAXBYTE, MAXBYTE], dtype="uint8")
25+
START_KEYWORD = "start_auto_splitter"
26+
RESET_KEYWORD = "reset"
27+
28+
29+
class ImageType(IntEnum):
30+
SPLIT = auto()
31+
RESET = auto()
32+
START = auto()
33+
34+
35+
class AutoSplitImage:
36+
path: str
37+
filename: str
38+
flags: int
39+
loops: int
40+
image_type: ImageType
41+
byte_array: MatLike | None = None
42+
mask: MatLike | None = None
43+
# This value is internal, check for mask instead
44+
_has_transparency = False
45+
# These values should be overriden by some Defaults if None. Use getters instead
46+
__delay_time: float | None = None
47+
__comparison_method: int | None = None
48+
__pause_time: float | None = None
49+
__similarity_threshold: float | None = None
50+
51+
def get_delay_time(self, default: "AutoSplit | int"):
52+
"""Get image's delay time or fallback to the default value from spinbox."""
53+
if self.__delay_time is not None:
54+
return self.__delay_time
55+
if isinstance(default, int):
56+
return default
57+
return default.settings_dict["default_delay_time"]
58+
59+
def __get_comparison_method_index(self, default: "AutoSplit | int"):
60+
"""Get image's comparison or fallback to the default value from combobox."""
61+
if self.__comparison_method is not None:
62+
return self.__comparison_method
63+
if isinstance(default, int):
64+
return default
65+
return default.settings_dict["default_comparison_method"]
66+
67+
def get_pause_time(self, default: "AutoSplit | float"):
68+
"""Get image's pause time or fallback to the default value from spinbox."""
69+
if self.__pause_time is not None:
70+
return self.__pause_time
71+
if isinstance(default, (float, int)):
72+
return default
73+
return default.settings_dict["default_pause_time"]
74+
75+
def get_similarity_threshold(self, default: "AutoSplit | float"):
76+
"""Get image's similarity threshold or fallback to the default value from spinbox."""
77+
if self.__similarity_threshold is not None:
78+
return self.__similarity_threshold
79+
if isinstance(default, (float, int)):
80+
return default
81+
return default.settings_dict["default_similarity_threshold"]
82+
83+
def __init__(self, path: str):
84+
self.path = path
85+
self.filename = os.path.split(path)[-1].lower()
86+
self.flags = flags_from_filename(self.filename)
87+
self.loops = loop_from_filename(self.filename)
88+
self.__delay_time = delay_time_from_filename(self.filename)
89+
self.__comparison_method = comparison_method_from_filename(self.filename)
90+
self.__pause_time = pause_from_filename(self.filename)
91+
self.__similarity_threshold = threshold_from_filename(self.filename)
92+
self.__read_image_bytes(path)
93+
94+
if START_KEYWORD in self.filename:
95+
self.image_type = ImageType.START
96+
elif RESET_KEYWORD in self.filename:
97+
self.image_type = ImageType.RESET
98+
else:
99+
self.image_type = ImageType.SPLIT
100+
101+
def __read_image_bytes(self, path: str):
102+
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
103+
if not is_valid_image(image):
104+
self.byte_array = None
105+
error_messages.image_type(path)
106+
return
107+
108+
self._has_transparency = check_if_image_has_transparency(image)
109+
# If image has transparency, create a mask
110+
if self._has_transparency:
111+
# Adaptively determine the target size according to
112+
# the number of nonzero elements in the alpha channel of the split image.
113+
# This may result in images bigger than COMPARISON_RESIZE if there's plenty of transparency.
114+
# Which wouldn't incur any performance loss in methods where masked regions are ignored.
115+
scale = min(1, sqrt(COMPARISON_RESIZE_AREA / cv2.countNonZero(image[:, :, ColorChannel.Alpha])))
116+
117+
image = cv2.resize(
118+
image,
119+
dsize=None,
120+
fx=scale,
121+
fy=scale,
122+
interpolation=cv2.INTER_NEAREST,
123+
)
124+
125+
# Mask based on adaptively resized, nearest neighbor interpolated split image
126+
self.mask = cv2.inRange(image, MASK_LOWER_BOUND, MASK_UPPER_BOUND)
127+
else:
128+
image = cv2.resize(image, COMPARISON_RESIZE, interpolation=cv2.INTER_NEAREST)
129+
# Add Alpha channel if missing
130+
if image.shape[ImageShape.Channels] == BGR_CHANNEL_COUNT:
131+
image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
132+
133+
self.byte_array = image
134+
135+
def check_flag(self, flag: int):
136+
return self.flags & flag == flag
137+
138+
def compare_with_capture(
139+
self,
140+
default: "AutoSplit | int",
141+
capture: MatLike | None,
142+
):
143+
"""Compare image with capture using image's comparison method. Falls back to combobox."""
144+
if not is_valid_image(self.byte_array) or not is_valid_image(capture):
145+
return 0.0
146+
resized_capture = cv2.resize(capture, self.byte_array.shape[1::-1])
147+
148+
return get_comparison_method_by_index(
149+
self.__get_comparison_method_index(default),
150+
)(
151+
self.byte_array,
152+
resized_capture,
153+
self.mask,
154+
)
155+
156+
157+
if True:
158+
from split_parser import (
159+
comparison_method_from_filename,
160+
delay_time_from_filename,
161+
flags_from_filename,
162+
loop_from_filename,
163+
pause_from_filename,
164+
threshold_from_filename,
165+
)

0 commit comments

Comments
 (0)