Example #1
0
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')
Example #2
0
    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.
Example #3
0
    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
Example #4
0
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
        }
Example #5
0
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)
Example #8
0
File: common.py Project: arperov/ib
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>')
Example #9
0
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)
Example #10
0
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
Example #11
0
    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))
Example #12
0
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')
Example #13
0
 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))
Example #14
0
    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()
Example #15
0
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)
Example #16
0
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
Example #17
0
    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()
Example #18
0
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
Example #19
0
 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
Example #20
0
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")
Example #21
0
    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
Example #23
0
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)])
Example #24
0
    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"))
Example #25
0
from wand.drawing import Drawing
Example #26
0
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",