Improvements to text rendering.
This commit is contained in:
parent
ed2b1a42ab
commit
d7299822ed
BIN
images/bamse_skorsten_1.png
Normal file
BIN
images/bamse_skorsten_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 430 KiB |
126
main.lua
126
main.lua
|
@ -20,7 +20,7 @@ if CONFIG.LUA_EXTRA_CPATH then package.cpath = package.cpath .. CONFIG.LUA_EXTR
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Constants
|
-- Constants
|
||||||
|
|
||||||
local FARVEL_INTERVAL = 60
|
local FARVEL_INTERVAL = 120
|
||||||
local MEME_INTERVAL = 30
|
local MEME_INTERVAL = 30
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -75,6 +75,22 @@ local function generate_bait_link()
|
||||||
return 'https://dcav.pw/jbait'
|
return 'https://dcav.pw/jbait'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function fit_font_to_line_height (font_name, height)
|
||||||
|
local size_min, size_max = 1, 50
|
||||||
|
while true do
|
||||||
|
local size_guess = math.floor((size_max + size_min)/2)
|
||||||
|
assert(size_min <= size_guess and size_guess <= size_max)
|
||||||
|
local font = assert(imlib.font.load(font_name..'/'..size_guess))
|
||||||
|
if size_guess == size_min then return font end
|
||||||
|
local text_w, text_h = font:get_size 'k'
|
||||||
|
--
|
||||||
|
if text_h <= height then size_min = size_guess
|
||||||
|
else size_max = size_guess
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function determine_required_font_size (font_name, text, width)
|
local function determine_required_font_size (font_name, text, width)
|
||||||
local size_min, size_max = 1, 50
|
local size_min, size_max = 1, 50
|
||||||
while true do
|
while true do
|
||||||
|
@ -82,7 +98,7 @@ local function determine_required_font_size (font_name, text, width)
|
||||||
assert(size_min <= size_guess and size_guess <= size_max)
|
assert(size_min <= size_guess and size_guess <= size_max)
|
||||||
local font = assert(imlib.font.load(font_name..'/'..size_guess))
|
local font = assert(imlib.font.load(font_name..'/'..size_guess))
|
||||||
if size_guess == size_min then return font end
|
if size_guess == size_min then return font end
|
||||||
local text_w = font:get_size(text)
|
local text_w, text_h = font:get_size(text)
|
||||||
--
|
--
|
||||||
if text_w <= width then size_min = size_guess
|
if text_w <= width then size_min = size_guess
|
||||||
else size_max = size_guess
|
else size_max = size_guess
|
||||||
|
@ -91,18 +107,82 @@ local function determine_required_font_size (font_name, text, width)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function wrap_lines (font, text, width)
|
||||||
|
local lines, current, x = {}, {}, 0
|
||||||
|
local SPACE_ADVANCE = font:get_advance ' '
|
||||||
|
for word in text:gmatch '[^%s]+' do
|
||||||
|
assert(type(word) == 'string')
|
||||||
|
local word_w = font:get_advance(word)
|
||||||
|
local next_x = x + word_w + SPACE_ADVANCE
|
||||||
|
if word == '' then
|
||||||
|
-- Do nothing
|
||||||
|
elseif next_x <= width then
|
||||||
|
current[#current+1], x = word, next_x
|
||||||
|
else
|
||||||
|
lines[#lines+1], current = table.concat(current, ' '), { word }
|
||||||
|
x = word_w
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Færdiggør sidste linje
|
||||||
|
lines[#lines+1] = table.concat(current, ' ')
|
||||||
|
-- Ret
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
|
||||||
local COLOR_WHITE = imlib.color.new(255, 255, 255)
|
local COLOR_WHITE = imlib.color.new(255, 255, 255)
|
||||||
local COLOR_BLACK = imlib.color.new( 0, 0, 0)
|
local COLOR_BLACK = imlib.color.new( 0, 0, 0)
|
||||||
|
|
||||||
local function draw_centered_text_in_box (font_name, draw_onto, text, x0, y0, width, height, bg_color)
|
local function draw_centered_lines (draw_onto, lines, x0, y0, width, font, font_color)
|
||||||
assert(type(font_name) == 'string')
|
assert(type(lines) == 'table')
|
||||||
font = determine_required_font_size(font_name, text, width)
|
local y = y0
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
local text_w, text_h = font:get_size(line)
|
||||||
|
local x = x0 + (width - text_w) / 2
|
||||||
|
draw_onto:draw_text(font, line, x, y, font_color or COLOR_BLACK)
|
||||||
--
|
--
|
||||||
local text_w, text_h = font:get_size(text)
|
y = y + text_h
|
||||||
local x, y = x0 + (width - text_w) / 2, y0 + (height - text_h) / 2
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function determine_font_and_lines_for_box (font_name, text, width, height)
|
||||||
|
local num_lines, last_actual, actual_lines = 1, nil, nil
|
||||||
|
for iteration = 1, 10 do
|
||||||
|
local estimate_font = determine_required_font_size(font_name, text, width * num_lines)
|
||||||
|
local line_height = select(2, estimate_font:get_size(text))
|
||||||
|
|
||||||
|
local estimate_num_lines = height / select(2, estimate_font:get_size(text))
|
||||||
|
local lines = wrap_lines(estimate_font, text, width)
|
||||||
|
local actual_num_lines = #lines
|
||||||
|
print(require'pretty'(lines))
|
||||||
|
--local estimate_num_lines = #lines
|
||||||
|
if #lines * line_height >= height then
|
||||||
|
estimate_num_lines = estimate_num_lines - 1
|
||||||
|
end
|
||||||
|
print(num_lines, estimate_num_lines)
|
||||||
|
-- Test for convergence
|
||||||
|
if last_actual == actual_num_lines then
|
||||||
|
actual_lines = lines
|
||||||
|
break
|
||||||
|
end
|
||||||
|
num_lines = (estimate_num_lines + actual_num_lines) / 2
|
||||||
|
last_actual = actual_num_lines
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(actual_lines)
|
||||||
|
local actual_font = fit_font_to_line_height(font_name, height / #actual_lines)
|
||||||
|
|
||||||
|
assert(#actual_lines * select(2, actual_font:get_size(text)) < height)
|
||||||
|
return actual_font, actual_lines
|
||||||
|
end
|
||||||
|
|
||||||
|
local function draw_centered_text_in_box (font_name, draw_onto, text, x0, y0, width, height, bg_color, font_color)
|
||||||
|
assert(type(font_name) == 'string')
|
||||||
|
local font, lines = determine_font_and_lines_for_box(font_name, text, width, height)
|
||||||
|
--
|
||||||
|
local y = y0 + (height - #lines * select(2, font:get_size(text))) / 2
|
||||||
--
|
--
|
||||||
if bg_color then draw_onto:fill_rectangle(x0, y0, width, height, bg_color) end
|
if bg_color then draw_onto:fill_rectangle(x0, y0, width, height, bg_color) end
|
||||||
draw_onto:draw_text(font, text, x, y, COLOR_BLACK)
|
draw_centered_lines(draw_onto, lines, x0, y, width, font, font_color)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function choose_random_font ()
|
local function choose_random_font ()
|
||||||
|
@ -161,7 +241,7 @@ local function fill_in_topics_information (topics)
|
||||||
return new_topics
|
return new_topics
|
||||||
end
|
end
|
||||||
|
|
||||||
local function paste_topic_onto_image (target, topic, x, y, w, h, bg_color, font_name)
|
local function paste_topic_onto_image (target, topic, x, y, w, h, bg_color, font_name, font_color)
|
||||||
assert(target)
|
assert(target)
|
||||||
assert(type(topic) == 'table')
|
assert(type(topic) == 'table')
|
||||||
assert(type(font_name) == 'string')
|
assert(type(font_name) == 'string')
|
||||||
|
@ -186,7 +266,7 @@ local function paste_topic_onto_image (target, topic, x, y, w, h, bg_color, font
|
||||||
--os.remove(filename)
|
--os.remove(filename)
|
||||||
elseif topic.type == 'text' then
|
elseif topic.type == 'text' then
|
||||||
local text = topic.text
|
local text = topic.text
|
||||||
draw_centered_text_in_box(font_name, target, text, x, y, w, h, bg_color)
|
draw_centered_text_in_box(font_name, target, text, x, y, w, h, bg_color, font_color)
|
||||||
elseif topic.type == 'droste' then
|
elseif topic.type == 'droste' then
|
||||||
target:fill_rectangle(x, y, w, h, COLOR_WHITE)
|
target:fill_rectangle(x, y, w, h, COLOR_WHITE)
|
||||||
else
|
else
|
||||||
|
@ -207,8 +287,8 @@ local function save_to_cloud (img)
|
||||||
img:save (MEME_OUTPUT)
|
img:save (MEME_OUTPUT)
|
||||||
img:free()
|
img:free()
|
||||||
-- Upload to dcav
|
-- Upload to dcav
|
||||||
local img_name = 'otmemes_'..os.time()
|
local img_name = 'otmemes_'..os.time()..'.png'
|
||||||
copy_remotely('localhost', MEME_OUTPUT, CONFIG.STORAGE_SERVER, CONFIG.STORAGE_SERVER_PATH..img_name..'.png')
|
copy_remotely('localhost', MEME_OUTPUT, CONFIG.STORAGE_SERVER, CONFIG.STORAGE_SERVER_PATH..img_name)
|
||||||
return CONFIG.STORAGE_DIR_URL..img_name
|
return CONFIG.STORAGE_DIR_URL..img_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -251,7 +331,7 @@ local function generate_comparison_meme_generator (positions)
|
||||||
assert(type(positions.base_img_path) == 'string')
|
assert(type(positions.base_img_path) == 'string')
|
||||||
|
|
||||||
return function (topics)
|
return function (topics)
|
||||||
assert(type(topics) == 'table' and #topics == 2)
|
assert(type(topics) == 'table' and #topics == #positions)
|
||||||
|
|
||||||
local font_name = choose_random_font()
|
local font_name = choose_random_font()
|
||||||
|
|
||||||
|
@ -267,7 +347,7 @@ local function generate_comparison_meme_generator (positions)
|
||||||
|
|
||||||
-- Paste topic onto head
|
-- Paste topic onto head
|
||||||
for index, pos in ipairs(rand_positions) do
|
for index, pos in ipairs(rand_positions) do
|
||||||
paste_topic_onto_image(base_img, topics[index], pos.x, pos.y, pos.w, pos.h, nil, font_name)
|
paste_topic_onto_image(base_img, topics[index], pos.x, pos.y, pos.w, pos.h, nil, font_name, pos.font_color)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Droste
|
-- Droste
|
||||||
|
@ -292,6 +372,12 @@ local generate_drake_egon_olsen = generate_comparison_meme_generator {
|
||||||
{ x = 377, xr = 0, y = 354, yr = 0, w = 383, h = 360 },
|
{ x = 377, xr = 0, y = 354, yr = 0, w = 383, h = 360 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local generate_skorsten_image = generate_comparison_meme_generator {
|
||||||
|
base_img_path = './images/bamse_skorsten_1.png',
|
||||||
|
|
||||||
|
{ x = 646, xr = 0, y = 366, yr = 0, w = 631, h = 215, font_color = COLOR_WHITE },
|
||||||
|
}
|
||||||
|
|
||||||
local GENERATE_COMPARISON_MEME_OF_2 = {
|
local GENERATE_COMPARISON_MEME_OF_2 = {
|
||||||
generate_distracted_boyfriend,
|
generate_distracted_boyfriend,
|
||||||
generate_drake_egon_olsen
|
generate_drake_egon_olsen
|
||||||
|
@ -548,6 +634,18 @@ local function handle_message(bot, user, channel, message, is_slow_channel)
|
||||||
return 'MACHINE'
|
return 'MACHINE'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Vælter min skorsten
|
||||||
|
do
|
||||||
|
local problem_text = message:lower():match 'vælter%s+min%s+skorsten%s*(.+)$'
|
||||||
|
if problem_text then
|
||||||
|
if problem_text:match '^er' then problem_text = problem_text:match '^er%s*(.+)$' end
|
||||||
|
if problem_text:match '^:' then problem_text = problem_text:match '^:%s*(.+)$' end
|
||||||
|
local img_link = generate_skorsten_image {{ type = 'text', text = problem_text }}
|
||||||
|
bot:sendChat(channel, img_link)
|
||||||
|
return 'SKRSTEN'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Comparison memes
|
-- Comparison memes
|
||||||
local topics = get_topics_from_comparison_message(message)
|
local topics = get_topics_from_comparison_message(message)
|
||||||
if not topics then return end
|
if not topics then return end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user