#!/usr/bin/env python """ Python implementation of ASCII85/ASCIIHex decoder (Adobe version). This code is in the public domain. """ import re import struct # ascii85decode(data) def ascii85decode(data): """ In ASCII85 encoding, every four bytes are encoded with five ASCII letters, using 85 different types of characters (as 256**4 < 85**5). When the length of the original bytes is not a multiple of 4, a special rule is used for round up. The Adobe's ASCII85 implementation is slightly different from its original in handling the last characters. The sample string is taken from: http://en.wikipedia.org/w/index.php?title=Ascii85 >>> ascii85decode(b'9jqo^BlbD-BleB1DJ+*+F(f,q') b'Man is distinguished' >>> ascii85decode(b'E,9)oF*2M7/c~>') b'pleasure.' """ n = b = 0 out = b'' for c in data: if 33 <= c and c <= 117: # b'!' <= c and c <= b'u' n += 1 b = b*85+(c-33) if n == 5: out += struct.pack('>L', b) n = b = 0 elif c == 122: # b'z' assert n == 0 out += b'\0\0\0\0' elif c == 126: # b'~' if n: for _ in range(5-n): b = b*85+84 out += struct.pack('>L', b)[:n-1] break return out # asciihexdecode(data) hex_re = re.compile(r'([a-f\d]{2})', re.IGNORECASE) trail_re = re.compile(r'^(?:[a-f\d]{2}|\s)*([a-f\d])[\s>]*$', re.IGNORECASE) def asciihexdecode(data): """ ASCIIHexDecode filter: PDFReference v1.4 section 3.3.1 For each pair of ASCII hexadecimal digits (0-9 and A-F or a-f), the ASCIIHexDecode filter produces one byte of binary data. All white-space characters are ignored. A right angle bracket character (>) indicates EOD. Any other characters will cause an error. If the filter encounters the EOD marker after reading an odd number of hexadecimal digits, it will behave as if a 0 followed the last digit. >>> asciihexdecode(b'61 62 2e6364 65') b'ab.cde' >>> asciihexdecode(b'61 62 2e6364 657>') b'ab.cdep' >>> asciihexdecode(b'7>') b'p' """ data = data.decode('latin1') out = [ int(hx,16) for hx in hex_re.findall(data) ] m = trail_re.search(data) if m: out.append(int(m.group(1),16) << 4) return bytes(out) if __name__ == '__main__': import doctest print('pdfminer.ascii85', doctest.testmod())