国内在线压缩gif都收费?那就自己写一个😏😏😏
emmmm,这样子怎么玩啊,没办法,那就只有找一些在线压缩 gif 的网站呗,随便找了一个看看:
如果我要上传的文件是小于 5MB 的我也不用找你了,脑子一转,突然想到我特么也是一个前端呀,我也可以搞一个啊,那就搞一个呗。
全局安装 gifsicle
Gifsicle 是一个命令行工具,用于创建、编辑、分析和优化 GIF 图像文件。它提供了一系列功能,如优化 GIF 以减小文件大小、创建动画 GIF、提取和插入 GIF 帧、转换不同的图像格式到 GIF,以及更多的高级编辑功能。
Gifsicle 特别适合于需要批量处理 GIF 文件或在脚本中自动化 GIF 处理的情况。用户可以通过命令行界面使用 Gifsicle,这意味着它不提供图形用户界面,但它的功能强大且灵活,适合高级用户和开发人员。
要想使用,你需要再你的电脑上安装 Gifsicle,如果你使用的是 MacOS,可以通过 Homebrew 安装:
brew install gifsicle
如果是其他操作系统的可自行查阅 官网
使用 NodeJs 编写脚本
安装好 Gifsicle 后,我们可以使用 Node 来执行相关的命令,这样就可以避免了我们直接在终端中输入命令了,而且我们还可以对这些文件进行逻辑判断了。
在这里我们使用 child_process 模块在 Node.js 脚本中调用 Gifsicle 命令。
首先是我们应该明白我们的需求,是大于 20MB 的 gif 文件是需要压缩的,而其他是不需要的,首先我们应该编写一个函数来判断文件的大小:
function getFileSizeInMegabytes(filePath) {
const stats = fs.statSync(filePath);
return stats.size / (1024 * 1024);
}
知道了文件的大小了之后我们就可以进行压缩的操作了。这里我们采用的是递减的方式对文件进行压缩,而不是一开始就对文件进行压缩,要对文件大小最接近到 20MB 的范围之内。
const { exec } = require("child_process");
const fs = require("fs");
function getFileSizeInMegabytes(filePath) {
const stats = fs.statSync(filePath);
return stats.size / (1024 * 1024);
}
function compressGIF(inputGif, outputGif, maxTargetSizeMB) {
const originalSizeMB = getFileSizeInMegabytes(inputGif);
// 如果原始文件大小已经小于等于20MB,则不进行压缩
if (originalSizeMB <= maxTargetSizeMB) {
console.log("原始文件大小已满足要求,无需压缩。");
return;
}
let scale = 0.95; // 初始缩放比例
const minScale = 0.1; // 最小缩放比例,防止过度压缩
let step = 0.05; // 初始调整步长
const attemptCompression = () => {
const command = `gifsicle --optimize=3 --scale=${scale.toFixed(
2
)} -o ${outputGif} ${inputGif}`;
exec(command, (error) => {
if (error) {
console.error(`执行出错: ${error}`);
return;
}
const outputFileSizeMB = getFileSizeInMegabytes(outputGif);
console.log(
`压缩比例: ${scale.toFixed(2)}, 文件大小: ${outputFileSizeMB.toFixed(
2
)}MB`
);
// 如果压缩后的文件大小仍然大于20MB
if (outputFileSizeMB > maxTargetSizeMB) {
scale -= step; // 减小缩放比例
if (scale < minScale) {
console.error("已达到最小缩放比例,无法进一步压缩。");
return;
}
attemptCompression(); // 递归调用,继续尝试
} else {
console.log("文件大小已降至20MB以下,完成压缩。");
}
});
};
attemptCompression();
}
// 使用示例
compressGIF("input.gif", "output.gif", 20);
在上面的这段代码当中,使用 child_process 模块中的 exec 函数:用于执行外部命令,这里用于调用 gifsicle 命令行工具。使用 fs 模块:用于访问文件系统,这里用于获取文件大小。
compressGIF 函数是是进行文件压缩的核心逻辑:
-
设置初始缩放比例 scale 为 0.95,即首次压缩时将图片尺寸缩减至原始的 95%。为避免压缩导致质量损失过大,设定最小缩放比例 minScale 为 0.1。每次压缩后,通过调整步长 step 值 0.05 来微调缩放比例。
-
使用 gifsicle 工具压缩 GIF 时,命令行中设置了优化级别--optimize=3 和缩放比例(使用 scale.toFixed(2)确保两位小数精度)。指定了输出和输入文件的路径。执行命令后,会检验输出文件的体积。如果仍超过目标值,则降低缩放比例后继续尝试。若缩放比例小于设定的最小值,将报错并终止流程。文件体积一旦达标或以下,便输出完成提示,结束压缩过程。
这段代码通过调整缩放比例和递归尝试,直到找到一个合适的缩放比例,使得压缩后的 GIF 文件大小不超过用户指定的最大大小。这种方法允许动态调整压缩强度,以适应不同的文件和压缩需求。
接下来执行终端命令来看看运行效果,如下图所示:
这样我们就可以对 gif 文件的内容进行成功压缩了,如果你还想对文件进行压缩的话,你还可以继续对压缩比例为 0.80 和 0.75 这个区间进行二分查找,查找到最逼近的那个 20MB 的那个比例。
总结
在上面的内容中我们只是简单地使用了 gifsicle 来实现 gif 压缩,它还可以实现更多的功能,如果感兴趣的朋友可以对它进行开发出更多有趣的功能。
转载自:https://juejin.cn/post/7329353489678909479