0

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.

Luca Clissa
  • 810
  • 2
  • 7
  • 27
  • 2
    In what way is the output from the join() technique not as required? – DarkKnight May 10 '23 at 11:19
  • @DarkKnight the string represents the `MakerNote` attribute metadata of an image, read through `piexif` library. I don't know exactly what to expect as a value, but the last part of the join output seems weird to me: `*&.6>FN\\jrzCOLORFINE AUTO AUTO AF-S "AUTO AUTO OFF dd OFF ar`!{&*]7JCa1uv RzchUddL@MceC!(4%,,`. I would guess this is due to possible errors during decoding? – Luca Clissa May 10 '23 at 12:37

2 Answers2

2

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.

Hoodlum
  • 950
  • 2
  • 13
  • Thanks a lot! Indeed I am not sure what is the best way to handle metadata in my case. My goal is to transform a set of `.tif` and `.jpg` images into `.png` maintaining as much metadata as possible. I was thinking to "forward" the metadata both to the image file and to a text file (human-readable). `pyexiv2` is extremely helpful for the latter! Do you know if I can convert an image with that? or even just copy metadata to the converted image? I am trying with `pyexiv2.Image.modify_exif` but it seems nothing happens to the original file – Luca Clissa May 10 '23 at 14:27
  • 1
    Ah, that's a bit tricky. PNG started supporting EXIF in 2017, I think, so not all encoders/decoders support it (looking at you, windows 'properties'). So your exif tag might exist in your fresh PNG, however your image viewer might not see it.... I'll add a little code snippet to the answer to show this – Hoodlum May 10 '23 at 16:05
  • Oh I see, in fact I have this exact problem: for some images I can see metadata from ubuntu file navigator gui --> image properties, for others (converted from tif to png) I cannot. Thanks a lot for all your insights! :) – Luca Clissa May 23 '23 at 15:48
0

You can use str.maketrans to create a dictionary to replace the required whitespaces and then use string.translate.

And also you can try using string.printable (import string), then iterate over each character of your string and check if it is in string.printable -

decode_string = "".join(ch if ch in string.printable else '' for ch in weird_string)
decode_string = decode_string.translate(str.maketrans({}))

You have to create your own desired maketrans dictionary.

You can refer to string.printable and str.maketrans / translate

Pravash Panigrahi
  • 701
  • 2
  • 7
  • 21