diff --git a/main.lua b/main.lua index 0a202de..588b1db 100644 --- a/main.lua +++ b/main.lua @@ -117,6 +117,30 @@ local function load_random_font () return font_name end +local DROSTE_EFFECT_TRIGGERS = { + ['induktion'] = true, + ['rekursion'] = true, + ['uendelig rekursion'] = true, + ['rekursive'] = true, + ['rekursive funktioner'] = true, + ['recursion'] = true, + ['infinite recursion'] = true, + ['tail recursion'] = true, + ['recursive'] = true, + ['recursive function'] = true, + ['induktion'] = true, + ['droste'] = true, + ['drostle'] = true, -- Misspelling + + ['uendelig'] = true, + ['uendeligt'] = true, + + ['strange loop'] = true, + ['loop'] = true, +} + +local DROSTE_ITERATIONS_DEFAULT = 5 + local function fill_in_topics_information (topics) assert(type(topics) == 'table') -- @@ -127,10 +151,10 @@ local function fill_in_topics_information (topics) assert(type(topic) == 'string') local url = topic_to_image_url[topic] - print(topic, url) - if url then new_topics[i] = { topic = topic, type = 'image', url = url } - else new_topics[i] = { topic = topic, type = 'text', text = topic } + if DROSTE_EFFECT_TRIGGERS[topic] then new_topics[i] = { topic = topic, type = 'droste' } + elseif url then new_topics[i] = { topic = topic, type = 'image', url = url } + else new_topics[i] = { topic = topic, type = 'text', text = topic } end end return new_topics @@ -162,6 +186,8 @@ local function paste_topic_onto_image (target, topic, x, y, w, h, bg_color, font elseif topic.type == 'text' then local text = topic.text draw_centered_text_in_box(font_name, target, text, x, y, w, h, bg_color) + elseif topic.type == 'droste' then + target:fill_rectangle(x, y, w, h, COLOR_WHITE) else assert(false, topic.type) end @@ -185,6 +211,34 @@ local function save_to_cloud (img) return CONFIG.STORAGE_DIR_URL..img_name end + +local function draw_droste_effect (target_image, droste_positions, iterations) + iterations = interations or DROSTE_ITERATIONS_DEFAULT + if #droste_positions <= 0 or iterations <= 0 then return target_image end + for _ = 1, iterations do + for _, position in ipairs(droste_positions) do + local paste_image = target_image:clone() + paste_image:crop_and_scale(0, 0, paste_image:get_width(), paste_image:get_height(), position.w, position.h) + flatten_onto (target_image, paste_image, position.x, position.y) + paste_image:free() + end + end + return target_image +end + +local function droste_positions_from_topics (topics, places) + local droste_poss = {} + for i, topic in ipairs(topics) do + if topic.type == 'droste' then + droste_poss[#droste_poss+1] = { + x = places[i].x, y = places[i].y, + w = places[i].w, h = places[i].h, + } + end + end + return droste_poss +end + local function generate_distracted_boyfriend (topics) assert(type(topics) == 'table' and #topics == 2) @@ -194,32 +248,57 @@ local function generate_distracted_boyfriend (topics) local HEAD_W, HEAD_H = 150, 150 - local x1, y1 = 640 + math.random(-20, 20), 50 + math.random(-20, 20) - local x2, y2 = 180 + math.random(-20, 20), 50 + math.random(-20, 20) - paste_topic_onto_image(base_img, topics[1], x1, y1, HEAD_W, HEAD_H, nil, font_name) - paste_topic_onto_image(base_img, topics[2], x2, y2, HEAD_W, HEAD_H, nil, font_name) + local DISTRACTED_BOYFRIEND_POS = { + { x = 640 + math.random(-20, 20), y = 50 + math.random(-20, 20), w = HEAD_W, h = HEAD_H }, + { x = 180 + math.random(-20, 20), y = 50 + math.random(-20, 20), w = HEAD_W, h = HEAD_H }, + } + + -- Paste topic onto head + for index, pos in ipairs(DISTRACTED_BOYFRIEND_POS) do + paste_topic_onto_image(base_img, topics[index], pos.x, pos.y, pos.w, pos.h, nil, font_name) + end + + -- Droste + base_img = draw_droste_effect(base_img, droste_positions_from_topics(topics, DISTRACTED_BOYFRIEND_POS)) -- return save_to_cloud(base_img) end +local BRAIN_ROW_HEIGHT = 150 +local BRAIN_ROW_WIDTH = 200 + +local BRAIN_MAX_EXPLOSION_TOPICS = 6 +local BRAIN_DROSTE_POS = {} +for i = 1, BRAIN_MAX_EXPLOSION_TOPICS do + BRAIN_DROSTE_POS[i] = { + x = 0, + y = (i-1) * BRAIN_ROW_HEIGHT, + w = BRAIN_ROW_WIDTH, + h = BRAIN_ROW_HEIGHT + } +end + + local function generate_brain_explosion_image (topics) - assert(type(topics) == 'table' and 1 <= #topics and #topics <= 6) + assert(type(topics) == 'table' and 1 <= #topics and #topics <= BRAIN_MAX_EXPLOSION_TOPICS) -- - local ROW_HEIGHT = 150 - local ROW_WIDTH = 200 - local base_img = imlib.image.new(ROW_WIDTH * 2, ROW_HEIGHT * #topics) + local base_img = imlib.image.new(BRAIN_ROW_WIDTH * 2, BRAIN_ROW_HEIGHT * #topics) local font_name = choose_random_font() -- for i, topic_info in ipairs(topics) do - paste_topic_onto_image(base_img, topic_info, 0, (i-1) * ROW_HEIGHT, ROW_WIDTH, ROW_HEIGHT, COLOR_WHITE, font_name) + paste_topic_onto_image(base_img, topic_info, 0, (i-1) * BRAIN_ROW_HEIGHT, BRAIN_ROW_WIDTH, BRAIN_ROW_HEIGHT, COLOR_WHITE, font_name) local brain_img = imlib.image.load(CONFIG.IMGGEN_PATH_BRAINS..'brain_'..i..'.png') - brain_img:crop_and_scale(0, 0, brain_img:get_width(), brain_img:get_height(), ROW_WIDTH, ROW_HEIGHT) - flatten_onto (base_img, brain_img, ROW_WIDTH, (i-1) * ROW_HEIGHT) + brain_img:crop_and_scale(0, 0, brain_img:get_width(), brain_img:get_height(), BRAIN_ROW_WIDTH, BRAIN_ROW_HEIGHT) + flatten_onto (base_img, brain_img, BRAIN_ROW_WIDTH, (i-1) * BRAIN_ROW_HEIGHT) brain_img:free() end + -- Droste + base_img = draw_droste_effect(base_img, droste_positions_from_topics(topics, BRAIN_DROSTE_POS)) + + -- Save return save_to_cloud(base_img) end