是否可以通过字节而不是宽度和高度来调整图像的大小?

时间:2018-10-23 02:36:37

标签: python-3.x reduce image-size

我想将图像缩小到较小的尺寸,以便于共享和更快地上传。

但是我意识到,如果仅通过减小其h&w来减小尺寸,它并不能真正解决问题,因为较大的图像文件可能具有较小的h&w,而较小的图像文件可能具有较大的h&w,因此请减小图像尺寸减小高度和重量可能并不总是按照我想要的方式缩小尺寸。

所以现在我有了这个字节大小:

import os
os.stat('myImage.jpg').st_size

是否可以通过减少字节来减小图像大小?并保持其比例?

2 个答案:

答案 0 :(得分:1)

这是我用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
)

编辑:

“内存中”是指在循环中将saveimg bufferBytesIO时,它将保存到io.BytesIO对象中磁盘上但内存中的文件。然后,从该对象中,我可以确定结果文件的大小(即该数据缓冲区的长度),而无需实际将其保存到文件中。最后,也许这就是您期望的那样,但是由于缺乏对Python img_target_filename的了解,我已经看到太多代码浪费了将性能保存到磁盘上的性能。

仅将最终结果保存到文件中-这就是您想要的位置。尝试使用comp = {'Bajaj Auto Ltd.':"Bajaj Auto Ltd., Bajaj Auto Ltd, Bajaj Auto, Bajaj Auto's, Bajaj Auto Limited"} comp_name='Bajaj Auto Ltd.' def findcname(comp_name,data,comp): comp=comp comp_name=comp[comp_name] #data=data[data.Head.str.contains("|".join(list(map(lambda x:x.strip(), #(comp_name.split(','))))),case=False) | #data.Content.str.contains("|".join(list(map(lambda x:x.strip(), #(comp_name.split(','))))),case=False)] data['Company']=list(comp.keys())list(comp.values()).index(comp[comp_name]) return data findcname(comp_name,data,comp) > Output: > > KeyError Traceback (most recent call last) > <ipython-input-122-37eb04bc7686> in <module>() > ----> 1 findcname(comp_name,data,comp) > > <ipython-input-121-29a90c8a1238> in findcname(comp_name, data, comp) #> 3 comp_name=comp[comp_name] #> 4 data=data[data.Head.str.contains("|".join(list(map(lambda # x:x.strip(),(comp_name.split(','))))),case=False) | # data.Content.str.contains("|".join(list(map(lambda # x:x.strip(),(comp_name.split(','))))),case=False)] > ----> 5 data['Company']=list(comp.keys())list(comp.values()).index(comp[comp_name])] > 6 return data > > KeyError: "Bajaj Auto Ltd., Bajaj Auto Ltd, Bajaj Auto, Bajaj Auto's, Bajaj Auto Limited" 的绝对文件名。

答案 1 :(得分:0)

碰巧我的一个朋友需要调整/调整个人图像的大小,并且该图像最大为40KB。考虑到磁盘的大小,我编写了以下代码来缩小/重新缩放图像。我假设40KB = 40000Bytes,虽然不准确,但可以派上用场

from skimage.io import imread, imshow
from skimage.transform import rescale, resize, downscale_local_mean
from skimage.io import imsave
import matplotlib.pyplot as plt
import os
import numpy as np

img = imread('original.jpg')
target_size = 40000
size = os.path.getsize('original.jpg')
factor = 0.9
while(size>=40000):
    image_rescaled = rescale(img, factor, anti_aliasing=False)
    imsave('new.jpg', image_rescaled)
    print('factor {} image of size {}'.format(factor,size))
    factor = factor - 0.05
    size = os.path.getsize('new.jpg')

end_size = os.path.getsize('new.jpg')
print(end_size)

希望有帮助!!!! 您可以在GitHub上以LeninGF的身份关注我