文章内容
GIF图形交换格式是一种位图图形文件格式,以8位色(即256种颜色)重现真彩色的图像。它实际上是一种压缩文档,采用LZW压缩算法进行编码,有效地减少了图像文件在网络上传输的时间。它是目前广泛应用于网络传输的图像格式之一。
一、优点
- 优秀的压缩算法使其在一定程度上保证图像质量的同时将体积变得很小。
- 可插入多帧,从而实现动画效果。
- 可设置透明色以产生对象浮现于背景之上的效果。
二、缺点
- 由于采用了8位压缩,最多只能处理256种颜色,故不宜应用于真彩图像。
三、代码实现
1、animated-gif-lib插件
https://github.com/rtyley/animated-gif-lib-for-java
2、Maven依赖
<dependency>
<groupId>com.madgag</groupId>
<artifactId>animated-gif-lib</artifactId>
<version>1.4</version>
</dependency>
3、工具类封装
import com.madgag.gif.fmsware.AnimatedGifEncoder;
import com.madgag.gif.fmsware.GifDecoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GifOperator {
/**
* 多图片转gif
* @param imageList
* @param outputPath
* @throws IOException
*/ public static void imagesToGif(List<String> imageList, String outputPath) throws IOException {
// 拆分一帧一帧的压缩之后合成
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
encoder.start(outputPath);
encoder.setRepeat(0);
for (String imagePath:
imageList) {
File outFile = new File(imagePath);
BufferedImage bufferedImage = ImageIO.read(outFile);
encoder.setDelay(100);
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
BufferedImage zoomImage = new BufferedImage(width, height, 3);
Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
Graphics gc = zoomImage.getGraphics();
gc.setColor(Color.WHITE);
gc.drawImage(image, 0, 0, null);
encoder.addFrame(zoomImage);
}
encoder.finish();
File outFile = new File(outputPath);
BufferedImage image = ImageIO.read(outFile);
ImageIO.write(image, outFile.getName(), outFile);
}
/**
* Gif转图片集
* @param imagePath
* @param outputDirPath
* @throws IOException
*/ public static void gifToImages(String imagePath, String outputDirPath) throws IOException {
GifDecoder decoder = new GifDecoder();
int status = decoder.read(imagePath);
if (status != GifDecoder.STATUS_OK) {
throw new IOException("read image " + imagePath + " error!");
}
for (int i = 0; i < decoder.getFrameCount();i++) {
BufferedImage bufferedImage = decoder.getFrame(i);// 获取每帧BufferedImage流
File outFile = new File(outputDirPath + i + ".png");
ImageIO.write(bufferedImage, "png", outFile);
}
}
/**
* 视频倒放
* @param imagePath
* @param outputPath
* @throws IOException
*/ public static void reverseGif(String imagePath, String outputPath) throws IOException {
GifDecoder decoder = new GifDecoder();
int status = decoder.read(imagePath);
if (status != GifDecoder.STATUS_OK) {
throw new IOException("read image " + imagePath + " error!");
}
// 拆分一帧一帧的压缩之后合成
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
encoder.start(outputPath);
encoder.setRepeat(decoder.getLoopCount());
for (int i = decoder.getFrameCount() -1; i >= 0; i--) {
encoder.setDelay(decoder.getDelay(i));// 设置播放延迟时间
BufferedImage bufferedImage = decoder.getFrame(i);// 获取每帧BufferedImage流
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
BufferedImage zoomImage = new BufferedImage(width, height, bufferedImage.getType());
Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
Graphics gc = zoomImage.getGraphics();
gc.setColor(Color.WHITE);
gc.drawImage(image, 0, 0, null);
encoder.addFrame(zoomImage);
}
encoder.finish();
File outFile = new File(outputPath);
BufferedImage image = ImageIO.read(outFile);
ImageIO.write(image, outFile.getName(), outFile);
}
}
4、测试
public static void main(String[] args) throws IOException {
String outputPath = "/home/lab/test/001.gif";
String imagePath = "/home/lab/test/33.gif";
reverseGif(imagePath, outputPath);
// Gif转图片
String dirPath = "/home/lab/test/22/";
gifToImages(imagePath, dirPath);
List<String> images = new ArrayList<>();
for (int i = 0; i < 111; i++) {
images.add(dirPath + i + ".png");
}
imagesToGif(images, "/home/lab/test/res.gif");
}