如何在Node.js中使用sharp.js将边框半径添加到复合图像中的图像?

huangapple go评论106阅读模式
英文:

How to add border radius to images in a composite image using sharp.js in Node.js?

问题

我正在我的Node.js项目中使用sharp库将一组图像合成为单个图像。
我已成功创建了合成图像,但我需要对网格中的每个图像应用边框半径。

我的代码:

  1. const sharp = require('sharp');
  2. const axios = require('axios');
  3. const fs = require('fs');
  4. // 虚拟图像列表,真实数据将通过API获取
  5. const imageUrls = Array(25).fill("").map((el, i) => `https://picsum.photos/id/${i}/1280/720`)
  6. // 基本设置
  7. const productWidth = 1080
  8. const productHeight = 1080
  9. const row = 5
  10. const col = 5
  11. const gapSize = 10;
  12. // 图像宽度和高度
  13. const imageWidth = (productWidth - gapSize * (row - 1) - gapSize * 2) / row;
  14. const imageHeight = (productHeight - gapSize * (col - 1) - gapSize * 2) / col;
  15. const borderRadius = 20;
  16. // 用于边框半径的蒙版
  17. const mask = Buffer.from(
  18. `<svg><rect x="0" y="0" width="${imageWidth}" height="${imageHeight}" rx="${borderRadius}" ry="${borderRadius}" /></svg>`
  19. );
  20. const imagePromises = imageUrls.map(async (url) => {
  21. const response = await axios.get(url, { responseType: 'arraybuffer' });
  22. const image = sharp(response.data);
  23. if (image) console.log('downloaded image')
  24. return image.resize(imageWidth, imageHeight, { fit: 'cover' }).composite([{
  25. input: mask,
  26. blend: 'dest-in'
  27. }]).toBuffer();
  28. });
  29. async function compositeImages() {
  30. try {
  31. const images = await Promise.all(imagePromises)
  32. // 初始化画布
  33. const canvas = sharp({
  34. create: {
  35. width: productWidth,
  36. height: productHeight,
  37. channels: 4, // RGBA
  38. background: { r: 255, g: 255, b: 255, alpha: 1 } // 白色背景
  39. }
  40. });
  41. // 绘制图像
  42. const compositeArr = images.map((buffer, index) => {
  43. const colValue = index % col
  44. const rowValue = Math.floor(index / col)
  45. const x = gapSize + colValue * (imageWidth + gapSize)
  46. const y = gapSize + rowValue * (imageHeight + gapSize)
  47. return {
  48. input: buffer,
  49. left: x,
  50. top: y,
  51. blend: 'atop'
  52. }
  53. })
  54. // 下载最终产品
  55. canvas.composite(compositeArr)
  56. .png()
  57. .toBuffer()
  58. .then((buffer) => {
  59. fs.writeFileSync('banner.png', buffer);
  60. });
  61. } catch (error) {
  62. console.log(error)
  63. }
  64. }
  65. compositeImages()

最终产品:
如何在Node.js中使用sharp.js将边框半径添加到复合图像中的图像?

黑色边缘仍然存在。如何移除?

我将不背答案的方式提供建议或见解以解决此问题。提前感谢您的帮助。

英文:

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:

  1. const sharp = require(&#39;sharp&#39;);
  2. const axios = require(&#39;axios&#39;);
  3. const fs = require(&#39;fs&#39;);
  4. //dummy image lists, the real data will be fetched by api
  5. const imageUrls = Array(25).fill(&quot;&quot;).map((el, i)=&gt; `https://picsum.photos/id/${i}/1280/720`)
  6. //basic setting
  7. const productWidth = 1080
  8. const productHeight = 1080
  9. const row = 5
  10. const col = 5
  11. const gapSize = 10;
  12. //length - padding * 2 - gap * row
  13. const imageWidth = (productWidth - gapSize * (row - 1) - gapSize * 2) / row;
  14. const imageHeight = (productHeight - gapSize * (col - 1) - gapSize * 2) / col;
  15. const borderRadius = 20;
  16. //for border radius
  17. const mask = Buffer.from(
  18. `&lt;svg&gt;&lt;rect x=&quot;0&quot; y=&quot;0&quot; width=&quot;${imageWidth}&quot; height=&quot;${imageHeight}&quot; rx=&quot;${borderRadius}&quot; ry=&quot;${borderRadius}&quot; /&gt;&lt;/svg&gt;`
  19. );
  20. const imagePromises = imageUrls.map(async (url) =&gt; {
  21. const response = await axios.get(url, { responseType: &#39;arraybuffer&#39; });
  22. const image = sharp(response.data);
  23. if (image) console.log(&#39;downloaded image&#39;)
  24. return image.resize(imageWidth, imageHeight, { fit: &#39;cover&#39; }).composite([{
  25. input: mask,
  26. blend: &#39;dest-in&#39;
  27. }]).toBuffer();
  28. });
  29. async function compositeImages() {
  30. try {
  31. const images = await Promise.all(imagePromises)
  32. //init canvas
  33. const canvas = sharp({
  34. create: {
  35. width: productWidth,
  36. height: productHeight,
  37. channels: 4, // RGBA
  38. background: { r: 255, g: 255, b: 255, alpha: 1 } // white background
  39. }
  40. });
  41. //draw images
  42. const compositeArr = images.map((buffer, index) =&gt; {
  43. const colValue = index % col
  44. const rowValue = Math.floor(index / col)
  45. const x = gapSize + colValue * (imageWidth + gapSize)
  46. const y = gapSize + rowValue * (imageHeight + gapSize)
  47. return {
  48. input: buffer,
  49. left: x,
  50. top: y,
  51. blend: &#39;atop&#39;
  52. }
  53. })
  54. //download final product
  55. canvas.composite(compositeArr)
  56. .png()
  57. .toBuffer()
  58. .then((buffer: any) =&gt; {
  59. fs.writeFileSync(&#39;banner.png&#39;, buffer);
  60. });
  61. } catch (error) {
  62. console.log(error)
  63. }
  64. }
  65. compositeImages()

The final product:
如何在Node.js中使用sharp.js将边框半径添加到复合图像中的图像?

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.

  1. return image.resize(imageWidth, imageHeight, { fit: &#39;cover&#39; }).png().composite([{
  2. input: mask,
  3. blend: &#39;dest-in&#39;
  4. }]).toBuffer();
英文:

Try converting the image to PNG before compositing.

  1. return image.resize(imageWidth, imageHeight, { fit: &#39;cover&#39; }).png().composite([{
  2. input: mask,
  3. blend: &#39;dest-in&#39;
  4. }]).toBuffer();

I hope this helps.

huangapple
  • 本文由 发表于 2023年6月1日 16:44:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76380120.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定