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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| const sharp = require('sharp'); const fs = require('fs'); const path = require('path');
function getImgFiles(dir: string): string[] { const filterImg = [".png", ".jpg", ".jpeg", ".bmp"] const files = fs.readdirSync(dir); return files .filter((file: string) => filterImg.indexOf(path.extname(file).toLowerCase()) > -1) .map((file: string) => path.resolve(dir, file)); }
async function getImageSize(filePath: String) { try { const metadata = await sharp(filePath).metadata(); return { width: metadata.width, height: metadata.height, format: metadata.format, }; } catch (err) { return null; } }
function fileExists(filePath: string) { try { fs.accessSync(filePath); return true; } catch (err) { return false; } }
async function mergeImagesInDir(dir: string) { let files = getImgFiles(dir); if (files.length == 0) { return "" } let sizeArr = [] let maxWidth = 0; let maxHeight = 0; for (let i = 0; i < files.length; i++) { let filePath = files[i]; let imgSize = await getImageSize(filePath); if (imgSize != null) { if (imgSize.width > maxWidth) { maxWidth = imgSize.width; } if (imgSize.height > maxHeight) { maxHeight = imgSize.height; }
sizeArr.push(imgSize) } } maxWidth = parseInt(maxWidth + "") maxHeight = parseInt(maxHeight + "")
if (sizeArr.length != files.length) { return ""; }
let cols = Math.ceil(Math.sqrt(files.length)) if (files.length <= 8) { cols = files.length } let rows = parseInt(Math.ceil(files.length / cols) + "") let totalWidth = maxWidth * cols; let totalHeight = maxHeight * rows; let outputDir = path.join(dir, '_z_merge'); if (!fileExists(outputDir)) { fs.mkdirSync(outputDir); } let outputPath = path.join(outputDir, 'z_merge_output.png'); try { if (fileExists(outputPath)) { fs.unlinkSync(outputPath); } } catch (e) { return "" }
const canvas = sharp({ create: { width: totalWidth, height: totalHeight, channels: 4, background: {r: 0, g: 0, b: 0, alpha: 0} } });
const overlays = []; for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { let currIndex = i * cols + j; if (currIndex < files.length) { let filePath = files[currIndex]; let imgSize = sizeArr[currIndex]; let x = j * maxWidth; let y = i * maxHeight; let left = parseInt((x + (maxWidth - imgSize.width) / 2) + "") overlays.push({ input: filePath, left: left, top: y + (maxHeight - imgSize.height), }); } } }
await canvas .composite(overlays) .png() .toFile(outputPath); return outputPath; }
export {getImgFiles, getImageSize, mergeImagesInDir}
|