Python 3.x 是否可以通过字节而不是宽度和高度来调整图像的大小?
我想将图像缩小到更小的尺寸,以便于共享和更快地上传 但是我意识到,如果我只是通过h&w来缩小尺寸,这并不能真正起作用,因为一个大的图像文件可能有一个较小的h&w,而小的图像文件可能有一个较大的h&w,所以通过降低高度和重量来缩小图像尺寸可能并不总是按照我想要的方式缩小尺寸 现在,我使用以下公式得到了字节大小:Python 3.x 是否可以通过字节而不是宽度和高度来调整图像的大小?,python-3.x,reduce,image-size,Python 3.x,Reduce,Image Size,我想将图像缩小到更小的尺寸,以便于共享和更快地上传 但是我意识到,如果我只是通过h&w来缩小尺寸,这并不能真正起作用,因为一个大的图像文件可能有一个较小的h&w,而小的图像文件可能有一个较大的h&w,所以通过降低高度和重量来缩小图像尺寸可能并不总是按照我想要的方式缩小尺寸 现在,我使用以下公式得到了字节大小: import os os.stat('myImage.jpg').st_size 是否可以通过减少字节来减少图像大小?保持它的比例 这是我用PIL编写的一个函数。它对图像进行迭代调整大小
import os
os.stat('myImage.jpg').st_size
是否可以通过减少字节来减少图像大小?保持它的比例 这是我用PIL编写的一个函数。它对图像进行迭代调整大小和jpeg压缩,然后查看生成的文件大小并将其与目标值进行比较,根据大小偏差比猜测下一个最佳宽度/高度组合(基本上是某种P控制器) 它利用io.BytesIO来完成内存中所有的大小调整工作,因此实际上只有一次对磁盘上文件的读写访问。此外,使用这种bruteforce方法,您可以将目标文件格式更改为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
)
编辑:
在内存中,我的意思是当它将img保存到循环中的缓冲区时,它将它保存到一个BytesIO对象,它不是磁盘上的文件,而是内存中的文件。从这个对象,我可以确定结果文件的大小,也就是数据缓冲区的长度,而不需要将它保存到文件中。最后,也许这正是您所期望的工作方式,但我看到过太多的代码由于缺乏对Python的io.BytesIO的了解而浪费了在磁盘上保存文件的性能
只有最终结果才会保存到文件中,而这正是您想要的ofc。尝试使用绝对文件名作为img\u target\u文件名。这是我用PIL编写的函数。它对图像进行迭代调整大小和jpeg压缩,然后查看生成的文件大小并将其与目标值进行比较,根据大小偏差比猜测下一个最佳宽度/高度组合(基本上是某种P控制器) 它利用io.BytesIO来完成内存中所有的大小调整工作,因此实际上只有一次对磁盘上文件的读写访问。此外,使用这种bruteforce方法,您可以将目标文件格式更改为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
)
编辑:
在内存中,我的意思是当它将img保存到循环中的缓冲区时,它将它保存到一个BytesIO对象,它不是磁盘上的文件,而是内存中的文件。从这个对象,我可以确定结果文件的大小,也就是数据缓冲区的长度,而不需要将它保存到文件中。最后,也许这正是您所期望的工作方式,但我看到过太多的代码由于缺乏对Python的io.BytesIO的了解而浪费了在磁盘上保存文件的性能
只有最终结果才会保存到文件中,而这正是您想要的ofc。尝试使用绝对文件名作为img\u target\u文件名。碰巧我的一个朋友需要调整/重新缩放个人图像,并且要求图像最大为40KB。考虑到磁盘上的大小,我编写了以下代码来缩小/重新缩放图像。我假设40KB=40000字节,这并不准确,但它可以派上用场
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上关注我,因为我的一个朋友需要调整/重新缩放个人图像,并且要求图像最大为40KB。考虑到磁盘上的大小,我编写了以下代码来缩小/重新缩放图像。我假设40KB=40000字节,这并不准确,但它可以派上用场
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一个有用的谷歌搜索短语可能是jpg压缩。你可以使用固定的宽度,然后用目标宽度乘以原始图像的纵横比来计算相应的高度。@Jeronimo,谢谢你的建议,但我不想用宽度来缩小尺寸,因为宽度和高度与实际的图像大小并不相关。否则,我可以使用:。resize500,int500/floatw*h,Image。ANTIALIAS@usr2564301,所以基本上,我不想通过控制图像的高度和重量来减小图像的大小,我只想通过减小图像的大小字节来减小图像的大小。一个有用的谷歌搜索短语可能是jpg压缩。你可以始终使用固定宽度,然后用目标宽度乘以原始图像的纵横比来计算相应的高度。@Jeronimo,谢谢你的建议,但我不想用宽度来缩小尺寸,因为宽度和高度与实际图像的大小并不相关。否则,我可以使用:。resize500,int500/floatw*h,Image。ANTIALIAS@usr2564301,所以基本上,我不想通过操纵图像的高度和重量来减小图像的大小,我只想简单地减小图像的大小
我花了好几天的时间试图找到一种方法,将图像大小减少一个给定的字节,而您的代码正是我所需要的,并且可以正常工作。让我花点时间来理解这段代码!谢谢,伙计。很高兴能帮上忙——如果你能把它标记为正确答案那就太好了;有了你的代码,我甚至可以用不同的格式保存PNG到jpg,这真是太棒了!由于我是Python新手,请您解释一下>调整内存中的内容是什么意思?这是否意味着我无法将修改后的图像保存到另一个目录中?在编辑中回答。我还有一个问题,一些图像无法正确缩小其大小,原因是使用BytesIO时,一些图像的大小存在显著差异,而使用os.stat'xxx.jpg'。st_size将始终返回实际大小。因此,使用这种方法,一些图像无法按需要缩小,这是为什么?我花了几天时间试图找到一种方法,将图像大小缩小一个给定的字节,而您的代码正是我所需要的,并且它可以工作。让我花点时间来理解这段代码!谢谢,伙计。很高兴能帮上忙——如果你能把它标记为正确答案那就太好了;有了你的代码,我甚至可以用不同的格式保存PNG到jpg,这真是太棒了!由于我是Python新手,请您解释一下>调整内存中的内容是什么意思?这是否意味着我无法将修改后的图像保存到另一个目录中?在编辑中回答。我还有一个问题,一些图像无法正确缩小其大小,原因是使用BytesIO时,一些图像的大小存在显著差异,而使用os.stat'xxx.jpg'。st_size将始终返回实际大小。因此,使用这种方法,一些图像无法按需要缩小,这是为什么?