Qual è l’algoritmo per calcolare le proporzioni? Ho bisogno di un output come: 4: 3, 16: 9

Ho intenzione di usarlo con javascript per ritagliare un’immagine per adattarla all’intera finestra.

Modifica: utilizzerò un componente di terze parti che accetta solo le proporzioni nel formato: 4: 3, 16: 9

Ho capito che stai cercando un integer:integer proporzioni utilizzabili integer:integer soluzione integer:integer come 16:9 invece di un float:1 soluzione come 1.77778:1 .

Se è così, quello che devi fare è trovare il massimo comun divisore (GCD) e dividere entrambi i valori con quello. Il GCD è il numero più alto che divide uniformsmente entrambi i numeri. Quindi il GCD per 6 e 10 è 2, il GCD per 44 e 99 è 11.

Ad esempio, un monitor 1024×768 ha un GCD di 256. Quando dividi entrambi i valori, ottieni 4×3 o 4: 3.

Algoritmo GCD (ricorsivo):

 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)); } 

Ed ecco alcuni HTML / Javascript completi che mostrano un modo per rilevare le dimensioni dello schermo e calcolare il rapporto aspetto da quello. Funziona in FF3, non sono sicuro di quale supporto hanno gli altri browser per screen.width e screen.height .

    

Emette (sul mio strano monitor widescreen):

 Dimensions = 1680 x 1050 Gcd = 210 Aspect = 8:5 

Altri su cui ho provato questo:

 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 

Vorrei avere quell’ultima a casa ma, no, è una macchina da lavoro, sfortunatamente.

Quello che fai se scopri che le proporzioni non sono supportate dal tuo strumento di ridimensionamento grafico è un’altra cosa. Sospetto che la soluzione migliore sarebbe aggiungere linee di lettere maiuscole (come quelle che si ottengono nella parte superiore e inferiore della vecchia TV quando si sta guardando un film su un grande schermo). Li aggiungerei in alto / in basso o ai lati (a seconda di quale si ottiene il numero minimo di righe di lettere maiuscole) finché l’immagine non soddisfa i requisiti.

Una cosa che potresti voler considerare è la qualità di un’immagine che è stata cambiata da 16: 9 a 5: 4 – Ricordo ancora i cowboys incredibilmente alti e magri che guardavo in gioventù in televisione prima dell’introduzione del letterboxing. Potrebbe essere meglio avere una immagine diversa per proporzioni e ridimensionare semplicemente quella corretta per le dimensioni effettive dello schermo prima di inviarla via cavo.

 aspectRatio = width / height 

se è quello che cerchi. È quindi ansible moltiplicarlo per una delle dimensioni dello spazio di destinazione per scoprire l’altro (che mantiene il rapporto) ad es

 widthT = heightT * aspectRatio heightT = widthT / aspectRatio 

La risposta di paxdiablo è ottima, ma ci sono molte risoluzioni comuni che hanno solo pochi pixel in più o in meno in una determinata direzione, e il più grande metodo di divisori comuni dà loro risultati orribili.

Prendiamo ad esempio la risoluzione ben educata di 1360×765 che offre un buon rapporto 16: 9 usando l’approccio gcd. Secondo Steam, questa risoluzione è utilizzata solo dallo 0,01% dei suoi utenti, mentre 1366×768 è utilizzata da un 18,9%. Vediamo cosa otteniamo usando l’approccio gcd:

 1360x765 - 16:9 (0.01%) 1360x768 - 85:48 (2.41%) 1366x768 - 683:384 (18.9%) 

Vorremmo arrotondare il rapporto 683: 384 al rapporto 16: 9 più vicino.

Ho scritto uno script python che analizza un file di testo con i numeri incollati dalla pagina di sondaggio di Steam Hardware e stampa tutte le risoluzioni e i rapporti noti più vicini, nonché la prevalenza di ciascun rapporto (che era il mio objective quando l’ho avviato):

 # Contents pasted from store.steampowered.com/hwsurvey, section 'Primary Display Resolution' steam_file = './steam.txt' # Taken from http://sofit.miximages.com/aspect-ratio/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% (wxh 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]) + '%') 

