pillow压缩图片
# image对象转换成图片字节
```
from PIL import Image
from io import BytesIO
im = Image.open("1.jpg")
new_img = im.convert("RGB")
img_byte = BytesIO()
new_img.save(img_byte, format='PNG') # format: PNG or JPEG
binary_content = img_byte.getvalue() # im对象转为二进制流
with open('test.qv', 'wb') as f: #写入文件
f.write(binary_content)
```
# 将字节流成图片
```
with open('test.qv', 'rb') as f:
data = f.read()
bytes_stream = BytesIO(data)
image = Image.open(bytes_stream)
image.show()
```
# 将文件分多次压缩
```
class DataCompress:
"""
原始数据压缩类
"""
def __init__(self, data_dir_path, qv_file, image_width, jpg_width, types, logger):
"""
:param data_dir_path: 数据目录
:param qvfile: 压缩qv文件
:param image_width: 图像原始尺寸宽度
:param jpg_width: 图像压缩宽度
:param types: 1单个(L),2多个(L),3RGB三通道(RGB)
"""
self.compress_length = int(dbapi.get_config('PNG_ENCODE_SIZE_LIMIT').value) # 单次PNG图片压缩所能处理的最大字节数, 从config表中获取
self.data_dir = data_dir_path
self.qv_file = qv_file
self.image_width = image_width
self.jpg_width = jpg_width
self.types = types
self.file_size = None # qv文件大小
self.logger = logger
# 读取文件
def _read_qv_files_data(self, fps):
offset = 1024 # 开头1024字节不读取
# 文件剩余大小
over_size = self.file_size - offset
[fp.seek(offset) for fp in fps]
times = 0
while True:
if over_size < self.image_width:
break
else:
height = math.floor(over_size / self.image_width)
# 如果文件大小大于或等于单次PNG图片压缩所能处理的最大字节数, 计算读取文件行数(单次PNG图片压缩所能处理的最大字节数/图片原始宽度),
# 否则读取文件大小, 计算读取文件行数(文件大小/图片原始宽度)
if self.types == 1 and over_size >= self.compress_length:
height = math.floor(self.compress_length / self.image_width)
else:
# 如果n个文件大小大于或等于单次PNG图片压缩所能处理的最大字节数, 计算读取文件行数(单次PNG图片压缩所能处理的最大字节数/图片原始宽度/n个文件),
if over_size * len(fps) >= self.compress_length:
height = math.floor(self.compress_length / self.image_width / len(fps))
length = self.image_width * height
if self.types == 1:
chunk = fps[0].read(length)
else:
bin_datas = [f.read(length) for f in fps]
btyes_io_raw = BytesIO()
start = 0
end = self.image_width
for i in range(height):
for j in bin_datas:
btyes_io_raw.write(j[start:end])
start = end
end = start+self.image_width
chunk = btyes_io_raw.getvalue()
times += 1
over_size -= length
self.logger.info(f"第{times}读了: {length}, 文件剩余:{over_size}")
yield height, chunk
def start_run(self, png_dir_path):
data = self._join_qv_file(png_dir_path)
jpg_dir_path, image_filename = data[0], data[1]
fps = []
# 单个文件压缩
if self.types == 1:
fps.append(open(f'{self.data_dir}{self.qv_file}', 'rb'))
else:
fps.extend([open(f'{self.data_dir}{qv_file}', 'rb') for qv_file in self.qv_file])
self._compress_images(fps, jpg_dir_path, image_filename)
[f.close() for f in fps]
def _compress_images(self, fps, jpg_dir_path, image_filename):
count = 0
for h, chunk in self._read_qv_files_data(fps):
jpg_height = math.floor(h / (self.image_width / self.jpg_width))
if self.types == 1:
im = Image.frombytes('L', (self.image_width, h), chunk, "raw")
self.logger.info(f"单文件压缩图片: 原尺寸 : image_width : {self.image_width} , image_height: {h},压缩尺寸: "
f"jpg_width:{self.jpg_width}, jpg_height: {jpg_height}")
elif self.types == 2:
jpg_height = math.floor(h / (self.image_width * len(fps) / self.jpg_width))
im = Image.frombytes('L', (self.image_width * len(fps), h), chunk, "raw")
self.logger.info(f"多文件压缩图片: 原尺寸 : image_width : {self.image_width * len(fps)} , image_height: {h},"
f"压缩尺寸: jpg_width: {self.jpg_width}, jpg_height: {jpg_height}")
else:
im = Image.frombytes('RGB', (self.image_width, h), chunk, "raw", "RGB;L")
self.logger.info(f"RGB压缩图片: 原尺寸 : image_width : {self.image_width} , image_height: {h}, 压缩尺寸: "
f"jpg_width: {self.jpg_width}, jpg_height: {jpg_height}")
if jpg_height >= 64:
new_im = im.resize((self.jpg_width, jpg_height))
save_png_path = f'{jpg_dir_path}/{image_filename}'
new_im.save(f'{save_png_path}_{str(count).zfill(3)}.png', quality=95)
count += 1
# 拼接qv文件路径以及创建图片存储路径: 1单个(L),2多个(L),3RGB三通道(RGB)
def _join_qv_file(self, png_dir_path):
if self.types == 1:
self.file_size = os.path.getsize(f'{self.data_dir}{self.qv_file}') # 获取文件大小
# 拼接单个文件存储的文件名
file_path = self.qv_file.split(".")[0]
else:
# 获取最小文件大小,以最小文件合并结束
self.file_size = min([os.path.getsize(f'{self.data_dir}{qv_file}') for qv_file in self.qv_file])
file_path = self.qv_file[0].split('_')
group_num = re.findall(r'QVIEW([\d]+)_', str(self.qv_file)) # 获取通道号
# 拼接多个文件存储路径
if self.types == 2:
file_path[3], filename_suffix = 'QVIEW_' + '_'.join(group_num), '_拼接_PNG'
# 拼接rgb多个路径
else:
r, g, b = group_num
file_path[3], filename_suffix = f'QVIEW_R{r}_G{g}_B{b}', '_RGB合成_PNG'
file_path = '_'.join(file_path).replace('.', '_').upper() + filename_suffix
self.logger.info(f"获取qv文件大小:size {self.file_size - 1024}")
jpg_dir_path = os.path.join(png_dir_path, file_path)
self.logger.info(f"创建图片存放子目录:mkdir {jpg_dir_path}")
if not os.path.exists(jpg_dir_path):
os.makedirs(jpg_dir_path)
self.logger.info(f"创建成功")
return jpg_dir_path, file_path
```
pillow压缩图片相关推荐
- 【pngquant】使用Python压缩图片,降低网页加载时间
更多内容请点击 我的博客 查看,欢迎来访. 用来做什么? 个人在写博客时,发现上传的图片如果很大,web访问第一次加载该图片就特别的慢. 可以考虑使用缩略图,浏览时显示缩略图,如果要看高清图,需点击图 ...
- python怎么把图片压缩_使用Python轻松批量压缩图片
在互联网,图片的大小对一个网站的响应速度有着明显的影响,因此在提供用户预览的时候,图片往往是使用压缩后的.如果一个网站图片较多,一张张压缩显然很浪费时间.那么接下来,我就跟大家分享一个批量压缩图片的方 ...
- 10 行 Python 代码,批量压缩图片 500 张,简直太强大了
这几天,我在用 Github page + hexo 搭建个人网站,为了延续风格,就想把配图与文章一起迁移过去.这时候就出现了一个难题:我所用的图片都是高清大图,放到网站上会严重拖慢加载速度.因此,需 ...
- python压缩图片--指定压缩大小且保真压缩
代码核心思路 循环降低图片质量quality 直至图片质量大小符合目标质量后退出循环 pillow压缩失真严重 ''' pip install pillow ''' from io import By ...
- Python中用PIL/Pillow裁剪图片
# pip install Pillow # 在img标签里面只设置宽,不设置高,图片就会等比例缩放. # coding=utf-8 from PIL import Image import Imag ...
- python 批处理压缩图片
巧合之下,需要一个能够批处理压缩图片的程序来帮我的私人图库做一个压缩.在网上找了一些软件,但是都没有遇到合适的(或者免费的bushi),于是想到能不能用自己拙劣的python写个小程序呢? 于是在网上 ...
- python --压缩图片不改变图片尺寸
方法1 from PIL import Image import osdef compress_image(infile, outfile, quality=50):""" ...
- Android 高清加载巨图方案 拒绝压缩图片
Android 高清加载巨图方案 拒绝压缩图片 转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/49300989: 本文出自: ...
- android h5 多图上传源码,JS移动端/H5同时选择多张图片上传并使用canvas压缩图片...
最近在做一个H5的项目,里边涉及到拍照上传图片的功能以及识别图片的功能,这里对识别图片的功能不做赘述,不属本文范畴.我在做完并上线项目后,同事跟我提了一个要求是可不可以同时选择多张图片上传,我做的时候 ...
最新文章
- 比ajax更好技术,ajax 技术
- dede如何给dede_sys_enum添加字段father
- 存储块的删除与状态查询
- 工作193:vue.runtime.esm.js?2b0e:619 [Vue warn]: <transition-group> children must be keyed: <ElTag>
- java map 缓存池_map端合并(分布式缓存)
- 安卓案例:启动和停止服务
- rust投递箱连接箱子_拆了的快递包装丢哪里?闵行试行24小时开放的网购包装回收箱...
- 二十一天学通VC++之创建工作者线程
- Spring自学教程-AOP学习(五)
- 自己写的微信小程序炸金花简单版
- pdf怎么合并成一个pdf?电脑怎么把多个pdf文件合并成一个pdf?
- 柴俊理金:临近公投市场屏息,黄金沥青谨慎而行
- 暗刺,高并发五个利器
- 调试的时候没有在断点处停止的原因
- 【天池竞赛】心跳数据挖掘
- 苹果遭遇史上最严厉的泄密:自家的iOS源代码居然泄漏了
- oracle for update wait 解析
- 关于小程序的https
- Python数据分析---回力评论关键字统计并制作词云图
- 史蒂芬·乔布斯amp;斯坦福大学
热门文章
- 安装win10,刻录U盘,还原刻录的U盘
- 佳能 c3000 系统设置改语言,win7如何更改语言 win7系统中将电脑语言改成英文的方法步骤介绍...
- 数据分析的目的和意义(作用)是什么?
- UserWarning: Previous unbuffered result was left incomplete
- 【SSM架构】博客系统开发(七)-登陆界面
- Gym 101142G Gangsters in Central City【思维+Lca】
- js源生实现图片点击弹出放大效果
- JAVA自学之路 [原创 - 尚学堂科技 - 马士兵老师]
- Elasticsearch[学习笔记]
- 使用 Elasticsearch 搭建自己的搜索系统,真心强大!