欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript純前端實(shí)現(xiàn)在線GIF壓縮

 更新時(shí)間:2024年03月06日 08:42:09   作者:可樂雞翅kele  
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript純前端實(shí)現(xiàn)在線GIF壓縮工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

原因是我在寫公眾號(hào)文章的時(shí)候,公眾號(hào)編輯器只能上傳最大10MGIF,而我剛好需要上傳的GIF超過了這個(gè)閾值。

所以我就隨便搜了一個(gè)壓縮GIF的工具,有一些壓縮完了下載需要付費(fèi),有一些不付費(fèi)就只能壓縮低于某個(gè)閾值的文件。

不過也能理解吧,畢竟別人也是需要賺錢的,這種文件的處理如果放在服務(wù)端做,那必然是要耗費(fèi)不少資源的,如果放在純前端做,又不能保證文件處理的速度。

然后我就想著GIF壓縮應(yīng)該不難吧,應(yīng)該有現(xiàn)成的工具庫吧,于是我就開始動(dòng)手去實(shí)現(xiàn)一個(gè)GIF壓縮工具。這里我很執(zhí)拗地要去實(shí)現(xiàn)一個(gè)純客戶端的GIF壓縮(也不知道為啥我這么執(zhí)拗。)

初探GIF壓縮

我們都知道GIF是一張張靜態(tài)的圖片播放形成的動(dòng)圖,所以我一開始就想著,如果我有一個(gè)庫,能幫我把GIF所有幀都抽取出來,然后我對(duì)所有幀的圖片進(jìn)行一個(gè)縮放的有損壓縮,壓縮完之后再把所有圖片合成一個(gè)新的GIF,那么我不就把GIF給壓縮了么。

然后我就找到了gif.jsomggif.js這兩個(gè)庫:

  • omggif負(fù)責(zé)解析GIF,獲取GIF的每一幀圖像
  • 把獲取到的每一幀圖像進(jìn)行處理了之后,使用gif.js合成GIF

那么可以寫出下面的代碼,以下的代碼就是一個(gè)分離GIF幀+合成GIF的代碼,還沒有加上壓縮每一幀的邏輯:

fetch("/test.gif")
  .then((response) => response.arrayBuffer())
  .then((buffer) => {
    // 用omggif解析GIF
    let reader = new omggif.GifReader(new Uint8Array(buffer));

    // 創(chuàng)建新的gif.js實(shí)例
    let gif = new GIF({
      workers: 2,
      quality: 5,
      width: reader.width,
      height: reader.height,
    });

    const width = reader.width;
    const height = reader.height;

    // 創(chuàng)建canvas元素
    const imgs = [];
    // 遍歷所有的frames,并添加到gif.js實(shí)例中
    for (let i = 0; i < reader.numFrames(); i++) {
      let frameInfo = reader.frameInfo(i);
      let canvas = document.createElement("canvas");
      canvas.width = width;
      canvas.height = height;
      let ctx = canvas.getContext("2d", { willReadFrequently: true });
      let imageData = ctx.createImageData(width, height);
      reader.decodeAndBlitFrameRGBA(i, imageData.data);
      ctx.putImageData(imageData, 0, 0);
      gif.addFrame(ctx, { delay: frameInfo.delay });
      imgs.push(canvas.toDataURL());
    }

    //預(yù)覽分離出來的幀
    const div = document.createElement("div");
    imgs.forEach((url) => {
      const img = document.createElement("img");
      img.src = url;
      div.appendChild(img);
    });
    document.body.appendChild(div);

    // 生成GIF并下載
    gif.on("finished", function (blob) {
      console.log("finish");
      let url = URL.createObjectURL(blob);
      document.querySelector("#img").src = url;
      const a = document.createElement("a");
      a.download = true;
      a.href = url;
      a.click();
    });

    gif.render();
  });

但是我分離幀之后發(fā)現(xiàn),分離出來的幀相當(dāng)奇怪:

