好吧,我已经弄清楚如何尽可能简洁地做到这一点。下面我解释如何实现这一点并列出所需的所有代码:)
为了允许触摸交互选择像素,首先添加一个UITapGestureRecognizer
给你的GLKViewController
子类(假设您想要点击选择像素),并在该类中使用以下目标方法。你必须让你的GLKViewController
子类aUIGestureRecognizerDelegate
:
@interface GLViewController : GLKViewController <GLKViewDelegate, UIGestureRecognizerDelegate>
实例化手势识别器后,将其添加到view
财产(其中在GLKViewController
实际上是一个GLKView
):
// Inside GLKViewController subclass init/awakeFromNib:
[[self view] addGestureRecognizer:[self tapRecognizer]];
[[self tapRecognizer] setDelegate:self];
设置手势识别器的目标动作;您可以在使用特定的创建它时执行此操作init...
然而,我使用 Storyboard(又名“Xcode 4.2 中的新 Interface Builder”)创建了我的,并以这种方式连接它。
无论如何,这是我的点击手势识别器的目标操作:
-(IBAction)onTapGesture:(UIGestureRecognizer*)recognizer {
const CGPoint loc = [recognizer locationInView:[self view]];
[self pickAtX:loc.x Y:loc.y];
}
那里调用的 pick 方法是我在我的内部定义的GLKViewController
子类:
-(void)pickAtX:(GLuint)x Y:(GLuint)y {
GLKView *glkView = (GLKView*)[self view];
UIImage *snapshot = [glkView snapshot];
[snapshot pickPixelAtX:x Y:y];
}
这利用了一种方便的新方法snapshot
Apple 善意地将其纳入其中GLKView
生产一个UIImage
从底层EAGLContext
.
值得注意的是评论中的评论snapshot
API 文档,其中指出:
只要您的应用程序显式地调用此方法
需要视图的内容;切勿尝试直接阅读
使用 OpenGL ES 函数的底层帧缓冲区的内容。
这给了我一个线索,解释为什么我之前尝试调用glReadPixels
在尝试访问生成的像素数据EXC_BAD_ACCESS
,以及让我走上正确道路的指标。
你会注意到我的pickAtX:Y:
刚才定义的方法我称之为pickPixelAtX:Y:
on the UIImage
。这是我添加的一个方法UIImage
在自定义类别中:
@interface UIImage (NDBExtensions)
-(void)pickPixelAtX:(NSUInteger)x Y:(NSUInteger)y;
@end
这是实现;这是所需的最终代码清单。代码来自这个问题并根据那里收到的答复进行了修改:
@implementation UIImage (NDBExtensions)
- (void)pickPixelAtX:(NSUInteger)x Y:(NSUInteger)y {
CGImageRef cgImage = [self CGImage];
size_t width = CGImageGetWidth(cgImage);
size_t height = CGImageGetHeight(cgImage);
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 b = data[offset+0];
UInt8 g = data[offset+1];
UInt8 r = data[offset+2];
UInt8 a = data[offset+3];
CFRelease(bitmapData);
NSLog(@"R:%i G:%i B:%i A:%i",r,g,b,a);
}
}
@end
我最初尝试了在 Apple API 文档中找到的一些相关代码,标题为:“从 CGImage 上下文获取像素数据”,它需要 2 个方法定义而不是这 1 个,但是需要更多代码并且存在类型的数据void *
对此我无法实施正确的解释。
就是这样!将此代码添加到您的项目中,然后在点击像素时,它将以以下形式输出:
R:24 G:46 B:244 A:255
当然,您应该编写一些方法来提取这些 RGBA int 值(范围为 0 - 255)并根据需要使用它们。一种方法是返回一个UIColor
从上面的方法,实例化如下:
UIColor *color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];