沿着ImageView边缘划线:IDL开发专题-灵活、多样的输入输出 - ENVI/IDL技术版 - ESRI中国社区 G...

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 20:54:54
社区活动

分享你的收获,讲述你的故事!“我与社区”主题征文活动火热进行中

[资源共享] IDL开发专题-灵活、多样的输入输出

本帖最后由 lianyi_dyq 于 2009-11-2 16:05 编辑

1 输入与输出
     IDL中输入输出的基本原则是:“只要有数据,就可以将其读进IDL”,IDL对数据的格式没有要求,也就是任何数据格式都能自由的解析,这使得IDL成为目前功能最强、最灵活的科学可视化分析语言。
1.1 标准输入输出
1.1.1 输入输出函数
     IDL中读写ASCII码文本是很重要的一部分。标准输入是键盘输入,标准输出指的是屏幕输出显示。表1-1中列出了标准输入输出的几个函数。
   
1.1.2 格式化输出
     数据的格式化输出是按照设计的格式进行输出。IDL支持“%”和“\”。
     标准的输入输出时可以进行格式的自由控制,格式化控制的格式为:[n]FC[+][-][width],各个字段代表的含义见表1-2
     
     

    如下面的 例子
  PRO Test_format
  COMPILE_OPT idl2
  ;
  PRINT, FORMAT = '(A6)', '123456789'
  PRINT, FORMAT = '(I2,$)', INDGEN(6)
  ;
  PRINT, FORMAT = '("First", 20X, "Last", T10, "Middle")'
  PRINT, FORMAT = '("First", 20X, "Last", T4, "Middle")'
  ;
  PRINT, FORMAT = '("First", 5X, "Last", TL2, "Middle")'
  ;
  PRINT, SYSTIME(/JULIAN)
  PRINT, FORMAT='(C())', SYSTIME(/JULIAN)
  PRINT, FORMAT='(C(CMOI,"/",CDI))',SYSTIME(/JULIAN)
  PRINT, FORMAT='(C(CHI2.2,":",CMI2.2,":",CSF05.2))',SYSTIME(/JULIAN)  
  ;
  PRINT, FORMAT='(%"I have %d monkeys, %s,", " and ", I0, " parrots.")', 10, 'Scott', 5
  PRINT, format='(%"I have \xb1%d monkeys [url=file://%22)]\\")'[/url], 5
  ;
  print,'0F'X ; 十六进制转十进制
  print,"17   ; 八进制转十进制
  print, 119, format='(B)';十进制转二进制的
  print, 119, format='(O)';十进制转到八进制
  print, 119, format='(Z)';十进制转到十六进制      
END


1.2 文件读写
1.2.1 打开文件
     IDL从磁盘上的文件读写数据,必须首先把一个逻辑设备号连接到一个特定的文件,然后进行文件操作如打开、关闭和读取等。IDL中的逻辑设备号范围是-2—128,其中1--99是可以用户任意指定的,100-128是根据get_lun和free_lun来管理的,其他是特殊函数专用的。
     0是常规标准输入流,一般是键盘。也就是说下面命令是一致的:
IDL> read,x
IDL> read,0,x
      -1是常规标准输出流,一般是显示屏幕,下面命令的功能是一致的: IDL> PRINTF, -1, X
IDL> PRINTF, -1, X
      -2是错误流,一般是显示屏幕。
     文件操作相关的函数见表1-4。

1.2.2 读写ASCII码文件
      IDL在读写该文件分为有两种格式化文件:自由文件格式和确定的文件格式。
      自由文件格式是用逗号或空白(tab键和空格键)分开文件中的每个元素的ASCII文件。确定的格式文件是用格式说明按照给定的规范进行编排的。二者相比后者比前者更正规一些。
1.2.2.1 读写自由文件格式
      IDL下用ReadF从文件中读入自由格式数据,Printf写入自由格式数据到文件中。IDL中读写自由格式文件遵循下面的几个规则:
      1) 如果读入到字符串变量中,那么,在当前行剩下的所有字符都将读入该变量中。
      2) 输入数据必须用逗号或空白分隔(空格键或tab键)。
      3) 输入通过数字变量完成。数组和结构都可作为数字变量的集合。
      4) 如果当前读入行是空的,并且还有变量要求输入,则读取另一行。
      5) 如果当前读入行不是空的,但是没有变量要求输入,则忽略此行剩下的数。
      6) 尽量将数据转换为变量所希望的数据类型。
      7) 复数数据必须有实数和虚数两部分,用逗号分隔,并用括号括起来。
