-
Notifications
You must be signed in to change notification settings - Fork 8
/
imagemaker.py
84 lines (72 loc) · 2.58 KB
/
imagemaker.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
import numpy as np
from PIL import Image
def read_rle_bytes(ods_bytes):
pixels = []
line_builder = []
i = 0
while i < len(ods_bytes):
if ods_bytes[i]:
incr = 1
color = ods_bytes[i]
length = 1
else:
check = ods_bytes[i+1]
if check == 0:
incr = 2
color = 0
length = 0
pixels.append(line_builder)
line_builder = []
elif check < 64:
incr = 2
color = 0
length = check
elif check < 128:
incr = 3
color = 0
length = ((check - 64) << 8) + ods_bytes[i + 2]
elif check < 192:
incr = 3
color = ods_bytes[i+2]
length = check - 128
else:
incr = 4
color = ods_bytes[i+3]
length = ((check - 192) << 8) + ods_bytes[i + 2]
line_builder.extend([color]*length)
i += incr
if line_builder:
print(f'Probably an error; hanging pixels: {line_builder}')
return pixels
def ycbcr2rgb(ar):
xform = np.array([[1, 0, 1.402], [1, -0.34414, -.71414], [1, 1.772, 0]])
rgb = ar.astype(float)
# Subtracting by 128 the R and G channels
rgb[:,[1,2]] -= 128
#.dot is multiplication of the matrices and xform.T is a transpose of the array axes
rgb = rgb.dot(xform.T)
# Makes any pixel value greater than 255 just be 255 (Max for RGB colorspace)
np.putmask(rgb, rgb > 255, 255)
# Sets any pixel value less than 0 to 0 (Min for RGB colorspace)
np.putmask(rgb, rgb < 0, 0)
return np.uint8(rgb)
def px_rgb_a(ods, pds, swap):
px = read_rle_bytes(ods.img_data)
px = np.array([[255]*(ods.width - len(l)) + l for l in px], dtype=np.uint8)
# Extract the YCbCrA palette data, swapping channels if requested.
if swap:
ycbcr = np.array([(entry.Y, entry.Cb, entry.Cr) for entry in pds.palette])
else:
ycbcr = np.array([(entry.Y, entry.Cr, entry.Cb) for entry in pds.palette])
rgb = ycbcr2rgb(ycbcr)
# Separate the Alpha channel from the YCbCr palette data
a = [entry.Alpha for entry in pds.palette]
a = np.array([[a[x] for x in l] for l in px], dtype=np.uint8)
return px, rgb, a
def make_image(ods, pds, swap=False):
px, rgb, a = px_rgb_a(ods, pds, swap)
alpha = Image.fromarray(a, mode='L')
img = Image.fromarray(px, mode='P')
img.putpalette(rgb)
img.putalpha(alpha)
return img