内容简介:ImageJ1的开发的参考资源有:下载ImageJ的一个简单事例(在这个例子是一个Maven工程(Maven是Java的一种项目管理软件),即遵循了Maven的代码约定:有一个关键的配置文件pom.xml,以及源代码放在src文件夹下。pom.xml文件中指明了src目录下的java源码的依赖,如果直接使用传统的javac编译该源码,就会报“找不到ij包”的错误,所以这里要使用Maven进行编译(Maven的下载、安装和配置不在这里赘述)。
前面介绍过开发ImageJ的 Python 脚本的过程(在这里),这里介绍怎样开发ImageJ的插件。
插件相对于脚本来说,一方面,它的功能更加强大,可以认为是寄生在ImageJ上面的一个完备的小程序;另一方面,它使用 Java 开发,格式可以采用编译好的class文件,有利于保护代码不被泄露。
ImageJ由于历史原因,存在着ImageJ1和ImageJ2两个版本,且两者的API是迥然不同的,底层架构更是不同,导致两者的开发套路有很大差别。在写这篇tutorial时,深感两者在网上的文档资源相互交叉,论坛里的答案在不同版本间有时不适用。所以这里尝试从零开始一步步地记录ImageJ2的插件开发过程。
所基于的Fiji/ImageJ版本为:
参考资源有:
ImageJ1的开发的参考资源有:
上手例子
下载ImageJ的一个简单事例(在 这里 ),看看插件的源代码是什么样子以及怎样编译和安装。
编译
这个例子是一个Maven工程(Maven是Java的一种项目管理软件),即遵循了Maven的代码约定:有一个关键的配置文件pom.xml,以及源代码放在src文件夹下。pom.xml文件中指明了src目录下的java源码的依赖,如果直接使用传统的javac编译该源码,就会报“找不到ij包”的错误,所以这里要使用Maven进行编译(Maven的下载、安装和配置不在这里赘述)。
mvn package
上述命令就是使用Maven进行打包,结果就是生成target文件夹及下面的“GaussFiltering-0.1.0-SNAPSHOT.jar”这个jar包。
(Attention!!:这里生成的jar包中并没有下划线,这是ImageJ2允许的,它可以通过在源码的Plugin注解中指明menuPath即可在ImageJ对应菜单下显示,而ImageJ1则不允许,其明确要求jar包中必须有下划线,且它自定义在菜单中的显示是通过plugins.config配置文件指定,说明在 这里 )
安装
第二步是将该jar包“安装”到Fiji目录中,这里就是直接复制过去就行:
copy target/GaussFiltering-0.1.0-SNAPSHOT.jar /Path/to/Fiji.app/plugins/
然后启动Fiji(如果Fiji本来就运行着,则退出重启)。
运行
那么,这个插件怎么在Fiji中调用呢?有两种方法:
- 直接使用命令查找功能,即Ctrl+l(小写的字母L),然后输入该插件的名字Gauss Filtering,这是最快捷的一种方式。
- 第二种方式是可以在Plugins菜单下找到Gauss Filtering该插件。默认情形下插件是安装在Plugins菜单下,但也可以在java源码中自定义,即在Plugin注解中指定参数menuPath,前面已提到过)。
使用IDE编译
上面是使用Maven的命令行进行编译,实际上Maven已经与常用的Java集成开发环境IDE进行了集成,同时IDE还方便对代码的编辑,所以推荐使用IDE进行源码编写和编译。
常用的Java开发的IDE有Eclipse、NetBeans和IDEA等,以下是三种软件打开Maven工程的方法:
- Eclipse:File > Import > Existing Maven Projects
- NetBeans:File > Open Project
- IDEA:File > Open Project (Select pom.xml)
这里使用IDEA-2018-2进行操作,将pom.xml作为Project打开后,IDEA会根据pom中指定的依赖dependencies联网下载所依赖的jar包。然后点击左侧的Maven Projects,选择LifeCycle下面的Package,双击即可进行打包操作,如下:
ImageJ插件开发的“Hello World”
学习任何一名编程语言,第一个例子肯定是向新世界打招呼——“Hello, World!”。基于ImageJ开发的插件也不例外。从 这里 下载ImageJ的入门例子,其中就包含了“Hello, World!”的书写方式。
编译运行
依然是用IDEA-2018-2来打开该项目的pom.xml文件,点击窗口左侧的Maven Projects,找到”Simple ImageJ Commands”这个项目,然后在LifeCycle下双击package命令进行打包,如图:
生成jar包后,复制到Fiji的plugins文件夹下,重启Fiji,然后可以在Help菜单下发现”Hello, World!”命令。
代码解析
下面是一步步地分析HelloWorld的代码。
插件声明
@Plugin(type = Command.class, headless = true, menuPath = "Help>Hello, World!")
技术上讲,ImageJ插件是一个名为Plugin的注解(ImageJ基于SciJava插件系统),这样注解的类可以在运行时自动查找到并索引。有很多种插件类型,HelloWorld用的是Command类型的插件,这种类型的插件是应用最广泛的:Command接收输入,然后产生输出。Command插件最常用的就是与菜单绑定,这里使用menuPath指定在哪个菜单下显示及其显示名称。
关于插件,多说两句:
(1)插件类型
除了上面的Command类型的插件,还有一些基于Service的插件。显式地指定插件type后,可以有效地找到某种类型的插件。比如:
@Plugin(type=Service.class) public class MyService implements Service { } @Plugin(type=SpecialService.class) public class SpecialService implements Service { }
那么问题来了,上述代码中,如果软件上下文想要的插件是Service,那么将会找到哪个插件?
答案是MyService和SpecialService都会返回,因为SpecialService是Service的Service的一个子类;而如果想要的是SpecialService插件,那么就只返回SpecialService类。
(2)插件优先级
当匹配的插件有很多时,插件会按类的priority的顺序来呈现,这个变量是double类型的数值,也可以使用已规定好的静态常量来表示:
@Plugin(priority=Priority.HIGH_PRIORITY) public class MyService implements Service { } @Plugin(priority=224) public class SpecialService implements Service { }
那么问题是,当寻找Service插件时,上面哪个插件会排在前面?
答案是SpecialService,因为从 SciJava-Common的源码 上可以看出HIGH_PRIORITY的数值是100。
更好的一种方式是使用相对优先级,比如:
@Plugin(priority=Priority.HIGH_PRIORITY+124) public class SpecialService implements Service { }
命令的输入输出
public class HelloWorld implements Command { @Parameter(label = "What is your name?") private String name = "J. Doe"; @Parameter(type = ItemIO.OUTPUT) private String greeting;
从command类中派生出helloWorld类。每个command类都有input和output,所以这里使用两个成员变量来承载,两者都要用Parameter来注解,所不同的是output需要Parameter的type明确指定为”ItemIO.OUTPUT”。
命令的运行函数
@Override public void run() { greeting = "Hello, " + name + "!"; }
上面的run函数是ImageJ的每个command的入口点,当用户点击菜单上的该命令时,先让用户输入input值,然后就会执行该函数。
命令的调试
public static void main(final String... args) { // Launch ImageJ as usual. final ImageJ ij = new ImageJ(); ij.launch(args); // Launch our "Hello World" command right away. ij.command().run(HelloWorld.class, true); } }
上面的代码是用来在IDE中调试所用。通过创建main函数,使得IDE创建一个ImageJ的上下文环境,然后调用该插件。
更一般的调用方式是:
ij.command().run(MyPlugin.class, "inputImage", myImage)}
这就是最基本的ImageJ插件。
上面的代码中除了HelloWorld,还包含了更多ImageJ插件开发的入门例子,自行探索吧!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Gradle插件开发系列之开发第一个gradle插件
- (是时候开发属于自己的插件了)数据校验插件开发指南
- IDEA 插件:多线程文件下载插件开发
- 从头开发一个Flutter插件(二)高德地图定位插件
- Gradle插件开发系列之gradle插件调试方法
- WordPress插件开发 -- 在插件使用数据库存储数据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web信息架构(第3版)
[美] Peter Morville、Louis Rosenfeld / 陈建勋 / 电子工业出版社 / 2013-10 / 99.00元
本书内容涵盖了信息架构基本原理和实践应用的方方面面。全书共7个部分,包括信息架构概述、信息架构的基本原理、信息架构的开发流程和方法论、信息架构实践、信息架构与组织、两个案例研究,以及参考资料清单。 本书兼具较高的理论价值和实用价值,曾被Web设计领域多本书籍重点推荐,是信息架构领域公认的经典书籍,不论新手还是专家都能各取所需。本书可供Web设计与开发者、Web架构师、网站管理者及信息管理相关......一起来看看 《Web信息架构(第3版)》 这本书的介绍吧!