而且合并之后的GIF感覺完全被破壞掉了,我不清楚是不是我的這種思路本身就是不可行的,還是說這兩個(gè)庫不能這么用。是不是我這樣做了之后導(dǎo)致描述GIF的信息丟了?(比如調(diào)色盤或者其他的一些全局信息,評(píng)論區(qū)有大神可以指導(dǎo)一下么)

這種方式不可行之后,我又嘗試了一下別的方式。這一次我不再寄希望于純js實(shí)現(xiàn)的庫,而是往wasm方向去探索。

然后我嘗試使用Rust去解析GIF,并返回所有解析后的圖片給前端,前端再去做有損壓縮,但這一做法耗時(shí)太長(zhǎng),也不是成功的嘗試,所以代碼就不放出來了。

接著我就想到了ffmpeg,我知道它有壓縮GIF的功能,而且他也有成熟的wasm版本,可以便捷地在前端引入使用,但是它壓縮后近10M的體積依舊讓人望而生畏。

gifsicle

在繼續(xù)搜索GIF壓縮等關(guān)鍵詞時(shí),發(fā)現(xiàn)了gifsicle這個(gè)庫。它是一個(gè)用于處理GIF圖像的命令行工具和庫,提供了很多功能包括創(chuàng)建、編輯、優(yōu)化和調(diào)整GIF

ffmpeg對(duì)比起來,它是一個(gè)更專注于GIF處理的庫,所以體積會(huì)比ffmpeg肯定小不少,所以我就想著能不能弄一個(gè)它的wasm版本移植到瀏覽器中使用。

后面還真讓我找到了它對(duì)應(yīng)的wasm版本,具體鏈接可以查看:gifsicle-wasm-browse,這個(gè)庫GZip壓縮之后只有150K左右,完全不用擔(dān)心體積問題。

使用gifsicle的時(shí)候,常常使用如下的手段去減少GIF的體積:

-O參數(shù):

  • O1:該選項(xiàng)對(duì)應(yīng)于輕度優(yōu)化,它會(huì)執(zhí)行一些基本的優(yōu)化步驟,刪除無用的圖像數(shù)據(jù)和元數(shù)據(jù),以減小文件大小。這個(gè)級(jí)別的優(yōu)化通常執(zhí)行較快,但可能不會(huì)最大限度地減小文件大小。
  • O2:中度優(yōu)化比輕度優(yōu)化更深入,它可能會(huì)花費(fèi)更多的時(shí)間來尋找更多的優(yōu)化機(jī)會(huì)。這通常會(huì)導(dǎo)致更好的壓縮比和更小的文件大小。
  • O3:最大優(yōu)化級(jí)別會(huì)執(zhí)行最深入的優(yōu)化,可能需要更多的時(shí)間來完成,但通常會(huì)實(shí)現(xiàn)最大的文件大小減小。這個(gè)級(jí)別的優(yōu)化可能對(duì)CPU和內(nèi)存的需求更高。

--loosy

  • --lossy 會(huì)減少圖像中使用的顏色數(shù)量,從而減小顏色表的大小。這會(huì)導(dǎo)致顏色的近似和失真,因?yàn)樵嫉念伾畔?huì)被近似為顏色表中的顏色。
  • --lossy 程度下,一些微小的圖像細(xì)節(jié)可能會(huì)被去除,以進(jìn)一步減小文件大小。這可能導(dǎo)致圖像的一些細(xì)節(jié)在視覺上的損失

減少顏色數(shù):

  • GIF中每個(gè)像素可以使用圖像調(diào)色板中的一種顏色,而顏色數(shù)量表示這些不同顏色的總數(shù)。GIF使用的顏色調(diào)色板通常是8位色,允許最多256種不同的顏色。
  • 減少GIF的顏色數(shù)量可以降低圖像的文件大小,因?yàn)閳D像中使用的顏色越少,每個(gè)像素的顏色信息所需的位數(shù)就越少。然而,減少顏色數(shù)量也可能導(dǎo)致圖像的視覺質(zhì)量下降,尤其是對(duì)于包含大量顏色細(xì)節(jié)的圖像。

