def test_idm_works_for_text_layer_without_content(self): bg = ColorBackgroundLayer("bg", content="White") # content is None layer = PointTextLayer("layer", "Arial", 12, "Black", left=NA(0), base=NA(40)) square = ColorLayer("sqr", content="Red", width=NA(20), height=NA(20), bottom=SA("layer.cap"), left=NA(25)) temp = Template("temp", layer, square, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() temp.render().save( filename= "tests/images/test_idm_works_for_text_layer_without_content.png")
def test_template_with_add_attribute_can_render(self): title = PTL("title", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) sub_title = PTL("sub_title", "Arial", 15, "Black", content="Bottom Text", left=NA(10), bottom=AA(SA("template.height"), NA(45, negative=True))) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", title, sub_title, bg, left=NA(0), top=NA(0), width=NA(200), height=NA(200)) temp.update_bounds() image = temp.render() image.save( filename= f"tests/images/test_template_with_add_attribute_can_render.jpg")
def test_can_render_shadow(self): pt = PTL("pt", "Arial", 15, "Black", content="PT", left=NA(0), top=NA(0)) pt2 = PTL("pt2", "Arial", 15, "Black", content="PT2", left=NA(0), top=AA(SA("pt.bottom"), NA(5))) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", pt, pt2, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() image = temp.render() image.save(filename="tests/images/test_can_render_shadow_1.png") shadow = pt2.shadow(2, 2, radius=4, sigma=2) image.composite(shadow, 0, 0) image.save(filename="tests/images/test_can_render_shadow_2.png")
def test_template_with_max_attribute_can_render(self): c1 = ColorLayer("color1", content="Green", left=NA(0), width=NA(50), top=NA(0), height=NA(50)) c2 = ColorLayer("color2", content="Blue", left=NA(0), width=NA(60), top=SA("color1.bottom"), height=NA(50)) text = PTL("test", "Arial", 15, "Black", content="Hello World", left=MinA(SA("color1.right"), SA("color2.right")), top=SA("color2.bottom")) bg = ColorBackgroundLayer("name", content="White") layers = [c1, c2, bg, text] temp = Template("temp", *layers, left=NA(0), top=NA(0), width=NA(300), height=NA(300)) temp.update_bounds() assert text["left"] == 60
def test_can_unset_attributes_evaluated_values(self): """Because the content of pt is changing per iteration, the left of square should change as well (top should change due to p in people).""" content_list = ["hello world", "people"] square_lefts = [] # stores left values per iteration square_tops = [] pt = PTL("pt", "Arial", 15, "Black", left=NA(0), top=NA(0)) square = ColorLayer("square", content="Red", left=AA(SA("pt.right")), top=SA("pt.bottom"), width=NA(20), height=NA(20)) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", pt, square, bg, left=NA(0), top=NA(0), height=NA(100), width=NA(100)) for i, content in enumerate(content_list): pt.pre_render = None pt.content = content temp.unset_bounds_and_attributes() temp.update_bounds() temp.render().save( filename= f"tests/images/{i}_test_can_unset_attributes_evaluated_values.png" ) square_lefts.append(temp.get_layer("square")["left"]) square_tops.append(temp.get_layer("square")["top"]) assert square_lefts[0] != square_lefts[1] assert square_tops[0] != square_tops[1]
def test_can_render_color_overlay(self): pt = PTL("pt", "Arial", 15, "Black", content="PT", left=NA(0), top=NA(0)) pt2 = PTL("pt2", "Arial", 15, "Black", content="PT2", left=NA(0), top=AA(SA("pt.bottom"), NA(5))) bg = ColorBackgroundLayer("bg", content="Red") temp = Template("temp", pt, pt2, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() image = temp.render() image.save(filename="tests/images/test_can_render_color_overlay_1.png") overlay = pt2.color_overlay("Blue") image.composite(overlay, int(pt2["left"]), int(pt2["top"])) image.save(filename="tests/images/test_can_render_color_overlay_2.png")
def test_can_order_layers_for_rendering(self): kwargs = { "left": SA("parent.left"), "right": SA("parent.right"), "top": SA("parent.top"), "bottom": SA("parent.bottom") } l1 = ColorLayer("layer_1", content="#FF0000", order=1, **kwargs) l2 = ColorLayer("layer_1", content="#00FF00", order=2, **kwargs) temp = Template("temp", l1, l2, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() green_above = temp.render() color_of_top_left_most_pixel = green_above.export_pixels(width=1, height=1) # RGBA, [1] is green assert color_of_top_left_most_pixel[:3] == [0, 255, 0] l1.order = 3 # move red above red_above = temp.render() color_of_top_left_most_pixel = red_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [255, 0, 0]
def test_can_have_templates_within_templates(self): pt = PointTextLayer("point_text_layer", content="Point Text Layer", font="Arial", size=35, color="Black", left=NA(0), top=NA(0)) bg = ColorLayer("bg", content="Red", left=NA(0), width=SA("parent.width"), height=SA("parent.height"), top=NA(0)) temp = Template("temp", pt, bg, left=NA(0), right=SA("point_text_layer.right"), top=NA(0), height=NA(100)) temp2 = Template("temp", temp, left=NA(0), right=SA("point_text_layer.right"), top=NA(0), height=NA(500)) temp2.update_bounds()
def test_setting_base_on_ptl_is_same_as_drawing_text(self): width = 100 text = "Hpqrs" left = 0 base = 20 median = 40 median_offset_for_font_size_12 = 6 bg_color = "White" bg = ColorBackgroundLayer("bg", content=bg_color) l = PointTextLayer("l", "Arial", 12, "Black", content=text, left=NA(left), base=NA(base)) l2 = PointTextLayer("l2", "Arial", 12, "Black", content=text, left=NA(left), median=NA(median)) temp = Template("temp", l, l2, bg, left=NA(0), right=NA(width), top=NA(0), bottom=NA(width)) temp.update_bounds() img = temp.render() img.save( filename= "tests/images/test_setting_base_on_ptl_is_same_as_drawing_text.png" ) with nested( Image(width=width, height=width, background=Color(bg_color)), Drawing()) as (img2, draw): draw.font = l.font draw.font_size = l.size draw.text(left, base, text) draw.text(left, median + median_offset_for_font_size_12, text) draw(img2) img2.save( filename= "tests/images/test_setting_base_on_ptl_is_same_as_drawing_text_2.png" ) location, diff = img.similarity(img2, metric="absolute") assert diff == 0
def test_template_can_render_boundary(self): pt = PointTextLayer("pt", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) square = ColorLayer("square", content="Orange", left=NA(20), top=NA(20), height=NA(20), width=NA(20)) bg = ColorBackgroundLayer("bg", content="None") temp = Template("temp", pt, square, bg, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp.update_bounds() boundary = temp.render_boundary() # boundary.save(filename="tests/images/test_template_can_render_boundary_b.png") image = temp.render()
def test_this_configuration_can_render(self): pt = PointTextLayer("ptl", "Arial", 15, "Black", content="Hello World", left=AA(SA("parent.left"), NA(5)), top=SA("parent.top")) bg = ColorBackgroundLayer("bg", content="Green") temp = Template("temp", pt, bg, left=NA(10), right=SA("ptl.right"), top=SA("parent.top"), height=NA(100)) temp2 = Template("temp2", temp, left=NA(0), right=NA(100), top=NA(0), height=NA(100)) temp2.update_bounds() image = temp2.render()
def test_point_text_layer_can_render_when_content_and_parent_is_set(self): l = PointTextLayer("layer", "Arial", 12, "Black", content="hello world", left=NA(30), top=NA(45)) temp = Template("temp", l, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() l.render() assert l.pre_render is not None
def test_layers_passed_in_first_without_order_are_rendered_first( self, save_images): kwargs = { "left": SA("parent.left"), "right": SA("parent.right"), "top": SA("parent.top"), "bottom": SA("parent.bottom") } l1 = ColorLayer("layer_1", content="#FF0000", **kwargs) # red l2 = ColorLayer("layer_1", content="#00FF00", **kwargs) # green # l1 is first, is rendered first; therefore l2 (green) should be on top temp = Template("temp", l1, l2, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() green_above = temp.render() color_of_top_left_most_pixel = green_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [0, 255, 0] # RGBA, [1] is green # remake template, now l2 is first, l1 rendered last temp = Template("temp", l2, l1, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() red_above = temp.render() color_of_top_left_most_pixel = red_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [255, 0, 0] if save_images: green_above.save(filename="tests/images/green_above.png") red_above.save(filename="tests/images/red_above.png")
def test_can_get_mean_indepth_font_metrics_for_ptl(self): bg = ColorBackgroundLayer("bg", content="White") l = PointTextLayer("l", "Arial", 12, "Black", content="Hpqrs", left=NA(0), base=NA(20)) l2 = PointTextLayer("l2", "Arial", 12, "Black", content="e", left=NA(10), median=NA(50)) # l3 = PointTextLayer("l3", "Arial", 12, "Black", content="l", left=NA(20), descender=NA(50)) l4 = PointTextLayer("l4", "Arial", 12, "Black", content="l", left=NA(30), cap=NA(50)) # l5 = PointTextLayer("l5", "Arial", 12, "Black", content="o", left=NA(40), ascender=NA(50)) temp = Template( "temp", l, l2, bg, left=NA(0), # temp = Template("temp", l, l2, l3, l4, l5, left=NA(0), # right=SA("l5.right"), top=NA(0), bottom=SA("l5.bottom")) right=SA("l.right"), top=NA(0), bottom=SA("l.bottom")) temp.update_bounds() temp.render().save( filename= "tests/images/test_can_get_mean_indepth_font_metrics_for_ptl.png")
def test_template_configurations_dont_change_output(self): pt = PointTextLayer("ptl", "Arial", 10, "Black", content="Hello", left=NA(0), top=NA(0)) pt2 = PointTextLayer("ptl2", "Arial", 10, "Black", content="foobar", left=NA(10), top=NA(10)) pt3 = PointTextLayer("ptl3", "Arial", 10, "Black", content="Garlic", left=NA(20), top=NA(20)) temp1 = Template("temp1", pt, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp23 = Template("temp23", pt2, pt3, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp123 = Template("temp123", temp1, temp23, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp4 = Template("temp", pt, pt2, pt3, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp123.update_bounds() image123 = temp123.render() image123.save(filename="tests/images/test_template_configurations_dont_change_output_1.png") temp4.update_bounds() image4 = temp4.render() image4.save(filename="tests/images/test_template_configurations_dont_change_output_2.png") location, diff = image123.similarity(image4, metric="absolute") assert diff == 0
def test_can_make_negative_string_attribute(self): """Tests if negative SAs can be initialised and if the different conventions will produce the same result""" negative_str_attr_1 = SA("-title.right") negative_str_attr_2 = SA("title.right", True) # test_layer_1 and test_layer_2 will have same left value title = PTL("title", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) test_layer_1 = ColorLayer("test_layer_1", content="Blue", left=negative_str_attr_1, right=SA("parent.right"), top=SA("title.top"), height=NA(20)) test_layer_2 = ColorLayer("test_layer_2", content="Green", left=negative_str_attr_2, right=SA("parent.right"), top=SA("test_layer_1.top"), height=NA(20)) temp = Template("temp", title, test_layer_1, test_layer_2, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp.update_bounds() assert test_layer_1["left"] == test_layer_2["left"]
def test_exception_raised_if_no_existant_layer_is_referenced_in_SA(self): with pytest.raises(LayerDoesNotExistError): pt = PTL("test", "Arial", 15, "Black", content="Hello", left=NA(0), top=NA(0)) sq = ColorLayer("square", content="Red", left=NA(0), top=SA("doesnotexist.bottom"), width=NA(20), height=NA(20)) bg = ColorBackgroundLayer("bg", content="Green") bg2 = ColorBackgroundLayer("bg2", content="White") temp2 = Template("temp2", sq, bg, left=NA(0), width=NA(25), top=NA(0), height=NA(25)) temp = Template("temp", pt, bg2, temp2, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp.update_bounds() # from pprint import pprint # pprint(temp.get_layer("temp2").__dict__) temp.render().save( filename= "tests/images/test_exception_raised_if_no_existant_layer_is_referenced_in_SA.png" )
image = Image(width=int(self["width"]), height=int(self["height"])) for layer in sorted(self.layers, key=lambda l: l.order): if layer.content is not None or isinstance(layer, Template): img = layer.render(fresh) if img is not None: image.composite(img, left=int(layer["left"] - self["left"]), top=int(layer["top"]- self["top"])) return image if __name__ == "__main__": # color = ColorLayer("color", content="Red", left=AA(SA('-parent.left'), NA(100)), width=NA(300), # top=AA(SA('-parent.top'), NA(100)), height=NA(500)) # bg = ColorBackgroundLayer("bg", content="White") # mask_bg = ColorBackgroundLayer("bg", content="Green") # mask = Template("mask", color, mask_bg, left=NA( # 200), width=NA(200), top=NA(100), height=NA(300)) # temp = Template("main", mask, bg, left=NA( # 0), width=NA(500), top=NA(0), height=NA(700)) color2 = ColorLayer("color", content="Red", left=NA(100), width=NA(300), top=NA(100), height=NA(500)) bg2 = ColorBackgroundLayer("bg", content="White") mask_bg2 = ColorBackgroundLayer("bg", content="Green") mask2 = Mask("mask", color2, mask_bg2, left=NA(200), width=NA(200), top=NA(100), height=NA(300)) temp2 = Template("main", mask2, bg2, left=NA(0), width=NA(500), top=NA(0), height=NA(700)) temp2.update_bounds() image = temp2.render() image.save(filename="test.png")
def make(self, card): art_layers, llayers = self.layers(card) text_template = Template("text_temp", *llayers, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) art_template = Template("art_temp", *art_layers, order=-5, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) temp = Template("template", text_template, art_template, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) # generic templating temp.mana_image_format = "svg" temp.resource_dir = self.RESOURCE_DIR # START setting content rules = self.getRules(card) temp.get_layer("rules").content = rules for name in temp.get_layer("text_temp").layers: layer = temp.get_layer(name) if layer.name in card: layer.content = card[layer.name] if card['flavor_name'] is not None: temp.get_layer('name').content = card['flavor_name'] temp.get_layer('flavor_name').content = card['name'] # card['name'], card['flavor_name'] = card['flavor_name'], card['name'] if card["layout"] == "adventure": for cc in card['card_faces']: if "power" in cc: creature = cc else: adventure_card = cc temp.get_layer('name').content = creature['name'] temp.get_layer('mana_cost').content = creature['mana_cost'] temp.get_layer('type').content = creature['type_line'] temp.get_layer( "adventure_rules").content = adventure_card['oracle_text'] temp.get_layer( "adventure_type").content = adventure_card["type_line"] temp.get_layer("adventure_name").content = adventure_card["name"] temp.get_layer( "adventure_mana_cost").content = adventure_card["mana_cost"] elif card["layout"] == "split": temp.get_layer("name").content = card["card_faces"][0]["name"] temp.get_layer("type").content = card["card_faces"][0]["type_line"] temp.get_layer( "mana_cost").content = card["card_faces"][0]["mana_cost"] temp.get_layer( "rules").content = card["card_faces"][1]["oracle_text"] temp.get_layer("split_art_top" ).content = card["card_faces"][0]["image_location"] temp.get_layer("split_art_bottom" ).content = card["card_faces"][1]["image_location"] temp.get_layer( "split_name").content = card["card_faces"][1]["name"] temp.get_layer( "split_mana_cost").content = card["card_faces"][1]["mana_cost"] temp.get_layer( "split_type").content = card["card_faces"][0]["type_line"] temp.get_layer( "split_rules").content = card["card_faces"][0]["oracle_text"] # generic if "Creature" in card["type"]: temp.get_layer( "PT").content = f"{card['power']}/{card['toughness']}" number = card['number'].upper().zfill(3) count = int(card['count']) temp.get_layer("number").content = f"{number}/{count:03}" rarity = card["rarity"][0].upper() temp.get_layer("rarity").color = self.rarity_colors[rarity] temp.get_layer("rarity").content = rarity # RULES CONTENT # if rules != "": # else: # temp.get_layer('rules').content = card[self.text_to_use] art_path = join(self.RESOURCE_DIR, "art", card['set'], f"{card['name']}_{card['id']}.jpg") \ .replace("//", "__") # print(art_path) if card['image_location']: temp.get_layer("art").content = card['image_location'] else: temp.get_layer("art").content = art_path if os.path.isfile( art_path) else None # generic temp.update_bounds() render_bg = temp.get_layer("art_temp").render() image = render_bg.clone() # if temp.get_layer("art").content is not None: render_text_shadow = temp.get_layer("text_temp").shadow(-4, 4, sigma=2, radius=4, color="Black") image.composite(render_text_shadow, left=0, top=0) render_text = temp.get_layer("text_temp").render() image.composite(render_text, left=0, top=0) # END setting content # SAVING content # image.save(filename=join(SAVE_LOCATION, f"{card['name']}_{card['id']}.jpg").replace("//", "__")) # image.save(filename=join(SAVE_LOCATION, f"{card['name']}.jpg").replace("//", "__")) p = self.pdf.clone() p.composite(image, left=73, top=67) p.save(filename=join(self.PDF_SAVE_LOCATION, f"{card['name']}_{card['id']}.pdf").replace( "//", "__"))
def main(): RESOURCE_DIR = join(os.getcwd(), "resources") SETS = join(RESOURCE_DIR, "card_data", "sets.json") TEST_DIR = "test_images" MPLANTIN = join(RESOURCE_DIR, "fonts", "MPlantin.ttf") BELEREN_SC = join(RESOURCE_DIR, "fonts", "Beleren_small_caps.ttf") BELEREN = join(RESOURCE_DIR, "fonts", "Jace_Beleren_bold.ttf") MPLANTIN_BOLD = join(RESOURCE_DIR, "fonts", "MPlantin_bold.ttf") MPLANTIN_ITAL = join(RESOURCE_DIR, "fonts", "MPlantin_italic.ttf") RELAY = join(RESOURCE_DIR, "fonts", "Relay_medium.ttf") FC = "White" FLAVOR_SPLIT_COLOR = "RGBA(255, 255, 255, 0.6)" FLAVOR_SPLIT_OFFSET = 40 if os.path.isfile(SETS): with open(SETS, "r") as f: sets = json.load(f) else: raise ValueError("sets.json not found.") myset = "WAR" # JSON = join(RESOURCE_DIR, "card_data", f"{myset}.json") # JSON = join(RESOURCE_DIR, "card_data", f"mardu_aristocrats_M20.json") # TOKENS = join(RESOURCE_DIR, "card_data", f"tokens.json") # ANGELS = join(RESOURCE_DIR, "card_data", f"mardu_angels_M20.json") JSON = join(RESOURCE_DIR, "set_data", f"{myset}.json") # SULTAI_FLASH = join(RESOURCE_DIR, "card_data", f"sultai_flash.json") SAVE_LOCATION = myset # SAVE_LOCATION = "sultai_flash" # JSON = SULTAI_FLASH # JSON = TOKENS """make directory in art""" # if not os.path.isdir(join(RESOURCE_DIR, "art", myset)): # dir does not exist # os.mkdir(join(RESOURCE_DIR, "art", myset)) """make directory in render dir""" if not os.path.isdir(join("test_images", "all_render", SAVE_LOCATION)): # dir does not exist os.mkdir(join("test_images", "all_render", SAVE_LOCATION)) """load cards""" with open(JSON, "r") as f: cards = json.load(f) """load tokens""" # with open(TOKENS, "r") as f: # tokens = json.load(f) BORDER = 45 RULES_BORDER = 52 HEIGHT = 1050 WIDTH = 752 SET_DOT_LANG_WIDTH = 5 INFO_SIZE = 18 # FONT_SIZE = 40 NAME_SIZE = 38 TYPE_SIZE = 33 PT_LOYAL_SIZE = 40 RULES_TEXT_SIZE = 25 la = AA(MA(SA("language.right"), SA("number.right")), NA(3)) lmiddle = AA( NA(WIDTH / 2), DivA(AA(SA("artist_brush.width"), NA(3), SA("artist.width")), NA(2), negative=True)) art_layers = { "bg": ColorBackgroundLayer("bg", content=Color("Black")), "art": FillIL("art", order=-5, XP50=NA(WIDTH / 2), YP50=NA(HEIGHT / 2), width=NA(WIDTH), height=NA(HEIGHT)), "shadow1": ColorLayer("shadow1", content="RGBA(0,0,0,0.4)", left=NA(0), width=NA(WIDTH), top=NA(0), bottom=SA("shadow2.top")), "shadow2": GradL("shadow2", start="RGBA(0,0,0,0.4)", end="RGBA(0,0,0,0.0)", left=NA(0), width=NA(WIDTH), top=SA("name.bottom"), height=NA(200)), "shadow3": GradL("shadow3", start="RGBA(0,0,0,0.0)", end="RGBA(0,0,0,0.7)", left=NA(0), width=NA(WIDTH), bottom=SA("shadow4.top"), top=AA(SA("type.cap"), NA(-150))), "shadow4": ColorLayer("shadow4", content="RGBA(0,0,0,0.7)", left=NA(0), width=NA(WIDTH), bottom=NA(HEIGHT + 1), top=SA("rules.YP70")) } no_content_reset = { "dot": PTL("dot", RELAY, 25, FC, content=".", left=AA(SA("set.right"), NA(SET_DOT_LANG_WIDTH)), ycenter=SA("set.ycenter")), "language": PTL("language", RELAY, INFO_SIZE, FC, content="EN", left=AA(SA("dot.right"), NA(SET_DOT_LANG_WIDTH)), base=NA(HEIGHT - BORDER)), "artist_brush": ResizeIL("artist_brush", content=join(RESOURCE_DIR, "artist_brush_white.png"), width=NA(20), left=lmiddle, height=SA("set.height"), bottom=NA(HEIGHT - BORDER)), "copyright": PTL("copyright", MPLANTIN, INFO_SIZE - 5, FC, right=NA(WIDTH - BORDER), bottom=SA("set.bottom")), } layers = { "name": PTL("name", BELEREN, NAME_SIZE, FC, left=NA(BORDER), base=NA(80)), "type": PTL("type", BELEREN, TYPE_SIZE, FC, left=NA(BORDER), base=AA(SA("rules.top"), NA(-10))), "PT": PTL("PT", BELEREN, PT_LOYAL_SIZE, FC, right=NA(WIDTH - BORDER), base=SA("set.base")), "loyalty": PTL("loyalty", BELEREN, PT_LOYAL_SIZE, FC, right=NA(WIDTH - BORDER), base=SA("set.base")), "set": PTL("set", RELAY, INFO_SIZE, FC, left=NA(BORDER), base=NA(HEIGHT - BORDER)), "number": PTL("number", RELAY, INFO_SIZE, FC, left=NA(BORDER), base=AA(SA("set.cap"), NA(-3))), "rarity": PTL("rarity", RELAY, INFO_SIZE, FC, left=SA("artist_brush.left"), base=SA("number.base")), "artist": PTL("artist", BELEREN_SC, INFO_SIZE, FC, left=AA(SA("artist_brush.right"), NA(3)), base=SA("set.base")), "mana_cost": ManaCost("mana_cost", font=BELEREN, font_size=NAME_SIZE, font_color=FC, right=NA(WIDTH - BORDER), bottom=AA(SA("name.base"), NA(4))), "rules": RulesText("rules", MPLANTIN, MPLANTIN_ITAL, RULES_TEXT_SIZE, FC, RULES_TEXT_SIZE - 4, left=NA(RULES_BORDER), right=NA(WIDTH - RULES_BORDER), bottom=AA(SA("PT.bottom"), NA(-PT_LOYAL_SIZE), NA(-5))), # "flavor_split": ColorLayer("flavor_split", left=NA(RULES_BORDER + FLAVOR_SPLIT_OFFSET), # right=NA(WIDTH - RULES_BORDER - FLAVOR_SPLIT_OFFSET), height=NA(2), # bottom=AA(SA("flavor.top"), NA(-5))), # "flavor": RulesText("flavor", MPLANTIN, MPLANTIN_ITAL, RULES_TEXT_SIZE, FC, # RULES_TEXT_SIZE - 4, left=NA(RULES_BORDER), right=NA(WIDTH-RULES_BORDER), # bottom=AA(SA("PT.bottom"), NA(-PT_LOYAL_SIZE), NA(-5))), } text_template = Template("text_temp", *layers.values(), *no_content_reset.values(), left=NA(0), width=NA(WIDTH), top=NA(0), height=NA(HEIGHT)) art_template = Template("art_temp", *art_layers.values(), order=-5, left=NA(0), width=NA(WIDTH), top=NA(0), height=NA(HEIGHT)) name = text_template.get_layer("name") with_art = list(os.listdir(join(RESOURCE_DIR, "art", myset))) cards = [c for c in cards if f"{c['name']}_{c['id']}.jpg" in with_art] cards = [c for c in cards if c['name'] == "Nicol Bolas, Dragon-God"] print(len(cards)) # no_content_reset["copyright"].content = f"™ & © {datetime.now().year} Wizards of the Coast" # no_content_reset["copyright"].content = f"™ & © {datetime.now().year} WOTC" loga = math.ceil(math.log10(len(cards))) temp = Template("template", text_template, art_template, left=NA(0), width=NA(WIDTH), top=NA(0), height=NA(HEIGHT)) temp.mana_image_format = "svg" temp.resource_dir = RESOURCE_DIR max_card_length = max(len(c['name']) for c in cards) row = f"| {{:0{loga}}}/{{:0{loga}}} | {{}} | {{}} | {{:07.3f}} |" total = 0 for i, card in enumerate(sorted(cards, key=lambda x: x['name'])): start_time = time.time() for shadow in ["shadow3", "shadow4"]: l = temp.get_layer(shadow) l.pre_render = None reset_layers = list(layers) + ["art"] for name in reset_layers: layer = temp.get_layer(name) layer.unset_content_and_pre_render() # layer.content = None # layer.pre_render = None if layer.name in card: layer.content = card[layer.name] temp.get_layer("artist_brush").pre_shadow = None if "Creature" in card["types"]: layers["PT"].content = f"{card['power']}/{card['toughness']}" # print(card) # print(repr(temp.get_layer("name").content)) count = 999 sset = [s for s in sets if s['code'] == card['set']] if len(sset) == 1: count = sset[0]["count"] number = card['number'].upper().zfill(3) layers["number"].content = f"{number}/{count:03}" rarity_colors = { "M": "#D15003", "R": "#DFBD6C", "U": "#C8C8C8", "C": FC, "L": FC, "T": FC, } rarity = card["rarity"][0].upper() layers["rarity"].color = rarity_colors[rarity] layers["rarity"].content = rarity rules = "" text_to_use = "text" if card[text_to_use] is not None: rules = card[text_to_use] if card["flavor"] is not None: flavor = "\n".join( [f"<i>{f}</i>" for f in card['flavor'].split('\n')]) if rules == "": rules = flavor else: rules += "\n" + flavor if rules != "": temp.get_layer("rules").content = rules art_path = join(RESOURCE_DIR, "art", card['set'], f"{card['name']}_{card['id']}.jpg") \ .replace("//", "__") temp.get_layer("art").content = art_path if os.path.isfile( art_path) else None temp.update_bounds() render_bg = temp.get_layer("art_temp").render() image = render_bg.clone() if temp.get_layer("art").content is not None: render_text_shadow = temp.get_layer("text_temp").shadow( -4, 4, sigma=2, radius=4, color="Black") image.composite(render_text_shadow, left=0, top=0) render_text = temp.get_layer("text_temp").render() render_text.save(filename="test.png") image.composite(render_text, left=0, top=0) # xb = Bounds(start=BORDER - 10, end=WIDTH - BORDER + 10) # yb = Bounds(start=temp.get_layer("type")["top"] - 10, # end=temp.get_layer("rules")['bottom'] + 10) # exp = render_bg.export_pixels(x=int(xb['start']), y=int(yb['start']), # width=int(xb['full']), height=int(yb['full'])) # with Image(width=int(xb['full']), height=int(yb['full']), # background=Color("Transparent")) as blur_image: # blur_image.import_pixels(width=int(xb['full']), height=int(yb['full']), # channel_map="RGBA", storage="char", data=exp) # with Image(width=blur_image.width, height=blur_image.height, # background=Color("RGBA(0,0,0,0.2)")) as dark: # blur_image.composite(dark, 0, 0) # blur_image.blur(radius=10, sigma=5) # with Image(width=blur_image.width, height=blur_image.height, # background=Color("Black")) as mask: # with Drawing() as ctx: # ctx.fill_color = Color("White") # ctx.rectangle(0, 0, width=mask.width, # height=mask.height, radius=15) # ctx(mask) # apply_mask(blur_image, mask) # image.composite(blur_image, left=int(xb['start']), top=int(yb['start'])) image.save(filename=join( "test_images", "all_render", f"{SAVE_LOCATION}", f"{card['name']}_{card['id']}.jpg").replace("//", "__")) # image.save(filename=join("test_images", "all_render", "Printing", f"{SAVE_LOCATION}", f"{card['name']}_{card['id']}.jpg").replace("//", "__")) # image.save(filename=join("test_images", "all_render", "Printing", f"{SAVE_LOCATION}", f"{card['name']}.jpg").replace("//", "__")) temp.unset_bounds_and_attributes() delta = time.time() - start_time total += delta if delta < .250: color = "green" elif delta < .500: color = "yellow" else: color = "red" print(f"\r{row}".format( i, len(cards) - 1, colored(f"{card['name']: <{max_card_length}}", color), colored(f"{delta:03.3f}", color), total))