1. 程式人生 > 實用技巧 >Python實現圖片長寬比例縮放和填充

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()