def _readCode(self): toread = self.bitspercode value = 0 while toread > 0: if self.bytepos >= len(self.data): return -1 nextbits = pypdfOrd(self.data[self.bytepos]) bitsfromhere = 8 - self.bitpos if bitsfromhere > toread: bitsfromhere = toread value |= ((nextbits >> (8 - self.bitpos - bitsfromhere)) & (0xFF >> (8 - bitsfromhere))) << (toread - bitsfromhere) toread -= bitsfromhere self.bitpos += bitsfromhere if self.bitpos >= 8: self.bitpos = 0 self.bytepos = self.bytepos + 1 return value
def encode(data, decodeParms=None): """ Encodes chunks of 4-byte sequences of textual or bytes data according to the base-85 ASCII encoding algorithm. :param data: a str or byte sequence of values. :return: ASCII85-encoded data in bytes format (equal to str in Python 2). """ if sys.version_info[0] < 3: result = str() filler = "\x00" if type(data) is str else b"\x00" if type(data) not in (str, bytes): raise TypeError( "Expected str or bytes type for data, got %s instead" % type(data)) for group in range(int(math.ceil(len(data) / 4.0))): decimalRepr = 0 ascii85 = str() groupWidth = min(4, len(data) - 4 * group) if groupWidth < 4: data = data + (4 - groupWidth) * filler for byte in range(4): decimalRepr += pypdfOrd( data[4 * group + byte]) << 8 * (4 - byte - 1) # If all bytes are 0, we turn them into a single 'z' character if decimalRepr == 0 and groupWidth == 4: ascii85 = "z" else: for i in range(5): ascii85 = chr(decimalRepr % 85 + 33) + ascii85 decimalRepr = int(decimalRepr / 85.0) # In case of a partial group of four bytes, the standard says: # «Finally, it shall write only the first n + 1 characters of the # resulting group of 5.» - ISO 32000 (2008), sec. 7.4.3 result += ascii85[:min(5, groupWidth + 1)] return ("<~" + result + "~>").encode("LATIN1") else: return base64.a85encode(data, adobe=True)
def decode(data, decodeParms=None): """ :param data: flate-encoded data. :param decodeParms: a dictionary of parameter values. :return: the flate-decoded data. :rtype: bytes """ data = decompress(data) predictor = 1 if decodeParms: try: predictor = decodeParms.get("/Predictor", 1) except AttributeError: pass # Usually an array with a null object was read # predictor 1 == no predictor if predictor != 1: # The /Columns param. has 1 as the default value; see ISO 32000, # §7.4.4.3 LZWDecode and FlateDecode Parameters, Table 8 columns = decodeParms.get("/Columns", 1) # PNG prediction: if 10 <= predictor <= 15: output = BytesIO() # PNG prediction can vary from row to row row_length = columns + 1 assert len(data) % row_length == 0 prev_rowdata = (0, ) * row_length for row in range(len(data) // row_length): rowdata = [ pypdfOrd(x) for x in data[(row * row_length):((row + 1) * row_length)] ] filterByte = rowdata[0] if filterByte == 0: pass elif filterByte == 1: for i in range(2, row_length): rowdata[i] = (rowdata[i] + rowdata[i - 1]) % 256 elif filterByte == 2: for i in range(1, row_length): rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256 elif filterByte == 3: for i in range(1, row_length): left = rowdata[i - 1] if i > 1 else 0 floor = math.floor(left + prev_rowdata[i]) / 2 rowdata[i] = (rowdata[i] + int(floor)) % 256 elif filterByte == 4: for i in range(1, row_length): left = rowdata[i - 1] if i > 1 else 0 up = prev_rowdata[i] up_left = prev_rowdata[i - 1] if i > 1 else 0 paeth = paethPredictor(left, up, up_left) rowdata[i] = (rowdata[i] + paeth) % 256 else: # Unsupported PNG filter raise PdfReadError("Unsupported PNG filter %r" % filterByte) prev_rowdata = rowdata for d in rowdata: if version_info < (3, 0): output.write(chr(d)) else: output.write(bytes([d])) data = output.getvalue() else: # unsupported predictor raise PdfReadError("Unsupported flatedecode predictor %r" % predictor) return data
def decode(data, decodeParms=None): """ :param data: flate-encoded data. :param decodeParms: a dictionary of parameter values. :return: the flate-decoded data. :rtype: bytes """ data = decompress(data) predictor = 1 if decodeParms: try: predictor = decodeParms.get("/Predictor", 1) except AttributeError: pass # Usually an array with a null object was read # predictor 1 == no predictor if predictor != 1: # The /Columns param. has 1 as the default value; see ISO 32000, # §7.4.4.3 LZWDecode and FlateDecode Parameters, Table 8 columns = decodeParms.get("/Columns", 1) colors = decodeParms.get("/Colors", 8) # PNG prediction: if 10 <= predictor <= 15: output = BytesIO( ) ### BytesIO au lieu de StringIO, car PIL attend des bytes (Pas de mon fait) # PNG prediction can vary from row to row row_length = columns * colors + 1 assert len(data) % row_length == 0 prev_rowdata = (0, ) * row_length for row in range(len(data) // row_length): rowdata = [ pypdfOrd(x) for x in data[(row * row_length):((row + 1) * row_length)] ] filterByte = rowdata[0] if filterByte == 0: pass elif filterByte == 1: for i in range(1, row_length): if i <= 3: ### On vise hors de la limite gauche, donc 0 (as per les specs) rowdata[i] = (rowdata[i] + 0) % 256 else: rowdata[i] = ( rowdata[i] + rowdata[i - colors] ) % 256 ### Pas le byte d'avant ! Son homologue dans le pixel d'avant ### (TODO : vérifier si le bitdepth < 8, auquel cas il faut ### bel et bien prendre simplement le byte d'avant) elif filterByte == 2: for i in range(1, row_length): rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256 elif filterByte == 3: for i in range(1, row_length): left = rowdata[i - 1] if i > 1 else 0 floor = math.floor(left + prev_rowdata[i]) / 2 rowdata[i] = (rowdata[i] + int(floor)) % 256 elif filterByte == 4: for i in range(1, row_length): left = rowdata[i - 1] if i > 1 else 0 up = prev_rowdata[i] up_left = prev_rowdata[i - 1] if i > 1 else 0 paeth = paethPredictor(left, up, up_left) rowdata[i] = (rowdata[i] + paeth) % 256 else: # Unsupported PNG filter raise PdfReadError("Unsupported PNG filter %r" % filterByte) prev_rowdata = rowdata for d in rowdata[ 1:]: ### Ignorer le premier bit de chaque scanline if version_info < (3, 0): output.write(chr(d)) else: output.write(bytes([d])) data = output.getvalue() else: # unsupported predictor raise PdfReadError("Unsupported flatedecode predictor %r" % predictor) return data