为什么将图像调整为50%(以像素为单位)不会将其大小降低50%的KB(PIL-枕头)?
tl; dr:是否可以将KB中的图像大小操纵到所需的大小?
有4种获取图像大小的方法,例如在我的另一个问题中被马克回答,我想知道大小的任何关系是否与像素的数量有任何关系?
(7460,24300,1),(2549,6075,2),(1303,2700,3),(808,1518,4),(552,972,5)
这些是> (os_stat_size,numpy_array_size,image_factor)
image_factor ==已调整图像大小的因素 如您所见,调整因子与KB中的大小不成比例。
下面给出的代码非常适合调整大小。我正在尝试操纵KBS 而不是像素的图像大小。我进行了一个实验,以将整体图像大小降低50%。这个想法是给定深度,应该是恒定的,像素应以线性方式对应于图像大小(思考元数据保持恒定),
我进行了实验,并且没有使用JPEG
获得结果。因此,我认为扩展程序可能会有一些问题“>第二个答案说:
JPEG文件的深度与GIF或PNG文件的方式相同。用于创建JPEG数据的转换使解压缩的连续颜色谱。
因此,我尝试了png
的同一实验,并且是相同的。以下是我对两个版本进行的实验,并在jpeg
和png
helper code and Imports 之间进行注释交换:工作
from PIL import Image
import numpy as np
import requests
from io import BytesIO
from os import stat
import os
import sys
def resize(image:Image, current_size:tuple, new_width_height:float)->Image:
'''
Resize and return Given Image
args:
image: Image object
current_size: Image size as (width, height)
new_width_height = Reshaped image's width and height. If integer is given, it'll keep the aspect ratio as it is by shrinking the Bigger dimension (width or height) to the max of new_width_height and then shring the smaller dimension accordingly
'''
fixed_size = True if isinstance(new_width_height, int) else False
w, h = current_size
if fixed_size:
if h > w:
fixed_height = new_width_height
height_percent = (fixed_height / float(h))
width_size = int((float(w) * float(height_percent)))
image = image.resize((width_size, fixed_height), Image.Resampling.LANCZOS) # # Try Image.NEAREST
else:
fixed_width = new_width_height
width_percent = (fixed_width / float(w))
height_size = int((float(h) * float(width_percent)))
image = image.resize((fixed_width, height_size), Image.Resampling.LANCZOS)
else:
w, h = int(new_width_height[0]), int(new_width_height[1])
image = image.resize((w,h), Image.Resampling.LANCZOS)
return image
实验:
- 实际图像统计:
url = "https://wallpaperaccess.com/full/508751.jpg"
buffer = BytesIO(requests.get(url).content)
size_buffer = buffer.getbuffer().nbytes//1024
image = Image.open(buffer)
size_uncompressed = len(image.tobytes()) // 1024
# image.save('./wallpaper.jpeg', format = 'jpeg', quality = 'keep', subsampling = False)
# size_os = os.stat('./wallpaper.jpeg').st_size // 1024
image.save('./wallpaper.PNG', format = 'PNG', quality = 'keep', subsampling = False)
size_os = os.stat('./wallpaper.PNG').st_size // 1024
numpy_size = sys.getsizeof(np.array(image)) // 1024 # same as len(image.tobytes())
print(image.size, image.format, image.mode, str(size_buffer)+' KB (buffer.getbuffer().nbytes//1024)', str(size_os)+' KB (os.stat().st_size // 1024)', str(size_uncompressed)+' KB (len(image.tobytes()) // 1024)', str(numpy_size)+' KB (sys.getsizeof(np.array(image)) // 1024)')
- 调整大小的图像统计:
image = resize(image, image.size, max(image.size)//2)
# image.format = "JPEG" # as it'll throw error when using quality='keep' with jpeg
image.format = "PNG"
size_uncompressed = len(image.tobytes()) // 1024
buffer = BytesIO()
# image.save(buffer, format="JPEG", format = 'jpeg', quality = 'keep', subsampling = False)
image.save(buffer, format="PNG")
size_buffer = buffer.getbuffer().nbytes//1024
# image.save('./resized_wallpaper.jpeg', format = 'jpeg', quality = 'keep', subsampling = False)
# size_os = os.stat('./resized_wallpaper.jpeg').st_size // 1024
image.save('./resized_wallpaper.PNG', format = 'PNG')
size_os = os.stat('./resized_wallpaper.PNG').st_size // 1024
numpy_size = sys.getsizeof(np.array(image)) // 1024
print(image.size, image.format, image.mode, str(size_buffer)+' KB (buffer.getbuffer().nbytes//1024)', str(size_os)+' KB (os.stat().st_size // 1024)', str(size_uncompressed)+' KB (len(image.tobytes()) // 1024)',str(numpy_size)+' KB (sys.getsizeof(np.array(image)) // 1024)')
它们实际上都不是线性的。是正常的还是我做错了什么?
Tl;DR: Is it possible to manipulate size of image in KB to the desired size?
There are 4 ways to get an image size as answered by Mark in my another question and I'm wondering if there's any relation of ANY of the size to the number of pixels?
(7460,24300,1),(2549,6075,2),(1303,2700,3),(808,1518,4), (552,972,5)
These are the (os_stat_size, numpy_array_size, image_factor)
image_factor == factor by which the image has been resized
As you can see the resizing factor is not proportional to the size in KB.
Code given below is working perfectly for resizing. I am experimenting on manipulating image size in KBs instead of pixels. I did an experiment to reduce the overall image size by 50%. The idea is that given any depth, it should be constant and the pixels should correspond to the image size in linear fashion (thinking metadata remains constant)
I did the experiment and did not get results with jpeg
. So I thought there might be some problem with the extension as I found this second answer saying :
Jpeg files don't have bit depth in the same manner as GIF or PNG files. The transform used to create the Jpeg data renders a continuous colour spectrum on decompression.
So I tried the same experiment with the PNG
and it was same. Below are my experiments with both the versions with commented out exchange between jpeg
and png
Helper code and imports: Working fine
from PIL import Image
import numpy as np
import requests
from io import BytesIO
from os import stat
import os
import sys
def resize(image:Image, current_size:tuple, new_width_height:float)->Image:
'''
Resize and return Given Image
args:
image: Image object
current_size: Image size as (width, height)
new_width_height = Reshaped image's width and height. If integer is given, it'll keep the aspect ratio as it is by shrinking the Bigger dimension (width or height) to the max of new_width_height and then shring the smaller dimension accordingly
'''
fixed_size = True if isinstance(new_width_height, int) else False
w, h = current_size
if fixed_size:
if h > w:
fixed_height = new_width_height
height_percent = (fixed_height / float(h))
width_size = int((float(w) * float(height_percent)))
image = image.resize((width_size, fixed_height), Image.Resampling.LANCZOS) # # Try Image.NEAREST
else:
fixed_width = new_width_height
width_percent = (fixed_width / float(w))
height_size = int((float(h) * float(width_percent)))
image = image.resize((fixed_width, height_size), Image.Resampling.LANCZOS)
else:
w, h = int(new_width_height[0]), int(new_width_height[1])
image = image.resize((w,h), Image.Resampling.LANCZOS)
return image
Experiment:
- Actual image stats:
url = "https://wallpaperaccess.com/full/508751.jpg"
buffer = BytesIO(requests.get(url).content)
size_buffer = buffer.getbuffer().nbytes//1024
image = Image.open(buffer)
size_uncompressed = len(image.tobytes()) // 1024
# image.save('./wallpaper.jpeg', format = 'jpeg', quality = 'keep', subsampling = False)
# size_os = os.stat('./wallpaper.jpeg').st_size // 1024
image.save('./wallpaper.PNG', format = 'PNG', quality = 'keep', subsampling = False)
size_os = os.stat('./wallpaper.PNG').st_size // 1024
numpy_size = sys.getsizeof(np.array(image)) // 1024 # same as len(image.tobytes())
print(image.size, image.format, image.mode, str(size_buffer)+' KB (buffer.getbuffer().nbytes//1024)', str(size_os)+' KB (os.stat().st_size // 1024)', str(size_uncompressed)+' KB (len(image.tobytes()) // 1024)', str(numpy_size)+' KB (sys.getsizeof(np.array(image)) // 1024)')
- Resized image stats:
image = resize(image, image.size, max(image.size)//2)
# image.format = "JPEG" # as it'll throw error when using quality='keep' with jpeg
image.format = "PNG"
size_uncompressed = len(image.tobytes()) // 1024
buffer = BytesIO()
# image.save(buffer, format="JPEG", format = 'jpeg', quality = 'keep', subsampling = False)
image.save(buffer, format="PNG")
size_buffer = buffer.getbuffer().nbytes//1024
# image.save('./resized_wallpaper.jpeg', format = 'jpeg', quality = 'keep', subsampling = False)
# size_os = os.stat('./resized_wallpaper.jpeg').st_size // 1024
image.save('./resized_wallpaper.PNG', format = 'PNG')
size_os = os.stat('./resized_wallpaper.PNG').st_size // 1024
numpy_size = sys.getsizeof(np.array(image)) // 1024
print(image.size, image.format, image.mode, str(size_buffer)+' KB (buffer.getbuffer().nbytes//1024)', str(size_os)+' KB (os.stat().st_size // 1024)', str(size_uncompressed)+' KB (len(image.tobytes()) // 1024)',str(numpy_size)+' KB (sys.getsizeof(np.array(image)) // 1024)')
None of them are actually linear. Is it normal or I'm doing something wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论