2011-08-27 15 views
15

Diciamo che ho un'immagine (ad esempio 1024 x 768 px) che viene visualizzata in una UIImageView (ad esempio 300 x 300 px). Ora, mi piacerebbe convertire un punto dall'immagine, ad es. la posizione del naso di una persona (x: 500, y: 600), nel punto corrispondente di UIImageView con la sua contentMode presa in considerazione.Convertire i punti dall'immagine ai punti UIImageView, contentMode-

Se contentMode è fissato su UIViewContentModeScaleToFill, la conversione sarà semplice. Ma se è UIViewContentModeScaleAspectFit, le cose si fanno più complesse.

Esiste un modo elegante per raggiungere questo obiettivo? Non voglio davvero calcolarlo per ogni singolo contentMode (più di 10, penso).

Grazie!

risposta

29

Oggi, ho avuto un po 'di tempo libero per mettere insieme la mia soluzione a questo problema e pubblicarlo su GitHub: UIImageView-GeometryConversion

Si tratta di una categoria a UIImageView che fornisce i metodi per la conversione di punti e rettangoli dal sull'immagine da visualizzare coordina e rispetta tutte le 13 diverse modalità di contenuto.

Spero che ti piaccia!

+0

Molto bello - Sarebbe ancora più bello se avessi anche fornito il contrario (dalle coordinate imageView alle coordinate dell'immagine). – sarfata

+0

Hai ragione, lo aggiungerò presto. – nubbel

+1

Non preoccupatevi, l'ho fatto per alcune delle modalità, sto finendo proprio ora e vi invierò una richiesta pull su github più tardi oggi. – sarfata

2

No, non esiste un modo incorporato, pubblico o elegante per farlo.

È necessario decodificare le funzioni per le modalità di contenuto necessarie.

+0

Grazie, lo farò per UIViewContentModeScaleToFill, UIViewContentModeAspectFit e UIViewContentModeAspectFill. Questo dovrebbe essere abbastanza – nubbel

+2

@nubbel - Al termine, rendilo pubblico su github o in altro modo, in modo che la persona successiva non debba saltare attraverso gli stessi cerchi. – PeyloW

-1

Perché non puoi semplicemente ridimensionare le coordinate:

X (UIImageView) = (X (immagine)/1024) * 300

e

Y (UIImageView) = (Y (immagine)/768) * 300

+0

Ciò è positivo per UIViewContentModeScaleToFill, ma per altri contentModes? – nubbel

+0

non funziona per UIContentModeScaleToFit poiché verrà visualizzato il margine e l'immagine sarà centrata nella vista immagine utente – Vassily

10

Questa è la mia soluzione frettoloso e approssimativo:

- (CGPoint)convertPoint:(CGPoint)sourcePoint fromContentSize:(CGSize)sourceSize { 
    CGPoint targetPoint = sourcePoint; 
    CGSize targetSize = self.bounds.size; 

    CGFloat ratioX = targetSize.width/sourceSize.width; 
    CGFloat ratioY = targetSize.height/sourceSize.height; 

    if (self.contentMode == UIViewContentModeScaleToFill) { 
     targetPoint.x *= ratioX; 
     targetPoint.y *= ratioY; 
    } 
    else if(self.contentMode == UIViewContentModeScaleAspectFit) { 
     CGFloat scale = MIN(ratioX, ratioY); 

     targetPoint.x *= scale; 
     targetPoint.y *= scale; 

     targetPoint.x += (self.frame.size.width - sourceSize.width * scale)/2.0f; 
     targetPoint.y += (self.frame.size.height - sourceSize.height * scale)/2.0f; 
    } 
    else if(self.contentMode == UIViewContentModeScaleAspectFill) { 
     CGFloat scale = MAX(ratioX, ratioY); 

     targetPoint.x *= scale; 
     targetPoint.y *= scale; 

     targetPoint.x += (self.frame.size.width - sourceSize.width * scale)/2.0f; 
     targetPoint.y += (self.frame.size.height - sourceSize.height * scale)/2.0f; 
    } 

    return targetPoint; 
} 

- (CGRect)convertRect:(CGRect)sourceRect fromContentSize:(CGSize)sourceSize { 
    CGRect targetRect = sourceRect; 
    CGSize targetSize = self.bounds.size; 

    CGFloat ratioX = targetSize.width/sourceSize.width; 
    CGFloat ratioY = targetSize.height/sourceSize.height; 

    if (self.contentMode == UIViewContentModeScaleToFill) { 
     targetRect.origin.x *= ratioX; 
     targetRect.origin.y *= ratioY; 

     targetRect.size.width *= ratioX; 
     targetRect.size.height *= ratioY; 
    } 
    else if(self.contentMode == UIViewContentModeScaleAspectFit) { 
     CGFloat scale = MIN(ratioX, ratioY); 

     targetRect.origin.x *= scale; 
     targetRect.origin.y *= scale; 

     targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale)/2.0f; 
     targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale)/2.0f; 

     targetRect.size.width *= scale; 
     targetRect.size.height *= scale; 
    } 
    else if(self.contentMode == UIViewContentModeScaleAspectFill) { 
     CGFloat scale = MAX(ratioX, ratioY); 

     targetRect.origin.x *= scale; 
     targetRect.origin.y *= scale; 

     targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale)/2.0f; 
     targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale)/2.0f; 

     targetRect.size.width *= scale; 
     targetRect.size.height *= scale; 
    } 

    return targetRect; 
} 

Quando è riscritta e ottimizzato, lo pubblicherò su github e posterò il link qui sotto. Forse anche quello snippet potrebbe essere utile per qualcuno.

+1

Hai mai pubblicato questo? –

+0

Ho fatto oggi, vedere il mio altro post. Spero che tu possa farne uso! – nubbel

Problemi correlati