Commit 5fa945b0 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement background blur on Safari.

Safari doesn't implement filtered drawing on HTML canvas,
it silently ignores the "filter" property of Context2D.
We implement our own blurring by scaling the background down
and then back up.
parent 590af61b
...@@ -1341,13 +1341,6 @@ let filters = { ...@@ -1341,13 +1341,6 @@ let filters = {
'background-blur': { 'background-blur': {
description: 'Background blur', description: 'Background blur',
predicate: async function() { predicate: async function() {
if(isSafari()) {
console.warn(
'Background blur does not work on Safari, disabled.'
);
return false;
}
let r = await fetch('/third-party/tasks-vision/vision_bundle.mjs', { let r = await fetch('/third-party/tasks-vision/vision_bundle.mjs', {
method: 'HEAD', method: 'HEAD',
}); });
...@@ -1399,21 +1392,48 @@ let filters = { ...@@ -1399,21 +1392,48 @@ let filters = {
// set the alpha mask, background is opaque // set the alpha mask, background is opaque
ctx.globalCompositeOperation = 'copy'; ctx.globalCompositeOperation = 'copy';
ctx.filter = 'none';
ctx.drawImage(mask, 0, 0); ctx.drawImage(mask, 0, 0);
// rather than blurring the original image, we first mask // rather than blurring the original image, we first mask
// the background then blur, this avoids a halo effect // the background then blur, this avoids a halo effect
ctx.globalCompositeOperation = 'source-in'; ctx.globalCompositeOperation = 'source-in';
ctx.filter = 'none';
ctx.drawImage(result.bitmap, 0, 0); ctx.drawImage(result.bitmap, 0, 0);
ctx.globalCompositeOperation = 'copy'; if('filter' in ctx) {
ctx.filter = `blur(${src.videoWidth / 48}px)`; ctx.globalCompositeOperation = 'copy';
ctx.drawImage(ctx.canvas, 0, 0); ctx.filter = `blur(${src.videoWidth / 48}px)`;
ctx.drawImage(ctx.canvas, 0, 0);
// now draw the foreground ctx.filter = 'none';
} else {
// Safari bug 198416, context.filter is not supported.
let scale = 24;
let swidth = src.videoWidth / scale;
let sheight = src.videoHeight / scale;
if(!('canvas' in this.userdata))
this.userdata.canvas = document.createElement('canvas');
let c2 = this.userdata.canvas;
if(c2.width != swidth)
c2.width = swidth;
if(c2.height != sheight)
c2.height = sheight;
let ctx2 = c2.getContext('2d');
// scale down the background
ctx2.globalCompositeOperation = 'copy';
ctx2.drawImage(ctx.canvas,
0, 0, src.videoWidth, src.videoHeight,
0, 0, swidth, sheight,
);
// scale back up, composite atop the original background
ctx.globalCompositeOperation = 'source-atop';
ctx.drawImage(ctx2.canvas,
0, 0,
src.videoWidth / scale,
src.videoHeight / scale,
0, 0, src.videoWidth, src.videoHeight,
);
}
// now draw the foreground
ctx.globalCompositeOperation = 'destination-atop'; ctx.globalCompositeOperation = 'destination-atop';
ctx.filter = 'none';
ctx.drawImage(result.bitmap, 0, 0); ctx.drawImage(result.bitmap, 0, 0);
ctx.globalCompositeOperation = 'source-over'; ctx.globalCompositeOperation = 'source-over';
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment