UNPKG

ngx-image-cropper-facet

Version:
1,891 lines 85 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Injectable, Input, NgModule, Output } from '@angular/core';
import { Observable as Observable$1 } from 'rxjs/Observable';
import { CommonModule } from '@angular/common';
import { DomSanitizer } from '@angular/platform-browser';
var ExifService = (function () {
    function ExifService() {
        /**
         * Private variables
         */
        this._debug = false;
        this._isXmpEnabled = false;
        this._fileType = 'image/jpg';
        this._errorMessage = {
            imageFailedToLoad: 'Could not load image',
            invalidImageFormat: 'Invalid image format provided'
        };
        /**
         * Public variables
         */
        this.exifTags = {
            // version tags
            0x9000: 'ExifVersion',
            0xA000: 'FlashpixVersion',
            // colorspace tags
            0xA001: 'ColorSpace',
            // image configuration
            0xA002: 'PixelXDimension',
            0xA003: 'PixelYDimension',
            0x9101: 'ComponentsConfiguration',
            0x9102: 'CompressedBitsPerPixel',
            // user information
            0x927C: 'MakerNote',
            0x9286: 'UserComment',
            // related file
            0xA004: 'RelatedSoundFile',
            // date and time
            0x9003: 'DateTimeOriginal',
            0x9004: 'DateTimeDigitized',
            0x9290: 'SubsecTime',
            0x9291: 'SubsecTimeOriginal',
            0x9292: 'SubsecTimeDigitized',
            // picture-taking conditions
            0x829A: 'ExposureTime',
            0x829D: 'FNumber',
            0x8822: 'ExposureProgram',
            0x8824: 'SpectralSensitivity',
            0x8827: 'ISOSpeedRatings',
            0x8828: 'OECF',
            0x9201: 'ShutterSpeedValue',
            0x9202: 'ApertureValue',
            0x9203: 'BrightnessValue',
            0x9204: 'ExposureBias',
            0x9205: 'MaxApertureValue',
            0x9206: 'SubjectDistance',
            0x9207: 'MeteringMode',
            0x9208: 'LightSource',
            0x9209: 'Flash',
            0x9214: 'SubjectArea',
            0x920A: 'FocalLength',
            0xA20B: 'FlashEnergy',
            0xA20C: 'SpatialFrequencyResponse',
            0xA20E: 'FocalPlaneXResolution',
            0xA20F: 'FocalPlaneYResolution',
            0xA210: 'FocalPlaneResolutionUnit',
            0xA214: 'SubjectLocation',
            0xA215: 'ExposureIndex',
            0xA217: 'SensingMethod',
            0xA300: 'FileSource',
            0xA301: 'SceneType',
            0xA302: 'CFAPattern',
            0xA401: 'CustomRendered',
            0xA402: 'ExposureMode',
            0xA403: 'WhiteBalance',
            0xA404: 'DigitalZoomRation',
            0xA405: 'FocalLengthIn35mmFilm',
            0xA406: 'SceneCaptureType',
            0xA407: 'GainControl',
            0xA408: 'Contrast',
            0xA409: 'Saturation',
            0xA40A: 'Sharpness',
            0xA40B: 'DeviceSettingDescription',
            0xA40C: 'SubjectDistanceRange',
            // other tags
            0xA005: 'InteroperabilityIFDPointer',
            0xA420: 'ImageUniqueID' // Identifier assigned uniquely to each image
        };
        this.tiffTags = {
            0x0100: 'ImageWidth',
            0x0101: 'ImageHeight',
            0x8769: 'ExifIFDPointer',
            0x8825: 'GPSInfoIFDPointer',
            0xA005: 'InteroperabilityIFDPointer',
            0x0102: 'BitsPerSample',
            0x0103: 'Compression',
            0x0106: 'PhotometricInterpretation',
            0x0112: 'Orientation',
            0x0115: 'SamplesPerPixel',
            0x011C: 'PlanarConfiguration',
            0x0212: 'YCbCrSubSampling',
            0x0213: 'YCbCrPositioning',
            0x011A: 'XResolution',
            0x011B: 'YResolution',
            0x0128: 'ResolutionUnit',
            0x0111: 'StripOffsets',
            0x0116: 'RowsPerStrip',
            0x0117: 'StripByteCounts',
            0x0201: 'JPEGInterchangeFormat',
            0x0202: 'JPEGInterchangeFormatLength',
            0x012D: 'TransferFunction',
            0x013E: 'WhitePoint',
            0x013F: 'PrimaryChromaticities',
            0x0211: 'YCbCrCoefficients',
            0x0214: 'ReferenceBlackWhite',
            0x0132: 'DateTime',
            0x010E: 'ImageDescription',
            0x010F: 'Make',
            0x0110: 'Model',
            0x0131: 'Software',
            0x013B: 'Artist',
            0x8298: 'Copyright'
        };
        this.gpsTags = {
            0x0000: 'GPSVersionID',
            0x0001: 'GPSLatitudeRef',
            0x0002: 'GPSLatitude',
            0x0003: 'GPSLongitudeRef',
            0x0004: 'GPSLongitude',
            0x0005: 'GPSAltitudeRef',
            0x0006: 'GPSAltitude',
            0x0007: 'GPSTimeStamp',
            0x0008: 'GPSSatellites',
            0x0009: 'GPSStatus',
            0x000A: 'GPSMeasureMode',
            0x000B: 'GPSDOP',
            0x000C: 'GPSSpeedRef',
            0x000D: 'GPSSpeed',
            0x000E: 'GPSTrackRef',
            0x000F: 'GPSTrack',
            0x0010: 'GPSImgDirectionRef',
            0x0011: 'GPSImgDirection',
            0x0012: 'GPSMapDatum',
            0x0013: 'GPSDestLatitudeRef',
            0x0014: 'GPSDestLatitude',
            0x0015: 'GPSDestLongitudeRef',
            0x0016: 'GPSDestLongitude',
            0x0017: 'GPSDestBearingRef',
            0x0018: 'GPSDestBearing',
            0x0019: 'GPSDestDistanceRef',
            0x001A: 'GPSDestDistance',
            0x001B: 'GPSProcessingMethod',
            0x001C: 'GPSAreaInformation',
            0x001D: 'GPSDateStamp',
            0x001E: 'GPSDifferential',
            0x001F: 'GPSHPositioningError'
        };
        /**
         * EXIF 2.3 Spec
         */
        this.ifd1Tags = {
            0x0100: 'ImageWidth',
            0x0101: 'ImageHeight',
            0x0102: 'BitsPerSample',
            0x0103: 'Compression',
            0x0106: 'PhotometricInterpretation',
            0x0111: 'StripOffsets',
            0x0112: 'Orientation',
            0x0115: 'SamplesPerPixel',
            0x0116: 'RowsPerStrip',
            0x0117: 'StripByteCounts',
            0x011A: 'XResolution',
            0x011B: 'YResolution',
            0x011C: 'PlanarConfiguration',
            0x0128: 'ResolutionUnit',
            0x0201: 'JpegIFOffset',
            0x0202: 'JpegIFByteCount',
            0x0211: 'YCbCrCoefficients',
            0x0212: 'YCbCrSubSampling',
            0x0213: 'YCbCrPositioning',
            0x0214: 'ReferenceBlackWhite'
        };
        this.stringValues = {
            ExposureProgram: {
                0: 'Not defined',
                1: 'Manual',
                2: 'Normal program',
                3: 'Aperture priority',
                4: 'Shutter priority',
                5: 'Creative program',
                6: 'Action program',
                7: 'Portrait mode',
                8: 'Landscape mode'
            },
            MeteringMode: {
                0: 'Unknown',
                1: 'Average',
                2: 'CenterWeightedAverage',
                3: 'Spot',
                4: 'MultiSpot',
                5: 'Pattern',
                6: 'Partial',
                255: 'Other'
            },
            LightSource: {
                0: 'Unknown',
                1: 'Daylight',
                2: 'Fluorescent',
                3: 'Tungsten (incandescent light)',
                4: 'Flash',
                9: 'Fine weather',
                10: 'Cloudy weather',
                11: 'Shade',
                12: 'Daylight fluorescent (D 5700 - 7100K)',
                13: 'Day white fluorescent (N 4600 - 5400K)',
                14: 'Cool white fluorescent (W 3900 - 4500K)',
                15: 'White fluorescent (WW 3200 - 3700K)',
                17: 'Standard light A',
                18: 'Standard light B',
                19: 'Standard light C',
                20: 'D55',
                21: 'D65',
                22: 'D75',
                23: 'D50',
                24: 'ISO studio tungsten',
                255: 'Other'
            },
            Flash: {
                0x0000: 'Flash did not fire',
                0x0001: 'Flash fired',
                0x0005: 'Strobe return light not detected',
                0x0007: 'Strobe return light detected',
                0x0009: 'Flash fired, compulsory flash mode',
                0x000D: 'Flash fired, compulsory flash mode, return light not detected',
                0x000F: 'Flash fired, compulsory flash mode, return light detected',
                0x0010: 'Flash did not fire, compulsory flash mode',
                0x0018: 'Flash did not fire, auto mode',
                0x0019: 'Flash fired, auto mode',
                0x001D: 'Flash fired, auto mode, return light not detected',
                0x001F: 'Flash fired, auto mode, return light detected',
                0x0020: 'No flash function',
                0x0041: 'Flash fired, red-eye reduction mode',
                0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
                0x0047: 'Flash fired, red-eye reduction mode, return light detected',
                0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
                0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
                0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
                0x0059: 'Flash fired, auto mode, red-eye reduction mode',
                0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
                0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
            },
            SensingMethod: {
                1: 'Not defined',
                2: 'One-chip color area sensor',
                3: 'Two-chip color area sensor',
                4: 'Three-chip color area sensor',
                5: 'Color sequential area sensor',
                7: 'Trilinear sensor',
                8: 'Color sequential linear sensor'
            },
            SceneCaptureType: {
                0: 'Standard',
                1: 'Landscape',
                2: 'Portrait',
                3: 'Night scene'
            },
            SceneType: {
                1: 'Directly photographed'
            },
            CustomRendered: {
                0: 'Normal process',
                1: 'Custom process'
            },
            WhiteBalance: {
                0: 'Auto white balance',
                1: 'Manual white balance'
            },
            GainControl: {
                0: 'None',
                1: 'Low gain up',
                2: 'High gain up',
                3: 'Low gain down',
                4: 'High gain down'
            },
            Contrast: {
                0: 'Normal',
                1: 'Soft',
                2: 'Hard'
            },
            Saturation: {
                0: 'Normal',
                1: 'Low saturation',
                2: 'High saturation'
            },
            Sharpness: {
                0: 'Normal',
                1: 'Soft',
                2: 'Hard'
            },
            SubjectDistanceRange: {
                0: 'Unknown',
                1: 'Macro',
                2: 'Close view',
                3: 'Distant view'
            },
            FileSource: {
                3: 'DSC'
            },
            Components: {
                0: '',
                1: 'Y',
                2: 'Cb',
                3: 'Cr',
                4: 'R',
                5: 'G',
                6: 'B'
            }
        };
        this.iptcFieldMap = {
            0x78: 'caption',
            0x6E: 'credit',
            0x16: 'fixtureID',
            0x19: 'keywords',
            0x37: 'dateCreated',
            0x50: 'byline',
            0x55: 'bylineTitle',
            0x7A: 'captionWriter',
            0x69: 'headline',
            0x74: 'copyright',
            0x0F: 'category'
        };
    }
    /**
     * @return {?}
     */
    ExifService.prototype.enableXmp = function () {
        this._isXmpEnabled = true;
    };
    /**
     * @return {?}
     */
    ExifService.prototype.disableXmp = function () {
        this._isXmpEnabled = false;
    };
    /**
     * @param {?} imageFormat
     * @return {?}
     */
    ExifService.prototype.fileType = function (imageFormat) {
        this._fileType = imageFormat;
    };
    /**
     * @param {?} image
     * @return {?}
     */
    ExifService.prototype.getData = function (image) {
        var _this = this;
        return Observable$1.create(function (observer) {
            _this.getImageData(image).subscribe(function (image) {
                observer.next(image);
            }, function (error) {
                observer.error(error);
            });
        });
    };
    /**
     * @param {?} imageData
     * @param {?} tag
     * @return {?}
     */
    ExifService.prototype.getTag = function (imageData, tag) {
        if (!this.imageHasData(imageData)) {
            return;
        }
        return imageData.exif[tag];
    };
    /**
     * @param {?} imageData
     * @param {?} tag
     * @return {?}
     */
    ExifService.prototype.getIptcTag = function (imageData, tag) {
        if (!this.imageHasData(imageData)) {
            return;
        }
        return imageData.iptc[tag];
    };
    /**
     * @param {?} imageData
     * @return {?}
     */
    ExifService.prototype.getAllTags = function (imageData) {
        if (!this.imageHasData(imageData)) {
            return {};
        }
        var /** @type {?} */ a;
        var /** @type {?} */ data = imageData.exif;
        var /** @type {?} */ tags = {};
        for (a in data) {
            if (data.hasOwnProperty(a)) {
                tags[a] = data[a];
            }
        }
        return tags;
    };
    /**
     * @param {?} imageData
     * @return {?}
     */
    ExifService.prototype.getAllIptcTags = function (imageData) {
        if (!this.imageHasData(imageData)) {
            return {};
        }
        var /** @type {?} */ a;
        var /** @type {?} */ data = imageData.iptc;
        var /** @type {?} */ tags = {};
        for (a in data) {
            if (data.hasOwnProperty(a)) {
                tags[a] = data[a];
            }
        }
        return tags;
    };
    /**
     * @param {?} imageData
     * @return {?}
     */
    ExifService.prototype.pretty = function (imageData) {
        if (!this.imageHasData(imageData)) {
            return '';
        }
        var /** @type {?} */ a;
        var /** @type {?} */ data = imageData.exif;
        var /** @type {?} */ prettyString = '';
        for (a in data) {
            if (data.hasOwnProperty(a)) {
                if (typeof data[a] === 'object') {
                    if (data[a] instanceof Number) {
                        prettyString += a + " : " + data[a] + " [" + data[a].numerator + "/" + data[a].denominator + "]\r\n";
                    }
                    else {
                        prettyString += a + " : [" + data[a].length + " values]\r\n";
                    }
                }
                else {
                    prettyString += a + " : " + data[a] + "\r\n";
                }
            }
        }
        return prettyString;
    };
    /**
     * @param {?} image
     * @return {?}
     */
    ExifService.prototype.getImageData = function (image) {
        var _this = this;
        return Observable$1.create(function (observer) {
            // If the image value provided is a Blob or File then use the file reader
            // to convert the image to an ArrayBuffer so we can extract the Exif, IPTC, XMP data
            if (FileReader && (image instanceof Blob || image instanceof File)) {
                var /** @type {?} */ reader = new FileReader();
                reader.onload = function (event) {
                    var /** @type {?} */ binaryFile = event.target.result;
                    var /** @type {?} */ imageData = _this.findAndSetImageTagData(binaryFile);
                    imageData.onload = function () {
                        observer.next(imageData);
                    };
                    imageData = _this.addImageSourceFromArrayBuffer(imageData, binaryFile);
                };
                if (image instanceof Blob) {
                    reader.readAsArrayBuffer(image);
                }
                else {
                    reader.readAsDataURL(image);
                }
            }
            else if (image instanceof ArrayBuffer) {
                var /** @type {?} */ imageData_1 = _this.findAndSetImageTagData(image);
                imageData_1.onload = function () {
                    observer.next(imageData_1);
                };
                imageData_1 = _this.addImageSourceFromArrayBuffer(imageData_1, image);
            }
            else if (image instanceof HTMLImageElement) {
                var /** @type {?} */ imageSource = image.src;
                // it take a long time to test the entire image string with
                // the initial regex and the "data" portion we are testing for
                // is always at the beginning so let's trim the string and only
                // test what needs to be tested.
                var /** @type {?} */ fileToTest = imageSource.slice(0, 25);
                if (/^data\:/i.test(fileToTest)) {
                    var /** @type {?} */ arrayBuffer = _this.base64ToArrayBuffer(imageSource);
                    var /** @type {?} */ imageData_2 = _this.findAndSetImageTagData(arrayBuffer);
                    imageData_2.onload = function () {
                        observer.next(imageData_2);
                    };
                    imageData_2 = _this.addImageSource(imageData_2, imageSource);
                }
                else if (/^blob\:/i.test(fileToTest)) {
                    var /** @type {?} */ fileReader_1 = new FileReader();
                    fileReader_1.onload = function (event) {
                        var /** @type {?} */ binaryFile = event.target.result;
                        var /** @type {?} */ imageData = _this.findAndSetImageTagData(binaryFile);
                        imageData.onload = function () {
                            observer.next(imageData);
                        };
                        imageData = _this.addImageSourceFromArrayBuffer(imageData, binaryFile);
                    };
                    _this.objectURLToBlob(imageSource, function (blob) {
                        fileReader_1.readAsArrayBuffer(blob);
                    });
                }
                else {
                    var /** @type {?} */ http_1 = new XMLHttpRequest();
                    http_1.onload = function () {
                        if (http_1.status == 200 || http_1.status === 0) {
                            var /** @type {?} */ binaryFile = http_1.response;
                            var /** @type {?} */ imageData_3 = _this.findAndSetImageTagData(binaryFile);
                            imageData_3.onload = function () {
                                observer.next(imageData_3);
                            };
                            imageData_3 = _this.addImageSourceFromArrayBuffer(imageData_3, binaryFile);
                        }
                        else {
                            observer.error(_this._errorMessage.imageFailedToLoad);
                        }
                    };
                    http_1.open('GET', imageSource, true);
                    http_1.responseType = 'arraybuffer';
                    http_1.send(null);
                }
            }
            else {
                var /** @type {?} */ imageSource = ((image));
                var /** @type {?} */ stringToTest = imageSource.slice(0, 25);
                if (/^data\:/i.test(stringToTest)) {
                    var /** @type {?} */ arrayBuffer = _this.base64ToArrayBuffer(imageSource);
                    var /** @type {?} */ imageData_4 = _this.findAndSetImageTagData(arrayBuffer);
                    imageData_4.onload = function () {
                        observer.next(imageData_4);
                    };
                    imageData_4 = _this.addImageSource(imageData_4, imageSource);
                }
                else {
                    observer.error(_this._errorMessage.invalidImageFormat);
                }
            }
        });
    };
    /**
     * @param {?} binaryFile
     * @return {?}
     */
    ExifService.prototype.findAndSetImageTagData = function (binaryFile) {
        var /** @type {?} */ exifData = this.findEXIFinJPEG(binaryFile);
        var /** @type {?} */ iptcData = this.findIPTCinJPEG(binaryFile);
        var /** @type {?} */ image = new Image();
        var /** @type {?} */ data = ((image));
        data.exif = exifData || {};
        data.iptc = iptcData || {};
        if (this._isXmpEnabled) {
            data.xmp = this.findXMPinJPEG(binaryFile);
        }
        return data;
    };
    /**
     * @param {?} data
     * @param {?} binaryFile
     * @return {?}
     */
    ExifService.prototype.addImageSourceFromArrayBuffer = function (data, binaryFile) {
        var /** @type {?} */ base64Image = this.arrayBufferToBase64(binaryFile);
        var /** @type {?} */ properBase64Image = "data:" + this._fileType + ";base64," + base64Image;
        return this.addImageSource(data, properBase64Image);
    };
    /**
     * @param {?} data
     * @param {?} imageString
     * @return {?}
     */
    ExifService.prototype.addImageSource = function (data, imageString) {
        data.src = imageString;
        return data;
    };
    /**
     * Convert the ArrayBuffer to a base 64 string
     *
     * @param {?} buffer ArrayBuffer returned from the file reader
     *
     * @return {?} A base64 string of the provided image
     */
    ExifService.prototype.arrayBufferToBase64 = function (buffer) {
        var /** @type {?} */ binary = '';
        var /** @type {?} */ bytes = new Uint8Array(buffer);
        var /** @type {?} */ length = bytes.byteLength;
        for (var /** @type {?} */ i = 0; i < length; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    };
    /**
     * @param {?} base64
     * @return {?}
     */
    ExifService.prototype.base64ToArrayBuffer = function (base64) {
        base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
        var /** @type {?} */ binary = atob(base64);
        var /** @type {?} */ len = binary.length;
        var /** @type {?} */ buffer = new ArrayBuffer(len);
        var /** @type {?} */ view = new Uint8Array(buffer);
        for (var /** @type {?} */ i = 0; i < len; i++) {
            view[i] = binary.charCodeAt(i);
        }
        return buffer;
    };
    /**
     * @param {?} url
     * @param {?} callback
     * @return {?}
     */
    ExifService.prototype.objectURLToBlob = function (url, callback) {
        var /** @type {?} */ http = new XMLHttpRequest();
        http.open('GET', url, true);
        http.responseType = 'blob';
        http.onload = function () {
            if (http.status == 200 || http.status === 0) {
                callback(http.response);
            }
        };
        http.send();
    };
    /**
     * @param {?} file
     * @return {?}
     */
    ExifService.prototype.findEXIFinJPEG = function (file) {
        var /** @type {?} */ dataView = new DataView(file);
        this.log("Got file of length " + file.byteLength);
        if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
            this.log('Not a valid JPEG');
            return false; // not a valid jpeg
        }
        var /** @type {?} */ offset = 2;
        var /** @type {?} */ length = file.byteLength;
        var /** @type {?} */ marker;
        while (offset < length) {
            if (dataView.getUint8(offset) != 0xFF) {
                this.log("Not a valid marker at offset " + offset + ", found: " + dataView.getUint8(offset));
                return false; // not a valid marker, something is wrong
            }
            marker = dataView.getUint8(offset + 1);
            this.log(marker);
            // we could implement handling for other markers here,
            // but we're only looking for 0xFFE1 for EXIF data
            if (marker == 225) {
                this.log('Found 0xFFE1 marker');
                return this.readEXIFData(dataView, offset + 4);
            }
            else {
                offset += 2 + dataView.getUint16(offset + 2);
            }
        }
    };
    /**
     * @param {?} file
     * @return {?}
     */
    ExifService.prototype.findIPTCinJPEG = function (file) {
        var /** @type {?} */ dataView = new DataView(file);
        this.log("Got file of length " + file.byteLength);
        if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
            this.log('Not a valid JPEG');
            return false; // not a valid jpeg
        }
        var /** @type {?} */ offset = 2;
        var /** @type {?} */ length = file.byteLength;
        var /** @type {?} */ isFieldSegmentStart = function (view, _offset) {
            return (view.getUint8(_offset) === 0x38 &&
                view.getUint8(_offset + 1) === 0x42 &&
                view.getUint8(_offset + 2) === 0x49 &&
                view.getUint8(_offset + 3) === 0x4D &&
                view.getUint8(_offset + 4) === 0x04 &&
                view.getUint8(_offset + 5) === 0x04);
        };
        while (offset < length) {
            if (isFieldSegmentStart(dataView, offset)) {
                // Get the length of the name header (which is padded to an even number of bytes)
                var /** @type {?} */ nameHeaderLength = dataView.getUint8(offset + 7);
                if (nameHeaderLength % 2 !== 0) {
                    nameHeaderLength += 1;
                }
                // Check for pre photoshop 6 format
                if (nameHeaderLength === 0) {
                    // Always 4
                    nameHeaderLength = 4;
                }
                var /** @type {?} */ startOffset = offset + 8 + nameHeaderLength;
                var /** @type {?} */ sectionLength = dataView.getUint16(offset + 6 + nameHeaderLength);
                return this.readIPTCData(file, startOffset, sectionLength);
            }
            // Not the marker, continue searching
            offset++;
        }
    };
    /**
     * @param {?} file
     * @param {?} startOffset
     * @param {?} sectionLength
     * @return {?}
     */
    ExifService.prototype.readIPTCData = function (file, startOffset, sectionLength) {
        var /** @type {?} */ dataView = new DataView(file);
        var /** @type {?} */ data = {};
        var /** @type {?} */ fieldValue, /** @type {?} */ fieldName, /** @type {?} */ dataSize, /** @type {?} */ segmentType;
        var /** @type {?} */ segmentStartPos = startOffset;
        while (segmentStartPos < startOffset + sectionLength) {
            if (dataView.getUint8(segmentStartPos) === 0x1C && dataView.getUint8(segmentStartPos + 1) === 0x02) {
                segmentType = dataView.getUint8(segmentStartPos + 2);
                if (segmentType in this.iptcFieldMap) {
                    dataSize = dataView.getInt16(segmentStartPos + 3);
                    fieldName = this.iptcFieldMap[segmentType];
                    fieldValue = this.getStringFromDB(dataView, segmentStartPos + 5, dataSize);
                    // Check if we already stored a value with this name
                    if (data.hasOwnProperty(fieldName)) {
                        // Value already stored with this name, create multivalue field
                        if (data[fieldName] instanceof Array) {
                            data[fieldName].push(fieldValue);
                        }
                        else {
                            data[fieldName] = [data[fieldName], fieldValue];
                        }
                    }
                    else {
                        data[fieldName] = fieldValue;
                    }
                }
            }
            segmentStartPos++;
        }
        return data;
    };
    /**
     * @param {?} file
     * @param {?} tiffStart
     * @param {?} dirStart
     * @param {?} strings
     * @param {?} bigEnd
     * @return {?}
     */
    ExifService.prototype.readTags = function (file, tiffStart, dirStart, strings, bigEnd) {
        var /** @type {?} */ entries = file.getUint16(dirStart, !bigEnd);
        var /** @type {?} */ tags = {};
        var /** @type {?} */ entryOffset;
        var /** @type {?} */ tag;
        for (var /** @type {?} */ i = 0; i < entries; i++) {
            entryOffset = dirStart + i * 12 + 2;
            tag = strings[file.getUint16(entryOffset, !bigEnd)];
            if (!tag) {
                this.log('Unknown tag: ' + file.getUint16(entryOffset, !bigEnd));
            }
            tags[tag] = this.readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd);
        }
        return tags;
    };
    /**
     * @param {?} file
     * @param {?} entryOffset
     * @param {?} tiffStart
     * @param {?} dirStart
     * @param {?} bigEnd
     * @return {?}
     */
    ExifService.prototype.readTagValue = function (file, entryOffset, tiffStart, dirStart, bigEnd) {
        var /** @type {?} */ type = file.getUint16(entryOffset + 2, !bigEnd);
        var /** @type {?} */ numValues = file.getUint32(entryOffset + 4, !bigEnd);
        var /** @type {?} */ valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart;
        var /** @type {?} */ offset;
        var /** @type {?} */ vals, /** @type {?} */ val, /** @type {?} */ n;
        var /** @type {?} */ numerator;
        var /** @type {?} */ denominator;
        switch (type) {
            case 1: // byte, 8-bit unsigned int
            case 7:// undefined, 8-bit byte, value depending on field
                if (numValues === 1) {
                    return file.getUint8(entryOffset + 8, !bigEnd);
                }
                else {
                    offset = numValues > 4 ? valueOffset : (entryOffset + 8);
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        vals[n] = file.getUint8(offset + n);
                    }
                    return vals;
                }
            case 2:// ascii, 8-bit byte
                offset = numValues > 4 ? valueOffset : (entryOffset + 8);
                return this.getStringFromDB(file, offset, numValues - 1);
            case 3:// short, 16 bit int
                if (numValues === 1) {
                    return file.getUint16(entryOffset + 8, !bigEnd);
                }
                else {
                    offset = numValues > 2 ? valueOffset : (entryOffset + 8);
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        vals[n] = file.getUint16(offset + 2 * n, !bigEnd);
                    }
                    return vals;
                }
            case 4:// long, 32 bit int
                if (numValues === 1) {
                    return file.getUint32(entryOffset + 8, !bigEnd);
                }
                else {
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd);
                    }
                    return vals;
                }
            case 5:// rational = two long values, first is numerator, second is denominator
                if (numValues === 1) {
                    numerator = file.getUint32(valueOffset, !bigEnd);
                    denominator = file.getUint32(valueOffset + 4, !bigEnd);
                    return {
                        numerator: numerator,
                        denominator: denominator,
                        value: numerator / denominator
                    };
                }
                else {
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        numerator = file.getUint32(valueOffset + 8 * n, !bigEnd);
                        denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd);
                        vals[n] = {
                            numerator: numerator,
                            denominator: denominator,
                            value: numerator / denominator
                        };
                    }
                    return vals;
                }
            case 9:// slong, 32 bit signed int
                if (numValues === 1) {
                    return file.getInt32(entryOffset + 8, !bigEnd);
                }
                else {
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        vals[n] = file.getInt32(valueOffset + 4 * n, !bigEnd);
                    }
                    return vals;
                }
            case 10:// signed rational, two slongs, first is numerator, second is denominator
                if (numValues === 1) {
                    var /** @type {?} */ numerator_1 = file.getInt32(valueOffset, !bigEnd);
                    var /** @type {?} */ denominator_1 = file.getInt32(valueOffset + 4, !bigEnd);
                    return numerator_1 / denominator_1;
                }
                else {
                    vals = [];
                    for (n = 0; n < numValues; n++) {
                        var /** @type {?} */ numerator_2 = file.getInt32(valueOffset + 8 * n, !bigEnd);
                        var /** @type {?} */ denominator_2 = file.getInt32(valueOffset + 4 + 8 * n, !bigEnd);
                        vals[n] = numerator_2 / denominator_2;
                    }
                    return vals;
                }
            default:
                break;
        }
    };
    /**
     * @param {?} dataView
     * @param {?} tiffStart
     * @param {?} firstIFDOffset
     * @param {?} bigEnd
     * @return {?}
     */
    ExifService.prototype.readThumbnailImage = function (dataView, tiffStart, firstIFDOffset, bigEnd) {
        // get the IFD1 offset
        var /** @type {?} */ IFD1OffsetPointer = this.getNextIFDOffset(dataView, tiffStart + firstIFDOffset, bigEnd);
        if (!IFD1OffsetPointer) {
            return {};
        }
        else if (IFD1OffsetPointer > dataView.byteLength) {
            // this should not happen
            return {};
        }
        var /** @type {?} */ thumbTags = this.readTags(dataView, tiffStart, tiffStart + IFD1OffsetPointer, this.ifd1Tags, bigEnd);
        // EXIF 2.3 specification for JPEG format thumbnail
        // If the value of Compression(0x0103) Tag in IFD1 is '6', thumbnail image format is JPEG.
        // Most of Exif image uses JPEG format for thumbnail. In that case, you can get offset of thumbnail
        // by JpegIFOffset(0x0201) Tag in IFD1, size of thumbnail by JpegIFByteCount(0x0202) Tag.
        // Data format is ordinary JPEG format, starts from 0xFFD8 and ends by 0xFFD9. It seems that
        // JPEG format and 160x120pixels of size are recommended thumbnail format for Exif2.1 or later.
        if (thumbTags['Compression']) {
            switch (thumbTags['Compression']) {
                case 6:
                    if (thumbTags['JpegIFOffset'] && thumbTags['JpegIFByteCount']) {
                        // extract the thumbnail
                        var /** @type {?} */ tOffset = tiffStart + thumbTags['JpegIFOffset'];
                        var /** @type {?} */ tLength = thumbTags['JpegIFByteCount'];
                        thumbTags['blob'] = new Blob([new Uint8Array(dataView.buffer, tOffset, tLength)], {
                            type: 'image/jpeg'
                        });
                    }
                    break;
                case 1:
                    this.log('Thumbnail image format is TIFF, which is not implemented.');
                    break;
                default:
                    this.log("Unknown thumbnail image format: " + thumbTags['Compression']);
            }
        }
        else if (thumbTags['PhotometricInterpretation'] == 2) {
            this.log('Thumbnail image format is RGB, which is not implemented.');
        }
        return thumbTags;
    };
    /**
     * Given an IFD (Image File Directory) start offset
     * returns an offset to next IFD or 0 if it's the last IFD.
     * @param {?} dataView
     * @param {?} dirStart
     * @param {?} bigEnd
     * @return {?}
     */
    ExifService.prototype.getNextIFDOffset = function (dataView, dirStart, bigEnd) {
        //the first 2bytes means the number of directory entries contains in this IFD
        var /** @type {?} */ entries = dataView.getUint16(dirStart, !bigEnd);
        // After last directory entry, there is a 4bytes of data,
        // it means an offset to next IFD.
        // If its value is '0x00000000', it means this is the last IFD and there is no linked IFD.
        return dataView.getUint32(dirStart + 2 + entries * 12, !bigEnd); // each entry is 12 bytes long
    };
    /**
     * @param {?} file
     * @param {?} start
     * @return {?}
     */
    ExifService.prototype.readEXIFData = function (file, start) {
        if (this.getStringFromDB(file, start, 4) != 'Exif') {
            this.log("Not valid EXIF data! " + this.getStringFromDB(file, start, 4));
            return false;
        }
        var /** @type {?} */ bigEnd, /** @type {?} */ tags, /** @type {?} */ tag, /** @type {?} */ exifData, /** @type {?} */ gpsData;
        var /** @type {?} */ tiffOffset = start + 6;
        // test for TIFF validity and endianness
        if (file.getUint16(tiffOffset) == 0x4949) {
            bigEnd = false;
        }
        else if (file.getUint16(tiffOffset) == 0x4D4D) {
            bigEnd = true;
        }
        else {
            this.log('Not valid TIFF data! (no 0x4949 or 0x4D4D)');
            return false;
        }
        if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) {
            this.log('Not valid TIFF data! (no 0x002A)');
            return false;
        }
        var /** @type {?} */ firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd);
        if (firstIFDOffset < 0x00000008) {
            this.log('Not valid TIFF data! (First offset less than 8)', file.getUint32(tiffOffset + 4, !bigEnd));
            return false;
        }
        tags = this.readTags(file, tiffOffset, tiffOffset + firstIFDOffset, this.tiffTags, bigEnd);
        if (tags.ExifIFDPointer) {
            exifData = this.readTags(file, tiffOffset, tiffOffset + tags.ExifIFDPointer, this.exifTags, bigEnd);
            for (tag in exifData) {
                switch (tag) {
                    case 'LightSource':
                    case 'Flash':
                    case 'MeteringMode':
                    case 'ExposureProgram':
                    case 'SensingMethod':
                    case 'SceneCaptureType':
                    case 'SceneType':
                    case 'CustomRendered':
                    case 'WhiteBalance':
                    case 'GainControl':
                    case 'Contrast':
                    case 'Saturation':
                    case 'Sharpness':
                    case 'SubjectDistanceRange':
                    case 'FileSource':
                        exifData[tag] = this.stringValues[tag][exifData[tag]];
                        break;
                    case 'ExifVersion':
                    case 'FlashpixVersion':
                        exifData[tag] = String.fromCharCode(exifData[tag][0], exifData[tag][1], exifData[tag][2], exifData[tag][3]);
                        break;
                    case 'ComponentsConfiguration':
                        exifData[tag] =
                            this.stringValues.Components[exifData[tag][0]] +
                                this.stringValues.Components[exifData[tag][1]] +
                                this.stringValues.Components[exifData[tag][2]] +
                                this.stringValues.Components[exifData[tag][3]];
                        break;
                    default:
                        break;
                }
                tags[tag] = exifData[tag];
            }
        }
        if (tags.GPSInfoIFDPointer) {
            gpsData = this.readTags(file, tiffOffset, tiffOffset + tags.GPSInfoIFDPointer, this.gpsTags, bigEnd);
            for (tag in gpsData) {
                switch (tag) {
                    case 'GPSVersionID':
                        // Skip broken GPSVersionID - iggfisk
                        // https://github.com/exif-js/exif-js/pull/161
                        if (gpsData[tag]) {
                            gpsData[tag] = gpsData[tag][0] + "." + gpsData[tag][1] + "." + gpsData[tag][2] + "." + gpsData[tag][3];
                        }
                        break;
                    default:
                        break;
                }
                tags[tag] = gpsData[tag];
            }
        }
        // extract thumbnail
        tags.thumbnail = this.readThumbnailImage(file, tiffOffset, firstIFDOffset, bigEnd);
        return tags;
    };
    /**
     * @param {?} buffer
     * @param {?} start
     * @param {?} length
     * @return {?}
     */
    ExifService.prototype.getStringFromDB = function (buffer, start, length) {
        var /** @type {?} */ outputString = '';
        for (var /** @type {?} */ n = start; n < start + length; n++) {
            outputString += String.fromCharCode(buffer.getUint8(n));
        }
        return outputString;
    };
    /**
     * @param {?} file
     * @return {?}
     */
    ExifService.prototype.findXMPinJPEG = function (file) {
        if (!('DOMParser' in self)) {
            return;
        }
        var /** @type {?} */ dataView = new DataView(file);
        this.log("Got file of length " + file.byteLength);
        if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
            this.log('Not a valid JPEG');
            return false; // not a valid jpeg
        }
        var /** @type {?} */ offset = 2;
        var /** @type {?} */ length = file.byteLength;
        var /** @type {?} */ dom = new DOMParser();
        while (offset < (length - 4)) {
            if (this.getStringFromDB(dataView, offset, 4) == 'http') {
                var /** @type {?} */ startOffset = offset - 1;
                var /** @type {?} */ sectionLength = dataView.getUint16(offset - 2) - 1;
                var /** @type {?} */ xmpString = this.getStringFromDB(dataView, startOffset, sectionLength);
                var /** @type {?} */ xmpEndIndex = xmpString.indexOf('xmpmeta>') + 8;
                xmpString = xmpString.substring(xmpString.indexOf('<x:xmpmeta'), xmpEndIndex);
                var /** @type {?} */ indexOfXmp = xmpString.indexOf('x:xmpmeta') + 10;
                // Many custom written programs embed xmp/xml without any namespace. Following are some of them.
                // Without these namespaces, XML is thought to be invalid by parsers
                xmpString = xmpString.slice(0, indexOfXmp)
                    + 'xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" '
                    + 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
                    + 'xmlns:tiff="http://ns.adobe.com/tiff/1.0/" '
                    + 'xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus" '
                    + 'xmlns:ext="http://www.gettyimages.com/xsltExtension/1.0" '
                    + 'xmlns:exif="http://ns.adobe.com/exif/1.0/" '
                    + 'xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" '
                    + 'xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" '
                    + 'xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/" '
                    + 'xmlns:xapGImg="http://ns.adobe.com/xap/1.0/g/img/" '
                    + 'xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/" '
                    + xmpString.slice(indexOfXmp);
                var /** @type {?} */ domDocument = dom.parseFromString(xmpString, 'text/xml');
                return this.xml2Object(domDocument);
            }
            else {
                offset++;
            }
        }
    };
    /**
     * @param {?} xml
     * @return {?}
     */
    ExifService.prototype.xml2json = function (xml) {
        var /** @type {?} */ json = {};
        if (xml.nodeType == 1) {
            if (xml.attributes.length > 0) {
                json['@attributes'] = {};
                for (var /** @type {?} */ j = 0; j < xml.attributes.length; j++) {
                    var /** @type {?} */ attribute = xml.attributes.item(j);
                    json['@attributes'][attribute.nodeName] = attribute.nodeValue;
                }
            }
        }
        else if (xml.nodeType == 3) {
            return xml.nodeValue;
        }
        // deal with children
        if (xml.hasChildNodes()) {
            for (var /** @type {?} */ i = 0; i < xml.childNodes.length; i++) {
                var /** @type {?} */ child = xml.childNodes.item(i);
                var /** @type {?} */ nodeName = child.nodeName;
                if (json[nodeName] == null) {
                    json[nodeName] = this.xml2json(child);
                }
                else {
                    if (json[nodeName].push == null) {
                        var /** @type {?} */ old = json[nodeName];
                        json[nodeName] = [];
                        json[nodeName].push(old);
                    }
                    json[nodeName].push(this.xml2json(child));
                }
            }
        }
        return json;
    };
    /**
     * @param {?} xml
     * @return {?}
     */
    ExifService.prototype.xml2Object = function (xml) {
        var /** @type {?} */ obj = {};
        if (xml.children.length > 0) {
            try {
                for (var /** @type {?} */ i = 0; i < xml.children.length; i++) {
                    var /** @type {?} */ item = xml.children.item(i);
                    var /** @type {?} */ attributes = item.attributes;
                    for (var /** @type {?} */ idx in attributes) {
                        var /** @type {?} */ itemAtt = attributes[idx];
                        var /** @type {?} */ dataKey = itemAtt.nodeName;
                        var /** @type {?} */ dataValue = itemAtt.nodeValue;
                        if (dataKey !== undefined) {
                            obj[dataKey] = dataValue;
                        }
                    }
                    var /** @type {?} */ nodeName = item.nodeName;
                    if (typeof (obj[nodeName]) == 'undefined') {
                        obj[nodeName] = this.xml2json(item);
                    }
                    else {
                        if (typeof (obj[nodeName].push) == 'undefined') {
                            var /** @type {?} */ old = obj[nodeName];
                            obj[nodeName] = [];
                            obj[nodeName].push(old);
                        }
                        obj[nodeName].push(this.xml2json(item));
                    }
                }
            }
            catch (error) {
                this.log(error.message);
            }
        }
        else {
            obj = xml.textContent;
        }
        return obj;
    };
    /**
     * @param {?} imageData
     * @return {?}
     */
    ExifService.prototype.imageHasData = function (imageData) {
        return !!(imageData.exif);
    };
    /**
     * @param {...?} args
     * @return {?}
     */
    ExifService.prototype.log = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        if (this._debug) {
            console.log(args);
        }
    };
    return ExifService;
}());
ExifService.decorators = [
    { type: Injectable },
];
/**
 * @nocollapse
 */
