【ENVI二次开发学习整理 02】IDL语言基础与程序设计
2026/8/4 12:23:48 网站建设 项目流程

【ENVI二次开发学习整理 02】IDL语言基础与程序设计

📝内容范围:本文重点介绍IDL工作台、工程与源码文件、程序运行方式、变量、数组、字符串、结构体、指针、链表、哈希表、运算符、程序控制、参数传递和关键字继承。

整理方式:延续前一篇的知识笔记风格,减少零散分点,更多使用表格和连续解释,并将语法知识与ENVI二次开发中的实际数据处理场景联系起来。

文章目录

  • 【ENVI二次开发学习整理 02】IDL语言基础与程序设计
    • @[toc]
    • 第一章 从IDL工作台开始认识程序开发
      • 1.1 IDL工作台不仅是代码编辑器
      • 1.2 工程化开发与命令行试验的区别
      • 1.3 工作台中的常用视图
    • 第二章 IDL程序的创建、编译和发布
      • 2.1 第一个程序的作用不只是输出文字
      • 2.2 源码文件名与过程名
      • 2.3 编译、运行与发布的区别
    • 第三章 变量、数据类型与动态类型
      • 3.1 IDL变量的命名
      • 3.2 变量的动态性
      • 3.3 常见数据类型与使用场景
      • 3.4 系统变量
    • 第四章 数组:IDL程序设计的核心
      • 4.1 数组为什么重要
      • 4.2 数组的创建方式
        • 直接赋值创建
        • 函数创建
      • 4.3 数组访问方式
      • 4.4 数组计算与序列生成
      • 4.5 数组存储与图像方向
    • 第五章 字符串与文件名处理
      • 5.1 字符串的创建
      • 5.2 常用字符串函数
      • 5.3 数值转字符串后的空格
      • 5.4 从文件名提取日期
      • 5.5 扩展名判断
    • 第六章 结构体:组织一组相关数据
      • 6.1 结构体的用途
      • 6.2 匿名结构体与命名结构体
      • 6.3 结构体访问
      • 6.4 结构体继承与动态扩展
    • 第七章 指针与堆变量
      • 7.1 指针解决什么问题
      • 7.2 指针的共享特点
      • 7.3 `/NO_COPY`与大数据
      • 7.4 指针的适用场景
    • 第八章 链表与哈希表
      • 8.1 链表
      • 8.2 哈希表
      • 8.3 结构体、链表和哈希表如何选择
    • 第九章 运算符
      • 9.1 数学运算符
      • 9.2 逻辑与位运算
      • 9.3 关系运算符
      • 9.4 数组乘与矩阵乘
      • 9.5 其他符号
    • 第十章 程序控制
      • 10.1 条件、循环与跳转
      • 10.2 `IF`结构
      • 10.3 `CASE`与`SWITCH`
      • 10.4 遥感批处理中的循环
    • 第十一章 参数传递
      • 11.1 位置参数与关键字参数
      • 11.2 地址传递与值传递
      • 11.3 参数设计建议
    • 第十二章 关键字继承
      • 12.1 `_EXTRA`与`_REF_EXTRA`
      • 12.2 关键字继承的使用场景
    • 第十三章 将语言基础应用到ENVI二次开发
      • 13.1 语言知识与开发任务的对应关系
      • 13.2 一个典型文件批处理框架
      • 13.3 代码组织建议
    • 第十四章 常见错误与排查思路
    • 第十五章 本篇学习重点总结
    • 第十六章 术语表

第一章 从IDL工作台开始认识程序开发

1.1 IDL工作台不仅是代码编辑器

IDL工作台同时承担工程管理、源码编辑、命令执行、变量查看、帮助查询和程序调试等任务。对于刚开始学习IDL的人来说,工作台中最容易混淆的是“工程”“源码文件”“工作空间”和“搜索路径”之间的关系。

名称作用实际理解
工作空间保存当前开发环境中的工程和配置类似一个总的开发目录
工程组织同一程序相关的源码和资源一个完整IDL程序的管理单元
源码文件保存IDL命令、过程或函数通常使用.pro扩展名
搜索路径IDL查找过程、函数和数据的位置文件不在路径中时可能无法调用
命令行直接输入并执行IDL语句适合试验语法和查看结果
变量查看器查看当前变量的类型、维数和值适合检查数组和结构体
命令历史保存之前执行过的命令便于重复运行和修改

