Python实现图片长宽比例缩放和填充
图片的大小(KB)也可以更改, 但是某些格式不太好操作, 我自己没发现啥比较好的办法, 所以暂时是放弃这一部分
PNG格式和JPG格式的区别应该就是图层吧, 导致对PNG更改大小(KB) 做不到我想要的效果, 这些我不是很专业, 所以也不太清楚
1 ''' 2 : 一个缩略图程序, 不需要的部分可以去掉 3 : 主要实现了尺寸(长宽)和大小(KB)的缩小 4 ''' 5 import cv2 6 import os.path 7 from PIL import Image 8 from psd_tools import PSDImage 9 10 11 class ChangeSize: 12 13 def __init__(self, out_width, out_height, start_path, output_path, limit_size=100): 14 ''' 15 :param start_path: 输入图片地址 16 :param limit_size: 输出图片大小(KB) 17 :param out_width: 输出图片宽度 18 :param out_height: 输出图片高度 19 ''' 20 self.out_width = out_width 21 self.out_height = out_height 22 self.limit_size = limit_size 23 self.start_path = start_path 24 self.output_path = output_path 25 print("start_path: ", self.start_path) 26 print("output_path: ", self.output_path) 27 28 def get_image(self): 29 self.suffix = self.start_path.rsplit("\\", 1)[-1].rsplit(".", 1)[-1] 30 31 if self.suffix == "exr": # 如果是exr, 单独处理 32 self.tmp_path = mk_tmp_dir() # 创建临时文件夹 33 self.temp_exr = self.tmp_path + "/temp_exr.hdr" # 先转换成hdr 34 img_read = cv2.imread(self.start_path, cv2.IMREAD_UNCHANGED) 35 cv2.imwrite(self.temp_exr, img_read) 36 return self.get_temp_obj() 37 elif self.suffix == "psd": 38 self.tmp_path = mk_tmp_dir() 39 self.temp_psd = self.tmp_path + "/temp_psd.png" 40 psd = PSDImage.open(self.start_path) 41 psd.compose().save(self.temp_psd) 42 return self.get_temp_obj() 43 else: # 其他格式图片正常处理 44 img_read = cv2.imread(self.start_path) 45 if img_read is None: 46 print("---Read Img Failed---") 47 else: 48 print("缩略图程序读取图片成功") 49 return img_read 50 51 def get_temp_obj(self): 52 ''' 53 用于需要转换格式的中转函数. exr, psd 等图片不能直接转换格式, 需要中转格式 54 :return: cv2 img Object 55 ''' 56 if self.suffix == "exr": 57 img_read = cv2.imread(self.temp_exr) 58 return img_read 59 # if self.suffix == "psd": 60 # img_read = cv2.imread(self.temp_psd) 61 # return img_read 62 63 def get_resize_img(self, img): 64 ''' 65 在这里转换尺寸, 保留原来尺寸比 66 :param img: cv2.img_Object 67 ''' 68 size = img.shape 69 h, w = size[0], size[1] 70 print(w, h) 71 72 if h == w: 73 longest = h 74 scale = longest / float(self.out_height) 75 new_h, new_w = int(h / scale), int(w / scale) 76 print(new_w, new_h) 77 resize_img = self.fill_blank(img=img, new_w=new_w, new_h=new_h) 78 return resize_img 79 elif w > h: 80 longest = w 81 scale = longest / float(self.out_width) 82 new_h, new_w = int(h / scale), int(w / scale) 83 if new_h > self.out_height: 84 longest1 = h 85 scale1 = longest1 / float(self.out_height) 86 new_h_1, new_w_1 = int(h / scale1), int(w / scale1) 87 resize_img = self.fill_blank(img=img, new_w=new_w_1, new_h=new_h_1) 88 return resize_img 89 resize_img = self.fill_blank(img=img, new_w=new_w, new_h=new_h) # 填充空白部分为黑色 90 return resize_img 91 92 elif h > w: 93 longest = h 94 scale = longest / float(self.out_height) 95 new_h, new_w = int(h / scale), int(w / scale) 96 print(new_w, new_h) 97 if new_w > self.out_width: 98 longest1 = w 99 scale1 = longest1 / float(self.out_width) 100 new_h_1, new_w_1 = int(h / scale1), int(w / scale1) 101 resize_img = self.fill_blank(img=img, new_w=new_w_1, new_h=new_h_1) 102 return resize_img 103 resize_img = self.fill_blank(img=img, new_w=new_w, new_h=new_h) 104 return resize_img 105 else: 106 print("---未知错误---") 107 108 def fill_blank(self, img, new_w, new_h): 109 ''' 110 :param img: 拿到cv2.imread() 返回的对象 111 :param new_w: 未补空白的时的宽度 112 :param new_h: 未补空白的时的高度 113 :return: 返回补空白后的对象(该对象用来写入) 114 ''' 115 resize_img1 = cv2.resize(img, (new_w, new_h)) 116 if new_w % 2 != 0 and new_h % 2 == 0: 117 top, bottom, left, right = (self.out_height - new_h) / 2, (self.out_height - new_h) / 2, ( 118 self.out_width - new_w) / 2 + 1, (self.out_width - new_w) / 2 119 elif new_h % 2 != 0 and new_w % 2 == 0: 120 top, bottom, left, right = (self.out_height - new_h) / 2 + 1, (self.out_height - new_h) / 2, ( 121 self.out_width - new_w) / 2, (self.out_width - new_w) / 2 122 elif new_h % 2 == 0 and new_w % 2 == 0: 123 top, bottom, left, right = (self.out_height - new_h) / 2, (self.out_height - new_h) / 2, (self.out_width - new_w) / 2, ( 124 self.out_width - new_w) / 2 125 else: 126 top, bottom, left, right = (self.out_height - new_h) / 2 + 1, (self.out_height - new_h) / 2, ( 127 self.out_width - new_w) / 2 + 1, (self.out_width - new_w) / 2 128 resize_img = cv2.copyMakeBorder(resize_img1, int(top), int(bottom), int(left), int(right), cv2.BORDER_CONSTANT, 129 value=[0, 0, 0]) 130 # 从图像边界向上,下,左,右扩的像素数目 131 # cv2.imwrite("img_out/finally_w.jpg", pad_img) 132 return resize_img 133 134 def limit_size(self, quality=80, step=5): 135 """ 136 图片尺寸压缩到指定大小(KB), 注意, 有些图片格式压缩不了. 此方法暂时废弃 137 :param step: 每次调整的压缩比率 138 :param quality: 初始压缩比率 139 :return: 压缩文件地址,压缩文件大小 140 """ 141 file_size = os.path.getsize(self.tmp_file) / 1024 142 print("size: ", file_size, "limit_size: ", self.limit_size) 143 im = Image.open(self.tmp_file) 144 if file_size < self.limit_size: 145 im.save(self.output_file) 146 return 147 while file_size > self.limit_size: 148 im.save(self.output_file, quality=quality) 149 if quality - step < 0: 150 break 151 quality -= step 152 o_size = os.path.getsize(self.output_file) / 1024 153 return o_size 154 155 def main(self): 156 img_obj = self.get_image() 157 img_obj1 = self.get_resize_img(img_obj) 158 cv2.imwrite(output, img_obj1) 159 # cv2.imwrite(output, img_read, [cv2.IMWRITE_PNG_COMPRESSION, 1]) 160 print("---缩略图程序完成---") 161 162 163 def rm_tmp_dir(start_path=None): 164 ''' 165 移除临时文件夹 166 ''' 167 savePath = current_path = os.getcwd() 168 tmp_path = savePath + "/tmp" 169 try: 170 import shutil 171 if os.path.exists(tmp_path): # 如果文件存在 172 print("临时文件夹存在, 开始删除") 173 shutil.rmtree(tmp_path, ignore_errors=True) 174 else: 175 print('no such file:%s' % tmp_path) # 则返回文件不存在 176 except Exception as rm_tmpdir_error: 177 print(rm_tmpdir_error) 178 179 180 def mk_tmp_dir(): 181 current_path = os.getcwd() 182 tmp_path = os.path.join(current_path, "tmp") 183 if not os.path.exists(tmp_path): 184 os.mkdir(tmp_path) 185 return tmp_path 186 187 188 if __name__ == "__main__": 189 path = r"C:\Users\Administrator\Desktop\update\enjinecgrender\timg (8).jpg" 190 output = os.path.join(os.getcwd(), "output.png") 191 handle = ChangeSize(480, 320, path, output) 192 handle.main()