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.

[View source]

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.

[View source]

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