Tutorial: Dynamically Resize Image on PHP Server with ImageMagick

Launch demo in a new window.

It is impractical to optimize a photo to display on a computer screen in all browsers ahead of time. However with ImageMagick and PHP we can dynamically configure an optimal image at runtime. In this example I use jQuery to send the maximum width and height of a user’s screen to a small PHP script. Leveraging the power of ImageMagick through PHP I dynamically down-size a large image to fit the maximum width or height the client is using, while maintaining the original aspect ratio.

Why would I do this?

This allows for the server to download to the clients computer an optimal file size to fill the client’s browser window. For example on my personal computer, this script converts a 5.5mb 3000×2250 .png file to a 54kb 1032×645 .jpg file. Much more optimized for downloading! (While still looking good fully enlarged on my display screen.)

For this demo, I am using two documents.

  • The HTML document passes the display screen’s dimensions to the PHP script. This document also run jQuery to resize the optimized image with the browser.
  • The PHP document that calls the ImageMagick convert command and returns the converted image.

Let’s look at the code, then we’ll break it down.
The HTML Document:

The important parts.

Row 4 includes the jQuery library from jquery.com’s CDN.

Row 7 creates an image element, with an “id” and a data attribute named “src” which contains the path of our image.

Row 10 calls our jQuery function once the document is ready to run functions.

Row 11 first selects our image element using the “id” selector. Next it assigns the image source a php file. This file will return an image, so this is ok. You’ll note we’ve included some extra URL GET request data that we will pass to the php script. The first assigns ‘src’ the ‘src’ value of our image’s data attribute. Secondly we pass the screen’s height and width. This should be the max resolution dimensions of the user’s display screen.

Row 12 tells the browser to reduce or expand the image to fit the browser’s window, while maintaining the image’s aspect ratio. This is not changing the downloaded image’s file size, it is merely changing the size displayed on the user’s monitor. If we sent a 200px by 150px image and the browser tried to stretch the image to 1000px by 750px it would be very pixelated with a lot of artifacts and noise.

Row 14 sets up a listener to detect when ever the browser changes size. If so, run the following function.

Row 15 once again tells the browser to reduce or expand the image to fit the browser’s window, while maintaining the image’s aspect ratio.

Now for the PHP code that runs the ImageMagick magic!
The PHP Document:

The important parts.

Rows 2-3 gets the height and width (respectively) from the GET URL request that was passed from our jQuery string in row 11 of the HTML document. Remember, that this height and width are the max-dimensions of the user’s display screen, not the browser or viewport size.

Row 4 gets the source images path that was passed from the jQuery string along with the height and width.

Row 5 uses a native PHP function that returns an array. The first two elements of the array contain the width and height of the source image.

Row 6 tests if the width of the user’s display is greater than or equal to the height, if not skip to row 9.

Row 7 is one long statement. Lets break it down by pieces.

  • $cmd stores the following statement in a variable. ‘cmd’ Is short for ‘command’.
  • /usr/local/bin/convert is where the convert.exe executable resides on my Godaddy’s server. Your server may have a different path to the ‘convert’ command.
  • -size {$size[0]}x{$size[1]} for efficiency, I am telling ImageMagick the exact dimensions of the source image, so it doesn’t have to spend time calculating that out too. Remember $size is an array of properties of the image. Element [0] is the width and element [1] is the height.
  • $src tells ImageMagick the path to the source image.
  • -resize “.$w.”x commands ImageMagick to resize a copy of the source image to the same width that was passed through the jQuery GET URL request. The height was not included after the ‘x’ so then the aspect ratio will be maintained.
  • -unsharp 0.2×0.6+1.0 Don’t let the unfortunate name deceive you. ‘unsharp’ actually sharpens an image, it does so by doing the reverse of a blur effect. Quite clever process that my mind is still trying to wrap around. We are using ‘unsharp’ to correct any blurring that may have occurred during the resizing. It’s too complex for me to properly explain, so I will just say that 0.2×0.6+1.0 works to my liking. Experiment for yourself or refer to this page.
  • -quality 50 commands ImageMagick to reduce the quality by 50%. This value is a personal preference, but I think it is still good quality.
  • JPG:- states that the final image will be of type ‘jpg’.

Row 9 is the same as row 7, but adjusts the image for tall screens instead of wide screens. -resize x”.$h.” leaves the width input blank, so the image ratio will be based on its height.

Row 11. The header() function must be called before any actual output is sent. We are telling the HTML document that we are sending content of type ‘image’ in the ‘jpeg’ format.

Row 12 passthru() is similar to ‘exec()’ in that it runs a command, however passthru() sends the returned value directly back to the browser. Inside the passthru() function we send the $cmd command string that we created earlier for the passthru() to execute. $retval Stores the returned value that is passed directly to the browser. We really only need this stored, if we were to then perform other actions on the image in PHP.

Row 13 terminates the PHP script.

That’s it! Two short little scripts to maximize the image size, while minimizing the download file size required.

I’d love to see how you use this information in your own code. Leave a link in the comments below.

Posted in PHP Tagged with: , , , , , , ,

Leave a Reply

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