-
Notifications
You must be signed in to change notification settings - Fork 0
/
scalenx.py
184 lines (132 loc) · 6.52 KB
/
scalenx.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env python3
"""Module contain Scale2x and Scale3x image rescaling functions.
Overview
----------
- scalenx.scale2x - Scale2x aka AdvMAME2x image scaling two times.
- scalenx.scale3x - Scale3x aka AdvMAME3x image scaling three times.
Installation
--------------
Simply put module into your program folder.
Usage
-------
After ``import scalenx``, use something like:
``ScaledImage = scalenx.scale3x(SourceImage)``
where both ``Image`` are lists. Note that ``Image`` X and Y sized are determined automatically, Z not used and remains unchanged.
Copyright and redistribution
-----------------------------
Python implementation developed by Ilya Razmanov (https://dnyarri.github.io/), (hereinafter referred to as "the Developer"), based on brief algorithm description by Andrea Mazzoleni (https://www.scale2x.it/) (hereinafter referred to as "the Inventor").
May be freely used, included and modified anywhere by anyone. In case of useful modifications sharing it with the Developer is almost obligatory.
History:
----------
2024.02.24 Release as shared module, versioning changed to YYYY.MM.DD.
2024.05.14 Arguments and return format changed. Incompatible with previous versions!
2024.07.03 Small improvements, one more retest with new test corpse, as you were, corpus.
2024.10.01 Internal restructure, imports change, maintenance release.
2024.11.24 Improved documentation.
"""
__author__ = 'Ilya Razmanov'
__copyright__ = '(c) 2024 Ilya Razmanov'
__credits__ = ['Ilya Razmanov', 'Andrea Mazzoleni']
__license__ = 'unlicense'
__version__ = '2024.11.24'
__maintainer__ = 'Ilya Razmanov'
__email__ = 'ilyarazmanov@gmail.com'
__status__ = 'Production'
''' ╔════════════════════════════════════════════╗
║ Scaling image nested list to 2x image list ║
╚════════════════════════════════════════════╝ '''
def scale2x(ImageAsListListList: list[list[list[int]]]) -> list[list[list[int]]]:
"""Rescale image with Scale2x.
Takes ``ImageAsListListList`` as 3D nested list (image) of lists (rows) of lists (pixels) of int (channel values) (see pnglpng.py for detail), and performs Scale2x rescaling, returning scaled image of similar structure.
"""
# determining image size from list
Y = len(ImageAsListListList)
X = len(ImageAsListListList[0])
# building new list
EPXImage = list()
for y in range(0, Y, 1):
RowRez = list()
RowDvo = list()
for x in range(0, X, 1):
P = ImageAsListListList[y][x]
A = ImageAsListListList[max(y - 1, 0)][x]
B = ImageAsListListList[y][min(x + 1, X - 1)]
C = ImageAsListListList[y][max(x - 1, 0)]
D = ImageAsListListList[min(y + 1, Y - 1)][x]
r1 = r2 = r3 = r4 = P
if (C == A) and (C != D) and (A != B):
r1 = A
if (A == B) and (A != C) and (B != D):
r2 = B
if (D == C) and (D != B) and (C != A):
r3 = C
if (B == D) and (B != A) and (D != C):
r4 = D
RowRez.append(r1)
RowRez.append(r2)
RowDvo.append(r3)
RowDvo.append(r4)
EPXImage.append(RowRez)
EPXImage.append(RowDvo)
return EPXImage # rescaling two times finished
''' ╔════════════════════════════════════════════╗
║ Scaling image nested list to 3x image list ║
╚════════════════════════════════════════════╝ '''
def scale3x(ImageAsListListList: list[list[list[int]]]) -> list[list[list[int]]]:
"""Rescale image with Scale3x.
Takes ``ImageAsListListList`` as 3D nested list (image) of lists (rows) of lists (pixels) of int (channel values) (see pnglpng.py for detail), and performs Scale3x rescaling, returning scaled image of similar structure.
"""
# determining image size from list
Y = len(ImageAsListListList)
X = len(ImageAsListListList[0])
# building new list
EPXImage = list()
for y in range(0, Y, 1):
RowRez = list()
RowDvo = list()
RowTre = list()
for x in range(0, X, 1):
E = ImageAsListListList[y][x] # E is a center of 3x3 square
A = ImageAsListListList[max(y - 1, 0)][max(x - 1, 0)]
B = ImageAsListListList[max(y - 1, 0)][x]
C = ImageAsListListList[max(y - 1, 0)][min(x + 1, X - 1)]
D = ImageAsListListList[y][max(x - 1, 0)]
# central pixel E = ImageAsListListList[y][x] calculated already
F = ImageAsListListList[y][min(x + 1, X - 1)]
G = ImageAsListListList[min(y + 1, Y - 1)][max(x - 1, 0)]
H = ImageAsListListList[min(y + 1, Y - 1)][x]
I = ImageAsListListList[min(y + 1, Y - 1)][min(x + 1, X - 1)]
r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = E
if (D == B) and (D != H) and (B != F):
r1 = D
if ((D == B) and (D != H) and (B != F) and (E != C)) or ((B == F) and (B != D) and (F != H) and (E != A)):
r2 = B
if (B == F) and (B != D) and (F != H):
r3 = F
if ((H == D) and (H != F) and (D != B) and (E != A)) or ((D == B) and (D != H) and (B != F) and (E != G)):
r4 = D
# r5 = E already
if ((B == F) and (B != D) and (F != H) and (E != I)) or ((F == H) and (F != B) and (H != D) and (E != C)):
r6 = F
if (H == D) and (H != F) and (D != B):
r7 = D
if ((F == H) and (F != B) and (H != D) and (E != G)) or ((H == D) and (H != F) and (D != B) and (E != I)):
r8 = H
if (F == H) and (F != B) and (H != D):
r9 = F
RowRez.append(r1)
RowRez.append(r2)
RowRez.append(r3)
RowDvo.append(r4)
RowDvo.append(r5)
RowDvo.append(r6)
RowTre.append(r7)
RowTre.append(r8)
RowTre.append(r9)
EPXImage.append(RowRez)
EPXImage.append(RowDvo)
EPXImage.append(RowTre)
return EPXImage # rescaling three times finished
# --------------------------------------------------------------
if __name__ == '__main__':
print('Module to be imported, not run as standalone')