3

我使用(在 Windows 下)以下命令

magick convert -units pixelsperinch file_in -density 600 file_out

设置 JPG 图像的 dpi(没有重新采样,因为 dpi 基本上是,据我所知,只是一个指定像素大小的标签)。它有效,但我不明白为什么它将文件大小增加了几千字节(我最初的 1658 kB 的图像变成了 1717 kB,增加了 59 kB),而我希望增加(如果有的话)只有几个字节。

我是不是搞错了什么?是否可以通过命令行更改 JPG 的密度/dpi(也欢迎使用 ImageMagick 以外的工具)而不增加文件大小?

提前感谢您提供任何线索。

4

4 回答 4

4

您可以更改/设置密度,而无需重新编码文件(从而可能更改其大小或质量),其更小、更轻且更易于安装exiftool,“只是”一个 Perl 脚本:

exiftool -jfif:Xresolution=300 -jfif:Yresolution=300 YourImage.jpg

不同的人称不同的东西为密度/分辨率,所以如果上面的命令没有做你想要/需要/希望/期望的事情,也许试试:

exiftool -XResolution=300 -YResolution=300 YourImage.jpg
于 2018-08-05T16:42:05.050 回答
3

试图重现您的问题:

  • Gimp 的隔行/逐行 JPEG 小于非隔行版本(也是 Gimp 生产的)
  • 输出的magick convertJPEG 不是隔行扫描的,实际上比 Gimp 自己的非隔行扫描的要小一些。该文件的大小相同,无论它是从隔行扫描还是非隔行扫描版本生成的。

因此,我认为您正在转换隔行扫描/逐行扫描 JPEG。请注意,这也表明 IM 正在重新编码文件,并且比较原始文件和 Gimp 中重新编码的文件显示出显着差异。

在 JPEG 格式中,H/V 定义在标头中以 4 个字节编码,补丁应该是任何编程语言中的 SMOP。

于 2018-08-05T12:53:17.060 回答
0

尝试使用在线工具 https://convert.town/image-dpi。在我的 JFIF jpg 上,这只改变了 DPI,并没有重新采样图像。可以在此超级用户问题上找到其他软件建议,但这是唯一对我有用的软件建议,而无需更改图像中的任何其他内容。

但是,我只有 JFIF jpg,而您的其他评论似乎有 Adob​​e jpg,因此您的里程可能会有所不同。

我使用 Windows 十六进制编辑器 HxD 验证了 DPI 更改并且没有重新采样,只是查看了 xenoid 链接的 Wikipedia 文章中详述的 4 个字节。一旦您知道哪些字节正在发生变化,您就可以跳过网站并直接使用十六进制编辑器来设置 X 和 Y DPI。

于 2019-12-11T06:32:30.360 回答
0

据我了解,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 标记的 Adob​​e JPEG 设置 DPI(无需重新编码)的方法,这并不罕见。

于 2021-06-02T21:01:40.450 回答