计算长宽比的算法是什么?我需要一个输出:4:3,16:9。

时间:2022-08-27 10:46:08

I plan to use it with javascript to crop an image to fit the entire window.

我计划使用javascript来裁剪图像以适应整个窗口。

Edit: I'll be using a 3rd part component that only accepts the aspect ratio in the format like: 4:3, 16:9

编辑:我将使用第三部分的组件,它只接受宽比的格式:4:3,16:9。

14 个解决方案

#1


158  

I gather you're looking for an usable aspect ratio integer:integer solution like 16:9 rather than a float:1 solution like 1.77778:1.

我收集您正在寻找一个可用的方面比率整数:整数解决方案,如16:9,而不是浮点数:1解决方案,如1.77778:1。

If so, what you need to do is find the greatest common divisor (GCD) and divide both values by that. The GCD is the highest number that evenly divides both numbers. So the GCD for 6 and 10 is 2, the GCD for 44 and 99 is 11.

如果是的话,你需要做的是找到最大的公约数(GCD)并将两个值都除以它。GCD是将这两个数字平均分配的最高数字。6和10的GCD是2,44和99的GCD是11。

For example, a 1024x768 monitor has a GCD of 256. When you divide both values by that you get 4x3 or 4:3.

例如,一个1024x768监视器有一个256的GCD。当你把两个值都除以,得到4x3或4:3。

A (recursive) GCD algorithm:

(递归)GCD算法:

function gcd (a,b):
    if b == 0:
        return a
    return gcd (b, a mod b)

In C:

在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));
}

And here's some complete HTML/Javascript which shows one way to detect the screen size and calculate the aspect ratio from that. This works in FF3, I'm unsure what support other browsers have for screen.width and screen.height.

这是一些完整的HTML/Javascript,它显示了一种检测屏幕尺寸的方法,并计算出了它的纵横比。这在FF3中起作用,我不确定其他浏览器对屏幕有什么支持。宽度和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>

It outputs (on my weird wide-screen monitor):

它输出(在我奇怪的宽屏幕显示器上):

Dimensions = 1680 x 1050
Gcd        = 210
Aspect     = 8:5

Others that I tested this on:

我测试过的其他人:

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

I wish I had that last one at home but, no, it's a work machine unfortunately.

我希望我有最后一个在家里,但是,不,这是一个工作机器很不幸。

What you do if you find out the aspect ratio is not supported by your graphic resize tool is another matter. I suspect the best bet there would be to add letter-boxing lines (like the ones you get at the top and bottom of your old TV when you're watching a wide-screen movie on it). I'd add them at the top/bottom or the sides (whichever one results in the least number of letter-boxing lines) until the image meets the requirements.

如果你发现图形调整工具不支持纵横比,你会做什么,这是另一回事。我猜想最好的办法就是添加一些字母的线条(就像你在看一部大屏幕电影时,你在旧电视的顶部和底部看到的那样)。我将它们添加到顶部/底部或两侧(无论哪一个结果都是最少量的字母-拳击线),直到图像符合要求为止。

One thing you may want to consider is the quality of a picture that's been changed from 16:9 to 5:4 - I still remember the incredibly tall, thin cowboys I used to watch in my youth on television before letter-boxing was introduced. You may be better off having one different image per aspect ratio and just resize the correct one for the actual screen dimensions before sending it down the wire.

你可能需要考虑的一件事是照片的质量从16:9到5:4——我还记得在我年轻的时候在电视前看电视前,我在电视上看到的那些身材高大、身材瘦小的牛仔。你最好有一个不同的图像,每个纵横比,在发送它之前,只调整正确的屏幕尺寸大小。

#2


33  

aspectRatio = width / height

if that is what you're after. You can then multiply it by one of the dimensions of the target space to find out the other (that maintains the ratio) e.g.

如果这就是你想要的。然后你可以把它乘以目标空间的一个维度来找出另一个(保持比率)。

widthT = heightT * aspectRatio
heightT = widthT / aspectRatio

#3


12  

paxdiablo's answer is great, but there are a lot of common resolutions that have just a few more or less pixels in a given direction, and the greatest common divisor approach gives horrible results to them.

paxdiablo的答案很好,但是有很多常见的分辨率,在给定的方向上只有几个像素,而最大的公约数方法给它们带来了可怕的结果。

Take for example the well behaved resolution of 1360x765 which gives a nice 16:9 ratio using the gcd approach. According to Steam, this resolution is only used by 0.01% of it's users, while 1366x768 is used by a whoping 18.9%. Let's see what we get using the gcd approach:

以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%)

