When trying to save a tkinter canvas using PIL, it works as expected when the canvas background is set to "white"
and fill option for the created lines to "black"
but when setting the canvas background to "black"
and the fill parameter of created lines to "white"
, the saved image will just be a solid color (white). Why does this happen?
Python 3.11.8
pillow==10.2.0
import tkinter as tk
import io
from PIL import Image
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.line_start = None
self.canvas = tk.Canvas(self, width=300, height=300, bg="white")
self.canvas.bind("<Button-1>", lambda e: self.draw(e.x, e.y))
self.button = tk.Button(self, text="save", command=self.save)
self.canvas.pack(fill="both", expand=True)
self.canvas.focus_set()
self.button.pack(pady=10)
def draw(self, x, y):
if self.line_start:
x_origin, y_origin = self.line_start
self.canvas.create_line(x_origin, y_origin, x, y, fill="black")
self.line_start = x, y
def save(self):
ps = self.canvas.postscript(colormode="color")
img = Image.open(io.BytesIO(ps.encode("utf-8")))
img.save("working.png")
app = App()
app.mainloop()
import tkinter as tk
import io
from PIL import Image
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.line_start = None
self.canvas = tk.Canvas(self, width=300, height=300, bg="black")
self.canvas.bind("<Button-1>", lambda e: self.draw(e.x, e.y))
self.button = tk.Button(self, text="save", command=self.save)
self.canvas.pack(fill="both", expand=True)
self.canvas.focus_set()
self.button.pack(pady=10)
def draw(self, x, y):
if self.line_start:
x_origin, y_origin = self.line_start
self.canvas.create_line(x_origin, y_origin, x, y, fill="white")
self.line_start = x, y
def save(self):
ps = self.canvas.postscript(colormode="color")
img = Image.open(io.BytesIO(ps.encode("utf-8")))
img.save("white.png")
app = App()
app.mainloop()
The contents of this article may apply to you.
Canvas background color not saved
I don't believe the
postscript
command is designed to preserve the background color of the canvas widget. It only saves the items that appear on the canvas.A simple solution is to draw a rectangle that is the exact size of the canvas, and change the color of that rectangle.
So, you just need to add the following line to the source of the saves fully white image in the question.
self.canvas = tk.Canvas(self, width=300, height=300, bg="black")
self.canvas.create_rectangle(0, 0, 300, 300, fill='black') #### added this line
self.canvas.bind("<Button-1>", lambda e: self.draw(e.x, e.y))