종횡비를 계산하는 알고리즘은 무엇입니까?
-
19-09-2019 - |
문제
전체 창에 맞게 이미지를 자르기 위해 JavaScript와 함께 사용하려고합니다.
편집하다: 나는 다음과 같은 형식의 종횡비 만 받아들이는 제 3 자 구성 요소를 사용합니다. 4:3
, 16:9
.
해결책
나는 당신이 사용 가능한 종횡비를 찾고 있습니다 integer:integer
솔루션과 같은 16:9
a보다는 float:1
솔루션과 같은 1.77778:1
.
그렇다면, 당신이해야 할 일은 가장 큰 공통 다이서 (GCD)를 찾아서 두 값을 그것으로 나눕니다. GCD는 두 숫자를 고르게 나누는 가장 높은 숫자입니다. 따라서 6 및 10의 GCD는 2, 44 및 99의 GCD는 11입니다.
예를 들어, 1024x768 모니터의 GCD는 256입니다. 두 값을 모두 나누면 4x3 또는 4 : 3을 얻습니다.
A (재귀) 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
나는 집에서 마지막으로 그것을 가지고 있었으면 좋겠지 만, 안타깝게도 작업 기계입니다.
그래픽 크기 조정 도구에 의해 종횡비가 지원되지 않는다는 것을 알게되면 당신이하는 일은 또 다른 문제입니다. 나는 넓은 화면 영화를 볼 때 오래된 TV의 상단과 하단에있는 것과 같이 레터 박스 라인을 추가하는 것이 가장 좋습니다. 이미지가 요구 사항을 충족 할 때까지 상단/하단 또는 측면 (최소 수의 레터 박스 라인을 초래 한 사람)에 추가합니다.
당신이 고려하고 싶은 한 가지는 16 : 9에서 5 : 4로 바뀌는 그림의 품질입니다. 나는 여전히 Let 종횡비당 하나의 다른 이미지를 사용하는 것이 더 나을 수 있으며 와이어를 보내기 전에 실제 화면 치수에 대한 올바른 이미지를 크기를 조정합니다.
다른 팁
aspectRatio = width / height
그것이 당신이 뒤 따르는 것이라면. 그런 다음 대상 공간의 크기 중 하나를 곱하여 다른 사람 (비율을 유지하는)을 찾을 수 있습니다.
widthT = heightT * aspectRatio
heightT = widthT / aspectRatio
Paxdiablo의 대답은 훌륭하지만 주어진 방향으로 픽셀이 몇 개나 적은 공통의 많은 결의안이 많이 있으며, 가장 큰 일반적인 divisor 접근법은 그들에게 끔찍한 결과를줍니다.
예를 들어 GCD 접근법을 사용하여 16 : 9 비율을 제공하는 1360x765의 잘 작동 해상도를 예로 들어보십시오. 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 비율로 반올림하고 싶습니다.
Steam 하드웨어 설문 조사 페이지에서 붙여 넣은 숫자가있는 텍스트 파일을 구문 분석하는 Python 스크립트를 작성하고 모든 해상도와 가장 가까운 비율과 각 비율의 유병률 (이 목표를 시작할 때의 목표였습니다)을 인쇄합니다.
# 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으로 작성되었습니다.
메소드는 플로트를 취합니다 (width/height
) 및 분수 분자/분모의 상한.
아래의 예에서 나는 상한을 설정하고있다. 50
필요하기 때문에 1035x582
(1.77835051546)로 처리됩니다 16:9
(1.77777777778)보다는 (1.7777777778) 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>
결과:
4,3 // (1.33333333333) (800 x 600)
16,9 // (1.77777777778) (2560.0 x 1440)
16,9 // (1.77835051546) (1035.0 x 582)
당신이 성능 괴물 인 경우를 대비하여 ...
사각형 비율을 계산하는 가장 빠른 방법 (JavaScript)은 진정한 이진 위대한 공통 분배기 알고리즘을 사용합니다.
(모든 속도 및 타이밍 테스트는 다른 속도에 의해 수행되었으며 여기에서 하나의 벤치 마크를 확인할 수 있습니다. https://lemire.me/blog/2013/12/26/fastest-way-to-compute-thegreatest-common-divisor/)
여기있어:
/* the binary Great Common Divisor calculator */
function gcd (u, v) {
if (u === v) return u;
if (u === 0) return v;
if (v === 0) return u;
if (~u & 1)
if (v & 1)
return gcd(u >> 1, v);
else
return gcd(u >> 1, v >> 1) << 1;
if (~v & 1) return gcd(u, v >> 1);
if (u > v) return gcd((u - v) >> 1, v);
return gcd((v - u) >> 1, u);
}
/* returns an array with the ratio */
function ratio (w, h) {
var d = gcd(w,h);
return [w/d, h/d];
}
/* example */
var r1 = ratio(1600, 900);
var r2 = ratio(1440, 900);
var r3 = ratio(1366, 768);
var r4 = ratio(1280, 1024);
var r5 = ratio(1280, 720);
var r6 = ratio(1024, 768);
/* will output this:
r1: [16, 9]
r2: [8, 5]
r3: [683, 384]
r4: [5, 4]
r5: [16, 9]
r6: [4, 3]
*/
나는 이것이 당신이 요구하는 일을한다고 생각합니다.
너비/높이는 "/'대신"비율 "을 제공하는": ":": ":": ":": "비율"을 제공합니다.
파이썬 의이 알고리즘 당신을 그 길의 일부로 데려갑니다.
창문이 재미있는 크기라면 어떻게되는지 알려주세요.
어쩌면 당신이 가지고 있어야 할 것은 허용되는 모든 비율 목록 (제 3 자 구성 요소) 일 것입니다. 그런 다음 창에 가장 가까운 일치를 찾아 목록에서 해당 비율을 반환하십시오.
GCD 검색에 대한 대체 솔루션으로 표준 값 세트에 대해 확인하는 것이 좋습니다. 목록을 찾을 수 있습니다 위키 백과.
여기에서 비디오에 대해 이야기한다고 가정하면 소스 비디오의 픽셀 종횡비에 대해 걱정해야 할 수도 있습니다. 예를 들어.
PAL DV는 720x576의 해상도로 제공됩니다. 4 : 3처럼 보일 것입니다. 이제 픽셀 종횡비 (PAR)에 따라 화면 비율은 4 : 3 또는 16 : 9 일 수 있습니다.
자세한 정보는 여기를 살펴보십시오 http://en.wikipedia.org/wiki/pixel_aspect_ratio
정사각형 픽셀 종횡비를 얻을 수 있으며 많은 웹 비디오는 그 사실입니다. 그러나 다른 경우를 살펴볼 수 있습니다.
도움이 되었기를 바랍니다
표시
다른 답변을 바탕으로, 여기에는 파이썬에서 필요한 숫자를 얻는 방법이 있습니다.
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')}
여기 내 솔루션이 있습니다. 제가 신경 쓰는 모든 것이 반드시 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
종횡비는 너비를 높이로 나눈 값이라고 생각합니다.
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);
}
}
function ratio(w, h) {
function mdc(w, h) {
var resto;
do {
resto = w % h;
w = h;
h = resto;
} while (resto != 0);
return w;
}
var mdc = mdc(w, h);
var width = w/mdc;
var height = h/mdc;
console.log(width + ':' + height);
}
ratio(1920, 1080);
내 경우에는 같은 것을 원합니다
[10,5,15,20,25] -> [ 2, 1, 3, 4, 5 ]
function ratio(array){
let min = Math.min(...array);
let ratio = array.map((element)=>{
return element/min;
});
return ratio;
}
document.write(ratio([10,5,15,20,25])); // [ 2, 1, 3, 4, 5 ]
Width / Height
?