We'd want to round up that 683:384 ratio to the closest, 16:9 ratio.

我们想把这个比例提高到最接近的,16:9的比例。

I wrote a python script that parses a text file with pasted numbers from the Steam Hardware survey page, and prints all resolutions and closest known ratios, as well as the prevalence of each ratio (which was my goal when I started this):

我编写了一个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://*.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]) + '%')

For the curious, these are the prevalence of screen ratios amongst Steam users (as of October 2012):

对于好奇的人来说,这些都是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


10  

I guess you want to decide which of 4:3 and 16:9 is the best fit.

我猜你想确定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';
}

#5


1  

I think this does what you are asking for:

我认为这是你所要求的:

webdeveloper.com - decimal to fraction

webdeveloper.com -小数到分数。

Width/height gets you a decimal, converted to a fraction with ":" in place of '/' gives you a "ratio".

宽度/高度使你得到一个小数,转换成一个分数,以“:”代替“/”给你一个“比例”。

#6


1  

This algorithm in Python gets you part of the way there.

Python里的这个算法可以让你在这方面有所作为。


Tell me what happens if the windows is a funny size.

告诉我,如果窗户是一个有趣的尺寸会发生什么。

Maybe what you should have is a list of all acceptable ratios (to the 3rd party component). Then, find the closest match to your window and return that ratio from the list.

也许你应该得到一个所有可接受比率的列表(给第三方组件)。然后,找到与您的窗口最近的匹配,并将该比率从列表中返回。

#7


1  

As an alternative solution to the GCD searching, I suggest you to check against a set of standard values. You can find a list on Wikipedia.

作为GCD搜索的另一种解决方案,我建议您检查一组标准值。你可以在*上找到一个列表。

#8


1  

Im assuming your talking about video here, in which case you may also need to worry about pixel aspect ratio of the source video. For example.

我假设你在这里讨论视频,在这种情况下,你可能还需要担心源视频的像素宽比。为例。

PAL DV comes in a resolution of 720x576. Which would look like its 4:3. Now depending on the Pixel aspect ratio (PAR) the screen ratio can be either 4:3 or 16:9.

PAL DV的分辨率为720x576。看起来是4:3。现在根据像素宽比(PAR),屏幕比可以是4:3或16:9。

For more info have a look here http://en.wikipedia.org/wiki/Pixel_aspect_ratio

更多信息请访问http://en.wikipedia.org/wiki/Pixel_aspect_ratio。

You can get Square pixel Aspect Ratio, and a lot of web video is that, but you may want to watch out of the other cases.

你可以得到正方形像素宽比,很多网络视频都是这样,但是你可能想要注意其他的情况。

Hope this helps

希望这有助于

Mark

马克

#9


1  

Based on the other answers, here is how I got the numbers I needed in Python;

基于其他的答案,这里是我如何得到我在Python中需要的数字;

from decimal import Decimal

def gcd(a,b):
    if b == 0:
        return a
    return gcd(b, a%b)

def closest_aspect_ratio(width, height):
    g = gcd(width, height)
    x = Decimal(str(float(width)/float(g)))
    y = Decimal(str(float(height)/float(g)))
    dec = Decimal(str(x/y))
    return dict(x=x, y=y, dec=dec)

>>> closest_aspect_ratio(1024, 768)
{'y': Decimal('3.0'), 
 'x': Decimal('4.0'), 
 'dec': Decimal('1.333333333333333333333333333')}

