Как скомпоновать статическое фоновое изображение и gif с помощью пакета Sharp nodejs

Кажется, что сколько бы вы ни искали в Интернете компоновку неподвижного фонового изображения (например, PNG или JPEG) с GIF, полных решений не существует. Наложение gif на неподвижный фон, похоже, просто не поддерживается Sharp или, по крайней мере, в большинстве случаев это не так. Как мы можем объединить неподвижное фоновое изображение с GIF-изображением, наложив его, чтобы создать новый GIF-изображение?
Спасибо

🤔 А знаете ли вы, что...
JavaScript был первоначально создан для улучшения интерактивности веб-страниц.


137
1

Ответ:

Решено

Обзор

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

Процесс

Процесс создания анимированного GIF-изображения путем наложения GIF-изображения на неподвижный фон требует нескольких шагов. по умолчанию false).

Сначала убедитесь, что размеры gif и входного изображения совместимы (согласно документации наложение должно быть того же размера или меньше, чем входное изображение). Поэтому следует учитывать любое изменение размера, обрезку или позиционирование. Вам нужно будет обработать изображения так, чтобы они были одинакового размера (если это еще не так), или при компоновке вам придется определить свое позиционирование.

Во-вторых, вам придется расширить статическое входное изображение так, чтобы оно создало рулон пленки (или, как некоторые могут назвать его, рулон туалетной бумаги). Повторение статического изображения по вертикали.

Наконец, вы можете объединить расширенное статическое изображение и GIF-изображения, преобразовать их в формат GIF и сохранить как файл .gif.

Результирующий код:

async function overlayGif (background, gifOverlay) { //takes two input paths.
    const overlay = await sharp(gifOverlay, {animated: true}); //make sure animated is true.
    const metadata = await overlay.metadata(); //We'll use the gif metadata to normalize the background.
    const backgroundImg = await sharp(background).resize(metadata.width, metadata.pageHeight); //We are resizing here to normalize background with gif.
    const imgRoll = backgroundImg.extend({bottom: metadata.pageHeight*(metadata.pages-1), extendWith: 'repeat'}); //Must extend to repeat how ever many pages (frames) are in the gif.
    const result = await imgRoll.composite([
        { input: await overlay.toBuffer(), gravity: 'center', animated: true}
    ]).gif (
        {progressive: metadata.isProgressive, delay: metadata.delay, loop: metadata.loop}
        //Just copying the metadata from the gif to the output format (not sure this is necessary).
    );
    const resInfo = await result.toFile("output.gif"); //Write the result to a gif file.
    return result;
}

Известные ограничения

Если вы используете приведенный выше код, вы заметите некоторые проблемы с результатом композиции метаданных... В первую очередь ограничением является то, что результирующий формат метаданных не является gif, это любой формат фонового изображения (png, jpeg и т. д.). Таким образом, вы не можете использовать какие-либо функции метаданных (и даже если вы используете свойство Force, чтобы принудительно сделать формат GIF, метаданные остаются в том же формате, что и фоновое изображение), хотя они действительно выглядят как GIF.