GithubHelp home page GithubHelp logo

pilmoji's Introduction

Pilmoji

Pilmoji is an emoji renderer for Pillow, Python's imaging library.

Pilmoji comes equipped with support for both unicode emojis and Discord emojis.

Features

  • Discord emoji support
  • Multi-line rendering support
  • Emoji position and/or size adjusting
  • Many built-in emoji sources
  • Optional caching

Installation and Requirements

You must have Python 3.8 or higher in order to install Pilmoji.

Installation can be done with pip:

$ pip install -U pilmoji

Optionally, you can add the [requests] option to install requests alongside Pilmoji:

$ pip install -U pilmoji[requests]

The option is not required, instead if requests is not installed, Pilmoji will fallback to use the builtin urllib.

You may also install from Github.

Usage

from pilmoji import Pilmoji
from PIL import Image, ImageFont


my_string = '''
Hello, world! ๐Ÿ‘‹ Here are some emojis: ๐ŸŽจ ๐ŸŒŠ ๐Ÿ˜Ž
I also support Discord emoji: <:rooThink:596576798351949847>
'''

with Image.new('RGB', (550, 80), (255, 255, 255)) as image:
    font = ImageFont.truetype('arial.ttf', 24)

    with Pilmoji(image) as pilmoji:
        pilmoji.text((10, 10), my_string.strip(), (0, 0, 0), font)

    image.show()

Result

Example result

Switching emoji sources

As seen from the example, Pilmoji defaults to the Twemoji emoji source.

If you prefer emojis from a different source, for example Microsoft, simply set the source kwarg in the constructor to a source found in the pilmoji.source module:

from pilmoji.source import MicrosoftEmojiSource

with Pilmoji(image, source=MicrosoftEmojiSource) as pilmoji:
    ...

results

It is also possible to create your own emoji sources via subclass.

Fine adjustments

If an emoji looks too small or too big, or out of place, you can make fine adjustments with the emoji_scale_factor and emoji_position_offset kwargs:

pilmoji.text((10, 10), my_string.strip(), (0, 0, 0), font,
             emoji_scale_factor=1.15, emoji_position_offset=(0, -2))

Contributing

Contributions are welcome. Make sure to follow PEP-8 styling guidelines.

pilmoji's People

Contributors

annihilatorrrr avatar jay3332 avatar owocado avatar vertyco avatar witherredaway avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pilmoji's Issues

might want to pin emoji==1.7.0

hi,

emoji package 2.0.0 got released few days ago and it has breaking changes which prevents pilmoji from loading. If you might wanna take a look or pin the package in requirements.txt

Support https://emojipedia.org

Hi developer, can you support the emoji under https://emojipedia.org/airplane? For some reason I can't download the emoji images under https://emojicdn.elk.sh/ properly.

I tried to override the get_emoji method under the source.py EmojiCDNSource class, so I found https://emojipedia.org/airplane. I tried to find the relevant python emoji-api library, but only found the npm dependency https://github.com/CesiumLabs/emoji-api. It's a lot of work, so I was wondering if you could support it?

AttributeError: __enter__

Code from readme is not working

from pilmoji import Pilmoji
from PIL import Image, ImageFont


my_string = '''
Hello, world! ๐Ÿ‘‹ Here are some emojis: ๐ŸŽจ ๐ŸŒŠ ๐Ÿ˜Ž
I also support Discord emoji: <:rooThink:596576798351949847>
'''

with Image.new('RGB', (550, 80), (255, 255, 255)) as image:
    font = ImageFont.truetype('arial.ttf', 24)

    with Pilmoji(image) as pilmoji:
        pilmoji.text((10, 10), my_string.strip(), (0, 0, 0), font)

    image.show()

Output:

Traceback (most recent call last):
  File "/path/to/that/script.py", line 14, in <module>
    pilmoji.text((10, 10), my_string.strip(), (0, 0, 0), font)
  File "/usr/local/lib/python3.9/site-packages/pilmoji/core.py", line 299, in text
    stream = self._get_emoji(content)
  File "/usr/local/lib/python3.9/site-packages/pilmoji/core.py", line 154, in _get_emoji
    if stream := self.source.get_emoji(emoji):
  File "/usr/local/lib/python3.9/site-packages/pilmoji/source.py", line 166, in get_emoji
    return BytesIO(self.request(url))
  File "/usr/local/lib/python3.9/site-packages/pilmoji/source.py", line 116, in request
    with self._requests_session.get(url, **self.REQUEST_KWARGS) as response:
AttributeError: __enter__

$ python3 -V
Python 3.9.8

OS:
MacOS BigSur 11.6

How to enable caching?

In your documentation is stated that optional caching is possible. How can I enable it and how is the data be cached?

[HELP] Render text with emojis

Hello, i'm trying to draw text with emojis to an image:

text =  "Hello ๐Ÿ˜„"
image = Image.open(rimg_path)
img = image.convert('RGB')
d = ImageDraw.Draw(img)
box = (565, 100, 1150, 450)
d.rectangle(box, outline="#fff")
font = ImageFont.truetype(THIS_FOLDER+"/fonts/arial.ttf", size=25)
[...]
Pilmoji(img).text((x_author,y_author), text , "#fff", font)

but i'm getting this error:

myfunction(text, author, tag)
  File "c:\Users\user\Desktop\myfile\myfile.py", line 69, in myfunction
    Pilmoji(img).text((x_author,y_author), text , "#fff", font)
  File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\pilmoji\core.py", line 315, in text
    self.image.paste(asset, (x + ox, y + oy), asset)
  File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\PIL\Image.py", line 1628, in paste
    self.im.paste(im, box, mask.im)
TypeError: 'float' object cannot be interpreted as an integer

PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000236633A08B0>

File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\pilmoji\core.py", line 309, in text with Image.open(stream).convert('RGBA') as asset: File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 3123, in open raise UnidentifiedImageError( PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000236633A08B0>

This error would make you think in the beginning that there was something with an image you created or loaded. However it is just a badly explained error of pilmoji and it happens when an emoji is not found at the emojicdn, which is very common if you try different styles. I could design my own CDN class of course
However this took me many hours to debug because the error isn't that explanatory.
In our case, let's say I was trying to use this emoji: https://emojicdn.elk.sh/๐Ÿฅณ?style=facebook. This query returns a string "Emoji exists, but style couldnโ€™t be found". The emojiCDN does not return an alternative .png and that causes pilmoji to throw the error. My problem with that is mostly that the error is not descriptive of what happened, it makes you assume that there are problems with the image you're rendering and not of a different CDN response.

Error when trying to import pilmoji

To be specific. The error happens when I try to run the following import in a file:

from pilmoji import Pilmoji

The bot is hosted on a server, and it worked all fine until I restarted my bot. (Worked with restarts before too!)

Full error:

    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting EMOJI_IMG_TAG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
[...]
ImproperlyConfigured: Requested setting EMOJI_IMG_TAG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

Do we need to set DJANGO_SETTINGS_MODULE or not? This is not stated in the docs.

Do not print non existing characters

Some time the resultant image as a rectangle in it in place of where a character it could not render is found, can this be made to render nothing for unrecognized characters?

Custom emoji not being drawn when the length of its name is 1 letter

Code to reproduce

with Image.new("RGBA", (128, 128), (255, 255, 255, 0)) as image:
    with Pilmoji(image) as pilmoji:
        pilmoji.text(
            xy=(0, 0),
            text=f"<:e:664509407421530114>",  # Put literally any custom emoji here with 1 letter name
            fill=(0, 0, 0),
            font=FONT,
            emoji_scale_factor=130,
            emoji_position_offset=(-1, -1),
        )
        image.save("emoji.png", "PNG")

This image will be a blank image:
emoji

Now try this with more than 1 letter name

with Image.new("RGBA", (128, 128), (255, 255, 255, 0)) as image:
    with Pilmoji(image) as pilmoji:
        pilmoji.text(
            xy=(0, 0),
            text=f"<:ee:664509407421530114>",
            fill=(0, 0, 0),
            font=FONT,
            emoji_scale_factor=130,
            emoji_position_offset=(-1, -1),
        )
        image.save("emoji.png", "PNG")

The image is finally the expected output:
emoji

P.S. I have lost sleep and 5 years off my life because of this absurd bug

Not working with Pillow v10

The module is not working with Pillow v10 when trying to add text.

This is the error:

Traceback (most recent call last):

  File "/root/venv/lib/python3.11/site-packages/lightbulb/app.py", line 1162, in invoke_application_command
    await context.invoke()

  File "/root/venv/lib/python3.11/site-packages/lightbulb/context/base.py", line 334, in invoke
    await self.command.invoke(self)

  File "/root/venv/lib/python3.11/site-packages/lightbulb/commands/base.py", line 798, in invoke
    await self(context, **kwargs)

  File "/root/venv/lib/python3.11/site-packages/lightbulb/commands/base.py", line 712, in __call__
    return await self.callback(context, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/root/runner/public/iodine/cogs/leveling.py", line 463, in rank
    name(im, str(member))

  File "/root/runner/public/iodine/cogs/leveling.py", line 425, in name
    pilmoji.text(

  File "/root/venv/lib/python3.11/site-packages/pilmoji/core.py", line 296, in text
    width, _ = font.getsize(content)
               ^^^^^^^^^^^^

AttributeError: 'FreeTypeFont' object has no attribute 'getsize'

Add alignment support

I'm using this bot to render text to an image as part of a confessions bot for Instagram, but it doesn't support alignment modes, because "some parameters have not been implemented yet." Please implement this one asap, I'm trying to do it myself too but I'm having trouble figuring out a way to do it based on Pillow's implementation.

Solve problem with the anchor

I have a code with some texts, in all of them the emojis work but in one that has an anchor it does not work.

Here is my code:

w, h = Pilmoji(base).getsize(f"{d['rank']}", font(65), spacing=2, emoji_scale_factor=1.15)
        base = text(base, (1162 - w, 65), "Rank: ", font(55), colour="white", stroke_fill="black")
        base = text(base, (1322, 100), f"{txt if txt_c == txt else f'{txt_c}...'}", font(65), colour=color, stroke_fill="black", anchor="rm", pos=(-30, -30))

IMG_20230102_195442

There is a problem about import Pilmoji

from pilmoji import Pilmoji
File "/usr/local/lib/python3.8/dist-packages/pilmoji/init.py", line 1, in
from . import helpers, source
File "/usr/local/lib/python3.8/dist-packages/pilmoji/helpers.py", line 7, in
from emoji import EMOJI_UNICODE
ImportError: cannot import name 'EMOJI_UNICODE' from 'emoji' (/usr/local/lib/python3.8/dist-packages/emoji/init.py)

My system is Ubuntu 20.04 ,pilmoji version: 2.0.1
What can I do?

Pilmoji not working with any emojis source

I've encountered an issue where Pilmoji doesn't seem to be working properly with all emoji sources. I've tried using various emoji sources, but the functionality is still not working.

Code Snippet:

response = requests.get(template_path)
img = Image.open(BytesIO(response.content))

width, height = img.size
draw = ImageDraw.Draw(img)
textsize = 34
string = textwrap.wrap(string, width=40)

font = ImageFont.truetype("./resources/upload_image/assets/fonts/Comfortaa-Regular.ttf", textsize)

string_prefix = ["[{}]".format(id), ""]
end_string = string_prefix + string
h = (height - len(end_string)*(textsize+16))/2
for line in end_string:
    a,b = draw.textsize(line, font=font)
    try:
        with Pilmoji(img) as pilmoji:
            pilmoji.text((int((width-a)/2),int(h)), line, (0,0,0), font, align='center', emoji_scale_factor=1, emoji_position_offset=(0, 2))
    except Exception as e:
        # Add error handling
        raise ConnectionError(e, request=request)
    h += textsize + 16
    img.save('./resources/upload_image/assets/img/out/sample-out.jpg')
return True

Error Message:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='emojicdn.elk.sh', port=443): Max retries exceeded with url: /%E2%9D%A4%EF%B8%8F?style=twitter (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000001FD97850520>: Failed to establish a new connection: [WinError 10060]

Additional Information:
Python Version: 3.8
Operating System: Win11
Pilmoji Version: 2.0.4

pilmoji-2.0.2 ImageFont.TransposedFont

pilmoji-2.0.2 ImageFont.TransposedFont

ex. font.size (lines 310, 318)
ex. text node rendering lines (lines 317, 318)

will not execute correctly (for font.size in ImageFont.TransposedFont the size is font.font.size, for rendering lines the orientation affects the coordinates)

SYNTAX ERROR coming from the package

The code:
from pilmoji import Pilmoji
The error:
File "/usr/local/lib/python3.7/dist-packages/pilmoji/sync/core.py", line 103 asset = asset.resize((width := int(emoji_size_factor * font.size), width), Image.ANTIALIAS) ^ SyntaxError: invalid syntax

From my observation, the error came from the package.
@jay3332

Pilmoji's line spacing is the not the same as Pillow's

Both of these have line spacing of 28, yet Pilmoji's output looks shorter than Pillow's.
The image on the left is made with Pilmoji's text() and the one on the right is made with PIllow's ImageDraw.multiline_text()
The thin rectangle is the size that ImageDraw.textsize() gives me. You can see that Pillow lines up with the rectangle but Pilmoji doesn't.
download

This is the code I'm using. I'm making it for a Discord bot.

    @commands.command()
    async def superchat2(self, ctx, amount, *, message):  
      await ctx.message.delete()
      ###TOP BOX
      img = Image.new('RGBA', (1760, 240), color = (208,0,0,255))

      blank = Image.new("RGBA", (1760, 240), (255, 255, 255, 0))
      draw = ImageDraw.Draw(blank)
      fnt = ImageFont.truetype("fonts/Roboto-Medium.ttf", 57)
      draw.text((287, 40),ctx.author.name,font=fnt, fill=(255, 255, 255, 179))

      blank2 = Image.new("RGBA", (1760, 240), (255, 255, 255, 0))
      draw2 = ImageDraw.Draw(blank2)
      fnt2 = ImageFont.truetype("fonts/Roboto-Medium.ttf", 60)
      draw2.text((288, 124),amount,font=fnt2, fill=(255, 255, 255, 255))


      out = Image.alpha_composite(img, blank)
      out = Image.alpha_composite(out, blank2)

      mask = Image.open('masks/circle-mask.png').convert('L')
      response = requests.get(ctx.message.author.display_avatar.url)
      byteio = io.BytesIO(response.content)
      im = Image.open(byteio)      
      imgoutput = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
      byteio.close()
      imgoutput.putalpha(mask)
      blank3 = Image.new("RGBA", (1760, 240), (255, 255, 255, 0))
      blank3.paste(imgoutput, (64, 33))
      out = Image.alpha_composite(out, blank3)

      ###BOTTOM BOX
      msg_split = textwrap.wrap(message,width=57)

      img = Image.new('RGBA', (1760, 152), color = (230,33,23,255))
      draw = ImageDraw.Draw(img)
      fnt = ImageFont.truetype("fonts/merged.ttf", 60)

      text_size = draw.textsize('\n'.join(msg_split), font=fnt,spacing=28)

      txt_height = int(re.search(r'(?<=, )\d+',str(text_size)).group())
      txt_width = int(re.search(r'\d+(?=, \d+\))',str(text_size)).group())
      print(f"text heigh: {txt_height}")      
      if len(msg_split) == 1:
        print("one line")
      else:
        print("more than one line")
        img = img.resize((1760,txt_height+62))
      draw = ImageDraw.Draw(img)
      draw.rectangle([(64, 31), (64+txt_width,31+txt_height)],outline ="black")

      #PIL
      # draw.multiline_text((64, 31), '\n'.join(msg_split), fill=(255, 255, 255, 255), font=fnt,spacing=28)


      #PILMOJI
      with Pilmoji(img) as pilmoji:
        pilmoji.text((64, 31), '\n'.join(msg_split), fill=(255, 255, 255, 255), font=fnt,spacing=28)


      dst = Image.new('RGB', (out.width, out.height + img.height))
      dst.paste(out, (0, 0))
      dst.paste(img, (0, out.height))
      byteio = io.BytesIO()
      byteio.seek(0)
      dst.save(byteio,format='PNG')
      byteio.seek(0)
      await ctx.send(file=disnake.File(byteio,filename='superchat.png'))
      byteio.close()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.