按比例缩小尺寸(设置最大宽度和高度)
Scale down a dimension (set max width and height)
我正在编写一个脚本来处理一堆高分辨率图像。这些图像的尺寸从 1000 到 5000 像素不等。为了让它们为网络(上传)做好准备,我需要缩小它们。
我对缩小(打开图像、缩放、保存等)的实现不感兴趣。我对新缩小尺寸的计算很感兴趣。
假设我有一张尺寸为 800x2000 像素的图像,并且我已将 2400x1200 设置为最大尺寸。图片的缩小尺寸应为 480x1200 像素。图片尺寸不能超过最大尺寸。
如何计算?
在脑海中形成问题的同时,我也在进行实验,并提出了以下算法:
def scale(dim, max_dim):
new_dim = {"w" : 0, "h" : 0}
# no change if dim is lower than given max_dim
if dim["w"] <= max_dim["w"] and dim["h"] <= max_dim["h"]:
return dim
ratio = 0
# detect which side overflows
if dim["w"] > max_dim["w"]:
ratio = max_dim["w"] / dim["w"]
else:
ratio = max_dim["h"] / dim["h"]
# scale according to overflowing side
new_dim["w"] = dim["w"] * ratio
new_dim["h"] = dim["h"] * ratio
# now the other side might overflow after scaling
# check if that's true and scale again
if new_dim["h"] > max_dim["h"]:
ratio = max_dim["h"] / dim["h"]
if new_dim["w"] > max_dim["w"]:
ratio = max_dim["w"] / dim["w"]
new_dim["w"] = math.floor(dim["w"] * ratio)
new_dim["h"] = math.floor(dim["h"] * ratio)
return new_dim
这似乎产生了正确的结果,但我不确定这是否是一种更可取的方法。例如,我正在做两项检查;首先检测溢出,其次,纠正由第一个秤引起的(可能的)第二次溢出。我可能在做多余的计算,所以我也需要这方面的建议。
测试用例:
max_dim = {"w" : 2400, "h" : 1200}
dim1 = {"w" : 800, "h" : 1000}
dim2 = {"w" : 800, "h" : 2000}
dim3 = {"w" : 800, "h" : 2500}
dim4 = {"w" : 2500, "h" : 800}
dim5 = {"w" : 2500, "h" : 3000}
dim6 = {"w" : 1800, "h" : 1500}
dim7 = {"w" : 2500, "h" : 1000}
dim8 = {"w" : 2500, "h" : 1400}
dim9 = {"w" : 2500, "h" : 2000}
print(scale(dim1, max_dim))
print(scale(dim2, max_dim))
print(scale(dim3, max_dim))
print(scale(dim4, max_dim))
print(scale(dim5, max_dim))
print(scale(dim6, max_dim))
print(scale(dim7, max_dim))
print(scale(dim8, max_dim))
print(scale(dim9, max_dim))
输出:
{'w': 800, 'h': 1000}
{'w': 480, 'h': 1200}
{'w': 384, 'h': 1200}
{'w': 2400, 'h': 768}
{'w': 1000, 'h': 1200}
{'w': 1440, 'h': 1200}
{'w': 2400, 'h': 960}
{'w': 2142, 'h': 1200}
{'w': 1500, 'h': 1200}
这些输出是正确的。输入尺寸的宽度和高度均未超出最大尺寸。
此外,我知道 Python 有内置的图像缩放方法(resize
和 thumbnail
),但我会做进一步的修改(更改宽高比,设置透明像素和空白区域为白色等),所以我需要手动计算。
是的,进行一次比较就足够了(也可以将Max_W * Hgt
和Max_H * Wdt
保存在变量中以节省一次矿石乘法:))
if (Max_W * Hgt < Max_H * Wdt):
W_Result = Max_W
H_Result = Hgt * Max_W / Wdt
else:
W_Result = Wdt * Max_H / Hgt
H_Result = Max_H
首先得到宽高比,根据这个可以写一个简单的if子句。
def resize(width, height):
pref_width = 2400
pref_height = 1200
pref_ratio = pref_width/pref_height
ratio = width/height
如果图片太宽,图片比例会大于首选比例,我们可以根据宽度计算一切,以避免溢出:
if ratio > pref_ratio:
return pref_width, height * (pref_width / width)
如果图片高度太大,我们将首选高度设置为新高度,并相应地计算宽度。我们不需要考虑大小相同的可调整大小的图像,因为公式不关心并且无论如何都会给我们正确的答案。
else:
return width * (pref_height / height), pref_height
我正在编写一个脚本来处理一堆高分辨率图像。这些图像的尺寸从 1000 到 5000 像素不等。为了让它们为网络(上传)做好准备,我需要缩小它们。
我对缩小(打开图像、缩放、保存等)的实现不感兴趣。我对新缩小尺寸的计算很感兴趣。
假设我有一张尺寸为 800x2000 像素的图像,并且我已将 2400x1200 设置为最大尺寸。图片的缩小尺寸应为 480x1200 像素。图片尺寸不能超过最大尺寸。
如何计算?
在脑海中形成问题的同时,我也在进行实验,并提出了以下算法:
def scale(dim, max_dim):
new_dim = {"w" : 0, "h" : 0}
# no change if dim is lower than given max_dim
if dim["w"] <= max_dim["w"] and dim["h"] <= max_dim["h"]:
return dim
ratio = 0
# detect which side overflows
if dim["w"] > max_dim["w"]:
ratio = max_dim["w"] / dim["w"]
else:
ratio = max_dim["h"] / dim["h"]
# scale according to overflowing side
new_dim["w"] = dim["w"] * ratio
new_dim["h"] = dim["h"] * ratio
# now the other side might overflow after scaling
# check if that's true and scale again
if new_dim["h"] > max_dim["h"]:
ratio = max_dim["h"] / dim["h"]
if new_dim["w"] > max_dim["w"]:
ratio = max_dim["w"] / dim["w"]
new_dim["w"] = math.floor(dim["w"] * ratio)
new_dim["h"] = math.floor(dim["h"] * ratio)
return new_dim
这似乎产生了正确的结果,但我不确定这是否是一种更可取的方法。例如,我正在做两项检查;首先检测溢出,其次,纠正由第一个秤引起的(可能的)第二次溢出。我可能在做多余的计算,所以我也需要这方面的建议。
测试用例:
max_dim = {"w" : 2400, "h" : 1200}
dim1 = {"w" : 800, "h" : 1000}
dim2 = {"w" : 800, "h" : 2000}
dim3 = {"w" : 800, "h" : 2500}
dim4 = {"w" : 2500, "h" : 800}
dim5 = {"w" : 2500, "h" : 3000}
dim6 = {"w" : 1800, "h" : 1500}
dim7 = {"w" : 2500, "h" : 1000}
dim8 = {"w" : 2500, "h" : 1400}
dim9 = {"w" : 2500, "h" : 2000}
print(scale(dim1, max_dim))
print(scale(dim2, max_dim))
print(scale(dim3, max_dim))
print(scale(dim4, max_dim))
print(scale(dim5, max_dim))
print(scale(dim6, max_dim))
print(scale(dim7, max_dim))
print(scale(dim8, max_dim))
print(scale(dim9, max_dim))
输出:
{'w': 800, 'h': 1000}
{'w': 480, 'h': 1200}
{'w': 384, 'h': 1200}
{'w': 2400, 'h': 768}
{'w': 1000, 'h': 1200}
{'w': 1440, 'h': 1200}
{'w': 2400, 'h': 960}
{'w': 2142, 'h': 1200}
{'w': 1500, 'h': 1200}
这些输出是正确的。输入尺寸的宽度和高度均未超出最大尺寸。
此外,我知道 Python 有内置的图像缩放方法(resize
和 thumbnail
),但我会做进一步的修改(更改宽高比,设置透明像素和空白区域为白色等),所以我需要手动计算。
是的,进行一次比较就足够了(也可以将Max_W * Hgt
和Max_H * Wdt
保存在变量中以节省一次矿石乘法:))
if (Max_W * Hgt < Max_H * Wdt):
W_Result = Max_W
H_Result = Hgt * Max_W / Wdt
else:
W_Result = Wdt * Max_H / Hgt
H_Result = Max_H
首先得到宽高比,根据这个可以写一个简单的if子句。
def resize(width, height):
pref_width = 2400
pref_height = 1200
pref_ratio = pref_width/pref_height
ratio = width/height
如果图片太宽,图片比例会大于首选比例,我们可以根据宽度计算一切,以避免溢出:
if ratio > pref_ratio:
return pref_width, height * (pref_width / width)
如果图片高度太大,我们将首选高度设置为新高度,并相应地计算宽度。我们不需要考虑大小相同的可调整大小的图像,因为公式不关心并且无论如何都会给我们正确的答案。
else:
return width * (pref_height / height), pref_height