File: binaryimage.py

package info (click to toggle)
python-fabio 0.11.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,092 kB
  • sloc: python: 19,244; ansic: 1,085; makefile: 219; sh: 215
file content (134 lines) | stat: -rw-r--r-- 4,872 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# coding: utf-8
#
#    Project: X-ray image reader
#             https://github.com/silx-kit/fabio
#
#
#    Copyright (C) European Synchrotron Radiation Facility, Grenoble, France
#
#    Principal author:       Jérôme Kieffer (Jerome.Kieffer@ESRF.eu)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

"""
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__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__version__ = "17/10/2012"

import io
from .fabioimage import FabioImage
import numpy
import logging
logger = logging.getLogger(__name__)


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.
    """

    DESCRIPTION = "Binary format (none-compressed 2D images)"

    DEFAULT_EXTENSIONS = ["bin"]

    def __init__(self, *args, **kwargs):
        FabioImage.__init__(self, *args, **kwargs)

    @staticmethod
    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

    def read(self, fname, dim1, dim2, offset=0, bytecode="int32", endian="<"):
        """
        Read a binary image

        :param str fname: file name
        :param int dim1: image dimensions (Fast index)
        :param int dim2: image dimensions (Slow index)
        :param int 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._shape = dim2, dim1
        self._bytecode = bytecode
        f = open(self.filename, "rb")
        dims = [dim2, dim1]
        bpp = len(numpy.array(0, bytecode).tobytes())
        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:
                logger.warning('expected datablock too large, please check bytecode settings: {}'.format(bytecode))
            except Exception:
                logger.debug("Backtrace", exc_info=True)
                logger.error('Uncommon error encountered when reading file')
        rawData = f.read(size)
        data = numpy.frombuffer(rawData, bytecode).copy().reshape(tuple(dims))
        if self.swap_needed(endian):
            data.byteswap(True)
        self.data = data
        self._shape = None
        return self

    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).tobytes())
            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)

    def write(self, fname):
        with self._open(fname, mode="wb") as outfile:
            if isinstance(outfile, io.BufferedWriter):
                self.data.tofile(outfile)
            else:
                outfile.write(self.data.tobytes())


binaryimage = BinaryImage