Exemplo n.º 1
0
def add_watermark(image_path,
                  watermark,
                  new_path=None,
                  image_enhancements=None,
                  image_filters=None):
    '''Function to add watermarks to images

    Args:
        image_path (str): path of the image to which watermark has to be added.
        watermark (nider.models.Watermark): watermark object.
        new_path (str): path where the image has to be saved. **If set to None (default option), initial image will be overwritten.**
        image_enhancements (itarable): itarable of tuples, each containing a class from ``PIL.ImageEnhance`` that will be applied and factor - a floating point value controlling the enhancement. Check `documentation <http://pillow.readthedocs.io/en/latest/reference/ImageEnhance.html>`_ of ``PIL.ImageEnhance`` for more info about availabe enhancements.
        image_filters (itarable): itarable of filters from ``PIL.ImageFilter`` that will be applied. Check `documentation <http://pillow.readthedocs.io/en/latest/reference/ImageFilter.html>`_ of ``PIL.ImageFilter`` for more info about availabe filters.

    Raises:
        FileNotFoundError: if image file at path ``image_path`` cannot be found.
        nider.exceptions.ImageGeneratorException: if the current user doesn't have sufficient permissions to create the file at passed ``new_path``.
    '''
    if new_path is None:
        new_path = image_path
    content = Content(watermark=watermark)
    new_image = Image(content, fullpath=new_path)
    new_image.draw_on_image(image_path,
                            image_enhancements=image_enhancements,
                            image_filters=image_filters)
Exemplo n.º 2
0
 def setUp(self):
     header = Header(text='foo', fontfullpath=None)
     linkback = Linkback(text='bar', fontfullpath=None)
     para = Paragraph(text='foo bar', fontfullpath=None)
     content = Content(para, header=header, linkback=linkback)
     fullpath = 'test.png'
     self.img = Image(content, fullpath)
Exemplo n.º 3
0
 def test_invalid_params_to_set_image_size(self):
     invalid_sizes = [(-1, -2), (-1.5, -5.5)]
     for invalid_size in invalid_sizes:
         with self.subTest():
             with self.assertRaises(AttributeError):
                 Image._set_image_size(self.image_mock, invalid_size[
                     0], invalid_size[1])
Exemplo n.º 4
0
 def setUp(self):
     header = Header(text='foo', fontfullpath=None, outline=Outline())
     linkback = Linkback(text='bar', fontfullpath=None, outline=Outline())
     para = Paragraph(text='foo bar', fontfullpath=None, outline=Outline())
     content = Content(para, header=header, linkback=linkback, padding=45)
     self.fullpath = 'test.png'
     self.img = Image(content, self.fullpath)
     self.img._create_image()
     self.img._create_draw_object()
     self.img.opposite_to_bg_color = '#000'
Exemplo n.º 5
0
def img_to_txt(txt, author, result):
    para = Paragraph(text=txt,
                     font=Font(roboto_font_folder + 'Roboto-Black.ttf', 30),
                     text_width=30,
                     align='center',
                     color='#ededed',
                     outline=text_outline)
    linkback = Linkback(text=author,
                        font=Font(roboto_font_folder + 'Roboto-Black.ttf', 30),
                        color='#ededed',
                        outline=text_outline)
    content = Content(paragraph=para, linkback=linkback)
    img = Image(content, fullpath=result, width=3000, height=2005)
    img.draw_on_image('bg.png')
Exemplo n.º 6
0
def card_gen(image, name,  fact, linkback = 'learnfacts.fun | @learnafunfact'):
    ''' Genera una tarjeta ./facts_imgs/[query]-fact.jpg a partir de  la imagen ./images/[query].jpg y el
    fact que se le envia en forma de texto. Opcional puedes agregar tu linkback pero si le mandas
    nada usa 'learnafact.fun' 
    '''

    fact_img = './facts_imgs/' + name + '-fact.png'

    roboto_font_folder = './fonts/Roboto/'
    outline = Outline(2, '#121212')
    para = Paragraph( text=fact,
        font = Font(roboto_font_folder + 'Roboto-Medium.ttf', 55),
        text_width = 30,
        align='left',
        color='#ededed', 
        outline=outline,
        )

    linkback = Linkback(text= str(linkback),
        font = Font(roboto_font_folder + 'Roboto-Bold.ttf', 18),
        color = '#ededed',
        bottom_padding = 300,
        outline=outline
        )
    content = Content(para, linkback)
    img = Image(content,
        fullpath = fact_img,
        width=1080,
        height=720
        )
    img.draw_on_image(image,
    image_enhancements=((ImageEnhance.Contrast, 0.75),
    (ImageEnhance.Brightness, 0.75)),
    image_filters=((ImageFilter.BLUR),)
    )
    return ({ 'image':image, 'fact_img': fact_img})
