Skip to content

Commit 77682f7

Browse files
committed
code refactoring
1 parent a7528cf commit 77682f7

File tree

8 files changed

+127
-118
lines changed

8 files changed

+127
-118
lines changed

dist/browser-image-compression.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/browser-image-compression.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/browser-image-compression.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/browser-image-compression.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/image-compression.js

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight } from './utils'
1+
import { canvasToFile, drawFileInCanvas, followExifOrientation, getExifOrientation, handleMaxWidthOrHeight, getNewCanvasAndCtx } from './utils'
22

33
/**
44
* Compress an image file.
@@ -16,55 +16,39 @@ export default async function compress (file, options) {
1616

1717
const maxSizeByte = options.maxSizeMB * 1024 * 1024
1818

19-
// no need to compress or resize
20-
if (file.size <= maxSizeByte && typeof options.maxWidthOrHeight === 'undefined') {
21-
return file
22-
}
23-
24-
let img, canvas, isResized
25-
2619
// drawFileInCanvas
27-
let temp = await drawFileInCanvas(file)
28-
img = temp[0]
29-
canvas = temp[1]
20+
let [img, canvas] = await drawFileInCanvas(file)
3021

3122
// handleMaxWidthOrHeight
32-
let temp2 = handleMaxWidthOrHeight(img, canvas, options)
33-
canvas = temp2[0]
34-
isResized = temp2[1]
23+
canvas = handleMaxWidthOrHeight(canvas, options)
3524

3625
// exifOrientation
3726
options.exifOrientation = options.exifOrientation || await getExifOrientation(file)
38-
canvas = followExifOrientation(img, canvas, options.exifOrientation)
39-
40-
// no need to compress or resize
41-
if (file.size <= maxSizeByte && !isResized) {
42-
return file
43-
}
27+
canvas = followExifOrientation(canvas, options.exifOrientation)
4428

4529
let quality = 1
46-
let compressedFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)
47-
if (file.type === 'image/png') {
48-
while (remainingTrials-- && compressedFile.size > maxSizeByte) {
49-
canvas.width *= 0.9
50-
canvas.height *= 0.9
5130

52-
const ctx = canvas.getContext('2d')
53-
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
31+
let tempFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)
32+
// check if we need to compress or resize
33+
if (tempFile.size <= maxSizeByte) {
34+
// no need to compress
35+
return tempFile
36+
}
5437

55-
compressedFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)
56-
}
57-
} else { // if (file.type === 'image/jpeg') {
58-
while (remainingTrials-- && compressedFile.size > maxSizeByte) {
59-
canvas.width *= 0.9
60-
canvas.height *= 0.9
38+
let compressedFile = tempFile
39+
while (remainingTrials-- && compressedFile.size > maxSizeByte) {
40+
const newWidth = canvas.width * 0.9
41+
const newHeight = canvas.height * 0.9
42+
const [newCanvas, ctx] = getNewCanvasAndCtx(newWidth, newHeight)
6143

62-
const ctx = canvas.getContext('2d')
63-
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
44+
ctx.drawImage(img, 0, 0, newWidth, newHeight)
6445

46+
if (file.type === 'image/jpeg') {
6547
quality *= 0.9
66-
compressedFile = await canvasToFile(canvas, file.type, file.name, file.lastModified, quality)
6748
}
49+
compressedFile = await canvasToFile(newCanvas, file.type, file.name, file.lastModified, quality)
50+
51+
canvas = newCanvas
6852
}
6953

7054
return compressedFile

lib/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async function imageCompression (file, options) {
5252
// "compressOnWebWorker" is kind of like a recursion to call "imageCompression" again inside web worker
5353
compressedFile = await compressOnWebWorker(file, options)
5454
} catch (e) {
55-
// console.error('run compression in web worker failed', e)
55+
console.warn('Run compression in web worker failed:', e, ', fall back to main thread')
5656
compressedFile = await compress(file, options)
5757
}
5858
} else {

lib/utils.js

Lines changed: 57 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// add support for cordova-plugin-file
2-
const moduleMapper = window.cordova && window.cordova.require('cordova/modulemapper');
2+
const moduleMapper = typeof window !== 'undefined' && window.cordova && window.cordova.require('cordova/modulemapper');
33
export const CustomFile = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'File')) || File;
44
export const CustomFileReader = (moduleMapper && moduleMapper.getOriginalSymbol(window, 'FileReader')) || FileReader;
55
/**
@@ -77,17 +77,7 @@ export function loadImage (src) {
7777
* @returns {HTMLCanvasElement}
7878
*/
7979
export function drawImageInCanvas (img) {
80-
let canvas
81-
let ctx
82-
try {
83-
canvas = new OffscreenCanvas(img.width, img.height)
84-
ctx = canvas.getContext('2d')
85-
} catch (e) {
86-
canvas = document.createElement('canvas')
87-
ctx = canvas.getContext('2d')
88-
}
89-
canvas.width = img.width
90-
canvas.height = img.height
80+
const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)
9181
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
9282
return canvas
9383
}
@@ -121,16 +111,16 @@ export async function drawFileInCanvas (file) {
121111
* @returns {Promise<File|Blob>}
122112
*/
123113
export async function canvasToFile (canvas, fileType, fileName, fileLastModified, quality = 1) {
124-
let compressedFile
114+
let file
125115
if (typeof OffscreenCanvas === 'function' && canvas instanceof OffscreenCanvas) {
126-
compressedFile = await canvas.convertToBlob({ type: fileType, quality })
127-
compressedFile.name = fileName
128-
compressedFile.lastModified = fileLastModified
116+
file = await canvas.convertToBlob({ type: fileType, quality })
117+
file.name = fileName
118+
file.lastModified = fileLastModified
129119
} else {
130120
const dataUrl = canvas.toDataURL(fileType, quality)
131-
compressedFile = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)
121+
file = await getFilefromDataUrl(dataUrl, fileName, fileLastModified)
132122
}
133-
return compressedFile
123+
return file
134124
}
135125

