Source code for fabio.pnmimage

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

Authors: Henning O. Sorensen & Erik Knudsen
         Center for Fundamental Research: Metal Structures in Four Dimensions
         Risoe National Laboratory
         Frederiksborgvej 399
         DK-4000 Roskilde
         email:henning.sorensen@risoe.dk

"""
# Get ready for python3:
from __future__ import with_statement, print_function

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

SUBFORMATS = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7']

HEADERITEMS = ['SUBFORMAT', 'DIMENSIONS', 'MAXVAL']
P7HEADERITEMS = ['WIDTH', 'HEIGHT', 'DEPTH', 'MAXVAL', 'TUPLTYPE', 'ENDHDR']

[docs]class pnmimage(fabioimage): def __init__(self, *arg, **kwargs): fabioimage.__init__(self, *arg, **kwargs) fun = getattr(fabioimage, '__init__', lambda x: None) fun(self) self.data = None self.header = {'Subformat':'P5'} self.dim1 = self.dim2 = 0 self.m = self.maxval = self.stddev = self.minval = None self.header_keys = self.header.keys() self.bytecode = None def _readheader(self, f): #pnm images have a 3-line header but ignore lines starting with '#' #1st line contains the pnm image sub format #2nd line contains the image pixel dimension #3rd line contains the maximum pixel value (at least for grayscale - check this) self.header_keys = ['SUBFORMAT', 'DIMENSIONS', 'MAXVAL'] l = f.readline().strip() if l not in SUBFORMATS: raise IOError, ('unknown subformat of pnm: %s' % l) else: self.header['SUBFORMAT'] = l if self.header['SUBFORMAT'] == 'P7': self.header_keys = P7HEADERITEMS #this one has a special header while 'ENDHDR' not in l: l = f.readline() while(l[0] == '#'): l = f.readline() s = l.lsplit(' ', 1) if s[0] not in P7HEADERITEMS: raise IOError, ('Illegal pam (netpnm p7) headeritem %s' % s[0]) self.header[s[0]] = s[1] else: self.header_keys = HEADERITEMS for k in self.header_keys[1:]: l = f.readline() while(l[0] == '#'): l = f.readline() self.header[k] = l.strip() #set the dimensions dims = (self.header['DIMENSIONS'].split()) self.dim1, self.dim2 = int(dims[0]), int(dims[1]) #figure out how many bytes are used to store the data #case construct here! m = int(self.header['MAXVAL']) if m < 256: self.bytecode = numpy.uint8 elif m < 65536: self.bytecode = numpy.uint16 elif m < 2147483648L: self.bytecode = numpy.uint32 logger.warning('32-bit pixels are not really supported by the netpgm standard') else: raise IOError, 'could not figure out what kind of pixels you have'
[docs] def read(self, fname, frame=None): """ try to read PNM images @param fname: name of the file @param frame: not relevant here! PNM is always single framed """ self.header = {} self.resetvals() infile = self._open(fname) self._readheader(infile) #read the image data decoder_name = "%sdec" % self.header['SUBFORMAT'] if decoder_name in dir(pnmimage): decoder = getattr(pnmimage, decoder_name) self.data = decoder(infile, self.bytecode) else: raise IOError("No decoder named %s for file %s" % (decoder_name, fname)) self.resetvals() return self
[docs] def P1dec(self, buf, bytecode): data = numpy.zeros((self.dim2, self.dim1)) i = 0 for l in buf.readlines(): try: data[i, :] = numpy.array(l.split()).astype(bytecode) except ValueError: raise IOError, 'Size spec in pnm-header does not match size of image data field' return data
@staticmethod
[docs] def P4dec(buf, bytecode): err = 'single bit (pbm) images are not supported - yet' logger.error(err) raise NotImplementedError(err)
[docs] def P2dec(self, buf, bytecode): data = numpy.zeros((self.dim2, self.dim1)) i = 0 for l in buf.readlines(): try: data[i, :] = numpy.array(l.split()).astype(bytecode) except ValueError: raise IOError, 'Size spec in pnm-header does not match size of image data field' return data
[docs] def P5dec(self, buf, bytecode): l = buf.read() try: data = numpy.reshape(numpy.fromstring(l, bytecode), [self.dim2, self.dim1]).byteswap() except ValueError: raise IOError, 'Size spec in pnm-header does not match size of image data field' return data
@staticmethod
[docs] def P3dec(buf, bytecode): err = '(plain-ppm) RGB images are not supported - yet' logger.error(err) raise NotImplementedError(err)
@staticmethod
[docs] def P6dec(buf, bytecode): err = '(ppm) RGB images are not supported - yet' logger.error(err) raise NotImplementedError(err)
@staticmethod
[docs] def P7dec(buf, bytecode): err = '(pam) images are not supported - yet' logger.error(err) raise NotImplementedError(err)
[docs] def write(self, filename): raise NotImplementedError('write pnm images is not implemented yet.')
@staticmethod
[docs] def checkData(data=None): if data is None: return None else: return data.astype(int)