2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pythonでmake it a quoteを作りたい(2)

Last updated at Posted at 2022-05-23

最初にdiscordpyでmake it a quoteを作りたいを書いた。
色々そのあと試行錯誤していろいろ変えることができた。
まず前のでは絵文字に対応していないため絵文字と文字両方が扱えるフォントを探そうと思ったがなかなか見つからず、こんな長いコードになった。
よさそうなフォントがあったら教えてください。
あと、文字をn文字ごとに空白を優先して区切ろうとしていたらtextwrap.wrapというのがあったので使った。
そして文字を中央揃えにした。

最初に

必須のpillowと、絵文字かの判定に使うためのemojiをインストールする。

$ pip install emoji
$ pip install pillow

最終的なコード

import emoji
import textwrap
from PIL import ImageFont,ImageDraw,Image
astr="a🤔🤔 aa🤔🤔aa aa aaaa 🦀🦀 bbb ydudufufuf jansjsjsenenenenwwmwmksk 👌👌🖕🤔😃😃😡😡👌👌 dndndndnsndn jdjsnenesnsn 🤔😃😃👾👾👌🤫🎃"
a=textwrap.wrap(astr,width=20)
def isemoji(em):
  i=em in emoji.UNICODE_EMOJI["en"]
  return i
i=Image.new("RGBA",(200,200),(0,0,0,0))
k=i.resize((1800,1200))
senobi_fnt=ImageFont.truetype("senobi.ttf",109)
emoji_fnt=ImageFont.truetype("NotoColorEmoji.ttf",109)

for i,aa in enumerate(a):
 w,h=0,0
 im=Image.new("RGBA",(1800,200),(0,0,0,0))
 draw=ImageDraw.Draw(im)
 for em in aa:
  if isemoji(em):
    draw.text((w,h),em,font=emoji_fnt,embedded_color=True)
    w1,h1=draw.textsize(em,font=emoji_fnt)
  else:
    w1,h1=draw.textsize(em,font=senobi_fnt)
    draw.text((w,h),em,font=senobi_fnt,fill="#FFF")
  w+=w1
 width,height=im.size
 t=Image.new("RGBA",(w,200),(0,0,0,0))
 for x in range(width):
    for y in range(height):
        pixel = im.getpixel( (x, y) )
        if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0:
            continue
        t.putpixel( (x, y), pixel )
 t.save(f"{i}.png")
d=int(len(a)/2)*120
for n in range(len(a)):
  img=Image.open(f"{n}.png")
  w2,h2=img.size
  k.paste(img,(900-int(w2/2),600-d))
  d-=120

icon=Image.open("yamato.jpeg").convert("L")
back=Image.open("grad.jpeg").convert("L")
black=Image.open("black.jpeg").convert("L")
w5,h5=back.size
black=black.resize((w5*2,h5*2))
to=Image.new("RGBA",black.size)
back=back.resize(black.size)
icon=icon.resize(black.size)
to.paste(icon)
img1=Image.composite(to,black,back)
img1=img1.convert("RGBA")
k=k.resize((int(h5*9/4),int(h5*3/2)))
img1.paste(k,(w5*2-int(h5*9/4),20),k)
img1.save("result.png")

コードの中身

textwrap.wrapはたとえばこういうふうになる

print(textwrap.wrap("abcdabc e fghijk",width=5))
#['abcda', 'bc e ', 'fghij', 'k']

そして絵文字

def isemoji(em):
  return em in emoji.UNICODE_EMOJI['en']

emoji.UNICODE_EMOJIには絵文字一覧が入っている。

あとこれだが

 width,height=im.size
 t=Image.new("RGBA",(w,200),(0,0,0,0))
 for x in range(width):
    for y in range(height):
        pixel = im.getpixel( (x, y) )
        if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0:
            continue
        t.putpixel( (x, y), pixel )
 t.save(f"{i}.png")

これはImage.newで透過画像を作ってもその上に文字を書くと何故か黒に変わるため、元画像のピクセルを取り出し黒以外だったらなにもない画像にそのピクセルを配置するということである。
できれば保存せずに処理をしたいが方法が思いつかない。

あと細かいとこはh5*9/4というのは微調整をした結果なので適宜変えた方が良い。

画像は前回と同じ。
時間はそれなりにかかる。
うまくいけば
0BBBFCEB-82C0-4A0A-8EB4-EE1CF48F72A7.png
このようになる。
前回よりも近づいたのでは?

ちなみに

文字だけでいいなら絵文字に対する処理が要らず、画像を保存する必要もなく、ただ文字を書けばいいので、2、3秒で終わる。
以下、discord botに実装した感じ

@client.command()
async def makequote(ctx,cmd=None):
    msg=ctx.message.reference
    id=msg.message_id
    message=await ctx.fetch_message(id)
    ico=message.author.avatar_url
    url = ico
    file_name = "icon.jpeg"
    await ctx.reply("生成しています")

    response = requests.get(url)
    image = response.content

    with open(file_name, "wb") as aaa:
      aaa.write(image)
    if message.content.replace("\n","").isascii():
        para = textwrap.wrap(message.content, width=23)
    else:
        para = textwrap.wrap(message.content, width=11)
    icon=Image.open("icon.jpeg")
    haikei=Image.open("grad.jpeg")
    black=Image.open("black.jpeg")
    w,h=(680,370)
    w1,h1=icon.size
    haikei=haikei.resize((w,h))
    black=black.resize((w,h))
    icon=icon.resize((h,h))
    if cmd=="color":
      haikei=haikei.convert("L")
      new=Image.new(mode="RGBA",size=(w,h))
      icon=icon.convert("RGBA")
      black=black.convert("RGBA")
    if not cmd:
      haikei=haikei.convert("L")
      new=Image.new(mode="L",size=(w,h))
      icon=icon.convert("L")
      black=black.convert("L")
    icon=icon.crop((40,0,680,370))
    new.paste(icon)
    sa=Image.composite(new,black,haikei)
    draw = ImageDraw.Draw(sa)
    fnt = ImageFont.truetype('senobi.ttf',30) 
    w2,h2=draw.textsize("a",font=fnt)
    i=(int(len(para)/2)*w2)+len(para)*5
    current_h, pad = 120-i, 0
    for line in para:
      if message.content.replace("\n","").isascii():
        w3,h3=draw.textsize(line.ljust(int(len(line)/2+11)," "),font=fnt)
        draw.text((11*(w - w3) / 13, current_h), line.ljust(int(len(line)/2+11)," "), font=fnt,fill="#FFF")
      else:
        w3,h3=draw.textsize(line.ljust(int(len(line)/2+5)," "),font=fnt)
        draw.text((11*(w - w3) / 13, current_h), line.ljust(int(len(line)/2+5)," "), font=fnt,fill="#FFF")
      current_h += h3 + pad
    dr=ImageDraw.Draw(sa)
    font = ImageFont.truetype('nijimi.otf',20)
    dr.text((400,300),f"--{str(message.author)}",font=font,fill="#FFF")
    sa.save("te.png")
    file=discord.File("te.png")
    await ctx.send(file=file)

文献

https://jablogs.com/detail/13065

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?