4

根据对上一个问题的回答,我在 UIImageView 上创建了一个用于提取像素数据的类别。这在模拟器中工作正常,但在部署到设备时却不行。我应该说并非总是如此——奇怪的是,如果 point.x == point.y; 它确实会获取正确的像素颜色;否则,它会为我提供该线另一侧像素的像素数据,就像镜像一样。(因此,点击图像右下角的像素会给我左上角相应像素的像素数据,但点击左下角的像素会返回正确的像素颜色)。触摸坐标(CGPoint)是正确的。

我究竟做错了什么?

这是我的代码:

@interface UIImageView (PixelColor)
- (UIColor*)getRGBPixelColorAtPoint:(CGPoint)point;
@end

@implementation UIImageView (PixelColor)

- (UIColor*)getRGBPixelColorAtPoint:(CGPoint)point
{
    UIColor* color = nil;

    CGImageRef cgImage = [self.image CGImage];
    size_t width = CGImageGetWidth(cgImage);
    size_t height = CGImageGetHeight(cgImage);
    NSUInteger x = (NSUInteger)floor(point.x);
    NSUInteger y = height - (NSUInteger)floor(point.y);

    if ((x < width) && (y < height))
    {
        CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
        CFDataRef bitmapData = CGDataProviderCopyData(provider);
        const UInt8* data = CFDataGetBytePtr(bitmapData);
        size_t offset = ((width * y) + x) * 4;
        UInt8 red = data[offset];
        UInt8 blue = data[offset+1];
        UInt8 green = data[offset+2];
        UInt8 alpha = data[offset+3];
        CFRelease(bitmapData);
        color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];
    }

    return color;
}
4

3 回答 3

5

我认为 R BG是错误的。你有:

UInt8 red =   data[offset];     
UInt8 blue =  data[offset+1];
UInt8 green = data[offset+2];

但你真的不是说 R GB吗?:

UInt8 red =   data[offset];     
UInt8 green = data[offset+1];
UInt8 blue =  data[offset+2];

但即使修复了这个问题,仍然存在问题,因为事实证明 Apple字节交换(很棒的文章)在设备上时 R 和 B 值,但在模拟器上时不是。

我在 CFDataGetBytePtr 返回的 PNG 像素缓冲区中遇到了类似的模拟器/设备问题。

这为我解决了这个问题:

#if TARGET_IPHONE_SIMULATOR
        UInt8 red =   data[offset];
        UInt8 green = data[offset + 1];
        UInt8 blue =  data[offset + 2];
#else
        //on device
        UInt8 blue =  data[offset];       //notice red and blue are swapped
        UInt8 green = data[offset + 1];
        UInt8 red =   data[offset + 2];
#endif

不确定这是否能解决您的问题,但您的行为不端代码看起来与我修复它之前的样子很接近。

data[]最后一件事:我相信模拟器即使在CFRelease(bitmapData)被调用之后也会让你访问你的像素缓冲区。在设备上,根据我的经验,情况并非如此。您的代码不应该受到影响,但如果这对其他人有帮助,我想我会提到它。

于 2010-06-10T13:01:48.550 回答
0

您可以尝试以下替代方法:

  • 创建一个 CGBitmapContext
  • 将图像绘制到上下文中
  • 在上下文上调用 CGBitmapContextGetData 以获取底层数据
  • 计算出原始数据的偏移量(基于您创建位图上下文的方式)
  • 提取价值

这种方法在模拟器和设备上适用于我。

于 2009-12-17T08:34:50.723 回答
0

在原始问题中发布的代码中看起来像这样,而不是:

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = height - (NSUInteger)floor(point.y);

它应该是:

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = (NSUInteger)floor(point.y);
于 2010-12-26T19:12:08.947 回答