一直想找个“无损压缩”的办法。
当然这并非真的无损。
我采用了Opencv的处理图像相关的方法。
请见代码:
# -*- coding: UTF-8 -*-# 开发人员:萌狼蓝天# 博客:Https://mllt.cc# 笔记:Https://cnblogs.com/mllt# 哔哩哔哩/微信公众号:萌狼蓝天# 开发时间:2022/10/21importurllib.parseasparseimportcv2ascvfromPILimportImageimportnumpyasnpimportosdefzipJPG(img,level,outpath): img=parse.unquote(img) outpath=parse.unquote(outpath) print(img) img=img.replace("%20"," ") outpath=outpath.replace("%20", " ") print(img) img=Image.open(img) # 避免P模式图片造成异常# print(img.mode)# 转换图片模式为RGBimg=img.convert("RGB") img=cv.cvtColor(np.asarray(img), cv.COLOR_RGB2BGR) # 转换为np数组# [1]cv.IMREAD_COLOR:加载彩色图像,任何图像的透明度都会被忽略,它是默认标志# [0]cv.IMREAD_GRAYSCALE:以灰度模式加载图像# [-1]cv.IMREAD_UNCHANGED:加载图像,包括 alpha 通道try: level=int(level) except: return"ERROR-IMG-ZIP-JPG-LEVEL"iflevel>100: level=100iflevel<0: level=0try: cv.imwrite("./temp.jpg",img,[cv.IMWRITE_JPEG_QUALITY,level]) img=Image.open("temp.jpg") img.save(outpath) if(os.path.exists(outpath)): returnoutpathelse: return"ERROR-IMG-ZIP-JPG-WRITE"exceptExceptionase: print(e) return"ERROR-IMG-ZIP-JPG-DEAL"# 对于JPEG格式的图片,这个参数表示从0 - 100的图片质量(CV_IMWRITE_JPEG_QUALITY), 默认值是95.## 对于PNG格式的图片,这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0 - 9.较高的值意味着更小的尺寸和更长的压缩时间而默认值是3.## 对于PPM,PGM或PBM格式的图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,而默认值为1.# 判断文件是否存在,存在则返回成功,失败则返回失败
如果要做成接口的话,可以这样
# -*- coding: UTF-8 -*-# 开发人员:萌狼蓝天# 博客:Https://mllt.cc# 笔记:Https://cnblogs.com/mllt# 哔哩哔哩/微信公众号:萌狼蓝天# 开发时间:2022/10/21importbase64importjsonfromfastapiimportFastAPI, QueryfrompydanticimportBaseModel# uvicorn main:app --reloadimportimg.PicDealapp=FastAPI() get("/img") .defhello(): return {"Hello": "World"} post('/img/zip/jpg') .asyncdefimg_zip_jpg(img,level,outpath): result=PicDeal.zipJPG(img,level,outpath=outpath) state="1"if(result=="ERROR-IMG-ZIP-JPG-WRITE"): state="0"if (result=="ERROR-IMG-ZIP-JPG-DEAL"): state="-1"if(result=="ERROR-IMG-ZIP-JPG-LEVEL"): state="-2"return {"data":[{"state":state},{"result":result}]} classImgs(BaseModel): imgs= [] # type: list[str]level=""# type: stroutpath= [] # type: list[str]post('/img/zip/jpg/many') .asyncdefimg_zip_jpg(Imgs:Imgs): print(Imgs) result=[] foriinrange(len(Imgs.imgs)): r=PicDeal.zipJPG(Imgs.imgs[i], Imgs.level, Imgs.outpath[i]) state="1"ifr=="ERROR-IMG-ZIP-JPG-WRITE": state="0"ifr=="ERROR-IMG-ZIP-JPG-DEAL": state="-1"ifr=="ERROR-IMG-ZIP-JPG-LEVEL": state="-2"result.append({"state": state, "result": r}) return {"data":{"result":result}}
下面是我做的。
手机拍的照片,1.84MB压缩成468kb(默认75)情况下
手机拍的照片,2.56MB压缩成532kb(默认50)情况下