Posts
图片文件大小压缩

图片文件大小压缩

疫情后在小公司实习的任务之一

微信内容安全 api上传文件大小限制图片数据1M, 文本500K 对图片数据进行适当的压缩,resize不怎么影响分类模型的结果

import cv2 
import pandas as pd
import numpy as np 
import io, os
 
def img_downsize(bin_img, ratio = 2):
    if len(bin_img) < 5 * (1 << 20):
        return bin_img
 
    arr = np.frombuffer(bin_img, dtype=np.uint8, count=-1)
    img = cv2.imdecode(arr, cv2.IMREAD_UNCHANGED)
 
    h, w = img.shape[:2]
    h = h // ratio
    w = w // ratio
    img = cv2.resize(img, (w, h))
 
    _, buffer = cv2.imencode(".jpg", img)
    ratio_bin_img = bytes(list(np.squeeze(buffer)))
    open(f'size_{ratio}.jpg', 'wb').write(ratio_bin_img)
    
    ratio_size = len(ratio_bin_img) / (1 << 20)
    print(" {}downsize: {:.2f}MB".format(ratio, ratio_size))
 
    return img_downsize(ratio_bin_img, ratio)
 
def img_compress(bin_img: str, ratio: int = 70):
    bin_img = img_resize(bin_img)
 
    if len(bin_img) < (1 << 20) or ratio < 10:
        return bin_img  
    
    arr = np.frombuffer(bin_img, dtype=np.uint8, count=-1)
    img = cv2.imdecode(arr, cv2.IMREAD_UNCHANGED)
    
    # imencode, the counterpart of imwrite, write img arr into mem
    # buffer (n, 1)
    is_success, buffer = cv2.imencode(".jpg", img, [cv2.IMWRITE_JPEG_QUALITY, ratio])
    ratio_bin_img = bytes(list(np.squeeze(buffer)))
    open(f'ratio_{ratio}.jpg', 'wb').write(ratio_bin_img)
 
    # # io bytes decode
    # io_buf = io.BytesIO(buffer)
    # decode_img = cv2.imdecode(np.frombuffer(io_buf.getbuffer(), np.uint8), -1)
    # print(np.allclose(img, decode_img))   # True    
 
    ratio_size = len(ratio_bin_img) / (1 << 20)
    
    print("{}% compression: {:.2f}MB".format(ratio, ratio_size))
    return img_downsize(ratio_bin_img, ratio - 10)
 
 
if __name__ == "__main__":
    for img in os.listdir('.'):
        if img.endswith('.jpg'):
            print(img)
            bin_img = open(img, 'rb').read()
            ratio_bin_img = img_downsize(bin_img)
 
Updated at