HTML5 Image uploader with Jcrop
Step 1. HTML
Our first step is html markup. first, we have to put styles and scripts in the HEAD section:1 | <!-- add styles --> |
2 | <link href="css/main.css" rel="stylesheet" type="text/css" /> |
3 | <link href="css/jquery.Jcrop.min.css" rel="stylesheet" type="text/css" /> |
4 |
5 | <!-- add scripts --> |
6 | <script src="js/jquery.min.js"></script> |
7 | <script src="js/jquery.Jcrop.min.js"></script> |
8 | <script src="js/script.js"></script> |
01 | <div class="bbody"> |
02 |
03 | <!-- upload form --> |
04 | <form id="upload_form" enctype="multipart/form-data" method="post" action="upload.php" onsubmit="return checkForm()"> |
05 | <!-- hidden crop params --> |
06 | <input type="hidden" id="x1" name="x1" /> |
07 | <input type="hidden" id="y1" name="y1" /> |
08 | <input type="hidden" id="x2" name="x2" /> |
09 | <input type="hidden" id="y2" name="y2" /> |
10 |
11 | <h2>Step1: Please select image file</h2> |
12 | <div><input type="file" name="image_file" id="image_file" onchange="fileSelectHandler()" /></div> |
13 |
14 | <div class="error"></div> |
15 |
16 | <div class="step2"> |
17 | <h2>Step2: Please select a crop region</h2> |
18 | <img id="preview" /> |
19 |
20 | <div class="info"> |
21 | <label>File size</label> <input type="text" id="filesize" name="filesize" /> |
22 | <label>Type</label> <input type="text" id="filetype" name="filetype" /> |
23 | <label>Image dimension</label> <input type="text" id="filedim" name="filedim" /> |
24 | <label>W</label> <input type="text" id="w" name="w" /> |
25 | <label>H</label> <input type="text" id="h" name="h" /> |
26 | </div> |
27 |
28 | <input type="submit" value="Upload" /> |
29 | </div> |
30 | </form> |
31 | </div> |
Step 2. CSS
Now, I would like to give you CSS styles to stylize our form:css/main.css
01 | .bheader { |
02 | background-color: #DDDDDD; |
03 | border-radius: 10px 10px 0 0; |
04 | padding: 10px 0; |
05 | text-align: center; |
06 | } |
07 | .bbody { |
08 | color: #000; |
09 | overflow: hidden; |
10 | padding-bottom: 20px; |
11 | text-align: center; |
12 |
13 | background: -moz-linear-gradient(#ffffff, #f2f2f2); |
14 | background: -ms-linear-gradient(#ffffff, #f2f2f2); |
15 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2)); |
16 | background: -webkit-linear-gradient(#ffffff, #f2f2f2); |
17 | background: -o-linear-gradient(#ffffff, #f2f2f2); |
18 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2'); |
19 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2')"; |
20 | background: linear-gradient(#ffffff, #f2f2f2); |
21 | } |
22 | .bbody h2, .info, .error { |
23 | margin: 10px 0; |
24 | } |
25 | .step2, .error { |
26 | display: none; |
27 | } |
28 | .error { |
29 | font-size: 18px; |
30 | font-weight: bold; |
31 | color: red; |
32 | } |
33 | .info { |
34 | font-size: 14px; |
35 | } |
36 | label { |
37 | margin: 0 5px; |
38 | } |
39 | input { |
40 | border: 1px solid #CCCCCC; |
41 | border-radius: 10px; |
42 | padding: 4px 8px; |
43 | text-align: center; |
44 | width: 70px; |
45 | } |
46 | .jcrop-holder { |
47 | display: inline-block; |
48 | } |
49 | input[type=submit] { |
50 | background: #e3e3e3; |
51 | border: 1px solid #bbb; |
52 | border-radius: 3px; |
53 | -webkit-box-shadow: inset 0 0 1px 1px #f6f6f6; |
54 | box-shadow: inset 0 0 1px 1px #f6f6f6; |
55 | color: #333; |
56 | font: bold 12px/1 "helvetica neue", helvetica, arial, sans-serif; |
57 | padding: 8px 0 9px; |
58 | text-align: center; |
59 | text-shadow: 0 1px 0 #fff; |
60 | width: 150px; |
61 | } |
62 | input[type=submit]:hover { |
63 | background: #d9d9d9; |
64 | -webkit-box-shadow: inset 0 0 1px 1px #eaeaea; |
65 | box-shadow: inset 0 0 1px 1px #eaeaea; |
66 | color: #222; |
67 | cursor: pointer; |
68 | } |
69 | input[type=submit]:active { |
70 | background: #d0d0d0; |
71 | -webkit-box-shadow: inset 0 0 1px 1px #e3e3e3; |
72 | box-shadow: inset 0 0 1px 1px #e3e3e3; |
73 | color: #000; |
74 | } |
Step 3. JS
Our next step – is javascript. Please review the result code (my comments are below the code):001 | // convert bytes into friendly format |
002 | function bytesToSize(bytes) { |
003 | var sizes = ['Bytes', 'KB', 'MB']; |
004 | if (bytes == 0) return 'n/a'; |
005 | var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); |
006 | return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]; |
007 | }; |
008 |
009 | // check for selected crop region |
010 | function checkForm() { |
011 | if (parseInt($('#w').val())) return true; |
012 | $('.error').html('Please select a crop region and then press Upload').show(); |
013 | return false; |
014 | }; |
015 |
016 | // update info by cropping (onChange and onSelect events handler) |
017 | function updateInfo(e) { |
018 | $('#x1').val(e.x); |
019 | $('#y1').val(e.y); |
020 | $('#x2').val(e.x2); |
021 | $('#y2').val(e.y2); |
022 | $('#w').val(e.w); |
023 | $('#h').val(e.h); |
024 | }; |
025 |
026 | // clear info by cropping (onRelease event handler) |
027 | function clearInfo() { |
028 | $('.info #w').val(''); |
029 | $('.info #h').val(''); |
030 | }; |
031 |
032 | function fileSelectHandler() { |
033 |
034 | // get selected file |
035 | var oFile = $('#image_file')[0].files[0]; |
036 |
037 | // hide all errors |
038 | $('.error').hide(); |
039 |
040 | // check for image type (jpg and png are allowed) |
041 | var rFilter = /^(image\/jpeg|image\/png)$/i; |
042 | if (! rFilter.test(oFile.type)) { |
043 | $('.error').html('Please select a valid image file (jpg and png are allowed)').show(); |
044 | return; |
045 | } |
046 |
047 | // check for file size |
048 | if (oFile.size > 250 * 1024) { |
049 | $('.error').html('You have selected too big file, please select a one smaller image file').show(); |
050 | return; |
051 | } |
052 |
053 | // preview element |
054 | var oImage = document.getElementById('preview'); |
055 |
056 | // prepare HTML5 FileReader |
057 | var oReader = new FileReader(); |
058 | oReader.onload = function(e) { |
059 |
060 | // e.target.result contains the DataURL which we can use as a source of the image |
061 | oImage.src = e.target.result; |
062 | oImage.onload = function () { // onload event handler |
063 |
064 | // display step 2 |
065 | $('.step2').fadeIn(500); |
066 |
067 | // display some basic image info |
068 | var sResultFileSize = bytesToSize(oFile.size); |
069 | $('#filesize').val(sResultFileSize); |
070 | $('#filetype').val(oFile.type); |
071 | $('#filedim').val(oImage.naturalWidth + ' x ' + oImage.naturalHeight); |
072 |
073 | // Create variables (in this scope) to hold the Jcrop API and image size |
074 | var jcrop_api, boundx, boundy; |
075 |
076 | // destroy Jcrop if it is existed |
077 | if (typeof jcrop_api != 'undefined') |
078 | jcrop_api.destroy(); |
079 |
080 | // initialize Jcrop |
081 | $('#preview').Jcrop({ |
082 | minSize: [32, 32], // min crop size |
083 | aspectRatio : 1, // keep aspect ratio 1:1 |
084 | bgFade: true, // use fade effect |
085 | bgOpacity: .3, // fade opacity |
086 | onChange: updateInfo, |
087 | onSelect: updateInfo, |
088 | onRelease: clearInfo |
089 | }, function(){ |
090 |
091 | // use the Jcrop API to get the real image size |
092 | var bounds = this.getBounds(); |
093 | boundx = bounds[0]; |
094 | boundy = bounds[1]; |
095 |
096 | // Store the Jcrop API in the jcrop_api variable |
097 | jcrop_api = this; |
098 | }); |
099 | }; |
100 | }; |
101 |
102 | // read selected file as DataURL |
103 | oReader.readAsDataURL(oFile); |
104 | } |
Step 4. PHP
In this step – we have to accept (and upload) our result photo. I prepared next useful PHP function for you:upload.php
01 | function uploadImageFile() { // Note: GD library is required for this function |
02 |
03 | if ($_SERVER['REQUEST_METHOD'] == 'POST') { |
04 | $iWidth = $iHeight = 200; // desired image result dimensions |
05 | $iJpgQuality = 90; |
06 |
07 | if ($_FILES) { |
08 |
09 | // if no errors and size less than 250kb |
10 | if (! $_FILES['image_file']['error'] && $_FILES['image_file']['size'] < 250 * 1024) { |
11 | if (is_uploaded_file($_FILES['image_file']['tmp_name'])) { |
12 |
13 | // new unique filename |
14 | $sTempFileName = 'cache/' . md5(time().rand()); |
15 |
16 | // move uploaded file into cache folder |
17 | move_uploaded_file($_FILES['image_file']['tmp_name'], $sTempFileName); |
18 |
19 | // change file permission to 644 |
20 | @chmod($sTempFileName, 0644); |
21 |
22 | if (file_exists($sTempFileName) && filesize($sTempFileName) > 0) { |
23 | $aSize = getimagesize($sTempFileName); // try to obtain image info |
24 | if (!$aSize) { |
25 | @unlink($sTempFileName); |
26 | return; |
27 | } |
28 |
29 | // check for image type |
30 | switch($aSize[2]) { |
31 | case IMAGETYPE_JPEG: |
32 | $sExt = '.jpg'; |
33 |
34 | // create a new image from file |
35 | $vImg = @imagecreatefromjpeg($sTempFileName); |
36 | break; |
37 | case IMAGETYPE_PNG: |
38 | $sExt = '.png'; |
39 |
40 | // create a new image from file |
41 | $vImg = @imagecreatefrompng($sTempFileName); |
42 | break; |
43 | default: |
44 | @unlink($sTempFileName); |
45 | return; |
46 | } |
47 |
48 | // create a new true color image |
49 | $vDstImg = @imagecreatetruecolor( $iWidth, $iHeight ); |
50 |
51 | // copy and resize part of an image with resampling |
52 | imagecopyresampled($vDstImg, $vImg, 0, 0, (int)$_POST['x1'], (int)$_POST['y1'], $iWidth, $iHeight, (int)$_POST['w'], (int)$_POST['h']); |
53 |
54 | // define a result image filename |
55 | $sResultFileName = $sTempFileName . $sExt; |
56 |
57 | // output image to file |
58 | imagejpeg($vDstImg, $sResultFileName, $iJpgQuality); |
59 | @unlink($sTempFileName); |
60 |
61 | return $sResultFileName; |
62 | } |
63 | } |
64 | } |
65 | } |
66 | } |
67 | } |
68 |
69 | $sImage = uploadImageFile(); |
70 | echo '<img src="'.$sImage.'" />'; |
For more details visit: http://www.script-tutorials.com/html5-image-uploader-with-jcrop/
ImagerJs is a platform-independent, web-based JavaScript
ReplyDeleteImage Uploader that is very easy and fun to use. A JavaScript library
for uploading images using drag & drop. Crop, rotate, resize,
or shrink your image before uploading https://www.imagerjs.com visit us you wont
be sorry! Have a nice day.