【问题标题】:EAGLView to UIImage timing questionEAGLView 转 UIImage 计时问题
【发布时间】:2011-10-26 05:36:07
【问题描述】:

我有一个想要转换为 UIImage 的 EAGLView。我可以使用此处发布的解决方案来做到这一点:

How to get UIImage from EAGLView?

但是,如果在创建 EAGLView 和 UIImage 之间经过了一小段时间,我只能完成此操作。

这段代码,它创建了一个 EAGLView,然后是一个 UIImageView,它不起作用:

EAGLView *EAGLphoto = [[EAGLView alloc] initWithImage:photo.workAreaImage];

[theWorkArea.photoArea1 addSubview:EAGLphoto];

//I put a glfinish() here but it didn't help

UIImageView *photoView = [[UIImageView alloc] initWithImage:[self glToUIImage]];
//glToUIImage is taken from the link above

[theWorkArea.photoArea2 addSubview:photoView];

我假设 UIImageView 尝试在 EAGLView 完成创建之前创建。我试图在两者之间放置一个 glfinish() 但它什么也没做。当我运行代码时,EAGLView 显示正常,但 UIImageView 显示为黑色。

但是,上面代码的这个修改版本可以工作:

EAGLView *EAGLphoto = [[EAGLView alloc] initWithImage:photo.workAreaImage];

[theWorkArea.photoArea1 addSubview:EAGLphoto];

[self performSelector:@selector(getUIImage) withObject:nil afterDelay:0.1];

- (void)getUIImage {

    UIImageView *photoView = [[UIImageView alloc] initWithImage:[self glToUIImage]];
    //glToUIImage is taken from the link above

    [theWorkArea.photoArea2 addSubview:photoView];

}

我是否错误地使用了 glfinish()?有没有比我的 hack 更好的方法?

【问题讨论】:

  • 你试过 afterDelay:0.0 吗?这有助于诊断。
  • Tommy,添加 0.0 的延迟仍然有效,我不知道为什么。有什么想法吗?

标签: iphone ios uiview opengl-es eaglview


【解决方案1】:

通常,当您对 UIKit 对象进行可见更改而不是立即更新时,它们只会标记自己以在将来进行这些更改,然后在您下次放弃主线程时将整个更改集作为批处理(通过返回到运行循环)。这不是实现中的错误或失败,实际上通常是您隐含的期望,这就是您可以编写如下代码的原因:

view.frame = someNewFrame;
view.someOtherProperty = someOtherValue;

不用担心视图会在采用其他更改之前经常明显地采用新框架。通常,您希望对视图执行的操作看起来是原子的。

有时您会遇到一种情况,就像您在这里遇到的情况一样,您已经请求的更改尚未生效的事实被暴露出来。 framesomeOtherProperty 将在上面的示例中返回它们的新值,因此您不必关心更改是否立即生效,但根据您对 performSelector:withObject:afterDelay: 的观察,您似乎可能偶然发现变化不会立即发生的情况。

EAGLView 很难诊断,因为它不是真正的 UIKit 功能。它所基于的 CAEAGLLayer 是,但 EAGLView 只是 Apple 在各种示例项目中为基于 CAEAGLLayer 构建的自定义 UIView 子类采用的名称。他们在他们的示例中对EAGLView 的接口或实现并不一致,但我猜测它可能正在创建 OpenGL 帧缓冲区对象(即 OpenGL 用来存储与像素,允许glReadPixels 工作)仅在被要求布置时,并且在 UIKit 要求它这样做之前它不会布置自己。直到你退出 runloop。

可以通过检查您拥有的EAGLView 的代码来确认该诊断。如果由于layoutSubviewsdrawRect 或其他未被相关init 直接调用的方法而触发了对glGenFramebuffers 之类的调用,那么这就证明了这一点。

假设诊断正确,您可以适应EAGLView,但我认为最好的解决方案可能就是坚持使用performSelector:withObject:afterDelay:0。这不是竞争条件,因此该解决方案一点也不可靠或不可靠,它只是一种稍微迂回的说法“让 UIKit 赶上所有这些指令,因为我知道这会让 EAGLView进入有意义的状态,然后继续我的工作”。

【讨论】:

  • 汤米,你是对的。由于 EAGLView 是在 layoutSubviews 函数中绘制的,因此在转换为 UIImage 之前等待该函数完成就可以了,谢谢!
  • Tommy,你似乎对这个话题很了解,也许你可以帮我解决下一个问题:stackoverflow.com/questions/7086468/…
猜你喜欢
  • 2011-10-28
  • 1970-01-01
  • 2010-11-24
  • 2012-08-11
  • 2020-06-03
  • 1970-01-01
  • 2010-11-23
  • 2010-12-21
  • 2011-12-23
相关资源
最近更新 更多