Module: JXL::Modular::Predictor

Defined in:
lib/jxl/modular/predictor.rb

Class Method Summary collapse

Class Method Details

.gradient(left, top, topleft) ⇒ Object



78
# File 'lib/jxl/modular/predictor.rb', line 78

def gradient(left, top, topleft) = (left + top - topleft).clamp([left, top].min, [left, top].max)

.neighbors(plane, x, y) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/jxl/modular/predictor.rb', line 85

def neighbors(plane, x, y)
  left =
    if x.positive?
      plane[x - 1, y]
    elsif y.positive?
      plane[x, y - 1]
    else
      0
    end
  top = y.positive? ? plane[x, y - 1] : left
  topright = y.positive? && x + 1 < plane.width ? plane[x + 1, y - 1] : top
  {
    left:, top:,
    topleft: x.positive? && y.positive? ? plane[x - 1, y - 1] : left,
    topright:,
    leftleft: x > 1 ? plane[x - 2, y] : left,
    toptop: y > 1 ? plane[x, y - 2] : top,
    toprightright: y.positive? && x + 2 < plane.width ? plane[x + 2, y - 1] : topright
  }
end

.predict(kind, plane, x, y) ⇒ Object



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
# File 'lib/jxl/modular/predictor.rb', line 41

def predict(kind, plane, x, y)
  data = plane.data
  width = plane.width
  index = (y * width) + x
  left = if x.positive?
           data[index - 1]
         elsif y.positive?
           data[index - width]
         else
           0
         end
  top = y.positive? ? data[index - width] : left
  topleft = x.positive? && y.positive? ? data[index - width - 1] : left
  topright = y.positive? && x + 1 < width ? data[index - width + 1] : top
  case kind
  when 0 then 0
  when 1 then left
  when 2 then top
  when 3 then Num.cdiv(left + top, 2)
  when 4 then select(left, top, topleft)
  when 5 then gradient(left, top, topleft)
  when 7 then topright
  when 8 then topleft
  when 9 then x > 1 ? data[index - 2] : left
  when 10 then Num.cdiv(left + topleft, 2)
  when 11 then Num.cdiv(topleft + top, 2)
  when 12 then Num.cdiv(top + topright, 2)
  when 13
    toptop = y > 1 ? data[index - (2 * width)] : top
    leftleft = x > 1 ? data[index - 2] : left
    toprightright = y.positive? && x + 2 < width ? data[index - width + 2] : topright
    Num.cdiv((6 * top) - (2 * toptop) + (7 * left) + leftleft + toprightright + (3 * topright) + 8, 16)
  else
    raise UnsupportedFeatureError, "weighted modular predictor"
  end
end

.properties(plane, x, y, channel:, group: 0, previous_gradient: 0, weighted_property: 0, references: []) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/jxl/modular/predictor.rb', line 8

def properties(plane, x, y, channel:, group: 0, previous_gradient: 0, weighted_property: 0, references: [])
  data = plane.data
  width = plane.width
  index = (y * width) + x
  left = if x.positive?
           data[index - 1]
         elsif y.positive?
           data[index - width]
         else
           0
         end
  top = y.positive? ? data[index - width] : left
  topleft = x.positive? && y.positive? ? data[index - width - 1] : left
  topright = y.positive? && x + 1 < width ? data[index - width + 1] : top
  leftleft = x > 1 ? data[index - 2] : left
  toptop = y > 1 ? data[index - (2 * width)] : top
  values = [channel, group, y, x, top.abs, left.abs, top, left,
            left - previous_gradient, left + top - topleft,
            left - topleft, topleft - top, top - topright,
            top - toptop, left - leftleft, weighted_property]
  references.reverse_each do |reference|
    next unless reference.width == plane.width && reference.height == plane.height

    value = reference[x, y]
    ref_left = x.positive? ? reference[x - 1, y] : 0
    ref_top = y.positive? ? reference[x, y - 1] : ref_left
    ref_topleft = x.positive? && y.positive? ? reference[x - 1, y - 1] : ref_left
    residual = value - gradient(ref_left, ref_top, ref_topleft)
    values.push(value.abs, value, residual.abs, residual)
  end
  values.map { Num.i32(_1) }
end

.select(left, top, topleft) ⇒ Object



80
81
82
83
# File 'lib/jxl/modular/predictor.rb', line 80

def select(left, top, topleft)
  predicted = left + top - topleft
  (predicted - left).abs < (predicted - top).abs ? left : top
end