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开发的简单概念.常见错误及处 ...
随机推荐
- 使用Eclipse创建Maven javaweb项目
其实是我自己不会创建Maven JavaWeb项目,就自己瞎蒙了一下,竟然成功了. 这里有个条件就是你的Maven已经在电脑上配好了. 第一步就是File->New->Maven Proj ...
- python基本概念——标识符
标识符是用来标识某样东西的名字.在命名标识符的时候,你要遵循这些规则: 标识符的第一个字符必须是字母表中的字母(大写或小写)或者一个下划线(‘ _ ’). 标识符名称的其他部分可以由字母(大写或小写) ...
- 让 Winform 窗口悬浮的简单方式
很多次设置这个 TopMost 属性会莫名的不起作用,有时又可以.一直在想是为什么会这样? 后来多次尝试,发现这个属性必须在窗体某些其他属性后设置,比如在 Height.Width 这样的属性后. 看 ...
- Delphi和C#数据类型对应表
Delphi DataType C# datatype ansistring string boolean bool byte byte char char comp double currency ...
- SQLServer存储引擎——01.数据库如何读写数据
一.引言 在SQL Server数据库中,数据是如何被读写的?日志里都有些什么?和数据页之间是什么关系?数据页又是如何存放数据的?索引又是用来干嘛的? 一起看看SQL Server的存储引擎. 二.S ...
- 一键结束port 5037占用
输入cmd进入dos界面,进入android-sdk-windows\platform-tools目录,执行下面命令启动adb start-server出现下面错误* daemon not runni ...
- 读《JavaScript权威指南》笔记(四)--数组、函数
一.数组 1.数组是值的有序集合.每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引.JavaScript数组是无类型的:数组元素可以是任意类型,并且同一个数组中的不同元素也可能有 ...
- 【Python发展】pandas和koalas
1.pandas介绍 Python 数据科学在过去几年中爆炸式增长, pandas 已成为生态系统的关键.当数据科学家得到一个数据集时,他们会使用 pandas 进行探索.它是数据处理和分析的终极工具 ...
- 【bzoj1951】: [Sdoi2010]古代猪文 数论-中国剩余定理-Lucas定理
[bzoj1951]: [Sdoi2010]古代猪文 因为999911659是个素数 欧拉定理得 然后指数上中国剩余定理 然后分别lucas定理就好了 注意G==P的时候的特判 /* http://w ...
- macOS 10.12.1 + Xcode 8.1 安装cocoapods 1.1.1
最近公司刚给配了一台27寸的iMac,5K屏幕,这酸爽~~,新电脑,免不了系统升级,环境搭建,当一切就绪之后,我就准备装cocoapods了,然而,以前所有的教程全部都变得没用了...然而网上一大堆关 ...