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


45

在GIMP中,有一种非常简单的方法可以执行我想要的操作。我只安装了德语对话框,但我将尝试对其进行翻译。我说的是去Picture -> PrintingSize然后调整值X-ResolutionY-Resolution这些值对我来说就是所谓的DPI值。您还可以选择默认为的格式Pixel/Inch。(在德语中,对话框位于Bild -> Druckgröße那里X-AuflösungY-Auflösung

好的,72默认情况下通常是这些值。当我将其更改为例如时,300具有使图像在计算机上保持不变的效果,但是如果我打印它,则如果您查看它,它将变小,但是所有细节仍然存在,只是更小->它具有在打印纸上具有更高的分辨率(但尺寸较小...对我来说很好)。

在使用LaTeX时,或者pdflatex在最近的Ubuntu-Machine上执行该命令时,我经常这样做。当我手动执行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使我感到困惑...所以这可能是错误的参数?

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

现在这是什么问题。我出了点问题吗?我不会错,因为GIMP可以正常工作。

感谢您的帮助。我也欢迎在Linux系统上轻松完成的其他自动化解决方案。


user1694803:您应该记住要返回Martin Wilson的答案并对其“进行投票”(单击^他的答案左侧的小图标),而不仅仅是在拥有足够个人声誉后立即“接受”(我认为您需要+15)...
Kurt Pfeifle

Answers:


76

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

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

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


2
我需要穿上-density 300衣服input.png。我正在转换PDF。不管怎么说,还是要谢谢你。
akostadinov

对于PNG到TIFF的转换,我需要使用-set units PixelsPerInch -density 300-units无论选项的顺序如何,简单的方法都不起作用。
Andrey

5

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

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

Exiftool也可以设置参数,但是如手册页Image::ExifTool::TagNames所述,Exiftool不能写入Extra Tags XResolution和YResolution。

我不知道ImageMagick是否具有改变分辨率的选项,但是如果没有,将会感到惊讶。同样,编写GIMP脚本以自动化这样的任务也很简单,而且还可以使用小程序更改分辨率。例如,下面是一个C程序(可通过编译gcc setRes.c -O3 -Wall -o setRes),该程序读取jpeg文件的前几个字节,将分辨率更改为300,然后将其重写。所示程序在x86之类的低端计算机上使用常量。如果在big-endian机器上运行Error: xyz may be not a .jpg file,则即使xyz jpeg文件,也应以诸如的消息终止。注意,我还没有通过来测试生成的图片pdflatex。您可能会发现值得在tex SE中发布问题。

/* 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;
}

1
这对我没有太大帮助,因为我正在处理PNG,并且对JPG甚至C都不了解。这是为了使我“深入”知识很有用。也许其他人可以使用它。
鲍里斯·达彭(BorisDäppen)2012年

是的,我应该更加注意这个问题!重新阅读它,没有提到JPG,显然是PNG。
詹姆斯·沃尔德比-jwpat7 2012年

是的,我是其他人,可以使用它:我已经在十六进制编辑器中打开了.jpg文件,并编辑了垂直和水平密度的第9和第11个字节。可以这么说,我手动“执行”了您的代码。
u_Ltd。

2

我不知道如何说服转换只添加元数据而不重新编码我的[单色]位图。它正在扩展文件> 50%。

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

pngcrush -res 600 in.png out.png

-1

“我想用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将把更多的图片信息转换成栅格格式,从而从真实的原始质量中保留更多的细节。当转换在给定大小的矢量图像mmcminch为具有更高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 -versionconvert -list configure);
  • (指向原始样本图像的链接);
  • (链接)由Gimp处理的同一张图片;
  • (指向的链接)由ImageMagick处理的同一图像。

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

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


更新资料

由于某些读者仍然不清楚我上面提到的内容,因此这里还有另一种尝试...

图像文件中被称为“分辨率”“密度”的是元数据属性。它对文件描述的实际像素数没有影响,并且在这方面是完全不相关的。这只是打印,渲染或显示图像时打印或渲染设备或应用程序可能遵循或可能不遵循的提示

为此,图像文件中仅存储了一些数字。这些数字告诉打印机等输出设备,并显示每英寸应显示多少点(或像素)。对于PostScript,PDF,MWF和SVG等矢量格式,它告诉像素比例绘制图像使用的任何实际坐标。

一个示例是Adobe Photoshop,其中应用程序遵守ImageMagick在图像元数据中标注的分辨率值。Photoshop将有关所需打印或显示分辨率的提示存储在名为8bim的专有配置文件中。即使要求将分辨率更改写入图像文件的元数据中,ImageMagick也不会触摸此配置文件。另一方面,一旦看到自己的8bim配置文件,Photoshop将忽略ImageMagick存储在为此目的定义的标准元数据字段中的所有分辨率提示。

OP应该选择了以下标题:

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

为了避免一切误会...


1
“当我检查文件时,它保持不变。” 这就是我要的。我不会说这让我惊讶。请再次阅读我的问题...慢慢地... ARGL
BorisDäppen2012年

6
“这完全不可能!” 不,有可能……只是打印时图像缩小了。这我解释了非常详细的在我的问题
鲍里斯Däppen

5
你在说什么 我已经在问题中详细解释了我的用例。如果您仅按标题回答问题,则对这里的任何人都无济于事。
鲍里斯·达彭(BorisDäppen)2012年

4
您的致命缺陷是最初的假设:“每个区域有更多的像素<==>每个图像有更多的总像素”只有在区域恒定的情况下才是正确的。不是这种情况。
Leo Izen

1
是。DPI仅在呈现给设备时才有意义。当与此分辨率相关时,它也恰好是可以存储在图像文件中的字段。该问题明确询问如何在不更改像素数据的情况下更改该字段。
Leo Izen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.