Tôi dự định sử dụng nó với JavaScript để cắt một hình ảnh cho vừa với toàn bộ cửa sổ.
Chỉnh sửa : Tôi sẽ sử dụng thành phần của bên thứ 3 chỉ chấp nhận tỷ lệ khung hình ở định dạng như: 4:3
, 16:9
.
Tôi dự định sử dụng nó với JavaScript để cắt một hình ảnh cho vừa với toàn bộ cửa sổ.
Chỉnh sửa : Tôi sẽ sử dụng thành phần của bên thứ 3 chỉ chấp nhận tỷ lệ khung hình ở định dạng như: 4:3
, 16:9
.
Câu trả lời:
Tôi hiểu rằng bạn đang tìm kiếm một integer:integer
giải pháp tỷ lệ khung hình có thể sử dụng được 16:9
hơn là một float:1
giải pháp như thế 1.77778:1
.
Nếu vậy, những gì bạn cần làm là tìm ước số chung lớn nhất (GCD) và chia cả hai giá trị cho đó. GCD là số cao nhất chia đều cả hai số. Vì vậy, GCD cho 6 và 10 là 2, GCD cho 44 và 99 là 11.
Ví dụ: màn hình 1024x768 có GCD là 256. Khi bạn chia cả hai giá trị đó, bạn nhận được 4x3 hoặc 4: 3.
Thuật toán GCD (đệ quy):
function gcd (a,b):
if b == 0:
return a
return gcd (b, a mod b)
Trong 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));
}
Và đây là một số HTML / Javascript hoàn chỉnh cho thấy một cách để phát hiện kích thước màn hình và tính toán tỷ lệ khung hình từ đó. Điều này hoạt động trong FF3, tôi không chắc các trình duyệt khác có hỗ trợ gì screen.width
và 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>
Nó xuất ra (trên màn hình rộng kỳ lạ của tôi):
Dimensions = 1680 x 1050
Gcd = 210
Aspect = 8:5
Những người khác mà tôi đã thử nghiệm điều này:
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
Tôi ước mình có cái cuối cùng đó ở nhà nhưng, không, thật không may, đó là một chiếc máy làm việc.
Bạn phải làm gì nếu phát hiện ra tỷ lệ khung hình không được công cụ thay đổi kích thước đồ họa của bạn hỗ trợ là một vấn đề khác. Tôi nghi ngờ cách tốt nhất là nên thêm các dòng đấm bốc chữ cái (như những dòng bạn nhận được ở đầu và cuối TV cũ khi bạn đang xem phim màn hình rộng trên đó). Tôi sẽ thêm chúng ở trên cùng / dưới cùng hoặc ở hai bên (tùy theo điều kiện nào dẫn đến số dòng chữ-boxing ít nhất) cho đến khi hình ảnh đáp ứng yêu cầu.
Một điều bạn có thể muốn xem xét là chất lượng của hình ảnh đã được thay đổi từ 16: 9 thành 5: 4 - Tôi vẫn nhớ những anh chàng cao bồi cực kỳ cao gầy mà tôi từng xem hồi trẻ trên truyền hình trước khi môn đấm bốc được giới thiệu. Tốt hơn là bạn nên có một hình ảnh khác nhau trên mỗi tỷ lệ khung hình và chỉ cần thay đổi kích thước hình ảnh chính xác cho kích thước màn hình thực tế trước khi gửi nó xuống dây.
728x90
-> 364:45
không chắc chắn đó là kết quả mong muốn
Câu trả lời của paxdiablo là tuyệt vời, nhưng có rất nhiều độ phân giải phổ biến chỉ có một vài pixel nhiều hơn hoặc ít hơn theo một hướng nhất định và phương pháp ước số chung lớn nhất mang lại kết quả khủng khiếp cho chúng.
Lấy ví dụ, độ phân giải hoạt động tốt là 1360x765 mang lại tỷ lệ 16: 9 đẹp bằng cách sử dụng phương pháp gcd. Theo Steam, độ phân giải này chỉ được 0,01% người dùng sử dụng, trong khi 1366x768 được sử dụng bởi 18,9%. Hãy xem những gì chúng ta nhận được khi sử dụng phương pháp gcd:
1360x765 - 16:9 (0.01%)
1360x768 - 85:48 (2.41%)
1366x768 - 683:384 (18.9%)
Chúng tôi muốn làm tròn tỷ lệ 683: 384 đó thành tỷ lệ 16: 9 gần nhất.
Tôi đã viết tập lệnh python phân tích cú pháp tệp văn bản với các số được dán từ trang khảo sát Phần cứng Steam và in tất cả các độ phân giải và tỷ lệ đã biết gần nhất, cũng như mức độ phổ biến của từng tỷ lệ (đó là mục tiêu của tôi khi tôi bắt đầu điều này):
# 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]) + '%')
Đối với những người tò mò, đây là tỷ lệ màn hình phổ biến giữa những người dùng Steam (tính đến tháng 10 năm 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%
Tôi đoán bạn muốn quyết định xem 4: 3 và 16: 9 nào là phù hợp nhất.
function getAspectRatio(width, height) {
var ratio = width / height;
return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';
}
Đây là phiên bản của thuật toán xấp xỉ hợp lý tốt nhất của James Farey với mức độ mờ có thể điều chỉnh được được chuyển sang javascript từ mã tính toán tỷ lệ khung hình ban đầu được viết bằng python.
Phương thức nhận float ( width/height
) và giới hạn trên cho tử số / mẫu số của phân số.
Trong ví dụ dưới đây, tôi đang đặt giới hạn trên 50
vì tôi cần 1035x582
(1.77835051546) được coi là 16:9
(1.77777777778) chứ không phải là giới hạn 345:194
bạn nhận được với gcd
thuật toán đơn giản được liệt kê trong các câu trả lời khác.
<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>
Kết quả:
4,3 // (1.33333333333) (800 x 600)
16,9 // (1.77777777778) (2560.0 x 1440)
16,9 // (1.77835051546) (1035.0 x 582)
Đề phòng trường hợp bạn là một người không thích trình diễn ...
Cách nhanh nhất (trong JavaScript) để tính tỷ lệ hình chữ nhật là sử dụng thuật toán Great Common Divisor nhị phân thực sự.
(Tất cả các bài kiểm tra tốc độ và thời gian đã được thực hiện bởi những người khác, bạn có thể kiểm tra một điểm chuẩn tại đây: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor / )
Nó đây rồi:
/* 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]
*/
Đây là giải pháp của tôi, nó khá đơn giản vì tất cả những gì tôi quan tâm không nhất thiết phải là GCD hoặc thậm chí là tỷ lệ chính xác: bởi vì sau đó bạn nhận được những thứ kỳ lạ như 345/113 mà con người không thể hiểu được.
Về cơ bản, tôi đặt tỷ lệ ngang hoặc tỷ lệ dọc có thể chấp nhận được và "giá trị" của chúng dưới dạng giá trị nổi ... Sau đó, tôi so sánh phiên bản tỷ lệ nổi của mình với mỗi tỷ lệ và cái nào có chênh lệch giá trị tuyệt đối thấp nhất là tỷ lệ gần nhất với mục. Theo cách đó, khi người dùng đặt nó thành 16: 9 nhưng sau đó xóa 10 pixel từ dưới cùng thì nó vẫn được tính là 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
Tôi giả sử bạn đang nói về video ở đây, trong trường hợp đó, bạn có thể cần phải lo lắng về tỷ lệ khung hình pixel của video nguồn. Ví dụ.
PAL DV có độ phân giải 720x576. Nó sẽ giống như 4: 3 của nó. Giờ đây, tùy thuộc vào tỷ lệ khung hình Pixel (PAR), tỷ lệ màn hình có thể là 4: 3 hoặc 16: 9.
Để biết thêm thông tin, hãy xem tại đây http://en.wikipedia.org/wiki/Pixel_aspect_ratio
Bạn có thể nhận được Tỷ lệ khung hình pixel vuông và rất nhiều video trên web là như vậy, nhưng bạn có thể muốn xem các trường hợp khác.
Hi vọng điêu nay co ich
dấu
Dựa trên các câu trả lời khác, đây là cách tôi có được các số tôi cần trong 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')}
Tôi tin rằng tỷ lệ khung hình là chiều rộng chia cho chiều cao.
r = w/h
Tôi nghĩ điều này thực hiện những gì bạn đang yêu cầu:
webdeveloper.com - thập phân thành phân số
Chiều rộng / chiều cao cho bạn một số thập phân, được chuyển đổi thành phân số với ":" thay cho '/' sẽ cho bạn một "tỷ lệ".
Thuật toán này trong Python giúp bạn làm được điều đó.
Hãy cho tôi biết điều gì sẽ xảy ra nếu cửa sổ có kích thước hài hước.
Có thể những gì bạn nên có là danh sách tất cả các tỷ lệ có thể chấp nhận được (đối với thành phần bên thứ 3). Sau đó, tìm kết quả phù hợp nhất với cửa sổ của bạn và trả về tỷ lệ đó từ danh sách.
trong trường hợp của tôi, tôi muốn một cái gì đó giống như
[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 ]
Bạn luôn có thể bắt đầu bằng cách lập bảng tra cứu dựa trên các tỷ lệ khung hình phổ biến. Kiểm tra https://en.wikipedia.org/wiki/Display_aspect_ratio Sau đó, bạn chỉ cần thực hiện phép chia
Đối với các vấn đề trong cuộc sống thực, bạn có thể làm như sau
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'
}
Sau đó, bạn chỉ cần cung cấp các kích thước theo thứ tự bất kỳ
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
?