Skip to content

Commit 7cbf6bd

Browse files
author
Carl Chang
committed
add command line argument support;
add decoding support based on registered WIC decoders; image delayed loading in viewer; improve error handling in GetImageSource; fix cache progress message display; simply some load methods; other minor fixes;
1 parent 0450d08 commit 7cbf6bd

File tree

12 files changed

+321
-262
lines changed

12 files changed

+321
-262
lines changed

App.xaml.cs

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@ public partial class App : Application
1818
public static readonly string ExeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
1919
public static readonly HashSet<string> ImageExtensions =
2020
new HashSet<string>(new[] {
21-
"jpg", "jpeg", "png", "gif", "tiff", "bmp",
22-
".jpg", ".jpeg", ".png", ".gif", ".tiff", ".bmp",
21+
".jpg", ".jpeg", ".png", ".tiff", ".gif", ".bmp", ".ico", ".dds", ".jxr", ".hdp", ".wdp"
2322
});
2423
public static readonly HashSet<string> ZipExtensions =
2524
new HashSet<string>(new[] {
26-
"zip", "rar", "7z",
27-
".zip", ".rar", ".7z",
25+
".zip", ".rar", ".7z", ".bz2", ".bzip2", ".tbz2", ".tbz", ".gz", ".gzip", ".tgz", ".tar",
26+
".wim", ".swm", ".esd", ".xz", ".txz", ".zipx", ".jar", ".xpi", ".odt", ".ods", ".docx",
27+
".xlsx", ".epub", ".apm", ".ar", ".a", ".deb", ".lib", ".arj", ".cab", ".chm", ".chw",
28+
".chi", ".chq", ".msi", ".msp", ".doc", ".xls", ".ppt", ".cpio", ".cramfs", ".dmg",
29+
".ext", ".ext2", ".ext3", ".ext4", ".img", ".fat", ".img", ".hfs", ".hfsx", ".hxs",
30+
".hxi", ".hxr", ".hxq", ".hxw", ".lit", ".ihex", ".iso", ".img", ".lzh", ".lha", ".lzma",
31+
".mbr", ".mslz", ".mub", ".nsis", ".ntfs", ".img", ".mbr", ".r00", ".rpm", ".ppmd",
32+
".qcow", ".qcow2", ".qcow2c", ".001", ".squashfs", ".udf", ".iso", ".img", ".scap",
33+
".uefif", ".vdi", ".vhd", ".vmdk", ".xar", ".pkg", ".z", ".taz"
2834
});
2935
//public const int PreviewCount = 4;
3036
public static Random Random = new Random();
@@ -48,6 +54,18 @@ public partial class App : Application
4854

