diff --git a/Little Story.ttf b/Little Story.ttf new file mode 100644 index 0000000..0d9b502 Binary files /dev/null and b/Little Story.ttf differ diff --git a/pillow_fight.py b/pillow_fight.py index 5e364bd..76425ef 100644 --- a/pillow_fight.py +++ b/pillow_fight.py @@ -1,3 +1,4 @@ +import math from PIL import Image from PIL import ImageDraw from PIL import ImageFont @@ -5,21 +6,22 @@ from PIL import ImageOps import requests import io from image_utils import ImageText - -LEFT_MARGIN_COLUMN = 20 -CONTENT_COLUMN = 300 -MIDDLE_MARGIN_COLUMN = 80 -RIGHT_MARGIN_COLUMN = LEFT_MARGIN_COLUMN -TOP_MARGIN_ROW = 80 -IMAGE_ROW = 300 -MIDDLE_MARGIN_ROW = 20 -TEXT_ROW = 100 -BOTTOM_MARGIN_ROW = 200 - -total_image_size_x = 2*CONTENT_COLUMN + LEFT_MARGIN_COLUMN + RIGHT_MARGIN_COLUMN + MIDDLE_MARGIN_COLUMN -total_image_size_y = TOP_MARGIN_ROW + IMAGE_ROW + MIDDLE_MARGIN_ROW + TEXT_ROW + BOTTOM_MARGIN_ROW +from os.path import exists def create_soy_vs_chad_meme(emoji1, emoji2, caption1, caption2): + LEFT_MARGIN_COLUMN = 20 + CONTENT_COLUMN = 300 + MIDDLE_MARGIN_COLUMN = 80 + RIGHT_MARGIN_COLUMN = LEFT_MARGIN_COLUMN + TOP_MARGIN_ROW = 80 + IMAGE_ROW = 300 + MIDDLE_MARGIN_ROW = 20 + TEXT_ROW = 100 + BOTTOM_MARGIN_ROW = 200 + + total_image_size_x = 2*CONTENT_COLUMN + LEFT_MARGIN_COLUMN + RIGHT_MARGIN_COLUMN + MIDDLE_MARGIN_COLUMN + total_image_size_y = TOP_MARGIN_ROW + IMAGE_ROW + MIDDLE_MARGIN_ROW + TEXT_ROW + BOTTOM_MARGIN_ROW + left_image = get_emoji_from_rdrama(emoji1) right_image = get_emoji_from_rdrama(emoji2) @@ -41,7 +43,116 @@ def create_soy_vs_chad_meme(emoji1, emoji2, caption1, caption2): add_text(base, caption2, (CONTENT_COLUMN, TEXT_ROW), (LEFT_MARGIN_COLUMN+CONTENT_COLUMN+MIDDLE_MARGIN_COLUMN, TOP_MARGIN_ROW+IMAGE_ROW+MIDDLE_MARGIN_ROW)) return add_watermark(base) +class WebcomicPanel(): + PANEL_SIZE = 400 + FONT = "Little Story.ttf" + + def __init__(self): + pass + + def create_image(self) -> Image: + return Image.new(mode="RGB", size=(self.PANEL_SIZE,self.PANEL_SIZE), color=(255,255,255)) + +class OneCharacterWebcomicPanel(WebcomicPanel): + def __init__(self, emoji, caption): + self.emoji = emoji + self.caption = caption + + def create_image(self) -> Image: + base = super().create_image() + panel_size_x, panel_size_y = base.size + + # We put marsey in the bottom left quadrant + emoji_region_x_size = int(panel_size_x/2) + emoji_region_y_size = int(panel_size_y/2) + emoji_placement_position_x = 0 + emoji_placement_position_y = int(panel_size_y/2) + emoji = get_emoji_from_rdrama(self.emoji) + center_and_paste(base, emoji, (emoji_placement_position_x, emoji_placement_position_y), (emoji_region_x_size, emoji_region_y_size)) + + # We put the text in the top half of the panel. + text_region_x_size = int(panel_size_x) + text_region_y_size = int(panel_size_y/2) + add_text(base, self.caption, (text_region_x_size, text_region_y_size), (0,0), font=super().FONT) + + return add_border_to_image(base) + +class TwoCharacterWebcomicPanel(WebcomicPanel): + def __init__(self, left_emoji, left_caption, right_emoji, right_caption): + self.left_emoji = left_emoji + self.left_caption = left_caption + self.right_emoji = right_emoji + self.right_caption = right_caption + + def create_image(self) -> Image: + base = super().create_image() + panel_size_x, panel_size_y = base.size + + # We put the left marsey in the bottom left quadrant + left_emoji_region_x_size = int(panel_size_x/2) + left_emoji_region_y_size = int(panel_size_y/2) + left_emoji_placement_position_x = 0 + left_emoji_placement_position_y = int(panel_size_y/2) + left_emoji = get_emoji_from_rdrama(self.left_emoji) + center_and_paste(base, left_emoji, (left_emoji_placement_position_x, left_emoji_placement_position_y), (left_emoji_region_x_size, left_emoji_region_y_size)) + + # We put the right marsey in the bottom right quadrant + right_emoji_region_x_size = int(panel_size_x/2) + right_emoji_region_y_size = int(panel_size_y/2) + right_emoji_placement_position_x = int(panel_size_x/2) + right_emoji_placement_position_y = int(panel_size_y/2) + right_emoji = get_emoji_from_rdrama(self.right_emoji) + center_and_paste(base, right_emoji, (right_emoji_placement_position_x, right_emoji_placement_position_y), (right_emoji_region_x_size, right_emoji_region_y_size)) + + #Each text caption will get 5/8 of the width, and 1/4 of the height of the panel. + #The left caption will be all the way to the left. The right caption will be 3/8 to the right. + + CAPTION_UNITS = 5 + CAPTION_DIVISOR = 8 + + # We put the text in the top half of the panel. + left_text_region_x_size = int(CAPTION_UNITS*(panel_size_x/CAPTION_DIVISOR)) + left_text_region_y_size = int(panel_size_y/4) + left_text_region_x_position = 0 + left_text_region_y_position = 0 + add_text(base, self.left_caption, (left_text_region_x_size, left_text_region_y_size), (left_text_region_x_position,left_text_region_y_position), font=super().FONT) + + # We put the text in the top half of the panel. + right_text_region_x_size = int(CAPTION_UNITS*(panel_size_x/CAPTION_DIVISOR)) + right_text_region_y_size = int(panel_size_y/4) + right_text_region_x_position = int((CAPTION_DIVISOR-CAPTION_UNITS)*(panel_size_x/8)) + right_text_region_y_position = int(panel_size_y/4) + add_text(base, self.right_caption, (right_text_region_x_size, right_text_region_y_size), (right_text_region_x_position,right_text_region_y_position), font=super().FONT) + + return add_border_to_image(base) + +class TitleCardWebcomicPanel(WebcomicPanel): + def __init__(self, caption): + self.caption = caption + + def create_image(self) -> Image: + base = super().create_image() + + add_text(base, self.caption, base.size, (0,0), font=super().FONT) + + return add_border_to_image(base) + +def create_webcomic(layout : 'list[WebcomicPanel]'): + assumed_panel_x_size, assumed_panel_y_size = layout[0].create_image().size + total_image_x_size = assumed_panel_x_size * 2 + total_image_y_size = assumed_panel_x_size * math.ceil(len(layout)/2) + + image = Image.new(mode="RGB", size=(total_image_x_size, total_image_y_size), color=(255,255,255)) + for i in range(len(layout)): + panel = layout[i] + x = i%2 + y = math.floor(i/2) + image.paste(panel.create_image(), (x*assumed_panel_x_size, y*assumed_panel_y_size)) + return add_watermark(image) + def add_text(base : Image, caption : str, region_size : tuple[int, int], coordinates : tuple[int, int], font : str= "arial.ttf"): + if caption == "": + return region_x_size, region_y_size = region_size line_image = ImageText((region_x_size, region_y_size)) line_image.fill_text_box((0,0), caption, region_x_size, region_y_size, font_filename=font) @@ -53,7 +164,7 @@ def add_watermark(image : Image): base = Image.new(mode="RGB", size=(image_size_x, image_size_y + WATERMARK_HEIGHT), color=(255,255,255)) base.paste(image) - marsey = get_emoji_from_rdrama("marseybangfast") + marsey = get_emoji_from_rdrama("marseyjamming") marsey = ImageOps.contain(marsey, (WATERMARK_HEIGHT, WATERMARK_HEIGHT)) base.paste(marsey, (0, image_size_y), marsey) @@ -65,6 +176,8 @@ def add_watermark(image : Image): return base def center_and_paste(base : Image, to_paste : Image, coordinates: tuple[int, int], box_size : tuple[int, int]): + to_paste = ImageOps.contain(to_paste, box_size) + image_size_x, image_size_y = to_paste.size box_size_x, box_size_y = box_size @@ -80,6 +193,19 @@ def center_and_paste(base : Image, to_paste : Image, coordinates: tuple[int, int base.paste(to_paste, (x, y), to_paste) +def add_border_to_image(image : Image, thickness : int = 5): + # image_draw = ImageDraw.Draw(image) + # image_x_size, image_y_size = image.size + # inner_rectangle_x_size, inner_rectangle_y_size = image_x_size - 2*thickness, image_y_size - 2*thickness + # image_draw.rectangle([(0,0),(image_x_size, image_y_size)], fill="black") + # image_draw.rectangle([(thickness, thickness),(image_x_size-thickness, image_y_size-thickness)], fill="white") + inner_image_x_size, inner_image_y_size = image.size + outer_image_x_size, outer_image_y_size = inner_image_x_size + 2*thickness, inner_image_y_size + 2*thickness + outside_image = Image.new(mode="RGB", size=(outer_image_x_size,outer_image_y_size), color=(0,0,0)) + + outside_image.paste(image, (thickness, thickness)) + return outside_image + def wrap_text_for_font(text, region_size, font_size) -> Image: image = Image.new(mode="RGB", size=region_size, color=(255,255,255)) imageDraw = ImageDraw.ImageDraw() @@ -91,7 +217,12 @@ def get_emoji_from_rdrama(emoji_name): if '!' in emoji_name: cleaned_emoji_name = cleaned_emoji_name.replace("!", "") should_flip = True - image = get_image_file_from_url(f"https://www.rdrama.net/e/{cleaned_emoji_name}.webp") + + if (exists(f"emoji_cache/{cleaned_emoji_name}.webp")): + image = Image.open(f"emoji_cache/{cleaned_emoji_name}.webp") + else: + image = get_image_file_from_url(f"https://www.rdrama.net/e/{cleaned_emoji_name}.webp") + image.save(f"emoji_cache/{cleaned_emoji_name}.webp") if should_flip: image = ImageOps.mirror(image) return image @@ -102,14 +233,13 @@ def get_image_file_from_url(url): im = Image.open(image_file) return im -#get_emoji_from_rdrama("zoomersoy").show() +#create_soy_vs_chad_meme("bigsmilesoyjak", "!marseyshooting", "I have fun new toys and games for your children", "Die").show() -create_soy_vs_chad_meme("bigsmilesoyjak", "!marseyshooting", "I have fun new toys and games for your children", "Die").show() - -# base_image = Image.new(mode="RGB", size=(1000,1000), color=(255,255,255)) -# marppy_image = Image.open("marppy.webp") -# base_image.paste(marppy_image, (0,0), marppy_image) -# I1 = ImageDraw.Draw(base_image) -# font = ImageFont.truetype("impact.ttf", 65) -# I1.text((300, 0), "GO HOME GAMER GIRL", font=font, fill=(255, 0, 0)) -# base_image.show() \ No newline at end of file +create_webcomic([ + TwoCharacterWebcomicPanel("soyjak", "Black people deserve the rope", "marseyconfused", "Why?"), + TwoCharacterWebcomicPanel("seethejak", "Because they are degenerate!!!", "marseysmug", "Kinda like you?"), + OneCharacterWebcomicPanel("soycry", "No!! I am a pure aryan white boy and I am special Hitler told me so, so fuck off you nigger cunt. God I hate you so much, if I commit suicide its gonna be your fault, fuck you"), + TitleCardWebcomicPanel("One Hour Later..."), + TwoCharacterWebcomicPanel("marseytombstone", "", "!marseycry", "He had so much to live for"), + OneCharacterWebcomicPanel("marseylaugh", "Just Kidding!") +]).show() \ No newline at end of file