feat(api): generate qrcode based on static text

This commit is contained in:
Pihkaal
2024-09-29 19:05:50 +02:00
parent b2b4ebc0f1
commit c44709b68c
4 changed files with 2632 additions and 4990 deletions

View File

@@ -13,9 +13,14 @@
},
"dependencies": {
"@nuxt/eslint": "^0.5.7",
"canvas": "^2.11.2",
"nuxt": "^3.13.0",
"qrcode": "^1.5.4",
"vue": "latest",
"vue-router": "latest"
},
"packageManager": "pnpm@9.11.0"
"packageManager": "pnpm@9.11.0",
"devDependencies": {
"@types/qrcode": "^1.5.5"
}
}

7336
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/session.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

65
server/api/[name].ts Normal file
View File

@@ -0,0 +1,65 @@
import { createCanvas, loadImage } from "canvas";
import QRCode from "qrcode";
const time = (label: string) => {
const start = performance.now();
return () => {
console.log(label, "\t", performance.now() - start);
}
}
export default defineEventHandler(async (event) => {
// TODO: define logo based on name
const name = getRouterParam(event, "name");
name;
const text = "https://pihkaal.me"
event.node.res.setHeader("Content-Type", "text/plain");
const tt = time("total");
let t;
const SIZE = 1000;
const LOGO_PADDING = 1;
t = time("render");
const canvas = createCanvas(SIZE, SIZE);
await QRCode.toCanvas(canvas, text, { errorCorrectionLevel: 'H', width: SIZE, margin: 1 });
t();
t = time("count");
const qrCode = QRCode.create(text, { errorCorrectionLevel: 'H' });
const moduleCount = qrCode.modules.size + 2;
t();
t = time("logo");
const logo = await loadImage("http://localhost:3000/session.png");
const moduleSize = SIZE / moduleCount;
let logoModules = Math.floor(moduleCount * 0.3);
if (logoModules % 2 !== moduleCount % 2) {
logoModules += 1;
}
const backgroundSize = logoModules * moduleSize + 1;
const backgroundPosition = moduleSize * (moduleCount - logoModules) / 2;
const logoSize = backgroundSize - LOGO_PADDING * 2;
const logoPosition = backgroundPosition + LOGO_PADDING;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "white";
ctx.fillRect(backgroundPosition, backgroundPosition, backgroundSize, backgroundSize);
ctx.drawImage(logo, logoPosition, logoPosition, logoSize, logoSize);
t();
t = time("buffer");
const image = canvas.toBuffer();
t();
tt();
return image;
});