Turned on the code for the Greenshot file format, hat to refactor the ImageOutput to accept an ISurface so we could wait to export it to an image until the last moment or save the surace-image & serialize the elements.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2373 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-12-10 17:50:26 +00:00
parent 745a17c3b1
commit f5e9618cd2
16 changed files with 159 additions and 77 deletions

View file

@ -102,10 +102,8 @@ namespace Greenshot.Destinations {
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
using (Image image = surface.GetImageForExport()) {
MapiMailMessage.SendImage(image, captureDetails);
exportInformation.ExportMade = true;
}
MapiMailMessage.SendImage(surface, captureDetails);
exportInformation.ExportMade = true;
ProcessExport(exportInformation, surface);
return exportInformation;
}

View file

@ -29,6 +29,7 @@ using GreenshotPlugin.Core;
using Greenshot.Plugin;
using Greenshot.Helpers;
using Greenshot.IniFile;
using GreenshotPlugin.Controls;
namespace Greenshot.Destinations {
/// <summary>
@ -74,12 +75,15 @@ namespace Greenshot.Destinations {
bool outputMade;
bool overwrite;
string fullPath;
// Get output settings from the configuration
OutputSettings outputSettings = new OutputSettings();
if (captureDetails.Filename != null) {
if (captureDetails != null && captureDetails.Filename != null) {
// As we save a pre-selected file, allow to overwrite.
overwrite = true;
LOG.InfoFormat("Using previous filename");
fullPath = captureDetails.Filename;
outputSettings.Format = ImageOutput.FormatForFilename(fullPath);
} else {
LOG.InfoFormat("Creating new filename");
string pattern = conf.OutputFileFilenamePattern;
@ -92,26 +96,29 @@ namespace Greenshot.Destinations {
// As we generate a file, the configuration tells us if we allow to overwrite
overwrite = conf.OutputFileAllowOverwrite;
}
if (conf.OutputFilePromptQuality) {
QualityDialog qualityDialog = new QualityDialog(outputSettings);
qualityDialog.ShowDialog();
}
// Catching any exception to prevent that the user can't write in the directory.
// This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642
using (Image image = surface.GetImageForExport()) {
try {
ImageOutput.Save(image, fullPath, overwrite);
outputMade = true;
} catch (ArgumentException ex1) {
// Our generated filename exists, display 'save-as'
LOG.InfoFormat("Not overwriting: {0}", ex1.Message);
// when we don't allow to overwrite present a new SaveWithDialog
fullPath = ImageOutput.SaveWithDialog(image, captureDetails);
outputMade = (fullPath != null);
} catch (Exception ex2) {
LOG.Error("Error saving screenshot!", ex2);
// Show the problem
MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error));
// when save failed we present a SaveWithDialog
fullPath = ImageOutput.SaveWithDialog(image, captureDetails);
outputMade = (fullPath != null);
}
try {
ImageOutput.Save(surface, fullPath, overwrite, outputSettings, conf.OutputFileCopyPathToClipboard);
outputMade = true;
} catch (ArgumentException ex1) {
// Our generated filename exists, display 'save-as'
LOG.InfoFormat("Not overwriting: {0}", ex1.Message);
// when we don't allow to overwrite present a new SaveWithDialog
fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
outputMade = (fullPath != null);
} catch (Exception ex2) {
LOG.Error("Error saving screenshot!", ex2);
// Show the problem
MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error));
// when save failed we present a SaveWithDialog
fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
outputMade = (fullPath != null);
}
// Don't overwite filename if no output is made
if (outputMade) {
@ -119,6 +126,7 @@ namespace Greenshot.Destinations {
exportInformation.Filepath = fullPath;
captureDetails.Filename = fullPath;
}
ProcessExport(exportInformation, surface);
return exportInformation;
}

View file

@ -72,14 +72,12 @@ namespace Greenshot.Destinations {
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
string savedTo = null;
using (Image image = surface.GetImageForExport()) {
// Bug #2918756 don't overwrite path if SaveWithDialog returns null!
savedTo = ImageOutput.SaveWithDialog(image, captureDetails);
if (savedTo != null) {
exportInformation.ExportMade = true;
exportInformation.Filepath = savedTo;
captureDetails.Filename = savedTo;
}
// Bug #2918756 don't overwrite path if SaveWithDialog returns null!
savedTo = ImageOutput.SaveWithDialog(surface, captureDetails);
if (savedTo != null) {
exportInformation.ExportMade = true;
exportInformation.Filepath = savedTo;
captureDetails.Filename = savedTo;
}
ProcessExport(exportInformation, surface);
return exportInformation;

View file

@ -232,6 +232,7 @@ namespace Greenshot.Drawing {
}
set {
image = value;
Size = image.Size;
}
}

View file

@ -336,6 +336,10 @@ namespace Greenshot {
}
}
/// <summary>
/// This is called when the size of the surface chances, used for resizing and displaying the size information
/// </summary>
/// <param name="source"></param>
private void SurfaceSizeChanged(object source) {
if (editorConfiguration.MatchSizeToCapture) {
// Set editor's initial size to the size of the surface plus the size of the chrome

View file

@ -593,7 +593,7 @@ namespace Greenshot {
void CaptureFile() {
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Image files (*.png, *.jpg, *.gif, *.bmp, *.ico, *.tiff, *.wmf)|*.png; *.jpg; *.jpeg; *.gif; *.bmp; *.ico; *.tiff; *.tif; *.wmf";
openFileDialog.Filter = "Image files (*.greenshot, *.png, *.jpg, *.gif, *.bmp, *.ico, *.tiff, *.wmf)|*.greenshot; *.png; *.jpg; *.jpeg; *.gif; *.bmp; *.ico; *.tiff; *.tif; *.wmf";
if (openFileDialog.ShowDialog() == DialogResult.OK) {
if (File.Exists(openFileDialog.FileName)) {
CaptureHelper.CaptureFile(openFileDialog.FileName);

View file

@ -331,11 +331,10 @@ namespace Greenshot.Helpers {
if (!string.IsNullOrEmpty(filename)) {
try {
if (filename.EndsWith(".gsf")) {
if (filename.ToLower().EndsWith("." + OutputFormat.greenshot)) {
ISurface surface = new Surface();
surface = ImageOutput.LoadGreenshotSurface(filename, surface);
surface.CaptureDetails = capture.CaptureDetails;
DestinationHelper.GetDestination(EditorDestination.DESIGNATION).ExportCapture(true, surface, capture.CaptureDetails);
break;
}

View file

@ -64,8 +64,8 @@ namespace Greenshot.Helpers {
/// </summary>
/// <param name="image">The image to send</param>
/// <param name="captureDetails">ICaptureDetails</param>
public static void SendImage(Image image, ICaptureDetails captureDetails) {
string tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, new OutputSettings());
public static void SendImage(ISurface surface, ICaptureDetails captureDetails) {
string tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new OutputSettings());
if (tmpFile != null) {
// Store the list of currently active windows, so we can make sure we show the email window later!

View file

@ -74,9 +74,7 @@ namespace ExternalCommand {
bool runInBackground = config.runInbackground[presetCommand];
string fullPath = captureDetails.Filename;
if (fullPath == null) {
using (Image image = surface.GetImageForExport()) {
fullPath = ImageOutput.SaveNamedTmpFile(image, captureDetails, outputSettings);
}
fullPath = ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
}
string output = null;

View file

@ -111,9 +111,7 @@ namespace GreenshotOfficePlugin {
ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
string tmpFile = captureDetails.Filename;
if (tmpFile == null || surface.Modified) {
using (Image image = surface.GetImageForExport()) {
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, new OutputSettings());
}
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new OutputSettings(OutputFormat.png));
}
if (workbookName != null) {
ExcelExporter.InsertIntoExistingWorkbook(workbookName, tmpFile);

View file

@ -153,9 +153,7 @@ namespace GreenshotOfficePlugin {
// Outlook logic
string tmpFile = captureDetails.Filename;
if (tmpFile == null || surface.Modified) {
using (Image image = surface.GetImageForExport()) {
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, new OutputSettings());
}
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new OutputSettings());
} else {
LOG.InfoFormat("Using already available file: {0}", tmpFile);
}

View file

@ -113,10 +113,8 @@ namespace GreenshotOfficePlugin {
string tmpFile = captureDetails.Filename;
Size imageSize = Size.Empty;
if (tmpFile == null || surface.Modified) {
using (Image image = surface.GetImageForExport()) {
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, new OutputSettings());
imageSize = image.Size;
}
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new OutputSettings());
imageSize = surface.Image.Size;
}
if (presentationName != null) {
exportInformation.ExportMade = PowerpointExporter.ExportToPresentation(presentationName, tmpFile, imageSize, captureDetails.Title);

View file

@ -112,9 +112,7 @@ namespace GreenshotOfficePlugin {
ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
string tmpFile = captureDetails.Filename;
if (tmpFile == null || surface.Modified) {
using (Image image = surface.GetImageForExport()) {
tmpFile = ImageOutput.SaveNamedTmpFile(image, captureDetails, new OutputSettings());
}
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new OutputSettings(OutputFormat.png));
}
if (documentCaption != null) {
try {

View file

@ -31,7 +31,7 @@ namespace GreenshotPlugin.Core {
PNG, DIB, HTML, HTMLDATAURL
}
public enum OutputFormat {
bmp, gif, jpg, png, tiff
bmp, gif, jpg, png, tiff, greenshot
}
public enum WindowCaptureMode {
Screen, GDI, Aero, AeroTransparent, Auto

View file

@ -216,6 +216,11 @@ namespace GreenshotPlugin.Core {
long bytesWritten = surface.SaveElementsToStream(stream);
using (BinaryWriter writer = new BinaryWriter(stream)) {
writer.Write(bytesWritten);
Version v = Assembly.GetExecutingAssembly().GetName().Version;
string marker = String.Format("Greenshot{0:00}.{1:00}", v.Major, v.Minor);
using (StreamWriter streamWriter = new StreamWriter(stream)) {
streamWriter.Write(marker);
}
}
}
}
@ -232,25 +237,38 @@ namespace GreenshotPlugin.Core {
Bitmap fileBitmap = null;
LOG.InfoFormat("Loading image from file {0}", fullPath);
// Fixed lock problem Bug #3431881
using (Stream imageFileStream = File.OpenRead(fullPath)) {
using (Stream surfaceFileStream = File.OpenRead(fullPath)) {
// And 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
imageFileStream.Position = 0;
using (Image tmpImage = Image.FromStream(imageFileStream, true, true)) {
surfaceFileStream.Position = 0;
using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true)) {
LOG.DebugFormat("Loaded {0} with Size {1}x{2} and PixelFormat {3}", fullPath, tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
fileBitmap = ImageHelper.Clone(tmpImage);
}
imageFileStream.Seek(-8, SeekOrigin.End);
long bytesWritten = 0;
using (BinaryReader reader = new BinaryReader(imageFileStream)) {
bytesWritten = reader.ReadInt64();
imageFileStream.Seek(-(bytesWritten + 8), SeekOrigin.End);
returnSurface.LoadElementsFromStream(imageFileStream);
// Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
const int markerSize = 14;
surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
string greenshotMarker;
using (StreamReader streamReader = new StreamReader(surfaceFileStream)) {
greenshotMarker = streamReader.ReadToEnd();
if (greenshotMarker == null || !greenshotMarker.StartsWith("Greenshot")) {
throw new ArgumentException(string.Format("{0} is not a Greenshot file!", fullPath));
}
LOG.InfoFormat("Greenshot file format: {0}", greenshotMarker);
const int filesizeLocation = 8 + markerSize;
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
long bytesWritten = 0;
using (BinaryReader reader = new BinaryReader(surfaceFileStream)) {
bytesWritten = reader.ReadInt64();
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
returnSurface.LoadElementsFromStream(surfaceFileStream);
}
}
}
if (fileBitmap != null) {
returnSurface.Image = fileBitmap;
LOG.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, fileBitmap.Width, fileBitmap.Height, fileBitmap.PixelFormat, fileBitmap.HorizontalResolution, fileBitmap.VerticalResolution);
}
return returnSurface;
@ -297,12 +315,46 @@ namespace GreenshotPlugin.Core {
}
/// <summary>
/// saves img to fullpath
/// Saves image to specific path with specified quality
/// </summary>
/// <param name="img">the image to save</param>
/// <param name="fullPath">the absolute destination path including file name</param>
/// <param name="allowOverwrite">true if overwrite is allowed, false if not</param>
public static void Save(Image img, string fullPath, bool allowOverwrite) {
public static void Save(ISurface surface, string fullPath, bool allowOverwrite, OutputSettings outputSettings, bool copyPathToClipboard) {
fullPath = FilenameHelper.MakeFQFilenameSafe(fullPath);
string path = Path.GetDirectoryName(fullPath);
// check whether path exists - if not create it
DirectoryInfo di = new DirectoryInfo(path);
if (!di.Exists) {
Directory.CreateDirectory(di.FullName);
}
if (!allowOverwrite && File.Exists(fullPath)) {
ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists.");
throwingException.Data.Add("fullPath", fullPath);
throw throwingException;
}
LOG.DebugFormat("Saving image to {0}", fullPath);
// Create the stream and call SaveToStream
if (outputSettings.Format == OutputFormat.greenshot) {
SaveGreenshotSurface(surface, fullPath);
} else {
using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) {
using (Image image = surface.GetImageForExport()) {
SaveToStream(image, stream, outputSettings);
}
}
}
if (copyPathToClipboard) {
ClipboardHelper.SetClipboardData(fullPath);
}
}
/// <summary>
/// Get the OutputFormat for a filename
/// </summary>
/// <param name="fullPath">filename (can be a complete path)</param>
/// <returns>OutputFormat</returns>
public static OutputFormat FormatForFilename(string fullPath) {
// Fix for bug 2912959
string extension = fullPath.Substring(fullPath.LastIndexOf(".") + 1);
OutputFormat format = OutputFormat.png;
@ -313,6 +365,17 @@ namespace GreenshotPlugin.Core {
} catch (ArgumentException ae) {
LOG.Warn("Couldn't parse extension: " + extension, ae);
}
return format;
}
/// <summary>
/// saves img to fullpath
/// </summary>
/// <param name="img">the image to save</param>
/// <param name="fullPath">the absolute destination path including file name</param>
/// <param name="allowOverwrite">true if overwrite is allowed, false if not</param>
public static void Save(Image img, string fullPath, bool allowOverwrite) {
OutputFormat format = FormatForFilename(fullPath);
// Get output settings from the configuration
OutputSettings outputSettings = new OutputSettings(format);
if (conf.OutputFilePromptQuality) {
@ -324,19 +387,27 @@ namespace GreenshotPlugin.Core {
#endregion
#region save-as
public static string SaveWithDialog(Image image) {
return SaveWithDialog(image, null);
}
public static string SaveWithDialog(Image image, ICaptureDetails captureDetails) {
/// <summary>
/// Save with showing a dialog
/// </summary>
/// <param name="surface"></param>
/// <param name="captureDetails"></param>
/// <returns>Path to filename</returns>
public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails) {
string returnValue = null;
SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails);
DialogResult dialogResult = saveImageFileDialog.ShowDialog();
if (dialogResult.Equals(DialogResult.OK)) {
try {
string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
// TODO: For now we overwrite, should be changed
ImageOutput.Save(image, fileNameWithExtension, true);
OutputSettings outputSettings = new OutputSettings(FormatForFilename(fileNameWithExtension));
if (conf.OutputFilePromptQuality) {
QualityDialog qualityDialog = new QualityDialog(outputSettings);
qualityDialog.ShowDialog();
}
// TODO: For now we always overwrite, should be changed
ImageOutput.Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard);
returnValue = fileNameWithExtension;
conf.OutputFileAsFullpath = fileNameWithExtension;
IniConfig.Save();
@ -348,7 +419,15 @@ namespace GreenshotPlugin.Core {
}
#endregion
public static string SaveNamedTmpFile(Image image, ICaptureDetails captureDetails, OutputSettings outputSettings) {
/// <summary>
/// Create a tmpfile which has the name like in the configured pattern.
/// Used e.g. by the email export
/// </summary>
/// <param name="surface"></param>
/// <param name="captureDetails"></param>
/// <param name="outputSettings"></param>
/// <returns>Path to image file</returns>
public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, OutputSettings outputSettings) {
string pattern = conf.OutputFileFilenamePattern;
if (pattern == null || string.IsNullOrEmpty(pattern.Trim())) {
pattern = "greenshot ${capturetime}";
@ -365,13 +444,13 @@ namespace GreenshotPlugin.Core {
// Catching any exception to prevent that the user can't write in the directory.
// This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218
try {
ImageOutput.Save(image, tmpFile, true, outputSettings, false);
ImageOutput.Save(surface, tmpFile, true, outputSettings, false);
tmpFileCache.Add(tmpFile, tmpFile);
} catch (Exception e) {
// Show the problem
MessageBox.Show(e.Message, "Error");
// when save failed we present a SaveWithDialog
tmpFile = ImageOutput.SaveWithDialog(image, captureDetails);
tmpFile = ImageOutput.SaveWithDialog(surface, captureDetails);
}
return tmpFile;
}

View file

@ -153,5 +153,10 @@ namespace Greenshot.Plugin {
bool HasCursor {
get;
}
ICaptureDetails CaptureDetails {
get;
set;
}
}
}