Files
Android-247-Radio/docs/plans/2026-03-18-heavy-blur-background-design.md
cottongin ada81dddd0 docs: add design doc for heavy blur background replacement
Replace Cloudy with Coil BlurTransformation for unblurred album art issue.

Made-with: Cursor
2026-03-18 11:13:16 -04:00

2.1 KiB

Design: Heavy Blur Background via Coil BlurTransformation

Date: 2026-03-18
Status: Approved

Problem

The player screen's blurred album art background uses the Cloudy library at its maximum radius of 25. This is insufficient — album art with text remains legible and fine details are still visible, breaking the intended "washed out background" aesthetic.

Solution

Replace Cloudy with a self-contained Stackblur BlurTransformation applied via Coil's image loading pipeline. Blur is baked into the decoded bitmap on a background thread, producing a heavily smeared result with no legible text or sharp edges.

Changes

1. Add BlurTransformation.kt

Create app/src/main/java/xyz/cottongin/radio247/ui/util/BlurTransformation.kt.

A ~130-line pure Kotlin + Android bitmap Stackblur implementation (no new library dependency). Accepts:

  • radius: Int — blur radius (25 is already very aggressive at low scale)
  • scale: Float — downsample factor applied before blurring (0.1f = 10% of original size)

2. Update BlurredBackground in NowPlayingScreen.kt

  • Remove .cloudy(radius = 25) modifier
  • Remove size(10, 10) from the ImageRequest (scale parameter in the transformation handles downsampling)
  • Add transformations(BlurTransformation(radius = 25, scale = 0.1f)) to the ImageRequest
  • Remove Cloudy import

3. Remove Cloudy dependency

  • Remove implementation(libs.cloudy) from app/build.gradle.kts
  • Remove cloudy version and library entries from gradle/libs.versions.toml

Parameters

Parameter Value Rationale
radius 25 Maximum effective Stackblur radius before diminishing returns
scale 0.1f Downsamples to 10% before blurring, destroying fine detail and text

Trade-offs

  • No new dependency — implementation is inlined as a project file
  • All API levels — pure bitmap manipulation, no RenderEffect/RenderScript
  • Background thread — blur computed by Coil pipeline, zero per-frame GPU cost
  • Not animatable — blur is baked at load time; cannot be animated at runtime (acceptable for this use case)