|
2 | 2 | # Watermarker - program for watermarking images |
3 | 3 | # |
4 | 4 |
|
5 | | -PROG_VERSION = '1.2' |
| 5 | +PROG_VERSION = '1.22' |
6 | 6 |
|
7 | 7 | IMG_ALLOWED_EXT = ['jpg','png'] # Supported image extentions (in lowercase !!) |
8 | 8 | IMG_TXT_DEFAULT_COLOR = 'black' # Default color for text |
|
16 | 16 | import shutil |
17 | 17 | from enum import Enum |
18 | 18 | from pprint import pprint |
| 19 | +import functools |
19 | 20 |
|
20 | 21 | try: |
21 | 22 | from PIL import Image, ImageDraw, ImageFont |
@@ -176,6 +177,37 @@ def ask(default_value,message): |
176 | 177 | return True |
177 | 178 | else: |
178 | 179 | return default_value |
| 180 | + |
| 181 | +def image_transpose_exif(im): |
| 182 | + """ |
| 183 | + Apply Image.transpose to ensure 0th row of pixels is at the visual |
| 184 | + top of the image, and 0th column is the visual left-hand side. |
| 185 | + Return the original image if unable to determine the orientation. |
| 186 | +
|
| 187 | + As per CIPA DC-008-2012, the orientation field contains an integer, |
| 188 | + 1 through 8. Other values are reserved. |
| 189 | + """ |
| 190 | + |
| 191 | + exif_orientation_tag = 0x0112 |
| 192 | + exif_transpose_sequences = [ # Val 0th row 0th col |
| 193 | + [], # 0 (reserved) |
| 194 | + [], # 1 top left |
| 195 | + [Image.FLIP_LEFT_RIGHT], # 2 top right |
| 196 | + [Image.ROTATE_180], # 3 bottom right |
| 197 | + [Image.FLIP_TOP_BOTTOM], # 4 bottom left |
| 198 | + [Image.FLIP_LEFT_RIGHT, Image.ROTATE_90], # 5 left top |
| 199 | + [Image.ROTATE_270], # 6 right top |
| 200 | + [Image.FLIP_TOP_BOTTOM, Image.ROTATE_90], # 7 right bottom |
| 201 | + [Image.ROTATE_90], # 8 left bottom |
| 202 | + ] |
| 203 | + |
| 204 | + try: |
| 205 | + seq = exif_transpose_sequences[im._getexif()[exif_orientation_tag]] |
| 206 | + except Exception: |
| 207 | + return im |
| 208 | + else: |
| 209 | + return functools.reduce(type(im).transpose, seq, im) |
| 210 | + |
179 | 211 | def resize_image(image,width=None,height=None,allowRatioChange=False): |
180 | 212 | orig_width,orig_height = image.size |
181 | 213 | if width is not None and height is None: # Resize base on width |
@@ -211,6 +243,7 @@ def make_text_img(): |
211 | 243 | def load_image(path): |
212 | 244 | lprint("Loading image %s" % (path)) |
213 | 245 | im = Image.open(path) |
| 246 | + im = image_transpose_exif(im) |
214 | 247 | im_safe = im.copy() |
215 | 248 | im.close() |
216 | 249 | lprint("Image %s loaded" % (path)) |
@@ -286,7 +319,7 @@ def process_image(base_img,watermark_img): |
286 | 319 |
|
287 | 320 | # Check if watermark will fit image in offset position |
288 | 321 | if watermark_w + pos_w > base_w or watermark_h + pos_h > base_h: |
289 | | - raise Exception(16,"Watermark does not fit in the picture") |
| 322 | + raise Exception(16,"Watermark does not fit in the picture") |
290 | 323 |
|
291 | 324 | lprint("Watermark position: X:%i Y:%i Margin:%i" % (pos_w,pos_h,margin)) |
292 | 325 |
|
|
0 commit comments