BrushCue Example: Light Leak¶

Open In Colab

You can use this tool online at https://www.brushcue.com/tools/light-leak

In [ ]:
!pip install brushcue
In [ ]:
import io
from PIL import Image

import brushcue as bc

input_image = bc.Composition.monet_women_with_parasol()
bounds = input_image.bounds()
position = 315.0
spread = 0.55
warmth = 0.65

leak = bc.Composition.freeform_shader(
    "let uv = vec2<f32>(canvas_position.x / max(width, 0.0001), canvas_position.y / max(height, 0.0001));\nlet aspect = width / max(height, 0.0001);\nlet angle = position * 0.0174532925;\nlet direction = vec2<f32>(cos(angle), sin(angle));\nlet tangent = vec2<f32>(-direction.y, direction.x);\nlet p = vec2<f32>((uv.x - 0.5) * aspect, uv.y - 0.5);\nlet source = direction * 0.68;\nlet delta = p - source;\nlet along = dot(delta, direction);\nlet across = dot(delta, tangent);\nlet outer_distance = length(vec2<f32>(along / (spread * 1.15), across / (spread * 0.62)));\nlet core_distance = length(vec2<f32>(along / (spread * 0.47), across / (spread * 0.22)));\nlet ripple = 0.94 + 0.06 * sin((uv.x * 15.0) + (uv.y * 9.0) + angle * 3.0);\nlet halo = clamp((1.0 - smoothstep(0.18, 1.15, outer_distance)) * ripple, 0.0, 1.0);\nlet core = 1.0 - smoothstep(0.08, 0.92, core_distance);\nlet halo_color = mix(vec3<f32>(1.0, 0.72, 0.35), vec3<f32>(1.0, 0.24, 0.04), warmth);\nlet core_color = mix(vec3<f32>(1.0, 0.96, 0.78), halo_color, 0.20 + (warmth * 0.25));\nlet alpha = clamp((halo * 0.58) + (core * 0.62), 0.0, 0.88);\nreturn vec4<f32>(mix(halo_color, core_color, core), alpha);",
    "",
    bounds,
    bc.ColorRepresentation.srgb(),
    bc.Dictionary.create()
    .add("width", bounds.width())
    .add("height", bounds.height())
    .add("position", position)
    .add("spread", spread)
    .add("warmth", warmth),
).opacity_scales(0.55)

graph = leak.blend_alpha(input_image, bc.Transform2.identity()).crop(bounds)

ctx = bc.Context()
composition = graph.execute(ctx)
data_bytes = composition.to_image_bytes(ctx)
img = Image.open(io.BytesIO(data_bytes))
img.thumbnail((400, 400))  # Remove this line for full resolution
img