1.2.2.2 读写确定的文件格式
      读写确定文件格式可同样用ReadF和PrintF命令,它们刚才已用于自由格式文件,但现在文件格式已由Format关键字明确声明。(在读写标准输入和输出时,也可将Format关键字用于Read 和Print命令)。
1.2.2.2.1 通用的格式说明符
      通用格式说明符Format关键字的语法参考1.1.2.
1.2.2.2.2 逗号分隔的确定格式
      有时数据文件必须用确定格式书写,以方便它们被其它软件读取。用逗号分隔的数据文件就是这类文件的典型代表。
      Format=’(F10.3, A1, 2x, F10.3, A1, 2x, F10.3)’
1.2.2.2.3 字符串中读取格式数据
      ReadS是一个有用的IDL命令,可以从字符串变量而不是从文件中为自由格式或确定格式读取数据。ReadS运用了和命令Read和ReadF相同的读取格式数据规则。也就是说,使用ReadS 就象从数据文件中读取一样,所不同的是所读的对象是一个字符串变量。
      当大量信息需从文件头部读取时,此命令特别有用。例如,假设ASCII 数据文件的第一行说明了数据文件的行数和列数,此文件头可以从文件中读取,并且可创建一个大小正确的数组来读取数据。
IDL> firstLine=' 10 24500 12 June 1996'
IDL> columns=0
IDL> rows=0
IDL> date=''
IDL> reads,firstline,columns,rows,date
10 24500 12 June 1996
IDL> print,columns;,rows,date
      10
IDL> print,rows;,date
   24500
IDL> print,date
12 June 1996

1.2.2.3 向导式读取函数
      IDL中提供了ASCII_TEMPLATE,QUERY_ASCII和READ_ASCII函数。 asciiFile =currentPath+'\data\ascii.txt'
  ;依次读取
  OPENR,lun,asciifile,/get_lun
  
  IF lun EQ -1 THEN RETURN;
  tmp = ''
  WHILE(~EOF(lun)) DO BEGIN
    READF,lun,tmp
  ENDWHILE
  
  FREE_LUN,lun
  ;分块读取
  tmp = STRARR(3)
  data = FLTARR(2,4)
  fdata = INTARR(20)
  OPENR,lun,asciifile,/get_lun
  
  READF,lun,tmp
  READF,lun,data
  
  FREE_LUN,lun
  
  ;自定义格式读取
  tmp  =''
  row =0
  columns =0
  type =0
  OPENR,lun,asciifile,/get_lun
  ;
  READF,lun,tmp
  READS,tmp,row,columns,type
  data =MAKE_ARRAY(row,columns,type = type)
  READF,lun,tmp
  READF,lun,tmp
  READF,lun,data
  
  FREE_LUN,lun
  
  template =Ascii_template(asciiFile)
  data = Read_ascii(asciiFile,TEMPLATE=template,count = yNum)
  help,data
  print,data.(0)



1.2.2.4 综合应用举例
      针对上面介绍的三种读取方式,对同一个数据采用了不同的读取方式进行了读取,附代码。
1.2.3 读写二进制文件
      二进制数据文件基本是以一长串的二进制字节存在文件中,这些字节的含义(也就是说,这些字节如何翻译成特定数据类型和结构的)很难描述的,除非刚开始就知道文件写入的是什么内容。二进制数据比格式化数据紧凑得多,经常用于存储大数据文件。有两种命令读写二进制数据,它们与前面用来读取格式数据文件的ReadF和 Print 命令等效。它们是ReadU和WriteU命令。
要读取非格式数据文件,简单定义变量,打开文件读取,并用ReadU命令将字节一个接一个地读入变量中。如果给定了变量的数据类型和组织结构,每个变量按其要求从文件中读出相应的字节数。
1.2.3.1 读写常规二进制文件 IDL> B = BYTARR(192, 192, /NOZERO)
IDL> ; Read the data into B:
IDL> READU, 1, B
IDL> ; Close the file:
IDL> CLOSE, 1
IDL> ; Display the image:
IDL> TV, B

