0

I have a hexdump string of a small PNG file that I want to convert to binary for writing out a PNG file:

clip = "0x89 0x50 0x4e 0x47 0xd 0xa 0x1a 0xa 0x0 0x0 0x0 0xd 0x49 0x48 0x44 0x52 0x0 0x0 0x0 0x8 0x0 0x0 0x0 0x7 0x8 0x2 0x0 0x0 0x0 0xba 0x3b 0x9b 0x9 0x0 0x0 0x0 0x3 0x73 0x42 0x49 0x54 0x8 0x8 0x8 0xdb 0xe1 0x4f 0xe0 0x0 0x0 0x0 0x29 0x49 0x44 0x41 0x54 0x8 0x5b 0x63 0xfc 0xff 0xff 0x3f 0x3 0x36 0xc0 0x84 0x4d 0x10 0x24 0x46 0x2b 0x89 0xf7 0x1f 0xfe 0xfd 0xfc 0x9 0x75 0xb 0x8a 0x1d 0x39 0x95 0x9f 0xef 0x3e 0xfc 0xb 0x71 0xe 0x0 0xfc 0x18 0xd 0x6c 0xa9 0xf7 0x56 0x2d 0x0 0x0 0x0 0x0 0x49 0x45 0x4e 0x44 0xae 0x42 0x60 0x82 "

I have tried using clip.encode("hex") but get the error

'hex' is not a text encoding

Using binascii.unhexlify(clip), I get

Odd-length string

And if I remove whitespace, the error is

Non-hexadecimal digit found

None of the other discussions on SO or the wider internet are helping.

Theo d'Or
  • 783
  • 1
  • 4
  • 17
  • Have you tried the solutions here: https://stackoverflow.com/questions/1425493/convert-hex-to-binary – DirtyBit Jan 25 '19 at 09:06
  • @user5173426 I have seen it but apart from using `binascii.unhexlify()` couldn't make much sense of it, didn't seem to apply to my case. – Theo d'Or Jan 25 '19 at 09:44

1 Answers1

1

You can use python's builtin eval function to evaluate each element in your string to an integer. Then in python2.7 can use the builtin chr to convert the integer to a byte: In python3 you can use builtin bytes conversion

>>> clip = clip[:-1] # Remove last space in your clip-string
>>> hex_list = clip.split(' ') # Convert your string to list of hex-characters
# FOR PYTHON3:
>>> byte_string = bytes([eval(h) for h in hex_list])
# FOR PYTHON2.7:
>>> byte_list = [chr(eval(h)) for h in hex_list]
>>> byte_string = ''.join(byte_list) # Convert to string
>>> byte_string
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x08\x00\x00\x00\x07\x08\x02\x00\x00\x00\xba;\x9b\t\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00)IDAT\x08[c\xfc\xff\xff?\x036\xc0\x84M\x10$F+\x89\xf7\x1f\xfe\xfd\xfc\tu\x0b\x8a\x1d9\x95\x9f\xef>\xfc\x0bq\x0e\x00\xfc\x18\rl\xa9\xf7V-\x00\x00\x00\x00IEND\xaeB`\x82'
jusx
  • 1,099
  • 9
  • 14
  • Thank you, that almost works! If I copy and paste the `byte_string` value produced by your code and prepend with "b" like so: `b'\x89PNG...'`, then writing out the value works, I get a valid PNG file. But I haven't been able to make a variable conversion. Tried `bytes(byte_string)`, tried encoding as hex, nothing works. I must be missing something obvious... How do I get the `byte_string` variable into the proper bytes format? – Theo d'Or Jan 25 '19 at 09:47
  • I don't exactly understand what you mean by variable conversion? In python2.7 (which I've used) a string is actually a byte string. In python3 you should use bytes([eval(h) for h in hex_list]) instead – jusx Jan 25 '19 at 10:15
  • In Python3, if I encode I get `b"\xc2\x89PNG\r\n\x1a\n\x00..."` What's the `\xc2` bit? I then notice similar additions toward the end and probably throughout the value. Hang on, just noticed your edit... `bytes([eval(h) for h in hex_list])` doesn't work either. – Theo d'Or Jan 25 '19 at 10:17
  • I don't get a valid PNG file. We have a conflict in Py 2.7 and 3 methods... I have edited the title to make Python 3 requirement clear. – Theo d'Or Jan 25 '19 at 10:30
  • byte_string = bytes([eval(h) for h in hex_list]) does not give you the same byte_string as in my answer? For me it does in python3 – jusx Jan 25 '19 at 10:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187314/discussion-between-justen-ingels-and-theo-dor). – jusx Jan 25 '19 at 10:39
  • All good, I was setting the byte_list instead of byte_string. Answer accepted - thank you again! – Theo d'Or Jan 25 '19 at 10:40