Android NDK开发 图片处理(五)
做过Java的同学可能经常会遇到一些关于图片处理的
例如类似QQ离线头像显示灰的。最快的算法是用colorMatrix来实现。这里通过Java调用JNI来处理每一个像素来实现。
- 对每一个像素点取出RGB每个通道的值R,G,B
- cololr=(R+G+B)/3;这个值是需要修改的值
- 将原来GRB的通道全设置成color的值
首先先看用Java怎么实现这个功能
public Bitmap convertGrayImg(int resID)
{
Bitmap img1=((BitmapDrawable) getResources().getDrawable(resID)).getBitmap(); int w=img1.getWidth(),h=img1.getHeight();
int[] pix = new int[w * h];
img1.getPixels(pix, 0, w, 0, 0, w, h); int alpha=0xFF<<24;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
// 获得像素的颜色
int color = pix[w * i + j];
int red = ((color & 0x00FF0000) >> 16);
int green = ((color & 0x0000FF00) >> 8);
int blue = color & 0x000000FF;
color = (red + green + blue)/3;
color = alpha | (color << 16) | (color << 8) | color;
pix[w * i + j] = color;
}
}
Bitmap result=Bitmap.createBitmap(w, h, Config.RGB_565);
result.setPixels(pix, 0, w, 0, 0,w, h);
return result;
}
下面是JNI来处理
c++代码如下
#include <jni.h>
#include <string>
extern "C"{
jintArray JNICALL
Java_com_tmf_test_ndk_bitmap_MainActivity_getImgToGray(JNIEnv *env, jobject instance,
jintArray data_, jint w, jint h);
} JNIEXPORT jintArray JNICALL
Java_com_tmf_test_ndk_bitmap_MainActivity_getImgToGray(JNIEnv *env, jobject instance,
jintArray data_, jint w, jint h) {
jint *data;
data = env->GetIntArrayElements(data_, NULL);
if (data == NULL) {
return ; /* exception occurred */
}
int alpha = 0xFF << ;
for (int i = ; i < h; i++) {
for (int j = ; j < w; j++) {
// 获得像素的颜色
int color = data[w * i + j];
int red = ((color & 0x00FF0000) >> );
int green = ((color & 0x0000FF00) >> );
int blue = color & 0x000000FF;
color = (red + green + blue) / ;
color = alpha | (color << ) | (color << ) | color;
data[w * i + j] = color;
}
}
int size=w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, , size, data);
env->ReleaseIntArrayElements(data_, data, );
return result;
}
activity实现如下
package com.tmf.test.ndk.bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView; public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // Example of a call to a native method
ImageView tv = (ImageView) findViewById(R.id.image);
tv.setImageBitmap(getJniBitmap());
} public Bitmap getJniBitmap(){
Bitmap bitmap=((BitmapDrawable) getResources().getDrawable(R.mipmap.timg)).getBitmap();
int w=bitmap.getWidth(),h=bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
//通过ImgToGray.so把彩色像素转为灰度像素
int[] resultInt=getImgToGray(pix, w, h);
Bitmap resultImg=Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
resultImg.setPixels(resultInt, 0, w, 0, 0,w, h);
return resultImg;
} public native int[] getImgToGray(int[] data,int w,int h); private int[] bitmapToArray(int resID)
{
Bitmap bitmap=((BitmapDrawable) getResources().getDrawable(resID)).getBitmap();
int w=bitmap.getWidth(),h=bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
return pix;
} }
效果如下
bitmap.h
目录android-ndk-r10e\platforms\android-21\arch-arm\usr\include\android里面
bitmap.h
头文件中的内容并不多,主要有这些部分组成:
- 结果状态定义。
- 位图格式枚举。
- 位图信息结构体。
- 位图操作函数声明。
define ANDROID_BITMAP_RESULT_SUCCESS
#define ANDROID_BITMAP_RESULT_BAD_PARAMETER -1
#define ANDROID_BITMAP_RESULT_JNI_EXCEPTION -2
#define ANDROID_BITMAP_RESULT_ALLOCATION_FAILED -3 /* Backward compatibility: this macro used to be misspelled. */
#define ANDROID_BITMAP_RESUT_SUCCESS ANDROID_BITMAP_RESULT_SUCCESS
这里定义了对Bitmap进行操作时的结果,分别对应成功,错误的参数,JNI异常,内存分配错误,至于最后一个,这是个梗。Google工程师在定义NDK的时候写错一个单词,居然没有检查就发布了,然后就233333333了。看来IDE的拼写检查对自己人也有好处。
位图格式枚举
enum AndroidBitmapFormat {
ANDROID_BITMAP_FORMAT_NONE = ,
ANDROID_BITMAP_FORMAT_RGBA_8888 = ,
ANDROID_BITMAP_FORMAT_RGB_565 = ,
ANDROID_BITMAP_FORMAT_RGBA_4444 = ,
ANDROID_BITMAP_FORMAT_A_8 = ,
};
一般而言,常见的位图格式有RGB_565 、RGBA_8888、 ARGB_8888、 RGBA_4444、 ARGB_4444、 ALPHA_8
位图信息结构体
typedef struct {
uint32_t width;
uint32_t height;
uint32_t stride;
int32_t format;
uint32_t flags; // 0 for now
} AndroidBitmapInfo;
width表示图片的宽度(列数),height表示图片的高度(行数),stride为行跨度,具体含义后面会进行介绍。最后一个参数已经被弃用,其值始终为0。
位图操作函数声明
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info); int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr); int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
- AndroidBitmap_getInfo:获取当前位图信息。
- AndroidBitmap_lockPixels:锁定当前位图像素,在锁定期间该Bitmap对象不会被回收,使用完成之后必须调用AndroidBitmap_unlockPixels函数来解除对像素的锁定。
- AndroidBitmap_unlockPixels:解除像素锁定。
JNIEXPORT jboolean JNICALL
Java_com_tmf_test_ndk_bitmap_MainActivity_getImgToGray1(JNIEnv *env, jclass type, jobject jsrcBitmap,
jobject desBitmap) {
AndroidBitmapInfo srcInfo, dstInfo;
if (ANDROID_BITMAP_RESULT_SUCCESS != AndroidBitmap_getInfo(env, jsrcBitmap, &srcInfo)
|| ANDROID_BITMAP_RESULT_SUCCESS != AndroidBitmap_getInfo(env, desBitmap, &dstInfo)) {
LOGE("get bitmap info failed");
return false;
} void *srcBuf, *dstBuf;
if (ANDROID_BITMAP_RESULT_SUCCESS != AndroidBitmap_lockPixels(env, jsrcBitmap, &srcBuf)) {
LOGE("lock src bitmap failed");
return false;
} if (ANDROID_BITMAP_RESULT_SUCCESS != AndroidBitmap_lockPixels(env, desBitmap, &dstBuf)) {
LOGE("lock dst bitmap failed");
return false;
} int w = srcInfo.width;
int h = srcInfo.height;
int32_t *srcPixs = (int32_t *) srcBuf;
int32_t *desPixs = (int32_t *) dstBuf;
int alpha = 0xFF << 24;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
// 获得像素的颜色
int color = srcPixs[w * i + j];
int red = ((color & 0x00FF0000) >> 16);
int green = ((color & 0x0000FF00) >> 8);
int blue = color & 0x000000FF;
color = (red + green + blue) / 3;
color = alpha | (color << 16) | (color << 8) | color;
desPixs[w * i + j] = color;
}
}
AndroidBitmap_unlockPixels(env, jsrcBitmap);
AndroidBitmap_unlockPixels(env, desBitmap);
return true;
}
Java层代码
public native boolean getImgToGray1(Bitmap src,Bitmap des);
效果和上面都一样的,只是这个直接在底层处理bitmap对象
如果有以下异常
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:52: undefined reference to `AndroidBitmap_getInfo'
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:53: undefined reference to `AndroidBitmap_getInfo'
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:59: undefined reference to `AndroidBitmap_lockPixels'
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:64: undefined reference to `AndroidBitmap_lockPixels'
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:86: undefined reference to `AndroidBitmap_unlockPixels'
E:\test\NdkBitmap\app\src\main\cpp/native-lib.cpp:87: undefined reference to `AndroidBitmap_unlockPixels'
我用的是Android studio自带的cmake打包的,需要在
在CMakeLists.txt 添加 -ljnigraphics
target_link_libraries( # Specifies the target library.
native-lib
-ljnigraphics
# Links the target library to the log library
# included in the NDK.
${log-lib} )
Android NDK开发 图片处理(五)的更多相关文章
- Android NDK开发初识
神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...
- Android NDK 开发(二) -- 从Hlello World学起【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41805719 上篇文章讲述了Android NDK开发的一些基本概念,以及NDK ...
- !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-opencv-development-3/ Android Ndk a ...
- Android NDK开发及OpenCV初步学习笔记
https://www.jianshu.com/p/c29bb20908da Android NDK开发及OpenCV初步学习笔记 Super_圣代 关注 2017.08.19 00:55* 字数 6 ...
- android NDK开发在本地C/C++源码中设置断点单步调试具体教程
近期在学android NDK开发,折腾了一天,最终可以成功在ADT中设置断点单步调试本地C/C++源码了.网上关于这方面的资料太少了,并且大都不全,并且调试过程中会出现各种各样的问题,真是非常磨人. ...
- windows下用ADT进行android NDK开发的具体教程(从环境搭建、配置到编译全过程)
郑重申明:如需转载本博客,请注明出处,谢谢! 这几天在学习android NDK的开发.那么首先让我们来看看android NDK开发的本质是什么. NDK(Native Development Ki ...
- Android NDK开发Hello Word!
在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...
- Android NDK开发
Android NDK 开发教程(极客学院) 一.Android NDK环境搭建 使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin( ...
- Android NDK 开发(四)java传递数据到C【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处 ...
随机推荐
- 树莓派研究笔记(10)-- Retropie 模拟器
前面介绍过lakka模拟器,小巧,轻便,支持中文.其实最著名的游戏系统还是要属于Retropie啊.虽然笨重了一点,但是很多树莓派系统的原汁原味还是保留的很好.这样就不需要我们自己还要对lakka的源 ...
- 福大软工1816 · 第五次作业 - 结对作业2_EXE图片_备用
1_每日推荐界面.png 2_论文搜索界面.png 2_论文搜索界面_搜索功能.png 3_流行趋势_十大热词排名统计图.png 4_人物界面.png 5_我的收藏界面.png 6_设置界面.png ...
- 【Java学习】Java泛型详解
1. 概述 在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型.例如原先的类型List,现在在细分成List<Obje ...
- TestNG入门
在Eclipse中安装TestNG 打开Eclipse Help ->Install New Software , 然后Add "http://beust.com/ecli ...
- JavaScript知识体系索引
JavaScript 参考手册 www.w3school.com.cn JavaScript基础语法 JavaScript的数据类型 Javascript的对象分类 JavaScript内置对象 Ja ...
- 转【C#调用DLL的几种方法,包括C#调用C\C++\C#DLL】
C#中dll调用方法 一. DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一, ...
- C:简单的学生信息处理程序实现
描述 在一个学生信息处理程序中,要求实现一个代表学生的类,并且所有成员变量都应该是私有的. (注:评测系统无法自动判断变量是否私有.我们会在结束之后统一对作业进行检查,请同学们严格按照题目要求完成,否 ...
- HashMap vs Hashtable
一.散列 1. HashMap 1) hashmap的数据结构 Hashmap是一个数组和链表的结合体(在数据结构称“链表散列“),如下图示: 当我们往hashmap中put元素的时候,先根据key ...
- win10更新后IE不见了
只是快捷方式不见了,到C:\Program Files\internet explorer\iexplore.exe就看到了,可以正常运行
- 【以太坊开发】区块链中的预言机:Oraclize原理介绍
智能合约的作用很多,但是很多数据还是要基于互联网,那么如何在合约中获取互联网中的数据?Oraclize就是为了这个目的而诞生的. 工作原理: 智能合约通过对Oraclize发布一个合约之间的调用请求来 ...