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

我打算用JavaScript来裁剪图像以适应整个窗口。

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

我收集你正在寻找一个可用的长宽比integer:integer16:9 integer:integer解决scheme,而不是一个float:1解决scheme,如1.77778:1

如果是这样,你需要做的是find最大公约数(GCD)并将这两个值相除。 GCD是平分这两个数字的最高数字。 所以6和10的GCD是2,44和99的GCD是11。

例如,一个1024×768显示器的GCD是256.当你将这两个值相除时,你得到4×3或4:3。

(recursion)GCDalgorithm:

 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.widthscreen.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 

其他我testing过的:

 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 

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

如果您发现graphicsresize工具不支持纵横比,您所做的是另一回事。 我怀疑最好的select是添加信箱(比如当你观看一部宽屏幕电影时,你在旧电视的顶部和底部得到的信封)。 我会将它们添加到顶部/底部或两侧(以最小数量的信箱线条为准),直到图像符合要求。

有一件事你可能要考虑的是画面质量已经从16:9变成了5:4 – 我仍然记得在信箱引入之前,我在电视里年轻时用过的那种瘦高的牛仔。 你可能会更好每个长宽比有一个不同的图像,只是调整正确的一个实际的屏幕尺寸之前,发送它的电线。

 Aspect Ratio = width / height 

如果那是你以后的事。 然后,您可以乘以目标空间的其中一个维度来找出另一个(维持比例),例如

 widthT = heightT * Aspect Ratio heightT = widthT / Aspect Ratio 

我想你想决定哪个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'; } 

paxdiablo的答案是很好的,但是有很多通用的解决scheme,在一个给定的方向上只有几个或更less的像素,最大的公约数方法给他们带来了可怕的结果。

举例来说,1360×765的分辨率非常好,使用gcd方法可以产生16:9的比例。 根据Steam的说法,这个分辨率只被用户的0.01%使用,而1366×768被使用的是18.9%。 让我们看看我们使用gcd方法得到了什么:

 1360x765 - 16:9 (0.01%) 1360x768 - 85:48 (2.41%) 1366x768 - 683:384 (18.9%) 

我们希望将683:384的比率调整到最接近的16:9的比例。

我编写了一个python脚本,用蒸汽硬件调查页面分析一个粘贴数字的文本文件,并打印出所有分辨率和最接近的已知比率,以及每个比率的stream行度(这是我开始时的目标):

 # 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% (wxh 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% 

我想这是你所要求的:

webdeveloper.com – 小数到分数

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

Python中的这个algorithm可以让你成为那里的一部分。


告诉我,如果窗户是一个有趣的大小会发生什么事情。

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

作为GCDsearch的替代解决scheme,我build议您检查一组标准值。 你可以在维基百科find一个列表。

我假设你在这里谈论video,在这种情况下,你可能还需要担心源video的像素长宽比。 例如。

PAL制式DV的分辨率为720×576。 这看起来像是4:3。 现在取决于像素长宽比(PAR),屏幕比率可以是4:3或16:9。

更多信息请看http://en.wikipedia.org/wiki/Pixel_aspect_ratio

你可以得到正方形像素宽高比,很多networkingvideo就是这样,但是你可能要注意其他情况。

希望这可以帮助

标记

基于其他的答案,这里是我如何得到我需要在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')} 
 Width / Height 

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

  r = w/h 

有点奇怪的方式来做到这一点,但使用分辨率作为方面。 例如

1024:768

或者你可以尝试

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

这是我的解决scheme,它是非常简单的,因为我所关心的不一定是GCD,甚至不是准确的比率,因为那样你会得到345/113这些不可理解的奇怪的东西。

我基本上把可接受的风景,或肖像比率和他们的“价值”作为一个浮动…我然后比较我的浮动版本的比例,每个有最低的绝对值差异是最接近该项目的比例。 这样,当用户使其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 

这里是James Farey最好的合理逼近algorithm的一个版本,可调节级别的模糊性,从最初用python编写的纵横比计算代码移植到javascript。

该方法采用浮点数( width/height )和分数分母/分母的上限。

在下面的示例中,我将上限设置为50因为我需要1035x582 (1.77835051546)作为16:9 (1.77777777778),而不是345:194 ,您可以使用其他答案中列出的普通gcdalgorithm。

 <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> 

结果:

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