2010-06-09 8 views
9

Ho un'applicazione in cui gli utenti finali possono ridimensionare e posizionare le immagini in un designer. Dato che la specifica richiede che l'immagine sia "allungata" al controllo di contenimento, l'utente finale può finire con un'immagine storta.Come "ridimensionare in modo intelligente" un'immagine visualizzata con le proporzioni originali

Per aiutare l'utente con il ridimensionamento delle immagini, sto pensando di implementare una funzione di resettaggio intelligente che consenta all'utente di fissare facilmente il rapporto di aspetto dell'immagine in modo che non appaia più teso.

Il modo rapido per risolvere questo è in realtà fornire due opzioni: 1) scala da larghezza 2) scala da altezza. L'utente sceglie il metodo e l'algoritmo regola le dimensioni dell'immagine utilizzando le proporzioni originali. Ad esempio: Un'immagine viene visualizzata come 200x200 sul designer, ma l'immagine originale è 1024x768 pixel. L'utente sceglie "Dimensione intelligente da larghezza" e la nuova dimensione diventa ~ 200x150 poiché lo aspect ratio originale è ~ 1.333

Questo è OK, ma come potrei rendere l'algoritmo più intelligente e non disturbare l'utente chiedendo quale dimensione ricalcolare dovrebbe essere basato su?

risposta

22

Se sto interpretando correttamente la spec, si vuole un risultato che è non più grande di quello che l'utente finale previsto fuori originariamente; vuoi che una delle due dimensioni si riduca e l'altra rimanga la stessa. In altre parole, la nuova dimensione dovrebbe riempire lo spazio del designer in una direzione mentre accorcia le dimensioni nell'altra direzione per mantenere le proporzioni originali.

original_ratio = original_width/original_height 
designer_ratio = designer_width/designer_height 
if original_ratio > designer_ratio 
    designer_height = designer_width/original_ratio 
else 
    designer_width = designer_height * original_ratio 

Spesso lavorerete con coordinate intere, ma le divisioni di produrre i rapporti sopra vanno in virgola mobile. Ecco un riarrangiamento della formula per essere più amichevole. Assicurati che i tuoi numeri interi abbiano l'intervallo per gestire la larghezza massima * altezza.

if original_width * designer_height > designer_width * original_height 
    designer_height = (designer_width * original_height)/original_width 
else 
    designer_width = (designer_height * original_width)/original_height 
+0

Sì, è necessario estendere le specifiche per definire il ridimensionamento intelligente. Questo algoritmo sembra ragionevole. Lo proverò. –

1

Calcolare le nuove dimensioni per entrambe le varianti ("scala per larghezza" e "scala per altezza"), quindi utilizzare quella che si adatta al display.

In alternativa è anche possibile calcolare il rapporto di aspetto del "rettangolo di selezione" e confrontarlo con le proporzioni dell'immagine originale. A seconda del rapporto di aspetto più grande, è necessario ridimensionare l'altezza o la larghezza.

È inoltre possibile limitare il processo di ridimensionamento in modo che in tutti i casi venga eseguita la "scala per larghezza". Quindi, per cambiare la dimensione dell'immagine, l'utente deve sempre cambiare la sua larghezza. L'altezza verrà sempre regolata automaticamente.

+0

Stavo pensando lungo queste linee, ma come faccio yhou determinare ciò che è troppo largo o troppo alto quando l'utente può arbitrariamente dimensioni e posizionare l'immagine ? –

+0

@Paul: non è limitato a 200x200? Da dove viene fuori l'attuale funzione smart-size? – sth

+0

ci stiamo avvicinando. I limiti sono implicitamente impostati dall'utente manipolando la dimensione delle immagini. Vedi la mia risposta a Khnle sotto. –

1

Poiché si desidera massimizzare visualizzando il più possibile l'immagine in scala (dell'originale) nella finestra, ovvero l'area nel proprio designer, si prenderà il più grande della larghezza o dell'altezza dell'immagine originale e scala che a 200. pseudo-codice (larghezza, altezza sono dimensioni di originale):

