Search code examples
pythonstringcharacter-encodingmetadatapiexif

How to decode `piexif` metadata strings containing both plain text and bytes characters?


I have a string containing both human-readable parts and bytes/control characters (I guess), like the following:

weird_string = 'Nikon\x00\x02\x00\x00\x00II*\x00\x08\x00\x00\x00\x15\x00\x01\x00\x07\x00\x04\x00\x00\x00\x00\x02\x00\x00\x02\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x02\x00\x06\x00\x00\x00\n\x01\x00\x00\x04\x00\x02\x00\x07\x00\x00\x00\x10\x01\x00\x00\x05\x00\x02\x00\r\x00\x00\x00\x18\x01\x00\x00\x06\x00\x02\x00\x07\x00\x00\x00&\x01\x00\x00\x07\x00\x02\x00\x07\x00\x00\x00.\x01\x00\x00\x08\x00\x02\x00\x08\x00\x00\x006\x01\x00\x00\n\x00\x05\x00\x01\x00\x00\x00>\x01\x00\x00\x0f\x00\x02\x00\x07\x00\x00\x00F\x01\x00\x00\x00\x02\x00\x0e\x00\x00\x00N\x01\x00\x00\x00\x02\x00\r\x00\x00\x00\\\x01\x00\x00\x00\x05\x00\x01\x00\x00\x00j\x01\x00\x00\x00\x05\x00\x01\x00\x00\x00r\x01\x00\x00\x00\x07\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00z\x01\x00\x00\x00\x08\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x01\x00\x00\x10\x00\x07\x00\x00\x00\x00\x01\x00\x00\x11\x00\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00COLOR\x00FINE  \x00\x00AUTO        \x00\x00AUTO  \x00\x00AF-S  \x00\x00       \x00"\x00\x00\x03\x00\x00AUTO  \x00\x00AUTO         \x00OFF         \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00d\x00\x00\x00               \x00OFF \x00\x00\x05\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00a\x05\x00\x00\x00\x03r\x00`\x14\x00\x01!\x00\x00\x06{\x00\x00\x00\x00\x00\x00\x1f\x05\x0b\x00\x1b\x07\x06&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07*]\x00\x00\x06\x07\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x007\x06\x00\x00J\x02\x15\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02C\x16\x00\x00\x00\x00\x04\x07\x00\x1a\x00\x00\x00\x00\x19a\x121uv\x1b\x17\x12\x18\x14\x15\x15\x17\x00\x00\x00\x00\x0c\x00\r\x01\x02 R\x00\x03\x03z\x00\x00\x00\x0fch\x0cU\x0ed\x00d\x00\x0e\x12\x06\x06\x01\x02L\x00\x02\x00\x00@\x00M\x00\x00\x00\x11\x00\x00\x00\x00\x11\x11\x11\x11\x00\x00\x00c\x00\x00\x03\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x0b\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00eC!\x07\x00\x03\x01\x03\x00\x01\x00\x00\x00\x06\x00\x00\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x02\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00\x02\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x02\x04\x00\x01\x00\x00\x00\x134\x00\x00\x02\x02\x04\x00\x01\x00\x00\x00%\x00\x00\x13\x02\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00,\x01\x00\x00\x01\x00\x00\x00,\x01\x00\x00\x01\x00\x00\x00'

I would like to "decode" it by:

  • keeping only human readable characters
  • substituting spaces/tabs/newlines/... with appropriate control characters
  • strip non-printable characters

I don't know exactly what the desired output should be. The closest I could get is based on this discussion:

''.join(c for c in weird_string if c.isprintable())

>>> 'NikonII*&.6>FN\\jrzCOLORFINE  AUTO        AUTO  AF-S         "AUTO  AUTO         OFF         dd               OFF ar`!{&*]7JCa1uv RzchUddL@MceC!(4%,,'

As you can see this one-liner does most part of the job done, however there are still some weird parts. Is this the "correct" human representation of weird_string?