1.2.3.2 读写带头文件的二进制文件
      当数据中含有特定的头文件时,读取的时候有时希望直接跳过,此时需要用Point_Lun函数,该函数支持对文件进行字节定位。
      调用格式为POINT_LUN, Unit, Position,其中Unit是文件打开后的lun,Position一般是需要跳转的字节数。
1.2.3.3 关联变量读写二进制文件
      IDL关联变量是把一个IDL数组或结构变量的组织结构映射到数据文件的内容上。文件被看作是这些重复单元的一个数组。 第一个单元的索引号是0,第二个单元的索引号1等等。关联变量不象常规变量那样将整个数据组都存储在内存里。而是当一关联变量被引用时,IDL仅对需要的部分数据执行相关的输入或输出请求,这部分数据就是要读入内存的。
      有时候大型的二进制数据文件都由一系列的重复单元组成。一个IDL关联变量通常是处理这种数据形式的最好方式(有时候是唯一的方式)。
关联变量有下面的几个优点:
当该变量被用于表达式时,才产生文件的输入和输出动作。不需要单独的读或写命令。
数据集的大小不受内存容量的限制,因为有时它可处理大型的数据集。对于物理存储器来说是太大的数据,通过把此数据分成块就能很容易地处理。
不必提前声明用于映射该数据的数组或结构的数量。
关联变量是效率最高的I/O形式。
1.2.3.4 向导式读取函数
READ_BINARY和BINARY_TEMPLATE
Read_Binary是直接读取二进制文件的函数,用法可参考下面的语句:

vHeadData = READ_BINARY(FILEPATH('head.dat', $
  SUBDIRECTORY=['examples', 'data']), DATA_DIMS=[80,100,57])
IVOLUME, vHeadData


1.2.3.5 例子
      读FY-3的9210AWX文件,FY-2C的卫星黑体亮度温度产品,下面的格式说明是参考国家卫星气候中心的《风云二号C卫星业务产品使用手册》。
  
   PRO test_ReadBinAWX
;
currentPath = sourceroot()
file = currentPath+'data\FY2C_TBB_IR1_OTG_20061130_AOAD.AWX'
;
OpenR, file_lun, file ,/Get_Lun
  ;定位到信息部分
  point_lun,file_lun,20
  HeadLine =indgen(3)
  readu,file_lun,HeadLine
  ;HeadLine[0]-数据的头文件长度 $
  ;HeadLine[]-文件头文件记录数 $
  ;HeadLine[2]-数据的记录数
  point_lun,file_lun,58
  ;定位到信息部分
  BeginDate=indgen(5) ;依次为年月日时分
  EndDate =indgen(5) ;依次为年月日时分
  LatLong=indgen(4) ;依次为左上角纬度经度右下角经度纬度
  readu,file_lun,BeginDate
  readu,file_lun,EndDate
  readu,file_lun,LatLong
  ;
  data = bytarr(HeadLine[2],(HeadLine[0]))
    ;定位到数据部分
  point_lun,file_lun,HeadLine[0]*HeadLine[1]
  readu,file_lun,data  
  
Free_Lun,lun
END




1.3 读写通用格式文件
      IDL可以读写许多常用文件格式,这些文件格式已在表1-5中列出。
  

1.3.1 图像文件信息查询
      IDL中提供了常用图像文件格式的查询程序。这些程序允许在没有真正读取其数据的情况下,就可以查询图像文件,并可以存取随着图像数据文件一起存储在文件里的元数据(关于数据的一些信息)。
      下面是新的图像查询程序列表:
Query_BMP
Query_DICOM
Query_GIF
Query_JPEG
Query_PICT
Query_PNG
Query_PPM
Query_SRF
Query_TIFF
      所有这些查询命令都是以同样的方式工作。它们都是返回0或1的函数,通过返回值确定是否成功地(返回值为1)读取了图像文件里的元数据。如果它们成功地读取了文件,将保存文件信息的IDL结构变量作为输出命令返回给用户。用户通过存取这个结构里面的字段从而获取文件的有关信息。
