android - 使用 libyuv 库缩放 YUV 图像时的问题

标签 android c++ image yuv libyuv

我正在开发一个基于 Camera API 2 的相机应用程序,我发现使用 libyuv 的几个问题. 我想转换从 ImageReader 检索到的 YUV_420_888 图像,但在可重新处理的表面中缩放时遇到了一些问题。

本质上:图像是绿色调而不是相应的色调(我正在导出 .yuv 文件并使用 http://rawpixels.net/ 检查它们)。

您可以在此处查看输入示例:enter image description here

我执行缩放后得到的结果:enter image description here

我认为我的步幅有问题,或者提供了无效的 YUV 格式(也许我必须将图像转换为另一种格式?)。但是,我不知道错误在哪里,因为我不知道如何将绿色与缩放算法相关联。

这是我正在使用的转换代码,您可以忽略返回 NULL,因为还有与问题无关的进一步处理。

#include <jni.h>
#include <stdint.h>
#include <android/log.h>
#include <inc/libyuv/scale.h>
#include <inc/libyuv.h>
#include <stdio.h>


#define  LOG_TAG    "libyuv-jni"

#define unused(x) UNUSED_ ## x __attribute__((__unused__))
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS_)

struct YuvFrame {
    int width;
    int height;
    uint8_t *data;
    uint8_t *y;
    uint8_t *u;
    uint8_t *v;
};

static struct YuvFrame i420_input_frame;
static struct YuvFrame i420_output_frame;

extern "C" {

JNIEXPORT jbyteArray JNICALL
Java_com_android_camera3_camera_hardware_session_output_photo_yuv_YuvJniInterface_scale420YuvByteArray(
        JNIEnv *env, jclass /*clazz*/, jbyteArray yuvByteArray_, jint src_width, jint src_height,
        jint out_width, jint out_height) {

    jbyte *yuvByteArray = env->GetByteArrayElements(yuvByteArray_, NULL);

    //Get input and output length
    int input_size = env->GetArrayLength(yuvByteArray_);
    int out_size = out_height * out_width;

    //Generate input frame
    i420_input_frame.width = src_width;
    i420_input_frame.height = src_height;
    i420_input_frame.data = (uint8_t *) yuvByteArray;
    i420_input_frame.y = i420_input_frame.data;
    i420_input_frame.u = i420_input_frame.y + input_size;
    i420_input_frame.v = i420_input_frame.u + input_size / 4;

    //Generate output frame
    free(i420_output_frame.data);
    i420_output_frame.width = out_width;
    i420_output_frame.height = out_height;
    i420_output_frame.data = new unsigned char[out_size * 3 / 2];
    i420_output_frame.y = i420_output_frame.data;
    i420_output_frame.u = i420_output_frame.y + out_size;
    i420_output_frame.v = i420_output_frame.u + out_size / 4;
    libyuv::FilterMode mode = libyuv::FilterModeEnum::kFilterBilinear;

    int result = I420Scale(i420_input_frame.y, i420_input_frame.width,
                           i420_input_frame.u, i420_input_frame.width / 2,
                           i420_input_frame.v, i420_input_frame.width / 2,
                           i420_input_frame.width, i420_input_frame.height,
                           i420_output_frame.y, i420_output_frame.width,
                           i420_output_frame.u, i420_output_frame.width / 2,
                           i420_output_frame.v, i420_output_frame.width / 2,
                           i420_output_frame.width, i420_output_frame.height,
                           mode);
    LOGD("Image result %d", result);
    env->ReleaseByteArrayElements(yuvByteArray_, yuvByteArray, 0);
    return NULL;
}

最佳答案

您可以尝试使用 y_size 而不是数组的完整大小的代码。

    ...
    //Get input and output length
    int input_size = env->GetArrayLength(yuvByteArray_);
    int y_size = src_width * src_height;
    int out_size = out_height * out_width;

    //Generate input frame
    i420_input_frame.width = src_width;
    i420_input_frame.height = src_height;
    i420_input_frame.data = (uint8_t *) yuvByteArray;
    i420_input_frame.y = i420_input_frame.data;
    i420_input_frame.u = i420_input_frame.y + y_size;
    i420_input_frame.v = i420_input_frame.u + y_size / 4;

    //Generate output frame
    free(i420_output_frame.data);
    i420_output_frame.width = out_width;
    i420_output_frame.height = out_height;
    i420_output_frame.data = new unsigned char[out_size * 3 / 2];
    i420_output_frame.y = i420_output_frame.data;
    i420_output_frame.u = i420_output_frame.y + out_size;
    i420_output_frame.v = i420_output_frame.u + out_size / 4;
    ...

您的代码可能基于 https://github.com/begeekmyfriend/yasea/blob/master/library/src/main/libenc/jni/libenc.cc根据该代码,您必须使用 y_size

关于android - 使用 libyuv 库缩放 YUV 图像时的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42960251/

相关文章:

javascript - 在 Nodejs 的 jimp(js 库)中创建具有透明颜色的新图像

c++ - 在一个项目中混合使用 boost 和 STL 库的缺点?

android - AsyncTask 不会进入 onPostExecute()

android - 在gradle中添加播放服务依赖导致Android Studio中出现许多错误

Android 开关按钮定制设计

C++:说 func()=30 是什么意思

c++ - LDADD 和 LIBADD 有什么区别?

android - 通过相机获取最近拍摄的图像的路径和图像名称

image - 带有图像链接替代文本的 SEO 与基于标准文本的链接

android - 如何在 ScrollView 中包装相对布局?