I want to change DPI with ImageMagick without changing the actual byte-size of the image data
Solution 1
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).
Solution 2
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;
}
Solution 3
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
Related videos on Youtube
Boris Däppen
Linux, Perl, Philosophy of Technology, Opensource
Updated on September 18, 2022Comments
-
Boris Däppen over 1 year
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 ValuesX-Resolution
andY-Resolution
which are known to me as so called DPI values. You can also choose the format which by default isPixel/Inch
. (In German the dialog isBild -> Druckgröße
and thereX-Auflösung
andY-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. But 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 to72
instead of300
. 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.
-
Boris Däppen over 11 years"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 over 11 years"Please provide the following to resolve the above issue:" The issue is already solved by Martin Wilson
-
Boris Däppen over 11 yearsSorry for my rage before... I edited my question a bit, so that there is less chance of misunderstanding my question. I hope your detailed explanation helps somebody else though. Keep on helping
-
Boris Däppen over 11 yearsThis 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 over 11 years"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
-
Kurt Pfeifle over 11 yearsNo it's not possible to get what you asked before! If you had formulated your question like this: "I want to change the size of image for printouts (different DPI) without changing the byte-size of my image data" -- then it would be a different thing altogether, and your question wouldn't have been so easy to mis-understand....
-
Boris Däppen over 11 yearsWhat 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.
-
Liam over 9 yearsYour 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.
-
Kurt Pfeifle over 9 years@LeoIzen: I explained in detail that the DPI is only meaningful for 'rendering to devices'. Which means, the area would not stay constant. Which is why your downvote is not justified.
-
dorien about 9 yearsLots of publishers require your image to be minimal 300 dpi. Even if you have less data, you need to duplicate the same pixels, they just won't accept the file otherwise. I have the same question as Boris. I did it before, just forgotten how to.
-
akostadinov almost 9 yearsI needed to put
-density 300
beforeinput.png
. I was converting PDFs. Thanks anyway. -
Andrey over 7 yearsFor 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. -
u_Ltd. over 7 yearsYes, 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.