Module: FastThumbhash

Defined in:
lib/fast_thumbhash.rb,
lib/fast_thumbhash/version.rb

Defined Under Namespace

Modules: Library

Constant Summary collapse

VERSION =
"0.7.2"

Class Method Summary collapse

Class Method Details

.binary_thumbhash_to_rgba(binary_thumbhash, max_size: nil, size: nil, fill_mode: :solid, fill_color: [255, 255, 255, 0], homogeneous_transform: nil, saturation: 0) ⇒ Object

Raises:

  • (ArgumentError)


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
# File 'lib/fast_thumbhash.rb', line 27

def self.binary_thumbhash_to_rgba(
  binary_thumbhash,
  max_size: nil,
  size: nil,
  fill_mode: :solid,
  fill_color: [255, 255, 255, 0],
  homogeneous_transform: nil,
  saturation: 0
)
  i[solid blur clamp].include?(fill_mode) or
    raise ArgumentError, "Invalid `fill_mode` option"

  if fill_color
    fill_color.length == 4 or
      raise ArgumentError, "You need to pass [r, g, b, a] to the `fill_color` option"
  end

  raise ArgumentError, "Option `fill_color` is required for :solid fill_mode" if fill_mode == :solid && fill_color.nil?

  if homogeneous_transform
    (homogeneous_transform.size == 3 && homogeneous_transform.all? { |row| row.size == 3 }) or
      raise ArgumentError, "`homogeneous_transform` option must be a 3x3 matrix"
  end

  if size
    size.length == 2 or
      raise ArgumentError, "You need to pass [width, height] to the `size` option"

    size.all? { |dimension| dimension < 100 } or
      raise ArgumentError, "Cannot generate images bigger then 100 pixels"
  end

  if max_size
    max_size <= 100 or
      raise ArgumentError, "Cannot generate images bigger then 100 pixels"
  end

  !max_size.nil? ^ !size.nil? or
    raise ArgumentError, "Pass either the `max_size` option, or an explicit `size`"

  binary_thumbhash_to_rgba!(
    binary_thumbhash,
    max_size: max_size,
    size: size,
    fill_mode: fill_mode,
    fill_color: fill_color,
    homogeneous_transform: homogeneous_transform,
    saturation: saturation
  )
end

.binary_thumbhash_to_rgba!(binary_thumbhash, max_size: nil, size: nil, fill_mode: :solid, fill_color: [255, 255, 255, 0], homogeneous_transform: nil, saturation: 0) ⇒ Object



78
79
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/fast_thumbhash.rb', line 78

def self.binary_thumbhash_to_rgba!(
  binary_thumbhash,
  max_size: nil,
  size: nil,
  fill_mode: :solid,
  fill_color: [255, 255, 255, 0],
  homogeneous_transform: nil,
  saturation: 0
)
  fill_color_pointer =
    if fill_color
      FFI::MemoryPointer.new(:uint8, 4).tap do |p|
        p.write_array_of_uint8(fill_color)
      end
    end

  transform_pointer =
    if homogeneous_transform
      FFI::MemoryPointer.new(:double, 6).tap do |p|
        p.write_array_of_double(
          [
            homogeneous_transform[0][0],
            homogeneous_transform[0][1],
            homogeneous_transform[0][2],
            homogeneous_transform[1][0],
            homogeneous_transform[1][1],
            homogeneous_transform[1][2]
          ]
        )
      end
    end

  thumbhash_pointer = FFI::MemoryPointer.new(:uint8, binary_thumbhash.size)
  thumbhash_pointer.put_array_of_uint8(0, binary_thumbhash.unpack("C*"))

  width, height =
    if size
      size
    else
      thumb_size_pointer = FFI::MemoryPointer.new(:uint8, 2)
      Library.thumb_size(thumbhash_pointer, max_size, thumb_size_pointer)
      thumb_size_pointer.read_array_of_uint8(2)
    end

  rgba_size = width * height * 4
  rgba_pointer = FFI::MemoryPointer.new(:uint8, rgba_size)

  Library.thumbhash_to_rgba(
    thumbhash_pointer,
    width,
    height,
    fill_mode.to_sym,
    fill_color_pointer,
    transform_pointer,
    saturation.clamp(-100, 100),
    rgba_pointer
  )

  [width, height, rgba_pointer.read_array_of_uint8(rgba_size)]
ensure
  fill_color_pointer&.free
  transform_pointer&.free
  thumbhash_pointer&.free
  thumb_size_pointer&.free
  rgba_pointer&.free
end

.rgba_to_binary_thumbhash(width, height, rgba) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/fast_thumbhash.rb', line 149

def self.rgba_to_binary_thumbhash(width, height, rgba)
  (width <= 100 && height <= 100) or
    raise ArgumentError, "Encoding an image larger than 100x100 is slow with no benefit"

  rgba_pointer = FFI::MemoryPointer.new(:uint8, rgba.size)
  rgba_pointer.put_array_of_uint8(0, rgba)

  thumbhash_pointer = FFI::MemoryPointer.new(:uint8, 25)

  length = Library.rgba_to_thumbhash(width, height, rgba_pointer, thumbhash_pointer)

  result = thumbhash_pointer.read_array_of_uint8(length)

  result.pack("C*")
ensure
  rgba_pointer&.free
  thumbhash_pointer&.free
end

.rgba_to_thumbhash(width, height, rgba) ⇒ Object



145
146
147
# File 'lib/fast_thumbhash.rb', line 145

def self.rgba_to_thumbhash(width, height, rgba)
  Base64.strict_encode64(rgba_to_binary_thumbhash(width, height, rgba))
end

.thumbhash_to_rgba(thumbhash, max_size: nil, size: nil, fill_mode: :solid, fill_color: [255, 255, 255, 0], homogeneous_transform: nil, saturation: 0) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/fast_thumbhash.rb', line 7

def self.thumbhash_to_rgba(
  thumbhash,
  max_size: nil,
  size: nil,
  fill_mode: :solid,
  fill_color: [255, 255, 255, 0],
  homogeneous_transform: nil,
  saturation: 0
)
  binary_thumbhash_to_rgba(
    Base64.decode64(thumbhash),
    max_size: max_size,
    size: size,
    fill_mode: fill_mode,
    fill_color: fill_color,
    homogeneous_transform: homogeneous_transform,
    saturation: saturation
  )
end