ngx-image-cropper 7.1.1 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,8 @@ import * as i0 from '@angular/core';
3
3
  import { Injectable, EventEmitter, isDevMode, Component, ChangeDetectionStrategy, Optional, Inject, ViewChild, Input, HostBinding, Output, HostListener, NgModule } from '@angular/core';
4
4
  import * as i4 from '@angular/platform-browser';
5
5
  import { HAMMER_LOADER } from '@angular/platform-browser';
6
- import { merge, fromEvent, takeUntil, first } from 'rxjs';
6
+ import { takeUntil, first } from 'rxjs/operators';
7
+ import { merge, fromEvent } from 'rxjs';
7
8
  import * as i5 from '@angular/common';
8
9
  import { CommonModule } from '@angular/common';
9
10
 
@@ -617,29 +618,33 @@ class LoadImageService {
617
618
  this.autoRotateSupported = supportsAutomaticRotation();
618
619
  }
619
620
  loadImageFile(file, cropperSettings) {
620
- return file.arrayBuffer()
621
- .then(arrayBuffer => this.checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, file.type, cropperSettings));
621
+ return __awaiter(this, void 0, void 0, function* () {
622
+ const arrayBuffer = yield file.arrayBuffer();
623
+ return yield this.checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, file.type, cropperSettings);
624
+ });
622
625
  }
623
626
  checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, imageType, cropperSettings) {
624
627
  if (!this.isValidImageType(imageType)) {
625
628
  return Promise.reject(new Error('Invalid image type'));
626
629
  }
627
- return this.loadImageFromArrayBuffer(arrayBuffer, cropperSettings);
630
+ return this.loadImageFromArrayBuffer(arrayBuffer, cropperSettings, imageType);
628
631
  }
629
632
  isValidImageType(type) {
630
- return /image\/(png|jpg|jpeg|bmp|gif|tiff|webp|x-icon|vnd.microsoft.icon)/.test(type);
633
+ return /image\/(png|jpg|jpeg|bmp|gif|tiff|svg|webp|x-icon|vnd.microsoft.icon)/.test(type);
631
634
  }
632
635
  loadImageFromURL(url, cropperSettings) {
633
- return fetch(url)
634
- .then(res => res.arrayBuffer())
635
- .then(buffer => this.loadImageFromArrayBuffer(buffer, cropperSettings));
636
+ return __awaiter(this, void 0, void 0, function* () {
637
+ const res = yield fetch(url);
638
+ const buffer = yield res.arrayBuffer();
639
+ return yield this.loadImageFromArrayBuffer(buffer, cropperSettings);
640
+ });
636
641
  }
637
642
  loadBase64Image(imageBase64, cropperSettings) {
638
643
  const arrayBuffer = this.base64ToArrayBuffer(imageBase64);
639
644
  return this.loadImageFromArrayBuffer(arrayBuffer, cropperSettings);
640
645
  }
641
646
  base64ToArrayBuffer(imageBase64) {
642
- imageBase64 = imageBase64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
647
+ imageBase64 = imageBase64.replace(/^data:([^;]+);base64,/gmi, '');
643
648
  const binaryString = atob(imageBase64);
644
649
  const len = binaryString.length;
645
650
  const bytes = new Uint8Array(len);
@@ -648,24 +653,61 @@ class LoadImageService {
648
653
  }
649
654
  return bytes.buffer;
650
655
  }
651
- loadImageFromArrayBuffer(arrayBuffer, cropperSettings) {
652
- return new Promise((resolve, reject) => {
653
- const blob = new Blob([arrayBuffer]);
654
- const objectUrl = URL.createObjectURL(blob);
655
- const originalImage = new Image();
656
- originalImage.onload = () => resolve({
657
- originalImage,
658
- originalObjectUrl: objectUrl,
659
- originalArrayBuffer: arrayBuffer
660
- });
661
- originalImage.onerror = reject;
662
- originalImage.src = objectUrl;
663
- }).then((res) => this.transformImageFromArrayBuffer(res, cropperSettings));
656
+ loadImageFromArrayBuffer(arrayBuffer, cropperSettings, imageType) {
657
+ return __awaiter(this, void 0, void 0, function* () {
658
+ const res = yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
659
+ try {
660
+ const blob = new Blob([arrayBuffer], imageType ? { type: imageType } : undefined);
661
+ const objectUrl = URL.createObjectURL(blob);
662
+ const originalImage = new Image();
663
+ const isSvg = imageType === 'image/svg+xml';
664
+ const originalImageSize = isSvg ? yield this.getSvgImageSize(blob) : undefined;
665
+ originalImage.onload = () => resolve({
666
+ originalImage,
667
+ originalImageSize,
668
+ originalObjectUrl: objectUrl,
669
+ originalArrayBuffer: arrayBuffer
670
+ });
671
+ originalImage.onerror = reject;
672
+ originalImage.src = objectUrl;
673
+ }
674
+ catch (e) {
675
+ reject(e);
676
+ }
677
+ }));
678
+ return yield this.transformImageFromArrayBuffer(res, cropperSettings, res.originalImageSize != null);
679
+ });
664
680
  }
