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_   输出图片宽度
 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_
 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:UsersAdministratorDesktopupdateenjinecgrender	img (8).jpg"
190     output = os.path.join(os.getcwd(), "output.png")
191     handle = ChangeSize(480, 320, path, output)
192     handle.main()
原文地址:https://www.cnblogs.com/MasonHu/p/13930230.html