Iphone 从UIImageView获取像素数据——在模拟器上工作,而不是在设备上
根据对的响应,我在UIImageView上创建了一个类别,用于提取像素数据。这在模拟器中可以正常工作,但在部署到设备时则不行。我应该说,不总是这样——奇怪的是,如果point.x==point.y,它确实能获得正确的像素颜色;否则,它会为该行另一侧的像素提供像素数据,就像镜像一样。(因此,点击图像右下角的一个像素可以得到左上角对应像素的像素数据,但点击左下角的一个像素可以返回正确的像素颜色)。触摸坐标(CGPoint)正确 我做错了什么 这是我的密码:Iphone 从UIImageView获取像素数据——在模拟器上工作,而不是在设备上,iphone,uiimageview,pixel,Iphone,Uiimageview,Pixel,根据对的响应,我在UIImageView上创建了一个类别,用于提取像素数据。这在模拟器中可以正常工作,但在部署到设备时则不行。我应该说,不总是这样——奇怪的是,如果point.x==point.y,它确实能获得正确的像素颜色;否则,它会为该行另一侧的像素提供像素数据,就像镜像一样。(因此,点击图像右下角的一个像素可以得到左上角对应像素的像素数据,但点击左下角的一个像素可以返回正确的像素颜色)。触摸坐标(CGPoint)正确 我做错了什么 这是我的密码: @interface UIImageVie
@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;
}
界面UIImageView(PixelColor)
-(UIColor*)getRGBPixelColorAtPoint:(CGPoint)点;
@结束
@实现UIImageView(像素颜色)
-(UIColor*)getRGBPixelColorAtPoint:(CGPoint)点
{
UIColor*color=nil;
CGImageRef cgImage=[self.image cgImage];
大小\u t宽度=CGImageGetWidth(cgImage);
尺寸高度=CGImageGetHeight(cgImage);
NSUInteger x=(NSUInteger)楼层(点x);
NSU整数y=高度-(NSU整数)楼层(点y);
如果((x<宽度)和(y<高度))
{
CGDataProviderRef provider=CGImageGetDataProvider(cgImage);
CFDataRef bitmapData=CGDataProviderCopyData(提供程序);
const UInt8*data=CFDataGetBytePtr(位图数据);
尺寸t偏移=((宽度*y)+x)*4;
UInt8红色=数据[偏移];
UInt8蓝色=数据[偏移量+1];
UInt8绿色=数据[偏移量+2];
UInt8 alpha=数据[偏移量+3];
CFRelease(位图数据);
颜色=[UIColor color WITH red:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];
}
返回颜色;
}
您可以尝试以下替代方法:
- 创建CGBitmapContext
- 将图像绘制到上下文中
- 在上下文上调用CGBitmapContextGetData以获取基础数据
- 计算原始数据中的偏移量(基于创建位图上下文的方式)
- 提取值
这种方法适用于我在模拟器和设备上使用。我认为Rbg是错误的。你有:
UInt8 red = data[offset];
UInt8 blue = data[offset+1];
UInt8 green = data[offset+2];
但你不是真的指Rgb
UInt8 red = data[offset];
UInt8 green = data[offset+1];
UInt8 blue = data[offset+2];
但即使修复了这个问题,仍然存在一个问题,因为苹果(伟大的文章)在设备上显示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)
之后。根据我的经验,在设备上这是而不是。您的代码不应该受到影响,但如果这对其他人有帮助,我想我会提到它。在原始问题中发布的代码中,它看起来是这样的,而不是:
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);
你能检查self.image.imageOrientation的值吗?您使用的图像可能是UIImageOrientationReftMirror中的图像,这可能是您看到的反射,尽管我不知道为什么只有在设备上才会是这样……模拟器和设备上都是UIImageOrientationUp。我不确定“左镜像”是对正在发生的事情的正确解释,因为反射(似乎)是沿着对角线y=x发生的,而UIImageOrientationLeftMirrored是根据SDK对整个图像“逆时针90度”的简单旋转。更多信息:如果我交换x和y的计算方式,行为是相反的——它在设备上工作,但在模拟器上不工作。(虽然设备上的精确定位似乎与逆时针方向相差几度,但可能是我的手指与使用鼠标相比不精确)我正试图避免这种情况,因为涉及的开销(此函数可能每秒调用一次以上)您可以缓存原始数据,然后将开销减少到数组查找,除非图像在不断变化,这是真的。然而,我仍然想知道我上面的代码中的潜在问题是什么。我花了一些时间才最终回到这个问题上来,但是你的代码非常棒。把G和B混在一起,不知道Xcode在幕后的字节顺序变化,这是一个致命的组合。