This assumes your files are `.jpg` files in a 1-deep tree, so example filenames are `my_folder_1/my_image.jpg`. Accessing the url `http://the_server:4000/next` returns a simple json document of the form `{ "path": "path_to/image.jpg" }`. Accessing `http://the_server:4000/` returns the html below, and accessing a url ending in `.jpg` attempts to serve the file. The image slides left-right or up-down depending on aspect ratios, as a kind of poor-man's Ken Burns effect. (At some point I may try to write a proper Ken Burns implementation, and crossfade between images.) ## Python server ```python #!/usr/bin/env python3 # Python 3 server example from http.server import BaseHTTPRequestHandler, HTTPServer from subprocess import run, PIPE import time import sys import re import random import os import json from glob import glob from datetime import datetime from threading import Thread hostName = "" serverPort = 4000 index_html = open("index.html").read() files_glob = "*/*.jpg" print(f"Indexing") files = glob(files_glob) def refresh_worker(): global files files = glob(files_glob) class MyServer(BaseHTTPRequestHandler): def homepage(self): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes(index_html, "utf-8")) def refresh(self): Thread(target=refresh_worker) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes("refresh requested", "utf-8")) def nextimg(self): src = random.choice(files) d = { "path": f"/{src}" } self.send_as_json(d) def sendimg(self,src): print(f"img {src}") if os.path.exists(src): self.send_response(200) self.send_header("Content-type", "image/jpeg") self.end_headers() with open(src,"rb") as f: self.wfile.write(f.read()) else: self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes(f"File {src} not found","utf8")) def send_as_json(self,d,response_code=200): j = json.dumps(d) self.send_json(j,response_code) def send_json(self,j,response_code=200): self.send_response(response_code) self.send_header("Content-type", "application/json") self.end_headers() self.wfile.write(bytes(j, "utf-8")) def do_GET(self): if self.path == "/favicon.ico": self.send_response(404) self.end_headers() self.wfile.write(b"No favicon") p = self.path.strip("/") if p == "": return self.homepage() if p == "next": return self.nextimg() if p == "refresh": return self.refresh() if p.endswith(".jpg"): return self.sendimg(p) if p == "quit": self.send_response(400) self.end_headers() self.wfile.write(b"Quitting") self.server.server_close() else: self.send_response(400) self.end_headers() self.wfile.write(b"Bad request") if __name__ == "__main__": print(f"Starting server") webServer = HTTPServer((hostName, serverPort), MyServer) print("Server started http://%s:%s" % (hostName, serverPort)) try: webServer.serve_forever() except KeyboardInterrupt: pass webServer.server_close() print("Server stopped.") ``` ## Python Server for Zip Files Launch this `server.py` in a folder containing .zip files of `.jpg` images, and it will serve those without needing to decompress beforehand. ```python #!/usr/bin/env python3 # Python 3 server example from http.server import BaseHTTPRequestHandler, HTTPServer from subprocess import run, PIPE import time import sys import re import random import os import json from glob import glob from datetime import datetime from threading import Thread import zipfile hostName = "" serverPort = 4000 zips_glob = "*.zip" print(f"Indexing") zips = [] files = [] def refresh_worker(): global zips global files nzips = glob(zips_glob) nfiles = [] for z in nzips: with zipfile.ZipFile(z) as f: for n in f.namelist(): if n.endswith(".jpg"): nfiles.append((z,n)) zips = nzips files = nfiles refresh_worker() class MyServer(BaseHTTPRequestHandler): def homepage(self): index_html = open("index.html").read() self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes(index_html, "utf-8")) def refresh(self): Thread(target=refresh_worker) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes("refresh requested", "utf-8")) def nextimg(self): src = random.choice(files) z,n = src d = { "path": f"/{z}/{n}" } self.send_as_json(d) def sendimg(self,src): print(f"img {src}") z, n = src.split("/",1) print(f"{z=} {n=}") if os.path.exists(z): with zipfile.ZipFile(z) as f: print(f"Opened zip") try: with f.open(n,"r") as g: data = g.read() self.send_response(200) self.send_header("Content-type", "image/jpeg") self.end_headers() self.wfile.write(data) return except Exception as e: print(f"Exception {e}") self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes(f"File {src} not found","utf8")) def send_as_json(self,d,response_code=200): j = json.dumps(d) self.send_json(j,response_code) def send_json(self,j,response_code=200): self.send_response(response_code) self.send_header("Content-type", "application/json") self.end_headers() self.wfile.write(bytes(j, "utf-8")) def do_GET(self): if self.path == "/favicon.ico": self.send_response(404) self.end_headers() self.wfile.write(b"No favicon") p = self.path.strip("/") if p == "": return self.homepage() if p == "next": return self.nextimg() if p == "refresh": return self.refresh() if p.endswith(".jpg"): return self.sendimg(p) if p == "quit": self.send_response(400) self.end_headers() self.wfile.write(b"Quitting") self.server.server_close() else: self.send_response(400) self.end_headers() self.wfile.write(b"Bad request") if __name__ == "__main__": print(f"Starting server") webServer = HTTPServer((hostName, serverPort), MyServer) print("Server started http://%s:%s" % (hostName, serverPort)) try: webServer.serve_forever() except KeyboardInterrupt: pass webServer.server_close() print("Server stopped.") ``` ## HTML Javascript client ```html Slideshow ``` ## HTML Client With Improved Ken Burns effect ```html Slideshow ```