Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,6 @@ Network Trash Folder
Temporary Items
.apdisk

.idea/
.idea/
dist/
coverage/
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## v1.0.7 (15 Mar 2020)
* add onProgress function in options for compression progress updates
* allow fileType override
* fix garbage clean canvas for safari
* fix issue in Cordova support
* fix issue in IE browser
* fix other issues
* useWebWorker default set to false
* add ts type file

## v1.0.6 (5 July 2019)
* fixed: exif orientation do not work in some situations

Expand All @@ -18,4 +28,4 @@
* optimized: use of OffscreenCanvas when support, fallback to document.createElement('canvas')
* optimized: use createImageBitmap when support, fallback to FileReader readAsDataURL
* added: support web worker
* added: follows image exif orientation
* added: follows image exif orientation
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ const options = {
maxSizeMB: number, // (default: Number.POSITIVE_INFINITY)
maxWidthOrHeight: number, // compressedFile will scale down by ratio to a point that width or height is smaller than maxWidthOrHeight (default: undefined)
useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true)
maxIteration: number // optional, max number of iteration to compress the image (default: 10)
maxIteration: number, // optional, max number of iteration to compress the image (default: 10)
exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024
onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100)
fileType: string // optional, fileType override
}

imageCompression(file: File, options): Promise<File>
Expand Down
2 changes: 1 addition & 1 deletion coverage/badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions coverage/coverage-final.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions coverage/coverage-summary.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"total": {"lines":{"total":157,"covered":120,"skipped":0,"pct":76.43},"statements":{"total":171,"covered":122,"skipped":0,"pct":71.35},"functions":{"total":22,"covered":19,"skipped":0,"pct":86.36},"branches":{"total":73,"covered":40,"skipped":0,"pct":54.79}}
,"/Users/donald/Project/browser-image-compression/lib/image-compression.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":10,"covered":9,"skipped":0,"pct":90}}
,"/Users/donald/Project/browser-image-compression/lib/index.js": {"lines":{"total":26,"covered":22,"skipped":0,"pct":84.62},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":26,"covered":22,"skipped":0,"pct":84.62},"branches":{"total":17,"covered":12,"skipped":0,"pct":70.59}}
,"/Users/donald/Project/browser-image-compression/lib/utils.js": {"lines":{"total":110,"covered":77,"skipped":0,"pct":70},"functions":{"total":20,"covered":17,"skipped":0,"pct":85},"statements":{"total":124,"covered":79,"skipped":0,"pct":63.71},"branches":{"total":46,"covered":19,"skipped":0,"pct":41.3}}
{"total": {"lines":{"total":175,"covered":135,"skipped":0,"pct":77.14},"statements":{"total":189,"covered":137,"skipped":0,"pct":72.49},"functions":{"total":24,"covered":20,"skipped":0,"pct":83.33},"branches":{"total":87,"covered":46,"skipped":0,"pct":52.87}}
,"/Users/donald/Project/browser-image-compression/lib/image-compression.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.86}}
,"/Users/donald/Project/browser-image-compression/lib/index.js": {"lines":{"total":29,"covered":25,"skipped":0,"pct":86.21},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":29,"covered":25,"skipped":0,"pct":86.21},"branches":{"total":19,"covered":13,"skipped":0,"pct":68.42}}
,"/Users/donald/Project/browser-image-compression/lib/utils.js": {"lines":{"total":118,"covered":82,"skipped":0,"pct":69.49},"functions":{"total":22,"covered":18,"skipped":0,"pct":81.82},"statements":{"total":132,"covered":84,"skipped":0,"pct":63.64},"branches":{"total":54,"covered":20,"skipped":0,"pct":37.04}}
}
203 changes: 140 additions & 63 deletions coverage/image-compression.js.html
Original file line number Diff line number Diff line change
@@ -1,51 +1,62 @@

<!doctype html>
<html lang="en">

<head>
<title>Code coverage report for image-compression.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>

<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="index.html">All files</a> image-compression.js
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>21/21</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">90% </span>
<span class="quiet">Branches</span>
<span class='fraction'>9/10</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>21/21</span>
</div>
<div class='pad1'>
<h1><a href="index.html">All files</a> image-compression.js</h1>
<div class='clearfix'>

<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>28/28</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">92.86% </span>
<span class="quiet">Branches</span>
<span class='fraction'>13/14</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/1</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>28/28</span>
</div>


</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
</div>
<div class='status-line high'></div>
<pre><table class="coverage">
<div class='status-line high'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
Expand Down Expand Up @@ -100,7 +111,38 @@ <h1>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
Expand Down Expand Up @@ -138,6 +180,8 @@ <h1>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
Expand All @@ -152,19 +196,39 @@ <h1>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import {
canvasToFile,
cleanupMemory,
drawFileInCanvas,
followExifOrientation,
getExifOrientation,
getNewCanvasAndCtx,
handleMaxWidthOrHeight
} from './utils'
&nbsp;
/**
* Compress an image file.
*
* @param {File} file
* @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=true, maxIteration = 10, exifOrientation }
* @param {Object} options - { maxSizeMB=Number.POSITIVE_INFINITY, maxWidthOrHeight, useWebWorker=false, maxIteration = 10, exifOrientation, fileType }
* @param {number} [options.maxSizeMB=Number.POSITIVE_INFINITY]
* @param {number} [options.maxWidthOrHeight=undefined] * @param {number} [options.maxWidthOrHeight=undefined]
* @param {number} [options.maxWidthOrHeight=undefined]
* @param {number} [options.maxIteration=10]
* @param {number} [options.exifOrientation=] - default to be the exif orientation from the image file
* @param {number} [options.fileType=undefined] - default to be the original mime type from the image file
* @returns {Promise&lt;File | Blob&gt;}
*/
export default async function compress (file, options) {
Expand All @@ -173,59 +237,72 @@ <h1>
const maxSizeByte = options.maxSizeMB * 1024 * 1024
&nbsp;
// drawFileInCanvas
let [img, canvas] = await drawFileInCanvas(file)
let [img, origCanvas] = await drawFileInCanvas(file)
&nbsp;
// handleMaxWidthOrHeight
canvas = handleMaxWidthOrHeight(canvas, options)
const maxWidthOrHeightFixedCanvas = handleMaxWidthOrHeight(origCanvas, options)
&nbsp;
// exifOrientation
options.exifOrientation = options.exifOrientation || <span class="branch-1 cbranch-no" title="branch not covered" >await getExifOrientation(file)</span>
canvas = followExifOrientation(canvas, options.exifOrientation)
const orientationFixedCanvas = followExifOrientation(maxWidthOrHeightFixedCanvas, options.exifOrientation)
&nbsp;
let quality = 1
&nbsp;
let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)
let tempFile = await canvasToFile(orientationFixedCanvas, options.fileType || file.type, file.name, file.lastModified, quality)
// check if we need to compress or resize
if (tempFile.size &lt;= maxSizeByte) {
// no need to compress
return tempFile
}
&nbsp;
let compressedFile = tempFile
let newCanvas, ctx
let canvas = orientationFixedCanvas
while (remainingTrials-- &amp;&amp; compressedFile.size &gt; maxSizeByte) {
const newWidth = canvas.width * 0.9
const newHeight = canvas.height * 0.9
const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)
const newHeight = canvas.height * 0.9;
[newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)
&nbsp;
ctx.drawImage(canvas, 0, 0, newWidth, newHeight)
&nbsp;
if (file.type === 'image/jpeg') {
quality *= 0.9
}
compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)
compressedFile = await canvasToFile(newCanvas, options.fileType || file.type, file.name, file.lastModified, quality)
&nbsp;
cleanupMemory(canvas)
&nbsp;
canvas = newCanvas
}
&nbsp;
// garbage clean canvas for safari
// ref: https://bugs.webkit.org/show_bug.cgi?id=195325
cleanupMemory(canvas)
cleanupMemory(newCanvas)
cleanupMemory(maxWidthOrHeightFixedCanvas)
cleanupMemory(orientationFixedCanvas)
cleanupMemory(origCanvas)
&nbsp;
return compressedFile
}</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="https://istanbul.js.org/" target="_blank">istanbul</a> at Fri Jul 05 2019 12:39:02 GMT+0800 (Hong Kong Standard Time)
</div>
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
}
&nbsp;</pre></td></tr></table></pre>

<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Sun Mar 15 2020 02:33:08 GMT+0800 (Hong Kong Standard Time)
</div>
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>

Loading