如何在node.js中使用graphicsmagick来裁剪圆形图片(其他使用任何其他方式在node.js上进行此操作)

时间:2015-03-25 13:11:05

标签: node.js graphicsmagick

如何使用graphicsmagick crop circle picture?

(使用png透明背景外圈)

我在node.js中使用了graphicsmagick,或者在node.js中有任何其他方法可以做到这一点吗?

在: http://i.stack.imgur.com/B34C5.png

在: http://i.stack.imgur.com/PWjQW.png

6 个答案:

答案 0 :(得分:4)

经过几个小时的摆弄,我找到了一个使用node-gm和Imagemagick的干净解决方案。

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

var original = 'app-server/photo.jpg'; 
var output = 'app-server/photo.png';
var size = 80;

gm(original)
  .crop(233, 233,29,26)
  .resize(size, size)
  .write(output, function() {

     gm(size, size, 'none')
        .fill(output)
        .drawCircle(size/2,size/2, size/2, 0)
        .write(output, function(err) {
           console.log(err || 'done');
        });
  });

答案 1 :(得分:1)

我使用另一个模块来解决这个问题:

此代码用于方形图像(this.height = this.width)

node-pngjs

var fs = require('fs'),
PNG = require('pngjs').PNG;

fs.createReadStream(__dirname + "/input.png")
    .pipe(new PNG({
        filterType: 4
    }))
    .on('parsed', function() {
    for (var y = 0; y < this.height; y++) {
        for (var x = 0; x < this.width; x++) {
            var idx = (this.width * y + x) << 2;
            var radius = this.height / 2;
            if(y >= Math.sqrt(Math.pow(radius, 2) - Math.pow(x - radius, 2)) + radius || y <= -(Math.sqrt(Math.pow(radius, 2) - Math.pow(x - radius, 2))) + radius) {
                this.data[idx + 3] = 0;
            }
        }
    }
        this.pack().pipe(fs.createWriteStream(__dirname + "/output.png"));
    });

答案 2 :(得分:1)

我能够使用以下插件执行此操作: https://www.npmjs.com/package/circle-image

安装后:

var images = require('circle-image');
var imageSizes = [125, 100, 30];
//uniqueId param is used to identify a user 
//so user the primary key or something guaranteed to be unique 
images.execute('imagepath', uniqueId, imageSizes).then(function (paths) {
  //array of circularized image paths 
  console.log(paths[0]); //circle_user_{uniqueId}_150.png 
})

答案 3 :(得分:0)

花我几个小时来弄清楚

  1. 我想避免使用像ImageMagick这样的第三方软件(许多npm软件包都基于该软件包)
  2. node-pngjs似乎仅支持PNG文件+需要太多自定义代码

这是我使用sharp的解决方案:

In [5]: j1 = ['8', '9']

In [6]: j1[0] + j1[1]
Out[6]: '89'

In [7]: 'f%d' % 2
Out[7]: 'f2'

In [8]: (j1[0] + j1[1]) % 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-69ab5a8355ef> in <module>
----> 1 (j1[0] + j1[1]) % 2

TypeError: not all arguments converted during string formatting

In [9]: (int(j1[0]) + int(j1[1])) % 2
Out[9]: 1

如果您有兴趣,基于上面的代码,我创建了一个实用程序,该实用程序获取base64编码的图像(来自前端),并输出带有圆圈图像的文件流。使用temp-write软件包将处理过的图像保存在temp目录中。:

const sharp = require('sharp');

const width = 400,
    r = width / 2,
    circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`);

sharp('input.jpg')
    .resize(width, width)
    .composite([{
        input: circleShape,
        blend: 'dest-in'
    }])
    .webp()
    .toFile('output.webp', (err, info) => err ?
        console.error(err.message) :
        console.log(info)
    );

答案 4 :(得分:0)

以下是使用gm和缓冲区的版本:

var gm = require('gm').subClass({ imageMagick: true });
var max = 200;
// buffer - is Buffer with picture

gm(buffer)
    .autoOrient()
    .gravity('Center')
    .resize(max, max, '^')
    .extent(max, max)
    .noProfile()
    .setFormat('png')
    .out('(')
        .rawSize(max, max)
        .out('xc:Black')
        .fill('White')
        .drawCircle(max/2,max/2, max/2, 1)
        .out('-alpha', 'Copy')
    .out(')')
    .compose('CopyOpacity')
    .out('-composite')
    .trim()
    .toBuffer((err, buffer) => {
        //...
    });

上面的node.js代码等效于此ImageMagick命令,但是使用了缓冲区:

convert input.png \
        -gravity Center \
        -resize 200x200^ \
        -extent 200x200 \
        \( -size 200x200 \
           xc:Black \
           -fill White \
           -draw 'circle 100 100 100 1' \
           -alpha Copy \
        \) -compose CopyOpacity -composite \
        -trim output.png

答案 5 :(得分:0)

使用裁剪

const gm = require("gm");
const path = require("path");
const fs = require("fs");

const pathIn = path.resolve(__dirname, "images/in.jpeg");
function circularize(path, callback) {
  const maskPath = path.replace(/\.[a-zA-Z]+$/g, "_mask.png");
  const tmpPath = path.replace(/\.[a-zA-Z]+$/g, "_tmp.png");
  gm(pathIn).size((err, iSize) => {
    if (err) return callback(err, null);
    const { width, height } = iSize;
    const size = Math.min(width, height);
    const r = size / 2;
    gm(width, height, "transparent")
      .fill("#ffffff")
      .drawCircle(r, r, r, 1)
      .setFormat("png")
      .trim()
      .write(maskPath, (err) => {
        if (err) return callback(err, null);
        gm(pathIn)
          .gravity("Center")
          .crop(size, size)
          .write(tmpPath, (err) => {
            if (err) return callback(err, null);
            gm(tmpPath)
              .composite(tmpPath, maskPath)
              .compose("CopyOpacity")
              .gravity("Center")
              .setFormat("png")
              .toBuffer((err, buffer) => {
                if (err) return callback(err, null);
                fs.unlinkSync(maskPath);
                fs.unlinkSync(tmpPath);
                return callback(null, buffer);
              });
          });
      });
  });
}