英文:
How to add border radius to images in a composite image using sharp.js in Node.js?
问题
我正在我的Node.js项目中使用sharp库将一组图像合成为单个图像。
我已成功创建了合成图像,但我需要对网格中的每个图像应用边框半径。
我的代码:
const sharp = require('sharp');
const axios = require('axios');
const fs = require('fs');
// 虚拟图像列表,真实数据将通过API获取
const imageUrls = Array(25).fill("").map((el, i) => `https://picsum.photos/id/${i}/1280/720`)
// 基本设置
const productWidth = 1080
const productHeight = 1080
const row = 5
const col = 5
const gapSize = 10;
// 图像宽度和高度
const imageWidth = (productWidth - gapSize * (row - 1) - gapSize * 2) / row;
const imageHeight = (productHeight - gapSize * (col - 1) - gapSize * 2) / col;
const borderRadius = 20;
// 用于边框半径的蒙版
const mask = Buffer.from(
`<svg><rect x="0" y="0" width="${imageWidth}" height="${imageHeight}" rx="${borderRadius}" ry="${borderRadius}" /></svg>`
);
const imagePromises = imageUrls.map(async (url) => {
const response = await axios.get(url, { responseType: 'arraybuffer' });
const image = sharp(response.data);
if (image) console.log('downloaded image')
return image.resize(imageWidth, imageHeight, { fit: 'cover' }).composite([{
input: mask,
blend: 'dest-in'
}]).toBuffer();
});
async function compositeImages() {
try {
const images = await Promise.all(imagePromises)
// 初始化画布
const canvas = sharp({
create: {
width: productWidth,
height: productHeight,
channels: 4, // RGBA
background: { r: 255, g: 255, b: 255, alpha: 1 } // 白色背景
}
});
// 绘制图像
const compositeArr = images.map((buffer, index) => {
const colValue = index % col
const rowValue = Math.floor(index / col)
const x = gapSize + colValue * (imageWidth + gapSize)
const y = gapSize + rowValue * (imageHeight + gapSize)
return {
input: buffer,
left: x,
top: y,
blend: 'atop'
}
})
// 下载最终产品
canvas.composite(compositeArr)
.png()
.toBuffer()
.then((buffer) => {
fs.writeFileSync('banner.png', buffer);
});
} catch (error) {
console.log(error)
}
}
compositeImages()
黑色边缘仍然存在。如何移除?
我将不背答案的方式提供建议或见解以解决此问题。提前感谢您的帮助。
英文:
I am using the sharp library in my Node.js project to composite a grid of images into a single image.
I have successfully created the composite image, but I need to apply a border radius to each of the images in the grid.
my code:
const sharp = require('sharp');
const axios = require('axios');
const fs = require('fs');
//dummy image lists, the real data will be fetched by api
const imageUrls = Array(25).fill("").map((el, i)=> `https://picsum.photos/id/${i}/1280/720`)
//basic setting
const productWidth = 1080
const productHeight = 1080
const row = 5
const col = 5
const gapSize = 10;
//length - padding * 2 - gap * row
const imageWidth = (productWidth - gapSize * (row - 1) - gapSize * 2) / row;
const imageHeight = (productHeight - gapSize * (col - 1) - gapSize * 2) / col;
const borderRadius = 20;
//for border radius
const mask = Buffer.from(
`<svg><rect x="0" y="0" width="${imageWidth}" height="${imageHeight}" rx="${borderRadius}" ry="${borderRadius}" /></svg>`
);
const imagePromises = imageUrls.map(async (url) => {
const response = await axios.get(url, { responseType: 'arraybuffer' });
const image = sharp(response.data);
if (image) console.log('downloaded image')
return image.resize(imageWidth, imageHeight, { fit: 'cover' }).composite([{
input: mask,
blend: 'dest-in'
}]).toBuffer();
});
async function compositeImages() {
try {
const images = await Promise.all(imagePromises)
//init canvas
const canvas = sharp({
create: {
width: productWidth,
height: productHeight,
channels: 4, // RGBA
background: { r: 255, g: 255, b: 255, alpha: 1 } // white background
}
});
//draw images
const compositeArr = images.map((buffer, index) => {
const colValue = index % col
const rowValue = Math.floor(index / col)
const x = gapSize + colValue * (imageWidth + gapSize)
const y = gapSize + rowValue * (imageHeight + gapSize)
return {
input: buffer,
left: x,
top: y,
blend: 'atop'
}
})
//download final product
canvas.composite(compositeArr)
.png()
.toBuffer()
.then((buffer: any) => {
fs.writeFileSync('banner.png', buffer);
});
} catch (error) {
console.log(error)
}
}
compositeImages()
The black color edge is still here. How to remove?
I would appreciate any suggestions or insights on how to resolve this issue. Thank you in advance.
答案1
得分: 2
Try converting the image to PNG before compositing.
return image.resize(imageWidth, imageHeight, { fit: 'cover' }).png().composite([{
input: mask,
blend: 'dest-in'
}]).toBuffer();
英文:
Try converting the image to PNG before compositing.
return image.resize(imageWidth, imageHeight, { fit: 'cover' }).png().composite([{
input: mask,
blend: 'dest-in'
}]).toBuffer();
I hope this helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论