工作空间负责管理开发环境,工程负责组织程序,源码文件保存代码,而搜索路径决定IDL能否找到相应的过程、函数或数据文件。后续进行ENVI二次开发时,一个工程通常会包含主程序、公共函数、配置文件、图标和测试数据。

1.2 工程化开发与命令行试验的区别

在IDL中,同一段代码可以先在命令行中试验,再整理到.pro文件中。命令行适合验证函数返回值、数组维度和语法写法,而工程和源码文件适合保存可重复运行的程序。

使用方式优点局限更适合的阶段
命令行模式立即执行、反馈快不便保存复杂流程语法试验和问题排查
批处理模式文件中直接写命令并顺序执行结构和复用能力有限简单一次性任务
编译运行模式支持过程、函数和工程组织需要理解编译规则正式程序和二次开发
工程运行统一管理多个文件和资源前期配置稍多中大型程序

在ENVI二次开发中,较可靠的做法是先在命令行中验证某个ENVI API调用,再将其封装成过程或函数,最后加入工程和批处理流程。

1.3 工作台中的常用视图

视图或功能主要用途使用建议
编辑器编写.pro源码保持缩进和注释统一
变量查看器查看变量类型和内容重点检查数组维数与数据类型
命令行交互执行命令用于快速验证
命令历史回看执行记录可复制到源码文件中
工程浏览器管理源码和资源按功能划分文件
帮助系统查询函数和关键字不确定参数时优先查看

专题材料还提到源码格式、颜色和首选项设置。统一的源码格式虽然不改变程序结果,却会显著影响代码可读性。IDL程序中条件语句、循环和过程体较多,缩进不清会使逻辑错误难以及时发现。


第二章 IDL程序的创建、编译和发布

2.1 第一个程序的作用不只是输出文字

专题以HelloWorld.pro作为第一个IDL程序。它的主要目的不是学习输出字符串,而是完整经历以下开发过程:

创建工程

创建pro文件

编写过程

编译

运行

生成sav

运行或发布

一个典型IDL过程可以写成:

PRO HelloWorld PRINT, 'Hello World' END

这里的PRO表示定义过程,HelloWorld是过程名,END表示过程结束。编译完成后,可在命令行中输入:

HelloWorld

即可调用该过程。

2.2 源码文件名与过程名

在IDL开发中,源码文件名、主过程名和调用名通常保持一致。例如:

项目示例
文件名helloworld.pro
过程名HelloWorld
调用方式HelloWorld

保持一致有助于IDL通过搜索路径找到源码,也便于工程维护。后续编写ENVI工具时,建议每个文件只放置一个主要公开过程或函数,其余辅助过程可以放在同一文件前部或拆分到独立文件。

2.3 编译、运行与发布的区别

阶段作用结果
编写保存IDL源码.pro文件
编译检查语法并生成可运行定义当前会话中可调用
运行执行过程或函数输出结果或生成文件
保存将编译结果保存.sav文件
发布将程序放入Runtime或虚拟机环境供其他用户运行

专题材料给出的发布示例为:

make_rt, 'helloWorld', 'c:\temp\out', $ savefile='D:\trainning\helloWorld\helloworld.sav', /vm

该示例体现了IDL程序可以生成可发布成果。实际发布时,还需要考虑数据文件、搜索路径、第三方库和用户运行环境。


第三章 变量、数据类型与动态类型

3.1 IDL变量的命名

专题材料给出的命名规则为:变量最大长度不超过255个字符,首位只能是字母或下划线,中后部可使用字母、数字、下划线和连接符号$

合法示例不合法示例原因
abc_3$d4_line首位不能是数字
ok_24_bitabc.cha不能使用点号
IDL_type
_day_month_year

IDL提供IDL_VALIDNAME检查或转换变量名:

result = IDL_VALIDNAME(string)

也可以使用/CONVERT_ALL/CONVERT_SPACES关键字处理不合法字符。该函数在根据文件名、字段名或外部配置动态生成变量或标签时具有实际价值。

3.2 变量的动态性

