@@ -46,6 +46,10 @@ const MESSAGE_NOTICE_TEXT_COLOR: Vec3 = Vec3 { x: 0.5, y: 0.5, z: 0.5 };
4646/// from getting into a long-running loop if an event cannot be found quickly.
4747const MAX_ITEMS_TO_SEARCH_THROUGH : usize = 100 ;
4848
49+ /// The max size (width or height) of a blurhash image to decode.
50+ const BLURHASH_IMAGE_MAX_SIZE : u32 = 500 ;
51+
52+
4953live_design ! {
5054 use link:: theme:: * ;
5155 use link:: shaders:: * ;
@@ -3884,17 +3888,42 @@ fn populate_image_message_content(
38843888 fully_drawn = true ;
38853889 }
38863890 ( MediaCacheEntry :: Requested , _media_format) => {
3891+ // If the image is being fetched, we try to show its blurhash.
38873892 if let ( Some ( ref blurhash) , Some ( width) , Some ( height) ) = ( image_info. blurhash . clone ( ) , image_info. width , image_info. height ) {
38883893 let show_image_result = text_or_image_ref. show_image ( cx, |cx, img| {
3889- let ( Ok ( width) , Ok ( height) ) = ( width. try_into ( ) , height. try_into ( ) ) else { return Err ( image_cache:: ImageError :: EmptyData ) } ;
3890- if let Ok ( data) = blurhash:: decode ( blurhash, width, height, 1.0 ) {
3891- ImageBuffer :: new ( & data, width as usize , height as usize ) . map ( |img_buff| {
3892- let texture = Some ( img_buff. into_new_texture ( cx) ) ;
3893- img. set_texture ( cx, texture) ;
3894- img. size_in_pixels ( cx) . unwrap_or_default ( )
3895- } )
3896- } else {
3897- Err ( image_cache:: ImageError :: EmptyData )
3894+ let ( Ok ( width) , Ok ( height) ) = ( width. try_into ( ) , height. try_into ( ) ) else {
3895+ return Err ( image_cache:: ImageError :: EmptyData )
3896+ } ;
3897+ let ( width, height) : ( u32 , u32 ) = ( width, height) ;
3898+ if width == 0 || height == 0 {
3899+ warning ! ( "Image had an invalid aspect ratio (width or height of 0)." ) ;
3900+ return Err ( image_cache:: ImageError :: EmptyData ) ;
3901+ }
3902+ let aspect_ratio: f32 = width as f32 / height as f32 ;
3903+ // Cap the blurhash to a max size of 500 pixels in each dimension
3904+ // because the `blurhash::decode()` function can be rather expensive.
3905+ let ( mut capped_width, mut capped_height) = ( width, height) ;
3906+ if capped_height > BLURHASH_IMAGE_MAX_SIZE {
3907+ capped_height = BLURHASH_IMAGE_MAX_SIZE ;
3908+ capped_width = ( capped_height as f32 * aspect_ratio) . floor ( ) as u32 ;
3909+ }
3910+ if capped_width > BLURHASH_IMAGE_MAX_SIZE {
3911+ capped_width = BLURHASH_IMAGE_MAX_SIZE ;
3912+ capped_height = ( capped_width as f32 / aspect_ratio) . floor ( ) as u32 ;
3913+ }
3914+
3915+ match blurhash:: decode ( blurhash, capped_width, capped_height, 1.0 ) {
3916+ Ok ( data) => {
3917+ ImageBuffer :: new ( & data, capped_width as usize , capped_height as usize ) . map ( |img_buff| {
3918+ let texture = Some ( img_buff. into_new_texture ( cx) ) ;
3919+ img. set_texture ( cx, texture) ;
3920+ img. size_in_pixels ( cx) . unwrap_or_default ( )
3921+ } )
3922+ }
3923+ Err ( e) => {
3924+ error ! ( "Failed to decode blurhash {e:?}" ) ;
3925+ Err ( image_cache:: ImageError :: EmptyData )
3926+ }
38983927 }
38993928 } ) ;
39003929 if let Err ( e) = show_image_result {
0 commit comments