我对 JPEG 进行了一些实验,文档说“100 完全禁用 JPEG 量化阶段。”
但是,我在保存过程中仍然进行了一些像素修改。这是我的代码:
import Image
red = [20,30,40,50,60,70];
img = Image.new("RGB", [1, len(red)], (255,255,255))
pix = img.load()
for x in range(0,len(red)):
pix[0,x] = (red[x],255,255)
img.save('test.jpg',quality=100)
img = Image.open('test.jpg')
pix = img.load()
for x in range(0,len(red)):
print pix[0,x][0],
我得到了意想不到的输出:
22 25 42 45 62 65
我应该怎么做才能保留像素值?请注意,我还尝试使用 PHP 使用 imagejpeg ,当质量 = 100 时它给了我正确的值。
我可以使用
png
来保存,但我想知道这背后的原因以及是否有任何选择可以避免
JPEG 由许多不同的步骤组成,其中许多步骤会带来一些损失。通过使用仅包含红色的示例图像,您可能会遇到最严重的问题 - 下采样或色度子采样。一半的颜色信息被丢弃,因为眼睛对亮度变化比颜色变化更敏感。
subsampling=0
来配置关闭子采样,包括 PIL 和 Pillow。无论如何,它不会为您提供完全无损的文件,因为还有其他步骤会导致丢失。
JPEG 始终存在有损风险,请参阅质量设置为 100 时 Jpeg 是否无损?。
您最好的选择是使用另一种格式,特别是如果您的实验是为了科学:)即使您被迫从 JPEG 开始(这似乎不太可能),您也应该立即转换为无损格式以进行任何类型的分析和修改。
如果你真的想尝试使用Python进行无损JPEG工作,你可以尝试
jpegtran
,“独立Jpeg组的无损jpeg图像转换软件”,但正如@Mark指出的那样,这不会让你走得太远。
顺便说一句,量化同样用于有损或无损压缩,所以我的猜测是
...100 完全禁用 JPEG 量化阶段。[1]
仅仅意味着它根本没有被压缩。
相信我已经弄清楚如何保持当前的颜色子采样和其他质量细节:
from PIL import Image, JpegImagePlugin as JIP
img = Image.open(filename)
img.save(
filename + '2.jpg', # copy
format='JPEG',
exif=img.info['exif'], # keep EXIF info
optimize=True,
subsampling=JIP.get_sampling(img), # keep color res
qtables=img.quantization, # keep quality
# quality=-1, # keep
)
Per https://www.exiv2.org/tags.html 我发现 YCbCrSubSampling 标签未保存在 JPEG 文件的 EXIF 中:
在 JPEG 压缩数据中,使用 JPEG 标记 而不是这个标签。
这一定就是为什么在一个看似偏僻的地方还有另一个功能可以抓住它。