scaled
Downscale to fit inside maxWidth×maxHeight, preserving aspect ratio, using box (area-average) filtering: each destination pixel averages every source pixel that maps into its bin, so thumbnails don't shimmer the way nearest-neighbor ones do.
Color channels average alpha-weighted (premultiply, average, unpremultiply): a fully transparent pixel contributes nothing to a bin's RGB, so transparent padding (whose RGB is usually black) doesn't smear dark halos into the edges of GIF/PNG thumbnails. For fully opaque input this reduces exactly to the plain per-channel mean.
Never upscales: if the bitmap already fits, the same instance returns.
This is a post-decode scale: the decoder still materialises the full-size image transiently. What it saves is retained memory (the thumbnail you keep vs the 12MP original). Decode-time DCT-domain scaling is future work.
Downscale every frame of an animation to fit inside maxWidth×maxHeight (same box filter and aspect handling as KiteBitmap.scaled), preserving delays and the loop count. This is where animated memory goes: a full-screen GIF shown as an avatar keeps W×H×4 bytes per frame unless scaled down.
Never upscales: if the canvas already fits, the same instance returns.