def do_it(): nonlocal img if not no_sepia: img = sepia(img) width, height = img.width, img.height if width < 300: width = 300 if height < 200: height = 200 img = resize_keep_aspect_ratio(img, (width, height), resample=Image.BILINEAR) width, height = img.width, img.height tbc = Image.open(os.path.join(TEMPLATES, 'tbc.png')) x = int(width * 0.09) y = int(height * 0.90) tbc = resize_keep_aspect_ratio(tbc, (width * 0.5, height * 0.3), can_be_bigger=False, resample=Image.BILINEAR) if y + tbc.height > height: y = height - tbc.height - 10 img.paste(tbc, (x, y), tbc) return self.save_image(img)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'sheer_heart_attack.png')) img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (1000, 567), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True, background_color='white') template.paste(img, (0, 563), img) return self.save_image(template)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'seeyouagain.png')) img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (360, 300), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) template.paste(img, (800, 915), img) return self.save_image(template)
def do_it(): nonlocal img img = img.convert('RGBA') template = Image.open(os.path.join(TEMPLATES, 'smug_man.png')) w, h = 729, 607 img = resize_keep_aspect_ratio(img, (w, h), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) template.paste(img, (168, 827), img) return self.save_image(template)
def do_it(): nonlocal img img = img.convert('RGBA') im = Image.open(os.path.join(TEMPLATES, 'pucci_bg.png')) overlay = Image.open(os.path.join(TEMPLATES, 'pucci_faded.png')) size = (682, 399) img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, crop_to_size=True, center_cropped=True) x, y = (0, 367) im.paste(img, (x, y), mask=img) im.alpha_composite(overlay) return self.save_image(im)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'zerotwo.png')).convert('RGBA') img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (840, 615), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) img = img.rotate(4, Image.BICUBIC, expand=True) template.alpha_composite(img, (192, 29)) return self.save_image(template)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'josuke.png')) img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (198, 250), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) bg = Image.new('RGBA', (1920, 1080), (0, 0, 0, 0)) bg.paste(img, (1000, 155), img) bg.alpha_composite(template) return self.save_image(bg)
def do_it(): nonlocal img overlay = Image.open(os.path.join(TEMPLATES, 'heaven.png')) base = Image.open(os.path.join(TEMPLATES, 'heaven_base.png')) size = (750, 750) img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, crop_to_size=True, center_cropped=True) img = img.convert('RGBA') x, y = (200, 160) base.paste(img, (x, y), mask=img) base.alpha_composite(overlay) return self.save_image(base)
def do_it(): nonlocal img r = 34.7 x = 6 y = -165 width = 468 height = 439 duration = [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 80, 120, 120, 120, 120, 120, 30, 120, 120, 120, 120, 120, 120, 120, 760, 2000] # Frame timing frames = [frame.copy().convert('RGBA') for frame in ImageSequence.Iterator(Image.open(os.path.join(TEMPLATES, 'jotaro_photo.gif')))] photo = os.path.join(TEMPLATES, 'photo.png') finger = os.path.join(TEMPLATES, 'finger.png') im = Image.open(photo) img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (width, height), resample=Image.BICUBIC, can_be_bigger=False, crop_to_size=True, center_cropped=True, background_color='black') w, h = img.size width, height = (472, 441) coeffs = find_coeffs( [(0, 0), (437, 0), (width, height), (0, height)], [(0, 0), (w, 0), (w, h), (0, h)]) img = img.transform((width, height), Image.PERSPECTIVE, coeffs, Image.BICUBIC) img = img.rotate(r, resample=Image.BICUBIC, expand=True) im.paste(img, box=(x, y), mask=img) finger = Image.open(finger) im.paste(finger, mask=finger) frames[-1] = im if use_webp: # We save room for some colors when not using the shadow in a gif shadow = os.path.join(TEMPLATES, 'photo.png') im.alpha_composite(shadow) kwargs = {} else: # Duration won't work in the save() params when using a gif so I have to do it this way frames[0].info['duration'] = duration kwargs = {'optimize': True} file = BytesIO() frames[0].save(file, format=extension, save_all=True, append_images=frames[1:], duration=duration, **kwargs) if file.tell() > 8000000: raise BotException('Generated image was too big in filesize') file.seek(0) return optimize_gif(file.getvalue())
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'josuke_binoculars.png')) img = img.convert('RGBA') size = (700, 415) img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) bg = Image.new('RGBA', template.size, (255, 255, 255)) bg.paste(img, (50, 460), img) bg.alpha_composite(template) return self.save_image(bg)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'jotaro_photo2.png')) img = img.convert('RGBA') img = resize_keep_aspect_ratio(img, (305, 440), can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) img = img.rotate(5, Image.BICUBIC, expand=True) bg = Image.new('RGBA', template.size) bg.paste(img, (460, 841), img) bg.alpha_composite(template) return self.save_image(bg)
def do_it(): nonlocal img im = Image.open(os.path.join(TEMPLATES, 'jotaro_smile.png')) img = img.convert('RGBA') i = Image.new('RGBA', im.size, 'black') size = (337, 350) img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, crop_to_size=True, center_cropped=True, resample=Image.BICUBIC) img = img.rotate(13.7, Image.BICUBIC, expand=True) x, y = (207, 490) i.paste(img, (x, y), mask=img) i.paste(im, mask=im) return self.save_image(i)
def do_it(): nonlocal img x, y = 9, 10 w, h = 854, 480 template = Image.open(path) img = resize_keep_aspect_ratio(img, (w, h), can_be_bigger=False, resample=Image.BILINEAR) new_w, new_h = img.width, img.height if new_w != w: x += int((w - new_w)/2) if new_h != h: y += int((h - new_h) / 2) img = img.convert("RGBA") template.paste(img, (x, y), img) return self.save_image(template)
def do_it(): nonlocal img template = Image.open(os.path.join(TEMPLATES, 'whatagreatview.png')) img = img.convert('RGBA') size = (868, 607) if stretch: img = img.resize(size, resample=Image.BICUBIC) else: img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, resample=Image.BICUBIC, crop_to_size=True, center_cropped=True) bg = Image.new('RGBA', template.size, 'white') bg.paste(img, (212, 608), img) bg.alpha_composite(template) return self.save_image(bg)
def do_it(): nonlocal img path = os.path.join(TEMPLATES, 'is_it_a_trap.png') path2 = os.path.join(TEMPLATES, 'is_it_a_trap_layer.png') img = img.convert("RGBA") x, y = 820, 396 w, h = 355, 505 rotation = -22.5 img = resize_keep_aspect_ratio(img, (w, h), can_be_bigger=False, resample=Image.BILINEAR) img = img.rotate(rotation, expand=True, resample=Image.BILINEAR) x_place = x - int(img.width / 2) y_place = y - int(img.height / 2) template = Image.open(path) template.paste(img, (x_place, y_place), img) layer = Image.open(path2) template.paste(layer, (0, 0), layer) return self.save_image(template)
def do_it(): nonlocal img im = Image.open(os.path.join(TEMPLATES, 'jotaro_smile.png')) img = img.convert('RGBA') i = Image.new('RGBA', im.size, 'black') size = (max(img.size), max(img.size)) img = resize_keep_aspect_ratio(img, size, can_be_bigger=False, crop_to_size=True, center_cropped=True) coeffs = find_coeffs([(0, 68), (358, 0), (410, 335), (80, 435)], [(0, 0), (img.width, 0), size, (0, img.height)]) img = img.transform((410, 435), Image.PERSPECTIVE, coeffs, Image.BICUBIC) x, y = (178, 479) i.paste(img, (x, y), mask=img) i.paste(im, mask=im) return self.save_image(i)
async def stand_gen(self, ctx, stand, user, image=None, advanced=None): """Generate a stand card. Arguments are stand name, user name and an image Image can be an attachment or a link. Passing -advanced as the last argument will enable advanced mode which gives the ability to tune some numbers. Use quotes for names that have spaces e.g. {prefix}{name} "Star Platinum" "Jotaro Kujo" [image] """ author = ctx.author name = author.name channel = ctx.channel stand = self._standify_text(stand, 2) user = '******' + user stand = '[STAND NAME]\n' + stand size = (1100, 700) shift = 800 if advanced is None and image == '-advanced': image = None advanced = True elif advanced is not None: advanced = advanced.strip() == '-advanced' if advanced: await ctx.send('`{}` Advanced mode activated'.format(name), delete_after=20) image_ = await get_image_from_message(ctx, image) img = await image_from_url(image_, self.bot.aiohttp_client) if img is None: image = image_ if image is None else image return await ctx.send( '`{}` Could not extract image from {}. Stopping command'. format(name, image)) m_, msg = await self.subcommand( ctx, '`{}` Give the stand **stats** in the given order ranging from **A** to **E** ' 'separated by **spaces**.\nDefault value is E\n`{}`'.format( name, '` `'.join(POWERS)), delete_after=120, author=author, channel=channel) await m_.delete() if msg is None: await ctx.send('{} cancelling stand generation'.format(author.name) ) return stats = msg.content.split(' ') stats = dict(zip_longest(POWERS, stats[:6])) m_, msg = await self.subcommand( ctx, '`{}` Use a custom background by uploading a **picture** or using a **link**. ' 'Posting something other than an image will use the **generated background**' .format(name), delete_after=120, author=author, channel=channel) bg = get_picture_from_msg(msg) await m_.delete() if bg is not None: try: bg = bg.strip() bg = await image_from_url(bg, self.bot.aiohttp_client) dominant_color = get_color(bg) color = Color(rgb=list(map(lambda c: c / 255, dominant_color))) bg = resize_keep_aspect_ratio(bg, size, True) except Exception: logger.exception('Failed to get background') await ctx.send( '`{}` Failed to use custom background. Using generated one' .format(name), delete_after=60.0) bg = None if bg is None: color = None pattern = random.choice(GeoPattern.available_generators) m_, msg = await self.subcommand( ctx, "`{}` Generating background. Select a **pattern** and **color** separated by space. " "Otherwise they'll will be randomly chosen. Available patterns:\n" '{}'.format(name, '\n'.join(GeoPattern.available_generators)), delete_after=120, channel=channel, author=author) await m_.delete() if msg is None: await ctx.send('`{}` Selecting randomly'.format(name), delete_after=20) if msg is not None: msg = msg.content.split(' ') pa, c = None, None if len(msg) == 1: pa = msg[0] elif len(msg) > 1: pa, c = msg[:2] if pa in GeoPattern.available_generators: pattern = pa else: await ctx.send( '`{}` Pattern {} not found. Selecting randomly'.format( name, pa), delete_after=20) try: color = Color(c) except: await ctx.send('`{}` {} not an available color'.format( name, c), delete_after=20) bg, color = create_geopattern_background(size, stand + user, generator=pattern, color=color) if advanced: m_, msg = await self.subcommand( ctx, '`{}` Input color value change as an **integer**. Default is {}. ' 'You can also input a **color** instead of the change value. ' 'The resulting color will be used in the stats circle'.format( name, shift), delete_after=120, channel=channel, author=author) try: shift = int(msg.content.split(' ')[0]) except ValueError: try: color = Color(msg.content.split(' ')[0]) shift = 0 except: await ctx.send( '`{}` Could not set color or color change int. Using default values' .format(name), delete_after=15) await m_.delete() bg_color = Color(color) shift_color( color, shift ) # Shift color hue and saturation so it's not the same as the bg fig, _ = self.create_stats_circle(color=color.get_hex_l(), bg_color=bg_color, **stats) path = os.path.join(IMAGES_PATH, 'stats.png') with self.stat_lock: try: fig.savefig(path, transparent=True) stat_img = Image.open(path) except: logger.exception('Could not create image') return await ctx.send( '`{}` Could not create picture because of an error.'. format(name)) plt.close(fig) stat_img = stat_img.resize( (int(stat_img.width * 0.85), int(stat_img.height * 0.85)), Image.BILINEAR) full = Image.new('RGBA', size) x, y = (-60, full.height - stat_img.height) stat_corner = (x + stat_img.width, y + stat_img.height) full.paste(stat_img, (x, y, *stat_corner)) font = ImageFont.truetype(os.path.join('M-1c', 'mplus-1c-bold.ttf'), 40) text = create_glow( create_shadow( create_text(stand, font, '#FFFFFF', (int(full.width * 0.75), int(y * 0.8)), (10, 10)), 80, 3, 2, 4), 3).convert('RGBA') full.paste(text, (20, 20), text) text2 = create_glow( create_shadow( create_text(user, font, '#FFFFFF', (int( (full.width - stat_corner[0]) * 0.8), int( full.height * 0.7)), (10, 10)), 80, 3, 2, 4), 3).convert('RGBA') text2.load() if img is not None: im = trim_image(img) m_, msg = await self.subcommand( ctx, '`{}` Try to automatically remove background (y/n)? ' 'This might f**k the picture up and will take a moment'.format( name), author=author, channel=channel, delete_after=120, check=y_n_check) await m_.delete() if msg and msg.content.lower() in ['y', 'yes']: kwargs = {} if advanced: m_, msg = await self.subcommand( ctx, '`{}` Change the arguments of background removing. Available' ' arguments are `blur`, `canny_thresh_1`, `canny_thresh_2`, ' '`mask_dilate_iter`, `mask_erode_iter`. ' 'Accepted values are integers.\nArguments are added like this ' '`-blur 30 -canny_thresh_2 50`. All arguments are optional' .format(name), channel=channel, author=author, delete_after=140) await m_.delete() await channel.trigger_typing() if msg is not None: try: kwargs = self.parser.parse_known_args( msg.content.split(' '))[0].__dict__ except: await ctx.send( '`{}` Could not get arguments from {}'.format( name, msg.content), delete_after=20) try: im = await self.bot.loop.run_in_executor( self.bot.threadpool, partial(remove_background, im, **kwargs)) except Exception: logger.exception('Failed to remove bg from image') await ctx.send( '`{}` Could not remove background because of an error'. format(name), delete_after=30) box = (500, 600) im = resize_keep_aspect_ratio(im, box, can_be_bigger=False) im = create_shadow(im, 70, 3, -22, -7).convert('RGBA') full.paste( im, (full.width - im.width, int( (full.height - im.height) / 2)), im) await channel.trigger_typing() full.paste(text2, (int( (full.width - stat_corner[0]) * 0.9), int(full.height * 0.7)), text2) bg.paste(full, (0, 0), full) file = BytesIO() bg.save(file, format='PNG') file.seek(0) await ctx.send(file=discord.File(file, filename='stand_card.png'))