检索UIImage的像素Alpha值
我目前正在尝试获取一个像素在UIImageView中的alpha值。 我从[UIImageView图像]获得了CGImage,并从中创build了一个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);
然后我使用UIImageView中的坐标来计算给定alpha通道的数组索引。
int byteIndex = (bytesPerRow * uiViewPoint.y) + uiViewPoint.x * bytesPerPixel; unsigned char alpha = rawData[byteIndex + 3];
但是,我没有得到我期望的价值。 对于图像的完全黑色的透明区域,我得到了alpha通道的非零值。 我是否需要翻译UIKit和Core Graphics之间的坐标 – 即:y轴是否倒置? 还是我误解了预乘alpha值?
更新:
@尼古拉·鲁赫的build议是关键。 事实上我并不需要在UIKit坐标和Core Graphics坐标之间进行翻译。 但是,设置混合模式后,我的alpha值是我所期望的:
CGContextSetBlendMode(context, kCGBlendModeCopy);
是的,CGContexts的y轴向上,而在UIKit它指向下。 看文档 。
阅读代码后编辑:
您还希望在绘制图像之前将混合模式设置为replace,因为您需要图像的alpha值,而不是之前在上下文缓冲区中的值:
CGContextSetBlendMode(context, kCGBlendModeCopy);
思考后编辑:
你可以通过构build最小可能的CGBitmapContext(1×1像素?也许8×8?有一个尝试),并在绘制之前将上下文转换为你想要的位置来进行查找:
CGContextTranslateCTM(context, xOffset, yOffset);
如果所有你想要的是一个点的alpha值,所有你需要的是一个alpha-only单点缓冲区。 我相信这应该就足够了:
// 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;
如果UIImage不必每次都重新创build,这是非常有效的。
编辑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;
我认为这将解决翻转问题。
我在研究如何使用图像数据的alpha值而不是矩形边界框进行精灵之间的碰撞检测时发现了这个问题/答案。 上下文是一个iPhone应用程序…我试图做上述build议1像素绘制,我仍然有问题得到这个工作,但我发现一个更简单的方法创build一个CGContextRef使用图像本身的数据,和帮手function在这里:
CGContextRef context = CGBitmapContextCreate( rawData, CGImageGetWidth(cgiRef), CGImageGetHeight(cgiRef), CGImageGetBitsPerComponent(cgiRef), CGImageGetBytesPerRow(cgiRef), CGImageGetColorSpace(cgiRef), kCGImageAlphaPremultipliedLast );
这绕过了上面示例中所有丑陋的硬编码。 最后一个值可以通过调用CGImageGetBitmapInfo()来获取,但在我的情况下,它从图像中返回一个值,导致ContextCreate函数中出现错误。 只有某些组合是有效的,如下所示: http : //developer.apple.com/qa/qa2001/qa1037.html
希望这是有帮助的!
我是否需要翻译UIKit和Core Graphics之间的坐标 – 即:y轴是否倒置?
这是可能的。 在CGImage中,像素数据是英文阅读顺序:从左到右,从上到下。 所以,arrays中的第一个像素是左上angular; 第二个像素是顶行左边的一个; 等等
假设你有这个权利,你也应该确保你正在寻找一个像素内的正确组件。 也许你期待RGBA,但要求ARGB,反之亦然。 或者,也许你有字节顺序错误(我不知道iPhone的sorting是什么)。
还是我误解了预乘alpha值?
听起来不像。
对于那些不知道的人来说:预乘意味着颜色分量被alpha预乘; 无论颜色分量是否被预乘,alpha分量都是相同的。 您可以通过将颜色分量除以alpha来反转(无预测)。