Skip to content

Commit 8f4e69f

Browse files
authored
Merge pull request #121 from Donaldcwl/dev
Dev v1.0.16
2 parents 5343922 + 8b97749 commit 8f4e69f

15 files changed

+892
-780
lines changed

.mocharc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module.exports = {
22
recursive: true,
3-
require: ['@babel/register', '@babel/polyfill', './test/setup_jsdom.js']
3+
require: ['@babel/register', '@babel/polyfill', './test/setup_global.js', './test/setup_jsdom.js']
44
}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## v1.0.16 (26 Sep 2021)
2+
* fixed: Fixed output white picture on iOS Safari for large image because of canvas max size [#116](https://github.com/Donaldcwl/browser-image-compression/issues/116)
3+
* fixed: Fixed wrong image orientation on iOS device [#118](https://github.com/Donaldcwl/browser-image-compression/issues/118)
4+
* feature: set white background for transparent png file with jpeg file extension [#119](https://github.com/Donaldcwl/browser-image-compression/issues/119)
5+
16
## v1.0.15 (12 Aug 2021)
27
* fixed: Fixed black Images and type error by considering Canvas maximum size supported by different browsers [#84](https://github.com/Donaldcwl/browser-image-compression/issues/84), [#36](https://github.com/Donaldcwl/browser-image-compression/issues/36)
38
* fixed: IE compatibility, include polyfill with core-js@3 e.g, globalThis, Promise [#108](https://github.com/Donaldcwl/browser-image-compression/issues/108), [#110](https://github.com/Donaldcwl/browser-image-compression/issues/110)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ So, we resize the image to less than the maximum size that each browser restrict
7878
imageCompression.getDataUrlFromFile(file: File): Promise<base64 encoded string>
7979
imageCompression.getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>
8080
imageCompression.loadImage(url: string): Promise<HTMLImageElement>
81-
imageCompression.drawImageInCanvas(img: HTMLImageElement): HTMLCanvasElement | OffscreenCanvas
81+
imageCompression.drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement | OffscreenCanvas
8282
imageCompression.drawFileInCanvas(file: File): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement | OffscreenCanvas]>
8383
imageCompression.canvasToFile(canvas: HTMLCanvasElement | OffscreenCanvas, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>
8484
imageCompression.getExifOrientation(file: File): Promise<number> // based on https://stackoverflow.com/a/32490603/10395024

example/basic.html

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,18 @@
7878
useWebWorker: useWebWorker,
7979
onProgress: onProgress
8080
}
81-
imageCompression(file, options).then(function (output) {
82-
logDom.innerHTML += ', output size:' + (output.size / 1024 / 1024).toFixed(2) + 'mb'
83-
console.log('output', output)
84-
const downloadLink = URL.createObjectURL(output)
85-
logDom.innerHTML += '&nbsp;<a href="' + downloadLink + '" download="' + file.name + '">download compressed image</a>'
86-
document.getElementById('preview-after-compress').src = downloadLink
87-
return uploadToServer(output)
88-
})
81+
imageCompression(file, options)
82+
.then(function (output) {
83+
logDom.innerHTML += ', output size:' + (output.size / 1024 / 1024).toFixed(2) + 'mb'
84+
console.log('output', output)
85+
const downloadLink = URL.createObjectURL(output)
86+
logDom.innerHTML += '&nbsp;<a href="' + downloadLink + '" download="' + file.name + '">download compressed image</a>'
87+
document.getElementById('preview-after-compress').src = downloadLink
88+
return uploadToServer(output)
89+
})
90+
.catch(function (error) {
91+
alert(error.message)
92+
})
8993

9094

9195
function onProgress (p) {

example/development.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@
8787
document.getElementById('preview-after-compress').src = downloadLink
8888
return uploadToServer(output)
8989
})
90+
.catch(function (error) {
91+
alert(error.message)
92+
})
9093

9194
function onProgress (p) {
9295
console.log('onProgress', p)

lib/config/max-canvas-size.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
1+
// see: https://github.com/jhildenbiddle/canvas-size#test-results
2+
// see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
23
export default {
34
chrome: 16384,
4-
firefox: 22528,
5-
safari: 16384,
5+
firefox: 11180,
6+
'desktop safari': 16384,
67
'internet explorer': 8192,
8+
'mobile safari': 4096,
79
etc: 8192,
810
};

lib/image-compression.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,17 @@ export default async function compress(file, options, previousProgress = 0) {
6969

7070
const origExceedMaxSize = tempFile.size > maxSizeByte;
7171
const sizeBecomeLarger = tempFile.size > file.size;
72-
// console.log('original file size', file.size)
73-
// console.log('current file size', tempFile.size)
72+
if (process.env.BUILD === 'development') {
73+
console.log('original file size', file.size);
74+
console.log('current file size', tempFile.size);
75+
}
7476

7577
// check if we need to compress or resize
7678
if (!origExceedMaxSize && !sizeBecomeLarger) {
7779
// no need to compress
80+
if (process.env.BUILD === 'development') {
81+
console.log('no need to compress');
82+
}
7883
setProgress(100);
7984
return tempFile;
8085
}
@@ -89,8 +94,10 @@ export default async function compress(file, options, previousProgress = 0) {
8994
while (remainingTrials-- && (currentSize > maxSizeByte || currentSize > sourceSize)) {
9095
const newWidth = origExceedMaxSize ? canvas.width * 0.95 : canvas.width;
9196
const newHeight = origExceedMaxSize ? canvas.height * 0.95 : canvas.height;
92-
// console.log('current width', newWidth);
93-
// console.log('current height', newHeight);
97+
if (process.env.BUILD === 'development') {
98+
console.log('current width', newWidth);
99+
console.log('current height', newHeight);
100+
}
94101
[newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight);
95102

96103
ctx.drawImage(canvas, 0, 0, newWidth, newHeight);

lib/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ declare namespace imageCompression {
2828
function getDataUrlFromFile(file: File): Promise<string>;
2929
function getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>;
3030
function loadImage(src: string): Promise<HTMLImageElement>;
31-
function drawImageInCanvas(img: HTMLImageElement): HTMLCanvasElement;
31+
function drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement;
3232
function drawFileInCanvas(file: File): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>;
3333
function canvasToFile(canvas: HTMLCanvasElement, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>;
3434
function getExifOrientation(file: File): Promise<number>;

lib/index.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
getBrowserName,
1919
} from './utils';
2020
// eslint-disable-next-line import/no-cycle
21-
import { compressOnWebWorker } from './web-worker';
21+
import compressOnWebWorker from './web-worker';
2222

2323
/**
2424
* Compress an image file.
@@ -61,18 +61,22 @@ async function imageCompression(file, options) {
6161
// eslint-disable-next-line no-undef, no-restricted-globals
6262
const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
6363

64-
// if ((useWebWorker && typeof Worker === 'function') || inWebWorker) {
65-
// console.log('run compression in web worker');
66-
// } else {
67-
// console.log('run compression in main thread');
68-
// }
64+
if (process.env.BUILD === 'development') {
65+
if ((useWebWorker && typeof Worker === 'function') || inWebWorker) {
66+
console.log('run compression in web worker');
67+
} else {
68+
console.log('run compression in main thread');
69+
}
70+
}
6971

7072
if (useWebWorker && typeof Worker === 'function' && !inWebWorker) {
7173
try {
7274
// "compressOnWebWorker" is kind of like a recursion to call "imageCompression" again inside web worker
7375
compressedFile = await compressOnWebWorker(file, opts);
7476
} catch (e) {
75-
// console.warn('Run compression in web worker failed:', e, ', fall back to main thread');
77+
if (process.env.BUILD === 'development') {
78+
console.warn('Run compression in web worker failed:', e, ', fall back to main thread');
79+
}
7680
compressedFile = await compress(file, opts);
7781
}
7882
} else {
@@ -82,8 +86,11 @@ async function imageCompression(file, options) {
8286
try {
8387
compressedFile.name = file.name;
8488
compressedFile.lastModified = file.lastModified;
85-
// eslint-disable-next-line no-empty
86-
} catch (e) {}
89+
} catch (e) {
90+
if (process.env.BUILD === 'development') {
91+
console.error(e);
92+
}
93+
}
8794

8895
return compressedFile;
8996
}
@@ -102,6 +109,6 @@ imageCompression.cleanupCanvasMemory = cleanupCanvasMemory;
102109
imageCompression.isAutoOrientationInBrowser = isAutoOrientationInBrowser;
103110
imageCompression.approximateBelowMaximumCanvasSizeOfBrowser = approximateBelowMaximumCanvasSizeOfBrowser;
104111
imageCompression.getBrowserName = getBrowserName;
105-
imageCompression.version = '1.0.15';
112+
imageCompression.version = __buildVersion__;
106113

107114
export default imageCompression;

lib/utils.js

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,17 @@ export function loadImage(src) {
8787
*/
8888
export function getBrowserName() {
8989
let browserName = 'etc';
90-
if (navigator.userAgent.indexOf('Chrome') !== -1 || navigator.userAgent.indexOf('Chromium') !== -1) {
90+
const { userAgent } = navigator;
91+
if (/Chrom(e|ium)/i.test(userAgent)) {
9192
browserName = 'chrome';
92-
} if (navigator.userAgent.indexOf('Safari') !== -1) {
93-
browserName = 'safari';
94-
} else if (navigator.userAgent.indexOf('Firefox') !== -1) {
93+
} else if (/iP(ad|od|hone)/i.test(userAgent) && /WebKit/i.test(userAgent) && !(/(CriOS|FxiOS|OPiOS|mercury)/i.test(userAgent))) {
94+
// see: https://stackoverflow.com/a/35813965
95+
browserName = 'mobile safari';
96+
} else if (/Safari/i.test(userAgent)) {
97+
browserName = 'desktop safari';
98+
} else if (/Firefox/i.test(userAgent)) {
9599
browserName = 'firefox';
96-
} else if ((navigator.userAgent.indexOf('MSIE') !== -1) || (!!document.documentMode === true)) { // IF IE > 10
100+
} else if (/MSIE/i.test(userAgent) || (!!document.documentMode) === true) { // IF IE > 10
97101
browserName = 'internet explorer';
98102
}
99103
return browserName;
@@ -104,8 +108,6 @@ export function getBrowserName() {
104108
*
105109
* it uses binary search to converge below the browser's maximum Canvas size.
106110
*
107-
* ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
108-
*
109111
* @param {number} initWidth
110112
* @param {number} initHeight
111113
* @returns {object}
@@ -168,15 +170,42 @@ export function getNewCanvasAndCtx(width, height) {
168170
* drawImageInCanvas
169171
*
170172
* @param {HTMLImageElement} img
173+
* @param {string} [fileType=undefined]
171174
* @returns {HTMLCanvasElement | OffscreenCanvas}
172175
*/
173-
export function drawImageInCanvas(img) {
176+
export function drawImageInCanvas(img, fileType = undefined) {
174177
const { width, height } = approximateBelowMaximumCanvasSizeOfBrowser(img.width, img.height);
175178
const [canvas, ctx] = getNewCanvasAndCtx(width, height);
179+
if (fileType && /jpe?g/.test(fileType)) {
180+
ctx.fillStyle = 'white'; // to fill the transparent background with white color for png file in jpeg extension
181+
ctx.fillRect(0, 0, canvas.width, canvas.height);
182+
}
176183
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
177184
return canvas;
178185
}
179186

187+
/**
188+
* Detect IOS device
189+
* see: https://stackoverflow.com/a/9039885
190+
* @returns {boolean} isIOS device
191+
*/
192+
export function isIOS() {
193+
if (isIOS.cachedResult !== undefined) {
194+
return isIOS.cachedResult;
195+
}
196+
isIOS.cachedResult = [
197+
'iPad Simulator',
198+
'iPhone Simulator',
199+
'iPod Simulator',
200+
'iPad',
201+
'iPhone',
202+
'iPod',
203+
].includes(navigator.platform)
204+
// iPad on iOS 13 detection
205+
|| (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
206+
return isIOS.cachedResult;
207+
}
208+
180209
/**
181210
* drawFileInCanvas
182211
*
@@ -186,12 +215,25 @@ export function drawImageInCanvas(img) {
186215
export async function drawFileInCanvas(file) {
187216
let img;
188217
try {
218+
if (isIOS()) {
219+
throw new Error('Skip createImageBitmap on IOS device'); // see https://github.com/Donaldcwl/browser-image-compression/issues/118
220+
}
189221
img = await createImageBitmap(file);
190222
} catch (e) {
191-
const dataUrl = await getDataUrlFromFile(file);
192-
img = await loadImage(dataUrl);
223+
if (process.env.BUILD === 'development') {
224+
console.error(e);
225+
}
226+
try {
227+
const dataUrl = await getDataUrlFromFile(file);
228+
img = await loadImage(dataUrl);
229+
} catch (e2) {
230+
if (process.env.BUILD === 'development') {
231+
console.error(e2);
232+
}
233+
throw e2;
234+
}
193235
}
194-
const canvas = drawImageInCanvas(img);
236+
const canvas = drawImageInCanvas(img, file.type);
195237
return [img, canvas];
196238
}
197239

0 commit comments

Comments
 (0)