ExifService.ctorParameters = function () { return []; };
var ImageCropperExifService = (function () {
    function ImageCropperExifService() {
        this.invalidImageFormatProvided = 'Invalid image format provided.';
    }
    /**
     * Check the image orientation from the EXIF data associated with the image.
     * If necessary, rotate and flip the image based on the orientation parameter.
     *
     * @param {?} image Original image provided by the user
     * @param {?} originalFileType File type of the image that was provided
     *
     * @return {?} An Observable containing either the original image if the orientation
     *          value is 1 or the modified image if the orientation is not 1.
     */
    ImageCropperExifService.prototype.getOrientedImage = function (image, originalFileType) {
        var _this = this;
        return Observable$1.create(function (observer) {
            if (!image) {
                observer.error(new Error(_this.invalidImageFormatProvided));
                return;
            }
            var /** @type {?} */ exifService = new ExifService();
            exifService.fileType(originalFileType);
            exifService.getData(image).subscribe(function (imageData) {
                var /** @type {?} */ imageOrientation = exifService.getTag(imageData, "Orientation");
                // if the orientation is set to 1, exit because we do not
                // need to do anything with the image as it is already in
                // the proper orientation
                if (!imageOrientation || imageOrientation === 1) {
                    observer.next(imageData);
                    return;
                }
                var /** @type {?} */ width = imageData.width;
                if (width === 0 && imageData.exif.ImageWidth > 0) {
                    width = imageData.exif.ImageWidth;
                    imageData.width = width;
                }
                var /** @type {?} */ height = imageData.height;
                if (height === 0 && imageData.exif.ImageHeight > 0) {
                    height = imageData.exif.ImageHeight;
                    imageData.height = height;
                }
                var /** @type {?} */ destinationParameters = _this.destinationParameters(imageOrientation, width, height);
                _this.modifyImage(destinationParameters, imageData, originalFileType).subscribe(function (modifiedImage) {
                    // Return the modified image
                    observer.next(modifiedImage);
                }, function (error) {
                    observer.error(new Error(error));
                });
            }, function (error) {
                observer.error(new Error(error));
            });
        });
    };
    /**
     * Determine the parameters to use for the destination canvas so that images
     * are not rotated horizontally when taking a photo on a mobile device.
     *
     * @param {?} imageOrientation The orientation of the image as extracted from the EXIF data
     * @param {?} width Original width of the provided image
     * @param {?} height Original height of the provided image
     *
     * @return {?} Canvas destination values
     */
    ImageCropperExifService.prototype.destinationParameters = function (imageOrientation, width, height) {
        var /** @type {?} */ destinationX = 0;
        var /** @type {?} */ destinationY = 0;
        var /** @type {?} */ destinationWidth = width;
        var /** @type {?} */ destinationHeight = height;
        var /** @type {?} */ rotationDegree = 0;
        switch (imageOrientation) {
            case 3:
            case 4:
                destinationX = -width;
                destinationY = -height;
                rotationDegree = 180;
                break;
            case 5:
            case 6:
                destinationWidth = height;
                destinationHeight = width;
                destinationY = -height;
                rotationDegree = 90;
                break;
            case 7:
            case 8:
                destinationWidth = height;
                destinationHeight = width;
                destinationX = -width;
                rotationDegree = 270;
                break;
            default:
                break;
        }
        return {
            x: destinationX,
            y: destinationY,
            width: destinationWidth,
            height: destinationHeight,
            rotationDegree: rotationDegree,
            imageOrientation: imageOrientation
        };
    };
    /**
     * Check the image orientation and modify the image if necessary
     *
     * @param {?} destinationParameters Parameters to use for the new image. i.e. height, width, rotation, etc.
     * @param {?} image The image to be modified
     * @param {?} fileType
     * @return {?} A new Image that has been rotated so that it appears in portait mode rather than landscape
     */
    ImageCropperExifService.prototype.modifyImage = function (destinationParameters, image, fileType) {
        return Observable$1.create(function (observer) {
            var /** @type {?} */ rotateCanvas = document.createElement("canvas");
            var /** @type {?} */ rotateContext = (rotateCanvas.getContext('2d'));
            rotateCanvas.width = destinationParameters.width;
            rotateCanvas.height = destinationParameters.height;
            if (rotateContext) {
                if ([2, 4, 5, 7].indexOf(destinationParameters.imageOrientation) > -1) {
                    // flip image
                    rotateContext.translate(destinationParameters.width, 0);
                    rotateContext.scale(-1, 1);
                }
                // Rotate the image as necessary by converting degrees to radians.
                // The rotationDegree should only be set to something other than 0
                // when the image provided is from a mobile device.
                rotateContext.rotate(destinationParameters.rotationDegree * Math.PI / 180);
                rotateContext.drawImage(image, destinationParameters.x, destinationParameters.y);
                var /** @type {?} */ modifiedImage_1 = new Image();
                modifiedImage_1.width = destinationParameters.width;
                modifiedImage_1.height = destinationParameters.height;
                modifiedImage_1.onload = function () {
                    observer.next(modifiedImage_1);
                };
                modifiedImage_1.src = rotateCanvas.toDataURL(fileType, 1);
            }
            else {
                observer.next(image);
            }
        });
    };
    return ImageCropperExifService;
}());
ImageCropperExifService.decorators = [
    { type: Injectable },
];
/**
 * @nocollapse
 */
