Saya berencana menggunakannya dengan JavaScript untuk memotong gambar agar sesuai dengan seluruh jendela.
Edit : Saya akan menggunakan komponen pihak ke-3 yang hanya menerima rasio aspek dalam format seperti: 4:3
, 16:9
.
Saya berencana menggunakannya dengan JavaScript untuk memotong gambar agar sesuai dengan seluruh jendela.
Edit : Saya akan menggunakan komponen pihak ke-3 yang hanya menerima rasio aspek dalam format seperti: 4:3
, 16:9
.
Jawaban:
Saya rasa Anda sedang mencari integer:integer
solusi rasio aspek yang dapat digunakan seperti 16:9
daripada float:1
solusi seperti 1.77778:1
.
Jika ya, yang perlu Anda lakukan adalah mencari pembagi persekutuan terbesar (PBT) dan membagi kedua nilai tersebut dengan itu. PBT adalah angka tertinggi yang membagi kedua angka secara merata. Jadi PBT untuk 6 dan 10 adalah 2, PBT 44 dan 99 adalah 11.
Misalnya, monitor 1024x768 memiliki GCD 256. Jika Anda membagi kedua nilai tersebut, Anda akan mendapatkan 4x3 atau 4: 3.
Algoritme GCD (rekursif):
function gcd (a,b):
if b == 0:
return a
return gcd (b, a mod b)
Di 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));
}
Dan inilah beberapa HTML / Javascript lengkap yang menunjukkan satu cara untuk mendeteksi ukuran layar dan menghitung rasio aspek dari itu. Ini berfungsi di FF3, saya tidak yakin dukungan apa yang dimiliki browser lain screen.width
dan 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>
Ini menghasilkan (pada monitor layar lebar aneh saya):
Dimensions = 1680 x 1050
Gcd = 210
Aspect = 8:5
Orang lain yang saya uji ini:
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
Saya berharap saya memiliki yang terakhir di rumah tetapi, tidak, sayangnya ini adalah mesin kerja.
Apa yang Anda lakukan jika Anda menemukan rasio aspek tidak didukung oleh alat pengubah ukuran grafik adalah masalah lain. Saya curiga cara terbaik adalah menambahkan baris letter-boxing (seperti yang Anda dapatkan di bagian atas dan bawah TV lama Anda saat Anda menonton film layar lebar di atasnya). Saya akan menambahkannya di bagian atas / bawah atau samping (mana saja yang menghasilkan paling sedikit garis kotak surat) sampai gambar memenuhi persyaratan.
Satu hal yang mungkin ingin Anda pertimbangkan adalah kualitas gambar yang telah diubah dari 16: 9 menjadi 5: 4 - Saya masih ingat koboi kurus dan tinggi yang biasa saya tonton di masa muda saya di televisi sebelum letter-boxing diperkenalkan. Anda mungkin lebih baik memiliki satu gambar berbeda per rasio aspek dan hanya mengubah ukuran yang benar untuk dimensi layar yang sebenarnya sebelum mengirimkannya ke kabel.
728x90
-> 364:45
saya tidak yakin itu adalah hasil yang diinginkan
Jawaban paxdiablo sangat bagus, tetapi ada banyak resolusi umum yang hanya memiliki sedikit lebih banyak atau lebih sedikit piksel ke arah tertentu, dan pendekatan pembagi umum terbesar memberikan hasil yang mengerikan bagi mereka.
Ambil contoh resolusi berperilaku baik 1360x765 yang memberikan rasio 16: 9 yang bagus menggunakan pendekatan gcd. Menurut Steam, resolusi ini hanya digunakan oleh 0,01% penggunanya, sementara 1366x768 digunakan oleh 18,9%. Mari kita lihat apa yang kita dapatkan menggunakan pendekatan gcd:
1360x765 - 16:9 (0.01%)
1360x768 - 85:48 (2.41%)
1366x768 - 683:384 (18.9%)
Kami ingin membulatkan rasio 683: 384 ke rasio terdekat, 16: 9.
Saya menulis skrip python yang mem-parsing file teks dengan nomor yang ditempel dari halaman survei Perangkat Keras Steam, dan mencetak semua resolusi dan rasio terdekat yang diketahui, serta prevalensi setiap rasio (yang merupakan tujuan saya ketika saya memulai ini):
# 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]) + '%')
Yang penasaran, berikut adalah prevalensi rasio layar di antara pengguna Steam (per Oktober 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%
Saya rasa Anda ingin memutuskan mana dari 4: 3 dan 16: 9 yang paling cocok.
function getAspectRatio(width, height) {
var ratio = width / height;
return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';
}
Berikut adalah versi algoritma pendekatan rasional terbaik James Farey dengan tingkat ketidakjelasan yang dapat disesuaikan yang ditransfer ke javascript dari kode penghitungan rasio aspek aslinya ditulis dengan python.
Metode ini menggunakan float ( width/height
) dan batas atas untuk pembilang / penyebut pecahan.
Dalam contoh di bawah ini saya menetapkan batas atas 50
karena saya perlu 1035x582
(1.77835051546) diperlakukan sebagai 16:9
(1.77777777778) daripada 345:194
yang Anda dapatkan dengan polosgcd
algoritma yang tercantum dalam jawaban lain.
<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>
Hasil:
4,3 // (1.33333333333) (800 x 600)
16,9 // (1.77777777778) (2560.0 x 1440)
16,9 // (1.77835051546) (1035.0 x 582)
Kalau-kalau Anda seorang performance freak ...
Cara tercepat (dalam JavaScript) untuk menghitung rasio persegi panjang adalah menggunakan algoritma biner Great Common Divisor sejati.
(Semua tes kecepatan dan waktu telah dilakukan oleh orang lain, Anda dapat memeriksa satu benchmark di sini: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor / )
Ini dia:
/* 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]
*/
Ini solusi saya. Ini cukup mudah karena yang saya pedulikan belum tentu GCD atau bahkan rasio yang akurat: karena Anda mendapatkan hal-hal aneh seperti 345/113 yang tidak dapat dipahami manusia.
Saya pada dasarnya menetapkan lanskap yang dapat diterima, atau rasio potret dan "nilai" mereka sebagai pelampung ... Saya kemudian membandingkan versi pelampung rasio untuk masing-masing dan yang pernah memiliki perbedaan nilai absolut terendah adalah rasio yang paling dekat dengan item. Dengan cara itu ketika pengguna membuatnya 16: 9 tetapi kemudian menghapus 10 piksel dari bawah masih dihitung sebagai 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
Saya berasumsi Anda berbicara tentang video di sini, dalam hal ini Anda mungkin juga perlu khawatir tentang rasio aspek piksel dari video sumber. Sebagai contoh.
PAL DV hadir dalam resolusi 720x576. Yang akan terlihat seperti 4: 3. Sekarang tergantung pada rasio aspek Pixel (PAR), rasio layar bisa menjadi 4: 3 atau 16: 9.
Untuk info lebih lanjut lihat di sini http://en.wikipedia.org/wiki/Pixel_aspect_ratio
Anda bisa mendapatkan Rasio Aspek piksel Persegi, dan banyak video web adalah itu, tetapi Anda mungkin ingin berhati-hati dari kasus lain.
Semoga ini membantu
Menandai
Berdasarkan jawaban lain, berikut adalah cara saya mendapatkan angka yang saya butuhkan dengan 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')}
Saya yakin rasio aspek adalah lebar dibagi tinggi.
r = w/h
Saya pikir ini melakukan apa yang Anda minta:
webdeveloper.com - desimal ke pecahan
Lebar / tinggi memberi Anda desimal, diubah menjadi pecahan dengan ":" di tempat '/' memberi Anda "rasio".
Algoritme dengan Python ini membantu Anda mencapai tujuan tersebut.
Ceritakan apa yang terjadi jika jendelanya berukuran lucu.
Mungkin yang harus Anda miliki adalah daftar semua rasio yang dapat diterima (untuk komponen pihak ke-3). Kemudian, temukan yang paling cocok dengan jendela Anda dan kembalikan rasio itu dari daftar.
dalam kasus saya, saya ingin sesuatu seperti
[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 ]
Anda selalu dapat memulai dengan membuat tabel pencarian berdasarkan rasio aspek umum. Periksa https://en.wikipedia.org/wiki/Display_aspect_ratio Kemudian Anda cukup melakukan pembagian
Untuk masalah kehidupan nyata, Anda bisa melakukan hal seperti di bawah ini
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'
}
Kemudian Anda cukup memberikan dimensi dalam urutan apa pun
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
?