File size: 2,122 Bytes
8539a00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
const CANVAS_SIZE = 200;
const PAD = 20;

function renderStroke(trajectory: [number, number][]): string {
  const canvas = document.createElement("canvas");
  canvas.width = CANVAS_SIZE;
  canvas.height = CANVAS_SIZE;
  const ctx = canvas.getContext("2d")!;

  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);

  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
  for (const [x, y] of trajectory) {
    if (x < minX) minX = x;
    if (y < minY) minY = y;
    if (x > maxX) maxX = x;
    if (y > maxY) maxY = y;
  }

  const drawArea = CANVAS_SIZE - 2 * PAD;
  const rangeX = Math.max(maxX - minX, 1);
  const rangeY = Math.max(maxY - minY, 1);
  const scale = Math.min(drawArea / rangeX, drawArea / rangeY);
  const offX = PAD + (drawArea - rangeX * scale) / 2;
  const offY = PAD + (drawArea - rangeY * scale) / 2;

  ctx.strokeStyle = "#000000";
  ctx.lineWidth = 5;
  ctx.lineCap = "round";
  ctx.lineJoin = "round";
  ctx.beginPath();
  const [x0, y0] = trajectory[0];
  ctx.moveTo((x0 - minX) * scale + offX, (y0 - minY) * scale + offY);
  for (let i = 1; i < trajectory.length; i++) {
    const [x, y] = trajectory[i];
    ctx.lineTo((x - minX) * scale + offX, (y - minY) * scale + offY);
  }
  ctx.stroke();

  return canvas.toDataURL("image/png").split(",")[1];
}

export async function recognizeInkStroke(
  trajectory: [number, number][]
): Promise<string> {
  if (trajectory.length < 5) return "";
  const base64 = renderStroke(trajectory);
  try {
    const res = await fetch("/ink/recognize", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ image_base64: base64 }),
    });
    if (!res.ok) {
      const body = await res.text().catch(() => "");
      console.error("[inkRecognizer] HTTP", res.status, body);
      return "";
    }
    const data = await res.json();
    const text = (data.text as string) || "";
    console.debug("[inkRecognizer] recognized:", JSON.stringify(text));
    return text;
  } catch (err) {
    console.error("[inkRecognizer] fetch failed:", err);
    return "";
  }
}