41 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
41 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
42 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
42 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
43 |
43 |
44 """ |
44 """ |
45 |
45 |
46 def make_string (seq): |
46 import decimal, itertools |
|
47 |
|
48 def filter_ascii (values) : |
47 """ |
49 """ |
48 Filter a string to strip out non-printing chars |
50 Default post-filter for ASCII values. |
|
51 |
|
52 This takes a single item of string data, splits it up into strings by ASCII-NUL, and trims the induvidual strings |
49 """ |
53 """ |
50 |
54 |
51 # screen out non-printing characters |
55 return [string.rstrip() for string in values[0].split('\x00') if string] |
52 str = ''.join(c for c in seq if 32 <= c < 256) |
56 |
53 |
57 |
54 if not str: |
58 def build_ratio (num, denom) : |
55 # no printing chars |
|
56 return seq |
|
57 |
|
58 else : |
|
59 return str |
|
60 |
|
61 def make_string_uc (seq) : |
|
62 """ |
59 """ |
63 # Special version to deal with the code in the first 8 bytes of a user comment. |
60 Builds a Decimal ratio out of the given numerator and denominator |
64 # First 8 bytes gives coding system e.g. ASCII vs. JIS vs Unicode |
|
65 |
|
66 XXX: decode? |
|
67 """ |
61 """ |
68 |
62 |
69 code = seq[0:8] |
63 return decimal.Decimal(num) / decimal.Decimal(denom) |
70 seq = seq[8:] |
64 |
71 |
65 def filter_ratio (values) : |
72 ## Of course, this is only correct if ASCII, and the standard explicitly |
66 """ |
73 ## allows JIS and Unicode. |
67 Default post-filter for Ratio values. |
74 return make_string(seq) |
68 |
|
69 This takes the pairs of numerator/denominator values and builds Decimals out of them |
|
70 """ |
|
71 |
|
72 return [build_ratio(values[i], values[i + 1]) for i in xrange(0, len(values), 2)] |
|
73 |
75 |
74 |
76 # IFD Tag type information, indexed by code |
75 # IFD Tag type information, indexed by code |
77 # { type_code: (type_fmt, name) } |
76 # { type_code: (type_fmt, name, filter_func) } |
|
77 # |
|
78 # type_fmt's that are one char will be prefixed with the count for use with struct.unpack, those with more chars will |
|
79 # be repeated as many times for use with struct.unpack. |
78 FIELD_TYPES = { |
80 FIELD_TYPES = { |
79 # 0x0000: (None, 'Proprietary' ), # ??? no such type |
81 # 0x0000: (None, 'Proprietary' ), # ??? no such type |
80 0x0001: ('B', 'Byte' ), |
82 0x0001: ('B', 'Byte', None ), |
81 0x0002: ('s', 'ASCII' ), |
83 0x0002: ('s', 'ASCII', filter_ascii ), |
82 0x0003: ('H', 'Short' ), |
84 0x0003: ('H', 'Short', None ), |
83 0x0004: ('L', 'Long' ), |
85 0x0004: ('L', 'Long', None ), |
84 0x0005: ('LL', 'Ratio' ), |
86 0x0005: ('LL', 'Ratio', filter_ratio ), |
85 0x0006: ('b', 'Signed Byte' ), |
87 0x0006: ('b', 'Signed Byte', None ), |
86 0x0007: ('c', 'Undefined' ), |
88 0x0007: ('s', 'Undefined', None ), |
87 0x0008: ('h', 'Signed Short' ), |
89 0x0008: ('h', 'Signed Short', None ), |
88 0x0009: ('l', 'Signed Long' ), |
90 0x0009: ('l', 'Signed Long', None ), |
89 0x000A: ('ll', 'Signed Ratio' ), |
91 0x000A: ('ll', 'Signed Ratio', filter_ratio ), |
90 } |
92 } |
91 |
93 |
92 def map_value (spec, value) : |
94 def map_value (spec, value) : |
93 """ |
95 """ |
94 Map the given tag value to a printable string using the given value spec. |
96 Map the given tag value to a printable string using the given value spec. |
98 # call mapping function |
100 # call mapping function |
99 return spec(value) |
101 return spec(value) |
100 |
102 |
101 else: |
103 else: |
102 return spec.get(value, repr(value)) |
104 return spec.get(value, repr(value)) |
|
105 |
|
106 |
|
107 def make_string (seq): |
|
108 """ |
|
109 Filter a string to strip out non-printing chars |
|
110 """ |
|
111 |
|
112 # screen out non-printing characters |
|
113 str = ''.join(c for c in seq if 32 <= c < 256) |
|
114 |
|
115 if not str: |
|
116 # no printing chars |
|
117 return seq |
|
118 |
|
119 else : |
|
120 return str |
|
121 |
|
122 def make_string_uc (seq) : |
|
123 """ |
|
124 # Special version to deal with the code in the first 8 bytes of a user comment. |
|
125 # First 8 bytes gives coding system e.g. ASCII vs. JIS vs Unicode |
|
126 |
|
127 XXX: decode? |
|
128 """ |
|
129 |
|
130 code = seq[0:8] |
|
131 seq = seq[8:] |
|
132 |
|
133 ## Of course, this is only correct if ASCII, and the standard explicitly |
|
134 ## allows JIS and Unicode. |
|
135 return make_string(seq) |
|
136 |
103 |
137 |
104 # dictionary of main EXIF tag names |
138 # dictionary of main EXIF tag names |
105 # first element of tuple is tag name, optional second element is |
139 # first element of tuple is tag name, optional second element is |
106 # another dictionary giving names to values |
140 # another dictionary giving names to values |
107 # { tag_type : (name, spec?) } |
141 # { tag_type : (name, spec?) } |