Skip to main content

Image Upload and Crop in Modal with jQuery, PHP & MySQL

Image upload and crop is an important feature of web applications. This feature is mainly used in user sections to allow users to upload and crop their profile picture before save to the database. The image crop before save is very user friendly feature as it allow users to resize picture to display correctly and also save memory.

So if you’re thinking about implementing image upload and crop functionality in your application, then you’re here at the right place. In this tutorial, you will you will learn how implement Image Upload and Crop in Bootstrap Modal using jQuery and PHP.

We will cover this tutorial in easy steps to implement live demo of image upload and crop functionality using jQuery, PHP and MySQL.

Also, read:

So let’s implement image upload and crop in modal example with jQuery, PHP and MySQL. The major files are:

  • index.php
  • image_crop_save.js
  • change_photo.php
  • User.php: Class to hold user methods.

Step1: Create MySQL Database Table

As we will create live example to upload and crop user profile picture and save into database table, so first we will create MySQL database table user_profile using following table create SQL query.

CREATE TABLE `user_profile` (
  `id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `photo` varchar(255) NOT NULL,
  `skills` varchar(255) NOT NULL,
  `website` varchar(255) NOT NULL,
  `designation` varchar(255) NOT NULL,
  `city` varchar(255) NOT NULL,
  `country` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

We will store a user record to upload and change user profile picture. We will use below insert SQL statment to insert record into table.

INSERT INTO `user_profile` (`id`, `name`, `email`, `phone`, `photo`, `skills`, `website`, `designation`, `city`, `country`) VALUES
(1, 'Jhon Smith', 'smith@webdamn.com', '1234567890', '', 'PHP, MySQL, JavaScript', 'abc.com', 'Web developer', 'Newyork', 'USA');

Step2: Include Bootstrap, jQuery Files

We will include required Boostrap, jQuery and CSS files. As we will use jquery.imgareaselect.js plugin to select and crop image, so we will include plugin files. We will also include CSS files.

<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">
<link rel="stylesheet" href="css/style.css">
<script src="js/image_crop_save.js"></script>

Step3: Display User Profile with Picture

In index.php file, we will display user profile details with profile picture by calling getUser() method from class User.php. We will a Bootstrap modal with form to upload image and crop in modal.

<div class="container emp-profile">		
	<div class="row">
		<div class="col-md-4">
			<div class="profile-img">
				<img id="profilePhoto" data-src="images/<?php echo $user['photo']; ?>"  data-holder-rendered="true" src="images/<?php echo $user['photo']; ?>"/>
				<div class="file btn btn-lg btn-primary" id="changeProfilePhoto">						
				 <?php echo $uploadText; ?>		
				</div>					
			</div>
		</div>				
		<div class="col-md-6">
			<div class="profile-head">
				<h5><?php echo $user['name']; ?></h5>
				<h6><?php echo $user['designation']; ?></h6>					
				<ul class="nav nav-tabs" id="myTab" role="tablist">
					<li class="nav-item">
						<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">About</a>
					</li>						
				</ul>
			</div>				
			<div class="col-md-8">
				<div class="tab-content profile-tab" id="myTabContent">
					<div class="show active" id="home" role="tabpanel" aria-labelledby="home-tab">							
						<div class="row">
							<div class="col-md-6">
								<label>Name</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['name']; ?></p>
							</div>
						</div>
						<div class="row">
							<div class="col-md-6">
								<label>Email</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['email']; ?></p>
							</div>
						</div>
						<div class="row">
							<div class="col-md-6">
								<label>Phone</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['phone']; ?></p>
							</div>
						</div>
						<div class="row">
							<div class="col-md-6">
								<label>Profession</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['designation']; ?></p>
							</div>
						</div>
						<div class="row">
							<div class="col-md-6">
								<label>City</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['city']; ?></p>
							</div>
						</div>
						<div class="row">
							<div class="col-md-6">
								<label>Country</label>
							</div>
							<div class="col-md-6">
								<p><?php echo $user['country']; ?></p>
							</div>
						</div>							
					</div>						
				</div>
			</div>			
		</div>			
		<div class="col-md-2">
			<input type="submit" class="profile-edit-btn" name="btnAddMore" value="Edit Profile"/>
		</div>		
	</div>
	<div class="row">
		<div class="col-md-4">
			<div class="profile-work">
				<p>Website</p>
				<a href="<?php echo $user['website']; ?>" rel="nofollow" target="_blank"><?php echo $user['website']; ?></a><br/>					
				<p>Skills</p>					
				<a href=""><?php echo $user['skills']; ?></a><br/>
			</div>
		</div>			
	</div>		
</div>		
<div id="changeProfilePhotoModal" 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 Photo</h3>
			</div>
			<div class="modal-body">
				<form id="cropImage" method="post" enctype="multipart/form-data" action="change_photo.php">
					<strong>Upload Image:</strong> <br><br>
					<input type="file" name="profileImage" id="profileImage" />
					<input type="hidden" name="hdn-profile-id" id="hdn-profile-id" value="<?php echo $user['id']; ?>" />
					<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="imageName" value="" id="imageName" />						
					<div id='previewProfilePhoto'></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="savePhoto" class="btn btn-primary">Crop & Save</button>
			</div>
		</div>
	</div>
</div>

Step4: Upload Image and Crop in Modal

In image_crop_save.js file, we will show image upload modal and handle image upload with image crop.

$('#changeProfilePhoto').on('click', function(e){
	$('#changeProfilePhotoModal').modal({show:true});        
});	
$('#profileImage').on('change', function()	{ 
	$("#previewProfilePhoto").html('');
	$("#previewProfilePhoto").html('Uploading....');
	$("#cropImage").ajaxForm(
	{
	target: '#previewProfilePhoto',
	success:    function() { 
			$('img#photo').imgAreaSelect({
			aspectRatio: '1:1',
			onSelectEnd: getSizes,
		});
		$('#imageName').val($('#photo').attr('file-name'));
		}
	}).submit();

});		

Step5: Handle Image Save

In image_crop_save.js file, we will also handle cropped image save functionality by calling saveCropImage() function with save action to change_photo.php file.

$('#savePhoto').on('click', function(e){
	e.preventDefault();
	params = {
		targetUrl: 'change_photo.php?action=save',
		action: 'save',
		x_axis: $('#hdn-x1-axis').val(),
		y_axis : $('#hdn-y1-axis').val(),
		x2_axis: $('#hdn-x2-axis').val(),
		y2_axis : $('#hdn-y2-axis').val(),
		thumb_width : $('#hdn-thumb-width').val(),
		thumb_height:$('#hdn-thumb-height').val()
	};
	saveCropImage(params);
});   

In function saveCropImage(), will make ajax request to change_photo.php file with image details and get saved image details.

function saveCropImage(params) {
	$.ajax({
		url: params['targetUrl'],
		cache: false,
		dataType: "html",
		data: {
			action: params['action'],
			id: $('#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'],
			imageName :$('#imageName').val()
		},
		type: 'Post',
		success: function (response) {
				$('#changeProfilePhotoModal').modal('hide');
				$(".imgareaselect-border1,.imgareaselect-border2,.imgareaselect-border3,.imgareaselect-border4,.imgareaselect-border2,.imgareaselect-outer").css('display', 'none');
				console.log(response);
				$("#profilePhoto").attr('src', response);
				$("#previewProfilePhoto").html('');
				$("#profileImage").val();
				$("#changeProfilePhoto").text('Change Photo');
		},
		error: function (xhr, ajaxOptions, thrownError) {
			alert('status Code:' + xhr.status + 'Error Message :' + thrownError);
		}
	});
}

Step6: Implement Upload Image and Crop Preview

We will implement method changeProfilePhoto() in class User.php to display upload image preview with crop image.

public function changeProfilePhoto() {
	$post = isset($_POST) ? $_POST: array();
	$maxWidth = "500"; 
	$userId = isset($post['hdn-profile-id']) ? intval($post['hdn-profile-id']) : 0;
	$path = 'images/tmp';
	$validFormats = array("jpg", "png", "gif", "jpeg");
	$picName = $_FILES['profileImage']['name'];
	$size = $_FILES['profileImage']['size'];
	if(strlen($picName)) {
		list($txt, $ext) = explode(".", $picName);
		if(in_array($ext,$validFormats)) {
			if($size<(1024*1024)) {
				$actualImageName = 'avatar' .'_'.$userId .'.'.$ext;
				$filePath = $path .'/'.$actualImageName;
				$tmp = $_FILES['profileImage']['tmp_name'];
				if(move_uploaded_file($tmp, $filePath)) {
					$width = $this->getWidth($filePath);
					$height = $this->getHeight($filePath);						
					if ($width > $maxWidth){
						$scale = $maxWidth/$width;
						$uploaded = $this->resizeImage($filePath,$width,$height,$scale, $ext);
					} else {
						$scale = 1;
						$uploaded = $this->resizeImage($filePath,$width,$height,$scale, $ext);
					}						
					echo "<img id='photo' file-name='".$actualImageName."' 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;
}	

Step7: Save Cropped Image to Server and MySQL Database Table

We will implement method saveProfilePhoto() in class User.php to save cropped profile picture to images directory and into MySQL database table.

public function saveProfilePhoto() {		
	$post = isset($_POST) ? $_POST: array();
	$userId = isset($post['id']) ? intval($post['id']) : 0;		
	$path = 'images/tmp/'.$_POST['imageName'];
	$tmpWidth = 300; 
	$tmpHeight = 300; 
	if(isset($_POST['t']) and $_POST['t'] == "ajax") {
		extract($_POST);		
		$imagePath = 'images/'.$_POST['imageName'];
		$ratio = ($tmpWidth/$w1); 
		$nw = ceil($w1 * $ratio);
		$nh = ceil($h1 * $ratio);
		$nimg = imagecreatetruecolor($nw,$nh);			
		$imgSrc = imagecreatefromjpeg($path);
		imagecopyresampled($nimg,$imgSrc,0,0,$x1,$y1,$nw,$nh,$w1,$h1);
		imagejpeg($nimg,$imagePath,90);		
	}
	$updateQuery = "
		UPDATE ".$this->userTable." 
		SET photo = '".$_POST['imageName']."'
		WHERE id = '$userId'";
	mysqli_query($this->dbConnect, $updateQuery);
	$saveImagePath = $imagePath.'?'.time();
	echo $saveImagePath;
	exit(0);    
}  

You may also like:

You can view the live demo from the Demo link and can download the script from the Download link below.
Demo Download

One thought on “Image Upload and Crop in Modal with jQuery, PHP & MySQL

Comments are closed.