gpt4 book ai didi

Node.js、Express 和 GM (GraphicsMagick) - 添加水印和一般图像处理效率

转载 作者:太空宇宙 更新时间:2023-11-04 01:04:30 24 4
gpt4 key购买 nike

我需要根据上传的照片创建 4 种图像尺寸:大、中、小和超小。它在很大程度上适用于下面的代码,但大尺寸和中尺寸需要在左下角放置水印,但较小的两个尺寸则不需要。

似乎对于带水印的图像,我需要复制文件流并为每个图像保存一个单独的实例。速度和效率在这里很重要,所以我想确保我以最好的方式做到这一点。

GM Node 模块确实缺乏文档。有关详细信息,他们链接到 GraphicsMagick 站点,如果您尝试使用 GM 模块执行此操作,则该站点没有帮助。真是令人沮丧。

所以基本上,我可以使用帮助来弄清楚如何在两个较大尺寸上制作水印,然后我也只是想知道下面的代码是否尽可能高效。在我的本地计算机上创建 4 个尺寸时似乎有点慢。

var fileName = req.files.photo.name,
fileBaseName = fileName.substr(0, fileName.lastIndexOf('.')),
uploadRoot = SiteConfig.root + '/upload/',
photosRoot = SiteConfig.root + '/photos/',
publicRoot = SiteConfig.root + '/public/';

require('fs').rename(
req.files.photo.path,
uploadRoot + fileName,
function(error)
{
if (error)
{
res.send({ error: 'upload error' });
return;
}

var ImageSizes = {
large: {
width: 990,
height: 990
},
medium: {
width: 550,
height: 550
},
small: {
width: 145,
height: 145
},
xsmall: {
width: 55,
height: 55
}
};

var GM = require('gm'),
fileStream = require('fs').createReadStream(photosRoot + fileName);

var lgPath = photosRoot + fileBaseName + '_lg.jpg',
mdPath = photosRoot + fileBaseName + '_md.jpg',
smPath = photosRoot + fileBaseName + '_sm.jpg',
xsPath = photosRoot + fileBaseName + '_xs.jpg';

// I'm guessing the second parameter is to set the format
GM(fileStream, 'img.jpg')
.size(
{
bufferStream: true
},
function(err, size)
{
console.log(size.width);
console.log(size.height);

if (size.width > ImageSizes.large.width || size.height > ImageSizes.large.height)
this.resize(ImageSizes.large.width, ImageSizes.large.height);

// Auto-orient based on EXIF data then remove EXIF data
this
.autoOrient()
.noProfile()
.quality(70)
.write(
lgPath,
function (err)
{
if (!err)
{
console.log('write large done');

this
.resize(ImageSizes.medium.width, ImageSizes.medium.height)
// watermark code - i want to continue using the file stream instead of a file path
//.subCommand('composite')
//.gravity('Center')
//.in('-compose', 'Over', watermarkFilePath, baseFilePath)
.quality(70)
.write(
mdPath,
function (err)
{
if (!err)
{
console.log('write medium done');

this
.resize(ImageSizes.small.width, ImageSizes.small.height)
.crop(ImageSizes.small.width, ImageSizes.small.height)
.quality(70)
.write(
smPath,
function (err)
{
if (!err)
{
console.log('write small done');

this
.resize(ImageSizes.xsmall.width, ImageSizes.xsmall.height)
.quality(70)
.write(
xsPath,
function (err)
{
if (!err)
console.log('write xsmall done');
else
console.log('write xsmall error');
}
);

}
else
console.log('write small error');
}
);
}
else
console.log('write medium error');
}
);
}
else
console.log('write large error');
}
);


}
);
}
);

最佳答案

(请注意,这不是真正的代码,只是关于实际代码可能是什么样子的想法)

我突然想到你想做这样的事情:

server.on('incomingImage', function (image, res) {
async.each(imageOptions, function (imageOptions, done) {
image
.pipe(resize(imageOptions))
.pipe(fs.createWriteStream(baseDir + image.path + imageOptions.path))
.on('end', done);
}, function (err) {
if (err) {
res.send(500);
} else {
res.send(204);
}
});
});

也就是说,当图像进来时,为每个图像选项创建一个调整大小通过流和一个文件写入流,然后将图像通过所有调整大小流传输到文件写入流,一旦所有文件都写入完毕,就做出响应。

通过使用流进行并行处理,您可以最大限度地减少服务器由于 IO 而必须执行的等待时间(这首先是 Node.js 背后的基本思想)。

您正在将文件写入磁盘,然后依次处理每个图像选项并将它们写入磁盘,然后再开始从磁盘读取文件。

所以这是写入时间 x 1 + 读取时间 x 5 + 处理时间 x 5 + 写入时间 x 5

相反,它应该是最大处理时间 + 最大写入时间,这要短得多。

由于 gm 模块没有提供良好的流接口(interface),因此存在一些复杂性。您可能想看看是否有更好的模块。

还有关于流的主题:

https://github.com/substack/stream-handbook http://nodeschool.io/#stream-adventure

并且异步

http://nodeschool.io/#asyncyou

关于Node.js、Express 和 GM (GraphicsMagick) - 添加水印和一般图像处理效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24375090/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com