使用ImageMagick实现多张图片拼接为gif(多线程版)

官网: https://imagemagick.org/

直接上代码

java 复制代码
ExecutorService es = Executors.newFixedThreadPool(10);
List<File> images = getImageFiles(sceneDir);
CountDownLatch cdl = new CountDownLatch(images.size());
// 拷贝图片
for (File file : images) {
	System.out.println(file.getPath());
	final File dstImage = new File(deploySceneImageDir, file.getName());
	es.submit(new Runnable() {
		@Override
		public void run() {
			// todo 预处理
			cdl.countDown();
		}
	});
}

logger.info("等待图片预处理完成");
cdl.await();
String gifPath = String.join(File.separator,deploySceneDir,"poster.gif");
// 拼接gif
es.submit(new Runnable() {
	@Override
	public void run() {
		toGif(new File(deploySceneImageDir),gifPath,delay,0);
	}
});
logger.info("完成图片的处理");
es.shutdown();

checker

java 复制代码
public boolean toGif(File srcDir, String outputImagePath,int delay,int loop){
		File[] files = srcDir.listFiles();
		if(files == null){
			return false;
		}
		int gifExpectSize = 0;
		List<String> images = new ArrayList<>();
		for (File file : files) {
			images.add("\""+file.getPath()+"\"") ;// 处理"convert: unable to open image"问题
			gifExpectSize += file.length();
		}
		System.out.println("期望的gif大小:"+(gifExpectSize/1024.0/1024.0)+"M");
		String imagePaths = String.join(" ",images);
		return toGif(imagePaths,outputImagePath,delay,loop);
	}

toGif方法

java 复制代码
public boolean toGif(String inputImagePath, String outputImagePath,int delay,int loop){
		List<String> command = new ArrayList<>();
		// -delay参数应该在输入图像之前指定
		command.add("-delay");// 指定每一帧之间的延迟时间(以毫秒为单位),这里是100毫秒。
		command.add(delay+"");
		command.add(inputImagePath);
		command.add("-loop");
		command.add(loop+"");
		command.add(outputImagePath);
		return execute(command);
	}

execute方法

java 复制代码
public boolean execute(List<String> command) {
		command.add(0,convertPath);
		try {
			String execCommand = Arrays.toString(command.toArray())
					.replace(",","")
					.replace("[","")
					.replace("]","");
			System.out.println("图像处理命令:"+execCommand);
			// 执行命令
			ProcessBuilder pb = new ProcessBuilder(command);
			Process process = pb.start();
			// 处理标准错误流
			BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
			String line;
			while ((line = errorReader.readLine()) != null) {
				System.err.println(line);
			}
			// 等待命令执行完成
			int exitCode = process.waitFor();
			return  exitCode == 0;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return false;
	}
java 复制代码
public List<File> getImageFiles(String sceneDir){
		List<File> ret = new ArrayList<>();
		if (new File(sceneDir).listFiles() == null) {
			return ret;
		}

		for (File file : new File(sceneDir).listFiles()) {
			if(file.getName().endsWith(".JPG")){
				ret.add(file);
			}
		}
		return ret;
	}
相关推荐
亦暖筑序7 分钟前
重新认识 AgentScope-Java 2.0:ReActAgent 负责推理,HarnessAgent 负责运行
java·后端·agent
会博通·代码搬运工9 分钟前
会博通API对接实战:工程企业文档分布式采集系统的技术实现与Python SDK详解
开发语言·分布式·python·线性代数·矩阵·架构·电子档案合规
木井巳15 分钟前
【DFS解决floodfill算法】岛屿的最大面积
java·算法·leetcode·深度优先
林森lsjs28 分钟前
完结撒花!Java SE 语法阶段总结!
java·开发语言
lupai28 分钟前
短信接口快速接入与调用实战指南
java·开发语言·数据库
ltqvibe29 分钟前
企业智能问数落地:从一句话到跨系统完整答案
java·人工智能·本体语义平台
刘名喜35 分钟前
第12篇-Gradle-Kotlin-DSL构建指南
开发语言·kotlin·springboot
会编程的吕洞宾36 分钟前
Spring Boot 虚拟线程实战:从原理到生产环境
java·后端·spring
大鱼>1 小时前
DSPy:LLM程序自动编译与提示词优化
开发语言·人工智能·python·深度学习
黑桃小柒71 小时前
Prompt 工程的“断舍离“:如何用更少的词让 AI Agent 更聪明
java·后端·spring