【问题标题】:How to add watermark to an animated gif image using jimp javascript?如何使用 jimp javascript 为动画 gif 图像添加水印?
【发布时间】:2021-02-16 18:45:35
【问题描述】:

这些是我用于向图像添加水印的代码:

    const ORIGINAL_IMAGE = "https://example/sample_image;
    const LOGO = fs.readFileSync('gangle.png');
    const LOGO_MARGIN_PERCENTAGE = 5;

    let [image, logo] = await Promise.all([
      Jimp.read(ORIGINAL_IMAGE),
      Jimp.read(LOGO)
    ]);

    logo.resize(image.bitmap.width, Jimp.AUTO);

    const xMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;
    const yMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;

    const X = image.bitmap.width - logo.bitmap.width - xMargin;
    const Y = image.bitmap.height - logo.bitmap.height - yMargin;

    image.composite(logo, X, Y, [
      {
        mode: Jimp.BLEND_SCREEN,
        opacitySource: 0.1,
        opacityDest: 1
      }
    ]);

    image.write('animatedimg.gif')

但它仅适用于文件类型为 png/jpg/jpeg 的图像。 它不适用于 gif 图像。

它将生成一个文件“animatedimg.gif”,但该文件不会加载到任何图像查看器或浏览器中。

如果我尝试在 mac 中打开该文件,弹出窗口将显示以下消息: "文件“animatedimg.gif”为空,无法打开。"

在 jimp 中有没有办法做到这一点? 或者还有其他 npm 包吗? 谢谢。

【问题讨论】:

  • 您需要处理 GIF 的每一帧,为每一帧添加水印...... jimp 有这样的功能吗?也许gifwrap 会有所帮助
  • @JaromandaX 我会试试的,谢谢。
  • @JaromandaX 有没有办法使用 gifwrap 从 url 读取图像?
  • 抱歉,我还没有阅读过 gifwrap 的文档 - 在 jimp 或 gifwrap 文档中与 jimp 结合使用 很有用 - 阅读文档并尝试一下我只想说,因为这是你的项目
  • @noyruto88 不,你必须自己做。发出 HTTP 请求,将该文件写入您的文件系统,然后利用 gifwrap 读取您刚刚使用 GifUtil.read 保存的文件。

标签: javascript npm gif animated-gif jimp


【解决方案1】:

令人困惑的是,Jimp 只处理单帧 GIF,而不是大多数人认为的多帧动画 GIF。所以你需要使用gifwrap

您可以从那里遍历多帧 GIF 中的每一帧。每个帧都是一个GifFrame,可以来回转换为一个 Jimp 实例(参见文档中的Leveraging Jimp)。您可以将水印添加到与GifFrame 对应的每个 Jimp 实例中。像这样的:

async function getGifFramesWithWatermarks(gifPath) {
  const readGif = await GifUtil.read(gifPath);
  const promises = readGif.frames.map(getGifFrameWithWatermark);
  const gifFramesWithWatermarks = await Promise.all(promises);

  return gifFramesWithWatermarks;
}

async function getGifFrameWithWatermark(gifFrame) {
  const jimpImage = GifUtil.copyAsJimp(Jimp, gifFrame);

  addWatermark(jimpImage); // function you will write

  return new GifFrame(jimpImage.bitmap, {
    disposalMethod: gifFrame.disposalMethod, // not documented by gifwrap but it's in the source
    delayCentisecs: gifFrame.delayCentisecs, // you'll probably want this
  });
}

const gifFramesWithWatermarks = await getGifFramesWithWatermark(GIF_PATH);
await GifUtil.write(WRITE_PATH, gifFramesWithWatermarks);

【讨论】:

  • 你能分享一个例子吗
  • @AdamZerner addWatermark 的样子如何?
  • @BrunoQuaresma 这是您需要使用jimp 编写的函数。好久没用了,忘记了。
【解决方案2】:

更新 我写了这个 npm 库,你可以用它在 gif 上写文本。它仍然有一些错误:https://www.npmjs.com/package/text-on-gif

这对我有用

const Jimp = require("jimp");
const { GifUtil,GifFrame,BitmapImage} = require('gifwrap');
var frames = [];

Jimp.loadFont(Jimp.FONT_SANS_32_WHITE).then(async function(font){
    await GifUtil.read("gif.gif").then(inputGif => {
        inputGif.frames.forEach(function(frame){
            jimpCopied = GifUtil.copyAsJimp(Jimp, frame);
            jimpCopied.print(font,0,0,"sanidhya");
            const GifCopied = new GifFrame(new BitmapImage(jimpCopied.bitmap,{
                disposalMethod: frame.disposalMethod,
                delayCentisecs: frame.delayCentisecs,
            }));
        frames.push(GifCopied);   
        });
    });
    GifUtil.quantizeDekker(frames);
    GifUtil.write("nyahhaha.gif",frames);
});

注意

仅当您的 Frame 使用超过 256 个颜色索引时才需要 qunatize*() 函数

【讨论】:

  • 这不适用于压缩 gif,仅适用于每帧包含所有颜色数据的 gif。它也超级慢。
  • @ThickMiddleManager 我注意到了,您能否建议进行更改以使其正常工作??
  • 您需要使用 imagemagick 重新渲染 gif。不幸的是,我认为 Jimp 不是这项工作的工具。
  • @ThickMiddleManager 重新渲染你的意思是使用类似“im.convert()”的东西?
  • 嗨,我如何在我的 gif 之前为多个帧预先附加一个 iamge?
猜你喜欢
  • 2016-12-14
  • 2014-02-28
  • 2013-08-15
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多