Ich habe vor, es mit JavaScript zu verwenden, um ein Bild so zuzuschneiden, dass es in das gesamte Fenster passt.
Bearbeiten : Ich verwende eine Komponente eines Drittanbieters, die nur das Seitenverhältnis im Format wie : 4:3
, akzeptiert 16:9
.
Ich habe vor, es mit JavaScript zu verwenden, um ein Bild so zuzuschneiden, dass es in das gesamte Fenster passt.
Bearbeiten : Ich verwende eine Komponente eines Drittanbieters, die nur das Seitenverhältnis im Format wie : 4:3
, akzeptiert 16:9
.
Antworten:
Ich nehme an, Sie suchen eher nach einer brauchbaren integer:integer
Lösung mit Seitenverhältnis 16:9
als nach einer float:1
Lösung wie 1.77778:1
.
Wenn ja, müssen Sie den größten gemeinsamen Teiler (GCD) finden und beide Werte dadurch dividieren. Die GCD ist die höchste Zahl, die beide Zahlen gleichmäßig teilt. Die GCD für 6 und 10 ist also 2, die GCD für 44 und 99 ist 11.
Ein 1024x768-Monitor hat beispielsweise eine GCD von 256. Wenn Sie beide Werte durch diese dividieren, erhalten Sie 4x3 oder 4: 3.
Ein (rekursiver) GCD-Algorithmus:
function gcd (a,b):
if b == 0:
return a
return gcd (b, a mod b)
In 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));
}
Und hier ist ein vollständiges HTML / Javascript, das eine Möglichkeit zeigt, die Bildschirmgröße zu ermitteln und das Seitenverhältnis daraus zu berechnen. Dies funktioniert in FF3. Ich bin mir nicht sicher, welche Unterstützung andere Browser für screen.width
und haben 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>
Es gibt aus (auf meinem seltsamen Breitbildmonitor):
Dimensions = 1680 x 1050
Gcd = 210
Aspect = 8:5
Andere, an denen ich das getestet habe:
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
Ich wünschte, ich hätte den letzten zu Hause, aber nein, es ist leider eine Arbeitsmaschine.
Was Sie tun, wenn Sie herausfinden, dass das Seitenverhältnis von Ihrem Grafikgrößestool nicht unterstützt wird, ist eine andere Sache. Ich vermute, die beste Wahl wäre es, Letterboxing-Zeilen hinzuzufügen (wie die, die Sie oben und unten auf Ihrem alten Fernseher erhalten, wenn Sie einen Breitbildfilm darauf ansehen). Ich würde sie oben / unten oder an den Seiten hinzufügen (je nachdem, was die geringste Anzahl von Briefkastenzeilen ergibt), bis das Bild den Anforderungen entspricht.
Eine Sache, die Sie vielleicht berücksichtigen möchten, ist die Qualität eines Bildes, das von 16: 9 auf 5: 4 geändert wurde. Ich erinnere mich noch an die unglaublich großen, dünnen Cowboys, die ich in meiner Jugend im Fernsehen gesehen habe, bevor das Briefboxen eingeführt wurde. Möglicherweise ist es besser, ein anderes Bild pro Seitenverhältnis zu haben und einfach die richtige Größe für die tatsächlichen Bildschirmabmessungen zu ändern, bevor Sie es über das Kabel senden.
728x90
-> 364:45
bin nicht sicher, ob das das gewünschte Ergebnis ist
Die Antwort von paxdiablo ist großartig, aber es gibt viele gängige Auflösungen, die nur wenige mehr oder weniger Pixel in einer bestimmten Richtung haben, und der größte gemeinsame Divisor-Ansatz liefert ihnen schreckliche Ergebnisse.
Nehmen wir zum Beispiel die gut erzogene Auflösung von 1360 x 765, die mit dem GCD-Ansatz ein gutes Verhältnis von 16: 9 ergibt. Laut Steam wird diese Auflösung nur von 0,01% der Benutzer verwendet, während 1366 x 768 von 18,9% verwendet wird. Mal sehen, was wir mit dem gcd-Ansatz bekommen:
1360x765 - 16:9 (0.01%)
1360x768 - 85:48 (2.41%)
1366x768 - 683:384 (18.9%)
Wir möchten dieses Verhältnis von 683: 384 auf das nächste Verhältnis von 16: 9 aufrunden.
Ich habe ein Python-Skript geschrieben, das eine Textdatei mit eingefügten Zahlen von der Steam Hardware-Umfrageseite analysiert und alle Auflösungen und nächsten bekannten Verhältnisse sowie die Häufigkeit der einzelnen Verhältnisse druckt (was mein Ziel war, als ich damit anfing):
# 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]) + '%')
Für Neugierige ist dies die Prävalenz der Bildschirmverhältnisse bei Steam-Nutzern (Stand 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%
Ich denke, Sie möchten entscheiden, welches von 4: 3 und 16: 9 am besten passt.
function getAspectRatio(width, height) {
var ratio = width / height;
return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';
}
Hier ist eine Version von James Fareys bestem Algorithmus für rationale Approximation mit einstellbarem Grad an Unschärfe, der aus dem ursprünglich in Python geschriebenen Berechnungscode für das Seitenverhältnis auf Javascript portiert wurde .
Die Methode verwendet ein float ( width/height
) und eine Obergrenze für den Bruchzähler / Nenner.
Im folgenden Beispiel setze ich eine Obergrenze von, 50
weil ich 1035x582
(1.77835051546) als 16:9
(1.77777777778) behandeln muss, anstatt 345:194
mit dem gcd
in anderen Antworten aufgeführten einfachen Algorithmus.
<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>
Das Ergebnis:
4,3 // (1.33333333333) (800 x 600)
16,9 // (1.77777777778) (2560.0 x 1440)
16,9 // (1.77835051546) (1035.0 x 582)
Nur für den Fall, dass Sie ein Performance-Freak sind ...
Der schnellste Weg (in JavaScript), um ein Rechteckverhältnis zu berechnen, ist die Verwendung eines echten binären Great Common Divisor-Algorithmus.
(Alle Geschwindigkeits- und Timing-Tests wurden von anderen durchgeführt. Sie können einen Benchmark hier überprüfen: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor / )
Hier ist es:
/* 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]
*/
Hier ist meine Lösung, es ist ziemlich einfach, da alles, was mich interessiert, nicht unbedingt GCD oder sogar genaue Verhältnisse sind: denn dann bekommt man seltsame Dinge wie 345/113, die für den Menschen nicht verständlich sind.
Grundsätzlich setze ich akzeptable Landschafts- oder Hochformatverhältnisse und deren "Wert" als Float ... Ich vergleiche dann meine Float-Version des Verhältnisses mit jedem und wer jemals die niedrigste absolute Wertdifferenz aufweist, ist das Verhältnis, das dem Objekt am nächsten liegt. Auf diese Weise zählt es immer noch als 16: 9, wenn der Benutzer es 16: 9 macht, dann aber 10 Pixel von der Unterseite entfernt ...
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
Ich glaube, dass das Seitenverhältnis die Breite geteilt durch die Höhe ist.
r = w/h
Ich denke, das macht das, wonach Sie fragen:
webdeveloper.com - dezimal zum Bruch
Mit Breite / Höhe erhalten Sie eine Dezimalstelle, die in einen Bruch mit ":" anstelle von "/" umgewandelt wird. Sie erhalten ein "Verhältnis".
Dieser Algorithmus in Python bringt Sie auf dem Weg dorthin.
Sag mir, was passiert, wenn die Fenster eine lustige Größe haben.
Vielleicht sollten Sie eine Liste aller akzeptablen Verhältnisse (zur Komponente eines Drittanbieters) haben. Suchen Sie dann die Übereinstimmung, die Ihrem Fenster am nächsten kommt, und geben Sie dieses Verhältnis aus der Liste zurück.
Ich gehe davon aus, dass Sie hier über Video sprechen. In diesem Fall müssen Sie sich möglicherweise auch um das Pixel-Seitenverhältnis des Quellvideos kümmern. Beispielsweise.
PAL DV ist in einer Auflösung von 720 x 576 erhältlich. Welches würde wie sein 4: 3 aussehen. Abhängig vom Pixel-Seitenverhältnis (PAR) kann das Bildschirmverhältnis nun entweder 4: 3 oder 16: 9 betragen.
Weitere Informationen finden Sie hier http://en.wikipedia.org/wiki/Pixel_aspect_ratio
Sie können ein quadratisches Pixel-Seitenverhältnis erhalten, und viele Webvideos sind das, aber Sie möchten vielleicht auch die anderen Fälle betrachten.
Hoffe das hilft
Kennzeichen
Basierend auf den anderen Antworten habe ich hier die Zahlen erhalten, die ich in Python benötigt habe.
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')}
in meinem Fall möchte ich so etwas wie
[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 ]
Sie können jederzeit eine Nachschlagetabelle erstellen, die auf allgemeinen Seitenverhältnissen basiert. Überprüfen Sie https://en.wikipedia.org/wiki/Display_aspect_ratio. Dann können Sie einfach die Teilung durchführen
Bei Problemen im wirklichen Leben können Sie wie folgt vorgehen
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'
}
Dann geben Sie einfach die Maße in beliebiger Reihenfolge an
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
?