creative/collage/SKILL.md

name: collage description: Build moodboards and collages from a set of images using ImageMagick — scraping sources (e.g. tumblr), curating via contact sheets, themed color pools, and iterative render-look-fix layout. Use when the user wants a moodboard, collage, photo wall, contact sheet, or creative image arrangement.

Collage / Moodboard builder

Build collages from local images or a scraped source. Work in a scratch dir (e.g. /tmp/moodboard/ with src/, work/, out/). Requires ImageMagick (brew install imagemagick).

The core loop

  1. Curate from a contact sheet — never lay out blind: magick montage -font /System/Library/Fonts/Supplemental/Arial.ttf imgs/* -tile 8x -geometry 150x150+2+2 -background '#222' -fill white -label '%f' sheet.jpg
  2. Render a layout (recipes below).
  3. Read the output image yourself and look for: dead/empty zones, rigid grid feel, pieces not bleeding off edges, color clashes. Fix coordinates and re-render. Expect 2–3 iterations; first renders are always too sparse and too grid-like. Denser + overlapping + edge-bleed = better.

Gotchas (macOS)

  • ImageMagick can't resolve font names — always pass a full path: /System/Library/Fonts/Supplemental/Arial.ttf, .../Futura.ttc.
  • No shuf / sort -R on macOS. Shuffle with: awk -v seed=$RANDOM 'BEGIN{srand(seed)} {print rand()"\t"$0}' | sort -n | cut -f2-
  • Validate downloads: magick identify -quiet "$f" and drop files < 5KB.

Piece-building snippets

Framed polaroid piece (white border + rotation + drop shadow):

magick src.jpg -resize 580x -bordercolor white -border 14 -background none -rotate -3 \
  \( +clone -background black -shadow 55x9+8+12 \) +swap -background none -layers merge piece.png

Raw rotated piece (no frame): same minus the border/shadow parts.

Circle crop:

magick src.jpg -resize 520x520^ -gravity center -extent 520x520 \
  \( -size 520x520 xc:none -fill white -draw "circle 260,260 260,2" \) \
  -compose CopyOpacity -composite circ.png

Vertical slice / letterbox strip: -gravity center -crop 460x1350+0+0 +repage.

Blurred photo backdrop (beats flat color — gaps read as mood, not emptiness):

magick src.jpg -resize 2400x1500^ -gravity center -extent 2400x1500 -blur 0x16 -modulate 50,110 bg.png

Composite everything in one command:

magick bg.png p1.png -geometry -140-120 -composite p2.png -geometry +590+130 -composite ... out.jpg

Negative geometry offsets = pieces bleed off canvas edges. Use them.

Palette strip extracted from the sources:

magick img1 img2 ... -resize 200x200 +append -colors 8 -unique-colors -scale 2400x80! palette.png

Photocopy/zine treatment (leave 1–2 pieces in color as pops; finish with paper noise and a solid accent bar):

magick src.jpg -resize 660x -colorspace gray -level 12%,88% -ordered-dither o4x4 \
  -bordercolor '#111' -border 10 -background none -rotate -6 z.png
# final: ... -fill '#c0392b' -draw "rectangle 0,1380 2400,1430" -attenuate 1.8 +noise Gaussian -colorspace sRGB out.jpg

CAUTION: magick arg order is strict — the output filename must come LAST, after any -attenuate/+noise finishing flags; a bash helper that appends flags after "$@" silently treats the output path as an input and fails.

Print-process treatments (syntax worth knowing; colors are examples, not specs):

  • Duotone/riso ink: after dither, +level-colors '<ink>','<paper>' maps black→ink, white→paper (e.g. riso red on cream, cyanotype navy on pale blue).
  • Chunky halftone: dither at quarter size then point-upscale: -resize 25% ... -ordered-dither o8x8 -filter point -resize 400%.
  • Hard threshold: -threshold 50% instead of dither — pure b/w, no grays.
  • Negative: -negate before dithering.
  • Tape strips: small xc:'#ffffff88' rectangles, rotated, composited at piece corners.

Themed color pools

Compute per-image stats once, then select pools by hue/sat instead of by hand:

for f in all/*; do
  read -r h s l <<< $(magick "$f" -resize 1x1\! -colorspace HSL -format "%[fx:u.r*360] %[fx:u.g] %[fx:u.b]" info:)
  echo "$f,$h,$s,$l" >> stats.csv
done
# red pool (hue wraps): awk -F, '($2>=335||$2<=25) && $3>=0.22 {print $1}' stats.csv
# hue-gradient board: filter sat>=0.28, sort by hue, lay out in reading order

Layout ideas (seeds, not specs — invent fresh per session)

Jittered grids beat pure random placement — random leaves dead zones; grid cell + jitter + rotation looks organic AND covers the canvas.

Proven directions to riff on: polished framed-polaroid rows with a palette footer; dense scatter over a blurred-photo bg; one hero image + small satellites; full-height vertical slices; circle-crop bubbles; packed tilted mosaic; diagonal cascade; photocopy zine with 1–2 color pops and an accent bar; saturated tiles sorted by hue. Mix crops (slices, circles, strips) and treatments within one board; design to the actual images, not to a template.

Scraping tumblr (no auth needed)

  • Pages: https://BLOG.tumblr.com/page/N with a browser User-Agent; blog is done when only ~4 theme-asset image refs remain per page.
  • Image URLs: 64.media.tumblr.com/<32-hex-hash>/.../s1280x1920/<hex>.jpgdedupe by the 32-hex media hash (path segment 4), since each photo appears in many sizes. Also catch legacy tumblr_*_1280.jpg format.
  • Download in parallel batches of ~12 with curl ... & ; wait.