【问题标题】:How can I get the underlying pixel data from a UIImage or CGImage?如何从 UIImage 或 CGImage 获取底层像素数据?
【发布时间】:2011-11-18 21:09:26
【问题描述】:

我在网上尝试了许多“解决方案”,但我发现所有这些解决方案都有错误,因此不起作用。我需要知道 UIImage 中像素的颜色。我怎样才能得到这些信息?

【问题讨论】:

标签: objective-c iphone uiimage cgimage


【解决方案1】:

获取原始数据

来自 Apple 的 Technical Q&A QA1509,它说这将通过从 Data Provider 获取原始格式的原始图像数据。

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

需要不同的格式或色彩空间

如果您想获得颜色匹配的数据并采用特定格式,您可以使用类似于以下代码示例的内容:

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;
}

特定像素的颜色

假设为 RGB,一旦您获得了您喜欢的格式的数据,查找颜色只需在数据数组中移动并在特定像素位置获取 RGB 值。

【讨论】:

【解决方案2】:

如果您只想获得一个像素或几个像素,您可以尝试一些不同的方法。创建一个 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];

【讨论】:

  • 我以前从未使用过 Core Graphics 的东西,所以我不知道该怎么做。你能解释一下我是如何做你一开始解释的,从拥有一个 UIImage 和我想要的像素坐标。
  • @Andrew 我刚刚为imagewidthheight 添加了变量。实际坐标应在offset.xoffset.y 中。代码可能有一个像素左右的问题......但是像这样
猜你喜欢
  • 2010-10-01
  • 2011-01-23
  • 1970-01-01
  • 2011-08-29
  • 2011-06-05
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
相关资源
最近更新 更多