js插件---图片裁剪cropImgBox(适合练习编写插件之用)
js插件---图片裁剪cropImgBox(适合练习编写插件之用)
一、总结
一句话总结:无论是灰度还是高对比度的图片,都是先处理canvas的像素,使其变成灰度或者高对比度,然后再用canvas.toDataURL('image/png');输出出来
1、img获取图片来源的两种方式是什么?
a、src直接接图片地址
b、src接图片base64格式数据
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMYAAADGCAYAAACJmedZ42w6ICXmpjvKovOPKYwGVmCsB8xsp+rpF01eCriAy7eYqpTYtCXF8P43revYrfaxf8CrXnKcdq0FW0AAAAASUVORK5CYII=" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;">
2、图片裁剪好的canvas是怎么输出图片数据的?
无论是灰度还是高对比度的图片,都是先处理canvas的像素,使其变成灰度或者高对比度,然后再用canvas.toDataURL('image/png');输出出来
1 var arr_result = [], arr = obj.clipType.split('|'); 2 3 var context = canvas.getContext("2d"); 4 context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh); 5 var imageData = canvas.toDataURL('image/png'); 6 arr_result.push(imageData); 7 8 var _param = 0, key = ''; 9 if (arr.length > 1 && arr[1] == '1') { 10 context.clearRect(0, 0, 10000, 10000); 11 key = 'gray'; 12 var imgToGray = imgTrans(canvas, imageData, key, function () { 13 _param += 1; 14 imageData = canvas.toDataURL('image/png'); 15 arr_result.push(imageData); 16 }); 17 } 18 if (arr.length > 2 && arr[2] == '1') { 19 context.clearRect(0, 0, 10000, 10000); 20 key = 'bright'; 21 var imgToGray = imgTrans(canvas, imageData, key, function () { 22 _param += 1; 23 imageData = canvas.toDataURL('image/png'); 24 arr_result.push(imageData); 25 }); 26 }
二、图片裁剪cropImgBox(适合练习)
百度盘下载地址:
链接:https://pan.baidu.com/s/1_gSUaEX23_b73tqHV0FwFQ 密码:1124
1、截图
2、代码
index.html
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 6 <meta name="description" content="图片裁剪并设置效果插件,暂时只设置了几种效果,后面会加更多效果,敬请期待..."> 7 <meta name="keywords" content="图片裁剪,crop,Image"> 8 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 9 <title>Amaze UI CorpImgBox</title> 10 <meta name="renderer" content="webkit"> 11 <meta http-equiv="Cache-Control" content="no-siteapp" /> 12 <link href="amazeui.css" rel="stylesheet" /> 13 <link href="amazeui.cropimgbox.min.css" rel="stylesheet" /> 14 <script type="text/javascript" src="jquery.min.js"></script> 15 <script src="cropimgbox.js"></script> 16 <script type="text/javascript"> 17 (function ($) { 18 $(function () { 19 var options = 20 { 21 thumbBox: '.cropimgbox-thumbBox', 22 spinner: '.cropimgbox-spinner', 23 imgSrc: '' 24 } 25 var cropper = $('.cropimgbox-imageBox').cropimgbox(options); 26 var img = ""; 27 28 $(document).on('change', '#upload-file', function () { 29 var reader = new FileReader(); 30 reader.onload = function (e) { 31 options.imgSrc = e.target.result; 32 cropper = $('.cropimgbox-imageBox').cropimgbox(options); 33 getImg(); 34 } 35 reader.readAsDataURL(this.files[0]); 36 this.files.length = 0; 37 }) 38 .on('mouseup','.cropimgbox-imageBox', function () { 39 getImg(); 40 }) 41 .on('click','#btnZoomIn', function () { 42 cropper.zoomIn(); 43 cropper.getBlob 44 }) 45 .on('click','#btnZoomOut', function () { 46 cropper.zoomOut(); 47 }) 48 49 function getImg() { 50 cropper.getDataURL(function (imgs) { 51 $('.cropimgbox-cropped').html(''); 52 $('.cropimgbox-cropped').append('<img src="' + imgs[0] + '" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;"><p>原图</p>'); 53 $('.cropimgbox-cropped').append('<img src="' + imgs[1] + '" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;"><p>灰化</p>'); 54 $('.cropimgbox-cropped').append('<img src="' + imgs[2] + '" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;"><p>高亮高对比</p>'); 55 }); 56 } 57 }) 58 })(jQuery); 59 </script> 60 </head> 61 <body> 62 <div class="cropimgbox"> 63 <div class="cropimgbox-imageBox"> 64 <div class="cropimgbox-thumbBox"></div> 65 <div class="cropimgbox-spinner" style="display: none"></div> 66 </div> 67 68 <div class="cropimgbox-action"> 69 <div class="am-btn-group am-btn-group-xs"> 70 <button type="button" id="btnZoomIn" class="am-btn am-btn-default am-btn-xs am-text-secondary"><span class="am-icon-plus"></span> 放大</button> 71 <button type="button" id="btnZoomOut" class="am-btn am-btn-default am-btn-xs am-text-secondary"><span class="am-icon-minus"></span> 缩小</button> 72 </div> 73 <div class="cropimgbox-contentarea"> 74 <a href="javascript:void(0)" class="cropimgbox-upload-img"> 75 <label for="cropimgbox-upload-file">选择图片...</label> 76 </a> 77 <input type="file" class="" name="cropimgbox-upload-file" id="upload-file" /> 78 </div> 79 </div> 80 <div class="cropimgbox-cropped"></div> 81 </div> 82 </body> 83 </html>
cropimgbox.js
1 /* 2 cropimgbox.js 3 ------------------------------------------------------------ 4 | Note:暂时提供了除原图外的2种效果(灰化、高亮高对比),可通过修改 5 | cvtColor、brightnessContrast函数在此基础上渐变多种效果。 6 ------------------------------------------------------------- 7 *********注:基于cropbox修改 https://github.com/hongkhanh/cropbox ************* 8 Version: 1.0.0 9 Author: lazyperson 10 QQ: 564981089 11 Website: https://github.com/lazyperson 12 */ 13 (function (factory) { 14 'use strict'; 15 if (typeof define === 'function' && define.amd) { 16 define(['jquery'], factory); 17 } else if (typeof exports !== 'undefined') { 18 module.exports = factory(require('jquery')); 19 } else { 20 factory(jQuery); 21 } 22 }(function ($) { 23 "use strict"; 24 var cropimgbox = function (options, el) { 25 options.expandRatio = options.expandRatio || 1.1; 26 options.narrowRatio = options.narrowRatio || 0.9; 27 var el = el || $(options.imageBox), 28 obj = 29 { 30 state: {}, 31 ratio: 1, 32 //clipType:裁剪后得到的效果图类型,1显示,0不显示。表示类型依次为 原图(必须有)|灰白图|高亮对比图 33 clipType: '1|1|1', 34 options: options, 35 imageBox: el, 36 thumbBox: el.find(options.thumbBox), 37 spinner: el.find(options.spinner), 38 image: new Image(), 39 getDataURL: function (callfun) { 40 var width = this.thumbBox.width(), 41 height = this.thumbBox.height(), 42 canvas = document.createElement("canvas"), 43 dim = el.css('background-position').split(' '), 44 size = el.css('background-size').split(' '), 45 dx = parseInt(dim[0]) - el.width() / 2 + width / 2, 46 dy = parseInt(dim[1]) - el.height() / 2 + height / 2, 47 dw = parseInt(size[0]), 48 dh = parseInt(size[1]), 49 sh = parseInt(this.image.height), 50 sw = parseInt(this.image.width); 51 52 canvas.width = width; 53 canvas.height = height; 54 55 var arr_result = [], arr = obj.clipType.split('|'); 56 57 var context = canvas.getContext("2d"); 58 context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh); 59 var imageData = canvas.toDataURL('image/png'); 60 arr_result.push(imageData); 61 62 var _param = 0, key = ''; 63 if (arr.length > 1 && arr[1] == '1') { 64 context.clearRect(0, 0, 10000, 10000); 65 key = 'gray'; 66 var imgToGray = imgTrans(canvas, imageData, key, function () { 67 _param += 1; 68 imageData = canvas.toDataURL('image/png'); 69 arr_result.push(imageData); 70 }); 71 } 72 if (arr.length > 2 && arr[2] == '1') { 73 context.clearRect(0, 0, 10000, 10000); 74 key = 'bright'; 75 var imgToGray = imgTrans(canvas, imageData, key, function () { 76 _param += 1; 77 imageData = canvas.toDataURL('image/png'); 78 arr_result.push(imageData); 79 }); 80 } 81 82 83 function imgTrans(iCanvas, url, key, callback) { 84 var _th = this; 85 var canvas = iCanvas, 86 iCtx = canvas.getContext("2d"), 87 url = url; 88 89 var imread = function (_image) { 90 var width = _image.width, 91 height = _image.height; 92 iResize(width, height); 93 iCtx.drawImage(_image, 0, 0); 94 var imageData = iCtx.getImageData(0, 0, width, height), 95 tempMat = new Mat(height, width, imageData.data); 96 imageData = null; 97 iCtx.clearRect(0, 0, width, height); 98 return tempMat; 99 }, 100 iResize = function (_width, _height) { 101 canvas.width = _width; 102 canvas.height = _height; 103 }, 104 RGBA2ImageData = function (_imgMat) { 105 var width = _imgMat.col, 106 height = _imgMat.row, 107 imageData = iCtx.createImageData(width, height); 108 imageData.data.set(_imgMat.data); 109 return imageData; 110 }, 111 render = function (key, callback) { 112 var img = new Image(); 113 img.onload = function () { 114 var myMat = imread(img); 115 if (key == 'gray') { 116 var newImage = cvtColor(myMat, "CV_RGBA"); 117 var newIamgeData = RGBA2ImageData(newImage); 118 iCtx.putImageData(newIamgeData, 0, 0); 119 } 120 if (key == 'bright') { 121 var newImage = brightnessContrast(myMat, 50, 50); 122 var newIamgeData = RGBA2ImageData(newImage); 123 iCtx.putImageData(newIamgeData, 0, 0); 124 } 125 callback(); 126 }; 127 img.src = url; 128 }; 129 130 render(key, callback); 131 } 132 133 134 function Mat(_row, _col, _data, _buffer) { 135 this.row = _row || 0; 136 this.col = _col || 0; 137 this.channel = 4; 138 this.buffer = _buffer || new ArrayBuffer(_row * _col * 4); 139 this.data = new Uint8ClampedArray(this.buffer); 140 _data && this.data.set(_data); 141 this.bytes = 1; 142 this.type = "CV_RGBA"; 143 } 144 145 function cvtColor(_src, _code) { 146 var row = _src.row, 147 col = _src.col; 148 if (_src.type && _code === "CV_RGBA") { 149 var dst = new Mat(row, col), 150 data = dst.data, 151 data2 = _src.data; 152 var pix1, pix2, pix = _src.row * _src.col * 4; 153 while (pix) { 154 data[pix -= 4] = data[pix1 = pix + 1] = data[pix2 = pix + 2] = (data2[pix] * 299 + data2[pix1] * 587 + data2[pix2] * 114) / 1000; 155 data[pix + 3] = data2[pix + 3]; 156 } 157 } else if (_src.type && _code === "CV_RGBA2GRAY") { 158 var dst = new Mat(row, col), 159 data = dst.data, 160 data2 = _src.data; 161 var pix = row * col; 162 while (pix) { 163 data[--pix] = (data2[4 * pix] * 9798 + data2[4 * pix + 1] * 19235 + data2[4 * pix + 2] * 3736) >> 15; 164 } 165 } 166 return dst; 167 } 168 169 var brightnessContrast = function (__src, __brightness, __contrast) { 170 if (__src.type === "CV_RGBA") { 171 var sData = __src.data, 172 width = __src.col, 173 height = __src.row, 174 dst = new Mat(height, width); 175 var dData = dst.data, 176 brightness = Math.max(-255, Math.min(255, __brightness || 0)), 177 contrast = Math.max(-255, Math.min(255, __contrast || 0)); 178 179 var gray = cvtColor(__src, "CV_RGBA2GRAY", 2), 180 allValue = 0, 181 gData = gray.data; 182 var y, x, c; 183 184 for (y = height; y--;) { 185 for (x = width; x--;) { 186 allValue += gData[y * width + x]; 187 } 188 } 189 190 var r, g, b, offset, gAverage = (allValue / (height * width)) | 0; 191 192 for (y = height; y--;) { 193 for (x = width; x--;) { 194 offset = (y * width + x) * 4; 195 dData[offset] = sData[offset] + brightness; 196 dData[offset + 1] = sData[offset + 1] + brightness; 197 dData[offset + 2] = sData[offset + 2] + brightness; 198 199 if (contrast >= 0) { 200 for (c = 3; c--;) { 201 if (dData[offset + c] >= gAverage) { 202 dData[offset + c] = dData[offset + c] + (255 - gAverage) * contrast / 255; 203 } else { 204 dData[offset + c] = dData[offset + c] - (gAverage * contrast / 255); 205 } 206 } 207 } else { 208 dData[offset] = dData[offset] + (dData[offset] - gAverage) * contrast / 255; 209 dData[offset + 1] = dData[offset + 1] + (dData[offset + 1] - gAverage) * contrast / 255; 210 dData[offset + 2] = dData[offset + 2] + (dData[offset + 2] - gAverage) * contrast / 255; 211 } 212 dData[offset + 3] = 255; 213 } 214 } 215 } 216 return dst; 217 }; 218 219 var num = arr.length > 1 && arr[1] == '1' || arr.length > 2 && arr[2] == '1' ? (arr.length > 1 && arr[1] == '1' && arr.length > 2 && arr[2] == '1' ? 2 : 1) : 0; 220 if (arr.length > 1 && arr[1] == '1' || arr.length > 2 && arr[2] == '1') { 221 if (_param > 0) 222 return arr_result; 223 else { 224 (function func() { 225 if (_param >= num) { 226 _param = 0; 227 callfun(arr_result); 228 } 229 else 230 setTimeout(func, 500); 231 })(); 232 } 233 } 234 }, 235 getBlob: function (i) { 236 var imageData = this.getDataURL()[i]; 237 var b64 = imageData.replace('data:image/png;base64,', ''); 238 var binary = atob(b64); 239 var array = []; 240 for (var i = 0; i < binary.length; i++) { 241 array.push(binary.charCodeAt(i)); 242 } 243 return new Blob([new Uint8Array(array)], { type: 'image/png' }); 244 }, 245 zoomIn: function () { 246 this.ratio *= options.expandRatio; 247 setBackground(); 248 }, 249 zoomOut: function () { 250 this.ratio *= options.narrowRatio; 251 setBackground(); 252 } 253 }, 254 setBackground = function () { 255 var w = parseInt(obj.image.width) * obj.ratio; 256 var h = parseInt(obj.image.height) * obj.ratio; 257 258 var pw = (el.width() - w) / 2; 259 var ph = (el.height() - h) / 2; 260 el.css({ 261 'background-image': 'url(' + obj.image.src + ')', 262 'background-size': w + 'px ' + h + 'px', 263 'background-position': pw + 'px ' + ph + 'px', 264 'background-repeat': 'no-repeat' 265 }); 266 }, 267 imgMouseDown = function (e) { 268 e.stopImmediatePropagation(); 269 270 obj.state.dragable = true; 271 obj.state.mouseX = e.clientX; 272 obj.state.mouseY = e.clientY; 273 }, 274 imgMouseMove = function (e) { 275 e.stopImmediatePropagation(); 276 277 if (obj.state.dragable) { 278 var x = e.clientX - obj.state.mouseX; 279 var y = e.clientY - obj.state.mouseY; 280 281 var bg = el.css('background-position').split(' '); 282 283 var bgX = x + parseInt(bg[0]); 284 var bgY = y + parseInt(bg[1]); 285 286 el.css('background-position', bgX + 'px ' + bgY + 'px'); 287 288 obj.state.mouseX = e.clientX; 289 obj.state.mouseY = e.clientY; 290 } 291 }, 292 imgMouseUp = function (e) { 293 e.stopImmediatePropagation(); 294 obj.state.dragable = false; 295 }, 296 zoomImage = function (e) { 297 e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0 ? obj.ratio *= options.expandRatio : obj.ratio *=options.narrowRatio; 298 setBackground(); 299 } 300 301 obj.spinner.show(); 302 303 obj.image.onload = function () { 304 obj.spinner.hide(); 305 setBackground(); 306 el.bind('mousedown', imgMouseDown); 307 el.bind('mousemove', imgMouseMove); 308 $(window).bind('mouseup', imgMouseUp); 309 el.bind('mousewheel DOMMouseScroll', zoomImage); 310 }; 311 312 obj.image.src = options.imgSrc; 313 el.on('remove', function () { $(window).unbind('mouseup', imgMouseUp) }); 314 315 return obj; 316 }; 317 318 jQuery.fn.cropimgbox = function (options) { 319 return new cropimgbox(options, this); 320 }; 321 }));