1.3.2 JPEG文件操作
1.3.2.1 JPEG读操作
      用Read_JPEG命令就可以读取并显示一个JPEG文件。
      假设正在8位显示器上显示24位的图像,应该使用TV命令里的关键字True:
IDL> TV, thisimage, true=1
1.3.2.2 JPEG写操作
      对图形窗口进行拍照可以用TVRD函数。
IDL> image3D=TVRD(true=1)
      最后,用Write_JPEG命令,将图像用输出为JPEG文件,运行命令:
IDL> Write_JPEG, ‘test.jpg’, image3D, true=1, quality=75
1.3.2.3 举例
      对一个jpg文件进行查询及读取操作。
PRO test_CommonImg
  currentPath =file_dirname(routine_file_path(“test_CommonImg”))
  imgFile =currentPath+'\data\idl.jpg'
  ;文件信息查询
  queryStatus = QUERY_IMAGE(imgFile, imageInfo,type = type)
  HELP,imageInfo,/str
  IF queryStatus EQ 1 THEN BEGIN
    CASE type OF
      'BMP': BEGIN      
      END
      'JPEG': BEGIN
        jpgStatus=QUERY_JPEG(imgFile, fileinfo)        
        IF jpgStatus THEN BEGIN
          HELP,fileInfo,/str
          READ_JPEG,imgFile,data
          TV,data,/true  
           image=TVRD(0,0,127,287,/true)
          Write_Jpeg,currentPath+'\data\result.jpg', image,true=1, quality=75
        ENDIF        
      END
      ELSE: BEGIN
      END
    ENDCASE
  ENDIF  
END

1.3.3 HDF数据读入
      HDF有两种基本对象—组(Group)和数据集(Dataset),同时也有一些其他的辅助对象,如数据类型(Datatype)、数据空间(Dataspace)、属性(Attribute)。HDF组织结构有些类似于Windows 中的文件结构,组相当于一个文件夹,数据集相当于一个数据文件,文件夹里面可以包含数据文件,也可以包含其他的组对象,这样嵌套下去,就形成了一个复杂的数据对象,这点正好的对应于HDF逻辑结构的层次性。
HDF文件的操作 读取-编辑
      HDF_OPEN: 这个过程首先要打开HDF文件,通过create关键字来确定是读取文件还是创建一个新的文件。
      HDF_DFAN_ADDFDS:  添加文件描述;Optionally, add a file description.
      HDF_DFAN_ADDFID:  添加文件Optionally, add a file annotation.
      对HDF 文件添加数据用到的过程:
      添加8位图像,用HDF_DFR8_ADDIMAGE 或DFR8_PUTIMAGE;
      添加颜色表,用HDF_DFP_ADDPAL或HDF_DFP_PUTPAL;
      添加24位图像,用HDF_DF24_ADDIMAGE 或HDF_DF24_PUTIMAGE;
      添加多数据时,需要用下面的命令:
      HDF_SD_CREATE 或 HDF_SD_SELECT 建立一个SDS或选择一个现有的SDS; HDF_SD_DIMSET 设置维数信息;
      HDF_SD_ATTRSET 设置属性信息;
      HDF_SD_SETINFO 添加一个数据信息;
      HDF_SD_ADDDATA 添加数据;
      HDF_SD_SETEXTFILE移动数据到外部存储文件;
      HDF_SD_ENDACCESS 结束读取SDS;
      添加数据表(vData)时需要用下面的命令:
      HDF_VD_ATTACH 获取一个数据表的标识;to get a Vdata identifier.      
      HDF_VD_SETINFO写入数据表的信息;
      HDF_VD_FDEFINE to prepare non-trivial fields (optional).
      HDF_VD_WRITE 写入数据表;
      将数据表(Vdata)添加到数据组合(Vgroup)中时,用下面的命令:
      HDF_VG_ATTACH to get a Vgroup identifier.
      HDF_VG_SETINFO to set the Vgroup name and class (optional).
      HDF_VG_INSERT to add the Vdata to a Vgroup.
      HDF_VG_DETACH to close the Vgroup.
      HDF_CLOSE to close the file
示例数据