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