【问题标题】:How to use graphicsmagick in node.js to crop circle picture (other use any other way to make this on node.js)如何在 node.js 中使用 graphicsmagick 来裁剪圆形图片(其他使用任何其他方式在 node.js 上制作)
【发布时间】:2015-03-25 13:11:05
【问题描述】:

如何使用graphicsmagick的麦田圈图片?

(使用png透明背景外圈)

我在 node.js 中使用 graphicsmagick,或者有任何其他方式在 node.js 中进行此操作?

之前: http://i.stack.imgur.com/B34C5.png

之后: http://i.stack.imgur.com/PWjQW.png

【问题讨论】:

    标签: node.js graphicsmagick


    【解决方案1】:

    经过几个小时的摆弄,我找到了一个使用 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');
            });
      });
    

    【讨论】:

    • 填充(输出)?填充在您的示例中采用的路径不是颜色没有意义
    【解决方案2】:

    我花了好几个小时才弄明白

    1. 我想避免使用第三方软件,例如 ImageMagick(许多 npm 包都是在此基础上构建的)
    2. node-pngjs 似乎只支持 PNG 文件 + 需要太多自定义代码

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

    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)
        );
    

    【讨论】:

    • 当我执行上述操作时,它会在圆形图像周围创建一个黑色背景。如何避免?
    【解决方案3】:

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

    此代码用于方形图像(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"));
        });
    

    【讨论】:

      【解决方案4】:

      我可以使用以下插件来做到这一点: 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 
      })
      

      【讨论】:

        【解决方案5】:

        这是使用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
        

        【讨论】:

          【解决方案6】:

          使用裁剪

          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);
                        });
                    });
                });
            });
          }
          
          

          【讨论】:

          • 您能否添加更多解释?这段代码能做到这一点,它将如何帮助 OP?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-26
          • 1970-01-01
          • 2019-10-29
          • 1970-01-01
          • 2020-05-06
          • 1970-01-01
          相关资源
          最近更新 更多