File size: 2,851 Bytes
e67f931
 
 
 
 
 
bdadca1
e67f931
 
 
 
 
 
bdadca1
e67f931
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import sharp from 'sharp';
import fs from 'fs';
import { tempPath, escapeXml } from './helpers.js';

// Accept positional args for compatibility with Bubble.js caller
export async function createTextBackgroundPng(text, fontSize=40, fontName='Arial', boxColor='#ffffff', boxBorderW=0, paddingX=20, paddingY=8, radius=10, fontColor='#000000'){
  // estimate size and create an SVG with rounded rect only (text is drawn by ffmpeg drawtext to ensure crisp font)
  const paddingXPx = Math.round(paddingX || 20);
  const paddingYPx = Math.round(paddingY || 8);
  const safeText = (text == null) ? '' : String(text);
  const estimatedWidth = Math.max(60, Math.round((fontSize || 40) * Math.max(1, safeText.length) * 0.6) + paddingXPx * 2);
  const estimatedHeight = Math.max(24, Math.round((fontSize || 40) * 1.4) + paddingYPx * 2);
  const rx = Math.max(0, Math.round(radius || 0));
  const svg = `<?xml version="1.0" encoding="utf-8"?>\n<svg xmlns='http://www.w3.org/2000/svg' width='${estimatedWidth}' height='${estimatedHeight}'>\n  <rect x='0' y='0' width='100%' height='100%' rx='${rx}' ry='${rx}' fill='${boxColor || '#ffffff'}' stroke='none' />\n</svg>`;
  const tmp = tempPath('text-bg','png');
  await sharp(Buffer.from(svg)).png().toFile(tmp);
  const meta = await sharp(tmp).metadata();
  return { path: tmp, width: meta.width, height: meta.height };
}

// Accept positional args for compatibility
export async function processImageWithBg(srcPath, width, height, backgroundColor=null, radius=0){
  const tmp = tempPath('img-out','png');
  const rx = Math.max(0, Math.round(radius || 0));
  let img = sharp(srcPath).resize(width, height, { fit: 'cover', position: 'centre' });
  const overlayBuf = await img.png().toBuffer();
  if (rx > 0) {
    const maskSvg = `<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"><rect x="0" y="0" rx="${rx}" ry="${rx}" width="${width}" height="${height}" fill="#fff"/></svg>`;
    const rounded = await sharp(overlayBuf).composite([{ input: Buffer.from(maskSvg), blend: 'dest-in' }]).png().toBuffer();
    if (backgroundColor) {
      const bg = sharp({ create: { width, height, channels: 4, background: backgroundColor } }).png();
      const out = tempPath('img-composite','png');
      await bg.composite([{ input: rounded, gravity: 'centre' }]).png().toFile(out);
      return out;
    }
    await sharp(rounded).png().toFile(tmp);
    return tmp;
  }

  if (backgroundColor) {
    const bg = sharp({ create: { width, height, channels: 4, background: backgroundColor } }).png();
    const out = tempPath('img-composite','png');
    await bg.composite([{ input: overlayBuf, gravity: 'centre' }]).png().toFile(out);
    return out;
  }

  await sharp(overlayBuf).png().toFile(tmp);
  return tmp;
}