Объединить 2 изображения с node.js ?

#image #node.js

#изображение #node.js

Вопрос:

Я хочу объединить 2 изображения с помощью node.js . Или, скорее, я хочу разместить одно изображение меньшего размера по координатам x, y на изображении большего размера. Еще точнее: у меня есть изображение очков и изображение лица, и я хочу надеть очки на лицо. Я немного погуглил и нашел несколько библиотек для обработки изображений, но, похоже, ни одна из них не способна объединять изображения.

Ответ №1:

Вам может понадобиться это:https://github.com/zhangyuanwei/node-images

Кроссплатформенный декодер изображений (png / jpeg / gif) и кодировщик (png / jpeg) для Nodejs

 images("big.jpg").draw(images("small.jpg"), 10, 10).save("output.jpg");
  

Комментарии:

1. Это то, что я искал. Никаких зависимостей, простой в использовании и быстрый.

2. последняя версия nodejs, которую поддерживает эта библиотека, — 6.0.0 для x64 и 5.0.0 для x86

3. Есть ли какая-либо функция обратного вызова или это асинхронная функция?

Ответ №2:

У меня недостаточно репутации, чтобы добавить комментарий, иначе я бы ответил на ответ Шмидко.

Sharp работает хорошо, однако overlayWith устарел, и вместо этого вам нужно использовать composite. Смотрите ниже:

 sharp(path   'example.jpg')
       .composite([{input: path   'logo.png', gravity: 'southeast' }])
       .toFile(path   'output.png');
  

Если вы хотите расположить по центру накладываемое изображение:
gravity: 'centre'

Ответ №3:

Я использовал:

https://github.com/learnboost/node-canvas

чтобы сделать что-то подобное (создать составное изображение из компонентов на лету).

Это отлично работает.

Вот несколько примеров кода:

 var Canvas = require('canvas'),
  fs = require('fs'),
  Image = Canvas.Image;



var _components = [{prefix:'f', count:12},
                   {prefix:'h', count:12},
                   {prefix:'i', count:12},
                   {prefix:'m', count:12}];


var _total = 1;
for (var i=_components.length - 1; i>=0; i--){
  _components[i].mult = _total;
  _total *= _components[i].count;
}


module.exports.ensureImageExists = function(img, cb){
  fs.stat(__dirname   '/../public/images/rb/'   img, function(err, stats){
    if (err){
      if (err.code == 'ENOENT')
        generateImage(img, cb);
      else
        cb(err);
    }
    else{
      cb();
    }
  });
}

function generateImage(name, cb){
  var re = /rb([0-9]*).png/

  var num = parseInt(re.exec(name)[1]) % _total;

  var parts = [];
  for (var i=0; i<_components.length; i  ){
    var n = Math.floor(num / _components[i].mult);
    parts.push(_components[i].prefix   (n   1));
    num -= n * _components[i].mult;
  }

  var canvas = new Canvas(45, 45),
   ctx = canvas.getContext('2d');

  drawParts();

  function drawParts(){
    var part = parts.shift();
    if (!part)
      saveCanvas();
    else {
      var img = new Image;
      img.onload = function(){
        ctx.drawImage(img, 0, 0, 45, 45);
        drawParts();
      };
     img.src = __dirname   '/components/'   part   '.png';
    }
  }

  function saveCanvas(){
    canvas.toBuffer(function(err, buf){
      if (err)
        cb(err);
      else
        fs.writeFile(__dirname   '/../public/images/rb/'   name, buf, function(){
          cb();
        });
    });
  }

}
  

В этом случае компоненты выбираются на основе названия изображения, но вы, очевидно, могли бы поступить иначе. Кроме того, я полагаю, вы могли бы просто передать изображение потоковой передачей, если хотите — я записываю его в файл, чтобы оно было доступно при следующем запросе.

Я ввел подобный маршрут для обработки генерации:

 app.get('/images/rb/:img', requireLogin, function(req, res, next){
  //first make sure image exists, then pass along so it is handled
  //by the static router
  rbgen.ensureImageExists(req.params.img, function(err){
    next();
  })
});
  

Комментарии:

1. Спасибо, это выглядит именно так, как я хочу.

2. Сбой с изображением в формате JPEG

Ответ №4:

Протестировал несколько библиотек для аналогичной задачи и, наконец, реализовал эту.

https://github.com/lovell/sharp.

Чистый API и все, что вам нужно для объединения двух изображений вместе.

Пример:

 sharp(path   'example.jpg')
    .overlayWith(path   'label.png', { gravity: sharp.gravity.southeast } )
    .toFile(path   'output.png')