]> git.ipfire.org Git - ipfire.org.git/blob - src/backend/util.py
search: Use PostgreSQL's websearch_to_tsquery()
[ipfire.org.git] / src / backend / util.py
1 #!/usr/bin/python3
2
3 import PIL.Image
4 import PIL.ImageFilter
5 import PIL.ImageOps
6 import io
7 import logging
8 import random
9 import re
10 import string
11 import unicodedata
12
13 def format_size(s, max_unit=None):
14 units = ("B", "kB", "MB", "GB", "TB")
15
16 i = 0
17 while s >= 1024 and i < len(units) - 1:
18 s /= 1024
19 i += 1
20
21 if max_unit and units[i] == max_unit:
22 break
23
24 return "%.0f%s" % (s, units[i])
25
26 def format_time(s, shorter=True):
27 #_ = handler.locale.translate
28 _ = lambda x: x
29
30 hrs, s = divmod(s, 3600)
31 min, s = divmod(s, 60)
32
33 if s >= 30:
34 min += 1
35
36 if shorter and not hrs:
37 return _("%(min)d min") % { "min" : min }
38
39 return _("%(hrs)d:%(min)02d hrs") % {"hrs" : hrs, "min" : min}
40
41 def random_string(length=8):
42 input_chars = string.ascii_letters + string.digits
43
44 r = (random.choice(input_chars) for i in range(length))
45
46 return "".join(r)
47
48 def normalize(s):
49 # Remove any non-ASCII characters
50 try:
51 s = unicodedata.normalize("NFKD", s)
52 except TypeError:
53 pass
54
55 # Remove excessive whitespace
56 s = re.sub(r"[^\w]+", " ", s)
57
58 return "-".join(s.split())
59
60 def generate_thumbnail(data, size, square=False, **args):
61 assert data, "No image data received"
62
63 image = PIL.Image.open(io.BytesIO(data))
64
65 # Save image format
66 format = image.format
67
68 # Remove any alpha-channels
69 if image.format == "JPEG" and not image.mode == "RGB":
70 # Make a white background
71 background = PIL.Image.new("RGBA", image.size, (255,255,255))
72
73 # Convert image to RGBA if not in RGBA, yet
74 if not image.mode == "RGBA":
75 image = image.convert("RGBA")
76
77 # Flatten both images together
78 flattened_image = PIL.Image.alpha_composite(background, image)
79
80 # Remove the alpha channel
81 image = flattened_image.convert("RGB")
82
83 # Resize the image to the desired resolution
84 if square:
85 image = PIL.ImageOps.fit(image, (size, size), PIL.Image.LANCZOS)
86 else:
87 image.thumbnail((size, size), PIL.Image.LANCZOS)
88
89 if image.format == "JPEG":
90 # Apply a gaussian blur to make compression easier
91 image = image.filter(PIL.ImageFilter.GaussianBlur(radius=0.05))
92
93 # Arguments to optimise the compression
94 args.update({
95 "subsampling" : "4:2:0",
96 "quality" : 70,
97 })
98
99 with io.BytesIO() as f:
100 # If writing out the image does not work with optimization,
101 # we try to write it out without any optimization.
102 try:
103 image.save(f, format, optimize=True, **args)
104 except:
105 image.save(f, format, **args)
106
107 return f.getvalue()