From 37200bdca0155ceba9801ed37e103cc526957435 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Sun, 14 May 2023 09:34:11 -0700 Subject: [PATCH] Crop images within 3% of device aspect ratio (#495) * Crop images within 3% of device aspect ratio * use pad instead of expand+fit * reafactor threshold check * remove default val --- kindlecomicconverter/image.py | 47 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py index 9c9b195..9df8049 100755 --- a/kindlecomicconverter/image.py +++ b/kindlecomicconverter/image.py @@ -24,6 +24,13 @@ import mozjpeg_lossless_optimization from PIL import Image, ImageOps, ImageStat, ImageChops, ImageFilter from .shared import md5Checksum +# 0.045 was determined by +# 1200 / 824 = 1.456 (Kindle DX resolution) +# 2250 / 1500 = 1.5 (Typical manga page resolution) +# 1.5 - 1.456 < 0.045 +# 0.045 / 1.5 = 0.03 (So maximum 3% of is cropped) +AUTO_CROP_THRESHOLD = 0.045 + class ProfileData: def __init__(self): @@ -306,36 +313,32 @@ class ComicPage: self.image = self.image.quantize(palette=palImg) def resizeImage(self): - if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: - method = Image.Resampling.BICUBIC - else: - method = Image.Resampling.LANCZOS + ratio_device = float(self.size[1]) / float(self.size[0]) + ratio_image = float(self.image.size[1]) / float(self.image.size[0]) + method = self.resize_method() if self.opt.stretch: - # if self.opt.stretch or (self.opt.kfx and ('-KCC-B' in self.targetPath or '-KCC-C' in self.targetPath)): self.image = self.image.resize(self.size, method) - elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale: + elif method == Image.Resampling.BICUBIC and not self.opt.upscale: if self.opt.format == 'CBZ' or self.opt.kfx: borderw = int((self.size[0] - self.image.size[0]) / 2) borderh = int((self.size[1] - self.image.size[1]) / 2) self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill) if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]: - self.image = ImageOps.fit(self.image, self.size, method=Image.Resampling.BICUBIC, centering=(0.5, 0.5)) - else: - if self.opt.format == 'CBZ' or self.opt.kfx: - ratioDev = float(self.size[0]) / float(self.size[1]) - if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev: - diff = int(self.image.size[1] * ratioDev) - self.image.size[0] - self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=self.fill) - elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev: - diff = int(self.image.size[0] / ratioDev) - self.image.size[1] - self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=self.fill) - self.image = ImageOps.fit(self.image, self.size, method=method, centering=(0.5, 0.5)) + self.image = ImageOps.fit(self.image, self.size, method=method) + else: # if image bigger than device resolution or smaller with upscaling + if abs(ratio_image - ratio_device) < AUTO_CROP_THRESHOLD: + self.image = ImageOps.fit(self.image, self.size, method=method) + elif self.opt.format == 'CBZ' or self.opt.kfx: + self.image = ImageOps.pad(self.image, self.size, method=method, color=self.fill) else: - hpercent = self.size[1] / float(self.image.size[1]) - wsize = int((float(self.image.size[0]) * float(hpercent))) - self.image = self.image.resize((wsize, self.size[1]), method) - if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]: - self.image.thumbnail(self.size, Image.Resampling.LANCZOS) + self.image = ImageOps.contain(self.image, self.size, method=method) + + def resize_method(self): + if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: + method = Image.Resampling.BICUBIC + else: + method = Image.Resampling.LANCZOS + return method def getBoundingBox(self, tmptmg): min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size]