From 8af33733c0b2c537cf7dc7d4b1d7558b3ff96f04 Mon Sep 17 00:00:00 2001 From: Donald Date: Sat, 1 Jun 2019 03:26:40 +0800 Subject: [PATCH] release 1.0.5 --- CHANGELOG.md | 2 +- README.md | 2 +- coverage/image-compression.js.html | 2 +- coverage/index.html | 2 +- coverage/index.js.html | 2 +- coverage/lcov-report/image-compression.js.html | 2 +- coverage/lcov-report/index.html | 2 +- coverage/lcov-report/index.js.html | 2 +- coverage/lcov-report/utils.js.html | 2 +- coverage/utils.js.html | 2 +- dist/browser-image-compression.js | 4 ++-- dist/browser-image-compression.js.map | 2 +- dist/browser-image-compression.mjs | 4 ++-- dist/browser-image-compression.mjs.map | 2 +- example/basic.html | 2 +- package.json | 2 +- rollup.config.js | 5 ++++- 17 files changed, 22 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f9a22..b453b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## v1.0.4 (1 June 2019) +## v1.0.5 (1 June 2019) * added: support for cordova project that uses cordova-plugin-file * optimized: follow image exif orientation even though image do not required to compress or resize * fixed: error may throw on iPhone Safari because of OffscreenCanvas cannot get 2d context diff --git a/README.md b/README.md index 7fb44a6..2f7c910 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ yarn add browser-image-compression ``` or use a CDN like [delivrjs]: ``` -https://cdn.jsdelivr.net/npm/browser-image-compression@1.0.4/dist/browser-image-compression.js +https://cdn.jsdelivr.net/npm/browser-image-compression@1.0.5/dist/browser-image-compression.js or https://cdn.jsdelivr.net/npm/browser-image-compression@latest/dist/browser-image-compression.js ``` diff --git a/coverage/image-compression.js.html b/coverage/image-compression.js.html index d1b6d35..131b6e3 100644 --- a/coverage/image-compression.js.html +++ b/coverage/image-compression.js.html @@ -214,7 +214,7 @@

diff --git a/coverage/index.html b/coverage/index.html index 2240a04..40f2bcd 100644 --- a/coverage/index.html +++ b/coverage/index.html @@ -106,7 +106,7 @@

diff --git a/coverage/index.js.html b/coverage/index.js.html index 52f0dae..cff732c 100644 --- a/coverage/index.js.html +++ b/coverage/index.js.html @@ -292,7 +292,7 @@

diff --git a/coverage/lcov-report/image-compression.js.html b/coverage/lcov-report/image-compression.js.html index d1b6d35..131b6e3 100644 --- a/coverage/lcov-report/image-compression.js.html +++ b/coverage/lcov-report/image-compression.js.html @@ -214,7 +214,7 @@

diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html index 2240a04..40f2bcd 100644 --- a/coverage/lcov-report/index.html +++ b/coverage/lcov-report/index.html @@ -106,7 +106,7 @@

diff --git a/coverage/lcov-report/index.js.html b/coverage/lcov-report/index.js.html index 52f0dae..cff732c 100644 --- a/coverage/lcov-report/index.js.html +++ b/coverage/lcov-report/index.js.html @@ -292,7 +292,7 @@

diff --git a/coverage/lcov-report/utils.js.html b/coverage/lcov-report/utils.js.html index df91ca7..092dc06 100644 --- a/coverage/lcov-report/utils.js.html +++ b/coverage/lcov-report/utils.js.html @@ -844,7 +844,7 @@

diff --git a/coverage/utils.js.html b/coverage/utils.js.html index df91ca7..092dc06 100644 --- a/coverage/utils.js.html +++ b/coverage/utils.js.html @@ -844,7 +844,7 @@

