diff --git a/src/avatar_mask.png b/src/avatar_mask.png index 6437265..655455b 100644 Binary files a/src/avatar_mask.png and b/src/avatar_mask.png differ diff --git a/src/img.rs b/src/img.rs index 7d319ad..316bf46 100644 --- a/src/img.rs +++ b/src/img.rs @@ -1,6 +1,7 @@ use image::{RgbaImage, ExtendedColorType, ImageEncoder, load_from_memory}; use image::codecs::png::PngEncoder; +use tiny_skia::{Pixmap, Transform, PixmapPaint, BlendMode, FilterQuality}; pub fn save_to_memory_png(p: &RgbaImage) -> Result, String> { let (width, height) = p.dimensions(); @@ -19,3 +20,17 @@ pub fn ensure_32_bit_png(p: &[u8]) -> Result, String> { }; save_to_memory_png(&img.into_rgba8()) } + +pub fn scale_skia_pixmap(p: Pixmap, width: u32, height: u32) -> Option { + let mut new_pixmap = Pixmap::new(width, height)?; + let width_scale = width as f32 / p.width() as f32; + let height_scale = height as f32 / p.width() as f32; + let matrix = Transform::from_scale(width_scale, height_scale); + let pixmap_paint = PixmapPaint { + opacity: 1.0, + blend_mode: BlendMode::Source, + quality: FilterQuality::Bilinear, + }; + new_pixmap.draw_pixmap(0, 0, p.as_ref(), &pixmap_paint, matrix, None); + Some(new_pixmap) +} diff --git a/src/main.rs b/src/main.rs index 64bba08..9f8c8fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -125,7 +125,9 @@ fn parse_cielab(s: String) -> Result<(f32, f32, f32), &'static str> { const FMI_WIDTH: u32 = 548; const FMI_HEIGHT: u32 = 147; -const FMI_GAP: i32 = 12; +const FMI_GAP: u32 = 12; +const FMI_AVATAR_SIZE: u32 = 64; +const FMI_AVATAR_GAP: u32 = 10; async fn fmi(ctx: &Context, arg: &str, id: UserId, avatar: Option) -> Reply { let lastfm_user = match arg { @@ -168,16 +170,24 @@ async fn fmi(ctx: &Context, arg: &str, id: UserId, avatar: Option) -> Re let mask_wand = MagickWand::new(); let text_image_wand = MagickWand::new();*/ let mut main_image = handle_option!(tiny_skia::Pixmap::new(FMI_WIDTH, FMI_HEIGHT), "Failed to load main image"); - let album_image = handle_result!(tiny_skia::Pixmap::decode_png(&image_base), "Failed to load album art image"); + let mut album_image = handle_result!(tiny_skia::Pixmap::decode_png(&image_base), "Failed to load album art image"); //let album_image = handle_result!(tiny_skia::Pixmap::decode_png(&image_rgba8), "Failed to decode album art"); - let art_size = (FMI_HEIGHT as i32 - 2_i32 * FMI_GAP) as f32 / 300.0; - let scale_matrix = tiny_skia::Transform::from_scale(art_size, art_size); - let paint = tiny_skia::PixmapPaint { - opacity: 1.0, + let color_paint = tiny_skia::Paint { + shader: tiny_skia::Shader::SolidColor(tiny_skia::Color::WHITE), + anti_alias: true, blend_mode: tiny_skia::BlendMode::Source, + force_hq_pipeline: false, + }; + main_image.fill_rect(tiny_skia::Rect::from_xywh(0.0, 0.0, FMI_WIDTH as f32, FMI_HEIGHT as f32).unwrap(), &color_paint, tiny_skia::Transform::identity(), None); + let art_size = FMI_HEIGHT- 2 * FMI_GAP; + album_image = handle_option!(img::scale_skia_pixmap(album_image, art_size, art_size), "Failed to scale bitmap"); + //let art_scale_matrix = tiny_skia::Transform::from_transla(art_size, art_size).pre_translate(FMI_GAP as f32, FMI_GAP as f32); + let source_paint = tiny_skia::PixmapPaint { + opacity: 1.0, + blend_mode: tiny_skia::BlendMode::SourceOver, quality: tiny_skia::FilterQuality::Bilinear, }; - main_image.draw_pixmap(FMI_GAP, FMI_GAP, album_image.as_ref(), &paint, scale_matrix, None); + main_image.draw_pixmap(FMI_GAP as i32, FMI_GAP as i32, album_image.as_ref(), &source_paint, tiny_skia::Transform::identity(), None); /*handle_magick_result!( base_color.set_color("#7f7f7f"), "Failed to set init base color" @@ -277,8 +287,21 @@ async fn fmi(ctx: &Context, arg: &str, id: UserId, avatar: Option) -> Re avatar_wand.new_image(100, 100, &white), "Failed to load dummy avatar" ), - } - let avatar_mask_wand = MagickWand::new(); + }*/ + let avatar_uri = avatar.unwrap(); // TODO: FIX THIS + let avatar_base = match get_image(ctx, avatar_uri.as_str()).await { + Ok(i) => i, + Err(e) => return Reply::Text(e.to_string()), + }; + let mut avatar_image = handle_result!(tiny_skia::Pixmap::decode_png(&avatar_base), "Failed to load album art image"); + let mut avatar_mask = handle_result!(tiny_skia::Mask::decode_png(include_bytes!("avatar_mask.png")), "Failed to load album art image"); + let (avatar_x, avatar_y) = (FMI_WIDTH - FMI_AVATAR_SIZE - FMI_AVATAR_GAP, FMI_HEIGHT - FMI_AVATAR_SIZE - FMI_AVATAR_GAP); + avatar_image.apply_mask(&avatar_mask); + avatar_image = handle_option!(img::scale_skia_pixmap(avatar_image, FMI_AVATAR_SIZE, FMI_AVATAR_SIZE), "Failed to scale avatar image"); + //let avatar_matrix = tiny_skia::Transform::from_scale(avatar_scale, avatar_scale).pre_translate(avatar_x as f32, avatar_y as f32); + main_image.draw_pixmap(avatar_x as i32, avatar_y as i32, avatar_image.as_ref(), &source_paint, tiny_skia::Transform::identity(), None); + + /*let avatar_mask_wand = MagickWand::new(); handle_magick_result!( avatar_mask_wand.read_image_blob(include_bytes!("avatar_mask.png")), "Failed to load avatar mask"