Exemplo n.º 7
0
 def test_set_title_with_title_provided(self):
     Image._set_title(self.image_mock, 'foo')
     self.assertEqual(self.image_mock.title, 'foo')
Exemplo n.º 8
0
from nider.core import Outline

from nider.models import Content
from nider.models import Header
from nider.models import Image


# TODO: change this fontpath to the fontpath on your machine
roboto_font_folder = '/home/ovd/.local/share/fonts/Roboto/'

text_outline = Outline(1, '#efefef')

header = Header(text='Google bought a service that allows patients to undergo basic clinical tests at home using smartphones.',
                font=Font(roboto_font_folder + 'Roboto-Bold.ttf', 22),
                text_width=50,
                align='left',
                color='#000100',
                outline=text_outline
                )

content = Content(header=header)

img = Image(content,
            fullpath='result.png',
            width=600,
            height=314
            )

# TODO: change this image path to the image path on your machine
img.draw_on_image('bg.jpg')
Exemplo n.º 9
0
 def test_set_description_default_behavior(self):
     self.image_mock.content.para = None
     Image._set_description(self.image_mock, None)
     self.assertEqual(self.image_mock.description, '')
Exemplo n.º 10
0
 def test_set_description_with_description_provided(self):
     Image._set_description(self.image_mock, 'foo')
     self.assertEqual(self.image_mock.description, 'foo')
Exemplo n.º 11
0
 def test_set_fullpath_with_invalid_path(self):
     fullpath = 'non/existent/directory/test.png'
     with self.assertRaises(ImageGeneratorException):
         Image._set_fullpath(self.image_mock, fullpath)
     self.assertNotEqual(self.image_mock.fullpath, fullpath)
Exemplo n.º 12
0
    para = Paragraph(text=body,
                     font=Font(FONTS + content_font, 48),
                     text_width=65,
                     align='left',
                     color='#ededed',
                     outline=outline)

    linkback = Linkback(text='myQuoteSite.com |' + author,
                        font=Font(FONTS + header_font, 18),
                        color='#ededed',
                        outline=outline)

    content = Content(para, header, linkback)

    img = Image(content,
                fullpath=TOI + 'resultant_' + ti[1],
                width=1024,
                height=640)

    choice = input('Do you wish to blur background image? y/n \n')
    if choice == 'y':

        img.draw_on_image(IMG + ti[1],
                          image_enhancements=((ImageEnhance.Contrast, 0.75),
                                              (ImageEnhance.Brightness, 0.5)),
                          image_filters=((ImageFilter.BLUR), ))
    else:
        img.draw_on_image(IMG + ti[1],
                          image_enhancements=((ImageEnhance.Contrast, 0.75),
                                              (ImageEnhance.Brightness, 0.5)))

if checker != 1:
Exemplo n.º 13
0
                text_width=40,
                align='left',
                color='#ededed',
                drop_shadow=True,
                shadowcolor='#999')

para = Paragraph(
    text=
    'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
    fontfullpath=roboto + 'Roboto-Medium.ttf',
    fontsize=29,
    text_width=65,
    align='left',
    color='#ededed',
    drop_shadow=True,
    shadowcolor='#999')

linkback = Linkback(text='foo.com | @username',
                    fontfullpath=roboto + 'Roboto-Bold.ttf',
                    fontsize=24,
                    color='#ededed',
                    drop_shadow=True,
                    shadowcolor='#999')

content = Content(para, header=header, linkback=linkback, padding=60)

img = Image(content, fullpath='result.png', width=1080, height=720)

# TODO: change this image path to the image path on your machine
img.draw_on_image('bg.jpg')
Exemplo n.º 14
0
from nider.core import Font

from nider.models import Paragraph
from nider.models import Content
from nider.models import Image

# TODO: change this fontpath to the fontpath on your machine
roboto_font_folder = '/home/ovd/.local/share/fonts/Roboto/'

para = Paragraph(
    text=
    'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
    font=Font(roboto_font_folder + 'Roboto-Medium.ttf', 20),
    text_width=49,
    align='center',
    color='#121212')

content = Content(para)

img = Image(content, width=500, height=500, fullpath='result.png')

img.draw_on_bg('#efefef')
Exemplo n.º 15
0
    text_width=53,
    line_padding=3,
    align='left',
    color='#ededed',
    outline=text_outline,
)

para = Paragraph(
    text=
    'Tens of millions of people are expected to cram into a narrow path, from Oregon to the Carolinas, to see the remarkable event.',
    font=Font(roboto_font_folder + 'Roboto-Medium.ttf', 25),
    text_width=60,
    align='left',
    color='#ededed',
    outline=text_outline,
)

linkback = Linkback(
    text='@washingtonpost',
    font=Font(roboto_font_folder + 'Roboto-Bold.ttf', 17),
    color='#ededed',
    outline=text_outline,
)

content = Content(para, header, linkback)

img = Image(content, fullpath='result.png', width=1080, height=720)

# TODO: change this image path to the image path on your machine
img.draw_on_image('bg.png', image_filters=((ImageFilter.BLUR), ))
Exemplo n.º 16
0
 def test_set_title_without_title_provided_but_with_header(self):
     header = Header('title')
     content = Content(header=header)
     Image._set_content(self.image_mock, content)
     Image._set_title(self.image_mock, '')
     self.assertEqual(self.image_mock.title, 'title')
Exemplo n.º 17
0
 def test_set_title_default_behavior(self):
     self.image_mock.content.header = None
     Image._set_title(self.image_mock, None)
     self.assertEqual(self.image_mock.title, '')
Exemplo n.º 18
0
def write_image_on_text(header='',
                        footer='',
                        source_path='sources/test.jpg',
                        width=1080, height=1080,
                        header_font_path='fonts/Roboto-Regular.ttf',
                        text_width_header=30,  font_size_header=40,
                        footer_font_path='fonts/Roboto-Regular.ttf',
                        font_size_footer=30, text_width_footer=30,
                        save_folder='temp/',
                        top_padding=200,
                        bottom_padding=140):
    header_text = Header(
        text=header.upper(),
        font=Font(header_font_path, font_size_header),
        text_width=text_width_header,
        align='center',
        color='#ffffff'
    )

    para = Paragraph(
        text='',
        font=Font(footer_font_path, font_size_footer),
        text_width=text_width_footer,
        align='center',
        color='#ffffff'
    )

    linkback = Linkback(
        text='',
        font=Font(footer_font_path, font_size_footer),
        align='center',
        color='#ffffff',
        bottom_padding=20
    )

    content = Content(para, header_text, linkback, padding=top_padding)

    temp_save_path = get_save_file_name(save_folder)
    img = Image(content, width=width, height=height, fullpath=temp_save_path)

    img.draw_on_texture(source_path)

    header_text = Header(
        text='',
        font=Font(header_font_path, font_size_header),
        text_width=text_width_header,
        align='center',
        color='#ffffff'
    )

    para = Paragraph(
        text=footer,
        font=Font(footer_font_path, font_size_footer),
        text_width=text_width_footer,
        align='center',
        color='#ffffff'
    )

    content = Content(para, header_text, linkback, padding=bottom_padding)

    new_save_path = get_save_file_name(save_folder)
    img = Image(content, width=width, height=height, fullpath=new_save_path)

    img.draw_on_texture(temp_save_path)

    img = Img.open(new_save_path)
    img = img.crop((0, 0, width, height))

    final_save_path = get_save_file_name(save_folder)
    img.save(final_save_path)

    return final_save_path
