File size: 2,204 Bytes
7e3630c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import type { PixelData } from "./types.js";

export function renderBraille(pixels: PixelData): string {
  const { data, info } = pixels;
  const { width, height, channels } = info;

  let result = "";
  for (let y = 0; y < height - 3; y += 4) {
    for (let x = 0; x < width - 1; x += 2) {
      const dot1Index = (y * width + x) * channels;
      const dot2Index = ((y + 1) * width + x) * channels;
      const dot3Index = ((y + 2) * width + x) * channels;
      const dot4Index = (y * width + x + 1) * channels;
      const dot5Index = ((y + 1) * width + x + 1) * channels;
      const dot6Index = ((y + 2) * width + x + 1) * channels;
      const dot7Index = ((y + 3) * width + x) * channels;
      const dot8Index = ((y + 3) * width + x + 1) * channels;

      const getRgba = (index: number) => {
        const r = data[index] as number;
        const g = data[index + 1] as number;
        const b = data[index + 2] as number;
        const a = channels === 4 ? (data[index + 3] as number) : 1;
        return { r, g, b, a };
      };

      const dot1 = rgbaToBlackOrWhite(getRgba(dot1Index));
      const dot2 = rgbaToBlackOrWhite(getRgba(dot2Index));
      const dot3 = rgbaToBlackOrWhite(getRgba(dot3Index));
      const dot4 = rgbaToBlackOrWhite(getRgba(dot4Index));
      const dot5 = rgbaToBlackOrWhite(getRgba(dot5Index));
      const dot6 = rgbaToBlackOrWhite(getRgba(dot6Index));
      const dot7 = rgbaToBlackOrWhite(getRgba(dot7Index));
      const dot8 = rgbaToBlackOrWhite(getRgba(dot8Index));

      const brailleChar = String.fromCharCode(
        0x2800 +
          (dot8 << 7) +
          (dot7 << 6) +
          (dot6 << 5) +
          (dot5 << 4) +
          (dot4 << 3) +
          (dot3 << 2) +
          (dot2 << 1) +
          dot1,
      );
      result += brailleChar;
    }
    result += "\n";
  }

  return result.slice(0, -1);
}

function rgbaToBlackOrWhite({
  r,
  g,
  b,
  a,
}: {
  r: number;
  g: number;
  b: number;
  a: number;
}) {
  const alpha = a / 255;
  const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  const alphaAdjustedLuminance = luminance * alpha + 255 * (1 - alpha);

  if (alphaAdjustedLuminance > 128) {
    return 1;
  }
  return 0;
}