4955
private void App_Startup(object sender, StartupEventArgs e) {
5056
try {
57+
//handle immersion mode change
58+
Setting.StaticPropertyChanged += Setting_StaticPropertyChanged;
59+
60+
//get supported extensions
61+
foreach (var ext in NativeHelpers.GetWICDecoders().Select(s => s.ToLowerInvariant())) {
62+
if (!ImageExtensions.Contains(ext)) ImageExtensions.Add(ext);
63+
}
64+
65+
//set working directory
66+
Directory.SetCurrentDirectory(ExeDir);
67+
68+
//load config
5169
Setting.LoadConfigFromFile();
5270

5371
//create resources
@@ -63,24 +81,34 @@ private void App_Startup(object sender, StartupEventArgs e) {
6381
//make sure thumbs db is correct
6482
CheckThumbsDB();
6583

84+
//check args
85+
if (e.Args?.Length > 0) {
6686
#if DEBUG
67-
if (e.Args?.Length > 0 && e.Args[0] == "-cleandb") {
68-
Execute(Table.Thumbs, (table, con) => {
69-
using (var cmd = new SQLiteCommand(con)) {
70-
cmd.CommandText = $@"delete from {table.Name}";
71-
cmd.ExecuteNonQuery();
72-
cmd.CommandText = @"vacuum";
73-
cmd.ExecuteNonQuery();
74-
}
75-
return 0;
76-
});
77-
}
87+
if (e.Args.Contains("-cleandb")) {
88+
Execute(Table.Thumbs, (table, con) => {
89+
using (var cmd = new SQLiteCommand(con)) {
90+
cmd.CommandText = $@"delete from {table.Name}";
91+
cmd.ExecuteNonQuery();
92+
cmd.CommandText = @"vacuum";
93+
cmd.ExecuteNonQuery();
94+
}
95+
return 0;
96+
});
97+
}
7898
#endif
99+
switch (Helpers.GetPathType(new DirectoryInfo(e.Args[0]))) {
100+
case FileFlags.Directory:
101+
case FileFlags.Archive:
102+
new MainWindow() { InitialPath = e.Args[0] }.Show();
103+
return;
104+
case FileFlags.Image:
105+
var objInfo = new ObjectInfo(e.Args[0], FileFlags.Image);
106+
new ViewWindow() { ObjectInfo = objInfo }.Show();
107+
return;
108+
}
109+
}
79110

80-
//handle immersion mode change
81-
Setting.StaticPropertyChanged += Setting_StaticPropertyChanged;
82-
83-
//show mainwindow
111+
//show mainwindow if no cmdline args
84112
new MainWindow().Show();
85113
}
86114
catch (Exception ex) {

Helpers/Helpers.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public static class Helpers {
126126
/// <returns></returns>
127127
public static FileFlags GetPathType(string fileName) {
128128
var ft = FileFlags.Unknown;
129-
var extension = Path.GetExtension(fileName)?.TrimStart('.').ToLowerInvariant();
129+
var extension = Path.GetExtension(fileName)?.ToLowerInvariant();
130130
if (extension?.Length == 0) return ft;
131131

132132
if (App.ImageExtensions.Contains(extension)) ft = FileFlags.Image;
@@ -135,6 +135,8 @@ public static FileFlags GetPathType(string fileName) {
135135
}
136136

137137
public static FileFlags GetPathType(FileSystemInfo fsInfo) {
138+
if (fsInfo.Attributes == (FileAttributes)(-1))//doesnt exist
139+
return FileFlags.Error;
138140
if (fsInfo.Attributes.HasFlag(FileAttributes.Directory))
139141
return FileFlags.Directory;
140142
if (App.ZipExtensions.Contains(fsInfo.Extension.ToLowerInvariant()))
@@ -352,6 +354,11 @@ public static void SwitchFullScreen(Window win, ref Rect lastRect, bool? fullScr
352354
win.Height = lastRect.Height;
353355
}
354356
}
357+
358+
public static void ShutdownCheck() {
359+
if (Application.Current.Windows.Cast<Window>().Count(w => w is MainWindow || w is ViewWindow) == 0)
360+
Application.Current.Shutdown();
361+
}
355362
}
356363

357364

Helpers/LoadHelper.cs

Lines changed: 85 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ internal static void UpdateSourcePaths(ObjectInfo objInfo) {
312312
case FileFlags.Archive:
313313
LoadFile(new LoadOptions(objInfo.FileSystemPath) {
314314
Flags = FileFlags.Archive,
315+
LoadImage = false,
315316
ObjInfoCallback = oi => objInfo.SourcePaths = oi.SourcePaths,
316317
});
317318
break;
@@ -377,25 +378,20 @@ public static ImageSource GetImageSource(ObjectInfo objInfo, int sourcePathIdx,
377378
}
378379
break;
379380
case FileFlags.Archive:
381+
case FileFlags.Archive | FileFlags.Image:
380382
if (objInfo.SourcePaths?.Length > 0) {
381383
LoadFile(new LoadOptions(objInfo.FileSystemPath) {
382384
DecodeSize = decodeSize,
383385
LoadImage = true,
384386
TryCache = tryCache,
385387
FileNames = new[] { objInfo.SourcePaths[sourcePathIdx] },
386-
Flags = FileFlags.Archive,
388+
Flags = objInfo.Flags,
387389
CldInfoCallback = oi => source = oi.ImageSource,
388390
ObjInfoCallback = oi => objInfo.Flags = oi.Flags
389391
});
390392
}
391393
if (source == null) {
392-
source = App.fa_archive;
393-
}
394-
break;
395-
case FileFlags.Archive | FileFlags.Image:
396-
source = objInfo.ImageSource;
397-
if (source == null) {
398-
source = App.fa_image;
394+
source = objInfo.Flags.HasFlag(FileFlags.Image) ? App.fa_image : App.fa_archive;
399395
}
400396
break;
401397
}
@@ -455,89 +451,95 @@ public static void UpdateImageInfo(Stream stream, ImageInfo imgInfo) {
455451
/// <para>A <paramref name="decodeSize"/> higher than the actual resolution will be ignored.
456452
/// Note that this is the size in pixel instead of the device-independent size used in WPF.</para>
457453
/// </summary>
454+
/// <returns>Returns null if error occured.</returns>
458455
public static BitmapSource GetImageSource(Stream stream, SizeInt decodeSize = default) {
459-
stream.Position = 0;
460-
var frame = BitmapFrame.Create(stream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
461-
var pixelSize = new SizeInt(frame.PixelWidth, frame.PixelHeight);
462-
ushort orien = 0;
463-
if ((frame.Metadata as BitmapMetadata)?.GetQuery("/app1/ifd/{ushort=274}") is ushort u)
464-
orien = u;
465-
frame = null;
466-
467-
//calculate decode size
468-
if (decodeSize.Width + decodeSize.Height > 0) {
469-
//use pixelSize if decodeSize is too big
470-
//DecodePixelWidth / Height is set to PixelWidth / Height anyway in reference source
471-
if (decodeSize.Width > pixelSize.Width) decodeSize.Width = pixelSize.Width;
472-
if (decodeSize.Height > pixelSize.Height) decodeSize.Height = pixelSize.Height;
473-
474-
//flip decodeSize according to orientation
475-
if (orien > 4 && orien < 9)
476-
decodeSize = new SizeInt(decodeSize.Height, decodeSize.Width);
477-
}
456+
try {
457+
stream.Position = 0;
458+
var frame = BitmapFrame.Create(stream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
459+
var pixelSize = new SizeInt(frame.PixelWidth, frame.PixelHeight);
460+
ushort orien = 0;
461+
if ((frame.Metadata as BitmapMetadata)?.GetQuery("/app1/ifd/{ushort=274}") is ushort u)
462+
orien = u;
463+
frame = null;
464+
465+
//calculate decode size
466+
if (decodeSize.Width + decodeSize.Height > 0) {
467+
//use pixelSize if decodeSize is too big
468+
//DecodePixelWidth / Height is set to PixelWidth / Height anyway in reference source
469+
if (decodeSize.Width > pixelSize.Width) decodeSize.Width = pixelSize.Width;
470+
if (decodeSize.Height > pixelSize.Height) decodeSize.Height = pixelSize.Height;
471+
472+
//flip decodeSize according to orientation
473+
if (orien > 4 && orien < 9)
474+
decodeSize = new SizeInt(decodeSize.Height, decodeSize.Width);
475+
}
478476

479-
//init bitmapimage
480-
stream.Position = 0;
481-
var bi = new BitmapImage();
482-
bi.BeginInit();
483-
bi.CacheOption = BitmapCacheOption.OnLoad;
484-
if (pixelSize.Width > 0 && pixelSize.Height > 0) {
485-
//setting both DecodePixelWidth and Height will break the aspect ratio
486-
var imgRatio = (double)pixelSize.Width / pixelSize.Height;
487-
if (decodeSize.Width > 0 && decodeSize.Height > 0) {
488-
if (imgRatio > (double)decodeSize.Width / decodeSize.Height)
477+
//init bitmapimage
478+
stream.Position = 0;
479+
var bi = new BitmapImage();
480+
bi.BeginInit();
481+
bi.CacheOption = BitmapCacheOption.OnLoad;
482+
if (pixelSize.Width > 0 && pixelSize.Height > 0) {
483+
//setting both DecodePixelWidth and Height will break the aspect ratio
484+
var imgRatio = (double)pixelSize.Width / pixelSize.Height;
485+
if (decodeSize.Width > 0 && decodeSize.Height > 0) {
486+
if (imgRatio > (double)decodeSize.Width / decodeSize.Height)
487+
bi.DecodePixelHeight = decodeSize.Height;
488+
else
489+
bi.DecodePixelWidth = decodeSize.Width;
490+
}
491+
else if (decodeSize.Width == 0 && decodeSize.Height > 0)
489492
bi.DecodePixelHeight = decodeSize.Height;
490-
else
493+
else if (decodeSize.Height == 0 && decodeSize.Width > 0)
491494
bi.DecodePixelWidth = decodeSize.Width;
492495
}
493-
else if (decodeSize.Width == 0 && decodeSize.Height > 0)
494-
bi.DecodePixelHeight = decodeSize.Height;
495-
else if (decodeSize.Height == 0 && decodeSize.Width > 0)
496-
bi.DecodePixelWidth = decodeSize.Width;
497-
}
498-
bi.StreamSource = stream;
499-
bi.EndInit();
500-
bi.Freeze();
501-
502-
if (orien < 2) return bi;
503-
//apply orientation based on metadata
504-
var tb = new TransformedBitmap();
505-
tb.BeginInit();
506-
tb.Source = bi;
507-
switch (orien) {
508-
case 2:
509-
tb.Transform = new ScaleTransform(-1d, 1d);
510-
break;
511-
case 3:
512-
tb.Transform = new RotateTransform(180d);
513-
break;
514-
case 4:
515-
tb.Transform = new ScaleTransform(1d, -1d);
516-
break;
517-
case 5: {
518-
var tg = new TransformGroup();
519-
tg.Children.Add(new RotateTransform(90d));
520-
tg.Children.Add(new ScaleTransform(-1d, 1d));
521-
tb.Transform = tg;
496+
bi.StreamSource = stream;
497+
bi.EndInit();
498+
bi.Freeze();
499+
500+
if (orien < 2) return bi;
501+
//apply orientation based on metadata
502+
var tb = new TransformedBitmap();
503+
tb.BeginInit();
504+
tb.Source = bi;
505+
switch (orien) {
506+
case 2:
507+
tb.Transform = new ScaleTransform(-1d, 1d);
522508
break;
523-
}
524-
case 6:
525-
tb.Transform = new RotateTransform(90d);
526-
break;
527-
case 7: {
528-
var tg = new TransformGroup();
529-
tg.Children.Add(new RotateTransform(90d));
530-
tg.Children.Add(new ScaleTransform(1d, -1d));
531-
tb.Transform = tg;
509+
case 3:
510+
tb.Transform = new RotateTransform(180d);
532511
break;
533-
}
534-
case 8:
535-
tb.Transform = new RotateTransform(270d);
536-
break;
512+
case 4:
513+
tb.Transform = new ScaleTransform(1d, -1d);
514+
break;
515+
case 5: {
516+
var tg = new TransformGroup();
517+
tg.Children.Add(new RotateTransform(90d));
518+
tg.Children.Add(new ScaleTransform(-1d, 1d));
519+
tb.Transform = tg;
520+
break;
521+
}
522+
case 6:
523+
tb.Transform = new RotateTransform(90d);
524+
break;
525+
case 7: {
526+
var tg = new TransformGroup();
527+
tg.Children.Add(new RotateTransform(90d));
528+
tg.Children.Add(new ScaleTransform(1d, -1d));
529+
tb.Transform = tg;
530+
break;
531+
}
532+
case 8:
533+
tb.Transform = new RotateTransform(270d);
534+
break;
535+
}
536+
tb.EndInit();
537+
tb.Freeze();
538+
return tb;
539+
}
540+
catch {
541+
return null;
537542
}
538-
tb.EndInit();
539-
tb.Freeze();
540-
return tb;
541543
}
542544

543545
public static void CacheFolder(string folderPath, ref CancellationTokenSource tknSrc, object tknLock, Action<string, int, int> callback) {
@@ -587,29 +589,6 @@ public static void CacheFolder(string folderPath, ref CancellationTokenSource tk
587589
tknSrc = null;
588590
Monitor.Exit(tknLock);
589591
}
590-
591-
// while (cacheThreadIdx < ObjectList.Count) {
592-
// while (tknSrc_LoadThumb != null || LoadThrottle.CurrentCount <= 1) {
593-
// if (cacheThreadExit) break;
594-
// Thread.Sleep(2000);
595-
// }
596-
597-
// var objInfo = ObjectList[cacheThreadIdx];
598-
// var decodeSize = (SizeInt)Setting.ThumbnailSize;
599-
// if (objInfo.SourcePaths == null) UpdateSourcePaths(objInfo);
600-
// var path = objInfo.Flags.HasFlag(FileFlags.Archive) ?
601-
// Path.Combine(objInfo.FileSystemPath, objInfo.SourcePaths[0]) :
602-
// objInfo.SourcePaths[0];
603-
// if (!SQLiteHelper.ThumbExistInDB(path, decodeSize)) {
604-
//#if DEBUG
605-
// Console.WriteLine($"Caching to DB: {path}");
606-
//#endif
607-
// GetImageSource(objInfo, 0, decodeSize, false);
608-
// }
609-
610-
// if (cacheThreadExit) break;
611-
// cacheThreadIdx += 1;
612-
// }
613592
}
614593
}
615594
}

0 commit comments

Comments
 (0)