Created
March 23, 2025 02:33
-
-
Save motebaya/b44ce5b65ca1d950827ebe694e59c879 to your computer and use it in GitHub Desktop.
merge image using sharp JS : https://github.com/lovell/sharp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/node | |
/** | |
* @github.com/motebaya | |
* 2024-02-16 03:28:08.599531900 +0700 | |
*/ | |
import sharp from "sharp"; | |
async function mergePanel(imageslist, output) { | |
return new Promise(async (resolve) => { | |
try { | |
console.log(` starting merge ${imageslist.length} images to ${output}`); | |
const start_time = Date.now(); | |
const firstImageMetadata = await sharp(imageslist[0]).metadata(); | |
const width = firstImageMetadata.width; | |
let imagesBuffer = await Promise.all( | |
imageslist.map((file) => sharp(file).resize({ width }).toBuffer()) | |
); | |
let totalHeight = 0; | |
for (let file of imageslist) { | |
const metadata = await sharp(file).metadata(); | |
totalHeight += metadata.height; | |
} | |
let compositeArray = []; | |
let currentHeight = 0; | |
for (let i = 0; i < imagesBuffer.length; i++) { | |
const metadata = await sharp(imageslist[i]).metadata(); | |
compositeArray.push({ | |
input: imagesBuffer[i], | |
top: currentHeight, | |
left: 0, | |
}); | |
currentHeight += metadata.height; | |
} | |
await sharp({ | |
create: { | |
width: width, | |
height: totalHeight, | |
channels: 4, | |
background: { r: 0, g: 0, b: 0, alpha: 0 }, // #FFFFFF | |
}, | |
}) | |
.composite(compositeArray) | |
.toFormat("png") | |
.toFile(output); | |
console.log(` merged ${imageslist.length} images into ${output}`); | |
console.log( | |
` completed in: ${((Date.now() - start_time) / 1000).toFixed( | |
2 | |
)} seconds` | |
); | |
resolve(); | |
} catch (err) { | |
console.error("Error merging images:", err); | |
resolve(); | |
} | |
}); | |
} | |
/** | |
* honestly, i often use this to merge dozens of small images into one. | |
* in my case, it's more complicated cuz i make the target and output | |
* more structured and batch processed. | |
*/ | |
await Promise.all( | |
mergePanel([...img1], "output"), | |
mergePanel([...img2], "output"), | |
mergePanel([...img3], "output") | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment