RGB24转YUV420P实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static unsigned char clip_value(unsigned char val, unsigned char min_val, unsigned char max_val)
{
if (val > max_val)
{
return max_val;
}
else if (val < min_val)
{
return min_val;
}
else
{
return val;
}
}
static int __rgb24_to_yuv420p(unsigned char *rgb24_buf, int w, int h, unsigned char *yuv420p_buf)
{
unsigned char *yuv420p_y = NULL;
unsigned char *yuv420p_u = NULL;
unsigned char *yuv420p_v = NULL;
unsigned char *rgb24 = NULL;
unsigned char y, u, v, r, g, b;
int i, j;
memset(yuv420p_buf, 0, (w * h * 3)/2);
yuv420p_y = yuv420p_buf;
yuv420p_u = yuv420p_buf + w * h;
yuv420p_v = yuv420p_buf + w * h + (w * h)/4;
for (j = 0; j < h; j++)
{
rgb24 = rgb24_buf + j * w * 3;
for (i = 0; i < w; i++)
{
r = *(rgb24++);
g = *(rgb24++);
b = *(rgb24++);
y = (unsigned char)(( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
*(yuv420p_y++) = clip_value(y, 0, 255);
if (j % 2 == 0)
{
if (i % 2 == 0)
{
*(yuv420p_u++) = clip_value(u, 0, 255);
}
}
else
{
if (i % 2 == 0)
{
*(yuv420p_v++) = clip_value(v, 0, 255);
}
}
}
}
return 0;
}
int rgb24_to_yuv420p(const char *file_rgb24, int w, int h, const char *file_yuv420p)
{
FILE *fp_rgb24 = fopen(file_rgb24, "rb+");
FILE *fp_yuv420p = fopen(file_yuv420p, "wb+");
unsigned int rgb24_size = w * h * 3;
unsigned int yuv420p_size = w * h * 3/2;
unsigned char *rgb24_buf = (unsigned char *)malloc(rgb24_size);
if (rgb24_buf == NULL)
{
printf("malloc error: rgb24_buf error\n");
fclose(fp_rgb24);
fclose(fp_yuv420p);
return -1;
}
unsigned char *yuv420p_buf = (unsigned char *)malloc(yuv420p_size);
if (rgb24_buf == NULL)
{
printf("malloc error: yuv420p_buf error\n");
free(rgb24_buf);
fclose(fp_rgb24);
fclose(fp_yuv420p);
return -1;
}
fread(rgb24_buf, 1, rgb24_size, fp_rgb24);
__rgb24_to_yuv420p(rgb24_buf, w, h, yuv420p_buf);
fwrite(yuv420p_buf, 1, yuv420p_size, fp_yuv420p);
free(rgb24_buf);
free(yuv420p_buf);
fclose(fp_rgb24);
fclose(fp_yuv420p);
return 0;
}
int main(void)
{
const char *file_rgb24 = "lena_256x256_rgb24.rgb";
const char *file_yuv420p = "output_lena_256x256_yuv420p.yuv";
rgb24_to_yuv420p(file_rgb24, 256, 256, file_yuv420p);
return 0;
}
参考
视音频数据处理入门:RGB、YUV像素数据处理