( inputPath: string, outPath?: string, bgColor: string = "#212338", borderPx: number = 14 )
| 116 | const meta = await sharp(inputPath).metadata(); |
| 117 | |
| 118 | // Choose an output path if not provided |
| 119 | const output = |
| 120 | outPath ?? |
| 121 | (() => { |
| 122 | const dir = path.dirname(inputPath); |
| 123 | const ext = |
| 124 | meta.format === "jpeg" || meta.format === "jpg" ? ".jpg" : ".png"; |
| 125 | const base = path.basename(inputPath, path.extname(inputPath)); |
| 126 | return path.join(dir, `${base}.filled${ext}`); |
| 127 | })(); |
| 128 | |
| 129 | const width = meta.width ?? 0; |
| 130 | const height = meta.height ?? 0; |
| 131 | if (!width || !height) { |
| 132 | throw new Error("Unable to read image dimensions"); |
| 133 | } |
| 134 | |
| 135 | // Clamp border so remaining area stays at least 1x1 |
| 136 | const maxInset = Math.floor((Math.min(width, height) - 1) / 2); |
| 137 | const inset = Math.max(0, Math.min(borderPx, maxInset)); |
| 138 | const cropW = width - inset * 2; |
| 139 | const cropH = height - inset * 2; |
| 140 | |
| 141 | // Background canvas with original dimensions |
| 142 | const background = sharp({ |
| 143 | create: { |
| 144 | width, |
| 145 | height, |
| 146 | channels: 4, |
| 147 | background: bgColor, |
| 148 | }, |
| 149 | }); |
| 150 | |
| 151 | // Inner cropped image (removes the outer border) |
| 152 | const innerBuf = await sharp(inputPath) |
| 153 | .extract({ left: inset, top: inset, width: cropW, height: cropH }) |
| 154 | .toBuffer(); |
| 155 | |
| 156 | // Center the inner image on the background |
| 157 | const left = Math.floor((width - cropW) / 2); |
| 158 | const top = Math.floor((height - cropH) / 2); |
| 159 | |
| 160 | let composed = background.composite([{ input: innerBuf, left, top }]); |
| 161 | |
| 162 | // Encode based on original format; default to PNG if unknown |
| 163 | if (meta.format === "jpeg" || meta.format === "jpg") { |
| 164 | composed = composed.jpeg({ quality: 95 }); |
| 165 | } else if (meta.format === "png" || !meta.format) { |
| 166 | composed = composed.png({ compressionLevel: 9 }); |
| 167 | } |
| 168 | |
| 169 | await composed.toFile(output); |
| 170 | return { output }; |
| 171 | } |
| 172 | function ensureDirectories(): void { |
| 173 | // createDirectoryInAssets already ensures directory exists |
| 174 | // No additional action needed |
| 175 | } |
no outgoing calls
no test coverage detected