Merge branch 'release/1.3' into fix/379-preferences-window

# Conflicts:
#	src/Greenshot/Forms/SettingsForm.Designer.cs
This commit is contained in:
Christian Schulz 2022-02-20 17:30:37 +01:00
commit 1585d1c2ea
90 changed files with 2795 additions and 1340 deletions

View file

@ -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
{ {

View file

@ -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,24 +508,38 @@ 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;
}
Bitmap bitmap = null;
try try
{ {
image = ImageHelper.FromStream(fileData); if (!fileFormatHandlers.TryLoadFromStream(stream, extension, out bitmap))
{
continue;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -529,31 +548,114 @@ EndSelection:<<<<<<<4
} }
finally finally
{ {
fileData?.Dispose(); stream?.Dispose();
} }
// If we get here, there is an image // If we get here, there is an image
yield return image; yield return bitmap;
} }
// check if files are supplied // check if files are supplied
foreach (string imageFile in GetImageFilenames(dataObject)) foreach (string imageFile in GetImageFilenames(dataObject))
{ {
Image returnImage = null; var extension = Path.GetExtension(imageFile)?.ToLowerInvariant();
try if (!supportedExtensions.Contains(extension))
{ {
returnImage = ImageHelper.LoadImage(imageFile); continue;
}
catch (Exception streamImageEx)
{
Log.Error("Problem retrieving Image from clipboard.", streamImageEx);
} }
if (returnImage != null) Bitmap bitmap = null;
using FileStream fileStream = new FileStream(imageFile, FileMode.Open, FileAccess.Read, FileShare.Read);
try
{ {
Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat); if (!fileFormatHandlers.TryLoadFromStream(fileStream, extension, out bitmap))
yield return returnImage; {
continue;
} }
} }
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,11 +664,11 @@ 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)
{ {
if (dataObject == null) return null;
Bitmap returnImage = null;
IList<string> formats = GetFormats(dataObject); IList<string> formats = GetFormats(dataObject);
string[] retrieveFormats; string[] retrieveFormats;
@ -608,21 +710,77 @@ EndSelection:<<<<<<<4
return returnImage; return returnImage;
} }
} }
return null;
}
/// <summary>
/// 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; return null;
} }
/// <summary> /// <summary>
/// Helper method to try to get an image in the specified format from the dataObject /// 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,113 +810,82 @@ 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>();
// From here, imageStream is a valid stream
if (!fileFormatHandlers.TryLoadFromStream(imageStream, format, out bitmap))
{
return bitmap;
}
return null;
} }
if (CoreConfig.EnableSpecialDIBClipboardReader) /// <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)
{ {
if (format == FORMAT_17 || format == DataFormats.Dib) IDrawableContainer drawableContainer = null;
{
Log.Info("Found DIB stream, trying to process it.");
try
{
if (imageStream != null)
{
byte[] dibBuffer = new byte[imageStream.Length];
_ = imageStream.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 if (format == FORMAT_HTML)
{ {
bfType = BITMAPFILEHEADER.BM, var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
bfSize = fileSize, if (textObject != null)
bfReserved1 = 0, {
bfReserved2 = 0, var doc = new HtmlDocument();
bfOffBits = (int) (fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4) doc.LoadHtml(textObject);
}; var imgNodes = doc.DocumentNode.SelectNodes("//img");
if (imgNodes != null)
{
foreach (var imgNode in imgNodes)
{
var srcAttribute = imgNode.Attributes["src"];
var imageUrl = srcAttribute.Value;
Log.Debug(imageUrl);
drawableContainer = NetworkHelper.DownloadImageAsDrawableContainer(imageUrl);
if (drawableContainer != null)
{
return drawableContainer;
}
}
}
}
}
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader); object clipboardObject = GetFromDataObject(dataObject, format);
var imageStream = clipboardObject as MemoryStream;
using var bitmapStream = new MemoryStream(); if (!IsValidStream(imageStream))
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize); {
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length); // TODO: add text based, like "HTML Format" support here...
bitmapStream.Seek(0, SeekOrigin.Begin); // TODO: solve the issue that we do not have a factory for the ImageContainer
var image = ImageHelper.FromStream(bitmapStream); /*var image = clipboardObject as Image;
if (image != null) if (image != null)
{ {
return image; return new ImageContainer(this)
}
}
else
{ {
Log.Info("Using special DIBV5 / Format17 format reader"); Image = image,
// CF_DIBV5 Left = x,
IntPtr gcHandle = IntPtr.Zero; Top = y
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) return clipboardObject as Image;
{ */
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
{
if (imageStream != null)
{
imageStream.Seek(0, SeekOrigin.Begin);
var tmpImage = ImageHelper.FromStream(imageStream);
if (tmpImage != null)
{
Log.InfoFormat("Got image with clipboard format {0} from the clipboard.", format);
return tmpImage;
}
}
}
catch (Exception streamImageEx)
{
Log.Error($"Problem retrieving {format} from clipboard.", streamImageEx);
}
return null; return null;
} }
// From here, imageStream is a valid stream
var fileFormatHandlers = SimpleServiceProvider.Current.GetAllInstances<IFileFormatHandler>();
return fileFormatHandlers.LoadDrawablesFromStream(imageStream, format).FirstOrDefault();
}
/// <summary> /// <summary>
/// Get Text from the DataObject /// Get Text from the DataObject
/// </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,13 +993,20 @@ 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);
if (!fileFormatHandlers.TrySaveToStream((Bitmap)imageToSave, dibStream, DataFormats.Dib))
{
dibStream.Dispose();
dibStream = null;
}
else
{
// Set the DIB to the clipboard DataObject // Set the DIB to the clipboard DataObject
dataObject.SetData(DataFormats.Dib, false, dibStream); dataObject.SetData(DataFormats.Dib, false, dibStream);
} }
} }
}
catch (Exception dibEx) catch (Exception dibEx)
{ {
Log.Error("Error creating DIB for the Clipboard.", dibEx); Log.Error("Error creating DIB for the Clipboard.", 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>();
var supportedExtensions = fileFormatHandlers.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
return dropFileNames return dropFileNames
.Where(filename => !string.IsNullOrEmpty(filename)) .Where(filename => !string.IsNullOrEmpty(filename))
.Where(Path.HasExtension) .Where(Path.HasExtension)
.Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1))); .Where(filename => supportedExtensions.Contains(Path.GetExtension(filename)));
}
return Enumerable.Empty<string>();
} }
/// <summary> /// <summary>