diff --git a/dist/browser-image-compression.js b/dist/browser-image-compression.js index 03d94f0..8169cad 100644 --- a/dist/browser-image-compression.js +++ b/dist/browser-image-compression.js @@ -1,9 +1,9 @@ /** * Browser Image Compression - * v1.0.4 + * v1.0.5 * by Donald * https://github.com/Donaldcwl/browser-image-compression */ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).imageCompression=n()}(this,function(){"use strict";function _slicedToArray(e,n){return function _arrayWithHoles(e){if(Array.isArray(e))return e}(e)||function _iterableToArrayLimit(e,n){var r=[],t=!0,i=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(t=(o=s.next()).done)&&(r.push(o.value),!n||r.length!==n);t=!0);}catch(e){i=!0,a=e}finally{try{t||null==s.return||s.return()}finally{if(i)throw a}}return r}(e,n)||function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}var e="undefined"!=typeof window&&window.cordova&&window.cordova.require("cordova/modulemapper"),n=e&&e.getOriginalSymbol(window,"File")||File,r=e&&e.getOriginalSymbol(window,"FileReader")||FileReader;function getDataUrlFromFile(e){return new Promise(function(n,t){var i=new r;i.onload=function(){return n(i.result)},i.onerror=function(e){return t(e)},i.readAsDataURL(e)})}function getFilefromDataUrl(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Date.now();return new Promise(function(t){for(var i=e.split(","),a=i[0].match(/:(.*?);/)[1],o=atob(i[1]),s=o.length,c=new Uint8Array(s);s--;)c[s]=o.charCodeAt(s);var u=new Blob([c],{type:a});u.name=n,u.lastModified=r,t(u)})}function loadImage(e){return new Promise(function(n,r){var t=new Image;t.onload=function(){return n(t)},t.onerror=function(e){return r(e)},t.src=e})}function drawImageInCanvas(e){var n=_slicedToArray(getNewCanvasAndCtx(e.width,e.height),2),r=n[0];return n[1].drawImage(e,0,0,r.width,r.height),r}function drawFileInCanvas(e){return new Promise(function(n,r){var t,i,a=function $Try_1_Post(){try{return i=drawImageInCanvas(t),n([t,i])}catch(e){return r(e)}},o=function $Try_1_Catch(n){try{return getDataUrlFromFile(e).then(function(e){try{return loadImage(e).then(function(e){try{return t=e,a()}catch(e){return r(e)}},r)}catch(e){return r(e)}},r)}catch(e){return r(e)}};try{return createImageBitmap(e).then(function(e){try{return t=e,a()}catch(e){return o()}},o)}catch(e){o()}})}function canvasToFile(e,n,r,t){var i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;return new Promise(function(a,o){var s;return"function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas?e.convertToBlob({type:n,quality:i}).then(function(e){try{return(s=e).name=r,s.lastModified=t,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o):getFilefromDataUrl(e.toDataURL(n,i),r,t).then(function(e){try{return s=e,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o);function $If_4(){return a(s)}})}function getExifOrientation(e){return new Promise(function(n,t){var i=new r;i.onload=function(e){var r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return n(-2);for(var t=r.byteLength,i=2;ia||i>a)){var s=_slicedToArray(getNewCanvasAndCtx(t,i),2);o=s[0],r=s[1],t>i?(o.width=a,o.height=i/t*a):(o.width=t/i*a,o.height=a),r.drawImage(e,0,0,o.width,o.height)}return o}function followExifOrientation(e,n){var r=e.width,t=e.height,i=_slicedToArray(getNewCanvasAndCtx(r,t),2),a=i[0],o=i[1];switch(4a){var n,r,u,m=_slicedToArray(getNewCanvasAndCtx(n=.9*s.width,r=.9*s.height),2);return u=m[0],m[1].drawImage(o,0,0,n,r),"image/jpeg"===e.type&&(c*=.9),canvasToFile(u,e.type,e.name,e.lastModified,c).then(function(e){try{return f=e,s=u,$Loop_3}catch(e){return t(e)}},t)}return[1]},g=function $Loop_3_exit(){return r(f)};return(u=n).size<=a?r(u):(f=u,(m=function(e){for(;e;){if(e.then)return void e.then(m,t);try{if(e.pop){if(e.length)return e.pop()?g.call(this):e;e=l}else e=e.call(this)}catch(e){return t(e)}}}.bind(this))(l))}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)})}var t,i=0;var a=function createWorker(e){return new Worker(URL.createObjectURL(new Blob(["(".concat(e,")()")])))}(function(){var e=!1;self.addEventListener("message",function(n){return new Promise(function(r,t){var i,a,o,s,c=n.data;i=c.file,a=c.id,o=c.imageCompressionLibUrl,s=c.options;var u=function $Try_1_Post(){try{return r()}catch(e){return t(e)}},f=function $Try_1_Catch(e){try{return self.postMessage({error:e.message,id:a}),u()}catch(e){return t(e)}};try{var m;return e||(importScripts(o),e=!0),imageCompression(i,s).then(function(e){try{return m=e,self.postMessage({file:m,id:a}),u()}catch(e){return f(e)}},f)}catch(e){f(e)}})})});function compressOnWebWorker(e,n){return new Promise(function(r,o){return new Promise(function(s,c){t||(t=function createSourceObject(e){return URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}("\n function imageCompression (){return (".concat(imageCompression,").apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ").concat(imageCompression.getDataUrlFromFile,"\n imageCompression.getFilefromDataUrl = ").concat(imageCompression.getFilefromDataUrl,"\n imageCompression.loadImage = ").concat(imageCompression.loadImage,"\n imageCompression.drawImageInCanvas = ").concat(imageCompression.drawImageInCanvas,"\n imageCompression.drawFileInCanvas = ").concat(imageCompression.drawFileInCanvas,"\n imageCompression.canvasToFile = ").concat(imageCompression.canvasToFile,"\n imageCompression.getExifOrientation = ").concat(imageCompression.getExifOrientation,"\n imageCompression.handleMaxWidthOrHeight = ").concat(imageCompression.handleMaxWidthOrHeight,"\n imageCompression.followExifOrientation = ").concat(imageCompression.followExifOrientation,"\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ").concat(getNewCanvasAndCtx,"\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (").concat(compress,").apply(null, arguments)}\n ")));var u=i++;return a.addEventListener("message",function handler(e){e.data.id===u&&(a.removeEventListener("message",handler),e.data.error&&o(e.data.error),r(e.data.file))}),a.postMessage({file:e,id:u,imageCompressionLibUrl:t,options:n}),s()})})}function imageCompression(e,r){return new Promise(function(t,i){var a,o;if(r.maxSizeMB=r.maxSizeMB||Number.POSITIVE_INFINITY,r.useWebWorker="boolean"!=typeof r.useWebWorker||r.useWebWorker,!(e instanceof Blob||e instanceof n))return i(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return i(new Error("The file given is not an image"));if(o="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!r.useWebWorker||"function"!=typeof Worker||o)return compress(e,r).then(function(e){try{return a=e,$If_3.call(this)}catch(e){return i(e)}}.bind(this),i);var s=function(){try{return $If_3.call(this)}catch(e){return i(e)}}.bind(this),c=function $Try_1_Catch(n){try{return console.warn("Run compression in web worker failed:",n,", fall back to main thread"),compress(e,r).then(function(e){try{return a=e,s()}catch(e){return i(e)}},i)}catch(e){return i(e)}};try{return compressOnWebWorker(e,r).then(function(e){try{return a=e,s()}catch(e){return c(e)}},c)}catch(e){c(e)}function $If_3(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}return t(a)}})}return imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression}); +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).imageCompression=n()}(this,function(){"use strict";function _slicedToArray(e,n){return function _arrayWithHoles(e){if(Array.isArray(e))return e}(e)||function _iterableToArrayLimit(e,n){var r=[],t=!0,i=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(t=(o=s.next()).done)&&(r.push(o.value),!n||r.length!==n);t=!0);}catch(e){i=!0,a=e}finally{try{t||null==s.return||s.return()}finally{if(i)throw a}}return r}(e,n)||function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}var e="undefined"!=typeof window&&window.cordova&&window.cordova.require("cordova/modulemapper"),CustomFile=e&&e.getOriginalSymbol(window,"File")||File,CustomFileReader=e&&e.getOriginalSymbol(window,"FileReader")||FileReader;function getDataUrlFromFile(e){return new Promise(function(n,r){var t=new CustomFileReader;t.onload=function(){return n(t.result)},t.onerror=function(e){return r(e)},t.readAsDataURL(e)})}function getFilefromDataUrl(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Date.now();return new Promise(function(t){for(var i=e.split(","),a=i[0].match(/:(.*?);/)[1],o=atob(i[1]),s=o.length,c=new Uint8Array(s);s--;)c[s]=o.charCodeAt(s);var u=new Blob([c],{type:a});u.name=n,u.lastModified=r,t(u)})}function loadImage(e){return new Promise(function(n,r){var t=new Image;t.onload=function(){return n(t)},t.onerror=function(e){return r(e)},t.src=e})}function drawImageInCanvas(e){var n=_slicedToArray(getNewCanvasAndCtx(e.width,e.height),2),r=n[0];return n[1].drawImage(e,0,0,r.width,r.height),r}function drawFileInCanvas(e){return new Promise(function(n,r){var t,i,a=function $Try_1_Post(){try{return i=drawImageInCanvas(t),n([t,i])}catch(e){return r(e)}},o=function $Try_1_Catch(n){try{return getDataUrlFromFile(e).then(function(e){try{return loadImage(e).then(function(e){try{return t=e,a()}catch(e){return r(e)}},r)}catch(e){return r(e)}},r)}catch(e){return r(e)}};try{return createImageBitmap(e).then(function(e){try{return t=e,a()}catch(e){return o()}},o)}catch(e){o()}})}function canvasToFile(e,n,r,t){var i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;return new Promise(function(a,o){var s;return"function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas?e.convertToBlob({type:n,quality:i}).then(function(e){try{return(s=e).name=r,s.lastModified=t,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o):getFilefromDataUrl(e.toDataURL(n,i),r,t).then(function(e){try{return s=e,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o);function $If_4(){return a(s)}})}function getExifOrientation(e){return new Promise(function(n,r){var t=new CustomFileReader;t.onload=function(e){var r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return n(-2);for(var t=r.byteLength,i=2;ia||i>a)){var s=_slicedToArray(getNewCanvasAndCtx(t,i),2);o=s[0],r=s[1],t>i?(o.width=a,o.height=i/t*a):(o.width=t/i*a,o.height=a),r.drawImage(e,0,0,o.width,o.height)}return o}function followExifOrientation(e,n){var r=e.width,t=e.height,i=_slicedToArray(getNewCanvasAndCtx(r,t),2),a=i[0],o=i[1];switch(4a){var n,r,u,m=_slicedToArray(getNewCanvasAndCtx(n=.9*s.width,r=.9*s.height),2);return u=m[0],m[1].drawImage(o,0,0,n,r),"image/jpeg"===e.type&&(c*=.9),canvasToFile(u,e.type,e.name,e.lastModified,c).then(function(e){try{return f=e,s=u,$Loop_3}catch(e){return t(e)}},t)}return[1]},g=function $Loop_3_exit(){return r(f)};return(u=n).size<=a?r(u):(f=u,(m=function(e){for(;e;){if(e.then)return void e.then(m,t);try{if(e.pop){if(e.length)return e.pop()?g.call(this):e;e=l}else e=e.call(this)}catch(e){return t(e)}}}.bind(this))(l))}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)})}var n,r=0;var t=function createWorker(e){return new Worker(URL.createObjectURL(new Blob(["(".concat(e,")()")])))}(function(){var e=!1;self.addEventListener("message",function(n){return new Promise(function(r,t){var i,a,o,s,c=n.data;i=c.file,a=c.id,o=c.imageCompressionLibUrl,s=c.options;var u=function $Try_1_Post(){try{return r()}catch(e){return t(e)}},f=function $Try_1_Catch(e){try{return self.postMessage({error:e.message,id:a}),u()}catch(e){return t(e)}};try{var m;return e||(importScripts(o),e=!0),imageCompression(i,s).then(function(e){try{return m=e,self.postMessage({file:m,id:a}),u()}catch(e){return f(e)}},f)}catch(e){f(e)}})})});function compressOnWebWorker(e,i){return new Promise(function(a,o){return new Promise(function(s,c){n||(n=function createSourceObject(e){return URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}("\n function imageCompression (){return (".concat(imageCompression,").apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ").concat(imageCompression.getDataUrlFromFile,"\n imageCompression.getFilefromDataUrl = ").concat(imageCompression.getFilefromDataUrl,"\n imageCompression.loadImage = ").concat(imageCompression.loadImage,"\n imageCompression.drawImageInCanvas = ").concat(imageCompression.drawImageInCanvas,"\n imageCompression.drawFileInCanvas = ").concat(imageCompression.drawFileInCanvas,"\n imageCompression.canvasToFile = ").concat(imageCompression.canvasToFile,"\n imageCompression.getExifOrientation = ").concat(imageCompression.getExifOrientation,"\n imageCompression.handleMaxWidthOrHeight = ").concat(imageCompression.handleMaxWidthOrHeight,"\n imageCompression.followExifOrientation = ").concat(imageCompression.followExifOrientation,"\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ").concat(getNewCanvasAndCtx,"\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (").concat(compress,").apply(null, arguments)}\n ")));var u=r++;return t.addEventListener("message",function handler(e){e.data.id===u&&(t.removeEventListener("message",handler),e.data.error&&o(e.data.error),a(e.data.file))}),t.postMessage({file:e,id:u,imageCompressionLibUrl:n,options:i}),s()})})}function imageCompression(e,n){return new Promise(function(r,t){var i,a;if(n.maxSizeMB=n.maxSizeMB||Number.POSITIVE_INFINITY,n.useWebWorker="boolean"!=typeof n.useWebWorker||n.useWebWorker,!(e instanceof Blob||e instanceof CustomFile))return t(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return t(new Error("The file given is not an image"));if(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!n.useWebWorker||"function"!=typeof Worker||a)return compress(e,n).then(function(e){try{return i=e,$If_3.call(this)}catch(e){return t(e)}}.bind(this),t);var o=function(){try{return $If_3.call(this)}catch(e){return t(e)}}.bind(this),s=function $Try_1_Catch(r){try{return console.warn("Run compression in web worker failed:",r,", fall back to main thread"),compress(e,n).then(function(e){try{return i=e,o()}catch(e){return t(e)}},t)}catch(e){return t(e)}};try{return compressOnWebWorker(e,n).then(function(e){try{return i=e,o()}catch(e){return s(e)}},s)}catch(e){s(e)}function $If_3(){try{i.name=e.name,i.lastModified=e.lastModified}catch(e){}return r(i)}})}return imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression}); //# sourceMappingURL=browser-image-compression.js.map diff --git a/dist/browser-image-compression.js.map b/dist/browser-image-compression.js.map index fd7ffba..29eb866 100644 --- a/dist/browser-image-compression.js.map +++ b/dist/browser-image-compression.js.map @@ -1 +1 @@ -{"version":3,"file":"browser-image-compression.js","sources":["../lib/utils.js","../lib/image-compression.js","../lib/web-worker.js","../lib/index.js"],"sourcesContent":["// add support for cordova-plugin-file\nconst moduleMapper = typeof window !== 'undefined' && window.cordova && window.cordova.require('cordova/modulemapper');\nexport const CustomFile = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'File')) || File;\nexport const CustomFileReader = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'FileReader')) || FileReader;\n/**\n * getDataUrlFromFile\n *\n * @param {File} file\n * @returns {Promise}\n */\nexport function getDataUrlFromFile (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = () => resolve(reader.result)\n reader.onerror = (e) => reject(e)\n reader.readAsDataURL(file)\n })\n}\n\n/**\n * getFilefromDataUrl\n *\n * @param {string} dataurl\n * @param {string} filename\n * @param {number} [lastModified=Date.now()]\n * @returns {Promise}\n */\nexport function getFilefromDataUrl (dataurl, filename, lastModified = Date.now()) {\n return new Promise((resolve) => {\n const arr = dataurl.split(',')\n const mime = arr[0].match(/:(.*?);/)[1]\n const bstr = atob(arr[1])\n let n = bstr.length\n const u8arr = new Uint8Array(n)\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n)\n }\n const file = new Blob([u8arr], { type: mime })\n file.name = filename\n file.lastModified = lastModified\n resolve(file)\n\n // Safari has issue with File constructor not being able to POST in FormData\n // https://github.com/Donaldcwl/browser-image-compression/issues/8\n // https://bugs.webkit.org/show_bug.cgi?id=165081\n // let file\n // try {\n // file = new File([u8arr], filename, { type: mime }) // Edge do not support File constructor\n // } catch (e) {\n // file = new Blob([u8arr], { type: mime })\n // file.name = filename\n // file.lastModified = lastModified\n // }\n // resolve(file)\n })\n}\n\n/**\n * loadImage\n *\n * @param {string} src\n * @returns {Promise}\n */\nexport function loadImage (src) {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = (e) => reject(e)\n img.src = src\n })\n}\n\n/**\n * drawImageInCanvas\n *\n * @param {HTMLImageElement} img\n * @returns {HTMLCanvasElement}\n */\nexport function drawImageInCanvas (img) {\n const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n return canvas\n}\n\n/**\n * drawFileInCanvas\n *\n * @param {File} file\n * @returns {Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>}\n */\nexport async function drawFileInCanvas (file) {\n let img\n try {\n img = await createImageBitmap(file)\n } catch (e) {\n const dataUrl = await getDataUrlFromFile(file)\n img = await loadImage(dataUrl)\n }\n const canvas = drawImageInCanvas(img)\n return [img, canvas]\n}\n\n/**\n * canvasToFile\n *\n * @param canvas\n * @param {string} fileType\n * @param {string} fileName\n * @param {number} fileLastModified\n * @param {number} [quality]\n * @returns {Promise}\n */\nexport async function canvasToFile (canvas, fileType, fileName, fileLastModified, quality = 1) {\n let file\n if (typeof OffscreenCanvas === 'function' && canvas instanceof OffscreenCanvas) {\n file = await canvas.convertToBlob({ type: fileType, quality })\n file.name = fileName\n file.lastModified = fileLastModified\n } else {\n const dataUrl = canvas.toDataURL(fileType, quality)\n file = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)\n }\n return file\n}\n\n/**\n * getExifOrientation\n * get image exif orientation info\n * source: https://stackoverflow.com/a/32490603/10395024\n *\n * @param {File} file\n * @returns {Promise} - orientation id, see https://i.stack.imgur.com/VGsAj.gif\n */\nexport function getExifOrientation (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = (e) => {\n const view = new DataView(e.target.result)\n if (view.getUint16(0, false) != 0xFFD8) {\n return resolve(-2)\n }\n const length = view.byteLength\n let offset = 2\n while (offset < length) {\n if (view.getUint16(offset + 2, false) <= 8) return resolve(-1)\n const marker = view.getUint16(offset, false)\n offset += 2\n if (marker == 0xFFE1) {\n if (view.getUint32(offset += 2, false) != 0x45786966) {\n return resolve(-1)\n }\n\n var little = view.getUint16(offset += 6, false) == 0x4949\n offset += view.getUint32(offset + 4, little)\n var tags = view.getUint16(offset, little)\n offset += 2\n for (var i = 0; i < tags; i++) {\n if (view.getUint16(offset + (i * 12), little) == 0x0112) {\n return resolve(view.getUint16(offset + (i * 12) + 8, little))\n }\n }\n } else if ((marker & 0xFF00) != 0xFF00) {\n break\n } else {\n offset += view.getUint16(offset, false)\n }\n }\n return resolve(-1)\n }\n reader.onerror = (e) => reject(e)\n reader.readAsArrayBuffer(file)\n })\n}\n\n/**\n *\n * @param {HTMLCanvasElement} canvas\n * @param options\n * @returns {HTMLCanvasElement>}\n */\nexport function handleMaxWidthOrHeight (canvas, options) {\n const width = canvas.width\n const height = canvas.height\n const maxWidthOrHeight = options.maxWidthOrHeight\n\n const needToHandle = Number.isInteger(maxWidthOrHeight) && (width > maxWidthOrHeight || height > maxWidthOrHeight)\n\n let newCanvas = canvas\n let ctx\n\n if (needToHandle) {\n [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n if (width > height) {\n newCanvas.width = maxWidthOrHeight\n newCanvas.height = (height / width) * maxWidthOrHeight\n } else {\n newCanvas.width = (width / height) * maxWidthOrHeight\n newCanvas.height = maxWidthOrHeight\n }\n ctx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height)\n }\n\n return newCanvas\n}\n\n/**\n * followExifOrientation\n * source: https://stackoverflow.com/a/40867559/10395024\n *\n * @param {HTMLCanvasElement} canvas\n * @param {number} exifOrientation\n * @returns {HTMLCanvasElement} canvas\n */\nexport function followExifOrientation (canvas, exifOrientation) {\n const width = canvas.width\n const height = canvas.height\n\n const [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n\n // set proper canvas dimensions before transform & export\n if (4 < exifOrientation && exifOrientation < 9) {\n newCanvas.width = height\n newCanvas.height = width\n } else {\n newCanvas.width = width\n newCanvas.height = height\n }\n\n // transform context before drawing image\n switch (exifOrientation) {\n case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;\n case 3: ctx.transform(-1, 0, 0, -1, width, height); break;\n case 4: ctx.transform(1, 0, 0, -1, 0, height); break;\n case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;\n case 6: ctx.transform(0, 1, -1, 0, height, 0); break;\n case 7: ctx.transform(0, -1, -1, 0, height, width); break;\n case 8: ctx.transform(0, -1, 1, 0, 0, width); break;\n default: break;\n }\n\n ctx.drawImage(canvas, 0, 0, width, height)\n\n return newCanvas\n}\n\n/**\n * get new Canvas and it's context\n * @param width\n * @param height\n * @returns {[HTMLCanvasElement, CanvasRenderingContext2D]}\n */\nexport function getNewCanvasAndCtx (width, height) {\n let canvas\n let ctx\n try {\n canvas = new OffscreenCanvas(width, height)\n ctx = canvas.getContext('2d')\n } catch (e) {\n canvas = document.createElement('canvas')\n ctx = canvas.getContext('2d')\n }\n canvas.width = width\n canvas.height = height\n return [canvas, ctx]\n}","import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nexport default async function compress (file, options) {\n let remainingTrials = options.maxIteration || 10\n\n const maxSizeByte = options.maxSizeMB * 1024 * 1024\n\n // drawFileInCanvas\n let [img, canvas] = await drawFileInCanvas(file)\n\n // handleMaxWidthOrHeight\n canvas = handleMaxWidthOrHeight(canvas, options)\n\n // exifOrientation\n options.exifOrientation = options.exifOrientation || await getExifOrientation(file)\n canvas = followExifOrientation(canvas, options.exifOrientation)\n\n let quality = 1\n\n let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)\n // check if we need to compress or resize\n if (tempFile.size <= maxSizeByte) {\n // no need to compress\n return tempFile\n }\n\n let compressedFile = tempFile\n while (remainingTrials-- && compressedFile.size > maxSizeByte) {\n const newWidth = canvas.width * 0.9\n const newHeight = canvas.height * 0.9\n const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)\n\n ctx.drawImage(img, 0, 0, newWidth, newHeight)\n\n if (file.type === 'image/jpeg') {\n quality *= 0.9\n }\n compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)\n\n canvas = newCanvas\n }\n\n return compressedFile\n}","import imageCompression from './index'\nimport compress from './image-compression'\nimport { getNewCanvasAndCtx } from './utils'\n\nlet cnt = 0\nlet imageCompressionLibUrl\n\nfunction createWorker (f) {\n return new Worker(URL.createObjectURL(new Blob([`(${f})()`])))\n}\n\nconst worker = createWorker(() => {\n let scriptImported = false\n self.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message, id })\n }\n })\n})\n\nfunction createSourceObject (str) {\n return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))\n}\n\nexport function compressOnWebWorker (file, options) {\n return new Promise(async (resolve, reject) => {\n if (!imageCompressionLibUrl) {\n imageCompressionLibUrl = createSourceObject(`\n function imageCompression (){return (${imageCompression}).apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}\n imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}\n imageCompression.loadImage = ${imageCompression.loadImage}\n imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}\n imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}\n imageCompression.canvasToFile = ${imageCompression.canvasToFile}\n imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}\n imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}\n imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ${getNewCanvasAndCtx}\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (${compress}).apply(null, arguments)}\n `)\n }\n let id = cnt++\n\n function handler (e) {\n if (e.data.id === id) {\n worker.removeEventListener('message', handler)\n if (e.data.error) {\n reject(e.data.error)\n }\n resolve(e.data.file)\n }\n }\n\n worker.addEventListener('message', handler)\n worker.postMessage({ file, id, imageCompressionLibUrl, options })\n })\n}","import compress from './image-compression'\nimport {\n canvasToFile,\n drawFileInCanvas,\n drawImageInCanvas,\n getDataUrlFromFile,\n getFilefromDataUrl,\n loadImage,\n getExifOrientation,\n handleMaxWidthOrHeight,\n followExifOrientation,\n CustomFile\n} from './utils'\nimport { compressOnWebWorker } from './web-worker'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {boolean} [options.useWebWorker=true]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nasync function imageCompression (file, options) {\n\n let compressedFile\n\n options.maxSizeMB = options.maxSizeMB || Number.POSITIVE_INFINITY\n options.useWebWorker = typeof options.useWebWorker === 'boolean' ? options.useWebWorker : true\n\n if (!(file instanceof Blob || file instanceof CustomFile)) {\n throw new Error('The file given is not an instance of Blob or File')\n } else if (!/^image/.test(file.type)) {\n throw new Error('The file given is not an image')\n }\n\n // try run in web worker, fall back to run in main thread\n const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n\n // if (inWebWorker) {\n // console.log('run compression in web worker')\n // } else {\n // console.log('run compression in main thread')\n // }\n\n if (options.useWebWorker && typeof Worker === 'function' && !inWebWorker) {\n try {\n // \"compressOnWebWorker\" is kind of like a recursion to call \"imageCompression\" again inside web worker\n compressedFile = await compressOnWebWorker(file, options)\n } catch (e) {\n console.warn('Run compression in web worker failed:', e, ', fall back to main thread')\n compressedFile = await compress(file, options)\n }\n } else {\n compressedFile = await compress(file, options)\n }\n\n try {\n compressedFile.name = file.name\n compressedFile.lastModified = file.lastModified\n } catch (e) {}\n\n return compressedFile\n}\n\nimageCompression.getDataUrlFromFile = getDataUrlFromFile\nimageCompression.getFilefromDataUrl = getFilefromDataUrl\nimageCompression.loadImage = loadImage\nimageCompression.drawImageInCanvas = drawImageInCanvas\nimageCompression.drawFileInCanvas = drawFileInCanvas\nimageCompression.canvasToFile = canvasToFile\nimageCompression.getExifOrientation = getExifOrientation\nimageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight\nimageCompression.followExifOrientation = followExifOrientation\n\nexport default imageCompression\n"],"names":["window","cordova","require","CustomFile","reader","onload","reject","file","getFilefromDataUrl","n","loadImage","fileType","view","result","length","offset","getUint32","marker","readAsArrayBuffer","width","height","canvas","options","ctx","maxWidthOrHeight","followExifOrientation","lastModified","cnt","compressOnWebWorker","name","imageCompression","drawImageInCanvas","drawFileInCanvas","canvasToFile","getExifOrientation","handleMaxWidthOrHeight"],"mappings":";;;;;;;4pBAEA,kCAA2CA,gBAAAA,OAAAC,QAAAC,gCAC9BC,oLAyBXC,EAAAC,OAAA,oBAAgCD,wCACVE,sBACHC,cAUTC,0LAuBe,mCAGvBC,wnBA8CkBC,qcAOF,MAAAC,iYAmBdC,wBAAIC,yDAIJC,iBACO,uBAC8CC,EAAS,2CAC9B,oBAEhB,IACoB,wBAAvBA,GAAU,wDAMnBH,EAAAI,UAAWD,iCAEX,4GAMAE,gFASVb,EAAAc,kEAoBIC,IAAAA,MACAC,EAAIC,WACFC,kHASJC,mCAW6CC,YAE9BL,8BAMHE,EAAQ,wCAWNI,sBAAuBJ,mBACnCD,kKAOiCD,mQAiBvBE,0xBCvOmBd,SAAgBmB,kIAW3C,0HAQgBnB,kdCxCtB,MAAIoB,UAIJ,0nBASQC,4oGC6CWC,0HAMnBC,iBAAAtB,mBAAsCA,mBACtCsB,iBAAApB,oBACAoB,iBAAAC,oCACAD,iBAAAE,iBAAAA,iBACAF,iBAAAG,0BACAH,iBAAAI,sCACAJ,iBAAAK,8CACAL,iBAAAL,sBAAAA"} \ No newline at end of file +{"version":3,"file":"browser-image-compression.js","sources":["../lib/utils.js","../lib/image-compression.js","../lib/web-worker.js","../lib/index.js"],"sourcesContent":["// add support for cordova-plugin-file\nconst moduleMapper = typeof window !== 'undefined' && window.cordova && window.cordova.require('cordova/modulemapper');\nexport const CustomFile = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'File')) || File;\nexport const CustomFileReader = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'FileReader')) || FileReader;\n/**\n * getDataUrlFromFile\n *\n * @param {File} file\n * @returns {Promise}\n */\nexport function getDataUrlFromFile (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = () => resolve(reader.result)\n reader.onerror = (e) => reject(e)\n reader.readAsDataURL(file)\n })\n}\n\n/**\n * getFilefromDataUrl\n *\n * @param {string} dataurl\n * @param {string} filename\n * @param {number} [lastModified=Date.now()]\n * @returns {Promise}\n */\nexport function getFilefromDataUrl (dataurl, filename, lastModified = Date.now()) {\n return new Promise((resolve) => {\n const arr = dataurl.split(',')\n const mime = arr[0].match(/:(.*?);/)[1]\n const bstr = atob(arr[1])\n let n = bstr.length\n const u8arr = new Uint8Array(n)\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n)\n }\n const file = new Blob([u8arr], { type: mime })\n file.name = filename\n file.lastModified = lastModified\n resolve(file)\n\n // Safari has issue with File constructor not being able to POST in FormData\n // https://github.com/Donaldcwl/browser-image-compression/issues/8\n // https://bugs.webkit.org/show_bug.cgi?id=165081\n // let file\n // try {\n // file = new File([u8arr], filename, { type: mime }) // Edge do not support File constructor\n // } catch (e) {\n // file = new Blob([u8arr], { type: mime })\n // file.name = filename\n // file.lastModified = lastModified\n // }\n // resolve(file)\n })\n}\n\n/**\n * loadImage\n *\n * @param {string} src\n * @returns {Promise}\n */\nexport function loadImage (src) {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = (e) => reject(e)\n img.src = src\n })\n}\n\n/**\n * drawImageInCanvas\n *\n * @param {HTMLImageElement} img\n * @returns {HTMLCanvasElement}\n */\nexport function drawImageInCanvas (img) {\n const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n return canvas\n}\n\n/**\n * drawFileInCanvas\n *\n * @param {File} file\n * @returns {Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>}\n */\nexport async function drawFileInCanvas (file) {\n let img\n try {\n img = await createImageBitmap(file)\n } catch (e) {\n const dataUrl = await getDataUrlFromFile(file)\n img = await loadImage(dataUrl)\n }\n const canvas = drawImageInCanvas(img)\n return [img, canvas]\n}\n\n/**\n * canvasToFile\n *\n * @param canvas\n * @param {string} fileType\n * @param {string} fileName\n * @param {number} fileLastModified\n * @param {number} [quality]\n * @returns {Promise}\n */\nexport async function canvasToFile (canvas, fileType, fileName, fileLastModified, quality = 1) {\n let file\n if (typeof OffscreenCanvas === 'function' && canvas instanceof OffscreenCanvas) {\n file = await canvas.convertToBlob({ type: fileType, quality })\n file.name = fileName\n file.lastModified = fileLastModified\n } else {\n const dataUrl = canvas.toDataURL(fileType, quality)\n file = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)\n }\n return file\n}\n\n/**\n * getExifOrientation\n * get image exif orientation info\n * source: https://stackoverflow.com/a/32490603/10395024\n *\n * @param {File} file\n * @returns {Promise} - orientation id, see https://i.stack.imgur.com/VGsAj.gif\n */\nexport function getExifOrientation (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = (e) => {\n const view = new DataView(e.target.result)\n if (view.getUint16(0, false) != 0xFFD8) {\n return resolve(-2)\n }\n const length = view.byteLength\n let offset = 2\n while (offset < length) {\n if (view.getUint16(offset + 2, false) <= 8) return resolve(-1)\n const marker = view.getUint16(offset, false)\n offset += 2\n if (marker == 0xFFE1) {\n if (view.getUint32(offset += 2, false) != 0x45786966) {\n return resolve(-1)\n }\n\n var little = view.getUint16(offset += 6, false) == 0x4949\n offset += view.getUint32(offset + 4, little)\n var tags = view.getUint16(offset, little)\n offset += 2\n for (var i = 0; i < tags; i++) {\n if (view.getUint16(offset + (i * 12), little) == 0x0112) {\n return resolve(view.getUint16(offset + (i * 12) + 8, little))\n }\n }\n } else if ((marker & 0xFF00) != 0xFF00) {\n break\n } else {\n offset += view.getUint16(offset, false)\n }\n }\n return resolve(-1)\n }\n reader.onerror = (e) => reject(e)\n reader.readAsArrayBuffer(file)\n })\n}\n\n/**\n *\n * @param {HTMLCanvasElement} canvas\n * @param options\n * @returns {HTMLCanvasElement>}\n */\nexport function handleMaxWidthOrHeight (canvas, options) {\n const width = canvas.width\n const height = canvas.height\n const maxWidthOrHeight = options.maxWidthOrHeight\n\n const needToHandle = Number.isInteger(maxWidthOrHeight) && (width > maxWidthOrHeight || height > maxWidthOrHeight)\n\n let newCanvas = canvas\n let ctx\n\n if (needToHandle) {\n [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n if (width > height) {\n newCanvas.width = maxWidthOrHeight\n newCanvas.height = (height / width) * maxWidthOrHeight\n } else {\n newCanvas.width = (width / height) * maxWidthOrHeight\n newCanvas.height = maxWidthOrHeight\n }\n ctx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height)\n }\n\n return newCanvas\n}\n\n/**\n * followExifOrientation\n * source: https://stackoverflow.com/a/40867559/10395024\n *\n * @param {HTMLCanvasElement} canvas\n * @param {number} exifOrientation\n * @returns {HTMLCanvasElement} canvas\n */\nexport function followExifOrientation (canvas, exifOrientation) {\n const width = canvas.width\n const height = canvas.height\n\n const [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n\n // set proper canvas dimensions before transform & export\n if (4 < exifOrientation && exifOrientation < 9) {\n newCanvas.width = height\n newCanvas.height = width\n } else {\n newCanvas.width = width\n newCanvas.height = height\n }\n\n // transform context before drawing image\n switch (exifOrientation) {\n case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;\n case 3: ctx.transform(-1, 0, 0, -1, width, height); break;\n case 4: ctx.transform(1, 0, 0, -1, 0, height); break;\n case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;\n case 6: ctx.transform(0, 1, -1, 0, height, 0); break;\n case 7: ctx.transform(0, -1, -1, 0, height, width); break;\n case 8: ctx.transform(0, -1, 1, 0, 0, width); break;\n default: break;\n }\n\n ctx.drawImage(canvas, 0, 0, width, height)\n\n return newCanvas\n}\n\n/**\n * get new Canvas and it's context\n * @param width\n * @param height\n * @returns {[HTMLCanvasElement, CanvasRenderingContext2D]}\n */\nexport function getNewCanvasAndCtx (width, height) {\n let canvas\n let ctx\n try {\n canvas = new OffscreenCanvas(width, height)\n ctx = canvas.getContext('2d')\n } catch (e) {\n canvas = document.createElement('canvas')\n ctx = canvas.getContext('2d')\n }\n canvas.width = width\n canvas.height = height\n return [canvas, ctx]\n}","import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nexport default async function compress (file, options) {\n let remainingTrials = options.maxIteration || 10\n\n const maxSizeByte = options.maxSizeMB * 1024 * 1024\n\n // drawFileInCanvas\n let [img, canvas] = await drawFileInCanvas(file)\n\n // handleMaxWidthOrHeight\n canvas = handleMaxWidthOrHeight(canvas, options)\n\n // exifOrientation\n options.exifOrientation = options.exifOrientation || await getExifOrientation(file)\n canvas = followExifOrientation(canvas, options.exifOrientation)\n\n let quality = 1\n\n let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)\n // check if we need to compress or resize\n if (tempFile.size <= maxSizeByte) {\n // no need to compress\n return tempFile\n }\n\n let compressedFile = tempFile\n while (remainingTrials-- && compressedFile.size > maxSizeByte) {\n const newWidth = canvas.width * 0.9\n const newHeight = canvas.height * 0.9\n const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)\n\n ctx.drawImage(img, 0, 0, newWidth, newHeight)\n\n if (file.type === 'image/jpeg') {\n quality *= 0.9\n }\n compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)\n\n canvas = newCanvas\n }\n\n return compressedFile\n}","import imageCompression from './index'\nimport compress from './image-compression'\nimport { getNewCanvasAndCtx } from './utils'\n\nlet cnt = 0\nlet imageCompressionLibUrl\n\nfunction createWorker (f) {\n return new Worker(URL.createObjectURL(new Blob([`(${f})()`])))\n}\n\nconst worker = createWorker(() => {\n let scriptImported = false\n self.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message, id })\n }\n })\n})\n\nfunction createSourceObject (str) {\n return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))\n}\n\nexport function compressOnWebWorker (file, options) {\n return new Promise(async (resolve, reject) => {\n if (!imageCompressionLibUrl) {\n imageCompressionLibUrl = createSourceObject(`\n function imageCompression (){return (${imageCompression}).apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}\n imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}\n imageCompression.loadImage = ${imageCompression.loadImage}\n imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}\n imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}\n imageCompression.canvasToFile = ${imageCompression.canvasToFile}\n imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}\n imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}\n imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ${getNewCanvasAndCtx}\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (${compress}).apply(null, arguments)}\n `)\n }\n let id = cnt++\n\n function handler (e) {\n if (e.data.id === id) {\n worker.removeEventListener('message', handler)\n if (e.data.error) {\n reject(e.data.error)\n }\n resolve(e.data.file)\n }\n }\n\n worker.addEventListener('message', handler)\n worker.postMessage({ file, id, imageCompressionLibUrl, options })\n })\n}","import compress from './image-compression'\nimport {\n canvasToFile,\n drawFileInCanvas,\n drawImageInCanvas,\n getDataUrlFromFile,\n getFilefromDataUrl,\n loadImage,\n getExifOrientation,\n handleMaxWidthOrHeight,\n followExifOrientation,\n CustomFile\n} from './utils'\nimport { compressOnWebWorker } from './web-worker'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {boolean} [options.useWebWorker=true]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nasync function imageCompression (file, options) {\n\n let compressedFile\n\n options.maxSizeMB = options.maxSizeMB || Number.POSITIVE_INFINITY\n options.useWebWorker = typeof options.useWebWorker === 'boolean' ? options.useWebWorker : true\n\n if (!(file instanceof Blob || file instanceof CustomFile)) {\n throw new Error('The file given is not an instance of Blob or File')\n } else if (!/^image/.test(file.type)) {\n throw new Error('The file given is not an image')\n }\n\n // try run in web worker, fall back to run in main thread\n const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n\n // if (inWebWorker) {\n // console.log('run compression in web worker')\n // } else {\n // console.log('run compression in main thread')\n // }\n\n if (options.useWebWorker && typeof Worker === 'function' && !inWebWorker) {\n try {\n // \"compressOnWebWorker\" is kind of like a recursion to call \"imageCompression\" again inside web worker\n compressedFile = await compressOnWebWorker(file, options)\n } catch (e) {\n console.warn('Run compression in web worker failed:', e, ', fall back to main thread')\n compressedFile = await compress(file, options)\n }\n } else {\n compressedFile = await compress(file, options)\n }\n\n try {\n compressedFile.name = file.name\n compressedFile.lastModified = file.lastModified\n } catch (e) {}\n\n return compressedFile\n}\n\nimageCompression.getDataUrlFromFile = getDataUrlFromFile\nimageCompression.getFilefromDataUrl = getFilefromDataUrl\nimageCompression.loadImage = loadImage\nimageCompression.drawImageInCanvas = drawImageInCanvas\nimageCompression.drawFileInCanvas = drawFileInCanvas\nimageCompression.canvasToFile = canvasToFile\nimageCompression.getExifOrientation = getExifOrientation\nimageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight\nimageCompression.followExifOrientation = followExifOrientation\n\nexport default imageCompression\n"],"names":["window","cordova","require","CustomFile","reader","onload","reject","file","getFilefromDataUrl","n","loadImage","fileType","view","result","length","offset","getUint32","marker","readAsArrayBuffer","width","height","canvas","options","ctx","maxWidthOrHeight","followExifOrientation","lastModified","cnt","compressOnWebWorker","name","imageCompression","drawImageInCanvas","drawFileInCanvas","canvasToFile","getExifOrientation","handleMaxWidthOrHeight"],"mappings":";;;;;;;4pBAEA,kCAA2CA,gBAAAA,OAAAC,QAAAC,gCAC9BC,2NAyBXC,EAAAC,OAAA,oBAAgCD,wCACVE,sBACHC,cAUTC,0LAuBe,mCAGvBC,wnBA8CkBC,qcAOF,MAAAC,gZAmBdC,wBAAIC,yDAIJC,iBACO,uBAC8CC,EAAS,2CAC9B,oBAEhB,IACoB,wBAAvBA,GAAU,wDAMnBH,EAAAI,UAAWD,iCAEX,4GAMAE,gFASVb,EAAAc,kEAoBIC,IAAAA,MACAC,EAAIC,WACFC,kHASJC,mCAW6CC,YAE9BL,8BAMHE,EAAQ,wCAWNI,sBAAuBJ,mBACnCD,kKAOiCD,mQAiBvBE,0xBCvOmBd,SAAgBmB,kIAW3C,0HAQgBnB,kdCxCtB,MAAIoB,UAIJ,0nBASQC,qpGC6CWC,0HAMnBC,iBAAAtB,mBAAsCA,mBACtCsB,iBAAApB,oBACAoB,iBAAAC,oCACAD,iBAAAE,iBAAAA,iBACAF,iBAAAG,0BACAH,iBAAAI,sCACAJ,iBAAAK,8CACAL,iBAAAL,sBAAAA"} \ No newline at end of file diff --git a/dist/browser-image-compression.mjs b/dist/browser-image-compression.mjs index 75c4d92..0fedc0b 100644 --- a/dist/browser-image-compression.mjs +++ b/dist/browser-image-compression.mjs @@ -1,9 +1,9 @@ /** * Browser Image Compression - * v1.0.4 + * v1.0.5 * by Donald * https://github.com/Donaldcwl/browser-image-compression */ -function _slicedToArray(e,n){return function _arrayWithHoles(e){if(Array.isArray(e))return e}(e)||function _iterableToArrayLimit(e,n){var r=[],t=!0,a=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(t=(o=s.next()).done)&&(r.push(o.value),!n||r.length!==n);t=!0);}catch(e){a=!0,i=e}finally{try{t||null==s.return||s.return()}finally{if(a)throw i}}return r}(e,n)||function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}var e="undefined"!=typeof window&&window.cordova&&window.cordova.require("cordova/modulemapper"),n=e&&e.getOriginalSymbol(window,"File")||File,r=e&&e.getOriginalSymbol(window,"FileReader")||FileReader;function getDataUrlFromFile(e){return new Promise(function(n,t){var a=new r;a.onload=function(){return n(a.result)},a.onerror=function(e){return t(e)},a.readAsDataURL(e)})}function getFilefromDataUrl(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Date.now();return new Promise(function(t){for(var a=e.split(","),i=a[0].match(/:(.*?);/)[1],o=atob(a[1]),s=o.length,c=new Uint8Array(s);s--;)c[s]=o.charCodeAt(s);var u=new Blob([c],{type:i});u.name=n,u.lastModified=r,t(u)})}function loadImage(e){return new Promise(function(n,r){var t=new Image;t.onload=function(){return n(t)},t.onerror=function(e){return r(e)},t.src=e})}function drawImageInCanvas(e){var n=_slicedToArray(getNewCanvasAndCtx(e.width,e.height),2),r=n[0];return n[1].drawImage(e,0,0,r.width,r.height),r}function drawFileInCanvas(e){return new Promise(function(n,r){var t,a,i=function $Try_1_Post(){try{return a=drawImageInCanvas(t),n([t,a])}catch(e){return r(e)}},o=function $Try_1_Catch(n){try{return getDataUrlFromFile(e).then(function(e){try{return loadImage(e).then(function(e){try{return t=e,i()}catch(e){return r(e)}},r)}catch(e){return r(e)}},r)}catch(e){return r(e)}};try{return createImageBitmap(e).then(function(e){try{return t=e,i()}catch(e){return o()}},o)}catch(e){o()}})}function canvasToFile(e,n,r,t){var a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;return new Promise(function(i,o){var s;return"function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas?e.convertToBlob({type:n,quality:a}).then(function(e){try{return(s=e).name=r,s.lastModified=t,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o):getFilefromDataUrl(e.toDataURL(n,a),r,t).then(function(e){try{return s=e,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o);function $If_4(){return i(s)}})}function getExifOrientation(e){return new Promise(function(n,t){var a=new r;a.onload=function(e){var r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return n(-2);for(var t=r.byteLength,a=2;ai||a>i)){var s=_slicedToArray(getNewCanvasAndCtx(t,a),2);o=s[0],r=s[1],t>a?(o.width=i,o.height=a/t*i):(o.width=t/a*i,o.height=i),r.drawImage(e,0,0,o.width,o.height)}return o}function followExifOrientation(e,n){var r=e.width,t=e.height,a=_slicedToArray(getNewCanvasAndCtx(r,t),2),i=a[0],o=a[1];switch(4i){var n,r,u,m=_slicedToArray(getNewCanvasAndCtx(n=.9*s.width,r=.9*s.height),2);return u=m[0],m[1].drawImage(o,0,0,n,r),"image/jpeg"===e.type&&(c*=.9),canvasToFile(u,e.type,e.name,e.lastModified,c).then(function(e){try{return l=e,s=u,$Loop_3}catch(e){return t(e)}},t)}return[1]},g=function $Loop_3_exit(){return r(l)};return(u=n).size<=i?r(u):(l=u,(m=function(e){for(;e;){if(e.then)return void e.then(m,t);try{if(e.pop){if(e.length)return e.pop()?g.call(this):e;e=f}else e=e.call(this)}catch(e){return t(e)}}}.bind(this))(f))}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)})}var t,a=0;var i=function createWorker(e){return new Worker(URL.createObjectURL(new Blob(["(".concat(e,")()")])))}(function(){var e=!1;self.addEventListener("message",function(n){return new Promise(function(r,t){var a,i,o,s,c=n.data;a=c.file,i=c.id,o=c.imageCompressionLibUrl,s=c.options;var u=function $Try_1_Post(){try{return r()}catch(e){return t(e)}},l=function $Try_1_Catch(e){try{return self.postMessage({error:e.message,id:i}),u()}catch(e){return t(e)}};try{var m;return e||(importScripts(o),e=!0),imageCompression(a,s).then(function(e){try{return m=e,self.postMessage({file:m,id:i}),u()}catch(e){return l(e)}},l)}catch(e){l(e)}})})});function compressOnWebWorker(e,n){return new Promise(function(r,o){return new Promise(function(s,c){t||(t=function createSourceObject(e){return URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}("\n function imageCompression (){return (".concat(imageCompression,").apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ").concat(imageCompression.getDataUrlFromFile,"\n imageCompression.getFilefromDataUrl = ").concat(imageCompression.getFilefromDataUrl,"\n imageCompression.loadImage = ").concat(imageCompression.loadImage,"\n imageCompression.drawImageInCanvas = ").concat(imageCompression.drawImageInCanvas,"\n imageCompression.drawFileInCanvas = ").concat(imageCompression.drawFileInCanvas,"\n imageCompression.canvasToFile = ").concat(imageCompression.canvasToFile,"\n imageCompression.getExifOrientation = ").concat(imageCompression.getExifOrientation,"\n imageCompression.handleMaxWidthOrHeight = ").concat(imageCompression.handleMaxWidthOrHeight,"\n imageCompression.followExifOrientation = ").concat(imageCompression.followExifOrientation,"\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ").concat(getNewCanvasAndCtx,"\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (").concat(compress,").apply(null, arguments)}\n ")));var u=a++;return i.addEventListener("message",function handler(e){e.data.id===u&&(i.removeEventListener("message",handler),e.data.error&&o(e.data.error),r(e.data.file))}),i.postMessage({file:e,id:u,imageCompressionLibUrl:t,options:n}),s()})})}function imageCompression(e,r){return new Promise(function(t,a){var i,o;if(r.maxSizeMB=r.maxSizeMB||Number.POSITIVE_INFINITY,r.useWebWorker="boolean"!=typeof r.useWebWorker||r.useWebWorker,!(e instanceof Blob||e instanceof n))return a(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return a(new Error("The file given is not an image"));if(o="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!r.useWebWorker||"function"!=typeof Worker||o)return compress(e,r).then(function(e){try{return i=e,$If_3.call(this)}catch(e){return a(e)}}.bind(this),a);var s=function(){try{return $If_3.call(this)}catch(e){return a(e)}}.bind(this),c=function $Try_1_Catch(n){try{return console.warn("Run compression in web worker failed:",n,", fall back to main thread"),compress(e,r).then(function(e){try{return i=e,s()}catch(e){return a(e)}},a)}catch(e){return a(e)}};try{return compressOnWebWorker(e,r).then(function(e){try{return i=e,s()}catch(e){return c(e)}},c)}catch(e){c(e)}function $If_3(){try{i.name=e.name,i.lastModified=e.lastModified}catch(e){}return t(i)}})}imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation;export default imageCompression; +function _slicedToArray(e,n){return function _arrayWithHoles(e){if(Array.isArray(e))return e}(e)||function _iterableToArrayLimit(e,n){var r=[],t=!0,a=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(t=(o=s.next()).done)&&(r.push(o.value),!n||r.length!==n);t=!0);}catch(e){a=!0,i=e}finally{try{t||null==s.return||s.return()}finally{if(a)throw i}}return r}(e,n)||function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}var e="undefined"!=typeof window&&window.cordova&&window.cordova.require("cordova/modulemapper"),CustomFile=e&&e.getOriginalSymbol(window,"File")||File,CustomFileReader=e&&e.getOriginalSymbol(window,"FileReader")||FileReader;function getDataUrlFromFile(e){return new Promise(function(n,r){var t=new CustomFileReader;t.onload=function(){return n(t.result)},t.onerror=function(e){return r(e)},t.readAsDataURL(e)})}function getFilefromDataUrl(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Date.now();return new Promise(function(t){for(var a=e.split(","),i=a[0].match(/:(.*?);/)[1],o=atob(a[1]),s=o.length,c=new Uint8Array(s);s--;)c[s]=o.charCodeAt(s);var u=new Blob([c],{type:i});u.name=n,u.lastModified=r,t(u)})}function loadImage(e){return new Promise(function(n,r){var t=new Image;t.onload=function(){return n(t)},t.onerror=function(e){return r(e)},t.src=e})}function drawImageInCanvas(e){var n=_slicedToArray(getNewCanvasAndCtx(e.width,e.height),2),r=n[0];return n[1].drawImage(e,0,0,r.width,r.height),r}function drawFileInCanvas(e){return new Promise(function(n,r){var t,a,i=function $Try_1_Post(){try{return a=drawImageInCanvas(t),n([t,a])}catch(e){return r(e)}},o=function $Try_1_Catch(n){try{return getDataUrlFromFile(e).then(function(e){try{return loadImage(e).then(function(e){try{return t=e,i()}catch(e){return r(e)}},r)}catch(e){return r(e)}},r)}catch(e){return r(e)}};try{return createImageBitmap(e).then(function(e){try{return t=e,i()}catch(e){return o()}},o)}catch(e){o()}})}function canvasToFile(e,n,r,t){var a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;return new Promise(function(i,o){var s;return"function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas?e.convertToBlob({type:n,quality:a}).then(function(e){try{return(s=e).name=r,s.lastModified=t,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o):getFilefromDataUrl(e.toDataURL(n,a),r,t).then(function(e){try{return s=e,$If_4.call(this)}catch(e){return o(e)}}.bind(this),o);function $If_4(){return i(s)}})}function getExifOrientation(e){return new Promise(function(n,r){var t=new CustomFileReader;t.onload=function(e){var r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return n(-2);for(var t=r.byteLength,a=2;ai||a>i)){var s=_slicedToArray(getNewCanvasAndCtx(t,a),2);o=s[0],r=s[1],t>a?(o.width=i,o.height=a/t*i):(o.width=t/a*i,o.height=i),r.drawImage(e,0,0,o.width,o.height)}return o}function followExifOrientation(e,n){var r=e.width,t=e.height,a=_slicedToArray(getNewCanvasAndCtx(r,t),2),i=a[0],o=a[1];switch(4i){var n,r,u,m=_slicedToArray(getNewCanvasAndCtx(n=.9*s.width,r=.9*s.height),2);return u=m[0],m[1].drawImage(o,0,0,n,r),"image/jpeg"===e.type&&(c*=.9),canvasToFile(u,e.type,e.name,e.lastModified,c).then(function(e){try{return l=e,s=u,$Loop_3}catch(e){return t(e)}},t)}return[1]},g=function $Loop_3_exit(){return r(l)};return(u=n).size<=i?r(u):(l=u,(m=function(e){for(;e;){if(e.then)return void e.then(m,t);try{if(e.pop){if(e.length)return e.pop()?g.call(this):e;e=f}else e=e.call(this)}catch(e){return t(e)}}}.bind(this))(f))}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)}catch(e){return t(e)}}.bind(this),t)})}var n,r=0;var t=function createWorker(e){return new Worker(URL.createObjectURL(new Blob(["(".concat(e,")()")])))}(function(){var e=!1;self.addEventListener("message",function(n){return new Promise(function(r,t){var a,i,o,s,c=n.data;a=c.file,i=c.id,o=c.imageCompressionLibUrl,s=c.options;var u=function $Try_1_Post(){try{return r()}catch(e){return t(e)}},l=function $Try_1_Catch(e){try{return self.postMessage({error:e.message,id:i}),u()}catch(e){return t(e)}};try{var m;return e||(importScripts(o),e=!0),imageCompression(a,s).then(function(e){try{return m=e,self.postMessage({file:m,id:i}),u()}catch(e){return l(e)}},l)}catch(e){l(e)}})})});function compressOnWebWorker(e,a){return new Promise(function(i,o){return new Promise(function(s,c){n||(n=function createSourceObject(e){return URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}("\n function imageCompression (){return (".concat(imageCompression,").apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ").concat(imageCompression.getDataUrlFromFile,"\n imageCompression.getFilefromDataUrl = ").concat(imageCompression.getFilefromDataUrl,"\n imageCompression.loadImage = ").concat(imageCompression.loadImage,"\n imageCompression.drawImageInCanvas = ").concat(imageCompression.drawImageInCanvas,"\n imageCompression.drawFileInCanvas = ").concat(imageCompression.drawFileInCanvas,"\n imageCompression.canvasToFile = ").concat(imageCompression.canvasToFile,"\n imageCompression.getExifOrientation = ").concat(imageCompression.getExifOrientation,"\n imageCompression.handleMaxWidthOrHeight = ").concat(imageCompression.handleMaxWidthOrHeight,"\n imageCompression.followExifOrientation = ").concat(imageCompression.followExifOrientation,"\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ").concat(getNewCanvasAndCtx,"\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (").concat(compress,").apply(null, arguments)}\n ")));var u=r++;return t.addEventListener("message",function handler(e){e.data.id===u&&(t.removeEventListener("message",handler),e.data.error&&o(e.data.error),i(e.data.file))}),t.postMessage({file:e,id:u,imageCompressionLibUrl:n,options:a}),s()})})}function imageCompression(e,n){return new Promise(function(r,t){var a,i;if(n.maxSizeMB=n.maxSizeMB||Number.POSITIVE_INFINITY,n.useWebWorker="boolean"!=typeof n.useWebWorker||n.useWebWorker,!(e instanceof Blob||e instanceof CustomFile))return t(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return t(new Error("The file given is not an image"));if(i="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!n.useWebWorker||"function"!=typeof Worker||i)return compress(e,n).then(function(e){try{return a=e,$If_3.call(this)}catch(e){return t(e)}}.bind(this),t);var o=function(){try{return $If_3.call(this)}catch(e){return t(e)}}.bind(this),s=function $Try_1_Catch(r){try{return console.warn("Run compression in web worker failed:",r,", fall back to main thread"),compress(e,n).then(function(e){try{return a=e,o()}catch(e){return t(e)}},t)}catch(e){return t(e)}};try{return compressOnWebWorker(e,n).then(function(e){try{return a=e,o()}catch(e){return s(e)}},s)}catch(e){s(e)}function $If_3(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}return r(a)}})}imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation;export default imageCompression; //# sourceMappingURL=browser-image-compression.mjs.map diff --git a/dist/browser-image-compression.mjs.map b/dist/browser-image-compression.mjs.map index a52cafb..7f2574c 100644 --- a/dist/browser-image-compression.mjs.map +++ b/dist/browser-image-compression.mjs.map @@ -1 +1 @@ -{"version":3,"file":"browser-image-compression.mjs","sources":["../lib/utils.js","../lib/image-compression.js","../lib/web-worker.js","../lib/index.js"],"sourcesContent":["// add support for cordova-plugin-file\nconst moduleMapper = typeof window !== 'undefined' && window.cordova && window.cordova.require('cordova/modulemapper');\nexport const CustomFile = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'File')) || File;\nexport const CustomFileReader = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'FileReader')) || FileReader;\n/**\n * getDataUrlFromFile\n *\n * @param {File} file\n * @returns {Promise}\n */\nexport function getDataUrlFromFile (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = () => resolve(reader.result)\n reader.onerror = (e) => reject(e)\n reader.readAsDataURL(file)\n })\n}\n\n/**\n * getFilefromDataUrl\n *\n * @param {string} dataurl\n * @param {string} filename\n * @param {number} [lastModified=Date.now()]\n * @returns {Promise}\n */\nexport function getFilefromDataUrl (dataurl, filename, lastModified = Date.now()) {\n return new Promise((resolve) => {\n const arr = dataurl.split(',')\n const mime = arr[0].match(/:(.*?);/)[1]\n const bstr = atob(arr[1])\n let n = bstr.length\n const u8arr = new Uint8Array(n)\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n)\n }\n const file = new Blob([u8arr], { type: mime })\n file.name = filename\n file.lastModified = lastModified\n resolve(file)\n\n // Safari has issue with File constructor not being able to POST in FormData\n // https://github.com/Donaldcwl/browser-image-compression/issues/8\n // https://bugs.webkit.org/show_bug.cgi?id=165081\n // let file\n // try {\n // file = new File([u8arr], filename, { type: mime }) // Edge do not support File constructor\n // } catch (e) {\n // file = new Blob([u8arr], { type: mime })\n // file.name = filename\n // file.lastModified = lastModified\n // }\n // resolve(file)\n })\n}\n\n/**\n * loadImage\n *\n * @param {string} src\n * @returns {Promise}\n */\nexport function loadImage (src) {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = (e) => reject(e)\n img.src = src\n })\n}\n\n/**\n * drawImageInCanvas\n *\n * @param {HTMLImageElement} img\n * @returns {HTMLCanvasElement}\n */\nexport function drawImageInCanvas (img) {\n const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n return canvas\n}\n\n/**\n * drawFileInCanvas\n *\n * @param {File} file\n * @returns {Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>}\n */\nexport async function drawFileInCanvas (file) {\n let img\n try {\n img = await createImageBitmap(file)\n } catch (e) {\n const dataUrl = await getDataUrlFromFile(file)\n img = await loadImage(dataUrl)\n }\n const canvas = drawImageInCanvas(img)\n return [img, canvas]\n}\n\n/**\n * canvasToFile\n *\n * @param canvas\n * @param {string} fileType\n * @param {string} fileName\n * @param {number} fileLastModified\n * @param {number} [quality]\n * @returns {Promise}\n */\nexport async function canvasToFile (canvas, fileType, fileName, fileLastModified, quality = 1) {\n let file\n if (typeof OffscreenCanvas === 'function' && canvas instanceof OffscreenCanvas) {\n file = await canvas.convertToBlob({ type: fileType, quality })\n file.name = fileName\n file.lastModified = fileLastModified\n } else {\n const dataUrl = canvas.toDataURL(fileType, quality)\n file = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)\n }\n return file\n}\n\n/**\n * getExifOrientation\n * get image exif orientation info\n * source: https://stackoverflow.com/a/32490603/10395024\n *\n * @param {File} file\n * @returns {Promise} - orientation id, see https://i.stack.imgur.com/VGsAj.gif\n */\nexport function getExifOrientation (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = (e) => {\n const view = new DataView(e.target.result)\n if (view.getUint16(0, false) != 0xFFD8) {\n return resolve(-2)\n }\n const length = view.byteLength\n let offset = 2\n while (offset < length) {\n if (view.getUint16(offset + 2, false) <= 8) return resolve(-1)\n const marker = view.getUint16(offset, false)\n offset += 2\n if (marker == 0xFFE1) {\n if (view.getUint32(offset += 2, false) != 0x45786966) {\n return resolve(-1)\n }\n\n var little = view.getUint16(offset += 6, false) == 0x4949\n offset += view.getUint32(offset + 4, little)\n var tags = view.getUint16(offset, little)\n offset += 2\n for (var i = 0; i < tags; i++) {\n if (view.getUint16(offset + (i * 12), little) == 0x0112) {\n return resolve(view.getUint16(offset + (i * 12) + 8, little))\n }\n }\n } else if ((marker & 0xFF00) != 0xFF00) {\n break\n } else {\n offset += view.getUint16(offset, false)\n }\n }\n return resolve(-1)\n }\n reader.onerror = (e) => reject(e)\n reader.readAsArrayBuffer(file)\n })\n}\n\n/**\n *\n * @param {HTMLCanvasElement} canvas\n * @param options\n * @returns {HTMLCanvasElement>}\n */\nexport function handleMaxWidthOrHeight (canvas, options) {\n const width = canvas.width\n const height = canvas.height\n const maxWidthOrHeight = options.maxWidthOrHeight\n\n const needToHandle = Number.isInteger(maxWidthOrHeight) && (width > maxWidthOrHeight || height > maxWidthOrHeight)\n\n let newCanvas = canvas\n let ctx\n\n if (needToHandle) {\n [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n if (width > height) {\n newCanvas.width = maxWidthOrHeight\n newCanvas.height = (height / width) * maxWidthOrHeight\n } else {\n newCanvas.width = (width / height) * maxWidthOrHeight\n newCanvas.height = maxWidthOrHeight\n }\n ctx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height)\n }\n\n return newCanvas\n}\n\n/**\n * followExifOrientation\n * source: https://stackoverflow.com/a/40867559/10395024\n *\n * @param {HTMLCanvasElement} canvas\n * @param {number} exifOrientation\n * @returns {HTMLCanvasElement} canvas\n */\nexport function followExifOrientation (canvas, exifOrientation) {\n const width = canvas.width\n const height = canvas.height\n\n const [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n\n // set proper canvas dimensions before transform & export\n if (4 < exifOrientation && exifOrientation < 9) {\n newCanvas.width = height\n newCanvas.height = width\n } else {\n newCanvas.width = width\n newCanvas.height = height\n }\n\n // transform context before drawing image\n switch (exifOrientation) {\n case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;\n case 3: ctx.transform(-1, 0, 0, -1, width, height); break;\n case 4: ctx.transform(1, 0, 0, -1, 0, height); break;\n case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;\n case 6: ctx.transform(0, 1, -1, 0, height, 0); break;\n case 7: ctx.transform(0, -1, -1, 0, height, width); break;\n case 8: ctx.transform(0, -1, 1, 0, 0, width); break;\n default: break;\n }\n\n ctx.drawImage(canvas, 0, 0, width, height)\n\n return newCanvas\n}\n\n/**\n * get new Canvas and it's context\n * @param width\n * @param height\n * @returns {[HTMLCanvasElement, CanvasRenderingContext2D]}\n */\nexport function getNewCanvasAndCtx (width, height) {\n let canvas\n let ctx\n try {\n canvas = new OffscreenCanvas(width, height)\n ctx = canvas.getContext('2d')\n } catch (e) {\n canvas = document.createElement('canvas')\n ctx = canvas.getContext('2d')\n }\n canvas.width = width\n canvas.height = height\n return [canvas, ctx]\n}","import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nexport default async function compress (file, options) {\n let remainingTrials = options.maxIteration || 10\n\n const maxSizeByte = options.maxSizeMB * 1024 * 1024\n\n // drawFileInCanvas\n let [img, canvas] = await drawFileInCanvas(file)\n\n // handleMaxWidthOrHeight\n canvas = handleMaxWidthOrHeight(canvas, options)\n\n // exifOrientation\n options.exifOrientation = options.exifOrientation || await getExifOrientation(file)\n canvas = followExifOrientation(canvas, options.exifOrientation)\n\n let quality = 1\n\n let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)\n // check if we need to compress or resize\n if (tempFile.size <= maxSizeByte) {\n // no need to compress\n return tempFile\n }\n\n let compressedFile = tempFile\n while (remainingTrials-- && compressedFile.size > maxSizeByte) {\n const newWidth = canvas.width * 0.9\n const newHeight = canvas.height * 0.9\n const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)\n\n ctx.drawImage(img, 0, 0, newWidth, newHeight)\n\n if (file.type === 'image/jpeg') {\n quality *= 0.9\n }\n compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)\n\n canvas = newCanvas\n }\n\n return compressedFile\n}","import imageCompression from './index'\nimport compress from './image-compression'\nimport { getNewCanvasAndCtx } from './utils'\n\nlet cnt = 0\nlet imageCompressionLibUrl\n\nfunction createWorker (f) {\n return new Worker(URL.createObjectURL(new Blob([`(${f})()`])))\n}\n\nconst worker = createWorker(() => {\n let scriptImported = false\n self.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message, id })\n }\n })\n})\n\nfunction createSourceObject (str) {\n return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))\n}\n\nexport function compressOnWebWorker (file, options) {\n return new Promise(async (resolve, reject) => {\n if (!imageCompressionLibUrl) {\n imageCompressionLibUrl = createSourceObject(`\n function imageCompression (){return (${imageCompression}).apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}\n imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}\n imageCompression.loadImage = ${imageCompression.loadImage}\n imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}\n imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}\n imageCompression.canvasToFile = ${imageCompression.canvasToFile}\n imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}\n imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}\n imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ${getNewCanvasAndCtx}\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (${compress}).apply(null, arguments)}\n `)\n }\n let id = cnt++\n\n function handler (e) {\n if (e.data.id === id) {\n worker.removeEventListener('message', handler)\n if (e.data.error) {\n reject(e.data.error)\n }\n resolve(e.data.file)\n }\n }\n\n worker.addEventListener('message', handler)\n worker.postMessage({ file, id, imageCompressionLibUrl, options })\n })\n}","import compress from './image-compression'\nimport {\n canvasToFile,\n drawFileInCanvas,\n drawImageInCanvas,\n getDataUrlFromFile,\n getFilefromDataUrl,\n loadImage,\n getExifOrientation,\n handleMaxWidthOrHeight,\n followExifOrientation,\n CustomFile\n} from './utils'\nimport { compressOnWebWorker } from './web-worker'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {boolean} [options.useWebWorker=true]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nasync function imageCompression (file, options) {\n\n let compressedFile\n\n options.maxSizeMB = options.maxSizeMB || Number.POSITIVE_INFINITY\n options.useWebWorker = typeof options.useWebWorker === 'boolean' ? options.useWebWorker : true\n\n if (!(file instanceof Blob || file instanceof CustomFile)) {\n throw new Error('The file given is not an instance of Blob or File')\n } else if (!/^image/.test(file.type)) {\n throw new Error('The file given is not an image')\n }\n\n // try run in web worker, fall back to run in main thread\n const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n\n // if (inWebWorker) {\n // console.log('run compression in web worker')\n // } else {\n // console.log('run compression in main thread')\n // }\n\n if (options.useWebWorker && typeof Worker === 'function' && !inWebWorker) {\n try {\n // \"compressOnWebWorker\" is kind of like a recursion to call \"imageCompression\" again inside web worker\n compressedFile = await compressOnWebWorker(file, options)\n } catch (e) {\n console.warn('Run compression in web worker failed:', e, ', fall back to main thread')\n compressedFile = await compress(file, options)\n }\n } else {\n compressedFile = await compress(file, options)\n }\n\n try {\n compressedFile.name = file.name\n compressedFile.lastModified = file.lastModified\n } catch (e) {}\n\n return compressedFile\n}\n\nimageCompression.getDataUrlFromFile = getDataUrlFromFile\nimageCompression.getFilefromDataUrl = getFilefromDataUrl\nimageCompression.loadImage = loadImage\nimageCompression.drawImageInCanvas = drawImageInCanvas\nimageCompression.drawFileInCanvas = drawFileInCanvas\nimageCompression.canvasToFile = canvasToFile\nimageCompression.getExifOrientation = getExifOrientation\nimageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight\nimageCompression.followExifOrientation = followExifOrientation\n\nexport default imageCompression\n"],"names":["window","cordova","require","CustomFile","reader","onload","reject","file","getFilefromDataUrl","n","loadImage","fileType","view","result","length","offset","getUint32","marker","readAsArrayBuffer","width","height","canvas","options","ctx","maxWidthOrHeight","followExifOrientation","lastModified","cnt","compressOnWebWorker","name","imageCompression","drawImageInCanvas","drawFileInCanvas","canvasToFile","getExifOrientation","handleMaxWidthOrHeight"],"mappings":";;;;;;;sdAEA,kCAA2CA,gBAAAA,OAAAC,QAAAC,gCAC9BC,oLAyBXC,EAAAC,OAAA,oBAAgCD,wCACVE,sBACHC,cAUTC,0LAuBe,mCAGvBC,wnBA8CkBC,qcAOF,MAAAC,iYAmBdC,wBAAIC,yDAIJC,iBACO,uBAC8CC,EAAS,2CAC9B,oBAEhB,IACoB,wBAAvBA,GAAU,wDAMnBH,EAAAI,UAAWD,iCAEX,4GAMAE,gFASVb,EAAAc,kEAoBIC,IAAAA,MACAC,EAAIC,WACFC,kHASJC,mCAW6CC,YAE9BL,8BAMHE,EAAQ,wCAWNI,sBAAuBJ,mBACnCD,kKAOiCD,mQAiBvBE,0xBCvOmBd,SAAgBmB,kIAW3C,0HAQgBnB,kdCxCtB,MAAIoB,UAIJ,0nBASQC,4oGC6CWC,mHAMnBC,iBAAAtB,mBAAsCA,mBACtCsB,iBAAApB,oBACAoB,iBAAAC,oCACAD,iBAAAE,iBAAAA,iBACAF,iBAAAG,0BACAH,iBAAAI,sCACAJ,iBAAAK,8CACAL,iBAAAL,sBAAAA"} \ No newline at end of file +{"version":3,"file":"browser-image-compression.mjs","sources":["../lib/utils.js","../lib/image-compression.js","../lib/web-worker.js","../lib/index.js"],"sourcesContent":["// add support for cordova-plugin-file\nconst moduleMapper = typeof window !== 'undefined' && window.cordova && window.cordova.require('cordova/modulemapper');\nexport const CustomFile = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'File')) || File;\nexport const CustomFileReader = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'FileReader')) || FileReader;\n/**\n * getDataUrlFromFile\n *\n * @param {File} file\n * @returns {Promise}\n */\nexport function getDataUrlFromFile (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = () => resolve(reader.result)\n reader.onerror = (e) => reject(e)\n reader.readAsDataURL(file)\n })\n}\n\n/**\n * getFilefromDataUrl\n *\n * @param {string} dataurl\n * @param {string} filename\n * @param {number} [lastModified=Date.now()]\n * @returns {Promise}\n */\nexport function getFilefromDataUrl (dataurl, filename, lastModified = Date.now()) {\n return new Promise((resolve) => {\n const arr = dataurl.split(',')\n const mime = arr[0].match(/:(.*?);/)[1]\n const bstr = atob(arr[1])\n let n = bstr.length\n const u8arr = new Uint8Array(n)\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n)\n }\n const file = new Blob([u8arr], { type: mime })\n file.name = filename\n file.lastModified = lastModified\n resolve(file)\n\n // Safari has issue with File constructor not being able to POST in FormData\n // https://github.com/Donaldcwl/browser-image-compression/issues/8\n // https://bugs.webkit.org/show_bug.cgi?id=165081\n // let file\n // try {\n // file = new File([u8arr], filename, { type: mime }) // Edge do not support File constructor\n // } catch (e) {\n // file = new Blob([u8arr], { type: mime })\n // file.name = filename\n // file.lastModified = lastModified\n // }\n // resolve(file)\n })\n}\n\n/**\n * loadImage\n *\n * @param {string} src\n * @returns {Promise}\n */\nexport function loadImage (src) {\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.onload = () => resolve(img)\n img.onerror = (e) => reject(e)\n img.src = src\n })\n}\n\n/**\n * drawImageInCanvas\n *\n * @param {HTMLImageElement} img\n * @returns {HTMLCanvasElement}\n */\nexport function drawImageInCanvas (img) {\n const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n return canvas\n}\n\n/**\n * drawFileInCanvas\n *\n * @param {File} file\n * @returns {Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>}\n */\nexport async function drawFileInCanvas (file) {\n let img\n try {\n img = await createImageBitmap(file)\n } catch (e) {\n const dataUrl = await getDataUrlFromFile(file)\n img = await loadImage(dataUrl)\n }\n const canvas = drawImageInCanvas(img)\n return [img, canvas]\n}\n\n/**\n * canvasToFile\n *\n * @param canvas\n * @param {string} fileType\n * @param {string} fileName\n * @param {number} fileLastModified\n * @param {number} [quality]\n * @returns {Promise}\n */\nexport async function canvasToFile (canvas, fileType, fileName, fileLastModified, quality = 1) {\n let file\n if (typeof OffscreenCanvas === 'function' && canvas instanceof OffscreenCanvas) {\n file = await canvas.convertToBlob({ type: fileType, quality })\n file.name = fileName\n file.lastModified = fileLastModified\n } else {\n const dataUrl = canvas.toDataURL(fileType, quality)\n file = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)\n }\n return file\n}\n\n/**\n * getExifOrientation\n * get image exif orientation info\n * source: https://stackoverflow.com/a/32490603/10395024\n *\n * @param {File} file\n * @returns {Promise} - orientation id, see https://i.stack.imgur.com/VGsAj.gif\n */\nexport function getExifOrientation (file) {\n return new Promise((resolve, reject) => {\n const reader = new CustomFileReader()\n reader.onload = (e) => {\n const view = new DataView(e.target.result)\n if (view.getUint16(0, false) != 0xFFD8) {\n return resolve(-2)\n }\n const length = view.byteLength\n let offset = 2\n while (offset < length) {\n if (view.getUint16(offset + 2, false) <= 8) return resolve(-1)\n const marker = view.getUint16(offset, false)\n offset += 2\n if (marker == 0xFFE1) {\n if (view.getUint32(offset += 2, false) != 0x45786966) {\n return resolve(-1)\n }\n\n var little = view.getUint16(offset += 6, false) == 0x4949\n offset += view.getUint32(offset + 4, little)\n var tags = view.getUint16(offset, little)\n offset += 2\n for (var i = 0; i < tags; i++) {\n if (view.getUint16(offset + (i * 12), little) == 0x0112) {\n return resolve(view.getUint16(offset + (i * 12) + 8, little))\n }\n }\n } else if ((marker & 0xFF00) != 0xFF00) {\n break\n } else {\n offset += view.getUint16(offset, false)\n }\n }\n return resolve(-1)\n }\n reader.onerror = (e) => reject(e)\n reader.readAsArrayBuffer(file)\n })\n}\n\n/**\n *\n * @param {HTMLCanvasElement} canvas\n * @param options\n * @returns {HTMLCanvasElement>}\n */\nexport function handleMaxWidthOrHeight (canvas, options) {\n const width = canvas.width\n const height = canvas.height\n const maxWidthOrHeight = options.maxWidthOrHeight\n\n const needToHandle = Number.isInteger(maxWidthOrHeight) && (width > maxWidthOrHeight || height > maxWidthOrHeight)\n\n let newCanvas = canvas\n let ctx\n\n if (needToHandle) {\n [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n if (width > height) {\n newCanvas.width = maxWidthOrHeight\n newCanvas.height = (height / width) * maxWidthOrHeight\n } else {\n newCanvas.width = (width / height) * maxWidthOrHeight\n newCanvas.height = maxWidthOrHeight\n }\n ctx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height)\n }\n\n return newCanvas\n}\n\n/**\n * followExifOrientation\n * source: https://stackoverflow.com/a/40867559/10395024\n *\n * @param {HTMLCanvasElement} canvas\n * @param {number} exifOrientation\n * @returns {HTMLCanvasElement} canvas\n */\nexport function followExifOrientation (canvas, exifOrientation) {\n const width = canvas.width\n const height = canvas.height\n\n const [newCanvas, ctx] = getNewCanvasAndCtx(width, height)\n\n // set proper canvas dimensions before transform & export\n if (4 < exifOrientation && exifOrientation < 9) {\n newCanvas.width = height\n newCanvas.height = width\n } else {\n newCanvas.width = width\n newCanvas.height = height\n }\n\n // transform context before drawing image\n switch (exifOrientation) {\n case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;\n case 3: ctx.transform(-1, 0, 0, -1, width, height); break;\n case 4: ctx.transform(1, 0, 0, -1, 0, height); break;\n case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;\n case 6: ctx.transform(0, 1, -1, 0, height, 0); break;\n case 7: ctx.transform(0, -1, -1, 0, height, width); break;\n case 8: ctx.transform(0, -1, 1, 0, 0, width); break;\n default: break;\n }\n\n ctx.drawImage(canvas, 0, 0, width, height)\n\n return newCanvas\n}\n\n/**\n * get new Canvas and it's context\n * @param width\n * @param height\n * @returns {[HTMLCanvasElement, CanvasRenderingContext2D]}\n */\nexport function getNewCanvasAndCtx (width, height) {\n let canvas\n let ctx\n try {\n canvas = new OffscreenCanvas(width, height)\n ctx = canvas.getContext('2d')\n } catch (e) {\n canvas = document.createElement('canvas')\n ctx = canvas.getContext('2d')\n }\n canvas.width = width\n canvas.height = height\n return [canvas, ctx]\n}","import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nexport default async function compress (file, options) {\n let remainingTrials = options.maxIteration || 10\n\n const maxSizeByte = options.maxSizeMB * 1024 * 1024\n\n // drawFileInCanvas\n let [img, canvas] = await drawFileInCanvas(file)\n\n // handleMaxWidthOrHeight\n canvas = handleMaxWidthOrHeight(canvas, options)\n\n // exifOrientation\n options.exifOrientation = options.exifOrientation || await getExifOrientation(file)\n canvas = followExifOrientation(canvas, options.exifOrientation)\n\n let quality = 1\n\n let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)\n // check if we need to compress or resize\n if (tempFile.size <= maxSizeByte) {\n // no need to compress\n return tempFile\n }\n\n let compressedFile = tempFile\n while (remainingTrials-- && compressedFile.size > maxSizeByte) {\n const newWidth = canvas.width * 0.9\n const newHeight = canvas.height * 0.9\n const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)\n\n ctx.drawImage(img, 0, 0, newWidth, newHeight)\n\n if (file.type === 'image/jpeg') {\n quality *= 0.9\n }\n compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)\n\n canvas = newCanvas\n }\n\n return compressedFile\n}","import imageCompression from './index'\nimport compress from './image-compression'\nimport { getNewCanvasAndCtx } from './utils'\n\nlet cnt = 0\nlet imageCompressionLibUrl\n\nfunction createWorker (f) {\n return new Worker(URL.createObjectURL(new Blob([`(${f})()`])))\n}\n\nconst worker = createWorker(() => {\n let scriptImported = false\n self.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message, id })\n }\n })\n})\n\nfunction createSourceObject (str) {\n return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))\n}\n\nexport function compressOnWebWorker (file, options) {\n return new Promise(async (resolve, reject) => {\n if (!imageCompressionLibUrl) {\n imageCompressionLibUrl = createSourceObject(`\n function imageCompression (){return (${imageCompression}).apply(null, arguments)}\n\n imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}\n imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}\n imageCompression.loadImage = ${imageCompression.loadImage}\n imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}\n imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}\n imageCompression.canvasToFile = ${imageCompression.canvasToFile}\n imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}\n imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}\n imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}\n\n getDataUrlFromFile = imageCompression.getDataUrlFromFile\n getFilefromDataUrl = imageCompression.getFilefromDataUrl\n loadImage = imageCompression.loadImage\n drawImageInCanvas = imageCompression.drawImageInCanvas\n drawFileInCanvas = imageCompression.drawFileInCanvas\n canvasToFile = imageCompression.canvasToFile\n getExifOrientation = imageCompression.getExifOrientation\n handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight\n followExifOrientation = imageCompression.followExifOrientation\n\n getNewCanvasAndCtx = ${getNewCanvasAndCtx}\n \n CustomFileReader = FileReader\n \n CustomFile = File\n \n function _slicedToArray(arr, n) { return arr }\n\n function compress (){return (${compress}).apply(null, arguments)}\n `)\n }\n let id = cnt++\n\n function handler (e) {\n if (e.data.id === id) {\n worker.removeEventListener('message', handler)\n if (e.data.error) {\n reject(e.data.error)\n }\n resolve(e.data.file)\n }\n }\n\n worker.addEventListener('message', handler)\n worker.postMessage({ file, id, imageCompressionLibUrl, options })\n })\n}","import compress from './image-compression'\nimport {\n canvasToFile,\n drawFileInCanvas,\n drawImageInCanvas,\n getDataUrlFromFile,\n getFilefromDataUrl,\n loadImage,\n getExifOrientation,\n handleMaxWidthOrHeight,\n followExifOrientation,\n CustomFile\n} from './utils'\nimport { compressOnWebWorker } from './web-worker'\n\n/**\n * Compress an image file.\n *\n * @param {File} file\n * @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }\n * @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]\n * @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]\n * @param {boolean} [options.useWebWorker=true]\n * @param {number} [options.maxIteration=10]\n * @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file\n * @returns {Promise}\n */\nasync function imageCompression (file, options) {\n\n let compressedFile\n\n options.maxSizeMB = options.maxSizeMB || Number.POSITIVE_INFINITY\n options.useWebWorker = typeof options.useWebWorker === 'boolean' ? options.useWebWorker : true\n\n if (!(file instanceof Blob || file instanceof CustomFile)) {\n throw new Error('The file given is not an instance of Blob or File')\n } else if (!/^image/.test(file.type)) {\n throw new Error('The file given is not an image')\n }\n\n // try run in web worker, fall back to run in main thread\n const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n\n // if (inWebWorker) {\n // console.log('run compression in web worker')\n // } else {\n // console.log('run compression in main thread')\n // }\n\n if (options.useWebWorker && typeof Worker === 'function' && !inWebWorker) {\n try {\n // \"compressOnWebWorker\" is kind of like a recursion to call \"imageCompression\" again inside web worker\n compressedFile = await compressOnWebWorker(file, options)\n } catch (e) {\n console.warn('Run compression in web worker failed:', e, ', fall back to main thread')\n compressedFile = await compress(file, options)\n }\n } else {\n compressedFile = await compress(file, options)\n }\n\n try {\n compressedFile.name = file.name\n compressedFile.lastModified = file.lastModified\n } catch (e) {}\n\n return compressedFile\n}\n\nimageCompression.getDataUrlFromFile = getDataUrlFromFile\nimageCompression.getFilefromDataUrl = getFilefromDataUrl\nimageCompression.loadImage = loadImage\nimageCompression.drawImageInCanvas = drawImageInCanvas\nimageCompression.drawFileInCanvas = drawFileInCanvas\nimageCompression.canvasToFile = canvasToFile\nimageCompression.getExifOrientation = getExifOrientation\nimageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight\nimageCompression.followExifOrientation = followExifOrientation\n\nexport default imageCompression\n"],"names":["window","cordova","require","CustomFile","reader","onload","reject","file","getFilefromDataUrl","n","loadImage","fileType","view","result","length","offset","getUint32","marker","readAsArrayBuffer","width","height","canvas","options","ctx","maxWidthOrHeight","followExifOrientation","lastModified","cnt","compressOnWebWorker","name","imageCompression","drawImageInCanvas","drawFileInCanvas","canvasToFile","getExifOrientation","handleMaxWidthOrHeight"],"mappings":";;;;;;;sdAEA,kCAA2CA,gBAAAA,OAAAC,QAAAC,gCAC9BC,2NAyBXC,EAAAC,OAAA,oBAAgCD,wCACVE,sBACHC,cAUTC,0LAuBe,mCAGvBC,wnBA8CkBC,qcAOF,MAAAC,gZAmBdC,wBAAIC,yDAIJC,iBACO,uBAC8CC,EAAS,2CAC9B,oBAEhB,IACoB,wBAAvBA,GAAU,wDAMnBH,EAAAI,UAAWD,iCAEX,4GAMAE,gFASVb,EAAAc,kEAoBIC,IAAAA,MACAC,EAAIC,WACFC,kHASJC,mCAW6CC,YAE9BL,8BAMHE,EAAQ,wCAWNI,sBAAuBJ,mBACnCD,kKAOiCD,mQAiBvBE,0xBCvOmBd,SAAgBmB,kIAW3C,0HAQgBnB,kdCxCtB,MAAIoB,UAIJ,0nBASQC,qpGC6CWC,mHAMnBC,iBAAAtB,mBAAsCA,mBACtCsB,iBAAApB,oBACAoB,iBAAAC,oCACAD,iBAAAE,iBAAAA,iBACAF,iBAAAG,0BACAH,iBAAAI,sCACAJ,iBAAAK,8CACAL,iBAAAL,sBAAAA"} \ No newline at end of file diff --git a/example/basic.html b/example/basic.html index a2749b8..b5a3bad 100644 --- a/example/basic.html +++ b/example/basic.html @@ -76,6 +76,6 @@ }) } - + diff --git a/package.json b/package.json index 469e0ea..c39c127 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "browser-image-compression", - "version": "1.0.4", + "version": "1.0.5", "description": "Compress images in the browser", "main": "dist/browser-image-compression.js", "module": "dist/browser-image-compression.mjs", diff --git a/rollup.config.js b/rollup.config.js index f84adf6..9d2cb13 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,7 +9,10 @@ let external = Object.keys(pkg.dependencies) let plugins = [ nodent({ noRuntime: true, promises: true }), babel(), - terser({ keep_fnames: true }), + terser({ + keep_fnames: true, + mangle: { reserved: ['CustomFile', 'CustomFileReader'] } + }), license({ sourcemap: true, banner: '<%= _.startCase(pkg.name) %>\nv<%= pkg.version %>\nby <%= pkg.author %>\n<%= pkg.repository.url %>',