moo*_*hen 1 reduce python-3.x image-size
我想将图像缩小到更小的尺寸,以便于共享和更快的上传。
但我意识到,如果我只是通过其硬件来减小尺寸,它并不能真正起到作用,因为大图像文件可能具有较小的硬件,而小图像文件可能具有较大的硬件,因此通过减小其高度来减小图像尺寸& 重量可能并不总是按照我想要的方式缩小尺寸。
所以现在我使用这个得到了字节大小:
import os
os.stat('myImage.jpg').st_size
Run Code Online (Sandbox Code Playgroud)
是否可以通过减少字节来减小图像大小?并保持其比例?
这是我用 PIL 编写的一个函数。它对图像进行一些迭代调整大小和 jpeg 压缩,然后查看生成的文件大小并将其与目标值进行比较,根据大小偏差比猜测下一个最佳宽度/高度组合(基本上是某种 P 控制器)。
它利用 io.BytesIO 来完成内存中的所有大小调整工作,因此对磁盘上的文件实际上只有一次读取和一次写入访问。此外,通过这种强力方法,您可以将目标文件格式更改为 PNG,并且它可以开箱即用。
from PIL import Image
import os
import io
def limit_img_size(img_filename, img_target_filename, target_filesize, tolerance=5):
img = img_orig = Image.open(img_filename)
aspect = img.size[0] / img.size[1]
while True:
with io.BytesIO() as buffer:
img.save(buffer, format="JPEG")
data = buffer.getvalue()
filesize = len(data)
size_deviation = filesize / target_filesize
print("size: {}; factor: {:.3f}".format(filesize, size_deviation))
if size_deviation <= (100 + tolerance) / 100:
# filesize fits
with open(img_target_filename, "wb") as f:
f.write(data)
break
else:
# filesize not good enough => adapt width and height
# use sqrt of deviation since applied both in width and height
new_width = img.size[0] / size_deviation**0.5
new_height = new_width / aspect
# resize from img_orig to not lose quality
img = img_orig.resize((int(new_width), int(new_height)))
limit_img_size(
"test.jpg", # input file
"test_with_limited_size.jpg", # target file
50000, # bytes
tolerance = 5 # percent of what the file may be bigger than target_filesize
)
Run Code Online (Sandbox Code Playgroud)
编辑:
“在内存中”我的意思是当循环中的 to 时,它会将其保存到一个save对象中,该img对象不是磁盘上的文件而是内存中的文件。然后,我可以从该对象确定生成的文件大小(这只是该数据缓冲区的长度),而无需实际将其保存到文件中。最后也许这正是您所期望的工作方式,但我见过太多代码由于缺乏对 Python 的.bufferBytesIOio.BytesIO
只有最终结果才会保存到文件中 - 这就是您想要的位置。尝试使用绝对文件名img_target_filename。
| 归档时间: |
|
| 查看次数: |
5538 次 |
| 最近记录: |