compressorjs-next 2.0.1 → 2.0.3
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.
- package/dist/compressor.common.js +50 -79
- package/dist/compressor.esm.js +50 -79
- package/dist/compressor.js +50 -79
- package/dist/compressor.min.js +2 -2
- package/package.json +12 -14
- package/src/index.js +50 -85
- /package/{LICENSE.md → LICENSE.txt} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.3
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -549,10 +549,7 @@ class Compressor {
|
|
|
549
549
|
type: mimeType,
|
|
550
550
|
lastModified: date.getTime()
|
|
551
551
|
});
|
|
552
|
-
this.result
|
|
553
|
-
if (options.success) {
|
|
554
|
-
options.success.call(this, result);
|
|
555
|
-
}
|
|
552
|
+
this.succeed(result);
|
|
556
553
|
};
|
|
557
554
|
reader.onabort = () => {
|
|
558
555
|
this.fail(new Error('Aborted to read the image with FileReader.'));
|
|
@@ -569,10 +566,7 @@ class Compressor {
|
|
|
569
566
|
// Defer callback to match the normal async flow
|
|
570
567
|
Promise.resolve().then(() => {
|
|
571
568
|
if (this.aborted) return;
|
|
572
|
-
this.
|
|
573
|
-
if (options.success) {
|
|
574
|
-
options.success.call(this, file);
|
|
575
|
-
}
|
|
569
|
+
this.succeed(file);
|
|
576
570
|
});
|
|
577
571
|
}
|
|
578
572
|
return;
|
|
@@ -761,67 +755,19 @@ class Compressor {
|
|
|
761
755
|
result
|
|
762
756
|
});
|
|
763
757
|
if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) {
|
|
764
|
-
|
|
758
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
765
759
|
if (this.aborted) return;
|
|
766
760
|
const withExif = insertExif(arrayBuffer, this.exif);
|
|
767
761
|
done(uint8ArrayToBlob(withExif, options.mimeType));
|
|
768
|
-
};
|
|
769
|
-
if (blob.arrayBuffer) {
|
|
770
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
771
|
-
if (this.aborted) return;
|
|
772
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
773
|
-
});
|
|
774
|
-
} else {
|
|
775
|
-
const reader = new FileReader();
|
|
776
|
-
this.reader = reader;
|
|
777
|
-
reader.onload = ({
|
|
778
|
-
target
|
|
779
|
-
}) => {
|
|
780
|
-
next(target.result);
|
|
781
|
-
};
|
|
782
|
-
reader.onabort = () => {
|
|
783
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
784
|
-
};
|
|
785
|
-
reader.onerror = () => {
|
|
786
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
787
|
-
};
|
|
788
|
-
reader.onloadend = () => {
|
|
789
|
-
this.reader = null;
|
|
790
|
-
};
|
|
791
|
-
reader.readAsArrayBuffer(blob);
|
|
792
|
-
}
|
|
762
|
+
});
|
|
793
763
|
} else if (blob && isJPEGImage && !options.retainExif) {
|
|
794
764
|
// Strip any EXIF that may be present in the canvas output
|
|
795
765
|
// (most browsers strip it automatically, but WebKit preserves the
|
|
796
766
|
// source EXIF—this ensures consistent, privacy-safe output)
|
|
797
|
-
|
|
767
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
798
768
|
if (this.aborted) return;
|
|
799
769
|
done(uint8ArrayToBlob(stripExif(arrayBuffer), options.mimeType));
|
|
800
|
-
};
|
|
801
|
-
if (blob.arrayBuffer) {
|
|
802
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
803
|
-
if (this.aborted) return;
|
|
804
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
805
|
-
});
|
|
806
|
-
} else {
|
|
807
|
-
const reader = new FileReader();
|
|
808
|
-
this.reader = reader;
|
|
809
|
-
reader.onload = ({
|
|
810
|
-
target
|
|
811
|
-
}) => {
|
|
812
|
-
next(target.result);
|
|
813
|
-
};
|
|
814
|
-
reader.onabort = () => {
|
|
815
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
816
|
-
};
|
|
817
|
-
reader.onerror = () => {
|
|
818
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
819
|
-
};
|
|
820
|
-
reader.onloadend = () => {
|
|
821
|
-
this.reader = null;
|
|
822
|
-
};
|
|
823
|
-
reader.readAsArrayBuffer(blob);
|
|
824
|
-
}
|
|
770
|
+
});
|
|
825
771
|
} else {
|
|
826
772
|
done(blob);
|
|
827
773
|
}
|
|
@@ -875,17 +821,11 @@ class Compressor {
|
|
|
875
821
|
type: file.type,
|
|
876
822
|
lastModified: file.lastModified || Date.now()
|
|
877
823
|
});
|
|
878
|
-
this.
|
|
879
|
-
if (options.success) {
|
|
880
|
-
options.success.call(this, stripped);
|
|
881
|
-
}
|
|
824
|
+
this.succeed(stripped);
|
|
882
825
|
}).catch(err => {
|
|
883
826
|
if (this.aborted) return;
|
|
884
827
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}${err?.message ? `: ${err.message}` : ''}`);
|
|
885
|
-
this.
|
|
886
|
-
if (options.success) {
|
|
887
|
-
options.success.call(this, file);
|
|
888
|
-
}
|
|
828
|
+
this.succeed(file);
|
|
889
829
|
});
|
|
890
830
|
} else {
|
|
891
831
|
const reader = new FileReader();
|
|
@@ -899,10 +839,7 @@ class Compressor {
|
|
|
899
839
|
type: file.type,
|
|
900
840
|
lastModified: file.lastModified || Date.now()
|
|
901
841
|
});
|
|
902
|
-
this.
|
|
903
|
-
if (options.success) {
|
|
904
|
-
options.success.call(this, stripped);
|
|
905
|
-
}
|
|
842
|
+
this.succeed(stripped);
|
|
906
843
|
};
|
|
907
844
|
reader.onabort = () => {
|
|
908
845
|
this.fail(new Error('Aborted to read the original file with FileReader.'));
|
|
@@ -910,10 +847,7 @@ class Compressor {
|
|
|
910
847
|
reader.onerror = () => {
|
|
911
848
|
if (this.aborted) return;
|
|
912
849
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}`);
|
|
913
|
-
this.
|
|
914
|
-
if (options.success) {
|
|
915
|
-
options.success.call(this, file);
|
|
916
|
-
}
|
|
850
|
+
this.succeed(file);
|
|
917
851
|
};
|
|
918
852
|
reader.onloadend = () => {
|
|
919
853
|
this.reader = null;
|
|
@@ -922,9 +856,46 @@ class Compressor {
|
|
|
922
856
|
}
|
|
923
857
|
return;
|
|
924
858
|
}
|
|
859
|
+
this.succeed(result);
|
|
860
|
+
}
|
|
861
|
+
readBlobAsArrayBuffer(blob, next) {
|
|
862
|
+
if (blob.arrayBuffer) {
|
|
863
|
+
blob.arrayBuffer().then(next).catch(() => {
|
|
864
|
+
// Defer to a macrotask so any `abort()` scheduled via `setTimeout()`
|
|
865
|
+
// in a `drew()` hook has a chance to set `this.aborted` first
|
|
866
|
+
setTimeout(() => {
|
|
867
|
+
if (this.aborted) return;
|
|
868
|
+
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
869
|
+
}, 0);
|
|
870
|
+
});
|
|
871
|
+
} else {
|
|
872
|
+
const reader = new FileReader();
|
|
873
|
+
this.reader = reader;
|
|
874
|
+
reader.onload = ({
|
|
875
|
+
target
|
|
876
|
+
}) => {
|
|
877
|
+
try {
|
|
878
|
+
next(target.result);
|
|
879
|
+
} catch (err) {
|
|
880
|
+
if (!this.aborted) this.fail(err);
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
reader.onabort = () => {
|
|
884
|
+
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
885
|
+
};
|
|
886
|
+
reader.onerror = () => {
|
|
887
|
+
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
888
|
+
};
|
|
889
|
+
reader.onloadend = () => {
|
|
890
|
+
this.reader = null;
|
|
891
|
+
};
|
|
892
|
+
reader.readAsArrayBuffer(blob);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
succeed(result) {
|
|
925
896
|
this.result = result;
|
|
926
|
-
if (options.success) {
|
|
927
|
-
options.success.call(this, result);
|
|
897
|
+
if (this.options.success) {
|
|
898
|
+
this.options.success.call(this, result);
|
|
928
899
|
}
|
|
929
900
|
}
|
|
930
901
|
fail(err) {
|
package/dist/compressor.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.3
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -547,10 +547,7 @@ class Compressor {
|
|
|
547
547
|
type: mimeType,
|
|
548
548
|
lastModified: date.getTime()
|
|
549
549
|
});
|
|
550
|
-
this.result
|
|
551
|
-
if (options.success) {
|
|
552
|
-
options.success.call(this, result);
|
|
553
|
-
}
|
|
550
|
+
this.succeed(result);
|
|
554
551
|
};
|
|
555
552
|
reader.onabort = () => {
|
|
556
553
|
this.fail(new Error('Aborted to read the image with FileReader.'));
|
|
@@ -567,10 +564,7 @@ class Compressor {
|
|
|
567
564
|
// Defer callback to match the normal async flow
|
|
568
565
|
Promise.resolve().then(() => {
|
|
569
566
|
if (this.aborted) return;
|
|
570
|
-
this.
|
|
571
|
-
if (options.success) {
|
|
572
|
-
options.success.call(this, file);
|
|
573
|
-
}
|
|
567
|
+
this.succeed(file);
|
|
574
568
|
});
|
|
575
569
|
}
|
|
576
570
|
return;
|
|
@@ -759,67 +753,19 @@ class Compressor {
|
|
|
759
753
|
result
|
|
760
754
|
});
|
|
761
755
|
if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) {
|
|
762
|
-
|
|
756
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
763
757
|
if (this.aborted) return;
|
|
764
758
|
const withExif = insertExif(arrayBuffer, this.exif);
|
|
765
759
|
done(uint8ArrayToBlob(withExif, options.mimeType));
|
|
766
|
-
};
|
|
767
|
-
if (blob.arrayBuffer) {
|
|
768
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
769
|
-
if (this.aborted) return;
|
|
770
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
771
|
-
});
|
|
772
|
-
} else {
|
|
773
|
-
const reader = new FileReader();
|
|
774
|
-
this.reader = reader;
|
|
775
|
-
reader.onload = ({
|
|
776
|
-
target
|
|
777
|
-
}) => {
|
|
778
|
-
next(target.result);
|
|
779
|
-
};
|
|
780
|
-
reader.onabort = () => {
|
|
781
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
782
|
-
};
|
|
783
|
-
reader.onerror = () => {
|
|
784
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
785
|
-
};
|
|
786
|
-
reader.onloadend = () => {
|
|
787
|
-
this.reader = null;
|
|
788
|
-
};
|
|
789
|
-
reader.readAsArrayBuffer(blob);
|
|
790
|
-
}
|
|
760
|
+
});
|
|
791
761
|
} else if (blob && isJPEGImage && !options.retainExif) {
|
|
792
762
|
// Strip any EXIF that may be present in the canvas output
|
|
793
763
|
// (most browsers strip it automatically, but WebKit preserves the
|
|
794
764
|
// source EXIF—this ensures consistent, privacy-safe output)
|
|
795
|
-
|
|
765
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
796
766
|
if (this.aborted) return;
|
|
797
767
|
done(uint8ArrayToBlob(stripExif(arrayBuffer), options.mimeType));
|
|
798
|
-
};
|
|
799
|
-
if (blob.arrayBuffer) {
|
|
800
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
801
|
-
if (this.aborted) return;
|
|
802
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
803
|
-
});
|
|
804
|
-
} else {
|
|
805
|
-
const reader = new FileReader();
|
|
806
|
-
this.reader = reader;
|
|
807
|
-
reader.onload = ({
|
|
808
|
-
target
|
|
809
|
-
}) => {
|
|
810
|
-
next(target.result);
|
|
811
|
-
};
|
|
812
|
-
reader.onabort = () => {
|
|
813
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
814
|
-
};
|
|
815
|
-
reader.onerror = () => {
|
|
816
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
817
|
-
};
|
|
818
|
-
reader.onloadend = () => {
|
|
819
|
-
this.reader = null;
|
|
820
|
-
};
|
|
821
|
-
reader.readAsArrayBuffer(blob);
|
|
822
|
-
}
|
|
768
|
+
});
|
|
823
769
|
} else {
|
|
824
770
|
done(blob);
|
|
825
771
|
}
|
|
@@ -873,17 +819,11 @@ class Compressor {
|
|
|
873
819
|
type: file.type,
|
|
874
820
|
lastModified: file.lastModified || Date.now()
|
|
875
821
|
});
|
|
876
|
-
this.
|
|
877
|
-
if (options.success) {
|
|
878
|
-
options.success.call(this, stripped);
|
|
879
|
-
}
|
|
822
|
+
this.succeed(stripped);
|
|
880
823
|
}).catch(err => {
|
|
881
824
|
if (this.aborted) return;
|
|
882
825
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}${err?.message ? `: ${err.message}` : ''}`);
|
|
883
|
-
this.
|
|
884
|
-
if (options.success) {
|
|
885
|
-
options.success.call(this, file);
|
|
886
|
-
}
|
|
826
|
+
this.succeed(file);
|
|
887
827
|
});
|
|
888
828
|
} else {
|
|
889
829
|
const reader = new FileReader();
|
|
@@ -897,10 +837,7 @@ class Compressor {
|
|
|
897
837
|
type: file.type,
|
|
898
838
|
lastModified: file.lastModified || Date.now()
|
|
899
839
|
});
|
|
900
|
-
this.
|
|
901
|
-
if (options.success) {
|
|
902
|
-
options.success.call(this, stripped);
|
|
903
|
-
}
|
|
840
|
+
this.succeed(stripped);
|
|
904
841
|
};
|
|
905
842
|
reader.onabort = () => {
|
|
906
843
|
this.fail(new Error('Aborted to read the original file with FileReader.'));
|
|
@@ -908,10 +845,7 @@ class Compressor {
|
|
|
908
845
|
reader.onerror = () => {
|
|
909
846
|
if (this.aborted) return;
|
|
910
847
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}`);
|
|
911
|
-
this.
|
|
912
|
-
if (options.success) {
|
|
913
|
-
options.success.call(this, file);
|
|
914
|
-
}
|
|
848
|
+
this.succeed(file);
|
|
915
849
|
};
|
|
916
850
|
reader.onloadend = () => {
|
|
917
851
|
this.reader = null;
|
|
@@ -920,9 +854,46 @@ class Compressor {
|
|
|
920
854
|
}
|
|
921
855
|
return;
|
|
922
856
|
}
|
|
857
|
+
this.succeed(result);
|
|
858
|
+
}
|
|
859
|
+
readBlobAsArrayBuffer(blob, next) {
|
|
860
|
+
if (blob.arrayBuffer) {
|
|
861
|
+
blob.arrayBuffer().then(next).catch(() => {
|
|
862
|
+
// Defer to a macrotask so any `abort()` scheduled via `setTimeout()`
|
|
863
|
+
// in a `drew()` hook has a chance to set `this.aborted` first
|
|
864
|
+
setTimeout(() => {
|
|
865
|
+
if (this.aborted) return;
|
|
866
|
+
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
867
|
+
}, 0);
|
|
868
|
+
});
|
|
869
|
+
} else {
|
|
870
|
+
const reader = new FileReader();
|
|
871
|
+
this.reader = reader;
|
|
872
|
+
reader.onload = ({
|
|
873
|
+
target
|
|
874
|
+
}) => {
|
|
875
|
+
try {
|
|
876
|
+
next(target.result);
|
|
877
|
+
} catch (err) {
|
|
878
|
+
if (!this.aborted) this.fail(err);
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
reader.onabort = () => {
|
|
882
|
+
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
883
|
+
};
|
|
884
|
+
reader.onerror = () => {
|
|
885
|
+
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
886
|
+
};
|
|
887
|
+
reader.onloadend = () => {
|
|
888
|
+
this.reader = null;
|
|
889
|
+
};
|
|
890
|
+
reader.readAsArrayBuffer(blob);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
succeed(result) {
|
|
923
894
|
this.result = result;
|
|
924
|
-
if (options.success) {
|
|
925
|
-
options.success.call(this, result);
|
|
895
|
+
if (this.options.success) {
|
|
896
|
+
this.options.success.call(this, result);
|
|
926
897
|
}
|
|
927
898
|
}
|
|
928
899
|
fail(err) {
|
package/dist/compressor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.3
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -553,10 +553,7 @@
|
|
|
553
553
|
type: mimeType,
|
|
554
554
|
lastModified: date.getTime()
|
|
555
555
|
});
|
|
556
|
-
this.result
|
|
557
|
-
if (options.success) {
|
|
558
|
-
options.success.call(this, result);
|
|
559
|
-
}
|
|
556
|
+
this.succeed(result);
|
|
560
557
|
};
|
|
561
558
|
reader.onabort = () => {
|
|
562
559
|
this.fail(new Error('Aborted to read the image with FileReader.'));
|
|
@@ -573,10 +570,7 @@
|
|
|
573
570
|
// Defer callback to match the normal async flow
|
|
574
571
|
Promise.resolve().then(() => {
|
|
575
572
|
if (this.aborted) return;
|
|
576
|
-
this.
|
|
577
|
-
if (options.success) {
|
|
578
|
-
options.success.call(this, file);
|
|
579
|
-
}
|
|
573
|
+
this.succeed(file);
|
|
580
574
|
});
|
|
581
575
|
}
|
|
582
576
|
return;
|
|
@@ -765,67 +759,19 @@
|
|
|
765
759
|
result
|
|
766
760
|
});
|
|
767
761
|
if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) {
|
|
768
|
-
|
|
762
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
769
763
|
if (this.aborted) return;
|
|
770
764
|
const withExif = insertExif(arrayBuffer, this.exif);
|
|
771
765
|
done(uint8ArrayToBlob(withExif, options.mimeType));
|
|
772
|
-
};
|
|
773
|
-
if (blob.arrayBuffer) {
|
|
774
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
775
|
-
if (this.aborted) return;
|
|
776
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
777
|
-
});
|
|
778
|
-
} else {
|
|
779
|
-
const reader = new FileReader();
|
|
780
|
-
this.reader = reader;
|
|
781
|
-
reader.onload = ({
|
|
782
|
-
target
|
|
783
|
-
}) => {
|
|
784
|
-
next(target.result);
|
|
785
|
-
};
|
|
786
|
-
reader.onabort = () => {
|
|
787
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
788
|
-
};
|
|
789
|
-
reader.onerror = () => {
|
|
790
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
791
|
-
};
|
|
792
|
-
reader.onloadend = () => {
|
|
793
|
-
this.reader = null;
|
|
794
|
-
};
|
|
795
|
-
reader.readAsArrayBuffer(blob);
|
|
796
|
-
}
|
|
766
|
+
});
|
|
797
767
|
} else if (blob && isJPEGImage && !options.retainExif) {
|
|
798
768
|
// Strip any EXIF that may be present in the canvas output
|
|
799
769
|
// (most browsers strip it automatically, but WebKit preserves the
|
|
800
770
|
// source EXIF—this ensures consistent, privacy-safe output)
|
|
801
|
-
|
|
771
|
+
this.readBlobAsArrayBuffer(blob, arrayBuffer => {
|
|
802
772
|
if (this.aborted) return;
|
|
803
773
|
done(uint8ArrayToBlob(stripExif(arrayBuffer), options.mimeType));
|
|
804
|
-
};
|
|
805
|
-
if (blob.arrayBuffer) {
|
|
806
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
807
|
-
if (this.aborted) return;
|
|
808
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
809
|
-
});
|
|
810
|
-
} else {
|
|
811
|
-
const reader = new FileReader();
|
|
812
|
-
this.reader = reader;
|
|
813
|
-
reader.onload = ({
|
|
814
|
-
target
|
|
815
|
-
}) => {
|
|
816
|
-
next(target.result);
|
|
817
|
-
};
|
|
818
|
-
reader.onabort = () => {
|
|
819
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
820
|
-
};
|
|
821
|
-
reader.onerror = () => {
|
|
822
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
823
|
-
};
|
|
824
|
-
reader.onloadend = () => {
|
|
825
|
-
this.reader = null;
|
|
826
|
-
};
|
|
827
|
-
reader.readAsArrayBuffer(blob);
|
|
828
|
-
}
|
|
774
|
+
});
|
|
829
775
|
} else {
|
|
830
776
|
done(blob);
|
|
831
777
|
}
|
|
@@ -879,17 +825,11 @@
|
|
|
879
825
|
type: file.type,
|
|
880
826
|
lastModified: file.lastModified || Date.now()
|
|
881
827
|
});
|
|
882
|
-
this.
|
|
883
|
-
if (options.success) {
|
|
884
|
-
options.success.call(this, stripped);
|
|
885
|
-
}
|
|
828
|
+
this.succeed(stripped);
|
|
886
829
|
}).catch(err => {
|
|
887
830
|
if (this.aborted) return;
|
|
888
831
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}${err?.message ? `: ${err.message}` : ''}`);
|
|
889
|
-
this.
|
|
890
|
-
if (options.success) {
|
|
891
|
-
options.success.call(this, file);
|
|
892
|
-
}
|
|
832
|
+
this.succeed(file);
|
|
893
833
|
});
|
|
894
834
|
} else {
|
|
895
835
|
const reader = new FileReader();
|
|
@@ -903,10 +843,7 @@
|
|
|
903
843
|
type: file.type,
|
|
904
844
|
lastModified: file.lastModified || Date.now()
|
|
905
845
|
});
|
|
906
|
-
this.
|
|
907
|
-
if (options.success) {
|
|
908
|
-
options.success.call(this, stripped);
|
|
909
|
-
}
|
|
846
|
+
this.succeed(stripped);
|
|
910
847
|
};
|
|
911
848
|
reader.onabort = () => {
|
|
912
849
|
this.fail(new Error('Aborted to read the original file with FileReader.'));
|
|
@@ -914,10 +851,7 @@
|
|
|
914
851
|
reader.onerror = () => {
|
|
915
852
|
if (this.aborted) return;
|
|
916
853
|
console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}`);
|
|
917
|
-
this.
|
|
918
|
-
if (options.success) {
|
|
919
|
-
options.success.call(this, file);
|
|
920
|
-
}
|
|
854
|
+
this.succeed(file);
|
|
921
855
|
};
|
|
922
856
|
reader.onloadend = () => {
|
|
923
857
|
this.reader = null;
|
|
@@ -926,9 +860,46 @@
|
|
|
926
860
|
}
|
|
927
861
|
return;
|
|
928
862
|
}
|
|
863
|
+
this.succeed(result);
|
|
864
|
+
}
|
|
865
|
+
readBlobAsArrayBuffer(blob, next) {
|
|
866
|
+
if (blob.arrayBuffer) {
|
|
867
|
+
blob.arrayBuffer().then(next).catch(() => {
|
|
868
|
+
// Defer to a macrotask so any `abort()` scheduled via `setTimeout()`
|
|
869
|
+
// in a `drew()` hook has a chance to set `this.aborted` first
|
|
870
|
+
setTimeout(() => {
|
|
871
|
+
if (this.aborted) return;
|
|
872
|
+
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
873
|
+
}, 0);
|
|
874
|
+
});
|
|
875
|
+
} else {
|
|
876
|
+
const reader = new FileReader();
|
|
877
|
+
this.reader = reader;
|
|
878
|
+
reader.onload = ({
|
|
879
|
+
target
|
|
880
|
+
}) => {
|
|
881
|
+
try {
|
|
882
|
+
next(target.result);
|
|
883
|
+
} catch (err) {
|
|
884
|
+
if (!this.aborted) this.fail(err);
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
reader.onabort = () => {
|
|
888
|
+
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
889
|
+
};
|
|
890
|
+
reader.onerror = () => {
|
|
891
|
+
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
892
|
+
};
|
|
893
|
+
reader.onloadend = () => {
|
|
894
|
+
this.reader = null;
|
|
895
|
+
};
|
|
896
|
+
reader.readAsArrayBuffer(blob);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
succeed(result) {
|
|
929
900
|
this.result = result;
|
|
930
|
-
if (options.success) {
|
|
931
|
-
options.success.call(this, result);
|
|
901
|
+
if (this.options.success) {
|
|
902
|
+
this.options.success.call(this, result);
|
|
932
903
|
}
|
|
933
904
|
}
|
|
934
905
|
fail(err) {
|
package/dist/compressor.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.3
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Released under the MIT license.
|
|
9
9
|
*/
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Compressor=t()}(this,function(){"use strict";var e={strict:!0,retainExif:!1,maxWidth:1/0,maxHeight:1/0,minWidth:0,minHeight:0,width:void 0,height:void 0,resize:"none",quality:.8,mimeType:"auto",convertTypes:[],convertSize:5e6,beforeDraw:null,drew:null,success:null,error:null};const t="undefined"!=typeof window&&void 0!==window.document?window:{},i=e=>e>0&&e<1/0,r=/^image\/.+$/;function a(e){return r.test(e)}const{fromCharCode:n}=String;function s(e){const t=new DataView(e);let i;try{let e,r,a;if(255===t.getUint8(0)&&216===t.getUint8(1)){const e=t.byteLength;let i=2;for(;i+1<e;){if(255===t.getUint8(i)&&225===t.getUint8(i+1)){r=i;break}i+=1}}if(r){const i=r+10;if("Exif"===function(e,t,i){let r,a="";for(i+=t,r=t;r<i;r+=1)a+=n(e.getUint8(r));return a}(t,r+4,4)){const r=t.getUint16(i);if(e=18761===r,(e||19789===r)&&42===t.getUint16(i+2,e)){const r=t.getUint32(i+4,e);r>=8&&(a=i+r)}}}if(a){const r=t.getUint16(a,e);let n,s;for(s=0;s<r;s+=1)if(n=a+12*s+2,274===t.getUint16(n,e)){n+=8,i=t.getUint16(n,e),t.setUint16(n,1,e);break}}}catch{i=1}return i}let o;function h(e){const t=new DataView(e),{byteLength:i}=t,r=[];if(i<4||255!==t.getUint8(0)||216!==t.getUint8(1))return new Uint8Array(e);r.push(new Uint8Array(e,0,2));let a=2;for(;a+3<i;){const n=t.getUint8(a),s=t.getUint8(a+1);if(255!==n)break;if(218===s){r.push(new Uint8Array(e,a));break}if(a+3>=i)break;const o=t.getUint16(a+2);if(o<2)break;const h=a+2+o;if(h>i)break;225!==s&&r.push(new Uint8Array(e,a,h-a)),a=h}const n=r.reduce((e,t)=>e+t.length,0),s=new Uint8Array(n);let o=0;for(const e of r)s.set(e,o),o+=e.length;return s}const l=/\.\d*(?:0|9){12}\d*$/;function d(e,t=1e11){return l.test(e)?Math.round(e*t)/t:e}function c({aspectRatio:e,height:t,width:r},a="none"){const n=i(r),s=i(t);if(n&&s){const i=t*e;("contain"===a||"none"===a)&&i>r||"cover"===a&&i<r?t=r/e:r=t*e}else n?t=r/e:s&&(r=t*e);return{width:r,height:t}}function f(e,t){return new Blob([e],{type:t})}const{ArrayBuffer:u,FileReader:g}=t,m=t.URL||t.webkitURL,w=/\.\w+$/;return class{constructor(t,i){this.file=t,this.exif=[],this.image=new Image,this.options={...e,...i},this.mimeTypeSet=i&&i.mimeType&&a(i.mimeType),this.aborted=!1,this.canvasFallback=!1,this.result=null,this.url=null,this.init()}init(){const{file:e,options:t}=this;if(!(e instanceof Blob))return void this.fail(new Error("The first argument must be a File or Blob object."));const i=e.type;if(!a(i))return void this.fail(new Error("The first argument must be an image File or Blob object."));if(!m||!g)return void this.fail(new Error("The current browser does not support image compression."));if(u||(t.retainExif=!1),!function(){if(void 0!==o)return o;try{const e=document.createElement("canvas");e.width=4,e.height=4;const t=e.getContext("2d"),i=t.createImageData(e.width,e.height);for(let e=0;e<i.data.length;e+=4)i.data[e]=e,i.data[e+1]=1,i.data[e+2]=2,i.data[e+3]=255;t.putImageData(i,0,0);const r=t.getImageData(0,0,e.width,e.height);o=r.data.every((e,t)=>{const i=t%4;return 0===i?e===(255&t):1===i?1===e:2===i?2===e:255===e})}catch{o=!1}return o}()){if(console.warn("Compressor.js Next: Canvas data is unreliable (e.g., due to browser fingerprinting resistance)—compression, resizing, and format conversion are unavailable"),this.canvasFallback=!0,"image/jpeg"!==i||t.retainExif)Promise.resolve().then(()=>{this.aborted||(this.result=e,t.success&&t.success.call(this,e))});else{const r=new g;this.reader=r,r.onload=({target:r})=>{if(this.aborted)return;let a;try{a=f(h(r.result),i)}catch{return void this.fail(new Error("Failed to process the image data."))}const n=new Date,s=new File([a],e.name||"",{type:i,lastModified:n.getTime()});this.result=s,t.success&&t.success.call(this,s)},r.onabort=()=>{this.fail(new Error("Aborted to read the image with FileReader."))},r.onerror=()=>{this.fail(new Error("Failed to read the image with FileReader."))},r.onloadend=()=>{this.reader=null},r.readAsArrayBuffer(e)}return}if("image/jpeg"===i&&t.retainExif){const t=new g;this.reader=t,t.onload=({target:t})=>{this.aborted||(s(t.result),this.exif=function(e){const t=new DataView(e),{byteLength:i}=t,r=[];let a=0;for(;a+3<i;){const e=t.getUint8(a),n=t.getUint8(a+1);if(255===e&&218===n)break;if(255===e&&216===n)a+=2;else{const s=a+t.getUint16(a+2)+2;if(255===e&&225===n)for(let e=a;e<s&&e<i;e+=1)r.push(t.getUint8(e));a=s}}return r}(t.result),this.url=m.createObjectURL(e),this.load({url:this.url}))},t.onabort=()=>{this.fail(new Error("Aborted to read the image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(e)}else this.url=m.createObjectURL(e),this.load({url:this.url})}load(e){const{file:i,image:r}=this;r.onload=()=>{this.draw({...e,naturalWidth:r.naturalWidth,naturalHeight:r.naturalHeight})},r.onabort=()=>{this.fail(new Error("Aborted to load the image."))},r.onerror=()=>{this.fail(new Error("Failed to load the image."))},t.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(t.navigator.userAgent)&&(r.crossOrigin="anonymous"),r.alt=i.name,r.src=e.url}draw({naturalWidth:e,naturalHeight:t}){const{file:r,image:n,options:s}=this,o=document.createElement("canvas"),l=o.getContext("2d"),u=("contain"===s.resize||"cover"===s.resize)&&i(s.width)&&i(s.height);let m=Math.max(s.maxWidth,0)||1/0,w=Math.max(s.maxHeight,0)||1/0,p=Math.max(s.minWidth,0)||0,b=Math.max(s.minHeight,0)||0,y=e/t,{width:U,height:v}=s;u&&(y=U/v),({width:m,height:w}=c({aspectRatio:y,width:m,height:w},"contain")),({width:p,height:b}=c({aspectRatio:y,width:p,height:b},"cover")),u?({width:U,height:v}=c({aspectRatio:y,width:U,height:v},s.resize)):({width:U=e,height:v=t}=c({aspectRatio:y,width:U,height:v})),U=Math.floor(d(Math.min(Math.max(U,p),m))),v=Math.floor(d(Math.min(Math.max(v,b),w)));const x=[];if(u){const{width:i,height:r}=c({aspectRatio:y,width:e,height:t},{contain:"cover",cover:"contain"}[s.resize]),a=(e-i)/2,n=(t-r)/2;x.push(a,n,i,r)}x.push(0,0,U,v),o.width=U,o.height=v,a(s.mimeType)||(s.mimeType=r.type);let E="transparent";!this.mimeTypeSet&&r.size>s.convertSize&&s.convertTypes.indexOf(s.mimeType)>=0&&(s.mimeType="image/jpeg");const F="image/jpeg"===s.mimeType;if(F&&(E="#fff"),l.fillStyle=E,l.fillRect(0,0,U,v),s.beforeDraw&&s.beforeDraw.call(this,l,o),this.aborted)return;if(l.drawImage(n,...x),s.drew&&s.drew.call(this,l,o),this.aborted)return;o.toBlob(i=>{if(!this.aborted){const r=i=>this.done({naturalWidth:e,naturalHeight:t,result:i});if(i&&F&&s.retainExif&&this.exif&&this.exif.length>0){const e=e=>{if(this.aborted)return;const t=function(e,t){const i=new DataView(e),r=new Uint8Array(e);if(255!==i.getUint8(2)||224!==i.getUint8(3))return r;const a=4+i.getUint16(4),n=r.byteLength-a,s=new Uint8Array(2+t.length+n);s[0]=255,s[1]=216;for(let e=0;e<t.length;e+=1)s[2+e]=t[e];return s.set(r.subarray(a),2+t.length),s}(e,this.exif);r(f(t,s.mimeType))};if(i.arrayBuffer)i.arrayBuffer().then(e).catch(()=>{this.aborted||this.fail(new Error("Failed to read the compressed image with `Blob.arrayBuffer()`."))});else{const t=new g;this.reader=t,t.onload=({target:t})=>{e(t.result)},t.onabort=()=>{this.fail(new Error("Aborted to read the compressed image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the compressed image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(i)}}else if(i&&F&&!s.retainExif){const e=e=>{this.aborted||r(f(h(e),s.mimeType))};if(i.arrayBuffer)i.arrayBuffer().then(e).catch(()=>{this.aborted||this.fail(new Error("Failed to read the compressed image with `Blob.arrayBuffer()`."))});else{const t=new g;this.reader=t,t.onload=({target:t})=>{e(t.result)},t.onabort=()=>{this.fail(new Error("Aborted to read the compressed image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the compressed image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(i)}}else r(i)}},s.mimeType,s.quality)}done({naturalWidth:e,naturalHeight:t,result:i}){const{file:r,options:n}=this;this.revokeUrl();let s=!1;if(i)if(n.strict&&!n.retainExif&&i.size>r.size&&n.mimeType===r.type&&!(n.width>e||n.height>t||n.minWidth>e||n.minHeight>t||n.maxWidth<e||n.maxHeight<t))i=r,s=!0;else{const e=new Date;let t=r.name||"";t&&i.type!==r.type&&(t=t.replace(w,function(e){let t=a(e)?e.slice(6):"";return"jpeg"===t&&(t="jpg"),`.${t}`}(i.type))),i=new File([i],t,{type:i.type,lastModified:e.getTime()})}else console.warn("Compressor.js Next: Canvas produced no output—returning the original image"),i=r;if(s&&"image/jpeg"===r.type)if(r.arrayBuffer)r.arrayBuffer().then(e=>{if(this.aborted)return;const t=f(h(e),r.type),i=new File([t],r.name||"",{type:r.type,lastModified:r.lastModified||Date.now()});this.result=i,n.success&&n.success.call(this,i)}).catch(e=>{this.aborted||(console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${r.name?` [${r.name}]`:""}${e?.message?`: ${e.message}`:""}`),this.result=r,n.success&&n.success.call(this,r))});else{const e=new g;this.reader=e,e.onload=({target:e})=>{if(this.aborted)return;const t=f(h(e.result),r.type),i=new File([t],r.name||"",{type:r.type,lastModified:r.lastModified||Date.now()});this.result=i,n.success&&n.success.call(this,i)},e.onabort=()=>{this.fail(new Error("Aborted to read the original file with FileReader."))},e.onerror=()=>{this.aborted||(console.warn("Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact"+(r.name?` [${r.name}]`:"")),this.result=r,n.success&&n.success.call(this,r))},e.onloadend=()=>{this.reader=null},e.readAsArrayBuffer(r)}else this.result=i,n.success&&n.success.call(this,i)}fail(e){const{options:t}=this;if(this.revokeUrl(),!t.error)throw e;t.error.call(this,e)}revokeUrl(){m&&this.url&&(m.revokeObjectURL(this.url),this.url=null)}abort(){this.aborted||(this.aborted=!0,this.reader?this.reader.abort():this.image.complete?this.fail(new Error("The compression process has been aborted.")):(this.image.onload=null,this.image.onerror=null,this.image.onabort=null,this.fail(new Error("Aborted to load the image."))))}static setDefaults(t){Object.assign(e,t)}}});
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Compressor=t()}(this,function(){"use strict";var e={strict:!0,retainExif:!1,maxWidth:1/0,maxHeight:1/0,minWidth:0,minHeight:0,width:void 0,height:void 0,resize:"none",quality:.8,mimeType:"auto",convertTypes:[],convertSize:5e6,beforeDraw:null,drew:null,success:null,error:null};const t="undefined"!=typeof window&&void 0!==window.document?window:{},i=e=>e>0&&e<1/0,r=/^image\/.+$/;function a(e){return r.test(e)}const{fromCharCode:n}=String;function o(e){const t=new DataView(e);let i;try{let e,r,a;if(255===t.getUint8(0)&&216===t.getUint8(1)){const e=t.byteLength;let i=2;for(;i+1<e;){if(255===t.getUint8(i)&&225===t.getUint8(i+1)){r=i;break}i+=1}}if(r){const i=r+10;if("Exif"===function(e,t,i){let r,a="";for(i+=t,r=t;r<i;r+=1)a+=n(e.getUint8(r));return a}(t,r+4,4)){const r=t.getUint16(i);if(e=18761===r,(e||19789===r)&&42===t.getUint16(i+2,e)){const r=t.getUint32(i+4,e);r>=8&&(a=i+r)}}}if(a){const r=t.getUint16(a,e);let n,o;for(o=0;o<r;o+=1)if(n=a+12*o+2,274===t.getUint16(n,e)){n+=8,i=t.getUint16(n,e),t.setUint16(n,1,e);break}}}catch{i=1}return i}let s;function h(e){const t=new DataView(e),{byteLength:i}=t,r=[];if(i<4||255!==t.getUint8(0)||216!==t.getUint8(1))return new Uint8Array(e);r.push(new Uint8Array(e,0,2));let a=2;for(;a+3<i;){const n=t.getUint8(a),o=t.getUint8(a+1);if(255!==n)break;if(218===o){r.push(new Uint8Array(e,a));break}if(a+3>=i)break;const s=t.getUint16(a+2);if(s<2)break;const h=a+2+s;if(h>i)break;225!==o&&r.push(new Uint8Array(e,a,h-a)),a=h}const n=r.reduce((e,t)=>e+t.length,0),o=new Uint8Array(n);let s=0;for(const e of r)o.set(e,s),s+=e.length;return o}const l=/\.\d*(?:0|9){12}\d*$/;function d(e,t=1e11){return l.test(e)?Math.round(e*t)/t:e}function c({aspectRatio:e,height:t,width:r},a="none"){const n=i(r),o=i(t);if(n&&o){const i=t*e;("contain"===a||"none"===a)&&i>r||"cover"===a&&i<r?t=r/e:r=t*e}else n?t=r/e:o&&(r=t*e);return{width:r,height:t}}function f(e,t){return new Blob([e],{type:t})}const{ArrayBuffer:u,FileReader:g}=t,m=t.URL||t.webkitURL,w=/\.\w+$/;return class{constructor(t,i){this.file=t,this.exif=[],this.image=new Image,this.options={...e,...i},this.mimeTypeSet=i&&i.mimeType&&a(i.mimeType),this.aborted=!1,this.canvasFallback=!1,this.result=null,this.url=null,this.init()}init(){const{file:e,options:t}=this;if(!(e instanceof Blob))return void this.fail(new Error("The first argument must be a File or Blob object."));const i=e.type;if(!a(i))return void this.fail(new Error("The first argument must be an image File or Blob object."));if(!m||!g)return void this.fail(new Error("The current browser does not support image compression."));if(u||(t.retainExif=!1),!function(){if(void 0!==s)return s;try{const e=document.createElement("canvas");e.width=4,e.height=4;const t=e.getContext("2d"),i=t.createImageData(e.width,e.height);for(let e=0;e<i.data.length;e+=4)i.data[e]=e,i.data[e+1]=1,i.data[e+2]=2,i.data[e+3]=255;t.putImageData(i,0,0);const r=t.getImageData(0,0,e.width,e.height);s=r.data.every((e,t)=>{const i=t%4;return 0===i?e===(255&t):1===i?1===e:2===i?2===e:255===e})}catch{s=!1}return s}()){if(console.warn("Compressor.js Next: Canvas data is unreliable (e.g., due to browser fingerprinting resistance)—compression, resizing, and format conversion are unavailable"),this.canvasFallback=!0,"image/jpeg"!==i||t.retainExif)Promise.resolve().then(()=>{this.aborted||this.succeed(e)});else{const t=new g;this.reader=t,t.onload=({target:t})=>{if(this.aborted)return;let r;try{r=f(h(t.result),i)}catch{return void this.fail(new Error("Failed to process the image data."))}const a=new Date,n=new File([r],e.name||"",{type:i,lastModified:a.getTime()});this.succeed(n)},t.onabort=()=>{this.fail(new Error("Aborted to read the image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(e)}return}if("image/jpeg"===i&&t.retainExif){const t=new g;this.reader=t,t.onload=({target:t})=>{this.aborted||(o(t.result),this.exif=function(e){const t=new DataView(e),{byteLength:i}=t,r=[];let a=0;for(;a+3<i;){const e=t.getUint8(a),n=t.getUint8(a+1);if(255===e&&218===n)break;if(255===e&&216===n)a+=2;else{const o=a+t.getUint16(a+2)+2;if(255===e&&225===n)for(let e=a;e<o&&e<i;e+=1)r.push(t.getUint8(e));a=o}}return r}(t.result),this.url=m.createObjectURL(e),this.load({url:this.url}))},t.onabort=()=>{this.fail(new Error("Aborted to read the image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(e)}else this.url=m.createObjectURL(e),this.load({url:this.url})}load(e){const{file:i,image:r}=this;r.onload=()=>{this.draw({...e,naturalWidth:r.naturalWidth,naturalHeight:r.naturalHeight})},r.onabort=()=>{this.fail(new Error("Aborted to load the image."))},r.onerror=()=>{this.fail(new Error("Failed to load the image."))},t.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(t.navigator.userAgent)&&(r.crossOrigin="anonymous"),r.alt=i.name,r.src=e.url}draw({naturalWidth:e,naturalHeight:t}){const{file:r,image:n,options:o}=this,s=document.createElement("canvas"),l=s.getContext("2d"),u=("contain"===o.resize||"cover"===o.resize)&&i(o.width)&&i(o.height);let g=Math.max(o.maxWidth,0)||1/0,m=Math.max(o.maxHeight,0)||1/0,w=Math.max(o.minWidth,0)||0,p=Math.max(o.minHeight,0)||0,b=e/t,{width:y,height:U}=o;u&&(b=y/U),({width:g,height:m}=c({aspectRatio:b,width:g,height:m},"contain")),({width:w,height:p}=c({aspectRatio:b,width:w,height:p},"cover")),u?({width:y,height:U}=c({aspectRatio:b,width:y,height:U},o.resize)):({width:y=e,height:U=t}=c({aspectRatio:b,width:y,height:U})),y=Math.floor(d(Math.min(Math.max(y,w),g))),U=Math.floor(d(Math.min(Math.max(U,p),m)));const v=[];if(u){const{width:i,height:r}=c({aspectRatio:b,width:e,height:t},{contain:"cover",cover:"contain"}[o.resize]),a=(e-i)/2,n=(t-r)/2;v.push(a,n,i,r)}v.push(0,0,y,U),s.width=y,s.height=U,a(o.mimeType)||(o.mimeType=r.type);let x="transparent";!this.mimeTypeSet&&r.size>o.convertSize&&o.convertTypes.indexOf(o.mimeType)>=0&&(o.mimeType="image/jpeg");const A="image/jpeg"===o.mimeType;if(A&&(x="#fff"),l.fillStyle=x,l.fillRect(0,0,y,U),o.beforeDraw&&o.beforeDraw.call(this,l,s),this.aborted)return;if(l.drawImage(n,...v),o.drew&&o.drew.call(this,l,s),this.aborted)return;s.toBlob(i=>{if(!this.aborted){const r=i=>this.done({naturalWidth:e,naturalHeight:t,result:i});i&&A&&o.retainExif&&this.exif&&this.exif.length>0?this.readBlobAsArrayBuffer(i,e=>{if(this.aborted)return;const t=function(e,t){const i=new DataView(e),r=new Uint8Array(e);if(255!==i.getUint8(2)||224!==i.getUint8(3))return r;const a=4+i.getUint16(4),n=r.byteLength-a,o=new Uint8Array(2+t.length+n);o[0]=255,o[1]=216;for(let e=0;e<t.length;e+=1)o[2+e]=t[e];return o.set(r.subarray(a),2+t.length),o}(e,this.exif);r(f(t,o.mimeType))}):i&&A&&!o.retainExif?this.readBlobAsArrayBuffer(i,e=>{this.aborted||r(f(h(e),o.mimeType))}):r(i)}},o.mimeType,o.quality)}done({naturalWidth:e,naturalHeight:t,result:i}){const{file:r,options:n}=this;this.revokeUrl();let o=!1;if(i)if(n.strict&&!n.retainExif&&i.size>r.size&&n.mimeType===r.type&&!(n.width>e||n.height>t||n.minWidth>e||n.minHeight>t||n.maxWidth<e||n.maxHeight<t))i=r,o=!0;else{const e=new Date;let t=r.name||"";t&&i.type!==r.type&&(t=t.replace(w,function(e){let t=a(e)?e.slice(6):"";return"jpeg"===t&&(t="jpg"),`.${t}`}(i.type))),i=new File([i],t,{type:i.type,lastModified:e.getTime()})}else console.warn("Compressor.js Next: Canvas produced no output—returning the original image"),i=r;if(o&&"image/jpeg"===r.type)if(r.arrayBuffer)r.arrayBuffer().then(e=>{if(this.aborted)return;const t=f(h(e),r.type),i=new File([t],r.name||"",{type:r.type,lastModified:r.lastModified||Date.now()});this.succeed(i)}).catch(e=>{this.aborted||(console.warn(`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${r.name?` [${r.name}]`:""}${e?.message?`: ${e.message}`:""}`),this.succeed(r))});else{const e=new g;this.reader=e,e.onload=({target:e})=>{if(this.aborted)return;const t=f(h(e.result),r.type),i=new File([t],r.name||"",{type:r.type,lastModified:r.lastModified||Date.now()});this.succeed(i)},e.onabort=()=>{this.fail(new Error("Aborted to read the original file with FileReader."))},e.onerror=()=>{this.aborted||(console.warn("Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact"+(r.name?` [${r.name}]`:"")),this.succeed(r))},e.onloadend=()=>{this.reader=null},e.readAsArrayBuffer(r)}else this.succeed(i)}readBlobAsArrayBuffer(e,t){if(e.arrayBuffer)e.arrayBuffer().then(t).catch(()=>{setTimeout(()=>{this.aborted||this.fail(new Error("Failed to read the compressed image with `Blob.arrayBuffer()`."))},0)});else{const i=new g;this.reader=i,i.onload=({target:e})=>{try{t(e.result)}catch(e){this.aborted||this.fail(e)}},i.onabort=()=>{this.fail(new Error("Aborted to read the compressed image with FileReader."))},i.onerror=()=>{this.fail(new Error("Failed to read the compressed image with FileReader."))},i.onloadend=()=>{this.reader=null},i.readAsArrayBuffer(e)}}succeed(e){this.result=e,this.options.success&&this.options.success.call(this,e)}fail(e){const{options:t}=this;if(this.revokeUrl(),!t.error)throw e;t.error.call(this,e)}revokeUrl(){m&&this.url&&(m.revokeObjectURL(this.url),this.url=null)}abort(){this.aborted||(this.aborted=!0,this.reader?this.reader.abort():this.image.complete?this.fail(new Error("The compression process has been aborted.")):(this.image.onload=null,this.image.onerror=null,this.image.onabort=null,this.fail(new Error("Aborted to load the image."))))}static setDefaults(t){Object.assign(e,t)}}});
|
package/package.json
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
"url": "https://meiert.com/"
|
|
5
5
|
},
|
|
6
6
|
"browser": "dist/compressor.js",
|
|
7
|
-
"bugs": {
|
|
8
|
-
"url": "https://github.com/j9t/compressorjs-next/issues"
|
|
9
|
-
},
|
|
10
7
|
"contributors": [
|
|
11
8
|
{
|
|
12
9
|
"name": "Chen Fengyuan",
|
|
@@ -18,21 +15,22 @@
|
|
|
18
15
|
"@babel/core": "^7.29.0",
|
|
19
16
|
"@babel/preset-env": "^7.29.0",
|
|
20
17
|
"@eslint/js": "^10.0.0",
|
|
21
|
-
"@rollup/plugin-babel": "^
|
|
22
|
-
"@rollup/plugin-commonjs": "^29.0.
|
|
18
|
+
"@rollup/plugin-babel": "^7.0.0",
|
|
19
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
23
20
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
24
|
-
"@vitest/browser-playwright": "^4.0
|
|
25
|
-
"@vitest/coverage-istanbul": "^4.0
|
|
21
|
+
"@vitest/browser-playwright": "^4.1.0",
|
|
22
|
+
"@vitest/coverage-istanbul": "^4.1.0",
|
|
26
23
|
"del-cli": "^7.0.0",
|
|
27
|
-
"eslint": "^10.
|
|
24
|
+
"eslint": "^10.1.0",
|
|
25
|
+
"globals": "^17.0.0",
|
|
28
26
|
"husky": "^9.1.7",
|
|
29
|
-
"playwright": "^1.
|
|
30
|
-
"rollup": "^4.
|
|
31
|
-
"stylelint": "^17.
|
|
27
|
+
"playwright": "^1.59.1",
|
|
28
|
+
"rollup": "^4.60.0",
|
|
29
|
+
"stylelint": "^17.6.0",
|
|
32
30
|
"stylelint-config-standard": "^40.0.0",
|
|
33
|
-
"stylelint-order": "^
|
|
31
|
+
"stylelint-order": "^8.1.1",
|
|
34
32
|
"terser": "^5.46.0",
|
|
35
|
-
"vitest": "^4.0
|
|
33
|
+
"vitest": "^4.1.0"
|
|
36
34
|
},
|
|
37
35
|
"exports": {
|
|
38
36
|
".": {
|
|
@@ -95,5 +93,5 @@
|
|
|
95
93
|
"sideEffects": false,
|
|
96
94
|
"type": "module",
|
|
97
95
|
"types": "types/index.d.ts",
|
|
98
|
-
"version": "2.0.
|
|
96
|
+
"version": "2.0.3"
|
|
99
97
|
}
|
package/src/index.js
CHANGED
|
@@ -98,11 +98,7 @@ export default class Compressor {
|
|
|
98
98
|
lastModified: date.getTime(),
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
this.result
|
|
102
|
-
|
|
103
|
-
if (options.success) {
|
|
104
|
-
options.success.call(this, result);
|
|
105
|
-
}
|
|
101
|
+
this.succeed(result);
|
|
106
102
|
};
|
|
107
103
|
reader.onabort = () => {
|
|
108
104
|
this.fail(new Error('Aborted to read the image with FileReader.'));
|
|
@@ -119,12 +115,7 @@ export default class Compressor {
|
|
|
119
115
|
// Defer callback to match the normal async flow
|
|
120
116
|
Promise.resolve().then(() => {
|
|
121
117
|
if (this.aborted) return;
|
|
122
|
-
|
|
123
|
-
this.result = file;
|
|
124
|
-
|
|
125
|
-
if (options.success) {
|
|
126
|
-
options.success.call(this, file);
|
|
127
|
-
}
|
|
118
|
+
this.succeed(file);
|
|
128
119
|
});
|
|
129
120
|
}
|
|
130
121
|
|
|
@@ -312,67 +303,19 @@ export default class Compressor {
|
|
|
312
303
|
});
|
|
313
304
|
|
|
314
305
|
if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) {
|
|
315
|
-
|
|
306
|
+
this.readBlobAsArrayBuffer(blob, (arrayBuffer) => {
|
|
316
307
|
if (this.aborted) return;
|
|
317
308
|
const withExif = insertExif(arrayBuffer, this.exif);
|
|
318
309
|
done(uint8ArrayToBlob(withExif, options.mimeType));
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
if (blob.arrayBuffer) {
|
|
322
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
323
|
-
if (this.aborted) return;
|
|
324
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
325
|
-
});
|
|
326
|
-
} else {
|
|
327
|
-
const reader = new FileReader();
|
|
328
|
-
|
|
329
|
-
this.reader = reader;
|
|
330
|
-
reader.onload = ({ target }) => {
|
|
331
|
-
next(target.result);
|
|
332
|
-
};
|
|
333
|
-
reader.onabort = () => {
|
|
334
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
335
|
-
};
|
|
336
|
-
reader.onerror = () => {
|
|
337
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
338
|
-
};
|
|
339
|
-
reader.onloadend = () => {
|
|
340
|
-
this.reader = null;
|
|
341
|
-
};
|
|
342
|
-
reader.readAsArrayBuffer(blob);
|
|
343
|
-
}
|
|
310
|
+
});
|
|
344
311
|
} else if (blob && isJPEGImage && !options.retainExif) {
|
|
345
312
|
// Strip any EXIF that may be present in the canvas output
|
|
346
313
|
// (most browsers strip it automatically, but WebKit preserves the
|
|
347
314
|
// source EXIF—this ensures consistent, privacy-safe output)
|
|
348
|
-
|
|
315
|
+
this.readBlobAsArrayBuffer(blob, (arrayBuffer) => {
|
|
349
316
|
if (this.aborted) return;
|
|
350
317
|
done(uint8ArrayToBlob(stripExif(arrayBuffer), options.mimeType));
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
if (blob.arrayBuffer) {
|
|
354
|
-
blob.arrayBuffer().then(next).catch(() => {
|
|
355
|
-
if (this.aborted) return;
|
|
356
|
-
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
357
|
-
});
|
|
358
|
-
} else {
|
|
359
|
-
const reader = new FileReader();
|
|
360
|
-
|
|
361
|
-
this.reader = reader;
|
|
362
|
-
reader.onload = ({ target }) => {
|
|
363
|
-
next(target.result);
|
|
364
|
-
};
|
|
365
|
-
reader.onabort = () => {
|
|
366
|
-
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
367
|
-
};
|
|
368
|
-
reader.onerror = () => {
|
|
369
|
-
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
370
|
-
};
|
|
371
|
-
reader.onloadend = () => {
|
|
372
|
-
this.reader = null;
|
|
373
|
-
};
|
|
374
|
-
reader.readAsArrayBuffer(blob);
|
|
375
|
-
}
|
|
318
|
+
});
|
|
376
319
|
} else {
|
|
377
320
|
done(blob);
|
|
378
321
|
}
|
|
@@ -447,11 +390,7 @@ export default class Compressor {
|
|
|
447
390
|
lastModified: file.lastModified || Date.now(),
|
|
448
391
|
});
|
|
449
392
|
|
|
450
|
-
this.
|
|
451
|
-
|
|
452
|
-
if (options.success) {
|
|
453
|
-
options.success.call(this, stripped);
|
|
454
|
-
}
|
|
393
|
+
this.succeed(stripped);
|
|
455
394
|
}).catch((err) => {
|
|
456
395
|
if (this.aborted) return;
|
|
457
396
|
|
|
@@ -459,11 +398,7 @@ export default class Compressor {
|
|
|
459
398
|
`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}${err?.message ? `: ${err.message}` : ''}`,
|
|
460
399
|
);
|
|
461
400
|
|
|
462
|
-
this.
|
|
463
|
-
|
|
464
|
-
if (options.success) {
|
|
465
|
-
options.success.call(this, file);
|
|
466
|
-
}
|
|
401
|
+
this.succeed(file);
|
|
467
402
|
});
|
|
468
403
|
} else {
|
|
469
404
|
const reader = new FileReader();
|
|
@@ -478,11 +413,7 @@ export default class Compressor {
|
|
|
478
413
|
lastModified: file.lastModified || Date.now(),
|
|
479
414
|
});
|
|
480
415
|
|
|
481
|
-
this.
|
|
482
|
-
|
|
483
|
-
if (options.success) {
|
|
484
|
-
options.success.call(this, stripped);
|
|
485
|
-
}
|
|
416
|
+
this.succeed(stripped);
|
|
486
417
|
};
|
|
487
418
|
reader.onabort = () => {
|
|
488
419
|
this.fail(new Error('Aborted to read the original file with FileReader.'));
|
|
@@ -494,11 +425,7 @@ export default class Compressor {
|
|
|
494
425
|
`Compressor.js Next: Failed to strip EXIF from original file—returning original with EXIF intact${file.name ? ` [${file.name}]` : ''}`,
|
|
495
426
|
);
|
|
496
427
|
|
|
497
|
-
this.
|
|
498
|
-
|
|
499
|
-
if (options.success) {
|
|
500
|
-
options.success.call(this, file);
|
|
501
|
-
}
|
|
428
|
+
this.succeed(file);
|
|
502
429
|
};
|
|
503
430
|
reader.onloadend = () => {
|
|
504
431
|
this.reader = null;
|
|
@@ -509,10 +436,48 @@ export default class Compressor {
|
|
|
509
436
|
return;
|
|
510
437
|
}
|
|
511
438
|
|
|
439
|
+
this.succeed(result);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
readBlobAsArrayBuffer(blob, next) {
|
|
443
|
+
if (blob.arrayBuffer) {
|
|
444
|
+
blob.arrayBuffer().then(next).catch(() => {
|
|
445
|
+
// Defer to a macrotask so any `abort()` scheduled via `setTimeout()`
|
|
446
|
+
// in a `drew()` hook has a chance to set `this.aborted` first
|
|
447
|
+
setTimeout(() => {
|
|
448
|
+
if (this.aborted) return;
|
|
449
|
+
this.fail(new Error('Failed to read the compressed image with `Blob.arrayBuffer()`.'));
|
|
450
|
+
}, 0);
|
|
451
|
+
});
|
|
452
|
+
} else {
|
|
453
|
+
const reader = new FileReader();
|
|
454
|
+
|
|
455
|
+
this.reader = reader;
|
|
456
|
+
reader.onload = ({ target }) => {
|
|
457
|
+
try {
|
|
458
|
+
next(target.result);
|
|
459
|
+
} catch (err) {
|
|
460
|
+
if (!this.aborted) this.fail(err);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
reader.onabort = () => {
|
|
464
|
+
this.fail(new Error('Aborted to read the compressed image with FileReader.'));
|
|
465
|
+
};
|
|
466
|
+
reader.onerror = () => {
|
|
467
|
+
this.fail(new Error('Failed to read the compressed image with FileReader.'));
|
|
468
|
+
};
|
|
469
|
+
reader.onloadend = () => {
|
|
470
|
+
this.reader = null;
|
|
471
|
+
};
|
|
472
|
+
reader.readAsArrayBuffer(blob);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
succeed(result) {
|
|
512
477
|
this.result = result;
|
|
513
478
|
|
|
514
|
-
if (options.success) {
|
|
515
|
-
options.success.call(this, result);
|
|
479
|
+
if (this.options.success) {
|
|
480
|
+
this.options.success.call(this, result);
|
|
516
481
|
}
|
|
517
482
|
}
|
|
518
483
|
|
|
File without changes
|