aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/test/canvas/CanvasImg.svelte
blob: ef9c870c5d41a88d493c9fd3e38a71f510419576 (plain) (blame)
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
<script lang="ts">
  import { onDestroy } from 'svelte';
  import { detect2dCanvasBlockOnCanvas } from './detect-canvas-block';

  let { src, alt }: { src: string; alt: string } = $props();
  let blobUrl = $state(undefined as undefined | string);

  const blobify = async (image: HTMLImageElement) => {
    if (!image.src.startsWith('blob:')) {
      const canvas = document.createElement('canvas');
      if (blobUrl) URL.revokeObjectURL(blobUrl);
      const canvasOpts = {
        desynchronized: true,
        alpha: true,
        willReadFrequently: false,
        // change to unorm8 to use 8-bit colours (will break HDR images)
        colorType: 'float16' as const,
        // change to srgb if colours look off
        colorSpace: 'display-p3' as const,
      } as const;
      const e = detect2dCanvasBlockOnCanvas(canvas, false, canvasOpts);
      if (e) throw e;
      try {
        // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight
        const cw = (canvas.width = image.naturalWidth);
        const ch = (canvas.height = image.naturalHeight);

        const ctx = canvas.getContext('2d', canvasOpts)!;
        ctx.drawImage(image, 0, 0, cw, ch);

        blobUrl = URL.createObjectURL(
          await new Promise<Blob>((rs, rj) =>
            canvas.toBlob((value) =>
              value ? rs(value) : rj(new Error('No blob')),
            ),
          ),
        );
      } catch (error) {
        console.error('Failed to get canvas data:', error);
      }
    }
  };

  onDestroy(() => {
    if (blobUrl) URL.revokeObjectURL(blobUrl);
  });
</script>

<img
  class="pointer-events-none"
  loading="lazy"
  src={blobUrl ?? src}
  {alt}
  onload={(e) =>
    blobify((e.currentTarget ?? e.target) as unknown as HTMLImageElement)}
/>