//! Original executable ICO encoder: DIB images and transparency masks. use super::app_icon; pub fn encode() -> Result, Box> { let sizes = [16usize, 24, 32, 48, 64, 128, 256]; let mut images = Vec::new(); for size in sizes { let rgba = app_icon::rgba(size)?; // ICO DIB: bottom-up BGRA plus a padded one-bit transparency mask. let mask_stride = size.div_ceil(32) * 4; let mut dib = Vec::new(); dib.extend_from_slice(&40u32.to_le_bytes()); dib.extend_from_slice(&(size as i32).to_le_bytes()); dib.extend_from_slice(&((size * 2) as i32).to_le_bytes()); dib.extend_from_slice(&1u16.to_le_bytes()); dib.extend_from_slice(&32u16.to_le_bytes()); dib.extend_from_slice(&[0; 24]); for row in rgba.chunks_exact(size * 4).rev() { for p in row.as_chunks::<4>().0.iter() { dib.extend_from_slice(&[p[2], p[1], p[0], p[3]]); } } for row in rgba.chunks_exact(size * 4).rev() { let mut mask = vec![0u8; mask_stride]; for (x, p) in row.as_chunks::<4>().0.iter().enumerate() { if p[3] == 0 { mask[x / 8] |= 0x80 >> (x % 8); } } dib.extend_from_slice(&mask); } images.push((size, dib)); } let mut ico = vec![0, 0, 1, 0]; ico.extend_from_slice(&(images.len() as u16).to_le_bytes()); let mut offset = 6 + 16 * images.len(); for (size, data) in &images { let dim = if *size == 256 { 0 } else { *size as u8 }; ico.extend_from_slice(&[dim, dim, 0, 0, 1, 0, 32, 0]); ico.extend_from_slice(&(data.len() as u32).to_le_bytes()); ico.extend_from_slice(&(offset as u32).to_le_bytes()); offset += data.len(); } for (_, data) in images { ico.extend_from_slice(&data); } Ok(ico) }