1#!/usr/local/bin/python3.8 2# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai 3 4 5__license__ = 'GPL v3' 6__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' 7__docformat__ = 'restructuredtext en' 8 9import os 10 11from calibre.utils.magick import Image, create_canvas 12from calibre.utils.img import save_cover_data_to as _save_cover_data_to, image_to_data, add_borders_to_image as abti 13from calibre.utils.imghdr import identify as _identify 14from calibre import fit_image 15 16 17def _data_to_image(data): 18 if isinstance(data, Image): 19 img = data 20 else: 21 img = Image() 22 img.load(data) 23 return img 24 25 26def minify_image(data, minify_to=(1200, 1600), preserve_aspect_ratio=True): 27 ''' 28 Minify image to specified size if image is bigger than specified 29 size and return minified image, otherwise, original image is 30 returned. 31 32 :param data: Image data as bytestring or Image object 33 :param minify_to: A tuple (width, height) to specify target size 34 :param preserve_aspect_ratio: whether preserve original aspect ratio 35 ''' 36 img = _data_to_image(data) 37 owidth, oheight = img.size 38 nwidth, nheight = minify_to 39 if owidth <= nwidth and oheight <= nheight: 40 return img 41 if preserve_aspect_ratio: 42 scaled, nwidth, nheight = fit_image(owidth, oheight, nwidth, nheight) 43 img.size = (nwidth, nheight) 44 return img 45 46 47def save_cover_data_to(data, path, bgcolor='#ffffff', resize_to=None, 48 return_data=False, compression_quality=90, minify_to=None, 49 grayscale=False): 50 ''' 51 Saves image in data to path, in the format specified by the path 52 extension. Removes any transparency. If there is no transparency and no 53 resize and the input and output image formats are the same, no changes are 54 made. 55 56 :param data: Image data as bytestring or Image object 57 :param compression_quality: The quality of the image after compression. 58 Number between 1 and 100. 1 means highest compression, 100 means no 59 compression (lossless). 60 :param bgcolor: The color for transparent pixels. Must be specified in hex. 61 :param resize_to: A tuple (width, height) or None for no resizing 62 :param minify_to: A tuple (width, height) to specify maximum target size. 63 :param grayscale: If True, the image is grayscaled 64 will be resized to fit into this target size. If None the value from the 65 tweak is used. 66 67 ''' 68 fmt = os.path.splitext(path)[1] 69 if return_data: 70 path = None 71 if isinstance(data, Image): 72 data = data.img 73 return _save_cover_data_to( 74 data, path, bgcolor=bgcolor, resize_to=resize_to, compression_quality=compression_quality, minify_to=minify_to, grayscale=grayscale, data_fmt=fmt) 75 76 77def thumbnail(data, width=120, height=120, bgcolor='#ffffff', fmt='jpg', 78 preserve_aspect_ratio=True, compression_quality=70): 79 img = Image() 80 img.load(data) 81 owidth, oheight = img.size 82 if width is None: 83 width = owidth 84 if height is None: 85 height = oheight 86 if not preserve_aspect_ratio: 87 scaled = owidth > width or oheight > height 88 nwidth = width 89 nheight = height 90 else: 91 scaled, nwidth, nheight = fit_image(owidth, oheight, width, height) 92 if scaled: 93 img.size = (nwidth, nheight) 94 canvas = create_canvas(img.size[0], img.size[1], bgcolor) 95 canvas.compose(img) 96 data = image_to_data(canvas.img, compression_quality=compression_quality) 97 return (canvas.size[0], canvas.size[1], data) 98 99 100def identify_data(data): 101 ''' 102 Identify the image in data. Returns a 3-tuple 103 (width, height, format) 104 or raises an Exception if data is not an image. 105 ''' 106 fmt, width, height = _identify(data) 107 return width, height, fmt 108 109 110def identify(path): 111 ''' 112 Identify the image at path. Returns a 3-tuple 113 (width, height, format) 114 or raises an Exception. 115 ''' 116 with lopen(path, 'rb') as f: 117 fmt, width, height = _identify(f) 118 return width, height, fmt 119 120 121def add_borders_to_image(img_data, left=0, top=0, right=0, bottom=0, 122 border_color='#ffffff', fmt='jpg'): 123 img = abti(img_data, left=left, top=top, right=right, bottom=bottom, border_color=border_color) 124 return image_to_data(img, fmt=fmt) 125