okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
b2e29fd
main
1//! An image scaled down so neither edge passes a provider's limit, for 2//! screenshots and photos albedo did not render itself. The aspect ratio is 3//! kept; a JPEG stays a JPEG, anything else becomes a PNG. 4 5use image:: codecs:: jpeg:: JpegEncoder ; 6use image:: imageops:: FilterType ; 7use image::{ ImageFormat , ImageReader }; 8use std:: io:: Cursor ; 9 10pub struct Fitted { 11pub bytes : Vec < u8 >, 12pub width : u32 , 13pub height : u32 , 14pub extension : &' static str , 15} 16 17pub fn fit ( bytes : & [ u8 ], edge : u32 ) ->Result < Fitted , String > { 18let reader =ImageReader :: new ( Cursor :: new ( bytes)) 19. with_guessed_format () 20. map_err ( |e| e. to_string ()) ?; 21let format = reader. format (). ok_or ( "not a PNG, JPEG, or WebP image" ) ?; 22let image = reader 23. decode () 24. map_err ( |e|format! ( "cannot decode the image: {e}" )) ?; 25let ( width, height) =scaled ( image. width (), image. height (), edge); 26let resized = image. resize_exact ( width, height, FilterType :: Lanczos3 ); 27let mut out =Cursor :: new ( Vec :: new ()); 28let extension =match format{ 29ImageFormat :: Jpeg =>{ 30JpegEncoder :: new_with_quality ( & mut out, 90 ) 31. encode_image ( & resized. to_rgb8 ()) 32. map_err ( |e| e. to_string ()) ?; 33"jpg" 34} 35 _ =>{ 36 resized 37. write_to ( & mut out, ImageFormat :: Png ) 38. map_err ( |e| e. to_string ()) ?; 39"png" 40} 41}; 42Ok ( Fitted { 43bytes : out. into_inner (), 44 width, 45 height, 46 extension, 47}) 48} 49 50/// The size `width` × `height` shrinks to so its longer edge is `edge`; an 51/// image already inside keeps its size. 52fn scaled ( width : u32 , height : u32 , edge : u32 ) ->( u32 , u32 ) { 53let longer = width. max ( height); 54if longer <= edge{ 55return ( width, height); 56} 57let shrink = 58 |side : u32 |(( sideas u64 * edgeas u64 + longeras u64 /2 ) / longeras u64 ). max ( 1 ) as u32 ; 59( shrink ( width), shrink ( height)) 60} 61 62# [ cfg ( test )] 63mod tests{ 64use super :: * ; 65 66# [ test ] 67fn the_longer_edge_lands_on_the_limit () { 68assert_eq! ( scaled ( 2304 , 1212 , 2000 ), ( 2000 , 1052 )); 69assert_eq! ( scaled ( 1000 , 8000 , 2000 ), ( 250 , 2000 )); 70assert_eq! ( scaled ( 1200 , 800 , 2000 ), ( 1200 , 800 )); 71assert_eq! ( scaled ( 9000 , 1 , 2000 ), ( 2000 , 1 )); 72} 73}