#!/usr/bin/python3
import struct
import socket
import tkinter as tk
from io import BytesIO
from sys import exit, stdout
from time import sleep, strftime
from PIL import Image, ImageTk
from threading import Thread
def printD(message):
print('[{}] {}'.format(strftime('%H:%M:%S'), message))
stdout.flush()
class PiVideoStream(object):
def __init__(self, master, host='127.0.0.1', port=8000):
self.master = master
self.host = host
self.port = port
self.running = False
def start(self):
self.client_socket = socket.socket()
self.client_socket.connect((self.host, self.port))
# Make a file-like object out of the connection
self.connection = self.client_socket.makefile('rb')
self.running = True
Thread(target=self.update, args=()).start()
sleep(0.2) #give videostream some time to start befor frames can be read
def update(self):
if self.running == False:
return
# Read the length of the image as a 32-bit unsigned int.
image_len = struct.unpack('<L', self.connection.read(struct.calcsize('<L')))[0]
if image_len:
print('Updating')
print('image_len: %s' % image_len)
image_stream = BytesIO()
image_stream.write(self.connection.read(image_len))
image_stream.seek(0)
# print('Frame received:')
# print(str(image_stream.read()))
newImage = ImageTk.PhotoImage(Image.open(image_stream))
self.master.stream_label.configure(image=newImage)
self.master.stream_label.image = newImage
def quit(self):
try: self.stop()
except: pass
def stop(self):
# indicate that the thread should be stopped
self.running = False
try: self.connection.close()
except: pass
try: self.client_socket.close()
except: pass
class GUI(object):
def __init__(self, resolution="640x480", stream_resolution=(320, 240), host='127.0.0.1', port=8000):
self.host = host
self.port = port
self.gui_resolution = resolution
self.stream_resolution = stream_resolution
self.running = False
self.master = tk.Tk()
self.master.protocol("WM_DELETE_WINDOW", self.quit)
self.main()
def main(self):
self.videostream = PiVideoStream(master=self, host=self.host, port=self.port)
self.master.geometry(self.gui_resolution)
self.master.title("picamera network stream to tkinter")
self.startstop_button = tk.Button(master=self.master, text="Start", bg="green", command=self.startstop_stream)
self.startstop_button.place(x=10, y=10, height=50, width=50)
self.stream_label = tk.Label(master=self.master)
self.stream_label.place(x=60, y=10)
self.exit_button = tk.Button(master=self.master, bg="#229", fg="white", text="Exit", command=self.quit)
self.exit_button.place(x=10, y=200, height=50, width=50)
def startstop_stream(self):
# start
if self.running == False:
printD("Start")
self.startstop_button.config(bg="red", text="Stop")
self.running = True
self.videostream.start()
# stop
else:
printD("Stop")
self.startstop_button.config(bg="green", text="Start")
self.running = False
self.videostream.stop()
def run(self):
self.master.mainloop()
def quit(self):
self.running = False
self.videostream.quit()
self.master.destroy()
print('Quit')
def main(DEBUG=True):
screen_width = 400
screen_height = 300
stream_resolution = (320, 240)
try:
tkinter_app = GUI(host='192.168.0.12', port=8000, resolution="{0}x{1}".format(screen_width, screen_height), stream_resolution=stream_resolution)
tkinter_app.run()
except (KeyboardInterrupt, SystemExit):
print('Quit')
tkinter_app.quit()
except Exception as error:
print('Error: ' + str(error))
exit()
if __name__ == '__main__':
main()
#EOF