python - 使用 PIL python 根据文件大小计算图像分辨率
问题描述
我想使用基于所需文件大小的resize()
方法调整图像大小。PIL
例如,我有一个文件大小为 14.1 MB、宽 x 高为3456 x 5184
. 如果所需的文件大小为2 MB ,它的分辨率是多少?我自己尝试了一些计算,比如使用这个公式image_size = (width * height * bit_depth + headers) / 8
加上图像当前状态的纵横比,但它没有像我预期的那样工作。
目标:
找到所需的高度或宽度
已知:
- 所需文件大小
- 当前文件大小
- 当前分辨率(宽 x 高)
解决方案
从这里复制 如何将 jpeg 大小减小到“所需大小”?在这里Python PIL: Find the size of image without write it as a file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Feb 27 18:26:54 2021
@author: Pietro
"""
import io
from PIL import Image
def SaveWithTargetFileSize(im, filename, target):
x, y =im.size
buffer = io.BytesIO()
im.save(buffer, format=mod_img, quality=100)
im_size = buffer.getbuffer().nbytes
if im_size <= target:
print('invalid target value ')
return
while im_size > target :
buffer = io.BytesIO()
im.save(buffer, format=mod_img, quality=100)
im_size = buffer.getbuffer().nbytes
im = im.resize((x,y))
# print(x,y ,' ', im_size)
x -= 1
y -= 1
print('image_size for target file_size :', im.size[0],' X ', im.size[1] ,' image_file_size :', im_size)
im.save(filename+'.'+mod_img.lower(), format=mod_img, quality=100)
im = Image.open('Immagine_6.tif')
x, y =im.size
typ_img = im.mode
mod_img = im.format
print('image size : ',x,' X ',y,' ',' image_type :', typ_img,' image_format :', mod_img)
SaveWithTargetFileSize(im, "result_2", 400000) # here the target values in bytes
您需要以字节为单位计算文件大小目标(或在代码中添加转换器)
它很慢,因为每次从初始值到目标值仅调整 1 个像素
也许其他人会使用最快的方法。
正如@thebjorn 所建议的那样,我尝试对分搜索
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Feb 27 18:26:54 2021
@author: Pietro
"""
import io
from PIL import Image
from datetime import datetime
begin = datetime.now()
def SaveWithTargetFileSize(im, filename, target):
xmax, ymax = im.size
xmin = 0
ymin = 0
buffer = io.BytesIO()
im.save(buffer, format=mod_img, quality=100)
im_size = buffer.getbuffer().nbytes
im_size_original = im_size
if im_size <= target:
print('invalid target value ')
return
numGuesses = 0
while xmin < xmax and ymin < ymax:
x_x, y_y = (xmax - xmin)//2, (ymax - ymin)//2
im = im.resize((x_x, y_y))
buffer = io.BytesIO()
im.save(buffer, format=mod_img, quality=100)
im_size = buffer.getbuffer().nbytes
#print(im.size[0], im.size[1], ' ', im_size, ' guesses :',
# numGuesses, ' ', im_size, target, x_x, y_y, xmax, ymax, xmin, #ymin)
if im_size < target:
xmax += x_x
ymax += y_y
elif im_size > target:
xmax -= x_x
ymax -= y_y
if abs(im_size - target) < (target*1)//100:
if im_size > target:
approx = str(200-(im_size*100/target))
if im_size < target:
approx = str(im_size*100/target)
return print('\nbest approximation : ',approx+'%\n\n',im.size[0],' ', im.size[1], ' ', im_size,
' guesses : ', numGuesses,
' ', im_size,' ', target,' ', x_x,' ', y_y,' ', xmax,' ', ymax,' ', xmin,' ', ymin,' ', im_size_original,'\n\n',sep='')
print(im.size[0], im.size[1], ' ', im_size, ' guesses :', numGuesses,
' ', im_size, target, x_x, y_y, xmax, ymax, xmin, ymin, im_size_original,'\n\n')
numGuesses += 1
print('image_size for target file_size :',
im.size[0], ' X ', im.size[1], ' image_file_size :', im_size)
# im.save(filename+'.'+mod_img.lower(), format=mod_img, quality=100)
im = Image.open('Immagine_6.tif')
x, y = im.size
typ_img = im.mode
mod_img = im.format
print('image size : ', x, ' X ', y, ' ', ' image_type :',
typ_img, ' image_format :', mod_img)
SaveWithTargetFileSize(im, "result_5", 558999)
# SaveWithTargetFileSize(im, "result_5", 568000)
# SaveWithTargetFileSize(im, "result_4", 558999000)
print('\nTIME : ', datetime.now() - begin)
使用此图像设置图像:图像大小:520 X 409 image_type:RGBA image_format:TIFF 它花费的时间不到第一次保留打印线的时间的一半
推荐阅读
- highcharts - 如何使 Highcharts 中饼图的连接器(连接数据标签的线)看起来是直线而不是弯曲的?
- angular - Azure 应用服务中的 Dotnet 发布错误 - 错误:找不到模块“@angular/core”
- babeljs - 如何在非nodejs环境/没有npm的情况下配置babel?
- unix - 仅从 csv 文件中获取重复项
- python - CNN 多输入,检查模型输入时出错:预计会看到 2 个数组,但得到了以下 1 个数组的列表:
- sql - 与 Oracle 部分匹配
- ios - 如何使可点击的 NSAttributedString 移动到另一个 ViewController Swift
- android - 如何以编程方式按 dialPad btn?
- java - 如何在 java CollectionUtils.class addAll 方法中分析“更改 |= collection.add(iterator.next()”?
- java - 删除数组元素后如何将元素向左移动?