if (width > height) { 
    scaledWidth = 200; 
    scaledHeight = (height * 200)/width; 
} else { 
    scaledHeight = 200; 
    scaledWidth = (width * 200)/height; 
} 
+0

No. Voglio che l'immagine sia il più vicino possibile a ciò che l'utente ha esposto il più possibile. Alla fine, una delle dimensioni rimarrebbe invariata. –

0

Hai solo bisogno di capire la scala necessaria per entrambe le dimensioni e poi prendere il più piccolo dei 2.

2

Non c'è contabili per la quantità di copie e pasters là fuori eh! Volevo anche sapere questo e tutti quelli che ho visto erano infiniti esempi di larghezza di scala O altezza ... chi vorrebbe che l'altro traboccasse ?!

  • larghezza ridimensionare e altezza senza la necessità di un ciclo
  • non superi le immagini dimensioni originarie
  • Utilizzi la matematica che funziona correttamente cioè larghezza/aspetto in altezza, e l'altezza * aspetto di larghezza in modo immagini sono in realtà in scala correttamente su e giù:/

//////////////

private void ResizeImage(Image img, double maxWidth, double maxHeight) 
{ 
    double srcWidth = img.Source.Width; 
    double srcHeight = img.Source.Height; 

    double resizeWidth = srcWidth; 
    double resizeHeight = srcHeight; 

    double aspect = resizeWidth/resizeHeight; 

    if (resizeWidth > maxWidth) 
    { 
     resizeWidth = maxWidth; 
     resizeHeight = resizeWidth/aspect; 
    } 
    if (resizeHeight > maxHeight) 
    { 
     aspect = resizeWidth/resizeHeight; 
     resizeHeight = maxHeight; 
     resizeWidth = resizeHeight * aspect; 
    } 

    img.Width = resizeWidth; 
    img.Height = resizeHeight; 
} 
+0

piuttosto buono, a parte quando si esegue ResizeImage (i, 2000,3000) –

6

Ecco una soluzione che ho trovato quando ho dovuto affrontare questo problema. Venuto fuori piuttosto breve e semplice, volevo solo condividerlo.

Handy "formule": ratio = W/HW = H * ratio

  1. calcolare il rapporto.
  2. Calcolare l'altezza dell'immagine se si desidera impostare la larghezza sulla nuova larghezza (larghezza massima consentita).
  3. Calcolare la larghezza dell'immagine se si desidera impostare l'altezza sulla nuova altezza (altezza massima consentita).
  4. Vedere quale delle due dimensioni non sostituisce la dimensione massima in nessuna dimensione. Se il rapporto non è 1, uno di essi sarà sempre sbagliato e uno sarà sempre corretto.

In JavaScript

// Returns array with new width and height 
function proportionalScale(originalSize, newSize) 
{ 
    var ratio = originalSize[0]/originalSize[1]; 

    var maximizedToWidth = [newSize[0], newSize[0]/ratio]; 
    var maximizedToHeight = [newSize[1] * ratio, newSize[1]]; 

    if (maximizedToWidth[1] > newSize[1]) { return maximizedToHeight; } 
    else { return maximizedToWidth; } 
} 

originalSize e newSize è un array [0] = width, [1] = height

2

prese il suggerimento sopra e reso scala su/giù all'interno massima altezza/larghezza. Qui il codice Python per esso e sostegno anche aggiunto per ruotare cose, mantenendosi nella limites:

def _resize (immagine, dimensioni, ruotare = None): """ Ridimensiona un'immagine per essere il più vicino possibile specificare dimensioni: l'immagine è un campo modello immagine django .

Will both scale up and down the image to meet this while keeping the proportions 
    in width and height 

""" 

