@@ -235,20 +235,15 @@ internal static void UpdateSourcePaths(ObjectInfo objInfo) {
235235 /// </summary>
236236 /// <param name="objInfo">The ObjectInfo of the container.</param>
237237 /// <param name="sourcePathIdx">Index of the file to load in ObjectInfo.SourcePaths.</param>
238- public static async Task < ImageSource > GetImageSource ( ObjectInfo objInfo , int sourcePathIdx , bool isThumb ) {
239- //var targetPath = objInfo.SourcePaths[sourcePathIdx];
240- //var fsPath = objInfo.FileSystemPath;
241- //var flags = objInfo.Flags;
242- var size = isThumb ? ( SizeInt ) Setting . ThumbnailSize : default ;
243- //var imgSource = objInfo.ImageSource;
244- return await Task . Run ( ( ) => GetImageSource ( objInfo , sourcePathIdx , size ) ) ;
238+ public static async Task < ImageSource > GetImageSourceAsync ( ObjectInfo objInfo , int sourcePathIdx , SizeInt decodeSize = default , double ? decodeScale = null ) {
239+ return await Task . Run ( ( ) => GetImageSource ( objInfo , sourcePathIdx , decodeSize , decodeScale ) ) ;
245240 }
246241
247242 /// <summary>
248243 /// Used to get image from within a container.
249244 /// </summary>
250- /// <param name="size ">Decode size.</param>
251- public static ImageSource GetImageSource ( ObjectInfo objInfo , int sourcePathIdx , SizeInt size ) {
245+ /// <param name="decodeSize ">Decode size.</param>
246+ public static ImageSource GetImageSource ( ObjectInfo objInfo , int sourcePathIdx , SizeInt decodeSize = default , double ? decodeScale = null ) {
252247 if ( objInfo . Flags . HasFlag ( FileFlags . Error ) ) return App . fa_exclamation ;
253248 if ( objInfo . Flags == FileFlags . Unknown ) return App . fa_file ;
254249
@@ -266,21 +261,21 @@ public static ImageSource GetImageSource(ObjectInfo objInfo, int sourcePathIdx,
266261 switch ( objInfo . Flags ) {
267262 case FileFlags . Directory :
268263 if ( objInfo . SourcePaths ? . Length > 0 )
269- source = GetImageSource ( objInfo . SourcePaths [ sourcePathIdx ] , size ) ;
264+ source = GetImageSource ( objInfo . SourcePaths [ sourcePathIdx ] , decodeSize : decodeSize , decodeScale : decodeScale ) ;
270265 if ( source == null ) {
271266 source = App . fa_folder ;
272267 }
273268 break ;
274269 case FileFlags . Image :
275- source = GetImageSource ( objInfo . FileSystemPath , size ) ;
270+ source = GetImageSource ( objInfo . FileSystemPath , decodeSize : decodeSize , decodeScale : decodeScale ) ;
276271 if ( source == null ) {
277272 source = App . fa_image ;
278273 }
279274 break ;
280275 case FileFlags . Archive :
281276 if ( objInfo . SourcePaths ? . Length > 0 ) {
282277 MainWindow . LoadFile ( new LoadOptions ( objInfo . FileSystemPath ) {
283- DecodeSize = size ,
278+ DecodeSize = decodeSize ,
284279 LoadImage = true ,
285280 FileNames = new [ ] { objInfo . SourcePaths [ sourcePathIdx ] } ,
286281 Flags = FileFlags . Archive ,
@@ -312,75 +307,86 @@ public static ImageSource GetImageSource(ObjectInfo objInfo, int sourcePathIdx,
312307 }
313308
314309 /// <summary>
315- /// Load image from disk if cache is not availble.
310+ /// <para>Load image from disk if cache is not availble.</para>
311+ /// <para>Setting <paramref name="decodeScale"/> to 1 is the same as leaving <paramref name="decodeSize"/> to default.</para>
316312 /// </summary>
317- public static BitmapSource GetImageSource ( string path , SizeInt decodeSize = default ) {
313+ public static BitmapSource GetImageSource ( string path , SizeInt decodeSize = default , double ? decodeScale = null ) {
318314 BitmapSource bs = null ;
319315 try {
320- var isThumb = decodeSize . Width + decodeSize . Height > 0 ;
316+ var isThumb = decodeSize . Width + decodeSize . Height > 0 && decodeScale == null ;
321317 if ( isThumb ) {
322318 //try load from cache when decodeSize is non-zero
323319 bs = SQLiteHelper . GetFromThumbDB ( path , decodeSize ) ;
324320 if ( bs != null ) return bs ;
325321 }
326-
327- ////avoid file dead locks
328- //Monitor.Enter(lock_Loading);
329- //var wait = loading.Contains(path);
330- //Monitor.Exit(lock_Loading);
331- //while (wait) {
332- // Thread.Sleep(100);
333- // Monitor.Enter(lock_Loading);
334- // wait = loading.Contains(path);
335- // Monitor.Exit(lock_Loading);
336- //}
337- //Monitor.Enter(lock_Loading);
338- //loading.Add(path);
339- //Monitor.Exit(lock_Loading);
340- //load from disk
341322#if DEBUG
342323 Console . WriteLine ( "Loading from disk: " + path ) ;
343324#endif
344325 using ( var fs = new FileStream ( path , FileMode . Open , FileAccess . Read ) ) {
345- bs = GetImageSource ( fs , decodeSize ) ;
326+ bs = GetImageSource ( fs , decodeSize , decodeScale ) ;
346327 }
347328 if ( isThumb && bs != null ) SQLiteHelper . AddToThumbDB ( bs , path , decodeSize ) ;
348329 }
349330 catch ( Exception ex ) {
350331 MessageBox . Show ( $ "Error loading file { path } .\r \n { ex . Message } ", "Error Loading File" , MessageBoxButton . OK , MessageBoxImage . Error ) ;
351332 }
352- finally {
353- //loading.Remove(path);
354- }
355333
356334 return bs ;
357335 }
358336
359337 /// <summary>
360- /// Decode image from stream (FileStream when loading from file or MemoryStream when loading from archive.
338+ /// <para>Decode image from stream (FileStream when loading from file or MemoryStream when loading from archive.</para>
339+ /// <para>A <paramref name="decodeSize"/> higher than the actual resolution will be ignored.
340+ /// Note that this is the size in pixel instead of the device-independent size used in WPF.</para>
341+ /// <para><paramref name="decodeScale"/> can be used to further scale up or down <paramref name="decodeSize"/>.</para>
361342 /// </summary>
362- public static BitmapSource GetImageSource ( Stream stream , SizeInt decodeSize ) {
343+ public static BitmapSource GetImageSource ( Stream stream , SizeInt decodeSize = default , double ? decodeScale = null ) {
363344 stream . Position = 0 ;
364345 var frame = BitmapFrame . Create ( stream , BitmapCreateOptions . DelayCreation , BitmapCacheOption . None ) ;
365- var frameSize = new Size ( frame . PixelWidth , frame . PixelHeight ) ;
346+ var pixelSize = new SizeInt ( frame . PixelWidth , frame . PixelHeight ) ;
366347 ushort orien = 0 ;
367348 if ( ( frame . Metadata as BitmapMetadata ) ? . GetQuery ( "/app1/ifd/{ushort=274}" ) is ushort u )
368349 orien = u ;
369350 frame = null ;
370351
371- //flip decodeSize according to orientation
372- if ( decodeSize . Width + decodeSize . Height > 0 && orien > 4 && orien < 9 )
373- decodeSize = new SizeInt ( decodeSize . Height , decodeSize . Width ) ;
352+ //calculate decode size
353+ double newW = 0d , newH = 0d ;
354+ if ( decodeSize . Width + decodeSize . Height > 0 ) {
355+ //use pixelSize if decodeSize is too big
356+ //DecodePixelWidth / Height is set to PixelWidth / Height anyway in reference source
357+ if ( decodeSize . Width > pixelSize . Width ) decodeSize . Width = pixelSize . Width ;
358+ if ( decodeSize . Height > pixelSize . Height ) decodeSize . Height = pixelSize . Height ;
359+
360+ //flip decodeSize according to orientation
361+ if ( orien > 4 && orien < 9 ) {
362+ newW = decodeSize . Height ;
363+ newH = decodeSize . Width ;
364+ }
365+ //apply decode scale
366+ if ( decodeScale > 0d ) {
367+ newW *= decodeScale . Value ;
368+ newH *= decodeScale . Value ;
369+ }
370+ }
371+ //apply decode scale
372+ else if ( decodeScale > 0d && decodeScale < 1d ) {
373+ newW = pixelSize . Width * decodeScale . Value ;
374+ newH = pixelSize . Height * decodeScale . Value ;
375+ }
376+
377+ if ( newW + newH > 0d )
378+ decodeSize = new SizeInt ( Convert . ToInt32 ( newW ) , Convert . ToInt32 ( newH ) ) ;
374379
375380 //init bitmapimage
376381 stream . Position = 0 ;
377382 var bi = new BitmapImage ( ) ;
378383 bi . BeginInit ( ) ;
379384 bi . CacheOption = BitmapCacheOption . OnLoad ;
380- if ( frameSize . Width > 0 && frameSize . Height > 0 ) {
381- var frameRatio = frameSize . Width / frameSize . Height ;
385+ if ( pixelSize . Width > 0 && pixelSize . Height > 0 ) {
386+ //setting both DecodePixelWidth and Height will break the aspect ratio
387+ var imgRatio = ( double ) pixelSize . Width / pixelSize . Height ;
382388 if ( decodeSize . Width > 0 && decodeSize . Height > 0 ) {
383- if ( frameRatio > ( double ) decodeSize . Width / decodeSize . Height )
389+ if ( imgRatio > ( double ) decodeSize . Width / decodeSize . Height )
384390 bi . DecodePixelHeight = decodeSize . Height ;
385391 else
386392 bi . DecodePixelWidth = decodeSize . Width ;
0 commit comments