Я планую використовувати його з JavaScript для обрізання зображення відповідно до всього вікна.
Редагувати : я буду використовувати сторонній компонент, який приймає співвідношення сторін лише у такому форматі як: 4:3
, 16:9
.
Я планую використовувати його з JavaScript для обрізання зображення відповідно до всього вікна.
Редагувати : я буду використовувати сторонній компонент, який приймає співвідношення сторін лише у такому форматі як: 4:3
, 16:9
.
Відповіді:
Мені здається, ви шукаєте корисне integer:integer
рішення зі співвідношенням сторін, 16:9
а не таке float:1
рішення 1.77778:1
.
Якщо так, то вам потрібно знайти найбільший спільний дільник (GCD) і розділити обидва значення на це. GCD - це найбільше число, яке рівномірно ділить обидва числа. Отже, GCD для 6 і 10 дорівнює 2, GCD для 44 і 99 дорівнює 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 - Я все ще пам’ятаю неймовірно високих худорлявих ковбоїв, яких я дивився в молодості на телебаченні до того, як був представлений бокс для листів. Можливо, вам краще мати одне інше зображення на співвідношення сторін і просто змінити розмір правильного для фактичних розмірів екрана, перш ніж відправити його по дроту.
728x90
-> 364:45
я не впевнений, що це
Відповідь paxdiablo чудова, але є багато загальних резолюцій, які мають лише кілька більш-менш пікселів у певному напрямку, і найбільший загальний підхід до дільників дає їм жахливі результати.
Візьмемо для прикладу добре виховану роздільну здатність 1360x765, яка дає приємне співвідношення 16: 9, використовуючи підхід gcd. За даними 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 р.):
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';
}
Ось версія найкращого раціонального алгоритму апроксимації Джеймса Фарі з регульованим рівнем нечіткості, перенесеним на javascript із коду розрахунку співвідношення сторін, спочатку написаного на python.
Метод бере float ( width/height
) і верхню межу для чисельника знаменника / знаменника.
У наведеному нижче прикладі я встановлюю верхню межу, 50
оскільки мені потрібно 1035x582
(1.77835051546) розглядати як 16:9
(1.77777777778), а не як 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-the-greatest-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]
*/
Ось моє рішення - це досить прямо, оскільки все, що мене цікавить, - це не обов’язково 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'
return find_closest_ratio(divided)
except TypeError:
return None
Я припускаю, що ви тут говорите про відео, і в цьому випадку вам також може знадобитися піклуватися про пропорцію пікселів вихідного відео. Наприклад.
PAL DV поставляється в роздільній здатності 720x576. Що виглядало б як його 4: 3. Тепер, залежно від пропорції пікселів (PAR), співвідношення екрану може становити 4: 3 або 16: 9.
Для отримання додаткової інформації загляньте тут http://en.wikipedia.org/wiki/Pixel_aspect_ratio
Ви можете отримати співвідношення сторін квадратних пікселів, і це багато веб-відео, але ви, можливо, захочете остерігатися інших випадків.
Сподіваюся, це допомагає
Марка
Виходячи з інших відповідей, ось як я отримав потрібні мені числа в 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')}
Я вважаю, що пропорція - це ширина, поділена на висоту.
r = w/h
Я думаю, що це робить те, про що ви просите:
webdeveloper.com - десятковий до дробу
Ширина / висота дає вам десятковий знак, перетворений у дріб з ":" замість "/" дає "співвідношення".
Цей алгоритм на Python доставить вам частину шляху.
Скажіть, що станеться, якщо вікна забавного розміру.
Можливо, те, що ви повинні мати, це перелік усіх прийнятних співвідношень (до сторонніх компонентів). Потім знайдіть найближчу відповідність до вашого вікна та поверніть це співвідношення зі списку.
у моєму випадку я хочу щось подібне
[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 ]
Ви завжди можете почати із створення таблиці пошуку на основі загальних пропорцій. Перевірте https://en.wikipedia.org/wiki/Display_aspect_ratio Тоді ви можете просто зробити поділ
Для реальних життєвих проблем ви можете зробити щось подібне нижче
let ERROR_ALLOWED = 0.05
let STANDARD_ASPECT_RATIOS = [
[1, '1:1'],
[4/3, '4:3'],
[5/4, '5:4'],
[3/2, '3:2'],
[16/10, '16:10'],
[16/9, '16:9'],
[21/9, '21:9'],
[32/9, '32:9'],
]
let RATIOS = STANDARD_ASPECT_RATIOS.map(function(tpl){return tpl[0]}).sort()
let LOOKUP = Object()
for (let i=0; i < STANDARD_ASPECT_RATIOS.length; i++){
LOOKUP[STANDARD_ASPECT_RATIOS[i][0]] = STANDARD_ASPECT_RATIOS[i][1]
}
/*
Find the closest value in a sorted array
*/
function findClosest(arrSorted, value){
closest = arrSorted[0]
closestDiff = Math.abs(arrSorted[0] - value)
for (let i=1; i<arrSorted.length; i++){
let diff = Math.abs(arrSorted[i] - value)
if (diff < closestDiff){
closestDiff = diff
closest = arrSorted[i]
} else {
return closest
}
}
return arrSorted[arrSorted.length-1]
}
/*
Estimate the aspect ratio based on width x height (order doesn't matter)
*/
function estimateAspectRatio(dim1, dim2){
let ratio = Math.max(dim1, dim2) / Math.min(dim1, dim2)
if (ratio in LOOKUP){
return LOOKUP[ratio]
}
// Look by approximation
closest = findClosest(RATIOS, ratio)
if (Math.abs(closest - ratio) <= ERROR_ALLOWED){
return '~' + LOOKUP[closest]
}
return 'non standard ratio: ' + Math.round(ratio * 100) / 100 + ':1'
}
Тоді ви просто вказуєте розміри в будь-якому порядку
estimateAspectRatio(1920, 1080) // 16:9
estimateAspectRatio(1920, 1085) // ~16:9
estimateAspectRatio(1920, 1150) // non standard ratio: 1.65:1
estimateAspectRatio(1920, 1200) // 16:10
estimateAspectRatio(1920, 1220) // ~16:10
Width / Height
?