1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
use super::{Encoder, Filter, Header, HeaderErr, Intent, Quantization}; use std::fmt::Display; pub struct HeaderBuilder { pub width: u32, pub height: u32, pub layers: u16, pub channels: u16, pub quality: u16, pub chroma_scale: u8, pub block_size: u8, pub filter: Filter, pub encoder: Encoder, pub intent: Intent, pub metadata_size: u32, } impl HeaderBuilder { pub fn build(self) -> Result<Header, HeaderErr> { let width = check_range(self.width, 0, 1 << 30, "Width")?; let height = check_range(self.height, 0, 1 << 30, "Height")?; let bit_depth = 8; let channel_size = width as usize * height as usize; let layer_size = channel_size .checked_mul(self.layers as usize) .ok_or_else(|| HeaderErr::WrongValue(String::from("layer size is too large")))?; let image_size = layer_size .checked_mul(self.channels as usize) .ok_or_else(|| HeaderErr::WrongValue(String::from("Image size is too large")))?; let _bit_depth_image_size = image_size .checked_mul((bit_depth as usize + 7) / 8) .ok_or_else(|| { HeaderErr::WrongValue(String::from("Image size and bit_depth are too large")) })?; Ok(Header { version: 1, width, height, layers: self.layers, channels: self.channels, bit_depth, is_signed: false, quality: check_range(self.quality, 0, 1025, "Quality")?, chroma_scale: self.chroma_scale, block_size: check_range(self.block_size, 0, 31, "Block size")?, filter: self.filter, quantization: Quantization::Scalar, encoder: self.encoder, intent: self.intent, metadata_size: self.metadata_size, channel_size, image_size, }) } } fn check_range<T>(value: T, min: T, max: T, name: &str) -> Result<T, HeaderErr> where T: PartialOrd + Display + Copy, { if min < value && value < max { Ok(value) } else { Err(HeaderErr::WrongValue(format!( "{} must be in range ({}..{})", name, min, max ))) } }