从UIImageView获取像素数据 - 适用于模拟器,而不是设备

Sha*_*rog 4 iphone pixel uiimageview

根据对上一个问题的回答,我在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;
}
Run Code Online (Sandbox Code Playgroud)

Mon*_*urd 5

我认为R BG错了.你有:

UInt8 red =   data[offset];     
UInt8 blue =  data[offset+1];
UInt8 green = data[offset+2];
Run Code Online (Sandbox Code Playgroud)

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

UInt8 red =   data[offset];     
UInt8 green = data[offset+1];
UInt8 blue =  data[offset+2];
Run Code Online (Sandbox Code Playgroud)

但即使修复了这个问题,仍然存在一个问题,因为它在设备上发现了苹果字节交换(伟大的文章)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
Run Code Online (Sandbox Code Playgroud)

不确定这是否能解决您的问题,但是在我修复之前,您行为不端的代码看起来与我的样子差不多.

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