目的:yuv420数据转换成jpg数据
网上例子:bmp/jpg格式互换的例子, yuv422-->jpg 的例子。
思路:模仿422->jpg的例子, 提取yuv420的rgb值进行转换。
依赖: libjpeg开源库,http://www.ijg.org/。
编译: gcc -o XXX 代码.c -ljpeg
代码:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <setjmp.h>
#include <jpeglib.h>
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define WIDTH 2432
#define HEIGHT 2048
unsigned char rgb[2432*2048*3] = {0,};
unsigned char yuv_src[2432*2048*3/2] = {0,};
void yuv420_to_rgb24()
{
FILE* fp = fopen("420-2432.yuv", "rb");
int ret = 0;
int r1,g1,b1,r2,g2,b2;
char* ptr = rgb;
fread(yuv_src, 1, WIDTH*HEIGHT*2, fp);
unsigned char* y_ou = yuv_src;
unsigned char* y_ji = yuv_src+ WIDTH;
unsigned char* uv_start = yuv_src + WIDTH*HEIGHT;
int i = 0, j=0;
unsigned char y0, y1,u0,v0;
for(i=0; i < HEIGHT/2; i++){
/*处理偶行*/
for(j = 0; j< WIDTH/2; j++){
y0 = *y_ou ++;
y1 = *y_ou ++;
//u0 = *uv_start++;
//v0 = *uv_start++;
v0 = *uv_start++;
u0 = *uv_start++;
r1 = y0 + 1.042*(v0-128);
g1 = y0 - 0.34414*(u0-128) - 0.71414*(v0-128);
b1 = y0 + 1.772*(u0-128);
r2 = y1 + 1.042*(v0-128);
g2 = y1 - 0.34414*(u0-128) - 0.71414*(v0-128);
b2 = y1 + 1.772*(u0-128);
if(r1<0) r1 = 0; else if(r1>255) r1 = 255;
if(g1<0) g1 = 0; else if(g1>255) g1 = 255;
if(b1<0) b1 = 0; else if(b1>255) b1 = 255;
if(r2<0) r2 = 0; else if(r2>255) r2 = 255;
if(g2<0) g2 = 0; else if(g2>255) g2 = 255;
if(b2<0) b2 = 0; else if(b2>255) b2 = 255;
*ptr = (unsigned char)b1;ptr++;
*ptr = (unsigned char)g1;ptr++;
*ptr = (unsigned char)r1;ptr++;
*ptr = (unsigned char)b2;ptr++;
*ptr = (unsigned char)g2;ptr++;
*ptr = (unsigned char)r2;ptr++;
}
uv_start -= WIDTH;
/*处理奇行*/
for(j=0; j<WIDTH/2; j++){
y0 = *y_ji ++;
y1 = *y_ji ++;
v0 = *uv_start++;
u0 = *uv_start++;
r1 = y0 + 1.042*(v0-128);
g1 = y0 - 0.34414*(u0-128) - 0.71414*(v0-128);
b1 = y0 + 1.772*(u0-128);
r2 = y1 + 1.042*(v0-128);
g2 = y1 - 0.34414*(u0-128) - 0.71414*(v0-128);
b2 = y1 + 1.772*(u0-128);
if(r1<0) r1 = 0; else if(r1>255) r1 = 255;
if(g1<0) g1 = 0; else if(g1>255) g1 = 255;
if(b1<0) b1 = 0; else if(b1>255) b1 = 255;
if(r2<0) r2 = 0; else if(r2>255) r2 = 255;
if(g2<0) g2 = 0; else if(g2>255) g2 = 255;
if(b2<0) b2 = 0; else if(b2>255) b2 = 255;
*ptr = (unsigned char)b1;ptr++;
*ptr = (unsigned char)g1;ptr++;
*ptr = (unsigned char)r1;ptr++;
*ptr = (unsigned char)b2;ptr++;
*ptr = (unsigned char)g2;ptr++;
*ptr = (unsigned char)r2;ptr++;
}
y_ou += WIDTH;
y_ji += WIDTH;
}
return ;
}
BOOL encode_jpeg(char *lpbuf,int width,int height, int quality)
{
struct jpeg_compress_struct cinfo ;
struct jpeg_error_mgr jerr ;
JSAMPROW row_pointer[1] ;
int row_stride ;
char *buf=NULL ;
int x ;
FILE *fptr_jpg = fopen ("f.jpg","wb");//注意这里为什么用fopen而不用open
if(fptr_jpg==NULL)
{
printf("Encoder:open file failed!/n") ;
return FALSE;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fptr_jpg);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality,TRUE);
jpeg_start_compress(&cinfo, TRUE);
row_stride = width * 3;
buf=malloc(row_stride) ;
row_pointer[0] = buf;
while (cinfo.next_scanline < height)
{
for (x = 0; x < row_stride; x+=3)
{
buf[x] = lpbuf[x];
buf[x+1] = lpbuf[x+1];
buf[x+2] = lpbuf[x+2];
}
jpeg_write_scanlines (&cinfo, row_pointer, 1);//critical
lpbuf += row_stride;
}
jpeg_finish_compress(&cinfo);
fclose(fptr_jpg);
jpeg_destroy_compress(&cinfo);
free(buf) ;
return TRUE ;
}
int main(int argc, char* argv[])
{
struct timeval tv;
gettimeofday(&tv, NULL);
printf("-------------- now: sec %d usec %d \n", (int)tv.tv_sec, (int)tv.tv_usec);
yuv420_to_rgb24();
encode_jpeg(rgb,2432,2048, atoi(argv[1])); //RGB24 to Jpeg
gettimeofday(&tv, NULL);
printf("-------------- now: sec %d usec %d \n", (int)tv.tv_sec, (int)tv.tv_usec);
printf("save JPEG OK\n");
return(TRUE);
}