Skip to content

Commit

Permalink
Add Support for GIFVs
Browse files Browse the repository at this point in the history
- For gifv files only an image was shown.
- Now the gifv file is played back.
  • Loading branch information
thomas694 committed Dec 26, 2021
1 parent 3cd91d5 commit 6786854
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 12 deletions.
38 changes: 32 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

A simple fullscreen WPF-based image viewer that closes when you press Esc and also supports a slideshow mode.

## Functionality
## Functionality / Usage

The image viewer can be used as a standalone application or its window for image viewing can be included as a dialog into another application.
It supports animated GIFs and can either run them or show a preview image only.
It supports animated GIFs and GIFVs and can either run them or show a preview image only.

You can assign the application as default viewer for any supported media format, but especially for gif/gifv files, by using the windows explorer "open with" "choose another app" "always use this app" functionality.

### Mouse

Expand Down Expand Up @@ -34,7 +36,7 @@ It supports animated GIFs and can either run them or show a preview image only.

### Config / Parameters

Some settings can be overridden in WpfImageViewer.exe.config.
Some settings can be overridden in `WpfImageViewer.exe.config`.

* ApplicationTitle
* set the name of the application, e.g. shown during Alt-Tab
Expand All @@ -51,7 +53,7 @@ Some settings can be overridden in WpfImageViewer.exe.config.
* IncludedFileExtensions
* extensions to include when loading images from folder
* include dot before extension, separate by only comma, no space
* default: .bmp,.gif,.jpeg,.jpg,.png,.tif,.tiff
* default: .bmp,.gif,.gifv,.jpeg,.jpg,.png,.tif,.tiff
* MsgColor
* set message text color using a color name
* default: Green
Expand All @@ -61,7 +63,7 @@ Some settings can be overridden in WpfImageViewer.exe.config.
* 0 disables the status text
* a negative value disables fadeout
* RunAnimatedGifs
* run the animated gif or show a preview only
* run the animated gif/gifv or show a preview only
* default: True
* ShowHelpOnLoad
* shows a help screen on application/dialog load
Expand All @@ -75,8 +77,9 @@ Some settings can be overridden in WpfImageViewer.exe.config.
* ZoomStep
* change in zoom value per step
* default: 1.25
<br/>

### Usage as dialog inside another application
## Usage as dialog inside another application

Either include the whole project to your solution or include a reference to the exe only. Then you can create a window object
```csharp
Expand All @@ -94,4 +97,27 @@ or if you only want to specify the folder to load:
// declaration of overloaded constructor
WpfImageViewer.MainWindow wnd = new WpfImageViewer.MainWindow(string folder)
```
<br/>

## Enable Gifv file thumbnails in Windows Explorer (Win 10)

By default no thumbnails are shown for gifv files even they are compatible to standard gif files. But you can enable a setting in windows so that thumbnails for gifv files are provided by windows itself.

To enable thumbnails for the current user only, copy the following lines into a text file named e.g. `enable.reg` and double-click it to import the setting into the windows registry:
```
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\SOFTWARE\Classes\.gifv\ShellEx\{e357fccd-a995-4576-b01f-234630154e96}]
@="{C7657C4A-9F68-40fa-A4DF-96BC08EB3551}"
```
To enable thumbnails for all users on the system, copy the following lines into a text file named e.g. `enable.reg` and double-click it to import the setting into the windows registry:
```
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.gifv\ShellEx\{e357fccd-a995-4576-b01f-234630154e96}]
@="{C7657C4A-9F68-40fa-A4DF-96BC08EB3551}"
```
Afterwards you need to restart your pc or at least log out and in before thumbnails are shown.
<br/><br/>
2 changes: 1 addition & 1 deletion src/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<value>2</value>
</setting>
<setting name="IncludedFileExtensions" serializeAs="String">
<value>.bmp,.gif,.jpeg,.jpg,.png,.tif,.tiff</value>
<value>.bmp,.gif,.gifv,.jpeg,.jpg,.png,.tif,.tiff</value>
</setting>
<setting name="MsgColor" serializeAs="String">
<value>Green</value>
Expand Down
49 changes: 46 additions & 3 deletions src/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
Expand Down Expand Up @@ -71,6 +73,8 @@ private enum Modi

readonly MediaViewModel _mediaViewModel = new MediaViewModel();

private MediaFileServer _mediaFileServer = null;

