Java實(shí)現(xiàn)動(dòng)態(tài)生成GIF圖像詳解
背景
在互聯(lián)網(wǎng)上有許多有趣的場(chǎng)景,其中的一種就是動(dòng)圖。這不是視頻,而是一種GIF圖像信息。雖然沒(méi)有聲音,卻給我們帶來(lái)了無(wú)窮的樂(lè)趣。如果說(shuō)斗圖是曾經(jīng)聊天或者網(wǎng)聊的樂(lè)趣,那動(dòng)圖一定是承包了這種歡樂(lè)的技術(shù)原理。
GIF的全稱(chēng)是Graphics Interchange Format,可譯為圖形交換格式,用于以超文本標(biāo)志語(yǔ)言(Hypertext Markup Language)方式顯示索引彩色圖像,在因特網(wǎng)和其他在線(xiàn)服務(wù)系統(tǒng)上得到廣泛應(yīng)用。GIF是一種公用的圖像文件格式標(biāo)準(zhǔn),版權(quán)歸Compu Serve公司所有。
那么這些GIF圖片可以使用什么技術(shù)來(lái)生成呢?今天分享一種JAVA的實(shí)現(xiàn),基于開(kāi)源庫(kù)AnimatedGifEncoder,動(dòng)態(tài)構(gòu)建GIF圖庫(kù)。掌握了這個(gè)技術(shù),加上你天才的頭腦,一定可以發(fā)揮出獨(dú)特的創(chuàng)意,創(chuàng)作出充滿(mǎn)智慧或者可以令人腦洞大開(kāi)的內(nèi)容。不多說(shuō),正式開(kāi)始吧。
特點(diǎn)
GIF格式的圖像文件具有如下特點(diǎn):
(1)GIF格式圖像文件的擴(kuò)展名是“.gif”;
(2)對(duì)于灰度圖像表現(xiàn)最佳;
(3)具有GIF87a和GIF89a兩個(gè)版本;
(4)采用改進(jìn)的LZW壓縮算法處理圖像數(shù)據(jù);
(5)調(diào)色板數(shù)據(jù)有通用調(diào)色板和局部調(diào)色板之分,有不同的顏色取值;
(6)不支持24bit彩色模式,最多存儲(chǔ)256色。
用途
①GIF是壓縮格式的文件,用于減少文件在網(wǎng)絡(luò)上傳遞的時(shí)間;
②GIF的位深為1-8bit,單色透明,由一個(gè)最多256種顏色的調(diào)色板實(shí)現(xiàn),圖像大小最多為64K×64K像素。GIF主要是為一個(gè)數(shù)據(jù)流而設(shè)計(jì)的一種傳輸格式,而不是作為文件的存當(dāng)格式,因此它是最復(fù)雜的一種圖像文件格式;
③支持Bitmap、Grayscale和索引彩色模式。
AnimatedGifEncoder簡(jiǎn)介
AnimatedGifEncoder是Kevin Weiner編寫(xiě)的,其作者授權(quán)所有人可以以任何方式使用這份代碼,但是需要注意代碼中所使用的LZW算法由Unisys掌握專(zhuān)利權(quán)。不過(guò)鑒于此專(zhuān)利在2006年就已經(jīng)在大部分國(guó)家及地區(qū)過(guò)期了,所以現(xiàn)在應(yīng)該可以放心地使用了。
GIF創(chuàng)作生成
一、創(chuàng)建maven項(xiàng)目
新建一個(gè)maven項(xiàng)目,引入相關(guān)資源包。關(guān)鍵代碼如下所示:
<!-- https://mvnrepository.com/artifact/com.madgag/animated-gif-lib --> <dependency> <groupId>com.madgag</groupId> <artifactId>animated-gif-lib</artifactId> <version>1.4</version> </dependency>
二、自定義生成
自定義生成之指,直接使用系統(tǒng)創(chuàng)建的方式來(lái)生成gif,不使用外部的圖片、視頻等資源,直接在界面上繪制一個(gè)GIF圖。下面給出關(guān)鍵代碼:
package com.yelang.mp42gif;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import com.madgag.gif.fmsware.AnimatedGifEncoder;
public class PageTest {
public static final int SIZE = 200;
public static void main(String[] args) throws IOException {
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
encoder.start("D:/giftest/out.gif");
encoder.setTransparent(Color.WHITE);
encoder.setRepeat(0);
encoder.setDelay(50);
BufferedImage img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2d = img.createGraphics();
for (int i=0; i<100; i++) {
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, SIZE, SIZE);
g2d.setColor(Color.BLACK);
g2d.drawOval(0, i, 120, 120);
encoder.addFrame(img);
}
g2d.dispose();
encoder.finish();
System.out.println("完成");
}
}執(zhí)行完成后,在目標(biāo)文件夾下,可以看到輸出了gif圖片,

將out.gif文件拖拽到瀏覽器中,可以看到動(dòng)態(tài)的效果,如下圖:

三、自定義將多張圖片合成
在一些需求里,比如根據(jù)給定的多張圖片(比如下面1-4.jpg四張)來(lái)合成一張gif圖片。這種需求又如何來(lái)實(shí)現(xiàn)呢?這里重點(diǎn)介紹這種需求的解決方案。




1、定義原始的數(shù)據(jù)源
BufferedImage image1 = ImageIO.read(new File("D:/giftest/dir2/1.jpg"));
BufferedImage image2 = ImageIO.read(new File("D:/giftest/dir2/2.jpg"));
BufferedImage image3 = ImageIO.read(new File("D:/giftest/dir2/3.jpg"));
BufferedImage image4 = ImageIO.read(new File("D:/giftest/dir2/4.jpg"));上述代碼將原始的圖片轉(zhuǎn)換成輸入流備用
2、gif對(duì)象設(shè)置
AnimatedGifEncoder e = new AnimatedGifEncoder();
// 設(shè)置生成圖片大小
e.setSize(4000, 3000);
//生成的圖片路徑
e.start("D:/giftest/dir2/demo1.gif");
//圖片之間間隔時(shí)間
e.setDelay(500);
//重復(fù)次數(shù) 0表示無(wú)限重復(fù) 默認(rèn)不重復(fù)
e.setRepeat(0);
e.setQuality(5);3、圖片填充
//添加圖片 e.addFrame(image1); e.addFrame(image2); e.addFrame(image3); e.addFrame(image4); e.finish();
完成的代碼如下:
public static void test3() throws IOException {
BufferedImage image1 = ImageIO.read(new File("D:/giftest/dir2/1.jpg"));
BufferedImage image2 = ImageIO.read(new File("D:/giftest/dir2/2.jpg"));
BufferedImage image3 = ImageIO.read(new File("D:/giftest/dir2/3.jpg"));
BufferedImage image4 = ImageIO.read(new File("D:/giftest/dir2/4.jpg"));
AnimatedGifEncoder e = new AnimatedGifEncoder();
// 設(shè)置生成圖片大小
e.setSize(4000, 3000);
//生成的圖片路徑
e.start("D:/giftest/dir2/demo1.gif");
//圖片之間間隔時(shí)間
e.setDelay(500);
//重復(fù)次數(shù) 0表示無(wú)限重復(fù) 默認(rèn)不重復(fù)
e.setRepeat(0);
e.setQuality(5);
//添加圖片
e.addFrame(image1);
e.addFrame(image2);
e.addFrame(image3);
e.addFrame(image4);
e.finish();
System.out.println("finish");
}執(zhí)行完成后,可以看到生成GIF圖如下:

話(huà)外題-懷念巨人
GIF的發(fā)明者是美國(guó)計(jì)算機(jī)科學(xué)家、GIF圖像格式發(fā)明人斯蒂芬•威爾海特(Stephen Wilhite)。據(jù)美國(guó)媒體報(bào)道,當(dāng)?shù)貢r(shí)間3月14日,gif的發(fā)明者斯蒂芬·威爾海特因疫情去世,享年74歲。他的妻子凱瑟琳在接受采訪(fǎng)時(shí)提到,威爾海特去世前他的家人都陪伴在他的身邊,而在訃告中也提到“盡管取得了諸多成就,但他仍然是一個(gè)非常謙遜、善良的好人。”

