Skip to content

Commit 1f8739b

Browse files
committed
specify the maximum size of Canvas supported by each browser
1 parent b15f68c commit 1f8739b

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

lib/config/max-canvas-size.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
2+
export default {
3+
"chrome": 16384,
4+
"firefox": 22528,
5+
"safari": 16384,
6+
"internet explorer": 8192,
7+
"etc": 8192
8+
}

lib/utils.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import UPNG from './UPNG'
2+
import Bowser from "bowser";
3+
import MaxCanvasSize from './config/max-canvas-size'
24

35
const isBrowser = typeof window !== 'undefined' // change browser environment to support SSR
46

@@ -102,14 +104,54 @@ export function loadImage (src) {
102104
})
103105
}
104106

107+
/**
108+
* approximateBelowCanvasMaximumSizeOfBrowser
109+
*
110+
* it uses binary search to converge below the browser's maximum Canvas size.
111+
*
112+
* ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
113+
*
114+
* @param {number} initWidth
115+
* @param {number} initHeight
116+
* @returns {object}
117+
*/
118+
function approximateBelowMaximumCanvasSizeOfBrowser(initWidth, initHeight) {
119+
const browserName = getBrowserName()
120+
const maximumCanvasSize = MaxCanvasSize[browserName]
121+
122+
let width = initWidth;
123+
let height = initHeight
124+
let size = width * height
125+
const ratio = width > height ? height / width : width / height
126+
127+
while(size > maximumCanvasSize * maximumCanvasSize) {
128+
const halfSizeWidth = (maximumCanvasSize + width) / 2;
129+
const halfSizeHeight = (maximumCanvasSize + height) / 2;
130+
if(halfSizeWidth < halfSizeHeight) {
131+
height = halfSizeHeight
132+
width = halfSizeHeight * ratio
133+
} else {
134+
height = halfSizeWidth * ratio
135+
width = halfSizeWidth
136+
}
137+
138+
size = width * height
139+
}
140+
141+
return {
142+
width, height
143+
}
144+
}
145+
105146
/**
106147
* drawImageInCanvas
107148
*
108149
* @param {HTMLImageElement} img
109150
* @returns {HTMLCanvasElement | OffscreenCanvas}
110151
*/
111152
export function drawImageInCanvas (img) {
112-
const [canvas, ctx] = getNewCanvasAndCtx(img.width, img.height)
153+
const {width, height} = approximateBelowMaximumCanvasSizeOfBrowser(img.width, img.height)
154+
const [canvas, ctx] = getNewCanvasAndCtx(width, height)
113155
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
114156
return canvas
115157
}
@@ -350,3 +392,20 @@ if (isBrowser) {
350392
Math.floor(value) === value
351393
}
352394
}
395+
396+
/**
397+
* getBrowserName
398+
*
399+
* Extracts the browser name from the useragent.
400+
*
401+
* @returns {string}
402+
*/
403+
export function getBrowserName() {
404+
const browserName = Bowser.parse(globalThis.navigator.userAgent).browser.name || ''
405+
const lowerCasedBrowserName = browserName.toLowerCase()
406+
if(['chrome', 'safari', 'firefox'].includes(lowerCasedBrowserName)) {
407+
return lowerCasedBrowserName
408+
}
409+
410+
return 'etc'
411+
}

0 commit comments

Comments
 (0)