Getting the pixel data from a CGImage object(Objective-c取得图像的像素信息)

本文介绍如何在MacOSX 10.5及以上版本中直接访问CGImage对象的像素数据,包括使用CGDataProviderCopyData获取原始像素数据的方法,以及在早期版本中通过创建位图上下文并绘制图像来获取像素数据的技巧。

Q: How do I access the pixel data of a CGImage object?

A: On Mac OS X 10.5 or later, a new call has been added that allows you to obtain the actual pixel data from a CGImage object. This call, CGDataProviderCopyData, returns a CFData object that contains the pixel data from the image in question. An example of using this call to obtain pixel data from a CGImage is shown in Listing 1. Once you have the CFData object with your pixel information, you can call CFDataGetBytePtr to get a pointer to the pixel data, or CFDataGetBytes to copy a subrange of pixel data.

Listing 1: Getting raw pixel data from a CGImage.

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

  

Note: CopyImagePixels as written will return NULL if the passed in CGImage object is NULL or if the contents of the image are too large to fit in memory.

WARNING: The pixel data returned by CGDataProviderCopyData has not been color matched and is in the format that the image is in, as described by the various CGImageGet functions (see for Getting Information About an Image more information). If you want the image in a different format, or color matched to a specific color space, then you should draw the image to a bitmap context as described later in this Q&A, with the caveat that alpha information from the image will be multiplied into the color components.

Prior to Mac OS X 10.5 an image's pixels are not as readily available. The only way to guarantee access to the equivalent bits is to create a bitmap context with a memory buffer you specify and then draw the CGImage to the context using CGContextDrawImage. After drawing the CGImage to the context you will have a copy of the data in the buffer you specified (which can also be easily accessed using the CGBitmapContexGetData function). The code in Listing 2 demonstrates how to do this.

IMPORTANT: Listing 2 creates a bitmap context with a 8-bits per component ARGB color space, draws the source image to this context, then retrieves the image bits in this color space from the context. Regardless of what the source image format is (CMYK, 24-bit RGB, Grayscale, and so on) it will be converted over to this color space.

For more information about creating bitmap contexts for other pixel formats, see the Quartz 2D Programming Guide.

Listing 2: Accessing the pixel data of a CGImage.

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

 

原文地址:http://developer.apple.com/library/mac/#qa/qa2007/qa1509.html
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值