136126
/**
@@ -184,55 +174,56 @@ export function getExifOrientation (file) {
184174

185175
/**
186176
*
187-
* @param img
188-
* @param canvas
177+
* @param {HTMLCanvasElement} canvas
189178
* @param options
190-
* @returns {Promise<[HTMLCanvasElement, boolean]>}
179+
* @returns {HTMLCanvasElement>}
191180
*/
192-
export function handleMaxWidthOrHeight (img, canvas, options) {
193-
const ctx = canvas.getContext('2d')
194-
181+
export function handleMaxWidthOrHeight (canvas, options) {
182+
const width = canvas.width
183+
const height = canvas.height
195184
const maxWidthOrHeight = options.maxWidthOrHeight
196-
const needToHandle = Number.isInteger(maxWidthOrHeight) && (img.width > maxWidthOrHeight || img.height > maxWidthOrHeight)
185+
186+
const needToHandle = Number.isInteger(maxWidthOrHeight) && (width > maxWidthOrHeight || height > maxWidthOrHeight)
187+
188+
let newCanvas = canvas
189+
let ctx
190+
197191
if (needToHandle) {
198-
if (img.width > img.height) {
199-
canvas.width = maxWidthOrHeight
200-
canvas.height = (img.height / img.width) * maxWidthOrHeight
192+
[newCanvas, ctx] = getNewCanvasAndCtx(width, height)
193+
if (width > height) {
194+
newCanvas.width = maxWidthOrHeight
195+
newCanvas.height = (height / width) * maxWidthOrHeight
201196
} else {
202-
canvas.width = (img.width / img.height) * maxWidthOrHeight
203-
canvas.height = maxWidthOrHeight
197+
newCanvas.width = (width / height) * maxWidthOrHeight
198+
newCanvas.height = maxWidthOrHeight
204199
}
205-
} else {
206-
canvas.width = img.width
207-
canvas.height = img.height
200+
ctx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height)
208201
}
209202

210-
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
211-
return [canvas, needToHandle]
203+
return newCanvas
212204
}
213205

214206
/**
215207
* followExifOrientation
216208
* source: https://stackoverflow.com/a/40867559/10395024
217209
*
218-
* @param {HTMLImageElement} img
219210
* @param {HTMLCanvasElement} canvas
220211
* @param {number} exifOrientation
221212
* @returns {HTMLCanvasElement} canvas
222213
*/
223-
export function followExifOrientation (img, canvas, exifOrientation) {
224-
const ctx = canvas.getContext('2d')
225-
214+
export function followExifOrientation (canvas, exifOrientation) {
226215
const width = canvas.width
227216
const height = canvas.height
228217

218+
const [newCanvas, ctx] = getNewCanvasAndCtx(width, height)
219+
229220
// set proper canvas dimensions before transform & export
230221
if (4 < exifOrientation && exifOrientation < 9) {
231-
canvas.width = height
232-
canvas.height = width
222+
newCanvas.width = height
223+
newCanvas.height = width
233224
} else {
234-
canvas.width = width
235-
canvas.height = height
225+
newCanvas.width = width
226+
newCanvas.height = height
236227
}
237228

238229
// transform context before drawing image
@@ -247,7 +238,28 @@ export function followExifOrientation (img, canvas, exifOrientation) {
247238
default: break;
248239
}
249240

250-
ctx.drawImage(img, 0, 0, width, height)
241+
ctx.drawImage(canvas, 0, 0, width, height)
251242

252-
return canvas
243+
return newCanvas
244+
}
245+
246+
/**
247+
* get new Canvas and it's context
248+
* @param width
249+
* @param height
250+
* @returns {[HTMLCanvasElement, CanvasRenderingContext2D]}
251+
*/
252+
export function getNewCanvasAndCtx (width, height) {
253+
let canvas
254+
let ctx
255+
try {
256+
canvas = new OffscreenCanvas(width, height)
257+
ctx = canvas.getContext('2d')
258+
} catch (e) {
259+
canvas = document.createElement('canvas')
260+
ctx = canvas.getContext('2d')
261+
}
262+
canvas.width = width
263+
canvas.height = height
264+
return [canvas, ctx]
253265
}

lib/web-worker.js

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import imageCompression from './index'
2-
import compress from './image-compression'
2+
// import compress from './image-compression'
3+
// import { getNewCanvasAndCtx } from './utils'
34

45
let cnt = 0
56
let imageCompressionLibUrl
@@ -9,11 +10,15 @@ function createWorker (f) {
910
}
1011

1112
const worker = createWorker(() => {
13+
let scriptImported = false
1214
self.addEventListener('message', async (e) => {
1315
const { file, id, imageCompressionLibUrl, options } = e.data
1416
try {
15-
// console.log('[worker] importScripts', imageCompressionLibUrl)
16-
importScripts(imageCompressionLibUrl)
17+
if (!scriptImported) {
18+
// console.log('[worker] importScripts', imageCompressionLibUrl)
19+
importScripts(imageCompressionLibUrl)
20+
scriptImported = true
21+
}
1722
// console.log('[worker] self', self)
1823
const compressedFile = await imageCompression(file, options)
1924
self.postMessage({ file: compressedFile, id })
@@ -24,40 +29,48 @@ const worker = createWorker(() => {
2429
})
2530
})
2631

27-
function createSourceObject (str) {
28-
return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))
29-
}
32+
// function createSourceObject (str) {
33+
// return URL.createObjectURL(new Blob([str], { type: 'application/javascript' }))
34+
// }
3035

3136
export function compressOnWebWorker (file, options) {
3237
return new Promise(async (resolve, reject) => {
3338
if (!imageCompressionLibUrl) {
34-
imageCompressionLibUrl = createSourceObject(`
35-
function imageCompression (){return (${imageCompression}).apply(null, arguments)}
36-
37-
imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}
38-
imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}
39-
imageCompression.loadImage = ${imageCompression.loadImage}
40-
imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}
41-
imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}
42-
imageCompression.canvasToFile = ${imageCompression.canvasToFile}
43-
imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}
44-
imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}
45-
imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}
46-
47-
getDataUrlFromFile = imageCompression.getDataUrlFromFile
48-
getFilefromDataUrl = imageCompression.getFilefromDataUrl
49-
loadImage = imageCompression.loadImage
50-
drawImageInCanvas = imageCompression.drawImageInCanvas
51-
drawFileInCanvas = imageCompression.drawFileInCanvas
52-
canvasToFile = imageCompression.canvasToFile
53-
getExifOrientation = imageCompression.getExifOrientation
54-
handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight
55-
followExifOrientation = imageCompression.followExifOrientation
56-
57-
function compress (){return (${compress}).apply(null, arguments)}
58-
`)
59-
// imageCompressionLibUrl = new URL('../dist/browser-image-compression.js', window.location.href).href
39+
if (typeof document !== 'undefined' && 'currentScript' in document) {
40+
imageCompressionLibUrl = document.currentScript.src
41+
} else {
42+
return reject(new Error('Cannot obtain library url to be loaded in web worker'))
43+
}
6044
}
45+
// if (!imageCompressionLibUrl) {
46+
// imageCompressionLibUrl = createSourceObject(`
47+
// function imageCompression (){return (${imageCompression}).apply(null, arguments)}
48+
//
49+
// imageCompression.getDataUrlFromFile = ${imageCompression.getDataUrlFromFile}
50+
// imageCompression.getFilefromDataUrl = ${imageCompression.getFilefromDataUrl}
51+
// imageCompression.loadImage = ${imageCompression.loadImage}
52+
// imageCompression.drawImageInCanvas = ${imageCompression.drawImageInCanvas}
53+
// imageCompression.drawFileInCanvas = ${imageCompression.drawFileInCanvas}
54+
// imageCompression.canvasToFile = ${imageCompression.canvasToFile}
55+
// imageCompression.getExifOrientation = ${imageCompression.getExifOrientation}
56+
// imageCompression.handleMaxWidthOrHeight = ${imageCompression.handleMaxWidthOrHeight}
57+
// imageCompression.followExifOrientation = ${imageCompression.followExifOrientation}
58+
//
59+
// getDataUrlFromFile = imageCompression.getDataUrlFromFile
60+
// getFilefromDataUrl = imageCompression.getFilefromDataUrl
61+
// loadImage = imageCompression.loadImage
62+
// drawImageInCanvas = imageCompression.drawImageInCanvas
63+
// drawFileInCanvas = imageCompression.drawFileInCanvas
64+
// canvasToFile = imageCompression.canvasToFile
65+
// getExifOrientation = imageCompression.getExifOrientation
66+
// handleMaxWidthOrHeight = imageCompression.handleMaxWidthOrHeight
67+
// followExifOrientation = imageCompression.followExifOrientation
68+
//
69+
// getNewCanvasAndCtx = ${getNewCanvasAndCtx}
70+
//
71+
// function compress (){return (${compress}).apply(null, arguments)}
72+
// `)
73+
// }
6174
let id = cnt++
6275

6376
function handler (e) {

0 commit comments

Comments
 (0)