a284628487 / JniSample

0 stars 0 forks source link

YUVtoARGB #7

Open a284628487 opened 6 years ago

a284628487 commented 6 years ago

YUVtoARGB

Java代码:

public static native void YUVtoARGB(byte[] yuv, int width, int height, int[] out);

C代码:

#include <jni.h>
#include <android/log.h>

JNIEXPORT void JNICALL
Java_com_ccflying_JNIBitmap_YUVtoARGB(JNIEnv *env, jobject obj,
                                 jbyteArray yuv420sp,
                                 jint width, jint height,
                                 jintArray rgbOut) {
    // byte[] yuv, int width, int height, int[] out
    int sz;
    int i;
    int j;
    int Y;
    int U = 0;
    int V = 0;
    int pixPtr = 0;
    int jDiv2 = 0;
    int R = 0;
    int G = 0;
    int B = 0;
    int cOff;
    //
    int w = width;
    int h = height;
    // 总像素点个数
    sz = w * h;
    // 输出结果: pixels
    jint *rgbData = (jint *) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0));
    // Camera原始byte数据
    jbyte *yuv = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0);

    for (j = 0; j < h; j++) { // height: 从上到下
        pixPtr = j * w; // 第 j 行左侧位置索引
        jDiv2 = j >> 1; // jDiv2为j整除2
        for (i = 0; i < w; i++) { // width: 从左到右
            Y = yuv[pixPtr]; // Y 行第 i 个像素点
            if (Y < 0) Y += 255;
            // ? (i & 0x1) 表示 i 为单数(奇数),1, 3, 5, 7, 9
            if ((i & 0x1) != 1) {
                cOff = sz + jDiv2 * w + (i >> 1) * 2;
                U = yuv[cOff]; // U
                V = yuv[cOff + 1]; // V
                if (U < 0) U += 127; else U -= 128;
                if (V < 0) V += 127; else V -= 128;
            } // 使用的是 comment#2 中的4:2:2采样格式

            //ITU-R BT.601 conversion
            //
            //R = 1.164*(Y-16) + 2.018*(U-128);
            //G = 1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128);
            //B = 1.164*(Y-16) + 1.596*(V-128);
            //
            Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7);
            // R
            R = Y + (int)(1.4f * U);
            R = limitRGBValue(R);
            // G
            G = Y - (int)(0.344f * V + 0.714f * U);
            G = limitRGBValue(G);
            // B
            B = Y + (int)(1.77f * V);
            B = limitRGBValue(B);
            // 写入进结果 pixels
            rgbData[pixPtr++] = 0xff000000 + (R << 16) + (G << 8) + B;
            // ARBG?
            // rgbData[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R;
        }
    }
    // release
    (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0);
    (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0);
}

// 限制RGB值的范围为[0-255]
int limitRGBValue(int input) {
    if (input < 0)
        input = 0;
    else if (input > 255)
        input = 255;
    return input;
}

Link