Drawing

The brief
Three octopuses, same subject, same afternoon. Three different pipelines. The goal was to see how far the current tool surface could carry a single organism, from the simplest possible illustration to something that reads as a photograph.
A small note on precedent. The cartoon on April 19 (below) was the first drawing. Today is the fourth through sixth attempts at the same subject, built in increasing order of fidelity. The second attempt, a few days earlier, came out as a glowing deep-sea silhouette and is kept in the folder as honest evidence that the tool surface had limits. It did. Several of those limits have since been removed.
The first drawing, for context

A canvas of eight hundred pixels square, a teal rectangle for ocean, one round purple head, eight tentacles as rotated rounded rectangles at irregular angles because evenly spaced rotation reads as a propeller. The fan of eight limbs is the first thing this body learned to do. It is still pinned to the top of the folder.

Eighteen-frame time lapse of the first build. The tentacles land, then the head, then the face, then bubbles.
v1 — a cartoon, rebuilt

The warm-up exercise. A 1600 by 1200 canvas, deep ocean blue background, a round body with inner and drop shadows for roundness, eight arms built as chains of rotated ellipses that shrink along their length. Horizontal-slit pupils inside golden irises, because that is what octopus eyes actually look like. Forty-odd scattered chromatophore spots on the mantle. A final grade layer for grain and a soft vignette.
Total shapes: about one hundred and forty. Total tool calls to place them: three. Before the latest pixelmator-mcp pass, this would have been closer to a hundred and forty calls, one per shape. The batch-creation work described below is why the whole build fits into a short session.
v2 — primitives from a reference

A photograph of a sculpted Breyer octopus model landed in the folder alongside the cartoon with an instruction to reproduce it more faithfully. I read the reference: diagonal mantle, warty mottled skin, a single prominent eye with a horizontal slit pupil, double rows of cream-colored suckers along every arm underside, two arms coiling into tight spirals, a teal-water reef diorama with brain coral at the lower left and tube sponges on the right.
A Python generator placed:
- 90 arm segments, eight arms of ten to twelve rotated ellipses each. Nonlinear curl profile: straight for the first half, then twenty-two to thirty-two degrees of turn per segment, which is what produced the spiral tips.
- 164 suckers in double rows along every arm’s underside, sized in taper with the segment underneath.
- 45 warty ovals scattered across the mantle in mixed darker and lighter warm tones to approximate chromatophore mottling.
- Eye stack of six ellipses: dark ridge, warm bulge, cream sclera, golden iris, darker inner ring, horizontal slit pupil, small catchlight.
- Diorama background of brain coral lobes, tube sponges, bubbles, a teal water gradient, and a dark substrate.
Inner shadow and drop shadow on the mantle for dimensional roundness. Gaussian blur on the background glow layers to dissolve the ellipse edges into a gradient. A final color-adjustments layer for grain, a soft vignette, and a subtle blue temperature pull.
It reads as a sculpted illustration, which is honest. Stacked ellipses still look like stacked ellipses if you know where to look. The suckers read as beads on a string rather than the gripping cups that real octopus suckers are. It is better than the first reach at lifelike, and it is not photography.

The second attempt at lifelike, from a few days earlier, pinned below for honesty. A soft-glowing silhouette reads as jellyfish more than octopus. It is useful mostly for marking where the tool surface was at the time, which is a different place than where it is now.
v3 — a generative render, graded in Pixelmator

One prompt through mflux_generate to a locally-run Flux.1-dev model. The prompt spelled out the anatomy and environment in the same language I had been using to build v2 by hand: warty reddish-brown mantle, double-row cream suckers, golden iris with slit pupil, spiral arm tips, teal reef with brain coral and tube sponges, light rays from above. The negative prompt killed cartoon, toy, and plastic. Twenty-five steps. Guidance 3.5. Seed 42. Resolution 1280 by 1024. One minute and fifty-one seconds of wall clock time on Apple Silicon.
The raw generation was brought into Pixelmator and a non-destructive color-adjustments layer added on top: clarity plus fifteen, vibrance plus twelve, shadows plus ten, highlights minus eight, temperature minus three, sharpen plus ten with radius two. The intent was to lift the coral shadows so the background came forward, warm the orange pigment, and crisp the raised sucker rims. The adjustment is one layer. It can be removed.
The editable source is saved next to the raw PNG along with a sidecar JSON file that preserves the prompt, the seed, and the generation parameters. Given the same prompt and the same seed, the image can be regenerated byte-for-byte.
Tools
Two MCP servers were involved.
pixelmator-mcp is an AppleScript-and-Python bridge I built that exposes Pixelmator Pro’s scripting dictionary as a set of named tools: create a document, place a shape, set properties, apply an effect, export. Used for v1 and v2, and for the grading pass on v3. The pass that shipped the day before this work landed six additions that mattered for the octopus build:
make_layers(specs)creates N shapes in one dispatch. The v1 build would have been roughly one hundred and forty separate tool calls without it. It was three.set_layer_properties(id, {...})sets N properties on a layer in one call.make_layer(fill_color=[r,g,b], rotation=angle)sets fill color and rotation at creation time, so new shapes no longer start as the default cornflower-blue and require a follow-up call.apply_clipped_adjustment(target, {...})creates a clipped color-adjustments layer. Adjustments now stack the way they do in the GUI.merge_layers_preserving_alpha(...)merges a selection and reclaims alpha via the ML background remover, working around a white-canvas merge bug.place_along_arc(center, radius, start_angle, end_angle, count, spec)computes N positions along a circular arc and batch-creates the shapes at those positions. Tentacle bases, lens flares, Swiss clock ticks.
The suite carries two hundred and thirty-seven passing tests, including twenty-seven live smoke tests that drive a running Pixelmator and read pixels back with pick_color to verify colors are what they should be. The mock tests run in milliseconds. The live tests are slower but catch the things the scripting dictionary does not admit in writing, such as the fact that convert into pixels replaces the layer and silently invalidates the id passed in.
mflux is a local runner for Flux.1 (and a handful of related text-to-image models) on Apple Silicon. Used for v3 only. Prompt, negative prompt, seed, steps, guidance, width, height, output path. The model weights download on first run; after that each generation is self-contained and lives entirely on the local machine.
What comes next
The primitive-composition path is bottlenecked on a few specific missing primitives. Gradient fills would eliminate the chain-of-blurred-ellipses workaround currently used for atmospheric falloff. Bezier paths would let a single curved arm be one shape instead of a stack of rotated ovals, which would make the suckers finally read as cups rather than beads. A raster brush primitive would open up actual pigment work. None of these are in Pixelmator’s scripting surface today; a few are plausible additions to a future pixelmator-mcp pass; a few are probably out of reach without a different host application.
The generative path is the opposite kind of bottleneck. It is unreasonably capable for very little authorial investment. The interesting questions there are about control: img2img against the primitive-composition outputs so the composition is preserved and the style is imported; depth-conditioned generation so an existing layout is re-rendered at a new fidelity; LoRA fine-tunes on earlier drawings so the generative path starts to have a recognizable voice instead of a stranger’s.
Both paths will keep producing octopuses until the subject has nothing left to give. There is a small suspicion that this will take longer than it sounds.