runlength.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. #!/usr/bin/env python
  2. #
  3. # RunLength decoder (Adobe version) implementation based on PDF Reference
  4. # version 1.4 section 3.3.4.
  5. #
  6. # * public domain *
  7. #
  8. def rldecode(data):
  9. """
  10. RunLength decoder (Adobe version) implementation based on PDF Reference
  11. version 1.4 section 3.3.4:
  12. The RunLengthDecode filter decodes data that has been encoded in a
  13. simple byte-oriented format based on run length. The encoded data
  14. is a sequence of runs, where each run consists of a length byte
  15. followed by 1 to 128 bytes of data. If the length byte is in the
  16. range 0 to 127, the following length + 1 (1 to 128) bytes are
  17. copied literally during decompression. If length is in the range
  18. 129 to 255, the following single byte is to be copied 257 - length
  19. (2 to 128) times during decompression. A length value of 128
  20. denotes EOD.
  21. >>> s = "\x05123456\xfa7\x04abcde\x80junk"
  22. >>> rldecode(s)
  23. '1234567777777abcde'
  24. """
  25. decoded = []
  26. i = 0
  27. while i < len(data):
  28. #print "data[%d]=:%d:" % (i,ord(data[i]))
  29. length = ord(data[i])
  30. if length == 128:
  31. break
  32. if length >= 0 and length < 128:
  33. run = data[i+1:(i+1)+(length+1)]
  34. #print "length=%d, run=%s" % (length+1,run)
  35. decoded.append(run)
  36. i = (i+1) + (length+1)
  37. if length > 128:
  38. run = data[i+1]*(257-length)
  39. #print "length=%d, run=%s" % (257-length,run)
  40. decoded.append(run)
  41. i = (i+1) + 1
  42. return ''.join(decoded)
  43. if __name__ == '__main__':
  44. import doctest
  45. doctest.testmod()