使用AndroiStudio、Cmake 开发ndk 入门(下)利用c++处理Bitmap

      接着上篇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代码里少说得十几秒执行完毕

       

猜你喜欢

转载自blog.csdn.net/fengchengwu2012/article/details/79429288
今日推荐