概述
最近学习雷神的博客,深受启发。后面的代码或者借鉴原作的代码,或者修改自原作。一般的图片播放器无法显示rgb和yuv格式的图片,为了方便查看rgb和yuv图片,雷神修改了一个网上的YUV/RGB播放器,既支持YUV又支持RGB的播放器。不过要求图片名字类似于test_320x420.yuv,320x420是图片的宽和高。
rgb24转yuv420p
首先要了解rgb24和yuv420p的存储方式,yuv420p是先存y再存u最后是v分量。废话少说,直接上代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char max_val){
if(x>max_val){
return max_val;
}else if(x<min_val){
return min_val;
}else{
return x;
}
}
//RGB to YUV420
bool RGB24_TO_YUV420(unsigned char *RgbBuf,int w,int h,unsigned char *yuvBuf)
{
unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;
memset(yuvBuf,0,w*h*3/2);
ptrY = yuvBuf;
ptrU = yuvBuf + w*h;
ptrV = ptrU + (w*h*1/4);
unsigned char y, u, v, r, g, b;
for (int j = 0; j<h;j++){
ptrRGB = RgbBuf + w*j*3 ;
for (int i = 0;i<w;i++){
r = *(ptrRGB++);
g = *(ptrRGB++);
b = *(ptrRGB++);
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 ;
*(ptrY++) = clip_value(y,0,255);
if (j%2==0&&i%2 ==0){
*(ptrU++) =clip_value(u,0,255);
}
else{
if (i%2==0){
*(ptrV++) =clip_value(v,0,255);
}
}
}
}
return true;
}
int simplest_rgb24_to_yuv420(const char *url_in, int w, int h,int num,const char *url_out){
FILE *fp=fopen(url_in,"rb+");
FILE *fp1=fopen(url_out,"wb+");
unsigned char *pic_rgb24=(unsigned char *)malloc(w*h*3);
unsigned char *pic_yuv420=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic_rgb24,1,w*h*3,fp);
RGB24_TO_YUV420(pic_rgb24,w,h,pic_yuv420);
fwrite(pic_yuv420,1,w*h*3/2,fp1);
}
free(pic_rgb24);
free(pic_yuv420);
fclose(fp);
fclose(fp1);
return 0;
}
int main(){
//Test
simplest_rgb24_to_yuv420("../process_100jpg/pic_rgb/15_1024x640.rgb",1024,640,1,"15_1024x640.yuv"