如何直接更新像素——使用CGImage和直接CGDataProvider

2023-11-24

实际问题

有几个答案可以解决我的问题:

  1. 我可以强制CGImage从直接数据提供者(使用创建的CGDataProviderCreateDirect) like CGContextDrawImage做?或者有其他方法可以设置 self.layer.contents 来做到这一点吗?
  2. 有没有CGContext我可以使用配置或技巧来渲染 1024x768 图像至少 30 fps 一致CGContextDrawImage.
  3. 有没有人能够成功使用CVOpenGLESTextureCacheCreateTextureFromImage使用自己的纹理数据进行实时缓冲区更新?我认为我最大的问题是创建一个CVImageBuffer因为我从苹果的纹理文档中复制了其他属性。如果有人有更多这方面的信息那就太好了。
  4. 关于如何以 30 fps 的速度从内存中获取图像到屏幕上的任何其他指南。

背景(很多):

我正在开发一个项目,需要实时修改 NPOT 图像数据的像素(至少 30 fps)并将其绘制在 iOS 的屏幕上。

我的第一个想法是使用 OpenGLglTexSubimage2D更新一下,不幸的是,最终速度非常慢(iPad 上为 6 fps),因为驱动程序会调整并将每帧的 RGB 数据转换为 BGR。所以你说用 BGR 发送,我也是,但由于某种原因你不能打电话glTexSubImage2D with GL_BGR去搞清楚。我知道速度有些慢是因为它不是 2 图像数据的幂,但我的要求决定了这一点。

更多的阅读让我CVOpenGLESTextureCacheCreateTextureFromImage但所有示例都是使用直接相机输入来获取CVImageBufferRef我尝试使用文档(没有官方但只有标题注释)来使我自己的 CVImageBuffer 形成我的图像数据,但它不适用于此(没有错误,只是调试器中的空纹理),这让我认为苹果专门构建了这个处理实时相机数据,除了 IDK 之外,它还没有在该领域之外进行过太多测试。

无论如何,在放弃我的尊严、放弃 OpenGL 并将我的想法转向 CoreGraphics 之后,我被引出了这个问题在 iPhone 上绘制屏幕缓冲区的最快方法建议使用CGImage受支持CGDataProviderCreateDirect,它允许您在 CGImage 需要时返回指向图像数据的指针,很棒吧?嗯,它似乎并不像广告中所说的那样有效。如果我使用CGContextDrawImage然后一切正常。我可以修改像素缓冲区,并且每次绘制时,它都会像应该的那样从我的数据提供程序请求图像数据,调用中的方法CGDataProviderDirectCallbacks (Note:他们似乎有一个内置的优化,如果更新的指针与先前的地址相同,则忽略更新的指针)。即使禁用插值,CGContextDrawImage 也不是超级快(大约 18 fps),这将其从大约 6 fps 提高了。苹果的文档告诉我使用self.layer.contents会比CGContextDrawImage. Using self.layer.contents适用于第一个作业,但CGImage永远不会像这样从数据提供者请求重新加载CGContextDrawImage即使我打电话时也是如此[layer setNeedsDisplay]。在我引用的SO问题中,用户通过每帧从数据源创建和销毁一个新的CGImage来展示他对问题的解决方案,这是一个极其缓慢的过程(是的,我确实尝试过),所以是时候讨论真正的问题了。

Note:我已经分析了所有这些操作并知道问题确实在于glTexSubImage对于 OpenGL 和CGContextDrawImage这确实是 CoreGraphics 的问题,所以没有“转到配置文件”答案。

EDIT现在可以在以下位置找到演示此技术的源代码http://github.com/narpas/image-sequence-streaming


感谢 Brad Larson 和 David H 帮助解决了这一问题(请参阅评论中的完整讨论)。结果使用 OpenGL 和 CoreVideoCVOpenGLESTextureCache最终成为将原始图像推送到屏幕的最快方式(我知道 CoreGraphics 不可能是最快的!),在 iPad 1 上为我提供 60 fps 的全屏 1024x768 图像。现在关于此的文档很少,所以我会尝试并尽可能多地解释以帮助人们:

