专栏首页进击的多媒体开发Android NDK 开发 — 从 Assets 文件夹加载图片并上传纹理

Android NDK 开发 — 从 Assets 文件夹加载图片并上传纹理

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

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

该方法的底层原理实际上也是解析了该 Bitmap ,得到了 Bitmap 所有的像素数据,类似于 Android NDK 关于 Bitmap 操作的 AndroidBitmap_lockPixels 方法,如果你不太了解该方法,可以参考这篇文章:Android JNI 之 Bitmap 操作

得到了所有像素数据之后,实际最终还是调用了 OpenGL 的 glTexImage2D 来实现纹理上传。当然,如果可以直接得到所有数据,也不需要走解析 Bitmap 这一步了,这种场景最常见的就是把相机作为输入了。


接下来我们会通过 Android NDK 开发中去渲染一张图片,步骤还是如上,从图像解析到纹理上传,不同的是我们将会解析 Assets 文件夹中的图片,而不是一张已经保存在手机 SDCard 上的图片。

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

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

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

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

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

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

 1    // NDK 中是 AssetManager
 2    AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);
 3    // 打开 Asset 文件夹下的文件
 4    AAsset *pathAsset = AAssetManager_open(mgr, assetPath, AASSET_MODE_UNKNOWN);
 5    // 得到文件的长度
 6    off_t assetLength = AAsset_getLength(pathAsset);
 7    // 得到文件对应的 Buffer
 8    unsigned char *fileData = (unsigned char *) AAsset_getBuffer(pathAsset);
 9    // stb_image 的方法,从内存中加载图片
10    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

本文分享自微信公众号 - 纸上浅谈(glumes_blog),作者:glumes

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android字符串相机

    很早就看到过这种场景,用字符来展示图片甚至播放视频,可以说是黑客炫(zhuang)技(b)神器。当然有了一定的技术之后,就明白其实实现挺简单。

    glumes
  • OpenGL 系列---基础绘制流程

    OpenGL 是一种应用程序编程接口,它是一种可以对图形硬件设备特性进行访问的软件库。

    glumes
  • 博客图床迁移记

    前几天在群里看到说新浪微博图床挂掉了,图床上的图片链接单独访问还可以,但是在博客文章上就显示不出来了。

    glumes
  • 面试官问我:你们的数据库是怎么架构的?

    1、高可用分析:高可用,主库挂了,keepalive(只是一种工具)会自动切换到备库。这个过程对业务层是透明的,无需修改代码或配置。

    黄泽杰
  • 数据库之互联网常用架构方案

    1.高可用分析: 高可用,主库挂了,keepalive(只是一种工具)会自动切换到备库。这个过程对业务层是透明的,无需修改代码或配置。

    小东啊
  • 数据库之架构:主备+分库?主从+读写分离?

    注:图中圈出的是数据同步的地方,数据同步(从库从主库拉取binlog日志,再执行一遍)是需要时间的,这个同步时间内主库和从库的数据会存在不一致的情况。如果同步过...

    用户5546570
  • 28:出现次数超过一半的数

    28:出现次数超过一半的数 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB描述 给出一个含有n(0 < n <= 1000)个...

    attack
  • 跟Google学写代码--Chromium工程中用到的C++11特性

    Ttile 跟Google学写代码--Chromium工程中用到的C++11特性 Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。 《跟...

    程序员的酒和故事
  • C++中的模板基础知识小结

    class类型:class A ,Struct B.。 如:Test<A> t;

    fieldli
  • Leetcode 16. 3Sum Closest

    版权声明:博客文章都是作者辛苦整理的,转载请注明出处,谢谢! https://blog.csdn....

    Tyan

扫码关注云+社区

领取腾讯云代金券