def render_username(template_image): with WandImage.from_array( cv2.cvtColor(template_image, cv2.COLOR_BGRA2RGBA) ) as img: with WandDrawing() as context: context.font_size = BASE_FONT_SIZE if username: context.fill_color = "#f7d676" # Icon height doesnt match measurements exactly... HEIGHT/2 would be best for y context.text(x=LOGO_WIDTH + 2, y=28, body=f"/u/{username}") else: context.fill_color = "white" context.fill_opacity = 0.8 context.text(x=LOGO_WIDTH + 2, y=28, body="• Temporary build") context(img) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: template_image = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED) return template_image
def render_background_rect(image_background): with WandImage.from_array( cv2.cvtColor(image_background, cv2.COLOR_BGRA2RGBA)) as img: with WandDrawing() as context: context.stroke_width = 1 context.stroke_color = "rgba(255,255,255,1)" context.fill = TRAIT_BG context.fill_opacity = TRAIT_BG_OPACITY x1 = trait_hex_inradius y1 = text_box_y_top x2 = image_background.shape[1] - TRAIT_BG_STROKE_WIDTH / 2 # padding is extra, but looks better y2 = text_box_y_top + text_box_height + TRAIT_BG_PADDING / 2 context.rectangle( left=int(x1), top=int(y1), width=int(x2 - x1), height=int(y2 - y1), radius=4, ) context(img) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: return cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)
def render_count(image_base): count_x = icon_background_width + TRAIT_GAP count_height = int(text_box_height * COUNT_HEIGHT_PROPORTION) count_y = int(text_baseline_y - count_height / 2) count_width = COUNT_WIDTH with WandImage.from_array(cv2.cvtColor(image_base, cv2.COLOR_BGRA2RGBA)) as img: with WandDrawing() as context: context.fill_color = TRAIT_COUNT_BG context.rectangle( left=count_x, top=count_y, width=count_width, height=count_height, radius=4, ) font = WandFont( os.path.join( PATH_TO_ASSETS, "fonts", "Montserrat-Bold.ttf", ), color=Color("white"), ) context(img) img.caption( f"{trait_count}", left=count_x, top=count_y, width=count_width, height=count_height, font=font, gravity="center", ) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: return cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)
def make_frame(self, streams): frame = WandImage(width=self.frame_d[0],background=Color('white'), height=self.frame_d[1]) for n, stream in enumerate(streams): img = WandImage(file=stream) x = config.photo_w * ((n >> 1) & 1) y = config.photo_h * (n & 1) frame.composite(img, left=x+18, top=y+18) drawing = WandDrawing() # drawing.font = '/home/pi/booth4/fonts/Steelworks.otf' drawing.font = '/home/pi/booth6/fonts/Vulturemotor.otf' drawing.font_size = 20 # drawing.font_style = 'italic' # drawing.fill_color = Color('orange') # drawing.stroke_color = Color('brown') drawing.text(310, 660, 'The Mighty Booth') drawing(frame) return frame
def render_trait_name_and_sets(image_base): text_x = icon_background_width + TRAIT_GAP + COUNT_WIDTH + TRAIT_GAP trait_text_y = text_baseline_y - FONT_BASELINE_GAP set_text_y = text_baseline_y + FONT_BASELINE_GAP + BASE_FONT_SIZE # draw trait name with WandImage.from_array(cv2.cvtColor(image_base, cv2.COLOR_BGRA2RGBA)) as img: with WandDrawing() as context: context.fill_color = "white" context.font_weight = 700 context.font_size = BASE_FONT_SIZE context.text(x=text_x, y=trait_text_y, body=trait_name) context(img) for idx, trait_set in enumerate(trait_sets): width_per_count = 6 # just a guess is_last = idx == len(trait_sets) - 1 set_x = text_x + idx * (width_per_count + TRAIT_SET_GAP + CARET_SIZE + TRAIT_SET_GAP) is_selected = (trait_set["min"] <= trait_count < (cast( float, trait_set.get("max", float("inf"))))) with WandDrawing() as context: context.fill_color = "white" context.font_size = BASE_FONT_SIZE context.font_weight = 600 if is_selected: context.fill_opacity = 1 else: context.fill_opacity = 0.7 context.text(x=set_x, y=set_text_y, body=f"{trait_set['min']}") context(img) if not is_last: with WandDrawing() as context: caret_x1 = set_x + TRAIT_GAP + width_per_count / 2 caret_x2 = caret_x1 + CARET_SIZE caret_y1 = set_text_y - BASE_FONT_SIZE / 2 - CARET_SIZE / 4 caret_y2 = caret_y1 + CARET_SIZE caret_pts = [ (caret_x1, caret_y1), (caret_x2, caret_y1 + CARET_SIZE / 2), (caret_x1, caret_y2), ] context.stroke_color = "white" context.stroke_opacity = 0.6 context.fill_color = "transparent" context.polyline(caret_pts) context(img) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: return cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)
def make_untrimmed_social_media_img(): social_config = [ { "id": twitch_id, "image_path": os.path.join( PATH_TO_ASSETS, "socials", "twitch-transparent.png" ), }, { "id": youtube_id, "image_path": os.path.join( PATH_TO_ASSETS, "socials", "youtube-22.png" ), }, ] # more space than we'll ever need; crop later social_base_image = np.zeros( (LOGO_HEIGHT, int(CARRY_IMAGE_WIDTH / 2), 4), dtype=np.uint8 ) SOCIAL_ROW_HEIGHT = 16 SOCIAL_ICON_WIDTH = 22 config_to_apply = [config for config in social_config if config["id"]] for idx, config in enumerate(config_to_apply): social_id = config["id"] image_path = config["image_path"] social_icon_image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED) social_row_y = (SOCIAL_ROW_HEIGHT + 12) * idx overlay_transparent( social_base_image, social_icon_image, 0, social_row_y ) with WandImage.from_array( cv2.cvtColor(social_base_image, cv2.COLOR_BGRA2RGBA) ) as img: with WandDrawing() as context: context.font_size = BASE_FONT_SIZE context.fill_color = "white" context.text( x=SOCIAL_ICON_WIDTH + 2, y=social_row_y + BASE_FONT_SIZE, body=f"{social_id}", ) context(img) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: social_base_image = cv2.imdecode( img_buffer, cv2.IMREAD_UNCHANGED ) return social_base_image
def render_trait_name(image): trait_name_img = np.zeros(image.shape, dtype=np.uint8) icon_background_width = trait_style_background_img.shape[1] icon_background_height = trait_style_background_img.shape[0] trait_hex_inradius = icon_background_width / 2 trait_hex_circumradius = icon_background_height / 2 text_x = int(icon_background_width + TEXT_MARGIN_LEFT) text_centre_y = int(trait_hex_circumradius) (text_width, text_height) = get_text_dimensions( text=trait_name, font_size=BASE_FONT_SIZE, ) pil_img = Image.fromarray(np.uint8(trait_name_img)) # wanted to get text drawn with pillow; could not get working. Resorting to wand d = ImageDraw.Draw(pil_img) rect_x1 = int(trait_hex_inradius - TRAIT_BG_PADDING / 2) rect_y1 = int(text_centre_y - text_height / 2 - TRAIT_BG_PADDING / 2) rect_x2 = int( trait_hex_inradius + TEXT_MARGIN_LEFT + rect_x1 + text_width + TRAIT_BG_PADDING ) rect_y2 = int(rect_y1 + text_height + TRAIT_BG_PADDING) d.rectangle( [(rect_x1, rect_y1), (rect_x2, rect_y2)], fill=TRAIT_BG, ) trait_name_img = np.asarray(pil_img) with WandImage.from_array( cv2.cvtColor(trait_name_img, cv2.COLOR_BGRA2RGBA) ) as img: with WandDrawing() as context: context.fill_color = "white" path_to_font = os.path.join( PATH_TO_ASSETS, "fonts", "Heebo-Bold.ttf", ) context.font = path_to_font context.font_size = BASE_FONT_SIZE text_y = int(text_centre_y + BASE_FONT_SIZE / 3) # idk why 3 context.text(text_x, text_y, trait_name) context(img) img.format = "png" img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8) if img_buffer is not None: # # uint16 -> uint8 conversion (needed coming from wand) trait_name_img = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED) trait_name_img = cv2.convertScaleAbs( trait_name_img, alpha=(255.0 / 65535.0) ) overlay_transparent(trait_name_img, image, 0, 0) return trait_name_img