-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTexUglifier.py
More file actions
172 lines (140 loc) · 5.07 KB
/
TexUglifier.py
File metadata and controls
172 lines (140 loc) · 5.07 KB
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
import os
import random
import math
import colorsys
import shutil
from PIL import Image
# VARIABLES
spread_amount_scale = 1.5
saturation_addition = 0.15
hue_shift_apply = 0.3
noise_percentage = 0.2
noise_strength = 30
color_reduction = 16
# FUNCTIONS
def clamp(value: float, min_value: float, max_value: float) -> float:
return max(min_value, min(value, max_value))
def lerp(start: float, end: float, alpha: float) -> float:
return start + alpha * (end - start)
def gLerp(start: float, end: float, alpha: float, gamma: float = 2.2) -> float:
a_lin = start ** gamma
b_lin = end ** gamma
result_lin = (1.0 - alpha) * a_lin + alpha * b_lin
return result_lin ** (1.0 / gamma)
# Offset/spread pixels randomly in a texture
def spread_pixels(image: Image):
width, height = image.size
amount = int(math.sqrt(width * height) * spread_amount_scale)
pixels = set()
for i in range(amount):
for j in range(10):
x = random.randint(0, width - 1)
y = random.randint(0, height - 1)
if x + y * width in pixels: continue
pixel = image.getpixel((x, y))
# Do ten attempts to swap the pixel
for l in range(10):
x_plot = x + random.randint(-2, 2)
y_plot = y + random.randint(-2, 2)
if x_plot < 0 or x_plot >= width: continue
if y_plot < 0 or y_plot >= height: continue
if x_plot == x or y_plot == y: continue
if x_plot + y_plot * width in pixels: continue
pixel_plot = image.getpixel((x_plot, y_plot))
image.putpixel((x_plot, y_plot), pixel)
image.putpixel((x, y), pixel_plot)
pixels.add(x_plot + y_plot * width)
pixels.add(x + y * width)
break
break
return
# Shift hue in a texture
def shift_hue(image: Image):
width, height = image.size
shift = random.random() * 0.8 + 0.1
for x in range(width):
for y in range(height):
old_pixel = image.getpixel((x, y))
ro, go, bo = (old_pixel[0] / 255.0, old_pixel[1] / 255.0, old_pixel[2] / 255.0)
# Convert RGB values (0–255) to HSV (where RGB must be in 0–1 range)
h, s, v = colorsys.rgb_to_hsv(ro, go, bo)
s = min(s + saturation_addition, 1.0)
# Shift hue and wrap around if necessary
h = (h + shift) % 1.0 # Hue stays within [0, 1] range
# Convert HSV back to RGB
rn, gn, bn = colorsys.hsv_to_rgb(h, s, v)
rn = gLerp(ro, rn, hue_shift_apply)
gn = gLerp(go, gn, hue_shift_apply)
bn = gLerp(bo, bn, hue_shift_apply)
# Convert RGB values back to integer range (0–255)
if image.mode == "RGBA":
new_pixel = (int(rn * 255), int(gn * 255), int(bn * 255), old_pixel[3])
else:
new_pixel = (int(rn * 255), int(gn * 255), int(bn * 255))
# Apply new pixel value
image.putpixel((x, y), new_pixel)
return
# Make random noise in a texture
def make_noise(image: Image):
width, height = image.size
for x in range(width):
for y in range(height):
if random.random() > noise_percentage:
continue
r, g, b, a = image.getpixel((x, y))
if a < 20:
continue
r, g, b = tuple(clamp(p + random.randint(-noise_strength, noise_strength), 0, 255) for p in (r, g, b)) # Invert RGB
image.putpixel((x, y), (r, g, b, a))
return
# Low res colors
def low_color(image: Image):
width, height = image.size
for x in range(width):
for y in range(height):
old_pixel = image.getpixel((x, y))
new_pixel = tuple((int(p / color_reduction) * color_reduction) for p in old_pixel[:3])
p = list(new_pixel)
p.append(old_pixel[3])
new_pixel = tuple(p)
image.putpixel((x, y), new_pixel)
return
# START CODE
# Get the script's working directory
working_dir = os.getcwd()
# Define the input and output directories within the working directory
input_dir = os.path.join(working_dir, "input")
output_dir = os.path.join(working_dir, "output")
# Walk through the input directory tree
for root, dirs, files in os.walk(input_dir):
for file in files:
# Specify the input file path
input_path = os.path.join(root, file)
# Determine the relative path from the input directory
rel_dir = os.path.relpath(root, input_dir)
# Create the same subdirectory structure in the output directory
dest_dir = os.path.join(output_dir, rel_dir)
# Create an empty directory if not exists
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
# Specify the output file path
output_path = os.path.join(dest_dir, file)
if file.lower().endswith('.png'):
# Open the image file
image = Image.open(input_path)
# Convert image format to RGBA
if image.mode != 'RGBA':
image = image.convert('RGBA')
# Start uglifying
spread_pixels(image)
shift_hue(image)
make_noise(image)
low_color(image)
# Save the inverted image in the output folder, preserving the relative path
image.save(output_path)
print(f"Modified image saved: {output_path}")
else:
# Copy all the metadata across.
shutil.copy(input_path, output_path)
print(f"Copied file across: {output_path}")
print("Done!")