Je prévois de l'utiliser avec JavaScript pour recadrer une image pour l'adapter à toute la fenêtre.
Edit : J'utiliserai un composant tiers qui n'accepte que le rapport hauteur / largeur au format comme: 4:3
, 16:9
.
javascript
algorithm
crop
aspect-ratio
Nathan
la source
la source
Réponses:
Je suppose que vous recherchez une
integer:integer
solution de rapport hauteur / largeur utilisable comme16:9
plutôt qu'unefloat:1
solution comme1.77778:1
.Si c'est le cas, ce que vous devez faire est de trouver le plus grand diviseur commun (GCD) et de diviser les deux valeurs par celui-ci. Le GCD est le nombre le plus élevé qui divise également les deux nombres. Ainsi, le GCD pour 6 et 10 est 2, le GCD pour 44 et 99 est 11.
Par exemple, un moniteur 1024x768 a un GCD de 256. Lorsque vous divisez les deux valeurs par cela, vous obtenez 4x3 ou 4: 3.
Un algorithme GCD (récursif):
function gcd (a,b): if b == 0: return a return gcd (b, a mod b)
En 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)); }
Et voici un HTML / Javascript complet qui montre une façon de détecter la taille de l'écran et de calculer le rapport hauteur / largeur à partir de cela. Cela fonctionne dans FF3, je ne suis pas sûr de la compatibilité des autres navigateurs
screen.width
etscreen.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>
Il sort (sur mon étrange moniteur à écran large):
Dimensions = 1680 x 1050 Gcd = 210 Aspect = 8:5
D'autres sur lesquels j'ai testé ceci:
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
J'aurais aimé avoir ce dernier à la maison mais, non, c'est une machine de travail malheureusement.
Ce que vous faites si vous découvrez que le rapport hauteur / largeur n'est pas pris en charge par votre outil de redimensionnement graphique est une autre affaire. Je soupçonne que le meilleur pari serait d'ajouter des lignes de boîte aux lettres (comme celles que vous obtenez en haut et en bas de votre ancien téléviseur lorsque vous regardez un film grand écran dessus). Je les ajouterais en haut / en bas ou sur les côtés (selon celui qui entraîne le moins de lignes de boîte aux lettres) jusqu'à ce que l'image réponde aux exigences.
Une chose que vous voudrez peut-être considérer est la qualité d'une image qui est passée de 16: 9 à 5: 4 - je me souviens encore des cowboys incroyablement grands et minces que je regardais dans ma jeunesse à la télévision avant l'introduction de la boxe aux lettres. Vous feriez peut-être mieux d'avoir une image différente par rapport d'aspect et de redimensionner simplement la bonne pour les dimensions réelles de l'écran avant de l'envoyer sur le fil.
la source
728x90
->364:45
je ne suis pas sûr que ce soit le résultat recherchési c'est ce que vous recherchez. Vous pouvez ensuite le multiplier par l'une des dimensions de l'espace cible pour découvrir l'autre (qui maintient le rapport) par exemple
la source
La réponse de paxdiablo est excellente, mais il existe de nombreuses résolutions communes qui n'ont que quelques pixels de plus ou moins dans une direction donnée, et la plus grande approche de diviseur commun leur donne des résultats horribles.
Prenons par exemple la résolution bien comportée de 1360x765 qui donne un joli rapport 16: 9 en utilisant l'approche gcd. Selon Steam, cette résolution n'est utilisée que par 0,01% de ses utilisateurs, tandis que 1366x768 est utilisée par 18,9%. Voyons ce que nous obtenons en utilisant l'approche gcd:
1360x765 - 16:9 (0.01%) 1360x768 - 85:48 (2.41%) 1366x768 - 683:384 (18.9%)
Nous voudrions arrondir ce rapport de 683: 384 au rapport 16: 9 le plus proche.
J'ai écrit un script python qui analyse un fichier texte avec des nombres collés à partir de la page d'enquête sur le matériel Steam, et imprime toutes les résolutions et les ratios connus les plus proches, ainsi que la prévalence de chaque ratio (ce qui était mon objectif lorsque j'ai commencé cela):
# 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]) + '%')
Pour les curieux, voici la prévalence des ratios d'écran parmi les utilisateurs de Steam (en octobre 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%
la source
Je suppose que vous voulez décider lequel des 4: 3 et 16: 9 est le meilleur ajustement.
function getAspectRatio(width, height) { var ratio = width / height; return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9'; }
la source
Voici une version du meilleur algorithme d'approximation rationnelle de James Farey avec un niveau de flou ajustable porté en javascript à partir du code de calcul du rapport hauteur / largeur écrit à l'origine en python.
La méthode prend un float (
width/height
) et une limite supérieure pour le numérateur / dénominateur de fraction.Dans l'exemple ci-dessous, je fixe une limite supérieure de
50
parce que j'ai besoin de1035x582
(1,77835051546) pour être traité comme16:9
(1,77777777778) plutôt que345:194
ce que vous obtenez avec l'gcd
algorithme simple répertorié dans d'autres réponses.<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)
la source
Juste au cas où vous êtes un maniaque de la performance ...
Le moyen le plus rapide (en JavaScript) de calculer un rapport rectangle consiste à utiliser un véritable algorithme binaire Great Common Divisor.
(Tous les tests de vitesse et de chronométrage ont été effectués par d'autres, vous pouvez vérifier un benchmark ici: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor / )
Le voici:
/* 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] */
la source
Voici ma solution, elle est assez simple car tout ce qui me préoccupe n'est pas nécessairement GCD ou même des ratios précis: parce que vous obtenez alors des choses étranges comme 345/113 qui ne sont pas compréhensibles par l'homme.
J'ai essentiellement défini des ratios de paysage ou de portrait acceptables et leur «valeur» en tant que flottant ... Je compare ensuite ma version flottante du rapport à chacun et celui qui a jamais la différence de valeur absolue la plus faible est le rapport le plus proche de l'élément. De cette façon, lorsque l'utilisateur fait 16: 9 mais supprime ensuite 10 pixels du bas, cela compte toujours pour 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
la source
Comme solution alternative à la recherche GCD, je vous suggère de vérifier par rapport à un ensemble de valeurs standard. Vous pouvez trouver une liste sur Wikipedia .
la source
Je suppose que vous parlez de vidéo ici, auquel cas vous devrez peut-être également vous soucier du rapport hauteur / largeur en pixels de la vidéo source. Par exemple.
PAL DV est disponible dans une résolution de 720x576. Ce qui ressemblerait à son 4: 3. Maintenant, en fonction du rapport hauteur / largeur des pixels (PAR), le rapport d'écran peut être de 4: 3 ou 16: 9.
Pour plus d'informations, regardez ici http://en.wikipedia.org/wiki/Pixel_aspect_ratio
Vous pouvez obtenir le rapport hauteur / largeur des pixels carrés, et beaucoup de vidéos sur le Web, mais vous voudrez peut-être faire attention aux autres cas.
J'espère que cela t'aides
marque
la source
Sur la base des autres réponses, voici comment j'ai obtenu les nombres dont j'avais besoin en 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')}
la source
Je crois que le rapport hauteur / largeur est la largeur divisée par la hauteur.
la source
Je pense que cela fait ce que vous demandez:
webdeveloper.com - décimal à fraction
Largeur / hauteur vous donne un nombre décimal, converti en fraction avec ":" au lieu de "/" vous donne un "rapport".
la source
Cet algorithme en Python vous permet de faire une partie du chemin.
Dites-moi ce qui se passe si les fenêtres sont d'une taille amusante.
Peut-être que vous devriez avoir une liste de tous les ratios acceptables (pour le composant tiers). Ensuite, trouvez la correspondance la plus proche de votre fenêtre et renvoyez ce ratio à partir de la liste.
la source
une façon un peu étrange de faire cela, mais utilisez la résolution comme aspect. PAR EXEMPLE
1024: 768
ou tu peux essayer
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); } }
la source
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);
la source
dans mon cas, je veux quelque chose comme
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 ]
la source
Vous pouvez toujours commencer par créer une table de consultation basée sur des proportions communes. Vérifiez https://en.wikipedia.org/wiki/Display_aspect_ratio Ensuite, vous pouvez simplement faire la division
Pour les problèmes de la vie réelle, vous pouvez faire quelque chose comme ci-dessous
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' }
Ensuite, vous donnez simplement les dimensions dans n'importe quel ordre
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
la source
?
la source