首页 > 解决方案 > 使用 PIL python 根据文件大小计算图像分辨率

问题描述

我想使用基于所需文件大小的resize()方法调整图像大小。PIL例如,我有一个文件大小为 14.1 MB、宽 x 高为3456 x 5184. 如果所需的文件大小为2 MB ,它的分辨率是多少?我自己尝试了一些计算,比如使用这个公式image_size = (width * height * bit_depth + headers) / 8加上图像当前状态的纵横比,但它没有像我预期的那样工作。

目标:

找到所需的高度或宽度

已知

  1. 所需文件大小
  2. 当前文件大小
  3. 当前分辨率(宽 x 高)

标签: pythonimage-processingpython-imaging-library

解决方案


从这里复制 如何将 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 它花费的时间不到第一次保留打印线的时间的一半


推荐阅读