Image Crop Functionality In Model Box Using PHP

Image uploading and cropping is very common functionality for any web application.You can upload and crop image on same page or in modal box.In this PHP article i am sharing Demo and Source Code to upload and cropped image using PHP and jQuery.There are a lot of image cropping jquery plugin available,In previous article i have list down Best Jquery Image Crop plugins.

Often we are given image/picture change functionality to end user,So user can upload and crop image.This is awesome user experience to give image change and cropping in modal box.I am using bootstrap Modal box to show upload image option.

There are following jQuery plugin and CSS Library Used

  • jQuery Library : Base library to support other jquery plugin
  • Boostrap 3 : Used to create awesome HTML layout
  • Imgareaselect : Use to define crop co-ordinate and cropp image,You can download from here.
  • Ajax form : Use to submit form Ajax manner,You can download from here

In This article i am using Imgareaselect plugin to crop image and PHP for resizing image with save cropped image.

There are Following files will participate in this image crop tutorial

  • index.php : This file is responsible to create HTML layout and show cropped image.
  • profile.php : This file is responsible to all server side functionality like image cropping and saving
  • dist : This is a folder, which is use to keep all library file.

Also Checkout other tutorial of image crop,

Image Upload and Cropping with PHP and jQuery

Step 1: First we will include all necessary jquery plugin and library files.We will keep all below files in head section of index.php file.

Select Code
1
2
3
4
5
6
7
<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/jquery.imgareaselect.js" type="text/javascript"></script>
<script src="dist/jquery.form.js"></script>
<link rel="stylesheet" href="dist/imgareaselect.css">

Step 2:We will Create div to show image and option to change image.

Select Code
1
2
3
4
<div>
    <img class="img-circle" id="avatar-edit-img" height="128" data-src="default.jpg"  data-holder-rendered="true" style="width: 140px; height: 140px;" src="default.jpg"/>
    <a type="button" class="btn btn-primary" id="change-pic">Change Image</a>
</div>

Here i am showing default.jpg image file for as a default image.

Step 3: Now we will create model box to upload and crop image.

Select Code
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
<!--model box -->
<div id="changePic" 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">&times;</button>
               <h3>Change Profile Picture</h3>
            </div>
            <div class="modal-body">
                <form id="cropimage" method="post" enctype="multipart/form-data" action="profile.php">
                    Upload your image <input type="file" name="photoimg" id="photoimg" />
                    <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-avatar-profile'>
                </div>
                <div id="thumbs" style="padding:5px; width:600"></div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" id="btn-crop" class="btn btn-primary">Crop & Save</button>
            </div>
        </div>
    </div>
</div>

Step 4: Now will write some jquery code to show the model box when we will click change pic button.

Select Code
1
2
3
4
5
6
jQuery('#change-pic').live('click', function(e){
        e.preventDefault();
        
        jQuery('#changePic').show();
        
    });

Now you can show image upload bootstrap modal box on click of Change Image.

Step 5: Now we will use jQuery Ajax form plugin for form submitting and show the image for crop process on bootstrap modal box.

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jQuery('#photoimg').live('change', function()   
{ 
jQuery("#preview-avatar-profile").html('');
jQuery("#preview-avatar-profile").html('Uploading....');
jQuery("#cropimage").ajaxForm(
{
target: '#preview-avatar-profile',
success:    function() { 
        jQuery('img#photo').imgAreaSelect({
        aspectRatio: '1:1',
        onSelectEnd: getSizes,
    });
    }
}).submit();
});

You can get image all parameters on 'success' call back function.

Step 6: Now we will cropped image and call save Ajax method to save image on hard disk storage.

Select Code
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//fucntion for get image cropped co-ordinate
function getSizes(img, obj)
    {
        var x_axis = obj.x1;
        var x2_axis = obj.x2;
        var y_axis = obj.y1;
        var y2_axis = obj.y2;
        var thumb_width = obj.width;
        var thumb_height = obj.height;
        if(thumb_width > 0)
            {

                jQuery('#hdn-x1-axis').val(x_axis);
                jQuery('#hdn-y1-axis').val(y_axis);
                jQuery('#hdn-x2-axis').val(x2_axis);
                jQuery('#hdn-y2-axis').val(y2_axis);
                jQuery('#hdn-thumb-width').val(thumb_width);
                jQuery('#hdn-thumb-height').val(thumb_height);
                
            }
        else
            alert("Please select portion..!");
    }
    //call on crop iamge button
jQuery('#btn-crop').live('click', function(e){
    e.preventDefault();
    params = {
            targetUrl: 'profiles/saveAvatarTmp/',
            action: 'profiles_controller_saveAvatarTmp',
            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);
    });
    //make ajax request to PHP for save image
function saveCropImage(params) {
    jQuery.ajax({
        url: siteurl + 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']
        },
        type: 'Post',
       // async:false,
        success: function (response) {
                jQuery("#changePic").hide();
                jQuery(".imgareaselect-border1,.imgareaselect-border2,.imgareaselect-border3,.imgareaselect-border4,.imgareaselect-border2,.imgareaselect-outer").css('display', 'none');
                
                jQuery("#avatar-edit-img").attr('src', response);
                jQuery("#preview-avatar-profile").html('');
                jQuery("#photoimg").val();
                AlertManager.showNotification('Image cropped!', 'Click Save Profile button to save image.', 'success');
                
                
        },
        error: function (xhr, ajaxOptions, thrownError) {
            alert('status Code:' + xhr.status + 'Error Message :' + thrownError);
        }
    });
    }

