/dependencies/pymic/zvi/zviread.py
Python | 209 lines | 196 code | 0 blank | 13 comment | 0 complexity | 69feac371d4c414f70e0454eb26c2b7a MD5 | raw file
Possible License(s): Apache-2.0
- '''
- read ZVI (Zeiss) image file
- - incomplete support
- - open uncompressed image from multi item image (Count>0)
- - require OleFileIO_PL - a Python module to read MS OLE2 files
- http://www.decalage.info/en/python/olefileio#attachments
- .. code-block:: python
- from zvi import zviread, getcount
-
- fname = '../../test/data/test1.zvi'
- n = getcount(fname)
- for s in getdir(fname):
- print s
- print 'Count = ',n
- for p in range(n):
- zvi = zviread(fname,p)
- x = zvi.Image.Array
- print x
- '''
- __author__ = 'olivier'
- import struct
- import numpy as np
- from collections import namedtuple
- import sys
- #sys.path.append('./dependencies')
- import OleFileIO_PL
- def i32(data):
- '''return int32 from len4 string'''
- low,high = struct.unpack('<hh',data[:4])
- return (high << 16) + low
- def print_hex(data,n = 16):
- print '|'.join(['%02x'%(ord(data[i])) for i in range(n)])
- def read_struct(data,t):
- '''read a t type from data(str)'''
- # vartype = (ord(data[0]),ord(data[1]))
- # print t,vartype
- next = data[2:] #skip vartype I16
- if t is '?':
- return [None,next]
- if t is 'EMPTY':
- return [None,next]
- if t is 'NULL':
- return [None,next]
- if t is 'I2':
- low = struct.unpack('<h',next[:2])
- return [low[0],next[2:]]
- if t is 'I4':
- r = i32(next[:4])
- return [r,next[4:]]
- if t is 'BLOB':
- size = i32(next[:4])
- r = next[4:4+size]
- return [r,next[4+size:]]
- if t is 'BSTR':
- #! 4 extra bytes escaped
- low,high = struct.unpack('<hh',next[:4])
- size = (high << 16) + low
- if size>0:
- s = struct.unpack('s',next[4:4+size])
- next = next[4+4+size:]
- else:
- s=''
- next = next[4+4:]
- return [s,next]
- raise ValueError('unknown type:%s'%type)
- ZviImageTuple = namedtuple('ZviImageTuple',
- 'Version FileName Width Height Depth PixelFormat Count \
- ValidBitsPerPixel m_PluginCLSID Others Layers Scaling')
- def read_image_container_content(stream):
- '''returns a ZviImageTuple from a stream'''
- data = stream.read()
- content = {}
- next = data
- [version,next] = read_struct(next,'I4')
- # [Type,next] = read_struct(next,'I4')
- # [TypeDescription,next] = read_struct(next,'BSTR')
- [filename,next] = read_struct(next,'BSTR')
- [width,next] = read_struct(next,'I4')
- [height,next] = read_struct(next,'I4')
- [depth,next] = read_struct(next,'I4')
- [pixel_format,next] = read_struct(next,'I4')
- [count,next] = read_struct(next,'I4')
- [valid_bits_per_pixel,next] = read_struct(next,'I4')
- [m_PluginCLSID,next] = read_struct(next,'I4')
- [others,next] = read_struct(next,'I4')
- [layers,next] = read_struct(next,'I4')
- [scaling,next] = read_struct(next,'I2')
- zvi_image = ZviImageTuple(version, filename, width, height, depth, pixel_format,
- count, valid_bits_per_pixel,m_PluginCLSID, others, layers, scaling)
- return zvi_image
- ZviItemTuple = namedtuple('ZviItemTuple',
- 'Version FileName Width Height Depth PixelFormat Count \
- ValidBitsPerPixel Others Layers Scaling Image')
- PixelFormat = {1:(3,'ByteBGR'),
- 2:(4,'ByteBGRA'),
- 3:(1,'Byte'),
- 4:(2,'Word'),
- 5:(4,'Long'),
- 6:(4,'Float'),
- 7:(8,'Double'),
- 8:(6,'WordBGR'),
- 9:(4,'LongBGR')}
- def read_item_storage_content(stream):
- '''returns ZviItemTuple from the stream'''
- data = stream.read()
- next = data
- [version,next] = read_struct(next,'I4')
- # [Type,next] = read_struct(next,'I4')
- # [TypeDescription,next] = read_struct(next,'BSTR')
- [filename,next] = read_struct(next,'BSTR')
- [width,next] = read_struct(next,'I4')
- [height,next] = read_struct(next,'I4')
- [depth,next] = read_struct(next,'I4')
- [pixel_format,next] = read_struct(next,'I4')
- [count,next] = read_struct(next,'I4')
- [valid_bits_per_pixel,next] = read_struct(next,'I4')
- [others,next] = read_struct(next,'BLOB')
- [layers,next] = read_struct(next,'BLOB')
- [scaling,next] = read_struct(next,'BLOB')
- # offset is image size + header size(28)
- offset = width*height*PixelFormat[pixel_format][0] + 28
- #parse the actual image data
- image = parse_image(data[-offset:])
- #group results into one single structure (namedtuple)
- zvi_item = ZviItemTuple(version, filename, width, height, depth, pixel_format,
- count, valid_bits_per_pixel, others, layers, scaling, image)
- return zvi_item
- ImageTuple = namedtuple('ImageTuple',
- 'Version Width Height Depth PixelWidth PixelFormat \
- ValidBitsPerPixel Array')
- def parse_image(data):
- '''returns ImageTuple from raw image data(header+image)'''
- version = i32(data[:4])
- width = i32(data[4:8])
- height = i32(data[8:12])
- depth = i32(data[12:16])
- pixel_width = i32(data[16:20])
- pixel_format = i32(data[20:24])
- valid_bits_per_pixel = i32(data[24:28])
- raw = np.fromstring(data[28:],'uint16')
- array = np.reshape(raw,(height,width))
- image = ImageTuple(version, width, height, depth, pixel_width, pixel_format,
- valid_bits_per_pixel, array)
- return image
- def getcount(filename):
- '''returns the number of image planes'''
- ole = OleFileIO_PL.OleFileIO(filename)
- s = ['Image', 'Contents']
- stream = ole.openstream(s)
- zvi_image = read_image_container_content(stream)
- return zvi_image.Count
- def getdir(filename):
- '''returns the content structure(streams) of the zvi file + length of each streams '''
- dir = []
- ole = OleFileIO_PL.OleFileIO(filename)
- for s in ole.listdir():
- stream = ole.openstream(s)
- dir.append('%10d %s'%(len(stream.read()),s))
- return dir
- def zviread(fname,plane):
- '''returns ZviItemTuple of the plane from zvi file fname'''
- ole = OleFileIO_PL.OleFileIO(fname)
- s = ['Image', 'Item(%d)'%plane, 'Contents']
- stream = ole.openstream(s)
- return read_item_storage_content(stream)
- def test():
- '''simple zvi 4 plane image reading'''
- fname = '../../test/data/test1.zvi'
- n = getcount(fname)
- for s in getdir(fname):
- print s
- print 'Count = ',n
- for p in range(n):
- zvi = zviread(fname,p)
- x = zvi.Image.Array
- print x
- if __name__ == "__main__":
- test()