动画 gif 上的 ImageMagick 文本水印
Posted
技术标签:
【中文标题】动画 gif 上的 ImageMagick 文本水印【英文标题】:ImageMagick text watermark on animated gif 【发布时间】:2018-01-09 08:52:27 【问题描述】://add text watermark on animated gif
std::vector<Image> imglist;
std::vector<Drawable> text_list;
text_list.push_back( DrawableText(0, 0, “I love you!"));
text_list.push_back( DrawableStrokeColor(Color("black")));
try
readImages(&imglist, "test.gif");
for (uint32_t i = 0; i < imglist.size(); ++i)
imglist[i].font("./MILT_RG.ttf");
imglist[i].draw(text_list);
writeImages(imglist.begin(), imglist.end(), "test_render.gif");
catch (Exception &error_)
cout << error_.what() << endl;
但是函数 writeImages 花费了太多时间。在我的测试示例中,一个 gif,900x600,20 帧,需要 1.5 秒。有什么办法可以加快速度吗?或者,一些更好的算法可以在 gif 上添加文本水印。谢谢。
【问题讨论】:
只是在 Eric 稍后上线之前疯狂地猜测,但您可以尝试将文本写入透明画布一次,然后在 20 帧中的每一帧上合成... 【参考方案1】:您也许可以通过利用 STL 来简化事情
std::vector<Image> imglist;
DrawableList text_list; // <= Same as vector<Drawable>
text_list.push_back( DrawableText(0, 0, "I love you!"));
text_list.push_back( DrawableStrokeColor(Color("black")));
try
readImages(&imglist, "test.gif");
for_each(imglist.begin(), imglist.end(), fontImage("./MILT_RG.ttf"));
for_each(imglist.begin(), imglist.end(), drawImage(text_list));
writeImages(imglist.begin(), imglist.end(), "test_render.gif");
// ...
但随着您对速度更感兴趣,可能是时候考虑使用OpenMP 进行并行处理了。
#pragma omp parallel for
for (size_t i = 0; i < imglist.size(); ++i)
imglist[i].font("./MILT_RG.ttf");
imglist[i].draw(text_list);
最后,您可以将字体移动到可绘制上下文中,并消除对同一 TTF 文件的重复读取。可能是最好的选择。
std::vector<Image> imglist;
DrawableList text_list;
text_list.push_back( DrawableFont("./MILT_RG.ttf"));
text_list.push_back( DrawableText(32, 32, "I love you!"));
text_list.push_back( DrawableStrokeColor(Color("black")));
try
readImages(&imglist, "test.gif");
for_each(imglist.begin(), imglist.end(), drawImage(text_list));
writeImages(imglist.begin(), imglist.end(), "test_render.gif");
// ...
YMMV
编辑
正如 Mark 在 cmets 中指出的那样,在临时图像中绘制一次文本并在所有帧中合成可能会更快。
Geometry imgSize = imglist[0].size();
Image imgText(imgSize, Color("transparent"));
imgText.draw(text_list);
for_each(imglist.begin(), imglist.end(), compositeImage(imgText, 0, 0, AtopCompositeOp));
【讨论】:
在我的测试中,绘制文本的循环花费了100多毫秒,而writeImages操作花费了1300多毫秒。瓶颈可能是writeImages。请问您知道原因吗? @Yang 您可以尝试在tmpfs
或 RAMdrive 文件系统上写入,看看它是否是导致您的问题的慢速磁盘。另一种可能性是 IM 可能正在尝试在所有 20 帧中优化您的调色板...
@emcconville 慢速磁盘不是问题,因为我尝试将图像写入 blob 并且它也很慢。您的后一种猜测可能是正确的。有没有办法验证并做一些优化?【参考方案2】:
我找到了一种可能的方法。我们可以根据@emcconville 的上述回答并行化程序。但是我们必须并行化成本操作,也就是量化。代码如下:
#pragma omp parallel for
for (size_t i = 0; i < imglist.size(); ++i)
imglist[i].font("./MILT_RG.ttf");
imglist[i].draw(text_list);
imglist[i].quantize(false);
【讨论】:
以上是关于动画 gif 上的 ImageMagick 文本水印的主要内容,如果未能解决你的问题,请参考以下文章
Imagemagick:如何减小具有大静态区域的动画 GIF 的大小?
如何使用 ImageMagick (php) 调整动画 gif 的大小?