Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I feel so horribly sorry that I have to ask this question here, but after hours of researching how to do an actually very simple task I'm still failing...

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 be 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...

share|improve this question

migrated from stackoverflow.com Sep 25 '12 at 2:26

This question came from our site for professional and enthusiast programmers.

    
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)... –  Kurt Pfeifle Sep 24 '12 at 21:19
    
But I don't have enough reputation... –  Boris Däppen Sep 25 '12 at 11:52
1  
Now you have. I upvoted your question, twice even... –  Kurt Pfeifle Sep 25 '12 at 20:31

3 Answers 3

up vote 21 down vote accepted

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 IM? For example, Photoshop uses Photoshop:XResolution and Photoshop:YResolution so you have to set these for Photoshop to recognise a density setting (IM can't do this - we use ExifTool).

share|improve this answer
    
Thanks a lot. Seems like convert has no good defaults here. Adding the -units options makes it working... You saved my day! –  user1694803 Sep 24 '12 at 19:34
    
Thanks exactly what I've been hunting around for (I was supplied with an 800x500px picture that someone had set a DPI of 8000 on!). In case anyone else is wondering, the exact same syntax worked for me with a Windows copy of ImageMagick and a JPG picture. –  GAThrawn Nov 1 '12 at 14:32

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;
}
share|improve this answer
    
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. –  Boris Däppen Sep 25 '12 at 12:04
    
Yes, I should have paid more attention to the question! Rereading it, JPG isn't mentioned, PNG clearly is. –  jwpat7 Sep 25 '12 at 12:17

"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"

share|improve this answer
    
"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 –  Boris Däppen Sep 25 '12 at 11:49
    
"Please provide the following to resolve the above issue:" The issue is already solved by Martin Wilson –  Boris Däppen Sep 25 '12 at 11:51
1  
"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 –  Boris Däppen Sep 25 '12 at 12:06
2  
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. –  Boris Däppen Sep 26 '12 at 8:26
1  
@BorisDäppen: You're the first one to tell me that I'm not a help to anyone here. A very bold statement for a SO/SU Noobie to make! :-) –  Kurt Pfeifle Sep 26 '12 at 10:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.