缩小尺寸(设置最大宽度和高度)

时间:2018-05-29 12:44:31

标签: python image math scale dimension

我正在编写一个脚本来处理一堆高分辨率图像。这些图像的尺寸从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有内置的图像缩放方法(resizethumbnail),但我会做进一步的修改(改变宽高比,设置透明像素和空白区域)白色等),所以我需要手动进行计算。

2 个答案:

答案 0 :(得分:1)

是的,进行一次比较就足够了(也可以在变量中保存Max_W * HgtMax_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

答案 1 :(得分:1)

首先,根据您可以编写一个简单的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