Exemplo n.º 19
0
 def test_set_description_without_description_provided_but_with_para(self):
     para = Paragraph('description')
     content = Content(paragraph=para)
     Image._set_content(self.image_mock, content)
     Image._set_description(self.image_mock, '')
     self.assertEqual(self.image_mock.description, 'description')
Exemplo n.º 20
0
# TODO: change this fontpath to the fontpath on your machine
roboto_font_folder = '/home/ovd/.local/share/fonts/Roboto/'

text_outline = Outline(1, '#121212')

para = Paragraph(text='Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
                 font=Font(roboto_font_folder + 'Roboto-Medium.ttf', 25),
                 text_width=35,
                 align='center',
                 color='#efefef',
                 outline=text_outline
                 )

linkback = Linkback(text='@foobar',
                    font=Font(roboto_font_folder + 'Roboto-Bold.ttf', 20),
                    color='#efefef',
                    outline=text_outline
                    )

content = Content(paragraph=para, linkback=linkback)

img = Image(content,
            fullpath='result.png',
            width=500,
            height=500
            )

# TODO: change this texture path to the texture path on your machine
img.draw_on_texture('texture.png')
Exemplo n.º 21
0
class TestImageBaseMethods(unittest.TestCase):

    def setUp(self):
        header = Header(text='foo', fontfullpath=None)
        linkback = Linkback(text='bar', fontfullpath=None)
        para = Paragraph(text='foo bar', fontfullpath=None)
        content = Content(para, header=header, linkback=linkback)
        fullpath = 'test.png'
        self.img = Image(content, fullpath)

    def test_fix_img_size(self):
        self.img.content.height = 101
        self.img.height = 100
        with self.assertWarns(ImageSizeFixedWarning):
            self.img._fix_image_size()
        self.assertFalse(self.img.content.fits)
        self.assertEqual(self.img.height, self.img.content.height)

    def test_no_need_for_fix_img_size(self):
        self.img.content.height = 100
        self.img.height = 101
        self.img._fix_image_size()
        self.assertTrue(self.img.content.fits)
        self.assertNotEqual(self.img.height, self.img.content.height)

    def test_create_img(self):
        self.img._create_image()
        self.assertIsInstance(self.img.image, PIL_Image.Image)

    def test_create_draw_object(self):
        self.img._create_image()
        self.img._create_draw_object()
        self.assertIsInstance(self.img.draw, ImageDraw.ImageDraw)

    @mock.patch('nider.models.Image._save')
    @mock.patch('nider.models.Image._draw_content')
    def test_draw_on_texture(self,
                             _draw_content_mock,
                             _save):
        self.img.draw_on_texture()
        self.assertIsNotNone(self.img.opposite_to_bg_color)
        self.assertTrue(_draw_content_mock.called)

    def test_draw_on_texture_with_invalid_texturepath(self):
        with self.assertRaises(FileNotFoundError):
            self.img.draw_on_texture(texture_path='foo/bar.png')

    @mock.patch('nider.models.Image._save')
    @mock.patch('nider.models.Image._draw_content')
    def test_draw_on_bg(self,
                        _draw_content_mock,
                        _save):
        self.img.draw_on_bg()
        self.assertIsNotNone(self.img.opposite_to_bg_color)
        self.assertTrue(_draw_content_mock.called)

    @mock.patch('nider.models.Image._save')
    @mock.patch('nider.models.Image._draw_content')
    def test_draw_on_image(self,
                           _draw_content_mock,
                           _save):
        with create_test_image():
            self.img.draw_on_image(
                image_path=os.path.abspath('test.png'))
        self.assertIsNotNone(self.img.opposite_to_bg_color)
        self.assertTrue(_draw_content_mock.called)

    @mock.patch('PIL.ImageEnhance._Enhance.enhance')
    @mock.patch('nider.models.Image._save')
    @mock.patch('nider.models.Image._draw_content')
    def test_draw_on_image_with_enhancements(self,
                                             _draw_content_mock,
                                             _save,
                                             enhance_mock):
        with create_test_image():
            enhance_mock.return_value = PIL_Image.open('test.png')
            self.img.draw_on_image(
                image_path=os.path.abspath('test.png'),
                image_enhancements=((ImageEnhance.Sharpness, 0.5),
                                    (ImageEnhance.Brightness, 0.5)))
        self.assertTrue(enhance_mock.called)
        self.assertTrue(_draw_content_mock.called)

    @mock.patch('PIL.Image.Image.filter')
    @mock.patch('nider.models.Image._save')
    @mock.patch('nider.models.Image._draw_content')
    def test_draw_on_image_with_filters(self,
                                        _draw_content_mock,
                                        _save,
                                        filter_mock):
        filters = (ImageFilter.BLUR, ImageFilter.GaussianBlur(2))
        with create_test_image():
            filter_mock.return_value = PIL_Image.open('test.png')
            self.img.draw_on_image(
                image_path=os.path.abspath('test.png'),
                image_filters=filters)
        self.assertTrue(filter_mock.called)
        self.assertTrue(_draw_content_mock.called)

    def test_draw_on_image_with_invalid_imagepath(self):
        with self.assertRaises(FileNotFoundError):
            self.img.draw_on_image('foo/bar.png')
Exemplo n.º 22
0
 def test_set_fullpath_with_valid_path(self):
     fullpath = 'test.png'
     Image._set_fullpath(self.image_mock, fullpath)
     self.assertEqual(self.image_mock.fullpath, fullpath)
Exemplo n.º 23
0
class TestImageMethodsThatRequireImageAndDraw(unittest.TestCase):

    def setUp(self):
        header = Header(text='foo', fontfullpath=None, outline=Outline())
        linkback = Linkback(text='bar', fontfullpath=None, outline=Outline())
        para = Paragraph(text='foo bar', fontfullpath=None, outline=Outline())
        content = Content(para, header=header, linkback=linkback, padding=45)
        self.fullpath = 'test.png'
        self.img = Image(content, self.fullpath)
        self.img._create_image()
        self.img._create_draw_object()
        self.img.opposite_to_bg_color = '#000'

    @classmethod
    def tearDownClass(self):
        fullpath = 'test.png'
        os.remove(fullpath)

    @mock.patch('PIL.Image.Image.paste')
    def test_fill_img_with_texture(self, mock):
        texture = get_random_texture()
        self.img._fill_image_with_texture(texture)
        self.assertTrue(mock.called)

    @mock.patch('PIL.ImageDraw.ImageDraw.rectangle')
    def test_fill_img_with_color(self, mock):
        bgcolor = '#000'
        self.img.bgcolor = bgcolor
        self.img._fill_image_with_color()
        mock.assert_called_once_with(
            [(0, 0), self.img.image.size], fill=bgcolor)

    @mock.patch('nider.models.Image._draw_unit')
    def test_draw_header(self, mock):
        self.img._draw_header()
        mock.assert_called_once_with(45,
                                     self.img.header)

    @mock.patch('nider.models.Image._draw_unit')
    def test_draw_para_with_content_that_fits(self, mock):
        self.img._draw_para()
        current_h = math.floor(
            (self.img.height - self.img.para.height) / 2)
        mock.assert_called_once_with(current_h, self.img.para)

    @mock.patch('nider.models.Image._draw_unit')
    def test_draw_para_content_with_header_that_does_not_fit(self, mock):
        self.img.content.fits = False
        self.img._draw_para()
        header_with_padding_height = 2 * \
            self.img.content.padding + self.img.header.height
        current_h = header_with_padding_height
        mock.assert_called_once_with(current_h, self.img.para)

    @mock.patch('nider.models.Image._draw_unit')
    def test_draw_para_content_without_header_that_does_not_fit(self, mock):
        self.img.content.fits = False
        self.img.header = None
        self.img._draw_para()
        current_h = self.img.content.padding
        mock.assert_called_once_with(current_h, self.img.para)

    @mock.patch('PIL.ImageDraw.ImageDraw.text')
    def test_draw_linkback(self, mock):
        self.img.color = '#000'
        aligns = ['center', 'right', 'left']
        for align in aligns:
            with self.subTest():
                self.img.linkback.align = align
                self.img._draw_linkback()
                self.assertTrue(mock.called)

    def test_prepare_content(self):
        content = self.img.content
        self.img._prepare_content()
        for unit in [content.header, content.para, content.linkback]:
            self.assertIsNotNone(unit.color)
            self.assertIsNotNone(unit.outline.color)

    def test_prepare_content_with_None_units(self):
        content = self.img.content
        content.header = None
        content.linkback = None
        self.img._prepare_content()
        self.assertIsNotNone(content.para.color)
        self.assertIsNotNone(content.para.outline.color)

    @mock.patch('nider.models.Image._draw_linkback')
    @mock.patch('nider.models.Image._draw_para')
    @mock.patch('nider.models.Image._draw_header')
    def test_draw_content(self, _draw_header_mock,
                          _draw_para_mock, _draw_linkback_mock):
        self.img._draw_content()
        self.assertTrue(_draw_header_mock.called)
        self.assertTrue(_draw_para_mock.called)
        self.assertTrue(_draw_linkback_mock.called)

    @mock.patch('PIL.ImageDraw.ImageDraw.text')
    def test_draw_unit_with_outline(self, text_mock):
        available_outlines = [None, Outline(2, '#111')]
        self.img.color = '#000'
        start_height = 0
        aligns = ['center', 'right', 'left']
        for align in aligns:
            for outline in available_outlines:
                with self.subTest():
                    unit = MultilineTextUnit(
                        text='foo', fontfullpath=None, outline=outline,
                        align=align)
                    self.img._draw_unit(start_height, unit)
                    self.assertTrue(text_mock.called)

    def test_save(self):
        self.img._save()
        self.assertTrue(os.path.isfile(self.fullpath))
