Files
Masterluke77andGitHub 6f48827f4d Vendoo 1.41.2 – Git Ignore Boundary & Module Tracking Hotfix (#18)
* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix

* fix: track native source modules with root-anchored runtime ignores
2026-07-09 17:09:00 +02:00

91 lines
2.8 KiB
JavaScript

import sharp from 'sharp';
import { join } from 'path';
import { UPLOADS_DIR } from './runtime-paths.mjs';
const uploadsDir = UPLOADS_DIR;
export async function prepareForAI(filenames, maxSize = 1024) {
const images = [];
for (const filename of filenames) {
const filepath = join(uploadsDir, filename);
const buffer = await sharp(filepath)
.resize(maxSize, maxSize, { fit: 'inside', withoutEnlargement: true })
.jpeg({ quality: 85 })
.toBuffer();
images.push({ base64: buffer.toString('base64'), mediaType: 'image/jpeg' });
}
return images;
}
export async function removeBackground(filename) {
const filepath = join(uploadsDir, filename);
const newName = filename.replace(/(\.\w+)$/, '_nobg.png');
const outPath = join(uploadsDir, newName);
const image = sharp(filepath);
const { width, height } = await image.metadata();
const { data, info } = await image
.ensureAlpha()
.raw()
.toBuffer({ resolveWithObject: true });
const corners = [
getPixel(data, 0, 0, info.width),
getPixel(data, info.width - 1, 0, info.width),
getPixel(data, 0, info.height - 1, info.width),
getPixel(data, info.width - 1, info.height - 1, info.width),
];
const bgColor = avgColor(corners);
const tolerance = 60;
const result = Buffer.from(data);
for (let i = 0; i < data.length; i += 4) {
const dr = Math.abs(data[i] - bgColor.r);
const dg = Math.abs(data[i + 1] - bgColor.g);
const db = Math.abs(data[i + 2] - bgColor.b);
if (dr + dg + db < tolerance * 3) {
result[i + 3] = 0;
}
}
await sharp(result, { raw: { width: info.width, height: info.height, channels: 4 } })
.png()
.toFile(outPath);
return newName;
}
function getPixel(data, x, y, width) {
const idx = (y * width + x) * 4;
return { r: data[idx], g: data[idx + 1], b: data[idx + 2] };
}
function avgColor(pixels) {
const sum = pixels.reduce((a, p) => ({ r: a.r + p.r, g: a.g + p.g, b: a.b + p.b }), { r: 0, g: 0, b: 0 });
const n = pixels.length;
return { r: Math.round(sum.r / n), g: Math.round(sum.g / n), b: Math.round(sum.b / n) };
}
export async function addWatermark(filename, text = 'Vendoo') {
const filepath = join(uploadsDir, filename);
const newName = filename.replace(/(\.\w+)$/, '_wm$1');
const outPath = join(uploadsDir, newName);
const image = sharp(filepath);
const { width, height } = await image.metadata();
const fontSize = Math.max(16, Math.round(width * 0.04));
const svg = `<svg width="${width}" height="${height}">
<style>.wm { fill: rgba(255,255,255,0.4); font-size: ${fontSize}px; font-family: sans-serif; font-weight: bold; }</style>
<text x="${width - 10}" y="${height - 10}" text-anchor="end" class="wm">${text}</text>
</svg>`;
await image
.composite([{ input: Buffer.from(svg), top: 0, left: 0 }])
.toFile(outPath);
return newName;
}