UNPKG

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
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; }]);