ngx-pica
Version:
Angular 5 module to resize images files in browser
450 lines • 15.8 kB
JavaScript
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { NgxPicaErrorType } from './ngx-pica-error.interface';
import { NgxPicaExifService } from './ngx-pica-exif.service';
import pica from 'pica/dist/pica';
var NgxPicaService = (function () {
function NgxPicaService(_ngxPicaExifService) {
this._ngxPicaExifService = _ngxPicaExifService;
this.picaResizer = new pica();
this.MAX_STEPS = 20;
if (!this.picaResizer || !this.picaResizer.resize) {
this.picaResizer = new window.pica();
}
}
/**
* Resize images array
* @param {File[]} files
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
/**
* Resize images array
* @param {File[]} files
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
NgxPicaService.prototype.resizeImages = /**
* Resize images array
* @param {File[]} files
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
function (files, width, height, options) {
var _this = this;
var resizedImage = new Subject();
var totalFiles = files.length;
if (totalFiles > 0) {
var nextFile_1 = new Subject();
var index_1 = 0;
var subscription_1 = nextFile_1.subscribe(function (file) {
_this.resizeImage(file, width, height, options).subscribe(function (imageResized) {
index_1++;
resizedImage.next(imageResized);
if (index_1 < totalFiles) {
nextFile_1.next(files[index_1]);
}
else {
resizedImage.complete();
subscription_1.unsubscribe();
}
}, function (err) {
var ngxPicaError = {
file: file,
err: err
};
resizedImage.error(ngxPicaError);
});
});
nextFile_1.next(files[index_1]);
}
else {
var ngxPicaError = {
err: NgxPicaErrorType.NO_FILES_RECEIVED
};
resizedImage.error(ngxPicaError);
resizedImage.complete();
}
return resizedImage.asObservable();
};
/**
* Resize image file
*
* @param {File} file
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
/**
* Resize image file
*
* @param {File} file
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
NgxPicaService.prototype.resizeImage = /**
* Resize image file
*
* @param {File} file
* @param {number} width
* @param {number} height
* @param {NgxPicaResizeOptionsInterface} options
* @returns {Observable<File>}
*/
function (file, width, height, options) {
var _this = this;
var resizedImage = new Subject();
var originCanvas = document.createElement('canvas');
var ctx = originCanvas.getContext('2d');
var img = new Image();
if (ctx) {
img.onload = function () {
_this._ngxPicaExifService.getExifOrientedImage(img).then(function (orientedImage) {
window.URL.revokeObjectURL(img.src);
originCanvas.width = orientedImage.width;
originCanvas.height = orientedImage.height;
ctx.drawImage(orientedImage, 0, 0);
var imageData = ctx.getImageData(0, 0, orientedImage.width, orientedImage.height);
if (options && options.aspectRatio && options.aspectRatio.keepAspectRatio) {
var ratio = 0;
if (options.aspectRatio.forceMinDimensions) {
ratio = Math.max(width / imageData.width, height / imageData.height);
}
else {
ratio = Math.min(width / imageData.width, height / imageData.height);
}
width = Math.round(imageData.width * ratio);
height = Math.round(imageData.height * ratio);
}
var destinationCanvas = document.createElement('canvas');
destinationCanvas.width = width;
destinationCanvas.height = height;
_this.picaResize(file, originCanvas, destinationCanvas, options)
.catch(function (err) { return resizedImage.error(err); })
.then(function (imgResized) {
resizedImage.next(imgResized);
});
});
};
img.src = window.URL.createObjectURL(file);
}
else {
resizedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED);
}
return resizedImage.asObservable();
};
/**
* Compress images array
*
* @param {File[]} files
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
/**
* Compress images array
*
* @param {File[]} files
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
NgxPicaService.prototype.compressImages = /**
* Compress images array
*
* @param {File[]} files
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
function (files, sizeInMB) {
var _this = this;
var compressedImage = new Subject();
var totalFiles = files.length;
if (totalFiles > 0) {
var nextFile_2 = new Subject();
var index_2 = 0;
var subscription_2 = nextFile_2.subscribe(function (file) {
_this.compressImage(file, sizeInMB).subscribe(function (imageCompressed) {
index_2++;
compressedImage.next(imageCompressed);
if (index_2 < totalFiles) {
nextFile_2.next(files[index_2]);
}
else {
compressedImage.complete();
subscription_2.unsubscribe();
}
}, function (err) {
var ngxPicaError = {
file: file,
err: err
};
compressedImage.error(ngxPicaError);
});
});
nextFile_2.next(files[index_2]);
}
else {
var ngxPicaError = {
err: NgxPicaErrorType.NO_FILES_RECEIVED
};
compressedImage.error(ngxPicaError);
compressedImage.complete();
}
return compressedImage.asObservable();
};
/**
* Compress image file
*
* @param {File} file
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
/**
* Compress image file
*
* @param {File} file
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
NgxPicaService.prototype.compressImage = /**
* Compress image file
*
* @param {File} file
* @param {number} sizeInMB
* @returns {Observable<File>}
*/
function (file, sizeInMB) {
var _this = this;
var compressedImage = new Subject();
if (this.bytesToMB(file.size) <= sizeInMB) {
setTimeout(function () {
compressedImage.next(file);
});
}
else {
var originCanvas_1 = document.createElement('canvas');
var ctx_1 = originCanvas_1.getContext('2d');
var img_1 = new Image();
if (ctx_1) {
img_1.onload = function () {
_this._ngxPicaExifService.getExifOrientedImage(img_1).then(function (orientedImage) {
window.URL.revokeObjectURL(img_1.src);
originCanvas_1.width = orientedImage.width;
originCanvas_1.height = orientedImage.height;
ctx_1.drawImage(orientedImage, 0, 0);
_this.getCompressedImage(originCanvas_1, file.type, 1, sizeInMB, 0)
.catch(function (err) { return compressedImage.error(err); })
.then(function (blob) {
var imgCompressed = _this.blobToFile(blob, file.name, file.type, new Date().getTime());
compressedImage.next(imgCompressed);
});
});
};
img_1.src = window.URL.createObjectURL(file);
}
else {
compressedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED);
}
}
return compressedImage.asObservable();
};
/**
* Through Pica toBlob method, compress image file
*
* @param {HTMLCanvasElement} canvas
* @param {string} type
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
/**
* Through Pica toBlob method, compress image file
*
* @param {HTMLCanvasElement} canvas
* @param {string} type
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
NgxPicaService.prototype.getCompressedImage = /**
* Through Pica toBlob method, compress image file
*
* @param {HTMLCanvasElement} canvas
* @param {string} type
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
function (canvas, type, quality, sizeInMB, step) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.picaResizer.toBlob(canvas, type, quality)
.catch(function (err) { return reject(err); })
.then(function (blob) {
_this.checkCompressedImageSize(canvas, blob, quality, sizeInMB, step)
.catch(function (err) { return reject(err); })
.then(function (blob) {
resolve(blob);
});
});
});
};
/**
* Check if image has been compressed enough
*
* @param {HTMLCanvasElement} canvas
* @param {Blob} blob
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
/**
* Check if image has been compressed enough
*
* @param {HTMLCanvasElement} canvas
* @param {Blob} blob
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
NgxPicaService.prototype.checkCompressedImageSize = /**
* Check if image has been compressed enough
*
* @param {HTMLCanvasElement} canvas
* @param {Blob} blob
* @param {number} quality
* @param {number} sizeInMB
* @param {number} step
* @returns {Promise<Blob>}
*/
function (canvas, blob, quality, sizeInMB, step) {
var _this = this;
return new Promise(function (resolve, reject) {
if (step > _this.MAX_STEPS) {
reject(NgxPicaErrorType.NOT_BE_ABLE_TO_COMPRESS_ENOUGH);
}
if (_this.bytesToMB(blob.size) < sizeInMB) {
resolve(blob);
}
else {
var newQuality = quality - (quality * 0.1);
var newStep = step + 1;
// recursively compression
resolve(_this.getCompressedImage(canvas, blob.type, newQuality, sizeInMB, newStep));
}
});
};
/**
* Through Pica resize method, resize image file
*
* @param {File} file
* @param {HTMLCanvasElement} from
* @param {HTMLCanvasElement} to
* @param options
* @returns {Promise<File>}
*/
/**
* Through Pica resize method, resize image file
*
* @param {File} file
* @param {HTMLCanvasElement} from
* @param {HTMLCanvasElement} to
* @param options
* @returns {Promise<File>}
*/
NgxPicaService.prototype.picaResize = /**
* Through Pica resize method, resize image file
*
* @param {File} file
* @param {HTMLCanvasElement} from
* @param {HTMLCanvasElement} to
* @param options
* @returns {Promise<File>}
*/
function (file, from, to, options) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.picaResizer.resize(from, to, options)
.catch(function (err) { return reject(err); })
.then(function (resizedCanvas) { return _this.picaResizer.toBlob(resizedCanvas, file.type); })
.then(function (blob) {
var fileResized = _this.blobToFile(blob, file.name, file.type, new Date().getTime());
resolve(fileResized);
});
});
};
/**
* Return new File from Blob
*
* @param {Blob} blob
* @param {string} name
* @param {string} type
* @param {number} lastModified
* @returns {File}
*/
/**
* Return new File from Blob
*
* @param {Blob} blob
* @param {string} name
* @param {string} type
* @param {number} lastModified
* @returns {File}
*/
NgxPicaService.prototype.blobToFile = /**
* Return new File from Blob
*
* @param {Blob} blob
* @param {string} name
* @param {string} type
* @param {number} lastModified
* @returns {File}
*/
function (blob, name, type, lastModified) {
return new File([blob], name, { type: type, lastModified: lastModified });
};
/**
* Convert bytes to MegaBytes
*
* @param {number} bytes
* @returns {number}
*/
/**
* Convert bytes to MegaBytes
*
* @param {number} bytes
* @returns {number}
*/
NgxPicaService.prototype.bytesToMB = /**
* Convert bytes to MegaBytes
*
* @param {number} bytes
* @returns {number}
*/
function (bytes) {
return bytes / 1048576;
};
NgxPicaService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
NgxPicaService.ctorParameters = function () { return [
{ type: NgxPicaExifService, },
]; };
return NgxPicaService;
}());
export { NgxPicaService };
//# sourceMappingURL=ngx-pica.service.js.map