compressorjs 1.2.0 → 1.3.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.
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Compressor.js v1.2.0
2
+ * Compressor.js v1.3.0
3
3
  * https://fengyuanchen.github.io/compressorjs
4
4
  *
5
5
  * Copyright 2018-present Chen Fengyuan
6
6
  * Released under the MIT license
7
7
  *
8
- * Date: 2023-02-25T11:35:56.625Z
8
+ * Date: 2026-04-06T07:12:45.816Z
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";function s(){return(s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var i,r=arguments[t];for(i in r)Object.prototype.hasOwnProperty.call(r,i)&&(e[i]=r[i])}return e}).apply(this,arguments)}var e,t,a,l,h,c,d,o,i={exports:{}},L=(e=i,"undefined"!=typeof window&&(a=(t=window).HTMLCanvasElement&&t.HTMLCanvasElement.prototype,l=t.Blob&&function(){try{return Boolean(new Blob)}catch(e){return!1}}(),h=l&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(e){return!1}}(),c=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,d=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,o=(l||c)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(e){var t,i,r,a,o,n=e.match(d);if(!n)throw new Error("invalid data URI");for(t=n[2]?n[1]:"text/plain"+(n[3]||";charset=US-ASCII"),o=!!n[4],e=e.slice(n[0].length),i=(o?atob:decodeURIComponent)(e),n=new ArrayBuffer(i.length),r=new Uint8Array(n),a=0;a<i.length;a+=1)r[a]=i.charCodeAt(a);return l?new Blob([h?r:n],{type:t}):((o=new c).append(n),o.getBlob(t))},t.HTMLCanvasElement&&!a.toBlob&&(a.mozGetAsFile?a.toBlob=function(e,t,i){var r=this;setTimeout(function(){i&&a.toDataURL&&o?e(o(r.toDataURL(t,i))):e(r.mozGetAsFile("blob",t))})}:a.toDataURL&&o&&(a.msToBlob?a.toBlob=function(e,t,i){var r=this;setTimeout(function(){(t&&"image/png"!==t||i)&&a.toDataURL&&o?e(o(r.toDataURL(t,i))):e(r.msToBlob(t))})}:a.toBlob=function(e,t,i){var r=this;setTimeout(function(){e(o(r.toDataURL(t,i)))})})),e.exports?e.exports=o:t.dataURLtoBlob=o),i.exports),r={strict:!0,checkOrientation:!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:["image/png"],convertSize:5e6,beforeDraw:null,drew:null,success:null,error:null};const n="undefined"!=typeof window&&void 0!==window.document?window:{},j=e=>0<e&&e<1/0,f=Array.prototype["slice"];function D(e){return Array.from?Array.from(e):f.call(e)}const u=/^image\/.+$/;function k(e){return u.test(e)}const m=String["fromCharCode"];const g=n["btoa"];function z(e,t){var i=[];let r=new Uint8Array(e);for(;0<r.length;)i.push(m.apply(null,D(r.subarray(0,8192)))),r=r.subarray(8192);return`data:${t};base64,`+g(i.join(""))}function b(e){var a,o,n,s,l=new DataView(e);let h;try{let t,i,r;if(255===l.getUint8(0)&&216===l.getUint8(1)){var c=l.byteLength;let e=2;for(;e+1<c;){if(255===l.getUint8(e)&&225===l.getUint8(e+1)){i=e;break}e+=1}}if(r=i&&(a=i+4,o=i+10,"Exif"===function(e,t,i){let r="",a;for(i+=t,a=t;a<i;a+=1)r+=m(e.getUint8(a));return r}(l,a,4))&&(n=l.getUint16(o),(t=18761===n)||19789===n)&&42===l.getUint16(o+2,t)&&8<=(s=l.getUint32(o+4,t))?o+s:r){var d,f=l.getUint16(r,t);let e;for(e=0;e<f;e+=1)if(d=r+12*e+2,274===l.getUint16(d,t)){d+=8,h=l.getUint16(d,t),l.setUint16(d,1,t);break}}}catch(e){h=1}return h}const p=/\.\d*(?:0|9){12}\d*$/;function H(e,t){t=1<arguments.length&&void 0!==t?t:1e11;return p.test(e)?Math.round(e*t)/t:e}function O(e,t){let{aspectRatio:i,height:r,width:a}=e;var o,e=1<arguments.length&&void 0!==t?t:"none",t=j(a),n=j(r);return t&&n?(o=r*i,("contain"===e||"none"===e)&&o>a||"cover"===e&&o<a?r=a/i:a=r*i):t?r=a/i:n&&(a=r*i),{width:a,height:r}}const{ArrayBuffer:w,FileReader:C}=n,y=n.URL||n.webkitURL,v=/\.\w+$/,B=n.Compressor;return class U{constructor(e,t){this.file=e,this.exif=[],this.image=new Image,this.options={...r,...t},this.aborted=!1,this.result=null,this.init()}init(){const{file:r,options:e}=this;if(t=r,"undefined"!=typeof Blob&&(t instanceof Blob||"[object Blob]"===Object.prototype.toString.call(t))){const a=r.type;if(k(a))if(y&&C){w||(e.checkOrientation=!1,e.retainExif=!1);var t="image/jpeg"===a;const o=t&&e.checkOrientation,n=t&&e.retainExif;!y||o||n?(t=new C,(this.reader=t).onload=e=>{var e=(e=e.target).result,t={};let i=1;o&&1<(i=b(e))&&s(t,function(e){let t=0,i=1,r=1;switch(e){case 2:i=-1;break;case 3:t=-180;break;case 4:r=-1;break;case 5:t=90,r=-1;break;case 6:t=90;break;case 7:t=90,i=-1;break;case 8:t=-90}return{rotate:t,scaleX:i,scaleY:r}}(i)),n&&(this.exif=function(e){var t=D(new Uint8Array(e)),i=t.length,r=[];let a=0;for(;a+3<i;){var o=t[a],n=t[a+1];if(255===o&&218===n)break;255===o&&216===n?a+=2:(o=256*t[a+2]+t[a+3],n=a+o+2,o=t.slice(a,n),r.push(o),a=n)}return r.reduce((e,t)=>255===t[0]&&225===t[1]?e.concat(t):e,[])}(e)),o||n?!y||1<i?t.url=z(e,a):t.url=y.createObjectURL(r):t.url=e,this.load(t)},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},o||n?t.readAsArrayBuffer(r):t.readAsDataURL(r)):this.load({url:y.createObjectURL(r)})}else this.fail(new Error("The current browser does not support image compression."));else this.fail(new Error("The first argument must be an image File or Blob object."))}else this.fail(new Error("The first argument must be a File or Blob object."))}load(e){const{file:t,image:i}=this;i.onload=()=>{this.draw({...e,naturalWidth:i.naturalWidth,naturalHeight:i.naturalHeight})},i.onabort=()=>{this.fail(new Error("Aborted to load the image."))},i.onerror=()=>{this.fail(new Error("Failed to load the image."))},n.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(n.navigator.userAgent)&&(i.crossOrigin="anonymous"),i.alt=t.name,i.src=e.url}draw(e){let{naturalWidth:a,naturalHeight:o,rotate:t=0,scaleX:i=1,scaleY:r=1}=e;const{file:n,image:s,options:l}=this;var h=(e=document.createElement("canvas")).getContext("2d"),c=Math.abs(t)%180==90,d=("contain"===l.resize||"cover"===l.resize)&&j(l.width)&&j(l.height);let f=Math.max(l.maxWidth,0)||1/0,u=Math.max(l.maxHeight,0)||1/0,m=Math.max(l.minWidth,0)||0,g=Math.max(l.minHeight,0)||0,b=a/o,{width:p,height:w}=l;c&&([f,u]=[u,f],[m,g]=[g,m],[p,w]=[w,p]),d&&(b=p/w),{width:f,height:u}=O({aspectRatio:b,width:f,height:u},"contain"),{width:m,height:g}=O({aspectRatio:b,width:m,height:g},"cover"),d?{width:p,height:w}=O({aspectRatio:b,width:p,height:w},l.resize):{width:p=a,height:w=o}=O({aspectRatio:b,width:p,height:w}),p=Math.floor(H(Math.min(Math.max(p,m),f))),w=Math.floor(H(Math.min(Math.max(w,g),u)));var y,v,B,U=-p/2,x=-w/2,A=p,R=w,T=[];d&&(y=d=0,v=a,B=o,{width:v,height:B}=O({aspectRatio:b,width:a,height:o},{contain:"cover",cover:"contain"}[l.resize]),d=(a-v)/2,y=(o-B)/2,T.push(d,y,v,B)),T.push(U,x,A,R),c&&([p,w]=[w,p]),e.width=p,e.height=w,k(l.mimeType)||(l.mimeType=n.type);let E="transparent";n.size>l.convertSize&&0<=l.convertTypes.indexOf(l.mimeType)&&(l.mimeType="image/jpeg");const M="image/jpeg"===l.mimeType;M&&(E="#fff"),h.fillStyle=E,h.fillRect(0,0,p,w),l.beforeDraw&&l.beforeDraw.call(this,h,e),this.aborted||(h.save(),h.translate(p/2,w/2),h.rotate(t*Math.PI/180),h.scale(i,r),h.drawImage(s,...T),h.restore(),l.drew&&l.drew.call(this,h,e),this.aborted)||(d=e=>{if(!this.aborted){const r=e=>this.done({naturalWidth:a,naturalHeight:o,result:e});if(e&&M&&l.retainExif&&this.exif&&0<this.exif.length){const i=e=>{return r(L(z((t=this.exif,255!==(i=D(new Uint8Array(e)))[2]||224!==i[3]?e:(e=256*i[4]+i[5],t=[255,216].concat(t,i.slice(4+e)),new Uint8Array(t))),l.mimeType)));var t,i};var t;e.arrayBuffer?e.arrayBuffer().then(i).catch(()=>{this.fail(new Error("Failed to read the compressed image with Blob.arrayBuffer()."))}):(t=new C,(this.reader=t).onload=e=>{e=e.target,i(e.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(e))}else r(e)}},e.toBlob?e.toBlob(d,l.mimeType,l.quality):d(L(e.toDataURL(l.mimeType,l.quality))))}done(e){let{naturalWidth:t,naturalHeight:i,result:r}=e;var{file:e,image:a,options:o}=this;y&&0===a.src.indexOf("blob:")&&y.revokeObjectURL(a.src),!r||o.strict&&!o.retainExif&&r.size>e.size&&o.mimeType===e.type&&!(o.width>t||o.height>i||o.minWidth>t||o.minHeight>i||o.maxWidth<t||o.maxHeight<i)?r=e:(a=new Date,r.lastModified=a.getTime(),r.lastModifiedDate=a,r.name=e.name,r.name&&r.type!==e.type&&(r.name=r.name.replace(v,function(e){let t=k(e)?e.substr(6):"";return"."+(t="jpeg"===t?"jpg":t)}(r.type)))),this.result=r,o.success&&o.success.call(this,r)}fail(e){var t=this.options;if(!t.error)throw e;t.error.call(this,e)}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.onabort()))}static noConflict(){return window.Compressor=B,U}static setDefaults(e){s(r,e)}}});
10
+ ((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(){function a(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,o(i.key),i)}}function s(){return(s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r,i=arguments[t];for(r in i)!{}.hasOwnProperty.call(i,r)||(e[r]=i[r])}return e}).apply(null,arguments)}function t(t,e){var r,i=Object.keys(t);return Object.getOwnPropertySymbols&&(r=Object.getOwnPropertySymbols(t),e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,r)),i}function n(i){for(var e=1;e<arguments.length;e++){var a=null!=arguments[e]?arguments[e]:{};e%2?t(Object(a),!0).forEach(function(e){var t,r;t=i,r=a[e=e],(e=o(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r}):Object.getOwnPropertyDescriptors?Object.defineProperties(i,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach(function(e){Object.defineProperty(i,e,Object.getOwnPropertyDescriptor(a,e))})}return i}function o(e){e=((e,t)=>{if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0===r)return("string"===t?String:Number)(e);if("object"!=typeof(r=r.call(e,t||"default")))return r;throw new TypeError("@@toPrimitive must return a primitive value.")})(e,"string");return"symbol"==typeof e?e:e+""}function x(e){return 0<e&&e<1/0}var e,r,l,c,h,u,f,d,i={exports:{}},O=(e=i,"undefined"!=typeof window&&(l=(r=window).HTMLCanvasElement&&r.HTMLCanvasElement.prototype,c=r.Blob&&(()=>{try{return Boolean(new Blob)}catch(e){return!1}})(),h=c&&r.Uint8Array&&(()=>{try{return 100===new Blob([new Uint8Array(100)]).size}catch(e){return!1}})(),u=r.BlobBuilder||r.WebKitBlobBuilder||r.MozBlobBuilder||r.MSBlobBuilder,f=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,d=(c||u)&&r.atob&&r.ArrayBuffer&&r.Uint8Array&&function(e){var t,r,i,a,n,o=e.match(f);if(!o)throw new Error("invalid data URI");for(t=o[2]?o[1]:"text/plain"+(o[3]||";charset=US-ASCII"),n=!!o[4],e=e.slice(o[0].length),r=(n?atob:decodeURIComponent)(e),o=new ArrayBuffer(r.length),i=new Uint8Array(o),a=0;a<r.length;a+=1)i[a]=r.charCodeAt(a);return c?new Blob([h?i:o],{type:t}):((n=new u).append(o),n.getBlob(t))},r.HTMLCanvasElement&&!l.toBlob&&(l.mozGetAsFile?l.toBlob=function(e,t,r){var i=this;setTimeout(function(){r&&l.toDataURL&&d?e(d(i.toDataURL(t,r))):e(i.mozGetAsFile("blob",t))})}:l.toDataURL&&d&&(l.msToBlob?l.toBlob=function(e,t,r){var i=this;setTimeout(function(){(t&&"image/png"!==t||r)&&l.toDataURL&&d?e(d(i.toDataURL(t,r))):e(i.msToBlob(t))})}:l.toBlob=function(e,t,r){var i=this;setTimeout(function(){e(d(i.toDataURL(t,r)))})})),e.exports?e.exports=d:r.dataURLtoBlob=d),i.exports),m={strict:!0,checkOrientation:!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:["image/png"],convertSize:5e6,beforeDraw:null,drew:null,success:null,error:null},g="undefined"!=typeof window&&void 0!==window.document?window:{},p=Array.prototype.slice;function j(e){return Array.from?Array.from(e):p.call(e)}var b=/^image\/.+$/;function T(e){return b.test(e)}var y=String.fromCharCode;var w=g.btoa;function A(e,t){for(var r=[],i=new Uint8Array(e);0<i.length;)r.push(y.apply(null,j(i.subarray(0,8192)))),i=i.subarray(8192);return"data:".concat(t,";base64,").concat(w(r.join("")))}function v(e){var t,r,i,a,n,o,l,s=new DataView(e);try{if(255===s.getUint8(0)&&216===s.getUint8(1))for(var c=s.byteLength,h=2;h+1<c;){if(255===s.getUint8(h)&&225===s.getUint8(h+1)){r=h;break}h+=1}if(i=r&&(a=r+10,"Exif"===((e,t,r)=>{var i,a="";for(r+=t,i=t;i<r;i+=1)a+=y(e.getUint8(i));return a})(s,r+4,4))&&((l=18761===(n=s.getUint16(a)))||19789===n)&&42===s.getUint16(a+2,l)&&8<=(o=s.getUint32(a+4,l))?a+o:i)for(var u,f=s.getUint16(i,l),d=0;d<f;d+=1)if(u=i+12*d+2,274===s.getUint16(u,l)){u+=8,t=s.getUint16(u,l),s.setUint16(u,1,l);break}}catch(e){t=1}return t}var B=/\.\d*(?:0|9){12}\d*$/;function R(e,t){t=1<arguments.length&&void 0!==t?t:1e11;return B.test(e)?Math.round(e*t)/t:e}function E(e,t){var r,i=e.aspectRatio,a=e.height,e=e.width,t=1<arguments.length&&void 0!==t?t:"none",n=x(e),o=x(a);return n&&o?(r=a*i,("contain"===t||"none"===t)&&e<r||"cover"===t&&r<e?a=e/i:e=a*i):n?a=e/i:o&&(e=a*i),{width:e,height:a}}var U=g.ArrayBuffer,k=g.FileReader,D=g.URL||g.webkitURL,M=/\.\w+$/,L=g.Compressor;return(()=>{function r(e,t){if(!(this instanceof r))throw new TypeError("Cannot call a class as a function");this.file=e,this.exif=[],this.image=new Image,this.options=n(n({},m),t),this.aborted=!1,this.result=null,this.init()}return e=r,i=[{key:"noConflict",value:function(){return window.Compressor=L,r}},{key:"setDefaults",value:function(e){s(m,e)}}],(t=[{key:"init",value:function(){var i,a,n,e,o=this,l=this.file,t=this.options;e=l,"undefined"!=typeof Blob&&(e instanceof Blob||"[object Blob]"===Object.prototype.toString.call(e))?T(i=l.type)?D&&k?(U||(t.checkOrientation=!1,t.retainExif=!1),a=(e="image/jpeg"===i)&&t.checkOrientation,n=e&&t.retainExif,!D||a||n?(e=new k,(this.reader=e).onload=function(e){var e=e.target.result,t={},r=1;a&&1<(r=v(e))&&s(t,(e=>{var t=0,r=1,i=1;switch(e){case 2:r=-1;break;case 3:t=-180;break;case 4:i=-1;break;case 5:t=90,i=-1;break;case 6:t=90;break;case 7:t=90,r=-1;break;case 8:t=-90}return{rotate:t,scaleX:r,scaleY:i}})(r)),n&&(o.exif=(e=>{for(var t=j(new Uint8Array(e)),r=t.length,i=[],a=0;a+3<r;){var n=t[a],o=t[a+1];if(255===n&&218===o)break;255===n&&216===o?a+=2:(n=a+(256*t[a+2]+t[a+3])+2,o=t.slice(a,n),i.push(o),a=n)}return i.reduce(function(e,t){return 255===t[0]&&225===t[1]?e.concat(t):e},[])})(e)),t.url=a||n?!D||1<r?A(e,i):D.createObjectURL(l):e,o.load(t)},e.onabort=function(){o.fail(new Error("Aborted to read the image with FileReader."))},e.onerror=function(){o.fail(new Error("Failed to read the image with FileReader."))},e.onloadend=function(){o.reader=null},a||n?e.readAsArrayBuffer(l):e.readAsDataURL(l)):this.load({url:D.createObjectURL(l)})):this.fail(new Error("The current browser does not support image compression.")):this.fail(new Error("The first argument must be an image File or Blob object.")):this.fail(new Error("The first argument must be a File or Blob object."))}},{key:"load",value:function(e){var t=this,r=this.file,i=this.image;i.onload=function(){(()=>{try{var e,t,r,i=document.createElement("canvas"),a=(i.width=2,i.height=1,i.getContext("2d"));if(a)return(e=a.createImageData(2,1)).data[0]=12,e.data[1]=23,e.data[2]=34,e.data[3]=255,e.data[4]=45,e.data[5]=56,e.data[6]=67,e.data[7]=255,a.putImageData(e,0,0),t=a.getImageData(0,0,2,1),r=[12,23,34,255,45,56,67,255],t.data.every(function(e,t){return e===r[t]})}catch(e){}})()?t.draw(n(n({},e),{},{naturalWidth:i.naturalWidth,naturalHeight:i.naturalHeight})):t.done({naturalWidth:i.naturalWidth,naturalHeight:i.naturalHeight,result:null})},i.onabort=function(){t.fail(new Error("Aborted to load the image."))},i.onerror=function(){t.fail(new Error("Failed to load the image."))},g.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(g.navigator.userAgent)&&(i.crossOrigin="anonymous"),i.alt=r.name,i.src=e.url}},{key:"draw",value:function(e){var a=this,n=e.naturalWidth,o=e.naturalHeight,t=e.rotate,t=void 0===t?0:t,r=e.scaleX,r=void 0===r?1:r,e=e.scaleY,e=void 0===e?1:e,i=this.file,l=this.image,s=this.options,c=document.createElement("canvas"),h=c.getContext("2d"),u=Math.abs(t)%180==90,f=("contain"===s.resize||"cover"===s.resize)&&x(s.width)&&x(s.height),d=Math.max(s.maxWidth,0)||1/0,m=Math.max(s.maxHeight,0)||1/0,g=Math.max(s.minWidth,0)||0,p=Math.max(s.minHeight,0)||0,b=n/o,y=s.width,w=s.height,v=(u&&(d=(v=[m,d])[0],m=v[1],g=(v=[p,g])[0],p=v[1],y=(v=[w,y])[0],w=v[1]),E({aspectRatio:b=f?y/w:b,width:d,height:m},"contain")),v=(d=v.width,m=v.height,E({aspectRatio:b,width:g,height:p},"cover")),v=(g=v.width,p=v.height,w=f?(y=(v=E({aspectRatio:b,width:y,height:w},s.resize)).width,v.height):(y=void 0===(B=(v=E({aspectRatio:b,width:y,height:w})).width)?n:B,void 0===(B=v.height)?o:B),-(y=Math.floor(R(Math.min(Math.max(y,g),d))))/2),B=-(w=Math.floor(R(Math.min(Math.max(w,p),m))))/2,g=y,d=w,p=[],m=(f&&(0,m=(b=E({aspectRatio:b,width:m=n,height:f=o},{contain:"cover",cover:"contain"}[s.resize])).width,p.push((n-m)/2,(o-(f=b.height))/2,m,f)),p.push(v,B,g,d),u&&(y=(b=[w,y])[0],w=b[1]),c.width=y,c.height=w,T(s.mimeType)||(s.mimeType=i.type),"transparent"),U=(i.size>s.convertSize&&0<=s.convertTypes.indexOf(s.mimeType)&&(s.mimeType="image/jpeg"),"image/jpeg"===s.mimeType);h.fillStyle=m=U?"#fff":m,h.fillRect(0,0,y,w),s.beforeDraw&&s.beforeDraw.call(this,h,c),this.aborted||(h.save(),h.translate(y/2,w/2),h.rotate(t*Math.PI/180),h.scale(r,e),h.drawImage.apply(h,[l].concat(p)),h.restore(),s.drew&&s.drew.call(this,h,c),this.aborted)||(f=function(e){var i,t,r;a.aborted||(i=function(e){return a.done({naturalWidth:n,naturalHeight:o,result:e})},e&&U&&s.retainExif&&a.exif&&0<a.exif.length?(t=function(e){return i(O(A((e=e,t=a.exif,255!==(r=j(new Uint8Array(e)))[2]||224!==r[3]?e:(e=[255,216].concat(t,r.slice(4+(256*r[4]+r[5]))),new Uint8Array(e))),s.mimeType)));var t,r},e.arrayBuffer?e.arrayBuffer().then(t).catch(function(){a.fail(new Error("Failed to read the compressed image with Blob.arrayBuffer()."))}):(r=new k,(a.reader=r).onload=function(e){e=e.target;t(e.result)},r.onabort=function(){a.fail(new Error("Aborted to read the compressed image with FileReader."))},r.onerror=function(){a.fail(new Error("Failed to read the compressed image with FileReader."))},r.onloadend=function(){a.reader=null},r.readAsArrayBuffer(e))):i(e))},c.toBlob?c.toBlob(f,s.mimeType,s.quality):f(O(c.toDataURL(s.mimeType,s.quality))))}},{key:"done",value:function(t){var e=t.naturalWidth,r=t.naturalHeight,t=t.result,i=this.file,a=this.image,n=this.options;if(D&&0===a.src.indexOf("blob:")&&D.revokeObjectURL(a.src),t)if(n.strict&&!n.retainExif&&t.size>i.size&&n.mimeType===i.type&&!(n.width>e||n.height>r||n.minWidth>e||n.minHeight>r||n.maxWidth<e||n.maxHeight<r))t=i;else{a=i.name;a&&t.type!==i.type&&(a=a.replace(M,(e=T(e=t.type)?e.substr(6):"",".".concat(e="jpeg"===e?"jpg":e))));try{t=new File([t],a,{type:t.type})}catch(e){r=new Date;t.name=a,t.lastModified=r.getTime(),t.lastModifiedDate=r}}else t=i;this.result=t,n.success&&n.success.call(this,t)}},{key:"fail",value:function(e){var t=this.options;if(!t.error)throw e;t.error.call(this,e)}},{key:"abort",value:function(){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.onabort()))}}])&&a(e.prototype,t),i&&a(e,i),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,t,i})()});
package/package.json CHANGED
@@ -1,34 +1,16 @@
1
1
  {
2
2
  "name": "compressorjs",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "JavaScript image compressor.",
5
5
  "main": "dist/compressor.common.js",
6
6
  "module": "dist/compressor.esm.js",
7
7
  "browser": "dist/compressor.js",
8
8
  "types": "types/index.d.ts",
9
- "repository": "fengyuanchen/compressorjs",
10
- "homepage": "https://fengyuanchen.github.io/compressorjs",
11
- "license": "MIT",
12
- "author": {
13
- "name": "Chen Fengyuan",
14
- "url": "https://chenfengyuan.com/"
15
- },
16
9
  "files": [
17
10
  "src",
18
11
  "dist",
19
12
  "types"
20
13
  ],
21
- "keywords": [
22
- "image",
23
- "compress",
24
- "compressor",
25
- "compressor.js",
26
- "image-compressor",
27
- "lossy-compression",
28
- "javascript",
29
- "front-end",
30
- "web"
31
- ],
32
14
  "scripts": {
33
15
  "build": "rollup -c",
34
16
  "clean": "del-cli dist",
@@ -40,48 +22,71 @@
40
22
  "prepare": "husky install",
41
23
  "release": "npm run clean && npm run lint && npm run build && npm run compress && npm test",
42
24
  "start": "npm run dev",
43
- "test": "cross-env NODE_ENV=test karma start test/karma.conf.js",
44
- "test:coverage": "cat coverage/lcov.info | codecov"
25
+ "test": "cross-env NODE_ENV=test karma start test/karma.conf.js"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/fengyuanchen/compressorjs.git"
45
30
  },
31
+ "keywords": [
32
+ "image",
33
+ "compress",
34
+ "compressor",
35
+ "compressor.js",
36
+ "image-compressor",
37
+ "lossy-compression",
38
+ "javascript",
39
+ "front-end",
40
+ "web"
41
+ ],
42
+ "author": {
43
+ "name": "Chen Fengyuan",
44
+ "url": "https://chenfengyuan.com/"
45
+ },
46
+ "license": "MIT",
47
+ "bugs": {
48
+ "url": "https://github.com/fengyuanchen/compressorjs/issues"
49
+ },
50
+ "homepage": "https://fengyuanchen.github.io/compressorjs",
46
51
  "dependencies": {
47
52
  "blueimp-canvas-to-blob": "^3.29.0",
48
53
  "is-blob": "^2.1.0"
49
54
  },
50
55
  "devDependencies": {
51
- "@babel/core": "^7.21.0",
52
- "@babel/plugin-transform-object-assign": "^7.18.6",
53
- "@babel/preset-env": "^7.20.2",
54
- "@commitlint/cli": "^17.4.4",
55
- "@commitlint/config-conventional": "^17.4.4",
56
+ "@babel/core": "^7.29.0",
57
+ "@babel/plugin-transform-object-assign": "^7.27.1",
58
+ "@babel/preset-env": "^7.29.2",
59
+ "@commitlint/cli": "^17.8.1",
60
+ "@commitlint/config-conventional": "^17.8.1",
56
61
  "@rollup/plugin-babel": "^5.3.1",
57
62
  "@rollup/plugin-commonjs": "^21.1.0",
58
63
  "@rollup/plugin-node-resolve": "^13.3.0",
59
64
  "@rollup/plugin-replace": "^3.1.0",
60
65
  "babel-plugin-istanbul": "^6.1.1",
61
- "chai": "^4.3.7",
66
+ "chai": "^4.5.0",
62
67
  "change-case": "^4.1.2",
63
68
  "codecov": "^3.8.3",
64
69
  "create-banner": "^2.0.0",
65
70
  "cross-env": "^7.0.3",
66
- "del-cli": "^5.0.0",
67
- "eslint": "^8.34.0",
71
+ "del-cli": "^5.1.0",
72
+ "eslint": "^8.57.1",
68
73
  "eslint-config-airbnb-base": "^15.0.0",
69
- "eslint-plugin-import": "^2.27.5",
74
+ "eslint-plugin-import": "^2.32.0",
70
75
  "husky": "^8.0.3",
71
- "karma": "^6.4.1",
76
+ "karma": "^6.4.4",
72
77
  "karma-chai": "^0.1.0",
73
- "karma-chrome-launcher": "^3.1.1",
78
+ "karma-chrome-launcher": "^3.2.0",
74
79
  "karma-coverage-istanbul-reporter": "^3.0.3",
75
80
  "karma-mocha": "^2.0.1",
76
81
  "karma-mocha-reporter": "^2.2.5",
77
82
  "karma-rollup-preprocessor": "^7.0.8",
78
- "lint-staged": "^13.1.2",
79
- "mocha": "^10.2.0",
80
- "puppeteer": "^19.7.2",
81
- "rollup": "^2.79.1",
82
- "stylelint": "^15.2.0",
83
+ "lint-staged": "^13.3.0",
84
+ "mocha": "^10.8.2",
85
+ "puppeteer": "^19.11.1",
86
+ "rollup": "^2.80.0",
87
+ "stylelint": "^15.11.0",
83
88
  "stylelint-config-standard": "^30.0.1",
84
- "stylelint-order": "^6.0.2",
85
- "uglify-js": "^3.17.4"
89
+ "stylelint-order": "^6.0.4",
90
+ "uglify-js": "^3.19.3"
86
91
  }
87
92
  }
