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
|
#!/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()
|