IDL变量具有动态类型。一个变量可以先保存整数,再保存浮点数、字符串或数组。

a = 4 a = 4.5 a = 'text' a = [1, 2, 3]

动态类型让交互试验更加方便,但也可能隐藏类型错误。尤其在遥感计算中,整型除法会造成精度丢失。

专题材料给出的示例:

result = 8 / 5 aspect = !D.X_Size / !D.Y_Size

若两个参与运算的值都是整数,结果可能按整型计算。为了获得浮点结果,可以显式写成:

result = 8.0 / 5.0 aspect = FLOAT(!D.X_Size) / FLOAT(!D.Y_Size)

3.3 常见数据类型与使用场景

数据类型典型写法遥感开发中的用途
Byte3B8位分类图、颜色值
Integer3一般整数和部分DN
Long4L较大整数和索引
Float3.0反射率、指数和一般计算
Double3D3.0D高精度计算
String'text'文件路径、名称和配置
ComplexCOMPLEX(1,2)复数科学数据
PointerPTR_NEW()动态数据和共享堆变量
ObjectLIST()HASH()动态容器和对象

3.4 系统变量

IDL系统变量通常以感叹号开头,例如!D。专题还介绍了自定义系统变量:

DEFSYSV, '!变量名', 值

使用时与普通变量类似:

PRINT, !变量名

系统变量在整个IDL会话中可访问,适合保存全局配置,但若大量使用,会使程序依赖隐式状态。正式ENVI工程中,更建议将配置放入结构体、哈希表或参数文件中。


第四章 数组:IDL程序设计的核心

4.1 数组为什么重要

遥感影像本身就是数组。单波段影像是二维数组,多光谱和高光谱影像通常可以组织为三维数组。IDL支持0至8维数组,因此数组操作是后续图像计算、波段运算和ENVI栅格处理的基础。

专题材料强调,IDL数组下标按照“先列后行”的方式理解。对于二维影像数组:

value = image[column, row]

第一维对应列,第二维对应行。若把顺序理解反了,读取位置、裁剪范围和邻域运算都会出现错误。

4.2 数组的创建方式

直接赋值创建
arr = [1, 2, 3] HELP, arr

类型会根据元素自动确定。

表达式推断类型
[1,2,3]Integer数组
[1,2,3B]材料示例仍显示为Integer数组
[1,2,3D]Double数组

数组元素类型通常需要保持一致。不同类型混合时,IDL会进行类型提升,因此应使用HELP检查实际类型。

函数创建

IDL可使用专门函数创建数组,例如:

a = INTARR(100, 100) b = FLTARR(100, 100) c = INDGEN(10) d = MAKE_ARRAY(10, 20, TYPE=4)
函数作用
BYTARR创建Byte全零数组
INTARR创建Integer全零数组
LONARR创建Long全零数组
FLTARR创建Float全零数组
DBLARR创建Double全零数组
STRARR创建字符串数组
INDGEN创建Integer索引数组
FINDGEN创建Float索引数组
MAKE_ARRAY按参数创建通用数组

4.3 数组访问方式

方式示例说明
单元素下标a[3]获取某个元素
二维下标img[10,20]获取第10列、第20行
向量下标a[[1,3,5]]获取多个指定元素
连续子数组a[2:6]获取索引2至6
二维裁剪img[x0:x1,y0:y1]获取矩形区域
全维选择cube[*,*,3]获取第4个波段

星号*表示该维度的全部元素。对于多波段数据,理解各维度顺序十分重要。不同文件读取函数可能返回不同维度组织方式,应通过HELPSIZE确认。

4.4 数组计算与序列生成

专题给出了等差数列和等比数列示例:

PRINT, INDGEN(6) * 5 + 1

结果为:

1 6 11 16 21 26

等比数列:

PRINT, 3 ^ INDGEN(6) PRINT, 3 ^ INDGEN(6) * 2

这种数组表达式说明IDL可以一次性完成整组数据计算。在遥感处理中,类似写法可用于:

  • 构建波长序列;
  • 生成坐标索引;
  • 批量计算阈值;
  • 创建查找表;
  • 计算多波段系数。

4.5 数组存储与图像方向

专题材料说明数组按行存储,并展示了一维和二维数组的存储关系。实际使用时,最重要的是区分:

  • 数组在内存中的顺序;
  • 数组下标的维度顺序;
  • 影像显示时的行列方向;
  • 文件中的存储顺序。

在读取二进制影像时,若维度、字节顺序或行列理解错误,影像可能出现旋转、转置或条带错位。应使用少量已知数据验证数组方向,再处理完整影像。


第五章 字符串与文件名处理

5.1 字符串的创建

字符串可直接赋值:

str = 'string'

字符串数组可使用:

names = STRARR(10)

字符串在ENVI二次开发中非常重要,因为文件路径、栅格名称、波段名称、任务参数和输出目录通常都以字符串表示。

5.2 常用字符串函数

函数作用示例用途
STRTRIM删除字符串两侧空格清理数值转字符串结果
STRMID截取子字符串从文件名提取日期
STRPOS查找子字符串位置查找扩展名分隔点
STRUPCASE转为大写不区分大小写比较扩展名
STRLOWCASE转为小写统一文件名
STRING数值转字符串生成输出名称
STRSPLIT分割字符串解析路径或配置
STRJOIN合并字符串拼接名称列表

5.3 数值转字符串后的空格

专题示例:

var = 4L str = STRING(var) HELP, str

转换结果前可能包含格式空格,因此常继续使用:

str = STRTRIM(str, 1)

这在生成文件名时很重要。若不去除前导空格,输出文件名中可能出现难以发现的空白字符。

5.4 从文件名提取日期

专题使用:

file = 'AMOD0320040707140331.hdf' PRINT, STRMID(file, 6, 8)

输出:

20040707

这种固定位置截取适用于命名结构稳定的卫星产品。更通用的程序还应检查文件名长度和命名规则,避免对不符合规范的文件直接截取。

5.5 扩展名判断

专题示例展示了如何查找扩展名并跳过头文件:

fName = FILE_BASENAME(imageNames[k]) pPos = STRPOS(fName, '.', /REVERSE_SEARCH) IF pPos[0] NE -1 THEN BEGIN IF STRUPCASE(STRMID(fName, pPos[0]+1, 3)) EQ 'HDR' THEN CONTINUE ENDIF
代码步骤作用
FILE_BASENAME去除目录,仅保留文件名
STRPOS(...,/REVERSE_SEARCH)从后向前查找最后一个点号
STRMID提取扩展名
STRUPCASE转为大写后比较
CONTINUE跳过当前循环

该模式非常适合批量处理遥感数据时过滤.hdr、临时文件和非目标格式。


第六章 结构体:组织一组相关数据

6.1 结构体的用途

结构体可以把标量、数组、字符串甚至其他结构体组合为一个复合变量。与多个独立变量相比,结构体更适合表示一个完整对象的属性。

例如,一个遥感影像信息结构可以包含:

  • 文件路径;
  • 行列数;
  • 波段数;
  • 数据类型;
  • 投影;
  • NoData;
  • 成像日期。

6.2 匿名结构体与命名结构体

p = CREATE_STRUCT('A', 1, 'B', 'xxx')

创建匿名结构体。

p = CREATE_STRUCT(NAME='struct1', 'A', 1, 'B', 'xxx')

创建命名结构体。

也可使用花括号语法:

info = {file:'image.dat', ncols:1000L, nrows:800L}

6.3 结构体访问

访问方式示例说明
标签名访问info.file按字段名获取
动态索引访问info.(idx)按字段顺序获取
标签查询TAG_NAMES(info)获取字段名称
字段数量N_TAGS(info)获取标签数

按字段名访问更清晰,动态索引适用于遍历结构体字段。

6.4 结构体继承与动态扩展

专题示例:

str1 = {str1name, a:1, b:2} str2 = {str2name, INHERITS str1name, c:3}

表示命名结构体可以继承已有结构。

匿名结构体可使用CREATE_STRUCT动态扩展:

a = {a:1, b:2} a = CREATE_STRUCT(a, 'c', 3)

结构体适合固定字段的数据组织。若字段需要频繁增加或删除,哈希表通常更加灵活。


第七章 指针与堆变量

7.1 指针解决什么问题

专题材料指出,指针指向存储在堆中的变量。堆变量在程序运行期间可动态分配,并通过指针访问。

c = PTR_NEW(2.0D) PRINT, *c

PTR_NEW创建指针,*c表示解引用并获取指向的数据。

7.2 指针的共享特点

若两个指针指向同一堆变量,对其中一个进行修改,会影响另一个访问到的结果。这是因为修改的是堆中的同一份数据,而不是复制后的独立变量。

操作含义
PTR_NEW(data)创建堆变量并复制数据
PTR_NEW(data,/NO_COPY)将数据直接移入堆,减少复制
*point访问指针指向的数据
PTR_VALID(point)检查指针是否有效
PTR_FREE, point释放堆变量

7.3/NO_COPY与大数据

pData = PTR_NEW(data, /NO_COPY)

/NO_COPY用于避免复制大数组,可以减少内存消耗。执行后,原变量的数据所有权发生转移,程序不应继续假设原变量仍保存完整数据。

在遥感影像处理中,一个数组可能占用数百MB甚至更多。指针和/NO_COPY可以提高内存效率,但也增加了内存管理复杂度。使用完毕后应释放指针:

PTR_FREE, pData

7.4 指针的适用场景

场景使用指针的原因
可选大数组没有数据时可使用空指针
多模块共享数据避免重复复制
动态结构运行期间创建和释放
复杂界面状态在事件处理中保存共享变量
大影像缓存减少内存复制

如果普通变量已经能够清晰完成任务,就不必为了“高级”而使用指针。


第八章 链表与哈希表

8.1 链表

IDL链表可保存不同类型的成员,适合长度动态变化的有序集合。

list = LIST('one', 2.0, 3, 4L, PTR_NEW(5), {n:6}, COMPLEX(7,0))

成员可通过索引访问:

PRINT, list[0]
链表方法作用
Add添加成员
Count返回成员数量
IsEmpty判断是否为空
Remove移除成员
Reverse逆转顺序
ToArray转换为数组
Where按条件查询

链表适合保存文件列表、任务列表、动态结果集合和不同类型对象。

8.2 哈希表

哈希表通过键访问值,适合保存配置项和名称—对象映射。

hash = HASH('black', 0, 'gray', 128, 'grey', 128, 'white', 255)

访问:

PRINT, hash['black']

新增成员:

hash['green'] = 50

也可写为:

hash += HASH('green', 50)
哈希表方法作用
Count返回成员数量
HasKey判断是否包含键
IsEmpty判断是否为空
Keys返回所有键
Values返回所有值
Remove删除成员
ToStruct转换为结构体
Where查询成员

8.3 结构体、链表和哈希表如何选择

数据结构主要特点更适合的情况
结构体字段固定、访问清晰影像元数据、固定配置
链表有序、长度动态、成员可异构文件队列、任务序列
哈希表键值访问、字段动态参数表、名称映射和配置

在ENVI批处理中,可使用链表保存待处理文件,使用哈希表保存任务参数,使用结构体保存每个结果的固定统计信息。


第九章 运算符

9.1 数学运算符

运算符含义
+加法
++自增
-减法
--自减
*乘法
/除法
^
MOD取余
<取较小值
>取较大值

IDL中的<>除了出现在关系判断中,还可以作为取小和取大运算。使用时应结合上下文区分。

9.2 逻辑与位运算

