mirror of
https://github.com/greenshot/greenshot
synced 2025-08-21 05:53:27 -07:00
Feature Improve file format support (#385)
This feature will make it easier to support different file formats later on, and also adds a "VectorGraphicsContainer" base class to better support non pixel graphics in the editor. Examples are SVG, WMF/EMF and Emoji which scale automatically to the correct size and are not resized from pixels. Multiple new formats have been added for reading, Jpeg XR for writing.
This commit is contained in:
parent
a32cc1888b
commit
60956771c8
90 changed files with 2793 additions and 1340 deletions
|
@ -120,6 +120,7 @@ namespace Greenshot.Base.Controls
|
||||||
|
|
||||||
private void PrepareFilterOptions()
|
private void PrepareFilterOptions()
|
||||||
{
|
{
|
||||||
|
// TODO: Change to the FileFormatHandlerRegistry to look for all the supported extensions
|
||||||
OutputFormat[] supportedImageFormats = (OutputFormat[]) Enum.GetValues(typeof(OutputFormat));
|
OutputFormat[] supportedImageFormats = (OutputFormat[]) Enum.GetValues(typeof(OutputFormat));
|
||||||
_filterOptions = new FilterOption[supportedImageFormats.Length];
|
_filterOptions = new FilterOption[supportedImageFormats.Length];
|
||||||
for (int i = 0; i < _filterOptions.Length; i++)
|
for (int i = 0; i < _filterOptions.Length; i++)
|
||||||
|
@ -166,7 +167,7 @@ namespace Greenshot.Base.Controls
|
||||||
// if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay
|
// if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay
|
||||||
if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn;
|
if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn;
|
||||||
// otherwise we just add the selected filter item's extension
|
// otherwise we just add the selected filter item's extension
|
||||||
else return fn + "." + Extension;
|
return fn + "." + Extension;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,8 +31,10 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.Base.Core.Enums;
|
using Greenshot.Base.Core.Enums;
|
||||||
|
using Greenshot.Base.Core.FileFormatHandlers;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Base.Interfaces;
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Base.Interfaces.Plugin;
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
using Greenshot.Base.UnmanagedHelpers;
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -63,7 +65,8 @@ namespace Greenshot.Base.Core
|
||||||
//private static readonly string FORMAT_HTML = "HTML Format";
|
//private static readonly string FORMAT_HTML = "HTML Format";
|
||||||
|
|
||||||
// Template for the HTML Text on the clipboard
|
// Template for the HTML Text on the clipboard
|
||||||
// see: https://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx
|
// see: https://msdn.microsoft.com/en-us/library/ms649015%28v=v
|
||||||
|
// s.85%29.aspx
|
||||||
// or: https://msdn.microsoft.com/en-us/library/Aa767917.aspx
|
// or: https://msdn.microsoft.com/en-us/library/Aa767917.aspx
|
||||||
private const string HtmlClipboardString = @"Version:0.9
|
private const string HtmlClipboardString = @"Version:0.9
|
||||||
StartHTML:<<<<<<<1
|
StartHTML:<<<<<<<1
|
||||||
|
@ -298,14 +301,15 @@ EndSelection:<<<<<<<4
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
foreach (var fileData in IterateClipboardContent(dataObject))
|
var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList();
|
||||||
|
foreach (var (stream, filename) in IterateClipboardContent(dataObject))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (ImageHelper.FromStream(fileData))
|
var extension = Path.GetExtension(filename)?.ToLowerInvariant();
|
||||||
|
if (supportedExtensions.Contains(extension))
|
||||||
{
|
{
|
||||||
// If we get here, there is an image
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +319,7 @@ EndSelection:<<<<<<<4
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
fileData?.Dispose();
|
stream?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +331,8 @@ EndSelection:<<<<<<<4
|
||||||
var imageStream = clipboardContent as MemoryStream;
|
var imageStream = clipboardContent as MemoryStream;
|
||||||
if (IsValidStream(imageStream))
|
if (IsValidStream(imageStream))
|
||||||
{
|
{
|
||||||
using (ImageHelper.FromStream(imageStream))
|
// TODO: How to check if we support "just a stream"?
|
||||||
|
using (ImageIO.FromStream(imageStream))
|
||||||
{
|
{
|
||||||
// If we get here, there is an image
|
// If we get here, there is an image
|
||||||
return true;
|
return true;
|
||||||
|
@ -373,8 +378,8 @@ EndSelection:<<<<<<<4
|
||||||
/// Iterate the clipboard content
|
/// Iterate the clipboard content
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataObject">IDataObject</param>
|
/// <param name="dataObject">IDataObject</param>
|
||||||
/// <returns>IEnumerable{MemoryStream}</returns>
|
/// <returns>IEnumerable{(MemoryStream,string)}</returns>
|
||||||
private static IEnumerable<MemoryStream> IterateClipboardContent(IDataObject dataObject)
|
private static IEnumerable<(MemoryStream stream,string filename)> IterateClipboardContent(IDataObject dataObject)
|
||||||
{
|
{
|
||||||
var fileDescriptors = AvailableFileDescriptors(dataObject);
|
var fileDescriptors = AvailableFileDescriptors(dataObject);
|
||||||
if (fileDescriptors == null) yield break;
|
if (fileDescriptors == null) yield break;
|
||||||
|
@ -413,8 +418,8 @@ EndSelection:<<<<<<<4
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileDescriptors">IEnumerable{FileDescriptor}</param>
|
/// <param name="fileDescriptors">IEnumerable{FileDescriptor}</param>
|
||||||
/// <param name="dataObject">IDataObject</param>
|
/// <param name="dataObject">IDataObject</param>
|
||||||
/// <returns>IEnumerable{MemoryStream}</returns>
|
/// <returns>IEnumerable{(MemoryStream stream, string filename)}</returns>
|
||||||
private static IEnumerable<MemoryStream> IterateFileDescriptors(IEnumerable<FileDescriptor> fileDescriptors, IDataObject dataObject)
|
private static IEnumerable<(MemoryStream stream, string filename)> IterateFileDescriptors(IEnumerable<FileDescriptor> fileDescriptors, IDataObject dataObject)
|
||||||
{
|
{
|
||||||
if (fileDescriptors == null)
|
if (fileDescriptors == null)
|
||||||
{
|
{
|
||||||
|
@ -445,7 +450,7 @@ EndSelection:<<<<<<<4
|
||||||
if (fileData?.Length > 0)
|
if (fileData?.Length > 0)
|
||||||
{
|
{
|
||||||
fileData.Position = 0;
|
fileData.Position = 0;
|
||||||
yield return fileData;
|
yield return (fileData, fileDescriptor.FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileIndex++;
|
fileIndex++;
|
||||||
|
@ -490,7 +495,7 @@ EndSelection:<<<<<<<4
|
||||||
{
|
{
|
||||||
IDataObject clipboardData = GetDataObject();
|
IDataObject clipboardData = GetDataObject();
|
||||||
// Return the first image
|
// Return the first image
|
||||||
foreach (Image clipboardImage in GetImages(clipboardData))
|
foreach (var clipboardImage in GetImages(clipboardData))
|
||||||
{
|
{
|
||||||
return clipboardImage;
|
return clipboardImage;
|
||||||
}
|
}
|
||||||
|
@ -503,57 +508,154 @@ EndSelection:<<<<<<<4
|
||||||
/// Returned images must be disposed by the calling code!
|
/// Returned images must be disposed by the calling code!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataObject"></param>
|
/// <param name="dataObject"></param>
|
||||||
/// <returns>IEnumerable of Image</returns>
|
/// <returns>IEnumerable of Bitmap</returns>
|
||||||
public static IEnumerable<Image> GetImages(IDataObject dataObject)
|
public static IEnumerable<Bitmap> GetImages(IDataObject dataObject)
|
||||||
{
|
{
|
||||||
// Get single image, this takes the "best" match
|
// Get single image, this takes the "best" match
|
||||||
Image singleImage = GetImage(dataObject);
|
Bitmap singleImage = GetImage(dataObject);
|
||||||
if (singleImage != null)
|
if (singleImage != null)
|
||||||
{
|
{
|
||||||
Log.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat);
|
Log.InfoFormat($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}");
|
||||||
yield return singleImage;
|
yield return singleImage;
|
||||||
|
yield break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList();
|
||||||
|
|
||||||
|
foreach (var (stream, filename) in IterateClipboardContent(dataObject))
|
||||||
{
|
{
|
||||||
foreach (var fileData in IterateClipboardContent(dataObject))
|
var extension = Path.GetExtension(filename)?.ToLowerInvariant();
|
||||||
|
if (!supportedExtensions.Contains(extension))
|
||||||
{
|
{
|
||||||
Image image;
|
continue;
|
||||||
try
|
|
||||||
{
|
|
||||||
image = ImageHelper.FromStream(fileData);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error("Couldn't read file contents", ex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
fileData?.Dispose();
|
|
||||||
}
|
|
||||||
// If we get here, there is an image
|
|
||||||
yield return image;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if files are supplied
|
Bitmap bitmap = null;
|
||||||
foreach (string imageFile in GetImageFilenames(dataObject))
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Image returnImage = null;
|
if (!fileFormatHandlers.TryLoadFromStream(stream, extension, out bitmap))
|
||||||
try
|
|
||||||
{
|
{
|
||||||
returnImage = ImageHelper.LoadImage(imageFile);
|
continue;
|
||||||
}
|
|
||||||
catch (Exception streamImageEx)
|
|
||||||
{
|
|
||||||
Log.Error("Problem retrieving Image from clipboard.", streamImageEx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnImage != null)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't read file contents", ex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stream?.Dispose();
|
||||||
|
}
|
||||||
|
// If we get here, there is an image
|
||||||
|
yield return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if files are supplied
|
||||||
|
foreach (string imageFile in GetImageFilenames(dataObject))
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(imageFile)?.ToLowerInvariant();
|
||||||
|
if (!supportedExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
using FileStream fileStream = new FileStream(imageFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!fileFormatHandlers.TryLoadFromStream(fileStream, extension, out bitmap))
|
||||||
{
|
{
|
||||||
Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat);
|
continue;
|
||||||
yield return returnImage;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't read file contents", ex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If we get here, there is an image
|
||||||
|
yield return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all images (multiple if file names are available) from the dataObject
|
||||||
|
/// Returned images must be disposed by the calling code!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns>IEnumerable of IDrawableContainer</returns>
|
||||||
|
public static IEnumerable<IDrawableContainer> GetDrawables(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
// Get single image, this takes the "best" match
|
||||||
|
IDrawableContainer singleImage = GetDrawable(dataObject);
|
||||||
|
if (singleImage != null)
|
||||||
|
{
|
||||||
|
Log.InfoFormat($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}");
|
||||||
|
yield return singleImage;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadDrawableFromStream).ToList();
|
||||||
|
|
||||||
|
foreach (var (stream, filename) in IterateClipboardContent(dataObject))
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(filename)?.ToLowerInvariant();
|
||||||
|
if (!supportedExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IDrawableContainer> drawableContainers;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
drawableContainers = fileFormatHandlers.LoadDrawablesFromStream(stream, extension);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't read file contents", ex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stream?.Dispose();
|
||||||
|
}
|
||||||
|
// If we get here, there is an image
|
||||||
|
foreach (var container in drawableContainers)
|
||||||
|
{
|
||||||
|
yield return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if files are supplied
|
||||||
|
foreach (string imageFile in GetImageFilenames(dataObject))
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(imageFile)?.ToLowerInvariant();
|
||||||
|
if (!supportedExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDrawableContainer drawableContainer = null;
|
||||||
|
using FileStream fileStream = new FileStream(imageFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
IEnumerable<IDrawableContainer> drawableContainers;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
drawableContainers = fileFormatHandlers.LoadDrawablesFromStream(fileStream, extension);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't read file contents", ex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If we get here, there is an image
|
||||||
|
foreach (var container in drawableContainers)
|
||||||
|
{
|
||||||
|
yield return container;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,51 +664,50 @@ EndSelection:<<<<<<<4
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataObject"></param>
|
/// <param name="dataObject"></param>
|
||||||
/// <returns>Image or null</returns>
|
/// <returns>Image or null</returns>
|
||||||
private static Image GetImage(IDataObject dataObject)
|
private static Bitmap GetImage(IDataObject dataObject)
|
||||||
{
|
{
|
||||||
Image returnImage = null;
|
if (dataObject == null) return null;
|
||||||
if (dataObject != null)
|
|
||||||
{
|
|
||||||
IList<string> formats = GetFormats(dataObject);
|
|
||||||
string[] retrieveFormats;
|
|
||||||
|
|
||||||
// Found a weird bug, where PNG's from Outlook 2010 are clipped
|
Bitmap returnImage = null;
|
||||||
// So I build some special logic to get the best format:
|
IList<string> formats = GetFormats(dataObject);
|
||||||
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
|
string[] retrieveFormats;
|
||||||
|
|
||||||
|
// Found a weird bug, where PNG's from Outlook 2010 are clipped
|
||||||
|
// So I build some special logic to get the best format:
|
||||||
|
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
|
||||||
|
{
|
||||||
|
// Outlook ??
|
||||||
|
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
|
||||||
|
retrieveFormats = new[]
|
||||||
{
|
{
|
||||||
// Outlook ??
|
DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF,
|
||||||
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
|
DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML
|
||||||
retrieveFormats = new[]
|
};
|
||||||
{
|
}
|
||||||
DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF,
|
else
|
||||||
DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML
|
{
|
||||||
};
|
retrieveFormats = new[]
|
||||||
|
{
|
||||||
|
FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP,
|
||||||
|
FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string currentFormat in retrieveFormats)
|
||||||
|
{
|
||||||
|
if (formats != null && formats.Contains(currentFormat))
|
||||||
|
{
|
||||||
|
Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
|
||||||
|
returnImage = GetImageForFormat(currentFormat, dataObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retrieveFormats = new[]
|
Log.DebugFormat("Couldn't find format {0}.", currentFormat);
|
||||||
{
|
|
||||||
FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP,
|
|
||||||
FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string currentFormat in retrieveFormats)
|
if (returnImage != null)
|
||||||
{
|
{
|
||||||
if (formats != null && formats.Contains(currentFormat))
|
return returnImage;
|
||||||
{
|
|
||||||
Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
|
|
||||||
returnImage = GetImageForFormat(currentFormat, dataObject);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.DebugFormat("Couldn't find format {0}.", currentFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (returnImage != null)
|
|
||||||
{
|
|
||||||
return returnImage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,15 +715,72 @@ EndSelection:<<<<<<<4
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to try to get an image in the specified format from the dataObject
|
/// Get an IDrawableContainer from the IDataObject, don't check for FileDrop
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns>Image or null</returns>
|
||||||
|
private static IDrawableContainer GetDrawable(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
if (dataObject == null) return null;
|
||||||
|
|
||||||
|
IDrawableContainer returnImage = null;
|
||||||
|
IList<string> formats = GetFormats(dataObject);
|
||||||
|
string[] retrieveFormats;
|
||||||
|
|
||||||
|
// Found a weird bug, where PNG's from Outlook 2010 are clipped
|
||||||
|
// So I build some special logic to get the best format:
|
||||||
|
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
|
||||||
|
{
|
||||||
|
// Outlook ??
|
||||||
|
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
|
||||||
|
retrieveFormats = new[]
|
||||||
|
{
|
||||||
|
DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF,
|
||||||
|
DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retrieveFormats = new[]
|
||||||
|
{
|
||||||
|
FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP,
|
||||||
|
FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string currentFormat in retrieveFormats)
|
||||||
|
{
|
||||||
|
if (formats != null && formats.Contains(currentFormat))
|
||||||
|
{
|
||||||
|
Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
|
||||||
|
returnImage = GetDrawableForFormat(currentFormat, dataObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.DebugFormat("Couldn't find format {0}.", currentFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnImage != null)
|
||||||
|
{
|
||||||
|
return returnImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to try to get an Bitmap in the specified format from the dataObject
|
||||||
/// the DIB reader should solve some issues
|
/// the DIB reader should solve some issues
|
||||||
/// It also supports Format17/DibV5, by using the following information: https://stackoverflow.com/a/14335591
|
/// It also supports Format17/DibV5, by using the following information: https://stackoverflow.com/a/14335591
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="format">string with the format</param>
|
/// <param name="format">string with the format</param>
|
||||||
/// <param name="dataObject">IDataObject</param>
|
/// <param name="dataObject">IDataObject</param>
|
||||||
/// <returns>Image or null</returns>
|
/// <returns>Bitmap or null</returns>
|
||||||
private static Image GetImageForFormat(string format, IDataObject dataObject)
|
private static Bitmap GetImageForFormat(string format, IDataObject dataObject)
|
||||||
{
|
{
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
|
||||||
if (format == FORMAT_HTML)
|
if (format == FORMAT_HTML)
|
||||||
{
|
{
|
||||||
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
|
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
|
||||||
|
@ -638,10 +796,10 @@ EndSelection:<<<<<<<4
|
||||||
var srcAttribute = imgNode.Attributes["src"];
|
var srcAttribute = imgNode.Attributes["src"];
|
||||||
var imageUrl = srcAttribute.Value;
|
var imageUrl = srcAttribute.Value;
|
||||||
Log.Debug(imageUrl);
|
Log.Debug(imageUrl);
|
||||||
var image = NetworkHelper.DownloadImage(imageUrl);
|
bitmap = NetworkHelper.DownloadImage(imageUrl);
|
||||||
if (image != null)
|
if (bitmap != null)
|
||||||
{
|
{
|
||||||
return image;
|
return bitmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -652,111 +810,80 @@ EndSelection:<<<<<<<4
|
||||||
var imageStream = clipboardObject as MemoryStream;
|
var imageStream = clipboardObject as MemoryStream;
|
||||||
if (!IsValidStream(imageStream))
|
if (!IsValidStream(imageStream))
|
||||||
{
|
{
|
||||||
// TODO: add "HTML Format" support here...
|
return clipboardObject as Bitmap;
|
||||||
return clipboardObject as Image;
|
|
||||||
}
|
}
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
|
||||||
if (CoreConfig.EnableSpecialDIBClipboardReader)
|
// From here, imageStream is a valid stream
|
||||||
|
if (!fileFormatHandlers.TryLoadFromStream(imageStream, format, out bitmap))
|
||||||
{
|
{
|
||||||
if (format == FORMAT_17 || format == DataFormats.Dib)
|
return bitmap;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to try to get an IDrawableContainer in the specified format from the dataObject
|
||||||
|
/// the DIB reader should solve some issues
|
||||||
|
/// It also supports Format17/DibV5, by using the following information: https://stackoverflow.com/a/14335591
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">string with the format</param>
|
||||||
|
/// <param name="dataObject">IDataObject</param>
|
||||||
|
/// <returns>IDrawableContainer or null</returns>
|
||||||
|
private static IDrawableContainer GetDrawableForFormat(string format, IDataObject dataObject)
|
||||||
|
{
|
||||||
|
IDrawableContainer drawableContainer = null;
|
||||||
|
|
||||||
|
if (format == FORMAT_HTML)
|
||||||
|
{
|
||||||
|
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
|
||||||
|
if (textObject != null)
|
||||||
{
|
{
|
||||||
Log.Info("Found DIB stream, trying to process it.");
|
var doc = new HtmlDocument();
|
||||||
try
|
doc.LoadHtml(textObject);
|
||||||
|
var imgNodes = doc.DocumentNode.SelectNodes("//img");
|
||||||
|
if (imgNodes != null)
|
||||||
{
|
{
|
||||||
if (imageStream != null)
|
foreach (var imgNode in imgNodes)
|
||||||
{
|
{
|
||||||
byte[] dibBuffer = new byte[imageStream.Length];
|
var srcAttribute = imgNode.Attributes["src"];
|
||||||
_ = imageStream.Read(dibBuffer, 0, dibBuffer.Length);
|
var imageUrl = srcAttribute.Value;
|
||||||
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADERV5>(dibBuffer);
|
Log.Debug(imageUrl);
|
||||||
if (!infoHeader.IsDibV5)
|
drawableContainer = NetworkHelper.DownloadImageAsDrawableContainer(imageUrl);
|
||||||
|
if (drawableContainer != null)
|
||||||
{
|
{
|
||||||
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
|
return drawableContainer;
|
||||||
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
|
|
||||||
uint infoHeaderSize = infoHeader.biSize;
|
|
||||||
int fileSize = (int) (fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
|
|
||||||
|
|
||||||
var fileHeader = new BITMAPFILEHEADER
|
|
||||||
{
|
|
||||||
bfType = BITMAPFILEHEADER.BM,
|
|
||||||
bfSize = fileSize,
|
|
||||||
bfReserved1 = 0,
|
|
||||||
bfReserved2 = 0,
|
|
||||||
bfOffBits = (int) (fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4)
|
|
||||||
};
|
|
||||||
|
|
||||||
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
|
|
||||||
|
|
||||||
using var bitmapStream = new MemoryStream();
|
|
||||||
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
|
||||||
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
|
||||||
bitmapStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
var image = ImageHelper.FromStream(bitmapStream);
|
|
||||||
if (image != null)
|
|
||||||
{
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Info("Using special DIBV5 / Format17 format reader");
|
|
||||||
// CF_DIBV5
|
|
||||||
IntPtr gcHandle = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
|
|
||||||
gcHandle = GCHandle.ToIntPtr(handle);
|
|
||||||
return
|
|
||||||
new Bitmap(infoHeader.biWidth, infoHeader.biHeight,
|
|
||||||
-(int) (infoHeader.biSizeImage / infoHeader.biHeight),
|
|
||||||
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
|
|
||||||
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels +
|
|
||||||
(infoHeader.biHeight - 1) * (int) (infoHeader.biSizeImage / infoHeader.biHeight))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error("Problem retrieving Format17 from clipboard.", ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (gcHandle == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
GCHandle.FromIntPtr(gcHandle).Free();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception dibEx)
|
|
||||||
{
|
|
||||||
Log.Error("Problem retrieving DIB from clipboard.", dibEx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Info("Skipping special DIB format reader as it's disabled in the configuration.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
object clipboardObject = GetFromDataObject(dataObject, format);
|
||||||
|
var imageStream = clipboardObject as MemoryStream;
|
||||||
|
if (!IsValidStream(imageStream))
|
||||||
{
|
{
|
||||||
if (imageStream != null)
|
// TODO: add text based, like "HTML Format" support here...
|
||||||
|
// TODO: solve the issue that we do not have a factory for the ImageContainer
|
||||||
|
/*var image = clipboardObject as Image;
|
||||||
|
if (image != null)
|
||||||
{
|
{
|
||||||
imageStream.Seek(0, SeekOrigin.Begin);
|
return new ImageContainer(this)
|
||||||
var tmpImage = ImageHelper.FromStream(imageStream);
|
|
||||||
if (tmpImage != null)
|
|
||||||
{
|
{
|
||||||
Log.InfoFormat("Got image with clipboard format {0} from the clipboard.", format);
|
Image = image,
|
||||||
return tmpImage;
|
Left = x,
|
||||||
}
|
Top = y
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
return clipboardObject as Image;
|
||||||
catch (Exception streamImageEx)
|
*/
|
||||||
{
|
return null;
|
||||||
Log.Error($"Problem retrieving {format} from clipboard.", streamImageEx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
// From here, imageStream is a valid stream
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
|
||||||
|
return fileFormatHandlers.LoadDrawablesFromStream(imageStream, format).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -840,7 +967,7 @@ EndSelection:<<<<<<<4
|
||||||
{
|
{
|
||||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
||||||
// Create the image which is going to be saved so we don't create it multiple times
|
// Create the image which is going to be saved so we don't create it multiple times
|
||||||
disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave);
|
disposeImage = ImageIO.CreateImageFromSurface(surface, outputSettings, out imageToSave);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Create PNG stream
|
// Create PNG stream
|
||||||
|
@ -849,7 +976,7 @@ EndSelection:<<<<<<<4
|
||||||
pngStream = new MemoryStream();
|
pngStream = new MemoryStream();
|
||||||
// PNG works for e.g. Powerpoint
|
// PNG works for e.g. Powerpoint
|
||||||
SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
||||||
ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings);
|
ImageIO.SaveToStream(imageToSave, null, pngStream, pngOutputSettings);
|
||||||
pngStream.Seek(0, SeekOrigin.Begin);
|
pngStream.Seek(0, SeekOrigin.Begin);
|
||||||
// Set the PNG stream
|
// Set the PNG stream
|
||||||
dataObject.SetData(FORMAT_PNG, false, pngStream);
|
dataObject.SetData(FORMAT_PNG, false, pngStream);
|
||||||
|
@ -866,11 +993,18 @@ EndSelection:<<<<<<<4
|
||||||
{
|
{
|
||||||
// Create the stream for the clipboard
|
// Create the stream for the clipboard
|
||||||
dibStream = new MemoryStream();
|
dibStream = new MemoryStream();
|
||||||
var dibBytes = ((Bitmap)imageToSave).ConvertToDib();
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
dibStream.Write(dibBytes,0, dibBytes.Length);
|
|
||||||
|
|
||||||
// Set the DIB to the clipboard DataObject
|
if (!fileFormatHandlers.TrySaveToStream((Bitmap)imageToSave, dibStream, DataFormats.Dib))
|
||||||
dataObject.SetData(DataFormats.Dib, false, dibStream);
|
{
|
||||||
|
dibStream.Dispose();
|
||||||
|
dibStream = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set the DIB to the clipboard DataObject
|
||||||
|
dataObject.SetData(DataFormats.Dib, false, dibStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception dibEx)
|
catch (Exception dibEx)
|
||||||
|
@ -924,7 +1058,7 @@ EndSelection:<<<<<<<4
|
||||||
// Set the HTML
|
// Set the HTML
|
||||||
if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTML))
|
if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTML))
|
||||||
{
|
{
|
||||||
string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null);
|
string tmpFile = ImageIO.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null);
|
||||||
string html = GetHtmlString(surface, tmpFile);
|
string html = GetHtmlString(surface, tmpFile);
|
||||||
dataObject.SetText(html, TextDataFormat.Html);
|
dataObject.SetText(html, TextDataFormat.Html);
|
||||||
}
|
}
|
||||||
|
@ -942,11 +1076,11 @@ EndSelection:<<<<<<<4
|
||||||
// Check if we can use the previously used image
|
// Check if we can use the previously used image
|
||||||
if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed)
|
if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed)
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(imageToSave, surface, tmpPngStream, pngOutputSettings);
|
ImageIO.SaveToStream(imageToSave, surface, tmpPngStream, pngOutputSettings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(surface, tmpPngStream, pngOutputSettings);
|
ImageIO.SaveToStream(surface, tmpPngStream, pngOutputSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
html = GetHtmlDataUrlString(surface, tmpPngStream);
|
html = GetHtmlDataUrlString(surface, tmpPngStream);
|
||||||
|
@ -1125,15 +1259,15 @@ EndSelection:<<<<<<<4
|
||||||
public static IEnumerable<string> GetImageFilenames(IDataObject dataObject)
|
public static IEnumerable<string> GetImageFilenames(IDataObject dataObject)
|
||||||
{
|
{
|
||||||
string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop);
|
string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop);
|
||||||
if (dropFileNames != null && dropFileNames.Length > 0)
|
if (dropFileNames is not { Length: > 0 }) return Enumerable.Empty<string>();
|
||||||
{
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
return dropFileNames
|
|
||||||
.Where(filename => !string.IsNullOrEmpty(filename))
|
var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
|
||||||
.Where(Path.HasExtension)
|
return dropFileNames
|
||||||
.Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1)));
|
.Where(filename => !string.IsNullOrEmpty(filename))
|
||||||
}
|
.Where(Path.HasExtension)
|
||||||
|
.Where(filename => supportedExtensions.Contains(Path.GetExtension(filename)));
|
||||||
|
|
||||||
return Enumerable.Empty<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
36
src/Greenshot.Base/Core/Enums/ExifOrientations.cs
Normal file
36
src/Greenshot.Base/Core/Enums/ExifOrientations.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Base.Core.Enums
|
||||||
|
{
|
||||||
|
internal enum ExifOrientations : byte
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
TopLeft = 1,
|
||||||
|
TopRight = 2,
|
||||||
|
BottomRight = 3,
|
||||||
|
BottomLeft = 4,
|
||||||
|
LeftTop = 5,
|
||||||
|
RightTop = 6,
|
||||||
|
RightBottom = 7,
|
||||||
|
LeftBottom = 8,
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ namespace Greenshot.Base.Core.Enums
|
||||||
jpg,
|
jpg,
|
||||||
png,
|
png,
|
||||||
tiff,
|
tiff,
|
||||||
|
jxr,
|
||||||
greenshot,
|
greenshot,
|
||||||
ico
|
ico
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
|
||||||
|
namespace Greenshot.Base.Core.FileFormatHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the registry where all IFileFormatHandler are registered and can be used
|
||||||
|
/// </summary>
|
||||||
|
public static class FileFormatHandlerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Make sure we handle the input extension always the same, by "normalizing" it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <returns>string</returns>
|
||||||
|
public static string NormalizeExtension(string extension)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(extension))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension = extension.ToLowerInvariant();
|
||||||
|
return !extension.StartsWith(".") ? $".{extension}" : extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the extensions that the provided IFileFormatHandlers can accept for the specified action
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandlers">IEnumerable{IFileFormatHandler}</param>
|
||||||
|
/// <param name="fileFormatHandlerAction"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<string> ExtensionsFor(this IEnumerable<IFileFormatHandler> fileFormatHandlers, FileFormatHandlerActions fileFormatHandlerAction)
|
||||||
|
{
|
||||||
|
return fileFormatHandlers.Where(ffh => ffh.SupportedExtensions.ContainsKey(fileFormatHandlerAction)).SelectMany(ffh => ffh.SupportedExtensions[fileFormatHandlerAction]).Distinct().OrderBy(e => e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension method to check if a certain IFileFormatHandler supports a certain action with a specific extension
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandler">IFileFormatHandler</param>
|
||||||
|
/// <param name="fileFormatHandlerAction">FileFormatHandlerActions</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <returns>bool</returns>
|
||||||
|
public static bool Supports(this IFileFormatHandler fileFormatHandler, FileFormatHandlerActions fileFormatHandlerAction, string extension)
|
||||||
|
{
|
||||||
|
extension = NormalizeExtension(extension);
|
||||||
|
return fileFormatHandler.SupportedExtensions.ContainsKey(fileFormatHandlerAction) && fileFormatHandler.SupportedExtensions[fileFormatHandlerAction].Contains(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This wrapper method for TrySaveToStream will do:
|
||||||
|
/// Find all the IFileFormatHandler which support the action for the supplied extension.
|
||||||
|
/// Take the first, to call the TrySaveToStream on.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandlers">IEnumerable{IFileFormatHandler}</param>
|
||||||
|
/// <param name="bitmap">Bitmap</param>
|
||||||
|
/// <param name="destination">Stream</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <param name="surface">ISurface</param>
|
||||||
|
/// <returns>bool</returns>
|
||||||
|
public static bool TrySaveToStream(this IEnumerable<IFileFormatHandler> fileFormatHandlers, Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
extension = NormalizeExtension(extension);
|
||||||
|
|
||||||
|
var saveFileFormatHandlers = fileFormatHandlers
|
||||||
|
.Where(ffh => ffh.Supports(FileFormatHandlerActions.LoadFromStream, extension))
|
||||||
|
.OrderBy(ffh => ffh.PriorityFor(FileFormatHandlerActions.LoadFromStream, extension)).ToList();
|
||||||
|
|
||||||
|
if (!saveFileFormatHandlers.Any())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var fileFormatHandler in saveFileFormatHandlers)
|
||||||
|
{
|
||||||
|
if (fileFormatHandler.TrySaveToStream(bitmap, destination, extension, surface))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to load a drawable container from the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandlers">IEnumerable{IFileFormatHandler}</param>
|
||||||
|
/// <param name="stream">Stream</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <param name="parentSurface">ISurface</param>
|
||||||
|
/// <returns>IEnumerable{IDrawableContainer}</returns>
|
||||||
|
public static IEnumerable<IDrawableContainer> LoadDrawablesFromStream(this IEnumerable<IFileFormatHandler> fileFormatHandlers, Stream stream, string extension, ISurface parentSurface = null)
|
||||||
|
{
|
||||||
|
extension = NormalizeExtension(extension);
|
||||||
|
|
||||||
|
var loadfileFormatHandler = fileFormatHandlers
|
||||||
|
.Where(ffh => ffh.Supports(FileFormatHandlerActions.LoadDrawableFromStream, extension))
|
||||||
|
.OrderBy(ffh => ffh.PriorityFor(FileFormatHandlerActions.LoadDrawableFromStream, extension))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (loadfileFormatHandler != null)
|
||||||
|
{
|
||||||
|
return loadfileFormatHandler.LoadDrawablesFromStream(stream, extension, parentSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enumerable.Empty<IDrawableContainer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to load a Bitmap from the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandlers">IEnumerable{IFileFormatHandler}</param>
|
||||||
|
/// <param name="stream">Stream</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <param name="bitmap">Bitmap out</param>
|
||||||
|
/// <returns>bool true if it was successful</returns>
|
||||||
|
public static bool TryLoadFromStream(this IEnumerable<IFileFormatHandler> fileFormatHandlers, Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
extension = NormalizeExtension(extension);
|
||||||
|
|
||||||
|
var loadFileFormatHandler = fileFormatHandlers
|
||||||
|
.Where(ffh => ffh.Supports(FileFormatHandlerActions.LoadFromStream, extension))
|
||||||
|
.OrderBy(ffh => ffh.PriorityFor(FileFormatHandlerActions.LoadFromStream, extension))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (loadFileFormatHandler == null)
|
||||||
|
{
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadFileFormatHandler.TryLoadFromStream(stream, extension, out bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ namespace Greenshot.Base.Core
|
||||||
float HorizontalResolution { get; }
|
float HorizontalResolution { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unterlying image, or an on demand rendered version with different attributes as the original
|
/// Underlying image, or an on demand rendered version with different attributes as the original
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Image Image { get; }
|
Image Image { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,28 +24,24 @@ using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using Greenshot.Base.Core.Enums;
|
||||||
using Greenshot.Base.Effects;
|
using Greenshot.Base.Effects;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Base.Interfaces;
|
|
||||||
using Greenshot.Base.UnmanagedHelpers;
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
using Brush = System.Drawing.Brush;
|
||||||
|
using Color = System.Drawing.Color;
|
||||||
|
using Matrix = System.Drawing.Drawing2D.Matrix;
|
||||||
|
using Pen = System.Drawing.Pen;
|
||||||
|
using PixelFormat = System.Drawing.Imaging.PixelFormat;
|
||||||
|
using Point = System.Drawing.Point;
|
||||||
|
using Size = System.Drawing.Size;
|
||||||
|
|
||||||
namespace Greenshot.Base.Core
|
namespace Greenshot.Base.Core
|
||||||
{
|
{
|
||||||
internal enum ExifOrientations : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
TopLeft = 1,
|
|
||||||
TopRight = 2,
|
|
||||||
BottomRight = 3,
|
|
||||||
BottomLeft = 4,
|
|
||||||
LeftTop = 5,
|
|
||||||
RightTop = 6,
|
|
||||||
RightBottom = 7,
|
|
||||||
LeftBottom = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of ImageHelper.
|
/// Description of ImageHelper.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -55,83 +51,6 @@ namespace Greenshot.Base.Core
|
||||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
private const int ExifOrientationId = 0x0112;
|
private const int ExifOrientationId = 0x0112;
|
||||||
|
|
||||||
static ImageHelper()
|
|
||||||
{
|
|
||||||
StreamConverters["greenshot"] = (stream, s) =>
|
|
||||||
{
|
|
||||||
var surface = SimpleServiceProvider.Current.GetInstance<Func<ISurface>>().Invoke();
|
|
||||||
return surface.GetImageForExport();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add a SVG converter
|
|
||||||
StreamConverters["svg"] = (stream, s) =>
|
|
||||||
{
|
|
||||||
stream.Position = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SvgImage.FromStream(stream).Image;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error("Can't load SVG", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Image DefaultConverter(Stream stream, string s)
|
|
||||||
{
|
|
||||||
stream.Position = 0;
|
|
||||||
using var tmpImage = Image.FromStream(stream, true, true);
|
|
||||||
Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
|
||||||
return Clone(tmpImage, PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback
|
|
||||||
StreamConverters[string.Empty] = DefaultConverter;
|
|
||||||
StreamConverters["gif"] = DefaultConverter;
|
|
||||||
StreamConverters["bmp"] = DefaultConverter;
|
|
||||||
StreamConverters["jpg"] = DefaultConverter;
|
|
||||||
StreamConverters["jpeg"] = DefaultConverter;
|
|
||||||
StreamConverters["png"] = DefaultConverter;
|
|
||||||
StreamConverters["wmf"] = DefaultConverter;
|
|
||||||
|
|
||||||
StreamConverters["ico"] = (stream, extension) =>
|
|
||||||
{
|
|
||||||
// Icon logic, try to get the Vista icon, else the biggest possible
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using Image tmpImage = ExtractVistaIcon(stream);
|
|
||||||
if (tmpImage != null)
|
|
||||||
{
|
|
||||||
return Clone(tmpImage, PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception vistaIconException)
|
|
||||||
{
|
|
||||||
Log.Warn("Can't read icon", vistaIconException);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// No vista icon, try normal icon
|
|
||||||
stream.Position = 0;
|
|
||||||
// We create a copy of the bitmap, so everything else can be disposed
|
|
||||||
using Icon tmpIcon = new Icon(stream, new Size(1024, 1024));
|
|
||||||
using Image tmpImage = tmpIcon.ToBitmap();
|
|
||||||
return Clone(tmpImage, PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
catch (Exception iconException)
|
|
||||||
{
|
|
||||||
Log.Warn("Can't read icon", iconException);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Position = 0;
|
|
||||||
return DefaultConverter(stream, extension);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDictionary<string, Func<Stream, string, Image>> StreamConverters { get; } = new Dictionary<string, Func<Stream, string, Image>>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make sure the image is orientated correctly
|
/// Make sure the image is orientated correctly
|
||||||
|
@ -371,127 +290,6 @@ namespace Greenshot.Base.Core
|
||||||
return cropRectangle;
|
return cropRectangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load an image from file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="filename"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Image LoadImage(string filename)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(filename))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(filename))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Image fileImage;
|
|
||||||
Log.InfoFormat("Loading image from file {0}", filename);
|
|
||||||
// Fixed lock problem Bug #3431881
|
|
||||||
using (Stream imageFileStream = File.OpenRead(filename))
|
|
||||||
{
|
|
||||||
fileImage = FromStream(imageFileStream, Path.GetExtension(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileImage != null)
|
|
||||||
{
|
|
||||||
Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat,
|
|
||||||
fileImage.HorizontalResolution, fileImage.VerticalResolution);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Based on: https://www.codeproject.com/KB/cs/IconExtractor.aspx
|
|
||||||
/// And a hint from: https://www.codeproject.com/KB/cs/IconLib.aspx
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="iconStream">Stream with the icon information</param>
|
|
||||||
/// <returns>Bitmap with the Vista Icon (256x256)</returns>
|
|
||||||
private static Bitmap ExtractVistaIcon(Stream iconStream)
|
|
||||||
{
|
|
||||||
const int sizeIconDir = 6;
|
|
||||||
const int sizeIconDirEntry = 16;
|
|
||||||
Bitmap bmpPngExtracted = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] srcBuf = new byte[iconStream.Length];
|
|
||||||
iconStream.Read(srcBuf, 0, (int) iconStream.Length);
|
|
||||||
int iCount = BitConverter.ToInt16(srcBuf, 4);
|
|
||||||
for (int iIndex = 0; iIndex < iCount; iIndex++)
|
|
||||||
{
|
|
||||||
int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex];
|
|
||||||
int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1];
|
|
||||||
if (iWidth == 0 && iHeight == 0)
|
|
||||||
{
|
|
||||||
int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
|
|
||||||
int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
|
|
||||||
using MemoryStream destStream = new MemoryStream();
|
|
||||||
destStream.Write(srcBuf, iImageOffset, iImageSize);
|
|
||||||
destStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bmpPngExtracted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="location">The file (EXE or DLL) to get the icon from</param>
|
|
||||||
/// <param name="index">Index of the icon</param>
|
|
||||||
/// <param name="takeLarge">true if the large icon is wanted</param>
|
|
||||||
/// <returns>Icon</returns>
|
|
||||||
public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge)
|
|
||||||
{
|
|
||||||
Shell32.ExtractIconEx(location, index, out var large, out var small, 1);
|
|
||||||
Icon returnIcon = null;
|
|
||||||
bool isLarge = false;
|
|
||||||
bool isSmall = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (takeLarge && !IntPtr.Zero.Equals(large))
|
|
||||||
{
|
|
||||||
returnIcon = Icon.FromHandle(large);
|
|
||||||
isLarge = true;
|
|
||||||
}
|
|
||||||
else if (!IntPtr.Zero.Equals(small))
|
|
||||||
{
|
|
||||||
returnIcon = Icon.FromHandle(small);
|
|
||||||
isSmall = true;
|
|
||||||
}
|
|
||||||
else if (!IntPtr.Zero.Equals(large))
|
|
||||||
{
|
|
||||||
returnIcon = Icon.FromHandle(large);
|
|
||||||
isLarge = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (isLarge && !IntPtr.Zero.Equals(small))
|
|
||||||
{
|
|
||||||
User32.DestroyIcon(small);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSmall && !IntPtr.Zero.Equals(large))
|
|
||||||
{
|
|
||||||
User32.DestroyIcon(large);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply the effect to the bitmap
|
/// Apply the effect to the bitmap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -563,8 +361,7 @@ namespace Greenshot.Base.Core
|
||||||
/// <returns>Changed bitmap</returns>
|
/// <returns>Changed bitmap</returns>
|
||||||
public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges)
|
public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges)
|
||||||
{
|
{
|
||||||
Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution,
|
Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
|
||||||
sourceImage.VerticalResolution);
|
|
||||||
using (var path = new GraphicsPath())
|
using (var path = new GraphicsPath())
|
||||||
{
|
{
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
@ -1396,7 +1193,7 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no pixelformat is supplied
|
// If no pixelformat is supplied
|
||||||
if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat)
|
if (targetFormat is PixelFormat.DontCare or PixelFormat.Undefined)
|
||||||
{
|
{
|
||||||
if (SupportsPixelFormat(sourceImage.PixelFormat))
|
if (SupportsPixelFormat(sourceImage.PixelFormat))
|
||||||
{
|
{
|
||||||
|
@ -1517,10 +1314,10 @@ namespace Greenshot.Base.Core
|
||||||
/// <param name="height"></param>
|
/// <param name="height"></param>
|
||||||
/// <param name="format"></param>
|
/// <param name="format"></param>
|
||||||
/// <param name="backgroundColor">The color to fill with, or Color.Empty to take the default depending on the pixel format</param>
|
/// <param name="backgroundColor">The color to fill with, or Color.Empty to take the default depending on the pixel format</param>
|
||||||
/// <param name="horizontalResolution"></param>
|
/// <param name="horizontalResolution">float</param>
|
||||||
/// <param name="verticalResolution"></param>
|
/// <param name="verticalResolution">float</param>
|
||||||
/// <returns>Bitmap</returns>
|
/// <returns>Bitmap</returns>
|
||||||
public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution, float verticalResolution)
|
public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution = 96f, float verticalResolution = 96f)
|
||||||
{
|
{
|
||||||
// Create a new "clean" image
|
// Create a new "clean" image
|
||||||
Bitmap newImage = new Bitmap(width, height, format);
|
Bitmap newImage = new Bitmap(width, height, format);
|
||||||
|
@ -1711,98 +1508,106 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load a Greenshot surface from a stream
|
/// Rotate the image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="surfaceFileStream">Stream</param>
|
/// <param name="image">Input image</param>
|
||||||
/// <param name="returnSurface"></param>
|
/// <param name="rotationAngle">Angle in degrees</param>
|
||||||
/// <returns>ISurface</returns>
|
/// <returns>Rotated image</returns>
|
||||||
public static ISurface LoadGreenshotSurface(Stream surfaceFileStream, ISurface returnSurface)
|
public static Image Rotate(this Image image, float rotationAngle)
|
||||||
{
|
{
|
||||||
Image fileImage;
|
var bitmap = CreateEmptyLike(image, Color.Transparent);
|
||||||
// Fixed problem that the bitmap stream is disposed... by Cloning the image
|
|
||||||
// This also ensures the bitmap is correctly created
|
|
||||||
|
|
||||||
// We create a copy of the bitmap, so everything else can be disposed
|
using var graphics = Graphics.FromImage(bitmap);
|
||||||
surfaceFileStream.Position = 0;
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true))
|
|
||||||
{
|
|
||||||
Log.DebugFormat("Loaded .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
|
||||||
fileImage = Clone(tmpImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
|
graphics.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2);
|
||||||
const int markerSize = 14;
|
graphics.RotateTransform(rotationAngle);
|
||||||
surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
|
graphics.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2);
|
||||||
using (StreamReader streamReader = new StreamReader(surfaceFileStream))
|
|
||||||
{
|
|
||||||
var greenshotMarker = streamReader.ReadToEnd();
|
|
||||||
if (!greenshotMarker.StartsWith("Greenshot"))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Stream is not a Greenshot file!");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.InfoFormat("Greenshot file format: {0}", greenshotMarker);
|
graphics.DrawImage(image, new Point(0, 0));
|
||||||
const int filesizeLocation = 8 + markerSize;
|
|
||||||
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
|
|
||||||
using BinaryReader reader = new BinaryReader(surfaceFileStream);
|
|
||||||
long bytesWritten = reader.ReadInt64();
|
|
||||||
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
|
|
||||||
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileImage != null)
|
return bitmap;
|
||||||
{
|
|
||||||
returnSurface.Image = fileImage;
|
|
||||||
Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", fileImage.Width, fileImage.Height, fileImage.PixelFormat,
|
|
||||||
fileImage.HorizontalResolution, fileImage.VerticalResolution);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnSurface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an image from a stream, if an extension is supplied more formats are supported.
|
/// Map a System.Drawing.Imaging.PixelFormat to a System.Windows.Media.PixelFormat
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">Stream</param>
|
/// <param name="pixelFormat">System.Drawing.Imaging.PixelFormat</param>
|
||||||
/// <param name="extension"></param>
|
/// <returns>System.Windows.Media.PixelFormat</returns>
|
||||||
/// <returns>Image</returns>
|
/// <exception cref="NotSupportedException"></exception>
|
||||||
public static Image FromStream(Stream stream, string extension = null)
|
public static System.Windows.Media.PixelFormat Map(this PixelFormat pixelFormat) =>
|
||||||
|
pixelFormat switch
|
||||||
|
{
|
||||||
|
PixelFormat.Format32bppArgb => PixelFormats.Bgra32,
|
||||||
|
PixelFormat.Format24bppRgb => PixelFormats.Bgr24,
|
||||||
|
PixelFormat.Format32bppRgb => PixelFormats.Bgr32,
|
||||||
|
_ => throw new NotSupportedException($"Can't map {pixelFormat}.")
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Map a System.Windows.Media.PixelFormat to a System.Drawing.Imaging.PixelFormat
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pixelFormat">System.Windows.Media.PixelFormat</param>
|
||||||
|
/// <returns>System.Drawing.Imaging.PixelFormat</returns>
|
||||||
|
/// <exception cref="NotSupportedException"></exception>
|
||||||
|
public static PixelFormat Map(this System.Windows.Media.PixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
if (pixelFormat == PixelFormats.Bgra32)
|
||||||
{
|
{
|
||||||
return null;
|
return PixelFormat.Format32bppArgb;
|
||||||
|
}
|
||||||
|
if (pixelFormat == PixelFormats.Bgr24)
|
||||||
|
{
|
||||||
|
return PixelFormat.Format24bppRgb;
|
||||||
|
}
|
||||||
|
if (pixelFormat == PixelFormats.Bgr32)
|
||||||
|
{
|
||||||
|
return PixelFormat.Format32bppRgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(extension))
|
throw new NotSupportedException($"Can't map {pixelFormat}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a Bitmap to a BitmapSource
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bitmap">Bitmap</param>
|
||||||
|
/// <returns>BitmapSource</returns>
|
||||||
|
public static BitmapSource ToBitmapSource(this Bitmap bitmap)
|
||||||
|
{
|
||||||
|
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||||
|
|
||||||
|
BitmapSource bitmapSource;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
extension = extension.Replace(".", string.Empty);
|
bitmapSource = BitmapSource.Create(
|
||||||
|
bitmapData.Width, bitmapData.Height,
|
||||||
|
bitmap.HorizontalResolution, bitmap.VerticalResolution,
|
||||||
|
bitmap.PixelFormat.Map(), null,
|
||||||
|
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
bitmap.UnlockBits(bitmapData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can try multiple times
|
return bitmapSource;
|
||||||
if (!stream.CanSeek)
|
}
|
||||||
{
|
|
||||||
var memoryStream = new MemoryStream();
|
|
||||||
stream.CopyTo(memoryStream);
|
|
||||||
stream = memoryStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
Image returnImage = null;
|
/// <summary>
|
||||||
if (StreamConverters.TryGetValue(extension ?? string.Empty, out var converter))
|
/// Convert a BitmapSource to a Bitmap
|
||||||
{
|
/// </summary>
|
||||||
returnImage = converter(stream, extension);
|
/// <param name="bitmapSource">BitmapSource</param>
|
||||||
}
|
/// <returns>Bitmap</returns>
|
||||||
|
public static Bitmap ToBitmap(this BitmapSource bitmapSource)
|
||||||
|
{
|
||||||
|
var pixelFormat = bitmapSource.Format.Map();
|
||||||
|
|
||||||
// Fallback
|
Bitmap bitmap = new Bitmap(bitmapSource.PixelWidth, bitmapSource.PixelHeight, pixelFormat);
|
||||||
if (returnImage == null)
|
BitmapData data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), ImageLockMode.WriteOnly, pixelFormat);
|
||||||
{
|
bitmapSource.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
|
||||||
// We create a copy of the bitmap, so everything else can be disposed
|
bitmap.UnlockBits(data);
|
||||||
stream.Position = 0;
|
return bitmap;
|
||||||
using var tmpImage = Image.FromStream(stream, true, true);
|
|
||||||
Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
|
||||||
returnImage = Clone(tmpImage, PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnImage;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,12 +20,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -33,20 +32,21 @@ using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.Base.Controls;
|
using Greenshot.Base.Controls;
|
||||||
using Greenshot.Base.Core.Enums;
|
using Greenshot.Base.Core.Enums;
|
||||||
|
using Greenshot.Base.Core.FileFormatHandlers;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Base.Interfaces;
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Plugin;
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
using log4net;
|
using log4net;
|
||||||
using Encoder = System.Drawing.Imaging.Encoder;
|
|
||||||
|
|
||||||
namespace Greenshot.Base.Core
|
namespace Greenshot.Base.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of ImageOutput.
|
/// Description of ImageOutput.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ImageOutput
|
public static class ImageIO
|
||||||
{
|
{
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageOutput));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageIO));
|
||||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
|
private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
|
||||||
private static readonly Cache<string, string> TmpFileCache = new Cache<string, string>(10 * 60 * 60, RemoveExpiredTmpFile);
|
private static readonly Cache<string, string> TmpFileCache = new Cache<string, string>(10 * 60 * 60, RemoveExpiredTmpFile);
|
||||||
|
@ -54,7 +54,7 @@ namespace Greenshot.Base.Core
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a PropertyItem (Metadata) to store with the image.
|
/// Creates a PropertyItem (Metadata) to store with the image.
|
||||||
/// For the possible ID's see: https://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx
|
/// For the possible ID's see: https://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx
|
||||||
/// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that!
|
/// This code uses Reflection to create a PropertyItem, although it's not advised it's not as stupid as having a image in the project so we can read a PropertyItem from that!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">ID</param>
|
/// <param name="id">ID</param>
|
||||||
/// <param name="text">Text</param>
|
/// <param name="text">Text</param>
|
||||||
|
@ -124,102 +124,21 @@ namespace Greenshot.Base.Core
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var imageFormat = outputSettings.Format switch
|
// Check if we want to use a memory stream, to prevent issues with non seekable streams
|
||||||
{
|
|
||||||
OutputFormat.bmp => ImageFormat.Bmp,
|
|
||||||
OutputFormat.gif => ImageFormat.Gif,
|
|
||||||
OutputFormat.jpg => ImageFormat.Jpeg,
|
|
||||||
OutputFormat.tiff => ImageFormat.Tiff,
|
|
||||||
OutputFormat.ico => ImageFormat.Icon,
|
|
||||||
_ => ImageFormat.Png
|
|
||||||
};
|
|
||||||
Log.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat);
|
|
||||||
|
|
||||||
// Check if we want to use a memory stream, to prevent issues with non seakable streams
|
|
||||||
// The save is made to the targetStream, this is directed to either the MemoryStream or the original
|
// The save is made to the targetStream, this is directed to either the MemoryStream or the original
|
||||||
Stream targetStream = stream;
|
Stream targetStream = stream;
|
||||||
if (!stream.CanSeek)
|
if (!stream.CanSeek)
|
||||||
{
|
{
|
||||||
useMemoryStream = true;
|
useMemoryStream = true;
|
||||||
Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream.");
|
Log.Warn("Using a memory stream prevent an issue with saving to a non seekable stream.");
|
||||||
memoryStream = new MemoryStream();
|
memoryStream = new MemoryStream();
|
||||||
targetStream = memoryStream;
|
targetStream = memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Equals(imageFormat, ImageFormat.Jpeg))
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
if (!fileFormatHandlers.TrySaveToStream(imageToSave as Bitmap, targetStream, outputSettings.Format.ToString(), surface, outputSettings))
|
||||||
{
|
{
|
||||||
bool foundEncoder = false;
|
return;
|
||||||
foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders())
|
|
||||||
{
|
|
||||||
if (imageCodec.FormatID == imageFormat.Guid)
|
|
||||||
{
|
|
||||||
EncoderParameters parameters = new EncoderParameters(1)
|
|
||||||
{
|
|
||||||
Param =
|
|
||||||
{
|
|
||||||
[0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Removing transparency if it's not supported in the output
|
|
||||||
if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
|
|
||||||
{
|
|
||||||
Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
|
|
||||||
AddTag(nonAlphaImage);
|
|
||||||
nonAlphaImage.Save(targetStream, imageCodec, parameters);
|
|
||||||
nonAlphaImage.Dispose();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddTag(imageToSave);
|
|
||||||
imageToSave.Save(targetStream, imageCodec, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
foundEncoder = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundEncoder)
|
|
||||||
{
|
|
||||||
throw new ApplicationException("No JPG encoder found, this should not happen.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Equals(imageFormat, ImageFormat.Icon))
|
|
||||||
{
|
|
||||||
// FEATURE-916: Added Icon support
|
|
||||||
IList<Image> images = new List<Image>
|
|
||||||
{
|
|
||||||
imageToSave
|
|
||||||
};
|
|
||||||
WriteIcon(stream, images);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool needsDispose = false;
|
|
||||||
// Removing transparency if it's not supported in the output
|
|
||||||
if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
|
|
||||||
{
|
|
||||||
imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
|
|
||||||
needsDispose = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddTag(imageToSave);
|
|
||||||
// Added for OptiPNG
|
|
||||||
bool processed = false;
|
|
||||||
if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand))
|
|
||||||
{
|
|
||||||
processed = ProcessPngImageExternally(imageToSave, targetStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processed)
|
|
||||||
{
|
|
||||||
imageToSave.Save(targetStream, imageFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsDispose)
|
|
||||||
{
|
|
||||||
imageToSave.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we used a memory stream, we need to stream the memory stream to the original stream.
|
// If we used a memory stream, we need to stream the memory stream to the original stream.
|
||||||
|
@ -227,21 +146,6 @@ namespace Greenshot.Base.Core
|
||||||
{
|
{
|
||||||
memoryStream.WriteTo(stream);
|
memoryStream.WriteTo(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output the surface elements, size and marker to the stream
|
|
||||||
if (outputSettings.Format != OutputFormat.greenshot)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using MemoryStream tmpStream = new MemoryStream();
|
|
||||||
long bytesWritten = surface.SaveElementsToStream(tmpStream);
|
|
||||||
using BinaryWriter writer = new BinaryWriter(tmpStream);
|
|
||||||
writer.Write(bytesWritten);
|
|
||||||
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
|
||||||
byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}");
|
|
||||||
writer.Write(marker);
|
|
||||||
tmpStream.WriteTo(stream);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -249,89 +153,6 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="imageToProcess">Image to pass to the external process</param>
|
|
||||||
/// <param name="targetStream">stream to write the processed image to</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static bool ProcessPngImageExternally(Image imageToProcess, Stream targetStream)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(CoreConfig.OptimizePNGCommand))
|
|
||||||
{
|
|
||||||
Log.WarnFormat("Can't find 'OptimizePNGCommand' {0}", CoreConfig.OptimizePNGCommand);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (FileStream tmpStream = File.Create(tmpFileName))
|
|
||||||
{
|
|
||||||
Log.DebugFormat("Writing png to tmp file: {0}", tmpFileName);
|
|
||||||
imageToProcess.Save(tmpStream, ImageFormat.Png);
|
|
||||||
if (Log.IsDebugEnabled)
|
|
||||||
{
|
|
||||||
Log.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Log.IsDebugEnabled)
|
|
||||||
{
|
|
||||||
Log.DebugFormat("Starting : {0}", CoreConfig.OptimizePNGCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessStartInfo processStartInfo = new ProcessStartInfo(CoreConfig.OptimizePNGCommand)
|
|
||||||
{
|
|
||||||
Arguments = string.Format(CoreConfig.OptimizePNGCommandArguments, tmpFileName),
|
|
||||||
CreateNoWindow = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
using Process process = Process.Start(processStartInfo);
|
|
||||||
if (process != null)
|
|
||||||
{
|
|
||||||
process.WaitForExit();
|
|
||||||
if (process.ExitCode == 0)
|
|
||||||
{
|
|
||||||
if (Log.IsDebugEnabled)
|
|
||||||
{
|
|
||||||
Log.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length);
|
|
||||||
Log.DebugFormat("Reading back tmp file: {0}", tmpFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] processedImage = File.ReadAllBytes(tmpFileName);
|
|
||||||
targetStream.Write(processedImage, 0, processedImage.Length);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode);
|
|
||||||
Log.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd());
|
|
||||||
Log.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error("Error while processing PNG image: ", e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (File.Exists(tmpFileName))
|
|
||||||
{
|
|
||||||
Log.DebugFormat("Cleaning up tmp file: {0}", tmpFileName);
|
|
||||||
File.Delete(tmpFileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an image from a surface with the settings from the output settings applied
|
/// Create an image from a surface with the settings from the output settings applied
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -429,20 +250,18 @@ namespace Greenshot.Base.Core
|
||||||
/// Add the greenshot property!
|
/// Add the greenshot property!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="imageToSave"></param>
|
/// <param name="imageToSave"></param>
|
||||||
private static void AddTag(Image imageToSave)
|
public static void AddTag(this Image imageToSave)
|
||||||
{
|
{
|
||||||
// Create meta-data
|
// Create meta-data
|
||||||
PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot");
|
PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot");
|
||||||
if (softwareUsedPropertyItem != null)
|
if (softwareUsedPropertyItem == null) return;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
imageToSave.SetPropertyItem(softwareUsedPropertyItem);
|
||||||
{
|
}
|
||||||
imageToSave.SetPropertyItem(softwareUsedPropertyItem);
|
catch (Exception)
|
||||||
}
|
{
|
||||||
catch (Exception)
|
Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id);
|
||||||
{
|
|
||||||
Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +282,7 @@ namespace Greenshot.Base.Core
|
||||||
// Fixed lock problem Bug #3431881
|
// Fixed lock problem Bug #3431881
|
||||||
using (Stream surfaceFileStream = File.OpenRead(fullPath))
|
using (Stream surfaceFileStream = File.OpenRead(fullPath))
|
||||||
{
|
{
|
||||||
returnSurface = ImageHelper.LoadGreenshotSurface(surfaceFileStream, returnSurface);
|
returnSurface = LoadGreenshotSurface(surfaceFileStream, returnSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnSurface != null)
|
if (returnSurface != null)
|
||||||
|
@ -547,27 +366,25 @@ namespace Greenshot.Base.Core
|
||||||
using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails))
|
using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails))
|
||||||
{
|
{
|
||||||
DialogResult dialogResult = saveImageFileDialog.ShowDialog();
|
DialogResult dialogResult = saveImageFileDialog.ShowDialog();
|
||||||
if (dialogResult.Equals(DialogResult.OK))
|
if (!dialogResult.Equals(DialogResult.OK)) return returnValue;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
|
||||||
|
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension));
|
||||||
|
if (CoreConfig.OutputFilePromptQuality)
|
||||||
{
|
{
|
||||||
string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
|
QualityDialog qualityDialog = new QualityDialog(outputSettings);
|
||||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension));
|
qualityDialog.ShowDialog();
|
||||||
if (CoreConfig.OutputFilePromptQuality)
|
}
|
||||||
{
|
|
||||||
QualityDialog qualityDialog = new QualityDialog(outputSettings);
|
|
||||||
qualityDialog.ShowDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: For now we always overwrite, should be changed
|
// TODO: For now we always overwrite, should be changed
|
||||||
Save(surface, fileNameWithExtension, true, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
|
Save(surface, fileNameWithExtension, true, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
|
||||||
returnValue = fileNameWithExtension;
|
returnValue = fileNameWithExtension;
|
||||||
IniConfig.Save();
|
IniConfig.Save();
|
||||||
}
|
}
|
||||||
catch (ExternalException)
|
catch (ExternalException)
|
||||||
{
|
{
|
||||||
MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error"));
|
MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,91 +526,218 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Write the images to the stream as icon
|
/// Load an image from file
|
||||||
/// Every image is resized to 256x256 (but the content maintains the aspect ratio)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">Stream to write to</param>
|
/// <param name="filename"></param>
|
||||||
/// <param name="images">List of images</param>
|
/// <returns></returns>
|
||||||
public static void WriteIcon(Stream stream, IList<Image> images)
|
public static Image LoadImage(string filename)
|
||||||
{
|
{
|
||||||
var binaryWriter = new BinaryWriter(stream);
|
if (string.IsNullOrEmpty(filename))
|
||||||
//
|
|
||||||
// ICONDIR structure
|
|
||||||
//
|
|
||||||
binaryWriter.Write((short) 0); // reserved
|
|
||||||
binaryWriter.Write((short) 1); // image type (icon)
|
|
||||||
binaryWriter.Write((short) images.Count); // number of images
|
|
||||||
|
|
||||||
IList<Size> imageSizes = new List<Size>();
|
|
||||||
IList<MemoryStream> encodedImages = new List<MemoryStream>();
|
|
||||||
foreach (var image in images)
|
|
||||||
{
|
{
|
||||||
// Pick the best fit
|
return null;
|
||||||
var sizes = new[]
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(filename))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image fileImage;
|
||||||
|
Log.InfoFormat("Loading image from file {0}", filename);
|
||||||
|
// Fixed lock problem Bug #3431881
|
||||||
|
using (Stream imageFileStream = File.OpenRead(filename))
|
||||||
|
{
|
||||||
|
fileImage = FromStream(imageFileStream, Path.GetExtension(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileImage != null)
|
||||||
|
{
|
||||||
|
Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat,
|
||||||
|
fileImage.HorizontalResolution, fileImage.VerticalResolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Based on: https://www.codeproject.com/KB/cs/IconExtractor.aspx
|
||||||
|
/// And a hint from: https://www.codeproject.com/KB/cs/IconLib.aspx
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iconStream">Stream with the icon information</param>
|
||||||
|
/// <returns>Bitmap with the Vista Icon (256x256)</returns>
|
||||||
|
private static Bitmap ExtractVistaIcon(Stream iconStream)
|
||||||
|
{
|
||||||
|
const int sizeIconDir = 6;
|
||||||
|
const int sizeIconDirEntry = 16;
|
||||||
|
Bitmap bmpPngExtracted = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] srcBuf = new byte[iconStream.Length];
|
||||||
|
iconStream.Read(srcBuf, 0, (int)iconStream.Length);
|
||||||
|
int iCount = BitConverter.ToInt16(srcBuf, 4);
|
||||||
|
for (int iIndex = 0; iIndex < iCount; iIndex++)
|
||||||
{
|
{
|
||||||
16, 32, 48
|
int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex];
|
||||||
};
|
int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1];
|
||||||
int size = 256;
|
if (iWidth == 0 && iHeight == 0)
|
||||||
foreach (var possibleSize in sizes)
|
|
||||||
{
|
|
||||||
if (image.Width <= possibleSize && image.Height <= possibleSize)
|
|
||||||
{
|
{
|
||||||
size = possibleSize;
|
int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
|
||||||
|
int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
|
||||||
|
using MemoryStream destStream = new MemoryStream();
|
||||||
|
destStream.Write(srcBuf, iImageOffset, iImageSize);
|
||||||
|
destStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var imageStream = new MemoryStream();
|
return bmpPngExtracted;
|
||||||
if (image.Width == size && image.Height == size)
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="location">The file (EXE or DLL) to get the icon from</param>
|
||||||
|
/// <param name="index">Index of the icon</param>
|
||||||
|
/// <param name="takeLarge">true if the large icon is wanted</param>
|
||||||
|
/// <returns>Icon</returns>
|
||||||
|
public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge)
|
||||||
|
{
|
||||||
|
Shell32.ExtractIconEx(location, index, out var large, out var small, 1);
|
||||||
|
Icon returnIcon = null;
|
||||||
|
bool isLarge = false;
|
||||||
|
bool isSmall = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (takeLarge && !IntPtr.Zero.Equals(large))
|
||||||
{
|
{
|
||||||
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
returnIcon = Icon.FromHandle(large);
|
||||||
clonedImage.Save(imageStream, ImageFormat.Png);
|
isLarge = true;
|
||||||
imageSizes.Add(new Size(size, size));
|
|
||||||
}
|
}
|
||||||
else
|
else if (!IntPtr.Zero.Equals(small))
|
||||||
{
|
{
|
||||||
// Resize to the specified size, first make sure the image is 32bpp
|
returnIcon = Icon.FromHandle(small);
|
||||||
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
isSmall = true;
|
||||||
using var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null);
|
}
|
||||||
resizedImage.Save(imageStream, ImageFormat.Png);
|
else if (!IntPtr.Zero.Equals(large))
|
||||||
imageSizes.Add(resizedImage.Size);
|
{
|
||||||
|
returnIcon = Icon.FromHandle(large);
|
||||||
|
isLarge = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (isLarge && !IntPtr.Zero.Equals(small))
|
||||||
|
{
|
||||||
|
User32.DestroyIcon(small);
|
||||||
}
|
}
|
||||||
|
|
||||||
imageStream.Seek(0, SeekOrigin.Begin);
|
if (isSmall && !IntPtr.Zero.Equals(large))
|
||||||
encodedImages.Add(imageStream);
|
{
|
||||||
|
User32.DestroyIcon(large);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
return returnIcon;
|
||||||
// ICONDIRENTRY structure
|
}
|
||||||
//
|
|
||||||
const int iconDirSize = 6;
|
|
||||||
const int iconDirEntrySize = 16;
|
|
||||||
|
|
||||||
var offset = iconDirSize + (images.Count * iconDirEntrySize);
|
/// <summary>
|
||||||
for (int i = 0; i < images.Count; i++)
|
/// Create an image from a stream, if an extension is supplied more formats are supported.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">Stream</param>
|
||||||
|
/// <param name="extension"></param>
|
||||||
|
/// <returns>Image</returns>
|
||||||
|
public static Image FromStream(Stream stream, string extension = null)
|
||||||
|
{
|
||||||
|
if (stream == null)
|
||||||
{
|
{
|
||||||
var imageSize = imageSizes[i];
|
return null;
|
||||||
// Write the width / height, 0 means 256
|
|
||||||
binaryWriter.Write(imageSize.Width == 256 ? (byte) 0 : (byte) imageSize.Width);
|
|
||||||
binaryWriter.Write(imageSize.Height == 256 ? (byte) 0 : (byte) imageSize.Height);
|
|
||||||
binaryWriter.Write((byte) 0); // no pallete
|
|
||||||
binaryWriter.Write((byte) 0); // reserved
|
|
||||||
binaryWriter.Write((short) 0); // no color planes
|
|
||||||
binaryWriter.Write((short) 32); // 32 bpp
|
|
||||||
binaryWriter.Write((int) encodedImages[i].Length); // image data length
|
|
||||||
binaryWriter.Write(offset);
|
|
||||||
offset += (int) encodedImages[i].Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binaryWriter.Flush();
|
if (!string.IsNullOrEmpty(extension))
|
||||||
//
|
|
||||||
// Write image data
|
|
||||||
//
|
|
||||||
foreach (var encodedImage in encodedImages)
|
|
||||||
{
|
{
|
||||||
encodedImage.WriteTo(stream);
|
extension = extension.Replace(".", string.Empty);
|
||||||
encodedImage.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var startingPosition = stream.Position;
|
||||||
|
|
||||||
|
// Make sure we can try multiple times
|
||||||
|
if (!stream.CanSeek)
|
||||||
|
{
|
||||||
|
var memoryStream = new MemoryStream();
|
||||||
|
stream.CopyTo(memoryStream);
|
||||||
|
stream = memoryStream;
|
||||||
|
// As we are if a different stream, which starts at 0, change the starting position
|
||||||
|
startingPosition = 0;
|
||||||
|
}
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
foreach (var fileFormatHandler in fileFormatHandlers
|
||||||
|
.Where(ffh => ffh.Supports(FileFormatHandlerActions.LoadFromStream, extension))
|
||||||
|
.OrderBy(ffh => ffh.PriorityFor(FileFormatHandlerActions.LoadFromStream, extension)))
|
||||||
|
{
|
||||||
|
stream.Seek(startingPosition, SeekOrigin.Begin);
|
||||||
|
if (fileFormatHandler.TryLoadFromStream(stream, extension, out var bitmap))
|
||||||
|
{
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load a Greenshot surface from a stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="surfaceFileStream">Stream</param>
|
||||||
|
/// <param name="returnSurface"></param>
|
||||||
|
/// <returns>ISurface</returns>
|
||||||
|
public static ISurface LoadGreenshotSurface(Stream surfaceFileStream, ISurface returnSurface)
|
||||||
|
{
|
||||||
|
Image fileImage;
|
||||||
|
// Fixed problem that the bitmap stream is disposed... by Cloning the image
|
||||||
|
// This also ensures the bitmap is correctly created
|
||||||
|
|
||||||
|
// We create a copy of the bitmap, so everything else can be disposed
|
||||||
|
surfaceFileStream.Position = 0;
|
||||||
|
using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true))
|
||||||
|
{
|
||||||
|
Log.DebugFormat("Loaded .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
||||||
|
fileImage = ImageHelper.Clone(tmpImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
|
||||||
|
const int markerSize = 14;
|
||||||
|
surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
|
||||||
|
using (StreamReader streamReader = new StreamReader(surfaceFileStream))
|
||||||
|
{
|
||||||
|
var greenshotMarker = streamReader.ReadToEnd();
|
||||||
|
if (!greenshotMarker.StartsWith("Greenshot"))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Stream is not a Greenshot file!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.InfoFormat("Greenshot file format: {0}", greenshotMarker);
|
||||||
|
const int filesizeLocation = 8 + markerSize;
|
||||||
|
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
|
||||||
|
using BinaryReader reader = new BinaryReader(surfaceFileStream);
|
||||||
|
long bytesWritten = reader.ReadInt64();
|
||||||
|
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
|
||||||
|
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileImage != null)
|
||||||
|
{
|
||||||
|
returnSurface.Image = fileImage;
|
||||||
|
Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", fileImage.Width, fileImage.Height, fileImage.PixelFormat,
|
||||||
|
fileImage.HorizontalResolution, fileImage.VerticalResolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnSurface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,77 +0,0 @@
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
|
|
||||||
namespace Greenshot.Base.Core
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wrap an image, make it resizeable
|
|
||||||
/// </summary>
|
|
||||||
public class ImageWrapper : IImage
|
|
||||||
{
|
|
||||||
// Underlying image, is used to generate a resized version of it when needed
|
|
||||||
private readonly Image _image;
|
|
||||||
private Image _imageClone;
|
|
||||||
|
|
||||||
public ImageWrapper(Image image)
|
|
||||||
{
|
|
||||||
// Make sure the orientation is set correctly so Greenshot can process the image correctly
|
|
||||||
ImageHelper.Orientate(image);
|
|
||||||
_image = image;
|
|
||||||
Width = _image.Width;
|
|
||||||
Height = _image.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_image.Dispose();
|
|
||||||
_imageClone?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height of the image, can be set to change
|
|
||||||
/// </summary>
|
|
||||||
public int Height { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Width of the image, can be set to change.
|
|
||||||
/// </summary>
|
|
||||||
public int Width { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of the image
|
|
||||||
/// </summary>
|
|
||||||
public Size Size => new Size(Width, Height);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pixelformat of the underlying image
|
|
||||||
/// </summary>
|
|
||||||
public PixelFormat PixelFormat => Image.PixelFormat;
|
|
||||||
|
|
||||||
public float HorizontalResolution => Image.HorizontalResolution;
|
|
||||||
public float VerticalResolution => Image.VerticalResolution;
|
|
||||||
|
|
||||||
public Image Image
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_imageClone == null)
|
|
||||||
{
|
|
||||||
if (_image.Height == Height && _image.Width == Width)
|
|
||||||
{
|
|
||||||
return _image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_imageClone?.Height == Height && _imageClone?.Width == Width)
|
|
||||||
{
|
|
||||||
return _imageClone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate new image clone
|
|
||||||
_imageClone?.Dispose();
|
|
||||||
_imageClone = ImageHelper.ResizeImage(_image, false, Width, Height, null);
|
|
||||||
return _imageClone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,11 +24,14 @@ using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Greenshot.Base.Core.FileFormatHandlers;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Base.Interfaces;
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Base.Interfaces.Plugin;
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
|
@ -87,24 +90,14 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Download the uri to Bitmap
|
/// Download the uri to build an IDrawableContainer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">Of an image</param>
|
/// <param name="url">Of an image</param>
|
||||||
/// <returns>Bitmap</returns>
|
/// <returns>IDrawableContainer</returns>
|
||||||
public static Image DownloadImage(string url)
|
public static IDrawableContainer DownloadImageAsDrawableContainer(string url)
|
||||||
{
|
{
|
||||||
var extensions = new StringBuilder();
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
foreach (var extension in ImageHelper.StreamConverters.Keys)
|
var extensions = string.Join("|", fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadFromStream));
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(extension))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.AppendFormat(@"\.{0}|", extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.Length--;
|
|
||||||
|
|
||||||
var imageUrlRegex = new Regex($@"(http|https)://.*(?<extension>{extensions})");
|
var imageUrlRegex = new Regex($@"(http|https)://.*(?<extension>{extensions})");
|
||||||
var match = imageUrlRegex.Match(url);
|
var match = imageUrlRegex.Match(url);
|
||||||
|
@ -113,7 +106,12 @@ namespace Greenshot.Base.Core
|
||||||
using var memoryStream = GetAsMemoryStream(url);
|
using var memoryStream = GetAsMemoryStream(url);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null);
|
var extension = match.Success ? match.Groups["extension"]?.Value : null;
|
||||||
|
var drawableContainer = fileFormatHandlers.LoadDrawablesFromStream(memoryStream, extension).FirstOrDefault();
|
||||||
|
if (drawableContainer != null)
|
||||||
|
{
|
||||||
|
return drawableContainer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +134,71 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
using var memoryStream2 = GetAsMemoryStream(match.Value);
|
using var memoryStream2 = GetAsMemoryStream(match.Value);
|
||||||
return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value);
|
|
||||||
|
var extension = match.Success ? match.Groups["extension"]?.Value : null;
|
||||||
|
var drawableContainer = fileFormatHandlers.LoadDrawablesFromStream(memoryStream2, extension).FirstOrDefault();
|
||||||
|
if (drawableContainer != null)
|
||||||
|
{
|
||||||
|
return drawableContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error("Problem downloading the image from: " + url, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Download the uri to create a Bitmap
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">Of an image</param>
|
||||||
|
/// <returns>Bitmap</returns>
|
||||||
|
public static Bitmap DownloadImage(string url)
|
||||||
|
{
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
|
||||||
|
var extensions = string.Join("|", fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadFromStream));
|
||||||
|
|
||||||
|
var imageUrlRegex = new Regex($@"(http|https)://.*(?<extension>{extensions})");
|
||||||
|
var match = imageUrlRegex.Match(url);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var memoryStream = GetAsMemoryStream(url);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (fileFormatHandlers.TryLoadFromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null, out var bitmap))
|
||||||
|
{
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
|
||||||
|
string content;
|
||||||
|
using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
|
||||||
|
{
|
||||||
|
content = streamReader.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(content))
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = imageUrlRegex.Match(content);
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var memoryStream2 = GetAsMemoryStream(match.Value);
|
||||||
|
if (fileFormatHandlers.TryLoadFromStream(memoryStream2, match.Success ? match.Groups["extension"]?.Value : null, out var bitmap))
|
||||||
|
{
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -670,7 +732,7 @@ namespace Greenshot.Base.Core
|
||||||
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
||||||
{
|
{
|
||||||
using MemoryStream stream = new MemoryStream();
|
using MemoryStream stream = new MemoryStream();
|
||||||
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
ImageIO.SaveToStream(_surface, stream, _outputSettings);
|
||||||
return Convert.ToBase64String(stream.GetBuffer(), 0, (int) stream.Length, formattingOptions);
|
return Convert.ToBase64String(stream.GetBuffer(), 0, (int) stream.Length, formattingOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +744,7 @@ namespace Greenshot.Base.Core
|
||||||
public byte[] ToByteArray()
|
public byte[] ToByteArray()
|
||||||
{
|
{
|
||||||
using MemoryStream stream = new MemoryStream();
|
using MemoryStream stream = new MemoryStream();
|
||||||
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
ImageIO.SaveToStream(_surface, stream, _outputSettings);
|
||||||
return stream.ToArray();
|
return stream.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +760,7 @@ namespace Greenshot.Base.Core
|
||||||
string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
|
string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
|
||||||
|
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||||
ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings);
|
ImageIO.SaveToStream(_surface, formDataStream, _outputSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -708,7 +770,7 @@ namespace Greenshot.Base.Core
|
||||||
public void WriteToStream(Stream dataStream)
|
public void WriteToStream(Stream dataStream)
|
||||||
{
|
{
|
||||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||||
ImageOutput.SaveToStream(_surface, dataStream, _outputSettings);
|
ImageIO.SaveToStream(_surface, dataStream, _outputSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace Greenshot.Base.Core
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, CoreConfig.UseLargeIcons))
|
using (Icon appIcon = ImageIO.ExtractAssociatedIcon(path, index, CoreConfig.UseLargeIcons))
|
||||||
{
|
{
|
||||||
if (appIcon != null)
|
if (appIcon != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,22 +10,19 @@ namespace Greenshot.Base.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimpleServiceProvider : IServiceLocator
|
public class SimpleServiceProvider : IServiceLocator
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Type, List<object>> _services = new Dictionary<Type, List<object>>();
|
private readonly Dictionary<Type, IList<object>> _services = new();
|
||||||
|
|
||||||
public static IServiceLocator Current { get; } = new SimpleServiceProvider();
|
public static IServiceLocator Current { get; } = new SimpleServiceProvider();
|
||||||
|
|
||||||
public IEnumerable<TService> GetAllInstances<TService>()
|
public IReadOnlyList<TService> GetAllInstances<TService>()
|
||||||
{
|
{
|
||||||
var typeOfService = typeof(TService);
|
var typeOfService = typeof(TService);
|
||||||
if (!_services.TryGetValue(typeOfService, out var results))
|
if (!_services.TryGetValue(typeOfService, out var results))
|
||||||
{
|
{
|
||||||
yield break;
|
return Array.Empty<TService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (TService result in results)
|
return results.Cast<TService>().ToArray();
|
||||||
{
|
|
||||||
yield return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TService GetInstance<TService>()
|
public TService GetInstance<TService>()
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* Greenshot - a free and open source screenshot tool
|
|
||||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
|
||||||
*
|
|
||||||
* For more information see: https://getgreenshot.org/
|
|
||||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 1 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using Svg;
|
|
||||||
|
|
||||||
namespace Greenshot.Base.Core
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Create an image look like of the SVG
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SvgImage : IImage
|
|
||||||
{
|
|
||||||
private readonly SvgDocument _svgDocument;
|
|
||||||
|
|
||||||
private Image _imageClone;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Factory to create via a stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">Stream</param>
|
|
||||||
/// <returns>IImage</returns>
|
|
||||||
public static IImage FromStream(Stream stream)
|
|
||||||
{
|
|
||||||
return new SvgImage(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream"></param>
|
|
||||||
public SvgImage(Stream stream)
|
|
||||||
{
|
|
||||||
_svgDocument = SvgDocument.Open<SvgDocument>(stream);
|
|
||||||
Height = (int) _svgDocument.ViewBox.Height;
|
|
||||||
Width = (int) _svgDocument.ViewBox.Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height of the image, can be set to change
|
|
||||||
/// </summary>
|
|
||||||
public int Height { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Width of the image, can be set to change.
|
|
||||||
/// </summary>
|
|
||||||
public int Width { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of the image
|
|
||||||
/// </summary>
|
|
||||||
public Size Size => new Size(Width, Height);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pixelformat of the underlying image
|
|
||||||
/// </summary>
|
|
||||||
public PixelFormat PixelFormat => Image.PixelFormat;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Horizontal resolution of the underlying image
|
|
||||||
/// </summary>
|
|
||||||
public float HorizontalResolution => Image.HorizontalResolution;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Vertical resolution of the underlying image
|
|
||||||
/// </summary>
|
|
||||||
public float VerticalResolution => Image.VerticalResolution;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Underlying image, or an on demand rendered version with different attributes as the original
|
|
||||||
/// </summary>
|
|
||||||
public Image Image
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_imageClone?.Height == Height && _imageClone?.Width == Width)
|
|
||||||
{
|
|
||||||
return _imageClone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate new image clone
|
|
||||||
_imageClone?.Dispose();
|
|
||||||
_imageClone = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent, 96, 96);
|
|
||||||
_svgDocument.Draw((Bitmap) _imageClone);
|
|
||||||
return _imageClone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_imageClone?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -782,7 +782,9 @@ namespace Greenshot.Base.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WindowStyleFlags WindowStyle
|
public WindowStyleFlags WindowStyle
|
||||||
{
|
{
|
||||||
get => (WindowStyleFlags) User32.GetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE);
|
get => unchecked(
|
||||||
|
(WindowStyleFlags)User32.GetWindowLongWrapper(Handle, (int)WindowLongIndex.GWL_STYLE).ToInt64()
|
||||||
|
);
|
||||||
set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE, new IntPtr((long) value));
|
set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE, new IntPtr((long) value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,14 @@ namespace Greenshot.Base.Interfaces.Drawing
|
||||||
{
|
{
|
||||||
public interface IDrawableContainer : INotifyPropertyChanged, IDisposable
|
public interface IDrawableContainer : INotifyPropertyChanged, IDisposable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The parent surface where this IDrawableContainer is on
|
||||||
|
/// </summary>
|
||||||
ISurface Parent { get; set; }
|
ISurface Parent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is this IDrawableContainer selected on the surface
|
||||||
|
/// </summary>
|
||||||
bool Selected { get; set; }
|
bool Selected { get; set; }
|
||||||
|
|
||||||
int Left { get; set; }
|
int Left { get; set; }
|
||||||
|
@ -54,15 +61,25 @@ namespace Greenshot.Base.Interfaces.Drawing
|
||||||
bool HasFilters { get; }
|
bool HasFilters { get; }
|
||||||
|
|
||||||
EditStatus Status { get; set; }
|
EditStatus Status { get; set; }
|
||||||
|
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
|
|
||||||
bool ClickableAt(int x, int y);
|
bool ClickableAt(int x, int y);
|
||||||
|
|
||||||
void MoveBy(int x, int y);
|
void MoveBy(int x, int y);
|
||||||
|
|
||||||
void Transform(Matrix matrix);
|
void Transform(Matrix matrix);
|
||||||
|
|
||||||
bool HandleMouseDown(int x, int y);
|
bool HandleMouseDown(int x, int y);
|
||||||
|
|
||||||
void HandleMouseUp(int x, int y);
|
void HandleMouseUp(int x, int y);
|
||||||
|
|
||||||
bool HandleMouseMove(int x, int y);
|
bool HandleMouseMove(int x, int y);
|
||||||
|
|
||||||
bool InitContent();
|
bool InitContent();
|
||||||
|
|
||||||
void MakeBoundsChangeUndoable(bool allowMerge);
|
void MakeBoundsChangeUndoable(bool allowMerge);
|
||||||
|
|
||||||
EditStatus DefaultEditMode { get; }
|
EditStatus DefaultEditMode { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
33
src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs
Normal file
33
src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Base.Interfaces.Drawing
|
||||||
|
{
|
||||||
|
public interface IFieldAggregator
|
||||||
|
{
|
||||||
|
void UnbindElement(IDrawableContainer dc);
|
||||||
|
void BindElements(IDrawableContainerList dcs);
|
||||||
|
void BindElement(IDrawableContainer dc);
|
||||||
|
IField GetField(IFieldType fieldType);
|
||||||
|
|
||||||
|
event FieldChangedEventHandler FieldChanged;
|
||||||
|
}
|
||||||
|
}
|
88
src/Greenshot.Base/Interfaces/IFileFormatHandler.cs
Normal file
88
src/Greenshot.Base/Interfaces/IFileFormatHandler.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
|
||||||
|
namespace Greenshot.Base.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The possible actions a IFileFormatHandler might support
|
||||||
|
/// </summary>
|
||||||
|
public enum FileFormatHandlerActions
|
||||||
|
{
|
||||||
|
SaveToStream,
|
||||||
|
LoadFromStream,
|
||||||
|
LoadDrawableFromStream
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This interface is for code to implement the loading and saving of certain file formats
|
||||||
|
/// </summary>
|
||||||
|
public interface IFileFormatHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registry for all the extensions this IFileFormatHandler support
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<FileFormatHandlerActions, IReadOnlyCollection<string>> SupportedExtensions { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Priority (from high int.MinValue, low int.MaxValue) of this IFileFormatHandler for the specified action and extension
|
||||||
|
/// This should be used to sort the possible IFileFormatHandler
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileFormatHandlerAction">FileFormatHandlerActions</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <returns>int specifying the priority for the action and extension</returns>
|
||||||
|
public int PriorityFor(FileFormatHandlerActions fileFormatHandlerAction, string extension);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to save the specified bitmap to the stream in the format belonging to the extension
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bitmap">Bitmap</param>
|
||||||
|
/// <param name="destination">Stream</param>
|
||||||
|
/// <param name="extension">extension</param>
|
||||||
|
/// <param name="surface">ISurface with the elements for those file types which can store a surface (.greenshot)</param>
|
||||||
|
/// <param name="surfaceOutputSettings">SurfaceOutputSettings</param>
|
||||||
|
/// <returns>bool true if it was successful</returns>
|
||||||
|
public bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"></param>
|
||||||
|
/// <param name="extension"></param>
|
||||||
|
/// <param name="bitmap"></param>
|
||||||
|
/// <returns>bool true if it was successful</returns>
|
||||||
|
public bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to load a drawable container from the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">Stream</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <param name="parentSurface">ISurface</param>
|
||||||
|
/// <returns>IEnumerable{IDrawableContainer}</returns>
|
||||||
|
public IEnumerable<IDrawableContainer> LoadDrawablesFromStream(Stream stream, string extension, ISurface parentSurface = null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ namespace Greenshot.Base.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TService">Service to find</typeparam>
|
/// <typeparam name="TService">Service to find</typeparam>
|
||||||
/// <returns>IEnumerable{TService}</returns>
|
/// <returns>IEnumerable{TService}</returns>
|
||||||
IEnumerable<TService> GetAllInstances<TService>();
|
IReadOnlyList<TService> GetAllInstances<TService>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the only instance of the specified service
|
/// Get the only instance of the specified service
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.Base.Core;
|
using Greenshot.Base.Core;
|
||||||
|
@ -201,5 +202,14 @@ namespace Greenshot.Base.Interfaces
|
||||||
Rectangle ToImageCoordinates(Rectangle rc);
|
Rectangle ToImageCoordinates(Rectangle rc);
|
||||||
|
|
||||||
void MakeUndoable(IMemento memento, bool allowMerge);
|
void MakeUndoable(IMemento memento, bool allowMerge);
|
||||||
|
|
||||||
|
IFieldAggregator FieldAggregator { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This reverses a change of the background image
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="previous">Image</param>
|
||||||
|
/// <param name="matrix">Matrix</param>
|
||||||
|
void UndoBackgroundChange(Image previous, Matrix matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,25 @@
|
||||||
using System.Collections.Generic;
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using Greenshot.Base.Core;
|
using Greenshot.Base.Core;
|
||||||
using Greenshot.Base.Core.Enums;
|
using Greenshot.Base.Core.Enums;
|
||||||
using Greenshot.Base.Effects;
|
using Greenshot.Base.Effects;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Greenshot.Base.UnmanagedHelpers.Enums
|
||||||
public enum WindowStyleFlags : int
|
public enum WindowStyleFlags : int
|
||||||
{
|
{
|
||||||
//WS_OVERLAPPED = 0x00000000,
|
//WS_OVERLAPPED = 0x00000000,
|
||||||
WS_POPUP = -2147483648,
|
WS_POPUP = -2147483648, // 0x80000000
|
||||||
WS_CHILD = 0x40000000,
|
WS_CHILD = 0x40000000,
|
||||||
WS_MINIMIZE = 0x20000000,
|
WS_MINIMIZE = 0x20000000,
|
||||||
WS_VISIBLE = 0x10000000,
|
WS_VISIBLE = 0x10000000,
|
||||||
|
|
|
@ -127,7 +127,7 @@ namespace Greenshot.Base.UnmanagedHelpers
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
|
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
[DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")]
|
[DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")]
|
||||||
public static extern int GetWindowLong(IntPtr hWnd, int index);
|
public static extern IntPtr GetWindowLong(IntPtr hWnd, int index);
|
||||||
|
|
||||||
[DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLongPtr")]
|
[DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLongPtr")]
|
||||||
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
||||||
|
@ -276,16 +276,14 @@ namespace Greenshot.Base.UnmanagedHelpers
|
||||||
/// <param name="hWnd"></param>
|
/// <param name="hWnd"></param>
|
||||||
/// <param name="nIndex"></param>
|
/// <param name="nIndex"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static long GetWindowLongWrapper(IntPtr hWnd, int nIndex)
|
public static IntPtr GetWindowLongWrapper(IntPtr hWnd, int nIndex)
|
||||||
{
|
{
|
||||||
if (IntPtr.Size == 8)
|
if (IntPtr.Size == 8)
|
||||||
{
|
{
|
||||||
return GetWindowLongPtr(hWnd, nIndex).ToInt64();
|
return GetWindowLongPtr(hWnd, nIndex);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return GetWindowLong(hWnd, nIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return GetWindowLong(hWnd, nIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6);
|
private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6);
|
||||||
|
|
||||||
public ArrowContainer(Surface parent) : base(parent)
|
public ArrowContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -32,7 +33,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CropContainer : DrawableContainer
|
public class CropContainer : DrawableContainer
|
||||||
{
|
{
|
||||||
public CropContainer(Surface parent) : base(parent)
|
public CropContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ using System.Drawing.Drawing2D;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
protected Cursor cursor;
|
protected Cursor cursor;
|
||||||
|
|
||||||
public CursorContainer(Surface parent) : base(parent)
|
public CursorContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +57,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
CreateDefaultAdorners();
|
CreateDefaultAdorners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CursorContainer(Surface parent, string filename) : this(parent)
|
public CursorContainer(ISurface parent, string filename) : this(parent)
|
||||||
{
|
{
|
||||||
Load(filename);
|
Load(filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,12 +126,17 @@ namespace Greenshot.Editor.Drawing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NonSerialized] internal Surface _parent;
|
[NonSerialized] internal ISurface _parent;
|
||||||
|
|
||||||
public ISurface Parent
|
public ISurface Parent
|
||||||
{
|
{
|
||||||
get => _parent;
|
get => _parent;
|
||||||
set => SwitchParent((Surface) value);
|
set => SwitchParent(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Surface InternalParent
|
||||||
|
{
|
||||||
|
get => (Surface)_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NonSerialized] private TargetAdorner _targetAdorner;
|
[NonSerialized] private TargetAdorner _targetAdorner;
|
||||||
|
@ -277,7 +282,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
Height = Round(newBounds.Height);
|
Height = Round(newBounds.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrawableContainer(Surface parent)
|
public DrawableContainer(ISurface parent)
|
||||||
{
|
{
|
||||||
InitializeFields();
|
InitializeFields();
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
|
@ -505,7 +510,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
|
||||||
// reset "workrbench" rectangle to current bounds
|
// reset "workbench" rectangle to current bounds
|
||||||
_boundsAfterResize.X = _boundsBeforeResize.Left;
|
_boundsAfterResize.X = _boundsBeforeResize.Left;
|
||||||
_boundsAfterResize.Y = _boundsBeforeResize.Top;
|
_boundsAfterResize.Y = _boundsBeforeResize.Top;
|
||||||
_boundsAfterResize.Width = x - _boundsAfterResize.Left;
|
_boundsAfterResize.Width = x - _boundsAfterResize.Left;
|
||||||
|
@ -529,7 +534,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SwitchParent(Surface newParent)
|
protected virtual void SwitchParent(ISurface newParent)
|
||||||
{
|
{
|
||||||
if (newParent == Parent)
|
if (newParent == Parent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -35,7 +36,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
[Serializable()]
|
[Serializable()]
|
||||||
public class EllipseContainer : DrawableContainer
|
public class EllipseContainer : DrawableContainer
|
||||||
{
|
{
|
||||||
public EllipseContainer(Surface parent) : base(parent)
|
public EllipseContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Greenshot.Editor.Drawing.Fields
|
||||||
/// If the property values of the selected elements differ, the value of the last bound element wins.
|
/// If the property values of the selected elements differ, the value of the last bound element wins.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class FieldAggregator : AbstractFieldHolder
|
public sealed class FieldAggregator : AbstractFieldHolder, IFieldAggregator
|
||||||
{
|
{
|
||||||
private readonly IDrawableContainerList _boundContainers;
|
private readonly IDrawableContainerList _boundContainers;
|
||||||
private bool _internalUpdateRunning;
|
private bool _internalUpdateRunning;
|
||||||
|
@ -117,11 +117,10 @@ namespace Greenshot.Editor.Drawing.Fields
|
||||||
|
|
||||||
public void UnbindElement(IDrawableContainer dc)
|
public void UnbindElement(IDrawableContainer dc)
|
||||||
{
|
{
|
||||||
if (_boundContainers.Contains(dc))
|
if (!_boundContainers.Contains(dc)) return;
|
||||||
{
|
|
||||||
_boundContainers.Remove(dc);
|
_boundContainers.Remove(dc);
|
||||||
UpdateFromBoundElements();
|
UpdateFromBoundElements();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
|
|
@ -23,6 +23,7 @@ using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -51,7 +52,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
MAGNIFICATION
|
MAGNIFICATION
|
||||||
};
|
};
|
||||||
|
|
||||||
public FilterContainer(Surface parent) : base(parent)
|
public FilterContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -50,7 +51,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FreehandContainer(Surface parent) : base(parent)
|
public FreehandContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Width = parent.Image.Width;
|
Width = parent.Image.Width;
|
||||||
Height = parent.Image.Height;
|
Height = parent.Image.Height;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Drawing.Filters;
|
using Greenshot.Editor.Drawing.Filters;
|
||||||
|
@ -33,7 +34,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class HighlightContainer : FilterContainer
|
public class HighlightContainer : FilterContainer
|
||||||
{
|
{
|
||||||
public HighlightContainer(Surface parent) : base(parent)
|
public HighlightContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
protected Icon icon;
|
protected Icon icon;
|
||||||
|
|
||||||
public IconContainer(Surface parent) : base(parent)
|
public IconContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
@ -55,11 +56,16 @@ namespace Greenshot.Editor.Drawing
|
||||||
CreateDefaultAdorners();
|
CreateDefaultAdorners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IconContainer(Surface parent, string filename) : base(parent)
|
public IconContainer(ISurface parent, string filename) : base(parent)
|
||||||
{
|
{
|
||||||
Load(filename);
|
Load(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IconContainer(ISurface parent, Stream stream) : base(parent)
|
||||||
|
{
|
||||||
|
Load(stream);
|
||||||
|
}
|
||||||
|
|
||||||
public Icon Icon
|
public Icon Icon
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
|
@ -99,6 +105,18 @@ namespace Greenshot.Editor.Drawing
|
||||||
Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Load(Stream iconStream)
|
||||||
|
{
|
||||||
|
if (iconStream == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Icon fileIcon = new Icon(iconStream);
|
||||||
|
Icon = fileIcon;
|
||||||
|
Log.Debug("Loaded stream: with resolution: " + Height + "," + Width);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Draw(Graphics graphics, RenderMode rm)
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
{
|
{
|
||||||
if (icon == null)
|
if (icon == null)
|
||||||
|
|
|
@ -26,6 +26,7 @@ using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using Greenshot.Base.Core;
|
using Greenshot.Base.Core;
|
||||||
using Greenshot.Base.Effects;
|
using Greenshot.Base.Effects;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -40,7 +41,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageContainer));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageContainer));
|
||||||
|
|
||||||
private Image image;
|
private Image _image;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the shadow version of the bitmap, rendered once to save performance
|
/// This is the shadow version of the bitmap, rendered once to save performance
|
||||||
|
@ -54,12 +55,12 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NonSerialized] private Point _shadowOffset = new Point(-1, -1);
|
[NonSerialized] private Point _shadowOffset = new Point(-1, -1);
|
||||||
|
|
||||||
public ImageContainer(Surface parent, string filename) : this(parent)
|
public ImageContainer(ISurface parent, string filename) : this(parent)
|
||||||
{
|
{
|
||||||
Load(filename);
|
Load(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageContainer(Surface parent) : base(parent)
|
public ImageContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
FieldChanged += BitmapContainer_OnFieldChanged;
|
FieldChanged += BitmapContainer_OnFieldChanged;
|
||||||
Init();
|
Init();
|
||||||
|
@ -107,8 +108,8 @@ namespace Greenshot.Editor.Drawing
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Width = image.Width;
|
Width = _image.Width;
|
||||||
Height = image.Height;
|
Height = _image.Height;
|
||||||
if (_shadowBitmap != null)
|
if (_shadowBitmap != null)
|
||||||
{
|
{
|
||||||
Left += _shadowOffset.X;
|
Left += _shadowOffset.X;
|
||||||
|
@ -124,13 +125,13 @@ namespace Greenshot.Editor.Drawing
|
||||||
// Remove all current bitmaps
|
// Remove all current bitmaps
|
||||||
DisposeImage();
|
DisposeImage();
|
||||||
DisposeShadow();
|
DisposeShadow();
|
||||||
image = ImageHelper.Clone(value);
|
_image = ImageHelper.Clone(value);
|
||||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||||
CheckShadow(shadow);
|
CheckShadow(shadow);
|
||||||
if (!shadow)
|
if (!shadow)
|
||||||
{
|
{
|
||||||
Width = image.Width;
|
Width = _image.Width;
|
||||||
Height = image.Height;
|
Height = _image.Height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -140,7 +141,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
Top -= _shadowOffset.Y;
|
Top -= _shadowOffset.Y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get { return image; }
|
get { return _image; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -162,8 +163,8 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
private void DisposeImage()
|
private void DisposeImage()
|
||||||
{
|
{
|
||||||
image?.Dispose();
|
_image?.Dispose();
|
||||||
image = null;
|
_image = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeShadow()
|
private void DisposeShadow()
|
||||||
|
@ -186,9 +187,9 @@ namespace Greenshot.Editor.Drawing
|
||||||
Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle);
|
Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle);
|
||||||
DisposeShadow();
|
DisposeShadow();
|
||||||
using var tmpMatrix = new Matrix();
|
using var tmpMatrix = new Matrix();
|
||||||
using (image)
|
using (_image)
|
||||||
{
|
{
|
||||||
image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix);
|
_image = ImageHelper.ApplyEffect(_image, new RotateEffect(rotateAngle), tmpMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +209,8 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
// Always make sure ImageHelper.LoadBitmap results are disposed some time,
|
// Always make sure ImageHelper.LoadBitmap results are disposed some time,
|
||||||
// as we close the bitmap internally, we need to do it afterwards
|
// as we close the bitmap internally, we need to do it afterwards
|
||||||
using (var tmpImage = ImageHelper.LoadImage(filename))
|
// TODO: Replace with some other code, like the file format handler, or move it completely outside of this class
|
||||||
|
using (var tmpImage = ImageIO.LoadImage(filename))
|
||||||
{
|
{
|
||||||
Image = tmpImage;
|
Image = tmpImage;
|
||||||
}
|
}
|
||||||
|
@ -228,7 +230,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
}
|
}
|
||||||
|
|
||||||
using var matrix = new Matrix();
|
using var matrix = new Matrix();
|
||||||
_shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix);
|
_shadowBitmap = ImageHelper.ApplyEffect(_image, new DropShadowEffect(), matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -238,7 +240,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// <param name="rm"></param>
|
/// <param name="rm"></param>
|
||||||
public override void Draw(Graphics graphics, RenderMode rm)
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
{
|
{
|
||||||
if (image == null)
|
if (_image == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -256,12 +258,12 @@ namespace Greenshot.Editor.Drawing
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
graphics.DrawImage(image, Bounds);
|
graphics.DrawImage(_image, Bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HasDefaultSize => true;
|
public override bool HasDefaultSize => true;
|
||||||
|
|
||||||
public override Size DefaultSize => image?.Size ?? new Size(32, 32);
|
public override Size DefaultSize => _image?.Size ?? new Size(32, 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,6 +23,7 @@ using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Adorners;
|
using Greenshot.Editor.Drawing.Adorners;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
|
@ -36,7 +37,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
[Serializable()]
|
[Serializable()]
|
||||||
public class LineContainer : DrawableContainer
|
public class LineContainer : DrawableContainer
|
||||||
{
|
{
|
||||||
public LineContainer(Surface parent) : base(parent)
|
public LineContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
81
src/Greenshot.Editor/Drawing/MetafileContainer.cs
Normal file
81
src/Greenshot.Editor/Drawing/MetafileContainer.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Svg;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This provides a resizable SVG container, redrawing the SVG in the size the container takes.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class MetafileContainer : VectorGraphicsContainer
|
||||||
|
{
|
||||||
|
private readonly Metafile _metafile;
|
||||||
|
|
||||||
|
public MetafileContainer(Metafile metafile, ISurface parent) : base(parent)
|
||||||
|
{
|
||||||
|
_metafile = metafile;
|
||||||
|
Size = new Size(metafile.Width/4, metafile.Height/4);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Image ComputeBitmap()
|
||||||
|
{
|
||||||
|
var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent);
|
||||||
|
|
||||||
|
var dstRect = new Rectangle(0, 0, Width, Height);
|
||||||
|
using (Graphics graphics = Graphics.FromImage(image))
|
||||||
|
{
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
graphics.DrawImage(_metafile, dstRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RotationAngle == 0) return image;
|
||||||
|
|
||||||
|
var newImage = image.Rotate(RotationAngle);
|
||||||
|
image.Dispose();
|
||||||
|
return newImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_metafile?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasDefaultSize => true;
|
||||||
|
|
||||||
|
public override Size DefaultSize => new Size(_metafile.Width, _metafile.Height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Drawing.Filters;
|
using Greenshot.Editor.Drawing.Filters;
|
||||||
|
@ -28,12 +29,12 @@ using Greenshot.Editor.Drawing.Filters;
|
||||||
namespace Greenshot.Editor.Drawing
|
namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of ObfuscateContainer.
|
/// This is a FilterContainer for the obfuscator filters like blur and pixelate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ObfuscateContainer : FilterContainer
|
public class ObfuscateContainer : FilterContainer
|
||||||
{
|
{
|
||||||
public ObfuscateContainer(Surface parent) : base(parent)
|
public ObfuscateContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -35,7 +36,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class RectangleContainer : DrawableContainer
|
public class RectangleContainer : DrawableContainer
|
||||||
{
|
{
|
||||||
public RectangleContainer(Surface parent) : base(parent)
|
public RectangleContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Text;
|
using System.Drawing.Text;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -64,8 +65,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
InitAdorner(Color.Green, _storedTargetGripperLocation);
|
InitAdorner(Color.Green, _storedTargetGripperLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpeechbubbleContainer(Surface parent)
|
public SpeechbubbleContainer(ISurface parent) : base(parent)
|
||||||
: base(parent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Text;
|
using System.Drawing.Text;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -41,9 +42,9 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
private readonly bool _drawAsRectangle = false;
|
private readonly bool _drawAsRectangle = false;
|
||||||
|
|
||||||
public StepLabelContainer(Surface parent) : base(parent)
|
public StepLabelContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
parent.AddStepLabel(this);
|
InternalParent?.AddStepLabel(this);
|
||||||
InitContent();
|
InitContent();
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
@ -72,11 +73,10 @@ namespace Greenshot.Editor.Drawing
|
||||||
[OnSerializing]
|
[OnSerializing]
|
||||||
private void SetValuesOnSerializing(StreamingContext context)
|
private void SetValuesOnSerializing(StreamingContext context)
|
||||||
{
|
{
|
||||||
if (Parent != null)
|
if (InternalParent == null) return;
|
||||||
{
|
|
||||||
Number = ((Surface) Parent).CountStepLabels(this);
|
Number = InternalParent.CountStepLabels(this);
|
||||||
_counterStart = ((Surface) Parent).CounterStart;
|
_counterStart = InternalParent.CounterStart;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -97,23 +97,23 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// Add the StepLabel to the parent
|
/// Add the StepLabel to the parent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newParent"></param>
|
/// <param name="newParent"></param>
|
||||||
protected override void SwitchParent(Surface newParent)
|
protected override void SwitchParent(ISurface newParent)
|
||||||
{
|
{
|
||||||
if (newParent == Parent)
|
if (newParent == Parent)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
((Surface) Parent)?.RemoveStepLabel(this);
|
if (newParent is not Surface newParentSurface)
|
||||||
base.SwitchParent(newParent);
|
|
||||||
if (newParent == null)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
InternalParent?.RemoveStepLabel(this);
|
||||||
|
base.SwitchParent(newParent);
|
||||||
|
|
||||||
// Make sure the counter start is restored (this unfortunately happens multiple times... -> hack)
|
// Make sure the counter start is restored (this unfortunately happens multiple times... -> hack)
|
||||||
newParent.CounterStart = _counterStart;
|
newParentSurface.CounterStart = _counterStart;
|
||||||
newParent.AddStepLabel(this);
|
newParentSurface.AddStepLabel(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Size DefaultSize => new Size(30, 30);
|
public override Size DefaultSize => new Size(30, 30);
|
||||||
|
|
|
@ -49,7 +49,6 @@ namespace Greenshot.Editor.Drawing
|
||||||
public sealed class Surface : Control, ISurface, INotifyPropertyChanged
|
public sealed class Surface : Control, ISurface, INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(Surface));
|
private static readonly ILog LOG = LogManager.GetLogger(typeof(Surface));
|
||||||
public static int Count;
|
|
||||||
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
|
||||||
// Property to identify the Surface ID
|
// Property to identify the Surface ID
|
||||||
|
@ -207,7 +206,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
[NonSerialized] private IDrawableContainer _undrawnElement;
|
[NonSerialized] private IDrawableContainer _undrawnElement;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the cropcontainer, when cropping this is set, do not serialize
|
/// the crop container, when cropping this is set, do not serialize
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NonSerialized] private IDrawableContainer _cropContainer;
|
[NonSerialized] private IDrawableContainer _cropContainer;
|
||||||
|
|
||||||
|
@ -294,7 +293,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// all elements on the surface, needed with serialization
|
/// all elements on the surface, needed with serialization
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private FieldAggregator _fieldAggregator;
|
private IFieldAggregator _fieldAggregator;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the cursor container, needed with serialization as we need a direct acces to it.
|
/// the cursor container, needed with serialization as we need a direct acces to it.
|
||||||
|
@ -355,7 +354,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// The field aggregator is that which is used to have access to all the fields inside the currently selected elements.
|
/// The field aggregator is that which is used to have access to all the fields inside the currently selected elements.
|
||||||
/// e.g. used to decided if and which line thickness is shown when multiple elements are selected.
|
/// e.g. used to decided if and which line thickness is shown when multiple elements are selected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FieldAggregator FieldAggregator
|
public IFieldAggregator FieldAggregator
|
||||||
{
|
{
|
||||||
get => _fieldAggregator;
|
get => _fieldAggregator;
|
||||||
set => _fieldAggregator = value;
|
set => _fieldAggregator = value;
|
||||||
|
@ -467,7 +466,6 @@ namespace Greenshot.Editor.Drawing
|
||||||
public Surface()
|
public Surface()
|
||||||
{
|
{
|
||||||
_fieldAggregator = new FieldAggregator(this);
|
_fieldAggregator = new FieldAggregator(this);
|
||||||
Count++;
|
|
||||||
_elements = new DrawableContainerList(_uniqueId);
|
_elements = new DrawableContainerList(_uniqueId);
|
||||||
selectedElements = new DrawableContainerList(_uniqueId);
|
selectedElements = new DrawableContainerList(_uniqueId);
|
||||||
LOG.Debug("Creating surface!");
|
LOG.Debug("Creating surface!");
|
||||||
|
@ -550,7 +548,6 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
Count--;
|
|
||||||
LOG.Debug("Disposing surface!");
|
LOG.Debug("Disposing surface!");
|
||||||
if (_buffer != null)
|
if (_buffer != null)
|
||||||
{
|
{
|
||||||
|
@ -913,6 +910,27 @@ namespace Greenshot.Editor.Drawing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will help to fit the container to the surface
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="drawableContainer">IDrawableContainer</param>
|
||||||
|
private void FitContainer(IDrawableContainer drawableContainer)
|
||||||
|
{
|
||||||
|
double factor = 1;
|
||||||
|
if (drawableContainer.Width > this.Width)
|
||||||
|
{
|
||||||
|
factor = drawableContainer.Width / (double)Width;
|
||||||
|
}
|
||||||
|
if (drawableContainer.Height > this.Height)
|
||||||
|
{
|
||||||
|
var otherFactor = drawableContainer.Height / (double)Height;
|
||||||
|
factor = Math.Max(factor, otherFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawableContainer.Width = (int)(drawableContainer.Width / factor);
|
||||||
|
drawableContainer.Height = (int)(drawableContainer.Height / factor);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle the drag/drop
|
/// Handle the drag/drop
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -927,20 +945,25 @@ namespace Greenshot.Editor.Drawing
|
||||||
// Test if it's an url and try to download the image so we have it in the original form
|
// Test if it's an url and try to download the image so we have it in the original form
|
||||||
if (possibleUrl != null && possibleUrl.StartsWith("http"))
|
if (possibleUrl != null && possibleUrl.StartsWith("http"))
|
||||||
{
|
{
|
||||||
using Image image = NetworkHelper.DownloadImage(possibleUrl);
|
var drawableContainer = NetworkHelper.DownloadImageAsDrawableContainer(possibleUrl);
|
||||||
if (image != null)
|
if (drawableContainer != null)
|
||||||
{
|
{
|
||||||
AddImageContainer(image, mouse.X, mouse.Y);
|
drawableContainer.Left = Location.X;
|
||||||
|
drawableContainer.Top = Location.Y;
|
||||||
|
FitContainer(drawableContainer);
|
||||||
|
AddElement(drawableContainer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Image image in ClipboardHelper.GetImages(e.Data))
|
foreach (var drawableContainer in ClipboardHelper.GetDrawables(e.Data))
|
||||||
{
|
{
|
||||||
AddImageContainer(image, mouse.X, mouse.Y);
|
drawableContainer.Left = mouse.X;
|
||||||
|
drawableContainer.Top = mouse.Y;
|
||||||
|
FitContainer(drawableContainer);
|
||||||
|
AddElement(drawableContainer);
|
||||||
mouse.Offset(10, 10);
|
mouse.Offset(10, 10);
|
||||||
image.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,13 +1010,11 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
//create a blank bitmap the same size as original
|
//create a blank bitmap the same size as original
|
||||||
Bitmap newBitmap = ImageHelper.CreateEmptyLike(Image, Color.Empty);
|
Bitmap newBitmap = ImageHelper.CreateEmptyLike(Image, Color.Empty);
|
||||||
if (newBitmap != null)
|
if (newBitmap == null) return;
|
||||||
{
|
// Make undoable
|
||||||
// Make undoable
|
MakeUndoable(new SurfaceBackgroundChangeMemento(this, null), false);
|
||||||
MakeUndoable(new SurfaceBackgroundChangeMemento(this, null), false);
|
SetImage(newBitmap, false);
|
||||||
SetImage(newBitmap, false);
|
Invalidate();
|
||||||
Invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2057,17 +2078,16 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
Point pasteLocation = GetPasteLocation(0.1f, 0.1f);
|
Point pasteLocation = GetPasteLocation(0.1f, 0.1f);
|
||||||
|
|
||||||
foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard))
|
foreach (var drawableContainer in ClipboardHelper.GetDrawables(clipboard))
|
||||||
{
|
{
|
||||||
if (clipboardImage != null)
|
if (drawableContainer == null) continue;
|
||||||
{
|
DeselectAllElements();
|
||||||
DeselectAllElements();
|
drawableContainer.Left = pasteLocation.X;
|
||||||
IImageContainer container = AddImageContainer(clipboardImage as Bitmap, pasteLocation.X, pasteLocation.Y);
|
drawableContainer.Top = pasteLocation.Y;
|
||||||
SelectElement(container);
|
AddElement(drawableContainer);
|
||||||
clipboardImage.Dispose();
|
SelectElement(drawableContainer);
|
||||||
pasteLocation.X += 10;
|
pasteLocation.X += 10;
|
||||||
pasteLocation.Y += 10;
|
pasteLocation.Y += 10;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ClipboardHelper.ContainsText(clipboard))
|
else if (ClipboardHelper.ContainsText(clipboard))
|
||||||
|
@ -2208,24 +2228,23 @@ namespace Greenshot.Editor.Drawing
|
||||||
/// <param name="generateEvents">false to skip event generation</param>
|
/// <param name="generateEvents">false to skip event generation</param>
|
||||||
public void SelectElement(IDrawableContainer container, bool invalidate = true, bool generateEvents = true)
|
public void SelectElement(IDrawableContainer container, bool invalidate = true, bool generateEvents = true)
|
||||||
{
|
{
|
||||||
if (!selectedElements.Contains(container))
|
if (selectedElements.Contains(container)) return;
|
||||||
{
|
|
||||||
selectedElements.Add(container);
|
|
||||||
container.Selected = true;
|
|
||||||
FieldAggregator.BindElement(container);
|
|
||||||
if (generateEvents && _movingElementChanged != null)
|
|
||||||
{
|
|
||||||
SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs
|
|
||||||
{
|
|
||||||
Elements = selectedElements
|
|
||||||
};
|
|
||||||
_movingElementChanged(this, eventArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invalidate)
|
selectedElements.Add(container);
|
||||||
|
container.Selected = true;
|
||||||
|
FieldAggregator.BindElement(container);
|
||||||
|
if (generateEvents && _movingElementChanged != null)
|
||||||
|
{
|
||||||
|
SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs
|
||||||
{
|
{
|
||||||
container.Invalidate();
|
Elements = selectedElements
|
||||||
}
|
};
|
||||||
|
_movingElementChanged(this, eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalidate)
|
||||||
|
{
|
||||||
|
container.Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
61
src/Greenshot.Editor/Drawing/SvgContainer.cs
Normal file
61
src/Greenshot.Editor/Drawing/SvgContainer.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Svg;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This provides a resizable SVG container, redrawing the SVG in the size the container takes.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class SvgContainer : VectorGraphicsContainer
|
||||||
|
{
|
||||||
|
private SvgDocument _svgDocument;
|
||||||
|
|
||||||
|
public SvgContainer(SvgDocument svgDocument, ISurface parent) : base(parent)
|
||||||
|
{
|
||||||
|
_svgDocument = svgDocument;
|
||||||
|
Size = new Size((int)svgDocument.Width, (int)svgDocument.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Image ComputeBitmap()
|
||||||
|
{
|
||||||
|
//var image = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent);
|
||||||
|
|
||||||
|
var image = _svgDocument.Draw(Width, Height);
|
||||||
|
|
||||||
|
if (RotationAngle == 0) return image;
|
||||||
|
|
||||||
|
var newImage = image.Rotate(RotationAngle);
|
||||||
|
image.Dispose();
|
||||||
|
return newImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasDefaultSize => true;
|
||||||
|
|
||||||
|
public override Size DefaultSize => new Size((int)_svgDocument.Width, (int)_svgDocument.Height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ using System.Drawing.Text;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.Base.Core;
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing.Fields;
|
using Greenshot.Editor.Drawing.Fields;
|
||||||
using Greenshot.Editor.Helpers;
|
using Greenshot.Editor.Helpers;
|
||||||
|
@ -83,7 +84,7 @@ namespace Greenshot.Editor.Drawing
|
||||||
OnPropertyChanged("Text");
|
OnPropertyChanged("Text");
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextContainer(Surface parent) : base(parent)
|
public TextContainer(ISurface parent) : base(parent)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
@ -154,17 +155,17 @@ namespace Greenshot.Editor.Drawing
|
||||||
FieldChanged += TextContainer_FieldChanged;
|
FieldChanged += TextContainer_FieldChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SwitchParent(Surface newParent)
|
protected override void SwitchParent(ISurface newParent)
|
||||||
{
|
{
|
||||||
if (_parent != null)
|
if (InternalParent != null)
|
||||||
{
|
{
|
||||||
_parent.SizeChanged -= Parent_SizeChanged;
|
InternalParent.SizeChanged -= Parent_SizeChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.SwitchParent(newParent);
|
base.SwitchParent(newParent);
|
||||||
if (_parent != null)
|
if (InternalParent != null)
|
||||||
{
|
{
|
||||||
_parent.SizeChanged += Parent_SizeChanged;
|
InternalParent.SizeChanged += Parent_SizeChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,10 +222,10 @@ namespace Greenshot.Editor.Drawing
|
||||||
{
|
{
|
||||||
ShowTextBox();
|
ShowTextBox();
|
||||||
}
|
}
|
||||||
else if (_parent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible)
|
else if (InternalParent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible)
|
||||||
{
|
{
|
||||||
// Fix (workaround) for BUG-1698
|
// Fix (workaround) for BUG-1698
|
||||||
_parent.KeysLocked = true;
|
InternalParent.KeysLocked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,10 +296,10 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
private void ShowTextBox()
|
private void ShowTextBox()
|
||||||
{
|
{
|
||||||
if (_parent != null)
|
if (InternalParent != null)
|
||||||
{
|
{
|
||||||
_parent.KeysLocked = true;
|
InternalParent.KeysLocked = true;
|
||||||
_parent.Controls.Add(_textBox);
|
InternalParent.Controls.Add(_textBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureTextBoxContrast();
|
EnsureTextBoxContrast();
|
||||||
|
@ -332,15 +333,15 @@ namespace Greenshot.Editor.Drawing
|
||||||
|
|
||||||
private void HideTextBox()
|
private void HideTextBox()
|
||||||
{
|
{
|
||||||
_parent?.Focus();
|
InternalParent?.Focus();
|
||||||
_textBox?.Hide();
|
_textBox?.Hide();
|
||||||
if (_parent == null)
|
if (InternalParent == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_parent.KeysLocked = false;
|
InternalParent.KeysLocked = false;
|
||||||
_parent.Controls.Remove(_textBox);
|
InternalParent.Controls.Remove(_textBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
117
src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs
Normal file
117
src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the base container for vector graphics, these ae graphics which can resize without loss of quality.
|
||||||
|
/// Examples for this are SVG, WMF or EMF, but also graphics based on fonts (e.g. Emoji)
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public abstract class VectorGraphicsContainer : DrawableContainer
|
||||||
|
{
|
||||||
|
protected int RotationAngle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the cached version of the bitmap, pre-rendered to save performance
|
||||||
|
/// Do not serialized, it can be rebuild with some other information.
|
||||||
|
/// </summary>
|
||||||
|
[NonSerialized] private Image _cachedImage;
|
||||||
|
|
||||||
|
public VectorGraphicsContainer(ISurface parent) : base(parent)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDeserialized(StreamingContext streamingContext)
|
||||||
|
{
|
||||||
|
base.OnDeserialized(streamingContext);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
CreateDefaultAdorners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bulk of the clean-up code is implemented in Dispose(bool)
|
||||||
|
/// This Dispose is called from the Dispose and the Destructor.
|
||||||
|
/// When disposing==true all non-managed resources should be freed too!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
ResetCachedBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IDrawableContainer"/>
|
||||||
|
public override void Transform(Matrix matrix)
|
||||||
|
{
|
||||||
|
RotationAngle += CalculateAngle(matrix);
|
||||||
|
RotationAngle %= 360;
|
||||||
|
|
||||||
|
ResetCachedBitmap();
|
||||||
|
|
||||||
|
base.Transform(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IDrawableContainer"/>
|
||||||
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
|
{
|
||||||
|
if (_cachedImage != null && _cachedImage.Size != Bounds.Size)
|
||||||
|
{
|
||||||
|
ResetCachedBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedImage ??= ComputeBitmap();
|
||||||
|
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
|
||||||
|
|
||||||
|
graphics.DrawImage(_cachedImage, Bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Image ComputeBitmap();
|
||||||
|
|
||||||
|
private void ResetCachedBitmap()
|
||||||
|
{
|
||||||
|
_cachedImage?.Dispose();
|
||||||
|
_cachedImage = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/Greenshot.Editor/EditorInitialize.cs
Normal file
50
src/Greenshot.Editor/EditorInitialize.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Editor.FileFormatHandlers;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor
|
||||||
|
{
|
||||||
|
public static class EditorInitialize
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
SimpleServiceProvider.Current.AddService<IFileFormatHandler>(
|
||||||
|
// All generic things, like gif, png, jpg etc.
|
||||||
|
new DefaultFileFormatHandler(),
|
||||||
|
// Greenshot format
|
||||||
|
new GreenshotFileFormatHandler(),
|
||||||
|
// For .svg support
|
||||||
|
new SvgFileFormatHandler(),
|
||||||
|
// For clipboard support
|
||||||
|
new DibFileFormatHandler(),
|
||||||
|
// .ico
|
||||||
|
new IconFileFormatHandler(),
|
||||||
|
// EMF & WMF
|
||||||
|
new MetaFileFormatHandler(),
|
||||||
|
// JPG XR
|
||||||
|
new WpfFileFormatHandler()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using Greenshot.Editor.Drawing;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
public abstract class AbstractFileFormatHandler : IFileFormatHandler
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IDictionary<FileFormatHandlerActions, IReadOnlyCollection<string>> SupportedExtensions { get; } = new Dictionary<FileFormatHandlerActions, IReadOnlyCollection<string>>();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual int PriorityFor(FileFormatHandlerActions fileFormatHandlerAction, string extension)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null);
|
||||||
|
|
||||||
|
public abstract bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default implementation taking the TryLoadFromStream image and placing it in an ImageContainer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">Stream</param>
|
||||||
|
/// <param name="extension">string</param>
|
||||||
|
/// <param name="parent">ISurface</param>
|
||||||
|
/// <returns>IEnumerable{IDrawableContainer}</returns>
|
||||||
|
public virtual IEnumerable<IDrawableContainer> LoadDrawablesFromStream(Stream stream, string extension, ISurface parent = null)
|
||||||
|
{
|
||||||
|
if (TryLoadFromStream(stream, extension, out var bitmap))
|
||||||
|
{
|
||||||
|
var imageContainer = new ImageContainer(parent)
|
||||||
|
{
|
||||||
|
Image = bitmap
|
||||||
|
};
|
||||||
|
yield return imageContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the default .NET bitmap file format handler
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(DefaultFileFormatHandler));
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg", ".tiff", ".tif" };
|
||||||
|
public DefaultFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.SaveToStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
ImageFormat imageFormat = extension switch
|
||||||
|
{
|
||||||
|
".png" => ImageFormat.Png,
|
||||||
|
".bmp" => ImageFormat.Bmp,
|
||||||
|
".gif" => ImageFormat.Gif,
|
||||||
|
".jpg" => ImageFormat.Jpeg,
|
||||||
|
".jpeg" => ImageFormat.Jpeg,
|
||||||
|
".tiff" => ImageFormat.Tiff,
|
||||||
|
".tif" => ImageFormat.Tiff,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (imageFormat == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
surfaceOutputSettings ??= new SurfaceOutputSettings();
|
||||||
|
var imageEncoder = ImageCodecInfo.GetImageEncoders().FirstOrDefault(ie => ie.FilenameExtension.ToLowerInvariant().Contains(extension));
|
||||||
|
if (imageEncoder == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EncoderParameters parameters = new EncoderParameters(1)
|
||||||
|
{
|
||||||
|
Param =
|
||||||
|
{
|
||||||
|
[0] = new EncoderParameter(Encoder.Quality, surfaceOutputSettings.JPGQuality)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// For those images which are with Alpha, but the format doesn't support this, change it to 24bpp
|
||||||
|
if (imageFormat.Guid == ImageFormat.Jpeg.Guid && Image.IsAlphaPixelFormat(bitmap.PixelFormat))
|
||||||
|
{
|
||||||
|
var nonAlphaImage = ImageHelper.Clone(bitmap, PixelFormat.Format24bppRgb) as Bitmap;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Set that this file was written by Greenshot
|
||||||
|
nonAlphaImage.AddTag();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn("Couldn't set 'software used' tag on image.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nonAlphaImage.Save(destination, imageEncoder, parameters);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't save image: ", ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
nonAlphaImage.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set that this file was written by Greenshot
|
||||||
|
bitmap.AddTag();
|
||||||
|
bitmap.Save(destination, imageEncoder, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var tmpImage = Image.FromStream(stream, true, true);
|
||||||
|
bitmap = ImageHelper.Clone(tmpImage, PixelFormat.DontCare);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't load image: ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,29 +20,112 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
using Greenshot.Base.UnmanagedHelpers;
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
namespace Greenshot.Base.Core
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Though Greenshot implements the specs for the DIB image format,
|
/// This handles creating a DIB (Device Independent Bitmap) on the clipboard
|
||||||
/// it seems to cause a lot of issues when using the clipboard.
|
|
||||||
/// There is some research done about the DIB on the clipboard, this code is based upon the information
|
|
||||||
/// <a href="https://stackoverflow.com/questions/44177115/copying-from-and-to-clipboard-loses-image-transparency">here</a>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class DibHelper
|
public class DibFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
{
|
{
|
||||||
private const double DpiToPelsPerMeter = 39.3701;
|
private const double DpiToPelsPerMeter = 39.3701;
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(DibFileFormatHandler));
|
||||||
|
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new[] { ".dib", ".format17" };
|
||||||
|
|
||||||
|
public DibFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.SaveToStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
var dibBytes = ConvertToDib(bitmap);
|
||||||
|
destination.Write(dibBytes, 0, dibBytes.Length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
byte[] dibBuffer = new byte[stream.Length];
|
||||||
|
_ = stream.Read(dibBuffer, 0, dibBuffer.Length);
|
||||||
|
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADERV5>(dibBuffer);
|
||||||
|
if (!infoHeader.IsDibV5)
|
||||||
|
{
|
||||||
|
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
|
||||||
|
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
|
||||||
|
uint infoHeaderSize = infoHeader.biSize;
|
||||||
|
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
|
||||||
|
|
||||||
|
var fileHeader = new BITMAPFILEHEADER
|
||||||
|
{
|
||||||
|
bfType = BITMAPFILEHEADER.BM,
|
||||||
|
bfSize = fileSize,
|
||||||
|
bfReserved1 = 0,
|
||||||
|
bfReserved2 = 0,
|
||||||
|
bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4)
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
|
||||||
|
|
||||||
|
using var bitmapStream = new MemoryStream();
|
||||||
|
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
||||||
|
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
||||||
|
bitmapStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
// TODO: Replace with a FileFormatHandler
|
||||||
|
bitmap = ImageIO.FromStream(bitmapStream) as Bitmap;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Log.Info("Using special DIBV5 / Format17 format reader");
|
||||||
|
// CF_DIBV5
|
||||||
|
IntPtr gcHandle = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
|
||||||
|
gcHandle = GCHandle.ToIntPtr(handle);
|
||||||
|
bitmap = new Bitmap(infoHeader.biWidth, infoHeader.biHeight,
|
||||||
|
-(int)(infoHeader.biSizeImage / infoHeader.biHeight),
|
||||||
|
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
|
||||||
|
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels +
|
||||||
|
(infoHeader.biHeight - 1) * (int)(infoHeader.biSizeImage / infoHeader.biHeight))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Problem retrieving Format17 from clipboard.", ex);
|
||||||
|
bitmap = null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (gcHandle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
GCHandle.FromIntPtr(gcHandle).Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts the Bitmap to a Device Independent Bitmap format of type BITFIELDS.
|
/// Converts the Bitmap to a Device Independent Bitmap format of type BITFIELDS.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sourceBitmap">Bitmap to convert to DIB</param>
|
/// <param name="sourceBitmap">Bitmap to convert to DIB</param>
|
||||||
/// <returns>byte{} with the image converted to DIB</returns>
|
/// <returns>byte{} with the image converted to DIB</returns>
|
||||||
public static byte[] ConvertToDib(this Bitmap sourceBitmap)
|
private static byte[] ConvertToDib(Bitmap sourceBitmap)
|
||||||
{
|
{
|
||||||
if (sourceBitmap == null) throw new ArgumentNullException(nameof(sourceBitmap));
|
if (sourceBitmap == null) throw new ArgumentNullException(nameof(sourceBitmap));
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
public class GreenshotFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(GreenshotFileFormatHandler));
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new [] { ".greenshot" };
|
||||||
|
public GreenshotFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.SaveToStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream stream, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
if (surface == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bitmap.Save(stream, ImageFormat.Png);
|
||||||
|
using MemoryStream tmpStream = new MemoryStream();
|
||||||
|
long bytesWritten = surface.SaveElementsToStream(tmpStream);
|
||||||
|
using BinaryWriter writer = new BinaryWriter(tmpStream);
|
||||||
|
writer.Write(bytesWritten);
|
||||||
|
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}");
|
||||||
|
writer.Write(marker);
|
||||||
|
tmpStream.WriteTo(stream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't save surface as .greenshot: ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var surface = LoadSurface(stream);
|
||||||
|
bitmap = (Bitmap)surface.GetImageForExport();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't load .greenshot: ", ex);
|
||||||
|
}
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISurface LoadSurface(Stream surfaceFileStream)
|
||||||
|
{
|
||||||
|
var returnSurface = SimpleServiceProvider.Current.GetInstance<Func<ISurface>>().Invoke();
|
||||||
|
Bitmap captureBitmap;
|
||||||
|
|
||||||
|
// Fixed problem that the bitmap stream is disposed... by Cloning the image
|
||||||
|
// This also ensures the bitmap is correctly created
|
||||||
|
using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true))
|
||||||
|
{
|
||||||
|
Log.DebugFormat("Loaded capture from .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
||||||
|
captureBitmap = ImageHelper.Clone(tmpImage) as Bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
|
||||||
|
const int markerSize = 14;
|
||||||
|
surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
|
||||||
|
using (var streamReader = new StreamReader(surfaceFileStream))
|
||||||
|
{
|
||||||
|
var greenshotMarker = streamReader.ReadToEnd();
|
||||||
|
if (!greenshotMarker.StartsWith("Greenshot"))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Stream is not a Greenshot file!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.InfoFormat("Greenshot file format: {0}", greenshotMarker);
|
||||||
|
const int fileSizeLocation = 8 + markerSize;
|
||||||
|
surfaceFileStream.Seek(-fileSizeLocation, SeekOrigin.End);
|
||||||
|
using BinaryReader reader = new BinaryReader(surfaceFileStream);
|
||||||
|
long bytesWritten = reader.ReadInt64();
|
||||||
|
surfaceFileStream.Seek(-(bytesWritten + fileSizeLocation), SeekOrigin.End);
|
||||||
|
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captureBitmap != null)
|
||||||
|
{
|
||||||
|
returnSurface.Image = captureBitmap;
|
||||||
|
Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", captureBitmap.Width, captureBitmap.Height, captureBitmap.PixelFormat, captureBitmap.HorizontalResolution, captureBitmap.VerticalResolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnSurface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
218
src/Greenshot.Editor/FileFormatHandlers/IconFileFormatHandler.cs
Normal file
218
src/Greenshot.Editor/FileFormatHandlers/IconFileFormatHandler.cs
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// THis is the .ico format handler
|
||||||
|
/// </summary>
|
||||||
|
public class IconFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(IconFileFormatHandler));
|
||||||
|
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new[] { ".ico" };
|
||||||
|
|
||||||
|
public IconFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.SaveToStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream stream, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
IList<Image> images = new List<Image>
|
||||||
|
{
|
||||||
|
bitmap
|
||||||
|
};
|
||||||
|
|
||||||
|
var binaryWriter = new BinaryWriter(stream);
|
||||||
|
//
|
||||||
|
// ICONDIR structure
|
||||||
|
//
|
||||||
|
binaryWriter.Write((short)0); // reserved
|
||||||
|
binaryWriter.Write((short)1); // image type (icon)
|
||||||
|
binaryWriter.Write((short)images.Count); // number of images
|
||||||
|
|
||||||
|
IList<Size> imageSizes = new List<Size>();
|
||||||
|
IList<MemoryStream> encodedImages = new List<MemoryStream>();
|
||||||
|
foreach (var image in images)
|
||||||
|
{
|
||||||
|
// Pick the best fit
|
||||||
|
var sizes = new[]
|
||||||
|
{
|
||||||
|
16, 32, 48
|
||||||
|
};
|
||||||
|
int size = 256;
|
||||||
|
foreach (var possibleSize in sizes)
|
||||||
|
{
|
||||||
|
if (image.Width <= possibleSize && image.Height <= possibleSize)
|
||||||
|
{
|
||||||
|
size = possibleSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageStream = new MemoryStream();
|
||||||
|
if (image.Width == size && image.Height == size)
|
||||||
|
{
|
||||||
|
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||||
|
clonedImage.Save(imageStream, ImageFormat.Png);
|
||||||
|
imageSizes.Add(new Size(size, size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Resize to the specified size, first make sure the image is 32bpp
|
||||||
|
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||||
|
using var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null);
|
||||||
|
resizedImage.Save(imageStream, ImageFormat.Png);
|
||||||
|
imageSizes.Add(resizedImage.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
encodedImages.Add(imageStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ICONDIRENTRY structure
|
||||||
|
//
|
||||||
|
const int iconDirSize = 6;
|
||||||
|
const int iconDirEntrySize = 16;
|
||||||
|
|
||||||
|
var offset = iconDirSize + (images.Count * iconDirEntrySize);
|
||||||
|
for (int i = 0; i < images.Count; i++)
|
||||||
|
{
|
||||||
|
var imageSize = imageSizes[i];
|
||||||
|
// Write the width / height, 0 means 256
|
||||||
|
binaryWriter.Write(imageSize.Width == 256 ? (byte)0 : (byte)imageSize.Width);
|
||||||
|
binaryWriter.Write(imageSize.Height == 256 ? (byte)0 : (byte)imageSize.Height);
|
||||||
|
binaryWriter.Write((byte)0); // no pallete
|
||||||
|
binaryWriter.Write((byte)0); // reserved
|
||||||
|
binaryWriter.Write((short)0); // no color planes
|
||||||
|
binaryWriter.Write((short)32); // 32 bpp
|
||||||
|
binaryWriter.Write((int)encodedImages[i].Length); // image data length
|
||||||
|
binaryWriter.Write(offset);
|
||||||
|
offset += (int)encodedImages[i].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
binaryWriter.Flush();
|
||||||
|
//
|
||||||
|
// Write image data
|
||||||
|
//
|
||||||
|
foreach (var encodedImage in encodedImages)
|
||||||
|
{
|
||||||
|
encodedImage.WriteTo(stream);
|
||||||
|
encodedImage.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
_ = stream.Seek(0, SeekOrigin.Current);
|
||||||
|
|
||||||
|
// Icon logic, try to get the Vista icon, else the biggest possible
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using Image tmpImage = ExtractVistaIcon(stream);
|
||||||
|
if (tmpImage != null)
|
||||||
|
{
|
||||||
|
bitmap = ImageHelper.Clone(tmpImage, PixelFormat.Format32bppArgb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception vistaIconException)
|
||||||
|
{
|
||||||
|
Log.Warn("Can't read icon", vistaIconException);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// No vista icon, try normal icon
|
||||||
|
stream.Position = stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
// We create a copy of the bitmap, so everything else can be disposed
|
||||||
|
using Icon tmpIcon = new Icon(stream, new Size(1024, 1024));
|
||||||
|
using Image tmpImage = tmpIcon.ToBitmap();
|
||||||
|
bitmap = ImageHelper.Clone(tmpImage, PixelFormat.Format32bppArgb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception iconException)
|
||||||
|
{
|
||||||
|
Log.Warn("Can't read icon", iconException);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Based on: https://www.codeproject.com/KB/cs/IconExtractor.aspx
|
||||||
|
/// And a hint from: https://www.codeproject.com/KB/cs/IconLib.aspx
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iconStream">Stream with the icon information</param>
|
||||||
|
/// <returns>Bitmap with the Vista Icon (256x256)</returns>
|
||||||
|
private static Bitmap ExtractVistaIcon(Stream iconStream)
|
||||||
|
{
|
||||||
|
const int sizeIconDir = 6;
|
||||||
|
const int sizeIconDirEntry = 16;
|
||||||
|
Bitmap bmpPngExtracted = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] srcBuf = new byte[iconStream.Length];
|
||||||
|
// TODO: Check if there is a need to process the result
|
||||||
|
_ = iconStream.Read(srcBuf, 0, (int)iconStream.Length);
|
||||||
|
int iCount = BitConverter.ToInt16(srcBuf, 4);
|
||||||
|
for (int iIndex = 0; iIndex < iCount; iIndex++)
|
||||||
|
{
|
||||||
|
int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex];
|
||||||
|
int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1];
|
||||||
|
if (iWidth != 0 || iHeight != 0) continue;
|
||||||
|
|
||||||
|
int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
|
||||||
|
int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
|
||||||
|
using MemoryStream destStream = new MemoryStream();
|
||||||
|
destStream.Write(srcBuf, iImageOffset, iImageSize);
|
||||||
|
destStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bmpPngExtracted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using Greenshot.Editor.Drawing;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This handles the Windows metafile files
|
||||||
|
/// </summary>
|
||||||
|
public class MetaFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new[] { ".wmf", ".emf" };
|
||||||
|
|
||||||
|
public MetaFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Image.FromStream(stream, true, true) is Metafile metaFile)
|
||||||
|
{
|
||||||
|
bitmap = ImageHelper.Clone(metaFile, PixelFormat.Format32bppArgb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<IDrawableContainer> LoadDrawablesFromStream(Stream stream, string extension, ISurface surface = null)
|
||||||
|
{
|
||||||
|
if (Image.FromStream(stream, true, true) is Metafile metaFile)
|
||||||
|
{
|
||||||
|
yield return new MetafileContainer(metaFile, surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
|
using Greenshot.Editor.Drawing;
|
||||||
|
using log4net;
|
||||||
|
using Svg;
|
||||||
|
|
||||||
|
namespace Greenshot.Editor.FileFormatHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This handled the loading of SVG images to the editor
|
||||||
|
/// </summary>
|
||||||
|
public class SvgFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(SvgFileFormatHandler));
|
||||||
|
private readonly IReadOnlyCollection<string> _ourExtensions = new[] { ".svg" };
|
||||||
|
|
||||||
|
public SvgFileFormatHandler()
|
||||||
|
{
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadDrawableFromStream] = _ourExtensions;
|
||||||
|
SupportedExtensions[FileFormatHandlerActions.LoadFromStream] = _ourExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
var svgDocument = SvgDocument.Open<SvgDocument>(stream);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bitmap = svgDocument.Draw();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Can't load SVG", ex);
|
||||||
|
}
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
// TODO: Implement this
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<IDrawableContainer> LoadDrawablesFromStream(Stream stream, string extension, ISurface parent = null)
|
||||||
|
{
|
||||||
|
SvgDocument svgDocument = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
svgDocument = SvgDocument.Open<SvgDocument>(stream);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Can't load SVG", ex);
|
||||||
|
}
|
||||||
|
if (svgDocument != null)
|
||||||
|
{
|
||||||
|
yield return new SvgContainer(svgDocument, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
144
src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs
Normal file
144
src/Greenshot.Editor/FileFormatHandlers/WpfFileFormatHandler.cs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the System.Windows.Media.Imaging (WPF) file format handler, which uses WIC
|
||||||
|
/// </summary>
|
||||||
|
public class WpfFileFormatHandler : AbstractFileFormatHandler, IFileFormatHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog Log = LogManager.GetLogger(typeof(WpfFileFormatHandler));
|
||||||
|
private const string HeifDecoder = "{E9A4A80A-44FE-4DE4-8971-7150B10A5199}";
|
||||||
|
private const string WicDecoderCategory = "{7ED96837-96F0-4812-B211-F13C24117ED3}";
|
||||||
|
|
||||||
|
private IReadOnlyCollection<string> LoadFromStreamExtensions { get; } = new []{ ".jxr", ".dds", ".hdp", ".wdp", ".wmp"};
|
||||||
|
private IReadOnlyCollection<string> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detect all the formats WIC supports
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>IEnumerable{string}</returns>
|
||||||
|
private IEnumerable<string> 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";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TrySaveToStream(Bitmap bitmap, Stream destination, string extension, ISurface surface = null, SurfaceOutputSettings surfaceOutputSettings = null)
|
||||||
|
{
|
||||||
|
surfaceOutputSettings ??= new SurfaceOutputSettings();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bitmapSource = bitmap.ToBitmapSource();
|
||||||
|
var bitmapFrame = BitmapFrame.Create(bitmapSource);
|
||||||
|
var jpegXrEncoder = new WmpBitmapEncoder();
|
||||||
|
jpegXrEncoder.Frames.Add(bitmapFrame);
|
||||||
|
// TODO: Support supplying a quality
|
||||||
|
jpegXrEncoder.ImageQualityLevel = surfaceOutputSettings.JPGQuality / 100f;
|
||||||
|
jpegXrEncoder.Save(destination);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't save image as JPEG XR: ", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool TryLoadFromStream(Stream stream, string extension, out Bitmap bitmap)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bitmapDecoder = BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
|
||||||
|
var bitmapSource = bitmapDecoder.Frames[0];
|
||||||
|
bitmap = bitmapSource.ToBitmap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't load image: ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,13 +56,13 @@ namespace Greenshot.Editor.Forms
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageEditorForm));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(ImageEditorForm));
|
||||||
private static readonly EditorConfiguration EditorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
|
private static readonly EditorConfiguration EditorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
|
||||||
|
|
||||||
private static readonly List<string> IgnoreDestinations = new List<string>
|
private static readonly List<string> IgnoreDestinations = new()
|
||||||
{
|
{
|
||||||
nameof(WellKnownDestinations.Picker),
|
nameof(WellKnownDestinations.Picker),
|
||||||
EditorDestination.DESIGNATION
|
EditorDestination.DESIGNATION
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly List<IImageEditor> EditorList = new List<IImageEditor>();
|
private static readonly List<IImageEditor> EditorList = new();
|
||||||
|
|
||||||
private Surface _surface;
|
private Surface _surface;
|
||||||
private GreenshotToolStripButton[] _toolbarButtons;
|
private GreenshotToolStripButton[] _toolbarButtons;
|
||||||
|
@ -78,7 +78,7 @@ namespace Greenshot.Editor.Forms
|
||||||
// whether part of the editor controls are disabled depending on selected item(s)
|
// whether part of the editor controls are disabled depending on selected item(s)
|
||||||
private bool _controlsDisabledDueToConfirmable;
|
private bool _controlsDisabledDueToConfirmable;
|
||||||
|
|
||||||
// Used for tracking the mouse scrollwheel changes
|
// Used for tracking the mouse scroll wheel changes
|
||||||
private DateTime _zoomStartTime = DateTime.Now;
|
private DateTime _zoomStartTime = DateTime.Now;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -181,6 +181,20 @@ namespace Greenshot.Editor.Forms
|
||||||
|
|
||||||
UpdateUi();
|
UpdateUi();
|
||||||
|
|
||||||
|
// Use best fit, for those capture modes where we can get huge images
|
||||||
|
bool useBestFit = _surface.CaptureDetails.CaptureMode switch
|
||||||
|
{
|
||||||
|
CaptureMode.File => true,
|
||||||
|
CaptureMode.Clipboard => true,
|
||||||
|
CaptureMode.IE => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (useBestFit)
|
||||||
|
{
|
||||||
|
ZoomBestFitMenuItemClick(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
// Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it.
|
// Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it.
|
||||||
HideToolstripItems();
|
HideToolstripItems();
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1304,7 @@ namespace Greenshot.Editor.Forms
|
||||||
propertiesToolStrip.SuspendLayout();
|
propertiesToolStrip.SuspendLayout();
|
||||||
if (_surface.HasSelectedElements || _surface.DrawingMode != DrawingModes.None)
|
if (_surface.HasSelectedElements || _surface.DrawingMode != DrawingModes.None)
|
||||||
{
|
{
|
||||||
FieldAggregator props = _surface.FieldAggregator;
|
var props = (FieldAggregator)_surface.FieldAggregator;
|
||||||
btnFillColor.Visible = props.HasFieldValue(FieldType.FILL_COLOR);
|
btnFillColor.Visible = props.HasFieldValue(FieldType.FILL_COLOR);
|
||||||
btnLineColor.Visible = props.HasFieldValue(FieldType.LINE_COLOR);
|
btnLineColor.Visible = props.HasFieldValue(FieldType.LINE_COLOR);
|
||||||
lineThicknessLabel.Visible = lineThicknessUpDown.Visible = props.HasFieldValue(FieldType.LINE_THICKNESS);
|
lineThicknessLabel.Visible = lineThicknessUpDown.Visible = props.HasFieldValue(FieldType.LINE_THICKNESS);
|
||||||
|
@ -1350,7 +1364,7 @@ namespace Greenshot.Editor.Forms
|
||||||
btnStepLabel.Image = icon;
|
btnStepLabel.Image = icon;
|
||||||
addCounterToolStripMenuItem.Image = icon;
|
addCounterToolStripMenuItem.Image = icon;
|
||||||
|
|
||||||
FieldAggregator props = _surface.FieldAggregator;
|
FieldAggregator props = (FieldAggregator)_surface.FieldAggregator;
|
||||||
// if a confirmable element is selected, we must disable most of the controls
|
// if a confirmable element is selected, we must disable most of the controls
|
||||||
// since we demand confirmation or cancel for confirmable element
|
// since we demand confirmation or cancel for confirmable element
|
||||||
if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE)
|
if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||||
|
<PropertyGroup>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Languages\language*.xml">
|
<None Include="Languages\language*.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
|
|
@ -20,9 +20,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Memento
|
namespace Greenshot.Editor.Memento
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -31,9 +30,9 @@ namespace Greenshot.Editor.Memento
|
||||||
public class AddElementMemento : IMemento
|
public class AddElementMemento : IMemento
|
||||||
{
|
{
|
||||||
private IDrawableContainer _drawableContainer;
|
private IDrawableContainer _drawableContainer;
|
||||||
private Surface _surface;
|
private ISurface _surface;
|
||||||
|
|
||||||
public AddElementMemento(Surface surface, IDrawableContainer drawableContainer)
|
public AddElementMemento(ISurface surface, IDrawableContainer drawableContainer)
|
||||||
{
|
{
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_drawableContainer = drawableContainer;
|
_drawableContainer = drawableContainer;
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Memento
|
namespace Greenshot.Editor.Memento
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,9 @@ namespace Greenshot.Editor.Memento
|
||||||
public class AddElementsMemento : IMemento
|
public class AddElementsMemento : IMemento
|
||||||
{
|
{
|
||||||
private IDrawableContainerList _containerList;
|
private IDrawableContainerList _containerList;
|
||||||
private Surface _surface;
|
private ISurface _surface;
|
||||||
|
|
||||||
public AddElementsMemento(Surface surface, IDrawableContainerList containerList)
|
public AddElementsMemento(ISurface surface, IDrawableContainerList containerList)
|
||||||
{
|
{
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_containerList = containerList;
|
_containerList = containerList;
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Memento
|
namespace Greenshot.Editor.Memento
|
||||||
{
|
{
|
||||||
|
@ -31,9 +31,9 @@ namespace Greenshot.Editor.Memento
|
||||||
public class DeleteElementMemento : IMemento
|
public class DeleteElementMemento : IMemento
|
||||||
{
|
{
|
||||||
private IDrawableContainer _drawableContainer;
|
private IDrawableContainer _drawableContainer;
|
||||||
private readonly Surface _surface;
|
private readonly ISurface _surface;
|
||||||
|
|
||||||
public DeleteElementMemento(Surface surface, IDrawableContainer drawableContainer)
|
public DeleteElementMemento(ISurface surface, IDrawableContainer drawableContainer)
|
||||||
{
|
{
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_drawableContainer = drawableContainer;
|
_drawableContainer = drawableContainer;
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Memento
|
namespace Greenshot.Editor.Memento
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,9 @@ namespace Greenshot.Editor.Memento
|
||||||
public class DeleteElementsMemento : IMemento
|
public class DeleteElementsMemento : IMemento
|
||||||
{
|
{
|
||||||
private IDrawableContainerList _containerList;
|
private IDrawableContainerList _containerList;
|
||||||
private Surface _surface;
|
private ISurface _surface;
|
||||||
|
|
||||||
public DeleteElementsMemento(Surface surface, IDrawableContainerList containerList)
|
public DeleteElementsMemento(ISurface surface, IDrawableContainerList containerList)
|
||||||
{
|
{
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_containerList = containerList;
|
_containerList = containerList;
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
|
using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Drawing;
|
using Greenshot.Base.Interfaces.Drawing;
|
||||||
using Greenshot.Editor.Drawing;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Memento
|
namespace Greenshot.Editor.Memento
|
||||||
{
|
{
|
||||||
|
@ -32,10 +32,10 @@ namespace Greenshot.Editor.Memento
|
||||||
public class SurfaceBackgroundChangeMemento : IMemento
|
public class SurfaceBackgroundChangeMemento : IMemento
|
||||||
{
|
{
|
||||||
private Image _image;
|
private Image _image;
|
||||||
private Surface _surface;
|
private ISurface _surface;
|
||||||
private Matrix _matrix;
|
private Matrix _matrix;
|
||||||
|
|
||||||
public SurfaceBackgroundChangeMemento(Surface surface, Matrix matrix)
|
public SurfaceBackgroundChangeMemento(ISurface surface, Matrix matrix)
|
||||||
{
|
{
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_image = surface.Image;
|
_image = surface.Image;
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Greenshot.Plugin.Box.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(208, 12);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(208, 12);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(BoxConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Box";
|
this.combobox_uploadimageformat.SectionName = "Box";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(215, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(215, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 5;
|
this.combobox_uploadimageformat.TabIndex = 5;
|
||||||
|
@ -115,7 +115,7 @@ namespace Greenshot.Plugin.Box.Forms {
|
||||||
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "box.label_AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "box.label_AfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(208, 45);
|
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(208, 45);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(BoxConfiguration.AfterUploadLinkToClipBoard);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Box";
|
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Box";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 10;
|
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 10;
|
||||||
|
|
|
@ -54,8 +54,8 @@ namespace Greenshot.Plugin.Confluence
|
||||||
Uri confluenceIconUri = new Uri("/Greenshot.Plugin.Confluence;component/Images/Confluence.ico", UriKind.Relative);
|
Uri confluenceIconUri = new Uri("/Greenshot.Plugin.Confluence;component/Images/Confluence.ico", UriKind.Relative);
|
||||||
using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
|
using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
|
||||||
{
|
{
|
||||||
// TODO: Check what to do with the IImage
|
// TODO: Replace with FileFormatHandler
|
||||||
ConfluenceIcon = ImageHelper.FromStream(iconStream);
|
ConfluenceIcon = ImageIO.FromStream(iconStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Greenshot.Base.Core;
|
|
||||||
using Greenshot.Base.Core.Enums;
|
using Greenshot.Base.Core.Enums;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Plugin.Dropbox.Forms;
|
using Greenshot.Plugin.Dropbox.Forms;
|
||||||
|
@ -29,10 +28,10 @@ using Greenshot.Plugin.Dropbox.Forms;
|
||||||
namespace Greenshot.Plugin.Dropbox
|
namespace Greenshot.Plugin.Dropbox
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of ImgurConfiguration.
|
/// The configuration for Dropbox
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")]
|
[IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")]
|
||||||
public class DropboxPluginConfiguration : IniSection
|
public class DropboxConfiguration : IniSection
|
||||||
{
|
{
|
||||||
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
|
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
|
||||||
public OutputFormat UploadFormat { get; set; }
|
public OutputFormat UploadFormat { get; set; }
|
|
@ -29,7 +29,7 @@ namespace Greenshot.Plugin.Dropbox
|
||||||
{
|
{
|
||||||
internal class DropboxDestination : AbstractDestination
|
internal class DropboxDestination : AbstractDestination
|
||||||
{
|
{
|
||||||
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
private static readonly DropboxConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxConfiguration>();
|
||||||
|
|
||||||
private readonly DropboxPlugin _plugin;
|
private readonly DropboxPlugin _plugin;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Greenshot.Plugin.Dropbox
|
||||||
public class DropboxPlugin : IGreenshotPlugin
|
public class DropboxPlugin : IGreenshotPlugin
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
|
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
|
||||||
private static DropboxPluginConfiguration _config;
|
private static DropboxConfiguration _config;
|
||||||
private ComponentResourceManager _resources;
|
private ComponentResourceManager _resources;
|
||||||
private ToolStripMenuItem _itemPlugInConfig;
|
private ToolStripMenuItem _itemPlugInConfig;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ namespace Greenshot.Plugin.Dropbox
|
||||||
public bool Initialize()
|
public bool Initialize()
|
||||||
{
|
{
|
||||||
// Register configuration (don't need the configuration itself)
|
// Register configuration (don't need the configuration itself)
|
||||||
_config = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
_config = IniConfig.GetIniSection<DropboxConfiguration>();
|
||||||
_resources = new ComponentResourceManager(typeof(DropboxPlugin));
|
_resources = new ComponentResourceManager(typeof(DropboxPlugin));
|
||||||
SimpleServiceProvider.Current.AddService<IDestination>(new DropboxDestination(this));
|
SimpleServiceProvider.Current.AddService<IDestination>(new DropboxDestination(this));
|
||||||
_itemPlugInConfig = new ToolStripMenuItem
|
_itemPlugInConfig = new ToolStripMenuItem
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Greenshot.Plugin.Dropbox
|
||||||
public class DropboxUtils
|
public class DropboxUtils
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
|
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
|
||||||
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
private static readonly DropboxConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxConfiguration>();
|
||||||
|
|
||||||
private DropboxUtils()
|
private DropboxUtils()
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace Greenshot.Plugin.Dropbox.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(116, 9);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(116, 9);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(DropboxConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Dropbox";
|
this.combobox_uploadimageformat.SectionName = "Dropbox";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(309, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(309, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 1;
|
this.combobox_uploadimageformat.TabIndex = 1;
|
||||||
|
@ -112,7 +112,7 @@ namespace Greenshot.Plugin.Dropbox.Forms {
|
||||||
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "dropbox.label_AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "dropbox.label_AfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(116, 37);
|
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(116, 37);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(DropboxConfiguration.AfterUploadLinkToClipBoard);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Dropbox";
|
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Dropbox";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
|
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace Greenshot.Plugin.ExternalCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runInBackground = config.RunInbackground[_presetCommand];
|
bool runInBackground = config.RunInbackground[_presetCommand];
|
||||||
string fullPath = captureDetails.Filename ?? ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
|
string fullPath = captureDetails.Filename ?? ImageIO.SaveNamedTmpFile(surface, captureDetails, outputSettings);
|
||||||
|
|
||||||
string output;
|
string output;
|
||||||
string error;
|
string error;
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(174, 6);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(174, 6);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(FlickrConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Flickr";
|
this.combobox_uploadimageformat.SectionName = "Flickr";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(251, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(251, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 1;
|
this.combobox_uploadimageformat.TabIndex = 1;
|
||||||
|
@ -111,7 +111,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.checkBoxPublic.LanguageKey = "flickr.public";
|
this.checkBoxPublic.LanguageKey = "flickr.public";
|
||||||
this.checkBoxPublic.Location = new System.Drawing.Point(174, 88);
|
this.checkBoxPublic.Location = new System.Drawing.Point(174, 88);
|
||||||
this.checkBoxPublic.Name = "checkBoxPublic";
|
this.checkBoxPublic.Name = "checkBoxPublic";
|
||||||
this.checkBoxPublic.PropertyName = "flickrIsPublic";
|
this.checkBoxPublic.PropertyName = nameof(FlickrConfiguration.IsPublic);
|
||||||
this.checkBoxPublic.SectionName = "Flickr";
|
this.checkBoxPublic.SectionName = "Flickr";
|
||||||
this.checkBoxPublic.Size = new System.Drawing.Size(55, 17);
|
this.checkBoxPublic.Size = new System.Drawing.Size(55, 17);
|
||||||
this.checkBoxPublic.TabIndex = 4;
|
this.checkBoxPublic.TabIndex = 4;
|
||||||
|
@ -122,7 +122,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.checkBoxFamily.LanguageKey = "flickr.family";
|
this.checkBoxFamily.LanguageKey = "flickr.family";
|
||||||
this.checkBoxFamily.Location = new System.Drawing.Point(265, 88);
|
this.checkBoxFamily.Location = new System.Drawing.Point(265, 88);
|
||||||
this.checkBoxFamily.Name = "checkBoxFamily";
|
this.checkBoxFamily.Name = "checkBoxFamily";
|
||||||
this.checkBoxFamily.PropertyName = "flickrIsFamily";
|
this.checkBoxFamily.PropertyName = nameof(FlickrConfiguration.IsFamily);
|
||||||
this.checkBoxFamily.SectionName = "Flickr";
|
this.checkBoxFamily.SectionName = "Flickr";
|
||||||
this.checkBoxFamily.Size = new System.Drawing.Size(55, 17);
|
this.checkBoxFamily.Size = new System.Drawing.Size(55, 17);
|
||||||
this.checkBoxFamily.TabIndex = 5;
|
this.checkBoxFamily.TabIndex = 5;
|
||||||
|
@ -133,7 +133,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.checkBoxFriend.LanguageKey = "flickr.friend";
|
this.checkBoxFriend.LanguageKey = "flickr.friend";
|
||||||
this.checkBoxFriend.Location = new System.Drawing.Point(350, 88);
|
this.checkBoxFriend.Location = new System.Drawing.Point(350, 88);
|
||||||
this.checkBoxFriend.Name = "checkBoxFriend";
|
this.checkBoxFriend.Name = "checkBoxFriend";
|
||||||
this.checkBoxFriend.PropertyName = "flickrIsFriend";
|
this.checkBoxFriend.PropertyName = nameof(FlickrConfiguration.IsFriend);
|
||||||
this.checkBoxFriend.SectionName = "Flickr";
|
this.checkBoxFriend.SectionName = "Flickr";
|
||||||
this.checkBoxFriend.Size = new System.Drawing.Size(55, 17);
|
this.checkBoxFriend.Size = new System.Drawing.Size(55, 17);
|
||||||
this.checkBoxFriend.TabIndex = 6;
|
this.checkBoxFriend.TabIndex = 6;
|
||||||
|
@ -155,7 +155,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.combobox_safetyLevel.FormattingEnabled = true;
|
this.combobox_safetyLevel.FormattingEnabled = true;
|
||||||
this.combobox_safetyLevel.Location = new System.Drawing.Point(174, 33);
|
this.combobox_safetyLevel.Location = new System.Drawing.Point(174, 33);
|
||||||
this.combobox_safetyLevel.Name = "combobox_safetyLevel";
|
this.combobox_safetyLevel.Name = "combobox_safetyLevel";
|
||||||
this.combobox_safetyLevel.PropertyName = "SafetyLevel";
|
this.combobox_safetyLevel.PropertyName = nameof(FlickrConfiguration.SafetyLevel);
|
||||||
this.combobox_safetyLevel.SectionName = "Flickr";
|
this.combobox_safetyLevel.SectionName = "Flickr";
|
||||||
this.combobox_safetyLevel.Size = new System.Drawing.Size(251, 21);
|
this.combobox_safetyLevel.Size = new System.Drawing.Size(251, 21);
|
||||||
this.combobox_safetyLevel.TabIndex = 2;
|
this.combobox_safetyLevel.TabIndex = 2;
|
||||||
|
@ -173,7 +173,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "flickr.label_AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "flickr.label_AfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(173, 116);
|
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(173, 116);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(FlickrConfiguration.AfterUploadLinkToClipBoard);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Flickr";
|
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Flickr";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 7;
|
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 7;
|
||||||
|
@ -184,7 +184,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
||||||
this.checkBox_hiddenfromsearch.LanguageKey = "flickr.label_HiddenFromSearch";
|
this.checkBox_hiddenfromsearch.LanguageKey = "flickr.label_HiddenFromSearch";
|
||||||
this.checkBox_hiddenfromsearch.Location = new System.Drawing.Point(174, 60);
|
this.checkBox_hiddenfromsearch.Location = new System.Drawing.Point(174, 60);
|
||||||
this.checkBox_hiddenfromsearch.Name = "checkBox_hiddenfromsearch";
|
this.checkBox_hiddenfromsearch.Name = "checkBox_hiddenfromsearch";
|
||||||
this.checkBox_hiddenfromsearch.PropertyName = "HiddenFromSearch";
|
this.checkBox_hiddenfromsearch.PropertyName = nameof(FlickrConfiguration.HiddenFromSearch);
|
||||||
this.checkBox_hiddenfromsearch.SectionName = "Flickr";
|
this.checkBox_hiddenfromsearch.SectionName = "Flickr";
|
||||||
this.checkBox_hiddenfromsearch.Size = new System.Drawing.Size(118, 17);
|
this.checkBox_hiddenfromsearch.Size = new System.Drawing.Size(118, 17);
|
||||||
this.checkBox_hiddenfromsearch.TabIndex = 3;
|
this.checkBox_hiddenfromsearch.TabIndex = 3;
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace Greenshot.Plugin.GooglePhotos.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(GooglePhotosConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "GooglePhotos";
|
this.combobox_uploadimageformat.SectionName = "GooglePhotos";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 1;
|
this.combobox_uploadimageformat.TabIndex = 1;
|
||||||
|
@ -114,7 +114,7 @@ namespace Greenshot.Plugin.GooglePhotos.Forms {
|
||||||
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "googlephotos.label_AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "googlephotos.label_AfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50);
|
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
|
this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(GooglePhotosConfiguration.AfterUploadLinkToClipBoard);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.SectionName = "GooglePhotos";
|
this.checkboxAfterUploadLinkToClipBoard.SectionName = "GooglePhotos";
|
||||||
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
|
||||||
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
|
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(168, 7);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(168, 7);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(ImgurConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Imgur";
|
this.combobox_uploadimageformat.SectionName = "Imgur";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(210, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(210, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 1;
|
this.combobox_uploadimageformat.TabIndex = 1;
|
||||||
|
@ -115,7 +115,7 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
||||||
this.checkbox_anonymous_access.LanguageKey = "imgur.anonymous_access";
|
this.checkbox_anonymous_access.LanguageKey = "imgur.anonymous_access";
|
||||||
this.checkbox_anonymous_access.Location = new System.Drawing.Point(15, 38);
|
this.checkbox_anonymous_access.Location = new System.Drawing.Point(15, 38);
|
||||||
this.checkbox_anonymous_access.Name = "checkbox_anonymous_access";
|
this.checkbox_anonymous_access.Name = "checkbox_anonymous_access";
|
||||||
this.checkbox_anonymous_access.PropertyName = "AnonymousAccess";
|
this.checkbox_anonymous_access.PropertyName = nameof(ImgurConfiguration.AnonymousAccess);
|
||||||
this.checkbox_anonymous_access.SectionName = "Imgur";
|
this.checkbox_anonymous_access.SectionName = "Imgur";
|
||||||
this.checkbox_anonymous_access.Size = new System.Drawing.Size(139, 17);
|
this.checkbox_anonymous_access.Size = new System.Drawing.Size(139, 17);
|
||||||
this.checkbox_anonymous_access.TabIndex = 2;
|
this.checkbox_anonymous_access.TabIndex = 2;
|
||||||
|
@ -126,7 +126,7 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
||||||
this.checkbox_usepagelink.LanguageKey = "imgur.use_page_link";
|
this.checkbox_usepagelink.LanguageKey = "imgur.use_page_link";
|
||||||
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 57);
|
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 57);
|
||||||
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
|
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
|
||||||
this.checkbox_usepagelink.PropertyName = "UsePageLink";
|
this.checkbox_usepagelink.PropertyName = nameof(ImgurConfiguration.UsePageLink);
|
||||||
this.checkbox_usepagelink.SectionName = "Imgur";
|
this.checkbox_usepagelink.SectionName = "Imgur";
|
||||||
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
|
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
|
||||||
this.checkbox_usepagelink.TabIndex = 3;
|
this.checkbox_usepagelink.TabIndex = 3;
|
||||||
|
|
|
@ -179,7 +179,7 @@ namespace Greenshot.Plugin.Imgur
|
||||||
{
|
{
|
||||||
using (var requestStream = webRequest.GetRequestStream())
|
using (var requestStream = webRequest.GetRequestStream())
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
ImageIO.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
using WebResponse response = webRequest.GetResponse();
|
using WebResponse response = webRequest.GetResponse();
|
||||||
|
@ -265,7 +265,8 @@ namespace Greenshot.Plugin.Imgur
|
||||||
Stream responseStream = response.GetResponseStream();
|
Stream responseStream = response.GetResponseStream();
|
||||||
if (responseStream != null)
|
if (responseStream != null)
|
||||||
{
|
{
|
||||||
imgurInfo.Image = ImageHelper.FromStream(responseStream);
|
// TODO: Replace with some other code, like the file format handler
|
||||||
|
imgurInfo.Image = ImageIO.FromStream(responseStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ namespace Greenshot.Plugin.Jira.Forms {
|
||||||
this.textBoxUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.textBoxUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.textBoxUrl.Location = new System.Drawing.Point(164, 21);
|
this.textBoxUrl.Location = new System.Drawing.Point(164, 21);
|
||||||
this.textBoxUrl.Name = "textBoxUrl";
|
this.textBoxUrl.Name = "textBoxUrl";
|
||||||
this.textBoxUrl.PropertyName = "Url";
|
this.textBoxUrl.PropertyName = nameof(JiraConfiguration.Url);
|
||||||
this.textBoxUrl.SectionName = "Jira";
|
this.textBoxUrl.SectionName = "Jira";
|
||||||
this.textBoxUrl.Size = new System.Drawing.Size(214, 20);
|
this.textBoxUrl.Size = new System.Drawing.Size(214, 20);
|
||||||
this.textBoxUrl.TabIndex = 6;
|
this.textBoxUrl.TabIndex = 6;
|
||||||
|
@ -105,7 +105,7 @@ namespace Greenshot.Plugin.Jira.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(164, 47);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(164, 47);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(JiraConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Jira";
|
this.combobox_uploadimageformat.SectionName = "Jira";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(214, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(214, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 8;
|
this.combobox_uploadimageformat.TabIndex = 8;
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace Greenshot.Plugin.Office.Destinations
|
||||||
string imageFile = captureDetails.Filename;
|
string imageFile = captureDetails.Filename;
|
||||||
if (imageFile == null || surface.Modified || !Regex.IsMatch(imageFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
if (imageFile == null || surface.Modified || !Regex.IsMatch(imageFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
||||||
{
|
{
|
||||||
imageFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
imageFile = ImageIO.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
||||||
createdFile = true;
|
createdFile = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ namespace Greenshot.Plugin.Office.Destinations
|
||||||
// Cleanup imageFile if we created it here, so less tmp-files are generated and left
|
// Cleanup imageFile if we created it here, so less tmp-files are generated and left
|
||||||
if (createdFile)
|
if (createdFile)
|
||||||
{
|
{
|
||||||
ImageOutput.DeleteNamedTmpFile(imageFile);
|
ImageIO.DeleteNamedTmpFile(imageFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return exportInformation;
|
return exportInformation;
|
||||||
|
|
|
@ -160,7 +160,7 @@ namespace Greenshot.Plugin.Office.Destinations
|
||||||
string tmpFile = captureDetails.Filename;
|
string tmpFile = captureDetails.Filename;
|
||||||
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
||||||
{
|
{
|
||||||
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
tmpFile = ImageIO.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace Greenshot.Plugin.Office.Destinations
|
||||||
Size imageSize = Size.Empty;
|
Size imageSize = Size.Empty;
|
||||||
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
||||||
{
|
{
|
||||||
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
tmpFile = ImageIO.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
||||||
imageSize = surface.Image.Size;
|
imageSize = surface.Image.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace Greenshot.Plugin.Office.Destinations
|
||||||
string tmpFile = captureDetails.Filename;
|
string tmpFile = captureDetails.Filename;
|
||||||
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
|
||||||
{
|
{
|
||||||
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
tmpFile = ImageIO.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_documentCaption != null)
|
if (_documentCaption != null)
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
||||||
|
|
||||||
using var pngStream = new MemoryStream();
|
using var pngStream = new MemoryStream();
|
||||||
var pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
var pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
||||||
ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
|
ImageIO.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
|
||||||
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
|
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
|
||||||
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height);
|
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height);
|
||||||
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
|
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace Greenshot.Plugin.Photobucket.Forms {
|
||||||
this.combobox_uploadimageformat.FormattingEnabled = true;
|
this.combobox_uploadimageformat.FormattingEnabled = true;
|
||||||
this.combobox_uploadimageformat.Location = new System.Drawing.Point(102, 11);
|
this.combobox_uploadimageformat.Location = new System.Drawing.Point(102, 11);
|
||||||
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
|
||||||
this.combobox_uploadimageformat.PropertyName = "UploadFormat";
|
this.combobox_uploadimageformat.PropertyName = nameof(PhotobucketConfiguration.UploadFormat);
|
||||||
this.combobox_uploadimageformat.SectionName = "Photobucket";
|
this.combobox_uploadimageformat.SectionName = "Photobucket";
|
||||||
this.combobox_uploadimageformat.Size = new System.Drawing.Size(276, 21);
|
this.combobox_uploadimageformat.Size = new System.Drawing.Size(276, 21);
|
||||||
this.combobox_uploadimageformat.TabIndex = 1;
|
this.combobox_uploadimageformat.TabIndex = 1;
|
||||||
|
@ -102,7 +102,7 @@ namespace Greenshot.Plugin.Photobucket.Forms {
|
||||||
this.checkbox_usepagelink.LanguageKey = "photobucket.use_page_link";
|
this.checkbox_usepagelink.LanguageKey = "photobucket.use_page_link";
|
||||||
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 43);
|
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 43);
|
||||||
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
|
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
|
||||||
this.checkbox_usepagelink.PropertyName = "UsePageLink";
|
this.checkbox_usepagelink.PropertyName = nameof(PhotobucketConfiguration.UsePageLink);
|
||||||
this.checkbox_usepagelink.SectionName = "Photobucket";
|
this.checkbox_usepagelink.SectionName = "Photobucket";
|
||||||
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
|
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
|
||||||
this.checkbox_usepagelink.TabIndex = 2;
|
this.checkbox_usepagelink.TabIndex = 2;
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace Greenshot.Plugin.Win10.Destinations
|
||||||
outputSettings.PreventGreenshotFormat();
|
outputSettings.PreventGreenshotFormat();
|
||||||
|
|
||||||
// Create capture for export
|
// Create capture for export
|
||||||
ImageOutput.SaveToStream(surface, imageStream, outputSettings);
|
ImageIO.SaveToStream(surface, imageStream, outputSettings);
|
||||||
imageStream.Position = 0;
|
imageStream.Position = 0;
|
||||||
Log.Debug("Created RandomAccessStreamReference for the image");
|
Log.Debug("Created RandomAccessStreamReference for the image");
|
||||||
var imageRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(imageStream);
|
var imageRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(imageStream);
|
||||||
|
@ -161,7 +161,7 @@ namespace Greenshot.Plugin.Win10.Destinations
|
||||||
using (var tmpImageForThumbnail = surface.GetImageForExport())
|
using (var tmpImageForThumbnail = surface.GetImageForExport())
|
||||||
using (var thumbnail = ImageHelper.CreateThumbnail(tmpImageForThumbnail, 240, 160))
|
using (var thumbnail = ImageHelper.CreateThumbnail(tmpImageForThumbnail, 240, 160))
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(thumbnail, null, thumbnailStream, outputSettings);
|
ImageIO.SaveToStream(thumbnail, null, thumbnailStream, outputSettings);
|
||||||
thumbnailStream.Position = 0;
|
thumbnailStream.Position = 0;
|
||||||
thumbnailRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(thumbnailStream);
|
thumbnailRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(thumbnailStream);
|
||||||
Log.Debug("Created RandomAccessStreamReference for the thumbnail");
|
Log.Debug("Created RandomAccessStreamReference for the thumbnail");
|
||||||
|
@ -172,7 +172,7 @@ namespace Greenshot.Plugin.Win10.Destinations
|
||||||
using (var logo = GreenshotResources.GetGreenshotIcon().ToBitmap())
|
using (var logo = GreenshotResources.GetGreenshotIcon().ToBitmap())
|
||||||
using (var logoThumbnail = ImageHelper.CreateThumbnail(logo, 30, 30))
|
using (var logoThumbnail = ImageHelper.CreateThumbnail(logo, 30, 30))
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(logoThumbnail, null, logoStream, outputSettings);
|
ImageIO.SaveToStream(logoThumbnail, null, logoStream, outputSettings);
|
||||||
logoStream.Position = 0;
|
logoStream.Position = 0;
|
||||||
logoRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(logoStream);
|
logoRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(logoStream);
|
||||||
Log.Info("Created RandomAccessStreamReference for the logo");
|
Log.Info("Created RandomAccessStreamReference for the logo");
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace Greenshot.Plugin.Win10
|
||||||
IEffect effect = new ResizeCanvasEffect(addedWidth, addedWidth, addedHeight, addedHeight);
|
IEffect effect = new ResizeCanvasEffect(addedWidth, addedWidth, addedHeight, addedHeight);
|
||||||
outputSettings.Effects.Add(effect);
|
outputSettings.Effects.Add(effect);
|
||||||
}
|
}
|
||||||
ImageOutput.SaveToStream(surface, imageStream, outputSettings);
|
ImageIO.SaveToStream(surface, imageStream, outputSettings);
|
||||||
imageStream.Position = 0;
|
imageStream.Position = 0;
|
||||||
var randomAccessStream = imageStream.AsRandomAccessStream();
|
var randomAccessStream = imageStream.AsRandomAccessStream();
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ namespace Greenshot.Plugin.Win10
|
||||||
OcrInformation result;
|
OcrInformation result;
|
||||||
using (var imageStream = new MemoryStream())
|
using (var imageStream = new MemoryStream())
|
||||||
{
|
{
|
||||||
ImageOutput.SaveToStream(image, null, imageStream, new SurfaceOutputSettings());
|
ImageIO.SaveToStream(image, null, imageStream, new SurfaceOutputSettings());
|
||||||
imageStream.Position = 0;
|
imageStream.Position = 0;
|
||||||
var randomAccessStream = imageStream.AsRandomAccessStream();
|
var randomAccessStream = imageStream.AsRandomAccessStream();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<!--<system.windows.forms jitDebugging="true" />-->
|
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||||
</startup>
|
</startup>
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Greenshot.Destinations
|
||||||
overwrite = true;
|
overwrite = true;
|
||||||
Log.InfoFormat("Using previous filename");
|
Log.InfoFormat("Using previous filename");
|
||||||
fullPath = captureDetails.Filename;
|
fullPath = captureDetails.Filename;
|
||||||
outputSettings.Format = ImageOutput.FormatForFilename(fullPath);
|
outputSettings.Format = ImageIO.FormatForFilename(fullPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ namespace Greenshot.Destinations
|
||||||
// This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642
|
// This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ImageOutput.Save(surface, fullPath, overwrite, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
|
ImageIO.Save(surface, fullPath, overwrite, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
|
||||||
outputMade = true;
|
outputMade = true;
|
||||||
}
|
}
|
||||||
catch (ArgumentException ex1)
|
catch (ArgumentException ex1)
|
||||||
|
@ -95,7 +95,7 @@ namespace Greenshot.Destinations
|
||||||
// Our generated filename exists, display 'save-as'
|
// Our generated filename exists, display 'save-as'
|
||||||
Log.InfoFormat("Not overwriting: {0}", ex1.Message);
|
Log.InfoFormat("Not overwriting: {0}", ex1.Message);
|
||||||
// when we don't allow to overwrite present a new SaveWithDialog
|
// when we don't allow to overwrite present a new SaveWithDialog
|
||||||
fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
|
fullPath = ImageIO.SaveWithDialog(surface, captureDetails);
|
||||||
outputMade = fullPath != null;
|
outputMade = fullPath != null;
|
||||||
}
|
}
|
||||||
catch (Exception ex2)
|
catch (Exception ex2)
|
||||||
|
@ -104,7 +104,7 @@ namespace Greenshot.Destinations
|
||||||
// Show the problem
|
// Show the problem
|
||||||
MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error));
|
MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error));
|
||||||
// when save failed we present a SaveWithDialog
|
// when save failed we present a SaveWithDialog
|
||||||
fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
|
fullPath = ImageIO.SaveWithDialog(surface, captureDetails);
|
||||||
outputMade = fullPath != null;
|
outputMade = fullPath != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Greenshot.Destinations
|
||||||
{
|
{
|
||||||
ExportInformation exportInformation = new ExportInformation(Designation, Description);
|
ExportInformation exportInformation = new ExportInformation(Designation, Description);
|
||||||
// Bug #2918756 don't overwrite path if SaveWithDialog returns null!
|
// Bug #2918756 don't overwrite path if SaveWithDialog returns null!
|
||||||
var savedTo = ImageOutput.SaveWithDialog(surface, captureDetails);
|
var savedTo = ImageIO.SaveWithDialog(surface, captureDetails);
|
||||||
if (savedTo != null)
|
if (savedTo != null)
|
||||||
{
|
{
|
||||||
exportInformation.ExportMade = true;
|
exportInformation.ExportMade = true;
|
||||||
|
|
|
@ -36,6 +36,7 @@ using Greenshot.Base;
|
||||||
using Greenshot.Base.Controls;
|
using Greenshot.Base.Controls;
|
||||||
using Greenshot.Base.Core;
|
using Greenshot.Base.Core;
|
||||||
using Greenshot.Base.Core.Enums;
|
using Greenshot.Base.Core.Enums;
|
||||||
|
using Greenshot.Base.Core.FileFormatHandlers;
|
||||||
using Greenshot.Base.Help;
|
using Greenshot.Base.Help;
|
||||||
using Greenshot.Base.IniFile;
|
using Greenshot.Base.IniFile;
|
||||||
using Greenshot.Base.Interfaces;
|
using Greenshot.Base.Interfaces;
|
||||||
|
@ -43,6 +44,7 @@ using Greenshot.Base.Interfaces.Plugin;
|
||||||
using Greenshot.Base.UnmanagedHelpers;
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
using Greenshot.Configuration;
|
using Greenshot.Configuration;
|
||||||
using Greenshot.Destinations;
|
using Greenshot.Destinations;
|
||||||
|
using Greenshot.Editor;
|
||||||
using Greenshot.Editor.Destinations;
|
using Greenshot.Editor.Destinations;
|
||||||
using Greenshot.Editor.Drawing;
|
using Greenshot.Editor.Drawing;
|
||||||
using Greenshot.Editor.Forms;
|
using Greenshot.Editor.Forms;
|
||||||
|
@ -162,7 +164,7 @@ namespace Greenshot.Forms
|
||||||
|
|
||||||
if (argument.ToLower().Equals("/exit"))
|
if (argument.ToLower().Equals("/exit"))
|
||||||
{
|
{
|
||||||
// unregister application on uninstall (allow uninstall)
|
// un-register application on uninstall (allow uninstall)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOG.Info("Sending all instances the exit command.");
|
LOG.Info("Sending all instances the exit command.");
|
||||||
|
@ -387,6 +389,8 @@ namespace Greenshot.Forms
|
||||||
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
|
||||||
|
EditorInitialize.Initialize();
|
||||||
|
|
||||||
// Factory for surface objects
|
// Factory for surface objects
|
||||||
ISurface SurfaceFactory() => new Surface();
|
ISurface SurfaceFactory() => new Surface();
|
||||||
|
|
||||||
|
@ -923,10 +927,10 @@ namespace Greenshot.Forms
|
||||||
Hide();
|
Hide();
|
||||||
ShowInTaskbar = false;
|
ShowInTaskbar = false;
|
||||||
|
|
||||||
|
// TODO: Do we really need this?
|
||||||
using var loProcess = Process.GetCurrentProcess();
|
//using var loProcess = Process.GetCurrentProcess();
|
||||||
loProcess.MaxWorkingSet = (IntPtr)750000;
|
//loProcess.MaxWorkingSet = (IntPtr)750000;
|
||||||
loProcess.MinWorkingSet = (IntPtr)300000;
|
//loProcess.MinWorkingSet = (IntPtr)300000;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CaptureRegion()
|
private void CaptureRegion()
|
||||||
|
@ -936,9 +940,12 @@ namespace Greenshot.Forms
|
||||||
|
|
||||||
private void CaptureFile(IDestination destination = null)
|
private void CaptureFile(IDestination destination = null)
|
||||||
{
|
{
|
||||||
|
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
|
||||||
|
var extensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).Select(e => $"*{e}").ToList();
|
||||||
|
|
||||||
var openFileDialog = new OpenFileDialog
|
var openFileDialog = new OpenFileDialog
|
||||||
{
|
{
|
||||||
Filter = @"Image files (*.greenshot, *.png, *.jpg, *.gif, *.bmp, *.ico, *.tiff, *.wmf)|*.greenshot; *.png; *.jpg; *.jpeg; *.gif; *.bmp; *.ico; *.tiff; *.tif; *.wmf"
|
Filter = @$"Image files ({string.Join(", ", extensions)})|{string.Join("; ", extensions)}"
|
||||||
};
|
};
|
||||||
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
||||||
{
|
{
|
||||||
|
@ -1904,7 +1911,7 @@ namespace Greenshot.Forms
|
||||||
LOG.Error("Error closing application!", e);
|
LOG.Error("Error closing application!", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageOutput.RemoveTmpFiles();
|
ImageIO.RemoveTmpFiles();
|
||||||
|
|
||||||
// Store any open configuration changes
|
// Store any open configuration changes
|
||||||
try
|
try
|
||||||
|
|
17
src/Greenshot/Forms/PrintOptionsDialog.Designer.cs
generated
17
src/Greenshot/Forms/PrintOptionsDialog.Designer.cs
generated
|
@ -89,7 +89,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
|
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
|
||||||
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
|
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
|
||||||
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
|
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
|
||||||
this.checkboxAllowShrink.PropertyName = "OutputPrintAllowShrink";
|
this.checkboxAllowShrink.PropertyName = nameof(coreConfiguration.OutputPrintAllowShrink);
|
||||||
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
|
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
|
||||||
this.checkboxAllowShrink.TabIndex = 2;
|
this.checkboxAllowShrink.TabIndex = 2;
|
||||||
this.checkboxAllowShrink.Text = "Shrink printout to fit paper size";
|
this.checkboxAllowShrink.Text = "Shrink printout to fit paper size";
|
||||||
|
@ -103,7 +103,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
|
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
|
||||||
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
|
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
|
||||||
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
|
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
|
||||||
this.checkboxAllowEnlarge.PropertyName = "OutputPrintAllowEnlarge";
|
this.checkboxAllowEnlarge.PropertyName = nameof(coreConfiguration.OutputPrintAllowEnlarge);
|
||||||
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
|
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
|
||||||
this.checkboxAllowEnlarge.TabIndex = 3;
|
this.checkboxAllowEnlarge.TabIndex = 3;
|
||||||
this.checkboxAllowEnlarge.Text = "Enlarge printout to fit paper size";
|
this.checkboxAllowEnlarge.Text = "Enlarge printout to fit paper size";
|
||||||
|
@ -117,7 +117,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
|
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
|
||||||
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
|
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
|
||||||
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
|
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
|
||||||
this.checkboxAllowCenter.PropertyName = "OutputPrintCenter";
|
this.checkboxAllowCenter.PropertyName = nameof(coreConfiguration.OutputPrintCenter);
|
||||||
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
|
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
|
||||||
this.checkboxAllowCenter.TabIndex = 5;
|
this.checkboxAllowCenter.TabIndex = 5;
|
||||||
this.checkboxAllowCenter.Text = "Center printout on page";
|
this.checkboxAllowCenter.Text = "Center printout on page";
|
||||||
|
@ -131,7 +131,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
|
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
|
||||||
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
|
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
|
||||||
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
|
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
|
||||||
this.checkboxAllowRotate.PropertyName = "OutputPrintAllowRotate";
|
this.checkboxAllowRotate.PropertyName = nameof(coreConfiguration.OutputPrintAllowRotate);
|
||||||
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
|
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
|
||||||
this.checkboxAllowRotate.TabIndex = 4;
|
this.checkboxAllowRotate.TabIndex = 4;
|
||||||
this.checkboxAllowRotate.Text = "Rotate printout to page orientation";
|
this.checkboxAllowRotate.Text = "Rotate printout to page orientation";
|
||||||
|
@ -158,7 +158,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
|
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
|
||||||
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
|
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
|
||||||
this.checkboxDateTime.Name = "checkboxDateTime";
|
this.checkboxDateTime.Name = "checkboxDateTime";
|
||||||
this.checkboxDateTime.PropertyName = "OutputPrintFooter";
|
this.checkboxDateTime.PropertyName = nameof(coreConfiguration.OutputPrintFooter);
|
||||||
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
|
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
|
||||||
this.checkboxDateTime.TabIndex = 6;
|
this.checkboxDateTime.TabIndex = 6;
|
||||||
this.checkboxDateTime.Text = "Print date / time at bottom of page";
|
this.checkboxDateTime.Text = "Print date / time at bottom of page";
|
||||||
|
@ -184,7 +184,7 @@ namespace Greenshot.Forms
|
||||||
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
|
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
|
||||||
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
|
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
|
||||||
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
|
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
|
||||||
this.checkboxPrintInverted.PropertyName = "OutputPrintInverted";
|
this.checkboxPrintInverted.PropertyName = nameof(coreConfiguration.OutputPrintInverted);
|
||||||
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
|
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
|
||||||
this.checkboxPrintInverted.TabIndex = 14;
|
this.checkboxPrintInverted.TabIndex = 14;
|
||||||
this.checkboxPrintInverted.Text = "Print with inverted colors";
|
this.checkboxPrintInverted.Text = "Print with inverted colors";
|
||||||
|
@ -198,7 +198,7 @@ namespace Greenshot.Forms
|
||||||
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
|
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
|
||||||
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
|
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
|
||||||
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
|
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
|
||||||
this.radioBtnGrayScale.PropertyName = "OutputPrintGrayscale";
|
this.radioBtnGrayScale.PropertyName = nameof(coreConfiguration.OutputPrintGrayscale);
|
||||||
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
|
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
|
||||||
this.radioBtnGrayScale.TabIndex = 12;
|
this.radioBtnGrayScale.TabIndex = 12;
|
||||||
this.radioBtnGrayScale.Text = "Force grayscale printing";
|
this.radioBtnGrayScale.Text = "Force grayscale printing";
|
||||||
|
@ -212,7 +212,7 @@ namespace Greenshot.Forms
|
||||||
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
|
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
|
||||||
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
|
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
|
||||||
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
|
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
|
||||||
this.radioBtnMonochrome.PropertyName = "OutputPrintMonochrome";
|
this.radioBtnMonochrome.PropertyName = nameof(coreConfiguration.OutputPrintMonochrome);
|
||||||
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
|
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
|
||||||
this.radioBtnMonochrome.TabIndex = 13;
|
this.radioBtnMonochrome.TabIndex = 13;
|
||||||
this.radioBtnMonochrome.Text = "Force black/white printing";
|
this.radioBtnMonochrome.Text = "Force black/white printing";
|
||||||
|
@ -255,7 +255,6 @@ namespace Greenshot.Forms
|
||||||
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
|
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
|
||||||
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
|
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
|
||||||
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
|
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
|
||||||
this.radioBtnColorPrint.PropertyName = "OutputPrintColor";
|
|
||||||
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
|
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
|
||||||
this.radioBtnColorPrint.TabIndex = 11;
|
this.radioBtnColorPrint.TabIndex = 11;
|
||||||
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
|
77
src/Greenshot/Forms/SettingsForm.Designer.cs
generated
77
src/Greenshot/Forms/SettingsForm.Designer.cs
generated
|
@ -20,6 +20,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Greenshot.Base.Controls;
|
using Greenshot.Base.Controls;
|
||||||
|
using Greenshot.Base.Core;
|
||||||
|
using Greenshot.Editor.Configuration;
|
||||||
using Greenshot.Editor.Controls;
|
using Greenshot.Editor.Controls;
|
||||||
|
|
||||||
namespace Greenshot.Forms {
|
namespace Greenshot.Forms {
|
||||||
|
@ -235,7 +237,7 @@ namespace Greenshot.Forms {
|
||||||
//
|
//
|
||||||
this.textbox_screenshotname.Location = new System.Drawing.Point(138, 41);
|
this.textbox_screenshotname.Location = new System.Drawing.Point(138, 41);
|
||||||
this.textbox_screenshotname.Name = "textbox_screenshotname";
|
this.textbox_screenshotname.Name = "textbox_screenshotname";
|
||||||
this.textbox_screenshotname.PropertyName = "OutputFileFilenamePattern";
|
this.textbox_screenshotname.PropertyName = nameof(CoreConfiguration.OutputFileFilenamePattern);
|
||||||
this.textbox_screenshotname.Size = new System.Drawing.Size(233, 20);
|
this.textbox_screenshotname.Size = new System.Drawing.Size(233, 20);
|
||||||
this.textbox_screenshotname.TabIndex = 3;
|
this.textbox_screenshotname.TabIndex = 3;
|
||||||
this.textbox_screenshotname.TextChanged += new System.EventHandler(this.FilenamePatternChanged);
|
this.textbox_screenshotname.TextChanged += new System.EventHandler(this.FilenamePatternChanged);
|
||||||
|
@ -264,7 +266,7 @@ namespace Greenshot.Forms {
|
||||||
this.combobox_primaryimageformat.FormattingEnabled = true;
|
this.combobox_primaryimageformat.FormattingEnabled = true;
|
||||||
this.combobox_primaryimageformat.Location = new System.Drawing.Point(138, 64);
|
this.combobox_primaryimageformat.Location = new System.Drawing.Point(138, 64);
|
||||||
this.combobox_primaryimageformat.Name = "combobox_primaryimageformat";
|
this.combobox_primaryimageformat.Name = "combobox_primaryimageformat";
|
||||||
this.combobox_primaryimageformat.PropertyName = "OutputFileFormat";
|
this.combobox_primaryimageformat.PropertyName = nameof(CoreConfiguration.OutputFileFormat);
|
||||||
this.combobox_primaryimageformat.Size = new System.Drawing.Size(268, 21);
|
this.combobox_primaryimageformat.Size = new System.Drawing.Size(268, 21);
|
||||||
this.combobox_primaryimageformat.TabIndex = 5;
|
this.combobox_primaryimageformat.TabIndex = 5;
|
||||||
//
|
//
|
||||||
|
@ -309,7 +311,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_copypathtoclipboard.LanguageKey = "settings_copypathtoclipboard";
|
this.checkbox_copypathtoclipboard.LanguageKey = "settings_copypathtoclipboard";
|
||||||
this.checkbox_copypathtoclipboard.Location = new System.Drawing.Point(12, 89);
|
this.checkbox_copypathtoclipboard.Location = new System.Drawing.Point(12, 89);
|
||||||
this.checkbox_copypathtoclipboard.Name = "checkbox_copypathtoclipboard";
|
this.checkbox_copypathtoclipboard.Name = "checkbox_copypathtoclipboard";
|
||||||
this.checkbox_copypathtoclipboard.PropertyName = "OutputFileCopyPathToClipboard";
|
this.checkbox_copypathtoclipboard.PropertyName = nameof(CoreConfiguration.OutputFileCopyPathToClipboard);
|
||||||
this.checkbox_copypathtoclipboard.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_copypathtoclipboard.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_copypathtoclipboard.TabIndex = 6;
|
this.checkbox_copypathtoclipboard.TabIndex = 6;
|
||||||
this.checkbox_copypathtoclipboard.UseVisualStyleBackColor = true;
|
this.checkbox_copypathtoclipboard.UseVisualStyleBackColor = true;
|
||||||
|
@ -374,7 +376,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_reducecolors.LanguageKey = "settings_reducecolors";
|
this.checkbox_reducecolors.LanguageKey = "settings_reducecolors";
|
||||||
this.checkbox_reducecolors.Location = new System.Drawing.Point(12, 72);
|
this.checkbox_reducecolors.Location = new System.Drawing.Point(12, 72);
|
||||||
this.checkbox_reducecolors.Name = "checkbox_reducecolors";
|
this.checkbox_reducecolors.Name = "checkbox_reducecolors";
|
||||||
this.checkbox_reducecolors.PropertyName = "OutputFileReduceColors";
|
this.checkbox_reducecolors.PropertyName = nameof(CoreConfiguration.OutputFileReduceColors);
|
||||||
this.checkbox_reducecolors.Size = new System.Drawing.Size(394, 25);
|
this.checkbox_reducecolors.Size = new System.Drawing.Size(394, 25);
|
||||||
this.checkbox_reducecolors.TabIndex = 10;
|
this.checkbox_reducecolors.TabIndex = 10;
|
||||||
this.checkbox_reducecolors.UseVisualStyleBackColor = true;
|
this.checkbox_reducecolors.UseVisualStyleBackColor = true;
|
||||||
|
@ -384,7 +386,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_alwaysshowqualitydialog.LanguageKey = "settings_alwaysshowqualitydialog";
|
this.checkbox_alwaysshowqualitydialog.LanguageKey = "settings_alwaysshowqualitydialog";
|
||||||
this.checkbox_alwaysshowqualitydialog.Location = new System.Drawing.Point(12, 50);
|
this.checkbox_alwaysshowqualitydialog.Location = new System.Drawing.Point(12, 50);
|
||||||
this.checkbox_alwaysshowqualitydialog.Name = "checkbox_alwaysshowqualitydialog";
|
this.checkbox_alwaysshowqualitydialog.Name = "checkbox_alwaysshowqualitydialog";
|
||||||
this.checkbox_alwaysshowqualitydialog.PropertyName = "OutputFilePromptQuality";
|
this.checkbox_alwaysshowqualitydialog.PropertyName = nameof(CoreConfiguration.OutputFilePromptQuality);
|
||||||
this.checkbox_alwaysshowqualitydialog.Size = new System.Drawing.Size(394, 25);
|
this.checkbox_alwaysshowqualitydialog.Size = new System.Drawing.Size(394, 25);
|
||||||
this.checkbox_alwaysshowqualitydialog.TabIndex = 9;
|
this.checkbox_alwaysshowqualitydialog.TabIndex = 9;
|
||||||
this.checkbox_alwaysshowqualitydialog.UseVisualStyleBackColor = true;
|
this.checkbox_alwaysshowqualitydialog.UseVisualStyleBackColor = true;
|
||||||
|
@ -526,7 +528,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_usedefaultproxy.LanguageKey = "settings_usedefaultproxy";
|
this.checkbox_usedefaultproxy.LanguageKey = "settings_usedefaultproxy";
|
||||||
this.checkbox_usedefaultproxy.Location = new System.Drawing.Point(7, 11);
|
this.checkbox_usedefaultproxy.Location = new System.Drawing.Point(7, 11);
|
||||||
this.checkbox_usedefaultproxy.Name = "checkbox_usedefaultproxy";
|
this.checkbox_usedefaultproxy.Name = "checkbox_usedefaultproxy";
|
||||||
this.checkbox_usedefaultproxy.PropertyName = "UseProxy";
|
this.checkbox_usedefaultproxy.PropertyName = nameof(CoreConfiguration.UseProxy);
|
||||||
this.checkbox_usedefaultproxy.Size = new System.Drawing.Size(397, 25);
|
this.checkbox_usedefaultproxy.Size = new System.Drawing.Size(397, 25);
|
||||||
this.checkbox_usedefaultproxy.TabIndex = 7;
|
this.checkbox_usedefaultproxy.TabIndex = 7;
|
||||||
this.checkbox_usedefaultproxy.UseVisualStyleBackColor = true;
|
this.checkbox_usedefaultproxy.UseVisualStyleBackColor = true;
|
||||||
|
@ -564,7 +566,7 @@ namespace Greenshot.Forms {
|
||||||
this.lastregion_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
this.lastregion_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
||||||
this.lastregion_hotkeyControl.Location = new System.Drawing.Point(224, 94);
|
this.lastregion_hotkeyControl.Location = new System.Drawing.Point(224, 94);
|
||||||
this.lastregion_hotkeyControl.Name = "lastregion_hotkeyControl";
|
this.lastregion_hotkeyControl.Name = "lastregion_hotkeyControl";
|
||||||
this.lastregion_hotkeyControl.PropertyName = "LastregionHotkey";
|
this.lastregion_hotkeyControl.PropertyName = nameof(CoreConfiguration.LastregionHotkey);
|
||||||
this.lastregion_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
this.lastregion_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
||||||
this.lastregion_hotkeyControl.TabIndex = 5;
|
this.lastregion_hotkeyControl.TabIndex = 5;
|
||||||
//
|
//
|
||||||
|
@ -582,7 +584,7 @@ namespace Greenshot.Forms {
|
||||||
this.ie_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
this.ie_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
||||||
this.ie_hotkeyControl.Location = new System.Drawing.Point(224, 120);
|
this.ie_hotkeyControl.Location = new System.Drawing.Point(224, 120);
|
||||||
this.ie_hotkeyControl.Name = "ie_hotkeyControl";
|
this.ie_hotkeyControl.Name = "ie_hotkeyControl";
|
||||||
this.ie_hotkeyControl.PropertyName = "IEHotkey";
|
this.ie_hotkeyControl.PropertyName = nameof(CoreConfiguration.IEHotkey);
|
||||||
this.ie_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
this.ie_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
||||||
this.ie_hotkeyControl.TabIndex = 6;
|
this.ie_hotkeyControl.TabIndex = 6;
|
||||||
//
|
//
|
||||||
|
@ -616,7 +618,7 @@ namespace Greenshot.Forms {
|
||||||
this.region_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
this.region_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
||||||
this.region_hotkeyControl.Location = new System.Drawing.Point(224, 68);
|
this.region_hotkeyControl.Location = new System.Drawing.Point(224, 68);
|
||||||
this.region_hotkeyControl.Name = "region_hotkeyControl";
|
this.region_hotkeyControl.Name = "region_hotkeyControl";
|
||||||
this.region_hotkeyControl.PropertyName = "RegionHotkey";
|
this.region_hotkeyControl.PropertyName = nameof(CoreConfiguration.RegionHotkey);
|
||||||
this.region_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
this.region_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
||||||
this.region_hotkeyControl.TabIndex = 4;
|
this.region_hotkeyControl.TabIndex = 4;
|
||||||
//
|
//
|
||||||
|
@ -626,7 +628,7 @@ namespace Greenshot.Forms {
|
||||||
this.window_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
this.window_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
||||||
this.window_hotkeyControl.Location = new System.Drawing.Point(224, 42);
|
this.window_hotkeyControl.Location = new System.Drawing.Point(224, 42);
|
||||||
this.window_hotkeyControl.Name = "window_hotkeyControl";
|
this.window_hotkeyControl.Name = "window_hotkeyControl";
|
||||||
this.window_hotkeyControl.PropertyName = "WindowHotkey";
|
this.window_hotkeyControl.PropertyName = nameof(CoreConfiguration.WindowHotkey);
|
||||||
this.window_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
this.window_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
||||||
this.window_hotkeyControl.TabIndex = 3;
|
this.window_hotkeyControl.TabIndex = 3;
|
||||||
//
|
//
|
||||||
|
@ -636,7 +638,7 @@ namespace Greenshot.Forms {
|
||||||
this.fullscreen_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
this.fullscreen_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
|
||||||
this.fullscreen_hotkeyControl.Location = new System.Drawing.Point(224, 16);
|
this.fullscreen_hotkeyControl.Location = new System.Drawing.Point(224, 16);
|
||||||
this.fullscreen_hotkeyControl.Name = "fullscreen_hotkeyControl";
|
this.fullscreen_hotkeyControl.Name = "fullscreen_hotkeyControl";
|
||||||
this.fullscreen_hotkeyControl.PropertyName = "FullscreenHotkey";
|
this.fullscreen_hotkeyControl.PropertyName = nameof(CoreConfiguration.FullscreenHotkey);
|
||||||
this.fullscreen_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
this.fullscreen_hotkeyControl.Size = new System.Drawing.Size(179, 20);
|
||||||
this.fullscreen_hotkeyControl.TabIndex = 2;
|
this.fullscreen_hotkeyControl.TabIndex = 2;
|
||||||
//
|
//
|
||||||
|
@ -668,7 +670,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_editor_match_capture_size.LanguageKey = "editor_match_capture_size";
|
this.checkbox_editor_match_capture_size.LanguageKey = "editor_match_capture_size";
|
||||||
this.checkbox_editor_match_capture_size.Location = new System.Drawing.Point(6, 19);
|
this.checkbox_editor_match_capture_size.Location = new System.Drawing.Point(6, 19);
|
||||||
this.checkbox_editor_match_capture_size.Name = "checkbox_editor_match_capture_size";
|
this.checkbox_editor_match_capture_size.Name = "checkbox_editor_match_capture_size";
|
||||||
this.checkbox_editor_match_capture_size.PropertyName = "MatchSizeToCapture";
|
this.checkbox_editor_match_capture_size.PropertyName = nameof(EditorConfiguration.MatchSizeToCapture);
|
||||||
this.checkbox_editor_match_capture_size.SectionName = "Editor";
|
this.checkbox_editor_match_capture_size.SectionName = "Editor";
|
||||||
this.checkbox_editor_match_capture_size.Size = new System.Drawing.Size(397, 24);
|
this.checkbox_editor_match_capture_size.Size = new System.Drawing.Size(397, 24);
|
||||||
this.checkbox_editor_match_capture_size.TabIndex = 11;
|
this.checkbox_editor_match_capture_size.TabIndex = 11;
|
||||||
|
@ -689,7 +691,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_ie_capture.LanguageKey = "settings_iecapture";
|
this.checkbox_ie_capture.LanguageKey = "settings_iecapture";
|
||||||
this.checkbox_ie_capture.Location = new System.Drawing.Point(6, 19);
|
this.checkbox_ie_capture.Location = new System.Drawing.Point(6, 19);
|
||||||
this.checkbox_ie_capture.Name = "checkbox_ie_capture";
|
this.checkbox_ie_capture.Name = "checkbox_ie_capture";
|
||||||
this.checkbox_ie_capture.PropertyName = "IECapture";
|
this.checkbox_ie_capture.PropertyName = nameof(CoreConfiguration.IECapture);
|
||||||
this.checkbox_ie_capture.Size = new System.Drawing.Size(404, 24);
|
this.checkbox_ie_capture.Size = new System.Drawing.Size(404, 24);
|
||||||
this.checkbox_ie_capture.TabIndex = 10;
|
this.checkbox_ie_capture.TabIndex = 10;
|
||||||
this.checkbox_ie_capture.UseVisualStyleBackColor = true;
|
this.checkbox_ie_capture.UseVisualStyleBackColor = true;
|
||||||
|
@ -732,7 +734,7 @@ namespace Greenshot.Forms {
|
||||||
this.radiobuttonInteractiveCapture.LanguageKey = "settings_capture_windows_interactive";
|
this.radiobuttonInteractiveCapture.LanguageKey = "settings_capture_windows_interactive";
|
||||||
this.radiobuttonInteractiveCapture.Location = new System.Drawing.Point(11, 20);
|
this.radiobuttonInteractiveCapture.Location = new System.Drawing.Point(11, 20);
|
||||||
this.radiobuttonInteractiveCapture.Name = "radiobuttonInteractiveCapture";
|
this.radiobuttonInteractiveCapture.Name = "radiobuttonInteractiveCapture";
|
||||||
this.radiobuttonInteractiveCapture.PropertyName = "CaptureWindowsInteractive";
|
this.radiobuttonInteractiveCapture.PropertyName = nameof(CoreConfiguration.CaptureWindowsInteractive);
|
||||||
this.radiobuttonInteractiveCapture.Size = new System.Drawing.Size(203, 17);
|
this.radiobuttonInteractiveCapture.Size = new System.Drawing.Size(203, 17);
|
||||||
this.radiobuttonInteractiveCapture.TabIndex = 6;
|
this.radiobuttonInteractiveCapture.TabIndex = 6;
|
||||||
this.radiobuttonInteractiveCapture.TabStop = true;
|
this.radiobuttonInteractiveCapture.TabStop = true;
|
||||||
|
@ -770,7 +772,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_zoomer.LanguageKey = "settings_zoom";
|
this.checkbox_zoomer.LanguageKey = "settings_zoom";
|
||||||
this.checkbox_zoomer.Location = new System.Drawing.Point(11, 79);
|
this.checkbox_zoomer.Location = new System.Drawing.Point(11, 79);
|
||||||
this.checkbox_zoomer.Name = "checkbox_zoomer";
|
this.checkbox_zoomer.Name = "checkbox_zoomer";
|
||||||
this.checkbox_zoomer.PropertyName = "ZoomerEnabled";
|
this.checkbox_zoomer.PropertyName = nameof(CoreConfiguration.ZoomerEnabled);
|
||||||
this.checkbox_zoomer.Size = new System.Drawing.Size(399, 24);
|
this.checkbox_zoomer.Size = new System.Drawing.Size(399, 24);
|
||||||
this.checkbox_zoomer.TabIndex = 4;
|
this.checkbox_zoomer.TabIndex = 4;
|
||||||
this.checkbox_zoomer.UseVisualStyleBackColor = true;
|
this.checkbox_zoomer.UseVisualStyleBackColor = true;
|
||||||
|
@ -780,7 +782,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_notifications.LanguageKey = "settings_shownotify";
|
this.checkbox_notifications.LanguageKey = "settings_shownotify";
|
||||||
this.checkbox_notifications.Location = new System.Drawing.Point(11, 59);
|
this.checkbox_notifications.Location = new System.Drawing.Point(11, 59);
|
||||||
this.checkbox_notifications.Name = "checkbox_notifications";
|
this.checkbox_notifications.Name = "checkbox_notifications";
|
||||||
this.checkbox_notifications.PropertyName = "ShowTrayNotification";
|
this.checkbox_notifications.PropertyName = nameof(CoreConfiguration.ShowTrayNotification);
|
||||||
this.checkbox_notifications.Size = new System.Drawing.Size(399, 24);
|
this.checkbox_notifications.Size = new System.Drawing.Size(399, 24);
|
||||||
this.checkbox_notifications.TabIndex = 3;
|
this.checkbox_notifications.TabIndex = 3;
|
||||||
this.checkbox_notifications.UseVisualStyleBackColor = true;
|
this.checkbox_notifications.UseVisualStyleBackColor = true;
|
||||||
|
@ -790,7 +792,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_playsound.LanguageKey = "settings_playsound";
|
this.checkbox_playsound.LanguageKey = "settings_playsound";
|
||||||
this.checkbox_playsound.Location = new System.Drawing.Point(11, 39);
|
this.checkbox_playsound.Location = new System.Drawing.Point(11, 39);
|
||||||
this.checkbox_playsound.Name = "checkbox_playsound";
|
this.checkbox_playsound.Name = "checkbox_playsound";
|
||||||
this.checkbox_playsound.PropertyName = "PlayCameraSound";
|
this.checkbox_playsound.PropertyName = nameof(CoreConfiguration.PlayCameraSound);
|
||||||
this.checkbox_playsound.Size = new System.Drawing.Size(399, 24);
|
this.checkbox_playsound.Size = new System.Drawing.Size(399, 24);
|
||||||
this.checkbox_playsound.TabIndex = 2;
|
this.checkbox_playsound.TabIndex = 2;
|
||||||
this.checkbox_playsound.UseVisualStyleBackColor = true;
|
this.checkbox_playsound.UseVisualStyleBackColor = true;
|
||||||
|
@ -800,7 +802,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_capture_mousepointer.LanguageKey = "settings_capture_mousepointer";
|
this.checkbox_capture_mousepointer.LanguageKey = "settings_capture_mousepointer";
|
||||||
this.checkbox_capture_mousepointer.Location = new System.Drawing.Point(11, 19);
|
this.checkbox_capture_mousepointer.Location = new System.Drawing.Point(11, 19);
|
||||||
this.checkbox_capture_mousepointer.Name = "checkbox_capture_mousepointer";
|
this.checkbox_capture_mousepointer.Name = "checkbox_capture_mousepointer";
|
||||||
this.checkbox_capture_mousepointer.PropertyName = "CaptureMousepointer";
|
this.checkbox_capture_mousepointer.PropertyName = nameof(CoreConfiguration.CaptureMousepointer);
|
||||||
this.checkbox_capture_mousepointer.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_capture_mousepointer.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_capture_mousepointer.TabIndex = 1;
|
this.checkbox_capture_mousepointer.TabIndex = 1;
|
||||||
this.checkbox_capture_mousepointer.UseVisualStyleBackColor = true;
|
this.checkbox_capture_mousepointer.UseVisualStyleBackColor = true;
|
||||||
|
@ -887,7 +889,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
|
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
|
||||||
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
|
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
|
||||||
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
|
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
|
||||||
this.checkboxPrintInverted.PropertyName = "OutputPrintInverted";
|
this.checkboxPrintInverted.PropertyName = nameof(CoreConfiguration.OutputPrintInverted);
|
||||||
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
|
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
|
||||||
this.checkboxPrintInverted.TabIndex = 14;
|
this.checkboxPrintInverted.TabIndex = 14;
|
||||||
this.checkboxPrintInverted.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxPrintInverted.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -900,7 +902,6 @@ namespace Greenshot.Forms {
|
||||||
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
|
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
|
||||||
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
|
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
|
||||||
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
|
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
|
||||||
this.radioBtnColorPrint.PropertyName = "OutputPrintColor";
|
|
||||||
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
|
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
|
||||||
this.radioBtnColorPrint.TabIndex = 11;
|
this.radioBtnColorPrint.TabIndex = 11;
|
||||||
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -913,7 +914,7 @@ namespace Greenshot.Forms {
|
||||||
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
|
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
|
||||||
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
|
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
|
||||||
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
|
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
|
||||||
this.radioBtnGrayScale.PropertyName = "OutputPrintGrayscale";
|
this.radioBtnGrayScale.PropertyName = nameof(coreConfiguration.OutputPrintGrayscale);
|
||||||
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
|
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
|
||||||
this.radioBtnGrayScale.TabIndex = 12;
|
this.radioBtnGrayScale.TabIndex = 12;
|
||||||
this.radioBtnGrayScale.Text = "Force grayscale printing";
|
this.radioBtnGrayScale.Text = "Force grayscale printing";
|
||||||
|
@ -927,7 +928,7 @@ namespace Greenshot.Forms {
|
||||||
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
|
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
|
||||||
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
|
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
|
||||||
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
|
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
|
||||||
this.radioBtnMonochrome.PropertyName = "OutputPrintMonochrome";
|
this.radioBtnMonochrome.PropertyName = nameof(coreConfiguration.OutputPrintMonochrome);
|
||||||
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
|
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
|
||||||
this.radioBtnMonochrome.TabIndex = 13;
|
this.radioBtnMonochrome.TabIndex = 13;
|
||||||
this.radioBtnMonochrome.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.radioBtnMonochrome.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -954,7 +955,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
|
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
|
||||||
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
|
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
|
||||||
this.checkboxDateTime.Name = "checkboxDateTime";
|
this.checkboxDateTime.Name = "checkboxDateTime";
|
||||||
this.checkboxDateTime.PropertyName = "OutputPrintFooter";
|
this.checkboxDateTime.PropertyName = nameof(coreConfiguration.OutputPrintFooter);
|
||||||
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
|
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
|
||||||
this.checkboxDateTime.TabIndex = 6;
|
this.checkboxDateTime.TabIndex = 6;
|
||||||
this.checkboxDateTime.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxDateTime.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -967,7 +968,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
|
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
|
||||||
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
|
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
|
||||||
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
|
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
|
||||||
this.checkboxAllowShrink.PropertyName = "OutputPrintAllowShrink";
|
this.checkboxAllowShrink.PropertyName = nameof(coreConfiguration.OutputPrintAllowShrink);
|
||||||
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
|
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
|
||||||
this.checkboxAllowShrink.TabIndex = 2;
|
this.checkboxAllowShrink.TabIndex = 2;
|
||||||
this.checkboxAllowShrink.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxAllowShrink.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -980,7 +981,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
|
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
|
||||||
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
|
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
|
||||||
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
|
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
|
||||||
this.checkboxAllowEnlarge.PropertyName = "OutputPrintAllowEnlarge";
|
this.checkboxAllowEnlarge.PropertyName = nameof(coreConfiguration.OutputPrintAllowEnlarge);
|
||||||
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
|
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
|
||||||
this.checkboxAllowEnlarge.TabIndex = 3;
|
this.checkboxAllowEnlarge.TabIndex = 3;
|
||||||
this.checkboxAllowEnlarge.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxAllowEnlarge.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -993,7 +994,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
|
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
|
||||||
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
|
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
|
||||||
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
|
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
|
||||||
this.checkboxAllowRotate.PropertyName = "OutputPrintAllowRotate";
|
this.checkboxAllowRotate.PropertyName = nameof(coreConfiguration.OutputPrintAllowRotate);
|
||||||
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
|
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
|
||||||
this.checkboxAllowRotate.TabIndex = 4;
|
this.checkboxAllowRotate.TabIndex = 4;
|
||||||
this.checkboxAllowRotate.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxAllowRotate.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -1006,7 +1007,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
|
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
|
||||||
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
|
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
|
||||||
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
|
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
|
||||||
this.checkboxAllowCenter.PropertyName = "OutputPrintCenter";
|
this.checkboxAllowCenter.PropertyName = nameof(coreConfiguration.OutputPrintCenter);
|
||||||
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
|
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
|
||||||
this.checkboxAllowCenter.TabIndex = 5;
|
this.checkboxAllowCenter.TabIndex = 5;
|
||||||
this.checkboxAllowCenter.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
this.checkboxAllowCenter.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
@ -1017,7 +1018,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.LanguageKey = "settings_alwaysshowprintoptionsdialog";
|
this.checkbox_alwaysshowprintoptionsdialog.LanguageKey = "settings_alwaysshowprintoptionsdialog";
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.Location = new System.Drawing.Point(19, 293);
|
this.checkbox_alwaysshowprintoptionsdialog.Location = new System.Drawing.Point(19, 293);
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.Name = "checkbox_alwaysshowprintoptionsdialog";
|
this.checkbox_alwaysshowprintoptionsdialog.Name = "checkbox_alwaysshowprintoptionsdialog";
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.PropertyName = "OutputPrintPromptOptions";
|
this.checkbox_alwaysshowprintoptionsdialog.PropertyName = nameof(coreConfiguration.OutputPrintPromptOptions);
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.Size = new System.Drawing.Size(394, 20);
|
this.checkbox_alwaysshowprintoptionsdialog.Size = new System.Drawing.Size(394, 20);
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.TabIndex = 15;
|
this.checkbox_alwaysshowprintoptionsdialog.TabIndex = 15;
|
||||||
this.checkbox_alwaysshowprintoptionsdialog.Text = "Show print options dialog every time an image is printed";
|
this.checkbox_alwaysshowprintoptionsdialog.Text = "Show print options dialog every time an image is printed";
|
||||||
|
@ -1114,7 +1115,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_reuseeditor.LanguageKey = "expertsettings_reuseeditorifpossible";
|
this.checkbox_reuseeditor.LanguageKey = "expertsettings_reuseeditorifpossible";
|
||||||
this.checkbox_reuseeditor.Location = new System.Drawing.Point(10, 225);
|
this.checkbox_reuseeditor.Location = new System.Drawing.Point(10, 225);
|
||||||
this.checkbox_reuseeditor.Name = "checkbox_reuseeditor";
|
this.checkbox_reuseeditor.Name = "checkbox_reuseeditor";
|
||||||
this.checkbox_reuseeditor.PropertyName = "ReuseEditor";
|
this.checkbox_reuseeditor.PropertyName = nameof(EditorConfiguration.ReuseEditor);
|
||||||
this.checkbox_reuseeditor.SectionName = "Editor";
|
this.checkbox_reuseeditor.SectionName = "Editor";
|
||||||
this.checkbox_reuseeditor.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_reuseeditor.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_reuseeditor.TabIndex = 9;
|
this.checkbox_reuseeditor.TabIndex = 9;
|
||||||
|
@ -1125,7 +1126,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_minimizememoryfootprint.LanguageKey = "expertsettings_minimizememoryfootprint";
|
this.checkbox_minimizememoryfootprint.LanguageKey = "expertsettings_minimizememoryfootprint";
|
||||||
this.checkbox_minimizememoryfootprint.Location = new System.Drawing.Point(10, 206);
|
this.checkbox_minimizememoryfootprint.Location = new System.Drawing.Point(10, 206);
|
||||||
this.checkbox_minimizememoryfootprint.Name = "checkbox_minimizememoryfootprint";
|
this.checkbox_minimizememoryfootprint.Name = "checkbox_minimizememoryfootprint";
|
||||||
this.checkbox_minimizememoryfootprint.PropertyName = "MinimizeWorkingSetSize";
|
this.checkbox_minimizememoryfootprint.PropertyName = nameof(coreConfiguration.MinimizeWorkingSetSize);
|
||||||
this.checkbox_minimizememoryfootprint.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_minimizememoryfootprint.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_minimizememoryfootprint.TabIndex = 8;
|
this.checkbox_minimizememoryfootprint.TabIndex = 8;
|
||||||
this.checkbox_minimizememoryfootprint.UseVisualStyleBackColor = true;
|
this.checkbox_minimizememoryfootprint.UseVisualStyleBackColor = true;
|
||||||
|
@ -1135,7 +1136,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_checkunstableupdates.LanguageKey = "expertsettings_checkunstableupdates";
|
this.checkbox_checkunstableupdates.LanguageKey = "expertsettings_checkunstableupdates";
|
||||||
this.checkbox_checkunstableupdates.Location = new System.Drawing.Point(10, 187);
|
this.checkbox_checkunstableupdates.Location = new System.Drawing.Point(10, 187);
|
||||||
this.checkbox_checkunstableupdates.Name = "checkbox_checkunstableupdates";
|
this.checkbox_checkunstableupdates.Name = "checkbox_checkunstableupdates";
|
||||||
this.checkbox_checkunstableupdates.PropertyName = "CheckForUnstable";
|
this.checkbox_checkunstableupdates.PropertyName = nameof(coreConfiguration.CheckForUnstable);
|
||||||
this.checkbox_checkunstableupdates.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_checkunstableupdates.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_checkunstableupdates.TabIndex = 7;
|
this.checkbox_checkunstableupdates.TabIndex = 7;
|
||||||
this.checkbox_checkunstableupdates.UseVisualStyleBackColor = true;
|
this.checkbox_checkunstableupdates.UseVisualStyleBackColor = true;
|
||||||
|
@ -1145,7 +1146,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_suppresssavedialogatclose.LanguageKey = "expertsettings_suppresssavedialogatclose";
|
this.checkbox_suppresssavedialogatclose.LanguageKey = "expertsettings_suppresssavedialogatclose";
|
||||||
this.checkbox_suppresssavedialogatclose.Location = new System.Drawing.Point(10, 168);
|
this.checkbox_suppresssavedialogatclose.Location = new System.Drawing.Point(10, 168);
|
||||||
this.checkbox_suppresssavedialogatclose.Name = "checkbox_suppresssavedialogatclose";
|
this.checkbox_suppresssavedialogatclose.Name = "checkbox_suppresssavedialogatclose";
|
||||||
this.checkbox_suppresssavedialogatclose.PropertyName = "SuppressSaveDialogAtClose";
|
this.checkbox_suppresssavedialogatclose.PropertyName = nameof(EditorConfiguration.SuppressSaveDialogAtClose);
|
||||||
this.checkbox_suppresssavedialogatclose.SectionName = "Editor";
|
this.checkbox_suppresssavedialogatclose.SectionName = "Editor";
|
||||||
this.checkbox_suppresssavedialogatclose.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_suppresssavedialogatclose.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_suppresssavedialogatclose.TabIndex = 6;
|
this.checkbox_suppresssavedialogatclose.TabIndex = 6;
|
||||||
|
@ -1163,7 +1164,7 @@ namespace Greenshot.Forms {
|
||||||
//
|
//
|
||||||
this.textbox_counter.Location = new System.Drawing.Point(259, 282);
|
this.textbox_counter.Location = new System.Drawing.Point(259, 282);
|
||||||
this.textbox_counter.Name = "textbox_counter";
|
this.textbox_counter.Name = "textbox_counter";
|
||||||
this.textbox_counter.PropertyName = "OutputFileIncrementingNumber";
|
this.textbox_counter.PropertyName = nameof(coreConfiguration.OutputFileIncrementingNumber);
|
||||||
this.textbox_counter.Size = new System.Drawing.Size(141, 20);
|
this.textbox_counter.Size = new System.Drawing.Size(141, 20);
|
||||||
this.textbox_counter.TabIndex = 11;
|
this.textbox_counter.TabIndex = 11;
|
||||||
//
|
//
|
||||||
|
@ -1180,7 +1181,7 @@ namespace Greenshot.Forms {
|
||||||
//
|
//
|
||||||
this.textbox_footerpattern.Location = new System.Drawing.Point(138, 256);
|
this.textbox_footerpattern.Location = new System.Drawing.Point(138, 256);
|
||||||
this.textbox_footerpattern.Name = "textbox_footerpattern";
|
this.textbox_footerpattern.Name = "textbox_footerpattern";
|
||||||
this.textbox_footerpattern.PropertyName = "OutputPrintFooterPattern";
|
this.textbox_footerpattern.PropertyName = nameof(coreConfiguration.OutputPrintFooterPattern);
|
||||||
this.textbox_footerpattern.Size = new System.Drawing.Size(262, 20);
|
this.textbox_footerpattern.Size = new System.Drawing.Size(262, 20);
|
||||||
this.textbox_footerpattern.TabIndex = 10;
|
this.textbox_footerpattern.TabIndex = 10;
|
||||||
//
|
//
|
||||||
|
@ -1189,7 +1190,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_thumbnailpreview.LanguageKey = "expertsettings_thumbnailpreview";
|
this.checkbox_thumbnailpreview.LanguageKey = "expertsettings_thumbnailpreview";
|
||||||
this.checkbox_thumbnailpreview.Location = new System.Drawing.Point(10, 149);
|
this.checkbox_thumbnailpreview.Location = new System.Drawing.Point(10, 149);
|
||||||
this.checkbox_thumbnailpreview.Name = "checkbox_thumbnailpreview";
|
this.checkbox_thumbnailpreview.Name = "checkbox_thumbnailpreview";
|
||||||
this.checkbox_thumbnailpreview.PropertyName = "ThumnailPreview";
|
this.checkbox_thumbnailpreview.PropertyName = nameof(coreConfiguration.ThumnailPreview);
|
||||||
this.checkbox_thumbnailpreview.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_thumbnailpreview.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_thumbnailpreview.TabIndex = 5;
|
this.checkbox_thumbnailpreview.TabIndex = 5;
|
||||||
this.checkbox_thumbnailpreview.UseVisualStyleBackColor = true;
|
this.checkbox_thumbnailpreview.UseVisualStyleBackColor = true;
|
||||||
|
@ -1199,7 +1200,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_optimizeforrdp.LanguageKey = "expertsettings_optimizeforrdp";
|
this.checkbox_optimizeforrdp.LanguageKey = "expertsettings_optimizeforrdp";
|
||||||
this.checkbox_optimizeforrdp.Location = new System.Drawing.Point(10, 130);
|
this.checkbox_optimizeforrdp.Location = new System.Drawing.Point(10, 130);
|
||||||
this.checkbox_optimizeforrdp.Name = "checkbox_optimizeforrdp";
|
this.checkbox_optimizeforrdp.Name = "checkbox_optimizeforrdp";
|
||||||
this.checkbox_optimizeforrdp.PropertyName = "OptimizeForRDP";
|
this.checkbox_optimizeforrdp.PropertyName = nameof(coreConfiguration.OptimizeForRDP);
|
||||||
this.checkbox_optimizeforrdp.Size = new System.Drawing.Size(394, 24);
|
this.checkbox_optimizeforrdp.Size = new System.Drawing.Size(394, 24);
|
||||||
this.checkbox_optimizeforrdp.TabIndex = 4;
|
this.checkbox_optimizeforrdp.TabIndex = 4;
|
||||||
this.checkbox_optimizeforrdp.UseVisualStyleBackColor = true;
|
this.checkbox_optimizeforrdp.UseVisualStyleBackColor = true;
|
||||||
|
@ -1209,7 +1210,7 @@ namespace Greenshot.Forms {
|
||||||
this.checkbox_autoreducecolors.LanguageKey = "expertsettings_autoreducecolors";
|
this.checkbox_autoreducecolors.LanguageKey = "expertsettings_autoreducecolors";
|
||||||
this.checkbox_autoreducecolors.Location = new System.Drawing.Point(10, 111);
|
this.checkbox_autoreducecolors.Location = new System.Drawing.Point(10, 111);
|
||||||
this.checkbox_autoreducecolors.Name = "checkbox_autoreducecolors";
|
this.checkbox_autoreducecolors.Name = "checkbox_autoreducecolors";
|
||||||
this.checkbox_autoreducecolors.PropertyName = "OutputFileAutoReduceColors";
|
this.checkbox_autoreducecolors.PropertyName = nameof(coreConfiguration.OutputFileAutoReduceColors);
|
||||||
this.checkbox_autoreducecolors.Size = new System.Drawing.Size(408, 24);
|
this.checkbox_autoreducecolors.Size = new System.Drawing.Size(408, 24);
|
||||||
this.checkbox_autoreducecolors.TabIndex = 3;
|
this.checkbox_autoreducecolors.TabIndex = 3;
|
||||||
this.checkbox_autoreducecolors.UseVisualStyleBackColor = true;
|
this.checkbox_autoreducecolors.UseVisualStyleBackColor = true;
|
||||||
|
@ -1257,7 +1258,7 @@ namespace Greenshot.Forms {
|
||||||
//
|
//
|
||||||
// SettingsForm
|
// SettingsForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(451, 431);
|
this.ClientSize = new System.Drawing.Size(451, 431);
|
||||||
this.Controls.Add(this.tabcontrol);
|
this.Controls.Add(this.tabcontrol);
|
||||||
|
|
|
@ -37,7 +37,6 @@ using Greenshot.Base.Interfaces;
|
||||||
using Greenshot.Base.Interfaces.Plugin;
|
using Greenshot.Base.Interfaces.Plugin;
|
||||||
using Greenshot.Base.UnmanagedHelpers;
|
using Greenshot.Base.UnmanagedHelpers;
|
||||||
using Greenshot.Configuration;
|
using Greenshot.Configuration;
|
||||||
using Greenshot.Destinations;
|
|
||||||
using Greenshot.Helpers;
|
using Greenshot.Helpers;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
|
@ -320,7 +319,7 @@ namespace Greenshot.Forms
|
||||||
combobox_language.SelectedValue = Language.CurrentLanguage;
|
combobox_language.SelectedValue = Language.CurrentLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delaying the SelectedIndexChanged events untill all is initiated
|
// Delaying the SelectedIndexChanged events until all is initiated
|
||||||
combobox_language.SelectedIndexChanged += Combobox_languageSelectedIndexChanged;
|
combobox_language.SelectedIndexChanged += Combobox_languageSelectedIndexChanged;
|
||||||
UpdateDestinationDescriptions();
|
UpdateDestinationDescriptions();
|
||||||
UpdateClipboardFormatDescriptions();
|
UpdateClipboardFormatDescriptions();
|
||||||
|
@ -829,22 +828,19 @@ namespace Greenshot.Forms
|
||||||
{
|
{
|
||||||
public int Compare(object x, object y)
|
public int Compare(object x, object y)
|
||||||
{
|
{
|
||||||
if (!(x is ListViewItem))
|
if (x is not ListViewItem listViewItemX)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(y is ListViewItem))
|
if (y is not ListViewItem listViewItemY)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListViewItem l1 = (ListViewItem) x;
|
IDestination firstDestination = listViewItemX.Tag as IDestination;
|
||||||
ListViewItem l2 = (ListViewItem) y;
|
|
||||||
|
|
||||||
IDestination firstDestination = l1.Tag as IDestination;
|
if (listViewItemY.Tag is not IDestination secondDestination)
|
||||||
|
|
||||||
if (!(l2.Tag is IDestination secondDestination))
|
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,6 +389,7 @@ namespace Greenshot.Helpers
|
||||||
HandleCapture();
|
HandleCapture();
|
||||||
break;
|
break;
|
||||||
case CaptureMode.Clipboard:
|
case CaptureMode.Clipboard:
|
||||||
|
// TODO: Fix getting image vs. drawablecontainer
|
||||||
Image clipboardImage = ClipboardHelper.GetImage();
|
Image clipboardImage = ClipboardHelper.GetImage();
|
||||||
if (clipboardImage != null)
|
if (clipboardImage != null)
|
||||||
{
|
{
|
||||||
|
@ -430,12 +431,13 @@ namespace Greenshot.Helpers
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(filename))
|
if (!string.IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
|
// TODO: Fix that the Greenshot format needs a separate code path
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (filename.ToLower().EndsWith("." + OutputFormat.greenshot))
|
if (filename.ToLower().EndsWith("." + OutputFormat.greenshot))
|
||||||
{
|
{
|
||||||
ISurface surface = new Surface();
|
ISurface surface = new Surface();
|
||||||
surface = ImageOutput.LoadGreenshotSurface(filename, surface);
|
surface = ImageIO.LoadGreenshotSurface(filename, surface);
|
||||||
surface.CaptureDetails = _capture.CaptureDetails;
|
surface.CaptureDetails = _capture.CaptureDetails;
|
||||||
DestinationHelper.GetDestination(EditorDestination.DESIGNATION).ExportCapture(true, surface, _capture.CaptureDetails);
|
DestinationHelper.GetDestination(EditorDestination.DESIGNATION).ExportCapture(true, surface, _capture.CaptureDetails);
|
||||||
break;
|
break;
|
||||||
|
@ -447,9 +449,10 @@ namespace Greenshot.Helpers
|
||||||
MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename));
|
MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove Image loading for here
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
fileImage = ImageHelper.LoadImage(filename);
|
fileImage = ImageIO.LoadImage(filename);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace Greenshot.Helpers
|
||||||
/// <param name="captureDetails">ICaptureDetails</param>
|
/// <param name="captureDetails">ICaptureDetails</param>
|
||||||
public static void SendImage(ISurface surface, ICaptureDetails captureDetails)
|
public static void SendImage(ISurface surface, ICaptureDetails captureDetails)
|
||||||
{
|
{
|
||||||
string tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings());
|
string tmpFile = ImageIO.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings());
|
||||||
|
|
||||||
if (tmpFile == null) return;
|
if (tmpFile == null) return;
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ namespace Greenshot.Helpers
|
||||||
|
|
||||||
ApplyEffects(printOutputSettings);
|
ApplyEffects(printOutputSettings);
|
||||||
|
|
||||||
bool disposeImage = ImageOutput.CreateImageFromSurface(_surface, printOutputSettings, out var image);
|
bool disposeImage = ImageIO.CreateImageFromSurface(_surface, printOutputSettings, out var image);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ContentAlignment alignment = CoreConfig.OutputPrintCenter ? ContentAlignment.MiddleCenter : ContentAlignment.TopLeft;
|
ContentAlignment alignment = CoreConfig.OutputPrintCenter ? ContentAlignment.MiddleCenter : ContentAlignment.TopLeft;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue