123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- #!/usr/bin/env python
- # $URL: http://pypng.googlecode.com/svn/trunk/code/pdsimgtopng $
- # $Rev: 154 $
- # PDS Image to PNG
- import re
- import struct
- import png
- class FormatError(Exception):
- pass
- def pdskey(s, k):
- """Lookup key `k` in string `s`. Returns value (as a string), or
- raises exception if not found.
- """
- assert re.match(r' *\^?[:\w]+$', k)
- safere = '^' + re.escape(k) +r' *= *(\w+)'
- m = re.search(safere, s, re.MULTILINE)
- if not m:
- raise FormatError("Can't find %s." % k)
- return m.group(1)
- def img(inp):
- """Open the PDS IMG file `inp` and return (*pixels*, *info*).
- *pixels* is an iterator over the rows, *info* is the information
- dictionary.
- """
- err = __import__('sys').stderr
- consumed = 1024
- s = inp.read(consumed)
- record_type = pdskey(s, 'RECORD_TYPE')
- if record_type != 'FIXED_LENGTH':
- raise FormatError(
- "Can only deal with FIXED_LENGTH record type (found %s)" %
- record_type)
- record_bytes = int(pdskey(s,'RECORD_BYTES'))
- file_records = int(pdskey(s, 'FILE_RECORDS'))
- label_records = int(pdskey(s, 'LABEL_RECORDS'))
- remaining = label_records * record_bytes - consumed
- s += inp.read(remaining)
- consumed += remaining
- image_pointer = int(pdskey(s, '^IMAGE'))
- # "^IMAGE" locates a record. Records are numbered starting from 1.
- image_index = image_pointer - 1
- image_offset = image_index * record_bytes
- gap = image_offset - consumed
- assert gap >= 0
- if gap:
- inp.read(gap)
- # This assumes there is only one OBJECT in the file, and it is the
- # IMAGE.
- height = int(pdskey(s, ' LINES'))
- width = int(pdskey(s, ' LINE_SAMPLES'))
- sample_type = pdskey(s, ' SAMPLE_TYPE')
- sample_bits = int(pdskey(s, ' SAMPLE_BITS'))
- # For Messenger MDIS, SAMPLE_BITS is reported as 16, but only values
- # from 0 ot 4095 are used.
- bitdepth = 12
- if sample_type == 'MSB_UNSIGNED_INTEGER':
- fmt = '>H'
- else:
- raise 'Unknown sample type: %s.' % sample_type
- sample_bytes = (1,2)[bitdepth > 8]
- row_bytes = sample_bytes * width
- fmt = fmt[:1] + str(width) + fmt[1:]
- def rowiter():
- for y in range(height):
- yield struct.unpack(fmt, inp.read(row_bytes))
- info = dict(greyscale=True, alpha=False, bitdepth=bitdepth,
- size=(width,height), gamma=1.0)
- return rowiter(), info
- def main(argv=None):
- import sys
- if argv is None:
- argv = sys.argv
- argv = argv[1:]
- arg = argv
- if len(arg) >= 1:
- f = open(arg[0], 'rb')
- else:
- f = sys.stdin
- pixels,info = img(f)
- w = png.Writer(**info)
- w.write(sys.stdout, pixels)
- if __name__ == '__main__':
- main()
|