package/src/index.js CHANGED
@@ -7,14 +7,15 @@ import {
7
7
  import {
8
8
  arrayBufferToDataURL,
9
9
  getAdjustedSizes,
10
+ getExif,
10
11
  imageTypeToExtension,
12
+ insertExif,
13
+ isCanvasAvailable,
11
14
  isImageType,
12
15
  isPositiveNumber,
13
16
  normalizeDecimalNumber,
14
17
  parseOrientation,
15
18
  resetAndGetOrientation,
16
- getExif,
17
- insertExif,
18
19
  } from './utilities';
19
20
 
20
21
  const { ArrayBuffer, FileReader } = WINDOW;
@@ -140,11 +141,19 @@ export default class Compressor {
140
141
  const { file, image } = this;
141
142
 
142
143
  image.onload = () => {
143
- this.draw({
144
- ...data,
145
- naturalWidth: image.naturalWidth,
146
- naturalHeight: image.naturalHeight,
147
- });
144
+ if (isCanvasAvailable()) {
145
+ this.draw({
146
+ ...data,
147
+ naturalWidth: image.naturalWidth,
148
+ naturalHeight: image.naturalHeight,
149
+ });
150
+ } else {
151
+ this.done({
152
+ naturalWidth: image.naturalWidth,
153
+ naturalHeight: image.naturalHeight,
154
+ result: null,
155
+ });
156
+ }
148
157
  };
149
158
  image.onabort = () => {
150
159
  this.fail(new Error('Aborted to load the image.'));
@@ -378,19 +387,31 @@ export default class Compressor {
378
387
  ) {
379
388
  result = file;
380
389
  } else {
381
- const date = new Date();
382
-
383
- result.lastModified = date.getTime();
384
- result.lastModifiedDate = date;
385
- result.name = file.name;
390
+ let fileName = file.name;
386
391
 
387
392
  // Convert the extension to match its type
388
- if (result.name && result.type !== file.type) {
389
- result.name = result.name.replace(
393
+ if (fileName && result.type !== file.type) {
394
+ fileName = fileName.replace(
390
395
  REGEXP_EXTENSION,
391
396
  imageTypeToExtension(result.type),
392
397
  );
393
398
  }
399
+
400
+ try {
401
+ // Convert the resulting Blob object into a File object for modern browsers.
402
+ result = new File([result], fileName, {
403
+ type: result.type,
404
+ });
405
+ } catch (error) {
406
+ // Fallback to Blob if the File constructor is not supported.
407
+ const date = new Date();
408
+
409
+ result.name = fileName;
410
+
411
+ // The last modified date is not accurate, but it's better than nothing.
412
+ result.lastModified = date.getTime();
413
+ result.lastModifiedDate = date;
414
+ }
394
415
  }
395
416
  } else {
396
417
  // Returns original file if the result is null in some cases.
package/src/utilities.js CHANGED
@@ -1,6 +1,4 @@
1
- import {
2
- WINDOW,
3
- } from './constants';
1
+ import { WINDOW } from './constants';
4
2
 
5
3
  /**
6
4
  * Check if the given value is a positive number.
@@ -68,6 +66,52 @@ export function getStringFromCharCode(dataView, start, length) {
68
66
  return str;
69
67
  }
70
68
 
69
+ /**
70
+ * Check if `canvas.getContext('2d').getImageData` is available,
71
+ * FireFox randomizes the output of that function in `privacy.resistFingerprinting` mode (#137)
72
+ * @link https://github.com/nodeca/pica/blob/master/lib/utils.js
73
+ * @returns {boolean} Returns `true` if it is available, else `false`.
74
+ */
75
+ export function isCanvasAvailable() {
76
+ try {
77
+ const canvas = document.createElement('canvas');
78
+
79
+ canvas.width = 2;
80
+ canvas.height = 1;
81
+
82
+ const context = canvas.getContext('2d');
83
+
84
+ if (!context) return false;
85
+
86
+ // Create 2x1 image data containing RGBA values for two pixels
87
+ const imageData = context.createImageData(2, 1);
88
+
89
+ // First pixel: R=12, G=23, B=34, A=255
90
+ imageData.data[0] = 12;
91
+ imageData.data[1] = 23;
92
+ imageData.data[2] = 34;
93
+ imageData.data[3] = 255;
94
+
95
+ // Second pixel: R=45, G=56, B=67, A=255
96
+ imageData.data[4] = 45;
97
+ imageData.data[5] = 56;
98
+ imageData.data[6] = 67;
99
+ imageData.data[7] = 255;
100
+
101
+ context.putImageData(imageData, 0, 0);
102
+
103
+ const readBack = context.getImageData(0, 0, 2, 1);
104
+
105
+ // Expected pixel data (matching the written values)
106
+ const expected = [12, 23, 34, 255, 45, 56, 67, 255];
107
+
108
+ // Compare element by element to ensure write and read consistency
109
+ return readBack.data.every((value, index) => value === expected[index]);
110
+ } catch (error) {
111
+ return false;
112
+ }
113
+ }
114
+
71
115
  const { btoa } = WINDOW;
72
116
 
73
117
  /**