Step 7: We will define controller/action method in profile.php.

Select Code
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*********************************************************************
     Purpose            : update image.
     Parameters         : null
     Returns            : integer
     ***********************************************************************/
    public function changeAvatar() {
        global $current_user;
        $loggedInId = $current_user->ID;
        $post = isset($_POST) ? $_POST: array();
        $max_width = "500"; 
        $userId = isset($post['hdn-profile-id']) ? intval($post['hdn-profile-id']) : 0;
        $path = get_theme_root(). '\images\uploads\tmp';

        $valid_formats = array("jpg", "png", "gif", "bmp","jpeg");
        $name = $_FILES['photoimg']['name'];
        $size = $_FILES['photoimg']['size'];
        if(strlen($name))
        {
        list($txt, $ext) = explode(".", $name);
        if(in_array($ext,$valid_formats))
        {
        if($size<(1024*1024)) // Image size max 1 MB
        {
        $actual_image_name = 'avatar' .'_'.$userId .'.'.$ext;
        $filePath = $path .'/'.$actual_image_name;
        $tmp = $_FILES['photoimg']['tmp_name'];
        
        if(move_uploaded_file($tmp, $filePath))
        {
        $width = $this->getWidth($filePath);
            $height = $this->getHeight($filePath);
            //Scale the image if it is greater than the width set above
            if ($width > $max_width){
                $scale = $max_width/$width;
                $uploaded = $this->resizeImage($filePath,$width,$height,$scale);
            }else{
                $scale = 1;
                $uploaded = $this->resizeImage($filePath,$width,$height,$scale);
            }
        $res = $this->Profile->saveAvatar(array(
                        'userId' => isset($userId) ? intval($userId) : 0,
                                                'avatar' => isset($actual_image_name) ? $actual_image_name : '',
                        ));
                        
        //mysql_query("UPDATE users SET profile_image='$actual_image_name' WHERE uid='$session_id'");
        echo "<img id='photo' class='' src='".getCustomAvatar($userId, true).'?'.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;
        
        
    }
    /*********************************************************************
     Purpose            : update image.
     Parameters         : null
     Returns            : integer
     ***********************************************************************/
    public function saveAvatarTmp() {
        global $current_user;
        $loggedInId = $current_user->ID;
        $post = isset($_POST) ? $_POST: array();
        $userId = isset($post['id']) ? intval($post['id']) : 0;
        $path = get_theme_root(). '\\images\uploads\tmp';
        $t_width = 300; // Maximum thumbnail width
        $t_height = 300;    // Maximum thumbnail height

    if(isset($_POST['t']) and $_POST['t'] == "ajax")
    {
        extract($_POST);
        
        $img = get_user_meta($userId, 'user_avatar', true);
        $imagePath = $path.'/'.$img;
        $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 getCustomAvatar($userId, true);
    exit(0);    
    }
    
    /*********************************************************************
     Purpose            : resize image.
     Parameters         : null
     Returns            : image
     ***********************************************************************/
    function resizeImage($image,$width,$height,$scale) {
    $newImageWidth = ceil($width * $scale);
    $newImageHeight = ceil($height * $scale);
    $newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
    $source = imagecreatefromjpeg($image);
    imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height);
    imagejpeg($newImage,$image,90);
    chmod($image, 0777);
    return $image;
}
/*********************************************************************
     Purpose            : get image height.
     Parameters         : null
     Returns            : height
     ***********************************************************************/
function getHeight($image) {
    $sizes = getimagesize($image);
    $height = $sizes[1];
    return $height;
}
/*********************************************************************
     Purpose            : get image width.
     Parameters         : null
     Returns            : width
     ***********************************************************************/
function getWidth($image) {
    $sizes = getimagesize($image);
    $width = $sizes[0];
    return $width;
}

Step 8: Model method to save image path into database.

Select Code
1
2
3
4
5
6
7
8
9
/*********************************************************************
     Purpose            : save avatar.
     Parameters         : $options 
     Returns            : true/false
     ***********************************************************************/
    function saveAvatar($options){
        //update sql

    }

Image Crop Result Using PHP and AJAX

Demo & Download Source Code Of Image Cropping with PHP and AJAX

  • sulung

    not working in safari. Its useless….

    • I have verified,its working fine on safari 5.1.7

      • Midhun MM

        can i get the code.zip

        • U can dwnld zip file from dwnld link

  • HJ Tsai

    it don’t support .bmp .gif .png , when I upload these picture, it show a black picture. How can I solve this problem?

    • You need to change imagecreatetruecolor method based on image type.

  • Paulo Serrano

    can anybody put a link with the complete source code working?

    • you can download from downlod link

  • Midhun MM

    i need the complete complete code.zip anybody help me

    • U can dwnld code frm dwnld link

  • as per error, method( get_user_meta()) is not in ur class or file.

    • Rohan Patil

      i am implementing your code in my codeigniter project, please suggest how to add get_user_meta() in my class or file of codeigniter project.