As I have received many requests from my readers to write on image upload and crop in modal box in PHP. Image upload and crop is the most important feature of any web project. We can provide great user experience to the end users to upload and change their profile pictures in a modal and also enable them to crop uploaded profile picture in same modal.
So here in this tutorial, you will learn how to implement image upload and crop in a modal box using PHP and jQuery. We will cover this tutorial in easy steps to implement live demo of image upload and crop. We will also allow to download complete source code of this project.
Also, read:
- Upload Multiple Images using jQuery, PHP & MySQL
- Reduce or Compress Image Size While Uploading in PHP
- Image Upload without Page Refresh with PHP and jQuery
- Amazon S3 File Upload using PHP
- Angular Multiple File Upload with PHP and MySQL
- Create Thumbnails While Uploading Images with PHP & jQuery
- Amazon S3 File Upload using JavaScript
We will use following library with this Example:
- jQuery Library : This is a base library to support other jQuery plugin
- Boostrap 3 : Bootstrap used to create page layout
- Imgareaselect : This plugin used to define crop co-ordinate and crop image.
- Ajax form : This jQuery plugin used to handle submit form Ajax manner.
We will use following files with this Example
- index.php : This is a main file that create HTML layout to show change image button with image preview.
- change_pic.php : This file is responsible to all server side functionality like image cropping and saving
- functions.js : This file contains JavaScript code and functions related to cropped image size and save cropped images.
Steps to implement image upload and crop in a modal using PHP and jQuery:
Step 1: First of all, we will include all necessary library files and JavaScript in head in index.php.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="dist_files/jquery.imgareaselect.js" type="text/javascript"></script> <script src="dist_files/jquery.form.js"></script> <link rel="stylesheet" href="dist_files/imgareaselect.css"> <script src="functions.js"></script>
Step 2: Now we will create HTML in index.php to display Change Profile Picture button and image preview section to display saved profile picture.
<div> <img class="img-circle" id="profile_picture" height="128" data-src="default.jpg" data-holder-rendered="true" style="width: 140px; height: 140px;" src="default.jpg"/> <br><br> <a type="button" class="btn btn-primary" id="change-profile-pic">Change Profile Picture</a> </div>
Step 3: Now we will create model box in index.php for image upload and crop functionality.
<div id="profile_pic_modal" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h3>Change Profile Picture</h3> </div> <div class="modal-body"> <form id="cropimage" method="post" enctype="multipart/form-data" action="change_pic.php"> <strong>Upload Image:</strong> <br><br> <input type="file" name="profile-pic" id="profile-pic" /> <input type="hidden" name="hdn-profile-id" id="hdn-profile-id" value="1" /> <input type="hidden" name="hdn-x1-axis" id="hdn-x1-axis" value="" /> <input type="hidden" name="hdn-y1-axis" id="hdn-y1-axis" value="" /> <input type="hidden" name="hdn-x2-axis" value="" id="hdn-x2-axis" /> <input type="hidden" name="hdn-y2-axis" value="" id="hdn-y2-axis" /> <input type="hidden" name="hdn-thumb-width" id="hdn-thumb-width" value="" /> <input type="hidden" name="hdn-thumb-height" id="hdn-thumb-height" value="" /> <input type="hidden" name="action" value="" id="action" /> <input type="hidden" name="image_name" value="" id="image_name" /> <div id='preview-profile-pic'></div> <div id="thumbs" style="padding:5px; width:600p"></div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" id="save_crop" class="btn btn-primary">Crop & Save</button> </div> </div> </div> </div>
Step 4: Now will show the model box using jQuery when click on Change Profile Picture button.
jQuery('#change-profile-pic').on('click', function(e){ jQuery('#profile_pic_modal').modal({show:true}); });
Step 5: Now we will show the image for crop process on bootstrap modal box and also handle form submit using jQuery form plguin.
jQuery('#profile-pic').on('change', function() { jQuery("#preview-profile-pic").html(''); jQuery("#preview-profile-pic").html('Uploading....'); jQuery("#cropimage").ajaxForm( { target: '#preview-profile-pic', success: function() { jQuery('img#photo').imgAreaSelect({ aspectRatio: '1:1', onSelectEnd: getSizes, }); jQuery('#image_name').val(jQuery('#photo').attr('file-name')); } }).submit(); });
Step 6: Now we will handle image crop and call saveCropImage() ajax method to save image on hard disk storage when click on Crop & Save button.
jQuery('#save_crop').on('click', function(e){ e.preventDefault(); params = { targetUrl: 'change_pic.php?action=save', action: 'save', x_axis: jQuery('#hdn-x1-axis').val(), y_axis : jQuery('#hdn-y1-axis').val(), x2_axis: jQuery('#hdn-x2-axis').val(), y2_axis : jQuery('#hdn-y2-axis').val(), thumb_width : jQuery('#hdn-thumb-width').val(), thumb_height:jQuery('#hdn-thumb-height').val() }; saveCropImage(params); });
Step 7: JavaScript function saveCropImage() to save cropped images.
function saveCropImage(params) { jQuery.ajax({ url: params['targetUrl'], cache: false, dataType: "html", data: { action: params['action'], id: jQuery('#hdn-profile-id').val(), t: 'ajax', w1:params['thumb_width'], x1:params['x_axis'], h1:params['thumb_height'], y1:params['y_axis'], x2:params['x2_axis'], y2:params['y2_axis'], image_name :jQuery('#image_name').val() }, type: 'Post', success: function (response) { jQuery('#profile_pic_modal').modal('hide'); jQuery(".imgareaselect-border1,.imgareaselect-border2,.imgareaselect-border3, .imgareaselect-border4,.imgareaselect-border2,.imgareaselect-outer").css('display', 'none'); jQuery("#profile_picture").attr('src', response); jQuery("#preview-profile-pic").html(''); jQuery("#profile-pic").val(); }, error: function (xhr, ajaxOptions, thrownError) { alert('status Code:' + xhr.status + 'Error Message :' + thrownError); } }); }
Step 8: Now handle upload profile picture at server side to upload image/change image on server and also handle save changed picture into MySQL database table in file change_pic.php.
<?php /* Get post details */ $post = isset($_POST) ? $_POST: array(); switch($post['action']) { case 'save' : saveProfilePic(); saveProfilePicTmp(); break; default: changeProfilePic(); } /* Function to change profile picture */ function changeProfilePic() { $post = isset($_POST) ? $_POST: array(); $max_width = "500"; $userId = isset($post['hdn-profile-id']) ? intval($post['hdn-profile-id']) : 0; $path = 'images/tmp'; $valid_formats = array("jpg", "png", "gif", "jpeg"); $name = $_FILES['profile-pic']['name']; $size = $_FILES['profile-pic']['size']; if(strlen($name)) { list($txt, $ext) = explode(".", $name); if(in_array($ext,$valid_formats)) { if($size < (1024*1024)) { $actual_image_name = 'avatar' .'_'.$userId .'.'.$ext; $filePath = $path .'/'.$actual_image_name; $tmp = $_FILES['profile-pic']['tmp_name']; if(move_uploaded_file($tmp, $filePath)) { $width = getWidth($filePath); $height = getHeight($filePath); //Scale the image if it is greater than the width set above if ($width > $max_width){ $scale = $max_width/$width; $uploaded = resizeImage($filePath,$width,$height,$scale, $ext); } else { $scale = 1; $uploaded = resizeImage($filePath,$width,$height,$scale, $ext); } echo "<img id='photo' file-name='".$actual_image_name."' class='' src='".$filePath.'?'.time()."' class='preview'/>"; } else echo "failed"; } else echo "Image file size max 1 MB"; } else echo "Invalid file format.."; } else echo "Please select image..!"; exit; } /* Function to update image */ function saveProfilePicTmp() { $post = isset($_POST) ? $_POST: array(); $userId = isset($post['id']) ? intval($post['id']) : 0; $path ='\\images\tmp'; $t_width = 300; // Maximum thumbnail width $t_height = 300; // Maximum thumbnail height if(isset($_POST['t']) and $_POST['t'] == "ajax") { extract($_POST); $imagePath = 'images/tmp/'.$_POST['image_name']; $ratio = ($t_width/$w1); $nw = ceil($w1 * $ratio); $nh = ceil($h1 * $ratio); $nimg = imagecreatetruecolor($nw,$nh); $im_src = imagecreatefromjpeg($imagePath); imagecopyresampled($nimg,$im_src,0,0,$x1,$y1,$nw,$nh,$w1,$h1); imagejpeg($nimg,$imagePath,90); } echo $imagePath.'?'.time();; exit(0); } /* Function to resize image */ function resizeImage($image,$width,$height,$scale) { $newImageWidth = ceil($width * $scale); $newImageHeight = ceil($height * $scale); $newImage = imagecreatetruecolor($newImageWidth,$newImageHeight); switch ($ext) { case 'jpg': case 'jpeg': $source = imagecreatefromjpeg($image); break; case 'gif': $source = imagecreatefromgif($image); break; case 'png': $source = imagecreatefrompng($image); break; default: $source = false; break; } imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height); imagejpeg($newImage,$image,90); chmod($image, 0777); return $image; } /* Function to get image height. */ function getHeight($image) { $sizes = getimagesize($image); $height = $sizes[1]; return $height; } /* Function to get image width */ function getWidth($image) { $sizes = getimagesize($image); $width = $sizes[0]; return $width; } ?>
Step 9: Now finally save/update changed image path into MySQL database using below PHP function saveProfilePic().
/* Function to handle profile pic update*/ function saveProfilePic(){ include_once("db_connect.php"); $post = isset($_POST) ? $_POST: array(); //Handle profile picture update with MySQL update Query using $options array if($post['id']){ $sql_query = "SELECT * FROM users WHERE uid = '".mysqli_escape_string($conn, $post['id'])."'"; $resultset = mysqli_query($conn, $sql_query) or die("database error:". mysqli_error($conn)); if(mysqli_num_rows($resultset)) { $sql_update = "UPDATE users set profile_photo='".mysqli_escape_string($conn,$post['image_name'])."' WHERE uid = '".mysqli_escape_string($conn, $post['id'])."'"; mysqli_query($conn, $sql_update) or die("database error:". mysqli_error($conn)); } } }
You may also like:
- Build Live Chat System with Ajax, PHP & MySQL
- Create Event Calendar with jQuery, PHP and MySQL
- Build Invoice System with PHP & MySQL
- Push Notification System with PHP & MySQL
- Create Bootstrap Cards with PHP and MySQL
- Build Content Management System with PHP & MySQL
- Convert Unix Timestamp To Readable Date Time in PHP
- Ajax Drop Down Selection Data Load with PHP & MySQL
- Inventory Management System with Ajax, PHP & MySQL
- Drag and Drop File Upload using jQuery and PHP
- Load Dynamic Content in Bootstrap Popover with Ajax, PHP & MySQL
You can see view the complete running example from the demo link. You can also download complete demo script from below links.
Demo Download
nice tutorial, but donwload link not working
Thanks! now its working.
I tried to add the functionality to save/ update to database
But i get this error below.
Fatal error: Call to undefined function saveAvatar() in C:\wamp\www\image-upload-image-crop-modal-php-jQuery\change_pic.php on line 47
Any idea why this is happening ? Thanks
The error returning due to function saveAvatar() not defined. Now I have updated demo zip file. You can download demo again and try.
where css file and full code download link?
Its at the end of tutorial. Thanks!
create database and import backup already provided in downloaded file
Sir, I dint get the sql file…
I have not handled image save info into database with this example. You can create your own MySQL queries to stor records as per requirement. Thanks!
Hi! It’s cool this example, Can you please to put some INSERT or UPDATE example for saveProfilePic function here in the comments? =) thnks a lot
Thanks! I will put these.
Sir, Can you please put some INSERT or UPDATE example for saveProfilePic function.
Yes, I will add these feature in few days.
Now implemented saveProfilePic() to update profile in user table.
it is fine but working is not 100% as:
1) same name image file is not show again to crop
2) image file other than .jpeg/.jpg show error while uploading and not show in the profile_picture but move to images/tmp folder as black image
3) upload any format image close modal image will move to images/tmp folder and
4) cancel image shown in modal after next open
please fix these issues
Thanks for precious comments! I have just updated tutorial and demo to also support jpg/jpeg, png, gif file format. Plz check demo.
I try put on live, but not preview image on modal,,,,
I have checked just and its working fine. If you had upload other than jpg file then there was issue. I have just updated script.
I have checked just and its working fine. If you had upload other than jpg file then there was issue. I have just updated script and now its working fine. Please check demo.
I have an issue if i make a selection to crop the image and close the modal box the selection still appears. How to hide it if i close modal box
Thanks for the precious comments! You can reset file input and preview html.
Hi. Trying demo with png files the images get black. Did you see that? Is that right? With a jpeg image it works Fine!!!
Thanks… This code is very nice!
Thanks for precious comments! The script was working only for jpg files. Now I have updated script to work with jpg, png and gif files. I have updated code in tutorial and also download script. You can check demo page. Thanks!
Hi, Thank a lot for your code!!!
But i’m facing with the below error; can you suggest me??? your demo is working perfect. but in my local system not working.
imagecopyresampled() expects parameter 2 to be resource, boolean given in C:\xampp\htdocs\cropimage\change_pic.php on line 85
I have just checked script and its running fine. what’s fileformat you have tried to upload? The current script supporting only (“jpg”, “png”, “gif”, “jpeg”) file format.
Sir im facing this error after uploading.
jQuery(…).imgAreaSelect is not a function
Please provide us source code to fix issue. Thanks!
Very impressive tutorial. Im not use to php. is there anyway i could do something like that with nodejs
Thanks, I will try to publish tutorial for this.
the pictures was save in the temp folder, but the database is still empty..
Can you help me save the file to the database?
Avartar image limit only for two pictures.. WHY?
Thanks! Please provide us source code fix issue.
nice tutorial, but donwload link not working
Thanks!. Its working, try again.
Hello Sr, Thanks a lot for the code.
I have one question how to do that when i upload the image the crop area automatically show on the picture.
Thanks in advance.
Thanks for precious comment!. In this tutorial, we have implemented image select with imgareaselect. If you want to select uploaded image automatically, you can check this link https://stackoverflow.com/questions/27261671/how-to-automatically-show-select-for-crop-on-image?rq=1
can you send me source codes with the image insertion function? I really need it. Thank you in advance
You can download complete from download link. Thanks!
The code isn’t responsive. The code is all fine with the desktop version.
Thanks PhpZag! This was exaclty what I was looking for! After extended research and many alternatives that I have tried out, this was the absolute best one. Thanks again, for the tutorial and the code!
One question: Can the square croparea show from the beginning, when the modal opens?
Then, the user would need only to resize/move it…
So, the user doesn’t have to figure on his own to select a square?
Thanks! I will try to do these changes.
nice tutorial, but browser image uploading get so much time what to do?
Its depend on file size, otherwise it should work same. thanks!
Sir after upload it insert into DB but file name only Like : avatar.png?10205
please how to make it insert into DB with path like : ./images/tmp/avatar.png?10205
You need to make changes in saveProfilePic() function to store file path instead of just file name. thanks!
Really Great Script,
One error i have noticed is that if i dont crop and just save the image without cropping it throws a warning error: A non-numeric value encountered on about like 90 of change_pic. This doesnt change the image preview also
I am checking this to fix and update soon. thanks for the details!