任务:
要把一堆遥感图片每一个像素点所对应的波段值和经纬度等信息统一插入到数据库中,以方便查询管理。
技术试探:
上一篇博文http://blog.csdn.net/niaokedaoren/article/details/8881620,只是试探性的用代码读取波段值和经纬度。
但是要处理多幅图片,势必要在几个文件夹之间游走,IDL在这方面貌似比较乏力;同时IDL虽然支持数据库的链接,
貌似是ODBC,但是感觉不好用。于是尝试用IDL和Java混编的形式,来完成这个任务。在IDL的help文档里面确实
提到了这个技术。
又一个helloworld
最好在写之前去看看IDL的help文档,在IDL Programmers' Guides->IDL Connectivity Bridges这一节当中。
在干具体任务之前,我先试验了一下help文档中例子helloworld,貌似helloworld无处不在,呵呵。
1. 配置环境
我用的是win7, classpath变量中加上:ENVI_DIR\ENVI\IDL71\resource\bridges\export\java\javaidlb.jar
2. 编写procedure
一个小的类
function helloword::init
return, 1
end
pro helloworld__define
struct = {helloworld, $
dummy:0b $
}
end
在IDE的命令行下输入命令: ENVI> IDLEBR_ASSISTANT
就会出来一个叫Export Bridge Assistant的窗口
具体操作看help文档吧,很详细的。
生成的代码:
// This code has been generated by the code Wizard and should not be
// modified. The recommended manner of changing the behavior is to
// implement a class that inherits from this generated class.
package helloworld;
import com.idl.javaidl.*;
public class helloworld extends JIDLObject
{
// Constants set by Wizard
private static String IDL_CLASS = "helloworld";
private static String OPS_NAME = "Default_Process_Name";
// Constructor
public helloworld() {
super(IDL_CLASS, OPS_NAME);
}
// properties generated by Wizard
// class methods generated by Wizard
}
4.用java调用
测试代码:
package helloworld;
import com.idl.javaidl.*;
public class helloworld_example extends helloworld
implements JIDLOutputListener
{
private helloworld hwObj;
// Constructor
public helloworld_example() {
hwObj = new helloworld();
hwObj.createObject();
hwObj.addIDLOutputListener(this);
hwObj.executeString("print, 'Hello World'");
}
// implement JIDLOutputListener
public void IDLoutput(JIDLObjectI obj, String sMessage) {
System.out.println("IDL: "+sMessage);
}
public static void main(String[] argv) {
helloworld_example example = new helloworld_example();
}
}
编译了一下,运行,直接报错:
to call undefined procedure/function: 'HELLOWORLD__DEFINE'.]
at com.idl.javaidl.JIDLPAL.nativeThrowJIDLException(Native Method)
at com.idl.javaidl.JIDLPAL.throwSpecificException(JIDLPAL.java:1073)
at com.idl.javaidl.JIDLPAL.throwJIDLException(JIDLPAL.java:1102)
at com.idl.javaidl.JIDLPAL.createObject(JIDLPAL.java:382)
at com.idl.javaidl.JIDLPAL.createObject(JIDLPAL.java:318)
at com.idl.javaidl.JIDLObject.createObject(JIDLObject.java:193)
at com.idl.javaidl.JIDLObject.createObject(JIDLObject.java:103)
at helloworld.helloworld_example.<init>(helloworld_example.java:11)
at helloworld.helloworld_example.main(helloworld_example.java:22)
解决方案:
问题的原因是IDL的search PATH下根本找不到刚才编写的那个pro,要知道被包装成java类的东东是不干实事的,它是通过调用pro
来返回结果。我尝试用 > PREF_SET, 'IDL_PATH', 'ADD_DIR;<IDL_DEFAULT>', /COMMIT
没有加成,所以干脆简单暴力,直接将helloworld__define.pro文件拷贝到ENVI\IDL71\lib下面,当然可以在下面建一个local什么的文件夹,
统一放自己的pro。
Can't be resolved
做了几个例子的实验,心里开始有底了,就着手完成真正的任务。
但是有时候,现实往往比想象中更加残酷。
诸如ENVI_FILE_OPEN, ENVI_FILE_QUERY, ENVI_GET_SLICE等ENVI_*形式的routine报出:Warning ... can not be resolved
这显然很正常,因为这些是ENVI提供的,不是IDL提供的API。
是你逼我用绝招的,再次使用google大法,苍天不负有心人啊,
请看神作:http://www.exelisvis.com/Company/PressRoom/TabId/190/ArtMID/786/ArticleID/4302/4302.aspx
一切显得如此顺利,O(∩_∩)O哈哈~
function DataExtractor::init
compile_opt STRICTARR
pathInfo = routine_info('dataextractor__define', /SOURCE)
sourceCodeDir = file_dirname(pathInfo.path)
cd, sourceCodeDir
; Basic ENVI startup routines
enviLogFile = filepath('DataExtractor.log', ROOT_DIR=sourceCodeDir)
call_procedure, "ENVI", /RESTORE_BASE_SAVE_FILES
call_procedure, "ENVI_BATCH_INIT", LOG_FILE=enviLogFile
return, 1
end
function DataExtractor::openFile, filename
if (n_elements(filename) ne 0) then begin
call_procedure, "ENVI_OPEN_FILE", filename, r_fid=fid, $
/no_realize, /no_interactive_query
endif else begin
call_procedure, "ENVI_BATCH_EXIT"
return, -1
endelse
if (fid eq -1) then begin
call_procedure, "ENVI_BATCH_EXIT"
return, -1
endif
self.fid = fid
return, self.fid
end
function DataExtractor::closeFile
call_procedure, "ENVI_FILE_MNG", id=self.fid, /remove
end
function DataExtractor::getMapInfo
call_procedure, "ENVI_FILE_QUERY", self.fid, nl=nl, ns=ns, nb=nb
self.mapInfo[0] = nl
self.mapInfo[1] = ns
self.mapInfo[2] = nb
return, self.mapInfo
end
function DataExtractor::getBands, x, y
pos = lindgen(self.mapInfo[2])
data = call_function("ENVI_GET_SLICE", fid=self.fid, line=y, pos=pos, $
xs=x, xe=x, /bip)
return, data
end
function DataExtractor::getLocation, x, y
iproj = call_function("ENVI_GET_PROJECTION", fid=self.fid)
oproj = call_function("ENVI_PROJ_CREATE", /geographic)
call_procedure, "ENVI_CONVERT_FILE_COORDINATES", $
self.fid, x, y, xmap, ymap, /to_map
call_procedure, "ENVI_CONVERT_PROJECTION_COORDINATES", $
xmap, ymap, iproj, oxmap, oymap, oproj
location = dblarr(2)
location[0] = oxmap
location[1] = oymap
return, location
end
pro DataExtractor__define
struct = { $
DataExtractor, $
mapInfo: intarr(3), $
fid: 0 $
}
end
数据库那一块就简单多了,那是熟悉的java干的事情,等明后天搞吧,呵呵,未完待续。