ImageCropperExifService.ctorParameters = function () { return []; };
var ImageCropperComponent = (function () {
    /**
     * @param {?} elementRef
     * @param {?} sanitizer
     * @param {?} cd
     * @param {?} exifService
     */
    function ImageCropperComponent(elementRef, sanitizer, cd, exifService) {
        this.elementRef = elementRef;
        this.sanitizer = sanitizer;
        this.cd = cd;
        this.exifService = exifService;
        this.marginLeft = '0px';
        this.imageVisible = false;
        this.format = 'png';
        this.maintainAspectRatio = true;
        this.aspectRatio = 1;
        this.resizeToWidth = 0;
        this.onlyScaleDown = false;
        this.imageQuality = 92;
        this.cropper = {
            x1: -100,
            y1: -100,
            x2: 10000,
            y2: 10000
        };
        this.imageCropped = new EventEmitter();
        this.imageLoaded = new EventEmitter();
        this.loadImageFailed = new EventEmitter();
        this.initCropper();
    }
    Object.defineProperty(ImageCropperComponent.prototype, "imageChangedEvent", {
        /**
         * @param {?} event
         * @return {?}
         */
        set: function (event) {
            this.initCropper();
            if (event && event.target && event.target.files && event.target.files.length > 0) {
                this.loadImage(event);
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(ImageCropperComponent.prototype, "imageBase64", {
        /**
         * @param {?} imageBase64
         * @return {?}
         */
        set: function (imageBase64) {
            this.initCropper();
            this.loadBase64Image(imageBase64);
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @param {?} changes
     * @return {?}
     */
    ImageCropperComponent.prototype.ngOnChanges = function (changes) {
        var _this = this;
        if (changes['cropper']) {
            setTimeout(function () {
                _this.setMaxSize();
                _this.checkCropperPosition(false);
                _this.crop();
                _this.cd.markForCheck();
            });
        }
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.initCropper = function () {
        this.imageVisible = false;
        this.originalImage = null;
        this.safeImgDataUrl = 'data:image/png;base64,iVBORw0KGg'
            + 'oAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAU'
            + 'AAarVyFEAAAAASUVORK5CYII=';
        this.moveStart = {
            active: false,
            type: null,
            position: null,
            x1: 0,
            y1: 0,
            x2: 0,
            y2: 0,
            clientX: 0,
            clientY: 0
        };
        this.maxSize = {
            width: 0,
            height: 0
        };
        this.originalSize = {
            width: 0,
            height: 0
        };
        this.cropper.x1 = -100;
        this.cropper.y1 = -100;
        this.cropper.x2 = 10000;
        this.cropper.y2 = 10000;
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.loadImage = function (event) {
        var _this = this;
        var /** @type {?} */ file = event.target.files[0];
        // Check the file type to see if a match is found.
        // If a match is found then the file uploaded is a valid image type
        if (/(jpe?g|png|gif)/i.test(file.type) === false) {
            this.loadImageFailed.emit();
            return;
        }
        var /** @type {?} */ fileReader = new FileReader();
        fileReader.onloadend = function (loadEvent) {
            var /** @type {?} */ image = loadEvent.target.result;
            _this.exifService.getOrientedImage(image, file.type).subscribe(function (modifiedImage) {
                _this.loadBase64Image(modifiedImage.src);
            }, function (error) {
                _this.loadImageFailed.emit();
            });
        };
        fileReader.readAsArrayBuffer(file);
    };
    /**
     * @param {?} imageBase64
     * @return {?}
     */
    ImageCropperComponent.prototype.loadBase64Image = function (imageBase64) {
        var _this = this;
        this.originalImage = new Image();
        this.originalImage.onload = function () {
            _this.originalSize.width = _this.originalImage.width;
            _this.originalSize.height = _this.originalImage.height;
            _this.cd.markForCheck();
        };
        this.safeImgDataUrl = this.sanitizer.bypassSecurityTrustResourceUrl(imageBase64);
        this.originalImage.src = imageBase64;
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.imageLoadedInView = function () {
        var _this = this;
        if (this.originalImage != null) {
            this.imageLoaded.emit();
            setTimeout(function () {
                _this.setMaxSize();
                _this.resetCropperPosition();
                _this.cd.markForCheck();
            });
        }
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.imageResizedInView = function (event) {
        this.resizeCropperPosition();
        this.setMaxSize();
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.resizeCropperPosition = function () {
        var /** @type {?} */ displayedImage = this.elementRef.nativeElement.querySelector('.source-image');
        if (this.maxSize.width !== displayedImage.offsetWidth || this.maxSize.height !== displayedImage.offsetHeight) {
            this.cropper.x1 = this.cropper.x1 * displayedImage.offsetWidth / this.maxSize.width;
            this.cropper.x2 = this.cropper.x2 * displayedImage.offsetWidth / this.maxSize.width;
            this.cropper.y1 = this.cropper.y1 * displayedImage.offsetHeight / this.maxSize.height;
            this.cropper.y2 = this.cropper.y2 * displayedImage.offsetHeight / this.maxSize.height;
        }
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.resetCropperPosition = function () {
        var /** @type {?} */ displayedImage = this.elementRef.nativeElement.querySelector('.source-image');
        if (displayedImage.offsetWidth / this.aspectRatio < displayedImage.offsetHeight) {
            this.cropper.x1 = 0;
            this.cropper.x2 = displayedImage.offsetWidth;
            var /** @type {?} */ cropperHeight = displayedImage.offsetWidth / this.aspectRatio;
            this.cropper.y1 = (displayedImage.offsetHeight - cropperHeight) / 2;
            this.cropper.y2 = this.cropper.y1 + cropperHeight;
        }
        else {
            this.cropper.y1 = 0;
            this.cropper.y2 = displayedImage.offsetHeight;
            var /** @type {?} */ cropperWidth = displayedImage.offsetHeight * this.aspectRatio;
            this.cropper.x1 = (displayedImage.offsetWidth - cropperWidth) / 2;
            this.cropper.x2 = this.cropper.x1 + cropperWidth;
        }
        this.crop();
        this.imageVisible = true;
    };
    /**
     * @param {?} event
     * @param {?} moveType
     * @param {?=} position
     * @return {?}
     */
    ImageCropperComponent.prototype.startMove = function (event, moveType, position) {
        if (position === void 0) { position = null; }
        this.moveStart.active = true;
        this.moveStart.type = moveType;
        this.moveStart.position = position;
        this.moveStart.clientX = this.getClientX(event);
        this.moveStart.clientY = this.getClientY(event);
        Object.assign(this.moveStart, this.cropper);
        this.cd.markForCheck();
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.moveImg = function (event) {
        if (this.moveStart.active) {
            event.stopPropagation();
            event.preventDefault();
            this.setMaxSize();
            if (this.moveStart.type === 'move') {
                this.move(event);
                this.checkCropperPosition(true);
            }
            else if (this.moveStart.type === 'resize') {
                this.resize(event);
                this.checkCropperPosition(false);
            }
            this.cd.markForCheck();
        }
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.setMaxSize = function () {
        var /** @type {?} */ el = this.elementRef.nativeElement.querySelector('.source-image');
        this.maxSize.width = el.offsetWidth;
        this.maxSize.height = el.offsetHeight;
        this.marginLeft = this.sanitizer.bypassSecurityTrustStyle('calc(50% - ' + this.maxSize.width / 2 + 'px)');
    };
    /**
     * @param {?=} maintainSize
     * @return {?}
     */
    ImageCropperComponent.prototype.checkCropperPosition = function (maintainSize) {
        if (maintainSize === void 0) { maintainSize = false; }
        if (this.cropper.x1 < 0) {
            this.cropper.x2 -= maintainSize ? this.cropper.x1 : 0;
            this.cropper.x1 = 0;
        }
        if (this.cropper.y1 < 0) {
            this.cropper.y2 -= maintainSize ? this.cropper.y1 : 0;
            this.cropper.y1 = 0;
        }
        if (this.cropper.x2 > this.maxSize.width) {
            this.cropper.x1 -= maintainSize ? (this.cropper.x2 - this.maxSize.width) : 0;
            this.cropper.x2 = this.maxSize.width;
        }
        if (this.cropper.y2 > this.maxSize.height) {
            this.cropper.y1 -= maintainSize ? (this.cropper.y2 - this.maxSize.height) : 0;
            this.cropper.y2 = this.maxSize.height;
        }
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.moveStop = function (event) {
        if (this.moveStart.active) {
            this.moveStart.active = false;
            this.crop();
            this.cd.markForCheck();
        }
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.move = function (event) {
        var /** @type {?} */ diffX = this.getClientX(event) - this.moveStart.clientX;
        var /** @type {?} */ diffY = this.getClientY(event) - this.moveStart.clientY;
        this.cropper.x1 = this.moveStart.x1 + diffX;
        this.cropper.y1 = this.moveStart.y1 + diffY;
        this.cropper.x2 = this.moveStart.x2 + diffX;
        this.cropper.y2 = this.moveStart.y2 + diffY;
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.resize = function (event) {
        var /** @type {?} */ diffX = this.getClientX(event) - this.moveStart.clientX;
        var /** @type {?} */ diffY = this.getClientY(event) - this.moveStart.clientY;
        switch (this.moveStart.position) {
            case 'left':
                this.cropper.x1 = Math.min(this.moveStart.x1 + diffX, this.cropper.x2 - 20);
                break;
            case 'topleft':
                this.cropper.x1 = Math.min(this.moveStart.x1 + diffX, this.cropper.x2 - 20);
                this.cropper.y1 = Math.min(this.moveStart.y1 + diffY, this.cropper.y2 - 20);
                break;
            case 'top':
                this.cropper.y1 = Math.min(this.moveStart.y1 + diffY, this.cropper.y2 - 20);
                break;
            case 'topright':
                this.cropper.x2 = Math.max(this.moveStart.x2 + diffX, this.cropper.x1 + 20);
                this.cropper.y1 = Math.min(this.moveStart.y1 + diffY, this.cropper.y2 - 20);
                break;
            case 'right':
                this.cropper.x2 = Math.max(this.moveStart.x2 + diffX, this.cropper.x1 + 20);
                break;
            case 'bottomright':
                this.cropper.x2 = Math.max(this.moveStart.x2 + diffX, this.cropper.x1 + 20);
                this.cropper.y2 = Math.max(this.moveStart.y2 + diffY, this.cropper.y1 + 20);
                break;
            case 'bottom':
                this.cropper.y2 = Math.max(this.moveStart.y2 + diffY, this.cropper.y1 + 20);
                break;
            case 'bottomleft':
                this.cropper.x1 = Math.min(this.moveStart.x1 + diffX, this.cropper.x2 - 20);
                this.cropper.y2 = Math.max(this.moveStart.y2 + diffY, this.cropper.y1 + 20);
                break;
        }
        if (this.maintainAspectRatio) {
            this.checkAspectRatio();
        }
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.checkAspectRatio = function () {
        var /** @type {?} */ overflowX = 0;
        var /** @type {?} */ overflowY = 0;
        switch (this.moveStart.position) {
            case 'top':
                this.cropper.x2 = this.cropper.x1 + (this.cropper.y2 - this.cropper.y1) * this.aspectRatio;
                overflowX = Math.max(this.cropper.x2 - this.maxSize.width, 0);
                overflowY = Math.max(0 - this.cropper.y1, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x2 -= (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y1 += (overflowY * this.aspectRatio) > overflowX ? overflowY : overflowX / this.aspectRatio;
                }
                break;
            case 'bottom':
                this.cropper.x2 = this.cropper.x1 + (this.cropper.y2 - this.cropper.y1) * this.aspectRatio;
                overflowX = Math.max(this.cropper.x2 - this.maxSize.width, 0);
                overflowY = Math.max(this.cropper.y2 - this.maxSize.height, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x2 -= (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y2 -= (overflowY * this.aspectRatio) > overflowX ? overflowY : (overflowX / this.aspectRatio);
                }
                break;
            case 'topleft':
                this.cropper.y1 = this.cropper.y2 - (this.cropper.x2 - this.cropper.x1) / this.aspectRatio;
                overflowX = Math.max(0 - this.cropper.x1, 0);
                overflowY = Math.max(0 - this.cropper.y1, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x1 += (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y1 += (overflowY * this.aspectRatio) > overflowX ? overflowY : overflowX / this.aspectRatio;
                }
                break;
            case 'topright':
                this.cropper.y1 = this.cropper.y2 - (this.cropper.x2 - this.cropper.x1) / this.aspectRatio;
                overflowX = Math.max(this.cropper.x2 - this.maxSize.width, 0);
                overflowY = Math.max(0 - this.cropper.y1, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x2 -= (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y1 += (overflowY * this.aspectRatio) > overflowX ? overflowY : overflowX / this.aspectRatio;
                }
                break;
            case 'right':
            case 'bottomright':
                this.cropper.y2 = this.cropper.y1 + (this.cropper.x2 - this.cropper.x1) / this.aspectRatio;
                overflowX = Math.max(this.cropper.x2 - this.maxSize.width, 0);
                overflowY = Math.max(this.cropper.y2 - this.maxSize.height, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x2 -= (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y2 -= (overflowY * this.aspectRatio) > overflowX ? overflowY : overflowX / this.aspectRatio;
                }
                break;
            case 'left':
            case 'bottomleft':
                this.cropper.y2 = this.cropper.y1 + (this.cropper.x2 - this.cropper.x1) / this.aspectRatio;
                overflowX = Math.max(0 - this.cropper.x1, 0);
                overflowY = Math.max(this.cropper.y2 - this.maxSize.height, 0);
                if (overflowX > 0 || overflowY > 0) {
                    this.cropper.x1 += (overflowY * this.aspectRatio) > overflowX ? (overflowY * this.aspectRatio) : overflowX;
                    this.cropper.y2 -= (overflowY * this.aspectRatio) > overflowX ? overflowY : overflowX / this.aspectRatio;
                }
                break;
        }
    };
    /**
     * @return {?}
     */
    ImageCropperComponent.prototype.crop = function () {
        var /** @type {?} */ displayedImage = this.elementRef.nativeElement.querySelector('.source-image');
        if (displayedImage && this.originalImage != null) {
            var /** @type {?} */ ratio = this.calculateRatio(this.originalImage, displayedImage);
            var /** @type {?} */ left = Math.round(this.cropper.x1 * ratio);
            var /** @type {?} */ top = Math.round(this.cropper.y1 * ratio);
            var /** @type {?} */ width = Math.round((this.cropper.x2 - this.cropper.x1) * ratio);
            var /** @type {?} */ height = Math.round((this.cropper.y2 - this.cropper.y1) * ratio);
            var /** @type {?} */ resizeRatio = this.getResizeRatio(width);
            var /** @type {?} */ resizedWidth = width * resizeRatio;
            var /** @type {?} */ resizedHeight = height * resizeRatio;
            var /** @type {?} */ cropCanvas = (document.createElement('canvas'));
            cropCanvas.width = resizedWidth;
            cropCanvas.height = resizedHeight;
            var /** @type {?} */ context = cropCanvas.getContext('2d');
            if (context) {
                // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
                // drawImage(
                //     image,
                //     source x,
                //     source y,
                //     source width,
                //     source height,
                //     destination x,
                //     destination y,
                //     destination width,
                //     destination height
                // )
                context.drawImage(this.originalImage, left, top, width, height, 0, 0, resizedWidth, resizedHeight);
                var /** @type {?} */ quality = Math.min(1, Math.max(0, this.imageQuality / 100));
                var /** @type {?} */ croppedImage = cropCanvas.toDataURL("image/" + this.format, quality);
                if (croppedImage.length > 10) {
                    this.imageCropped.emit(croppedImage);
                }
            }
        }
    };
    /**
     * @param {?} width
     * @return {?}
     */
    ImageCropperComponent.prototype.getResizeRatio = function (width) {
        return this.resizeToWidth > 0 && (!this.onlyScaleDown || width > this.resizeToWidth)
            ? this.resizeToWidth / width
            : 1;
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.getClientX = function (event) {
        return event.clientX != null ? event.clientX : event.touches[0].clientX;
    };
    /**
     * @param {?} event
     * @return {?}
     */
    ImageCropperComponent.prototype.getClientY = function (event) {
        return event.clientY != null ? event.clientY : event.touches[0].clientY;
    };
    /**
     * Calculate the ratio to use when determining the proper
     * cropping coordinates the user has chosen
     *
     * @param {?} workingImage The image we are currently working with. This may be the original
     *                     image the user took or a rotated version of that image
     * @param {?} displayedImage Image that is currently set in the img component in the HTML view
     * @return {?}
     */
    ImageCropperComponent.prototype.calculateRatio = function (workingImage, displayedImage) {
        return workingImage.width / displayedImage.offsetWidth;
    };
    return ImageCropperComponent;
}());
ImageCropperComponent.decorators = [
    { type: Component, args: [{
                selector: 'image-cropper',
                template: "\n      <div>\n          <img\n              [src]=\"safeImgDataUrl\"\n              [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n              (load)=\"imageLoadedInView()\"\n              class=\"source-image\"\n          />\n          <div class=\"cropper\"\n               [style.top.px]=\"cropper.y1\"\n               [style.left.px]=\"cropper.x1\"\n               [style.width.px]=\"cropper.x2 - cropper.x1\"\n               [style.height.px]=\"cropper.y2 - cropper.y1\"\n               [style.margin-left]=\"marginLeft\"\n               [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n          >\n              <div\n                  (mousedown)=\"startMove($event, 'move')\"\n                  (touchstart)=\"startMove($event, 'move')\"\n                  class=\"move\"\n              >&nbsp;</div>\n              <span\n                  class=\"resize topleft\"\n                  (mousedown)=\"startMove($event, 'resize', 'topleft')\"\n                  (touchstart)=\"startMove($event, 'resize', 'topleft')\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize top\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize topright\"\n                  (mousedown)=\"startMove($event, 'resize', 'topright')\"\n                  (touchstart)=\"startMove($event, 'resize', 'topright')\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize right\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize bottomright\"\n                  (mousedown)=\"startMove($event, 'resize', 'bottomright')\"\n                  (touchstart)=\"startMove($event, 'resize', 'bottomright')\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize bottom\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize bottomleft\"\n                  (mousedown)=\"startMove($event, 'resize', 'bottomleft')\"\n                  (touchstart)=\"startMove($event, 'resize', 'bottomleft')\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize left\"\n              ><span class=\"square\"></span></span>\n              <span\n                  class=\"resize-bar top\"\n                  (mousedown)=\"startMove($event, 'resize', 'top')\"\n                  (touchstart)=\"startMove($event, 'resize', 'top')\"\n              ></span>\n              <span\n                  class=\"resize-bar right\"\n                  (mousedown)=\"startMove($event, 'resize', 'right')\"\n                  (touchstart)=\"startMove($event, 'resize', 'right')\"\n              ></span>\n              <span\n                  class=\"resize-bar bottom\"\n                  (mousedown)=\"startMove($event, 'resize', 'bottom')\"\n                  (touchstart)=\"startMove($event, 'resize', 'bottom')\"\n              ></span>\n              <span\n                  class=\"resize-bar left\"\n                  (mousedown)=\"startMove($event, 'resize', 'left')\"\n                  (touchstart)=\"startMove($event, 'resize', 'left')\"\n              ></span>\n          </div>\n      </div>\n    ",
                styles: ["\n      :host {\n        display: -webkit-box;\n        display: -ms-flexbox;\n        display: flex;\n        position: relative;\n        width: 100%;\n        max-width: 100%;\n        max-height: 100%;\n        overflow: hidden;\n        padding: 5px;\n        text-align: center;\n        -webkit-user-select: none;\n        -moz-user-select: none;\n        -ms-user-select: none;\n        user-select: none; }\n        :host > div {\n          position: relative;\n          width: 100%; }\n          :host > div .source-image {\n            max-width: 100%;\n            max-height: 100%; }\n        :host .cropper {\n          position: absolute;\n          display: -webkit-box;\n          display: -ms-flexbox;\n          display: flex;\n          color: #53535C !important;\n          background: transparent !important;\n          outline-color: rgba(255, 255, 255, 0.3);\n          outline-width: 1000px;\n          outline-style: solid;\n          -ms-touch-action: none;\n              touch-action: none; }\n          :host .cropper:after {\n            position: absolute;\n            content: '';\n            top: 0;\n            bottom: 0;\n            left: 0;\n            right: 0;\n            pointer-events: none;\n            border: dashed 1px;\n            opacity: .75;\n            color: inherit;\n            z-index: 1; }\n          :host .cropper .move {\n            width: 100%;\n            cursor: move;\n            border: 1px solid rgba(255, 255, 255, 0.5); }\n          :host .cropper .resize {\n            position: absolute;\n            display: inline-block;\n            line-height: 6px;\n            padding: 8px;\n            opacity: .85;\n            z-index: 1; }\n            :host .cropper .resize .square {\n              display: inline-block;\n              background: #53535C !important;\n              width: 6px;\n              height: 6px;\n              border: 1px solid rgba(255, 255, 255, 0.5); }\n            :host .cropper .resize.topleft {\n              top: -12px;\n              left: -12px;\n              cursor: nw-resize; }\n            :host .cropper .resize.top {\n              top: -12px;\n              left: calc(50% - 12px);\n              cursor: n-resize; }\n            :host .cropper .resize.topright {\n              top: -12px;\n              right: -12px;\n              cursor: ne-resize; }\n            :host .cropper .resize.right {\n              top: calc(50% - 12px);\n              right: -12px;\n              cursor: e-resize; }\n            :host .cropper .resize.bottomright {\n              bottom: -12px;\n              right: -12px;\n              cursor: se-resize; }\n            :host .cropper .resize.bottom {\n              bottom: -12px;\n              left: calc(50% - 12px);\n              cursor: s-resize; }\n            :host .cropper .resize.bottomleft {\n              bottom: -12px;\n              left: -12px;\n              cursor: sw-resize; }\n            :host .cropper .resize.left {\n              top: calc(50% - 12px);\n              left: -12px;\n              cursor: w-resize; }\n          :host .cropper .resize-bar {\n            position: absolute;\n            z-index: 1; }\n            :host .cropper .resize-bar.top {\n              top: -11px;\n              left: 11px;\n              width: calc(100% - 22px);\n              height: 22px;\n              cursor: n-resize; }\n            :host .cropper .resize-bar.right {\n              top: 11px;\n              right: -11px;\n              height: calc(100% - 22px);\n              width: 22px;\n              cursor: e-resize; }\n            :host .cropper .resize-bar.bottom {\n              bottom: -11px;\n              left: 11px;\n              width: calc(100% - 22px);\n              height: 22px;\n              cursor: s-resize; }\n            :host .cropper .resize-bar.left {\n              top: 11px;\n              left: -11px;\n              height: calc(100% - 22px);\n              width: 22px;\n              cursor: w-resize; }\n    "],
                changeDetection: ChangeDetectionStrategy.OnPush
            },] },
];
/**
 * @nocollapse
 */
ImageCropperComponent.ctorParameters = function () { return [
    { type: ElementRef, },
    { type: DomSanitizer, },
    { type: ChangeDetectorRef, },
    { type: ImageCropperExifService, },
]; };
ImageCropperComponent.propDecorators = {
    'imageChangedEvent': [{ type: Input },],
    'imageBase64': [{ type: Input },],
    'format': [{ type: Input },],
    'maintainAspectRatio': [{ type: Input },],
    'aspectRatio': [{ type: Input },],
    'resizeToWidth': [{ type: Input },],
    'onlyScaleDown': [{ type: Input },],
    'imageQuality': [{ type: Input },],
    'cropper': [{ type: Input },],
    'imageCropped': [{ type: Output },],
    'imageLoaded': [{ type: Output },],
    'loadImageFailed': [{ type: Output },],
    'imageResizedInView': [{ type: HostListener, args: ['window:resize', ['$event'],] },],
    'moveImg': [{ type: HostListener, args: ['document:mousemove', ['$event'],] }, { type: HostListener, args: ['document:touchmove', ['$event'],] },],
    'moveStop': [{ type: HostListener, args: ['document:mouseup', ['$event'],] }, { type: HostListener, args: ['document:touchend', ['$event'],] },],
};
var ImageCropperModule = (function () {
    function ImageCropperModule() {
    }
    return ImageCropperModule;
}());
ImageCropperModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule
                ],
                declarations: [
                    ImageCropperComponent
                ],
                exports: [
                    ImageCropperComponent
                ],
                /**
                 * Expose Services and Providers into Angular's dependency injection.
                 */
                providers: [
                    ExifService,
                    ImageCropperExifService
                ]
            },] },
];
/**
 * @nocollapse
 */
ImageCropperModule.ctorParameters = function () { return []; };
/**
 * Generated bundle index. Do not edit.
 */
export { ExifService, ImageCropperModule, ImageCropperComponent, ImageCropperExifService };
//# sourceMappingURL=ngx-image-cropper-facet.es5.js.map