我计划将它与 JavaScript 一起使用来裁剪图像以适合整个窗口。
编辑:我将使用仅接受以下格式的纵横比的 3rd 方组件:4:3
, 16:9
。
~12岁编辑:这种问题挺有意思的!这里有东西吧?绝对地!
我计划将它与 JavaScript 一起使用来裁剪图像以适合整个窗口。
编辑:我将使用仅接受以下格式的纵横比的 3rd 方组件:4:3
, 16:9
。
~12岁编辑:这种问题挺有意思的!这里有东西吧?绝对地!
我猜你正在寻找一个可用的纵横比integer:integer
解决方案,16:9
而不是float:1
像1.77778:1
.
如果是这样,您需要做的是找到最大公约数 (GCD) 并将两个值除以它。GCD 是将两个数字均分的最高数字。所以 6 和 10 的 GCD 是 2,44 和 99 的 GCD 是 11。
例如,1024x768 显示器的 GCD 为 256。将两个值除以 4x3 或 4:3。
一个(递归)GCD 算法:
function gcd (a,b):
if b == 0:
return a
return gcd (b, a mod b)
在 C 中:
static int gcd (int a, int b) {
return (b == 0) ? a : gcd (b, a%b);
}
int main(void) {
printf ("gcd(1024,768) = %d\n",gcd(1024,768));
}
这里有一些完整的 HTML/Javascript,它展示了一种检测屏幕尺寸并从中计算纵横比的方法。这适用于 FF3,我不确定其他浏览器对screen.width
和 的支持screen.height
。
<html><body>
<script type="text/javascript">
function gcd (a, b) {
return (b == 0) ? a : gcd (b, a%b);
}
var w = screen.width;
var h = screen.height;
var r = gcd (w, h);
document.write ("<pre>");
document.write ("Dimensions = ", w, " x ", h, "<br>");
document.write ("Gcd = ", r, "<br>");
document.write ("Aspect = ", w/r, ":", h/r);
document.write ("</pre>");
</script>
</body></html>
它输出(在我奇怪的宽屏显示器上):
Dimensions = 1680 x 1050
Gcd = 210
Aspect = 8:5
我测试过的其他人:
Dimensions = 1280 x 1024
Gcd = 256
Aspect = 5:4
Dimensions = 1152 x 960
Gcd = 192
Aspect = 6:5
Dimensions = 1280 x 960
Gcd = 320
Aspect = 4:3
Dimensions = 1920 x 1080
Gcd = 120
Aspect = 16:9
我希望我家里有最后一个,但不幸的是,它是一台工作机器。
如果您发现图形调整工具不支持纵横比,您会怎么做是另一回事。我怀疑最好的办法是添加信箱线(就像您在旧电视上观看宽屏电影时在其顶部和底部看到的那些)。我会将它们添加到顶部/底部或侧面(以产生最少的信箱线数为准),直到图像满足要求。
您可能需要考虑的一件事是从 16:9 更改为 5:4 的图片质量 - 我仍然记得在引入信箱之前,我年轻时曾在电视上观看过的令人难以置信的高大苗条的牛仔。您最好为每个纵横比设置一张不同的图像,并在发送之前根据实际屏幕尺寸调整正确的图像。
aspectRatio = width / height
如果这就是你所追求的。然后,您可以将其乘以目标空间的维度之一以找出另一个维度(保持比率),例如
widthT = heightT * aspectRatio
heightT = widthT / aspectRatio
paxdiablo 的回答很好,但是有很多常见的分辨率在给定方向上只有几个或多或少的像素,而最大公约数方法给它们带来了可怕的结果。
以表现良好的 1360x765 分辨率为例,它使用 gcd 方法提供了一个很好的 16:9 比例。根据 Steam 的说法,这个分辨率只有 0.01% 的用户使用,而 1366x768 的用户使用率高达 18.9%。让我们看看使用 gcd 方法会得到什么:
1360x765 - 16:9 (0.01%)
1360x768 - 85:48 (2.41%)
1366x768 - 683:384 (18.9%)
我们想把 683:384 的比例四舍五入到最接近的 16:9 比例。
我编写了一个 python 脚本,它解析带有来自 Steam 硬件调查页面的粘贴数字的文本文件,并打印所有分辨率和最接近的已知比率,以及每个比率的普遍性(这是我开始时的目标):
# Contents pasted from store.steampowered.com/hwsurvey, section 'Primary Display Resolution'
steam_file = './steam.txt'
# Taken from http://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Vector_Video_Standards4.svg/750px-Vector_Video_Standards4.svg.png
accepted_ratios = ['5:4', '4:3', '3:2', '8:5', '5:3', '16:9', '17:9']
#-------------------------------------------------------
def gcd(a, b):
if b == 0: return a
return gcd (b, a % b)
#-------------------------------------------------------
class ResData:
#-------------------------------------------------------
# Expected format: 1024 x 768 4.37% -0.21% (w x h prevalence% change%)
def __init__(self, steam_line):
tokens = steam_line.split(' ')
self.width = int(tokens[0])
self.height = int(tokens[2])
self.prevalence = float(tokens[3].replace('%', ''))
# This part based on pixdiablo's gcd answer - http://stackoverflow.com/a/1186465/828681
common = gcd(self.width, self.height)
self.ratio = str(self.width / common) + ':' + str(self.height / common)
self.ratio_error = 0
# Special case: ratio is not well behaved
if not self.ratio in accepted_ratios:
lesser_error = 999
lesser_index = -1
my_ratio_normalized = float(self.width) / float(self.height)
# Check how far from each known aspect this resolution is, and take one with the smaller error
for i in range(len(accepted_ratios)):
ratio = accepted_ratios[i].split(':')
w = float(ratio[0])
h = float(ratio[1])
known_ratio_normalized = w / h
distance = abs(my_ratio_normalized - known_ratio_normalized)
if (distance < lesser_error):
lesser_index = i
lesser_error = distance
self.ratio_error = distance
self.ratio = accepted_ratios[lesser_index]
#-------------------------------------------------------
def __str__(self):
descr = str(self.width) + 'x' + str(self.height) + ' - ' + self.ratio + ' - ' + str(self.prevalence) + '%'
if self.ratio_error > 0:
descr += ' error: %.2f' % (self.ratio_error * 100) + '%'
return descr
#-------------------------------------------------------
# Returns a list of ResData
def parse_steam_file(steam_file):
result = []
for line in file(steam_file):
result.append(ResData(line))
return result
#-------------------------------------------------------
ratios_prevalence = {}
data = parse_steam_file(steam_file)
print('Known Steam resolutions:')
for res in data:
print(res)
acc_prevalence = ratios_prevalence[res.ratio] if (res.ratio in ratios_prevalence) else 0
ratios_prevalence[res.ratio] = acc_prevalence + res.prevalence
# Hack to fix 8:5, more known as 16:10
ratios_prevalence['16:10'] = ratios_prevalence['8:5']
del ratios_prevalence['8:5']
print('\nSteam screen ratio prevalences:')
sorted_ratios = sorted(ratios_prevalence.items(), key=lambda x: x[1], reverse=True)
for value in sorted_ratios:
print(value[0] + ' -> ' + str(value[1]) + '%')
出于好奇,以下是 Steam 用户中屏幕比例的流行情况(截至 2012 年 10 月):
16:9 -> 58.9%
16:10 -> 24.0%
5:4 -> 9.57%
4:3 -> 6.38%
5:3 -> 0.84%
17:9 -> 0.11%
我猜您想决定 4:3 和 16:9 中的哪一个最合适。
function getAspectRatio(width, height) {
var ratio = width / height;
return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';
}
James Farey 的最佳有理近似算法具有可调整的模糊程度,从最初用 Python 编写的纵横比计算代码移植到 Javascript 。
该方法采用浮点数 ( width/height
) 和分数分子/分母的上限。
在下面的示例中,我设置了上限,50
因为我需要将1035x582
(1.77835051546) 视为16:9
(1.77777777778) 而不是345:194
您使用gcd
其他答案中列出的普通算法获得的上限。
function aspect_ratio(val, lim) {
var lower = [0, 1];
var upper = [1, 0];
while (true) {
var mediant = [lower[0] + upper[0], lower[1] + upper[1]];
if (val * mediant[1] > mediant[0]) {
if (lim < mediant[1]) {
return upper;
}
lower = mediant;
} else if (val * mediant[1] == mediant[0]) {
if (lim >= mediant[1]) {
return mediant;
}
if (lower[1] < upper[1]) {
return lower;
}
return upper;
} else {
if (lim < mediant[1]) {
return lower;
}
upper = mediant;
}
}
}
console.log(aspect_ratio(801/600, 50));
console.log(aspect_ratio(1035/582, 50));
console.log(aspect_ratio(2560/1441, 50));