View 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,
}
}

View file

@ -31,6 +31,7 @@ namespace Greenshot.Base.Core.Enums
jpg, jpg,
png, png,
tiff, tiff,
jxr,
greenshot, greenshot,
ico ico
} }

View file

@ -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);
}
}
}

View file

@ -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; }
} }

View file

@ -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
{ {
if (stream == null) 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)
{ {
return null; if (pixelFormat == PixelFormats.Bgra32)
{
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}.");
{
extension = extension.Replace(".", string.Empty);
} }
// Make sure we can try multiple times /// <summary>
if (!stream.CanSeek) /// Convert a Bitmap to a BitmapSource
/// </summary>
/// <param name="bitmap">Bitmap</param>
/// <returns>BitmapSource</returns>
public static BitmapSource ToBitmapSource(this Bitmap bitmap)
{ {
var memoryStream = new MemoryStream(); var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
stream.CopyTo(memoryStream);
stream = memoryStream; BitmapSource bitmapSource;
try
{
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);
} }
Image returnImage = null; return bitmapSource;
if (StreamConverters.TryGetValue(extension ?? string.Empty, out var converter))
{
returnImage = converter(stream, extension);
} }
// Fallback /// <summary>
if (returnImage == null) /// Convert a BitmapSource to a Bitmap
/// </summary>
/// <param name="bitmapSource">BitmapSource</param>
/// <returns>Bitmap</returns>
public static Bitmap ToBitmap(this BitmapSource bitmapSource)
{ {
// We create a copy of the bitmap, so everything else can be disposed var pixelFormat = bitmapSource.Format.Map();
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);
returnImage = Clone(tmpImage, PixelFormat.Format32bppArgb);
}
return returnImage; Bitmap bitmap = new Bitmap(bitmapSource.PixelWidth, bitmapSource.PixelHeight, pixelFormat);
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);
bitmap.UnlockBits(data);
return bitmap;
} }
} }
} }

View file

@ -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,12 +250,11 @@ 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);
@ -444,7 +264,6 @@ namespace Greenshot.Base.Core
Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id); Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id);
} }
} }
}
/// <summary> /// <summary>
/// Load a Greenshot surface /// Load a Greenshot surface
@ -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,8 +366,7 @@ 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; string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
@ -569,7 +387,6 @@ namespace Greenshot.Base.Core
MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error")); MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error"));
} }
} }
}
return returnValue; return returnValue;
} }
@ -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 return null;
// }
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>(); if (!File.Exists(filename))
IList<MemoryStream> encodedImages = new List<MemoryStream>();
foreach (var image in images)
{ {
// Pick the best fit return null;
var sizes = new[] }
Image fileImage;
Log.InfoFormat("Loading image from file {0}", filename);
// Fixed lock problem Bug #3431881
using (Stream imageFileStream = File.OpenRead(filename))
{ {
16, 32, 48 fileImage = FromStream(imageFileStream, Path.GetExtension(filename));
}; }
int size = 256;
foreach (var possibleSize in sizes) if (fileImage != null)
{ {
if (image.Width <= possibleSize && image.Height <= possibleSize) 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)
{ {
size = possibleSize; 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; break;
} }
} }
}
var imageStream = new MemoryStream(); catch
if (image.Width == size && image.Height == size)
{ {
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); return null;
clonedImage.Save(imageStream, ImageFormat.Png);
imageSizes.Add(new Size(size, size));
} }
else
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)
{ {
// Resize to the specified size, first make sure the image is 32bpp Shell32.ExtractIconEx(location, index, out var large, out var small, 1);
using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); Icon returnIcon = null;
using var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null); bool isLarge = false;
resizedImage.Save(imageStream, ImageFormat.Png); bool isSmall = false;
imageSizes.Add(resizedImage.Size); try
}
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]; if (takeLarge && !IntPtr.Zero.Equals(large))
// Write the width / height, 0 means 256 {
binaryWriter.Write(imageSize.Width == 256 ? (byte) 0 : (byte) imageSize.Width); returnIcon = Icon.FromHandle(large);
binaryWriter.Write(imageSize.Height == 256 ? (byte) 0 : (byte) imageSize.Height); isLarge = true;
binaryWriter.Write((byte) 0); // no pallete }
binaryWriter.Write((byte) 0); // reserved else if (!IntPtr.Zero.Equals(small))
binaryWriter.Write((short) 0); // no color planes {
binaryWriter.Write((short) 32); // 32 bpp returnIcon = Icon.FromHandle(small);
binaryWriter.Write((int) encodedImages[i].Length); // image data length isSmall = true;
binaryWriter.Write(offset); }
offset += (int) encodedImages[i].Length; else if (!IntPtr.Zero.Equals(large))
{
returnIcon = Icon.FromHandle(large);
isLarge = true;
}
}
finally
{
if (isLarge && !IntPtr.Zero.Equals(small))
{
User32.DestroyIcon(small);
} }
binaryWriter.Flush(); if (isSmall && !IntPtr.Zero.Equals(large))
//
// Write image data
//
foreach (var encodedImage in encodedImages)
{ {
encodedImage.WriteTo(stream); User32.DestroyIcon(large);
encodedImage.Dispose();
} }
} }
return returnIcon;
}
/// <summary>
/// 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)
{
return null;
}
if (!string.IsNullOrEmpty(extension))
{
extension = extension.Replace(".", string.Empty);
}
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;
}
} }
} }

View file

@ -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;
}
}
}
}

View file

@ -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>

View file

@ -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)
{ {

View file

@ -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>()

View file

@ -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();
}
}
}

View file

@ -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));
} }

View file

@ -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>

View 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;
}
}

View 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);
}
}

View file

@ -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

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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,

View file

@ -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,17 +276,15 @@ 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>
/// Wrapper for the SetWindowLong which decides if the system is 64-bit or not and calls the right one. /// Wrapper for the SetWindowLong which decides if the system is 64-bit or not and calls the right one.

View file

@ -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)
{ {
} }

View file

@ -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();
} }

View file

@ -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);
} }

View file

@ -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)
{ {

View file

@ -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();
} }

View file

@ -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,12 +117,11 @@ 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()
{ {

View file

@ -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();
} }

View file

@ -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;

View file

@ -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();
} }

View file

@ -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)

View file

@ -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);
} }
} }

View file

@ -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();
} }

View 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);
}
}

View file

@ -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();
} }

View file

@ -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();
} }

View file

@ -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)
{ {
} }

View file

@ -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);
@ -204,7 +204,7 @@ namespace Greenshot.Editor.Drawing
EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false); EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
} }
float fontSize = Math.Min(Width, Height) / 1.4f; float fontSize = Math.Min(Math.Abs(Width), Math.Abs(Height)) / 1.4f;
using FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name); using FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name);
using Font font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel); using Font font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font); TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font);

View file

@ -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,14 +1010,12 @@ 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>
/// Apply a bitmap effect to the surface /// Apply a bitmap effect to the surface
@ -2057,19 +2078,18 @@ 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();
IImageContainer container = AddImageContainer(clipboardImage as Bitmap, pasteLocation.X, pasteLocation.Y); drawableContainer.Left = pasteLocation.X;
SelectElement(container); drawableContainer.Top = pasteLocation.Y;
clipboardImage.Dispose(); AddElement(drawableContainer);
SelectElement(drawableContainer);
pasteLocation.X += 10; pasteLocation.X += 10;
pasteLocation.Y += 10; pasteLocation.Y += 10;
} }
} }
}
else if (ClipboardHelper.ContainsText(clipboard)) else if (ClipboardHelper.ContainsText(clipboard))
{ {
Point pasteLocation = GetPasteLocation(0.4f, 0.4f); Point pasteLocation = GetPasteLocation(0.4f, 0.4f);
@ -2208,8 +2228,8 @@ 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); selectedElements.Add(container);
container.Selected = true; container.Selected = true;
FieldAggregator.BindElement(container); FieldAggregator.BindElement(container);
@ -2227,7 +2247,6 @@ namespace Greenshot.Editor.Drawing
container.Invalidate(); container.Invalidate();
} }
} }
}
/// <summary> /// <summary>
/// Select all elements, this is called when Ctrl+A is pressed /// Select all elements, this is called when Ctrl+A is pressed

