0

我有一个保存在服务器中的示例图像框架(见下文)和一个函数,该函数将采用一组图像 URL,将图像裁剪成圆形以匹配框架中猫图像的高度/宽度(60px x 60px ) 并根据图像的数量从左侧替换猫,最后将图像保存回来我需要知道如何在 node.js 中使用graphicMagick来做到这一点。

只是为了更清楚

  • 我有一个图像 frame.png
  • 我有两个 URL 的数组 ['www.someurl.com/image1.jpg', 'www.someurl.com/image2.jpg]
  • 对于数组中的每个 URL
    • 将图像 i 从 URL 下载到临时位置
    • 将图像 i 裁剪成半径为 60 的圆形。
    • 将它放在 frame.png 顶部的某个位置 (xi,yi)
  • 保存新的合成图像
  • 上传回来

样品架

4

1 回答 1

1

在这里,我发布了我为循环图像所做的解决方案,然后将它们组合在帧图像 (png) 上。该解决方案的唯一缺点是对文件有多次写入,而我无法在一次写入中完成。

我希望这对将来的人有所帮助,

const gm = require('gm').subClass({ imageMagick: true })

export async function convertToCircularImage(imagePath: string, resultPath: string) {
  const radius = 180

  return new Promise(function (resolve, reject) {
    gm(imagePath)
      .autoOrient()
      .gravity('Center')
      .resize(radius, radius, '^')
      .extent(radius, radius)
      .noProfile()
      .setFormat('png')
      .out('(')
      .rawSize(radius, radius)
      .out('xc:Black')
      .fill('White')
      .drawCircle(radius / 2, radius / 2, radius / 2, 1)
      .out('-alpha', 'Copy')
      .out(')')
      .compose('CopyOpacity')
      .out('-composite')
      .trim()
      .write(resultPath, (err: Error) => {
        if (err) {
          console.error('Failed to crop image.', err)
          reject(err)
        } else {
          console.log(`Cropped image at ${imagePath} and saved it at ${resultPath}`)
          resolve(resultPath)
        }
      })
  })
}

export async function composite(
  frameImagePath: string,
  circularImagesPaths: string[],
  resultImagePath: string,
  points: string[],
) {

  let frameImage = frameImagePath
  let index = 0
  for (const circularImagePath of circularImagesPaths) {
    const point = points[index]
    try {
      // this method return the resultImagePath which is then used as a frame for next composition
      frameImage = await composeImage(frameImage, circularImagePath, point, resultImagePath)
    } catch (e) {
      console.log('Composite: some error', e)
    }
    index = index + 1
  }
}

async function composeImage(
  frameImage: string,
  circularImage: string,
  point: string,
  resultPath: string,
): Promise<string | any> {
  console.log('Composing circular image to frame...', frameImage, circularImage)
  return new Promise(function (resolve, reject) {
    gm(frameImage)
      .composite(circularImage)
      .in('-compose', 'Dst_Over') // to only overlap on transparent parts
      .geometry(point)
      .in()
      .write(resultPath, function (err: any) {
        if (err) {
          console.error('Composing failed', err)
          reject(err)
        } else {
          console.log('Composing complete')
          resolve(resultPath)
        }
      })
  })
}
于 2020-09-08T17:00:25.467 回答