title: Why is tkinter "Fail to allocate bitmap" crashing the Spyder kernel after script completes?
body: <p>I have written a short script which emulates a &quot;waterfall&quot; display, wherein a very long image is displayed by scrolling it through a smaller window. My program scrolls two images side-by-side: the first image is uncalibrated, and the second image is a calibrated version of the first image. In practice, these images are generated line-by-line, and would be displayed in (roughly) real time. My emulator is not real time, but just reads in the two images from data files.</p>
  <p>Here is a screen capture of the GUI:
  <a href="https://i.stack.imgur.com/DIER3.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DIER3.png" alt="Screen capture of GUI running" /></a></p>
  <p>I am new to tkinter, and just trying to follow tutorials online to make a simple GUI. The GUI windows are each 300x480 - the two images are ~10000x480 color images with are scrolled through the GUI windows simultaneously.</p>
  <p>The script basically runs as expected until the end.</p>
  <p>After the two images have completed scrolling, in Spyder the kernel dies and is restarted. No error is given other than &quot;Kernel died, restarting&quot;. Running my program from the command line, I get the error &quot;Fail to allocate bitmap&quot; after the script has displayed the full images. I presume the &quot;Fail to allocate bitmap&quot; is what is causing the kernel to die in Spyder, and that it is something I am doing wrong with Tk.</p>
  <p>Here is my (pseudo)code:</p>
  <pre><code>import tkinter 
  from PIL import Image, ImageTk 
  import numpy as np
  import sys
  
  lines = &lt;length of image along one dimension&gt;
  extractedImageArray = &lt;uncalibrated 24-bit image as array of dimension [lines, 480, 3]&gt;
  calibratedImageArray = &lt;calibrated 24-bit image as array of dimension [lines, 480, 3]&gt;
  
  im1 = np.zeros((300,480,3), dtype=np.uint8)
  im2 = np.zeros((300,480,3), dtype=np.uint8)
  
  root = tkinter.Tk()
  root.geometry('960x350+0+0')
  root.title('Waterfall Emulator')
  root.grid_columnconfigure(0, weight=1)
  root.grid_columnconfigure(1, weight=1)
  root.grid_rowconfigure(0,weight=1)
  root.grid_rowconfigure(1,weight=0)
  
  root.button = tkinter.Button(root,text='Quit',command=root.destroy)
  root.button.grid(row=1, column=0, columnspan=2)
          
  for i in range(lines):
      try:
          im1 = np.vstack((im1[1:,:,:],extractedImageArray[i,:,:].reshape((1,480,3))))
          leftImage=ImageTk.PhotoImage(Image.fromarray(im1))
          leftImageLabel = tkinter.Label(image=leftImage)
          leftImageLabel.grid(row=0, column=0, padx=4, pady=4)
          # Store a reference to a PhotoImage object, to avoid it
          # being garbage collected! This is necesary to display the image!
          leftImageLabel.image = leftImage
  
          im2 = np.vstack((im2[1:,:,:],calibratedImageArray[i,:,:].reshape((1,480,3))))        
          rightImage=ImageTk.PhotoImage(Image.fromarray(im2))
          rightImageLabel = tkinter.Label(image=rightImage)
          rightImageLabel.grid(row=0, column=1, padx=4, pady=4)
          # Store a reference to a PhotoImage object, to avoid it
          # being garbage collected! This is necesary to display the image!
          rightImageLabel.image = rightImage
          
          root.update()
      except:
          sys.exit()
          
  root.mainloop()
  </code></pre>
  <p>The program basically does what I need it to, but it's irritating that the kernel dies at the end instead of there being a clean exit. I think the error must be due to my inexperience with tkinter.</p>
  <p>Why is the kernel dying after the script is executed?</p>
  <p>=======================================================</p>
  <p>ADDED:</p>
  <p>For completeness, here is how I modified my script after Martineau's solution: I pulled the button creation outside the loop and now just update the labels.</p>
  <pre><code>&lt;--snip--&gt;
  
  root.button = tkinter.Button(root,text='Quit',command=root.destroy)
  root.button.grid(row=1, column=0, columnspan=2)
  
  leftImage=ImageTk.PhotoImage(Image.fromarray(im1))
  leftImageLabel = tkinter.Label(image=leftImage)
  leftImageLabel.grid(row=0, column=0, padx=4, pady=4)
  
  rightImage=ImageTk.PhotoImage(Image.fromarray(im2))
  rightImageLabel = tkinter.Label(image=rightImage)
  rightImageLabel.grid(row=0, column=1, padx=4, pady=4)
          
  for i in range(lines):
      try:
          im1 = np.vstack((im1[1:,:,:],extractedImageArray[i,:,:].reshape((1,480,3))))
          leftImage=ImageTk.PhotoImage(Image.fromarray(im1))
          leftImageLabel.configure(image=leftImage)
          # Store a reference to a PhotoImage object, to avoid it
          # being garbage collected! This is necesary to display the image!
          leftImageLabel.image = leftImage
  
          im2 = np.vstack((im2[1:,:,:],calibratedImageArray[i,:,:].reshape((1,480,3))))        
          rightImage=ImageTk.PhotoImage(Image.fromarray(im2))
          rightImageLabel.configure(image=rightImage)
          # Store a reference to a PhotoImage object, to avoid it
          # being garbage collected! This is necesary to display the image!
          rightImageLabel.image = rightImage
  </code></pre>