123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*
- *
- * canvasResize
- *
- * Version: 1.2.0
- * Date (d/m/y): 02/10/12
- * Update (d/m/y): 14/05/13
- * Original author: @gokercebeci
- * Licensed under the MIT license
- * - This plugin working with binaryajax.js and exif.js
- * (It's under the MPL License http://www.nihilogic.dk/licenses/mpl-license.txt)
- * Demo: http://canvasResize.gokercebeci.com/
- *
- * - I fixed iOS6 Safari's image file rendering issue for large size image (over mega-pixel)
- * using few functions from https://github.com/stomita/ios-imagefile-megapixel
- * (detectSubsampling, )
- * And fixed orientation issue by using https://github.com/jseidelin/exif-js
- * Thanks, Shinichi Tomita and Jacob Seidelin
- */
- (function($) {
- var pluginName = 'canvasResize',
- methods = {
- newsize: function(w, h, W, H, C) {
- var c = C ? 'h' : '';
- if ((W && w > W) || (H && h > H)) {
- var r = w / h;
- if ((r >= 1 || H === 0) && W && !C) {
- w = W;
- h = (W / r) >> 0;
- } else if (C && r <= (W / H)) {
- w = W;
- h = (W / r) >> 0;
- c = 'w';
- } else {
- w = (H * r) >> 0;
- h = H;
- }
- }
- return {
- 'width': w,
- 'height': h,
- 'cropped': c
- };
- },
- dataURLtoBlob: function(data) {
- var mimeString = data.split(',')[0].split(':')[1].split(';')[0];
- var byteString = atob(data.split(',')[1]);
- var ab = new ArrayBuffer(byteString.length);
- var ia = new Uint8Array(ab);
- for (var i = 0; i < byteString.length; i++) {
- ia[i] = byteString.charCodeAt(i);
- }
- var bb = (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder);
- if (bb) {
- // console.log('BlobBuilder');
- bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)();
- bb.append(ab);
- return bb.getBlob(mimeString);
- } else {
- // console.log('Blob');
- bb = new Blob([ab], {
- 'type': (mimeString)
- });
- return bb;
- }
- },
- /**
- * Detect subsampling in loaded image.
- * In iOS, larger images than 2M pixels may be subsampled in rendering.
- */
- detectSubsampling: function(img) {
- var iw = img.width, ih = img.height;
- if (iw * ih > 1048576) { // subsampling may happen over megapixel image
- var canvas = document.createElement('canvas');
- canvas.width = canvas.height = 1;
- var ctx = canvas.getContext('2d');
- ctx.drawImage(img, -iw + 1, 0);
- // subsampled image becomes half smaller in rendering size.
- // check alpha channel value to confirm image is covering edge pixel or not.
- // if alpha value is 0 image is not covering, hence subsampled.
- return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
- } else {
- return false;
- }
- },
- /**
- * Update the orientation according to the specified rotation angle
- */
- rotate: function(orientation, angle) {
- var o = {
- // nothing
- 1: {90: 6, 180: 3, 270: 8},
- // horizontal flip
- 2: {90: 7, 180: 4, 270: 5},
- // 180 rotate left
- 3: {90: 8, 180: 1, 270: 6},
- // vertical flip
- 4: {90: 5, 180: 2, 270: 7},
- // vertical flip + 90 rotate right
- 5: {90: 2, 180: 7, 270: 4},
- // 90 rotate right
- 6: {90: 3, 180: 8, 270: 1},
- // horizontal flip + 90 rotate right
- 7: {90: 4, 180: 5, 270: 2},
- // 90 rotate left
- 8: {90: 1, 180: 6, 270: 3}
- };
- return o[orientation][angle] ? o[orientation][angle] : orientation;
- },
- /**
- * Transform canvas coordination according to specified frame size and orientation
- * Orientation value is from EXIF tag
- */
- transformCoordinate: function(canvas, width, height, orientation) {
- switch (orientation) {
- case 5:
- case 6:
- case 7:
- case 8:
- canvas.width = height;
- canvas.height = width;
- break;
- default:
- canvas.width = width;
- canvas.height = height;
- }
- var ctx = canvas.getContext('2d');
- switch (orientation) {
- case 1:
- // nothing
- break;
- case 2:
- // horizontal flip
- ctx.translate(width, 0);
- ctx.scale(-1, 1);
- break;
- case 3:
- // 180 rotate left
- ctx.translate(width, height);
- ctx.rotate(Math.PI);
- break;
- case 4:
- // vertical flip
- ctx.translate(0, height);
- ctx.scale(1, -1);
- break;
- case 5:
- // vertical flip + 90 rotate right
- ctx.rotate(0.5 * Math.PI);
- ctx.scale(1, -1);
- break;
- case 6:
- // 90 rotate right
- ctx.rotate(0.5 * Math.PI);
- ctx.translate(0, -height);
- break;
- case 7:
- // horizontal flip + 90 rotate right
- ctx.rotate(0.5 * Math.PI);
- ctx.translate(width, -height);
- ctx.scale(-1, 1);
- break;
- case 8:
- // 90 rotate left
- ctx.rotate(-0.5 * Math.PI);
- ctx.translate(-width, 0);
- break;
- default:
- break;
- }
- },
- /**
- * Detecting vertical squash in loaded image.
- * Fixes a bug which squash image vertically while drawing into canvas for some images.
- */
- detectVerticalSquash: function(img, iw, ih) {
- var canvas = document.createElement('canvas');
- canvas.width = 1;
- canvas.height = ih;
- var ctx = canvas.getContext('2d');
- ctx.drawImage(img, 0, 0);
- var data = ctx.getImageData(0, 0, 1, ih).data;
- // search image edge pixel position in case it is squashed vertically.
- var sy = 0;
- var ey = ih;
- var py = ih;
- while (py > sy) {
- var alpha = data[(py - 1) * 4 + 3];
- if (alpha === 0) {
- ey = py;
- } else {
- sy = py;
- }
- py = (ey + sy) >> 1;
- }
- var ratio = py / ih;
- return ratio === 0 ? 1 : ratio;
- },
- callback: function(d) {
- return d;
- },
- extend: function() {
- var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false;
- if (target.constructor === Boolean) {
- deep = target;
- target = arguments[1] || {};
- }
- if (al === 1) {
- target = this;
- a = 0;
- }
- var prop;
- for (; a < al; a++)
- if ((prop = arguments[a]) !== null)
- for (var i in prop) {
- if (target === prop[i])
- continue;
- if (deep && typeof prop[i] === 'object' && target[i])
- methods.extend(target[i], prop[i]);
- else if (prop[i] !== undefined)
- target[i] = prop[i];
- }
- return target;
- }
- },
- defaults = {
- width: 300,
- height: 0,
- crop: false,
- quality: 80,
- rotate: 0,
- 'callback': methods.callback
- };
- function Plugin(file, options) {
- this.file = file;
- // EXTEND
- this.options = methods.extend({}, defaults, options);
- this._defaults = defaults;
- this._name = pluginName;
- this.init();
- }
- Plugin.prototype = {
- init: function() {
- //this.options.init(this);
- var $this = this;
- var file = this.file;
- var reader = new plus.io.FileReader();
- reader.onloadend = function(e) {
- var dataURL = e.target.result;
- var byteString = atob(dataURL.split(',')[1]);
- var binary = new BinaryFile(byteString, 0, byteString.length);
- var exif = EXIF.readFromBinaryFile(binary);
- var img = new Image();
- img.onload = function(e) {
- var orientation = exif['Orientation'] || 1;
- orientation = methods.rotate(orientation, $this.options.rotate);
- // CW or CCW ? replace width and height
- var size = (orientation >= 5 && orientation <= 8)
- ? methods.newsize(img.height, img.width, $this.options.width, $this.options.height, $this.options.crop)
- : methods.newsize(img.width, img.height, $this.options.width, $this.options.height, $this.options.crop);
- var iw = img.width, ih = img.height;
- var width = size.width, height = size.height;
- var canvas = document.createElement("canvas");
- var ctx = canvas.getContext("2d");
- ctx.save();
- methods.transformCoordinate(canvas, width, height, orientation);
- // over image size
- if (methods.detectSubsampling(img)) {
- iw /= 2;
- ih /= 2;
- }
- var d = 1024; // size of tiling canvas
- var tmpCanvas = document.createElement('canvas');
- tmpCanvas.width = tmpCanvas.height = d;
- var tmpCtx = tmpCanvas.getContext('2d');
- var vertSquashRatio = methods.detectVerticalSquash(img, iw, ih);
- var sy = 0;
- while (sy < ih) {
- var sh = sy + d > ih ? ih - sy : d;
- var sx = 0;
- while (sx < iw) {
- var sw = sx + d > iw ? iw - sx : d;
- tmpCtx.clearRect(0, 0, d, d);
- tmpCtx.drawImage(img, -sx, -sy);
- var dx = Math.floor(sx * width / iw);
- var dw = Math.ceil(sw * width / iw);
- var dy = Math.floor(sy * height / ih / vertSquashRatio);
- var dh = Math.ceil(sh * height / ih / vertSquashRatio);
- ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
- sx += d;
- }
- sy += d;
- }
- ctx.restore();
- tmpCanvas = tmpCtx = null;
- // if rotated width and height data replacing issue
- var newcanvas = document.createElement('canvas');
- newcanvas.width = size.cropped === 'h' ? height : width;
- newcanvas.height = size.cropped === 'w' ? width : height;
- var x = size.cropped === 'h' ? (height - width) * .5 : 0;
- var y = size.cropped === 'w' ? (width - height) * .5 : 0;
- newctx = newcanvas.getContext('2d');
- newctx.drawImage(canvas, x, y, width, height);
- // console.log(file, file.type);
- var data = null;
- if (file.type === "image/png") {
- data = newcanvas.toDataURL(file.type);
- } else {
- data = newcanvas.toDataURL("image/jpeg", ($this.options.quality * .01));
- }
- // CALLBACK
- $this.options.callback(data, newcanvas.width, newcanvas.height);
- // });
- };
- img.src = dataURL;
- // =====================================================
- };
- reader.readAsDataURL(file);
- //reader.readAsBinaryString(file);
- }
- };
- $[pluginName] = function(file, options) {
- // console.log(file.size);
- if (typeof file === 'string')
- return methods[file](options);
- else
- new Plugin(file, options);
- };
- })(window);
|