This commit is contained in:
freedakgmail
2025-11-22 23:49:24 +08:00
parent b83382b604
commit c033e46782
3580 changed files with 1745279 additions and 2428 deletions
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Donald Chan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,229 @@
# Browser Image Compression
[![npm](https://img.shields.io/npm/v/browser-image-compression.svg)](https://www.npmjs.com/package/browser-image-compression)
[![npm](./coverage/badge.svg)](https://github.com/Donaldcwl/browser-image-compression)
[![npm](https://img.shields.io/npm/l/browser-image-compression.svg)](https://github.com/Donaldcwl/browser-image-compression)
Javascript module to be run in the web browser for image compression.
## Features
- You can use this module to compress jpeg, png, webp, and bmp images by reducing **resolution** or **storage size** before uploading to the application server to save bandwidth.
- **Multi-thread** (web worker) non-blocking compression is supported through options.
## Demo / Example
open https://donaldcwl.github.io/browser-image-compression/example/basic.html
or check the "[example]" folder in this repo
## Usage
```html
<input type="file" accept="image/*" onchange="handleImageUpload(event);">
```
### async await syntax:
```javascript
async function handleImageUpload(event) {
const imageFile = event.target.files[0];
console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
const options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
}
try {
const compressedFile = await imageCompression(imageFile, options);
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); // true
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
await uploadToServer(compressedFile); // write your own logic
} catch (error) {
console.log(error);
}
}
```
### Promise.then().catch() syntax:
<details>
<summary>Click to expand</summary>
```javascript
function handleImageUpload(event) {
var imageFile = event.target.files[0];
console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
var options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true
}
imageCompression(imageFile, options)
.then(function (compressedFile) {
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); // true
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
return uploadToServer(compressedFile); // write your own logic
})
.catch(function (error) {
console.log(error.message);
});
}
```
</details>
## Installing
### Use as ES module:
You can install it via npm or yarn
```bash
npm install browser-image-compression --save
# or
yarn add browser-image-compression
```
```javascript
import imageCompression from 'browser-image-compression';
```
(can be used in frameworks like React, Angular, Vue etc)
(work with bundlers like webpack and rollup)
### (or) Load UMD js file:
You can download imageCompression from the [dist folder][dist].
Alternatively, you can use a CDN like [delivrjs]:
```html
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.1/dist/browser-image-compression.js"></script>
```
## Support
If this project helps you reduce the time to develop, you can buy me a cup of coffee :)
<a href="https://donaldcwl.github.io/donation/" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png" alt="Buy Me A Coffee" height=60 width=217 ></a>
(powered by Stripe)
## API
### Main function
```javascript
// you should provide one of maxSizeMB, maxWidthOrHeight in the options
const options: 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)
// but, automatically reduce the size to smaller than the maximum Canvas size supported by each browser.
// Please check the Caveat part for details.
onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100)
useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true)
libURL: string, // optional, the libURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js)
preserveExif: boolean, // optional, use preserve Exif metadata for JPEG image e.g., Camera model, Focal length, etc (default: false)
signal: AbortSignal, // optional, to abort / cancel the compression
// following options are for advanced users
maxIteration: number, // optional, max number of iteration to compress the image (default: 10)
exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024
fileType: string, // optional, fileType override e.g., 'image/jpeg', 'image/png' (default: file.type)
initialQuality: number, // optional, initial quality value between 0 and 1 (default: 1)
alwaysKeepResolution: boolean // optional, only reduce quality, always keep width and height (default: false)
}
imageCompression(file: File, options: Options): Promise<File>
```
#### Caveat
Each browser limits [the maximum size](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size) of a browser Canvas object. <br/>
So, we resize the image to less than the maximum size that each browser restricts. <br/>
(However, the `proportion/ratio` of the image remains.)
#### Abort / Cancel Compression
To use this feature, please check the browser compatibility: https://caniuse.com/?search=AbortController
```javascript
function handleImageUpload(event) {
var imageFile = event.target.files[0];
var controller = new AbortController();
var options = {
// other options here
signal: controller.signal,
}
imageCompression(imageFile, options)
.then(function (compressedFile) {
return uploadToServer(compressedFile); // write your own logic
})
.catch(function (error) {
console.log(error.message); // output: I just want to stop
});
// simulate abort the compression after 1.5 seconds
setTimeout(function () {
controller.abort(new Error('I just want to stop'));
}, 1500);
}
```
### Helper function
- for advanced users only, most users won't need to use the helper functions
```javascript
imageCompression.getDataUrlFromFile(file: File): Promise<base64 encoded string>
imageCompression.getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>
imageCompression.loadImage(url: string): Promise<HTMLImageElement>
imageCompression.drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement | OffscreenCanvas
imageCompression.drawFileInCanvas(file: File, options?: Options): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement | OffscreenCanvas]>
imageCompression.canvasToFile(canvas: HTMLCanvasElement | OffscreenCanvas, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>
imageCompression.getExifOrientation(file: File): Promise<number> // based on https://stackoverflow.com/a/32490603/10395024
imageCompression.copyExifWithoutOrientation(copyExifFromFile: File, copyExifToFile: File): Promise<File> // based on https://gist.github.com/tonytonyjan/ffb7cd0e82cb293b843ece7e79364233
```
## Browsers support
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Opera |
| --------- | --------- | --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions| last 2 versions
### IE support
This library uses ES features such as Promise API, globalThis. If you need to support browsers that do not support new ES features like IE. You can include the core-js polyfill in your project.
You can include the following script to load the core-js polyfill:
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.min.js"></script>
```
### Webp support
The webp compression is supported on major browsers. Please see https://caniuse.com/mdn-api_offscreencanvas_converttoblob_option_type_parameter_webp for browser compatibility.
## Remarks for compression to work in Web Worker
The browser needs to support "OffscreenCanvas" API in order to take advantage of non-blocking compression. If the browser does not support "OffscreenCanvas" API, the main thread is used instead. See https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#browser_compatibility for browser compatibility of "OffscreenCanvas" API.
## Typescript type definitions
Typescript definitions are included in the package & referenced in the `types` section of the `package.json`
## Remarks on Content Security Policy (CSP)
If your website has CSP enabled and you want to use Web Worker (useWebWorker: true), please add the following to the response header
`content-security-policy: script-src 'self' blob: https://cdn.jsdelivr.net`
- `blob:` is for loading Web Worker script
- `https://cdn.jsdelivr.net` is for importing this library from CDN inside Web Worker script. If you don't want to load this library from CDN, you can set your self hosted library URL in `options.libURL`.
## Contribution
1. fork the repo and git clone it
2. run `npm run watch` # it will watch code change in lib/ folder and generate js in dist/ folder
3. add/update code in lib/ folder
4. try the code by opening example/development.html which will load the js in dist/ folder
5. add/update test in test/ folder
6. `npm run test`
7. push to your forked repo on github
8. make a pull request to dev branch of this repo
[dist]: https://github.com/Donaldcwl/browser-image-compression/tree/master/dist
[example]: https://github.com/Donaldcwl/browser-image-compression/tree/master/example
[delivrjs]: https://cdn.jsdelivr.net/
@@ -0,0 +1,46 @@
// Type definitions for browser-image-compression 2.0
// Project: https://github.com/Donaldcwl/browser-image-compression
// Definitions by: Donald <https://github.com/Donaldcwl> & Jamie Haywood <https://github.com/jamiehaywood>
export interface Options {
/** @default Number.POSITIVE_INFINITY */
maxSizeMB?: number;
/** @default undefined */
maxWidthOrHeight?: number;
/** @default true */
useWebWorker?: boolean;
/** @default 10 */
maxIteration?: number;
/** Default to be the exif orientation from the image file */
exifOrientation?: number;
/** A function takes one progress argument (progress from 0 to 100) */
onProgress?: (progress: number) => void;
/** Default to be the original mime type from the image file */
fileType?: string;
/** @default 1.0 */
initialQuality?: number;
/** @default false */
alwaysKeepResolution?: boolean;
/** @default undefined */
signal?: AbortSignal;
/** @default false */
preserveExif?: boolean;
/** @default https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js */
libURL?: string;
}
declare function imageCompression(image: File, options: Options): Promise<File>;
declare namespace imageCompression {
function getDataUrlFromFile(file: File): Promise<string>;
function getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>;
function loadImage(src: string): Promise<HTMLImageElement>;
function drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement;
function drawFileInCanvas(file: File, options?: Options): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>;
function canvasToFile(canvas: HTMLCanvasElement, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>;
function getExifOrientation(file: File): Promise<number>;
}
export as namespace imageCompression;
export default imageCompression;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,79 @@
{
"name": "browser-image-compression",
"version": "2.0.2",
"description": "Compress images in the browser",
"main": "dist/browser-image-compression.js",
"module": "dist/browser-image-compression.mjs",
"jsnext:main": "dist/browser-image-compression.mjs",
"types": "dist/browser-image-compression.d.ts",
"scripts": {
"eslint": "eslint lib test --fix",
"build": "rollup -c --environment BUILD:production --bundleConfigAsCjs",
"watch": "rollup -c -w --environment BUILD:development --bundleConfigAsCjs",
"dev": "npm run watch",
"test": "cross-env NODE_ENV=test nyc mocha",
"posttest": "npm run coverage-badges",
"test:watch": "cross-env NODE_ENV=test nyc mocha -w",
"prepublishOnly": "npm test && npm run build",
"coverage-badges": "make-coverage-badge",
"commit": "cz"
},
"homepage": "https://github.com/Donaldcwl/browser-image-compression#readme",
"repository": {
"type": "git",
"url": "https://github.com/Donaldcwl/browser-image-compression"
},
"bugs": {
"url": "https://github.com/Donaldcwl/browser-image-compression/issues"
},
"keywords": [
"image compression",
"browser",
"image processing",
"reduce resolution",
"reduce size"
],
"author": "Donald <donaldcwl@gmail.com>",
"license": "MIT",
"files": [
"dist"
],
"dependencies": {
"uzip": "0.20201231.0"
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/polyfill": "^7.2.5",
"@babel/preset-env": "^7.3.1",
"@babel/register": "^7.0.0",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"babel-plugin-istanbul": "^6.0.0",
"canvas": "2.6.1",
"chai": "^4.1.0",
"chai-as-promised": "^7.1.1",
"cross-env": "^7.0.2",
"cz-conventional-changelog": "3.3.0",
"eslint": "^8.34.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.22.1",
"istanbul": "^0.4.5",
"jsdom": "^21.1.0",
"make-coverage-badge": "^1.0.1",
"mocha": "^10.2.0",
"nyc": "^15.0.1",
"rollup": "^3.15.0",
"rollup-plugin-copy": "^3.3.0",
"rollup-plugin-license": "^3.0.1",
"rollup-plugin-nodent": "^0.2.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-visualizer": "^5.6.0"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
+1
View File
@@ -0,0 +1 @@
../../uzip@0.20201231.0/node_modules/uzip