检索UIImage的像素alpha值

tea*_*bot 35 iphone core-graphics quartz-graphics uikit

我目前正在尝试获取UIImageView中像素的alpha值.我从[UIImageView image]中获取了CGImage,并从中创建了一个RGBA字节数组.Alpha是预乘的.

CGImageRef image = uiImage.CGImage;
NSUInteger width = CGImageGetWidth(image);
NSUInteger height = CGImageGetHeight(image);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
rawData = malloc(height * width * 4);
bytesPerPixel = 4;
bytesPerRow = bytesPerPixel * width;

NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(
    rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace,
    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
);
CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGContextRelease(context);
Run Code Online (Sandbox Code Playgroud)

然后,我使用UIImageView中的坐标计算给定alpha通道的数组索引.

int byteIndex = (bytesPerRow * uiViewPoint.y) + uiViewPoint.x * bytesPerPixel;
unsigned char alpha = rawData[byteIndex + 3];
Run Code Online (Sandbox Code Playgroud)

但是我没有得到我期望的价值.对于图像的完全黑色透明区域,我得到alpha通道的非零值.我是否需要翻译UIKit和Core Graphics之间的坐标 - 即:y轴是倒置的吗?或者我误解了预乘alpha值?

更新:

@Nikolai Ruhe的建议是关键.我实际上并不需要在UIKit坐标和Core Graphics坐标之间进行转换.但是,在设置混合模式后,我的alpha值就是我的预期:

CGContextSetBlendMode(context, kCGBlendModeCopy);
Run Code Online (Sandbox Code Playgroud)

mat*_*att 36

如果你想要的只是单个点的alpha值,你只需要一个只有alpha的单点缓冲区.我相信这应该足够了:

// assume im is a UIImage, point is the CGPoint to test
CGImageRef cgim = im.CGImage;
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel, 
                                         1, 1, 8, 1, NULL,
                                         kCGImageAlphaOnly);
CGContextDrawImage(context, CGRectMake(-point.x, 
                                   -point.y, 
                                   CGImageGetWidth(cgim), 
                                   CGImageGetHeight(cgim)), 
               cgim);
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
BOOL transparent = alpha < 0.01;
Run Code Online (Sandbox Code Playgroud)

如果不必每次都重新创建UIImage,这非常有效.

编辑2011年12月8日:

一位意见提供者指出,在某些情况下,图像可能会被翻转.我一直在考虑这个,我有点遗憾,我没有直接使用UIImage编写代码,就像这样(我认为原因是当时我不明白UIGraphicsPushContext):

// assume im is a UIImage, point is the CGPoint to test
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel, 
                                             1, 1, 8, 1, NULL,
                                             kCGImageAlphaOnly);
UIGraphicsPushContext(context);
[im drawAtPoint:CGPointMake(-point.x, -point.y)];
UIGraphicsPopContext();
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
BOOL transparent = alpha < 0.01;
Run Code Online (Sandbox Code Playgroud)

我认为这样可以解决翻转问题.

  • 出于某种原因,我不得不使用以下行作为`CGContextDrawImage(...`:`CGContextDrawImage(context,CGRectMake(-point.x, - (image.size.height-point.y),CGImageGetWidth(cgim), CGImageGetHeight(cgim)),cgim);` (3认同)

Nik*_*uhe 10

是的,CGContexts的y轴向上,而在UIKit中,它指向下方.查看文档.

阅读代码后编辑:

您还希望在绘制图像之前将混合模式设置为替换,因为您需要图像的alpha值,而不是之前上下文缓冲区中的值:

CGContextSetBlendMode(context, kCGBlendModeCopy);
Run Code Online (Sandbox Code Playgroud)

思考后编辑:

你可以做,查找更有效地通过建立尽可能小的CGBitmapContext(1x1像素的8x8也许有一试?)和绘图之前转换的背景下,以你想要的位置:

CGContextTranslateCTM(context, xOffset, yOffset);
Run Code Online (Sandbox Code Playgroud)