From baad75aacc446fb33c2ac4e65be994375f0e9418 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Sat, 19 Feb 2022 00:37:36 +0100 Subject: [PATCH] Added a routine to get the WIC supported extensions automatically. --- src/Greenshot.Base/Core/ClipboardHelper.cs | 16 +++--- .../FileFormatHandlerExtensions.cs | 2 +- .../DefaultFileFormatHandler.cs | 2 - .../WpfFileFormatHandler.cs | 56 ++++++++++++++++++- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 3 + src/Greenshot/Forms/MainForm.cs | 5 +- src/Greenshot/GreenshotMain.cs | 3 - 7 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/Greenshot.Base/Core/ClipboardHelper.cs b/src/Greenshot.Base/Core/ClipboardHelper.cs index 6030ecf16..6276e9c6e 100644 --- a/src/Greenshot.Base/Core/ClipboardHelper.cs +++ b/src/Greenshot.Base/Core/ClipboardHelper.cs @@ -523,9 +523,9 @@ EndSelection:<<<<<<<4 var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances(); var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList(); - foreach (var fileData in IterateClipboardContent(dataObject)) + foreach (var (stream, filename) in IterateClipboardContent(dataObject)) { - var extension = Path.GetExtension(fileData.filename)?.ToLowerInvariant(); + var extension = Path.GetExtension(filename)?.ToLowerInvariant(); if (!supportedExtensions.Contains(extension)) { continue; @@ -535,7 +535,7 @@ EndSelection:<<<<<<<4 try { - if (!fileFormatHandlers.TryLoadFromStream(fileData.stream, extension, out bitmap)) + if (!fileFormatHandlers.TryLoadFromStream(stream, extension, out bitmap)) { continue; } @@ -548,7 +548,7 @@ EndSelection:<<<<<<<4 } finally { - fileData.stream?.Dispose(); + stream?.Dispose(); } // If we get here, there is an image yield return bitmap; @@ -601,9 +601,9 @@ EndSelection:<<<<<<<4 var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances(); var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList(); - foreach (var fileData in IterateClipboardContent(dataObject)) + foreach (var (stream, filename) in IterateClipboardContent(dataObject)) { - var extension = Path.GetExtension(fileData.filename)?.ToLowerInvariant(); + var extension = Path.GetExtension(filename)?.ToLowerInvariant(); if (!supportedExtensions.Contains(extension)) { continue; @@ -612,7 +612,7 @@ EndSelection:<<<<<<<4 IEnumerable drawableContainers; try { - drawableContainers = fileFormatHandlers.LoadDrawablesFromStream(fileData.stream, extension); + drawableContainers = fileFormatHandlers.LoadDrawablesFromStream(stream, extension); } catch (Exception ex) { @@ -621,7 +621,7 @@ EndSelection:<<<<<<<4 } finally { - fileData.stream?.Dispose(); + stream?.Dispose(); } // If we get here, there is an image foreach (var container in drawableContainers) diff --git a/src/Greenshot.Base/Core/FileFormatHandlers/FileFormatHandlerExtensions.cs b/src/Greenshot.Base/Core/FileFormatHandlers/FileFormatHandlerExtensions.cs index 54eed9762..8941c7184 100644 --- a/src/Greenshot.Base/Core/FileFormatHandlers/FileFormatHandlerExtensions.cs +++ b/src/Greenshot.Base/Core/FileFormatHandlers/FileFormatHandlerExtensions.cs @@ -58,7 +58,7 @@ namespace Greenshot.Base.Core.FileFormatHandlers /// public static IEnumerable ExtensionsFor(this IEnumerable fileFormatHandlers, FileFormatHandlerActions fileFormatHandlerAction) { - return fileFormatHandlers.Where(ffh => ffh.SupportedExtensions.ContainsKey(fileFormatHandlerAction)).SelectMany(ffh => ffh.SupportedExtensions[fileFormatHandlerAction]).Distinct(); + return fileFormatHandlers.Where(ffh => ffh.SupportedExtensions.ContainsKey(fileFormatHandlerAction)).SelectMany(ffh => ffh.SupportedExtensions[fileFormatHandlerAction]).Distinct().OrderBy(e => e); } /// diff --git a/src/Greenshot.Editor/FileFormatHandlers/DefaultFileFormatHandler.cs b/src/Greenshot.Editor/FileFormatHandlers/DefaultFileFormatHandler.cs index e5b8c3e2a..30d785bb5 100644 --- a/src/Greenshot.Editor/FileFormatHandlers/DefaultFileFormatHandler.cs +++ b/src/Greenshot.Editor/FileFormatHandlers/DefaultFileFormatHandler.cs @@ -26,7 +26,6 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using Greenshot.Base.Core; -using Greenshot.Base.IniFile; using Greenshot.Base.Interfaces; using Greenshot.Base.Interfaces.Plugin; using log4net; @@ -40,7 +39,6 @@ namespace Greenshot.Editor.FileFormatHandlers { private static readonly ILog Log = LogManager.GetLogger(typeof(DefaultFileFormatHandler)); private readonly IReadOnlyCollection _ourExtensions = new[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg", ".tiff", ".tif" }; - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); public DefaultFileFormatHandler() { SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions; diff --git a/src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs b/src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs index 46b414197..2d655bb1b 100644 --- a/src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs +++ b/src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs @@ -21,14 +21,15 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Drawing; using System.IO; +using System.Linq; using System.Windows.Media.Imaging; using Greenshot.Base.Interfaces; using Greenshot.Base.Core; using Greenshot.Base.Interfaces.Plugin; using log4net; +using Microsoft.Win32; namespace Greenshot.Editor.FileFormatHandlers { @@ -38,16 +39,67 @@ namespace Greenshot.Editor.FileFormatHandlers public class WpfFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler { private static readonly ILog Log = LogManager.GetLogger(typeof(WpfFileFormatHandler)); - private IReadOnlyCollection LoadFromStreamExtensions { get; } = new []{ ".jxr", ".wdp", ".wmp", ".heic", ".heif" }; + private const string HeifDecoder = "{E9A4A80A-44FE-4DE4-8971-7150B10A5199}"; + private const string WicDecoderCategory = "{7ED96837-96F0-4812-B211-F13C24117ED3}"; + + private IReadOnlyCollection LoadFromStreamExtensions { get; } = new []{ ".jxr", ".dds", ".hdp", ".wdp", ".wmp"}; private IReadOnlyCollection SaveToStreamExtensions { get; } = new[] { ".jxr" }; public WpfFileFormatHandler() { + LoadFromStreamExtensions = LoadFromStreamExtensions.ToList().Concat(RetrieveSupportedExtensions()).OrderBy(e => e).Distinct().ToArray(); + SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = LoadFromStreamExtensions; SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = LoadFromStreamExtensions; SupportedExtensions[FileFormatHandlerActions.SaveToStream] = SaveToStreamExtensions; } + /// + /// Detect all the formats WIC supports + /// + /// IEnumerable{string} + private IEnumerable RetrieveSupportedExtensions() + { + string baseKeyPath; + if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) + { + baseKeyPath = "Wow6432Node\\CLSID"; + } + else + { + baseKeyPath = "CLSID"; + } + + using RegistryKey baseKey = Registry.ClassesRoot.OpenSubKey(baseKeyPath, false); + if (baseKey == null) yield break; + + var wicDecoderCategoryPath = Path.Combine(baseKeyPath, WicDecoderCategory, "instance"); + using RegistryKey categoryKey = Registry.ClassesRoot.OpenSubKey(wicDecoderCategoryPath, false); + if (categoryKey == null) + { + yield break; + } + foreach (var codecGuid in categoryKey.GetSubKeyNames()) + { + // Read the properties of the single registered decoder + using var codecKey = baseKey.OpenSubKey(codecGuid); + if (codecKey == null) continue; + + var fileExtensions = Convert.ToString(codecKey.GetValue("FileExtensions", "")).ToLowerInvariant(); + foreach (var fileExtension in fileExtensions.Split(',')) + { + yield return fileExtension; + } + } + var heifDecoderPath = Path.Combine(baseKeyPath, HeifDecoder); + + using RegistryKey heifKey = Registry.ClassesRoot.OpenSubKey(heifDecoderPath, false); + if (heifKey == null) yield break; + + yield return ".heic"; + yield return ".heif"; + } + /// public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null) { diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index 1b83dee9c..e782aa232 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -181,6 +181,9 @@ namespace Greenshot.Editor.Forms UpdateUi(); + // Use best fit + ZoomBestFitMenuItemClick(this, EventArgs.Empty); + // Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it. HideToolstripItems(); } diff --git a/src/Greenshot/Forms/MainForm.cs b/src/Greenshot/Forms/MainForm.cs index 7e69629c7..64f2e521f 100644 --- a/src/Greenshot/Forms/MainForm.cs +++ b/src/Greenshot/Forms/MainForm.cs @@ -44,6 +44,7 @@ using Greenshot.Base.Interfaces.Plugin; using Greenshot.Base.UnmanagedHelpers; using Greenshot.Configuration; using Greenshot.Destinations; +using Greenshot.Editor; using Greenshot.Editor.Destinations; using Greenshot.Editor.Drawing; using Greenshot.Editor.Forms; @@ -163,7 +164,7 @@ namespace Greenshot.Forms if (argument.ToLower().Equals("/exit")) { - // unregister application on uninstall (allow uninstall) + // un-register application on uninstall (allow uninstall) try { LOG.Info("Sending all instances the exit command."); @@ -388,6 +389,8 @@ namespace Greenshot.Forms _instance = this; + EditorInitialize.Initialize(); + // Factory for surface objects ISurface SurfaceFactory() => new Surface(); diff --git a/src/Greenshot/GreenshotMain.cs b/src/Greenshot/GreenshotMain.cs index adb936976..2d42d4b11 100644 --- a/src/Greenshot/GreenshotMain.cs +++ b/src/Greenshot/GreenshotMain.cs @@ -20,11 +20,9 @@ */ using System; -using System.Drawing.Imaging; using System.Globalization; using System.Net; using System.Reflection; -using Greenshot.Editor; using Greenshot.Forms; namespace Greenshot @@ -67,7 +65,6 @@ namespace Greenshot CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; - EditorInitialize.Initialize(); MainForm.Start(args); } }