读取JPEG文件的压缩质量/质量因子参数
JPEG是一种图像压缩算法,而JPEG在做压缩编码的时候往往需要设定一个压缩质量/质量因子的参数(quality)。而在编码完成以后我们有时候希望获取到JPEG压缩文件的这个quality,好在万恶的jpeg编码协议却并没有直接存储这个quality参数,而opencv libjpeg这样的第三方库也没有提供获取JPEG文件质量参数的接口。可是JPEG文件存储了一个量化表的参数(quantize table),这里我们就是运用读取这个JPEG文件的quantize table然后反推这个JPEG文件的quality。
- 关于JPEG具体的压缩算法请查看wiki
- 需要用到第三方库文件:libjpeg(下载链接)
- 安装方法:
tar xvf jpegsrc.v9.tar.gz cd jpeg-9 mkdir build cd build ../configure make -j make install
实现代码
#include <stdio.h> #include <math.h> #include "jpeglib.h" #include <setjmp.h> //标准明度量化表 static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { 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 }; //读取JPG文件的质量参数 int ReadJpegQuality(const char *filename) { FILE * infile = fopen(filename, "rb"); fseek(infile,0,SEEK_END); size_t sz = ftell(infile); fseek(infile,0,SEEK_SET); unsigned char* buffer = new unsigned char[sz]; fread(buffer,1,sz,infile); fclose(infile); //如果不是JPG格式的文件返回-1 if(buffer==NULL || sz <= 2 || 0xFF != (uint8_t)buffer[0] || 0xD8 != (uint8_t)buffer[1]) { return -1; } struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_mem_src(&cinfo,(unsigned char*)buffer,sz); jpeg_read_header(&cinfo, TRUE); int tmp_quality = 0; int linear_quality = 0; const int aver_times = 3; int times = 0; int aver_quality = 0; //量化表反推3次,取平均值 for(int i=0;i<DCTSIZE2;i++) { long temp = cinfo.quant_tbl_ptrs[0]->quantval[i]; if(temp<32767L&&temp>0) { linear_quality = ceil((float)(temp*100L - 50L)/std_luminance_quant_tbl[i]); if(linear_quality==1) tmp_quality = 1; else if(linear_quality==100) tmp_quality = 100; else if(linear_quality>100) { tmp_quality = ceil((float)5000/linear_quality); } else { tmp_quality = 100 - ceil((float)linear_quality/2); } aver_quality += tmp_quality; if(aver_times==++times) { aver_quality /= aver_times; break; } } } jpeg_destroy_decompress(&cinfo); return aver_quality; } int main(int argc,char** argv) { printf("quality: %d\n",ReadJpegQuality("test1.jpg")); return 0; }
- 编译链接的方法也很简单了
g++ main.cpp -I/your_path_to/libjpeg-9b/build/include -L/your_path_to/libjpeg-9b/build/lib/ -ljpeg
Comments
<% if(config.disqus_shortname) { %>