ng-file-upload-haikulearning
Version:
An AngularJS directive for file upload using HTML5 with FileAPI polyfill for unsupported browsers
136 lines (126 loc) • 4.86 kB
JavaScript
ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadValidate, $q) {
var upload = UploadValidate;
/**
* Conserve aspect ratio of the original region. Useful when shrinking/enlarging
* images to fit into a certain area.
* Source: http://stackoverflow.com/a/14731922
*
* @param {Number} srcWidth Source area width
* @param {Number} srcHeight Source area height
* @param {Number} maxWidth Nestable area maximum available width
* @param {Number} maxHeight Nestable area maximum available height
* @return {Object} { width, height }
*/
var calculateAspectRatioFit = function (srcWidth, srcHeight, maxWidth, maxHeight, centerCrop) {
var ratio = centerCrop ? Math.max(maxWidth / srcWidth, maxHeight / srcHeight) :
Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return {
width: srcWidth * ratio, height: srcHeight * ratio,
marginX: srcWidth * ratio - maxWidth, marginY: srcHeight * ratio - maxHeight
};
};
// Extracted from https://github.com/romelgomez/angular-firebase-image-upload/blob/master/app/scripts/fileUpload.js#L89
var resize = function (imagen, width, height, quality, type, ratio, centerCrop, resizeIf) {
var deferred = $q.defer();
var canvasElement = document.createElement('canvas');
var imageElement = document.createElement('img');
imageElement.onload = function () {
if (resizeIf != null && resizeIf(imageElement.width, imageElement.height) === false) {
deferred.reject('resizeIf');
return;
}
try {
if (ratio) {
var ratioFloat = upload.ratioToFloat(ratio);
var imgRatio = imageElement.width / imageElement.height;
if (imgRatio < ratioFloat) {
width = imageElement.width;
height = width / ratioFloat;
} else {
height = imageElement.height;
width = height * ratioFloat;
}
}
if (!width) {
width = imageElement.width;
}
if (!height) {
height = imageElement.height;
}
var dimensions = calculateAspectRatioFit(imageElement.width, imageElement.height, width, height, centerCrop);
canvasElement.width = Math.min(dimensions.width, width);
canvasElement.height = Math.min(dimensions.height, height);
var context = canvasElement.getContext('2d');
context.drawImage(imageElement,
Math.min(0, -dimensions.marginX / 2), Math.min(0, -dimensions.marginY / 2),
dimensions.width, dimensions.height);
deferred.resolve(canvasElement.toDataURL(type || 'image/WebP', quality || 0.934));
} catch (e) {
deferred.reject(e);
}
};
imageElement.onerror = function () {
deferred.reject();
};
imageElement.src = imagen;
return deferred.promise;
};
upload.dataUrltoBlob = function (dataurl, name, origSize) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var blob = new window.Blob([u8arr], {type: mime});
blob.name = name;
blob.$ngfOrigSize = origSize;
return blob;
};
upload.isResizeSupported = function () {
var elem = document.createElement('canvas');
return window.atob && elem.getContext && elem.getContext('2d') && window.Blob;
};
if (upload.isResizeSupported()) {
// add name getter to the blob constructor prototype
Object.defineProperty(window.Blob.prototype, 'name', {
get: function () {
return this.$ngfName;
},
set: function (v) {
this.$ngfName = v;
},
configurable: true
});
}
upload.resize = function (file, width, height, quality, type, ratio, centerCrop, resizeIf, restoreExif) {
if (file.type.indexOf('image') !== 0) return upload.emptyPromise(file);
var deferred = $q.defer();
upload.dataUrl(file, true).then(function (url) {
resize(url, width, height, quality, type || file.type, ratio, centerCrop, resizeIf)
.then(function (dataUrl) {
if (file.type === 'image/jpeg' && restoreExif) {
try {
dataUrl = upload.restoreExif(url, dataUrl);
} catch (e) {
setTimeout(function () {throw e;}, 1);
}
}
try {
var blob = upload.dataUrltoBlob(dataUrl, file.name, file.size);
deferred.resolve(blob);
} catch (e) {
deferred.reject(e);
}
}, function (r) {
if (r === 'resizeIf') {
deferred.resolve(file);
}
deferred.reject(r);
});
}, function (e) {
deferred.reject(e);
});
return deferred.promise;
};
return upload;
}]);