55

In GIMP there is a very simple way to do what I want. I only have the German dialog installed but I’ll try to translate it. I’m talking about going to Picture -> PrintingSize and then adjusting the Values X-Resolution and Y-Resolution which are known to me as so called DPI values. You can also choose the format which by default is Pixel/Inch. (In German the dialog is Bild -> Druckgröße and there X-Auflösung and Y-Auflösung)

Ok, the values there are often 72 by default. When I change them to e.g. 300 this has the effect that the image stays the same on the computer, but if I print it, it will be smaller if you look at it, but all the details are still there, just smaller -> it has a higher resolution on the printed paper (but smaller size... which is fine for me).

I am often doing that when I am working with LaTeX, or to be exact with the command pdflatex on a recent Ubuntu-Machine. When I’m doing the above process with GIMP manually everything works just fine. The images will appear smaller in the resulting PDF but with high printing quality.

What I am trying to do is to automate the process of going into GIMP and adjusting the DPI values. Since ImageMagick is known to be superb and I used it for many other tasks I tried to achieve my goal with this tool. But it does just not do what I want.

After trying a lot of things, I think this actually is the command that should be my friend:

convert input.png -density 300 output.png

This should set the DPI to 300, as I can read everywhere in the web. It seems to work. When I check the file it stays the same (EDIT: which is what I expect, as explained above).

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

When I use this command, it seems like it did what I wanted:

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

(Funny enough, the same output comes for input.png which confuses me... so this might be the wrong parameters to watch?)

But when I now render my TeX with pdflatex the image is still big and blurry. Also when I open the image with GIMP again the DPI values are set to 72 instead of 300. So there actually was no effect at all.

Now what is the problem here. Am I getting something completely wrong? I can’t be that wrong since everything works just fine with GIMP.

Thanks for any help in this. I am also open to other automated solutions which are easily done on a Linux system.

1
  • user1694803: You should remember to return to Martin Wilson's answer and 'upvote' it too (click on the small ^ icon to the left of his answer), not just 'accept' it as soon as you have enough personal reputation (I think you need +15)... Sep 24, 2012 at 21:19

5 Answers 5

93

Specify the units - I seem to remember having a problem when I omitted this option (although DPI should be the default), for example:

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

Do you know which embedded data fields GIMP uses to read the resolution - does it have its own that override the standard ones used by ImageMagick? For example, Photoshop uses Photoshop:XResolution and Photoshop:YResolution so you have to set these for Photoshop to recognise a density setting (ImageMagick can’t do this - we use ExifTool).

2
  • 4
    I needed to put -density 300 before input.png. I was converting PDFs. Thanks anyway. May 27, 2015 at 15:22
  • 2
    For PNG to TIFF conversion I needed to use -set units PixelsPerInch -density 300, simple -units didn't work regardless of the order of the options.
    – Andrey
    Nov 16, 2016 at 21:35
4

I could not figure out how to convince convert to only add the metadata and not re-encode my [monochrome] bitmap; it was expanding the file >50%.

I discovered that pngcrush (not an ImageMagick tool) can also add the density metadata. This command line marks it 600dpi and allows other optimizations, which reduced the file size by ~10%:

pngcrush -res 600 in.png out.png
1
  • In my case convert produced a file where the DPI value for the width was slightly off (rounding error?), whereas the output of pngcrush had the correct DPI value for both dimensions. The exact resolution of a PNG image can be checked with pngcheck using pngcheck -v image.png | grep pHYs. Nov 9, 2023 at 17:10
4

Note that you can use Exiftool to read out resolutions. For example, Exiftool '-*resolution*' c.jpg might show

Resolution Unit : inches X Resolution : 300 Y Resolution : 300

Exiftool also is able to set parameters, but as noted in man page Image::ExifTool::TagNames, the Extra Tags XResolution and YResolution are not writable by Exiftool.

