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.


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/origami/filters/runlength.rb', line 72

def decode(stream)
    result = "".b

    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
# 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 = compute_run_length(stream, i)

        # If more than 1, then compress them.
        if length > 1
            result << (257 - length).chr << stream[i]
            i += length

        # Otherwise how many different bytes to copy?
        else
            next_pos = find_next_run(stream, i)
            length = next_pos - i

            result << (length - 1).chr << stream[i, length]

            i += length
        end
    end

    result << EOD.chr
end