Android NDK图形API篇

前言

我们知道,在游戏和多媒体领域,图形和图像的处理速度和性能至关重要,在Java层处理图形、图像速度又比较慢,不能满足实际的需要,这时候我们就可以借助原生图形API来让自己的游戏和多媒体应用表现更出色。

本篇重点介绍原生图形API的相关知识,并通过一些示例,让大家更好的掌握原生图形API的相关知识。

原生图形API

原生图形API的种类

l  JNI图形API也叫位图API

l  Open GL ES API

l  原生Window API

JNI图形API也叫位图API

需要引用的头文件

#include <android/bitmap.h>

需要引用的so库

jnigraphics.so

JNI图形API函数解析

获取Bitmap对象信息

int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo*info);

enum AndroidBitmapFormat {ANDROID_BITMAP_FORMAT_NONE      = 0,ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,ANDROID_BITMAP_FORMAT_RGB_565   = 4,ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,ANDROID_BITMAP_FORMAT_A_8       = 8,
};typedef struct {uint32_t    width;uint32_t    height;uint32_t    stride;int32_t     format;uint32_t    flags;      // 0 for now
} AndroidBitmapInfo;

函数解析

env,指JNIEnv结构体指针

jbitmap,指android的Bitmap对象

info,指AndroidBitmapInfo结构体指针

如果函数调用成功,返回0,否则返回-1

示例代码

AndroidBitmapInfo info;
int result=AndroidBitmap_getInfo(env,bitmap,&info);
锁定Bitmap像素缓存
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);

函数解析

env,指JNIEnv结构体指针

jbitmap,指android的Bitmap对象

addrPtr,指指向jbitmap对象的像素数据指针

如果函数调用成功,返回0,否则返回-1

示例代码

int32_t *buffer=0;
result=AndroidBitmap_lockPixels(env,bitmap,(void**)&buffer);

解锁Bitmap像素缓存
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);

函数解析

env,指JNIEnv结构体指针

jbitmap,指android的Bitmap对象

如果函数调用成功,返回0,否则返回-1

示例代码

AndroidBitmap_unlockPixels(env,bitmap);

JNI图形API示例

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_render(JNIEnv* env, jobject thiz,jobject bitmap,jobject bitmap2){
    int32_t *buffer=0;
    AndroidBitmapInfo info;
    int result=AndroidBitmap_getInfo(env,bitmap,&info);

result=AndroidBitmap_lockPixels(env,bitmap,(void**)&buffer);

int32_t *data=0;
   result=AndroidBitmap_lockPixels(env,bitmap2,(void**)&data);
    long len= sizeof(int)*info.width*info.height;
    //memcpy(buffer,data,len);
   
memmove(buffer,data,len);
    AndroidBitmap_unlockPixels(env,bitmap2);
   AndroidBitmap_unlockPixels(env,bitmap);
}

其中bitmap是一个动态生成的bitmap,没有位图数据,bitmap2是一个真实的图像bitmap,这个例子要做的就是把bitmap2的位图数据复制到bitmap的位图数据所指向的地址空间里面。

Open GL ES API

需要引用的头文件

Open GL ES 1.x头文件

#include <GLES/gl.h>

#include <GLES/glext.h>

Open GL ES 2.x头文件

#include <GLES2/gl2.h>

#include <GLES2/gl2ext.h>

需要引用的so库

Open GL ES 1.x库文件

GLESV1_CM.so

Open GL ES 2.x库文件

GLESv2.so

GLSurfaceView

如果原生代码需要使用Open GL ES的相关函数来进行view的渲染,在android端需要使用GLSurfaceView进显示渲染后的内容

Open GL ES API函数解析

关于Open GL ES API,由于这个函数库比较大,涉及的函数比较多,请大家参考专业的Open GL ES相关的书籍,这里就不再介绍了。

Open GL ES API示例

请大家参考Open GL ES的相关书箱或者官方教程

原生Window API

需要引用的头文件

#include <android/native_window.h>

#include<android/native_window_jni.h>

需要引用的so库

android.so

原生Window API函数解析

从Surface对象中检索原生Window

ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);

函数解析

env,指JNIEnv结构体的指针

suerface,指向android的Surface对象

如果函数调用成功,返回指向ANativeWindow的指针,否则返回NULL

获取原生Window实例中的引用

