Skip to content

Commit

Permalink
Add ruby-vips for processing opengraph image
Browse files Browse the repository at this point in the history
  • Loading branch information
malkoG committed Apr 19, 2024
1 parent cc292c2 commit bede446
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ group :development do
end

gem "bridgetown-lit-renderer", "= 2.1.0.beta2"

gem "ruby-vips", "~> 2.2"
22 changes: 13 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ GEM
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.6)
json (2.6.3)
json (2.7.1)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
Expand All @@ -95,13 +95,14 @@ GEM
minitest (5.20.0)
mutex_m (0.1.2)
nio4r (2.5.8)
nokogiri (1.15.4)
nokogiri (1.16.0)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
parallel (1.23.0)
parser (3.2.2.4)
parallel (1.24.0)
parser (3.3.0.3)
ast (~> 2.4.1)
racc
prism (0.24.0)
public_suffix (5.0.3)
puma (5.6.2)
nio4r (~> 2.0)
Expand All @@ -115,22 +116,22 @@ GEM
ffi (~> 1.0)
rbs (2.8.4)
redcarpet (3.6.0)
regexp_parser (2.8.2)
regexp_parser (2.9.0)
reverse_markdown (2.1.1)
nokogiri
rexml (3.2.6)
roda (3.73.0)
rack
rouge (3.30.0)
rubocop (1.57.2)
rubocop (1.59.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
Expand All @@ -140,12 +141,14 @@ GEM
prism (>= 0.22.0, < 0.25)
sorbet-runtime (>= 0.5.10782)
ruby-progressbar (1.13.0)
ruby-vips (2.2.1)
ffi (~> 1.12)
ruby2_keywords (0.0.5)
serbea (1.0.1)
activesupport (>= 6.0)
erubi (>= 1.10)
tilt (~> 2.0)
solargraph (0.49.0)
solargraph (0.50.0)
backport (~> 1.2)
benchmark
bundler (~> 2.0)
Expand All @@ -161,8 +164,8 @@ GEM
thor (~> 1.0)
tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24)
thor (1.2.2)
sorbet-runtime (0.5.11351)
thor (1.3.0)
tilt (2.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
Expand All @@ -182,6 +185,7 @@ DEPENDENCIES
puma (~> 5.6)
redcarpet (~> 3.5)
ruby-lsp (~> 0.14.6)
ruby-vips (~> 2.2)
solargraph

BUNDLED WITH
Expand Down
73 changes: 73 additions & 0 deletions plugins/utils/opengraph/image.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'vips'

module Utils
module Opengraph
class Image
attr_reader :elements, :canvas, :borders, :canvas_color

def initialize(width, height, color: '#ffffff')
@elements = []
@canvas_color = color
@canvas = Vips::Image.black(width, height).ifthenelse([0, 0, 0], hex_to_rgb(color))
@borders = {}
end

def image(source, resize_with_ratio:)
im = source ? Vips::Image.new_from_buffer(source, '') : Vips::Image.black(1, 1).ifthenelse([0, 0, 0], hex_to_rgb(canvas_color))
if resize_with_ratio && source
width, height = resize_with_ratio
ratio = get_ratio(im, width, height, :min)
im = im.resize(ratio)
end
@elements << im
self
end

def text(message, width:, height:, dpi: 300, color: '#2f363d', font: 'Open Sans Bold')
im = Vips::Image.text(message, width: width, height: height, dpi: dpi, font: font)
im = im.new_from_image(hex_to_rgb(color)).copy(interpretation: :srgb).bandjoin(im)
@elements << im

self
end

def border_bottom(height, color: '#000000')
im = Vips::Image.black(canvas.width, height).ifthenelse([0, 0, 0], hex_to_rgb(color))
borders[:bottom] = im

self
end

def compose(filename)
result = yield(canvas, *elements)
@canvas = @canvas.composite(
elements + [borders[:bottom]], :over,
x: result[:x] + (borders[:bottom] ? [0] : []),
y: result[:y] + (borders[:bottom] ? [canvas.height - borders[:bottom].height] : [])
)

@canvas.write_to_file(filename)
end

private

def hex_to_rgb(input)
case input
when String
input.match(/#(..)(..)(..)/)[1..3].map(&:hex)
when Array
input
else
raise ArgumentError, "Unknown input #{input.inspect}"
end
end

# https://github.com/dariocravero/vips-process/blob/master/lib/vips-process/resize.rb#L109
def get_ratio(image, width, height, min_or_max = :min)
width_ratio = width.to_f / image.width
height_ratio = height.to_f / image.height
[width_ratio, height_ratio].send min_or_max
end
end
end
end

0 comments on commit bede446

Please sign in to comment.