几句代码实现美美的GIF录屏工具

admin2021-10-30  1K+

 ​Jacen He

GIF 还是非常有用的,很多时候我们需要这种小、简单、不复杂又粗暴够用的东西。GIF 录屏的工具虽然很多,但是用着用着有时候就发现不需要的功能很多,需要的功能他又没有或者不方便,今天我们自己用 aardio 来写一个,放心要不了几句代码。

 

一、窗口开洞

 

首先我们要在录屏工具的窗口上挖一个洞,这样我们就可以把窗口作为截图选框 ,挖个洞当然要不了几句代码,之前我在论坛有写过,但是如果这几句代码都不用写就更好了,于是我把这几句代码封装了一个库 win.region.hole, 这个库特别好用,首先我们在窗口上拖一个控件,调整好位置和自动缩放参数,然后 win.regin.hole( winform.ctrlName ) 就可以在控件所在的位置开洞了,这样可以方便地、可视化的任意指定要开洞的区域。

 

二、GIF 动画与剪贴板的小秘密

 

GIF 录制好了,我们一般当然是复制并分享了,如果我们打开图像再去复制还是有些麻烦,能一键复制多好。但是这个看起来简单的事 —— 还真是有些麻烦,首先系统剪贴板其实并不支持 GIF 图像,所以很多软件里复制 GIF 只复制了第一帧。

 

但是我们发现有些软件他是可以复制GIF的,有的文章说通过复制HTML就可以了,用 aardio 来写实际上就是这样:

import win.clip.html;
var html = win.clip.html();
html.write(`<img src="c:\test.gif" />`)


popdes 就写过一篇长文《对剪贴板的深入探讨》其中就提到了这个方法,网上很多文章都这么写,但实际上根据我的测试,这样复制 GIF 以后浏览器或者 QQ 等软件里并不能粘贴。

这个其实可以理解,浏览器是没有权限访问本地文件的,即使他得到了剪贴板中的HTML,也没有权限去读任意位置的本地文件,考虑到了这一点,我决定把本地图像转换为 Data URL 直接嵌入HTML,主要代码如下:

import win.clip.html;
import crypt;

var html = win.clip.html();
var dataUrl = string.format('data:image/gif;base64,%s'
  ,crypt.encodeBin( string.loadBuffer(filePah),,0x40000001/*_CRYPT_STRING_BASE64*/) ); 
  
html.write(`<img src="`  dataUrl `" />`,,false);


上面的代码实现了以后,我在公众号编辑器里测试了一下,用这种方法复制一个 GIF 文件以后,到公众号编辑器里 Ctrl V 粘贴,看到了 GIF 动画在编辑器里显示出来了,还没高兴零点几秒,弹出一个错误信息:粘贴图像失败。看了一下是远程错误,猜测他把这个当作普通远程图像地址去处理了。

然后在 QQ 里试着粘贴了一下,也没任何反应。看来此路不通。看到有人说可以复制为 CF_HDROP 格式,好吧,aardio 干这事倒也方便,代码如下:

import win.clip.file;
win.clip.file.write( filePath );


其实这等价于在资源管理器里右键复制文件。用上面的方法复制了图像以后,到 QQ 里粘贴试了一下,粘贴出来的是一个文件图标,并没有认出是 GIF 动画。

想起之前看到有人说 IE 能复制 GIF,但是在剪贴板里看到的只是静态的 BMP 图像,不知道 IE 是如何实现的,难道 …… 于是试着在剪贴板里先复制 GIF 第一帧的静态图像,再复制文件本身(同时复制2种格式),用这种方法复制了一个 GIF 图像,然后到 QQ里粘贴,这回粘贴出来的还真是 GIF 动画 ,直接就显示预览动画了 —— 完美!

然后打开公众编辑器,试着粘贴了一下,遇到2种不同的反应,第1种是出现了静态图像 —— 没动画,第2种是静态图像也没有,细节没有深究。想起之前复制 Data URL 失败的过程,这难道是 …… 于是赶紧换每 3 种方法,复制第一帧静态图像,复制文件,然后再复制 Data URL ,一气呵成三连击以后终于成功了,公众号编辑器里完美粘贴出来 GIF 动画,QQ 试了一下也支持,再试了其他编辑器也能完美支持。

于是,我又加了一个库 win.clip.gif,用起来就太简单了:

import win.clip.gif;
win.clip.gif.write( filePath );


大家看这就是 aardio 的好处了,像这种库一天能写一打出来,再复杂的代码都可以简化,这得益于 aardio 良好的模块化支持。有人就说我用其他语言也可以,不就是库多吗,其实很多编程语言你随随便便地就能在网上找到几千上万GB的库 …… 但是你试试,做这些事,很多时候不如几 MB的 aardio 代码简洁。

 

三、 GIF 压缩优化


下面我们还有更重要的事要做,我录了一些屏幕动作生成 GIF 以后,打开一看吓到了,6MB …… 于是准备弄个 GIF 优化,减少调色板的颜色数量,让每帧都不处理不清除背景从而可以避免保存重复的图像,再试试自动抽帧,因为我们使用 soImage 扩展库生成 GIF,而 soImage 有比对图像相似度的功能,于是加了几句代码,每一帧都跟之前的帧比对相似度,图像没变化的就扔掉,写完了试了一下体积是小了,但图像过度不自然,感觉这种一边录一边处理图像的方法不是很好,而且这越搞越复杂,显然不是个把小时内能完成的事,搞太复杂就背离初衷了,有没有简单粗暴的方法?!

首先我们很多时候对普通动画帧数要求其实没那么高,就算是手工抽帧吧,几百上千个帧我们能很认真的抽吗?也是粗暴的看一下粗暴的删帧,所以我考虑了一下,用了一个简单的方案,直接在界面上弄了一个设置每秒抓取帧数的滑块:


图片


这样可以简单粗暴地控制输出图像的体积,我们录一般的动画其实只需要非常低的帧数就可以,GIF的帧数是影响输出体积最重要的因素,另外一个就是「清除帧背景」设置,网上说得最多的减少调色板的颜色数 —— 优化效果很多时候基本可以忽略。

然后还有其他更简单的方法可以快速地、进一步的优化 GIF 体积,又不用自己写代码吗?!打开 GitHub 搜一下,比较火的一个是 Gifsicle,这是一个命令行工具,我可不想每次都去敲命令行,我们希望下载 Gifsicle,执行 Gifsicle,敲命令行全部自动完成 …… 至于我们自己呢,最好什么都不用干。为了做到这一点,我又写了一个扩展库 process.gifsicle, 这个扩展库源码没几句,大家可以自己看看,用法很简单:

import process.gifsicle;
process.gifsicle.optimize("/screenshots.gif") 


这就可以把一个几MB的 GIF 瞬间优化为几百KB了,真是太好了,会编程真是一件愉快的事,麻烦事只要做一次,以后就可以千万次的简化。

好吧,更多的细节请打开「范例 / 图形图像 / 录微 GIF 」查看源代码:


图片

转载请注明原文地址: http://aardio.net/read-259.html
最新回复(0)
aardio问答
aardio编程语言