Class: Origami::Filter::LZW

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

Overview

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

Constant Summary collapse

EOD =

:nodoc:

257
CLEARTABLE =

:nodoc:

256

Constants included from Predictor

Predictor::NONE, Predictor::PNG_AVERAGE, Predictor::PNG_NONE, Predictor::PNG_OPTIMUM, Predictor::PNG_PAETH, Predictor::PNG_SUB, Predictor::PNG_UP, Predictor::TIFF

Constants included from Origami::Filter

A85, AHx, CCF, Fl, RL

Instance Method Summary collapse

Methods included from Predictor

included, #initialize

Methods included from Origami::Filter

included, #initialize

Instance Method Details

#decode(string) ⇒ Object

Decodes given data using LZW compression method.

stream

The data to decode.



80
81
82
83
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
# File 'lib/origami/filters/lzw.rb', line 80

def decode(string)
  result = "".b
  bstring = Utils::BitReader.new(string)
  table, codesize = reset_state
  prevbyte = nil

  until bstring.eod?
    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) ⇒ Object

Encodes given data using LZW compression method.

stream

The data to encode.



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
# File 'lib/origami/filters/lzw.rb', line 42

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