ng-pica
Version:
Angular module to resize images files in browser
515 lines • 42.3 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { NgxPicaErrorType } from './ngx-pica-error.interface';
import { NgxPicaExifService } from './ngx-pica-exif.service';
import Pica from 'pica';
var NgxPicaService = /** @class */ (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();
}
}
/**
* @param {?} files
* @param {?} width
* @param {?} height
* @param {?=} options
* @return {?}
*/
NgxPicaService.prototype.resizeImages = /**
* @param {?} files
* @param {?} width
* @param {?} height
* @param {?=} options
* @return {?}
*/
function (files, width, height, options) {
var _this = this;
/** @type {?} */
var resizedImage = new Subject();
/** @type {?} */
var totalFiles = files.length;
if (totalFiles > 0) {
/** @type {?} */
var nextFile_1 = new Subject();
/** @type {?} */
var index_1 = 0;
/** @type {?} */
var subscription_1 = nextFile_1.subscribe((/**
* @param {?} file
* @return {?}
*/
function (file) {
_this.resizeImage(file, width, height, options).subscribe((/**
* @param {?} imageResized
* @return {?}
*/
function (imageResized) {
index_1++;
resizedImage.next(imageResized);
if (index_1 < totalFiles) {
nextFile_1.next(files[index_1]);
}
else {
resizedImage.complete();
subscription_1.unsubscribe();
}
}), (/**
* @param {?} err
* @return {?}
*/
function (err) {
/** @type {?} */
var ngxPicaError = {
file: file,
err: err
};
resizedImage.error(ngxPicaError);
}));
}));
nextFile_1.next(files[index_1]);
}
else {
/** @type {?} */
var ngxPicaError = {
err: NgxPicaErrorType.NO_FILES_RECEIVED
};
resizedImage.error(ngxPicaError);
resizedImage.complete();
}
return resizedImage.asObservable();
};
/**
* @param {?} file
* @param {?} width
* @param {?} height
* @param {?=} options
* @return {?}
*/
NgxPicaService.prototype.resizeImage = /**
* @param {?} file
* @param {?} width
* @param {?} height
* @param {?=} options
* @return {?}
*/
function (file, width, height, options) {
var _this = this;
/** @type {?} */
var resizedImage = new Subject();
/** @type {?} */
var originCanvas = document.createElement('canvas');
/** @type {?} */
var ctx = originCanvas.getContext('2d');
/** @type {?} */
var img = new Image();
if (ctx) {
img.onload = (/**
* @return {?}
*/
function () {
_this._ngxPicaExifService.getExifOrientedImage(img).then((/**
* @param {?} orientedImage
* @return {?}
*/
function (orientedImage) {
window.URL.revokeObjectURL(img.src);
originCanvas.width = orientedImage.width;
originCanvas.height = orientedImage.height;
ctx.drawImage(orientedImage, 0, 0);
/** @type {?} */
var imageData = ctx.getImageData(0, 0, orientedImage.width, orientedImage.height);
if (options && options.aspectRatio && options.aspectRatio.keepAspectRatio) {
/** @type {?} */
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);
}
/** @type {?} */
var destinationCanvas = document.createElement('canvas');
destinationCanvas.width = width;
destinationCanvas.height = height;
_this.picaResize(file, originCanvas, destinationCanvas, options)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return resizedImage.error(err); }))
.then((/**
* @param {?} imgResized
* @return {?}
*/
function (imgResized) {
resizedImage.next(imgResized);
}));
}));
});
img.src = window.URL.createObjectURL(file);
}
else {
resizedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED);
}
return resizedImage.asObservable();
};
/**
* @param {?} files
* @param {?} sizeInMB
* @return {?}
*/
NgxPicaService.prototype.compressImages = /**
* @param {?} files
* @param {?} sizeInMB
* @return {?}
*/
function (files, sizeInMB) {
var _this = this;
/** @type {?} */
var compressedImage = new Subject();
/** @type {?} */
var totalFiles = files.length;
if (totalFiles > 0) {
/** @type {?} */
var nextFile_2 = new Subject();
/** @type {?} */
var index_2 = 0;
/** @type {?} */
var subscription_2 = nextFile_2.subscribe((/**
* @param {?} file
* @return {?}
*/
function (file) {
_this.compressImage(file, sizeInMB).subscribe((/**
* @param {?} imageCompressed
* @return {?}
*/
function (imageCompressed) {
index_2++;
compressedImage.next(imageCompressed);
if (index_2 < totalFiles) {
nextFile_2.next(files[index_2]);
}
else {
compressedImage.complete();
subscription_2.unsubscribe();
}
}), (/**
* @param {?} err
* @return {?}
*/
function (err) {
/** @type {?} */
var ngxPicaError = {
file: file,
err: err
};
compressedImage.error(ngxPicaError);
}));
}));
nextFile_2.next(files[index_2]);
}
else {
/** @type {?} */
var ngxPicaError = {
err: NgxPicaErrorType.NO_FILES_RECEIVED
};
compressedImage.error(ngxPicaError);
compressedImage.complete();
}
return compressedImage.asObservable();
};
/**
* @param {?} file
* @param {?} sizeInMB
* @return {?}
*/
NgxPicaService.prototype.compressImage = /**
* @param {?} file
* @param {?} sizeInMB
* @return {?}
*/
function (file, sizeInMB) {
var _this = this;
/** @type {?} */
var compressedImage = new Subject();
/** @type {?} */
var originCanvas = document.createElement('canvas');
/** @type {?} */
var ctx = originCanvas.getContext('2d');
/** @type {?} */
var img = new Image();
if (ctx) {
img.onload = (/**
* @return {?}
*/
function () {
_this._ngxPicaExifService.getExifOrientedImage(img).then((/**
* @param {?} orientedImage
* @return {?}
*/
function (orientedImage) {
window.URL.revokeObjectURL(img.src);
originCanvas.width = orientedImage.width;
originCanvas.height = orientedImage.height;
ctx.drawImage(orientedImage, 0, 0);
_this.picaResizer.toBlob(originCanvas, file.type, 1)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return compressedImage.error(err); }))
.then((/**
* @param {?} blob
* @return {?}
*/
function (blob) {
if (_this.bytesToMB(blob.size) <= sizeInMB) {
/** @type {?} */
var imgCompressed = _this.blobToFile(blob, file.name, file.type, new Date().getTime());
compressedImage.next(imgCompressed);
}
else {
_this.getCompressedImage(originCanvas, file.type, 1, sizeInMB, 0)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return compressedImage.error(err); }))
.then((/**
* @param {?} blob
* @return {?}
*/
function (blob) {
/** @type {?} */
var imgCompressed = _this.blobToFile(blob, file.name, file.type, new Date().getTime());
compressedImage.next(imgCompressed);
}));
}
}));
}));
});
img.src = window.URL.createObjectURL(file);
}
else {
compressedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED);
}
return compressedImage.asObservable();
};
/**
* @private
* @param {?} canvas
* @param {?} type
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
NgxPicaService.prototype.getCompressedImage = /**
* @private
* @param {?} canvas
* @param {?} type
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
function (canvas, type, quality, sizeInMB, step) {
var _this = this;
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
function (resolve, reject) {
_this.picaResizer.toBlob(canvas, type, quality)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return reject(err); }))
.then((/**
* @param {?} blob
* @return {?}
*/
function (blob) {
_this.checkCompressedImageSize(canvas, blob, quality, sizeInMB, step)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return reject(err); }))
.then((/**
* @param {?} compressedBlob
* @return {?}
*/
function (compressedBlob) {
resolve(compressedBlob);
}));
}));
}));
};
/**
* @private
* @param {?} canvas
* @param {?} blob
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
NgxPicaService.prototype.checkCompressedImageSize = /**
* @private
* @param {?} canvas
* @param {?} blob
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
function (canvas, blob, quality, sizeInMB, step) {
var _this = this;
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
function (resolve, reject) {
if (step > _this.MAX_STEPS) {
reject(NgxPicaErrorType.NOT_BE_ABLE_TO_COMPRESS_ENOUGH);
}
else if (_this.bytesToMB(blob.size) < sizeInMB) {
resolve(blob);
}
else {
/** @type {?} */
var newQuality = quality - (quality * 0.1);
/** @type {?} */
var newStep = step + 1;
// recursively compression
resolve(_this.getCompressedImage(canvas, blob.type, newQuality, sizeInMB, newStep));
}
}));
};
/**
* @private
* @param {?} file
* @param {?} from
* @param {?} to
* @param {?} options
* @return {?}
*/
NgxPicaService.prototype.picaResize = /**
* @private
* @param {?} file
* @param {?} from
* @param {?} to
* @param {?} options
* @return {?}
*/
function (file, from, to, options) {
var _this = this;
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
function (resolve, reject) {
_this.picaResizer.resize(from, to, options)
.catch((/**
* @param {?} err
* @return {?}
*/
function (err) { return reject(err); }))
.then((/**
* @param {?} resizedCanvas
* @return {?}
*/
function (resizedCanvas) { return _this.picaResizer.toBlob(resizedCanvas, file.type); }))
.then((/**
* @param {?} blob
* @return {?}
*/
function (blob) {
/** @type {?} */
var fileResized = _this.blobToFile(blob, file.name, file.type, new Date().getTime());
resolve(fileResized);
}));
}));
};
/**
* @private
* @param {?} blob
* @param {?} name
* @param {?} type
* @param {?} lastModified
* @return {?}
*/
NgxPicaService.prototype.blobToFile = /**
* @private
* @param {?} blob
* @param {?} name
* @param {?} type
* @param {?} lastModified
* @return {?}
*/
function (blob, name, type, lastModified) {
// return new File([blob], name, {type: type, lastModified: lastModified});
/** @type {?} */
var file = (/** @type {?} */ (new Blob([blob], { type: type })));
file.name = name;
file.lastModifiedDate = lastModified;
return (/** @type {?} */ (file));
};
/**
* @private
* @param {?} bytes
* @return {?}
*/
NgxPicaService.prototype.bytesToMB = /**
* @private
* @param {?} bytes
* @return {?}
*/
function (bytes) {
return bytes / 1048576;
};
NgxPicaService.decorators = [
{ type: Injectable }
];
/** @nocollapse */
NgxPicaService.ctorParameters = function () { return [
{ type: NgxPicaExifService }
]; };
return NgxPicaService;
}());
export { NgxPicaService };
if (false) {
/**
* @type {?}
* @private
*/
NgxPicaService.prototype.picaResizer;
/**
* @type {?}
* @private
*/
NgxPicaService.prototype.MAX_STEPS;
/**
* @type {?}
* @private
*/
NgxPicaService.prototype._ngxPicaExifService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBpY2Euc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLXBpY2EvIiwic291cmNlcyI6WyJsaWIvbmd4LXBpY2Euc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUMsT0FBTyxFQUEyQixNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQXdCLGdCQUFnQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFFbkYsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDM0QsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBS3hCO0lBS0ksd0JBQW9CLG1CQUF1QztRQUF2Qyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQW9CO1FBSG5ELGdCQUFXLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN6QixjQUFTLEdBQUcsRUFBRSxDQUFDO1FBR25CLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUU7WUFDL0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUN4QztJQUNMLENBQUM7Ozs7Ozs7O0lBRU0scUNBQVk7Ozs7Ozs7SUFBbkIsVUFBb0IsS0FBYSxFQUFFLEtBQWEsRUFBRSxNQUFjLEVBQUUsT0FBdUM7UUFBekcsaUJBeUNDOztZQXhDUyxZQUFZLEdBQWtCLElBQUksT0FBTyxFQUFFOztZQUMzQyxVQUFVLEdBQVcsS0FBSyxDQUFDLE1BQU07UUFFdkMsSUFBSSxVQUFVLEdBQUcsQ0FBQyxFQUFFOztnQkFDVixVQUFRLEdBQWtCLElBQUksT0FBTyxFQUFFOztnQkFDekMsT0FBSyxHQUFHLENBQUM7O2dCQUVQLGNBQVksR0FBaUIsVUFBUSxDQUFDLFNBQVM7Ozs7WUFBQyxVQUFDLElBQVU7Z0JBQzdELEtB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QUMsQ0FBQyxFQUFPO1FBQ2pELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxZQUFZLENBQUM7UUFDckMsT0FBTyxtQkFBQSxJQUFJLEVBQVEsQ0FBQTtJQUN2QixDQUFDOzs7Ozs7SUFFTyxrQ0FBUzs7Ozs7SUFBakIsVUFBa0IsS0FBYTtRQUMzQixPQUFPLEtBQUssR0FBRyxPQUFPLENBQUM7SUFDM0IsQ0FBQzs7Z0JBMVBKLFVBQVU7Ozs7Z0JBTkgsa0JBQWtCOztJQWlRMUIscUJBQUM7Q0FBQSxBQTNQRCxJQTJQQztTQTFQWSxjQUFjOzs7Ozs7SUFDdkIscUNBQWlDOzs7OztJQUNqQyxtQ0FBdUI7Ozs7O0lBRVgsNkNBQStDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7U3ViamVjdCwgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7Tmd4UGljYUVycm9ySW50ZXJmYWNlLCBOZ3hQaWNhRXJyb3JUeXBlfSBmcm9tICcuL25neC1waWNhLWVycm9yLmludGVyZmFjZSc7XG5pbXBvcnQge05neFBpY2FSZXNpemVPcHRpb25zSW50ZXJmYWNlfSBmcm9tICcuL25neC1waWNhLXJlc2l6ZS1vcHRpb25zLmludGVyZmFjZSc7XG5pbXBvcnQge05neFBpY2FFeGlmU2VydmljZX0gZnJvbSAnLi9uZ3gtcGljYS1leGlmLnNlcnZpY2UnO1xuaW1wb3J0IFBpY2EgZnJvbSAncGljYSc7XG5cblxuZGVjbGFyZSBsZXQgd2luZG93OiBhbnk7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBOZ3hQaWNhU2VydmljZSB7XG4gICAgcHJpdmF0ZSBwaWNhUmVzaXplciA9IG5ldyBQaWNhKCk7XG4gICAgcHJpdmF0ZSBNQVhfU1RFUFMgPSAyMDtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX25neFBpY2FFeGlmU2VydmljZTogTmd4UGljYUV4aWZTZXJ2aWNlKSB7XG4gICAgICAgIGlmICghdGhpcy5waWNhUmVzaXplciB8fCAhdGhpcy5waWNhUmVzaXplci5yZXNpemUpIHtcbiAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZXIgPSBuZXcgd2luZG93LlBpY2EoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyByZXNpemVJbWFnZXMoZmlsZXM6IEZpbGVbXSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIG9wdGlvbnM/OiBOZ3hQaWNhUmVzaXplT3B0aW9uc0ludGVyZmFjZSk6IE9ic2VydmFibGU8RmlsZT4ge1xuICAgICAgICBjb25zdCByZXNpemVkSW1hZ2U6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICBjb25zdCB0b3RhbEZpbGVzOiBudW1iZXIgPSBmaWxlcy5sZW5ndGg7XG5cbiAgICAgICAgaWYgKHRvdGFsRmlsZXMgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBuZXh0RmlsZTogU3ViamVjdDxGaWxlPiA9IG5ldyBTdWJqZWN0KCk7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgICAgICAgICBjb25zdCBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiA9IG5leHRGaWxlLnN1YnNjcmliZSgoZmlsZTogRmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplSW1hZ2UoZmlsZSwgd2lkdGgsIGhlaWdodCwgb3B0aW9ucykuc3Vic2NyaWJlKGltYWdlUmVzaXplZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgIHJlc2l6ZWRJbWFnZS5uZXh0KGltYWdlUmVzaXplZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4IDwgdG90YWxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEZpbGUubmV4dChmaWxlc1tpbmRleF0pO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU6IGZpbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnI6IGVyclxuICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgIHJlc2l6ZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5neFBpY2FFcnJvcjogTmd4UGljYUVycm9ySW50ZXJmYWNlID0ge1xuICAgICAgICAgICAgICAgIGVycjogTmd4UGljYUVycm9yVHlwZS5OT19GSUxFU19SRUNFSVZFRFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmVzaXplZEltYWdlLmVycm9yKG5neFBpY2FFcnJvcik7XG4gICAgICAgICAgICByZXNpemVkSW1hZ2UuY29tcGxldGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNpemVkSW1hZ2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlc2l6ZUltYWdlKGZpbGU6IEZpbGUsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBvcHRpb25zPzogTmd4UGljYVJlc2l6ZU9wdGlvbnNJbnRlcmZhY2UpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgcmVzaXplZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcbiAgICAgICAgY29uc3Qgb3JpZ2luQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICBjb25zdCBjdHggPSBvcmlnaW5DYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaWYgKGN0eCkge1xuICAgICAgICAgICAgaW1nLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9uZ3hQaWNhRXhpZlNlcnZpY2UuZ2V0RXhpZk9yaWVudGVkSW1hZ2UoaW1nKS50aGVuKG9yaWVudGVkSW1hZ2UgPT4ge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTChpbWcuc3JjKTtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luQ2FudmFzLndpZHRoID0gb3JpZW50ZWRJbWFnZS53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luQ2FudmFzLmhlaWdodCA9IG9yaWVudGVkSW1hZ2UuaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2Uob3JpZW50ZWRJbWFnZSwgMCwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1hZ2VEYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCBvcmllbnRlZEltYWdlLndpZHRoLCBvcmllbnRlZEltYWdlLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuYXNwZWN0UmF0aW8gJiYgb3B0aW9ucy5hc3BlY3RSYXRpby5rZWVwQXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByYXRpbyA9IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmFzcGVjdFJhdGlvLmZvcmNlTWluRGltZW5zaW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhdGlvID0gTWF0aC5tYXgod2lkdGggLyBpbWFnZURhdGEud2lkdGgsIGhlaWdodCAvIGltYWdlRGF0YS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRpbyA9IE1hdGgubWluKHdpZHRoIC8gaW1hZ2VEYXRhLndpZHRoLCBoZWlnaHQgLyBpbWFnZURhdGEuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSBNYXRoLnJvdW5kKGltYWdlRGF0YS53aWR0aCAqIHJhdGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IE1hdGgucm91bmQoaW1hZ2VEYXRhLmhlaWdodCAqIHJhdGlvKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc3RpbmF0aW9uQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbkNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbkNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5waWNhUmVzaXplKGZpbGUsIG9yaWdpbkNhbnZhcywgZGVzdGluYXRpb25DYW52YXMsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gcmVzaXplZEltYWdlLmVycm9yKGVycikpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoaW1nUmVzaXplZDogRmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZWRJbWFnZS5uZXh0KGltZ1Jlc2l6ZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpbWcuc3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNpemVkSW1hZ2UuZXJyb3IoTmd4UGljYUVycm9yVHlwZS5DQU5WQVNfQ09OVEVYVF9JREVOVElGSUVSX05PVF9TVVBQT1JURUQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc2l6ZWRJbWFnZS5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcHJlc3NJbWFnZXMoZmlsZXM6IEZpbGVbXSwgc2l6ZUluTUI6IG51bWJlcik6IE9ic2VydmFibGU8RmlsZT4ge1xuICAgICAgICBjb25zdCBjb21wcmVzc2VkSW1hZ2U6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICBjb25zdCB0b3RhbEZpbGVzOiBudW1iZXIgPSBmaWxlcy5sZW5ndGg7XG5cbiAgICAgICAgaWYgKHRvdGFsRmlsZXMgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBuZXh0RmlsZTogU3ViamVjdDxGaWxlPiA9IG5ldyBTdWJqZWN0KCk7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgICAgICAgICBjb25zdCBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiA9IG5leHRGaWxlLnN1YnNjcmliZSgoZmlsZTogRmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29tcHJlc3NJbWFnZShmaWxlLCBzaXplSW5NQikuc3Vic2NyaWJlKGltYWdlQ29tcHJlc3NlZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5uZXh0KGltYWdlQ29tcHJlc3NlZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4IDwgdG90YWxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEZpbGUubmV4dChmaWxlc1tpbmRleF0pO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU6IGZpbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnI6IGVyclxuICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5neFBpY2FFcnJvcjogTmd4UGljYUVycm9ySW50ZXJmYWNlID0ge1xuICAgICAgICAgICAgICAgIGVycjogTmd4UGljYUVycm9yVHlwZS5OT19GSUxFU19SRUNFSVZFRFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmVycm9yKG5neFBpY2FFcnJvcik7XG4gICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UuY29tcGxldGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb21wcmVzc2VkSW1hZ2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXByZXNzSW1hZ2UoZmlsZTogRmlsZSwgc2l6ZUluTUI6IG51bWJlcik6IE9ic2VydmFibGU8RmlsZT4ge1xuICAgICAgICBjb25zdCBjb21wcmVzc2VkSW1hZ2U6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgICAgIGNvbnN0IG9yaWdpbkNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgY29uc3QgY3R4ID0gb3JpZ2luQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICAgIGlmIChjdHgpIHtcbiAgICAgICAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbmd4UGljYUV4aWZTZXJ2aWNlLmdldEV4aWZPcmllbnRlZEltYWdlKGltZykudGhlbihvcmllbnRlZEltYWdlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwoaW1nLnNyYyk7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy53aWR0aCA9IG9yaWVudGVkSW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy5oZWlnaHQgPSBvcmllbnRlZEltYWdlLmhlaWdodDtcblxuICAgICAgICAgICAgICAgICAgICBjdHguZHJhd0ltYWdlKG9yaWVudGVkSW1hZ2UsIDAsIDApO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZXIudG9CbG9iKG9yaWdpbkNhbnZhcywgZmlsZS50eXBlLCAxKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGNvbXByZXNzZWRJbWFnZS5lcnJvcihlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKGJsb2I6IEJsb2IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ieXRlc1RvTUIoYmxvYi5zaXplKSA8PSBzaXplSW5NQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbWdDb21wcmVzc2VkOiBGaWxlID0gdGhpcy5ibG9iVG9GaWxlKGJsb2IsIGZpbGUubmFtZSwgZmlsZS50eXBlLCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5uZXh0KGltZ0NvbXByZXNzZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0Q29tcHJlc3NlZEltYWdlKG9yaWdpbkNhbnZhcywgZmlsZS50eXBlLCAxLCBzaXplSW5NQiwgMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiBjb21wcmVzc2VkSW1hZ2UuZXJyb3IoZXJyKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1nQ29tcHJlc3NlZDogRmlsZSA9IHRoaXMuYmxvYlRvRmlsZShibG9iLCBmaWxlLm5hbWUsIGZpbGUudHlwZSwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLm5leHQoaW1nQ29tcHJlc3NlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGltZy5zcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5lcnJvcihOZ3hQaWNhRXJyb3JUeXBlLkNBTlZBU19DT05URVhUX0lERU5USUZJRVJfTk9UX1NVUFBPUlRFRCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcHJlc3NlZEltYWdlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q29tcHJlc3NlZEltYWdlKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHR5cGU6IHN0cmluZywgcXVhbGl0eTogbnVtYmVyLCBzaXplSW5NQjogbnVtYmVyLCBzdGVwOiBudW1iZXIpOiBQcm9taXNlPEJsb2I+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPEJsb2I+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZXIudG9CbG9iKGNhbnZhcywgdHlwZSwgcXVhbGl0eSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gcmVqZWN0KGVycikpXG4gICAgICAgICAgICAgICAgLnRoZW4oKGJsb2I6IEJsb2IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGVja0NvbXByZXNzZWRJbWFnZVNpemUoY2FudmFzLCBibG9iLCBxdWFsaXR5LCBzaXplSW5NQiwgc3RlcClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiByZWplY3QoZXJyKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKChjb21wcmVzc2VkQmxvYjogQmxvYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGNvbXByZXNzZWRCbG9iKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrQ29tcHJlc3NlZEltYWdlU2l6ZShcbiAgICAgICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCxcbiAgICAgICAgYmxvYjogQmxvYixcbiAgICAgICAgcXVhbGl0eTogbnVtYmVyLFxuICAgICAgICBzaXplSW5NQjogbnVtYmVyLFxuICAgICAgICBzdGVwOiBudW1iZXJcbiAgICApOiBQcm9taXNlPEJsb2I+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPEJsb2I+KChyZXNvbHZlLFxuICAgICAgICAgICAgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChzdGVwID4gdGhpcy5NQVhfU1RFUFMpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoTmd4UGljYUVycm9yVHlwZS5OT1RfQkVfQUJMRV9UT19DT01QUkVTU19FTk9VR0gpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmJ5dGVzVG9NQihibG9iLnNpemUpIDwgc2l6ZUluTUIpIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGJsb2IpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdRdWFsaXR5OiBudW1iZXIgPSBxdWFsaXR5IC0gKHF1YWxpdHkgKiAwLjEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1N0ZXA6IG51bWJlciA9IHN0ZXAgKyAxO1xuXG4gICAgICAgICAgICAgICAgLy8gcmVjdXJzaXZlbHkgY29tcHJlc3Npb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0Q29tcHJlc3NlZEltYWdlKGNhbnZhcywgYmxvYi50eXBlLCBuZXdRdWFsaXR5LCBzaXplSW5NQiwgbmV3U3RlcCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHBpY2FSZXNpemUoZmlsZTogRmlsZSwgZnJvbTogSFRNTENhbnZhc0VsZW1lbnQsIHRvOiBIVE1MQ2FudmFzRWxlbWVudCwgb3B0aW9uczogYW55KTogUHJvbWlzZTxGaWxlPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxGaWxlPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBpY2FSZXNpemVyLnJlc2l6ZShmcm9tLCB0bywgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gcmVqZWN0KGVycikpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlc2l6ZWRDYW52YXM6IEhUTUxDYW52YXNFbGVtZW50KSA9PiB0aGlzLnBpY2FSZXNpemVyLnRvQmxvYihyZXNpemVkQ2FudmFzLCBmaWxlLnR5cGUpKVxuICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVSZXNpemVkOiBGaWxlID0gdGhpcy5ibG9iVG9GaWxlKGJsb2IsIGZpbGUubmFtZSwgZmlsZS50eXBlLCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZmlsZVJlc2l6ZWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGJsb2JUb0ZpbGUoYmxvYjogQmxvYiwgbmFtZTogc3RyaW5nLCB0eXBlOiBzdHJpbmcsIGxhc3RNb2RpZmllZDogbnVtYmVyKTogRmlsZSB7XG4gICAgICAgIC8vIHJldHVybiBuZXcgRmlsZShbYmxvYl0sIG5hbWUsIHt0eXBlOiB0eXBlLCBsYXN0TW9kaWZpZWQ6IGxhc3RNb2RpZmllZH0pO1xuICAgICAgICBsZXQgZmlsZSA9IG5ldyBCbG9iKFtibG9iXSwge3R5cGUgOiB0eXBlfSkgYXMgYW55O1xuICAgICAgICBmaWxlLm5hbWUgPSBuYW1lO1xuICAgICAgICBmaWxlLmxhc3RNb2RpZmllZERhdGUgPSBsYXN0TW9kaWZpZWQ7XG4gICAgICAgIHJldHVybiBmaWxlIGFzIEZpbGVcbiAgICB9XG5cbiAgICBwcml2YXRlIGJ5dGVzVG9NQihieXRlczogbnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBieXRlcyAvIDEwNDg1NzY7XG4gICAgfVxufVxuIl19