接着上篇ndk入门环境搭建(http://blog.csdn.net/fengchengwu2012/article/details/79412501),今天来探讨一下使用android 平台下使用c++处理Bitmap
(1)在app/sarc/main下新建一个c++的源文件bitmap-lib.cpp
(2) 创建NdkUtils的java类,写相应处理图片的native方法,并执行javah生成ndk工具类映射到cpp的头文件
public class NdkUtils {
static {
System.loadLibrary("bitmap-lib");
}
public static native int convertBm(Bitmap srtBm);
public static native int[] convertBmByPixels(int[] pixels, int w, int h);
}
javah -classpath C:\sdk\platforms\android-26\android.jar;. ndkdev.fcw.cn.bitamptool.NdkUtils
文件目录如下:
(3)在bitmap-lib.cpp编写c++代码:
#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <android/bitmap.h>
#include <android/log.h>
#include "ndkdev_fcw_cn_bitamptool_NdkUtils.h"
#define LOG "bitmap"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__)
JNIEXPORT jintArray JNICALL Java_ndkdev_fcw_cn_bitamptool_NdkUtils_convertBmByPixels
(JNIEnv *env, jclass job, jintArray jarr, jint w, jint h){
jint *buffer=env->GetIntArrayElements(jarr, NULL);
if (buffer!=NULL){
int a=0xFF<<24;
for(int i=h;i<h;i++){
for(int j=0;j<w;j++){
int color = buffer[w * i + j];
int red = ((color & 0x00FF0000) >> 16);
int green = ((color & 0x0000FF00) >> 8);
int blue = color & 0x000000FF;
color = (red + green + blue) / 3;
color = a| (color << 16) | (color << 8) | color;
buffer[w * i + j] = color;
}
}
jintArray res = env->NewIntArray(w * h);
env->SetIntArrayRegion(res, 0,w * h, buffer);
env->ReleaseIntArrayElements(jarr, buffer, 0);
return res;
} else{
return 0;
}
}
JNIEXPORT jint JNICALL Java_ndkdev_fcw_cn_bitamptool_NdkUtils_convertBm
(JNIEnv *env, jclass jc, jobject srcBm){
}
(4) 写MainActivity的布局及java代码
public class MainActivity extends AppCompatActivity {
private ImageView srcIv, desIv;
private TextView mDoneTv;
private MainActivity mActivity;
private int w, h;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mActivity = this;
mDoneTv = findViewById(R.id.done_tv);
srcIv = findViewById(R.id.src_iv);
desIv = findViewById(R.id.des_iv);
layoutIv(srcIv);
layoutIv(desIv);
mDoneTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bitmap tm = BitmapFactory.decodeResource(getResources(), R.drawable.lid).copy(Bitmap.Config.RGB_565, true);
Bitmap.createBitmap(tm, 0, 0, w, h);
Bitmap bitmap = getBitmap(tm);
desIv.setImageBitmap(bitmap);
if (bitmap.isRecycled())
bitmap.recycle();
}
});
}
private void layoutIv(ImageView imageView) {
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
w = (int) (dm.widthPixels / 2.0);
h = (int) (dm.widthPixels / 2 * 37 / 48.0);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) imageView.getLayoutParams();
lp.width = w;
lp.height = h;
imageView.setLayoutParams(lp);
}
private Bitmap getBitmap(Bitmap bitmap) {
initPalette(bitmap,0);
int[] pixels = new int[w * h];
bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
Bitmap resBm = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
//调用c++方法处理bitmap的高密度计算 如果将循环到java代码中,h会非常耗时,而在c++中计算效率倍增
resBm.setPixels(NdkUtils.convertBmByPixels(pixels, w, h), 0, w, 0, 0, w, h);
initPalette(bitmap,0);
return resBm;
}
/**
* <p> Paltte的一些常用方法
* //1.活力颜色
Palette.Swatch a = palette.getVibrantSwatch();
//2.亮的活力颜色
Palette.Swatch b=palette.getLightVibrantSwatch();
//3.暗的活力颜色
Palette.Swatch c = palette.getDarkVibrantSwatch();
//4.柔色
Palette.Swatch d = palette.getMutedSwatch();
//5.亮的柔色
Palette.Swatch e = palette.getLightMutedSwatch();
//6.暗的柔色
Palette.Swatch f = palette.getDarkMutedSwatch();
f.getRgb(); //rgb颜色
f.getTitleTextColor();//文本颜色
//返回float[],可以进行修改,后使用ColorUtils工具类进行转换
f.getHsl();
f.getBodyTextColor();//和文本颜色一样
*
* </p>
* @param bitmap
*/
private void initPalette(Bitmap bitmap, final int type) {
// Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {//异步方法
// @Override
// public void onGenerated(Palette palette) {
// Palette.Swatch f = palette.getDarkMutedSwatch();
// int rgb=f.getRgb(); //rgb颜色
// Log.i("TAG",type==0?"c++未处理前的RGD值=":"c++处理后的RGD值="+(rgb));
// }
// });
Palette palette=Palette.from(bitmap).generate();
Palette.Swatch f = palette.getDarkMutedSwatch();
int rgb=f.getRgb(); //rgb颜色
Log.i("TAG",type==0?"c++未处理前的RGD值=":"c++处理后的RGD值="+(rgb));
}
}
通过日志打印可对比Rgb值,如果写在c++里的循环放到java代码里少说得十几秒执行完毕