标签:return 方法 line inpu org == who 生成器 mod
作者:马健
邮箱:stronghorse_mj@hotmail.com
主页:http://www.comicer.com/stronghorse/
发布:2017.07.23
众所周知,JPG是一种“有损”压缩格式,与PNG等无损压缩格式相比,最大的问题是:如果反复压缩,会造成图像质量逐渐退化。所以在对JPG文件进行处理,并且输出仍然选择JPG格式的情况下,很多人都会问同样的一个问题:如何才能在尽情享受有损压缩带来的较小文件长度的便利前提下,尽量避免图像质量退化?
为了解决这个问题,从v4.13开始,除传统的JPG质量系数外,在CEP中还允许对JPEG质量进行更精细的控制,界面如下图所示:
图1
总体来说,允许对三个方面的参数进行控制:
如果三个“优先”都被勾选,那么当您用CEP打开一个JPG文件,然后什么也不做就另存为另外一个JPG文件,则两个文件的长度和质量应该差别都不大——注意我说的是“不大”,不是“没有”。长度差异一个DIR命令就知道,图像差异可以用眼睛看,也可以用CEP v4.13开始提供的“图像比较”功能进行量化比较,详见教程二十。
如果想深入了解这些参数究竟如何影响JPG文件长度与质量,可以阅读著名小众软件JPEGsnoop的作者Calvin
Hass写的系列文章,以下是其中关键的几篇:
JPEG
Compression, Quality and File Size
JPEG
Color Space Conversion Error
JPEG
Chroma Subsampling
JPEG
Compression Quality from Quantization Tables
JPEG Huffman Coding Tutorial
What is
an Optimized JPEG?
为便于后续理解,我先从上面第一篇文章中摘取对JPG压缩过程的说明,做无责任翻译(“无责任”的意思就是胡言乱语,各路专家不必较真,也谢绝较真):
如果上面的翻译还是看得眼晕,可以再去看看hesays写的中文文章《JPEG图像编码解码》,或《常用多媒体文件格式与压缩标准解析》(姜楠,王健编著,电子工业出版社,2005.05,SSID=11417553)的第5章。
对于JPEG有损压缩的误差来源,Calvin Hass认为最大的来源是量化过程。用户可以通过选择压缩系数或质量系数对量化表进行控制,从而影响最终JPEG文件的文件长度和质量。其他来源,如色彩空间转换的舍入误差,其重要性都不如量化误差。因此对JPEG进行无损转存的唯一方法是不要经过解压过程,直接对MCU进行操作以避开量化过程。在IJG提供的命令行程序jpegtran中,就是通过直接操作MCU实现JPEG文件的无损90度旋转、 镜像翻转、裁剪(左上角必须是MCU的边界)等,我怀疑收费软件cPicture中的JPEG无损旋转、裁剪就是学它的,只不过加了图形界面。
我个人的看法:
JPEGsnoop的作者Calvin Hass更进一步认为:
针对上面的第1点,除CEP外,在我的其它一些软件中也采用了类似的技术进行JPG文件转存,包括:
在上面的叙述中,JPG质量系数即量化表对JPG质量的影响可能大家还比较好理解,但颜色缩水对质量的影响可能就有人要较真了。这里提供一个例子,先是原图(出自MyReader使用说明书的插图):
图2
在CEP中打开后JPG质量系数点到95,颜色采样方式选“自动”,其实就是不缩水,另存为JPG后的结果:
图3
在JPG质量系数不变的情况下,只是把颜色采样方式从“自动”改成“手动”,然后勾选“水平方向缩一半”和“垂直方向缩一半”,则效果变成:
图4
把图片从网页里另存出来,用看图软件来回切换着看,可以看出颜色缩水后文件长度确实比不缩水的要小,但即使质量系数95%,红色仍然显得黯淡了许多(图4)。而颜色不缩水的JPG图像与原始PNG图像相比则肉眼基本看不出差距 (图3)。但不论是否缩水,JPG文件长度都比原PNG文件(图2)更大,这是因为我故意选择了一张不适合用JPG文件格式存储的人工(artificial)图像,一方面其中的渐变部分更容易看出差距,另一方面是想说明JPG格式并不是包打天下的,总有其适用范围(如颜色数较多的自然图像,包括风光、人物照片等),也有其不适用的范围(如颜色数较少的人工图像),算是给狂热的 坚持JPG格式可以包打天下的JPG偏执狂们浇点冷水。
杂七杂八写到这里,可能还是有人拎不清在CEP里究竟应该怎么设置JPG质量,以下是一些建议:
附录 IJG中从质量系数到量化表的计算过程的源代码
在使用IJG把图像压缩成JPG时,通常调用下面的代码设置质量系数(出自IJG的示例源代码cjpeg.c)
/* Set quantization tables for selected quality. */ /* Some or all may be overridden if -qtables is present. */ jpeg_set_quality(cinfo, quality, force_baseline);
而jpeg_set_quality函数及其所调用函数的实现如下:
GLOBAL(void) jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) /* Set or change the ‘quality‘ (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables * would use the preceding three routines directly. */ { /* Convert user 0-100 rating to percentage scaling */ quality = jpeg_quality_scaling(quality); /* Set up standard quality tables */ jpeg_set_linear_quality(cinfo, quality, force_baseline); }
GLOBAL(int) jpeg_quality_scaling (int quality) /* Convert a user-specified quality rating to a percentage scaling factor * for an underlying quantization table, using our recommended scaling curve. * The input ‘quality‘ factor should be 0 (terrible) to 100 (very good). */ { /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; /* The basic table is used as-is (scaling 100) for a quality of 50. * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table * to make all the table entries 1 (hence, minimum quantization loss). * Qualities 1..50 are converted to scaling percentage 5000/Q. */ if (quality < 50) quality = 5000 / quality; else quality = 200 - quality*2; return quality; }
GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) /* Set or change the ‘quality‘ (quantization) setting, using default tables * and a straight percentage-scaling quality scale. In most cases it‘s better * to use jpeg_set_quality (below); this entry point is provided for * applications that insist on a linear percentage scaling. */ { /* 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[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 }; static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { 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 }; /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, scale_factor, force_baseline); }
GLOBAL(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries * are limited to 1..255 for JPEG baseline compatibility. */ { JQUANT_TBL ** qtblptr; int i; long temp; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); for (i = 0; i < DCTSIZE2; i++) { temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; /* limit the values to the valid range */ if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if (force_baseline && temp > 255L) temp = 255L; /* limit to baseline range if requested */ (*qtblptr)->quantval[i] = (UINT16) temp; } /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*qtblptr)->sent_table = FALSE; }
从jpeg_quality_scaling函数可以看出,用户指定的质量(quality)系数[1, 100]被分段线性映射成了[0, 1000),然后在jpeg_set_linear_quality函数中作为乘数与预设(推荐)的量化表相乘。
ComicEnhancerPro 系列教程十八:JPG文件长度与质量
标签:return 方法 line inpu org == who 生成器 mod
原文地址:http://www.cnblogs.com/stronghorse/p/7225069.html