把大尺寸UYVY格式图像转换为小尺寸RGB565格式图像,下面的两种方案哪个更好?为什么?
1:先使用libyuv的ConvertToI420函数把UYVY格式转换为I420格式,再对I420进行缩放,再对I420进行旋转,再使用libyuv的I420ToRGB565函数把I420格式转换为RGB565格式。
2:先使用libyuv的UYVYToARGB函数将UYVY格式转换为ARGB格式,再使用libyuv的ARGBToRGB565函数将ARGB格式转换为RGB565格式,再对RGB565进行缩放,最后对RGB565进行旋转
RGB565 是一种16位色彩模式,其中红色占据5位,绿色占据6位,蓝色占据5位。在进行旋转和缩放操作时,可能会导致像素的位置和值发生变化,进而引起颜色空间变换和精度损失。由于 RGB565 是一个固定位深度的格式,其颜色表示范围和精度有限,因此对像素进行缩放和旋转会引入一定的损失,导致输出图像质量降低。
而 I420 是一种YUV格式,其中包含亮度分量 Y 和色度分量 U、V。Y 分量存储亮度信息,而 U 和 V 分量存储色度信息。在进行旋转和缩放操作时,对 YUV 分量进行处理并不会引入颜色空间变换和精度损失,因为 YUV 格式相对于 RGB 格式来说,更适合进行图像处理操作。所以,在将 UYVY 转换为 I420 格式后,对 I420 进行旋转和缩放不会引起颜色空间变换和精度损失。
综上所述,为了保持较高的图像质量,建议在 I420 格式下进行旋转和缩放操作,而不是在 RGB565 格式下进行。
在使用 libyuv 对 UYVY 和 I420 图像进行缩放和旋转时,通常来说 I420 图像处理的效率会更高一些,因为 I420 格式的图像在处理过程中可以更好地利用硬件加速和优化算法。此外,由于 I420 格式的图像数据存储方式更符合现代处理器的内存访问模式,因此在进行图像处理时可能会有更好的性能表现。
至于图像质量,这取决于具体的应用场景和处理算法。一般来说,无论是 UYVY 还是 I420,libyuv 库都提供了高质量的图像处理函数,因此在正确使用的情况下,它们可以提供相似的图像质量。
总的来说,针对缩放和旋转操作,I420 图像在效率上可能会略胜一筹,但在实际应用中,最好进行实际的测试和评估,以找到最适合特定需求的图像格式和处理方式。
使用libyuv把大尺寸的UYVY转换为小尺寸的RGB565,要求转换效率高且输出的RGB565图像质量高,有下面两个方案:
方案1:先把UYVY转换为I420,再对I420进行缩放,最后把I420转换为RGB565。
方案2:先把UYVY转换为I420,再把I420转换为RGB565,最后对RGB565进行缩放。
请问方案1和方案2哪个更好?哪个方案转换效率和输出的RGB565图像质量更高?
在这两个方案中,方案1 更适合要求转换效率高且输出的 RGB565 图像质量高的情况。原因如下:
1:转换效率:方案1 中先将 UYVY 转换为 I420,然后对 I420 进行缩放,最后再将 I420 转换为 RGB565。这样可以将缩放操作和格式转换操作分离,使得每个操作的复杂度降低,从而提高整体的转换效率。
2:输出图像质量:通过将缩放操作放在格式转换之前,可以避免在 RGB565 格式下进行缩放可能引入的颜色空间变换和精度损失,因此方案1 在输出的 RGB565 图像质量上更有优势。
综上所述,方案1 更适合要求转换效率高且输出的 RGB565 图像质量高的场景。因此,建议选择方案1来实现 UYVY 到 RGB565 的转换。如果还有其他问题或者需要进一步解释,请随时告诉我。
使用libyuv把大尺寸的UYVY转换为小尺寸的RGB565,要求转换效率高且输出的RGB565图像质量高,有下面三个方案:
方案1:先把UYVY转换为I420,再对I420进行缩放,再把I420转换为RGB565,最后对RGB565进行旋转
方案2:先把UYVY转换为I420,再对I420进行缩放,再对I420进行旋转,最后把I420转换为RGB565
方案3:先把UYVY转换为I420,再把I420转换为RGB565,再对RGB565进行缩放,最后对RGB565进行旋转
哪个方案转换效率和输出的RGB565图像质量更高?
int ConvertToI420(const uint8* sample,
size_t sample_size,
uint8* y,
int y_stride,
uint8* u,
int u_stride,
uint8* v,
int v_stride,
int crop_x,
int crop_y,
int src_width,
int src_height,
int crop_width,
int crop_height,
enum RotationMode rotation,
uint32 fourcc)
参数说明:
sample:输入数据的指针。
sample_size:输入数据的大小。
y:输出 Y 分量数据的指针。
y_stride:输出 Y 分量数据的跨度(stride)。
u:输出 U 分量数据的指针。
u_stride:输出 U 分量数据的跨度。
v:输出 V 分量数据的指针。
v_stride:输出 V 分量数据的跨度。
crop_x:裁剪起始点的 x 坐标。
crop_y:裁剪起始点的 y 坐标。
src_width:输入图像的宽度。
src_height:输入图像的高度。
crop_width:裁剪的宽度。
crop_height:裁剪的高度。
rotation:旋转角度,可选值为 0(不旋转)、90、180 和 270。
fourcc:输入图像的格式,例如 UYVY、YUY2 等。
int I420Scale(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
int src_width,
int src_height,
uint8* dst_y,
int dst_stride_y,
uint8* dst_u,
int dst_stride_u,
uint8* dst_v,
int dst_stride_v,
int dst_width,
int dst_height,
enum FilterMode filtering)
I420Scale 函数参数含义:
src_y:源图像的 Y 分量数据指针。
src_stride_y:源图像的 Y 分量数据行跨度(即每行像素数据占用的字节数)。
src_u:源图像的 U 分量数据指针。
src_stride_u:源图像的 U 分量数据行跨度。
src_v:源图像的 V 分量数据指针。
src_stride_v:源图像的 V 分量数据行跨度。
src_width:源图像的宽度。
src_height:源图像的高度。
dst_y:目标图像的 Y 分量数据指针。
dst_stride_y:目标图像的 Y 分量数据行跨度。
dst_u:目标图像的 U 分量数据指针。
dst_stride_u:目标图像的 U 分量数据行跨度。
dst_v:目标图像的 V 分量数据指针。
dst_stride_v:目标图像的 V 分量数据行跨度。
dst_width:目标图像的宽度。
dst_height:目标图像的高度。
filtering:指定缩放时使用的滤波器模式。
int I420Rotate(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
uint8* dst_y,
int dst_stride_y,
uint8* dst_u,
int dst_stride_u,
uint8* dst_v,
int dst_stride_v,
int width,
int height,
enum RotationMode mode)
src_y:指向输入图像的 Y 分量数据的指针。
src_stride_y:输入图像 Y 分量数据的跨度,即每行像素数据占用的字节数。
src_u:指向输入图像的 U 分量数据的指针。
src_stride_u:输入图像 U 分量数据的跨度,即每行像素数据占用的字节数。
src_v:指向输入图像的 V 分量数据的指针。
src_stride_v:输入图像 V 分量数据的跨度,即每行像素数据占用的字节数。
dst_y:指向输出图像的 Y 分量数据的指针。
dst_stride_y:输出图像 Y 分量数据的跨度,即每行像素数据占用的字节数。
dst_u:指向输出图像的 U 分量数据的指针。
dst_stride_u:输出图像 U 分量数据的跨度,即每行像素数据占用的字节数。
dst_v:指向输出图像的 V 分量数据的指针。
dst_stride_v:输出图像 V 分量数据的跨度,即每行像素数据占用的字节数。
width:输入图像的宽度。
height:输入图像的高度。
mode:旋转模式,可以是 kRotate0(不旋转,默认值)、kRotate90(顺时针旋转90度)、kRotate180(顺时针旋转180度)和 kRotate270(顺时针旋转270度)。
int I420ToRGB565(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
uint8* dst_rgb565,
int dst_stride_rgb565,
int width,
int height)
I420ToRGB565 函数参数含义:
src_y:源图像的 Y 分量数据指针。
src_stride_y:源图像的 Y 分量数据行跨度。
src_u:源图像的 U 分量数据指针。
src_stride_u:源图像的 U 分量数据行跨度。
src_v:源图像的 V 分量数据指针。
src_stride_v:源图像的 V 分量数据行跨度。
dst_rgb565:目标图像的 RGB565 数据指针。
dst_stride_rgb565:目标图像的 RGB565 数据行跨度。
width:图像的宽度。
height:图像的高度。
int RotatePlane(const uint8* src,
int src_stride,
uint8* dst,
int dst_stride,
int width,
int height,
enum RotationMode mode)
RotatePlane 函数参数含义:
src:源图像数据指针。
src_stride:源图像数据行跨度。
dst:目标图像数据指针。
dst_stride:目标图像数据行跨度。
width:图像的宽度。
height:图像的高度。
mode:指定旋转的模式。
//i420裁剪
int Jni_CutI420(JNIEnv * env,jclass clazz,jbyteArray src,jint srcWidth,jint srcHeight,jbyteArray dst,jint xStart,jint yStart,jint xSize,jint ySize){
jbyte * src_=env->GetByteArrayElements(src,JNI_FALSE);
jbyte * dst_=env->GetByteArrayElements(dst,JNI_FALSE);
libyuv::ConvertToI420(
(uint8 *)src_,
srcWidth*srcHeight*3/2,
(uint8 *)dst_,
xSize,
(uint8 *)dst_+xSize*ySize,
(xSize+1)/2,
(uint8 *)dst_+xSize*ySize+((xSize+1)/2)*((ySize+1)/2),
(xSize+1)/2,
xStart,
yStart,
srcWidth,
srcHeight,
xSize,
ySize,
libyuv::kRotate0,
libyuv::FOURCC_YU12);
env->ReleaseByteArrayElements(src,src_,JNI_OK);
env->ReleaseByteArrayElements(dst,dst_,JNI_OK);
return 0;
}
用下面方案把大尺寸的UYVY视频转换为小尺寸的RGB565视频,输出画面内容混乱,偏绿,画面很不清晰,画面有很多小网格,请分析下面代码,并给出修正后能使输出的RGB565画面正常的代码,并给出完整的新方案
typedef enum RotationMode {
kRotate0 = 0, // No rotation.
kRotate90 = 90, // Rotate 90 degrees clockwise.
kRotate180 = 180, // Rotate 180 degrees.
kRotate270 = 270, // Rotate 270 degrees clockwise.
// Deprecated.
kRotateNone = 0,
kRotateClockwise = 90,
kRotateCounterClockwise = 270,
} RotationModeEnum;
typedef enum FilterMode {
kFilterNone = 0, // Point sample; Fastest.
kFilterLinear = 1, // Filter horizontally only.
kFilterBilinear = 2, // Faster than box, but lower quality scaling down.
kFilterBox = 3 // Highest quality.
} FilterModeEnum;
typedef unsigned char uint8;
typedef unsigned int uint32;
// 声明libyuv.so中的函数原型
typedef int (*ConvertToI420Func)(const uint8* sample,
size_t sample_size,
uint8* y,
int y_stride,
uint8* u,
int u_stride,
uint8* v,
int v_stride,
int crop_x,
int crop_y,
int src_width,
int src_height,
int crop_width,
int crop_height,
enum RotationMode rotation,
uint32 fourcc);
typedef int (*I420ScaleFunc)(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
int src_width,
int src_height,
uint8* dst_y,
int dst_stride_y,
uint8* dst_u,
int dst_stride_u,
uint8* dst_v,
int dst_stride_v,
int dst_width,
int dst_height,
enum FilterMode filtering);
typedef int (*I420RotateFunc)(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
uint8* dst_y,
int dst_stride_y,
uint8* dst_u,
int dst_stride_u,
uint8* dst_v,
int dst_stride_v,
int width,
int height,
enum RotationMode mode);
typedef int (*I420ToRGB565Func)(const uint8* src_y,
int src_stride_y,
const uint8* src_u,
int src_stride_u,
const uint8* src_v,
int src_stride_v,
uint8* dst_rgb565,
int dst_stride_rgb565,
int width,
int height);
static int hw_convert_image(int in_fmt, int in_width, int in_height, uintptr_t in_addr, int out_fmt, int out_width, int out_height, uintptr_t out_addr, int rot) {
void* libyuv = dlopen("/system/lib/vndk-28/libyuv.so", RTLD_LAZY);
if (libyuv == NULL) {
ERROR("Failed to load libyuv.so\n");
return -1;
}
// 获取各个函数地址
ConvertToI420Func convertToI420 = (ConvertToI420Func)dlsym(libyuv, "ConvertToI420");
I420ScaleFunc i420Scale = (I420ScaleFunc)dlsym(libyuv, "I420Scale");
I420RotateFunc i420Rotate = (I420RotateFunc)dlsym(libyuv, "I420Rotate");
I420ToRGB565Func i420ToRGB565 = (I420ToRGB565Func)dlsym(libyuv, "I420ToRGB565");
if (convertToI420 == NULL || i420Scale == NULL || i420Rotate == NULL || i420ToRGB565 == NULL) {
ERROR("Failed to get function addresses\n");
dlclose(libyuv);
return -1;
}
// 输入参数
const int src_width = in_width;
const int src_height = in_height;
const int src_stride_y = src_width * 2;
const int src_stride_uv = src_width;
const uint8* src = (const uint8*)in_addr;
// 创建I420格式的临时数据存储转换结果
const int i420_size = src_width * src_height * 3 / 2;
uint8* i420_data = (uint8*)malloc(i420_size);
uint8* y_plane = i420_data;
uint8* u_plane = i420_data + src_width * src_height;
uint8* v_plane = u_plane + (src_width + 1) / 2;
// 将输入数据复制到临时缓冲区
memcpy(i420_data, src, i420_size);
// 转换为I420格式
convertToI420(i420_data, i420_size, y_plane, src_width, u_plane, src_width / 2, v_plane, src_width / 2, 0, 0, src_width, src_height, src_width, src_height, (enum RotationMode)rot, 0);
// 输出参数
const int dst_width = out_width;
const int dst_height = out_height;
const int dst_stride_y = dst_width;
const int dst_stride_uv = (dst_width + 1) / 2;
uint8* dst = (uint8*)out_addr;
// 创建输出RGB565或RGB888的缓冲区
const int dst_size = dst_width * dst_height * (out_fmt == JPEG_OUT_FORMAT_RGB565 ? 2 : 3);
uint8* dst_data = (uint8*)malloc(dst_size);
// 图像缩放
i420Scale(y_plane, src_width, u_plane, src_width / 2, v_plane, src_width / 2, src_width, src_height, y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_width, dst_height, kFilterBilinear);
// 图像旋转
i420Rotate(y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_width, dst_height, (enum RotationMode)rot);
// I420格式转换为RGB565或RGB888
i420ToRGB565(y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_data, dst_width * (out_fmt == JPEG_OUT_FORMAT_RGB565 ? 2 : 3), dst_width, dst_height);
// 将结果拷贝到输出地址
memcpy(dst, dst_data, dst_size);
// 释放内存和关闭库
free(i420_data);
free(dst_data);
dlclose(libyuv);
return 0;
}
NO1
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
// 定义 libyuv 函数指针类型
typedef int (*ConvertToI420Func)(const uint8_t* sample, size_t sample_size,
uint8_t* y, int y_stride,
uint8_t* u, int u_stride,
uint8_t* v, int v_stride,
int crop_x, int crop_y,
int src_width, int src_height,
int crop_width, int crop_height,
enum RotationMode rotation,
uint32_t fourcc);
typedef int (*I420ScaleFunc)(const uint8_t* src_y, int src_stride_y,
const uint8_t* src_u, int src_stride_u,
const uint8_t* src_v, int src_stride_v,
int src_width, int src_height,
uint8_t* dst_y, int dst_stride_y,
uint8_t* dst_u, int dst_stride_u,
uint8_t* dst_v, int dst_stride_v,
int dst_width, int dst_height,
enum FilterMode filtering);
typedef int (*I420ToRGB565Func)(const uint8_t* src_y, int src_stride_y,
const uint8_t* src_u, int src_stride_u,
const uint8_t* src_v, int src_stride_v,
uint8_t* dst_rgb565, int dst_stride_rgb565,
int width, int height);
typedef int (*RotatePlaneFunc)(const uint8_t* src, int src_stride,
uint8_t* dst, int dst_stride,
int width, int height,
enum RotationMode mode);
int hw_convert_image(int in_fmt, int in_width, int in_height, uintptr_t in_addr,
int out_fmt, int out_width, int out_height, uintptr_t out_addr,
int rot) {
void* libyuv_lib = dlopen("libyuv.so", RTLD_NOW);
if (!libyuv_lib) {
printf("Failed to load libyuv.so: %s\n", dlerror());
return -1;
}
// 使用 dlsym 获取函数指针
ConvertToI420Func convertToI420 = (ConvertToI420Func)dlsym(libyuv_lib, "ConvertToI420");
I420ScaleFunc i420Scale = (I420ScaleFunc)dlsym(libyuv_lib, "I420Scale");
I420ToRGB565Func i420ToRGB565 = (I420ToRGB565Func)dlsym(libyuv_lib, "I420ToRGB565");
RotatePlaneFunc rotatePlane = (RotatePlaneFunc)dlsym(libyuv_lib, "RotatePlane");
if (!convertToI420 || !i420Scale || !i420ToRGB565 || !rotatePlane) {
printf("Failed to get function pointers from libyuv.so: %s\n", dlerror());
dlclose(libyuv_lib);
return -1;
}
// 输入参数
const uint8_t* in_data = (const uint8_t*)in_addr;
int in_stride_y = in_width;
int in_stride_uv = in_width;
int crop_x = 0;
int crop_y = 0;
int crop_width = in_width;
int crop_height = in_height;
// 输出参数
uint8_t* out_data = (uint8_t*)out_addr;
int out_stride_rgb565 = out_width * 2;
// 转换为 I420 格式
uint8_t* y_plane = out_data;
int y_stride = out_width;
uint8_t* u_plane = y_plane + (y_stride * out_height);
int u_stride = out_width / 2;
uint8_t* v_plane = u_plane + (u_stride * out_height / 2);
int v_stride = out_width / 2;
convertToI420(in_data, in_width * in_height * 2, y_plane, y_stride, u_plane, u_stride, v_plane, v_stride,
crop_x, crop_y, in_width, in_height, crop_width, crop_height, rot, 'UYVY');
// 缩放为目标尺寸
uint8_t* scaled_y_plane = malloc(out_width * out_height);
int scaled_y_stride = out_width;
uint8_t* scaled_u_plane = malloc(out_width / 2 * out_height / 2);
int scaled_u_stride = out_width / 2;
uint8_t* scaled_v_plane = malloc(out_width / 2 * out_height / 2);
int scaled_v_stride = out_width / 2;
i420Scale(y_plane, y_stride, u_plane, u_stride, v_plane, v_stride, out_width, out_height,
scaled_y_plane, scaled_y_stride, scaled_u_plane, scaled_u_stride,
scaled_v_plane, scaled_v_stride, out_width, out_height, kFilterNone);
// 转换为 RGB565
uint8_t* rgb565_data = malloc(out_width * out_height * 2);
int rgb565_stride = out_width * 2;
i420ToRGB565(scaled_y_plane, scaled_y_stride, scaled_u_plane, scaled_u_stride,
scaled_v_plane, scaled_v_stride, rgb565_data, rgb565_stride, out_width, out_height);
// 释放缓冲区内存
free(scaled_y_plane);
free(scaled_u_plane);
free(scaled_v_plane);
// 旋转图像
rotatePlane(rgb565_data, rgb565_stride, out_data, out_stride_rgb565, out_width, out_height, rot);
// 释放缓冲区内存
free(rgb565_data);
dlclose(libyuv_lib);
return 0;
}
NO2
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "libyuv.h"
// 定义输入格式和输出格式的枚举类型
typedef enum {
UYVY,
YUYV
} InputFormat;
typedef enum {
RGB565,
RGB888
} OutputFormat;
// 实现hw_convert_image函数
int hw_convert_image(int in_fmt, int in_width, int in_height, uintptr_t in_addr,
int out_fmt, int out_width, int out_height, uintptr_t out_addr, int rot) {
void *libyuv_handle = dlopen("libyuv.so", RTLD_LAZY); // 动态加载libyuv库
if (!libyuv_handle) {
fprintf(stderr, "Error opening libyuv.so: %s\n", dlerror());
return -1;
}
// 获取ConvertToI420函数指针
int (*ConvertToI420)(const uint8_t*, size_t, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, int, int, int, int, enum RotationMode, uint32_t);
ConvertToI420 = (int (*)(const uint8_t*, size_t, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, int, int, int, int, enum RotationMode, uint32_t))dlsym(libyuv_handle, "ConvertToI420");
// 获取I420Scale函数指针
int (*I420Scale)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, int, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, enum FilterMode);
I420Scale = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, int, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, enum FilterMode))dlsym(libyuv_handle, "I420Scale");
// 获取I420ToRGB565函数指针
int (*I420ToRGB565)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int);
I420ToRGB565 = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "I420ToRGB565");
// 获取RotatePlane函数指针
int (*RotatePlane)(const uint8_t*, int, uint8_t*, int, int, int, enum RotationMode);
RotatePlane = (int (*)(const uint8_t*, int, uint8_t*, int, int, int, enum RotationMode))dlsym(libyuv_handle, "RotatePlane");
if (!ConvertToI420 || !I420Scale || !I420ToRGB565 || !RotatePlane) {
fprintf(stderr, "Error getting symbol for functions: %s\n", dlerror());
dlclose(libyuv_handle);
return -1;
}
// 其他参数设置
int crop_x = 0;
int crop_y = 0;
int crop_width = in_width;
int crop_height = in_height;
uint32_t fourcc = 0;
// 计算输入数据每行的字节数
int in_stride = in_width * 2; // UYVY和YUYV格式每像素占2字节
// 计算输出数据每行的字节数
int out_stride = (out_fmt == RGB565) ? (out_width * 2) : (out_width * 3); // RGB565每像素占2字节,RGB888每像素占3字节
// 分配输入和输出数据的内存
uint8_t* in_data = (uint8_t*)malloc(in_stride * in_height);
uint8_t* out_data = (uint8_t*)malloc(out_stride * out_height);
// 将输入数据拷贝到内存中
memcpy(in_data, (uint8_t*)in_addr, in_stride * in_height);
// 分配I420数据内存
int i420_size = out_width * out_height * 3 / 2;
uint8_t* i420_data = (uint8_t*)malloc(i420_size);
// 调用ConvertToI420函数将输入数据转换为I420格式
ConvertToI420(in_data, in_stride, i420_data, out_width,
i420_data + out_width * out_height, out_width / 2,
i420_data + out_width * out_height * 5 / 4, out_width / 2,
crop_x, crop_y, in_width, in_height, crop_width, crop_height, (enum RotationMode)rot, fourcc);
// 调用I420Scale函数将I420数据缩放到指定尺寸
I420Scale(i420_data, out_width,
i420_data + out_width * out_height, out_width / 2,
i420_data + out_width * out_height * 5 / 4, out_width / 2,
out_width, out_height,
out_data, out_stride,
out_data + out_width * out_height, out_stride / 2,
out_data + out_width * out_height * 5 / 4, out_stride / 2,
out_width, out_height,
kFilterBox);
// 根据输出格式选择相应的函数进行格式转换
if (out_fmt == RGB565) {
// 调用I420ToRGB565函数将I420数据转换为RGB565格式
I420ToRGB565(out_data, out_stride,
out_data + out_width * out_height, out_stride / 2,
out_data + out_width * out_height * 5 / 4, out_stride / 2,
out_data, out_stride,
out_width, out_height);
} else if (out_fmt == RGB888) {
// 调用RotatePlane函数将RGB565格式旋转为RGB888格式
RotatePlane(out_data, out_stride,
out_data, out_stride,
out_width, out_height, kRotate0);
}
// 将输出数据拷贝到指定地址
memcpy((uint8_t*)out_addr, out_data, out_stride * out_height);
// 释放内存
free(in_data);
free(out_data);
free(i420_data);
dlclose(libyuv_handle); // 关闭libyuv库
return 0;
}
int main() {
// 输入参数
int in_fmt = UYVY;
int in_width = 1884;
int in_height = 1056;
// 分配输入数据内存并初始化
size_t in_size = in_width * in_height * 2; // UYVY格式每像素占2字节
uint8_t* in_data = (uint8_t*)malloc(in_size);
memset(in_data, 0xFF, in_size); // 假设输入数据全为白色
// 输出参数
int out_fmt = RGB565;
int out_width = 1440;
int out_height = 720;
// 分配输出数据内存
size_t out_size = out_width * out_height * 2; // RGB565格式每像素占2字节
uint8_t* out_data = (uint8_t*)malloc(out_size);
// 调用hw_convert_image函数进行图像格式转换
hw_convert_image(in_fmt, in_width, in_height, (uintptr_t)in_data,
out_fmt, out_width, out_height, (uintptr_t)out_data, 0);
// 在这里可以对输出数据进行处理或保存到文件
// 释放内存
free(in_data);
free(out_data);
return 0;
}
TWO:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "libyuv.h"
// 实现hw_convert_video函数
int hw_convert_video(int in_width, int in_height, uintptr_t in_addr,
int out_width, int out_height, uintptr_t out_addr) {
void *libyuv_handle = dlopen("libyuv.so", RTLD_LAZY); // 动态加载libyuv库
if (!libyuv_handle) {
fprintf(stderr, "Error opening libyuv.so: %s\n", dlerror());
return -1;
}
// 获取UYVYToI420函数指针
int (*UYVYToI420)(const uint8_t*, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int);
UYVYToI420 = (int (*)(const uint8_t*, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "UYVYToI420");
// 获取I420ToRGB565函数指针
int (*I420ToRGB565)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int);
I420ToRGB565 = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "I420ToRGB565");
if (!UYVYToI420 || !I420ToRGB565) {
fprintf(stderr, "Error getting symbol for functions: %s\n", dlerror());
dlclose(libyuv_handle);
return -1;
}
// 计算输入数据每行的字节数
int in_stride = in_width * 2; // UYVY格式每像素占2字节
// 计算输出数据每行的字节数
int out_stride = out_width * 2; // RGB565每像素占2字节
// 分配输入和输出数据的内存
uint8_t* in_data = (uint8_t*)malloc(in_stride * in_height);
uint8_t* out_data = (uint8_t*)malloc(out_stride * out_height);
// 将输入数据拷贝到内存中
memcpy(in_data, (uint8_t*)in_addr, in_stride * in_height);
// 分配I420数据内存
int i420_size = out_width * out_height * 3 / 2;
uint8_t* i420_data = (uint8_t*)malloc(i420_size);
// 调用UYVYToI420函数将输入数据转换为I420格式
UYVYToI420(in_data, in_stride, i420_data, out_width,
i420_data + out_width * out_height, out_width / 2,
i420_data + out_width * out_height * 5 / 4, out_width / 2,
in_width, in_height);
// 调用I420ToRGB565函数将I420数据转换为RGB565格式
I420ToRGB565(i420_data, out_width,
i420_data + out_width * out_height, out_width / 2,
i420_data + out_width * out_height * 5 / 4, out_width / 2,
out_data, out_stride,
out_width, out_height);
// 将输出数据拷贝到指定地址
memcpy((uint8_t*)out_addr, out_data, out_stride * out_height);
// 释放内存
free(in_data);
free(out_data);
free(i420_data);
dlclose(libyuv_handle); // 关闭libyuv库
return 0;
}
int main() {
// 输入参数
int in_width = 1884;
int in_height = 1056;
// 分配输入数据内存并初始化
size_t in_size = in_width * in_height * 2; // UYVY格式每像素占2字节
uint8_t* in_data = (uint8_t*)malloc(in_size);
memset(in_data, 0xFF, in_size); // 假设输入数据全为白色
// 输出参数
int out_width = 1440;
int out_height = 720;
// 分配输出数据内存
size_t out_size = out_width * out_height * 2; // RGB565格式每像素占2字节
uint8_t* out_data = (uint8_t*)malloc(out_size);
// 调用hw_convert_video函数进行视频格式转换
hw_convert_video(in_width, in_height, (uintptr_t)in_data,
out_width, out_height, (uintptr_t)out_data);
// 在这里可以对输出数据进行处理或保存到文件
// 释放内存
free(in_data);
free(out_data);
return 0;
}