Package-level declarations
Types
Thrown when input claims to be an image but can't be decoded: truncated data, corrupt structures, failed checksums, dimension overflow, or no recognisable format at all.
Image container formats KiteImage can identify from magic bytes. Sniffing intentionally recognises more formats than KiteImage.decode currently handles: "that's a WebP we can't decode yet" is a far better error than "unknown format".
What a file says about itself, read from its header alone: no pixel decode, no multi-megabyte allocation. This is what you want for laying out a grid before the images arrive, rejecting an upload that's 20000 px wide, or deciding whether a decoder should claim a file at all.
A decoded animation: GIF, APNG and animated WebP all arrive in this shape. Static images decode as a single frame, so KiteImage.decodeAnimation is total over every supported format.
A decoded raster image: width × height pixels, packed as non-premultiplied ARGB_8888 in a row-major argb array (argb[y * width + x], alpha in the top byte). One layout for every source format: decoders normalise grayscale, palette, BGR and 16-bit inputs into this on the way out, so consumers and the Compose interop never branch on the source format.
One presented frame of an animation: the fully composited canvas (disposal methods, transparency overlay and frame offsets already applied), plus its display duration.
How a decoded image relates to the scene it was captured from: the EXIF Orientation tag (TIFF tag 274), which phone cameras write instead of physically rotating pixels. A portrait photo is usually stored landscape with Rotate90 set, so anything that draws raw decoded pixels shows it sideways.
The input is a well-formed image in a format, or a format feature, KiteImage doesn't decode: lossy WebP, an arithmetic-coded JPEG, a CgBI PNG. The message always names the specific feature, and KiteImage.probe reports the same thing up front through ImageInfo.unsupportedReason, so a caller can route the file elsewhere instead of catching this.
Functions
cropped applied to every frame, preserving delays and loop count.
Mirror left-to-right.
Mirror top-to-bottom.
oriented applied to every frame, preserving delays and loop count.
Apply an EXIF orientation so the result is oriented the way the camera meant it to be seen. Orientation.Normal returns the same instance.
rotated180 applied to every frame.
Rotate a half turn. Dimensions are unchanged.
rotated270 applied to every frame.
Rotate a quarter turn counter-clockwise. Width and height swap.
rotated90 applied to every frame.
Rotate a quarter turn clockwise. Width and height swap.
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.
Mirror across the main diagonal: dst(x, y) = src(y, x). Axes swap.
Mirror across the anti-diagonal. Axes swap.