如何获取iPhone上的图像上的像素的RGB值

我正在写一个iPhone应用程序,需要基本上实现一些相当于Photoshop中的“吸pipe”工具,在那里你可以触摸图像上的一个点,并捕获有问题的像素的RGB值,以确定和匹配它的颜色。 获取UIImage是很容易的一部分,但有没有办法将UIImage数据转换成位图表示,在这种表示中我可以为给定的像素提取这些信息? 一个工作代码示例将不胜感激,请注意,我不关心alpha值。

多一点细节…

我今天早些时候发布了一个整合,并且在本页上发表了一些内容 – 可以在这篇文章的底部find。 我现在正在编辑这个post,但是,张贴我所build议的(至less对于我的要求,包括修改像素数据)是一个更好的方法,因为它提供了可写的数据(而据我所知,提供的方法通过以前的post和在这篇文章的底部提供了对数据的只读引用)。

方法1:可写入的像素信息

  1. 我定义了常量

    #define RGBA 4 #define RGBA_8_BIT 8 
  2. 在我的UIImage子类中,我声明了实例variables:

     size_t bytesPerRow; size_t byteCount; size_t pixelCount; CGContextRef context; CGColorSpaceRef colorSpace; UInt8 *pixelByteData; // A pointer to an array of RGBA bytes in memory RPVW_RGBAPixel *pixelData; 
  3. 像素结构(在这个版本中有alpha)

     typedef struct RGBAPixel { byte red; byte green; byte blue; byte alpha; } RGBAPixel; 
  4. 位图函数(返回预先计算的RGBA;用A除RGB得到未修改的RGB):

     -(RGBAPixel*) bitmap { NSLog( @"Returning bitmap representation of UIImage." ); // 8 bits each of red, green, blue, and alpha. [self setBytesPerRow:self.size.width * RGBA]; [self setByteCount:bytesPerRow * self.size.height]; [self setPixelCount:self.size.width * self.size.height]; // Create RGB color space [self setColorSpace:CGColorSpaceCreateDeviceRGB()]; if (!colorSpace) { NSLog(@"Error allocating color space."); return nil; } [self setPixelData:malloc(byteCount)]; if (!pixelData) { NSLog(@"Error allocating bitmap memory. Releasing color space."); CGColorSpaceRelease(colorSpace); return nil; } // Create the bitmap context. // Pre-multiplied RGBA, 8-bits per component. // The source image format will be converted to the format specified here by CGBitmapContextCreate. [self setContext:CGBitmapContextCreate( (void*)pixelData, self.size.width, self.size.height, RGBA_8_BIT, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast )]; // Make sure we have our context if (!context) { free(pixelData); NSLog(@"Context not created!"); } // Draw the image to the bitmap context. // The memory allocated for the context for rendering will then contain the raw image pixelData in the specified color space. CGRect rect = { { 0 , 0 }, { self.size.width, self.size.height } }; CGContextDrawImage( context, rect, self.CGImage ); // Now we can get a pointer to the image pixelData associated with the bitmap context. pixelData = (RGBAPixel*) CGBitmapContextGetData(context); return pixelData; } 

只读数据(以前的信息) – 方法2:


第1步。我声明了一个字节types:

  typedef unsigned char byte; 

第2步。我宣布一个结构对应于一个像素:

  typedef struct RGBPixel{ byte red; byte green; byte blue; } RGBPixel; 

第3步。我分类UIImageView并声明(与相应的综合属性):

 // Reference to Quartz CGImage for receiver (self) CFDataRef bitmapData; // Buffer holding raw pixel data copied from Quartz CGImage held in receiver (self) UInt8* pixelByteData; // A pointer to the first pixel element in an array RGBPixel* pixelData; 

第4步。子类代码我把一个名为位图的方法(返回位图像素数据):

 //Get the bitmap data from the receiver's CGImage (see UIImage docs) [self setBitmapData: CGDataProviderCopyData(CGImageGetDataProvider([self CGImage]))]; //Create a buffer to store bitmap data (unitialized memory as long as the data) [self setPixelBitData:malloc(CFDataGetLength(bitmapData))]; //Copy image data into allocated buffer CFDataGetBytes(bitmapData,CFRangeMake(0,CFDataGetLength(bitmapData)),pixelByteData); //Cast a pointer to the first element of pixelByteData //Essentially what we're doing is making a second pointer that divides the byteData's units differently - instead of dividing each unit as 1 byte we will divide each unit as 3 bytes (1 pixel). pixelData = (RGBPixel*) pixelByteData; //Now you can access pixels by index: pixelData[ index ] NSLog(@"Pixel data one red (%i), green (%i), blue (%i).", pixelData[0].red, pixelData[0].green, pixelData[0].blue); //You can determine the desired index by multiplying row * column. return pixelData; 

第5步。我做了一个访问器的方法:

 -(RGBPixel*)pixelDataForRow:(int)row column:(int)column{ //Return a pointer to the pixel data return &pixelData[row * column]; } 

这是我的UIImage的颜色取样解决scheme。

这种方法将请求的像素渲染成1px大的RGBA缓冲区,并以UIColor对象的forms返回结果的颜色值。 这比我见过的大多数其他方法要快得多,而且只用很less的内存。

这对于像颜色select器这样的应用程序来说应该是非常好的,在任何给定的时间,通常只需要一个特定像素的值。

的UIImage + Picker.h

 #import <UIKit/UIKit.h> @interface UIImage (Picker) - (UIColor *)colorAtPosition:(CGPoint)position; @end 

的UIImage + Picker.m

 #import "UIImage+Picker.h" @implementation UIImage (Picker) - (UIColor *)colorAtPosition:(CGPoint)position { CGRect sourceRect = CGRectMake(position.x, position.y, 1.f, 1.f); CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, sourceRect); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char *buffer = malloc(4); CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; CGContextRef context = CGBitmapContextCreate(buffer, 1, 1, 8, 4, colorSpace, bitmapInfo); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0.f, 0.f, 1.f, 1.f), imageRef); CGImageRelease(imageRef); CGContextRelease(context); CGFloat r = buffer[0] / 255.f; CGFloat g = buffer[1] / 255.f; CGFloat b = buffer[2] / 255.f; CGFloat a = buffer[3] / 255.f; free(buffer); return [UIColor colorWithRed:r green:g blue:b alpha:a]; } @end 

你不能直接访问UIImage的位图数据。

您需要获取UIImage的CGImage表示。 然后从这个位图的CFData表示中获取CGImage的数据提供者。 确保完成后释放CFData。

 CGImageRef cgImage = [image CGImage]; CGDataProviderRef provider = CGImageGetDataProvider(cgImage); CFDataRef bitmapData = CGDataProviderCopyData(provider); 

您可能需要查看CGImage的位图信息以获取像素顺序,图像尺寸等。

拉霍斯的答案为我工作。 为了像素数据作为一个字节数组,我做到了这一点:

UInt8* data = CFDataGetBytePtr(bitmapData);

更多信息:CFDataRef 文档 。

此外,请记住包括CoreGraphics.framework

感谢大家! 把这些答案放在一起我得到:

 - (UIColor*)colorFromImage:(UIImage*)image sampledAtPoint:(CGPoint)p { CGImageRef cgImage = [image CGImage]; CGDataProviderRef provider = CGImageGetDataProvider(cgImage); CFDataRef bitmapData = CGDataProviderCopyData(provider); const UInt8* data = CFDataGetBytePtr(bitmapData); size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); size_t width = CGImageGetWidth(cgImage); size_t height = CGImageGetHeight(cgImage); int col = px*(width-1); int row = py*(height-1); const UInt8* pixel = data + row*bytesPerRow+col*4; UIColor* returnColor = [UIColor colorWithRed:pixel[0]/255. green:pixel[1]/255. blue:pixel[2]/255. alpha:1.0]; CFRelease(bitmapData); return returnColor; } 

对于x和y,这只需要0.0-1.0的范围。 例:

 UIColor* sampledColor = [self colorFromImage:image sampledAtPoint:CGPointMake(px/imageView.frame.size.width, py/imageView.frame.size.height)]; 

这对我很好。 我正在做一些像素位和RGBA色彩空间的假设,但这应该适用于大多数情况。

还有一点需要注意的是,它同时适用于模拟器和设备 – 由于在设备上进行PNG优化,我以前遇到过这个问题。

为了在我的应用程序中做类似的事情,我创build了一个小屏幕外的CGImageContext,然后把UIImage渲染到它里面。 这允许我一次快速提取多个像素。 这意味着你可以用你容易parsing的格式设置目标位图,让CoreGraphics在颜色模型或位图格式之间进行转换。

我不知道如何基于给定的X,Y坐标正确地索引图像数据。 有人知道吗?

pixelPosition =(x +(y *((imagewidth)* BytesPerPixel)));

/ /沥青是不是这个设备的问题,据我所知,可以让零…(或从math中拉出)。

使用ANImageBitmapRep可以进行像素级访问(读/写)。