@@ -12,9 +12,9 @@ namespace Flow.Launcher.Helper;
1212
1313public static class WallpaperPathRetrieval
1414{
15- private static readonly int MAX_CACHE_SIZE = 3 ;
16-
17- private static readonly Dictionary < ( string , DateTime ) , ImageBrush > wallpaperCache = new ( ) ;
15+ private const int MaxCacheSize = 3 ;
16+ private static readonly Dictionary < ( string , DateTime ) , ImageBrush > WallpaperCache = new ( ) ;
17+ private static readonly object CacheLock = new ( ) ;
1818
1919 public static Brush GetWallpaperBrush ( )
2020 {
@@ -27,46 +27,71 @@ public static Brush GetWallpaperBrush()
2727 try
2828 {
2929 var wallpaperPath = Win32Helper . GetWallpaperPath ( ) ;
30- if ( wallpaperPath is not null && File . Exists ( wallpaperPath ) )
30+ if ( string . IsNullOrEmpty ( wallpaperPath ) || ! File . Exists ( wallpaperPath ) )
31+ {
32+ App . API . LogInfo ( nameof ( WallpaperPathRetrieval ) , $ "Wallpaper path is invalid: { wallpaperPath } ") ;
33+ var wallpaperColor = GetWallpaperColor ( ) ;
34+ return new SolidColorBrush ( wallpaperColor ) ;
35+ }
36+
37+ // Since the wallpaper file name can be the same (TranscodedWallpaper),
38+ // we need to add the last modified date to differentiate them
39+ var dateModified = File . GetLastWriteTime ( wallpaperPath ) ;
40+ lock ( CacheLock )
3141 {
32- // Since the wallpaper file name can be the same (TranscodedWallpaper),
33- // we need to add the last modified date to differentiate them
34- var dateModified = File . GetLastWriteTime ( wallpaperPath ) ;
35- wallpaperCache . TryGetValue ( ( wallpaperPath , dateModified ) , out var cachedWallpaper ) ;
42+ WallpaperCache . TryGetValue ( ( wallpaperPath , dateModified ) , out var cachedWallpaper ) ;
3643 if ( cachedWallpaper != null )
3744 {
3845 return cachedWallpaper ;
3946 }
47+ }
48+
49+ using var fileStream = File . OpenRead ( wallpaperPath ) ;
50+ var decoder = BitmapDecoder . Create ( fileStream , BitmapCreateOptions . DelayCreation , BitmapCacheOption . None ) ;
51+ var frame = decoder . Frames [ 0 ] ;
52+ var originalWidth = frame . PixelWidth ;
53+ var originalHeight = frame . PixelHeight ;
4054
41- // We should not dispose the memory stream since the bitmap is still in use
42- var memStream = new MemoryStream ( File . ReadAllBytes ( wallpaperPath ) ) ;
43- var bitmap = new BitmapImage ( ) ;
44- bitmap . BeginInit ( ) ;
45- bitmap . StreamSource = memStream ;
46- bitmap . DecodePixelWidth = 800 ;
47- bitmap . DecodePixelHeight = 600 ;
48- bitmap . EndInit ( ) ;
49- bitmap . Freeze ( ) ; // Make the bitmap thread-safe
50- var wallpaperBrush = new ImageBrush ( bitmap ) { Stretch = Stretch . UniformToFill } ;
51- wallpaperBrush . Freeze ( ) ; // Make the brush thread-safe
55+ if ( originalWidth == 0 || originalHeight == 0 )
56+ {
57+ App . API . LogInfo ( nameof ( WallpaperPathRetrieval ) , $ "Failed to load bitmap: Width={ originalWidth } , Height={ originalHeight } ") ;
58+ return new SolidColorBrush ( Colors . Transparent ) ;
59+ }
60+
61+ // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio
62+ var widthRatio = 800.0 / originalWidth ;
63+ var heightRatio = 600.0 / originalHeight ;
64+ var scaleFactor = Math . Min ( widthRatio , heightRatio ) ;
65+ var decodedPixelWidth = ( int ) ( originalWidth * scaleFactor ) ;
66+ var decodedPixelHeight = ( int ) ( originalHeight * scaleFactor ) ;
67+
68+ // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio
69+ var bitmap = new BitmapImage ( ) ;
70+ bitmap . BeginInit ( ) ;
71+ bitmap . UriSource = new Uri ( wallpaperPath ) ;
72+ bitmap . DecodePixelWidth = decodedPixelWidth ;
73+ bitmap . DecodePixelHeight = decodedPixelHeight ;
74+ bitmap . EndInit ( ) ;
75+ bitmap . Freeze ( ) ; // Make the bitmap thread-safe
76+ var wallpaperBrush = new ImageBrush ( bitmap ) { Stretch = Stretch . UniformToFill } ;
77+ wallpaperBrush . Freeze ( ) ; // Make the brush thread-safe
5278
53- // Manage cache size
54- if ( wallpaperCache . Count >= MAX_CACHE_SIZE )
79+ // Manage cache size
80+ lock ( CacheLock )
81+ {
82+ if ( WallpaperCache . Count >= MaxCacheSize )
5583 {
5684 // Remove the oldest wallpaper from the cache
57- var oldestCache = wallpaperCache . Keys . OrderBy ( k => k . Item2 ) . FirstOrDefault ( ) ;
85+ var oldestCache = WallpaperCache . Keys . OrderBy ( k => k . Item2 ) . FirstOrDefault ( ) ;
5886 if ( oldestCache != default )
5987 {
60- wallpaperCache . Remove ( oldestCache ) ;
88+ WallpaperCache . Remove ( oldestCache ) ;
6189 }
6290 }
6391
64- wallpaperCache . Add ( ( wallpaperPath , dateModified ) , wallpaperBrush ) ;
92+ WallpaperCache . Add ( ( wallpaperPath , dateModified ) , wallpaperBrush ) ;
6593 return wallpaperBrush ;
6694 }
67-
68- var wallpaperColor = GetWallpaperColor ( ) ;
69- return new SolidColorBrush ( wallpaperColor ) ;
7095 }
7196 catch ( Exception ex )
7297 {
@@ -77,7 +102,7 @@ public static Brush GetWallpaperBrush()
77102
78103 private static Color GetWallpaperColor ( )
79104 {
80- RegistryKey key = Registry . CurrentUser . OpenSubKey ( @"Control Panel\Colors" , true ) ;
105+ RegistryKey key = Registry . CurrentUser . OpenSubKey ( @"Control Panel\Colors" , false ) ;
81106 var result = key ? . GetValue ( "Background" , null ) ;
82107 if ( result is string strResult )
83108 {
@@ -86,8 +111,9 @@ private static Color GetWallpaperColor()
86111 var parts = strResult . Trim ( ) . Split ( new [ ] { ' ' } , 3 ) . Select ( byte . Parse ) . ToList ( ) ;
87112 return Color . FromRgb ( parts [ 0 ] , parts [ 1 ] , parts [ 2 ] ) ;
88113 }
89- catch
114+ catch ( Exception ex )
90115 {
116+ App . API . LogException ( nameof ( WallpaperPathRetrieval ) , "Error parsing wallpaper color" , ex ) ;
91117 }
92118 }
93119
0 commit comments