def test_font_set(fx_asset): with Image(width=144, height=192, background=Color('#1e50a2')) as img: font = Font( path=str(fx_asset.join('League_Gothic.otf')), color=Color('gold'), size=12, antialias=False ) img.font = font assert img.font_path == font.path assert img.font_size == font.size assert img.font_color == font.color assert img.antialias == font.antialias assert img.font == font fontStroke = Font( path=str(fx_asset.join('League_Gothic.otf')), stroke_color=Color('ORANGE'), stroke_width=1.5 ) img.font = fontStroke assert img.stroke_color == fontStroke.stroke_color assert img.stroke_width == fontStroke.stroke_width img.font_color = 'gold' assert img.font_color == Color('gold') img.stroke_color = 'gold' assert img.stroke_color == Color('gold') fontColor = Font( path=str(fx_asset.join('League_Gothic.otf')), color='YELLOW', stroke_color='PINK' ) img.font = fontColor assert img.font_color == Color('YELLOW') assert img.stroke_color == Color('PINK')
async def chad_magic(self, ctx, response): #Initialize Variables text = await self.pull_messages(ctx, response) x = 200 #The x coord of the caption y = 150 #The y coord of the caption width = 500 #the width of the caption height = 225 #the height of the caption font = Font('/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf') #Random font that ill use just for now #Determine the response from the command if response.lower() == 'yes': #Load the Yes template if yes is a parameter template = 'data/chadtemplateyes.png' elif response.lower() == 'no': #Load the No template if no is a parameter template = 'data/chadtemplateno.png' else: #If not load the normal template template = 'data/chadtemplate.png' #Create the image with Image(filename=template) as img: #Load the original image with img.clone() as clonedimage: #Clone the image for manipulation if template == 'data/chadtemplate.png': #If the default option gets loaded up clonedimage.caption(text[0], x, y, width, height, font) #Add the caption to the image clonedimage.caption(text[1], x+1085, y+700, width, height, font) #Add the caption response to the image else: #If the default option is not loaded clonedimage.caption(text[1], x, y, width, height, font) #Add the caption to the image clonedimage.save(filename='data/response.png') #Save the file.
def make_trade_offer(self, left_text: str="", right_text: str=""): # Load image, then work on its clone self.load_image(os.path.join(os.path.dirname(__file__), "trade_template.jpg")) img = self.wand_image.clone() # Set font img.font = Font(path=self.font_path, color='white', antialias=True, stroke_width=2, stroke_color='black') # Add text on the left img.caption( left_text, gravity='north', left=5, top=181, width=254, height=171 ) # Add text on the right img.caption( right_text, gravity='north', left=322, top=181, width=254, height=171 ) # Close current object's image and load current as new one self.close_image() self.wand_image=img
def placeholder_it(filename, message=None): bg = '#' + request.args.get('bg', 'fff') filename = filename.lower() basename, ext = os.path.splitext(filename) ext = ext.strip(".") width, height = basename.split("x") width, height = int(width), int(height) content_type = 'image/{}'.format(normalize_mimetype(ext)) if ext in ('jpg', 'jpeg'): fmt = 'jpg' elif ext == 'png': fmt = 'png' else: return "I don't know how to handle format .{} files".format(ext), 404 if message: text = message else: text = '{}x{}'.format(width, height) min_font_ratio = width / (len(text) * 12.0) size = max(16 * (height / 100), 16 * min_font_ratio) font = Font(path='fonts/Inconsolata-dz-Powerline.otf', size=size) c = Color(bg) if fmt == "jpg" else None with Image(width=width, height=height, background=c) as image: image.caption(text, left=0, top=0, font=font, gravity="center") buff = image_to_buffer(image, fmt=ext, compress=False) buff.seek(0) return buff.read(), 200, { "Content-Type": content_type, "Cache-Control": CACHE_CONTROL }
def create_sentence_image(sentence_index: int, text: str): OUTPUT_FILE = os.path.join('content', 'images', 'sentences', f'{sentence_index}-sentence.png') TEMPLATE_SETTINGS = { 0: { 'width': 1920, 'height': 400, 'gravity': 'center' }, 1: { 'width': 1920, 'height': 1080, 'gravity': 'center' }, 2: { 'width': 800, 'height': 1080, 'gravity': 'west' }, 3: { 'width': 1920, 'height': 400, 'gravity': 'center' }, 4: { 'width': 1920, 'height': 1080, 'gravity': 'center' }, 5: { 'width': 800, 'height': 1080, 'gravity': 'west' }, 6: { 'width': 1920, 'height': 400, 'gravity': 'center' } } image_width = TEMPLATE_SETTINGS[sentence_index].get('width') image_height = TEMPLATE_SETTINGS[sentence_index].get('height') with Image(width=image_width, height=image_height) as sentence_image: sentence_image.gravity = TEMPLATE_SETTINGS[sentence_index].get('gravity') sentence_image.caption( text, font=Font( 'Helvetica, sans-serif', color=Color('white'), stroke_color=Color('#696969'), stroke_width=2 ) ) sentence_image.save(filename=OUTPUT_FILE) print(f'> [Video Robot] Sentence image created: {OUTPUT_FILE}')
def create_row(imgs, offsets, gap, fixed_width=0, caption=None, caption_offset=(0, 0)): row_width = 0 i = 0 row_height = 0 for img in imgs: if isinstance(img, Image): row_width += img.width + gap row_height = max(img.height, row_height) else: row_width += offsets[i][0] + gap i += 1 if fixed_width: row_width = fixed_width row = Image(width=row_width, height=row_height) i = 0 x = 0 for img in imgs: if isinstance(img, Image): row.composite(img, left=x + offsets[i], top=(row_height - img.height) / 2) x += img.width + offsets[i] + gap else: (offset_x, offset_y, width, font) = offsets[i] row.caption(img, left=x + offset_x, top=offset_y, width=250, height=250, font=font) x += width + gap i += 1 if caption: caption_font = Font( path="%s/source-code-pro/SourceCodePro-Medium.otf" % args.fonts, size=14) row_w_caption = Image(width=row_width, height=row_height + 20) row_w_caption.caption(caption, left=caption_offset[0], top=caption_offset[1], width=1450, height=50, font=caption_font) row_w_caption.composite(row, left=0, top=20) return row_w_caption else: return row
def caption(self, input_filename, output_filename, caption): with Image(filename=input_filename) as img: with img.clone() as clone: font_path = Path( Captioner.DEFAULT_FONT_PATH).resolve().as_posix() font_color = Color(self._font_folor) if self._best_fit: font = Font(path=font_path, color=font_color, stroke_color=font_color) else: font_size = self._calculate_font_size(img.height) font = Font(path=font_path, color=font_color, stroke_color=font_color, size=font_size) clone.caption(text=caption, gravity=self._gravity, font=font) clone.save(filename=output_filename)
def write_banner(): img = Image(width=250, height=100, pseudo='plasma:fractal') f = Font(path='/cgi-bin/sarial.ttf', size=32, color="#d33682") img.caption(text='ibbb.me', font=f, gravity='south_east') img.save(filename='/var/www/cgi-bin/files/banner.png') print('<div class="banner">' '<center>' '<img src="/cgi-bin/files/banner.png">' '</center>' '</div>')
def create_sentence_image(idx_sentence, text): if not ga.existe_diretorio(f'./assets/img/{idx_sentence}-original.png'): print(f'"./assets/img/{idx_sentence}-original.png" nao foi encontrado') return output_file = f'./assets/img/{idx_sentence}-sentence.png' template_conf = { '0': { 'width': 1920, 'height': 400, 'gravity': 'center' }, '1': { 'width': 1920, 'height': 1080, 'gravity': 'center' }, '2': { 'width': 800, 'height': 1080, 'gravity': 'west' }, '3': { 'width': 1920, 'height': 400, 'gravity': 'center' }, '4': { 'width': 1920, 'height': 1080, 'gravity': 'center' }, '5': { 'width': 800, 'height': 1080, 'gravity': 'west' }, '6': { 'width': 1920, 'height': 400, 'gravity': 'center' } } current_sent = template_conf[str(idx_sentence)] with Image(width=current_sent['width'], height=current_sent['height']) as img: img.gravity = current_sent['gravity'] img.background_color = Color('transparent') img.text_kerning = -1 img.caption(text, font=Font(path='./assets/font/Roboto-Regular.ttf', color=Color('white'))) img.save(filename=output_file)
def test_setfont(fx_asset): with Image(width=144, height=192, background=Color('#1e50a2')) as img: font = Font(path=str(fx_asset.join('League_Gothic.otf')), color=Color('gold'), size=12, antialias=False) img.font = font assert img.font_path == font.path assert img.font_size == font.size assert img.font_color == font.color assert img.font_antialias == font.antialias assert img.font == font
def generate_thumbnail(self): self.thumbnail_uuid = hash_file(self.file_path) + ".jpg" with Image(background=Color('#EEEEEE'), width=256, height=256) as bg: with open(self.file_path, encoding='utf-8', errors='ignore') as f: text = f.read() if len(text) > 512: text = text[0:512] font = Font(path="Arial", size=20, color=Color('#333333')) bg.caption(text=text, left=10, top=10, font=font) bg.save( filename=os.path.join(self.dir_path, self.thumbnail_uuid))
def test_caption(fx_asset): with Image(width=144, height=192, background=Color('#1e50a2')) as img: font = Font(path=str(fx_asset.join('League_Gothic.otf')), color=Color("gold"), size=12, antialias=False) img.caption('Test message', font=font, left=5, top=144, width=134, height=20, gravity='center')
def create_sentence_image(self, keyword, sentence): idx = randrange(0, 3) font = Font(path='tests/assets/League_Gothic.otf', size=64, color='white') sentence_image = IMAGES_DATA_PATH.joinpath(self.search_term + '_' + keyword + '_sentences.png') with Image(width=self.template[idx]['width'], height=self.template[idx]['height'], background='transparent') as original: original.caption(sentence, font=font, gravity=self.template[idx]['gravity']) original.save(filename=str(sentence_image))
def add_caption(self, top_text: str="", bottom_text: str=""): img = self.wand_image.clone() # Bar height barHeight = min(int(0.2 * img.height), int(0.2 * img.width)) # Height to add to image to include bars heightToAdd = 0 if top_text: heightToAdd += barHeight if bottom_text: heightToAdd += barHeight with Image(width=img.width, height=img.height+heightToAdd, background='black') as canvas: # Set used font canvas.font = Font(path=self.font_path, color='white', antialias=True) # Paste original image (separate cases whether top text is or is not included) if top_text: canvas.composite(img, 0, barHeight) else: canvas.composite(img, 0, 0) # Render top text if top_text: canvas.caption(top_text, gravity='center', left=0, top=0, width=canvas.width, height=barHeight) # Render bottom text if bottom_text: # Calculate position of bottom bar if top_text: BottomBarStartY = img.height + barHeight else: BottomBarStartY = img.height canvas.caption(bottom_text, gravity='center', left=0, top=BottomBarStartY, width=canvas.width, height=barHeight) self.close_image() self.wand_image = canvas.clone()
def addCaption(f, date, w, h): with Image(filename=f) as theImage: captionHeight=int(theImage.height/8) bg = Color('#0008') with Image(width=w+2, height=captionHeight+2, background=bg) as canvas: with Drawing() as context: mystring = "hackathon! taken " + date.strftime('%-I:%M%p on %A, %B %-d, %Y') font = Font(path="/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf") context.fill_color = Color('white') context.font_style = 'italic' context.font_size = 36 context.text(x=130, y=(2*captionHeight/3)+2, body=mystring) context(canvas) theImage.watermark(image=canvas, transparency=0.0, left=0, top=theImage.height-captionHeight) with Image(filename="little_n.png") as logo: theImage.watermark(image=logo, transparency=0.0, left=9, top=theImage.height-logo.height-4) theImage.save(filename=f)
def generate_profile_pic(save_path, name): words = name.split() letters = [word[0] for word in words] initials = "".join(letters) colors = ["#c75650", "#d67a27", "#7e6ccf", "#4eb331", "#2ea4ca"] with wandImage(width=756, height=756, background=Color(random.choice(colors))) as img: left, top, width, height = 200, 265, 340, 240 with Drawing() as context: font = Font(font_path, color="white") context(img) img.caption(initials, left=left, top=top, width=width, height=height, font=font, gravity="center") img.save(filename=save_path) return save_path
def make_expanding_brain(self, strings): if len(strings) > 6: raise IndexError("Too many arguments passed, max is 6.") # Load meme template self.load_image(os.path.join(os.path.dirname(__file__), "expanding_meme_template.jpg")) img = self.wand_image.clone() img.font = Font(path=self.font_path, color='black', antialias=True) # Calculate final image height # Template's every row's heights rows_heights = [230, 230, 230, 232, 232, 230] rows_count = len(strings) # Setup final image height final_height = 0 for i in range(rows_count): final_height += rows_heights[i] # TODO: pink background is for testing purposes, remove afetrwards with Image(width=img.width, height=final_height, background='pink') as canvas: canvas.font = img.font # Use same font as aboce canvas.composite(img, 0, 0) # Add original image # Iterate through strings to add caption to every row current_height = 16 # Height at which current caption will be printed for i, string in enumerate(strings): canvas.caption(string, gravity='center', left=16, top=current_height, width=382, height=200) current_height += rows_heights[i] # Close current object's image if exists self.close_image() # And save as new image self.wand_image = canvas.clone()
def generate_jpg(jpg_file, split_jpgs_path, bates_number, confidentiality): # generate jpg from input parameters # generate bates number / confidentiality designations caption1 = bates_number caption2 = "CONFIDENTIAL BUSINESS INFORMATION - SUBJECT TO PROTECTIVE ORDER" # use wand image library to edit jpg with Image(filename=jpg_file) as img: height = img.height width = img.width # 10 point arial font = 1/80th the height of the image # 12 point arial font = 1/66th the height of the image # different font sizes for portrait vs landscape; detected by dividing height by width if (height / width) > 1: nfh = 80 # nfh = number of font heights (i.e. letters that fit from top to bottom of screen) else: nfh = 45 # nfh = number of font heights (i.e. letters that fit from top to bottom of screen) # use nfh to calculate height of font in pixels font_height = height / nfh # select font font = Font(path='Arial.ttf', size=font_height, color=Color("black")) # draw bates caption img.caption(caption1, font=font, gravity="south_east") # draw confidentiality caption if confidentiality == True: img.caption(caption2, font=font, gravity="south_west") # save image (overwrite old) img.save(filename=jpg_file) # rename image with bates number new_filename = f"{bates_number}.jpg" os.rename(jpg_file, f"{split_jpgs_path}/{new_filename}") return
def make_drake(self, top_text: str="", bottom_text: str=""): self.load_image(os.path.join(os.path.dirname(__file__), "drake_template.jpg")) img = self.wand_image.clone() img.font = Font(path=self.font_path, color='black', antialias=True) img.caption( top_text, gravity='center', left=505, top=12, width=460, height=360 ) img.caption( bottom_text, gravity='center', left=505, top=400, width=460, height=360 ) self.close_image() self.wand_image = img
def fit_text(img, filename, text, name): text = "«" + text + "»" name = "— " + name with wandImage(blob=img) as canvas: text_left, text_top, text_width, text_height = 475, 50, 675, 410 name_left, name_top, name_width, name_height = 530, 460, 570, 50 with Drawing() as context: font = Font(font_path, color="white") context(canvas) canvas.caption(text, left=text_left, top=text_top, width=text_width, height=text_height, font=font, gravity="center") canvas.caption(name, left=name_left, top=name_top, width=name_width, height=name_height, font=font, gravity="center") canvas.save(filename=path + filename + ".jpg")
if i == 3: return img[:, intensity:] print args if not os.path.isdir('./frames'): os.mkdir('./frames') with Image(file=open(args.image)) as img: gif = img.convert('gif') for x in range(4): frame = gif.clone() if args.wiggle: frame = cropshift(x, frame, int(args.intensity) if args.intensity else 20) color = Color('#FFFFFF') if args.flash_text and (x == 1 or x == 3): color = Color('FF0000') if (args.text): frame.caption(text=args.text, font=Font("./Impact.ttf", 48, color), gravity='south') frame.save(filename=('./frames/%d.gif' % x)) subprocess.call([ 'convert', '-dispose', 'none', '-delay', str((5 - (float(args.speed) if args.speed else 3)) + 1.5), './frames/*.gif', '-coalesce', '-loop', '0', args.outfile if args.outfile else 'out.gif' ])
def compose_adaptive_prey(img_paths=None, match_json=None, gap=5, horizontal_gap=5, description=None, caption="Catcierge"): img = Image(width=600, height=1124, background=Color("#8A968E")) #print("Font path: %s" % args.fonts) font = Font(path="%s/source-code-pro/SourceCodePro-Medium.otf" % args.fonts, size=64) font_title = Font(path="%s/alex-brush/AlexBrush-Regular.ttf" % args.fonts, size=64) font_math = Font(path="%s/Asana-Math/Asana-Math.otf" % args.fonts, size=64) imgs = [] assert (img_paths and (len(img_paths) > 0)) or match_json, \ "Missing either a list of input image paths or a match json" if not img_paths or len(img_paths) == 0: step_count = match_json["step_count"] for step in match_json["steps"][:step_count]: print("Step: %s" % step["name"]) img_paths.append(step["path"]) # TODO: Allow any matcher type and number of images... assert len(img_paths) == 1 or len(img_paths) == 11, \ "Invalid number of images %d, expected 2 or 11" % len(img_paths) for img_path in img_paths: #print img_path imgs.append(Image(filename=img_path)) mpos = lambda w: (img.width - w) / 2 if len(img_paths) == 1: img.caption(caption, left=(img.width - 250) / 2, top=5, width=250, height=100, font=font_title) img.composite(imgs[0], left=mpos(imgs[0].width), top=120) return img orgimg = imgs[0] # Original image. detected = imgs[1] # Detected cat head roi. croproi = imgs[2] # Cropped/extended roi. globalthr = imgs[3] # Global threshold (inverted). adpthr = imgs[4] # Adaptive threshold (inverted). combthr = imgs[5] # Combined threshold. opened = imgs[6] # Opened image. dilated = imgs[7] # Dilated image. combined = imgs[8] # Combined image (re-inverted). contours = imgs[9] # Contours of white areas. final = imgs[10] # Final image. # TODO: Enable creating these based on input instead. kernel3x3 = create_kernel(w=3, h=3) kernel2x2 = create_kernel(w=2, h=2) kernel5x1 = create_kernel(w=5, h=1) x_start = 20 img.caption(caption, left=(img.width - 250) / 2, top=5, width=250, height=100, font=font_title) if description: desc_font = Font(path="%s/source-code-pro/SourceCodePro-Medium.otf" % args.fonts, size=24) text_width = (desc_font.size) * int(len(description) * 0.7) img.caption(description, left=(img.width - text_width) / 2, top=80, width=text_width, height=100, font=desc_font) height = 120 # Original. img.composite(orgimg, left=mpos(orgimg.width), top=height) height += orgimg.height + gap # Detected head + cropped region of interest. head_row = create_row([detected, croproi], [0, 0], horizontal_gap, caption="Detected head Cropped ROI") img.composite(head_row, left=mpos(head_row.width), top=height) height += head_row.height + gap # TODO: simplify the code below by making the symbols into images before they're used to create the rows. # Combine the threshold images. thr_row = create_row( [globalthr, "+", adpthr, "=", combthr], [ x_start, (4 * horizontal_gap, -15, 14 * horizontal_gap, font), 0, (2 * horizontal_gap, -15, 8 * horizontal_gap, font), 2 * horizontal_gap ], horizontal_gap, fixed_width=img.width, caption= "Global Threshold Adaptive Threshold Combined Threshold", caption_offset=(x_start, 0)) img.composite(thr_row, left=mpos(thr_row.width), top=height) height += thr_row.height + gap # Open the combined threshold. open_row = create_row( [combthr, u"∘", kernel2x2, "=", opened], [ x_start, (5 * horizontal_gap, -5, 14 * horizontal_gap, font_math), 0, (21 * horizontal_gap, -15, 10 * horizontal_gap, font), 19 * horizontal_gap + 3 ], horizontal_gap, fixed_width=img.width, caption= "Combined Threshold 2x2 Kernel Opened Image", caption_offset=(x_start, 0)) img.composite(open_row, left=mpos(open_row.width), top=height) height += open_row.height + gap # Dilate opened and combined threshold with a kernel3x3. dilated_row = create_row( [opened, u"⊕", kernel3x3, "=", dilated], [ x_start, (3 * horizontal_gap, -5, 14 * horizontal_gap, font_math), 0, (17 * horizontal_gap, -15, 10 * horizontal_gap, font), 15 * horizontal_gap + 3 ], horizontal_gap, fixed_width=img.width, caption= "Opened Image 3x3 Kernel Dilated Image", caption_offset=(x_start, 0)) img.composite(dilated_row, left=mpos(dilated_row.width), top=height) height += dilated_row.height + gap # Inverted image and contour. contour_row = create_row([combined, contours], [0, 0], horizontal_gap, caption=" Re-Inverted Contours") img.composite(contour_row, left=mpos(contour_row.width), top=height) height += contour_row.height + 2 * gap # Final. img.composite(final, left=mpos(final.width), top=height) height += final.height + gap return img
class FunPlugin(Plugin): font = Font('Impact') @Plugin.command('convert', '<a:str> <b:str> <value:str...>') def convert_command(self, event, a, b, value): """= convert = Converts something to something else usage :: !convert <from> <to> <thing to convert> aliases :: None category :: Fun == Examples !convert text binary some example text !convert binary text 01100010 01101111 01110100 !convert decimal binary 42 !convert binary decimal 101010 """ if a == 'text' and b == 'binary': text = map(ord, value) binary = ' '.join([format(int(bin(n)[2:]), '08') for n in text]) event.msg.reply(binary) elif a == 'binary' and b == 'text': binary = value.split() if len(binary) == 1: binary = binary[0] binary = [ binary[byte:byte + 8] for byte in range(0, len(binary), 8) ] decimal = [int(n, 2) for n in binary] text = ''.join(map(chr, decimal)) event.msg.reply(text) elif a == 'binary' and b == 'decimal': binary = value.split() decimal = ' '.join([str(int(n, 2)) for n in binary]) event.msg.reply(decimal) elif a == 'decimal' and b == 'binary': decimal = map(int, value.split()) binary = ' '.join([bin(n)[2:] for n in decimal]) event.msg.reply(binary) @Plugin.command('caesar', '<rot:int> <msg:str...>') def caesar_command(self, event, rot, msg): """= caesar = Performs a simple caesar cipher usage :: !caesar <rotation> <message> aliases :: None category :: Fun == Constraints rotation :: Must be a number between -25 and +25 == Examples !caesar 1 abc `=> bcd' !caesar -1 bcd `=> abc' !caesar 5 foo bar `=> ktt gfw' """ event.msg.delete() if rot > 25 or rot < -25: return alpha = string.ascii_lowercase table = string.maketrans(alpha, alpha[rot:] + alpha[:rot]) cipher = string.translate(str(msg).lower(), table) event.msg.reply('{} says: ```{}```'.format(event.member, cipher)) @Plugin.command('foo') def foo_command(self, event): dm = event.author.open_dm() dm.send_message('foo') @Plugin.command('someone') def someone_command(self, event): members = event.guild.members.copy() # Don't mention self or user who triggered command del members[435938181750456322] # bot id del members[event.msg.author.id] # id of user who triggered command someone = choice(members.values()).user.mention event.msg.reply(someone) @Plugin.command('mock', parser=True) @Plugin.add_argument('--scroll', '-s', type=int) @Plugin.add_argument('--text', '-t', nargs='+') def mock_command(self, event, args): """= mock = Uses spongemock meme to mock someone's message or creates custom one usage :: !mock [--scroll/-s <N> | --text/-t <custom text>] aliases :: None category :: Fun == Defaults scroll :: 1 == Constraints scroll :: Must be a number >=1 and <=100 == Examples !mock `Will mock previous message, equivalent to !mock --scroll 1' !mock --scroll 2 ``Mock's 2nd to last message in channel'' !mock -s2 `Equivalent to previous example' !mock -s 2 `Equivalent to previous example' !mock --text some example text `Creates custom mock' !mock -t some example text `Equivalent to previous example' """ if args.text is None: if args.scroll is None: args.scroll = 1 msg = next( islice( event.channel.messages_iter(direction='DOWN', before=event.msg.id), args.scroll - 1, args.scroll)) args.text = msg.content elif args.scroll < 1: return msg = next( islice( event.channel.messages_iter(direction='DOWN', before=event.msg.id), args.scroll - 1, args.scroll)) args.text = msg.content if isinstance(args.text, list): args.text = ' '.join(args.text) args.text = ''.join( [choice([char, char.upper()]) for char in args.text.lower()]) with Image(filename='images/mock.jpg') as original: img = original.clone() img.caption(text=args.text, top=810, left=10, width=1150, height=200, font=self.font, gravity='center') img.save(filename='images/last_mock.jpg') with open('images/last_mock.jpg', 'rb') as f: event.channel.send_message(attachments=[('last_mock.jpg', f)]) @Plugin.command('coliru', aliases=['code', 'run'], parser=True) @Plugin.add_argument( 'lang', nargs='+' ) # This is a hack because the regex isn't matching the way I need it to def coliru_command(self, event, args): """= coliru = Executes and displays the output of code in a user's message using [http://coliru.stacked-crooked.com] usage :: !coliru <py | python | c | cpp | haskell> :: <code> aliases :: code, run category :: Fun == Example !coliru python ```py for i in range(3): print 'foobar' ``` == Notes Supported Languages: C++, C, Python, Haskell Anything else isn't supported The python support is only Python 2.7 (sorry python3 users) == More Info For more information on discord markdown syntax, go here: [https://support.discordapp.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-] """ lang = args.lang[ 0] # args parses the entire message because I have to, so I grab just the first element output_msg = event.msg.reply('`Compiling...`') cmds = { 'cpp': 'g++ -std=c++1z -O2 -Wall -Wextra -pedantic -pthread main.cpp -lstdc++fs && ./a.out', 'c': 'mv main.cpp main.c && gcc -std=c11 -O2 -Wall -Wextra -pedantic main.c && ./a.out', 'py': 'python main.cpp', # coliru has no python3 'python': 'python main.cpp', 'haskell': 'runhaskell main.cpp' } payload = { 'cmd': cmds.get(lang), 'src': '\n'.join(event.codeblock.splitlines()[1:]) } if payload['cmd'] is None: msg = output_msg.edit( '[ERROR] - Invalid language "{}"'.format(lang)) time.sleep(15) msg.delete() return r = requests.post('http://coliru.stacked-crooked.com/compile', json=payload) if r.status_code != 200: output_msg.edit('Coliru did not respond in time') return output = r.text if len(output) < 1992 and len(output.splitlines()) <= 30: output_msg.edit(u'```\n{}\n```'.format(output)) else: url = 'https://api.paste.ee/v1/pastes' with open('json/paste_ee.json') as f: header = json.load(f) # Auth Token payload = {'sections': [{'contents': output}]} r = requests.post(url, headers=header, json=payload) output_msg.edit( 'Pasting to `https://paste.ee` because output is too long: {}'. format(r.json()['link'])) @Plugin.command('test') def test_command(self, event): self.client.api.channels_typing(event.channel.id) time.sleep(5) event.msg.reply('test typing') @Plugin.command('jpeg', aliases=['morejpeg', 'jpg', 'morejpg'], parser=True) @Plugin.add_argument('--scroll', '-s', type=int, default=1) @Plugin.add_argument('--quality', '-q', type=int, default=1) def jpeg_command(self, event, args): """= jpeg = Adds more jpeg to an image usage :: !jpeg [--scroll/-s] [--quality/-q] aliases :: morejpeg, jpg, morejpg category :: Fun == Defaults scroll :: 1 quality :: 1 == Constraints scroll :: Must be a number >=1 and <=100 quality :: Must be a number >=1 and <=95 == Examples !jpeg `Performs action on last message in channel with quality set to 1' !jpeg --scroll 2 `Performs action on 2nd to last message with quality set to 1' !jpeg -s 2 `Equivalent to previous example' !jpeg -s2 `Equivalent to previous example' !jpeg --quality 5 `Sets quality to 5' !jpeg -q5 `Equivalent to previous example' !jpeg -s2 -q5 `Performs action on 2nd to last message with quality as 5' """ qt = args.quality if args.scroll < 1: return msg = next( islice( event.channel.messages_iter(direction='DOWN', before=event.msg.id), args.scroll - 1, args.scroll)) for attachment in msg.attachments.values(): url = attachment.url r = requests.get(url) f = StringIO(r.content) with pil_Image.open(f) as img: img.load() try: background = pil_Image.new("RGB", img.size, (255, 255, 255)) background.paste(img, mask=img.split()[3]) background.save('images/last_jpeg.jpg', quality=qt) except IndexError: img.save('images/last_jpeg.jpg', 'JPEG', quality=qt) with open('images/last_jpeg.jpg', 'rb') as f: event.channel.send_message(attachments=[('last_jpeg.jpg', f)]) @Plugin.command('drama', aliases=['nonsense'], parser=True) @Plugin.add_argument('action', nargs='?', choices=['alert', 'record', 'archive']) def drama_command(self, event, args): """= drama = Keeps track of the last time there was drama on the server usage :: !drama [alert | record | archive] aliases :: nonsense category :: Fun == Examples !drama `Will display when the last occurrence of drama happened' !drama record `Will display the record of most days without drama' !drama archive `Will display all recorded incidents of drama' !drama alert `Will declare that drama has just happened (STAFF ONLY)' """ if event.channel.is_dm: event.msg.reply('This command only works in a server :/') return action = args.action server_id = event.guild.id # Use pendulum for timezone information today = pendulum.now(tz='America/New_York') # Convert to standard datetime so sqlite doesn't complain today = datetime(today.year, today.month, today.day, today.hour, today.minute, today.second) try: conn = sqlite3.connect('db/{}.db'.format(server_id), detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES) c = conn.cursor() if action is None: c.execute('select last_drama from drama') last_drama = c.fetchone() if last_drama is None: event.msg.reply('There has never been any {}'.format( event.name)) else: last_drama = last_drama[0] days_ago = (today.date() - last_drama.date()).days event.msg.reply( 'Last time there was {} was {} {} ago on {:%x at %I:%M%p EST}' .format(event.name, days_ago, 'day' if days_ago == 1 else 'days', last_drama)) elif action == 'record': if c.execute('select count(*) from drama').fetchone()[0] == 0: event.msg.reply('There has never been any {}'.format( event.name)) else: c.execute('select * from drama') record, last_drama = c.fetchone() cur_record = (today.date() - last_drama.date()).days record = max(record, cur_record) event.msg.reply('{} {} {}'.format( record, 'day' if record == 1 else 'days', ':unamused:' if record <= 1 else '')) elif action == 'alert': user_level = self.bot.get_level(event.author) if user_level < CommandLevels.MOD: event.msg.reply("You're not qualified to declare drama") return if c.execute('select count(*) from drama').fetchone( )[0] == 0: # First run in a server if event.guild.id == 414960415018057738: # Retro retro_opening = pendulum.datetime( 2018, 6, 22, tz='America/New_York') # Retro opening day start_date = datetime(retro_opening.year, retro_opening.month, retro_opening.day) self.log.info( 'Detected drama in retro, using custom date instead of server creation' ) else: server_creation = pendulum.from_timestamp( snowflake.to_unix(event.guild.id), tz='America/New_York') start_date = datetime(server_creation.year, server_creation.month, server_creation.day) record = (today.date() - start_date.date()).days c.execute('insert into drama values (?,?)', (record, start_date)) conn.commit() c.execute('select * from drama') record, last_drama = c.fetchone() cur_record = (today.date() - last_drama.date()).days new_record = max(record, cur_record) c.execute('update drama set record = ?, last_drama = ?', (new_record, today)) c.execute('insert into drama_archive values (?)', (today, )) conn.commit() event.msg.reply( 'Uh oh, {} alert :popcorn:\nThe peace lasted for {} {}. {}\n\n{}' .format( event.name, cur_record, 'day' if cur_record == 1 else 'days', ':unamused:' if cur_record <= 1 else '', 'New record btw :clap:' if cur_record > record and record > 0 else '')) elif action == 'archive': if c.execute('select count(*) from drama_archive').fetchone( )[0] == 0: event.msg.reply('There has never been any {}'.format( event.name)) else: incidents = c.execute( 'select count(*) from drama_archive').fetchone()[0] r = '{} {} {}:\n'.format( incidents, 'Dramatic' if event.name == 'drama' else 'Nonsensical', 'event' if incidents == 1 else 'events') c.execute('select incident from drama_archive') for row in c: r += '{:%x - %I:%M%p EST}\n'.format(row[0]) event.msg.reply(r) except sqlite3.OperationalError: event.msg.reply( '[INFO] - First time running `!{}` command, creating new table in database' .format(event.name)) c.execute( 'create table drama (record integer, last_drama timestamp)') c.execute('create table drama_archive (incident timestamp)') conn.commit() event.msg.reply('Table created. Please run your command again.') finally: conn.close() @staticmethod def clean_html(raw_html): """Cleans html tags from jeopardy questions that happen to have them. """ p = re.compile('<.*?>') clean_text = re.sub(p, '', raw_html) return clean_text @Plugin.command('jeopardy', aliases=['j'], parser=True) @Plugin.add_argument('-r', '--random', action='store_true') def jeopardy_command(self, event, args): self.log.info('{} executed !jeopardy with args: {}'.format( event.author, args)) if not args.random: return jservice_base_url = 'http://jservice.io/{}' jservice_random = '/api/random' jeopardy_response = requests.get( jservice_base_url.format(jservice_random)).json()[0] from pprint import pprint pprint(jeopardy_response) jeopardy_q = jeopardy_response['question'].replace('&', 'and') jeopardy_a = self.clean_html(jeopardy_response['answer']) jeopardy_id = jeopardy_response['id'] jeopardy_amount = '${}'.format(jeopardy_response['value']) jeopardy_category = jeopardy_response['category']['title'] jeopardy_q = '\n'.join([ ' '.join(jeopardy_q.split()[s:s + 6]) for s in range(0, len(jeopardy_q.split()), 6) ]) self.log.info('amount: {}'.format(jeopardy_amount)) img2txt_url = 'http://api.img4me.com/?text={}&font=impact&size=35&fcolor={}&bcolor=060CE9' question_color = 'FFFFFF' amount_color = 'D49516' question_value = requests.get( img2txt_url.format(jeopardy_q, question_color)).text amount_value = requests.get( img2txt_url.format(jeopardy_amount, amount_color)).text embed = MessageEmbed() embed.set_author( name='Jeopardy!', url='http://jservice.io/', icon_url= 'http://jservice.io/assets/trebek-503ecf6eafde622b2c3e2dfebb13cc30.png' ) embed.title = 'Category: {}'.format(jeopardy_category) embed.timestamp = pendulum.now().in_tz('America/New_York').isoformat() embed.set_thumbnail(url=amount_value) embed.set_image(url=question_value) embed.set_footer(text='Powered by jservice.io') embed.color = '13931798' # dark yellow (hex: #D49516) event.msg.reply(embed=embed) @Plugin.command('qr', '<text:str...>') def qr_command(self, event, text): event.msg.delete() img = qrcode.make(text) f = StringIO() img.save(f, img.format) code = f.getvalue() f.close() event.msg.reply(attachments=[('qrcode.png', code)])
def __init__(self, src_dir, out_dir): self.src = src_dir self.out = out_dir self.FONT = Font(path="{}/font.ttf".format(src_dir), color=Color("#ffffff"))
from wand.drawing import Drawing
def process_native_file(file, filename, file_extension, volume_number, production_prefix, start_bates_number, num_digits, confidentiality, current_bates_number, beginning_bates_number, temp_dir, temp_split_dir, temp_txt_file, temp_txt_dir, temp_zip_file, temp_zip_dir, dirs, files): prod_home, prod_data, prod_img, prod_nat, prod_txt, prod_img001, prod_nat001, prod_txt001, completed_dir = dirs opt_file, dat_file = files ## STEP 1: COPY NATIVE AND RENAME WITH BATES NUMBER # create new file name (potentially incorporating confidentiality designation) if confidentiality == True: new_filename = f"{production_prefix}{str(current_bates_number).zfill(num_digits)}-CONFIDENTIAL" else: new_filename = f"{production_prefix}{str(current_bates_number).zfill(num_digits)}" # copy native file into correct production folder and name with new file name copyfile(file, prod_nat001 + "/" + f"{new_filename}{file_extension}") ## STEP 2: CREATE IMAGE PLACEHOLDER TO NOTIFY RECIPIENT THAT DOCUMENT IS PRODUCED IN NATIVE FORM # create sheet, create bates number / confidentiality designations / main text caption1 = f"{production_prefix}{str(current_bates_number).zfill(num_digits)}" caption2 = "CONFIDENTIAL BUSINESS INFORMATION - SUBJECT TO PROTECTIVE ORDER" main_text = "DOCUMENT PRODUCED AS NATIVE" # sheet is 8.5 x 11 (plain letter size) with Image(width=2550, height=3300, background=Color("WHITE")) as img: height = img.height width = img.width # 10 point arial font should be roughly 1/80th the height of the image and 1/118th the width # 12 point arial font should be roughly 1/66th the height of the image and 1/98th the width # 24 point arial font should be roughly 1/33rd the height of the image and 1/49th the width # use the values to dynamically size the caption added to each page font1 = Font(path='Arial.ttf', size=int(height / 80), color=Color("black")) font2 = Font(path='Arial.ttf', size=int(height / 33), color=Color("black")) img.caption(caption1, font=font1, gravity="south_east") img.caption(main_text, font=font2, gravity="center") if confidentiality == True: img.caption(caption2, font=font1, gravity="south_west") img.save(filename=f"{prod_img001}/{caption1}.jpg") # reduce file size convert_command = f'convert "{prod_img001}/{caption1}.jpg" -compress group4 "{prod_img001}/{caption1}.tiff"' delete_command = f'rm "{prod_img001}/{caption1}.jpg"' os.system(convert_command) os.system(delete_command) ## STEP 3: UPDATE PRODUCTION DATA FILES # write OPT file row with open(opt_file, mode="a", encoding="cp1252") as opt_f: opt_writer = csv.writer(opt_f, delimiter=",") opt_writer.writerow([ f"{production_prefix}{str(current_bates_number).zfill(num_digits)}", volume_number, f".\\{volume_number}\\IMAGES\\IMG001\\{caption1}.tiff", "Y", "", "", "1" ]) # write DAT file row with open(dat_file, mode="a", encoding="utf-8") as dat_f: dat_writer = csv.writer(dat_f, delimiter=f"{chr(20)}") dat_writer.writerow([ f"{chr(254)}{production_prefix}{str(current_bates_number).zfill(num_digits)}{chr(254)}", f"{chr(254)}{production_prefix}{str(current_bates_number).zfill(num_digits)}{chr(254)}", f"{chr(254)}.\\{volume_number}\\TEXT\\TEXT001\\{caption1}.txt{chr(254)}", f"{chr(254)}.\\{volume_number}\\NATIVES\\NATIVE001\\{new_filename}{file_extension}{chr(254)}" ]) ## STEP 4: CREATE EMPTY TEXT FILE -- NOT EXTRACTING TEXT FOR DOCUMENTS PRODUCED AS NATIVE create_dirs.touch(f"{prod_txt001}/{caption1}.txt") current_bates_number += 1 # clean up temporary directory temp_dir.cleanup() return current_bates_number
offset = (width - new_width) / 2 resize = ((0, 0, int(new_width), int(height)), (int(width - new_width), 0, int(width), int(height))) else: # ... crop the top and bottom: new_height = int(width / ideal_aspect) offset = (height - new_height) / 2 resize = ((0, 0, int(width), int(new_height)), (0, int(height - new_height), int(width), int(height))) with Image(blob=image_blob.content) as canvas: print(canvas.width) canvas.crop(*resize[0]) print(canvas.width) canvas.font = Font("SanFranciscoDisplay-Bold.otf", size=53, color=Color('white')) caption_width = int(canvas.width / 1.2) margin_left = int((canvas.width - caption_width) / 2) margin_top = int(canvas.height / 2) canvas.caption(CAPTION, gravity='center', width=caption_width, left=margin_left, top=margin_top) canvas.format = "jpg" canvas.save(filename='text_overlayed_1.jpg') with Image(blob=image_blob.content) as canvas: canvas.crop(*resize[1]) canvas.font = Font("SanFranciscoDisplay-Bold.otf",