CVOpenGLESTextureCacheCreateTextureFromImage允许您创建一个 OpenGL 纹理,其内存直接映射到CVImageBuffer你用来创建它。这允许您创建一个CVPixelBuffer使用您的原始数据并修改从收集的数据指针CVPixelBufferGetBaseAddress。这可以在 OpenGL 中为您提供即时结果,无需修改或重新上传实际纹理。请务必锁定CVPixelBufferLockBaseAddress在修改像素之前并在完成后解锁。请注意,目前这在 iOS 模拟器中不起作用,仅在我推测来自 VRAM/RAM 分区的设备上起作用,其中 CPU 无法直接访问 VRAM。 Brad 建议使用条件编译器检查来在原始版本之间切换glTexImage2D更新并使用纹理缓存。

有几件事需要注意(这些因素的结合导致它对我不起作用):

  1. 在设备上测试
  2. 确保你CVPixelBuffer支持kCVPixelBufferIOSurfacePropertiesKey see link例如(再次感谢布拉德)。
  3. 你必须使用GL_CLAMP_TO_EDGE用于 OpenGL ES 2.0 的 NPOT 纹理数据
  4. 绑定纹理缓存glBindTexture(CVOpenGLESTextureGetTarget(_cvTexture), CVOpenGLESTextureGetName(_cvTexture));不要像我一样愚蠢并使用CVOpenGLESTextureGetTarget对于这两个参数。
  5. 不要每帧重新创建纹理,只需将图像数据复制到从CVPixelBufferGetBaseAddress更新纹理。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何直接更新像素——使用CGImage和直接CGDataProvider 的相关文章

