Ajax Image upload & Resize with PHP ImageMagick & jQuery

ImageMagick is great image processing for PHP, with ImageMagick you can resize your image, crop and do many other things in a very simple manner, it supports numerous image formats. Today we are going to create a very simple Ajax based image resize script using ImageMagick (PHP) and jQuery.

ImageMagick Installation

ImageMagick is not always available, but installation is pretty straight forward, for example here's a guide to install ImageMagick in ubuntu 16.04, similar resources on ImageMagick installation can be found on the internet for different OS. If you are on shared hosting, most companies already offer ImageMagick to their clients, so if you face some problems make sure ImageMagick is available.

Upload Box

Let's create an HTML upload form, images will be uploaded with Ajax requests so we will be using jQuery later, hence there's no regular HTML form to trigger upload, instead we want to upload image automatically as soon as the user chooses a file with <input type="file">.
HTML
  • 1
  • 2
  • 3
  • 4
  • 5
<div class="upload-box"> <label for="image-file">Upload file</label> <input type="file" name="image-file" id="image-file" accept="image/*" /> <div id="server-results"></div> </div>
Note that our <input type="file"> will be hidden, as we can't style this element too much, instead we will use <label> to trigger open our hidden file field, and we can style the label as much as we want. <div id="server-results"></div> is where our Ajax server response to be displayed.

File API & jQuery

Now that our upload box is ready, we can obtain information of any selected file using browser's File interface, which can be accessed using JavaScript. In the script below we are doing some client side inspection of the file before we upload it to the server, here we mainly check for file size and the file types allowed. <input type="file" accept="image/*" /> will also filter out image types during file selection with accept="image/*" in HTML.
You can remove regex filter below if that's sufficient for you.
JQUERY
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
var ajax_url = "upload_resize.php"; //path to upload_resize.php var max_file_size = 2194304; //Max file size allowed (2MB) //Regex filter to allow only image file types var image_filters = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i; $("#image-file").change(function(){ //user has selected a file if(window.File && window.FileReader && window.FileList && window.Blob){ //does browser support file API? if($(this).val()){ var oFile = $(this)[0].files[0]; //get file var fsize = oFile.size; //get file size var ftype = oFile.type; // get file type if(fsize > max_file_size){ //if file size is more than allowed alert("File size can not be more than (" + max_file_size +") 2MB" ); return false; } if(!image_filters.test(oFile.type)){ //unsupported file type alert("Unsupported file type!" ); return false; } var mdata = new FormData(); mdata.append('image_data', oFile); $.ajax({ type: "POST", // HTTP method POST processData: false, contentType: false, url: ajax_url, //Where to make Ajax call data: mdata, //Form variables dataType: 'json', success:function(response){ if(response.type == 'success'){ $("#server-results").html('<div class="success">' + response.msg + '</div>'); }else{ $("#server-results").html('<div class="error">' + response.msg + '</div>'); } } }); } }else{ alert("Can't upload! Your browser does not support File API!</div>"); return false; } });
When a file meets our requirement, we can then proceed to jQuery $.ajax method, which makes the Ajax call to target PHP script and uploading our image file to server. You may want to show some fancy loading animation just before the Ajax call and hide it when the server returns some response. You can also show a progress while the image is being upladed using XHR see example here.

PHP & ImageMagick

ImageMagick in PHP is very handy image processor, it can resize, distort, crop, explode, blur and do many more on fly with neat looking very less code.
Resize Image : For example, here's how simple it is to resize your image using ImageMagick in PHP.
PHP
  • 1
  • 2
  • 3
$image = new Imagick("myfile.jpg"); //image file $image->resizeImage( 100, 100 , Imagick::FILTER_LANCZOS, 1, TRUE); //just resize it $image->writeImage("Upload_dir/new_image.jpg", true); //save to destination folder
Resize Animated GIF : Some people face problem with Animated GIF in PHP GD, but with ImageMagick it's not a problem. To resize animated GIF file, you can simply follow code below. It will resize your GIF file but keeping your animation intact.
PHP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
$image = new Imagick("my_animation.gif"); $image = $image->coalesceImages(); foreach ($image as $frame) { $frame->resizeImage( $image_height , $image_width , Imagick::FILTER_LANCZOS, 1, TRUE); } $image = $image->deconstructImages(); $image->writeImages("Upload_dir/my_new_animation.gif", true); //notice writeImages();
Let's combine these two examples and create our image resize processes, which will not only resize regular images, but animated GIFs as well.
PHP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
$upload_dir = "/home/image_magick_upload/uploads/"; //path to upload directory $upload_dir_url = "http://yourwebsite/image_magick_upload/uploads/"; //url pointing to upload directory $image_height = 400; //max image height $image_width = 400; //max image width //make sure uploaded file is not empty if(!isset($_FILES['image_data']) || !is_uploaded_file($_FILES['image_data']['tmp_name'])){ //generate an error json response $response = json_encode( array( 'type'=>'error', 'msg'=>'Image file is Missing!' ) ); print $response; exit; } //get image info from a valid image file $image_info = getimagesize($_FILES['image_data']['tmp_name']); //get mime type of the image if($image_info){ $image_type = $image_info['mime']; //image mime }else{ print json_encode(array('type'=>'error', 'msg'=>'Invalid Image file !')); exit; } //ImageMagick $image = new Imagick($_FILES['image_data']['tmp_name']); /* At this point you can do many other things with ImageMagick, not just resize. See http://php.net/manual/en/class.imagick.php */ if($image_type=="image/gif"){ //Determine image format, if it's GIF file, resize each frame $image = $image->coalesceImages(); foreach ($image as $frame) { $frame->resizeImage( $image_height , $image_width , Imagick::FILTER_LANCZOS, 1, TRUE); } $image = $image->deconstructImages(); }else{ //otherwise just resize $image->resizeImage( $image_height , $image_width , Imagick::FILTER_LANCZOS, 1, TRUE); } //save image file to destination directory $results = $image->writeImages($upload_dir. $_FILES['image_data']['name'], true); //output success response if($results){ print json_encode(array('type'=>'success', 'msg'=>'Image Uploaded! <br /><img src="'.$upload_dir_url. $_FILES["image_data"]["name"].'">')); exit; }
That's all you need to create an Ajax based image uploader with PHP ImageMagick features to resize normal images as well as GIF animated images. If you want to resize images using regular PHP GD, read my another article here.
You can also checkout this step by step video created by Webucator below :
Download Demo
New question is currently disabled!