A Recursive QR Code

I've been thinking about fun little artistic things to do with QR codes. What if each individual pixel were a QR code?
There's two fundamental problems with that idea. Firstly, a QR code needs whitespace around it in order to be scanned properly.
So I focussed on the top left positional marker. There's plenty of whitespace there.
Secondly, because QR codes contain a lot of white pixels inside them, scaling down the code usually results in a grey square - which is unlikely to be recognised as a black pixel when scanning.
So I cheated! I made the smaller code transparent and gradually increased its opacity as it grows larger.
I took a Version 2 QR code - which is 25px wide. With a 2px whitespace border around it, that makes 29px * 29px.
Blow it up to 2900px * 2900px. That will be the base image.
Take the original 25px code and blow it up to the size of the new marker, 300px * 300px. Place it on a new transparent canvas the size of the base image, and place it where the marker is - 400px from the top and left.
Next step is creating the image sequence for zooming in. The aim is to move in to the target area, then directly zoom in.
The whole code, if you want to build one yourself, is:
Bash
#!/bin/bash # Input file input="25.png" # Add a whitespace border convert "$input" -bordercolor white -border 2 29.png # Upscaled image size upscaled_size=2900 # Scale it up for the base convert 29.png -scale "${upscaled_size}x${upscaled_size}"\! base.png # Create the overlay convert -size "${upscaled_size}x${upscaled_size}" xc:none canvas.png convert "$input" -scale 300x300\! 300.png convert canvas.png 300.png -geometry +400+400 -composite overlay.png # Start crop size (full image) and end crop size (target region) start_crop=$upscaled_size end_crop=350 # Zoom-in target position (top-left corner) target_x=375 target_y=375 # Start with a completely opaque image original_opacity=0 # Number of intermediate images steps=100 for i in $(seq 0 $((steps - 1))); do # Calculate current crop size crop_size=$(echo "$start_crop - ($start_crop - $end_crop) * $i / ($steps - 1)" | bc) crop_size=$(printf "%.0f" "$crop_size") # Round to nearest integer # Keep zoom centered on the target crop_x_offset=$(echo "$target_x - ($crop_size - $end_crop) / 2" | bc) crop_y_offset=$(echo "$target_y - ($crop_size - $end_crop) / 2" | bc) # Once centred, zoom in normally if (( crop_x_offset < 0 )); then crop_x_offset=0; fi if (( crop_y_offset < 0 )); then crop_y_offset=0; fi # Generate output filenames background_file=$(printf "%s_%03d.png" "background" "$i") overlay_file=$(printf "%s_%03d.png" "overlay" "$i") combined_file=$(printf "%s_%03d.png" "combined" "$i") # Crop and resize the base convert "base.png" -crop "${crop_size}x${crop_size}+${crop_x_offset}+${crop_y_offset}" \ -resize "${upscaled_size}x${upscaled_size}" \ "$background_file" # Transparancy for the overlay opacity=$(echo "$original_opacity + 0.01 * $i" | bc) # Crop and resize the overlay convert "overlay.png" -alpha on -channel A -evaluate multiply "$opacity" \ -crop "${crop_size}x${crop_size}+${crop_x_offset}+${crop_y_offset}" \ -resize "${upscaled_size}x${upscaled_size}" \ "$overlay_file" # Combine the two files convert "$background_file" "$overlay_file" -composite "$combined_file" done # Create a 25fps video, scaled to 1024px ffmpeg -framerate 25 -i combined_%03d.png -vf "scale=1024:1024" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p recursive.mp4