随机推荐

  • 在 10.9 上以编程方式启用对辅助设备的访问

    我想在 10 9 上以编程方式启用对辅助设备的访问 在 10 8 及更低版本中 我使用以下 Applescript 来启用对辅助设备的访问 tell application System Events if UI elements enab
  • 是否可以更改扩展WPF工具包的Busyindicator中的忙碌动画?

    是否可以更改扩展WPF工具包的Busyindicator中的忙碌动画 特别是 我想将其更改为 gif 动画 是的当然 您可以定义自己的自定义内容 文档 繁忙指示器自定义内容示例
  • 具有相同名称的控制器的 asp.net Web api 路由

    我正在将我的项目与另一个项目集成 Multiple types were found that match the controller named XXXXX This can happen if the route that servi
  • persp3d 图的格式

    我有以下 3d 图 With my data我用以下代码创建了它 library rugarch library rgl library fGarch fd lt as data frame modelfit which density c
  • 适用于 Firefox 的 WebDriver:浏览器启动时为空页面,挂起 2 分钟,重新启动,然后测试运行。为什么?

    我正在尝试更新我的 Java 测试套件以使用 Selenium 3 和 geckodriver 但是 我在执行测试命令时看到了这种非常奇怪的行为 Firefox 将打开一个空白页面 这样保持大约2分钟 它关闭然后立即重新启动 测试运行并通过
  • 我可以打开一个套接字并将其传递给 Linux 中的另一个进程吗

    在Linux中 我是否可以打开一个套接字并将该套接字传递给另一个进程 如果是 您能告诉我在哪里可以找到示例吗 谢谢 是的 你可以 使用sendmsg 使用 SCM RIGHTS 从一个进程到另一个进程 SCM RIGHTS 发送或接收一组
  • 在 ActionBarSherlock 中使用自定义布局构建 ActionMode

    我刚刚开始使用 ActionBarSherlock 来构建一些简单的应用程序 在我的第一个屏幕中 我有简单的列表 并添加了新的菜单项以将新项目添加到列表中 MenuItem newItem menu add New newItem setI
  • Entity Framework 4.1 - 刷新不是 Context 的成员

    我正在尝试使用 Context Refresh 方法恢复 Context 更改 但 Refresh 似乎不是 Context 的成员 我正在使用 Microsoft ADO NET Entity Framework 4 1 RC 版本 任何
  • C# CPU 和 GPU 温度

    我正在为系统性能创建个人监控程序 但在弄清楚 C 如何检索 CPU 和 GPU 温度信息时遇到问题 我已经让程序通过 PerformanceCounter 检索 CPU 负载和频率信息 以及各种其他信息 但我无法找到 CPU 温度的实例 对
  • python中urllib的响应时间

    我想在使用时获得响应时间urllib 我做了下面的代码 但它超过了响应时间 我可以利用时间吗urllib或者有其他方法吗 import urllib import datetime def main urllist http google
  • java中如何调用抽象类方法

    我想在我自己的类中调用抽象类的方法 抽象类是 public abstract class Call public Connection getEarliestConnection Connection earliest null retur
  • 在 Go 包中哪里放​​置测试的共享代码? [复制]

    这个问题在这里已经有答案了 我有一个包含多个文件的 Go 包 按照 Go 标准 我正在为包中的每个源文件创建一个关联的测试文件 就我而言 不同的测试使用相同的测试帮助功能 我不希望这些函数出现在包源文件中 因为它仅用于测试目的 我还想避免在
  • 编辑文本最大长度并在 texview 中显示长度

    我有一个编辑文本和一个文本视图 我想在编辑文本中设置最大长度 它显示在我的文本视图中 每次用户输入字符时 它都会减去字符数 例如 我将编辑文本的最大长度设置为 150 如果用户输入 150 个字符 他 她就无法再输入了 如何解决这个问题 设
  • 抓取亚马逊时被阻止(即使有标头、代理、延迟)[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我有一个Python代码来抓取亚马逊产品列表 我已经设置了代理和标头 我也有sleep 每次爬行之前 但是 我仍然无法获取数据 我收到的消息是 要讨论自动访问亚马逊数据 请联系
  • 如果两个不同网站上的会话名称相同,会发生什么情况?

    我有两个差异 项目在我的XAMPP说是Project1 and Project2 当我登录时Project1 我检查身份验证 如果成功则存储会话 会话名称是 SESSION username 上述过程与Project2 现在 为了防止直接访
  • ffmpeg退出状态-1094995529

    我正在开发一个应用程序 使打电话给ffprobe返回非正统的退出状态 1094995529对于 Windows 上的某些文件 这个退出状态是一致给出的 并且有一些小的讨论这个的 为什么给出这个值 它记录在哪里 我是否可以期望此状态在允许的退
  • document.getElementByID 外部还是内联?

    我一直在尝试使用document getElementByID从外部 JS 文件中提取 HTML 文件的信息 但它似乎不起作用 是否document getElementByID仅当它与 HTML 文件内联时才有效 或者它可以在外部 JS
  • 如何让 Windows 窗体设计器使用外部程序集中的资源?

    我在资源文件中有一些资源 在本例中为图像 我在 Windows 窗体项目中的控件上使用这些资源 Visual Studio 资源选择对话框没有很好地支持从资源文件中选择图像 除非它们位于特定位置 但您可以直接编辑设计器文件 这工作得很好 应
  • 如何使用 git-bundle 保持开发同步?

    我需要使我的开发树在不同的计算机上保持同步 并且它们之间没有网络连接 我们有一个中央 git 存储库 我通常在我的办公室计算机上使用我自己的克隆 有时我需要在另一台从未连接到办公网络的计算机上进行一些开发 没有一台计算机曾经连接到互联网 可
  • 如何直接更新像素——使用CGImage和直接CGDataProvider

    实际问题 有几个答案可以解决我的问题 我可以强制CGImage从直接数据提供者 使用创建的CGDataProviderCreateDirect like CGContextDrawImage做 或者有其他方法可以设置 self layer