Я планирую использовать его с JavaScript, чтобы обрезать изображение, чтобы оно уместилось во всем окне.
Изменить : я буду использовать сторонний компонент, который принимает только соотношение сторон в формате, например: 4:3
, 16:9
.
Я планирую использовать его с JavaScript, чтобы обрезать изображение, чтобы оно уместилось во всем окне.
Изменить : я буду использовать сторонний компонент, который принимает только соотношение сторон в формате, например: 4:3
, 16:9
.
Ответы:
Я так понимаю, вы ищете подходящее
integer:integer
решение для соотношения сторон,16:9
а не такоеfloat:1
решение1.77778:1
.Если да, то вам нужно найти наибольший общий делитель (НОД) и разделить на него оба значения. НОД - это наибольшее число, которое равномерно делит оба числа. Итак, НОД для 6 и 10 равно 2, НОД для 44 и 99 - 11.
Например, монитор 1024x768 имеет НОД 256. Если вы разделите оба значения на это, вы получите 4x3 или 4: 3.
(Рекурсивный) алгоритм НОД:
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
источник
В качестве альтернативы поиску в GCD я предлагаю вам проверить набор стандартных значений. Вы можете найти список в Википедии .
источник
Я предполагаю, что вы говорите здесь о видео, и в этом случае вам также может потребоваться позаботиться о соотношении сторон пикселя исходного видео. Например.
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')}
источник
Я считаю, что соотношение сторон - это ширина, разделенная на высоту.
источник
Я думаю, что это то, о чем вы просите:
webdeveloper.com - десятичная дробь
Ширина / высота дает вам десятичное число, преобразованное в дробь с ":" вместо '/' дает вам "соотношение".
источник
Этот алгоритм в Python поможет вам в этом.
Подскажите, что будет, если окна смешного размера.
Возможно, вам нужен список всех приемлемых соотношений (для стороннего компонента). Затем найдите наиболее близкое соответствие к вашему окну и верните это соотношение из списка.
источник
немного странный способ сделать это, но использовать разрешение как аспект. НАПРИМЕР
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);
источник
в моем случае я хочу что-то вроде
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
источник
?
источник