JNI Image RGBA格式转NV21

以480640尺寸为例
Image对象获取到的RGBA_8888数据格式分析如下
1.getPixelStride方法获取相邻像素间距 = 4
2.getRowStride方法获取行跨度 = 2048
3.2048-4
480 = 128,说明每行多出128个byte,这128个byte表示行填充的值,里面的数据为无效数据。
4.转换:需要将每行的最后128个数据忽略掉,再进行转换

JNIEXPORT void JNICALL
Java_com_xxx_xxx_RGBAtoNV21(JNIEnv *env,
                                                                  jclass clazz,
                                                                  jbyteArray rgbasp,
                                                                  jint width,
                                                                  jint height,
                                                                  jint rowPadding,//行填充的值
                                                                  jbyteArray yuvOut) {
    jbyte *yuvData = (jbyte *) ((*env)->GetPrimitiveArrayCritical(env, yuvOut, 0));
    jbyte *rgba = (jbyte *) ((*env)->GetPrimitiveArrayCritical(env, rgbasp, 0));
    int length = (*env)->GetArrayLength(env, yuvOut);
    int yIndex = 0;
    int uvIndex = width * height;
    int argbIndex = 0;
    int R, G, B, Y, U, V;
    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            R = rgba[argbIndex++] & 0xFF;
            G = rgba[argbIndex++] & 0xFF;
            B = rgba[argbIndex++] & 0xFF;
            argbIndex++;//跳过a
            Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
            yuvData[yIndex++] = ((Y > 0xFF) ? 0xFF : ((Y < 0) ? 0 : Y));
            //__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%hhd", yuvData[yIndex - 1]);
            if ((j & 1) == 0 && ((argbIndex >> 2) & 1) == 0 && uvIndex < length - 2) {
                U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
                V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
                yuvData[uvIndex++] = ((V > 0xFF) ? 0xFF : ((V < 0) ? 0 : V));
                yuvData[uvIndex++] = ((U > 0xFF) ? 0xFF : ((U < 0) ? 0 : U));
            }
        }
        argbIndex += rowPadding;    //跳过rowPadding长度的填充数据
    }
    //__android_log_print(ANDROID_LOG_ERROR, LOG_TAG,"%s",s);
    (*env)->ReleasePrimitiveArrayCritical(env, rgbasp, rgba, 0);
    (*env)->ReleasePrimitiveArrayCritical(env, yuvOut, yuvData, 0);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容