Class: LZW::Compressor

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/lzw/compressor.rb

Overview

Scaling LZW data compressor with some configurables

Constant Summary

Constants included from Constants

LZW::Constants::BL_INIT_CODE, LZW::Constants::CHECKPOINT_BITS, LZW::Constants::INIT_CODE_SIZE, LZW::Constants::MAGIC, LZW::Constants::MASK_BITS, LZW::Constants::MASK_BLOCK, LZW::Constants::NR_INIT_CODE, LZW::Constants::RESET_CODE

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(block_mode: true, max_code_size: 16) ⇒ Compressor

LZW::Compressors work fine with the default settings.

Parameters:

  • block_mode (Boolean) (defaults to: true)

    (see #block_mode)

  • max_code_size (Fixnum) (defaults to: 16)


24
25
26
27
28
29
30
31
32
33
34
# File 'lib/lzw/compressor.rb', line 24

def initialize(
  block_mode: true,
  max_code_size: 16
)
  unless max_code_size.between?(INIT_CODE_SIZE, 31)
    fail ArgumentError, "max_code_size must be between #{INIT_CODE_SIZE} and 31"
  end

  @block_mode = block_mode
  @max_code_size = max_code_size
end

Instance Attribute Details

#block_modeBoolean (readonly)

If true, enables compression in block mode. Default true.

After reaching #max_code_size bits per code, the compression dictionary and code size may be reset if a drop in compression ratio is observed.

Returns:

  • (Boolean)


10
11
12
# File 'lib/lzw/compressor.rb', line 10

def block_mode
  @block_mode
end

#max_code_sizeFixnum (readonly)

The maximum code size, in bits, that compression may scale up to. Default 16.

Valid values are init_code_size(9) to 31. Values greater than 16 break compatibility with compress(1).

Returns:

  • (Fixnum)


18
19
20
# File 'lib/lzw/compressor.rb', line 18

def max_code_size
  @max_code_size
end

Instance Method Details

#compress(data) ⇒ String

Given a String(ish) of data, return the LZW-compressed result as another String.

Parameters:

  • data (#each_byte<#chr>)

    Input data

Returns:

  • (String)


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
# File 'lib/lzw/compressor.rb', line 41

def compress(data)
  reset

  # In block mode, we track compression ratio
  @checkpoint = nil
  @last_ratio = nil
  @bytes_in = 0

  seen = +""
  @next_increase = 2**@code_size

  data.each_byte do |byte|
    char = byte.chr
    @bytes_in += 1

    if @code_table.has_key?(seen + char)
      seen << char
    else
      write_code(@code_table[seen])

      new_code(seen + char)

      check_ratio_at_cap

      seen = char
    end
  end

  write_code(@code_table[seen])

  @buf.field
end

#reset

Reset compressor state. This is run at the beginning of #compress, so it’s not necessary for repeated compression, but this allows wiping the last code table and buffer from the object instance.



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/lzw/compressor.rb', line 77

def reset
  @buf = LZW::BitBuf.new
  @buf_pos = 0

  # begin with the magic bytes
  magic.each_byte do |b|
    @buf.set_varint(@buf_pos, 8, b.ord)
    @buf_pos += 8
  end

  code_reset
end