好吧,我已经弄清楚了如何尽可能简洁地做到这一点。下面我将解释如何实现这一点并列出所需的所有代码:)
为了允许触摸交互选择像素,首先将 a 添加UITapGestureRecognizer
到您的GLKViewController
子类(假设您想要点击选择像素),在该类中使用以下目标方法。您必须使您的GLKViewController
子类 a UIGestureRecognizerDelegate
:
@interface GLViewController : GLKViewController <GLKViewDelegate, UIGestureRecognizerDelegate>
实例化手势识别器后,将其添加到view
属性中(GLKViewController
实际上是 a GLKView
):
// Inside GLKViewController subclass init/awakeFromNib:
[[self view] addGestureRecognizer:[self tapRecognizer]];
[[self tapRecognizer] setDelegate:self];
为您的手势识别器设置目标操作;您可以在使用特定创建它时执行此操作,init...
但是我使用 Storyboard(又名“Xcode 4.2 中的新界面生成器”)创建我的并以这种方式连接它。
无论如何,这是我对点击手势识别器的目标操作:
-(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:
在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 文档中找到的一些相关代码,标题为:“Getting the pixel data from a CGImage context”,它需要 2 个方法定义而不是这个 1,但需要更多代码,并且有void *
我使用的类型的数据无法实施正确的解释。
就是这样!将此代码添加到您的项目中,然后点击一个像素,它将以以下形式输出:
R:24 G:46 B:244 A:255
当然,您应该编写一些方法来提取这些 RGBA int 值(将在 0 - 255 范围内)并根据需要使用它们。UIColor
一种方法是从上述方法返回 a ,实例化如下:
UIColor *color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];