在Android平臺(tái)下合成Gif

原文首發(fā)于我的個(gè)人博客網(wǎng)站,歡迎訪問(wèn),轉(zhuǎn)載請(qǐng)注明出處

本文介紹在 Android 平臺(tái)下合成 GIF 的方法,查閱資料的過(guò)程中發(fā)現(xiàn)大致有兩種方案。

  1. 使用 giflen (一個(gè) C 的合成 gif 的庫(kù)) 進(jìn)行 gif 合成。

  2. 使用 java 層的 GifEncoder、LZWEncoderNeuQuant 來(lái)進(jìn)行 gif 合成。

當(dāng)然二者都是基于 LZW 算法,簡(jiǎn)單測(cè)試的結(jié)果是,速度上差不多,由于對(duì) C 不是很擅長(zhǎng),因此我選擇了 java 層進(jìn)行合成的方法,但是兩種方法速度上都是 很慢很慢 ??。

因此本文還將會(huì)使用多線程獨(dú)立編碼的方法來(lái)進(jìn)行優(yōu)化,每幀圖片并行編碼,加快合成速度,現(xiàn)在的成果是 600 * 450 的圖片 20 張的話,時(shí)間大約在 12s 左右。

本文相關(guān)源碼在 GitHub - GifMaker

使用 giflen 合成

使用 jni 合成,感興趣的同學(xué)可以 google 一下 giflen 這個(gè)庫(kù),這里有一個(gè)編譯好的 sojar 文件,以及相關(guān) C 源碼,備份在 GitHub 上,有需要的同學(xué)可以直接下載使用。經(jīng)過(guò)我的簡(jiǎn)單嘗試發(fā)現(xiàn),使用 so 合成的速度和 java 合成的速度差不多,都是慢的要死...

優(yōu)化后的 java 合成

原始的合成方法,真的慢...特別慢,簡(jiǎn)直不能忍。

原始的合成方法是將每一個(gè) Bitmap 使用 LZWEncoder 進(jìn)行編碼,由于是一個(gè)串行的邏輯,后面的圖片需要等待前面的編碼完成才可以繼續(xù)下一張編碼,優(yōu)化后的邏輯是啟動(dòng)一個(gè)線程池,每張圖片獨(dú)立編碼,最后在所有圖片編碼完成之后輸出流合并,輸出到文件中,就完成了 gif 的合成。

缺點(diǎn):大量的 Bitmap 持有在內(nèi)存中并行編碼,可能會(huì) OOM,不過(guò)我測(cè)試 20 張 450 * 600 的圖片,暫時(shí)沒(méi)有出現(xiàn)問(wèn)題。合成的圖片要求寬高應(yīng)該是一樣的,當(dāng)然使用寬高不一致的圖片也不會(huì)有問(wèn)題,但是會(huì)優(yōu)先使用第一張的圖片的寬高作為 gif 的寬高,出來(lái)的圖片就有些尷尬,因此圖片的轉(zhuǎn)換和處理需要在外面完成。

簡(jiǎn)單演示

private void composeGif(List<Bitmap> bitmaps) {
    String absolutePath = new File(Environment.getExternalStorageDirectory()
            , System.currentTimeMillis() + ".gif").getAbsolutePath();
    new GifMaker(100, mExecutorService)
            .makeGifInThread(bitmaps, absolutePath, new GifMaker.OnGifMakerListener() {
                @Override
                public void onMakeGifSucceed(String outPath) {
                    if (!isFinishing()) {
                        GlideUtils.with(mActivity, outPath).into(mImageView);
                    }
                }
            });
}

看一下輸出的結(jié)果,20 張大約維持在 12s 左右

I/GifMaker: 完成第10幀,耗時(shí):9.594 s - bitmap [600,450]
I/GifMaker: 完成第11幀,耗時(shí):9.774 s - bitmap [600,450]
I/GifMaker: 完成第18幀,耗時(shí):9.880 s - bitmap [450,600]
I/GifMaker: 完成第9幀,耗時(shí):10.41 s - bitmap [600,450]
I/GifMaker: 完成第17幀,耗時(shí):10.145 s - bitmap [450,600]
I/GifMaker: 完成第16幀,耗時(shí):10.331 s - bitmap [450,600]
I/GifMaker: 完成第6幀,耗時(shí):10.586 s - bitmap [450,600]
I/GifMaker: 完成第5幀,耗時(shí):10.557 s - bitmap [450,600]
I/GifMaker: 完成第8幀,耗時(shí):10.701 s - bitmap [450,600]
I/GifMaker: 完成第15幀,耗時(shí):10.715 s - bitmap [450,600]
I/GifMaker: 完成第4幀,耗時(shí):10.736 s - bitmap [450,600]
I/GifMaker: 完成第1幀,耗時(shí):10.835 s - bitmap [450,600]
I/GifMaker: 完成第19幀,耗時(shí):10.842 s - bitmap [450,600]
I/GifMaker: 完成第13幀,耗時(shí):10.940 s - bitmap [450,600]
I/GifMaker: 完成第0幀,耗時(shí):10.944 s - bitmap [450,600]
I/GifMaker: 完成第14幀,耗時(shí):10.967 s - bitmap [450,600]
I/GifMaker: 完成第3幀,耗時(shí):10.989 s - bitmap [450,600]
I/GifMaker: 完成第12幀,耗時(shí):10.994 s - bitmap [450,600]
I/GifMaker: 完成第2幀,耗時(shí):10.994 s - bitmap [450,600]
I/GifMaker: 完成第7幀,耗時(shí):11.148 s - bitmap [450,600]
I/GifMaker: 合成完成,耗時(shí):11.167 s
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容