Class: Blurhash::Encode

Inherits:
Object
  • Object
show all
Defined in:
lib/blurhash/encode.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.callObject

rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity



7
# File 'lib/blurhash/encode.rb', line 7

def self.call(...) = new.call(...)

Instance Method Details

#call(pixels:, width:, height:, component_x:, component_y:) ⇒ Object



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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/blurhash/encode.rb', line 9

def call(pixels:, width:, height:, component_x:, component_y:)
  if component_x < 1 ||
      component_x > 9 ||
      component_y < 1 ||
      component_y > 9
    raise ValidationError,
      "BlurHash must have between 1 and 9 components"
  end
  unless pixels.length == width * height * 3
    raise ValidationError,
      "Width and height must match the pixels array"
  end

  factors = []

  component_y.times do |y|
    component_x.times do |x|
      normalisation = x.zero? && y.zero? ? 1 : 2
      factor = multiply_basis_function(pixels, width, height) do |i, j|
        normalisation *
          Math.cos(Math::PI * x * i / width) *
          Math.cos(Math::PI * y * j / height)
      end
      factors << factor
    end
  end

  dc = factors[0]
  ac = factors[1..]

  hash = +""

  size_flag = (component_x - 1) + ((component_y - 1) * 9)
  hash << Base83.encode(size_flag, 1)

  if ac.any?
    actual_max = ac.map(&:max).max
    quant_max = ((actual_max * 166) - 0.5).floor.clamp(0, 82)
    max_val = (quant_max + 1) / 166.0
    hash << Base83.encode(quant_max, 1)
  else
    max_val = 1.0
    hash << Base83.encode(0, 1)
  end

  hash << Base83.encode(encode_dc(dc), 4)

  ac.each do |factor|
    hash << Base83.encode(encode_ac(factor, max_val), 2)
  end

  hash
end