鉴于最近需要合成一些GIF图像,而看到很多GIF制作都需要收费,所以花了些时间,能基本满足自己的需求了,读者可以随意自行复制修改。
效果(这里的图片本来可以达到是14M效果好,但是超过了csdn上传图片文件的大小限制,所以保持了缩放,图片帧也会有点少,只有4.7M,画面有会有点断断续续的,读者可以自己修改一些代码中有关FPS的参数,就会达到流畅的效果… )
相关代码如下:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.wu</groupId>
<artifactId>Edge</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.madgag</groupId>
<artifactId>animated-gif-lib</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
GIF.java
package com.wu;
import com.madgag.gif.fmsware.AnimatedGifEncoder;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
public class GIF extends JFrame {
private Robot robot = null;
private int times = 2; // 初始命中次数
private Rectangle rectangle = new Rectangle();
private BufferedImage[] images = null;
private int frames = 0; // 当前帧数
private final static int FRAMES = 150; // 最大帧数 只影响总帧数
private int framePerMS = 100; // 毫秒每帧 只影响帧捕捉时间间隔
private int currentProgress = 0; // 当前进度
private String path = null; // 文件路径
private FileOutputStream fileOutputStream = null; // 导出文件流
private final static String GIFNAME = "MyGif.gif"; // 默认文件名
private JTextField text = null;
public GIF(){
this.setSize(350,110);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("GIF生成");
this.setLayout(null);
this.images = new BufferedImage[FRAMES];
this.setAlwaysOnTop(true);
this.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
// System.out.println("这里工作了… ");
if(e.getKeyChar() == 's' && times > 0){
times--;
Point point = MouseInfo.getPointerInfo().getLocation(); // 获取当前鼠标坐标
if(times == 1){
rectangle.x = point.x;
rectangle.y = point.y;
}else if(times == 0){
if(point.x > rectangle.x && point.y < rectangle.y){ // 相对与第一个点的第一坐标系内
rectangle.height = rectangle.y - point.y;
rectangle.y = point.y;
rectangle.width = point.x - rectangle.x;
}else if(point.x < rectangle.x && point.y < rectangle.y){ // 相对于第一个点的第二坐标系
int temp = point.x;
point.x = rectangle.x;
rectangle.x = temp;
temp = point.y;
point.y = rectangle.y;
rectangle.y = temp;
rectangle.width = point.x - rectangle.x;
rectangle.height = point.y - rectangle.y;
}else if(point.x < rectangle.x && point.y > rectangle.y){ // 相对于第一个点的第三坐标系
rectangle.width = rectangle.x - point.x;
rectangle.height = point.y - rectangle.y;
rectangle.x = point.x;
}else{ // 相对于第一个点的第四坐标系
rectangle.width = point.x - rectangle.x;
rectangle.height = point.y - rectangle.y;
}
}
}
}
});
this.setResizable(false);
try{
Thread.sleep(100);
robot = new Robot();
}catch(Exception exception){}
JLabel fileName = null;
{
fileName = new JLabel("导出位置:");
this.add(fileName);
fileName.setBounds(5,10,83,30);
final Font font = new Font("宋体",Font.BOLD,17);
fileName.setFont(font);
text = new JTextField("\\");
this.add(text);
text.setToolTipText("GIF文件导出位置");
text.setEditable(false); // 初始设置为不可编辑状态
text.setForeground(Color.gray);
text.setBackground(Color.white);
text.setFont(font);
text.setBounds(92,10,242,30);
{
text.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
// System.out.println("鼠标退出… ");
text.setFocusable(false);
text.setEditable(false);
try{ // 处理文件位置异常问题
path = text.getText();
File file = new File(path);
if(path.charAt(path.length() - 1) == '\\'){
fileOutputStream = new FileOutputStream(file+GIFNAME);
}else{
fileOutputStream = new FileOutputStream(file+"\\"+GIFNAME);
}
}catch(Exception exception){
JOptionPane jOptionPane = new JOptionPane();
JLabel jLabel = new JLabel("导出文件目录错误,并重置矩形区域!");
jLabel.setFont(font);/**
Component[] components = jOptionPane.getComponents();
JPanel jPanel = (JPanel) components[1];
JButton jButton = (JButton) jPanel.getComponent(0);
jButton.setFont(font);
jButton.setBorderPainted(false);
jButton.setBorder(BorderFactory.createRaisedBevelBorder());
**/
jOptionPane.showMessageDialog(null,jLabel,"Error",JOptionPane.WARNING_MESSAGE);
times = 2; // 还原
text.setText("\\");
}
}
@Override
public void mouseClicked(MouseEvent e) {
// System.out.println("鼠标点击… ");
text.setEditable(true); // 设置为可编辑状态
text.setFocusable(true);
}
});
}
}
int delay = framePerMS; // 监听
final JProgressBar progressBar = new JProgressBar();
// 设置进度的 最小值 和 最大值
progressBar.setMinimum(0);
progressBar.setMaximum(100);
// 设置当前进度值
progressBar.setValue(currentProgress);
// 绘制百分比文本(进度条中间显示的百分数)
progressBar.setStringPainted(true);
progressBar.setBounds(20,50,300,20);
this.add(progressBar);
this.setVisible(true);
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(rectangle.x >= 0 && rectangle.y >= 0 && rectangle.width > 0 && rectangle.height > 0 &&
frames < FRAMES){
try{
images[frames++] = robot.createScreenCapture(rectangle);
// ImageIO.write(image,"jpg",new File("C:\\Users\\Administrator\\OneDrive\\图片\\1.jpg"));
progressBar.setValue(frames*100/FRAMES);
}catch(Exception exception){
exception.printStackTrace();
}
}else if(frames >= FRAMES){
try{
generateGIF();
}catch(Exception exception){
System.exit(0);
}
}
}
};
// 启动计时器
new Timer(delay,actionListener).start();
}
/**
* 生成GIF
*/
public void generateGIF() throws Exception{
AnimatedGifEncoder animatedGifEncoder = new AnimatedGifEncoder();
try{
animatedGifEncoder.start(fileOutputStream);
animatedGifEncoder.setDelay(framePerMS);
animatedGifEncoder.setRepeat(0);
for(int i = 0 ; i < FRAMES ; i++){
animatedGifEncoder.addFrame(images[i]);
}
animatedGifEncoder.finish();
System.exit(0); // 退出
}catch(Exception e){
throw e;
}
}
public static void main(String[] args) throws Exception{
new GIF();
}
}
功能说明:第一次点击's'键确定一个矩形GIF图片角,再次点击's'键确定另一个图片角,然后开始根据该矩形区域截取视频帧,最终等待一会,并把合成的GIF图片保存到自定义目录下,默认文件名为MyGif.gif。
读者有疑问欢迎留言…