类型运算符
逻辑与&&
逻辑或`
逻辑非~
位与AND
位非NOT
位或OR
位异或XOR

逻辑运算用于条件真假,位运算直接处理整数的二进制位。遥感质量控制数据经常使用位编码,因此位与、位移和掩码操作具有实际用途。

9.3 关系运算符

运算符含义
EQ等于
NE不等于
GE大于等于
GT大于
LE小于等于
LT小于

IDL关系运算通常写成关键字形式,而不是常见的==!=。例如:

IF value GT 0 THEN PRINT, value

对数组使用关系运算时,会返回布尔数组,可配合WHERE筛选像元。

9.4 数组乘与矩阵乘

专题材料区分了:

运算符作用
#数组乘
##矩阵乘

矩阵维度和乘法方向需要通过小型示例验证。对于遥感算法中的线性变换、回归和主成分计算,矩阵形状错误是常见问题,应在计算前使用HELP检查维度。

9.5 其他符号

符号用途
()控制运算顺序、函数参数
[]数组和下标
?:条件表达式
->调用对象方法
*指针解引用
$续行符

$还可出现在变量名中,但在代码行末通常表示下一行继续。为了避免阅读混乱,应保持续行缩进统一。


第十章 程序控制

10.1 条件、循环与跳转

类型语句适用场景
条件IF单一条件判断
多分支CASE多个互斥值
多分支SWITCH允许继续执行后续分支
固定循环FOR已知次数
条件循环WHILE条件成立时继续
后判断循环REPEAT至少执行一次
容器遍历FOREACH遍历链表、哈希表等
跳出BREAK退出循环
跳过CONTINUE跳到下一轮
跳转GOTO跳到标签,不建议大量使用

10.2IF结构

IF condition THEN BEGIN ; 条件成立 ENDIF ELSE BEGIN ; 条件不成立 ENDELSE

当分支只有一条语句时,可以省略BEGINENDIF,但复杂程序中保持块结构通常更清晰。

10.3CASESWITCH

CASE适合根据一个表达式选择一个分支;SWITCH允许从匹配位置继续向后执行。若不了解两者差异,容易造成多执行分支的问题。

10.4 遥感批处理中的循环

FOR i = 0, N_ELEMENTS(files)-1 DO BEGIN file = files[i] ; 打开并处理文件 ENDFOR

批处理程序还应考虑:

  • 文件列表为空;
  • 某个文件读取失败;
  • 输出已存在;
  • 单个文件失败后是否继续;
  • 是否记录日志。

程序控制不仅用于实现流程,还决定程序在异常条件下是否稳定。


第十一章 参数传递

11.1 位置参数与关键字参数

IDL过程和函数可以同时使用位置参数和关键字参数。

PRO Process_Image, input_file, output_file, METHOD=method, OVERWRITE=overwrite

调用:

Process_Image, in_file, out_file, METHOD='nearest', /OVERWRITE
参数类型特点建议用途
位置参数按顺序传入必需且数量较少的参数
关键字参数按名称传入可选参数和配置项
开关关键字使用/KEYWORD布尔选项

位置参数过多会降低可读性,因此复杂ENVI工具通常把可选配置设计为关键字。

11.2 地址传递与值传递

专题材料强调IDL参数传递涉及地址和值。IDL过程参数通常可以修改调用者变量,因此编写过程时应明确哪些参数是输入、哪些是输出。

例如:

PRO Add_One, value value = value + 1 END

调用后,原变量可能发生改变。为了避免意外修改,可以在过程内部创建副本,或在文档中明确参数方向。

11.3 参数设计建议

参数类别命名建议示例
输入名称直接表示数据input_raster
输出可使用out_前缀out_result
可选参数使用关键字METHOD=method
布尔开关使用开关关键字/OVERWRITE
错误信息独立输出或异常机制ERROR=error

第十二章 关键字继承

12.1_EXTRA_REF_EXTRA

专题材料给出两种关键字继承机制:

关键字传递方式
_EXTRA值传递
_REF_EXTRA引用传递

关键字继承允许一个过程接收自身未明确声明的关键字,并继续传递给内部调用的过程或函数。这样可以减少包装函数重复声明大量参数。

12.2 关键字继承的使用场景

假设自定义过程封装了绘图函数:

PRO Show_Result, data, _EXTRA=extra p = PLOT(data, _EXTRA=extra) END

调用者可以把颜色、标题和线型等关键字传给内部PLOT函数,而Show_Result不需要逐一声明所有绘图参数。

在ENVI二次开发中,关键字继承可用于:

  • 包装ENVI API;
  • 传递任务参数;
  • 扩展绘图和输出函数;
  • 保持接口兼容。

但关键字传递过于隐式,也会降低代码可读性。对于核心业务参数,仍应明确声明。


第十三章 将语言基础应用到ENVI二次开发

13.1 语言知识与开发任务的对应关系

IDL知识ENVI二次开发中的用途
变量与类型保存路径、阈值、数据类型和任务参数
数组处理波段、掩膜和像元计算
字符串文件命名、目录遍历和产品日期解析
结构体保存影像元数据和统计结果
指针管理大数组和界面共享状态
链表保存动态文件和任务列表
哈希表保存配置和名称—对象映射
运算符实现指数、阈值和逻辑筛选
控制语句批处理、条件分支和异常流程
参数传递设计可复用过程和函数
关键字继承包装ENVI与绘图接口

13.2 一个典型文件批处理框架

PRO Batch_Process, input_dir, output_dir, OVERWRITE=overwrite files = FILE_SEARCH(input_dir, '*.dat', COUNT=count) IF count EQ 0 THEN BEGIN PRINT, 'No input files.' RETURN ENDIF FOR i = 0, count-1 DO BEGIN input_file = files[i] base_name = FILE_BASENAME(input_file, '.dat') output_file = FILEPATH(base_name + '_result.dat', ROOT_DIR=output_dir) IF FILE_TEST(output_file) AND ~KEYWORD_SET(overwrite) THEN CONTINUE ; 在此调用ENVI任务或自定义算法 ENDFOR END

这个框架同时使用了字符串、数组、循环、条件、关键字参数和文件函数。后续加入ENVI API后,就可以发展为实际遥感批处理程序。

13.3 代码组织建议

文件类型建议内容
主程序程序入口和总体流程
数据读取模块文件搜索、元数据和数据打开
算法模块指数、分类和统计计算
输出模块文件保存、命名和日志
公共工具字符串、路径和参数检查
测试文件小数据和单元测试

把所有代码写在一个.pro文件中,短期看起来方便,但后期难以维护。随着ENVI开发内容增加,应逐步按功能拆分。


第十四章 常见错误与排查思路

问题表现常见原因排查方式
除法结果为整数输入变量是整型使用HELP检查类型并显式转浮点
数组裁剪位置错误行列下标顺序理解错误用小数组测试索引
读取影像方向异常维度或存储顺序错误检查SIZE和原始文件说明
文件找不到文件不在搜索路径检查工作目录和IDL路径
字符串比较失败大小写或空格不同使用STRUPCASESTRTRIM
结构体无法新增字段结构体字段固定使用CREATE_STRUCT扩展或改用哈希表
内存持续增长指针或对象未释放使用PTR_FREEOBJ_DESTROY
循环跳过错误文件扩展名解析不正确检查STRPOSSTRMID结果
参数被意外修改地址传递明确输入输出并创建副本
关键字未传入内部函数_EXTRA使用错误检查关键字继承写法

排查IDL程序时,应优先检查数据类型、数组维数和文件路径。许多看似算法错误的问题,实际来自整型计算、维度顺序或字符串空格。


第十五章 本篇学习重点总结

IDL语言基础可以概括为三条主线。

第一条是数据线:变量、数组、字符串、结构体、指针、链表和哈希表决定程序如何保存和组织数据。其中数组是遥感影像处理的核心,字符串决定文件和产品管理,结构体与哈希表适合保存元数据和配置。

第二条是计算线:运算符、条件、循环和参数传递决定算法如何执行。只有理解整型和浮点型差异、数组关系运算和矩阵维度,才能正确实现遥感公式和批处理。

第三条是工程线:工作空间、工程、源码文件、编译、运行和发布决定程序如何从临时代码变成可维护工具。ENVI二次开发最终需要同时具备这三类能力。


第十六章 术语表

术语说明
工作空间用于管理IDL工程和环境配置的目录
工程组织同一程序源码与资源的开发单元
.proIDL源码文件扩展名
.savIDL编译保存文件
动态类型变量在运行中可改变数据类型
系统变量!开头的全局系统状态变量
数组IDL科学计算和图像处理的核心数据结构
结构体由多个命名字段组成的复合变量
指针指向堆变量的引用
堆变量在运行期间动态分配的全局内存变量
链表有序且长度可动态变化的对象容器
哈希表按键访问值的动态容器
WHERE根据条件查找数组索引
#IDL数组乘运算符
##IDL矩阵乘运算符
位置参数按调用顺序传递的参数
关键字参数按名称传递的可选参数
_EXTRA以值方式继承关键字
_REF_EXTRA以引用方式继承关键字
/NO_COPY在部分操作中避免复制大数据的关键字

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询