
After playing around with some image manipulation code in Python, I decided it would be fun to publish it as a web app for other people to play around with it!
The original idea is simple: take a random crop of an image (select 4 random points within the bounds of the image). Paste that crop back onto the image in a randomly-selected place. Repeat this process, but take crops from the original image, and paste them onto the latest frame to build up layers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50import argparse from PIL import Image import random import string import os import imageio.v3 as iio NUM_LOOPS = 40 DURATION = 5 def create_images(image_filepath): original = Image.open(image_filepath) img = original.copy() filenames = [] dir_name = ''.join(random.choices( string.ascii_letters + string.digits, k=8)) os.mkdir(dir_name) img.save(f'./{dir_name}/img0.jpg') filenames.append(f'./{dir_name}/img0.jpg') width, height = img.size for i in range(NUM_LOOPS): left = random.randint(0, width) top = random.randint(0, height) right = left + random.randint(0, (width-left)) bottom = top + random.randint(0, (height-top)) crop = original.crop((left, top, right, bottom)) img.paste(crop, (random.randint(0, width), random.randint(0, height))) filename = f'./{dir_name}/img{i+1}.jpg' img.save(filename) filenames.append(filename) images = [] for file in filenames: images.append(iio.imread(file)) iio.imwrite(f"./{dir_name}/animation.gif", images, duration=500, loop=0) if __name__ == "__main__": parser = argparse.ArgumentParser(prog="imageCropReplicator") parser.add_argument("image_file", help="Path to the input image file.") args = parser.parse_args() image_filepath = args.image_file create_images(image_filepath)
Since I'm more well-versed in React.js, I converted this logic to JavaScript and began building a web app.
For the design, I found the 98.css design system created by Jordan Scales. It gave the site the nostalgic feel I was looking for.

After uploading an image, users can view a gif preview of the frames generated using the crop & paste process. They can change the delay, and add a variety of image effects: invert colors, grayscale, sepia, pixelate, and detect edge. Users can also choose to create a seamless loop, which plays the frames start-to-end, then end-to-start.
Thanks for reading! To see the rest of the source code, visit the GitHub repository.