All files / src/components/world ColorizedImage.tsx

0% Statements 0/33
0% Branches 0/8
0% Functions 0/6
0% Lines 0/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                                                                                                                                                                 
import React, { useCallback, useEffect, useRef } from "react";
import { Palette } from "shared/lib/entities/entitiesTypes";
import ColorizedImageWorker, {
  ColorizedImageResult,
} from "./ColorizedImage.worker";
 
const workerPool: ColorizedImageWorker[] = [];
for (let i = 0; i < navigator.hardwareConcurrency; i++) {
  workerPool.push(new ColorizedImageWorker());
}
 
interface ColorizedImageProps {
  width: number;
  height: number;
  src: string;
  tiles: number[];
  palettes: Palette[];
  previewAsMono?: boolean;
}
 
const ColorizedImage = ({
  width,
  height,
  src,
  tiles,
  palettes,
  previewAsMono,
}: ColorizedImageProps) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const workerId = useRef(Math.random());
  const worker = useRef(
    workerPool[Math.floor(workerPool.length * Math.random())]
  );
 
  const onWorkerComplete = useCallback(
    (e: MessageEvent<ColorizedImageResult>) => {
      Iif (e.data.id === workerId.current) {
        const offscreenCanvas = document.createElement("canvas");
        const offscreenCtx = offscreenCanvas.getContext("bitmaprenderer");
        Iif (!canvasRef.current || !offscreenCtx) {
          return;
        }
        const ctx = canvasRef.current.getContext("2d");
        Iif (!ctx) {
          return;
        }
        offscreenCtx.transferFromImageBitmap(e.data.canvasImage);
        ctx.clearRect(0, 0, width, height);
        ctx.drawImage(offscreenCanvas, 0, 0);
      }
    },
    [height, width]
  );
 
  useEffect(() => {
    const theWorker = worker.current;
    theWorker.addEventListener("message", onWorkerComplete);
    return () => {
      theWorker.removeEventListener("message", onWorkerComplete);
    };
  }, [width, height, onWorkerComplete]);
 
  useEffect(() => {
    Iif (canvasRef.current && worker.current) {
      worker.current.postMessage({
        src,
        palettes: palettes.map((p) => p.colors),
        tiles,
        width,
        height,
        previewAsMono,
        id: workerId.current,
      });
    }
  }, [height, palettes, previewAsMono, src, tiles, width]);
 
  return <canvas ref={canvasRef} width={width} height={height} />;
};
 
export default ColorizedImage;