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

时间:2020-03-06 14:49:46  来源:igfitidea点击:

我正在编写一个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];           
}