使用 IDL 代码创建分块 TIFF 文件
12121 评价此文章:
暂无评分
使用 IDL 代码创建分块 TIFF 文件
匿名作者 2014年6月5日,星期四
下方显示的代码示例,使用了分块图像格式而非标准的TIFF图像格式来写入TIFF图像。标准的TIFF图像使用条带,这些条带横跨整个X维度,并且仅在Y维度上进行分割。根据TIFF规范文档第15节所述:
对于低分辨率到中等分辨率的图像,将图像分解为条带的标准TIFF方法是足够的。然而,对于高分辨率图像,如果图像被分解为大致正方形的图块,而不是水平方向很宽但垂直方向很窄的条带,则访问效率更高,并且压缩效果往往更好。
这是一个快速测试来检查支持的数据类型:
IDL> data = double(dist(800,600))
IDL> tiff6_write, 'test.tif', data & help, read_tiff('test.tif')
<表达式> DOUBLE = 数组[800, 600]
IDL> tiff6_write, 'test.tif', float(data) & help, read_tiff('test.tif')
<表达式> FLOAT = 数组[800, 600]
IDL> tiff6_write, 'test.tif', ulong(data) & help, read_tiff('test.tif')
<表达式> ULONG = 数组[800, 600]
IDL> tiff6_write, 'test.tif', long(data) & help, read_tiff('test.tif')
<表达式> LONG = 数组[800, 600]
IDL> tiff6_write, 'test.tif', uint(data) & help, read_tiff('test.tif')
<表达式> UINT = 数组[800, 600]
IDL> tiff6_write, 'test.tif', fix(data) & help, read_tiff('test.tif')
<表达式> INT = 数组[800, 600]
IDL> tiff6_write, 'test.tif', byte(data) & help, read_tiff('test.tif')
<表达式> BYTE = 数组[800, 600]
以下是用于生成分块 TIFF 文件的代码:
**function** **tiff6\_Ifd**, tag, type, count,valueOffset
**compile\_opt** idl2,logical\_predicate
typelen = [**1**,**1**,**1**,**2**,**4**,**8**,**1**,**1**,**2**,**4**,**8**,**4**,**8**]
ifd = { tiff6ifd, tag: **0us**, type: **0us**, count: **0ul**, valueOffset: **0ul** }
ifd.*tag* = tag
ifd.*type* = type
ifd.*count* = count
len = typelen[type]\*count
**if** len **le** **4** **then** **begin**
**case** type **of**
**3**: ifd.*valueOffset*= **ulong**([**uint**(valueOffset), **0us**],**0**)
**4**: ifd.*valueOffset*= **ulong**(valueOffset)
**8**: ifd.*valueOffset*= **ulong**([**fix**(valueOffset), **0s**],**0**)
**9**: ifd.*valueOffset*= **ulong**(**long**(valueOffset),**0**)
**11**: ifd.*valueOffset*= **ulong**(**float**(valueOffset),**0**)
**else**: **if** **max**(type **eq** [**1**,**2**,**6**,**7**]) **then** **begin**
ifd.*valueOffset* = **ulong**([**byte**(valueOffset), **0b**,**0b**,**0b**],**0**)
**endif** **else** **message**, 'Unsupported type: '+**strtrim**(type,**2**)
**endcase**
**endif** **else** **begin**
ifd.*valueOffset* = **ulong**(valueOffset)
**if** **arg\_present**(valueOffset) **then** **begin**
valueOffset += len
**endif**
**endelse**
**return**, ifd
**end**
**pro** **tiff6\_write**, filename, data
**compile\_opt** idl2,logical\_predicate
;header
byteord = **byte**(**1us**,**0**) ? 'II' : 'MM'
header = { byteord: byteord, magic: **42us**, ifdOffset: **8ul** }
numIfd = **18us**
;determine length and type
sz = **size**(data, /struct)
sz.*dimensions* >= **1**
h = **hash**('BYTE',[**1**,**1**,**1**],'INT',[**8**,**2**,**2**],'UINT',[**3**,**2**,**1**],'LONG',[**9**,**4**,**2**], $
'ULONG',[**4**,**4**,**1**],'FLOAT',[**11**,**4**,**3**],'DOUBLE',[**12**,**8**,**3**])
**if** h.**HasKey**(sz.*type\_name*)**then** **begin**
info = (**orderedhash**(**list**('type','len','frmt'), $
**list**(h[sz.*type\_name*],/extract))).**ToStruct**()
**endif** **else** **message**, 'Unsupported type: '+sz.*type\_name*
;strings need to be 0 terminated and even length
software = [**byte**('IDL 8.3'),**0b**]
datetime = [**byte**(**string**(**systime**(/julian), format= $
'(c(cyi4.4,":",cmoi2.2,":",cdi2.2,"",cHi2.2,":",cmi2.2,":",csi2.2))')),**0b**]
;compute tile info
tileSize = **128**
tileByteSize = info.*len*\*tileSize^**2**
n = sz.*dimensions*/tileSize + (sz.*dimensions* **mod** tileSize **ne** **0**)
ntiles = n[**0**]\*n[**1**]
ptr = **8** + **2** + numIfd\***12** + **4**
;fill in fields
ifds = **list**()
ifds.**Add**, **tiff6\_ifd**(**256**, **4**, **1**, sz.*dimensions*[**0**]) ; width
ifds.**Add**, **tiff6\_ifd**(**257**, **4**, **1**, sz.*dimensions*[**1**]) ; length
ifds.**Add**, **tiff6\_ifd**(**258**, **3**, **1**, info.*len*\***8**) ; bits
ifds.**Add**, **tiff6\_ifd**(**259**, **3**, **1**, **1**) ; compression
ifds.**Add**, **tiff6\_ifd**(**262**, **3**, **1**, **1**) ; photometric interpretation
ifds.**Add**, **tiff6\_ifd**(**274**, **3**, **1**, **1**) ; orientation
ifds.**Add**, **tiff6\_ifd**(**277**, **3**, **1**, **1**) ; samples per pixel
ifds.**Add**, **tiff6\_ifd**(**282**, **5**, **1**, ptr) ; xresolution
ifds.**Add**, **tiff6\_ifd**(**283**, **5**, **1**, ptr) ; yresolution
ifds.**Add**, **tiff6\_ifd**(**284**, **3**, **1**, **1**) ; planar configuration
ifds.**Add**, **tiff6\_ifd**(**296**, **3**, **1**, **2**) ; resolution unit
ifds.**Add**, **tiff6\_ifd**(**305**, **2**, **n\_elements**(software), ptr) ; software
ifds.**Add**, **tiff6\_ifd**(**306**, **2**, **n\_elements**(datetime), ptr) ; datetime
ifds.**Add**, **tiff6\_ifd**(**322**, **4**, **1**, tileSize) ; tile width
ifds.**Add**, **tiff6\_ifd**(**323**, **4**, **1**, tileSize) ; tile length
ifds.**Add**, **tiff6\_ifd**(**324**, **4**, ntiles, ptr) ; tile offsets
ifds.**Add**, **tiff6\_ifd**(**325**, **4**, ntiles, ptr) ; tile byte counts
ifds.**Add**, **tiff6\_ifd**(**339**, **3**, **1**, info.*frmt*) ; sample format
;fields that require more data
aux = **list**()
aux.**Add**, **ulong**([**100**,**1**])
aux.**Add**, **ulong**([**100**,**1**])
aux.**Add**, software
aux.**Add**, datetime
aux.**Add**, **ulindgen**(ntiles, start=ptr, increment=tileByteSize)
tmp = **replicate**(tileByteSize, ntiles)
aux.**Add**, tmp
**if** numifd **ne** **n\_elements**(ifds) **then** **message**, 'IFD size mismatch'
;write to file
**openw**, lun, filename,/get\_lun
**writeu**, lun, header
**writeu**, lun, numIfd
**writeu**, lun, ifds.**ToArray**()
**writeu**, lun, **0ul** ; next IFD, formulti image
**foreach** x, aux **do** **writeu**, lun, x
tmp = **make\_array**([tileSize,tileSize], type=**size**(data,/type))
**for** j=**0**, n[**1**]-**1** **do** **begin**
ys = j\*tileSize
ye = (j\*tileSize + tileSize-**1**) < (sz.*dimensions*[**1**]-**1**)
**for** i=**0**, n[**0**]-**1** **do** **begin**
xs = i\*tileSize
xe = (i\*tileSize +tileSize-**1**) < (sz.*dimensions*[**0**]-**1**)
tmp[**0**,**0**] = data[xs:xe,ys:ye]
**writeu**, lun, tmp
**endfor**
**endfor**
**free\_lun**, lun
**end**