2009-07-21 21 views
27

Sto provando a sviluppare una piccola applicazione. In esso, ho bisogno di rilevare il colore di un pixel all'interno di un UIView. Ho un CGPoint che definisce il pixel di cui ho bisogno. I colori di UIView sono cambiati usando CoreAnimation.Come ottenere il colore di un pixel in un UIView?

So che esistono alcuni modi complessi per estrarre informazioni sul colore da UIImages. Tuttavia non sono riuscito a trovare una soluzione per UIViews.

In pseudo-codice Cerco qualcosa di simile

pixel = [view getPixelAtPoint:myPoint]; 
UIColor *mycolor = [pixel getColor]; 

Qualsiasi input molto apprezzato.

+0

Hai trovato una soluzione (veloce)? – CodeAndCats

+0

L'utilizzo del contesto bitmap si è rivelato abbastanza veloce per i miei scopi. Fare un tentativo e vedere come funziona per voi. – 0x90

risposta

8

È piuttosto orribile e lento. Fondamentalmente si crea un contesto bitmap con un backing store che si assegna in modo da poter leggere la memoria, quindi si renderizza il livello delle viste nel contesto e si legge il punto appropriato nella ram.

Se sai come farlo per un'immagine già si può fare qualcosa di simile:

- (UIImage *)imageForView:(UIView *)view { 
    UIGraphicsBeginImageContext(view.frame.size); 
    [view.layer renderInContext: UIGraphicsGetCurrentContext()]; 
    UIImage *retval = UIGraphicsGetImageFromCurrentImageContext(void); 
    UIGraphicsEndImageContext(); 

    return retval; 
} 

E quindi si otterrà un'immagine in cui è possibile ottenere i dati dei pixel. Sono sicuro che il meccanismo che hai per trattare le immagini implica renderle comunque in un contesto, quindi puoi unirlo a questo e considerare l'effettiva creazione dell'immagine. Quindi, se si prendere che potrebbe e rimuovere il pezzo in cui si carica l'immagine e sostituirlo con il contesto di rendering:

[view.layer renderInContext: UIGraphicsGetCurrentContext()]; 

si dovrebbe essere buono.

3

Corretti alcuni piccoli errori

- (UIImage *)imageForView:(UIView *)view { 
    UIGraphicsBeginImageContext(view.frame.size); 
    [view.layer renderInContext: UIGraphicsGetCurrentContext()]; 
    UIImage *retval = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return retval; 
} 

Inoltre, aggiungere

#import <QuartzCore/QuartzCore.h> 

al file per evitare messaggi di avviso.

Combinando il codice con il codice trovato here funziona perfettamente.

+0

Perché sembrare che semplicemente copiato il codice di Louis e rimosso il "vuoto" superfluo nella chiamata a 'UIGraphicsGetImageFromCurrentImageContext()'? –

+1

Questo è quello che ho fatto. Qual è un modo migliore per gestire le correzioni qui? – 0x90

70

Qui è la soluzione più efficiente:

// UIView+ColorOfPoint.h 
@interface UIView (ColorOfPoint) 
- (UIColor *) colorOfPoint:(CGPoint)point; 
@end 

// UIView+ColorOfPoint.m 
#import "UIView+ColorOfPoint.h" 
#import <QuartzCore/QuartzCore.h> 

@implementation UIView (ColorOfPoint) 

- (UIColor *) colorOfPoint:(CGPoint)point 
{ 
    unsigned char pixel[4] = {0}; 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast); 

    CGContextTranslateCTM(context, -point.x, -point.y); 

    [self.layer renderInContext:context]; 

    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    //NSLog(@"pixel: %d %d %d %d", pixel[0], pixel[1], pixel[2], pixel[3]); 

    UIColor *color = [UIColor colorWithRed:pixel[0]/255.0 green:pixel[1]/255.0 blue:pixel[2]/255.0 alpha:pixel[3]/255.0]; 

    return color; 
} 

@end 

link a file: https://github.com/ivanzoid/ikit/tree/master/UIView+ColorOfPoint

+0

Attenzione a .m, rimosso con '#import ' – Jonny

+0

Sembra che si sta renderizzando solo un singolo pixel. Molto bello – mahboudz

+1

@mahboudz: sì, siete assolutamente corretto – ivanzoid

14

Una versione swift'ified di ivanzoid 's risposta

Swift 3

extension CALayer { 

    func colorOfPoint(point:CGPoint) -> CGColor { 

     var pixel: [CUnsignedChar] = [0, 0, 0, 0] 

     let colorSpace = CGColorSpaceCreateDeviceRGB() 
     let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) 

     let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) 

     context!.translateBy(x: -point.x, y: -point.y) 

     self.render(in: context!) 

     let red: CGFloat = CGFloat(pixel[0])/255.0 
     let green: CGFloat = CGFloat(pixel[1])/255.0 
     let blue: CGFloat = CGFloat(pixel[2])/255.0 
     let alpha: CGFloat = CGFloat(pixel[3])/255.0 

     let color = UIColor(red:red, green: green, blue:blue, alpha:alpha) 

     return color.cgColor 
    } 
} 

Swift 2

extension CALayer { 

    func colorOfPoint(point:CGPoint)->CGColorRef 
    { 
     var pixel:[CUnsignedChar] = [0,0,0,0] 

     let colorSpace = CGColorSpaceCreateDeviceRGB() 
     let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue) 

     let context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, bitmapInfo.rawValue) 

     CGContextTranslateCTM(context, -point.x, -point.y) 

     self.renderInContext(context!) 

     let red:CGFloat = CGFloat(pixel[0])/255.0 
     let green:CGFloat = CGFloat(pixel[1])/255.0 
     let blue:CGFloat = CGFloat(pixel[2])/255.0 
     let alpha:CGFloat = CGFloat(pixel[3])/255.0 

     let color = UIColor(red:red, green: green, blue:blue, alpha:alpha) 

     return color.CGColor 
    } 

} 

basata soprattutto sottostante CALayer ma facilmente traducibile ritorna UIView.

+0

grazie così tanto – Jacky

+1

ho provato ad usarlo ma restituisce solo zero. quindi ottengo sempre il colore bianco. sfortunatamente le mie capacità di programmazione non sono così avanzate da scoprirmi. grazie – Lachtan

Problemi correlati