I don't know whether ImageMagick has resolution-changing options, but would be surprised if it doesn't. Also, it is straightforward to write GIMP scripts to automate tasks like this, and also it is possible to change resolutions with small programs. For example, following is a C program (compilable via gcc setRes.c -O3 -Wall -o setRes) that reads the first few bytes of a jpeg file, changes resolutions to 300, and rewrites them. The program as shown uses constants for little-endian machines, like x86. If run on a big-endian machine it should terminate with a message like Error: xyz may be not a .jpg file, even if xyz is a jpeg file. Note, I haven't tested the resulting pictures via pdflatex; you probably would find it worthwhile to post a question in the 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;
}
3
  • 1
    This does not help me a lot, since I'm dealing with PNG and have not much clue of JPG or even C. That is to "deep" knowledge for me to be useful. Maybe someone else can use it. Sep 25, 2012 at 12:04
  • Yes, I should have paid more attention to the question! Rereading it, JPG isn't mentioned, PNG clearly is. Sep 25, 2012 at 12:17
  • Yes, I'm someone else and I can use it: I've opened my .jpg file in a hex editor and edited the ninth and eleventh byte for the vertical and horizontal density. So-to-speak I "executed" your code manually.
    – u_Ltd.
    Nov 28, 2016 at 23:08
0

How to change the DPI of an image via the command-line in Linux

For some reason, setting the -density does absolutely nothing to the image. But, using -resample does work to change the DPI:

# [doesn't work]
# does absolutely nothing to the image
convert -units PixelsPerInch in.jpg -density 75 out3.jpg

# [DOES work!]
# resamples the image into a smaller DPI of only 75 dots per inch
convert -units PixelsPerInch in.jpg -resample 75 out3.jpg

Where I learned about the -resample option: https://legacy.imagemagick.org/discourse-server/viewtopic.php?p=69724&sid=867d964e2aa20481e26c4f49914bc53c#p69724

Note that convert --version for me shows the following on my Ubuntu 20.04 machine:

$ convert --version
Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff webp wmf x xml zlib
-5

"I want to change DPI with Imagemagick without changing the actual byte-size of the image data."

This is completely impossible!

Because:

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