#10


0  

Width / Height

?

吗?

#11


0  

I believe that aspect ratio is width divided by height.

我相信纵横比是宽度除以高度。

 r = w/h

#12


0  

bit of a strange way to do this but use the resolution as the aspect. E.G.

这是一种奇怪的方法,但使用分辨率作为方面。如

1024:768

1024:768

or you can try

或者你可以试一试

var w = screen.width;
var h = screen.height;
for(var i=1,asp=w/h;i<5000;i++){
  if(asp*i % 1==0){
    i=9999;
    document.write(asp*i,":",1*i);
  }
}

#13


0  

Here is my solution it is pretty straight forward since all I care about is not necessarily GCD or even accurate ratios: because then you get weird things like 345/113 which are not human comprehensible.

这是我的解决方案,这是非常直接的,因为我所关心的并不一定是GCD,甚至是精确的比例:因为你会得到一些奇怪的东西,比如345/113,这不是人类可以理解的。

I basically set acceptable landscape, or portrait ratios and their "value" as a float... I then compare my float version of the ratio to each and which ever has the lowest absolute value difference is the ratio closest to the item. That way when the user makes it 16:9 but then removes 10 pixels from the bottom it still counts as 16:9...

我基本上设置了可接受的景观,或肖像比例和它们的“价值”作为浮动…然后,我将我的浮点数与每一个的比率进行比较,它的绝对值最小的差值是最接近项的比率。这样当用户设置为16:9,然后从底部移除10个像素时,它仍然算作16:9……

accepted_ratios = {
    'landscape': (
        (u'5:4', 1.25),
        (u'4:3', 1.33333333333),
        (u'3:2', 1.5),
        (u'16:10', 1.6),
        (u'5:3', 1.66666666667),
        (u'16:9', 1.77777777778),
        (u'17:9', 1.88888888889),
        (u'21:9', 2.33333333333),
        (u'1:1', 1.0)
    ),
    'portrait': (
        (u'4:5', 0.8),
        (u'3:4', 0.75),
        (u'2:3', 0.66666666667),
        (u'10:16', 0.625),
        (u'3:5', 0.6),
        (u'9:16', 0.5625),
        (u'9:17', 0.5294117647),
        (u'9:21', 0.4285714286),
        (u'1:1', 1.0)
    ),
}


def find_closest_ratio(ratio):
    lowest_diff, best_std = 9999999999, '1:1'
    layout = 'portrait' if ratio < 1.0 else 'landscape'
    for pretty_str, std_ratio in accepted_ratios[layout]:
        diff = abs(std_ratio - ratio)
        if diff < lowest_diff:
            lowest_diff = diff
            best_std = pretty_str
    return best_std


def extract_ratio(width, height):
    try:
        divided = float(width)/float(height)
        if divided == 1.0:
            return '1:1'
        else:
            return find_closest_ratio(divided)
    except TypeError:
        return None

#14


0  

Here is a version of James Farey's best rational approximation algorithm with adjustable level of fuzziness ported to javascript from the aspect ratio calculation code originally written in python.

这里是James Farey的最佳合理近似算法的版本,该算法从最初用python编写的长宽比计算代码移植到javascript。

The method takes a float (width/height) and an upper limit for the fraction numerator/denominator.

该方法采用浮点(宽/高)和分数分子/分母的上限。

In the example below I am setting an upper limit of 50 because I need 1035x582 (1.77835051546) to be treated as 16:9 (1.77777777778) rather than 345:194 which you get with the plain gcd algorithm listed in other answers.

在下面的例子中,我设置了一个上限为50,因为我需要1035x582(1.77835051546),而不是345:194,而你使用的是在其他答案中列出的普通gcd算法。

<html>
<body>
<script type="text/javascript">
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;
        }
    }
}

document.write (aspect_ratio(800 / 600, 50) +"<br/>");
document.write (aspect_ratio(1035 / 582, 50) + "<br/>");
document.write (aspect_ratio(2560 / 1440, 50) + "<br/>");

    </script>
