据我了解,JPEG 文件有几种风格。此处解释了更改 JFIF 风格的 DPI 元数据所需的详细信息。基于此,我编写了自己的 Python 脚本,该脚本允许在不重新编码的情况下更改JFIF 风格JPEG 的 DPI 设置:
import sys,os
filename = sys.argv[1]
x_density = int(sys.argv[2])
y_density = int(sys.argv[3])
echo = True
if len(sys.argv) > 4:
if sys.argv[4] == 'quiet':
echo = False
assert x_density > 0 and x_density < 65536
assert y_density > 0 and y_density < 65536
# JPEG markers
APP0 = bytes.fromhex('FFD8FFE0') # JFIF
APP1 = bytes.fromhex('FFD8FFE1') # EXIF
with open(filename, 'rb+') as f: # 'w+b'
chunk = f.read(4)
if chunk == APP0:
f.seek(2,1) # relative seek
chunk = f.read(5)
if chunk == bytes.fromhex('4A46494600'): # JFIF indentfier
f.seek(2,1) # relative seek
print('Setting density of ' + os.path.split(filename)[1] + ' to ' + str(x_density) + 'x' + str(y_density) + ' dpi.') if echo else None
f.write(bytes.fromhex('01'))
f.write(x_density.to_bytes(2,'big'))
f.write(y_density.to_bytes(2,'big'))
else:
print('File hasn''t got the JFIF indentifier, nothing was done.')
elif chunk == APP1:
f.close() # needed otherwise exiftool cannot operate on file
print('This is an EXIF-JPEG, using exiftool to set DPI...')
os.system('exiftool -P -overwrite_original -XResolution={} -YResolution={} "{}"'.format(x_density,y_density,filename))
else:
print('File is not JFIF nor EXIF, cannot set DPI, nothing was done.')
print('Done.') if echo else None
用法:
python this_script.py some-image.jpg Xdpi Ydpi [quiet]
该脚本不会读取完整图像,也不会更改文件长度,它只是直接在 JPEG 文件上修改几个字节。此外,没有制作临时/备份副本,因为我希望脚本可以处理硬链接文件,因此 JFIF JPEG 的整体过程非常快。
该脚本能够识别 EXIF JPEG 并使用 exiftool 更改 DPI。如果您的计算机中没有安装 exiftool,请记住相应地调整脚本。即使您安装了 exiftool,使用此脚本的一个原因是速度;在我的测试中,这个脚本比 exiftool 快得多。
JFIF 和 EXIF 是最常见的 JPEG 文件风格,但我希望有人能够改进此脚本或报告一种为带有 APP14 标记的 Adobe JPEG 设置 DPI(无需重新编码)的方法,这并不罕见。