How to show time in an image ?
We could liquify clocks or just use timelapse-video. But we can do this better in one frame.
We can just take many pictures of the same subject and capture them at different times.
This is the image we want:
All we need is a small python-script.
What it should do:
- process JPG-files
- clculate column-widths
- Alert, if there are more images than pixel
- even distribution of leftover pixels
- Tell us how big a single slice will be.
- (optional) process subdirectories recursively
- input ans output-images are the same size
- Alert if the image size varies.
- import-folder path
- booloean, if subdirectories should be processed (default: false)
- (optional) output-filename
We start by checking if the given directory exists and process the other arguments. If anything is unexpected, we stop and alert the user.
# Main if __name__ == "__main__": path = sys.argv path = os.path.abspath(path) if not os.path.isdir(path): sys.exit("Path is not a directory or does not exist.") rec = sys.argv name = "" # if len(sys.argv) > 3: name = sys.argv if rec == "True": get_dir(path) else: process_dir(path, name)
Single folders will always only be processed by process_dir()
Lets collect the relevant directories:
def get_dir(path): dir =  for currentpath, folders, files in os.walk(path): for folder in folders: print(os.path.join(currentpath, folder)) dir.append(os.path.join(currentpath, folder)) for d in dir: print("Processing " + str(d)) process_dir(d, "")
First we set up an array, which will be our ToDo-list.
We add every subfolder to this list and print it out, so we could cancel before we start processing.
After this, a single directory ist given to process_dir() and we pint out what we are currently processing.
def process_dir(d, name): files =  images =  # Load Image (JPEG/JPG needs libjpeg to load) for file_name in sorted(glob.iglob(d + '/*.jpg', recursive=True)): files.append(file_name) # check if folder contains no images if not files: print("This folder contains no images.") return if check_files(files): print("All images have the same size.") else: print("Not all images have the same size.") return print("Processing " + str(len(files)) + " images.") # Slice and save new = slice(files) print("Saving image...") filename = "" if name == "": filename = str(d).replace("/", '_') else: filename = name.replace("/", '_') p = "output/" + filename.replace("\\", '_') save_image(new, p + '.png') print(p + ".png is ready.")
First we collect all image files. If a directory doesn’t contain any images, we just carry on with the ToDo-list.
def check_files(files): width, height = open_image(files).size if len(files) > width: print("To many images. Each slice would be smaller than 1px.") return print("The output image will be " + str(width) + "x" + str(height)) for x in files: w, h = open_image(x).size if w != width or h != height: return False return True
We make sure, that all pictures in a series have the same aspect ratio. If there are more pictures than available pixel (width of a picture) we can’t proceed and will inform te user about the problem. (Otherwise the slices would be smaller than 1px).
After checking all files, we can begin processing. All process_dir does afer processing ist taking care of the filename and saving of the final image.
If no output-filename is given, we will use the name of the directory.
slice() – Where the magic happens
def slice(files): # Get size width, height = open_image(files).size # calculate slices s = int((width / len(files))) print("Each slice will be " + str(s) + "pixel wide.") slices =  for x in files: slices.append(s) if (s * len(files)) < width: print("Distributing lextover columns.") leftover = width - (s * len(files)) print(str(leftover)) for i in range((len(files) - 1), 0, -1): if leftover > 0: slices[i] = slices[i] + 1 leftover = leftover - 1 print("Image " + str(i) + " will be 1px bigger.") # slices[len(files) - 1] = slices[len(files) - 1] + (width - (s * len(files))) print("Leftover pixel-columns were distributed evenly among the leftmost slices.") # Create new Image and a Pixel Map new = create_image(width, height) pixels = new.load() current = 0 # column c = 0 for row in slices: pic = open_image(files) print("Slicing image " + str(c + 1) + " - " + str(slices) + " Pixels wide.") for i in range(current, current + row): for j in range(height): # print(str(c+1) + " - " + str(i) + " - " + str(j)) # Set Pixel in new image pixels[i, j] = get_pixel(pic, i, j) c = c + 1 current = current + row # Return new image return
We need to calculate how big our slices will be. Leftover pixels will be evenly distributedby adding single pixels to each slice starting left. After creating a new image, we walk through all pixel-columns und check where these pixels will come from. These pixels will be copied from the origin-image.
You can find the whole script on github to try it whith your own images.