Change the DPI of a Jpeg Image with PHP

Recently I was finishing a QR Code generator, and I had to prepare two versions of the generated files – for web (72DPI) and for print (300DPI). The first option is working right out of the box for GD Library. That is because the default value of the 72DPI is hard-coded in the config file gd.h (sometimes can be 96DPI by default, depending on the build) and every time we use the imagecreate() function, the DPI setting is read from there. The bottom line is, that whatever the density of the original image is, every time you create/manipulate it with GD Library, you will get 72DPI image as result. We can always change the value in gd.h to be 300DPI, but that would mean that the default DPI for ALL the images will be 300DPI, which is not what we want (after all probably you will want to use GD mostly for web, and not so much for printing). The second and better option is to manipulate the header of the created file, in order to change the density bits to the ones we want.

Let’s start with the original image. For this case I’ve chosen a beautiful Bulgarian landscape with original DPI of 72 and size of 560 by 311 px. The printing size for 72DPI will be 7.778 by 4.319 in. (560/72 by 311/72). Let’s change this info: Demo

And this is the source of the script above:

<?php

//Read the jpeg image
$path = "path_to_the_image.jpg";
$image = file_get_contents($path);

$image = substr_replace($image, pack("cnn", 1, 300, 300), 13, 5);

header("Content-type: image/jpeg");
header('Content-Disposition: attachment; filename="'.basename($path).'"');

echo $image;

?>

In line #7 we are replacing the binary info with a new one, converted from text to binary thanks to the PHP pack function. The first argument in that function is format of the string, supplied as second, third and forth argument. We are changing 5 bytes in the header:

  • byte #14 becomes signed char of 1 (this sets the resolution type: 0 is none, 1 is pixels per inch / DPI , 2 is pixels per cm / DPC)
  • bytes #15 and #16 are unsigned short char of 300 (this is the X resolution)
  • bytes #17 and #18 are unsigned short char of 300 (this is the Y resolution)
  • The last thing to do is to make sure that you are generating the image with the resolution needed for that DPI. So if we want to have a width of 3 in. / 300DPI, we need to make sure that our image created by GD is 300×3 = 900px. instead of the default 3×72 = 216px. Good rule of the thumb is every time you need image for printing to multiply the width and the height by 4.166666666666667 (which is the 300/72 ratio).

      5 comments for “Change the DPI of a Jpeg Image with PHP

    1. June 21, 2011 at 10:40

      Thank You For Sharing this thing. it is very helpful.

      Thanks Again.

    2. August 8, 2011 at 02:46

      Thanks

      For This useful Article

    3. November 9, 2011 at 21:51

      Thanks a lot. I have a slightly different scenario. I have a 300 dpi image on which I have to write some text using imagettftext function. When I load that image through GD, its dpi is reduced to 72 and the text becomes very small.

      Can you help me with it? My requirements are that the text should remain of proper size and the output image generated should be of 300 dpi.

    4. January 12, 2012 at 08:43

      how can i save the image in the server

    5. Tao
      August 25, 2015 at 09:47

      Hey Andrey Voev you are a Genius. Thank you for this informations.

    Leave a Reply

    Your email address will not be published. Required fields are marked *