Class: Radio::Gif

Inherits:
Object
  • Object
show all
Defined in:
lib/radio/gif.rb

Class Method Summary collapse

Class Method Details

.waterfall(colors, data, min = nil, max = nil) ⇒ Object

This is a very fast GIF generator for waterfalls. It requires 128 RGB colors, the first is unused and reserved for transparency if we ever need it. data is expected to be an NArray



27
28
29
30
31
32
33
34
35
36
37
38
39
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
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/radio/gif.rb', line 27

def self.waterfall colors, data, min=nil, max=nil
  width = data[true,0].size
  height = data[0,true].size
  gif = [
    'GIF87a', # Start Header
    width,
    height,
    0xF6, # 128 24-bit colors
    0x00, # background color index
    0x00 # aspect ratio
  ].pack 'a6vvCCC'
  gif += colors.flatten.pack 'C*'
  gif += [
    0x2C, # Start Image Block
    0x0000, # Left position
    0x0000, # Top position
    width,
    height,
    0x00, # No color table, not interlaced
    0x07 # LZW code size
  ].pack('CvvvvCC')
  data = data.reshape(data.size)
  min ||= data.min
  max ||= data.max
  range = [1e-99, max - min].max
  data -= min # will dup
  data.div!(range).mul!(126).add!(1)
  # add in a frame+reset every 126 plus the 4 byte end block
  predict = gif.size + (data.size+125) / 126 * 2 + data.size + 4
  out = NArray.byte predict
  out[0...gif.size] = NArray.to_na gif, NArray::BYTE, gif.size
  i = 0
  pos = gif.size
  while i < data.size
    qty = [126,data.size-i].min
    out[pos] = qty+1
    pos+=1
    if qty == 1
      out[pos] = data[i]
    else
      out[pos...pos+qty] = data[i...i+qty]
    end
    pos+=qty
    out[pos] = 0x80 # LZW reset
    pos+=1
    i += qty
  end
  out[pos] = 0x01, # end image blocks
  out[pos+1] = 0x81, # final image block: LZW end
  out[pos+2] = 0x00, # end image blocks
  out[pos+3] = 0x3B # end gif
  out.to_s
end