openpuzzle-captcha/module/gm.js
2025-12-28 15:54:54 +03:00

54 lines
1.3 KiB
JavaScript

const { spawn } = require("child_process");
// GM
async function callGM(params, stdin) {
const out = [];
const err = [];
return await new Promise((resolve, reject) => {
gm = spawn("gm", params);
gm.stdout.on("data", (c) => out.push(c));
gm.stderr.on("data", (c) => err.push(c));
gm.on("close", (code) => {
if (code !== 0) return reject(Buffer.concat(err).toString());
resolve(Buffer.concat(out));
});
gm.stdin.end(stdin);
});
}
const d = (dbg) => console.debug(dbg) || dbg;
class GMController {
async cropImage(buffer, x, y, offsetX = 0, offsetY = 0) {
return await callGM(
["convert", "-", "-crop", `${x}x${y}+${offsetX}+${offsetY}`, "png:-"],
buffer,
);
}
// For change hash-sum by insignificant changes in pixel colors
async repixelise(buffer) {
const noiseAmount = Math.random() * 1; // 0..1%
const brightness = (98 + Math.random() * 4).toFixed(2); // 98..102%
return await callGM(
["convert", "-", "-noise", ""+noiseAmount, "-modulate", brightness.toString(), "png:-"],
buffer,
);
}
async getSize (buffer) {
const [width, height] =(await callGM(
['identify', '-format', '%w %h', '-'],
buffer,
)).toString().split(/\s{1,}/g).map(s => +s);
return { width, height };
}
}
module.exports = new GMController();