#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')