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.
This commit is contained in:
+30
-10
@@ -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 = {
|
|||||||
|
|
||||||
// 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);
|
||||||
|
if('filter' in ctx) {
|
||||||
ctx.globalCompositeOperation = 'copy';
|
ctx.globalCompositeOperation = 'copy';
|
||||||
ctx.filter = `blur(${src.videoWidth / 48}px)`;
|
ctx.filter = `blur(${src.videoWidth / 48}px)`;
|
||||||
ctx.drawImage(ctx.canvas, 0, 0);
|
ctx.drawImage(ctx.canvas, 0, 0);
|
||||||
|
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
|
// 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';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user