几乎所有图像质量损失都是在图像第一次压缩为JPEG时发生的。不管使用相同设置将JPEG重新压缩多少次,代损失都限于舍入误差。
MCU边界保持不变(8x8块)。
色度二次采样已禁用。
恒定DQT(相同的质量设置)。
但是,对于不满足上述条件的每次迭代,舍入误差可能会很大,因此,请谨慎保留所有原始文件的备份。
转换色彩空间。如果需要,请对颜色信息进行下采样(色度二次采样)(有损)。如果不进行降采样,则信息丢失是舍入误差的结果。
分割。将每个通道划分为8x8块(MCU =最小编码单位)。 (无损)
注意:如果启用了色度二次采样,就原始图像而言,MCU实际上可能是16x8、8x16或16x16。但是,MCU仍然都是8x8块。
每个MCU上的离散余弦变换(DCT)。信息丢失是舍入误差的结果。
量化。 MCU的每个单元中的值除以量化表(DQT)中指定的数字。值四舍五入,其中许多将变为零。 这是算法的主要有损部分。
之字形扫描。按照锯齿形将每个MCU中的值重新排列为数字序列。量化期间发生的零将被分组在一起。 (无损)
DPCM =差分脉冲编码调制。将数字序列转换为更易于压缩的形式。 (无损)
RLE =游程长度编码。连续零被压缩。(无损)
熵/霍夫曼编码。 (无损)
重新压缩JPEG
请注意,对颜色通道进行降采样和量化是仅有的有意损耗步骤。暂时保留舍入错误,所有其他步骤都是无损的。量化一旦发生,反转并重复该步骤即可得到相同的结果。换句话说,重新量化(使用相同的DQT)是无损的。
原则上,可以创建在第一次通过后无损失的重采样算法。但是,通过ImageMagick的实现,颜色可能会在达到稳定状态之前急剧变化,如该图所示。
在最佳条件下,以相同的质量设置重新压缩JPEG将得到完全相同的JPEG。换句话说,重新压缩JPEG 可能无损。实际上,重新压缩JPEG不是无损的,而是受舍入误差的限制。尽管舍入误差通常最终会收敛到零,以便重新创建完全相同的图像,但是色度二次采样可能会导致颜色发生重大变化。
演示(相同的质量设置)
我编写了以下bash
脚本,该脚本使用ImageMagick以给定的质量设置重复地重新压缩JPEG文件:
#!/usr/bin/env bash
n=10001; q1=90
convert original.png -sampling-factor 4:4:4 -quality ${q1} ${n}.jpg
while true ; do
q2=${q1} # for variants, such as adding randomness
convert ${n}.jpg -quality ${q2} $((n+1)).jpg
#\rm $((n-5)).jpg # uncomment to avoid running out of space
n=$((n+1))
echo -n "$q2 "
md5sum ${n}.jpg
done
让它运行数百次迭代后,我运行md5sum
了结果:
d9c0d55ee5c8b5408f7e50f8ebc1010e original.jpg
880db8f146db87d293def674c6845007 10316.jpg
880db8f146db87d293def674c6845007 10317.jpg
880db8f146db87d293def674c6845007 10318.jpg
880db8f146db87d293def674c6845007 10319.jpg
880db8f146db87d293def674c6845007 10320.jpg
我们可以看到,确实,舍入误差已收敛到零,并且一遍又一遍地复制了完全相同的图像。
我已经用不同的图像和质量设置重复了多次。通常,会达到稳定状态,并且一遍又一遍地复制完全相同的图像。
我试图在Ubuntu 18.04上使用Imagemagick复制mattdm的结果。最初是在Rawtherapee中原始转换为TIFF,但似乎不再可用。取而代之的是,我采用了放大版本并将其缩小为原始尺寸(256x256)。然后我在75处重复压缩,直到收敛为止。这是结果(原始,1,n,差):
我的结果是不同的。没有真实的原件,差异的原因无法确定。
我从蒙太奇的左上角重新压缩图像,直到在90处收敛。这是结果(原始,1,n,差):
启用色度二次采样后,颜色会在达到稳定状态时发生变化。
在少数设置之间进行更改
通过修改变量q2
,可以将质量设置限制为一组均匀分布的值。
q2=$(( (RANDOM % 3)*5 + 70 ))
对于少数设置选项,最终可能会达到平衡,这是在md5值开始重复出现时看到的。在达到平衡之前,设置似乎越大,花费的时间越长,并且图像变得越差。
平衡时似乎发生的事情是,量化之前的DCT系数必须被所有(或大部分)量子值整除。例如,如果在DCT系数被3和5交替除的两个DQT之间切换,则DCT系数被15除时将达到平衡。这解释了为什么质量下降远大于原始设置之间的差异。
在大量设置中进行更改
q2
像这样改变时,Eeyore不高兴:
q2=$(( (RANDOM % 9) + 90 ))
要制作视频,请使用ffmpeg
:
rename 's@1@@' 1*.jpg
ffmpeg -r 30 -i %04d.jpg -c:v libx264 -crf 1 -vf fps=25 -pix_fmt yuv420p output.mp4
观看前9999次迭代几乎就像观看水沸腾一样。可能希望将播放速度提高一倍。这是11999年迭代后的Eeyore:
如果MCU边界发生变化怎么办?
如果更改发生的次数有限,则反复进行重新压缩很可能会达到稳定状态。如果在每次迭代中发生更改,则图像可能会以与DQT更改时类似的方式降级。
那编辑呢?
编辑后重新压缩的效果取决于执行的特定编辑。例如,减少JPEG伪像后以相同的质量设置进行保存将重新引入相同的伪像。但是,应用局部变化(例如修复刷)不会影响未被触摸的区域。
图像质量的最大下降发生在第一次以给定的质量设置压缩文件时。随后使用相同的设置进行重新压缩不应引起大于舍入误差的变化。因此,我希望在给定的质量设置下,编辑-重新保存周期看起来像保存了相同质量设置的任何其他图像一样(只要MCU边界保持不变且色度二次采样被禁用)。
那些视频呢?
我可以用重新压缩的JPEG覆盖原稿吗?
保留所有原始文件的备份是谨慎的做法,但是如果您不小心覆盖了一个原始文件,则损坏可能会受到限制。在禁用色度二次采样的情况下在JPEG中工作也很好。
JPEG不能用于每种颜色使用8位以上的图像。