Also you don't seem to understand what DPI in reality is:

  1. It's a completely abstract value that gets practical value only in the context of knowing also the absolute size of the printout or rendering on screen or monitor:
    • You can 'print' the very same 72x72 pixels image on a 1 inch wide square: the printout will have a resolution of 72dpi.
    • You can 'print' it on a 1/4 inch wide square too: then the printout will have a resolution of 288dpi.
    • (Note: If you 'print' it at 288dpi on a 1 inch square, it's no longer the same image: it will have undergone some extrapolation through the printer driver or some other filtering mechanism, and it will have become a 288x288 pixels image instead of a 72x72 pixels image...)
  2. Both printouts will have the very same image information -- the 288dpi image will not suddenly have more.

If you want to print the original 72x72 pixels image as a 1 inch wide square, but at 288dpi, then you'll have to rescale the image (in this case scaling it up). For every 1 pixel in the original you'll need 4 pixels of the new, upscaled image. Now there are different algorithms which can be used to compute what color values these 4 pixels (3 of them new pixels) should have:

  • you could give them the same as the original pixel (which is a very "raw" algorithm,
  • or you could do some averaging of the original pixel's color value with the color values of the neighboring pixels.

In any case you are creating a bigger image consisting of 288 rows of pixels which are each 288 pixels high (288x288 pixels).

What Gimp does for you when you go through "Picture -> Printing Size": it simplifies the process of re-calculating the required changes in absolute pixel sizes, making it more user-friendly. For this purpose...

  • ...it first asks you about the DPI because a given printer can not change its printing resolution arbitrarily (some can offer not just one, but maybe even 2 or 3 different resolutions). So it asks you at which resolution you want to print. That is the first info.
  • ...then it also asks for the second piece of info: at which size (in cm, mm or inch) the printout should appear on paper.

According to these two pieces of info Gimp then calculates the total number of pixels it has to use (extrapolate from the original number of pixels) to fill the requested space at the requested resolution.

However, scaling up a raster image by making it contain more pixels does not add real info to it, and it does only add 'quality' to it which is fictitious. It may look nicer to the human eye if your scale up algorithm is a 'good' one. And it will look ugly, if you just double, treble or quadruple existing pixels, like some simple algorithms do.

For raster images,
the DPI setting is only relevant in the context of printing or displaying it. Because printers or monitors have given, fixed resolutions. Therefor it is info that only...

  • ...a printer driver or
  • ...an image processing application that supports printing

need to know.

And ImageMagick's documentation is in full agreement with me:

-density width
-density widthxheight
Set the horizontal and vertical resolution of an image for rendering to devices.

For vector images or file formats
(such as PDF or PostScript) the DPI setting however is extremely important in the context of rasterizing them. A higher DPI will transfer more picture information into the raster format and hence preserve more details from the real original quality. When converting a vector image of a given size in mm, cm or inch into raster with a higher DPI will directly translate into a higher number of total pixels in the image.

Also, ImageMagick does not support 'printing' as such. Instead, ImageMagick only...

  • ...converts files from a given raster format to other raster formats;
  • ...or it scales down or scales up raster images;
  • ...or it changes color values according to a specific algorithm;
  • ...or it crops images, overlays them, inverts them, mirrors them;
  • ...and what-not....

...but to print the manipulated images, you need to use a different program.

Some image formats (TIFF, PNG,...) do support storing a DPI setting internally in their meta data.

But this is no more than a 'hint' attribute that does not alter the underlying raster image. That's the reason why you made this discovery:

"When I check the file it stays the same."

This 'hint' can possibly be automatically evaluated by printer drivers or by page creation programs such as LaTeX. In the absence of such DPI 'hints' (or if they somehow don't present themselves in the way LaTeX expects them to do), LaTeX should still be able to be commanded to render any given image on a page the way one expects it to -- it needs just some more explicit LaTeX code around the image!

Some other image formats (JPEG(?), BMP,...) do not even support storing a DPI hint at their internal meta data.

So Gimp only does support what you see it's doing with "Picture -> Printing Size" because it wants to print an image. With ImageMagick you cannot print.

Keep doing what you want to do with Gimp when you print. It doesn't make sense with ImageMagick.

See also this additional IM documentation snippet, which explains the very same topic in different words.


So what remains is this:

  • If you 'manipulate' your image with Gimp, and then embed the result in LaTeX, the page looks like you expect it.
  • If you 'manipulate' your image with ImageMagick, and then embed the result in LaTeX, the page looks not like you expect.

Please provide the following to resolve the above issue:

  • the exact version of your ImageMagick installation (complete output of convert -version and convert -list configure);
  • (a link to an) original sample image;
  • (a link to the) same image manipulated by Gimp;
  • (a link to the) same image manipulated by ImageMagick.

This way we can help to solve the problem.

But note: this is a different problem from what your current subject/headline asks: "I want to change DPI with Imagemagick without changing the actual byte-size of the image data"


Update

Since it is still not clear to some readers what I noted above, here is one more attempt...

Whatever is noted as 'Resolution' or 'Density' inside an image file, is a metadata attribute. It has no influence upon the number of actual pixels described by the file and is completely irrelevant in this respect. It is just a hint which a printing or rendering device or an application may or may not follow when printing, rendering or displaying the image.

For this purpose, it is just a a few number stored within the image file. These numbers tell output devices such as printers and displays how many dots (or pixels) per inch the image should be displayed at. For vector formats like PostScript, PDF, MWF and SVG it tells the pixel scale to draw any real world coordinates used by the image.

One example, where the resolution value noted by ImageMagick inside the image metadata is NOT honored by an application is Adobe Photoshop. Photoshop stores its hints about a desired print or display resolution in a proprietary profile named 8bim. ImageMagick does not touch this profile, even when asked to write a resolution change into the metadata of an image file. Photoshop on the other hand, will ignore all resolution hints stored by ImageMagick in the otherwise standard metadata field that is defined for this purpose as soon as it sees its own 8bim profile.

The OP should have chosen the heading:

  • 'I want to change DPI (metadata resolution hint) with ImageMagick without changing the actual number of pixels in the image'

in order to avoid all misunderstandings...

10
  • 2
    "When I check the file it stays the same." THIS IS WHAT I WANT. I DO NOT SAY IN THE TEXT THAT THIS SURPRISES ME. PLEAS READ MY QUESTION AGAIN... SLOWLY... ARGL Sep 25, 2012 at 11:49
  • 7
    "This is completely impossible!" No it is possible... it is just that the image shrinks when printed. Which I explained very detailed in my question Sep 25, 2012 at 12:06
  • 7
    What are you even talking about. I have explained my use-case in detail inside the question. If you answer questions just by title you are not a help to anyone here. Sep 26, 2012 at 8:26
  • 4
    Your fatal flaw was the initial assumption: "more pixels per area <==> more total pixels per image" That's only true if the area is constant. This is not the case.
    – Leo Izen
    Jan 22, 2015 at 2:14
  • 2
    Yes. DPI is only meaningful if rendered to devices. It also happens to be a field that can be stored in an image file for when this resolution is relevant. The question clearly asked how to change this field without changing the pixel data.
    – Leo Izen
    Jan 24, 2015 at 6:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .