class Origami::Filter::LZW

Class representing a filter used to encode and decode data with LZW compression algorithm.

Public Instance Methods

decode(string) click to toggle source

Decodes given data using LZW compression method.

stream

The data to decode.

# File lib/origami/filters/lzw.rb, line 82
def decode(string)
    result = "".b
    bstring = Utils::BitReader.new(string)
    table, codesize = reset_state
    prevbyte = nil

    until bstring.eod? do
        byte = bstring.read(codesize)
        break if byte == EOD

        if byte == CLEARTABLE
            table, codesize = reset_state
            prevbyte = nil
            redo
        end

        begin
            codesize = decode_codeword_size(table)
            result << decode_byte(table, prevbyte, byte, codesize)
        rescue InvalidLZWDataError => error
            error.message.concat " (bit pos #{bstring.pos - codesize})"
            error.input_data = string
            error.decoded_data = result
            raise(error)
        end

        prevbyte = byte
    end

    post_prediction(result)
end
encode(string) click to toggle source

Encodes given data using LZW compression method.

stream

The data to encode.

# File lib/origami/filters/lzw.rb, line 44
def encode(string)
    input = pre_prediction(string)

    table, codesize = reset_state
    result = Utils::BitWriter.new
    result.write(CLEARTABLE, codesize)

    s = ''
    input.each_byte do |byte|
        char = byte.chr

        if table.size == 4096
            result.write(CLEARTABLE, codesize)
            table, _ = reset_state
        end

        codesize = table.size.bit_length

        it = s + char
        if table.has_key?(it)
            s = it
        else
            result.write(table[s], codesize)
            table[it] = table.size
            s = char
        end
    end

    result.write(table[s], codesize) unless s.empty?
    result.write(EOD, codesize)

    result.final.to_s
end

Private Instance Methods

decode_codeword_size(table) click to toggle source
# File lib/origami/filters/lzw.rb, line 116
def decode_codeword_size(table)
    case table.size
    when 258...510 then 9
    when 510...1022 then 10
    when 1022...2046 then 11
    when 2046...4095 then 12
    else
        raise InvalidLZWDataError, "LZW table is full and no clear flag was set"
    end
end