-
-
Save pseudosavant/a6d970b945ae85ef4dbc43200da94faf to your computer and use it in GitHub Desktop.
createImageBitmap polyfill with support for CanvasImageSource (img, video, canvas) sources, Blobs, and ImageData. https://createimagebitmap-polyfill.glitch.me/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Polyfill for createImageBitmap | |
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap | |
* | |
* Supports CanvasImageSource (img, video, canvas) sources, Blobs, and ImageData. | |
* | |
* From: | |
* - https://dev.to/nektro/createimagebitmap-polyfill-for-safari-and-edge-228 | |
* - https://gist.github.com/MonsieurV/fb640c29084c171b4444184858a91bc7 | |
* Updated by: | |
* - Yoan Tournade <[email protected]> | |
* - diachedelic, https://gist.github.com/diachedelic | |
* - Paul Ellis, https://pseudosavant.com | |
*/ | |
(function createImageBitmapIIFE(global){ | |
function isCanvasImageSource(el) { | |
const validElements = ['img', 'video', 'canvas']; | |
return (el && el.tagName && validElements.includes(el.tagName.toLowerCase())); | |
} | |
function idealSize(currentValue, newValue, numerator, denominator){ | |
if (typeof newValue === 'number') return newValue; | |
if (typeof numerator !== 'number' || typeof denominator !== 'number') return currentValue; | |
return (numerator / denominator) * currentValue; | |
} | |
if (!('createImageBitmap' in global) || test) { | |
global.createImageBitmap = async function polyfillCreateImageBitmap(data, opts) { | |
return new Promise((resolve, reject) => { | |
opts = opts || {}; | |
let dataURL; | |
const canvas = document.createElement('canvas'); | |
try { | |
const ctx = canvas.getContext('2d'); | |
if (data instanceof Blob) { | |
dataURL = URL.createObjectURL(data); | |
} else if (isCanvasImageSource(data)) { | |
const width = data.naturalWidth || data.videoWidth || data.clientWidth || data.width | |
const height = data.naturalHeight || data.videoHeight || data.clientHeight || data.height | |
canvas.width = idealSize(width, opts.resizeWidth, opts.resizeHeight, height); | |
canvas.height = idealSize(height, opts.resizeHeight, opts.resizeWidth, width); | |
ctx.drawImage(data, 0, 0, canvas.width, canvas.height); | |
dataURL = canvas.toDataURL(); | |
} else if (data instanceof ImageData) { | |
canvas.width = idealSize(data.width, opts.resizeWidth, opts.resizeHeight, data.height);; | |
canvas.height = idealSize(data.height, opts.resizeHeight, opts.resizeWidth, data.width); | |
ctx.putImageData(data,0,0); | |
dataURL = canvas.toDataURL(); | |
} else { | |
reject('createImageBitmap does not handle the provided image source type'); | |
} | |
const img = new Image(); | |
img.onerror = reject; | |
img.onload = () => resolve(img); | |
img.src = dataURL; | |
} finally { | |
// avoid memory leaks on iOS Safari, see https://stackoverflow.com/a/52586606 | |
canvas.width = 0; | |
canvas.height = 0; | |
} | |
}); | |
}; | |
} | |
})(this); |
Drop this into any page inline or put it in a separate script file. You can even use a service like Statically.io to use the gist as the script file (like this link). Then try to use window.createImageBitmap
as you normally would. createImageBitmap
is supported by every major browser but Safari now so it is really only useful there.
iOS Safari 12+ has a memory leak where, unless you set the width and height of a canvas to zero, it does not release the resources, fairly quickly crashing your page/webview if you are working with photos. I added that in a finally
clause:
...
const canvas = document.createElement("canvas");
try {
const ctx = canvas.getContext("2d");
...
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = dataURL;
} finally {
// avoid memory leaks on iOS Safari, see https://stackoverflow.com/a/52586606
canvas.width = 0;
canvas.height = 0;
}
Source: openlayers/openlayers#9291
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how do we use it exactly?