Apologies in advance for not being specific enough and possible misused terms. I am not familiar with string manipulation, which makes it difficult explaining clearly the problem and the desired output. I'm happy to include more details if asked.

EDIT:

I add a bit more context:

The weird_string comes from exif metadata of a .jpeg image. My ultimate goal is to dump all available metadata in a human-readable txt.

Specifically, I get the metadata using the piexif library:


with Image.open(image_path) as pil:
    metadata = piexif.load(pil.info['exif'])

This gives me a metadata dictionary as the following:

>>> metadata
{'0th': {270: '          ', 271: 'NIKON', 272: 'E4500', 274: 1, 282: (300, 1), 283: (300, 1), 296: 2, 305: 'E4500v1.3', 306: '0000:00:00 00:00:00', 531: 2, 34665: 284}, 'Exif': {33434: (10, 80), 33437: (31, 10), 34850: 4, 34855: 100, 36864: '0220', 36867: '0000:00:00 00:00:00', 36868: '0000:00:00 00:00:00', 37121: '\x01\x02\x03\x00', 37122: (3, 1), 37380: (0, 10), 37381: (28, 10), 37383: 5, 37384: 0, 37385: 16, 37386: (126, 10), 37500: 'Nikon\x00\x02\x00\x00\x00II*\x00\x08\x00\x00\x00\x15\x00\x01\x00\x07\x00\x04\x00\x00\x00\x00\x02\x00\x00\x02\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x02\x00\x06\x00\x00\x00\n\x01\x00\x00\x04\x00\x02\x00\x07\x00\x00\x00\x10\x01\x00\x00\x05\x00\x02\x00\r\x00\x00\x00\x18\x01\x00\x00\x06\x00\x02\x00\x07\x00\x00\x00&\x01\x00\x00\x07\x00\x02\x00\x07\x00\x00\x00.\x01\x00\x00\x08\x00\x02\x00\x08\x00\x00\x006\x01\x00\x00\n\x00\x05\x00\x01\x00\x00\x00>\x01\x00\x00\x0f\x00\x02\x00\x07\x00\x00\x00F\x01\x00\x00\x00\x02\x00\x0e\x00\x00\x00N\x01\x00\x00\x00\x02\x00\r\x00\x00\x00\\\x01\x00\x00\x00\x05\x00\x01\x00\x00\x00j\x01\x00\x00\x00\x05\x00\x01\x00\x00\x00r\x01\x00\x00\x00\x07\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00z\x01\x00\x00\x00\x08\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x01\x00\x00\x10\x00\x07\x00\x00\x00\x00\x01\x00\x00\x11\x00\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00COLOR\x00FINE  \x00\x00AUTO        \x00\x00AUTO  \x00\x00AF-S  \x00\x00       \x00"\x00\x00\x03\x00\x00AUTO  \x00\x00AUTO         \x00OFF         \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00d\x00\x00\x00               \x00OFF \x00\x00\x05\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00a\x05\x00\x00\x00\x03r\x00`\x14\x00\x01!\x00\x00\x06{\x00\x00\x00\x00\x00\x00\x1f\x05\x0b\x00\x1b\x07\x06&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07*]\x00\x00\x06\x07\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x007\x06\x00\x00J\x02\x15\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02C\x16\x00\x00\x00\x00\x04\x07\x00\x1a\x00\x00\x00\x00\x19a\x121uv\x1b\x17\x12\x18\x14\x15\x15\x17\x00\x00\x00\x00\x0c\x00\r\x01\x02 R\x00\x03\x03z\x00\x00\x00\x0fch\x0cU\x0ed\x00d\x00\x0e\x12\x06\x06\x01\x02L\x00\x02\x00\x00@\x00M\x00\x00\x00\x11\x00\x00\x00\x00\x11\x11\x11\x11\x00\x00\x00c\x00\x00\x03\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x0b\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00eC!\x07\x00\x03\x01\x03\x00\x01\x00\x00\x00\x06\x00\x00\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x02\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00\x02\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x02\x04\x00\x01\x00\x00\x00\x134\x00\x00\x02\x02\x04\x00\x01\x00\x00\x00%\x00\x00\x13\x02\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00,\x01\x00\x00\x01\x00\x00\x00,\x01\x00\x00\x01\x00\x00\x00', 37510: '\x00\x00\x00\x00\x00\x00\x00\x00                                                                                                                     ', 40960: '0100', 40961: 1, 40962: 2272, 40963: 1704, 40965: 1026, 41728: '\x03', 41729: '\x01', 41985: 0, 41986: 0, 41987: 0, 41988: (0, 100), 41989: 60, 41990: 0, 41991: 0, 41992: 0, 41993: 0, 41994: 0, 41996: 0}, 'GPS': {}, 'Interop': {1: 'R98'}, '1st': {259: 6, 282: (300, 1), 283: (300, 1), 296: 2, 513: 4084, 514: 3682}, 'thumbnail': b'\xff\xd8\xff\xdb\x00\xc5\x00\x07\x05\x06\x06\x06\x05\x07\x06\x06\x06\x08\x08\x07\t\x0b\x12\x0c\x0b\n\n\x0b\x17\x10\x11\r\x12\x1b\x17\x1c\x1c\x1a\x17\x1a\x19\x1d!*$\x1d\x1f( \x19\x1a%2%(,-/0/\x1d#484.7*./.\x01\x08\x08\x08\x0b\n\x0b\x16\x0c\x0c\x16.\x1e\x1a\x1e..................................................\x02\x08\x08\x08\x0b\n\x0b\x16\x0c\x0c\x16.\x1e\x1a\x1e..................................................\xff\xc4\x01\xa2\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01}\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\x07"q\x142\x81\x91\xa1\x08#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19\x1a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02w\x00\x01\x02\x03\x11\x04\x05!1\x06\x12AQ\x07aq\x13"2\x81\x08\x14B\x91\xa1\xb1\xc1\t#3R\xf0\x15br\xd1\n\x16$4\xe1%\xf1\x17\x18\x19\x1a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xc0\x00\x11\x08\x00x\x00\xa0\x03\x01!\x00\x02\x11\x01\x03\x11\x01\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf9\xb8\x03\x8e\r;\x91\xd2\xb3gDSB\xf2\xd5*c\x18\xc6O\xaeje\xa2:h\xfb\xd2\xbb\x15\xa4.6\x0e\x175\'\x9f\'\xd9\xc4[\xbe\\\xf7\xac\x9c.\xb5\xefs\xd0\x865\xd3\xa8\xe5\x0f\xe5q\xf9\x11.9\x1c\xf3S+\xba\xae\t\xe2\x9c\xf5D\xe1%\xc9%(\xff\x00Z\x92\x02\x18\x029\x03\xb8?\xd2\x9e\xecX\xe1A\xcfN\xb5\x8b\xbd\xd1\xec\xc2Q\x8c%%\xd6\xdf\x93$\xb6\x91!\x95\x1b`v\x1e\xf5\xa3y|\x97V\xe9\x1a+,\x91\x9c\x82y\xaeJ\xd0\x94\xa6\xa5\xd0\xf50U#\n2\xa6\xb7\xfdlcN\xe7\xa0$\x9fZ\xae\xc1\xb0\t8\xae\xfaj\xc8\xf9\x8c\xc2\xa3\x9dF\x84\xdc;PX\xf5\'5\xa5\x8e.{l\x1b\xb3\xc1\xe9M\xe3<f\x9a\xd0\x99\xcb\x9b\xa9eK\x18\xf6\x9eW\xd2\xa0\x990\x85\x80>\xf5\x9ct\x91\xd9\x88\x8f=\x14\xdfE\xff\x00\x07\xfc\xca\xf5 \xc7\x97\xc1\xc75\xbb<zoP\\\x03\x92i\xc7\x1c\x9d\xd5,\xde\x9a\xf7w\x00FG8\x1fJ\xd4[\x15\x93O\x17\x10\xb0\xdf\x82J\x93\xdb\xbdc^\xa7\xb3I\xbe\xac\xf4r\xec*\xc5JQ[\xa4\xda("\x00\xe0\xb3\x0f\xf8\r$\xd2\x19\x0f<\x01\xc0\xaa\xbf4\x8c\xf9=\x95)_\xe2n\xc3\xa2\xc8\\\xa8<r\xd5e\xbfv\x81\xbf\x88\xf6\xc7J\xce\xa6\xe7~\x05\xfe\xed\xb7\xb4U\xc6E\xb4\xb6O\x15<\x04.\xe6\xcf\x15\x9c\xfa\x9d\xf8K{\xad=/\xfa\x14\xa5;\x9d\xba\xe74\x83\x95\xe4f\xb7\x8e\x91G\x8dZ\\\xf5\xa4\xba;\x89\x81\xce\x05!\x1d\r]\xceWO\xb1\x1bcu*\x8ey5]\x0e\x7f\xb4O\x18\x00|\xcf\xd7\xb5,\x8c\xa2\x07\x199==\xf8\xac%\xbe\x87\xb1\x87\xb2\x8as}\xff\x00&S\xc1\xcf\x14u\xe2\xbaO\x9fJ\xc0\xa0\xf4\xa5 \x8aE$\xf9G\x85,\x06\xd1\xd3\xadn\xdb<6v@HI\x91\x91\x8f\x1d\xb28\xaeL^\xb0\xe5\xea\xcf\xa1\xc8#\xcb\x88u\x1e\x89G\xfc\x91KKX\xa5\xbbH\x9d?vrI$\xfa\x1fJ\x9a\xe5t\xd9ZFY\x9a)\x03p\x19\x0e\x1b\xdf\x8a\x89\xceq\xab\xa2\xbe\x87V\x1e\x86\x1e\xb6\t\xf3;{\xd6M\xf9+\x91\xa0\x11\xc7..#p\xc0\x05\x03\x8d\xdc\xfd=\xaa0\x03"\x93\x92s\x83MJ\xee\xe8\xb5I\xc6*\x13\xb6\xcd\xe9\xe4\xee\xbf\x0b\x88\xcb\xb7\xae>\x94\xe8NCc\xa9\x15M\xdd\\\x9aP\xe4\xa8\xa2\xc6<L0\xcc1\x91\x90j\x06Vl\xee8\xc75pi\x9c\x18\x9aR\x8b\xdbW\xfd~#\x01\xc0\xc0\x1f\xfdzF\'8\x15\xaaZ\x9et\xa4\xd4l\x86?\x06\x9595}\x0eo\xb7bpq\xc6\xd1\xc52Ts\x19b\xa7\x1e\xb5\x92\xdc\xf4g\xac\x1f*+\x80O\x15&\xdd\xa7\xaf5\xabv<\xb8E\xc9_\xb0\x00\xc0\xf0rjDf\xc7\xcc\xa1\xbd\xcdL\xb5GM\x06\xe3+I]\x0fH\xdagU_\x97\x9f\xc0{\xd1q6ID\xe5s\xd4\xfe\x95\x9bW\x92G|d\xe9P\x95G\xa5\xf4K\xef\xb9%\xa4\x8e#\x9ff\x01\xd9\x8f\xcc\x8a`\x8c\xa2\x96fP\xde\x84g\x14\x9d\xa3&\xfa\xbb"\xa9\xf3U\xa3\x08-\x12\xe6\x7f\xd7\xdc\x08\x1f\xa9\xe4\x9e\xe7\xbd[\xb6\x8fyh\xc9\xc6\xee\x06}j*;&\xce\xcc\x04eRQR\xeb\xa7\xde6E\xc68\xe0\xfe\x7f\x8dI\x12\x95\x8aFT\xce\x07$\xf6\xac\xdb\xbct=\x08\xd3J\xbf3\xd6\xca\xff\x00\x81^w\x93\x08\x01#\x19?Oj\x82B\n\xaeF\xd3\xdcz\xd6\xd0\x8aJ\xe8\xf21\x95e)\xca2\xf2\xb7\xdc\xbfO\xc8`8\x18\xc5\x0cpA\xc7\xe3Z\x9e[k\x94i\x19\xf7\x14\xaa\xc5xP?\x1aoUb"\xd4e\xcc\xd1z\xc3l\xb3\x85\x91q\x90H#\xd6\xac\xde\\\xaa\xdbI\x19q\x92\xa5p\x17\x19\xe2\xb8+\xa99\xf2\xa3\xeb\xf2\xba\x94V\x1eUf\x92\xd5\xfeI\xfeF\x1e\x08\x18\xc1\xa9\n8\x1ev\xd3\xb7w^\xd9\xafA\xb5{\x9f\x17\x05\'\x17\x14\xbc\xfe\xeb\x8d\xe0\xf2?#K\x8c\xf2()7\xd0\x96\'\x08x\xeb\xdc\xd4j\t`\xb9\xc78\xcdJZ\xb6tT\xa9zQ\x87f\xff\x00\x1b\x7f\x9123FN\xdc\xe4\xf4\xc51\x9d\x8bd\xf5\xf7\xa9Q\xbb\xb9\xd1:\xf2\x855K\xb7\xf5\xfed\xd0\xfc\xc7\xe6\xfc\xebsM\xb43B\xea1\xe6\x8f\x9a2z1\xf4\xae\\L\xb9Q\xee\xe4\xd0u\x1d\xda\xfe\xba\x16\xb5(\xa0u\x8d\x90)\xb8s\xcag\x1b\x07|\xfe=\xeb0O\xb2\x16O\x97\x0c1\xc0\xc5rSr\x94-s\xdd\x9a\x85:\x9c\xd6\xe8B\xe1Z%g\xc0\xeb\xc9\xaa\x13*\xef$\x13\x8e\xd9\xae\xea2\xd6\xc7\xce\xe6t\xa2\xe9\xa9\xad\x1b\xb1\x1e\xd2A\xa4\xdb\xc7Q\xf9\xd7M\xcf\x9e\xf6r\xb0,lN\x17\x19\xf4\xcd.\xc6S\xf3!\x06\x8ed%JV\xbbZ\x16"\x93\xcab\xe1\xb0\xd8 ~T\xddA\xcc\x8b\x1b\x92\x0bl\xc3}\x7f\xfdX\xac-\xfb\xc5/\xeb\xa9\xeb\xcai\xe0\xa7O\xb6\xbf\x8cW\xe5r\x96A$\xf2*X\xa4d\xc8\x00:\x1e\xaa{\xd7D\xa3ufx\x94k8M\xce;v\xee\x9e\xeb\xee-=\x98\x99D\xb6\xc1Jc\xe6\xf9\xb9_\xadUr\xaa\xa1\n\x9e\x0f\xde\x15\x9c*s\xabuGn+\t\x1c<\xdc\xd7\xc1%\xa3\xf9\x7fHz\xa4L\x01\x12\xed#\xae\xe1JQb\xce\xec3v\xe6\x9b\x9fN\xa4\xc3\n\x92U\x1b\xbc\x7f\x1f\xebr=\xed\x90s\x8f\xa7\x14\xed\xf2\x7fx\xfeu\\\xa8\xc9W\x93\xbd\x8bVL\x03\x1c\xaa\x16\xecH\xc8\xad;i\xda\xd6u\x98\r\xed\x9e\x9f\xd6\xb8q\x11\xbb\xb1\xf5\x99D\x92\xa0\xa5\xdb\x7f\xc4\xb7\x7fp\xb7\xac\x18G\xe5N\x13\xee\x9ew\xa8\xcf\x7fZ\xcb\x92\x19"\x80Jc>^J\x86#\xa9\xac(\xfb\xab\x95\xeez8\xa4\xa5\xefn\x92\x7f\xd7\xdcT\x0cX|\xdd\x052@r\x08\xe9]\xf1I3\xe6\xb1\x12\x95Jw\xea@\xd9Q\xd3\xad4\xa9\x00b\xb6G\x8bQ\xbd\x97A\xc1NA\x06\xac\x99H\x08\x08\'\xdc\xd4TW\xb5\x8e\xdc\x15_f\xa5\xcd\xaa\xff\x00\x82F\xc4n\xdd\x8c\x81\xebPL\xc4\xe7\x07\x8cS\x8a2\xc4\xd4\xd2\\\xbd_\xe0C\xc6i\xd9\xe3\x15\xb3<\xa8\xe8\xc7E#\xc4\xe1\xd1\x88"\xad<\x96\xf2\x8eU\xa3\xe3?(\xcf?\x8dc85.h\x9e\xa6\x17\x11\t\xd1t+=\x16\xdeW\xdf\xfc\xc6l\xb7PI\x95\x98\xf6P\xbc\xd2\x96\x85\x94\x06,1\xd0\xe34\x9c\xa4\xf5H\xb8R\xa1\x04\xe3*\x9f\x17\xf4\x88\xca(\xfb\xae\x18}1M\x18\x1dsZ\'s\x92PPv\xbe\x86\x85\x94,\xc8\\\x0e2\x07\xf3\xff\x00\x03Vf\x95Xn\x0b\x83\x8c\x0c\x1a\xe1\xab\xadM\x0f\xaf\xcb\xa3\xec\xf0\x9a\xf5\xd4B\xf21\x0c_\xe6\x8c\x8c\x03\xd7\xebW/o\x12M,\xc6\xca7y\xc3f:`\x03\xfe5\xcf({\xd1\xb7F\xbf3\xb9\xd4n\x95G.\xa9\xfe\t\xa7\xf9\x18\x84\xf1\xd7\xad\x0c\xd8LW\xa1c\xe69\xdd\x9f\xa7\xfc\x126\xc1\xc1\xa7\x02\xb8\xc6;Ut9R\x8f3o\xa8\xc1\x958\xc5+6\xd5\xcfq\xd2\x9b\xd5\x91\x07\xcb\x17\xe4F\xccH\xf9\x98\x93Q7O\xc2\xb4\x8a\xb1\xc5^\xa3\x9b\xbb\x10\x8e\x01\xf5\xa5\x15G2Z\xa0\xc6)rzR-h\xc5\x1c\x9e\xb4\xb8\xe4\x8c\xd2\xd8\xd1\'-Az\xf3N\xdb\x83\xd7\x8fZ]M\x12\xbcM\x18w\xad\xba\x84\x03q\'\'\xda\x86f_\xbd\xdcb\xb8\x9cW3\xf3>\xbe\x95G\x1a0V\xd1%\xf8\x8f\x87k\xb1\xec6\xf1\xfdi/\x19~\xcd\x14H\xd9\xdaX\x9e;\xf01\xfaP\xbe4\x8a\x9b\xbe\x1esO\xa3\xfclg\xe4\x8c\xf2)7d\xe3\xd6\xba\xac|\xc3\xa9ef\x04\xf6\xe2\x85\xe7\xad>\x84\xb7yXS\xc7O\xc2\x99\'^\xbcP\xb7\x14\xfe\x17a\x87\x90Nj3\xd2\xb5G\x9f;\x8b\xd8R\x8a,.k\xbb\xff\x00[\x05;\x07\x19\xe9H\xb5\xa8/\x19\xf5\xa3\xa8\x07\xa5\x03\x8e\xd6\x1d\x8e}\xaa`W\x01v\xe7\x1f\xadD\xaf\xd0\xec\xa1\xcbw\xcd\xb1~\'P\x81\x9d\xb2\x7f\xba*\xbc\xb2\x17l\x0e\x95\xc7\x18\xfb\xf7>\x9e\xbd~\\2\x8fV[\xd3\xd8\x12Up\x1c\x8e2~\xb9\xa3S\xb6d?\xbb\xc9U\xc7 pI\x15\nV\xadfm8)\xe5\xf7\x86\xeb\xf43\n\x9c\x1cs\xeaE0\x8fC]\xc9\x9f\'R-=@\x9anMU\x8c\x9c\xac\xf4\r\xc7\xa54\x9e1M#9M\xbb\x8d4\xd3\xd2\xa8\xe6a\x9a^)\x82c\xfa\x01\xefJ>`I5\x0c\xde=\x84\xfci\xf8R3\xcf\xe1C\x1c"\x9e\x8c\x06:\x02}\xaa\xf0\x81\xe1\xf2\xcc\x91\xb7\xef\x13p\x1e\xd9\xc7\xf4\xac\xaaJ\xc7\xa1\x83\xa2\xaaK]\x96\xff\x00z_\xa8\xc9$"C\x8e\x9d\xb1\xe9P\xee\x00\xf0ja\x1d\x0e\xccUd\xe6\xd2\xe8\xd8\xe4\x90\x06\x07\x15dL\xe7\x19vt\xe9\xeaqY\xce\x9arM\x9d\x18ld\xa3I\xc6/\xd5}\xdf\xe5\xf8\x91KnVW\x88\x90\xb2)\xe8x\x06\xa0t\x92#\x89\x10\xaf\xd4V\xb4\xe6\xa4pb\xf0\xd2\xa4\xef\xbaW\xf9\x111\xcd6\xb6G\x979]\x81\xa0\xfb\xd3!\xa1\xa4\x8ai\xe9M\x19HJx\x1d\xcfJl\x88+\x8b\x9c\x8a;T\x9b\xde\xfa\x8b\x8c\xf3K@\xd1$Q\xef\'\xe6\n\xa0d\xb1\xedV\xa1\x90m\x06L\xb6\x0f\xe9XUI\xfc\x8fc,\x94\xa1-v\x95\xd7\xdd\xa9Y\x8e*%`[\x93ZEhpV\x9f\xbc\x90\x8d&\x0f\x15f\xcac\xe6\xa8\xf7\xa5R\x17\x8b4\xc1b\xb9q1^e\xeb\xfb\x85\xbdu@\x80L\x99]\xe3\x8f3\xd35\x07\x9b\xe6\xdb\xb5\xbc\xa9\xfb\xd4_\x91\xbb\xf1\xd8\xfe\x1f\xc8W-8\xb5\x08\xf7Z\xfc\x8fo\x15R2\xc4T\xe5W\x8c\xef\x1f\xfbym\xf8\xfee\x03GA]\xa7\xcc\xf5\x1d\xc6\xc0I8&\xa3&\x9a\xdcS~\xea\x1bHj\x8ev \xa7f\x86(\xec(\xf5\xa7\x13\x9a\x96m\x1d\x80S\x95K0\x00d\x9e1AkRS\xc9\xf2\xe3\x19\x19\xea?\x8a\x96F\n6\x82=\xf1Yoo3\xd1\x8bt\xf9\x9f\xf2\xe9\xf3\xfe\xaeW/\x9e\xf5\x1f\xbdl\x91\xe5U\x9f3\xb8\x84w\x15=\x98\xcc\x99\xee\x07\x14M\xfb\xac0\x91\xe6\xc4Awh\x92l\x89\x0f\xa8\xa5I\x01?9\xe7\xfb\xde\x95\x8f-\xd5\xd1\xea\xaa\xdc\x95\\$\xf4\xbe\xbe\xbd\xc6J\xa1\\\x8e8\xf4\xa8\xc9\xc9\xab\x8b\xba\xb9\xc5^<\x93q\xf3\x06\'\xa7\xa50\xd5#\n\x9b\xd8\r5\xb8\xc8\xaaF,Jp\x19\xa6\xc9Z\x8e\xc8\xed\xd3\xde\x94\x1a\x8b\x1b\xa9!\xc0\xfd?*\xb1l\xb2J\xdbU\x80\xe3<\xd4N\xc96\xce\xcc/4\xaaF\x11Z\xb6Mp\x12\xd4\x10\x8c\x0b0\xc7\xd3\xd6\xb3\x1d\x89=jh\xfb\xde\xf1\xbek\xfb\x8bP[\xad_\xab\xff\x00\x81a\xb9\xa2\xba,xw\x14T\xb1\xb6\x0f\x1djd\x8d\xe8\xcb\x96J]\x89\xe6\x0c\xc7\xcc \xf3\xd4\xfb\xd4\\g\xadg\x1d\x15\x8fC\x11\xefUr}u\xfb\xc5\xde\x08\n\xdd\x07\xe9L\xdb\x9e\x9c\x8fj\xa5\xa1\x85G\xcf\xaa\xdck\x1c\x92i\xb5QZ\x18U\x95\xe4\xd8g\x1f\x854\xd3F-\xe88\x15\x1e\xff\x00Z7v\x1c\nM6T\\b\xb4\xdc\x05-0D\x88\xa5\x8e\x05\\\x8eh\xad\x83\x15\xf9\x99O\x04\x8e\xf5\x85k\xb5\xca\x8fc,\xe4\xa7?mSh\xff\x00\x93\xff\x00#>Y^V,\xc7$\xd3+hC\x96)\x1eN\'\x11,EYT\x97V%\x15g0S\x94\xe0\x8aL\xa8\xbdK\xca\xc5\xe2*\x0fj\xafX\xc1Z\xe8\xf5\xf12sP\x9f\x95\xbf_\xd4i\xa0\x1e\xb5v8\x94\xac\xee\x84\'\xda\x93\x00\xf1\x9c\x1fzd=Cc\x00IS\x8f\xa50\xe6\xa93)&\xb7\x12\x96\x99(ZQRh\x89\xd7\xf7}z\xd5wb\xccI\xa9\x8a\xbc\xaetV\x9b\x85%\x0e\xff\x00\xd7\xea\x00w4\x8c1Ws\x92\xda\\J)\x90\x14P\x05\xbbi\x00 \x13\x81\xde\x98\xe0\x06\xe38\xec+\x1d\xa4z\xbc\xcaxx\xf9?\xf2\x19A8\x15g*\x1aM&i\xa4d\xd8d\xf2sHY\x8f$\x93\x9fZ\x14P\xa5VOs\xff\xd9'}

