from PIL import Image SCALE = 0.25 PIXEL_SIZE = 4 FRAME_COUNT = 3288 FPS = 15 size = None pixel_data = {} def color_to_hex(pil_color): return "#" + hex(pil_color)[2:].zfill(2) * 3 for i in range(1, FRAME_COUNT + 1): print('frame', i) frame_path = f"frames/{i:04d}.png" percentage = i / FRAME_COUNT * 100 image = Image.open(frame_path) width, height = [round(i * SCALE) for i in image.size] size = (width, height) image = image.resize(size) # get pixels in red channel pixels = image.getdata(band=0) for y in range(height): pixels_thing = [] if y not in pixel_data: pixel_data[y] = [] for x in range(width): # get the pixel index index = y * width + x # get the current color current_color = pixels[index] # get the previous pixel if len(pixels_thing): prev_pixel = pixels_thing[-1] else: prev_pixel = None # note down pixel change if prev_pixel: if prev_pixel['color'] == current_color: continue pixels_thing.append({'color': prev_pixel['color'], 'x': x - 1}) pixels_thing.append({'color': current_color, 'x': x}) pixel_data[y].append(pixels_thing) print('finished processing pixel data, generating CSS keyframes') keyframes = [] divs = [] for pixel in pixel_data.keys(): # for every pixel row in the pixel data print('pixel Y', pixel) keyframe_data = [] gradients = [] # for every frame for i, frame in enumerate(pixel_data[pixel]): # get previous frame if len(gradients): prev_gradient = gradients[-1] else: prev_gradient = None # add an extra color packet at the end for completeness frame.append({'color': frame[-1]['color'], 'x': size[0]}) # get the linear gradient linear_gradient = 'linear-gradient(to right,' + ','.join([f'{color_to_hex(data["color"])} {data["x"] / size[0] * 100}%' for data in frame]) + ')' # if we already have this gradient, skip if prev_gradient == linear_gradient: continue # note it down in keyframes percentage = i / FRAME_COUNT * 100 gradients.append(linear_gradient) keyframe_data.append(f"{percentage}% " "{" f"background: {linear_gradient};" "}") # note down everything in keyframes keyframes.append(f"@keyframes pixelrow{pixel}" "{\n" + '\n'.join(keyframe_data) + "\n}") # make corresponding div divs.append(f".pixelrow{pixel} " "{\n" f"\tanimation-name: pixelrow{pixel};\n" "}") preamble = f"""/* Bad CSS !! */ /* Written and generated by omame */ body {'{'} margin: 0; display: flex; flex-direction: column; width: 100vw; background-color: black; {'}'} .pixelrow {'{'} width: {size[0] * PIXEL_SIZE}px; height: {PIXEL_SIZE}px; animation-duration: {round(FRAME_COUNT / FPS)}s; {'}'} """ with open('out.css', 'w+') as file: file.write(preamble + '\n'.join(keyframes) + '\n'.join(divs)) print('generating accompanying HTML...') html_pixels = "" for y in range(height): html_pixels += f'
' html_body = f""" Bad CSS !! {html_pixels} """ with open('out.html', 'w+') as file: file.write(html_body)