Porting to tiny_skia: art and avatar working

This commit is contained in:
2025-05-22 09:41:06 -05:00
parent 4d71f7fe23
commit 6038240d5a
3 changed files with 47 additions and 9 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -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<Vec<u8>, String> {
let (width, height) = p.dimensions();
@ -19,3 +20,17 @@ pub fn ensure_32_bit_png(p: &[u8]) -> Result<Vec<u8>, String> {
};
save_to_memory_png(&img.into_rgba8())
}
pub fn scale_skia_pixmap(p: Pixmap, width: u32, height: u32) -> Option<Pixmap> {
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)
}

View File

@ -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<String>) -> Reply {
let lastfm_user = match arg {
@ -168,16 +170,24 @@ async fn fmi(ctx: &Context, arg: &str, id: UserId, avatar: Option<String>) -> 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<String>) -> 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"