def _convert_image(self, file_path: str, preview_dims: ImgDims) -> Image: """ refer: https://legacy.imagemagick.org/Usage/thumbnails/ like cmd: convert -layers merge -background white -thumbnail widthxheight \ -auto-orient -quality 85 -interlace plane input.jpeg output.jpeg """ img = Image(filename=file_path) resize_dim = compute_resize_dims(dims_in=ImgDims(width=img.width, height=img.height), dims_out=preview_dims) img.auto_orient() img.iterator_reset() img.background_color = Color("white") img.merge_layers("merge") if self.progressive: img.interlace_scheme = "plane" img.compression_quality = self.quality img.thumbnail(resize_dim.width, resize_dim.height) return img
def orient_and_resize(image_filename): resized_images = {} img = Image(filename=image_filename) img.auto_orient() (w,h) = img.size w = int(w) h = int(h) filename_base = image_filename filename_base = filename_base.replace("/", "-") filename_base = filename_base.replace(" ", "_") with img.clone() as img_clone: img_clone.resize(1280, int((1280.0/w)*h)) fname = "Resized/" + filename_base + "_1280.jpg" resized_images['1280'] = fname img_clone.save(filename=PREFIX_DIR + fname) with img.clone() as img_clone: img_clone.resize(640, int((640.0/w)*h)) fname = "Resized/" + filename_base + "_640.jpg" resized_images['640'] = fname img_clone.save(filename=PREFIX_DIR + fname) with img.clone() as img_clone: img_clone.resize(320, int((320.0/w)*h)) fname = "Resized/" + filename_base + "_320.jpg" resized_images['320'] = fname img_clone.save(filename=PREFIX_DIR + fname) with img.clone() as img_clone: img_clone.resize(160, int((160.0/w)*h)) fname = "Resized/" + filename_base + "_160.jpg" resized_images['160'] = fname img_clone.save(filename=PREFIX_DIR + fname) img.close() return ((w, h), resized_images)
def resize_image(path=None, blob=None, img=None, name=None, fmt='jpeg', auto_orient=True, upscale=False): """A coroutine that resizes a single image multiple times Note that the same image buffer is used across multiple operations so operations should be ordered from highest-quality to lowest. Parameters: - path/blob/img: Source data (img is a Wand Image object) - name: The name of the file (for logging purposes only) - fmt: The image format of the resulting images (default: 'jpeg') - auto_orient: Automatically orient image before processing (default: true) - upscale: Upscale images to fit the desired resolution if they're too small (default: False) Receives a 4-tuple of (size, quality, square, fp) - size: The image will be resized so that the longest edge is this many pixels. If None the image will not be resized. - quality: The JPEG quality level - square: If true, the images will be cropped to square before being resized - fp: A file-like object to write() the result into """ if sum([bool(path), bool(blob), bool(img)]) != 1: raise ValueError("One of 'path', 'blob', or 'img' is required") if path: img = Image(filename=path) elif blob: img = Image(blob=blob) with img: # If there are multiple frames only use the first one (this # prevents GIFs and ICOs from exploding their frames into # individual images) if img.sequence: for _ in range(1, len(img.sequence)): img.sequence.pop() # Rotation and conversion to desired output format if auto_orient: img.auto_orient() img.format = fmt while True: size, quality, square, fp = yield __log__.debug("[resizing] %s -> %s%s", name or "<img data>", "{}px".format(size) if size else "fullsize", ", square" if square else "" ) if square: crop = min(img.size) img.crop(width=crop, height=crop, gravity='center') if size is not None and (upscale or size < crop): img.resize(size, size) elif size is not None: # Work around a bug in Wand's image transformation by # manually calculating the scaled dimensions and resizing ratio = size/max(img.size) if upscale or ratio < 1: img.resize(*[round(x*ratio) for x in img.size]) img.compression_quality = quality try: img.save(file=fp) except IOError as e: __log__.error("[error] Failed to write image: %s", e, exc_info=True) raise