Source code for fabio.binaryimage

#!/usr/bin/env python
# coding: utf8

# Get ready for python3:
from __future__ import with_statement
__doc__ = """
Authors: Gael Goret, Jerome Kieffer, ESRF, France
Emails: gael.goret@esrf.fr, jerome.kieffer@esrf.fr
        Brian Richard Pauw <brian@stack.nl>

Binary files images are simple none-compressed 2D images only defined by their :
data-type, dimensions, byte order and offset

This simple library has been made for manipulating exotic/unknown files format.
"""

__authors__ = ["Gaël Goret", "Jérôme Kieffer", "Brian Pauw"]
__contact__ = "gael.goret@esrf.fr"
__license__ = "GPLv3+"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__version__ = "17 Oct 2012"

from fabioimage import fabioimage
import numpy, logging
logger = logging.getLogger("binaryimage")

[docs]class binaryimage(fabioimage): """ This simple library has been made for manipulating exotic/unknown files format. Binary files images are simple none-compressed 2D images only defined by their : data-type, dimensions, byte order and offset if offset is set to a negative value, the image is read using the last data but n data in the file, skipping any header. """ def __init__(self, *args, **kwargs): fabioimage.__init__(self, *args, **kwargs) @staticmethod
[docs] def swap_needed(endian): """ Decide if we need to byteswap """ if (endian == '<' and numpy.little_endian) or (endian == '>' and not numpy.little_endian): return False if (endian == '>' and numpy.little_endian) or (endian == '<' and not numpy.little_endian): return True
[docs] def read(self, fname, dim1, dim2, offset=0, bytecode="int32", endian="<"): """ Read a binary image @param fname: file name @type fname: string @param dim1: image dimensions (Fast index) @param dim2: image dimensions (Slow index) @param offset: starting position of the data-block. If negative, starts at the end. @param bytecode: can be "int8","int16","int32","int64","uint8","uint16","uint32","uint64","float32","float64",... @param endian: among short or long endian ("<" or ">") """ self.filename = fname self.dim1 = dim1 self.dim2 = dim2 self.bytecode = bytecode f = open(self.filename, "rb") dims = [dim2, dim1] bpp = len(numpy.array(0, bytecode).tostring()) size = dims[0] * dims[1] * bpp if offset >= 0: f.seek(offset) else: try: f.seek(-size + offset + 1, 2) #seek from EOF backwards except IOError: logging.warn('expected datablock too large, please check bytecode settings: {}'.format(bytecode)) except: logging.error('Uncommon error encountered when reading file') rawData = f.read(size) if self.swap_needed(endian): data = numpy.fromstring(rawData, bytecode).byteswap().reshape(tuple(dims)) else: data = numpy.fromstring(rawData, bytecode).reshape(tuple(dims)) self.data = data return self
[docs] def estimate_offset_value(self, fname, dim1, dim2, bytecode="int32"): "Estimates the size of a file" with open(fname, "rb") as f: bpp = len(numpy.array(0, bytecode).tostring()) size = dim1 * dim2 * bpp totsize = len(f.read()) logger.info('total size (bytes): %s', totsize) logger.info('expected data size given parameters (bytes): %s', size) logger.info('estimation of the offset value (bytes): %s', totsize - size)
[docs] def write(self, fname): with open(fname, mode="wb") as outfile: outfile.write(self.data.tostring())