我想用 ImageMagick 更改 DPI,但不更改图像数据的实际字节大小

我想用 ImageMagick 更改 DPI,但不更改图像数据的实际字节大小

在 GIMP 中,有一种非常简单的方法可以实现我想要的功能。我只安装了德语对话框,但我会尝试翻译它。我说的是转到Picture -> PrintingSize,然后调整值X-Resolution和,Y-Resolution也就是我所知道的所谓的 DPI 值。您还可以选择默认格式Pixel/Inch。(德语中对话框是Bild -> Druckgröße和那里X-AuflösungY-Auflösung

好的,那里的值通常是72默认值。当我将它们更改为例如时,300图像在计算机上保持不变,但如果我打印它,如果你看它,它会变小,但所有细节仍然存在,只是更小 -> 它在打印纸上具有更高的分辨率(但尺寸更小……这对我来说没问题)。

当我使用 LaTeX 时,或者确切地说,使用pdflatex最近的 Ubuntu 机器上的命令时,我经常这样做。当我手动使用 GIMP 执行上述过程时,一切都运行正常。图像在生成的 PDF 中会显得较小,但打印质量较高。

我想要做的是自动完成进入 GIMP 并调整 DPI 值的过程。由于 ImageMagick 以出色而闻名,而且我将其用于许多其他任务,所以我尝试使用此工具实现我的目标。但它并没有达到我想要的效果。

尝试了很多方法之后,我认为这实际上是我应该使用的一个命令:

convert input.png -density 300 output.png

这应该将 DPI 设置为 300,因为我可以在网络上的任何地方阅读。这似乎有效。当我检查文件时,它保持不变(编辑:这是我所期望的,如上所述)。

file input.png output.png
     input.png: PNG image data, 611 x 453, 8-bit grayscale, non-interlaced
    output.png: PNG image data, 611 x 453, 8-bit grayscale, non-interlaced

当我使用此命令时,它似乎做了我想要做的事情:

identify -verbose output.png | grep 300
    Resolution: 300x300
    PNG:pHYs                 : x_res=300, y_res=300, units=0

(有趣的是,相同的输出让input.png我感到困惑......所以这可能是错误的参数?)

现在当我用图像渲染 TeX 时,pdflatex图像仍然很大而且模糊。此外,当我再次使用 GIMP 打开图像时,DPI 值设置为72而不是300。所以实际上根本没有效果。

现在问题出在哪里。我是不是搞错了?我不可能错得这么离谱,因为 GIMP 可以正常工作。

感谢您在这方面提供的帮助。我也愿意接受其他可以在 Linux 系统上轻松实现的自动化解决方案。

答案1

指定单位 - 我似乎记得当我省略这个选项时遇到了一个问题(尽管 DPI 应该是默认值),例如:

convert -units PixelsPerInch input.png -density 300 output.png

您知道 GIMP 使用哪些嵌入数据字段来读取分辨率吗 - 它是否有自己的数据字段来覆盖 ImageMagick 使用的标准数据字段?例如,Photoshop 使用Photoshop:XResolutionPhotoshop:YResolution因此您必须设置这些字段,以便 Photoshop 识别密度设置(ImageMagick 无法做到这一点 - 我们使用 ExifTool)。

答案2

我不知道该如何说服转变仅添加元数据而不重新编码我的[单色]位图;它将文件扩大了>50%。

我发现pngcrush(不是 ImageMagick 工具)也可以添加密度元数据。此命令行将其标记为 600dpi 并允许其他优化,从而将文件大小减少了约 10%:

pngcrush -res 600 in.png out.png

答案3

请注意,您可以使用 Exiftool 读取分辨率。例如,Exiftool '-*resolution*' c.jpg可能会显示

分辨率单位:英寸 X 分辨率:300 Y 分辨率:300

Exiftool 也能够设置参数,但正如手册页中所述Image::ExifTool::TagNames,Exiftool 无法写入额外标签 XResolution 和 YResolution。

我不知道 ImageMagick 是否有改变分辨率的选项,但如果没有,我会感到惊讶。此外,编写 GIMP 脚本来自动执行此类任务非常简单,也可以使用小程序更改分辨率。例如,下面是一个 C 程序(可通过 编译gcc setRes.c -O3 -Wall -o setRes),它读取 jpeg 文件的前几个字节,将分辨率更改为 300,然后重写它们。所示的程序使用小端机器(如 x86)的常量。如果在大端机器上运行,它应该以类似 的消息终止Error: xyz may be not a .jpg file,即使 xyzjpeg 文件。请注意,我还没有通过 测试生成的图片pdflatex;您可能会发现在特克斯东南

/* jiw -- 24 Sep 2012 -- Re: set resolution in a jpg -- Offered without
warranty under GPL v3 terms as at http://www.gnu.org/licenses/gpl.html
*/
#include <stdlib.h>
#include <stdio.h>
void errorExit(char *msg, char *par, int fe) {
  fprintf (stderr, "\n%3d Error: %s %s\n", fe, msg, par);
  exit (1);
}
// Note, hex constants are byte-reversed on little vs big endian machines
enum { JF=0x464a, IF=0x4649, L300=0x2c01, B300=0x012c, NEWRES=L300};
int main(int argc, char *argv[]) {
  FILE *fi;
  short int buf[9];
  int r, L=sizeof buf;
  if (argc<2) errorExit(argv[0], "requires a .jpg file name", 0);
  fi = fopen(argv[1], "r+b");
  if(!fi) errorExit("open failed for", argv[1], ferror(fi));
  r = fread(buf, 1, L, fi);
  if (r != L) errorExit("read failed for", argv[1], ferror(fi));
  if (buf[3] != JF || buf[4] != IF) // Check JFIF signature
    errorExit(argv[1], "may be not a .jpg file", 0);
  buf[7] = buf[8] = NEWRES;
  fseek(fi, 0, SEEK_SET);
  r = fwrite(buf, 1, L, fi);
  if (r != L) errorExit("write failed for", argv[1], ferror(fi));
  return 0;
}

答案4

“我想使用 Imagemagick 改变 DPI,而不改变图像数据的实际字节大小。”

这根本就不可能啊!

因为:

     more "Dots per Inch" 
<==> more pixels per area 
<==> more total pixels per image 
<==> more total bytes per image

而且你似乎不明白实际上 DPI 是什么:

  1. 它是一个完全抽象的值,只有在了解打印输出或屏幕或显示器上的渲染的绝对大小的情况下才具有实际价值:
    • 您可以在 1 英寸宽的正方形上“打印”相同的 72x72 像素图像:打印输出的分辨率为72dpi
    • 您也可以将其“打印”在 1/4 英寸宽的正方形上:那么打印输出的分辨率将为288dpi
    • 注意:如果您将其“打印”在288dpi1 英寸见方的面积上,它就不再是相同的图像了:它将通过打印机驱动程序或其他过滤机制进行一些外推,并且将变成 288x288 像素的图像,而不是 72x72 像素的图像……
  2. 两个打印输出都具有相同的图像信息 - 288dpi 的图像不会突然包含更多信息。

如果你想将原始的 72x72 像素图像打印为 1 英寸宽的正方形,但尺寸为288dpi,那么你必须重新缩放图像(在本例中将其放大)。对于原始图像中的每 1 个像素,您将需要新的放大图像的 4 个像素。现在有不同的算法可用于计算这 4 个像素(其中 3 个是新像素)应该具有的颜色值:

  • 你可以给它们与原始像素相同(这是一个非常“原始”的算法,
  • 或者您可以对原始像素的颜色值与相邻像素的颜色值进行平均。

无论如何,您都在创建一个更大的图像,该图像由 288 行像素组成,每行 288 像素高(288x288 像素)。

当您通过“图片 -> 打印尺寸”时,Gimp 会为您做什么:它简化了重新计算绝对像素大小所需更改的过程,使其更加用户友好。为此...

  • ...它首先询问您 DPI,因为给定的打印机不能任意更改其打印分辨率(有些打印机不仅提供一种,甚至可能提供 2 种或 3 种不同的分辨率)。因此,它会询问您要以哪种分辨率进行打印。这是第一个信息。
  • ...然后它还会询问第二条信息:打印输出应以哪种尺寸( 或 )出现在纸张cmmminch

根据这两条信息,Gimp 计算出它必须使用的总像素数(从原始像素数推断)以按照请求的分辨率填充请求的空间。

然而,通过增加光栅图像的像素来放大它并不会为其添加真正的信息,它只会为其增加虚构的“质量”。它可能如果您的放大算法是“好的”,则对人眼来说会更美观。如果您只是将现有像素增加一倍、三倍或四倍,就像一些简单的算法那样,它看起来会很丑陋。

对于光栅图像,
DPI 设置仅在以下情况下相关印刷或者显示它。因为打印机或显示器有给定的固定分辨率。因此,只有...

  • ...打印机驱动程序或
  • ...支持打印的图像处理应用程序

需要知道。

ImageMagick 的文档完全同意我的观点:

-density width
-density widthxheight
设置图像的水平和垂直分辨率 渲染到设备。

对于矢量图像或文件格式
(如 PDF 或 PostScript)然而,DPI 设置在以下情况下极其重要:光栅化它们。更高的 DPI 会将更多的图片信息转换为光栅格式,从而保留更多真实原始质量的细节。当将给定大小的矢量图像转换为mm或光栅cminch,更高的 DPI 将直接转化为图像中更高的总像素数。

此外,ImageMagick 不支持“打印”功能。相反,ImageMagick 仅...

  • ...将文件从给定的栅格格式转换为其他栅格格式;
  • ...或者它缩小或放大光栅图像;
  • ...或者它根据特定的算法改变颜色值;
  • ...或者它裁剪图像、叠加图像、反转图像、镜像图像;
  • ...还有其他....

...但是要打印处理过的图像,您需要使用不同的程序。

某些图像格式(TIFF、PNG 等)确实支持在其元数据中内部存储 DPI 设置。

但这只不过是一个不会改变底层光栅图像的“提示”属性。这就是你发现这一点的原因:

“当我检查文件时,它仍然保持不变。”

此“提示”可能由打印机驱动程序或页面创建程序(如 LaTeX)自动评估。在没有此类 DPI“提示”的情况下(或者如果它们以某种方式没有按照 LaTeX 期望的方式呈现),LaTeX 仍然应该能够被命令以期望的方式在页面上呈现任何给定的图像 - 它只需要在图像周围添加一些更明确的 LaTeX 代码!

一些其他图像格式(JPEG(?)、BMP……)甚至不支持在其内部元数据中存储 DPI 提示。

因此,Gimp 仅支持您看到的“图片 -> 打印尺寸”操作,因为它想要打印图像。使用 ImageMagick 您无法打印。

打印时继续使用 Gimp 执行您想要执行的操作。使用 ImageMagick 则毫无意义。

也可以看看此附加 IM 文档片段,用不同的语言解释同一个话题。


剩下的就是这个:

  • 如果您使用 Gimp“处理”您的图像,然后将结果嵌入 LaTeX,页面看起来就会像您期望的那样。
  • 如果你使用 ImageMagick 处理图像,然后将结果嵌入到 LaTeX 中,页面看起来不是正如您所期望的。

请提供以下信息来解决上述问题:

  • 您安装的 ImageMagick 的确切版本(convert -version和的完整输出convert -list configure);
  • 原始样本图像(链接);
  • (指向)由 Gimp 处理的同一图像的链接;
  • (指向)由 ImageMagick 处理的同一幅图像的链接。

这样我们就可以协助解决问题。

但请注意:这与您当前的主题/标题所问的问题不同:“我想使用 Imagemagick 更改 DPI,但不更改图像数据的实际字节大小”


更新

因为它是仍然有些读者不清楚我上面提到的内容,这里是另一次尝试......

凡注明为'解决'或者'密度'在图像文件中,是元数据属性。它对文件描述的实际像素数量没有影响,在这方面完全无关紧要。它只是一个暗示打印或渲染设备或应用程序可能或者可能不会打印、渲染或显示图像时请遵循此规定。

为此,它只是存储在图像文件中的几个数字。这些数字告诉输出设备(例如打印机和显示器)图像应以每英寸多少点(或像素)显示。对于 PostScript、PDF、MWF 和 SVG 等矢量格式,它告诉像素比例绘制图像使用的任何真实世界坐标。

举个例子,ImageMagick 在图像元数据中记录的分辨率值为不是Adobe Photoshop 是应用程序所支持的。Photoshop 将其有关所需打印或显示分辨率的提示存储在名为8bim。ImageMagick 不会触碰此配置文件,即使被要求将分辨率更改写入图像文件的元数据。另一方面,Photoshop 会在遇到自己的分辨率提示时立即忽略 ImageMagick 存储在为此目的定义的标准元数据字段中的所有分辨率提示8bim轮廓。

OP应该选择以下标题:

  • “我想使用 ImageMagick 更改 DPI(元数据分辨率提示),但不更改图像中的实际像素数”

为了避免一切误解……

相关内容