NDK/JNI Development Series (1) -- Principle Understanding, Picture Simple Processing

The powerful ps function of PC end is gradually realized in mobile end nowadays, thanks to the powerful library called C/C++. Its processing efficiency and security are incomparable to java.

github code download address: https://github.com/18380438200/NdkUse

Firstly, the effect map is shown.



low source

What is jni?
It is abbreviated as Java Native Interface, or Java Local Interface. Through this protocol, Java can call external C/C++ methods. JNI belongs to Java and has no direct relationship with Android.

What is NDK?
Abbreviated as Native Develop Kit, the local development toolkit. It is the result of the official change of jni, more method developers call C/C++ function. NDK belongs to Android and is not directly related to Java.

Configure NDK, run helloword, and select the CMake configuration method here (plus model configuration method)

First install CMake in SDK Tool



image.png

Selecting projects to support C/C++



image.png

image.png

Generate project directory structure:


image.png

Implementation of the simplest native method

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_ndkdemo_ndkdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Nice to meet you";
    return env->NewStringUTF(hello.c_str());
}
public class NdkFilter {

    static {
        System.loadLibrary("native-lib");
    }

    public static native String stringFromJNI();
}

Don't do anything, go straight to one:



helloworld's results

Simple filter to increase contrast:

The implementation of java is as follows:

public class JavaFilter {
    public static final float brightness = 0.2f;  //brightness
    public static final float contrainst = 0.2f;  //Contrast, color deepening

    public static Bitmap getImageBitmap(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Bitmap result = Bitmap.createBitmap(width,height, Bitmap.Config.RGB_565); 
        int a,r,g,b;
        int bab = (int) (255*brightness);
        float ca = 1.0f + contrainst;
        //Change the rgb value of all pixels
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int color = bitmap.getPixel(x,y);  //Get the color value
                a = Color.alpha(color);
                r = Color.red(color);  // (color > > 16) & 0xFF asked Lao Wang why
                g = Color.green(color);
                b = Color.blue(color);

                //Skin whitening
                int ri = r + bab;
                int gi = g + bab;
                int bi = b + bab;

                //boundary detection
                r = ri > 255 ? 255 : (ri<0?0:ri);
                g = gi > 255 ? 255 : (gi<0?0:gi);
                b = bi > 255 ? 255 : (bi<0?0:bi);

                //Expanding contrast requires whiter white and darker black.
                //More than 128 are strengthened, and less than 128 are subtracted.
                ri = r - 128;
                gi = g - 128;
                bi = b - 128;

                ri = (int) (ri * ca);
                gi = (int) (gi * ca);
                bi = (int) (bi * ca);

                ri += 128;
                gi += 128;
                bi += 128;

                //boundary detection
                r = ri > 255 ? 255 : (ri<0?0:ri);
                g = gi > 255 ? 255 : (gi<0?0:gi);
                b = bi > 255 ? 255 : (bi<0?0:bi);

                result.setPixel(x,y,Color.argb(a,r,g,b));
            }
        }

        return result;
    }

Bitmap.createBitmap()

Create Bitmap (Bitmap source, int x, int y, int width, int height): Starting with the specified coordinate point (x,y) in the original image, dig out a wide, high height block from it and create a new Bitmap object.

Create Scaled Bitmap (Bitmap source, int dstWidth, int dstHeight, Boolean filter): Scale the source bitmap to a new bitmap object of specified width and height size.

Create Bitmap (int width, int height, Bitmap. Config config): Create a new bitmap with wide width and high height.
Create Bitmap (Bitmap source, int x, int y, int width, int height, Matrix matrix, Boolean filter): Start with the specified coordinate point (x,y) in the original image, dig out a wide, high height block from it and create a new Bitmap object. And transform according to the rules specified by Matrix.

Bitmap.Config.RGB_565 Understanding: Internal Classes of Bitmap
public enum Config {
ALPHA_8 (1),
RGB_565 (3),
ARGB_4444 (4),
ARGB_8888 (5),
RGBA_F16 (6),
...
}
ALPHA_8 is that Alpha consists of eight bits.
ARGB_4444 is composed of four bits, namely 16 bits.
ARGB_8888 is composed of 4 8 bits, 32 bits, the original color.
RGB_565 is R 5, G 6, B 5 16.
The higher the number of digits, the richer the color stored, and the clearer the picture.

C Implementation Code

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_example_apple_ndkconfig_NdkFilter_getNdkBitmap(JNIEnv *env, jobject /* this */,
                                                           jintArray buffer_, jint width,
                                                           jint height) {
    float brightness = 0.2f;  //brightness
    float contrainst = 0.2f;  //Contrast, color deepening

    //All color values of an image are stored in an array
    jint* source = env->GetIntArrayElements(buffer_,NULL); 

    int a,r,g,b;
    int bab = (int) (255 * brightness);
    float ca = 1.0f + contrainst;
    //Change the rgb value of all pixels
    int x,y;
    for (x = 0; x < width; x++) {
        for (y = 0; y < height; y++) {
            int color = source[width*y + x];  //Get the color value
            a = color >> 24;
            r = color >> 16 & 0xFF;  // (color >> 16) & 0xFF
            g = color >> 8 & 0xFF;
            b = color & 0xFF;

            //Increase brightness (whitening)
            int ri = r + bab;
            int gi = g + bab;
            int bi = b + bab;

            //In boundary detection, the argb values are in the range of [0-255].
            r = ri > 255 ? 255 : (ri < 0 ? 0 : ri);
            g = gi > 255 ? 255 : (gi < 0 ? 0 : gi);
            b = bi > 255 ? 255 : (bi < 0 ? 0 : bi);

            //Expanding contrast requires whiter white and darker black.
            //More than 128 are strengthened, and less than 128 are subtracted.
            ri = r - 128;
            gi = g - 128;
            bi = b - 128;

            ri = (int) (ri * ca);
            gi = (int) (gi * ca);
            bi = (int) (bi * ca);

            ri += 128;
            gi += 128;
            bi += 128;

            //Re-boundary Detection
            r = ri > 255 ? 255 : (ri < 0 ? 0 : ri);
            g = gi > 255 ? 255 : (gi < 0 ? 0 : gi);
            b = bi > 255 ? 255 : (bi < 0 ? 0 : bi);

            //result.setPixel(x, y, Color.argb(a, r, g, b));
            //argb synthesis of jni
            source[width * y + x] = a << 24| r << 16 | g << 8 | b;
        }
    }
    //Processing principle is the same as java, but the way to get data and objects is different.
    int newSize = width * height;
    //Depending on the length of the array, save the source to jintArray for resource release
    jintArray result = env->NewIntArray(newSize);
    env->SetIntArrayRegion(result,0,newSize,source); 

    env->ReleaseIntArrayElements(buffer_, source, 0);

    return result;
}
a = color >> 24;
r = color >> 16 & 0xFF;  // (color >> 16) & 0xFF
g = color >> 8 & 0xFF;
b = color & 0xFF;

Here, because the color value is 32-bit int, argb occupies 8 places respectively. Take r = color > > 16 & 0xFF as an example.
Move right 16 bits to get high 16 bits, then - 0xFF, that is, process low 8 bits and 1 bits and still get the original value, so get the corresponding r value.


image.png

For more NDK development functions, see my next blog in this series.

Tags: Java github Android cmake

Posted on Sat, 18 May 2019 10:18:12 -0700 by andz