//! Fixed preview geometry. These are deliberately constants instead of config: //! the preview is a product decision (what a list view loads), not a per-host //! tuning knob, and every deployment must produce identical derivatives for the //! same upload. /// Longest-edge ceiling for full-content images (chat pictures, banners). pub const CONTENT_MAX_EDGE: u32 = 1920; /// Longest-edge ceiling for avatar-shaped images. pub const AVATAR_MAX_EDGE: u32 = 512; /// JPEG quality for the opaque preview encoding. pub const JPEG_QUALITY: u8 = 82; /// Sources above this size are served as-is instead of being decoded. pub const MAX_SOURCE_BYTES: u64 = 32 * 1024 * 1024; /// Decoded pixel ceiling; guards against decompression bombs. pub const MAX_DECODE_PIXELS: u64 = 40_000_000; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PreviewPreset { /// Small, square-ish target for avatars and space avatars. Avatar, /// General picture target for chat attachments and space banners. Content, } impl PreviewPreset { #[must_use] pub fn max_edge(self) -> u32 { match self { Self::Avatar => AVATAR_MAX_EDGE, Self::Content => CONTENT_MAX_EDGE, } } #[must_use] pub fn jpeg_quality(self) -> u8 { JPEG_QUALITY } #[must_use] pub fn max_source_bytes(self) -> u64 { MAX_SOURCE_BYTES } #[must_use] pub fn max_decode_pixels(self) -> u64 { MAX_DECODE_PIXELS } /// Whether a source alpha channel must survive into the preview. Avatars and /// pictures can both be cut-outs, so both keep it. #[must_use] pub fn keep_alpha(self) -> bool { true } }