degal/exif_data.py
branchnew-exif
changeset 103 63e89dc2d6f1
parent 102 ef2c1ffdca8f
child 104 6afe59e5ffae
equal deleted inserted replaced
102:ef2c1ffdca8f 103:63e89dc2d6f1
    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?) }