</body></html>

The result:

结果:

 4,3  // (1.33333333333) (800 x 600)
 16,9 // (1.77777777778) (2560.0 x 1440)
 16,9 // (1.77835051546) (1035.0 x 582)

#1


158  

I gather you're looking for an usable aspect ratio integer:integer solution like 16:9 rather than a float:1 solution like 1.77778:1.

我收集您正在寻找一个可用的方面比率整数:整数解决方案,如16:9,而不是浮点数:1解决方案,如1.77778:1。

If so, what you need to do is find the greatest common divisor (GCD) and divide both values by that. The GCD is the highest number that evenly divides both numbers. So the GCD for 6 and 10 is 2, the GCD for 44 and 99 is 11.

如果是的话,你需要做的是找到最大的公约数(GCD)并将两个值都除以它。GCD是将这两个数字平均分配的最高数字。6和10的GCD是2,44和99的GCD是11。

For example, a 1024x768 monitor has a GCD of 256. When you divide both values by that you get 4x3 or 4:3.

例如,一个1024x768监视器有一个256的GCD。当你把两个值都除以,得到4x3或4:3。

A (recursive) GCD algorithm:

(递归)GCD算法:

function gcd (a,b):
    if b == 0:
        return a
    return gcd (b, a mod b)

In C:

在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));
}

And here's some complete HTML/Javascript which shows one way to detect the screen size and calculate the aspect ratio from that. This works in FF3, I'm unsure what support other browsers have for screen.width and screen.height.

这是一些完整的HTML/Javascript,它显示了一种检测屏幕尺寸的方法,并计算出了它的纵横比。这在FF3中起作用,我不确定其他浏览器对屏幕有什么支持。宽度和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>

It outputs (on my weird wide-screen monitor):

它输出(在我奇怪的宽屏幕显示器上):

Dimensions = 1680 x 1050
Gcd        = 210
Aspect     = 8:5

Others that I tested this on:

我测试过的其他人:

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

I wish I had that last one at home but, no, it's a work machine unfortunately.

我希望我有最后一个在家里,但是,不,这是一个工作机器很不幸。

What you do if you find out the aspect ratio is not supported by your graphic resize tool is another matter. I suspect the best bet there would be to add letter-boxing lines (like the ones you get at the top and bottom of your old TV when you're watching a wide-screen movie on it). I'd add them at the top/bottom or the sides (whichever one results in the least number of letter-boxing lines) until the image meets the requirements.

如果你发现图形调整工具不支持纵横比,你会做什么,这是另一回事。我猜想最好的办法就是添加一些字母的线条(就像你在看一部大屏幕电影时,你在旧电视的顶部和底部看到的那样)。我将它们添加到顶部/底部或两侧(无论哪一个结果都是最少量的字母-拳击线),直到图像符合要求为止。

One thing you may want to consider is the quality of a picture that's been changed from 16:9 to 5:4 - I still remember the incredibly tall, thin cowboys I used to watch in my youth on television before letter-boxing was introduced. You may be better off having one different image per aspect ratio and just resize the correct one for the actual screen dimensions before sending it down the wire.

你可能需要考虑的一件事是照片的质量从16:9到5:4——我还记得在我年轻的时候在电视前看电视前,我在电视上看到的那些身材高大、身材瘦小的牛仔。你最好有一个不同的图像,每个纵横比,在发送它之前,只调整正确的屏幕尺寸大小。

#2


33  

aspectRatio = width / height

if that is what you're after. You can then multiply it by one of the dimensions of the target space to find out the other (that maintains the ratio) e.g.

如果这就是你想要的。然后你可以把它乘以目标空间的一个维度来找出另一个(保持比率)。

widthT = heightT * aspectRatio
heightT = widthT / aspectRatio

#3


12  

paxdiablo's answer is great, but there are a lot of common resolutions that have just a few more or less pixels in a given direction, and the greatest common divisor approach gives horrible results to them.

paxdiablo的答案很好,但是有很多常见的分辨率,在给定的方向上只有几个像素,而最大的公约数方法给它们带来了可怕的结果。

Take for example the well behaved resolution of 1360x765 which gives a nice 16:9 ratio using the gcd approach. According to Steam, this resolution is only used by 0.01% of it's users, while 1366x768 is used by a whoping 18.9%. Let's see what we get using the gcd approach:

以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%)

