im4java开发向导
0、搜索ImageMagick下载安装
1、Setting up the Environment
引入im4java到classpath
设置图片处理引擎的command searchpath
三种方式:
设置系统环境变量 IM4JAVA_TOOLPATH
在程序中设置全局变量(将覆盖上一层)
String myPath="C:\\Programs\\ImageMagick;C:\\Programs\\exiftool";
ProcessStarter.setGlobalSearchPath(myPath);
设置命令单独变量(将覆盖上两层)
String imPath="C:\\Programs\\ImageMagick";
ConvertCmd cmd = new ConvertCmd();
cmd.setSearchPath(imPath);
2、Simple Use
ImageCommand 对象 e.g. ConvertCmd
ProcessStarter包装了java.lang.ProcessBuilder,掌管输入输出流、支持asynchronous execution
ImageCommand是ProcessStarter的子类,持有一个通过ProcessStarter获得的process ID,提供了reusing operations或dynamic operations等方法
所有的command类都是ImageCommand的子类
ImageCommand并不是无状态类,同步使用时一般创建一次就可以了,并发处理除外
Operation 对象 e.g. IMOperation 每个操作创建一次
示例:
// create command
ConvertCmd cmd = new ConvertCmd(); // create the operation, add images and operators/options
IMOperation op = new IMOperation();
op.addImage("myimage.jpg");
op.resize(800,600);
op.addImage("myimage_small.jpg"); // execute the operation
cmd.run(op);
3、Using GraphicsMagick
GraphicsMagick是ImageMagick的一个分支、改进了IM的效率和命令行语法
在im4java中有三种方式使用GraphicsMagick
直接创建GM对象 GraphicsMagickCmd cmd = new GraphicsMagickCmd("convert");
使用包装类 ConvertCmd cmd = new ConvertCmd(true);
运行时通过system-property im4java.useGM = true 决定
4、Reusing Operations
直接看代码
public void resizeImages(String... pImageNames) {
// create command
ConvertCmd cmd = new ConvertCmd(); // create the operation, add images and operators/options
IMOperation op = new IMOperation();
op.addImage();// 这里相当于插入了一个占位符,无参方法相当于op.addImage(Operation.IMG_PLACEHOLDER)
//addImage方法还有两个重载方法
//op.addImage(String... images) 支持修饰符
//如op.addImage("[300x200]");
//op.addImage(Operation.IMG_PLACEHOLDER+"[300x200]");
//op.addImage(int count) 一次性传入占位符的数量
op.resize(800,600);
op.addImage(); for (String srcImage:pImageNames) {
int lastDot = srcImage.lastIndexOf('.');
String dstImage = srcImage.substring(1,lastDot-1)+"_small.jpg";
cmd.run(op,srcImage,dstImage);//在run的时候,逐一替换占位符,这样相当于复用了Operation对象
//run方法的第二个参数实际是一个Object[]支持任意个数的替换
}
}
第二种复用Operation的方式
IMOperation frame = new IMOperation();
frame.rotate("90");
frame.resize(640);
frame.border(10,10); IMOperation row = new IMOperation();
row.addImages(3);
row.add(frame);
row.p_append();
子操作的概念
IMOperation frame = new IMOperation();
frame.openOperation();
frame.rotate("90");
frame.resize(640);
frame.border(10,10);
frame.closeOperation();
另一种写法
IMOperation frame = new IMOperation();
frame.rotate("90");
frame.resize(640);
frame.border(10,10); IMOperation row = new IMOperation();
row.addImages(3);
row.addSubOperation(frame);
row.p_append();
5、Dynamic Operations
op.addDynamicOperation(new DynamicOperation() {
public Operation resolveOperation(Object... pImages) throws IM4JavaException {
//封装一些逻辑处理
//返回一个Operation对象或null
}
});
6、Capturing Output
默认的输出会传递给stdout和stderr
可以设置Consumer改变默认行为
ImageCommand.setOutputConsumer(OutputConsumer oc)
ImageCommand.setErrorConsumer(ErrorConsumer ec)
提供了一个示例实现ArrayListOutputConsumer 把输出转为String[]
7、Piping
Pipe implements InputProvider, OutputConsumer, ErrorConsumer
后补详情
8、Using BufferedImages
BufferedImage是一种java本地图片对象
在作为输入的时候,im4java可以透明的使用
IMOperation op = new IMOperation();
op.addImage(); // input
op.blur(2.0).paint(10.0);
op.addImage(); // output ConvertCmd convert = new ConvertCmd();
BufferedImage img = ...;
String outfile = ...;
...
convert.run(op,img,outfile);
作为输出的时候要转一下
IMOperation op = new IMOperation();
op.addImage(); // input
....
op.addImage("png:-"); // output: stdout
...
images = ...; // set up command
ConvertCmd convert = new ConvertCmd();
Stream2BufferedImage s2b = new Stream2BufferedImage();
convert.setOutputConsumer(s2b); // run command and extract BufferedImage from OutputConsumer
convert.run(op,(Object[]) images);
BufferedImage img = s2b.getImage();
9、 Asynchronous Execution
ConvertCmd cmd = new ConvertCmd();
cmd.setAsyncMode(true);//fire-and-forget 方式
...
cmd.run(op);
如果需要线程执行的反馈,则实现org.im4java.process.ProcessEventListener接口
processInitiated()
processStarted()
processTerminated()
利用ProcessStarter的addProcessEventListener方法添加监听(ImageCommand对象扩展自ProcessStarter)
如果要自己控制线程的执行
用java原生的执行器
ProcessTask pt = cmd.getProcessTask(op);
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(pt);
exec.shutdown();
上述异步执行方式有三个问题
问题一:处理大量图片严重消耗系统资源
问题二:不知道每项处理何时完成
问题三:不知道每项任务执行成功还是失败
解决问题一
java.util.concurrent.Executors以工厂的方式返回执行器对象,你可以控制线程排队,线程数量、停止或销毁线程
但有一个严重的缺点,一旦ImageCommand在线程中running,就不能被kill
使用org.im4java.process.ProcessExecutor(扩展自java.util.concurrent.ThreadPoolExecutor )
默认的构造器查询系统的处理器能力限制并发处理量,也可以显式的传入一个整数控制,比如new ProcessExecutor(10)
// load images into an array, e.g. from a directoy
ArrayList<String> images = load(myDir); // convert all images
ProcessExecutor exec = new ProcessExecutor();
Operation op = ...;
for (String img:images) {
String outfile = ...;
ConvertCmd cmd = new ConvertCmd();
ProcessTask pt = cmd.getProcessTask(op,img,outfile);
exec.execute(pt);
}
exec.shutdown();
ProcessTask 对象扩展自java.util.concurrent.FutureTask
解决问题二
因为org.im4java.process.ProcessExecutor扩展自java.util.concurrent.ThreadPoolExecutor
可以调用ThreadPoolExecutor的awaitTermination方法,等候执行器执行完成
awaitTermination方法会阻塞线程直到发生以下情况之一:所有任务执行完成、任务执行超时、当前线程被interrupt
根据这个特点,可以在上面的代码下加上一段
ProcessExecutor exec = new ProcessExecutor();
for (String img:images) {
...
}
exec.shutdown();
if (exec.awaitTermination(10,TimeUnit.SECONDS)) {
System.err.println("processes terminated on their own");
} else {
System.err.println("trying to cancel all running processes ...");
exec.shutdownNow();
}
另外可以扩展ProcessExecutor 的terminated方法,当所有任务执行完成时,这个方法将被调用
解决问题三
对于简单的异步处理,可以用ProcessEventListener 的processTerminated(ProcessEvent pEvent)方法监听到执行结果
对于大量的并发处理,则需要借助ProcessEvent,它提供了一系列定位线程的方法,比如getPID()
PID是ImageCommand内部的一个标识,可以在创建对象的时候手动设置
还可以通过ProcessEvent.getProcessStarter()的方法拿到整个ImageCommand对象(因为ImageCommand扩展自ProcessStarter)
10、Utilities
Image Information
通常查询图片完整信息使用IdentifyCmd这个命令对象,它封装了IM的identify命令
另外使用Info对象可以更快速的查询基本信息
Info imageInfo = new Info(filename,true);
System.out.println("Format: " + imageInfo.getImageFormat());
System.out.println("Width: " + imageInfo.getImageWidth());
System.out.println("Height: " + imageInfo.getImageHeight());
System.out.println("Geometry: " + imageInfo.getImageGeometry());
System.out.println("Depth: " + imageInfo.getImageDepth());
System.out.println("Class: " + imageInfo.getImageClass());
第二个构造参数true代表查询基本信息
对于像TIF或GIF这样的支持多张图片的格式(IM里称之为scenes)
imageInfo.getImageWidth()//返回第一张图片的宽度(基本信息模式)
imageInfo.getProperty("Width")//返回最后张图片的宽度(完整信息模式)
imageInfo.getImageWidth(3)
imageInfo.getProperty("Width",3)
完整信息模式中,getSceneCount()方法返回scene的数量
另外还有ExiftoolCmd对象
FilenameLoader
FilenameLoader对象的List<String> loadFilenames(String pDir)可以根据传入的路径参数加载所有的文件返回一个String List
ExtensionFilter filter = new ExtensionFilter("jpg");
filter.setRecursion(true);
filter.ignoreDotDirs(true);
FilenameLoader loader = new FilenameLoader(filter);
List<String> files = loader.loadFilenames(mydir);
FilenamePatternResolver
直接看代码
// define operation and command
IMOperation op = new IMOperation();
op.addImage(); // input-file
op.addImage(); // output-file
ConvertCmd cmd = new ConvertCmd(); // load files
ExtensionFilter filter = new ExtensionFilter("jpg");
FilenameLoader loader = new FilenameLoader(filter);
List<String> files = loader.loadFilenames(mydir); // create the resolver
FilenamePatternResolver resolver =
new FilenamePatternResolver("%P/%f.tif"); // now iterate over all files
for (String img:files) {
cmd.run(op,img,resolver.createName(img));
}
%P: full pathname of source-image (i.e. the directory)
%p: last component of %P
%F: full filename without directory part
%f: filename without directory part and extension
%e: only the extension
%D: drive-letter (on windows systems). Not available for source-files with an UNC-name.
BatchConverter
org.im4java.utils.BatchConverter 是为客户端应用提供的一个工具类,会并发调用所有可用的CPU资源完成转换,不太适合Web应用使用
//首先获得要操作的文件列表
ExtensionFilter filter = new ExtensionFilter("jpg");
filter.setRecursion(false);
FilenameLoader loader = new FilenameLoader(filter);
List<String> images=loader.loadFilenames(dir);
然后通过BatchConverter的run方法开始批量操作
// create a simple thumbnail operation
op = new IMOperation();
op.size(80);
op.addImage(); // placeholder input filename
op.thumbnail(80);
op.addImage(); // placeholder output filename // create a template for the output-files:
// we put them in targetDir with the same filename as the original
// images
String template=targetDir+"%F"; // create instance of BatchConverter and convert images
BatchConverter bc = new BatchConverter(BatchConverter.Mode.PARALLEL);
bc.run(op,images,targetDir+"%F");
BatchConverter扩展自ProcessExecutor,可以使用awaitTermination方法控制线程终止
BatchConverter有三种模式
BatchConverter.SEQUENTIAL - 顺序处理
BatchConverter.PARALLEL - 多核并发处理
BatchConverter.BATCH - 单核处理器可以用这个
另外使用terminated()完成线程终止时的回调逻辑,使用getFailedConversions()方法获得处理出现错误的资源信息
Debugging
ImageCommand对象的createScript()方法,可以把执行脚本生成出来,供调试
IMOperation op = new IMOperation();
...
ConvertCmd cmd = new ConvertCmd();
cmd.createScript("myscript.sh",op);//Win下会自动添加.cmd扩展名
im4java开发向导的更多相关文章
- VS自定义开发向导中的vsdir文件的简单说明
作者:朱金灿 来源:http://blog.csdn.net/clever101 VS自定义开发向导中有一个vsdir文件.这个文件指定了在VS中项目的标题.默认工程名等内容.下面对vsdir文件做一 ...
- VS中创建自定义一个VC工程为基础的开发向导的总结
作者:朱金灿 来源:http://blog.csdn.net/clever101 VS允许用户进行自定义开发向导.自定义开发向导的好处在于将常用的设置都通过向导生成,从而大大提供开发效率.特别是在开发 ...
- NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))
在看这个博客前,请读者先去完整看完:NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article ...
- NX二次开发-创建NX9 NXOpenCPP Wizard开发向导模板
这篇文章,我在CSDN,在唐工论坛都发过.http://www.nxopen.cn/forum.php?mod=viewthread&tid=2039&highlight=NX9 博客 ...
- RabbitMQ 客户端开发向导
准备工作:composer 引入 php-amqplib 说明:本文说明基于 Java(主要说明原理),实现使用 php RabbitMQ Java 客户端使用 com.rabbitmq.client ...
- Yii2.0中文开发向导——Yii2中多表关联查询(join、joinwith)(转)
我们用实例来说明这一部分 表结构 现在有客户表.订单表.图书表.作者表, 客户表Customer (id customer_name) 订单表Order (id order_ ...
- Yii2.0中文开发向导——控制器(Controller)
控制器(Controller) 本节包含以下方面的内容 基本概念 路由 默认路由 动作的参数 在动作中定义参数 从请求(request)中获取参数 独立动作 动作过滤器(Action Filters) ...
- Yii2.0中文开发向导——Where条件查询全解析
在Yii的Model里进行查询的时候 where是必不可少的.Where方法声明为 static where( $condition ) 其中参数 $condition类型为字符串或者数组 1.字符串 ...
- Yii2.0中文开发向导——Yii2中多表关联查询(join、joinwith)
我们用实例来说明这一部分 表结构 现在有客户表.订单表.图书表.作者表, 客户表Customer (id customer_name) 订单表Order (id order_ ...
随机推荐
- Shiro权限控制框架
Subject:主体,可以看到主体可以是任何可以与应用交互的"用户": SecurityManager:相当于SpringMVC中的DispatcherServlet或者Strut ...
- SQL 获取本年第几周
根据输入的日期得出,算出是本年第几周 select datepart(week,getdate())
- 对象生命周期及crud操作
1. 对象状态及生命周期 瞬时状态: 持久状态: 游离状态: 2. new->save->close->update public void testSave(){ Session ...
- 对CSS中的Position属性的一些深入探讨
转:http://www.cnblogs.com/coffeedeveloper/p/3145790.html Position属性 Position的属性值共有四个static.relative.a ...
- Installing Redis on Ubuntu
wget http://download.redis.io/redis-stable.tar.gz tar xvzf redis-stable.tar.gz cd redis-stable sudo ...
- sql server异地备份数据库
--注意:异地备份数据库,需要先开启备份文件夹的网络共享,数据库选择master --打开允许执行xp_cmdshell exec master..xp_cmdshell 'net use \\192 ...
- block的传值简单示例仅供参考,大牛勿喷
#import "ViewController.h" typedef void(^sumBlock)(int s);//声明为一个类型; /** * 用声明的block类型 su ...
- git重写历史记录
1 修改上一次历史提交,替换掉上次的提交git commit --amend 2 git rebase 将不同分支路径合并到同一分支路径上eg:将master分支上的 conflic rebase合并 ...
- minicom的安装及使用
1.下载 sudo apt-get install minicom 2.运行 sudo minicom -s 3.修改端口 首先查看端口:ls /dev/tty...
- Dapper.NET使用(转)
Dapper.NET使用 本文目录 Dapper.NET使用 1.为什么选择Dapper 2.以Dapper(4.0)为例. 2.1 在数据库中建立几张表. 2.2实体类. 3.使用方法 3.1 一 ...