刪除注釋和元數(shù)據(jù)

裁剪和縮?。鹤钪庇^的壓縮手段,屬于有損壓縮

調(diào)整幀速率:相當(dāng)于減少組成這個(gè)GIF文件的圖片數(shù)量,也是有損壓縮

具體實(shí)現(xiàn)

首先安裝gifsicle-wasm-browser這個(gè)包,然后簡(jiǎn)單搭建一個(gè)表單如下:

gifsicle的具體文檔,可以點(diǎn)擊這里查看。

在前端中可以參照以下方式來使用gifsicle

  gifsicle
    .run({
      input: [
        {
          file: buffer,
          name: "input.gif",
        },
      ],
      command: [command],
    })
    .then(async (res) => {

    });

GIF的壓縮過程中,常常會(huì)把多種壓縮方式結(jié)合起來使用。如果單純的想壓縮GIF的體積而不考慮GIF的質(zhì)量,那就直接使用縮放進(jìn)行有損壓縮就好了;如果想保留GIF的質(zhì)量的同時(shí)壓縮GIF的體積,那還是需要多方參數(shù)的組合嘗試。

壓縮前的圖像:

以下是我一些嘗試壓縮的參數(shù)以及壓縮前后的對(duì)比:

壓縮參數(shù): -O2 --lossy=180 input.gif --colors 64 --scale 0.8 -o /out/out.gif

  • 壓縮后:體積:4.0MB,顏色數(shù)量:64,幀數(shù)不變,分辨率不變
  • 執(zhí)行時(shí)間:72s

壓縮參數(shù):-O2 --lossy=180 input.gif --colors 32 --scale 0.8 -o /out/out.gif

  • 壓縮后:體積:3MB,顏色數(shù)量:32,幀數(shù)不變,分辨率不變
  • 執(zhí)行時(shí)間:60s
  • 可見圖像顏色已經(jīng)嚴(yán)重變形

壓縮參數(shù):input.gif --colors 64 --scale 0.5 -o /out/out.gif

  • 壓縮后:體積:3MB,顏色數(shù)量:64,幀數(shù)不變,分辨率變?yōu)橹耙话?/li>
  • 執(zhí)行時(shí)間:19s
  • 圖像較為模糊,顏色也有少許變形

可以看到在大多數(shù)的壓縮參數(shù)下,都需要較長(zhǎng)的執(zhí)行時(shí)間,這是因?yàn)檫@個(gè)wasm包還沒有實(shí)現(xiàn)多核處理,還沒辦法利用多核CPU的優(yōu)勢(shì),所以處理起來時(shí)間會(huì)比較長(zhǎng)。

總結(jié)

如果這個(gè)包實(shí)現(xiàn)了多核處理,執(zhí)行時(shí)間能縮短一些的話,那么我覺得會(huì)有更多的GIF處理會(huì)放在前端來做。

我一直覺得純前端處理是一件很酷的事情,對(duì)于開發(fā)者來說,無需承擔(dān)昂貴的計(jì)算資源成本,如果不想承擔(dān)服務(wù)器成本,這個(gè)時(shí)候還有一種解決方法就是做成桌面應(yīng)用,把任務(wù)處理的二進(jìn)制文件打包下載到用戶本地。

但如果是純前端實(shí)現(xiàn)的話,對(duì)于使用者來說,無需下載任何東西,點(diǎn)開即用。

所以后面也理解了網(wǎng)上一些壓縮GIF需要收費(fèi)的工具,一個(gè)好的在線GIF壓縮產(chǎn)品它能同時(shí)保證執(zhí)行速度、壓縮體積、壓縮質(zhì)量,這還是相當(dāng)不容易的。

以上就是JavaScript純前端實(shí)現(xiàn)在線GIF壓縮的詳細(xì)內(nèi)容,更多關(guān)于JavaScript GIF壓縮的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論