Per i curiosi, questi sono la prevalenza dei rapporti dello schermo tra gli utenti di Steam (a partire da ottobre 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% 

Immagino tu voglia decidere quale di 4: 3 e 16: 9 sia la soluzione migliore.

 function getAspectRatio(width, height) { var ratio = width / height; return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9'; } 

Penso che questo faccia quello che stai chiedendo:

webdeveloper.com – decimale in frazione

Larghezza / altezza si ottiene un decimale, convertito in una frazione con “:” al posto di “/” ti dà un “rapporto”.

Questo algoritmo in Python ti fa diventare parte di questo.


Dimmi cosa succede se le windows sono di dimensioni ridotte.

Forse quello che dovresti avere è un elenco di tutti i rapporti accettabili (al componente di terze parti). Quindi, trova la corrispondenza più vicina alla tua finestra e restituisci tale rapporto dall’elenco.

Come soluzione alternativa alla ricerca GCD, ti suggerisco di controllare un insieme di valori standard. Puoi trovare un elenco su Wikipedia .

Im supponendo che parli di video qui, nel qual caso potresti anche doverti preoccupare delle proporzioni pixel del video sorgente. Per esempio.

PAL DV ha una risoluzione di 720×576. Quale sarebbe il suo 4: 3. Ora, in base al rapporto di aspetto dei pixel (PAR), il rapporto dello schermo può essere 4: 3 o 16: 9.

Per maggiori informazioni dai un’occhiata qui http://en.wikipedia.org/wiki/Pixel_aspect_ratio

Puoi ottenere l’Aspect Ratio con pixel quadrati e un sacco di video sul web è questo, ma potresti voler controllare gli altri casi.

Spero che questo ti aiuti

marchio

Sulla base delle altre risposte, ecco come ho ottenuto i numeri che mi servivano in 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')} 

Solo nel caso in cui sei un maniaco della performance …

Il modo più veloce (in JavaScript) per calcolare un rapporto di rettangolo è utilizzare un vero algoritmo di binario del grande divisore.

(Tutti i test di velocità e temporizzazione sono stati fatti da altri, puoi controllare un punto di riferimento qui: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor / )

Eccolo:

 /* 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] */ 
 Width / Height 

?

Credo che le proporzioni siano larghe per altezza.

  r = w/h 

un po ‘strano per farlo, ma usa la risoluzione come aspetto. PER ESEMPIO

1024: 768

oppure puoi provare

 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); } } 

Ecco la mia soluzione è abbastanza semplice poiché tutto ciò a cui tengo non è necessariamente GCD o anche rapporti accurati: perché poi ottieni cose strane come 345/113 che non sono comprensibili.

Fondamentalmente ho impostato un panorama accettabile, o i rapporti di ritratto e il loro “valore” come un float … Paragono quindi la mia versione float del rapporto a ciascuno e che ha sempre la differenza di valore assoluto più bassa è il rapporto più vicino all’articolo. In questo modo quando l’utente fa 16: 9 ma poi rimuove 10 pixel dal fondo, conta ancora come 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' else: return find_closest_ratio(divided) except TypeError: return None 

Ecco una versione del migliore algoritmo di approssimazione razionale di James Farey con livello regolabile di fuzziness portato su javascript dal codice di calcolo del rapporto di aspetto originariamente scritto in python.

Il metodo prende un float ( width/height ) e un limite superiore per il numeratore / denominatore della frazione.

Nell’esempio seguente sto impostando un limite superiore di 50 perché ho bisogno di 1035x582 (1.77835051546) per essere trattato come 16:9 (1.77777777778) piuttosto che 345:194 che ottieni con l’algoritmo gcd normale elencato in altre risposte.

     

Il risultato:

  4,3 // (1.33333333333) (800 x 600) 16,9 // (1.77777777778) (2560.0 x 1440) 16,9 // (1.77835051546) (1035.0 x 582)