if image and os.path.isfile(image.path): 

    im = pil.open(image.path) 
    logging.debug('resizing image from %s x %s --> %s x %s ' % (im.size[0], im.size[1], dimensions[0], dimensions[1])) 

    if rotate: 
     logging.debug('first rotating image %s' % rotate) 
     im = im.rotate(90) 

    srcWidth = Decimal(im.size[0]) 
    srcHeight = Decimal(im.size[1]) 

    resizeWidth = srcWidth 
    resizeHeight = srcHeight 

    aspect = resizeWidth/resizeHeight # Decimal 

    logging.debug('resize aspect is %s' % aspect) 

    if resizeWidth > dimensions[0] or resizeHeight > dimensions[1]: 
     # if width or height is bigger we need to shrink things 
     if resizeWidth > dimensions[0]: 
      resizeWidth = Decimal(dimensions[0]) 
      resizeHeight = resizeWidth/aspect 

     if resizeHeight > dimensions[1] : 
      aspect = resizeWidth/resizeHeight 
      resizeHeight = Decimal(dimensions[1]) 
      resizeWidth = resizeHeight * aspect 

    else: 
     # if both width and height are smaller we need to increase size 
     if resizeWidth < dimensions[0]: 
      resizeWidth = Decimal(dimensions[0]) 
      resizeHeight = resizeWidth/aspect 

     if resizeHeight > dimensions[1] : 
      aspect = resizeWidth/resizeHeight 
      resizeHeight = Decimal(dimensions[1]) 
      resizeWidth = resizeHeight * aspect 

    im = im.resize((resizeWidth, resizeHeight), pil.ANTIALIAS) 

    logging.debug('resized image to %s %s' % im.size) 
    im.save(image.path) 

else: 
    # no action, due to no image or no image in path 
    pass 

return image 
0

qui è la mia soluzione,

a = aspetto sw = immagine originale larghezza sh = altezza dell'immagine originale dw = richiesto larghezza massima dh = richiesto altezza massima

sw e sh conterrà i valori ridimensionati finali

codice è PHP:

$a = $sw/$sh; 

if($a > 1){ 
    // wider image 
    if($sw != $dw){ 
     $rt = $dw/$sw; 
     $sw = $sw * $rt; 
     $sh = $sh * $rt; 
    } 

    if($sh > $dh){ 
     $rt = $dh/$sh; 
     $sw = $sw * $rt; 
     $sh = $sh * $rt; 
    } 
}else{ 
    // taller image 
    if($sh != $dh){ 
     $rt = $dh/$sh; 
     $sh = $sh * $rt; 
     $sw = $sw * $rt; 
    } 

    if($sw > $dw){ 
     $rt = $dw/$sw; 
     $sh = $sh * $rt; 
     $sw = $sw * $rt; 
    } 
} 
0

Ho usato questo modo per ridimensionare l'immagine per FHD modo

if (width >= height) { 
    var original_ratio = width/height 
    new_width = 1080 * original_ratio 
    console.log("new new_width = " + Math.round(new_width)); 
    console.log("new new_height = 1080"); 
} else { 
    var original_ratio = height/width 
    new_height = 1080 * original_ratio 
    console.log("new new_height = " + Math.round(new_height)); 
    console.log("new new_width = 1080"); 
} 

è possibile modificare il 1080 alla nuova dimensione.

Spero sia utile per qualcuno almeno.

0

La mia soluzione per Shrink e crescere dimensioni in javascript sulla base di https://stackoverflow.com/a/5654847/1055015

var scale = function (srcWidth, srcHeight, maxWidth, maxHeight) { 

     let resizeWidth = srcWidth; 
     let resizeHeight = srcHeight; 

     let aspect = resizeWidth/resizeHeight; 
     let scaleX = maxWidth/srcWidth; 
     let scaleY = maxHeight/srcHeight; 
     let scale = Math.min(scaleX, scaleY); 

     resizeWidth *= scale; 
     resizeHeight *= scale; 

     if (resizeWidth > maxWidth) { 
     resizeWidth = maxWidth; 
     resizeHeight = resizeWidth/aspect; 
     } 

     if (resizeHeight > maxHeight) { 
     aspect  = resizeWidth/resizeHeight; 
     resizeHeight = maxHeight; 
     resizeWidth = resizeHeight * aspect; 
     } 

     return { 
     width : resizeWidth, 
     height: resizeHeight, 
     }; 
    } 
Problemi correlati