665
- transformImageFromArrayBuffer(res, cropperSettings) {
681
+ getSvgImageSize(blob) {
682
+ return __awaiter(this, void 0, void 0, function* () {
683
+ const parser = new DOMParser();
684
+ const doc = parser.parseFromString(yield blob.text(), 'image/svg+xml');
685
+ const svgElement = doc.querySelector('svg');
686
+ if (!svgElement) {
687
+ throw Error('Failed to parse SVG image');
688
+ }
689
+ const widthAttr = svgElement.getAttribute('width');
690
+ const heightAttr = svgElement.getAttribute('height');
691
+ if (widthAttr && heightAttr) {
692
+ return null;
693
+ }
694
+ const viewBoxAttr = svgElement.getAttribute('viewBox')
695
+ || svgElement.getAttribute('viewbox');
696
+ if (viewBoxAttr) {
697
+ const viewBox = viewBoxAttr.split(' ');
698
+ return {
699
+ width: +viewBox[2],
700
+ height: +viewBox[3]
701
+ };
702
+ }
703
+ throw Error('Failed to load SVG image. SVG must have width + height or viewBox definition.');
704
+ });
705
+ }
706
+ transformImageFromArrayBuffer(res, cropperSettings, forceTransform = false) {
707
+ var _a;
666
708
  return __awaiter(this, void 0, void 0, function* () {
667
709
  const autoRotate = yield this.autoRotateSupported;
668
- const exifTransform = yield getTransformationsFromExifData(autoRotate ? -1 : res.originalArrayBuffer);
710
+ const exifTransform = getTransformationsFromExifData(autoRotate ? -1 : res.originalArrayBuffer);
669
711
  if (!res.originalImage || !res.originalImage.complete) {
670
712
  return Promise.reject(new Error('No image loaded'));
671
713
  }
@@ -673,24 +715,21 @@ class LoadImageService {
673
715
  original: {
674
716
  objectUrl: res.originalObjectUrl,
675
717
  image: res.originalImage,
676
- size: {
718
+ size: (_a = res.originalImageSize) !== null && _a !== void 0 ? _a : {
677
719
  width: res.originalImage.naturalWidth,
678
720
  height: res.originalImage.naturalHeight
679
721
  }
680
722
  },
681
723
  exifTransform
682
724
  };
683
- return this.transformLoadedImage(loadedImage, cropperSettings);
725
+ return this.transformLoadedImage(loadedImage, cropperSettings, forceTransform);
684
726
  });
685
727
  }
686
- transformLoadedImage(loadedImage, cropperSettings) {
728
+ transformLoadedImage(loadedImage, cropperSettings, forceTransform = false) {
687
729
  return __awaiter(this, void 0, void 0, function* () {
688
730
  const canvasRotation = cropperSettings.canvasRotation + loadedImage.exifTransform.rotate;
689
- const originalSize = {
690
- width: loadedImage.original.image.naturalWidth,
691
- height: loadedImage.original.image.naturalHeight
692
- };
693
- if (canvasRotation === 0 && !loadedImage.exifTransform.flip && !cropperSettings.containWithinAspectRatio) {
731
+ const originalSize = loadedImage.original.size;
732
+ if (!forceTransform && canvasRotation === 0 && !loadedImage.exifTransform.flip && !cropperSettings.containWithinAspectRatio) {
694
733
  return {
695
734
  original: {
696
735
  objectUrl: loadedImage.original.objectUrl,