如何在iPhone上获取图像上像素的RGB值
我正在编写一个iPhone应用程序,实际上需要实现与photoshop中的"吸管"工具等效的功能,在该工具中,我们可以触摸图像上的一个点并捕获相关像素的RGB值以确定并匹配其颜色。获取UIImage很容易,但是有没有一种方法可以将UIImage数据转换为位图表示形式,从而可以提取给定像素的此信息?一个工作代码示例将不胜感激,请注意,我不关心alpha值。
解决方案
我们不能直接访问UIImage的位图数据。
我们需要获取UIImage的CGImage表示形式。然后从该位图的CFData表示中获取CGImage的数据提供程序。完成后,请确保释放CFData。
CGImageRef cgImage = [image CGImage]; CGDataProviderRef provider = CGImageGetDataProvider(cgImage); CFDataRef bitmapData = CGDataProviderCopyData(provider);
我们可能需要查看CGImage的位图信息,以获取像素顺序,图像尺寸等。
为了在应用程序中执行类似的操作,我创建了一个小的屏幕外CGImageContext,然后将UIImage渲染到其中。这使我可以快速提取一次像素。这意味着我们可以以一种易于解析的格式设置目标位图,并让CoreGraphics进行在颜色模型或者位图格式之间进行转换的艰苦工作。
拉霍斯的答案对我有用。为了获得像素数据作为字节数组,我这样做:
UInt8 *数据= CFDataGetBytePtr(bitmapData);
更多信息:CFDataRef文档。
另外,请记住包括CoreGraphics.framework
。
I dont know how to index into image data correctly based on given X,Y cordination. Does anyone know?
pixelPosition =(x +(y ((imagewidth)BytesPerPixel)));
//据我所知,此设备的音高不是问题,可以设为零...
//(或者退出数学运算)。
更多细节...
我今晚早些时候发布了此页面的内容,并在页面底部做了一些补充和补充。不过,我现在正在编辑帖子,以发布我建议的内容(至少出于我的要求,其中包括修改像素数据)是一种更好的方法,因为它提供了可写的数据(据我所知,该方法提供了由以前的帖子提供,并且在这篇文章的底部提供了对数据的只读引用)。
方法1:可写像素信息
- 我定义了常量
#define RGBA 4 #define RGBA_8_BIT 8
- 在我的UIImage子类中,我声明了实例变量:
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;
- 像素结构(在此版本中为Alpha)
typedef struct RGBAPixel { byte red; byte green; byte blue; byte alpha; } RGBAPixel;
- 位图功能(返回预先计算的RGBA;将RGB除以A得到未修改的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.我声明了字节的类型:
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.子类代码我放入了一个名为bitmap的方法(以返回位图像素数据):
//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]; }