and finally, weird_string is one of the weird entries of the metadata dicionary, precisely the MakerNote attribute of exif metadata:

weird_string = metadata['Exif'][37500]

Hope this clarifies better the question.


Solution

  • If you 'decode' TIFF/EXIF data by dropping all non-human readable characters, you're dropping most of the useful information from it. Are you sure this is what you want ?

    That being said, parsing/decoding TIFF/EXIF is a nightmare. You'll need to do some specification reading to figure out how to decode it properly, if you want to do it by hand. Or you could try and see if the pyexiv2 package might be able to help you, since the underlying Exiv2 library does seem to auto-detect these tags, and even has a handy list of the tags used in this Maker Note.

    EDIT

    As OP has stated they are looking to transfer metadata from a JPEG/TIF image to a PNG image, I'm adding a code snippet to demo this unsing PIL below:

    import requests
    from PIL import Image
    
    # get a standard JPEG image from an awesome GitHub repo with exif sample images
    resp = requests.get(
        'https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/Nikon_D70.jpg')
    # write it t a file
    with open('test.jpg', 'wb') as fp:
        fp.write(resp.content)
    
    # read it in as a PIL image
    jpg = Image.open('test.jpg')
    jpg_exif = jpg.getexif()
    
    # save the image as a PNG
    jpg.save('test.png', 'PNG', exif=jpg_exif)
    
    # read the new PNG
    png = Image.open('test.png')
    png_exif = png.getexif()
    
    # are they really the same ?
    if jpg_exif == png_exif:
        print('Yay')
    else:
        print('Nay')
    
    

    Note : as the EXIF metadata tag is a 'recent' addition to the PNG standard, not every image viewer will support it (many will just ignore it). It might be better to transcribe the tags to standard PNG data tags, using PngInfo in PIL.PngImagePlugin, as suggested here.