fabio.pnmimage

Package fabio :: Module pnmimage |
[hide private]
[frames] | no frames]

# Source Code for Module fabio.pnmimage

      1  #!/usr/bin/env python
      2  #coding: utf8
      3  """
      4
      5  Authors: Henning O. Sorensen & Erik Knudsen
      6           Center for Fundamental Research: Metal Structures in Four Dimensions
      7           Risoe National Laboratory
      8           Frederiksborgvej 399
      9           DK-4000 Roskilde
     10           email:henning.sorensen@risoe.dk
     11
     12  """
     13
     14  import numpy, logging
     15  logger = logging.getLogger("pnmimage")
     16  from fabioimage import fabioimage
     17
     18  SUBFORMATS = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7']
     19
     20  HEADERITEMS = ['SUBFORMAT', 'DIMENSIONS', 'MAXVAL']
     21  P7HEADERITEMS = ['WIDTH', 'HEIGHT', 'DEPTH', 'MAXVAL', 'TUPLTYPE', 'ENDHDR']
     22
     23 -class pnmimage(fabioimage):
     24 -    def __init__(self, *arg, **kwargs):
     25          fabioimage.__init__(self, *arg, **kwargs)
     26          fun = getattr(fabioimage, '__init__', lambda x: None)
     27          fun(self)
     28          self.data = None
     29          self.header = {'Subformat':'P5'}
     30          self.dim1 = self.dim2 = 0
     31          self.m = self.maxval = self.stddev = self.minval = None
     32          self.header_keys = self.header.keys()
     33          self.bytecode = None
     34
     35 -    def _readheader(self, f):
     36          #pnm images have a 3-line header but ignore lines starting with '#'
     37          #1st line contains the pnm image sub format
     38          #2nd line contains the image pixel dimension
     39          #3rd line contains the maximum pixel value (at least for grayscale - check this)
     40          self.header_keys = ['SUBFORMAT', 'DIMENSIONS', 'MAXVAL']
     41
     42          l = f.readline().strip()
     43          if l not in SUBFORMATS:
     44              raise IOError, ('unknown subformat of pnm: %s' % l)
     45          else:
     46              self.header['SUBFORMAT'] = l
     47
     48          if self.header['SUBFORMAT'] == 'P7':
     49              self.header_keys = P7HEADERITEMS
     50              #this one has a special header
     51              while 'ENDHDR' not in l:
     52                  l = f.readline()
     53                  while(l[0] == '#'): l = f.readline()
     54                  s = l.lsplit(' ', 1)
     55                  if s[0] not in P7HEADERITEMS:
     56                      raise IOError, ('Illegal pam (netpnm p7) headeritem %s' % s[0])
     57                  self.header[s[0]] = s[1]
     58          else:
     59              self.header_keys = HEADERITEMS
     60              for k in self.header_keys[1:]:
     61                  l = f.readline()
     62                  while(l[0] == '#'): l = f.readline()
     63                  self.header[k] = l.strip()
     64
     65          #set the dimensions
     66          dims = (self.header['DIMENSIONS'].split())
     67          self.dim1, self.dim2 = int(dims[0]), int(dims[1])
     68          #figure out how many bytes are used to store the data
     69          #case construct here!
     70          m = int(self.header['MAXVAL'])
     71          if m < 256:
     72              self.bytecode = numpy.uint8
     73          elif m < 65536:
     74              self.bytecode = numpy.uint16
     75          elif m < 2147483648L:
     76              self.bytecode = numpy.uint32
     77              logger.warning('32-bit pixels are not really supported by the netpgm standard')
     78          else:
     79              raise IOError, 'could not figure out what kind of pixels you have'
     80
     81 -    def read(self, fname, frame=None):
     82          """
     83          try to read PNM images
     84          @param fname: name of the file
     85          @param frame: not relevant here! PNM is always single framed
     86          """
     87          self.header = {}
     88          self.resetvals()
     89          infile = self._open(fname)
     90          self._readheader(infile)
     91
     92          #read the image data
     93          decoder_name = "%sdec" % self.header['SUBFORMAT']
     94          if decoder_name in dir(pnmimage):
     95              decoder = getattr(pnmimage, decoder_name)
     96              self.data = decoder(infile, self.bytecode)
     97          else:
     98              raise IOError("No decoder named %s for file %s" % (decoder_name, fname))
     99          self.resetvals()
    100          return self
    101
    102      @staticmethod
    103 -    def P1dec(buf, bytecode):
    104          data = numpy.zeros((self.dim2, self.dim1))
    105          i = 0
    106          for l in buf.readlines():
    107              try:
    108                  data[i, :] = numpy.array(l.split()).astype(bytecode)
    109              except ValueError:
    110                  raise IOError, 'Size spec in pnm-header does not match size of image data field'
    111          return data
    112
    113      @staticmethod
    114 -    def P4dec(buf, bytecode):
    115          err = 'single bit (pbm) images are not supported - yet'
    116          logger.error(err)
    117          raise NotImplementedError(err)
    118
    119      @staticmethod
    120 -    def P2dec(buf, bytecode):
    121          data = numpy.zeros((self.dim2, self.dim1))
    122          i = 0
    123          for l in buf.readlines():
    124              try:
    125                  data[i, :] = numpy.array(l.split()).astype(bytecode)
    126              except ValueError:
    127                  raise IOError, 'Size spec in pnm-header does not match size of image data field'
    128          return data
    129
    130      @staticmethod
    131 -    def P5dec(buf, bytecode):
    132          l = buf.read()
    133          try:
    134              data = numpy.reshape(numpy.fromstring(l, bytecode), [self.dim2, self.dim1]).byteswap()
    135          except ValueError:
    136              raise IOError, 'Size spec in pnm-header does not match size of image data field'
    137          return data
    138
    139      @staticmethod
    140 -    def P3dec(buf, bytecode):
    141          err = '(plain-ppm) RGB images are not supported - yet'
    142          logger.error(err)
    143          raise NotImplementedError(err)
    144
    145      @staticmethod
    146 -    def P6dec(buf, bytecode):
    147          err = '(ppm) RGB images are not supported - yet'
    148          logger.error(err)
    149          raise NotImplementedError(err)
    150
    151      @staticmethod
    152 -    def P7dec(buf, bytecode):
    153          err = '(pam) images are not supported - yet'
    154          logger.error(err)
    155          raise NotImplementedError(err)
    156
    157 -    def write(self, filename):
    158          raise NotImplementedError('write pnm images is not implemented yet.')
    159
    160      @staticmethod
    161 -    def checkData(data=None):
    162          if data is None:
    163              return None
    164          else:
    165              return data.astype(int)
    166