简体   繁体   中英

PIL not writing text a second time onto image

I'm trying to make a somewhat ambitious hangman game for a discord bot, and for that I need PIL to write in text. After writing some text to an image, and then trying to write text again to that same image, instead of sending the image with the second text added, it only sends the image with the first text. The weird thing is, is that the function goes through, it saves it as a new file with a different name, but no text (the second set, that is). What gives? What am I doing wrong here?

import random, discord
from requests import get as reGet
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont

# Just a random image I found off google, not actually using it
inp_shell = reGet("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Circle_-_black_simple.svg/1200px-Circle_-_black_simple.svg.png")

# Yes, I know, probably not the best place to put the font, I'll change it later
fnt = ImageFont.truetype("modules/Roboto-Regular.ttf", size= 40)

# Opens a list of words that it can get from; The file here is just a stub
with open('words_alpha.txt') as words_file:
    word_list = words_file.read().splitlines()


class img():

    def __init__(self):
        self.open_shell = Image.open(BytesIO(inp_shell.content))

    # Text in the top left
    async def tLeft(self, txt, inp_img):
        image = ImageDraw.Draw(inp_img)
        image.text((10,10), txt, font=fnt, fill=(0, 0, 0))
        self.open_shell.save("tLeft.png")
    
    async def main_text(self, txt, inp_img):
        image = ImageDraw.Draw(inp_img)

        # Used to position the text in the center but currently is not being used
        x, y = inp_img.size 
        pos = x/2

        # I've tried changing the fill and position, and still nothing.
        # This is probably the source of the problem
        image.text((20,20), txt, font=fnt, fill=(255, 255, 255))
        print(txt)
        self.open_shell.save("mainText.png")


# Creates a dictionary with the length of the words assigned as they keys,
# I think anyways, I didn't write this
by_length = {}
for word in word_list:
    by_length.setdefault(len(word), []).append(word)

# Retrieves a random word with a certain length
async def word_finder(wordlength):
    global word
    word = random.choice(by_length[wordlength])
    print(word)
  
# Main function
async def hanggMan(message): #double g in hang is intentional

    content = message.clean_content[11:] 
    print(content) # Just used to make sure it's going through

    # For now I'm using a word length of 5
    if content.lower() == "5":
        z = img() # Calls an instance of the img class

        # Puts the image in an embed; ignore t his
        embed = discord.Embed(title="testtest                                 testtesttesttest") 
        embed.type = "rich"
        embed.colour = discord.Color.gold() 

        await word_finder(5) # Tells the word_finder function to find a random word with a length of 5
        await z.tLeft(txt="tLeft", inp_img= z.open_shell) # Calls the tLeft function and tells it to write "tLeft"

        # Calls the main_text function and tells it to write the word on top of
        # "tLeft.png". There is a print statement in the function and it actually
        # does print the word, so this is not likely to be the source of the problem
        await z.main_text(txt=word, inp_img=Image.open("tLeft.png")) 
        
        embed.set_image(url="attachment://mainText.png")

        # The interesting thing about this is that it actually does save it as "mainText.png"
        # and sends the file properly, but the word is nowhere to be found
        await message.channel.send(embed=embed, file=discord.File("mainText.png"))

I can't run it but when I start removing not imprtant code then I saw you use image in class img() in wrong way.

You always save image which you have in self.open_shell

In first function you send the same image as argument

 z.tLeft(txt="tLeft", inp_img=z.open_shell)

so add text to z.open_shell and you save z.open_shell

But in function you send different image as argument

 z.main_text(txt=word, inp_img=Image.open("tLeft.png"))

so you add text to new image but you save again z.open_shell which has older version.

You need

    self.open_shell = inp_img

Like this

def main_text(self, txt, inp_img):

    self.open_shell = inp_img

    image = ImageDraw.Draw(inp_img)
    image.text((20,20), txt, font=fnt, fill=(255, 255, 255))

    self.open_shell.save("mainText.png")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM