runlength.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. #
  2. # RunLength decoder (Adobe version) implementation based on PDF Reference
  3. # version 1.4 section 3.3.4.
  4. #
  5. # * public domain *
  6. #
  7. from typing import List
  8. def rldecode(data: bytes) -> bytes:
  9. """RunLength decoder (Adobe version) implementation based on PDF Reference
  10. version 1.4 section 3.3.4:
  11. The RunLengthDecode filter decodes data that has been encoded in a
  12. simple byte-oriented format based on run length. The encoded data
  13. is a sequence of runs, where each run consists of a length byte
  14. followed by 1 to 128 bytes of data. If the length byte is in the
  15. range 0 to 127, the following length + 1 (1 to 128) bytes are
  16. copied literally during decompression. If length is in the range
  17. 129 to 255, the following single byte is to be copied 257 - length
  18. (2 to 128) times during decompression. A length value of 128
  19. denotes EOD.
  20. """
  21. decoded_array: List[int] = []
  22. data_iter = iter(data)
  23. while True:
  24. length = next(data_iter, 128)
  25. if length == 128:
  26. break
  27. if 0 <= length < 128:
  28. decoded_array.extend((next(data_iter) for _ in range(length + 1)))
  29. if length > 128:
  30. run = [next(data_iter)] * (257 - length)
  31. decoded_array.extend(run)
  32. return bytes(decoded_array)