void ANativeWindow_acquire(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

这个函数的功能就是防止引用的surface对象被删除,获取一个指向surface对象的引用

释放原生Window实例中的引用

void ANativeWindow_release(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

这个函数的功能就是释放通过ANativeWindow_acquire函数获取的surface对象的引用

检索原生Window的信息
获取原生window的宽度

int32_t ANativeWindow_getWidth(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

如果调用成功,返回原生window的宽度,否则返回-1

获取原生window的高度

int32_t ANativeWindow_getHeight(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

如果调用成功,返回原生window的高度,否则返回-1

获取原生window的像素格式

int32_t ANativeWindow_getFormat(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

如果函数调用成功,返回原生window的像素格式,否则返回-1

设置原生window缓冲区的几何形状

int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
        int32_t width, int32_t height,int32_t format);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

width,设置原生window的宽度

height,设置原生window的高度

format,设置原生window的像素格式

如果函数调用成功,返回0,否则,返回-1

锁定原生Window的缓冲区

typedef struct ANativeWindow_Buffer {
    // The number ofpixels that are show horizontally.
   
int32_t width;

// The number ofpixels that are shown vertically.
   
int32_t height;

// The number of*pixels* that a line in the buffer takes in
    // memory.  This may be >= width.
   
int32_t stride;

// The format of thebuffer.  One of WINDOW_FORMAT_*
   
int32_t format;

// The actual bits.
   
void* bits;
   
    // Do not touch.
   
uint32_t reserved[6];
} ANativeWindow_Buffer;

int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer*outBuffer,
        ARect* inOutDirtyBounds);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

outBuffer,指向ANativeWindow_Buffer结构体的指针,

inOutDirtyBounds,指向ARect结构体的指针,这个参数为可选参数

如果函数调用成功,返回0,否则,返回-1

释放原生Window的缓冲区

int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);

函数解析

window,指通过ANativeWindow_fromSurface函数获取的ANativeWindow指针

如果函数调用成功,返回0,否则,返回-1

SurfaceView

在android层要想使用原生windowAPI,我们需要使用SurfaceView来和原生windowAPI配置,我们可以通过SurfaceView来获取原生windowAPI需要的surface对象

原生Window API示例

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_render2(JNIEnv* env, jobject thiz,jobject surface,jobject bitmap){
    AndroidBitmapInfo info;
   AndroidBitmap_getInfo(env,bitmap,&info);
    int dataLen= sizeof(int) * info.width *info.height;

char *data=NULL;
    AndroidBitmap_lockPixels(env,bitmap,(void**)&data);
    AndroidBitmap_unlockPixels(env,bitmap);

ANativeWindow *window=ANativeWindow_fromSurface(env,surface);
//    intwidth=ANativeWindow_getWidth(window);
//    intheight=ANativeWindow_getHeight(window);
//    intformat=ANativeWindow_getFormat(window);
//   ANativeWindow_setBuffersGeometry(window,width,height,format);

ANativeWindow_acquire(window);

ANativeWindow_BufferwindowBuffer;
   ANativeWindow_lock(window,&windowBuffer,NULL);

dataLen= sizeof(int)*windowBuffer.width*windowBuffer.height;

if (windowBuffer.bits != NULL) {
        //memcpy(windowBuffer.bits,data, dataLen);
       
if (windowBuffer.width == windowBuffer.stride) {
            memcpy(windowBuffer.bits, data, dataLen);
        } else {
            int offset=windowBuffer.stride-windowBuffer.width;
            for (int ii=0; ii <windowBuffer.height*2; ii++) {
                char *srcPointer = data+ windowBuffer.width * ii*2;
                char *dstPointer = ((char *)windowBuffer.bits) + windowBuffer.stride * ii*2;

memcpy(dstPointer,srcPointer, windowBuffer.stride*2);
            }
        }
    }

ANativeWindow_release(window);

ANativeWindow_unlockAndPost(window);
}

结束语

本篇介绍了android NDK三种原生图形API,各有所长,大家可以根据需要来选用,对于最强大最复杂的Open GL ES的内容,本篇暂时不作深入介绍,有兴趣的同学可以参考其它Open GL ES的专业书籍或教程来系统的学习。

Android NDK提供的这三种强大的图形API,让我们可以在游戏和多媒体领域充分发挥我们所长,设计和开发中精美的作品。

本篇文章只是抛砖引玉,大家如果想在图形图像领域有所成就,仅仅学习本篇文章是远远不够的。大家还需要在图形图像领域进行更深入的学习和研究。

最后,祝大家在NDK原生技术领域越走越远,都能成为NDK原生应用开发专家。

Android NDK图形API篇相关推荐

  1. CMake 构建项目Android NDK项目基础知识

    本篇文章将介绍如何使用 CMake 构建实现你的第一个 NDK 项目. ##前言 你好!欢迎来到我的的学习笔记分享系列,第一次给大家分享的是 Android NDK 开发的学习笔记,让我们先开始了解 ...

  2. Android开发之高德API篇:2、高德API线路规划

    TIME:2020年7月6日 2.高德API线路规划----步行线路规划 前言: step1 工程配置 step2 整体实现过程 step3 具体实现过程 总结 附上源码 前言: 该篇博客主要是介绍高 ...

  3. Google宣布支持Vulkan作为Android的底层图形API

    很多人在刚听到底层图形API的时候似乎都不怎么激动,但是苹果已经在去年的iOS 8上推出了Metal,并计划于今秋将之推送至Mac OS X EI Capitan.此外,刚刚发布的Windows 10 ...

  4. Android NDK开发篇(一):新版NDK环境搭建(免Cygwin,超级快)

    以前做Android的项目要用到NDK就必须要 下载NDK,下载安装Cygwin(模拟Linux环境用的),下载CDT(Eclipse C/C++开发插件),还要配置编译器,环境变量... 麻烦到不想 ...

  5. protobuf android ndk,直接在Android NDK端使用tensorflow(不使用JAVA api)

    这是我如何解决这个问题.虽然没有太多关于在an​​droid上使用c apis以及编译和链接tensorflow到NDK的文档,但是makefile有重要的注释以及相关的脚本.编译步骤与ios非常相似 ...

  6. [引擎开发] 现代图形API - dx12篇

    本文将从性能优化的角度去阐述像dx12这样的现代图形API的一些设计理念. 当我们深入优化渲染管线的时候,我们会发现存在的几个瓶颈主要是这样的: ① 线程存在不合理的等待 ② CPU向GPU编码传输数 ...

  7. android gdb 命令大全,ndk-gdb  |  Android NDK  |  Android Developers

    NDK 包含一个名为 ndk-gdb 的 Shell 脚本,可以启动命令行原生调试会话.偏好使用 GUI 的用户则应阅读在 Android Studio 中调试这篇文档. 要求 要运行命令行原生调试, ...

  8. 使用 Android NDK 的交叉编译工具链移植 C/C++ 项目到安卓平台

    什么是 NDK? Android NDK 是一套可以让开发者在安卓应用开发中使用 C/C++ 实现特定模块的工具集,不是所有应用都需要用到,但是正确地使用可以有效提高应用运行效率和安全性. 为什么要在 ...

  9. Android开源项目第二篇——工具库篇

    本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍经常使用的开发库,包含依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本号向低版本号 ...

最新文章

  1. 技术图文:Python描述符 (descriptor) 详解
  2. 读书笔记:做人不要太老实读后感
  3. 【PC工具】注意安全,建议使用:安全软件,谷歌输入法下载
  4. Nginx与Lua开发
  5. C 中可以这样写函数的参数 !!
  6. RyuJIT的华丽转身
  7. java中no1_Java程序设计实验(NO.1).doc
  8. android studio查看jar包源码,Android Studio查看源代码报错
  9. FPGA基础知识之主要的FPGA生产厂商介绍
  10. 计算机实用知识风云初动,风云初动 第一节 养气韬光
  11. dgen模拟器 linux,怎么样在Linux/FreeBSD下玩模拟器游戏
  12. 服务器上很多iOS临时文件,iOS的临时文件夹位置(iOS temporary folder location)
  13. 华商网H.S.W社团:寻找有创造力的陕西大学生
  14. 智能体:华为给时代炼一炉钢
  15. 【读书联动】认知觉醒:开启自我改变的原动力
  16. android用户界面组件都是放置在,Android开发工程师第十章 节 用户界面高级组件.ppt...
  17. 学会Redis缓存中间件,这一篇就够了
  18. 电脑开机密码忘记,如何修改电脑密码?
  19. c语言中有裁剪字符串的函数吗,C语言中的字符串截取函数
  20. SCADA系列 系统评估

热门文章

  1. 更改netbios计算机名,NetBIOS主机名解析
  2. 南京信息工程大学计算机专业是几本,南京信息工程大学是211还是985
  3. 使用CVS进行版本管理
  4. 2023年全国最新高校辅导员精选真题及答案34
  5. 构建header爬虫构建请求头header
  6. 通过14个示例彻底掌握 linux ls 命令的使用
  7. A-Level商务例题解析及练习Sources of finance
  8. 1+X云计算平台运维与开发认证 数据库管理
  9. 搭建个人博客之 mysql 数据库表设计
  10. kail linux dns欺骗,Kali Linux渗透测试-Ettercap DNS欺骗攻击-Go语言中文社区