Message: Fix Offscreen Canvas blur error after sending a message

This commit is contained in:
Alexander Zinchuk 2024-09-06 15:43:08 +02:00
parent 2c3b9ce7ad
commit e9c069d356
2 changed files with 17 additions and 8 deletions

View File

@ -8,29 +8,30 @@ const RADIUS = 7;
let lastWorkerIndex = -1;
export default function useOffscreenCanvasBlur(
dataUri?: string,
thumbData?: string, // data URI or blob URL
isDisabled = false,
radius = RADIUS,
) {
// eslint-disable-next-line no-null/no-null
const canvasRef = useRef<HTMLCanvasElement>(null);
const workerIndex = useMemo(() => cycleRestrict(MAX_WORKERS, ++lastWorkerIndex), []);
const offscreenRef = useRef<OffscreenCanvas>();
useLayoutEffect(() => {
if (!dataUri || isDisabled) return;
if (!thumbData || isDisabled || offscreenRef.current) return;
const canvas = canvasRef.current;
if (!canvas) return;
const offscreen = canvas.transferControlToOffscreen();
offscreenRef.current = canvas.transferControlToOffscreen();
const { connector } = launchMediaWorkers()[workerIndex];
connector.request({
name: 'blurThumb',
args: [offscreen, dataUri, radius],
transferables: [offscreen],
args: [offscreenRef.current, thumbData, radius],
transferables: [offscreenRef.current],
});
}, [dataUri, isDisabled, radius, workerIndex]);
}, [thumbData, isDisabled, radius, workerIndex]);
return canvasRef;
}

View File

@ -3,8 +3,10 @@ import fastBlur from '../fastBlur';
const FAST_BLUR_ITERATIONS = 2;
export async function blurThumb(canvas: OffscreenCanvas, dataUri: string, radius: number) {
const imageBitmap = await dataUriToImageBitmap(dataUri);
export async function blurThumb(canvas: OffscreenCanvas, thumbData: string, radius: number) {
const imageBitmap = thumbData.startsWith('data:')
? await dataUriToImageBitmap(thumbData)
: await blobUrlToImageBitmap(thumbData);
const { width, height } = canvas;
const ctx = canvas.getContext('2d')!;
const isFilterSupported = 'filter' in ctx;
@ -35,6 +37,12 @@ function dataUriToImageBitmap(dataUri: string) {
return createImageBitmap(blob);
}
async function blobUrlToImageBitmap(blobUrl: string) {
const response = await fetch(blobUrl);
const blob = await response.blob();
return createImageBitmap(blob);
}
const api = { blurThumb };
createWorkerInterface(api, 'media');