jni开发:jni基础教程及实例(二)

       接上一篇,上一篇讲了jni的一些基本知识,可能大家都很懵逼,这很正常,在这里,我们将以一个简单的小实例,继续探索jni的使用,没有看上一篇博客的可以先看上一篇哦,附上链接: jni开发:jni基础教程及实例(一),当然,如果你对jni已经有了基本的了解,可以跳过上一篇博客,废话不说,我们进入正题。

我们写一个demo,将一张res下的彩色图片转换为黑白图片,功能还是很简单的,简单粗暴,直接上代码:

1.首先是布局文件,一个Button,两个ImageView,so easy,这里不再赘述:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/change"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:text="过滤" />

            <ImageView
                android:id="@+id/iv1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                />

            <ImageView
                android:id="@+id/iv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

2.接着,我们在MainAvtivity里面添加如下代码:

package com.example.admin.jnitestbitmapdemo;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.IOException;
import java.io.InputStream;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    private ImageView mImg1, mImg2;
    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImg1 = (ImageView) findViewById(R.id.iv1);
        mImg2 = (ImageView) findViewById(R.id.iv2);
        btn = (Button) findViewById(R.id.change);
        btn.setOnClickListener(this);
        mImg1.setImageResource(R.mipmap.test2);
        // Example of a call to a native method

    }
    /**
     * 从assets中加载图片
     * @return
     */
    private Bitmap loadBitmap() {
        Bitmap bmp = null;
        AssetManager am = getResources().getAssets();
        try {
            InputStream is = am.open("test2.jpg");
            BitmapFactory.Options options = new BitmapFactory.Options();
            bmp = BitmapFactory.decodeStream(is ,null , options);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmp;
    }

    /**
     * 处理图片,此方法中会调用nativeProcessBitmap
     * @param bitmap
     * @return
     */
    private Bitmap processBitmap(Bitmap bitmap) {
        Bitmap bmp = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        nativeProcessBitmap( bmp);
        return bmp;
    }
    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native void nativeProcessBitmap(Bitmap bitmap);

    @Override
    public void onClick(View view) {
        Bitmap originalBitmap = loadBitmap();
        Bitmap resultBitmap = processBitmap(originalBitmap);
        mImg2.setImageBitmap(resultBitmap);
    }
}

可以看到,使用jni之前,需要调用System.loadLibrary导入,而jni里的方法都是native在前的

3.现在进入我们的jni部分

#include <jni.h>
#include <string>

#include <android/bitmap.h>
#include <android/log.h>
#ifndef eprintf
#define eprintf(...) __android_log_print(ANDROID_LOG_ERROR,"@",__VA_ARGS__)
#endif
#define MAKE_RGB565(r,g,b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
#define MAKE_ARGB(a,r,g,b) ((a&0xff)<<24) | ((r&0xff)<<16) | ((g&0xff)<<8) | (b&0xff)

#define RGB565_R(p) ((((p) & 0xF800) >> 11) << 3)
#define RGB565_G(p) ((((p) & 0x7E0 ) >> 5) << 2)
#define RGB565_B(p) ( ((p) & 0x1F )    << 3)

#define RGB8888_A(p) (p & (0xff<<24) >> 24 )
#define RGB8888_R(p) (p & (0xff<<16) >> 16 )
#define RGB8888_G(p) (p & (0xff<<8) >> 8 )
#define RGB8888_B(p) (p & (0xff) )
extern "C" JNIEXPORT jstring

JNICALL
Java_com_example_admin_jnitestbitmapdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_admin_jnitestbitmapdemo_MainActivity_nativeProcessBitmap(JNIEnv *env,
                                                                          jobject instance,
                                                                          jobject bitmap) {

    // TODO
    if (bitmap == NULL) {
        eprintf("bitmap is null\n");
        return;
    }
    /*
     * 通过bitmap获得AndroidBitmapInfo对象,AndroidBitmapInfo为我们提供了Bitmap的所有信息
     */
    AndroidBitmapInfo bitmapInfo;
    memset(&bitmapInfo , 0 , sizeof(bitmapInfo));
    AndroidBitmap_getInfo(env , bitmap , &bitmapInfo);

    //获得bitmap的像素矩阵,并将它存放在&pixels中
    void * pixels = NULL;
    int res = AndroidBitmap_lockPixels(env, bitmap, &pixels);

    int x = 0, y = 0;
    for (y = 0; y < bitmapInfo.height; ++y) {
        // From left to right
        for (x = 0; x < bitmapInfo.width; ++x) {
            int a = 0, r = 0, g = 0, b = 0;
            void *pixel = NULL;
            // Get each pixel by format

            if(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888)
            {
                pixel = ((uint32_t *)pixels) + y * bitmapInfo.width + x;
                int r,g,b;
                uint32_t v = *((uint32_t *)pixel);
                r = RGB8888_R(v);
                g = RGB8888_G(v);
                b = RGB8888_B(v);
                int sum = r+g+b;
                *((uint32_t *)pixel) = MAKE_ARGB(0x1f , sum/3, sum/3, sum/3);
            }
            else if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565) {
                pixel = ((uint16_t *)pixels) + y * bitmapInfo.width + x;
                int r,g,b;
                uint16_t v = *((uint16_t *)pixel);
                r = RGB565_R(v);
                g = RGB565_G(v);
                b = RGB565_B(v);
                int sum = r+g+b;
                *((uint16_t *)pixel) = MAKE_RGB565(sum/3, sum/3, sum/3); }
        }
    }
    //解锁
    AndroidBitmap_unlockPixels(env, bitmap);

}

在这里面,有两个方法,第一个是我们使用Andoid Studio配置ndk的时候自动生成的,当它可能被调用成功时,说明jni环境已配置好,可以开始做jni开发了,我们在这里用的是第二个方法,它将传进来的bitmap转换为灰度图。

4.最后是导入图片,这个太简单咯,自己任意导入一张即可,我们来看看最后的效果:

效果图

这就是jni的使用,当然,实际开发中,通常我们会在jni里面调用算法so库里的函数,比这个要复杂,不过理解了这个后,jni的开发算是有了基本的理解了

附上demo的下载地址:jni转换为灰度图demo 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值