简体   繁体   English

如何从UIImage或CGImage获取基础像素数据?

[英]How can I get the underlying pixel data from a UIImage or CGImage?

I've tried numerous 'solutions' around the net, all of those I found have errors and thus don't work. 我在网上尝试了许多“解决方案”,发现的所有解决方案都有错误,因此无法正常工作。 I need to know the color of a pixel in a UIImage. 我需要知道UIImage中像素的颜色。 How can i get this information? 我如何获得此信息?

Getting the raw data 获取原始数据

From Apple's Technical Q&A QA1509 it says this will get the raw image data in it's original format by getting it from the Data Provider. 苹果公司的技术问答QA1509表示,它将通过从数据提供商处获取原始格式的原始图像数据。

CFDataRef CopyImagePixels(CGImageRef inImage) 
{     
   return CGDataProviderCopyData(CGImageGetDataProvider(inImage)); 
}

Needed in a different format or color-space 需要不同的格式或颜色空间

If you want to get the data color-matched and in a specific format you can use something similar to the following code sample: 如果要获得颜色匹配的数据并采用特定格式,则可以使用类似于以下代码示例的内容:

void ManipulateImagePixelData(CGImageRef inImage)
{
    // Create the bitmap context
    CGContextRef cgctx = CreateARGBBitmapContext(inImage);
    if (cgctx == NULL) 
    { 
        // error creating context
        return;
    }

     // Get image width, height. We'll use the entire image.
    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.
    void *data = CGBitmapContextGetData (cgctx);
    if (data != NULL)
    {

        // **** You have a pointer to the image data ****

        // **** Do stuff with the data here ****

    }

    // When finished, release the context
    CGContextRelease(cgctx); 
    // Free image data memory for the context
    if (data)
    {
        free(data);
    }

}

CGContextRef CreateARGBBitmapContext (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);
    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;
}

Color of a particular pixel 特定像素的颜色

Assuming RGB, once you have the data in a format you like finding the color is a matter of moving through the array of data and getting the RGB value at a particular pixel location. 假设为RGB,一旦有了某种格式的数据,就喜欢查找颜色,这是在数据数组中移动并在特定像素位置获取RGB值的问题。

If you're looking to just get a single pixel or a few ones you can look to do a little different approach. 如果您只想获得一个像素或几个像素,可以尝试采用一些不同的方法。 Create a 1x1 bitmap context and draw the image over it with an offset so you just get the pixel you want. 创建一个1x1位图上下文,并在其上绘制具有偏移量的图像,以便仅获取所需的像素。

CGImageRef image = uiimage.CGImage;
NSUInteger width = CGImageGetWidth(image);
NSUInteger height = CGImageGetHeight(image);

// Setup 1x1 pixel context to draw into
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char rawData[4];
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, 
                                             1, 
                                             1, 
                                             bitsPerComponent,
                                             bytesPerRow,
                                             colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy);

// Draw the image
CGContextDrawImage(context,
                   CGRectMake(-offset.x, offset.y-height, width, height),
                   image);

// Done
CGContextRelease(context);

// Get the pixel information     
unsigned char red   = rawData[0];
unsigned char green = rawData[1];
unsigned char blue  = rawData[2];
unsigned char alpha = rawData[3];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM