-1

I am trying to create an image editor that adds text to an image using Pillow. My problem is with saving my edited image so that the user can choose the name of the save file by opening up a save-as dialog. Looking at other questions and answers, I came up with this:

def onOpen(self):
        im = Image.open(askopenfilename())
        caption = simpledialog.askstring("Label", "What would you like the label on your picture to say?")
        fontsize = 15
        if im.mode != "RGB":
            im = im.convert("RGB")

        draw = ImageDraw.Draw(im)
        font = ImageFont.truetype("arial.ttf", fontsize)

        draw.text((0, 0),str(caption),(255,0,0),font=font)

        file = filedialog.asksaveasfile(mode='w', defaultextension=".png")
        if file:
            file.write(im)
            file.close()

However, I get the following error when running it:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Renee\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
  File "C:\Users\Renee\AppData\Local\Programs\Python\Python35-32\tkinterguitest.py", line 52, in onOpen
    file.write(im)
TypeError: write() argument must be str, not Image

I know the issue is that write can only be used with strings, so is there a command, like file.write, but for images?

0

2 Answers 2

3

You should save the image through the save method that is in the Image object:

file = filedialog.asksaveasfile(mode='w', defaultextension=".png")
if file:
    im.save(file) # Saves the image to the input file name.
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the help! unfortunately i'm still receiving an error. This is the error: TypeError: write() argument must be str, not bytes which is strange, since I removed the write argument
specifically it says the error is on line 39, in onOpen im = Image.open(askopenfilename()) and line 52, in onOpen im.save(file) # saves the image to the input file name.
I just realized that the problem is in this line: file = filedialog.asksaveasfile(mode='w', defaultextension=".png", filetypes=(("PNG file", "*.png"),("All Files", "*.*") )) if i open it with wb instead of w it saves, but without the text i wanted on top of it
@Renee , Instead of wb write a
It returned the same error code as it has been. I'm not sure if its significant but if i print the contents of file instead of trying to save it it gives me this: <_io.TextIOWrapper name='C:/Users/Renee/Pictures/testfile.png' mode='a' encoding='cp1252'>
|
2

I finally figured it out.

I ended up creating each component (the image and text) separately and then saving the final image as a composite. Here is the final code:

def onOpen(self):
    im = Image.open(askopenfilename())
    caption = simpledialog.askstring("Label", "What would you like the label on your picture to say?")
    fontsize = 30
    if im.mode != "RGBA":
        im = im.convert("RGBA")
    txt = Image.new('RGBA', im.size, (255, 255, 255, 0))

    draw = ImageDraw.Draw(txt)
    font = ImageFont.truetype("arial.ttf", fontsize)
    draw.text((0, 0), caption, (255, 0, 0), font=font)

    file = filedialog.asksaveasfile(mode='w', defaultextension=".png", filetypes=(("PNG file", "*.png"), ("All Files", "*.*")))
    if file:
        abs_path = os.path.abspath(file.name)
        out = Image.alpha_composite(im, txt)
        out.save(abs_path) # Saves the image to the input file name.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.