日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java创建GIF图,带透明背景

發(fā)布時(shí)間:2023/12/20 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java创建GIF图,带透明背景 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

需求

使用Java將序列圖轉(zhuǎn)換為GIF動(dòng)圖,如果序列圖本身包含alpha透明通道,生成的GIF圖也要保留透明通道。
對(duì)于序列圖轉(zhuǎn)換為GIF動(dòng)圖的需求,如果數(shù)量比較大,對(duì)性能要求較高,建議直接使用專業(yè)的處理工具,比如ImageMagick, GraphicsMagick ,FFmpeg 等,不僅可以轉(zhuǎn)換成GIF,還可以轉(zhuǎn)換出壓縮率更高的webp動(dòng)圖。

但是吧,有時(shí)候只需要一個(gè)很小的功能,引入一個(gè)大塊頭的組件,就有點(diǎn)殺雞用牛刀了。故這里介紹下怎么用簡單的Java代碼實(shí)現(xiàn)序列圖到GIF圖的轉(zhuǎn)換。

實(shí)現(xiàn)代碼

import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.FileImageOutputStream; import javax.imageio.stream.ImageOutputStream; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List;/*** 序列圖轉(zhuǎn)gif圖工具類** @author lixk*/ public class Gif {private ImageWriter writer;private ImageWriteParam params;private IIOMetadata metadata;/*** 創(chuàng)建GIF圖構(gòu)造方法** @param outputStream 輸出流* @param imageType 圖片類型* @param delay 序列幀間隔延遲,單位:毫秒* @param loop 是否循環(huán)播放* @throws IOException*/private Gif(ImageOutputStream outputStream, int imageType, int delay, boolean loop) throws IOException {this.writer = ImageIO.getImageWritersBySuffix("gif").next();this.params = writer.getDefaultWriteParam();this.metadata = writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromBufferedImageType(imageType), params);//配置元數(shù)據(jù)this.configureRootMetadata(delay, loop);//設(shè)置輸出流writer.setOutput(outputStream);writer.prepareWriteSequence(null);}/*** 配置元數(shù)據(jù)** @param delay 延遲,單位:毫秒* @param loop 是否循環(huán)播放* @throws IIOInvalidTreeException*/private void configureRootMetadata(int delay, boolean loop) throws IIOInvalidTreeException {String metaFormatName = metadata.getNativeMetadataFormatName();IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");graphicsControlExtensionNode.setAttribute("disposalMethod", "none");graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(delay / 10));graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");IIOMetadataNode appExtensionsNode = getNode(root, "ApplicationExtensions");IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");child.setAttribute("applicationID", "NETSCAPE");child.setAttribute("authenticationCode", "2.0");int loopContinuously = loop ? 0 : 1;child.setUserObject(new byte[]{0x1, (byte) (loopContinuously & 0xFF), (byte) ((loopContinuously >> 8) & 0xFF)});appExtensionsNode.appendChild(child);metadata.setFromTree(metaFormatName, root);}/*** 獲取元數(shù)據(jù)節(jié)點(diǎn)** @param rootNode 根節(jié)點(diǎn)* @param nodeName 節(jié)點(diǎn)名稱* @return IIOMetadataNode*/private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName) {int nNodes = rootNode.getLength();for (int i = 0; i < nNodes; i++) {if (rootNode.item(i).getNodeName().equalsIgnoreCase(nodeName)) {return (IIOMetadataNode) rootNode.item(i);}}IIOMetadataNode node = new IIOMetadataNode(nodeName);rootNode.appendChild(node);return (node);}/*** 將圖片數(shù)據(jù)寫入序列幀** @param img 圖片數(shù)據(jù)* @throws IOException*/public void writeToSequence(RenderedImage img) throws IOException {writer.writeToSequence(new IIOImage(img, null, metadata), params);}public void close() throws IOException {writer.endWriteSequence();}/*** 將序列圖數(shù)據(jù)轉(zhuǎn)換成gif圖并寫入輸出流** @param images 輸入序列圖* @param outputStream 圖像輸出流* @param delay 幀延遲,單位:毫秒* @param loop 是否循環(huán)播放* @param width 寬度* @param height 高度*/public static void convert(BufferedImage[] images, ImageOutputStream outputStream, int delay, boolean loop, Integer width, Integer height) {//圖像類型int imageType = images[0].getType();//縮放參數(shù)double sx = width == null ? 1.0 : ((double) width / images[0].getWidth());double sy = height == null ? 1.0 : ((double) height / images[0].getHeight());AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(sx, sy), null);try {Gif gif = new Gif(outputStream, imageType, delay, loop);for (BufferedImage image : images) {gif.writeToSequence(op.filter(image, null));}gif.close();outputStream.close();} catch (Exception e) {throw new RuntimeException("GIF convert error", e);}}/*** 將序列圖數(shù)據(jù)轉(zhuǎn)換成gif圖并寫入輸出流** @param images 輸入序列圖* @param outputStream 圖像輸出流* @param delay 幀延遲,單位:毫秒* @param loop 是否循環(huán)播放*/public static void convert(BufferedImage[] images, ImageOutputStream outputStream, int delay, boolean loop) {Gif.convert(images, outputStream, delay, loop, null, null);}/*** 將序列圖轉(zhuǎn)換成gif圖** @param imagePaths 輸入序列圖路徑* @param gifPath gif圖路徑* @param delay 幀延遲,單位:毫秒* @param loop 是否循環(huán)播放* @param width 寬度* @param height 高度*/public static void convert(String[] imagePaths, String gifPath, int delay, boolean loop, Integer width, Integer height) {try {BufferedImage[] images = new BufferedImage[imagePaths.length];for (int i = 0; i < imagePaths.length; i++) {images[i] = ImageIO.read(new File(imagePaths[i]));}FileImageOutputStream fileImageOutputStream = new FileImageOutputStream(new File(gifPath));convert(images, fileImageOutputStream, delay, loop, width, height);} catch (Exception e) {throw new RuntimeException("GIF convert error", e);}}/*** 將序列圖轉(zhuǎn)換成gif圖** @param imagePaths 輸入序列圖路徑* @param gifPath gif圖路徑* @param delay 幀延遲,單位:毫秒* @param loop 是否循環(huán)播放*/public static void convert(String[] imagePaths, String gifPath, int delay, boolean loop) {Gif.convert(imagePaths, gifPath, delay, loop, null, null);}}

測(cè)試代碼

public class GifTest {public static void main(String[] args) {//圖1String[] images = new String[]{"E:/圖片/圖標(biāo)/葉子.png", "E:/圖片/圖標(biāo)/four_leaf_clover.png", "E:/圖片/圖標(biāo)/Monster.png"};Gif.convert(images, "E:/output1.gif", 300, true);List<String> list = new ArrayList<>();//圖2for (int i = 1; i <= 5; i++) {list.add(String.format("F:/video/images/%04d.jpg", i));}Gif.convert(list.toArray(new String[]{}), "E:/output2.gif", 100, true, 192, 108);}}

輸出結(jié)果

output1.gif

output2.gif

總結(jié)

以上是生活随笔為你收集整理的Java创建GIF图,带透明背景的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。