pythoncanvastkinterbitmap

how to maintain canvas size when converting python turtle canvas to bitmap


I want to convert a Python Turtle module (tkinter) canvas into a bitmap. I have followed the suggestion at "How to convert a Python tkinter canvas postscript file to an image file readable by the PIL?" to convert it first to postscript; then I open it as a PIL image, then save that as a bitmap. But the bitmap is a different size from the original canvas.

import turtle
import io
from PIL import Image

myttl = turtle.Turtle()

wd=500
ht=500
turtle.setup(width=wd, height=ht, startx=0, starty=0)    
turtle.mode('logo')        # start pointing north
myttl.forward(100)

screen = turtle.Screen()
cv = screen.getcanvas()
ps = cv.postscript(colormode='mono')
img = Image.open(io.BytesIO(ps.encode('utf-8'))).convert(mode='1')
img.save('test.bmp')

In the above code, the canvas is 500x500. But the file test.bmp is shrunk to 374x374, and its image is smaller than the on-screen turtle graphic. How can I get an unshrunk 500x500 bitmap?


Solution

  • If we start by analyzing the postscript contents, we see that it does a scaling by 0.7498 to the dimensions of your canvas

    %%Page: 1 1
    save
    306.0 396.0 translate
    0.7498 0.7498 scale
    3 -241 translate
    -244 483 moveto 239 483 lineto 239 0 lineto -244 0 lineto closepath clip newpath
    gsave
    grestore
    gsave
    0 239 moveto
    0 339 lineto
    1 setlinecap
    1 setlinejoin
    1 setlinewidth
    [] 0 setdash
    0.000 0.000 0.000 setrgbcolor AdjustColor
    stroke
    grestore
    gsave
    grestore
    gsave
    0 339 moveto
    -5 330 lineto
    0 332 lineto
    5 330 lineto
    0 339 lineto
    0.000 0.000 0.000 setrgbcolor AdjustColor
    eofill
    0 339 moveto
    -5 330 lineto
    0 332 lineto
    5 330 lineto
    0 339 lineto
    1 setlinejoin 1 setlinecap
    1 setlinewidth
    [] 0 setdash
    0.000 0.000 0.000 setrgbcolor AdjustColor
    stroke
    grestore
    restore showpage
    

    After some digging done on postscript I came across a perl/Tk reference guide on postscript conversion from tkinter's canvas here

    What you actually can do is to set not only colormode but also pagewidth/pageheight. This resulted in the following line being changed from

    ps = cv.postscript(colormode='mono')
    

    to

    ps = cv.postscript(colormode='mono', pagewidth=wd-1, pageheight=ht-1)
    

    Result:

    enter image description here

    If you have any questions feel free to leave a comment and I will try my best to reply!

    PS:

    Don't ask me about the -1 part, it wouldn't give me anything other that 501x501 pixels so I compensated for that. I do not know why it still didn't work though.