动态清晰地叠加多个图像

时间:2018-07-24 19:33:08

标签: javascript node.js image sharp

我正在尝试使用sharp覆盖多张图像。下面显示了一个独立的示例,该示例失败并显示错误:

  

错误:输入缓冲区包含不受支持的图像格式

在第一次覆盖操作期间引发错误。我的实际生产代码中将要动态缝合大量图像,因此我需要某种形式的循环来创建合成图像。

有什么想法出错了吗?我是JavaScript新手,所以也许某处有一个陌生人...

const sharp = require('sharp');

let photoWidth = 400;
let imagePromises = [];

// This would be a dynamic amount of images in reality
let images = ['https://i.imgur.com/ej54FT4.jpg', 'https://i.imgur.com/ej54FT4.jpg'];

// Centre, square crop each image
images.forEach((img) => {
    imagePromises.push(
        get(img)
            .then((imgBuffer) => {
                return sharp(imgBuffer)
                    .resize(photoWidth, null)
                    .max()
                    .withMetadata()
                    .toBuffer();
            })
            .then((imgBuffer) => {
                return sharp(imgBuffer)
                    .resize(photoWidth, photoWidth)
                    .withMetadata()
                    .toBuffer();
            })
    );
});

// Create something to overlay the images on
let backgroundPromise = sharp({
    create: {
        width: photoWidth,
        height: images.length * photoWidth,
        channels: 3,
        background: {r: 0, g: 0, b: 0}
    }
}).toBuffer();

Promise.all(imagePromises)
    .then((imgBuffers) => {
        let i = -1;

        return imgBuffers.reduce((current, overlay) => {
            return current.then((curr) => {
                i++;
                console.log(`Overlaying image ${i + 1}`);
                // Error occurs here:
                return sharp(curr)
                    .overlayWith(overlay, {top: i * photoWidth, left: 0})
                    .withMetadata()
                    .toBuffer();
            });
        }, backgroundPromise);
    })
    .then((noFormatImage) => {
        console.log("Converting to JPG");
        return sharp(noFormatImage)
            .jpeg({
                quality: 95
            })
            .toBuffer();
    })
    .then((finishedImageBuffer) => {
        console.log("Writing to storage");
        return sharp(finishedImageBuffer)
            .toFile('output.jpg');
    })
    .then((info) => {
        console.log(info);
    })
    .catch((err) => console.log(err));


function get(url) {
    return new Promise((resolve, reject) => {
        let request = require('request').defaults({encoding: null});

        request.get(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(body);
            } else {
                reject(error);
            }
        });
    });
}

1 个答案:

答案 0 :(得分:1)

解决了。我需要将背景转换为JPEG:

// Create something to overlay the images on
let backgroundPromise = sharp({
    create: {
        width: photoWidth,
        height: images.length * photoWidth,
        channels: 3,
        background: {r: 0, g: 0, b: 0}
    }
})
    .jpeg()   // <--- this was needed
    .toBuffer();