最初に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というのは微調整をした結果なので適宜変えた方が良い。
画像は前回と同じ。
時間はそれなりにかかる。
うまくいけば
このようになる。
前回よりも近づいたのでは?
ちなみに
文字だけでいいなら絵文字に対する処理が要らず、画像を保存する必要もなく、ただ文字を書けばいいので、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)