2009-07-21 12 views
27

Tôi đang cố gắng phát triển một ứng dụng nhỏ. Trong đó, tôi cần phát hiện màu của một pixel trong một UIView. Tôi có một CGPoint xác định pixel tôi cần. Màu sắc của UIView được thay đổi bằng cách sử dụng CoreAnimation.Cách lấy màu của pixel trong UIView?

Tôi biết có một số cách phức tạp để trích xuất thông tin màu từ UIImages. Tuy nhiên tôi không thể tìm thấy một giải pháp cho UIViews.

Trong Pseudo-Code Tôi đang tìm kiếm một cái gì đó giống như

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

Bất kỳ đầu vào đánh giá rất cao.

+0

Bạn có tìm thấy giải pháp (nhanh) không? – CodeAndCats

+0

Sử dụng ngữ cảnh bitmap hóa ra đủ nhanh cho mục đích của tôi. Hãy thử và xem nó hoạt động như thế nào cho bạn. – 0x90

Trả lời

8

Khá khủng khiếp và chậm. Về cơ bản bạn tạo ra một bối cảnh bitmap với một cửa hàng sao lưu bạn phân bổ để bạn có thể đọc bộ nhớ, sau đó bạn render lớp khung nhìn trong ngữ cảnh và đọc điểm thích hợp trong ram.

Nếu bạn biết làm thế nào để làm điều đó cho một hình ảnh đã được bạn có thể làm một cái gì đó như thế này:

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

    return retval; 
} 

Và sau đó bạn sẽ nhận được một hình ảnh nơi bạn có thể lấy dữ liệu pixel. Tôi chắc chắn rằng cơ chế bạn có để xử lý hình ảnh liên quan đến việc đưa chúng vào một ngữ cảnh, vì vậy bạn có thể hợp nhất với điều này và tạo ra yếu tố tạo ra hình ảnh thực tế. Vì vậy, nếu bạn thực hiện điều đó và xóa bit mà bạn tải hình ảnh và thay thế nó bằng ngữ cảnh hiển thị:

[view.layer renderInContext: UIGraphicsGetCurrentContext()]; 

bạn nên làm tốt.

3

Cố định một số lỗi nhỏ

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

    return retval; 
} 

Ngoài ra, thêm

#import <QuartzCore/QuartzCore.h> 

đến tập tin của bạn để tránh thông điệp cảnh báo.

Kết hợp mã của bạn với mã được tìm thấy here hoạt động hoàn hảo.

+0

Tại sao nó trông giống như bạn chỉ cần sao chép mã của Louis và loại bỏ các "không có giá trị" thừa trong cuộc gọi đến 'UIGraphicsGetImageFromCurrentImageContext()'? –

+1

Đó là những gì tôi đã làm. Một cách tốt hơn để xử lý sửa chữa ở đây là gì? – 0x90

70

Đây là giải pháp hiệu quả hơn:

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

Liên kết đến tập tin: https://github.com/ivanzoid/ikit/tree/master/UIView+ColorOfPoint

+0

Cảnh báo bằng .m, bị xóa bằng '#import ' – Jonny

+0

Có vẻ như bạn đang hiển thị chỉ một pixel. Rất tuyệt. – mahboudz

+1

@mahboudz: vâng, bạn hoàn toàn chính xác – ivanzoid

14

Một phiên bản swift'ified của ivanzoid 's câu trả lời

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 
    } 

} 

dựa trên những tiềm ẩn CALayer nhưng dễ dàng thể dịch lại UIView.

+0

cảm ơn rất nhiều – Jacky

+1

tôi đã cố gắng sử dụng nó nhưng nó trả về chỉ số không. nên tôi luôn có màu trắng. tiếc là kỹ năng lập trình của tôi không quá tiên tiến để tìm ra bản thân mình. cảm ơn bạn – Lachtan