jpeglib库实现MJPEG图像的压缩与解压缩

linux提供了jpeglib库用于MJPEG图像的压缩与解压缩等,编写V4L2应用程序,编译的时候加上选项-ljpeg表示使用jpeg库中的API函数

关于jpeg库API使用的说明在网站:http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Desktop-generic/LSB-Desktop-generic/toclibjpeg.html

一、压缩步骤

1、申请并初始化jpeg压缩对象,同时要指定错误处理器

 struct jpeg_compress_struct cinfo;

 // 声明错误处理器,并赋值给cinfo.err域
  struct jpeg_error_mgr jem;
  cinfo.err = jpeg_std_error(&jem);

  jpeg_create_compress(&cinfo);

2、指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开

 f=fopen("test.jpg","wb");
  if (f==NULL) 
  {
    printf("can't open file test.jpg\n");
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, f);

3、设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量等,如下:

  cinfo.image_width = nWidth;    // 为图的宽和高,单位为像素 
  cinfo.image_height = nHeight;
  cinfo.input_components = 1;   // 在此为1,表示灰度图, 如果是彩色位图,则为3 
  cinfo.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

  jpeg_set_defaults(&cinfo); 
 jpeg_set_quality (&cinfo, 80, true);

需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数计色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩,如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置,但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可。

4、上面的工作准备完成后,就可以压缩了,压缩过程非常简单,首先调用jpeg_start_compress,然后可以对每一行进行压缩,也可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数,如下:

  jpeg_start_compress(&cinfo, TRUE);

  JSAMPROW row_pointer[1];   // 一行位图
  int row_stride;      // 每一行的字节数

  row_stride = cinfo.image_width;  // 如果不是索引图,此处需要乘以3

  // 对每一行进行压缩
  while (cinfo.next_scanline <cinfo.image_height) {
       row_pointer[0] = & pDataConv[cinfo.next_scanline * row_stride];
       jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  jpeg_finish_compress(&cinfo);

5、最后就是释放压缩工作过程中所申请的资源了,主要就是jpeg压缩对象,由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compress这个函数即可,如下:

 jpeg_destroy_compress(&cinfo);


二、解压缩步骤
解压缩步骤与压缩步骤非常相似,只是解压缩对象为jpeg_decompress_struct类型,步骤如下:
1、声明并初始化解压缩对象,同时制定错误信息管理器
 struct jpeg_decompress_struct cinfo;
 struct jpeg_error_mgr jerr;

 cinfo.err = jpeg_std_error(&jerr);
 jpeg_create_decompress(&cinfo);
2、打开jpg图像文件,并指定为解压缩对象的源文件
 FILE *f = fopen(strSourceFileName,"rb");
 if (f==NULL)
 {
  printf("Open file error!/n");
  return;
 }
 jpeg_stdio_src(&cinfo, f);
3、读取图像信息
 jpeg_read_header(&cinfo, TRUE);
4、根据图像信息申请一个图像缓冲区
 data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
5、开始解压缩
 jpeg_start_decompress(&cinfo);

 JSAMPROW row_pointer[1];
 while (cinfo.output_scanline < cinfo.output_height)
 {
  row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
  jpeg_read_scanlines(&cinfo,row_pointer , 1);
 }
 jpeg_finish_decompress(&cinfo);
6、释放资源
 jpeg_destroy_decompress(&cinfo);

 fclose(f);

好了,利用IJG JPEG Library进行图像压缩就介绍到这里,希望对大家有所帮助


以下是部分压缩与解压缩的代码,方便大家参考,需要说明的是我这里MJPEG使用RGB数据压缩,然后MJPEG解压出来也是RGB数据,完整的程序下载在:http://download.csdn.net/detail/luckywang1103/6707987

三、压缩代码

void write_JPEG_file(unsigned char *buf, int size, int quality)   
{   
	struct jpeg_compress_struct cinfo;   
	struct jpeg_error_mgr jerr;   
	FILE *outFile;                   			/* target file */   
	JSAMPROW row_pointer[1];		/* pointer to JSAMPLE row[s] */   
	unsigned char *line_buffer, *yuyv;	/* physical row width in image buffer */   
	int z;

	line_buffer = calloc(WIDTH * 3, 1);
	yuyv = buf;
	printf("compress start...\n");
	cinfo.err = jpeg_std_error(&jerr);   
	jpeg_create_compress(&cinfo);                       //Initialization of JPEG compression objects.   
	if ( (outFile= fopen("testx.jpg", "wb")) == NULL)  //open file   
	{     
		fprintf(stderr, "can't open %s\n", "testx.jpg");   
		exit(1);   
	}   
	jpeg_stdio_dest(&cinfo, outFile);           //Initialize state for output to stdio stream   
	cinfo.image_width = WIDTH;                /* image width and height, in pixels */   
	cinfo.image_height = HEIGHT;   
	cinfo.input_components = 3;                /* # of color components per pixel */   
	cinfo.in_color_space = JCS_RGB;         /* colorspace of input image */   
	jpeg_set_defaults(&cinfo);                   //set compression parameters to default values   
	jpeg_set_quality(&cinfo, 80, TRUE );     //construct JPEG quantization tables for indicated quality (between 0 and 100)   
	jpeg_start_compress(&cinfo, TRUE);     //initialize a compression cycle   

	z = 0;
	while(cinfo.next_scanline < HEIGHT)
	{
		int x;
		unsigned char *ptr = line_buffer;
		for(x = 0; x < WIDTH; 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);//cinfo.next_scanline会自动增加
	}	
	jpeg_finish_compress(&cinfo);   
	jpeg_destroy_compress(&cinfo);  
	fclose(outFile);   
}//end write_JPEG_file  


四、解压缩代码

if ((infile = fopen(s, "rb")) == NULL)
{
	fprintf(stderr, "open %s failed\n", s);
	exit(-1);
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
//导入要解压的Jpeg文件infile
jpeg_stdio_src(&cinfo, infile);	
//读取jpeg文件的文件头
jpeg_read_header(&cinfo, TRUE);		
//开始解压Jpeg文件,解压后将分配给scanline缓冲区,
jpeg_start_decompress(&cinfo);
buffer = (unsigned char *) malloc(cinfo.output_width * cinfo.output_components);
y = 0;
while (cinfo.output_scanline < cinfo.output_height)
{
	jpeg_read_scanlines(&cinfo, &buffer, 1);
	if (fbdev.fb_bpp == 16)
	{
		unsigned short color;
		for (x = 0; x < cinfo.output_width; x++)
		{
			color = RGB888toRGB565(buffer[x * 3],buffer[x * 3 + 1], buffer[x * 3 + 2]);
			fb_pixel(fbdev.fb_mem, fbdev.fb_width, fbdev.fb_height, x, y, color);///
		}
	}
	else if (fbdev.fb_bpp == 24)
	{
		memcpy((unsigned char *)fbdev.fb_mem + y * fbdev.fb_width * 3, buffer,
				cinfo.output_width * cinfo.output_components);
	}
	y++;//下一个scanline
}
//完成Jpeg解码,释放Jpeg文件
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
//释放帧缓冲区
free(buffer);





评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckywang1103

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值