说明:将图片转到jpeg(我用的是jpegsrc.v9d.tar.gz),需要用到libjpeg库,下载目录http://www.ijg.org/,
安装方法:
1. ./configure --prefix=目录
2. make
3. make install
yuyv转rgb:
void yuv_to_rgb(unsigned char *yuv, unsigned char *rgb)
{
unsigned int i;
unsigned char* y0 = yuv + 0;
unsigned char* u0 = yuv + 1;
unsigned char* y1 = yuv + 2;
unsigned char* v0 = yuv + 3;
unsigned char* r0 = rgb + 0;
unsigned char* g0 = rgb + 1;
unsigned char* b0 = rgb + 2;
unsigned char* r1 = rgb + 3;
unsigned char* g1 = rgb + 4;
unsigned char* b1 = rgb + 5;
float rt0 = 0, gt0 = 0, bt0 = 0, rt1 = 0, gt1 = 0, bt1 = 0;
for(i = 0; i <= (IMAGE_W * IMAGE_H) / 2 ;i++)
{
bt0 = 1.164 * (*y0 - 16) + 2.018 * (*u0 - 128);
gt0 = 1.164 * (*y0 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
rt0 = 1.164 * (*y0 - 16) + 1.596 * (*v0 - 128);
bt1 = 1.164 * (*y1 - 16) + 2.018 * (*u0 - 128);
gt1 = 1.164 * (*y1 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
rt1 = 1.164 * (*y1 - 16) + 1.596 * (*v0 - 128);
if(rt0 > 250) rt0 = 255;
if(rt0< 0) rt0 = 0;
if(gt0 > 250) gt0 = 255;
if(gt0 < 0) gt0 = 0;
if(bt0 > 250) bt0 = 255;
if(bt0 < 0) bt0 = 0;
if(rt1 > 250) rt1 = 255;
if(rt1 < 0) rt1 = 0;
if(gt1 > 250) gt1 = 255;
if(gt1 < 0) gt1 = 0;
if(bt1 > 250) bt1 = 255;
if(bt1 < 0) bt1 = 0;
*r0 = (unsigned char)rt0;
*g0 = (unsigned char)gt0;
*b0 = (unsigned char)bt0;
*r1 = (unsigned char)rt1;
*g1 = (unsigned char)gt1;
*b1 = (unsigned char)bt1;
yuv = yuv + 4;
rgb = rgb + 6;
if(yuv == NULL)
break;
y0 = yuv;
u0 = yuv + 1;
y1 = yuv + 2;
v0 = yuv + 3;
r0 = rgb + 0;
g0 = rgb + 1;
b0 = rgb + 2;
r1 = rgb + 3;
g1 = rgb + 4;
b1 = rgb + 5;
}
}
rgb转jpeg:
long rgb_to_jpeg(unsigned char *rgb, unsigned char *jpeg)
{
size_t jpeg_size;
struct jpeg_compress_struct jcs;
struct jpeg_error_mgr jem;
JSAMPROW row_pointer[1];
int row_stride;
jcs.err = jpeg_std_error(&jem);
jpeg_create_compress(&jcs);
jpeg_mem_dest(&jcs, &jpeg, &jpeg_size);//就是这个函数!!!!!!!
jcs.image_width = IMAGE_W;
jcs.image_height = IMAGE_H;
jcs.input_components = 3;//1;
jcs.in_color_space = JCS_RGB;//JCS_GRAYSCALE;
jpeg_set_defaults(&jcs);
jpeg_set_quality(&jcs, 180, TRUE);
jpeg_start_compress(&jcs, TRUE);
row_stride =jcs.image_width * 3;
while(jcs.next_scanline < jcs.image_height){//对每一行进行压缩
row_pointer[0] = &rgb[jcs.next_scanline * row_stride];
(void)jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
jpeg_destroy_compress(&jcs);
#ifdef JPEG //jpeg 保存,测试用
FILE *jpeg_fd;
jpeg_fd = fopen("./jpeg.jpg","w");
if(jpeg_fd < 0 ){
perror("open jpeg.jpg failed!\n");
exit(-1);
}
fwrite(jpeg, jpeg_size, 1, jpeg_fd);
fclose(jpeg_fd);
#endif
return jpeg_size;
}
yuyv转yuv420:
int YUV422To420(unsigned char *yuv422, unsigned char *yuv420, int width, int height)
{
int ynum=width*height;
int i,j,k=0;
//得到Y分量
for(i=0;i<ynum;i++){
yuv420[i]=yuv422[i*2];
}
//得到U分量
for(i=0;i<height;i++){
if((i%2)!=0)continue;
for(j=0;j<(width/2);j++){
if((4*j+1)>(2*width))break;
yuv420[ynum+k*2*width/4+j]=yuv422[i*2*width+4*j+1];
}
k++;
}
k=0;
//得到V分量
for(i=0;i<height;i++){
if((i%2)==0)continue;
for(j=0;j<(width/2);j++){
if((4*j+3)>(2*width))break;
yuv420[ynum+ynum/4+k*2*width/4+j]=yuv422[i*2*width+4*j+3];
}
k++;
}
return 1;
}
yuv420转jpeg:待测试
uint32_t yuv420sp_to_jpg(int width, int height, unsigned char *inputYuv,unsigned char *outJpeg)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
int i = 0, j = 0;
unsigned char *pY, *pU, *pV;
unsigned char yuvbuf[width * 3];
unsigned long outSize;
cinfo.err = jpeg_std_error(&jerr);//用于错误信息
jpeg_create_compress(&cinfo); //初始化压缩对象
jpeg_mem_dest(&cinfo, &outJpeg, &outSize);
cinfo.image_width = width;//设置输入图片宽度
cinfo.image_height = height;//设置图片高度
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;//设置输入图片的格式,支持RGB/YUV/YCC等等
cinfo.dct_method = JDCT_FLOAT;
jpeg_set_defaults(&cinfo);//其它参数设置为默认的!
jpeg_set_quality(&cinfo, 40, TRUE);//设置转化图片质量,范围0-100
jpeg_start_compress(&cinfo, TRUE);
pY = inputYuv ;
pU = inputYuv +1 ;
pV = inputYuv + 3;
j = 1;
while (cinfo.next_scanline < cinfo.image_height) {
int index = 0;
for (i = 0; i < width; i += 2){//输入的YUV图片格式为标准的YUV444格式,所以需要把YUV420转化成YUV444.
yuvbuf[index++] = *pY;
yuvbuf[index++] = *pU;
yuvbuf[index++] = *pV;
pY += 2;
yuvbuf[index++] = *pY;
yuvbuf[index++] = *pU;
yuvbuf[index++] = *pV;
pY += 2;
pU += 4;
pV += 4;
}
row_pointer[0] = yuvbuf;
(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);//单行图片转换压缩
j++;
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
fwrite(outJpeg, outSize, 1, jpeg_fd);
fclose(jpeg_fd);
return (uint32_t)outSize;
}
yuyv转jpeg:
#define IMAGE_W 1280
#define IMAGE_H 720
#define OUTPUT_BUF_SIZE 4096
typedef struct {
struct jpeg_destination_mgr pub;
JOCTET * buffer;
unsigned char *outbuffer;
int outbuffer_size;
unsigned char *outbuffer_cursor;
int *written;
}mjpg_destination_mgr;
typedef mjpg_destination_mgr *mjpg_dest_ptr;
METHODDEF(void) init_destination(j_compress_ptr cinfo) {
mjpg_dest_ptr dest =(mjpg_dest_ptr) cinfo->dest;
dest->buffer =(JOCTET *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE*sizeof(JOCTET));
*(dest->written) = 0;
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo) {
mjpg_dest_ptr dest =(mjpg_dest_ptr) cinfo->dest;
memcpy(dest->outbuffer_cursor, dest->buffer, OUTPUT_BUF_SIZE);
dest->outbuffer_cursor += OUTPUT_BUF_SIZE;
*(dest->written) += OUTPUT_BUF_SIZE;
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
METHODDEF(void) term_destination(j_compress_ptr cinfo) {
mjpg_dest_ptr dest =(mjpg_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
memcpy(dest->outbuffer_cursor, dest->buffer, datacount);
dest->outbuffer_cursor += datacount;
*(dest->written) += datacount;
}
void dest_buffer(j_compress_ptr cinfo, unsigned char *buffer, int size, int *written) {
mjpg_dest_ptr dest;
if(cinfo->dest == NULL) {
cinfo->dest =(struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(mjpg_destination_mgr));
}
dest =(mjpg_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->outbuffer = buffer;
dest->outbuffer_size = size;
dest->outbuffer_cursor = buffer;
dest->written = written;
}
//......YUYV.....JPEG..
int compress_yuyv_to_jpeg(unsigned char *buf, unsigned char *buffer, int size, int quality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
unsigned char *line_buffer, *yuyv;
int z;
static int written;
//int count = 0;
//printf("%s\n", buf);
line_buffer = (unsigned char*)calloc(IMAGE_W * 3, 1);
yuyv = buf;
printf("compress start...\n");
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
/* jpeg_stdio_dest(&cinfo, file); */
dest_buffer(&cinfo, buffer, size, &written);
cinfo.image_width = IMAGE_W;
cinfo.image_height = IMAGE_H;
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);
z = 0;
while(cinfo.next_scanline < IMAGE_H) {
int x;
unsigned char *ptr = line_buffer;
for(x = 0; x < IMAGE_W; x++) {
int r, g, b;
int y, u, v;
if(!z)
y = yuyv[0] << 8;
else
y = yuyv[2] << 8;
u = yuyv[1] - 128;
v = yuyv[3] - 128;
r =(y +(359 * v))>> 8;
g =(y -(88 * u) -(183 * v)) >> 8;
b =(y +(454 * u)) >> 8;
*(ptr++) =(r > 255) ? 255 :((r < 0) ? 0 : r);
*(ptr++) =(g > 255) ? 255 :((g < 0) ? 0 : g);
*(ptr++) =(b > 255) ? 255 :((b < 0) ? 0 : b);
if(z++) {
z = 0;
yuyv += 4;
}
}
row_pointer[0] = line_buffer;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
free(line_buffer);
return(written);
}
使用方法:
compress_yuyv_to_jpeg(buf, buffer,(IMAGE_W * IMAGE_H), 80);