2009-07-21 10 views
27

J'essaie de développer une petite application. Dans celui-ci, j'ai besoin de détecter la couleur d'un pixel dans un UIView. J'ai un CGPoint définissant le pixel dont j'ai besoin. Les couleurs de l'UIView sont modifiées en utilisant CoreAnimation.Comment obtenir la couleur d'un pixel dans un UIView?

Je sais qu'il existe des moyens complexes d'extraire des informations de couleur à partir de UIImages. Cependant, je n'ai pas trouvé de solution pour UIViews.

En pseudo-code Je cherche quelque chose comme

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

Toute entrée très appréciée.

+0

Avez-vous trouvé une solution (rapide)? – CodeAndCats

+0

L'utilisation du contexte bitmap s'est avérée assez rapide pour mes besoins. Essayez-le et voyez comment cela fonctionne pour vous. – 0x90

Répondre

8

C'est assez horrible et lent. Fondamentalement, vous créez un contexte bitmap avec un magasin de sauvegarde que vous allouez afin que vous puissiez lire la mémoire, puis vous affichez le calque de vues dans le contexte et lisez le point approprié dans le ram.

Si vous savez comment le faire pour une image déjà que vous pouvez faire quelque chose comme ceci:

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

    return retval; 
} 

Et vous obtiendrez une image où vous pouvez obtenir les données de pixels. Je suis sûr que le mécanisme que vous avez pour traiter les images implique de les rendre dans un contexte de toute façon, de sorte que vous pouvez fusionner cela avec cela et prendre en compte la création d'image réelle. Donc, si vous prenez et qui pourrait supprimer le bit où vous chargez l'image et le remplacer par le contexte rendu:

[view.layer renderInContext: UIGraphicsGetCurrentContext()]; 

vous devriez être bon.

3

Correction de quelques erreurs mineures

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

    return retval; 
} 

, ajoutez également

#import <QuartzCore/QuartzCore.h> 

à votre fichier pour éviter les messages d'avertissement. Combiner votre code avec le code here fonctionne parfaitement.

+0

Pourquoi semble-t-il que vous avez simplement copié le code de Louis et supprimé le «vide» superflu dans l'appel de 'UIGraphicsGetImageFromCurrentImageContext()'? –

+1

C'est ce que j'ai fait. Quelle est la meilleure façon de gérer les corrections ici? – 0x90

70

Voici une solution plus efficace:

// 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 

Lien vers les fichiers: https://github.com/ivanzoid/ikit/tree/master/UIView+ColorOfPoint

+0

Avertissement en .m, supprimé avec '#import ' – Jonny

+0

Il semble que vous ne visualisez qu'un seul pixel. Très sympa. – mahboudz

+1

@mahboudz: oui, vous avez absolument raison – ivanzoid

14

Une version swift'ified réponse de de ivanzoid

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 
    } 

} 

basé autour du CALayer sous-jacente mais facilement traduisible retour à UIView.

+0

merci tellement – Jacky

+1

j'ai essayé de l'utiliser, mais il renvoie juste des zéros. donc je reçois toujours la couleur blanche. Malheureusement, mes compétences en programmation ne sont pas si avancées pour me découvrir. Je vous remercie – Lachtan

Questions connexes