Coverage for thumbhash / decode.py: 9%
55 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-28 17:06 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-28 17:06 +0000
1from base64 import b64decode
3from PIL import Image
5from thumbhash.hash import Hash
8def thumbhash_to_image(
9 hash: bytes | str, base_size: int = 32, saturation_boost: float = 1.25
10) -> Image.Image:
11 hash = b64decode(hash) if isinstance(hash, str) else hash
13 width, height, rgba_data = thumbhash_to_rgba(hash, base_size, saturation_boost)
15 return Image.frombytes("RGBA", (width, height), bytes(rgba_data))
18def thumbhash_to_rgba(
19 hash: bytes, base_size: int = 32, saturation_boost: float = 1.25
20) -> tuple[int, int, list[int]]:
21 hash_decoded = Hash.decode(hash, saturation_boost)
23 w, h = hash_decoded.size(base_size)
25 idx = 0
26 data: list[int] = [0] * (w * h * 4)
28 for y in range(h):
29 for x in range(w):
30 fx, fy = hash_decoded.coefficients(x, y, w, h)
32 l = hash_decoded.l_dc # noqa: E741
33 j = 0
34 for cy in range(hash_decoded.ly):
35 cx = 1 if cy == 0 else 0
36 fy2 = fy[cy] * 2.0
38 while cx * hash_decoded.ly < hash_decoded.lx * (hash_decoded.ly - cy):
39 l += hash_decoded.l_ac[j] * fx[cx] * fy2 # noqa: E741
40 j += 1
41 cx += 1
43 p = hash_decoded.p_dc
44 q = hash_decoded.q_dc
46 j = 0
47 for cy in range(3):
48 cx = 1 if cy == 0 else 0
49 fy2 = fy[cy] * 2.0
51 while cx < 3 - cy:
52 f = fx[cx] * fy2
53 p += hash_decoded.p_ac[j] * f
54 q += hash_decoded.q_ac[j] * f
55 j += 1
56 cx += 1
58 a = hash_decoded.a_dc
60 if hash_decoded.has_alpha:
61 j = 0
62 for cy in range(5):
63 cx = 1 if cy == 0 else 0
64 fy2 = fy[cy] * 2.0
66 while cx < 5 - cy:
67 a += hash_decoded.a_ac[j] * fx[cx] * fy2
68 j += 1
69 cx += 1
71 b = l - 2.0 / 3.0 * p
72 r = (3.0 * l - b + q) / 2.0
73 g = r - q
75 data[idx] = round(max(0.0, min(1.0, r) * 255.0))
76 data[idx + 1] = round(max(0.0, min(1.0, g) * 255.0))
77 data[idx + 2] = round(max(0.0, min(1.0, b) * 255.0))
78 data[idx + 3] = round(max(0.0, min(1.0, a) * 255.0))
80 idx += 4
82 return w, h, data