如何在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];
}