public MainWindow()
{
string[] args = null;
Expand Down Expand Up @@ -137,6 +141,13 @@ public MainWindow(string folder, bool showHelpOnLoad, bool runAnimatedGifs, bool
Initialize();
}

~MainWindow()
{
if (_mediaFileServer != null)
{
_mediaFileServer.Stop();
}
}

/// <summary>
/// Run modal window asynchronously and let the calling application continue its background work
Expand Down Expand Up @@ -267,13 +278,40 @@ private void Initialize()
}
catch
{
_fileExtensions = new[] { ".bmp", ".gif", ".jpeg", ".jpg", ".png", ".tif", ".tiff" };
_fileExtensions = new[] { ".bmp", ".gif", ".gifv", ".jpeg", ".jpg", ".png", ".tif", ".tiff" };
}

PreviewKeyDown += Window1_PreviewKeyDown;
LostKeyboardFocus += Window1_LostKeyboardFocus;
GotKeyboardFocus += Window1_GotKeyboardFocus;
Closing += Window1_Closing;

// workaround for showing files with .gifv extension
if (_fileExtensions.Contains(".gifv"))
{
int port = 56789;
int count = 0;
do
{
count++;
try
{
_mediaFileServer = new MediaFileServer($"http://localhost:{port}/", RequestHandlerMethod);
port = 0;
}
catch (HttpListenerException)
{
port = new Random().Next(50000, 65000);
}
} while (port != 0 || count < 3);
_mediaFileServer.Run();
}
}

private byte[] RequestHandlerMethod(HttpListenerRequest r)
{
var path = HttpUtility.UrlDecode(r.RawUrl.TrimStart('/'));
return File.ReadAllBytes(path);
}

private void Window1_Loaded(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -335,10 +373,15 @@ private void SetImage(string imagePath = null)
imageBitmap = null;
}
SwitchableImage.Stretch = (imageBitmap == null || (imageBitmap.Width <= Grid1.ActualWidth && imageBitmap.Height <= Grid1.ActualHeight)) ? Stretch.None : Stretch.Uniform;
if (imageBitmap == null || (_runAnimatedGifs && imagePath.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)))
if (imageBitmap == null || (_runAnimatedGifs && (imagePath.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) || imagePath.EndsWith(".gifv", StringComparison.OrdinalIgnoreCase))))
{
var imagePathEncoded = imagePath;
if (_mediaFileServer != null && imagePath.EndsWith(".gifv", StringComparison.OrdinalIgnoreCase))
{
imagePathEncoded = _mediaFileServer.Prefix + HttpUtility.UrlEncode(imagePath);
}
_mediaViewModel.FilenameImage = null;
_mediaViewModel.FilenameMedia = imagePath;
_mediaViewModel.FilenameMedia = imagePathEncoded;
_mediaViewModel.CurrentVisualState = VisualStates.ShowMedia;
}
else
Expand Down
62 changes: 62 additions & 0 deletions src/MediaFileServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Net;
using System.Threading;

namespace WpfImageViewer
{
internal class MediaFileServer
{
private readonly HttpListener _httpListener = new HttpListener();
private readonly Func<HttpListenerRequest, byte[]> _requestHandlerMethod;
private string _prefix;

public string Prefix { get => _prefix; }

public MediaFileServer(string prefix, Func<HttpListenerRequest, byte[]> requestHandlerMethod)
{
_ = prefix ?? throw new ArgumentNullException(nameof(prefix));
_ = requestHandlerMethod ?? throw new ArgumentNullException(nameof(requestHandlerMethod));

_prefix = prefix;
_requestHandlerMethod = requestHandlerMethod;
_httpListener.Prefixes.Add(prefix);
_httpListener.Start();
}

public void Run()
{
_ = ThreadPool.QueueUserWorkItem((o) =>
{
try
{
while (_httpListener.IsListening)
{
_ = ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
byte[] buffer = _requestHandlerMethod(ctx.Request);
ctx.Response.ContentLength64 = buffer.Length;
ctx.Response.ContentType = "application/octet-stream";
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch { }
finally
{
ctx.Response.OutputStream.Close();
}
}, _httpListener.GetContext());
}
}
catch { }
});
}

public void Stop()
{
_httpListener.Stop();
_httpListener.Close();
}
}
}
4 changes: 2 additions & 2 deletions src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
Binary file modified src/Resources/AppIcon.ico
Binary file not shown.
2 changes: 2 additions & 0 deletions src/WpfImageViewer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
Expand All @@ -76,6 +77,7 @@
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MediaFileServer.cs" />
<Compile Include="NullImageConverter.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
Expand Down

0 comments on commit 6786854

Please sign in to comment.