View 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);
}
}

View file

@ -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>

View 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;
}
}
}

View 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()
);
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}

View file

@ -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));

View file

@ -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;
}
}
}

View 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;
}
}
}

View 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.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);
}
}
}
}

View file

@ -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);
}
}
}
}

View 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;
}
}
}

View file

@ -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)

View file

@ -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>

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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; }

View file

@ -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;

View file

@ -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

View file

@ -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()
{ {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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;

View file

@ -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
{ {

View file

@ -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;
} }

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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");

View file

@ -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();

View file

@ -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>

View file

@ -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;
} }

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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 {
@ -248,7 +250,7 @@ namespace Greenshot.Forms {
this.textbox_screenshotname.Location = new System.Drawing.Point(205, 42); this.textbox_screenshotname.Location = new System.Drawing.Point(205, 42);
this.textbox_screenshotname.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.textbox_screenshotname.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(205, 20); this.textbox_screenshotname.Size = new System.Drawing.Size(205, 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);
@ -281,7 +283,7 @@ namespace Greenshot.Forms {
this.combobox_primaryimageformat.Location = new System.Drawing.Point(205, 66); this.combobox_primaryimageformat.Location = new System.Drawing.Point(205, 66);
this.combobox_primaryimageformat.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.combobox_primaryimageformat.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(235, 21); this.combobox_primaryimageformat.Size = new System.Drawing.Size(235, 21);
this.combobox_primaryimageformat.TabIndex = 5; this.combobox_primaryimageformat.TabIndex = 5;
// //
@ -333,7 +335,7 @@ namespace Greenshot.Forms {
this.checkbox_copypathtoclipboard.Location = new System.Drawing.Point(8, 93); this.checkbox_copypathtoclipboard.Location = new System.Drawing.Point(8, 93);
this.checkbox_copypathtoclipboard.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_copypathtoclipboard.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(358, 20); this.checkbox_copypathtoclipboard.Size = new System.Drawing.Size(358, 20);
this.checkbox_copypathtoclipboard.TabIndex = 6; this.checkbox_copypathtoclipboard.TabIndex = 6;
this.checkbox_copypathtoclipboard.Text = "Copy file path to clipboard every time an image is saved"; this.checkbox_copypathtoclipboard.Text = "Copy file path to clipboard every time an image is saved";
@ -345,7 +347,7 @@ namespace Greenshot.Forms {
this.checkbox_zoomer.Location = new System.Drawing.Point(4, 82); this.checkbox_zoomer.Location = new System.Drawing.Point(4, 82);
this.checkbox_zoomer.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_zoomer.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_zoomer.Size = new System.Drawing.Size(362, 20);
this.checkbox_zoomer.TabIndex = 4; this.checkbox_zoomer.TabIndex = 4;
this.checkbox_zoomer.Text = "Show magnifier"; this.checkbox_zoomer.Text = "Show magnifier";
@ -440,7 +442,7 @@ namespace Greenshot.Forms {
this.checkbox_reducecolors.Location = new System.Drawing.Point(8, 95); this.checkbox_reducecolors.Location = new System.Drawing.Point(8, 95);
this.checkbox_reducecolors.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_reducecolors.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(358, 20); this.checkbox_reducecolors.Size = new System.Drawing.Size(358, 20);
this.checkbox_reducecolors.TabIndex = 10; this.checkbox_reducecolors.TabIndex = 10;
this.checkbox_reducecolors.Text = "Reduce the amount of colors to a maximum of 256"; this.checkbox_reducecolors.Text = "Reduce the amount of colors to a maximum of 256";
@ -452,7 +454,7 @@ namespace Greenshot.Forms {
this.checkbox_alwaysshowqualitydialog.Location = new System.Drawing.Point(8, 69); this.checkbox_alwaysshowqualitydialog.Location = new System.Drawing.Point(8, 69);
this.checkbox_alwaysshowqualitydialog.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_alwaysshowqualitydialog.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(358, 20); this.checkbox_alwaysshowqualitydialog.Size = new System.Drawing.Size(358, 20);
this.checkbox_alwaysshowqualitydialog.TabIndex = 9; this.checkbox_alwaysshowqualitydialog.TabIndex = 9;
this.checkbox_alwaysshowqualitydialog.Text = "Show quality dialog every time an image is saved"; this.checkbox_alwaysshowqualitydialog.Text = "Show quality dialog every time an image is saved";
@ -620,7 +622,7 @@ namespace Greenshot.Forms {
this.checkbox_usedefaultproxy.Location = new System.Drawing.Point(7, 19); this.checkbox_usedefaultproxy.Location = new System.Drawing.Point(7, 19);
this.checkbox_usedefaultproxy.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_usedefaultproxy.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(359, 20); this.checkbox_usedefaultproxy.Size = new System.Drawing.Size(359, 20);
this.checkbox_usedefaultproxy.TabIndex = 7; this.checkbox_usedefaultproxy.TabIndex = 7;
this.checkbox_usedefaultproxy.Text = "Use default system proxy"; this.checkbox_usedefaultproxy.Text = "Use default system proxy";
@ -665,7 +667,7 @@ namespace Greenshot.Forms {
this.lastregion_hotkeyControl.Location = new System.Drawing.Point(280, 81); this.lastregion_hotkeyControl.Location = new System.Drawing.Point(280, 81);
this.lastregion_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.lastregion_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(158, 20); this.lastregion_hotkeyControl.Size = new System.Drawing.Size(158, 20);
this.lastregion_hotkeyControl.TabIndex = 5; this.lastregion_hotkeyControl.TabIndex = 5;
// //
@ -686,7 +688,7 @@ namespace Greenshot.Forms {
this.ie_hotkeyControl.Location = new System.Drawing.Point(280, 104); this.ie_hotkeyControl.Location = new System.Drawing.Point(280, 104);
this.ie_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.ie_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(158, 20); this.ie_hotkeyControl.Size = new System.Drawing.Size(158, 20);
this.ie_hotkeyControl.TabIndex = 6; this.ie_hotkeyControl.TabIndex = 6;
// //
@ -727,7 +729,7 @@ namespace Greenshot.Forms {
this.region_hotkeyControl.Location = new System.Drawing.Point(280, 59); this.region_hotkeyControl.Location = new System.Drawing.Point(280, 59);
this.region_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.region_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(158, 20); this.region_hotkeyControl.Size = new System.Drawing.Size(158, 20);
this.region_hotkeyControl.TabIndex = 4; this.region_hotkeyControl.TabIndex = 4;
// //
@ -738,7 +740,7 @@ namespace Greenshot.Forms {
this.window_hotkeyControl.Location = new System.Drawing.Point(280, 36); this.window_hotkeyControl.Location = new System.Drawing.Point(280, 36);
this.window_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.window_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(158, 20); this.window_hotkeyControl.Size = new System.Drawing.Size(158, 20);
this.window_hotkeyControl.TabIndex = 3; this.window_hotkeyControl.TabIndex = 3;
// //
@ -749,7 +751,7 @@ namespace Greenshot.Forms {
this.fullscreen_hotkeyControl.Location = new System.Drawing.Point(280, 14); this.fullscreen_hotkeyControl.Location = new System.Drawing.Point(280, 14);
this.fullscreen_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.fullscreen_hotkeyControl.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(158, 20); this.fullscreen_hotkeyControl.Size = new System.Drawing.Size(158, 20);
this.fullscreen_hotkeyControl.TabIndex = 2; this.fullscreen_hotkeyControl.TabIndex = 2;
// //
@ -787,7 +789,7 @@ namespace Greenshot.Forms {
this.checkbox_editor_match_capture_size.Location = new System.Drawing.Point(4, 17); this.checkbox_editor_match_capture_size.Location = new System.Drawing.Point(4, 17);
this.checkbox_editor_match_capture_size.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_editor_match_capture_size.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_editor_match_capture_size.Size = new System.Drawing.Size(362, 20);
this.checkbox_editor_match_capture_size.TabIndex = 11; this.checkbox_editor_match_capture_size.TabIndex = 11;
@ -813,7 +815,7 @@ namespace Greenshot.Forms {
this.checkbox_ie_capture.Location = new System.Drawing.Point(4, 16); this.checkbox_ie_capture.Location = new System.Drawing.Point(4, 16);
this.checkbox_ie_capture.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_ie_capture.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_ie_capture.Size = new System.Drawing.Size(362, 20);
this.checkbox_ie_capture.TabIndex = 10; this.checkbox_ie_capture.TabIndex = 10;
this.checkbox_ie_capture.Text = "Internet Explorer capture"; this.checkbox_ie_capture.Text = "Internet Explorer capture";
@ -864,7 +866,7 @@ namespace Greenshot.Forms {
this.radiobuttonInteractiveCapture.Location = new System.Drawing.Point(4, 17); this.radiobuttonInteractiveCapture.Location = new System.Drawing.Point(4, 17);
this.radiobuttonInteractiveCapture.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.radiobuttonInteractiveCapture.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.radiobuttonInteractiveCapture.Size = new System.Drawing.Size(362, 20);
this.radiobuttonInteractiveCapture.TabIndex = 6; this.radiobuttonInteractiveCapture.TabIndex = 6;
this.radiobuttonInteractiveCapture.TabStop = true; this.radiobuttonInteractiveCapture.TabStop = true;
@ -910,7 +912,7 @@ namespace Greenshot.Forms {
this.checkbox_notifications.Location = new System.Drawing.Point(4, 60); this.checkbox_notifications.Location = new System.Drawing.Point(4, 60);
this.checkbox_notifications.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_notifications.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_notifications.Size = new System.Drawing.Size(362, 20);
this.checkbox_notifications.TabIndex = 3; this.checkbox_notifications.TabIndex = 3;
this.checkbox_notifications.Text = "Show notifications"; this.checkbox_notifications.Text = "Show notifications";
@ -922,7 +924,7 @@ namespace Greenshot.Forms {
this.checkbox_playsound.Location = new System.Drawing.Point(4, 38); this.checkbox_playsound.Location = new System.Drawing.Point(4, 38);
this.checkbox_playsound.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_playsound.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_playsound.Size = new System.Drawing.Size(362, 20);
this.checkbox_playsound.TabIndex = 2; this.checkbox_playsound.TabIndex = 2;
this.checkbox_playsound.Text = "Play camera sound"; this.checkbox_playsound.Text = "Play camera sound";
@ -934,7 +936,7 @@ namespace Greenshot.Forms {
this.checkbox_capture_mousepointer.Location = new System.Drawing.Point(4, 16); this.checkbox_capture_mousepointer.Location = new System.Drawing.Point(4, 16);
this.checkbox_capture_mousepointer.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_capture_mousepointer.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(362, 20); this.checkbox_capture_mousepointer.Size = new System.Drawing.Size(362, 20);
this.checkbox_capture_mousepointer.TabIndex = 1; this.checkbox_capture_mousepointer.TabIndex = 1;
this.checkbox_capture_mousepointer.Text = "Capture mousepointer"; this.checkbox_capture_mousepointer.Text = "Capture mousepointer";
@ -1035,7 +1037,7 @@ namespace Greenshot.Forms {
this.checkboxPrintInverted.Location = new System.Drawing.Point(10, 94); this.checkboxPrintInverted.Location = new System.Drawing.Point(10, 94);
this.checkboxPrintInverted.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxPrintInverted.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxPrintInverted.Size = new System.Drawing.Size(355, 20);
this.checkboxPrintInverted.TabIndex = 14; this.checkboxPrintInverted.TabIndex = 14;
this.checkboxPrintInverted.Text = "Print with inverted colors"; this.checkboxPrintInverted.Text = "Print with inverted colors";
@ -1050,7 +1052,8 @@ namespace Greenshot.Forms {
this.radioBtnColorPrint.Location = new System.Drawing.Point(10, 16); this.radioBtnColorPrint.Location = new System.Drawing.Point(10, 16);
this.radioBtnColorPrint.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.radioBtnColorPrint.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.radioBtnColorPrint.Name = "radioBtnColorPrint"; this.radioBtnColorPrint.Name = "radioBtnColorPrint";
this.radioBtnColorPrint.PropertyName = "OutputPrintColor"; //TODO missing property in coreConfiguration
//this.radioBtnColorPrint.PropertyName = nameof(coreConfiguration.OutputPrintColor);
this.radioBtnColorPrint.Size = new System.Drawing.Size(355, 20); this.radioBtnColorPrint.Size = new System.Drawing.Size(355, 20);
this.radioBtnColorPrint.TabIndex = 11; this.radioBtnColorPrint.TabIndex = 11;
this.radioBtnColorPrint.Text = "Full color print"; this.radioBtnColorPrint.Text = "Full color print";
@ -1065,7 +1068,7 @@ namespace Greenshot.Forms {
this.radioBtnGrayScale.Location = new System.Drawing.Point(10, 42); this.radioBtnGrayScale.Location = new System.Drawing.Point(10, 42);
this.radioBtnGrayScale.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.radioBtnGrayScale.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.radioBtnGrayScale.Size = new System.Drawing.Size(355, 20);
this.radioBtnGrayScale.TabIndex = 12; this.radioBtnGrayScale.TabIndex = 12;
this.radioBtnGrayScale.Text = "Force grayscale printing"; this.radioBtnGrayScale.Text = "Force grayscale printing";
@ -1080,7 +1083,7 @@ namespace Greenshot.Forms {
this.radioBtnMonochrome.Location = new System.Drawing.Point(10, 68); this.radioBtnMonochrome.Location = new System.Drawing.Point(10, 68);
this.radioBtnMonochrome.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.radioBtnMonochrome.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.radioBtnMonochrome.Size = new System.Drawing.Size(355, 20);
this.radioBtnMonochrome.TabIndex = 13; this.radioBtnMonochrome.TabIndex = 13;
this.radioBtnMonochrome.Text = "Force black/white printing"; this.radioBtnMonochrome.Text = "Force black/white printing";
@ -1112,7 +1115,7 @@ namespace Greenshot.Forms {
this.checkboxDateTime.Location = new System.Drawing.Point(10, 116); this.checkboxDateTime.Location = new System.Drawing.Point(10, 116);
this.checkboxDateTime.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxDateTime.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxDateTime.Size = new System.Drawing.Size(355, 20);
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";
@ -1127,7 +1130,7 @@ namespace Greenshot.Forms {
this.checkboxAllowShrink.Location = new System.Drawing.Point(10, 20); this.checkboxAllowShrink.Location = new System.Drawing.Point(10, 20);
this.checkboxAllowShrink.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxAllowShrink.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxAllowShrink.Size = new System.Drawing.Size(355, 20);
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";
@ -1142,7 +1145,7 @@ namespace Greenshot.Forms {
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(10, 44); this.checkboxAllowEnlarge.Location = new System.Drawing.Point(10, 44);
this.checkboxAllowEnlarge.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxAllowEnlarge.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxAllowEnlarge.Size = new System.Drawing.Size(355, 20);
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";
@ -1157,7 +1160,7 @@ namespace Greenshot.Forms {
this.checkboxAllowRotate.Location = new System.Drawing.Point(10, 68); this.checkboxAllowRotate.Location = new System.Drawing.Point(10, 68);
this.checkboxAllowRotate.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxAllowRotate.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxAllowRotate.Size = new System.Drawing.Size(355, 20);
this.checkboxAllowRotate.TabIndex = 4; this.checkboxAllowRotate.TabIndex = 4;
this.checkboxAllowRotate.Text = "Rotate printout to page orientation"; this.checkboxAllowRotate.Text = "Rotate printout to page orientation";
@ -1172,7 +1175,7 @@ namespace Greenshot.Forms {
this.checkboxAllowCenter.Location = new System.Drawing.Point(10, 92); this.checkboxAllowCenter.Location = new System.Drawing.Point(10, 92);
this.checkboxAllowCenter.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkboxAllowCenter.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkboxAllowCenter.Size = new System.Drawing.Size(355, 20);
this.checkboxAllowCenter.TabIndex = 5; this.checkboxAllowCenter.TabIndex = 5;
this.checkboxAllowCenter.Text = "Center printout on page"; this.checkboxAllowCenter.Text = "Center printout on page";
@ -1185,7 +1188,7 @@ namespace Greenshot.Forms {
this.checkbox_alwaysshowprintoptionsdialog.Location = new System.Drawing.Point(14, 282); this.checkbox_alwaysshowprintoptionsdialog.Location = new System.Drawing.Point(14, 282);
this.checkbox_alwaysshowprintoptionsdialog.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_alwaysshowprintoptionsdialog.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(355, 20); this.checkbox_alwaysshowprintoptionsdialog.Size = new System.Drawing.Size(355, 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";
@ -1293,7 +1296,7 @@ namespace Greenshot.Forms {
this.checkbox_reuseeditor.Location = new System.Drawing.Point(8, 240); this.checkbox_reuseeditor.Location = new System.Drawing.Point(8, 240);
this.checkbox_reuseeditor.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_reuseeditor.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_reuseeditor.Size = new System.Drawing.Size(410, 20);
this.checkbox_reuseeditor.TabIndex = 9; this.checkbox_reuseeditor.TabIndex = 9;
@ -1306,7 +1309,7 @@ namespace Greenshot.Forms {
this.checkbox_minimizememoryfootprint.Location = new System.Drawing.Point(8, 216); this.checkbox_minimizememoryfootprint.Location = new System.Drawing.Point(8, 216);
this.checkbox_minimizememoryfootprint.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_minimizememoryfootprint.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_minimizememoryfootprint.Size = new System.Drawing.Size(410, 20);
this.checkbox_minimizememoryfootprint.TabIndex = 8; this.checkbox_minimizememoryfootprint.TabIndex = 8;
this.checkbox_minimizememoryfootprint.Text = "Minimize memory footprint, but with a performance penalty (not advised)."; this.checkbox_minimizememoryfootprint.Text = "Minimize memory footprint, but with a performance penalty (not advised).";
@ -1318,7 +1321,7 @@ namespace Greenshot.Forms {
this.checkbox_checkunstableupdates.Location = new System.Drawing.Point(8, 192); this.checkbox_checkunstableupdates.Location = new System.Drawing.Point(8, 192);
this.checkbox_checkunstableupdates.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_checkunstableupdates.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_checkunstableupdates.Size = new System.Drawing.Size(410, 20);
this.checkbox_checkunstableupdates.TabIndex = 7; this.checkbox_checkunstableupdates.TabIndex = 7;
this.checkbox_checkunstableupdates.Text = "Check for unstable updates"; this.checkbox_checkunstableupdates.Text = "Check for unstable updates";
@ -1330,7 +1333,7 @@ namespace Greenshot.Forms {
this.checkbox_suppresssavedialogatclose.Location = new System.Drawing.Point(8, 168); this.checkbox_suppresssavedialogatclose.Location = new System.Drawing.Point(8, 168);
this.checkbox_suppresssavedialogatclose.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_suppresssavedialogatclose.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_suppresssavedialogatclose.Size = new System.Drawing.Size(410, 20);
this.checkbox_suppresssavedialogatclose.TabIndex = 6; this.checkbox_suppresssavedialogatclose.TabIndex = 6;
@ -1352,7 +1355,7 @@ namespace Greenshot.Forms {
this.textbox_counter.Location = new System.Drawing.Point(304, 288); this.textbox_counter.Location = new System.Drawing.Point(304, 288);
this.textbox_counter.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.textbox_counter.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(134, 20); this.textbox_counter.Size = new System.Drawing.Size(134, 20);
this.textbox_counter.TabIndex = 11; this.textbox_counter.TabIndex = 11;
// //
@ -1371,7 +1374,7 @@ namespace Greenshot.Forms {
this.textbox_footerpattern.Location = new System.Drawing.Point(155, 264); this.textbox_footerpattern.Location = new System.Drawing.Point(155, 264);
this.textbox_footerpattern.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.textbox_footerpattern.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(283, 20); this.textbox_footerpattern.Size = new System.Drawing.Size(283, 20);
this.textbox_footerpattern.TabIndex = 10; this.textbox_footerpattern.TabIndex = 10;
// //
@ -1381,7 +1384,7 @@ namespace Greenshot.Forms {
this.checkbox_thumbnailpreview.Location = new System.Drawing.Point(8, 144); this.checkbox_thumbnailpreview.Location = new System.Drawing.Point(8, 144);
this.checkbox_thumbnailpreview.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_thumbnailpreview.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_thumbnailpreview.Size = new System.Drawing.Size(410, 20);
this.checkbox_thumbnailpreview.TabIndex = 5; this.checkbox_thumbnailpreview.TabIndex = 5;
this.checkbox_thumbnailpreview.Text = "Show window thumbnails in context menu (for Vista and windows 7)"; this.checkbox_thumbnailpreview.Text = "Show window thumbnails in context menu (for Vista and windows 7)";
@ -1393,7 +1396,7 @@ namespace Greenshot.Forms {
this.checkbox_optimizeforrdp.Location = new System.Drawing.Point(8, 120); this.checkbox_optimizeforrdp.Location = new System.Drawing.Point(8, 120);
this.checkbox_optimizeforrdp.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_optimizeforrdp.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_optimizeforrdp.Size = new System.Drawing.Size(410, 20);
this.checkbox_optimizeforrdp.TabIndex = 4; this.checkbox_optimizeforrdp.TabIndex = 4;
this.checkbox_optimizeforrdp.Text = "Make some optimizations for usage with remote desktop"; this.checkbox_optimizeforrdp.Text = "Make some optimizations for usage with remote desktop";
@ -1405,7 +1408,7 @@ namespace Greenshot.Forms {
this.checkbox_autoreducecolors.Location = new System.Drawing.Point(8, 102); this.checkbox_autoreducecolors.Location = new System.Drawing.Point(8, 102);
this.checkbox_autoreducecolors.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3); this.checkbox_autoreducecolors.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
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(410, 20); this.checkbox_autoreducecolors.Size = new System.Drawing.Size(410, 20);
this.checkbox_autoreducecolors.TabIndex = 3; this.checkbox_autoreducecolors.TabIndex = 3;
this.checkbox_autoreducecolors.Text = "Create an 8-bit image if the colors are less than 256 while having a > 8 bits ima" + this.checkbox_autoreducecolors.Text = "Create an 8-bit image if the colors are less than 256 while having a > 8 bits ima" +

View file

@ -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();
@ -832,22 +831,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;
} }

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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;