2009-07-21 14 views
27

Próbuję opracować małą aplikację. W tym celu muszę wykryć kolor piksela w ramach UIView. Mam CGPoint określający piksel, którego potrzebuję. Kolory UIView są zmieniane za pomocą CoreAnimation.Jak uzyskać kolor piksela w UIView?

Wiem, że istnieją pewne skomplikowane sposoby wyodrębniania informacji o kolorach z UIImages. Jednak nie mogłem znaleźć rozwiązania dla UIViews.

W Pseudo-Code szukam czegoś jak

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

dowolnego wejścia mile widziana.

+0

Czy znalazłeś (szybkie) rozwiązanie? – CodeAndCats

+0

Korzystanie z kontekstu bitmapy okazało się wystarczająco szybkie dla moich celów. Spróbuj i zobacz, jak to działa. – 0x90

Odpowiedz

8

Jest dość okropny i powolny. Zasadniczo tworzysz bitmapowy kontekst z przydzielonym rezerwowaniem, dzięki czemu możesz odczytać pamięć, następnie renderujesz warstwę widoków w kontekście i czytasz odpowiedni punkt w pamięci RAM.

Jeśli wiesz, jak to zrobić dla obrazu już można zrobić coś takiego:

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

    return retval; 
} 

A potem dostaniesz obrazu, gdzie można uzyskać danych pikseli. Jestem pewien, że mechanizm, z jakim masz do czynienia z obrazami, polega na renderowaniu ich do kontekstu, więc możesz połączyć to z tym i obliczyć rzeczywiste tworzenie obrazu. Więc jeśli to zrobisz i usuniesz bit, w którym załadujesz obraz i zastąp go renderowaniem kontekstowym:

powinieneś być dobry.

3

Poprawiono kilka drobnych błędów

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

    return retval; 
} 

Również dodać

#import <QuartzCore/QuartzCore.h> 

do pliku, aby uniknąć komunikatów ostrzegawczych.

Łączenie kodu z znalezionym kodem here działa bezbłędnie.

+0

Dlaczego wygląda na to, że skopiowałeś kod Louisa i usunąłeś zbędną "pustkę" w wywołaniu 'UIGraphicsGetImageFromCurrentImageContext()'? –

+1

To właśnie zrobiłem. Jaki jest lepszy sposób obsługi korekt tutaj? – 0x90

70

Tutaj jest bardziej efektywne rozwiązanie:

// 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 do plików: https://github.com/ivanzoid/ikit/tree/master/UIView+ColorOfPoint

+0

Ostrzeżenie w .m, usunięte z '#import ' – Jonny

+0

Wygląda na to, że renderujesz tylko jeden piksel. Bardzo fajny. – mahboudz

+1

@mahboudz: tak, masz absolutną rację – ivanzoid

14

swift'ified wersja ivanzoid „s odpowiedzi

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 
    } 

} 

skupione wokół leżącej CALayer ale łatwo przetłumaczyć z powrotem do UIView.

+0

dzięki tak bardzo – Jacky

+1

próbowałem go użyć, ale zwraca tylko zera. więc zawsze mam biały kolor. niestety moje umiejętności programistyczne nie są tak zaawansowane, aby się samemu dowiedzieć. Dziękuję Ci – Lachtan

Powiązane problemy