Orientation:
I created the following functions, allowing the user to change the turtle to an image of their choice, and then stamp it on the canvas at any point:
def TurtleShape(): try: # Tkinter buttons related to turtle manipulation manipulateimage.config(state = NORMAL) flipButton.config(state = NORMAL) mirrorButton.config(state = NORMAL) originalButton.config(state = NORMAL) resetturtle.config(state = NORMAL) rotateButton.config(state = NORMAL) # Ask user for file name from tkinter file dialog, and return file name as `klob` global klob klob = filedialog.askopenfilename() global im # Open `klob` and return as `im` im = Image.open(klob) # Append `im` to pictures deque pictures.append(im) # Clear `edited` deque edited.clear() # Save `im` as an image, then register image as shape, and finally set image as turtle shape im.save(klob + '.gif', "GIF") register_shape(klob + '.gif') shape(klob + '.gif') update() except: # If user selects cancel in file dialog, then pass pass def StampPic(): stamp() draw_space() # Go forward 100 pixels with pen up after every stamp update()
The image can also be manipulated by the user by selecting the following functions:
Resize function . This function works either as a first or secondary function. The first means that it is called initially, and the secondary - edits an already edited image. Thus, if ONLY is called first, this function will take the image added to the pictures deque, resize it and output the edited image as a .gif image, which will become the new turtle shape. However, if you call two or more times in a row, due to a problem where resizing the same image more than once will result in a distorted image, I had to create another deque jiop that saves the original element from the pictures deque, and any the time this function is called more than once in a row, this original image changes every time, instead of the same image every time. But, if ONLY called a secondary function, then the function will simply output the current image from the edited deque, resize that image, and then set it as the new turtle shape:
def TurtleImageResize(): if not hasattr(TurtleImageResize, "counter"): TurtleImageResize.counter = 0 TurtleImageResize.counter += 1
Functions flip, rotate and mirror . They work much easier than the resize function above. If they are called initially, each of them will take an image with pictures deque, process it, add the edited image to deque edited , and then change the โshapeโ of the turtle to this new image. However, if they are called secondly, each of them will take the image with the edited deque, manipulate it, add the processed image back to the edited deque again, and then set it as the new "shape" of the turtle. These features are shown below:
def flippic(): if not hasattr(flippic, "counter"): flippic.counter = 0 flippic.counter += 1 try: # Secondary step: Take previously edited image from `edited` deque, manipulate that, and append newly edited image to the `edited` deque jiop.clear() ghy = edited.pop() # Flip image over horizontal line kpl = ImageOps.flip(ghy) edited.append(kpl) print("Jlop") except: # Initial step: Take image appended to `pictures` deque from `TurtleShape` function, then edit that and append newly edited image to both `editpic` and `pictures` neer = pictures.pop() # Flip image over horizontal line kpl = ImageOps.flip(neer) pictures.append(kpl) edited.append(kpl) print("Yup") # Save image as `.gif` kpl.save(klob + str(flippic.counter) + '.gif', "GIF") # Register image as a shape, and use it as shape of turtle register_shape(klob + str(flippic.counter) + '.gif') shape(klob + str(flippic.counter) + '.gif') update() def mirror(): if not hasattr(mirror, "counter"): mirror.counter = 0 mirror.counter += 1 try: jiop.clear() jui = edited.pop() # Flip image over vertical line fgrt = ImageOps.mirror(jui) edited.append(fgrt) except: bbc = pictures.pop() # Flip image over vertical line fgrt = ImageOps.mirror(bbc) pictures.append(fgrt) edited.append(fgrt) fgrt.save(klob + str(mirror.counter) + ".gif") register_shape(klob + str(mirror.counter) + ".gif") shape(klob + str(mirror.counter) + ".gif") update() def rotatePic(): if not hasattr(rotatePic, "counter"): rotatePic.counter = 0 rotatePic.counter += 1 try: jiop.clear() lmcb = edited.pop() # Rotate image 90ยบ right fetch = lmcb.rotate(-90, expand = True) edited.append(fetch) except: bolt = pictures.pop() # Rotate image 90ยบ right fetch = bolt.rotate(-90, expand = True) pictures.append(fetch) edited.append(fetch) fetch.save(klob + str(rotatePic.counter) + ".gif") register_shape(klob + str(rotatePic.counter) + ".gif") shape(klob + str(rotatePic.counter) + ".gif") update()
Thus, ALL editing functions work together essentially with the same main image.
Problem:
Now think that the user wants to take the image of the turtle, and then resize it to a size, for example, 800x400, and mark it in a specific place on the canvas. After that, the user decides to move the image of the turtle to another place on the canvas, flip the image and then print the image. Should there now be two images? One stamp and another rolled over? However, for some reason this is not the case with my program . . Instead, the stamped image disappears when the user flips the turtle image, even if there is no clear() function anywhere (to show what I mean, refer to edit below). Obviously, this problem ONLY occurs after the TurtleImageResize function is TurtleImageResize .
What is wrong with my TurtleImageResize function that leads to this problem? I completely updated the process of managing images of the turtle to understand what it is now, in the hope that it will fix this problem, that I also tested my previous setup, but, apparently, this is not so. Therefore, any help in this matter is greatly appreciated!
EDIT: The following is a minimal, complete, and verifiable way to reproduce the problem I am facing (MUST have PIL (or Pillow) and GhostScript for this to work) :
import os,shutil,subprocess, sys her = sys.platform if her == "win32": print("Windows is your Operating System") win_gs = ["gs","gswin32c","gswin64c"] if all( shutil.which(gs_version) is None for gs_version in win_gs ): paths = ["C:\\Program Files\\gs\\gs9.18\\bin","C:\\Program Files (x86)\\gs\\gs9.18\\bin"] for path in (x for x in paths if os.path.exists(x)): os.environ["PATH"] += ";" + path break if any( shutil.which(gs_version) for gs_version in win_gs ): print("GhostScript 9.18 for Windows found and utilized") else: print("You do not have GhostScript 9.18 installed for Windows. Please install it.") sys.exit(0) else: print("GhostScript 9.18 for Windows found and utilized") elif her == 'darwin': print("Macintosh is your Operating System") if shutil.which("gs") is None: os.environ["PATH"] += ":/usr/local/bin" if shutil.which("gs") is None: print("You do not have GhostScript installed for Macintosh. Please install it.") sys.exit(0) else: print("GhostScript for Macintosh found and utilized") from turtle import * from tkinter import * try: import tkinter.filedialog as filedialog except ImportError: pass import collections from PIL import Image, ImageEnhance, ImageOps jiop = collections.deque() pictures = collections.deque() edited = collections.deque() picwidth = collections.deque() picheight = collections.deque() def draw_space(): # Draw a space 200 pixels wide. penup() forward(200) pendown() def TurtleShape(): try: manipulateimage.config(state = NORMAL) flipButton.config(state = NORMAL) mirrorButton.config(state = NORMAL) rotateButton.config(state = NORMAL) global klob klob = filedialog.askopenfilename() global im im = Image.open(klob) pictures.append(im) edited.clear() im.save(klob + '.gif', "GIF") register_shape(klob + '.gif') shape(klob + '.gif') update() except AttributeError: pass def TurtleImageResize(): if not hasattr(TurtleImageResize, "counter"): TurtleImageResize.counter = 0 TurtleImageResize.counter += 1 width = im.size[0] height = im.size[1] NewOne2 = numinput('Width of Image', 'Set the width of the image: ', minval = 1) NewOne = numinput('Height of Image', 'Set the height of your image: ', minval = 1) Picwidth = NewOne2 if NewOne2 != None else width picwidth.append(Picwidth) Picheight = NewOne if NewOne != None else height picheight.append(Picheight) try: try: hye = jiop.pop() jiop.append(hye) except: hye = edited.pop() jiop.append(hye) editpic = hye.resize((int(Picwidth), int(Picheight)), Image.ANTIALIAS) edited.append(editpic) pictures.append(editpic) except: geer = pictures.pop() editpic = geer.resize((int(Picwidth), int(Picheight)), Image.ANTIALIAS) jiop.append(geer) edited.append(editpic) pictures.append(editpic) editpic.save(klob + str(TurtleImageResize.counter) + '.gif', 'GIF') register_shape(klob + str(TurtleImageResize.counter) + '.gif') shape(klob + str(TurtleImageResize.counter) + '.gif') update() def flippic(): if not hasattr(flippic, "counter"): flippic.counter = 0 flippic.counter += 1 try: jiop.clear() ghy = edited.pop() kpl = ImageOps.flip(ghy) edited.append(kpl) pictures.append(kpl) print("Jlop") except: neer = pictures.pop() kpl = ImageOps.flip(neer) pictures.append(kpl) edited.append(kpl) print("Yup") kpl.save(klob + str(flippic.counter) + '.gif', "GIF") register_shape(klob + str(flippic.counter) + '.gif') shape(klob + str(flippic.counter) + '.gif') update() def mirror(): if not hasattr(mirror, "counter"): mirror.counter = 0 mirror.counter += 1 try: jiop.clear() jui = edited.pop() fgrt = ImageOps.mirror(jui) edited.append(fgrt) pictures.append(fgrt) except: bbc = pictures.pop() fgrt = ImageOps.mirror(bbc) pictures.append(fgrt) edited.append(fgrt) fgrt.save(klob + str(mirror.counter) + ".gif") register_shape(klob + str(mirror.counter) + ".gif") shape(klob + str(mirror.counter) + ".gif") update() def rotatePic(): if not hasattr(rotatePic, "counter"): rotatePic.counter = 0 rotatePic.counter += 1 try: jiop.clear() lmcb = edited.pop() fetch = lmcb.rotate(-90, expand = True) edited.append(fetch) pictures.append(fetch) except: bolt = pictures.pop() fetch = bolt.rotate(-90, expand = True) pictures.append(fetch) edited.append(fetch) fetch.save(klob + str(rotatePic.counter) + ".gif") register_shape(klob + str(rotatePic.counter) + ".gif") shape(klob + str(rotatePic.counter) + ".gif") update() def StampPic(): stamp() draw_space() update() def move_turtle(): # Pick up the turtle and move it to its starting location. penup() goto(-200, 100) pendown() def settings(): # Tkinter buttons turtlepic = Button(text = "Set Turtle Image", command = TurtleShape) turtlepic.pack(side = 'left') stampimage = Button(text = "Stamp", command = StampPic) stampimage.pack(side = 'left') global manipulateimage manipulateimage = Button(text = "Resize Turtle Image", command = TurtleImageResize, state = DISABLED) manipulateimage.pack(side = 'left') global flipButton flipButton = Button(text = "Flip image", command = flippic, state = DISABLED) flipButton.pack(side = 'left') global mirrorButton mirrorButton = Button(text = "Mirror Image", command = mirror, state = DISABLED) mirrorButton.pack(side = 'left') global rotateButton rotateButton = Button(text = "Rotate Image", command = rotatePic, state = DISABLED) rotateButton.pack(side = 'left') def skip(x, y): penup() goto(x, y) pendown() update() move_turtle() settings() speed(0) tracer(0, 0) onscreenclick(skip) if sys.platform == 'win32': input() else: pass
If / if both GhostScript and PIL (or pillow) are installed on your system, to reproduce my problem, follow these steps (all steps are required , except for step No. 4):
Click the Set Turtle Image button at the bottom of the window, select any image you want to make a turtle, and then click Open . The turtle gets this image.
Resize the image to 800x400 (or any other size) by clicking the Resize turtle Image button at the bottom of the screen. Two dialogs will appear. In the first dialog box, enter a width of 800 (or your own width), and then enter a height of 400 (or your own height) in the second dialog box, and after you finish, the image will resize to fit the dimensions provided (or set the image back to initial measurement (dimensions) depending on whether you click cancel).
Select the Stamp button at the bottom of the window. The image is applied to the canvas, and the turtle moves forward 400 pixels โbehindโ the stamped image.
OPTIONAL: click anywhere on the canvas to take the turtle to this place.
Flip / Mirror / Rotate Image.
As you can see, after doing all this, just as you flip / flip the image, the stamped image just disappears. What is wrong with my TurtleImageResize function that calls this?
EDIT # 2: Just in case this information is useful, I am running Python 3.5.1 on Macintosh with OS version 10.11.2 (El Capitan).