应用libjpeg提取jpeg质量因子
来源:互联网 发布:域名la 编辑:程序博客网 时间:2024/06/02 02:50
data = new BYTE [cinfo.image_width*cinfo.image_height*cinfo.num_components];
基本思路:利用开源库实现对jpeg的解压缩以直接提取量化表,根据标准量化表和所提取量化表编写算法实现质量因子的求算。
步骤一:使用libjpeg库实现对jpeg的解压缩并提取量化表
参照:http://www.vckbase.com/index.php/wv/1488.html
步骤如下:
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:获取解压缩后的量化表
GetQualityTabl(&cinfo,QualTabl,1);//获取解压缩后的量化表
7:释放资源
jpeg_destroy_decompress(&cinfo);fclose(f);
步骤二:根据标准量化表和所提取的量化表求出质量因子
注解:由于质量因子为1到100的整数,所以可以采用遍历的方式查出质量因子
1:在libjpeg库中jcparam.c中复制标准量化表
亮度量化表:
static const unsigned int std_luminance_quant_tbl[64] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99};
色度量化表:
static const unsigned int std_chrominance_quant_tbl[64] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99};
2:创建从质量因子从1到100所对应的两种量化表,并将其存入一维数组中(按从左到右,从上到下,先亮度后色度的顺序进行存储),其中对质量因子的量化表和质量因子的关系请预读jcparam.c中的jpeg_set_quality()和jpeg_add_quant_table()函数。
for(int quality=1;quality<=100;quality++){ if(quality<=0) quality = 1; if(quality > 100) quality = 100; if(quality<50) scale_factor=5000 / quality; else scale_factor= 200 - quality*2; for(int j=0;j<2;j++) { for(int i=0;i<64;i++) { if(j==0) { temp=((long) std_luminance_quant_tbl[i]*scale_factor+ 50L)/100L; if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if(temp>255) temp = 255L; AllQualTabls[quality-1][i]=(UINT16) temp; } if(j==1) { temp=((long) std_chrominance_quant_tbl[i]*scale_factor+ 50L)/100L; if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if(temp>255) temp = 255L; AllQualTabls[quality-1][64+i]=(UINT16) temp; } } }}
3:遍历上述所得二维数组与所得量化表进行匹配,得到质量因子
for(int tmp=99;tmp>=0;tmp--)//逆序寻找,因为一般质量因子都大于50{ for(int j=0;j<128;j++) { if( (QualTabl[j]==AllQualTabls[tmp][j])&&(j==127)) { //Q_Factor=tmp; count++;//满足条件的质量因子的数量加1 if(tmp>final)//选择最大满足条件的最大的质量因子 final=tmp; } else if(QualTabl[j]!=AllQualTabls[tmp][j]) break;//发现不相等的项将跳出该循环进入下一个循环(质量因子不同)。 }}
源程序:
1:解压缩JPEG图片
unsigned char * DeJpeg(char * JpegName,int QualTabl[128],int AllQualTabls[100][128],int *Factor)//解压jpeg格式图片并显示相应的量化表,并已指针参数形式传递Factor的值,并返回RGB(unsigned char)数据的指针{ FILE *openJpeg; unsigned char *data; //存放解压后的数据 unsigned char *jpgbuf; //存放解压后一行图像数据 int row_stride; //定义每行的字节数 struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo);//声明并初始化解压缩对象 openJpeg=fopen(JpegName,"rb");//二进制模式读取jpeg文件 if(openJpeg==NULL) //二进制模式读取 { printf("error: cannot open the file\n"); return NULL; }//打开jpeg图片 jpeg_stdio_src(&cinfo, openJpeg);//指定解压对象的源文件 jpeg_read_header(&cinfo, TRUE);//读取文件信息,将图像的缺省的信息填充到cinfo结构中比便程序使用 jpeg_start_decompress(&cinfo);//开始接压缩 data=(unsigned char *)malloc(cinfo.output_width* cinfo.output_components*cinfo.output_width);//动态分配数据存储内存 memset(data,0,cinfo.output_width*cinfo.output_width*cinfo.output_components);//设置图像数据初值为0 jpgbuf = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);//动态分配缓存内存 memset(jpgbuf,0,cinfo.output_width*cinfo.output_components);//为缓存内存设置初值 row_stride = cinfo.output_width * cinfo.output_components; //计算每行所需的空间,字节为单位 while (cinfo.output_scanline < cinfo.output_height) { int line=cinfo.output_scanline;//当前行数 (void) jpeg_read_scanlines(&cinfo, &jpgbuf, 1);//执行该操作读取第line行数据,cinfo.output_scanline将加一,指向下一个要扫描的行 for(int i=0;i< cinfo.output_width;i++)//循环将存储在jpgbuf缓存区的数据放入data中 { data[line*row_stride+i*cinfo.output_components+0]=jpgbuf[i*3]; data[line*row_stride+i*cinfo.output_components+1]=jpgbuf[i*3+1]; data[line*row_stride+i*cinfo.output_components+2]=jpgbuf[i*3+2];#ifdef DEBUG__ //printf("(%d,%d,%d),(%d,%d)",jpgbuf[i*3],jpgbuf[i*3+1],jpgbuf[i*3+2],line,i);//打印图像数据#endif } } GetQualityTabl(&cinfo,QualTabl,1);//获取解压缩后的量化表 *Factor=GetFactor(QualTabl,AllQualTabls,Q_FACTOR);//获取质量因子 jpeg_finish_decompress(&cinfo);//完成解压过程 jpeg_destroy_decompress(&cinfo);//释放cinfo free(jpgbuf);//释放缓存 fclose(openJpeg); return data; }
2:遍历寻找质量因子
int GetFactor(int QualTabl[128],int AllQualTabls[100][128],int testFactor)//通过将得到的向量表(以一维维数组存储)和实验中所有情况的数组进行匹配(????是否存在与多个数组相匹配情况){ /* These are the sample quantization tables given in JPEG spec section K.1. * The spec says that the values given produce "good" quality, and * when divided by 2, "very good" quality. */static const unsigned int std_luminance_quant_tbl[64] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99};static const unsigned int std_chrominance_quant_tbl[64] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99};long temp;//存储临时的质量因子int scale_factor=0;//默认值为0,品质因子最高//int Q_Factor=-1;//寻找到的质量因子,默认值为-1,表示没找到int count=0;//记录量化表相同的质量因子的个数int final=-2;//如果有多个质量因子满足条件,将选择最大的那个。-1表示没找到 for(int quality=1;quality<=100;quality++){ if(quality<=0) quality = 1; if(quality > 100) quality = 100; if(quality<50) scale_factor=5000 / quality; else scale_factor= 200 - quality*2; for(int j=0;j<2;j++) { for(int i=0;i<64;i++) { if(j==0) { temp=((long) std_luminance_quant_tbl[i]*scale_factor+ 50L)/100L; if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if(temp>255) temp = 255L; AllQualTabls[quality-1][i]=(UINT16) temp; } if(j==1) { temp=((long) std_chrominance_quant_tbl[i]*scale_factor+ 50L)/100L; if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if(temp>255) temp = 255L; AllQualTabls[quality-1][64+i]=(UINT16) temp; } } }}//int testNum=testFactor-1; for(int tmp=99;tmp>=0;tmp--)//逆序寻找,因为一般质量因子都大于50{ for(int j=0;j<128;j++) { if( (QualTabl[j]==AllQualTabls[tmp][j])&&(j==127)) { //Q_Factor=tmp; count++;//满足条件的质量因子的数量加1 if(tmp>final)//选择最大满足条件的最大的质量因子 final=tmp; } else if(QualTabl[j]!=AllQualTabls[tmp][j]) break;//发现不相等的项将跳出该循环进入下一个循环(质量因子不同)。 }}#ifdef DEBUG__printf("比较得出质量因子为:%d\n",final+1);printf("与之量化表相等所对应的质量因子的个数:%d\n",count);printf("任意键继续\n");getchar();#endif #ifdef DEBUG__if(final!=-2){ printf("quantization table of luminance:the quality is %d \n",final+1);//输出CI通道的量化表 if(testFactor<=0) testFactor=1; if(testFactor>100) testFactor=100;//保障质量因子在1-100之间 for (int i = 0; i <64; ++i) { printf("% 4d ", AllQualTabls[final][i]); if ((i + 1) % 8 == 0) printf("\n"); } printf("quantization table of chrominance ,the quality is %d: \n",final+1);//输出CI通道的量化表 for (int i = 0; i <64; ++i) { printf("% 4d ", AllQualTabls[final][64+i]); if ((i + 1) % 8 == 0) printf("\n"); } printf("任意键继续\n"); getchar();}else { printf("没有找到匹配的向量表\n\n 任意键继续\n"); getchar();}#endif return final+1;}
相关阅读:
C 实现BMP 转换为JPG 附源代码
[置顶] C实现jpg转换为BMP 附源文件
- 应用libjpeg提取jpeg质量因子
- 读取JPEG文件的压缩质量/质量因子参数
- JPEG开源代码:libjpeg
- 使用libjpeg解码jpeg图片
- 使用libjpeg解码jpeg图片
- libjpeg-jpeg压缩与解压缩
- 转载:libjpeg解码内存jpeg数据
- encode RGB24 to jpeg, using libjpeg
- decoder jpeg to rgb 24, using libjpeg
- encode YUV420 to jpeg, using libjpeg
- LibJpeg解码内存中的Jpeg数据
- FW:使用libjpeg解码jpeg图片
- FW:使用libjpeg解码jpeg图片
- FW:使用libjpeg解码jpeg图片
- YUV422 to JPEG ---libjpeg 参考网页
- 使用libjpeg进行JPEG图像解码
- CImg、libjpeg--介绍、配置(操作JPEG)
- 使用libjpeg进行JPEG图像解码
- VIM用户手册 For Vim version 7.3. *usr_07.txt*
- log4j tomcat下可以websphere下不可以
- Source Insight完美转换UTF-8 到 GB2312
- 存储过程和函数
- struts2用ajax返回一个jsonArray
- 应用libjpeg提取jpeg质量因子
- VIM用户手册 For Vim version 7.3. *usr_08.txt*
- C#数据库交互
- VIM用户手册 For Vim version 7.3. *usr_09.txt*
- 在虚拟机上安装XP
- Lucas-Kandade 算法 opencv中的cvCalcOpticalFlowLK()与cvCalcOpticalFlowPyrLK()原理及其部分代码理解。
- Android 内存溢出解决方案(OOM) 整理总结
- 基于struts的图书系统
- windows多线程详解