You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
344
static/app2/js/canvasResize.js
Executable file
344
static/app2/js/canvasResize.js
Executable file
@ -0,0 +1,344 @@
|
||||
/*
|
||||
*
|
||||
* 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);
|
||||
if (file.type === "image/png") {
|
||||
var data = newcanvas.toDataURL(file.type);
|
||||
} else {
|
||||
var 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);
|
Reference in New Issue
Block a user