Class: Origami::Filter::RunLength

Inherits:
Object
  • Object
show all
Includes:
Origami::Filter
Defined in:
lib/origami/filters/runlength.rb

Overview

Class representing a Filter used to encode and decode data using RLE compression algorithm.

Constant Summary collapse

EOD =

:nodoc:

128

Constants included from Origami::Filter

A85, AHx, CCF, Fl, RL

Instance Method Summary collapse

Methods included from Origami::Filter

included, #initialize

Instance Method Details

#decode(stream) ⇒ Object

Decodes data using RLE decompression method.

stream

The data to decode.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/origami/filters/runlength.rb', line 84

def decode(stream)
    result = "".b
    return result if stream.empty?

    i = 0
    until i >= stream.length or stream[i].ord == EOD do

        # At least two bytes are required.
        if i > stream.length - 2
            raise InvalidRunLengthDataError.new("Truncated run-length data", input_data: stream, decoded_data: result)
        end

        length = stream[i].ord
        if length < EOD
            result << stream[i + 1, length + 1]
            i = i + length + 2
        else
            result << stream[i + 1] * (257 - length)
            i = i + 2
        end
    end

    # Check if offset is beyond the end of data.
    if i >= stream.length
        raise InvalidRunLengthDataError.new("Truncated run-length data", input_data: stream, decoded_data: result)
    end

    result
end

#encode(stream) ⇒ Object

Encodes data using RLE compression method.

stream

The data to encode.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/origami/filters/runlength.rb', line 40

def encode(stream)
    result = "".b
    i = 0

    while i < stream.size
        #
        # How many identical bytes coming?
        #
        length = 1
        while i+1 < stream.size and length < EOD and stream[i] == stream[i+1]
            length = length + 1
            i = i + 1
        end

        #
        # If more than 1, then compress them.
        #
        if length > 1
            result << (257 - length).chr << stream[i]
        #
        # Otherwise how many different bytes to copy?
        #
        else
            j = i
            while j+1 < stream.size and (j - i + 1) < EOD and stream[j] != stream[j+1]
                j = j + 1
            end

            length = j - i
            result << length.chr << stream[i, length+1]

            i = j
        end

        i = i + 1
    end

    result << EOD.chr
end