Cómo obtener el color de píxel en el tacto?

Sé que esta es una pregunta común y hay muchas respuestas a esta pregunta. He usado algo de esto. Aunque muchos de ellos son iguales. Pero lo triste para mí es que ninguno de ellos funcionó para mí. Los siguientes códigos que he usado hasta ahora.

-(void)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy { // First get the image into your data buffer CGImageRef imageRef = [image CGImage]; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGContextRelease(context); // Now your rawData contains the image data in the RGBA8888 pixel format. int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel; CGFloat red = (rawData[byteIndex] * 1.0) / 255.0; CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0; CGFloat blue = (rawData[byteIndex + 2] * 1.0) / 255.0; CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0; byteIndex += 4; NSLog(@"the vale of the rbg of red is %f",red); demoColor.tintColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; free(rawData); } 

Aquí hay otro enfoque que he usado:

 - (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; // Get image width, height. We'll use the entire image. size_t pixelsWide = CGImageGetWidth(inImage); size_t pixelsHigh = CGImageGetHeight(inImage); // Declare the number of bytes per row. Each pixel in the bitmap in this // example is represented by 4 bytes; 8 bits each of red, green, blue, and // alpha. bitmapBytesPerRow = (pixelsWide * 4); bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); // Use the generic RGB color space. //colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); colorSpace = CGColorSpaceCreateDeviceRGB(); if (colorSpace == NULL) { fprintf(stderr, "Error allocating color space\n"); return NULL; } // Allocate memory for image data. This is the destination in memory // where any drawing to the bitmap context will be rendered. bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { fprintf (stderr, "Memory not allocated!"); CGColorSpaceRelease( colorSpace ); return NULL; } // Create the bitmap context. We want pre-multiplied ARGB, 8-bits // per component. Regardless of what the source image format is // (CMYK, Grayscale, and so on) it will be converted over to the format // specified here by CGBitmapContextCreate. context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, // bits per component bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst); if (context == NULL) { free (bitmapData); fprintf (stderr, "Context not created!"); } // Make sure and release colorspace before returning CGColorSpaceRelease( colorSpace ); return context; } - (UIColor*) getPixelColorAtLocation:(CGPoint)point { UIColor* color = nil; //CGImageRef inImage = self.image.CGImage; CGImageRef inImage = [AppDelegate getInstance].capturedImage.CGImage; // Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage]; if (cgctx == NULL) { return nil; /* error */ } size_t w = CGImageGetWidth(inImage); size_t h = CGImageGetHeight(inImage); CGRect rect = {{0,0},{w,h}}; // Draw the image to the bitmap context. Once we draw, the memory // allocated for the context for rendering will then contain the // raw image data in the specified color space. CGContextDrawImage(cgctx, rect, inImage); // Now we can get a pointer to the image data associated with the bitmap // context. unsigned char* data = CGBitmapContextGetData (cgctx); if (data != NULL) { //offset locates the pixel in the data from x,y. //4 for 4 bytes of data per pixel, w is width of one row of data. int offset = 4*((w*round(point.y))+round(point.x)); int alpha = data[offset]; int red = data[offset+1]; int green = data[offset+2]; int blue = data[offset+3]; NSLog(@"offset: %i colors: RGB A %i %i %i %i",offset,red,green,blue,alpha); color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)]; } // When finished, release the context CGContextRelease(cgctx); // Free image data memory for the context if (data) { free(data); } return color; } 

Pero ninguno de estos me ha funcionado. Por favor, ayúdame a trabajar con esto. ¿Hay algo que me pierdo?

Tengo 2 UIImageView en mi UI. El que está en la parte posterior contiene la imagen de la que necesito elegir el color de un píxel que se toca. Y el otro UIImageView es pintar sobre la imagen de atrás con el color elegido.

Por favor ayuda. Cualquier ayuda será muy apreciada.

Este es el que he usado, y parece más simple que los métodos que has probado.

En mi clase de vista personalizada, tengo esto:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; CGPoint loc = [touch locationInView:self]; self.pickedColor = [self colorOfPoint:loc]; } 

colorOfPoint es un método en una categoría en UIView, con este código:

 #import "UIView+ColorOfPoint.h" #import  @implementation UIView (ColorOfPoint) -(UIColor *) colorOfPoint:(CGPoint)point { unsigned char pixel[4] = {0}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast); CGContextTranslateCTM(context, -point.x, -point.y); [self.layer renderInContext:context]; CGContextRelease(context); CGColorSpaceRelease(colorSpace); 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; } 

No olvides importar la categoría en la clase de vista personalizada y agregar el marco QuartzCore.


Nota trivial para 2013: echa el último argumento como (CGBitmapInfo) para evitar una advertencia de conversión implícita: ejemplo aquí . Espero eso ayude.

Gracias por publicar en @Agrgressor el código anterior

Swift 2.1

 func getPixelColorAtPoint(point:CGPoint) -> UIColor{ let pixel = UnsafeMutablePointer.alloc(4) 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) view.layer.renderInContext(context!) let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0) pixel.dealloc(4) return color } 

Swift 3 , Xcode versión 8.2 (8C38) y Swift 4 , Xcode versión 9.1 (9B55)

  func getPixelColorAtPoint(point:CGPoint, sourceView: UIView) -> UIColor{ let pixel = UnsafeMutablePointer.allocate(capacity: 4) 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) var color: UIColor? = nil if let context = context { context.translateBy(x: -point.x, y: -point.y) sourceView.layer.render(in: context) color = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0) pixel.deallocate(capacity: 4) } return color } 

Gran respuesta rdelmar esto me ayudó MUCHO!

Así es como hice lo anterior en Swift:

 override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { var touch:UITouch = event.allTouches()!.anyObject() as UITouch var loc = touch.locationInView(self) var color:UIColor = getPixelColorAtPoint(loc) println(color) } //returns the color data of the pixel at the currently selected point func getPixelColorAtPoint(point:CGPoint)->UIColor { let pixel = UnsafeMutablePointer.alloc(4) var colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue) let context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, bitmapInfo) CGContextTranslateCTM(context, -point.x, -point.y) layer.renderInContext(context) var color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0) pixel.dealloc(4) return color } 

Swift 4, Xcode 9 – Con una extensión UIImageView

Esta es una combinación de todas las respuestas anteriores pero en una extensión

 extension UIImageView { func getPixelColorAt(point:CGPoint) -> UIColor{ let pixel = UnsafeMutablePointer.allocate(capacity: 4) 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) layer.render(in: context!) let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0) pixel.deallocate(capacity: 4) return color } } 

Cómo utilizar

 override func touchesBegan(_ touches: Set, with event: UIEvent?) { let touch = touches.first if let point = touch?.location(in: view) { let color = myUIImageView.getPixelColorAt(point: point) print(color) } }