We'd want to round up that 683:384 ratio to the closest, 16:9 ratio.

我们想把这个比例提高到最接近的,16:9的比例。

I wrote a python script that parses a text file with pasted numbers from the Steam Hardware survey page, and prints all resolutions and closest known ratios, as well as the prevalence of each ratio (which was my goal when I started this):

我编写了一个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://*.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]) + '%')

For the curious, these are the prevalence of screen ratios amongst Steam users (as of October 2012):

对于好奇的人来说,这些都是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


10  

I guess you want to decide which of 4:3 and 16:9 is the best fit.

我猜你想确定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';
}

#5


1  

I think this does what you are asking for:

我认为这是你所要求的:

webdeveloper.com - decimal to fraction

webdeveloper.com -小数到分数。

Width/height gets you a decimal, converted to a fraction with ":" in place of '/' gives you a "ratio".

宽度/高度使你得到一个小数,转换成一个分数,以“:”代替“/”给你一个“比例”。

#6


1  

This algorithm in Python gets you part of the way there.

Python里的这个算法可以让你在这方面有所作为。


Tell me what happens if the windows is a funny size.

告诉我,如果窗户是一个有趣的尺寸会发生什么。

Maybe what you should have is a list of all acceptable ratios (to the 3rd party component). Then, find the closest match to your window and return that ratio from the list.

也许你应该得到一个所有可接受比率的列表(给第三方组件)。然后,找到与您的窗口最近的匹配,并将该比率从列表中返回。

#7


1  

As an alternative solution to the GCD searching, I suggest you to check against a set of standard values. You can find a list on Wikipedia.

作为GCD搜索的另一种解决方案,我建议您检查一组标准值。你可以在*上找到一个列表。

#8


1  

Im assuming your talking about video here, in which case you may also need to worry about pixel aspect ratio of the source video. For example.

我假设你在这里讨论视频,在这种情况下,你可能还需要担心源视频的像素宽比。为例。

PAL DV comes in a resolution of 720x576. Which would look like its 4:3. Now depending on the Pixel aspect ratio (PAR) the screen ratio can be either 4:3 or 16:9.

PAL DV的分辨率为720x576。看起来是4:3。现在根据像素宽比(PAR),屏幕比可以是4:3或16:9。

For more info have a look here http://en.wikipedia.org/wiki/Pixel_aspect_ratio

更多信息请访问http://en.wikipedia.org/wiki/Pixel_aspect_ratio。

You can get Square pixel Aspect Ratio, and a lot of web video is that, but you may want to watch out of the other cases.

你可以得到正方形像素宽比,很多网络视频都是这样,但是你可能想要注意其他的情况。

Hope this helps

希望这有助于

Mark

马克

#9


1  

Based on the other answers, here is how I got the numbers I needed in Python;

基于其他的答案,这里是我如何得到我在Python中需要的数字;

from decimal import Decimal

def gcd(a,b):
    if b == 0:
        return a
    return gcd(b, a%b)

def closest_aspect_ratio(width, height):
    g = gcd(width, height)
    x = Decimal(str(float(width)/float(g)))
    y = Decimal(str(float(height)/float(g)))
    dec = Decimal(str(x/y))
    return dict(x=x, y=y, dec=dec)

>>> closest_aspect_ratio(1024, 768)
{'y': Decimal('3.0'), 
 'x': Decimal('4.0'), 
 'dec': Decimal('1.333333333333333333333333333')}

#10


0  

Width / Height

?

吗?

#11


0  

I believe that aspect ratio is width divided by height.

我相信纵横比是宽度除以高度。

 r = w/h

#12


0  

bit of a strange way to do this but use the resolution as the aspect. E.G.

