compressorjs-next 2.0.0 → 2.0.1
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/README.md +1 -1
- package/dist/compressor.common.js +24 -16
- package/dist/compressor.esm.js +24 -16
- package/dist/compressor.js +24 -16
- package/dist/compressor.min.js +2 -2
- package/package.json +2 -2
- package/src/index.js +24 -18
- /package/{LICENSE → LICENSE.md} +0 -0
package/README.md
CHANGED
|
@@ -297,7 +297,7 @@ new Compressor(file, {
|
|
|
297
297
|
* Type: `Function`
|
|
298
298
|
* Default: `null`
|
|
299
299
|
* Parameters:
|
|
300
|
-
- `result`: The compressed image (a `File`
|
|
300
|
+
- `result`: The compressed image (a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) object, which is also a `Blob`).
|
|
301
301
|
|
|
302
302
|
The hook function to execute when successful to compress the image.
|
|
303
303
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.1
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -537,17 +537,18 @@ class Compressor {
|
|
|
537
537
|
target
|
|
538
538
|
}) => {
|
|
539
539
|
if (this.aborted) return;
|
|
540
|
-
let
|
|
540
|
+
let blob;
|
|
541
541
|
try {
|
|
542
|
-
|
|
543
|
-
result = uint8ArrayToBlob(stripped, mimeType);
|
|
542
|
+
blob = uint8ArrayToBlob(stripExif(target.result), mimeType);
|
|
544
543
|
} catch {
|
|
545
544
|
this.fail(new Error('Failed to process the image data.'));
|
|
546
545
|
return;
|
|
547
546
|
}
|
|
548
547
|
const date = new Date();
|
|
549
|
-
result
|
|
550
|
-
|
|
548
|
+
const result = new File([blob], file.name || '', {
|
|
549
|
+
type: mimeType,
|
|
550
|
+
lastModified: date.getTime()
|
|
551
|
+
});
|
|
551
552
|
this.result = result;
|
|
552
553
|
if (options.success) {
|
|
553
554
|
options.success.call(this, result);
|
|
@@ -846,13 +847,16 @@ class Compressor {
|
|
|
846
847
|
strictFallback = true;
|
|
847
848
|
} else {
|
|
848
849
|
const date = new Date();
|
|
849
|
-
|
|
850
|
-
result.name = file.name;
|
|
850
|
+
let name = file.name || '';
|
|
851
851
|
|
|
852
852
|
// Convert the extension to match its type
|
|
853
|
-
if (
|
|
854
|
-
|
|
853
|
+
if (name && result.type !== file.type) {
|
|
854
|
+
name = name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
|
|
855
855
|
}
|
|
856
|
+
result = new File([result], name, {
|
|
857
|
+
type: result.type,
|
|
858
|
+
lastModified: date.getTime()
|
|
859
|
+
});
|
|
856
860
|
}
|
|
857
861
|
} else {
|
|
858
862
|
// Returns original file if the result is null in some cases
|
|
@@ -866,9 +870,11 @@ class Compressor {
|
|
|
866
870
|
if (file.arrayBuffer) {
|
|
867
871
|
file.arrayBuffer().then(arrayBuffer => {
|
|
868
872
|
if (this.aborted) return;
|
|
869
|
-
const
|
|
870
|
-
stripped
|
|
871
|
-
|
|
873
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(arrayBuffer), file.type);
|
|
874
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
875
|
+
type: file.type,
|
|
876
|
+
lastModified: file.lastModified || Date.now()
|
|
877
|
+
});
|
|
872
878
|
this.result = stripped;
|
|
873
879
|
if (options.success) {
|
|
874
880
|
options.success.call(this, stripped);
|
|
@@ -888,9 +894,11 @@ class Compressor {
|
|
|
888
894
|
target
|
|
889
895
|
}) => {
|
|
890
896
|
if (this.aborted) return;
|
|
891
|
-
const
|
|
892
|
-
stripped
|
|
893
|
-
|
|
897
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(target.result), file.type);
|
|
898
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
899
|
+
type: file.type,
|
|
900
|
+
lastModified: file.lastModified || Date.now()
|
|
901
|
+
});
|
|
894
902
|
this.result = stripped;
|
|
895
903
|
if (options.success) {
|
|
896
904
|
options.success.call(this, stripped);
|
package/dist/compressor.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.1
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -535,17 +535,18 @@ class Compressor {
|
|
|
535
535
|
target
|
|
536
536
|
}) => {
|
|
537
537
|
if (this.aborted) return;
|
|
538
|
-
let
|
|
538
|
+
let blob;
|
|
539
539
|
try {
|
|
540
|
-
|
|
541
|
-
result = uint8ArrayToBlob(stripped, mimeType);
|
|
540
|
+
blob = uint8ArrayToBlob(stripExif(target.result), mimeType);
|
|
542
541
|
} catch {
|
|
543
542
|
this.fail(new Error('Failed to process the image data.'));
|
|
544
543
|
return;
|
|
545
544
|
}
|
|
546
545
|
const date = new Date();
|
|
547
|
-
result
|
|
548
|
-
|
|
546
|
+
const result = new File([blob], file.name || '', {
|
|
547
|
+
type: mimeType,
|
|
548
|
+
lastModified: date.getTime()
|
|
549
|
+
});
|
|
549
550
|
this.result = result;
|
|
550
551
|
if (options.success) {
|
|
551
552
|
options.success.call(this, result);
|
|
@@ -844,13 +845,16 @@ class Compressor {
|
|
|
844
845
|
strictFallback = true;
|
|
845
846
|
} else {
|
|
846
847
|
const date = new Date();
|
|
847
|
-
|
|
848
|
-
result.name = file.name;
|
|
848
|
+
let name = file.name || '';
|
|
849
849
|
|
|
850
850
|
// Convert the extension to match its type
|
|
851
|
-
if (
|
|
852
|
-
|
|
851
|
+
if (name && result.type !== file.type) {
|
|
852
|
+
name = name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
|
|
853
853
|
}
|
|
854
|
+
result = new File([result], name, {
|
|
855
|
+
type: result.type,
|
|
856
|
+
lastModified: date.getTime()
|
|
857
|
+
});
|
|
854
858
|
}
|
|
855
859
|
} else {
|
|
856
860
|
// Returns original file if the result is null in some cases
|
|
@@ -864,9 +868,11 @@ class Compressor {
|
|
|
864
868
|
if (file.arrayBuffer) {
|
|
865
869
|
file.arrayBuffer().then(arrayBuffer => {
|
|
866
870
|
if (this.aborted) return;
|
|
867
|
-
const
|
|
868
|
-
stripped
|
|
869
|
-
|
|
871
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(arrayBuffer), file.type);
|
|
872
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
873
|
+
type: file.type,
|
|
874
|
+
lastModified: file.lastModified || Date.now()
|
|
875
|
+
});
|
|
870
876
|
this.result = stripped;
|
|
871
877
|
if (options.success) {
|
|
872
878
|
options.success.call(this, stripped);
|
|
@@ -886,9 +892,11 @@ class Compressor {
|
|
|
886
892
|
target
|
|
887
893
|
}) => {
|
|
888
894
|
if (this.aborted) return;
|
|
889
|
-
const
|
|
890
|
-
stripped
|
|
891
|
-
|
|
895
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(target.result), file.type);
|
|
896
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
897
|
+
type: file.type,
|
|
898
|
+
lastModified: file.lastModified || Date.now()
|
|
899
|
+
});
|
|
892
900
|
this.result = stripped;
|
|
893
901
|
if (options.success) {
|
|
894
902
|
options.success.call(this, stripped);
|
package/dist/compressor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.1
|
|
3
3
|
* https://github.com/j9t/compressorjs-next
|
|
4
4
|
*
|
|
5
5
|
* Copyright 2018–2024 Chen Fengyuan
|
|
@@ -541,17 +541,18 @@
|
|
|
541
541
|
target
|
|
542
542
|
}) => {
|
|
543
543
|
if (this.aborted) return;
|
|
544
|
-
let
|
|
544
|
+
let blob;
|
|
545
545
|
try {
|
|
546
|
-
|
|
547
|
-
result = uint8ArrayToBlob(stripped, mimeType);
|
|
546
|
+
blob = uint8ArrayToBlob(stripExif(target.result), mimeType);
|
|
548
547
|
} catch {
|
|
549
548
|
this.fail(new Error('Failed to process the image data.'));
|
|
550
549
|
return;
|
|
551
550
|
}
|
|
552
551
|
const date = new Date();
|
|
553
|
-
result
|
|
554
|
-
|
|
552
|
+
const result = new File([blob], file.name || '', {
|
|
553
|
+
type: mimeType,
|
|
554
|
+
lastModified: date.getTime()
|
|
555
|
+
});
|
|
555
556
|
this.result = result;
|
|
556
557
|
if (options.success) {
|
|
557
558
|
options.success.call(this, result);
|
|
@@ -850,13 +851,16 @@
|
|
|
850
851
|
strictFallback = true;
|
|
851
852
|
} else {
|
|
852
853
|
const date = new Date();
|
|
853
|
-
|
|
854
|
-
result.name = file.name;
|
|
854
|
+
let name = file.name || '';
|
|
855
855
|
|
|
856
856
|
// Convert the extension to match its type
|
|
857
|
-
if (
|
|
858
|
-
|
|
857
|
+
if (name && result.type !== file.type) {
|
|
858
|
+
name = name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
|
|
859
859
|
}
|
|
860
|
+
result = new File([result], name, {
|
|
861
|
+
type: result.type,
|
|
862
|
+
lastModified: date.getTime()
|
|
863
|
+
});
|
|
860
864
|
}
|
|
861
865
|
} else {
|
|
862
866
|
// Returns original file if the result is null in some cases
|
|
@@ -870,9 +874,11 @@
|
|
|
870
874
|
if (file.arrayBuffer) {
|
|
871
875
|
file.arrayBuffer().then(arrayBuffer => {
|
|
872
876
|
if (this.aborted) return;
|
|
873
|
-
const
|
|
874
|
-
stripped
|
|
875
|
-
|
|
877
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(arrayBuffer), file.type);
|
|
878
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
879
|
+
type: file.type,
|
|
880
|
+
lastModified: file.lastModified || Date.now()
|
|
881
|
+
});
|
|
876
882
|
this.result = stripped;
|
|
877
883
|
if (options.success) {
|
|
878
884
|
options.success.call(this, stripped);
|
|
@@ -892,9 +898,11 @@
|
|
|
892
898
|
target
|
|
893
899
|
}) => {
|
|
894
900
|
if (this.aborted) return;
|
|
895
|
-
const
|
|
896
|
-
stripped
|
|
897
|
-
|
|
901
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(target.result), file.type);
|
|
902
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
903
|
+
type: file.type,
|
|
904
|
+
lastModified: file.lastModified || Date.now()
|
|
905
|
+
});
|
|
898
906
|
this.result = stripped;
|
|
899
907
|
if (options.success) {
|
|
900
908
|
options.success.call(this, stripped);
|
package/dist/compressor.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Compressor.js Next v2.0.
|
|
2
|
+
* Compressor.js Next v2.0.1
|
|
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;a.name=e.name,a.lastModified=n.getTime(),this.result=a,t.success&&t.success.call(this,a)},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;i.lastModified=e.getTime(),i.name=r.name,i.name&&i.type!==r.type&&(i.name=i.name.replace(w,function(e){let t=a(e)?e.slice(6):"";return"jpeg"===t&&(t="jpg"),`.${t}`}(i.type)))}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);t.name=r.name,t.lastModified=r.lastModified,this.result=t,n.success&&n.success.call(this,t)}).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);t.name=r.name,t.lastModified=r.lastModified,this.result=t,n.success&&n.success.call(this,t)},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 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)}}});
|
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"eslint": "^10.0.0",
|
|
28
28
|
"husky": "^9.1.7",
|
|
29
29
|
"playwright": "^1.58.2",
|
|
30
|
-
"rollup": "^4.
|
|
30
|
+
"rollup": "^4.59.0",
|
|
31
31
|
"stylelint": "^17.1.1",
|
|
32
32
|
"stylelint-config-standard": "^40.0.0",
|
|
33
33
|
"stylelint-order": "^7.0.1",
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
"sideEffects": false,
|
|
96
96
|
"type": "module",
|
|
97
97
|
"types": "types/index.d.ts",
|
|
98
|
-
"version": "2.0.
|
|
98
|
+
"version": "2.0.1"
|
|
99
99
|
}
|
package/src/index.js
CHANGED
|
@@ -83,21 +83,20 @@ export default class Compressor {
|
|
|
83
83
|
reader.onload = ({ target }) => {
|
|
84
84
|
if (this.aborted) return;
|
|
85
85
|
|
|
86
|
-
let
|
|
86
|
+
let blob;
|
|
87
87
|
|
|
88
88
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
result = uint8ArrayToBlob(stripped, mimeType);
|
|
89
|
+
blob = uint8ArrayToBlob(stripExif(target.result), mimeType);
|
|
92
90
|
} catch {
|
|
93
91
|
this.fail(new Error('Failed to process the image data.'));
|
|
94
92
|
return;
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
const date = new Date();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
const result = new File([blob], file.name || '', {
|
|
97
|
+
type: mimeType,
|
|
98
|
+
lastModified: date.getTime(),
|
|
99
|
+
});
|
|
101
100
|
|
|
102
101
|
this.result = result;
|
|
103
102
|
|
|
@@ -414,17 +413,20 @@ export default class Compressor {
|
|
|
414
413
|
strictFallback = true;
|
|
415
414
|
} else {
|
|
416
415
|
const date = new Date();
|
|
417
|
-
|
|
418
|
-
result.lastModified = date.getTime();
|
|
419
|
-
result.name = file.name;
|
|
416
|
+
let name = file.name || '';
|
|
420
417
|
|
|
421
418
|
// Convert the extension to match its type
|
|
422
|
-
if (
|
|
423
|
-
|
|
419
|
+
if (name && result.type !== file.type) {
|
|
420
|
+
name = name.replace(
|
|
424
421
|
REGEXP_EXTENSION,
|
|
425
422
|
imageTypeToExtension(result.type),
|
|
426
423
|
);
|
|
427
424
|
}
|
|
425
|
+
|
|
426
|
+
result = new File([result], name, {
|
|
427
|
+
type: result.type,
|
|
428
|
+
lastModified: date.getTime(),
|
|
429
|
+
});
|
|
428
430
|
}
|
|
429
431
|
} else {
|
|
430
432
|
// Returns original file if the result is null in some cases
|
|
@@ -439,10 +441,12 @@ export default class Compressor {
|
|
|
439
441
|
file.arrayBuffer().then((arrayBuffer) => {
|
|
440
442
|
if (this.aborted) return;
|
|
441
443
|
|
|
442
|
-
const
|
|
444
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(arrayBuffer), file.type);
|
|
445
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
446
|
+
type: file.type,
|
|
447
|
+
lastModified: file.lastModified || Date.now(),
|
|
448
|
+
});
|
|
443
449
|
|
|
444
|
-
stripped.name = file.name;
|
|
445
|
-
stripped.lastModified = file.lastModified;
|
|
446
450
|
this.result = stripped;
|
|
447
451
|
|
|
448
452
|
if (options.success) {
|
|
@@ -468,10 +472,12 @@ export default class Compressor {
|
|
|
468
472
|
reader.onload = ({ target }) => {
|
|
469
473
|
if (this.aborted) return;
|
|
470
474
|
|
|
471
|
-
const
|
|
475
|
+
const strippedBlob = uint8ArrayToBlob(stripExif(target.result), file.type);
|
|
476
|
+
const stripped = new File([strippedBlob], file.name || '', {
|
|
477
|
+
type: file.type,
|
|
478
|
+
lastModified: file.lastModified || Date.now(),
|
|
479
|
+
});
|
|
472
480
|
|
|
473
|
-
stripped.name = file.name;
|
|
474
|
-
stripped.lastModified = file.lastModified;
|
|
475
481
|
this.result = stripped;
|
|
476
482
|
|
|
477
483
|
if (options.success) {
|
/package/{LICENSE → LICENSE.md}
RENAMED
|
File without changes
|