import BackgroundFilterProcessor from '../backgroundfilter/BackgroundFilterProcessor' ; import BackgroundFilterSpec from '../backgroundfilter/BackgroundFilterSpec' ; import BackgroundBlurOptions from './BackgroundBlurOptions' ; import BackgroundBlurProcessor from './BackgroundBlurProcessor' ; import { BlurStrengthMapper } from './BackgroundBlurStrength' ; import BackgroundBlurVideoFrameProcessorDelegate from './BackgroundBlurVideoFrameProcessorDelegate' ; import BackgroundBlurVideoFrameProcessorObserver from './BackgroundBlurVideoFrameProcessorObserver' ; /**
 * [[BackgroundBlurProcessorProvided]] implements [[BackgroundBlurProcessor]].
 * It's a background blur processor and input is passed into a worker that will apply a segmentation
 * to separate the foreground from the background. Then the background will have a blur applied.
 *
 * The [[BackgroundBlurProcessorProvided]] uses WASM and TensorFlow Lite to apply the blurring of the
 * background image as apposed to [[BackgroundBlurProcessorBuiltIn]] that uses the browser's built-in
 * capability to apply the blur.
 */ internal export default class BackgroundBlurProcessorProvided extends BackgroundFilterProcessor implements BackgroundBlurProcessor { protected blurAmount = 0 ; protected _blurStrength : number ; protected validateOptions ( options ) { super . validateOptions ( options ) ; if ( ! options . blurStrength ) { throw new Error ( 'processor has null options - blurStrength' ) ; } } param spec param options constructor ( spec , options ) { super ( 'background blur' , spec , options , new BackgroundBlurVideoFrameProcessorDelegate ( ) ) ; this . setBlurStrength ( options . blurStrength ) ; this . logger . info ( 'BackgroundBlur processor successfully created' ) ; this . logger . info ( `BackgroundBlur spec: ${ this . stringify ( this . spec ) }` ) ; this . logger . info ( `BackgroundBlur options: ${ this . stringify ( options ) }` ) ; } initOnFirstExecution ( ) { this . setBlurPixels ( ) ; } drawImageWithMask ( inputCanvas , mask ) { if ( ! mask ) { mask = new ImageData ( this . spec . model . input . width , this . spec . model . input . height ) ; } const scaledCtx = this . scaledCanvas . getContext ( '2d' ) ; scaledCtx . putImageData ( mask , 0 , 0 ) ; const { canvasCtx , targetCanvas } = this ; const { width , height } = targetCanvas ; canvasCtx . save ( ) ; canvasCtx . clearRect ( 0 , 0 , width , height ) ; canvasCtx . drawImage ( this . scaledCanvas , 0 , 0 , width , height ) ; canvasCtx . globalCompositeOperation = 'source-in' ; canvasCtx . drawImage ( inputCanvas , 0 , 0 , width , height ) ; canvasCtx . globalCompositeOperation = 'destination-over' ; canvasCtx . filter = `blur(${ this . blurAmount }px)` ; canvasCtx . drawImage ( inputCanvas , 0 , 0 , targetCanvas . width , targetCanvas . height ) ; canvasCtx . restore ( ) ; } setBlurStrength ( blurStrength ) { this . _blurStrength = blurStrength ; this . logger . info ( `blur strength set to ${ this . _blurStrength }` ) ; this . setBlurPixels ( ) ; } /**
     * Calculate the blur amount based on the blur strength passed in and height of the image being blurred.
     */ setBlurPixels ( ) { this . blurAmount = BlurStrengthMapper . getBlurAmount ( this . _blurStrength , { height : this . sourceHeight , } ) ; this . logger . info ( `background blur amount set to ${ this . blurAmount }` ) ; } addObserver ( observer ) { this . delegate . addObserver ( observer ) ; } removeObserver ( observer ) { this . delegate . removeObserver ( observer ) ; } static async isSupported ( ) { const canvas = document . createElement ( 'canvas' ) ; const supportsBlurFilter = canvas . getContext ( '2d' ) . filter !== undefined ; canvas . remove ( ) ; return supportsBlurFilter ; } }