这是一种奇怪的方法,但使用分辨率作为方面。如

1024:768

1024:768

or you can try

或者你可以试一试

var w = screen.width;
var h = screen.height;
for(var i=1,asp=w/h;i<5000;i++){
  if(asp*i % 1==0){
    i=9999;
    document.write(asp*i,":",1*i);
  }
}

#13


0  

Here is my solution it is pretty straight forward since all I care about is not necessarily GCD or even accurate ratios: because then you get weird things like 345/113 which are not human comprehensible.

这是我的解决方案,这是非常直接的,因为我所关心的并不一定是GCD,甚至是精确的比例:因为你会得到一些奇怪的东西,比如345/113,这不是人类可以理解的。

I basically set acceptable landscape, or portrait ratios and their "value" as a float... I then compare my float version of the ratio to each and which ever has the lowest absolute value difference is the ratio closest to the item. That way when the user makes it 16:9 but then removes 10 pixels from the bottom it still counts as 16:9...

我基本上设置了可接受的景观,或肖像比例和它们的“价值”作为浮动…然后,我将我的浮点数与每一个的比率进行比较,它的绝对值最小的差值是最接近项的比率。这样当用户设置为16:9,然后从底部移除10个像素时,它仍然算作16:9……

accepted_ratios = {
    'landscape': (
        (u'5:4', 1.25),
        (u'4:3', 1.33333333333),
        (u'3:2', 1.5),
        (u'16:10', 1.6),
        (u'5:3', 1.66666666667),
        (u'16:9', 1.77777777778),
        (u'17:9', 1.88888888889),
        (u'21:9', 2.33333333333),
        (u'1:1', 1.0)
    ),
    'portrait': (
        (u'4:5', 0.8),
        (u'3:4', 0.75),
        (u'2:3', 0.66666666667),
        (u'10:16', 0.625),
        (u'3:5', 0.6),
        (u'9:16', 0.5625),
        (u'9:17', 0.5294117647),
        (u'9:21', 0.4285714286),
        (u'1:1', 1.0)
    ),
}


def find_closest_ratio(ratio):
    lowest_diff, best_std = 9999999999, '1:1'
    layout = 'portrait' if ratio < 1.0 else 'landscape'
    for pretty_str, std_ratio in accepted_ratios[layout]:
        diff = abs(std_ratio - ratio)
        if diff < lowest_diff:
            lowest_diff = diff
            best_std = pretty_str
    return best_std


def extract_ratio(width, height):
    try:
        divided = float(width)/float(height)
        if divided == 1.0:
            return '1:1'
        else:
            return find_closest_ratio(divided)
    except TypeError:
        return None

#14


0  

Here is a version of James Farey's best rational approximation algorithm with adjustable level of fuzziness ported to javascript from the aspect ratio calculation code originally written in python.

这里是James Farey的最佳合理近似算法的版本,该算法从最初用python编写的长宽比计算代码移植到javascript。

The method takes a float (width/height) and an upper limit for the fraction numerator/denominator.

该方法采用浮点(宽/高)和分数分子/分母的上限。

In the example below I am setting an upper limit of 50 because I need 1035x582 (1.77835051546) to be treated as 16:9 (1.77777777778) rather than 345:194 which you get with the plain gcd algorithm listed in other answers.

在下面的例子中,我设置了一个上限为50,因为我需要1035x582(1.77835051546),而不是345:194,而你使用的是在其他答案中列出的普通gcd算法。

<html>
<body>
<script type="text/javascript">
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;
        }
    }
}

document.write (aspect_ratio(800 / 600, 50) +"<br/>");
document.write (aspect_ratio(1035 / 582, 50) + "<br/>");
document.write (aspect_ratio(2560 / 1440, 50) + "<br/>");

    </script>
</body></html>

The result:

结果:

 4,3  // (1.33333333333) (800 x 600)
 16,9 // (1.77777777778) (2560.0 x 1440)
 16,9 // (1.77835051546) (1035.0 x 582)