總結(jié)
本文簡(jiǎn)要講述了GIF圖像知識(shí),并且以JAVA技術(shù)為例,介紹了后臺(tái)生成GIF的技術(shù),并提供較詳細(xì)的代碼示例,希望對(duì)您有幫助。最后懷念因新冠感染去世的GIF的發(fā)明者,斯蒂芬•威爾海特。感恩這個(gè)時(shí)代,我們站在無(wú)數(shù)巨人的肩膀上,以至于可以專(zhuān)心去享受這些技術(shù)帶來(lái)的快感。
以上就是Java實(shí)現(xiàn)動(dòng)態(tài)生成GIF圖像詳解的詳細(xì)內(nèi)容,更多關(guān)于Java生成GIF的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入學(xué)習(xí)java并發(fā)包ConcurrentHashMap源碼
這篇文章主要介紹了深入學(xué)習(xí)java并發(fā)包ConcurrentHashMap源碼,整個(gè) ConcurrentHashMap 由一個(gè)個(gè) Segment 組成,Segment 代表”部分“或”一段“的意思,所以很多地方都會(huì)將其描述為分段鎖。,需要的朋友可以參考下2019-06-06
springboot前端傳參date類(lèi)型后臺(tái)處理的方式
這篇文章主要介紹了springboot前端傳參date類(lèi)型后臺(tái)處理的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Java如何實(shí)現(xiàn)可折疊Panel方法示例
這篇文章主要給大家介紹了關(guān)于利用Java如何實(shí)現(xiàn)可折疊Panel的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
spring?boot?executable?jar/war?原理解析
spring boot里其實(shí)不僅可以直接以 java -jar demo.jar的方式啟動(dòng),還可以把jar/war變?yōu)橐粋€(gè)可以執(zhí)行的腳本來(lái)啟動(dòng),比如./demo.jar,這篇文章主要介紹了spring?boot?executable?jar/war?原理,需要的朋友可以參考下2023-02-02
SpringMVC處理multipart請(qǐng)求的示例代碼
本篇文章主要介紹了SpringMVC處理multipart請(qǐng)求的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
微服務(wù)架構(gòu)設(shè)計(jì)RocketMQ基礎(chǔ)及環(huán)境整合
這篇文章主要介紹了微服務(wù)架構(gòu)設(shè)計(jì)入門(mén)RocketMQ的基礎(chǔ)及環(huán)境整合實(shí)現(xiàn)步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10
IDEA如何對(duì)多線(xiàn)程進(jìn)行debug的示例詳解
開(kāi)發(fā)中使用到多線(xiàn)程的時(shí)候不少,但是debug起來(lái)還是比較困難的,因?yàn)槟J(rèn)每次只會(huì)進(jìn)入一個(gè)線(xiàn)程,這樣有些問(wèn)題是發(fā)現(xiàn)不了的,其實(shí)IDEA也是支持進(jìn)入每個(gè)線(xiàn)程來(lái)debug的,本文給大家介紹了IDEA如何對(duì)多線(xiàn)程進(jìn)行debug的示例,需要的朋友可以參考下2024-05-05
java正則匹配讀取txt文件提取特定開(kāi)頭和結(jié)尾的字符串
通常我們可以直接通過(guò)文件流來(lái)讀取txt文件的內(nèi)容,但有時(shí)候也會(huì)遇到問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于java正則匹配讀取txt文件提取特定開(kāi)頭和結(jié)尾的字符串的相關(guān)資料,需要的朋友可以參考下2022-11-11
Java使用@Validated注解進(jìn)行參數(shù)驗(yàn)證的方法
這篇文章主要介紹了Java使用@Validated注解進(jìn)行參數(shù)驗(yàn)證的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08

