/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ import type fastBlur from '../vendor/fastBlur'; import addHeavyTask from './heavyQueue'; import IS_CANVAS_FILTER_SUPPORTED from '../environment/canvasFilterSupport'; const RADIUS = 2; const ITERATIONS = 2; let requireBlurPromise: Promise; let fastBlurFunc: typeof fastBlur; if(!IS_CANVAS_FILTER_SUPPORTED) { requireBlurPromise = import('../vendor/fastBlur').then((m) => { fastBlurFunc = m.default; }); } else { requireBlurPromise = Promise.resolve(); } function processBlurNext( img: HTMLImageElement, radius: number, iterations: number, canvas: HTMLCanvasElement = document.createElement('canvas') ) { canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d', {alpha: false}); if(IS_CANVAS_FILTER_SUPPORTED) { ctx.filter = `blur(${radius}px)`; ctx.drawImage(img, -radius * 2, -radius * 2, canvas.width + radius * 4, canvas.height + radius * 4); } else { ctx.drawImage(img, 0, 0); fastBlurFunc(ctx, 0, 0, canvas.width, canvas.height, radius, iterations); } return canvas; } type CacheValue = {canvas: HTMLCanvasElement, promise: Promise}; const cache: Map = new Map(); const CACHE_SIZE = 150; export default function blur(dataUri: string, radius: number = RADIUS, iterations: number = ITERATIONS) { if(!dataUri) { throw 'no dataUri for blur: ' + dataUri; } if(cache.size > CACHE_SIZE) { cache.clear(); } const canvas = document.createElement('canvas'); canvas.className = 'canvas-thumbnail'; let cached = cache.get(dataUri); if(!cached) { const promise: CacheValue['promise'] = new Promise((resolve) => { // return resolve(dataUri); requireBlurPromise.then(() => { const img = new Image(); img.onload = () => { // if(IS_CANVAS_FILTER_SUPPORTED) { // resolve(processBlurNext(img, radius, iterations)); // } else { const promise = addHeavyTask({ items: [[img, radius, iterations, canvas]], context: null, process: processBlurNext }, 'unshift'); promise.then(() => { resolve(); }); // } }; img.src = dataUri; }); }); cache.set(dataUri, cached = { canvas, promise }); } else { canvas.width = cached.canvas.width; canvas.height = cached.canvas.height; cached.promise.then(() => { canvas.getContext('2d').drawImage(cached.canvas, 0, 0, canvas.width, canvas.height); }); } return { ...cached, canvas }; }