惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
IT之家
IT之家
C
Check Point Blog
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
M
MIT News - Artificial intelligence
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
F
Fortinet All Blogs
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率
Android NDK 开发 —— 从 Assets 文件夹加载图片并上传纹理
音视频开发进阶 · 2019-05-14 · via 音视频开发进阶

一个专注音视频领域的小圈子

在 OpenGL 开发中,我们要渲染一张图片,通常先是得到一张图片对应的 Bitmap ,然后将该 Bitmap 作为纹理上传到 OpenGL 中。在 Android 中有封装好的 GLUtils 类的 texImage2D 方法供我们调用。

    public static void texImage2D(int target, int level, int internalformat,
            Bitmap bitmap, int type, int border)

该方法的底层原理实际上也是解析了该 Bitmap ,得到了 Bitmap 所有的像素数据,类似于 Android NDK 关于 Bitmap 操作的 AndroidBitmap_lockPixels 方法,如果你不太了解该方法,可以参考这篇文章:Android JNI 之 Bitmap 操作。 得到了所有像素数据之后,实际最终还是调用了 OpenGL 的 glTexImage2D 来实现纹理上传。当然,如果可以直接得到所有数据,也不需要走解析 Bitmap 这一步了,这种场景最常见的就是把相机作为输入了。 接下来我们会通过 Android NDK 开发中去渲染一张图片,步骤还是如上,从图像解析到纹理上传,不同的是我们将会解析 Assets 文件夹中的图片,而不是一张已经保存在手机 SDCard 上的图片。

相比于前者,SDCard 上的图片已经有了绝对地址了,直接把地址传到 stb_image 库就可以完成解析了(参考之前的文章 ),而 Assets 文件夹的内容在手机上可没有绝对地址哦,不信你仔细回想,可曾在看到过 APK 安装后 Assets 文件夹对应的内容?

一开始陷入了误区,想着怎么去获得文件的绝对地址,看到了 AssetManager 的 AAsset_openFileDescriptor 方法以为拿到文件描述符就万事大吉了,结果打印的地址是这样的 /proc/9941/fd/79 ,这基本的不可用了。

换个思路,在 Java 中去加载 Assets 目录下的图片:

InputStream is = getAssets().open(fileName); 

通过 AssertManager 的 open 方法直接拿到文件的输入流了。

而在 NDK 开发中同样的方式是行不通的,这里要采用另外一种方式,但其实意思都差不多的:

    // NDK 中是 AssetManager
    AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);
    // 打开 Asset 文件夹下的文件
    AAsset *pathAsset = AAssetManager_open(mgr, assetPath, AASSET_MODE_UNKNOWN);
    // 得到文件的长度
    off_t assetLength = AAsset_getLength(pathAsset);
    // 得到文件对应的 Buffer
    unsigned char *fileData = (unsigned char *) AAsset_getBuffer(pathAsset);
    // stb_image 的方法,从内存中加载图片
    unsigned char *contnet = stbi_load_from_memory(fileData, assetLength, &w, &h, &n, 0);

NDK 中可拿不到像 Java 那样的输入流,但是可以通过 AssetManager 的 AAsset_getBuffer 或者是 AAsset_read 方法去获取文件内容。

看到上面那两个 API 基本就稳了,再配合 stb_image 介绍过的方法,stbi_load_from_memory 从内存中加载图片的像素数据,最后就是 glTexImage2D 方法实现纹理上传。

具体的代码实践参考项目:

https://github.com/glumes/InstantGLSL

原创文章,转载请注明来源:    Android NDK 开发 —— 从 Assets 文件夹加载图片并上传纹理