Exemplo n.º 24
0
 def test_set_fullpath_with_invalid_path(self):
     fullpath = 'non/existent/directory/test.png'
     with self.assertRaises(AttributeError):
         Image._set_fullpath(self.image_mock, fullpath)
     self.assertNotEqual(self.image_mock.fullpath, fullpath)
Exemplo n.º 25
0
 def test_set_content(self):
     para = Paragraph(text='foo bar', fontfullpath=None)
     content = Content(para)
     Image._set_content(self.image_mock, content)
     self.assertEqual(self.image_mock.content, content)
Exemplo n.º 26
0
 def test_set_image_size(self):
     w, h = 500, 500
     Image._set_image_size(self.image_mock, w, h)
     self.assertEqual(self.image_mock.width, w)
     self.assertEqual(self.image_mock.height, h)
Exemplo n.º 27
0
    i = 0
    for q in wikiquote.quotes(a, lang='es', max_quotes=25):

        if len(q) <= 256:

            para = Paragraph(text='"' + q + '"',
                             font=Font(
                                 roboto_font_folder + 'Roboto-Medium.ttf', 25),
                             text_width=35,
                             align='center',
                             color='#ffff00',
                             outline=text_outline)

            linkback = Linkback(text='@quienlodice',
                                font=Font(
                                    roboto_font_folder + 'Roboto-Bold.ttf',
                                    20),
                                color='#efefef',
                                outline=text_outline)

            content = Content(paragraph=para, linkback=linkback)

            img = Image(content,
                        fullpath=a + '-' + str(uuid.uuid4()) + '.png',
                        width=640,
                        height=480)

            # TODO: change this texture path to the texture path on your machine
            img.draw_on_texture(paths[a][i])
            i = i + 1
Exemplo n.º 28
0
header = Header(text='Your super interesting title!',
                font=Font(roboto_font_folder + 'Roboto-Bold.ttf', 30),
                text_width=40,
                align='left',
                color='#ededed',
                outline=outline)

para = Paragraph(
    text=
    'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
    font=Font(roboto_font_folder + 'Roboto-Medium.ttf', 29),
    text_width=65,
    align='left',
    color='#ededed',
    outline=outline)

linkback = Linkback(text='foo.com | @username',
                    font=Font(roboto_font_folder + 'Roboto-Bold.ttf', 24),
                    color='#ededed',
                    outline=outline)

content = Content(para, header, linkback)

img = Image(content, fullpath='result.png', width=1080, height=720)

# TODO: change this image path to the image path on your machine
img.draw_on_image('bg.jpg',
                  image_enhancements=((ImageEnhance.Contrast, 0.75),
                                      (ImageEnhance.Brightness, 0.5)),
                  image_filters=((ImageFilter.BLUR), ))