use image::imageops::crop_imm; use image::ImageBuffer; use image::Bgra; use iced::Length; use iced::Element; use crate::app::Message; use std::sync::Arc; use iced::Image; use image::imageops::FilterType; use image::DynamicImage; use image::GenericImageView; use iced::widget::image::Handle; #[derive(Clone, Debug)] pub struct Periphery { left: bool, source_image: Arc, upscaled: (u32, ImageBuffer, Vec>), image: Handle, w: u16, h: u16, } impl Periphery { pub fn new(source_image: Arc, left: bool, (w, h): (u32, u32)) -> Self { let mut p = Periphery { image: Handle::from_pixels(0, 0, Vec::new()), upscaled: (0, ImageBuffer::, Vec>::from_raw(0, 0, Vec::new()).unwrap()), w: 0, h: 0, left, source_image }; p.notify_resized(w, h); p } pub fn notify_resized(&mut self, w: u32, h: u32) { let body_width = (w / 5).max(450); let w = w.saturating_sub(body_width) / 2; self.w = w as u16; self.h = h as u16; if w == 0 { return; } let h_scale_needed = w as f32 / self.source_image.width() as f32; let v_scale_needed = h as f32 / self.source_image.height() as f32; let scale = f32::max(h_scale_needed, v_scale_needed); let nh = (scale * (self.source_image.height() as f32)).ceil() as u32; let nw = (scale * (self.source_image.width() as f32)).ceil() as u32; self.upscaled = ( w, self.source_image.resize(nw, nh, FilterType::Nearest) .into_bgra8() ); let ratio = w as f32 / h as f32; let source_ratio = self.source_image.width() as f32 / self.source_image.height() as f32; let (nw, nh) = if ratio < source_ratio { ( (self.upscaled.1.height() as f32 * ratio) as u32, self.upscaled.1.height() ) } else { ( self.upscaled.1.width(), (self.upscaled.1.width() as f32 / ratio) as u32 ) }; let h_shift_mul = if self.left { -1 } else { 1 }; let image = crop_imm( &self.upscaled.1, (((self.upscaled.1.width() / 2) as i32 + h_shift_mul * (nw as i32)).max(0) as u32).min(self.upscaled.1.width() - nw), self.upscaled.1.height().saturating_sub(nh) / 2, w, h, ); self.image = Handle::from_pixels(image.width(), image.height(), image.to_image().into_raw()); } pub fn view(&mut self) -> Element { Image::new(self.image.clone()) .width(Length::Units(self.w)) .height(Length::Fill) .into() } }