1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android JNI操作Bitmap实现黑白图片

Android JNI操作Bitmap实现黑白图片

时间:2023-02-09 00:45:29

相关推荐

Android JNI操作Bitmap实现黑白图片

最近想练习一下NDK,基于我接下来的目标是多媒体,多以想多点学习一下关于滤镜的知识,黑白滤镜是最简单的了。

这里实现的是将一张彩色图片转成黑白图片,是黑白滤镜的基础!

直接上码:

// java 代码public void gray(View view) {Bitmap source = BitmapFactory.decodeResource(getResources(), R.drawable.time);Bitmap target = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);BitmapTools.gray(source, target);targetView.setImageBitmap(target);}

// c 代码#include <jni.h>#include <android/bitmap.h>#include <android/log.h>#define TAG "bitmap-lib"#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG ,__VA_ARGS__)extern "C"JNIEXPORT void JNICALLJava_com_johan_ndk_BitmapTools_gray(JNIEnv *env, jobject obj, jobject source, jobject target) {int result;// 获取源Bitmap相关信息:宽、高等AndroidBitmapInfo sourceInfo;result = AndroidBitmap_getInfo(env, source, &sourceInfo);if (result < 0) {LOGE("get bitmap info error : %d", result);return;}// 获取源Bitmap像素数据 这里用的是32位的int类型 argb每个8位uint32_t *sourceData;result = AndroidBitmap_lockPixels(env, source, (void**) &sourceData);if (result < 0) {LOGE("bitmap lock pixels error : %d", result);return;}// 锁定Bitmap // 并获取目标Bitmap像素数据 // 注意:传进来的Bitmap只是一张空的Bitmapuint32_t *targetData;result = AndroidBitmap_lockPixels(env, target, (void**) &targetData);if (result < 0) {LOGE("bitmap lock pixels error : %d", result);return;}// 遍历各个像素点int color;int alpha = 0xff << 24;int red, green, blue;int width = sourceInfo.width;int height = sourceInfo.height;int w, h;for (h = 0; h < height; h++) {for (w = 0; w < width; w++) {color = sourceData[h*width+w];red = (color & 0x00ff0000) >> 16;green = (color & 0x0000ff00) >> 8;blue = color & 0x000000ff;// rgb颜色相同就是黑白图片了 取平均值只是一个方案color = (red + green + blue) / 3;targetData[h*width+w] = alpha | (color << 16) | (color << 8) | color;}}AndroidBitmap_unlockPixels(env, source);AndroidBitmap_unlockPixels(env, target);}

注意Cmake文件要添加库,否则会报找不到 AndroidBitmap_getInfo 等Bitmap方法:

target_link_libraries( ...jnigraphics)

效果:

以上是我仿 这篇博文 写的,但是我看到这篇博文有一条评论,说是像素点在c上存在大小端的问题,于是乎我改了一点代码:

...for (h = 0; h < height; h++) {for (w = 0; w < width; w++) {color = sourceData[h*width+w];red = (color & 0x00ff0000) >> 16;green = (color & 0x0000ff00) >> 8;blue = color & 0x000000ff;blue += 60;if (blue > 255) {blue = 255;}color = (red + green + blue) / 3;targetData[h*width+w] = alpha | (red << 16) | (green << 8) | blue;}}...

这样改之后,界面应该偏冷色,结果却是:

居然是暖色调了,证明的确存在大小端的问题,所以在C层中,Bitmap像素点的值是BGR,而不是RGB,也就是说,高端到低端:B,G,R!所以代码得改一下:

...for (h = 0; h < height; h++) {for (w = 0; w < width; w++) {color = sourceData[h*width+w];blue = (color & 0x00ff0000) >> 16;green = (color & 0x0000ff00) >> 8;red = color & 0x000000ff;blue += 80;if (blue > 255) {blue = 255;}color = (red + green + blue) / 3;targetData[h*width+w] = alpha | (blue << 16) | (green << 8) | red;}}...

这样改了之后,结果就正常为冷色调了:

至于黑白时没有高低端问题呢,是因为color去的是rgb的平均值,所以不论是r+g+b,还是b+g+r,值都是一样!!

通过这个例子,不仅复习了一下NDK操作,而且还知道了Bitmap像素点存在高低端问题!!值了~

参考资料

JNI下使用AndroidBitmap_lockPixels修改位图为黑白照片

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。