- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在制作一个 PDF 注释器,当您切换页面时,它必须重新绘制所有以前绘制的 OpenGL 内容(以 JSON 格式保存到文件中)。问题是绘制的内容越多,花费的时间越长。我为每个页面都将一个 UIImage 保存到磁盘,因此我希望通过一次大笔画将该 UIImage 绘制到 EAGLContext 上来加快这个过程。
我想知道如何获取 UIImage(或 JPEG/PNG 文件)并将其直接绘制到屏幕上。它必须在 EAGLView 上的原因是因为它需要支持橡皮擦,而使用常规的 UIKit 方式将无法使用。
我假设有一些方法可以将画笔设置为整个图像,然后只用它在屏幕上标记一次。有什么建议吗?
最佳答案
作为迂腐的注释,there is no standard class named EAGLView ,但我假设您指的是 Apple 的示例 UIView 子类之一,该子类托管 OpenGL ES 内容。
这样做的第一步是将 UIImage 加载到纹理中。以下是我在我的图像处理框架中为此使用的一些代码(newImageSource
是输入 UIImage):
CGSize pointSizeOfImage = [newImageSource size];
CGFloat scaleOfImage = [newImageSource scale];
pixelSizeOfImage = CGSizeMake(scaleOfImage * pointSizeOfImage.width, scaleOfImage * pointSizeOfImage.height);
CGSize pixelSizeToUseForTexture = pixelSizeOfImage;
BOOL shouldRedrawUsingCoreGraphics = YES;
// For now, deal with images larger than the maximum texture size by resizing to be within that limit
CGSize scaledImageSizeToFitOnGPU = [GPUImageOpenGLESContext sizeThatFitsWithinATextureForSize:pixelSizeOfImage];
if (!CGSizeEqualToSize(scaledImageSizeToFitOnGPU, pixelSizeOfImage))
{
pixelSizeOfImage = scaledImageSizeToFitOnGPU;
pixelSizeToUseForTexture = pixelSizeOfImage;
shouldRedrawUsingCoreGraphics = YES;
}
if (self.shouldSmoothlyScaleOutput)
{
// In order to use mipmaps, you need to provide power-of-two textures, so convert to the next largest power of two and stretch to fill
CGFloat powerClosestToWidth = ceil(log2(pixelSizeOfImage.width));
CGFloat powerClosestToHeight = ceil(log2(pixelSizeOfImage.height));
pixelSizeToUseForTexture = CGSizeMake(pow(2.0, powerClosestToWidth), pow(2.0, powerClosestToHeight));
shouldRedrawUsingCoreGraphics = YES;
}
GLubyte *imageData = NULL;
CFDataRef dataFromImageDataProvider;
if (shouldRedrawUsingCoreGraphics)
{
// For resized image, redraw
imageData = (GLubyte *) calloc(1, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * 4);
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 8, (int)pixelSizeToUseForTexture.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), [newImageSource CGImage]);
CGContextRelease(imageContext);
CGColorSpaceRelease(genericRGBColorspace);
}
else
{
// Access the raw image bytes directly
dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider([newImageSource CGImage]));
imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
}
glBindTexture(GL_TEXTURE_2D, outputTexture);
if (self.shouldSmoothlyScaleOutput)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
if (self.shouldSmoothlyScaleOutput)
{
glGenerateMipmap(GL_TEXTURE_2D);
}
if (shouldRedrawUsingCoreGraphics)
{
free(imageData);
}
else
{
CFRelease(dataFromImageDataProvider);
}
如你所见,这有一些函数用于调整超过设备最大纹理大小的图像(上面代码中的类方法仅查询最大纹理大小),以及一个 bool 标志是否为纹理生成 mipmap 以实现更平滑的下采样。如果您不关心这些情况,可以删除这些。这也是 OpenGL ES 2.0 代码,因此您可能需要将一两个 OES
后缀添加到上面的某些函数中,以便它们与 1.1 一起使用。
在纹理中拥有 UIImage 后,您可以使用带纹理的四边形(两个三角形组成一个矩形,角具有适当的纹理坐标)将其绘制到屏幕上。如何做到这一点在 OpenGL ES 1.1 和 2.0 之间会有所不同。对于 2.0,您使用直通着色器程序,该程序仅从纹理中的该位置读取颜色并将其绘制到屏幕上;对于 1.1,您只需为几何体设置纹理坐标并绘制两个三角形。
我在 this answer 中有一些用于此的 OpenGL ES 2.0 代码.
关于objective-c - 将 UIImage(或 JPEG)绘制到 EAGLView 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11958037/
当我收到内存警告级别 1 时,我的 EAGLView 开始吐出一行 openGL 错误(502 和 506),并且应用程序没有崩溃,但 EAGLView 变得无响应。由于 Cocos2d Direct
...沮丧。我希望我的游戏仅在横向模式下运行。我已将适当的键/值添加到 Info.plist 文件中,以强制设备方向在启动时正确。 我现在正在尝试旋转 OpenGL 坐标空间以匹配设备的坐标空间。我正
重新启动我的游戏时,它崩溃并显示内存不足警告。我正在寻找一种关闭 EAGLView 并停止所有进程的方法。我不确定要向您展示什么,所以如果需要,请询问更多信息。 我有一个带有 mainGameLoop
我在使用 Apple 的 EAGLView 和 Texture2D 时遇到了一些问题。如果我创建一个 EAGLView 实例并绘制一些纹理,效果会很好。但是,每当我创建 EAGLView 的第二个实例
我正在尝试将我的 CCScene 类(class)附加到我的 EAGLView。所以我的 EAGLView 是 1 类中的 IBOutlet。我连接它并设置和获取它。然后在我的 Class 1 的 V
我有一个 UITableView,每个单元格内有 3 个 EAGLView,用户可以在其中绘制一些东西(在 apple GLPaint 之后,我只是使用该示例中的 PaintingView 类) 我试
我有一个 EAGLView,我希望将其转换为 UIImage。我可以使用此处发布的解决方案来做到这一点: How to get UIImage from EAGLView? 但是,如果在创建 EAGL
我有一个在 iPad 上运行的应用程序,它使用大量纹理,渲染到一个 EAGLView 中。现在我需要第二个 EAGLView,与第一个共享纹理。 通过修复 Apple 代码中的一些设计错误(例如,默认
我有一个显示 OpenGL 3D 模型的 EAGLView 和一个显示图像的 UIImageView。 我想要的是在具有透明背景的 UIImageView 上方显示 EAGLView。 有什么方法可以
我有一个 EAGLView(取自 Apple 的示例),我可以使用以下代码将其成功转换为 UIImage: - (UIImage *)glToUIImage:(CGSize)size { NSInte
我见过 EAGLView 和 GLKView 都用在 iOS 应用程序中。它们有什么区别? 最佳答案 这两个类都与 OpenGL ES 相关,但实际上只有一个由 Apple 作为 iOS SDK 的一
我在 EAGLView 层上渲染了一个 opengl 场景,并在 UIView 上渲染了一些其他元素(圆圈等)(它是 EAGLView 的同级,位于其上方)。是否可以在两层之间混合颜色?我想做一些差异
我有一个 EAGLView,我正在动画中调整其大小,动画由调用绘图函数的 NSTimer 驱动。当我调整 EAGLView 的大小时,我需要调整 View 的投影以保持内容的纵横比。绘制函数如下所示:
我正在制作 OpenGL 游戏并希望同时支持纵向和横向。我编写了所有必要的代码来支持自动旋转,并希望通过以下方式通知我的游戏有关视口(viewport)大小的更改 [[NSNotificationCe
是否可以在EAGLView中使用UIKit类? 例如,是否可以在 EAGLView 中使用 UIScrollView,或者您是否需要重新实现某些内容? 最佳答案 据我所知 EAGLView 是一个 U
在我的 ios 应用程序中,我正在尝试录制 EAGLView 内容的视频(没有摄像头参与)。我录制视频没有问题。录制后,我必须向视频添加一些音轨,然后必须将此视频分享到 Youtube 和 faceb
我必须在我的 iOS 应用程序中的一些其他 View 之上覆盖一个(大部分)透明的 OpenGL View ,但是在我的 iPod touch(第一代,尽管是 iPhone OS 3.1)上进行的测试
我有一个 EAGLView,它有一个 EAGLLayer 作为支持层。我的应用程序基于 UIKit,但我想全屏显示基于 OpenGL 的图表。删除底层 View 会很痛苦,我只想在其他任何内容之上显示
试图获得 Cocos2D和 openFrameworks在 iOS 上一起玩得很好。两者都想使用 GL/EAGLview,当然他们不能同时使用 glView = [[EAGLView alloc] i
我已经实现了GPUImage framework在我的 cocos2d 项目中,GPUImage 框架是一个 BSD 许可的 iOS 库,可让您将 GPU 加速滤镜和其他效果应用于图像、实时摄像机视频
我是一名优秀的程序员,十分优秀!