ENVI/IDL——Java-IDL Export Bridge

来源:互联网 发布:朝鲜洪水知乎 编辑:程序博客网 时间:2024/04/29 13:45

任务:

要把一堆遥感图片每一个像素点所对应的波段值和经纬度等信息统一插入到数据库中,以方便查询管理。


技术试探:

上一篇博文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, 1endpro helloworld__define  struct = {helloworld, $    dummy:0b $  }end


3.包装成java类

在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();    } }

编译了一下,运行,直接报错:

Exception in thread "main" com.idl.javaidl.JIDLException[iErr=-999 sMsg=Attempt
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, 1endfunction 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.fidendfunction DataExtractor::closeFile  call_procedure, "ENVI_FILE_MNG", id=self.fid, /removeendfunction 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 endfunction 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, dataendfunction 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, locationendpro DataExtractor__define  struct = { $    DataExtractor, $    mapInfo: intarr(3), $    fid: 0 $  }end


数据库那一块就简单多了,那是熟悉的java干的事情,等明后天搞吧,呵呵,未完待续。

原创粉丝点击