public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(); if (presetCommand != null) { if (!config.runInbackground.ContainsKey(presetCommand)) { config.runInbackground.Add(presetCommand, true); } bool runInBackground = config.runInbackground[presetCommand]; string fullPath = captureDetails.Filename; if (fullPath == null) { fullPath = ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings); } string output; string error; if (runInBackground) { Thread commandThread = new Thread(delegate() { CallExternalCommand(exportInformation, presetCommand, fullPath, out output, out error); ProcessExport(exportInformation, surface); }); commandThread.Name = "Running " + presetCommand; commandThread.IsBackground = true; commandThread.SetApartmentState(ApartmentState.STA); commandThread.Start(); exportInformation.ExportMade = true; } else { CallExternalCommand(exportInformation, presetCommand, fullPath, out output, out error); ProcessExport(exportInformation, surface); } } return exportInformation; }
/// <summary> /// Do the actual upload to Picasa /// </summary> /// <param name="surfaceToUpload">Image to upload</param> /// <param name="outputSettings"></param> /// <param name="title"></param> /// <param name="filename"></param> /// <returns>PicasaResponse</returns> public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { // Fill the OAuth2Settings OAuth2Settings settings = new OAuth2Settings(); settings.AuthUrlPattern = AuthUrl; settings.TokenUrl = TokenUrl; settings.CloudServiceName = "Picasa"; settings.ClientId = PicasaCredentials.ClientId; settings.ClientSecret = PicasaCredentials.ClientSecret; settings.AuthorizeMode = OAuth2AuthorizeMode.LocalServer; // Copy the settings from the config, which is kept in memory and on the disk settings.RefreshToken = Config.RefreshToken; settings.AccessToken = Config.AccessToken; settings.AccessTokenExpires = Config.AccessTokenExpires; try { var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings); if (Config.AddFilename) { webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename)); } SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename); container.Upload(webRequest); string response = NetworkHelper.GetResponseAsString(webRequest); return ParseResponse(response); } finally { // Copy the settings back to the config, so they are stored. Config.RefreshToken = settings.RefreshToken; Config.AccessToken = settings.AccessToken; Config.AccessTokenExpires = settings.AccessTokenExpires; Config.IsDirty = true; IniConfig.Save(); } }
/// <summary> /// Saves ISurface to stream with specified output settings /// </summary> /// <param name="surface">ISurface to save</param> /// <param name="stream">Stream to save to</param> /// <param name="outputSettings">SurfaceOutputSettings</param> public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) { Image imageToSave; bool disposeImage = CreateImageFromSurface(surface, outputSettings, out imageToSave); SaveToStream(imageToSave, surface, stream, outputSettings); // cleanup if needed if (disposeImage && imageToSave != null) { imageToSave.Dispose(); } }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); bool outputMade; bool overwrite; string fullPath; // Get output settings from the configuration SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(); 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 { fullPath = CreateNewFilename(captureDetails); // 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 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 overwrite filename if no output is made if (outputMade) { exportInformation.ExportMade = outputMade; exportInformation.Filepath = fullPath; captureDetails.Filename = fullPath; conf.OutputFileAsFullpath = fullPath; } ProcessExport(exportInformation, surface); return exportInformation; }
/// <summary> /// Do the actual upload to Photobucket /// For more details on the available parameters, see: http://api.Photobucket.com/resources_anon /// </summary> /// <returns>PhotobucketResponse</returns> public static PhotobucketInfo UploadToPhotobucket(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string albumPath, string title, string filename) { string responseString; if (string.IsNullOrEmpty(albumPath)) { albumPath = "!"; } OAuthSession oAuth = createSession(true); if (oAuth == null) { return null; } IDictionary<string, object> signedParameters = new Dictionary<string, object>(); // add album if (albumPath == null) { signedParameters.Add("id", config.Username); } else { signedParameters.Add("id", albumPath); } // add type signedParameters.Add("type", "image"); // add title if (title != null) { signedParameters.Add("title", title); } // add filename if (filename != null) { signedParameters.Add("filename", filename); } IDictionary<string, object> unsignedParameters = new Dictionary<string, object>(); // Add image unsignedParameters.Add("uploadfile", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); try { string apiUrl = "http://api.photobucket.com/album/!/upload"; responseString = oAuth.MakeOAuthRequest(HTTPMethod.POST, apiUrl, apiUrl.Replace("api.photobucket.com", config.SubDomain), signedParameters, unsignedParameters, null); } catch (Exception ex) { LOG.Error("Error uploading to Photobucket.", ex); throw; } finally { if (!string.IsNullOrEmpty(oAuth.Token)) { config.Token = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { config.TokenSecret = oAuth.TokenSecret; } } if (responseString == null) { return null; } LOG.Info(responseString); PhotobucketInfo PhotobucketInfo = PhotobucketInfo.FromUploadResponse(responseString); LOG.Debug("Upload to Photobucket was finished"); return PhotobucketInfo; }
/// <summary> /// Do the actual upload to Flickr /// For more details on the available parameters, see: http://flickrnet.codeplex.com /// </summary> /// <param name="surfaceToUpload"></param> /// <param name="outputSettings"></param> /// <param name="title"></param> /// <param name="filename"></param> /// <returns>url to image</returns> public static string UploadToFlickr(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { OAuthSession oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret); oAuth.BrowserSize = new Size(520, 800); oAuth.CheckVerifier = false; oAuth.AccessTokenUrl = FLICKR_ACCESS_TOKEN_URL; oAuth.AuthorizeUrl = FLICKR_AUTHORIZE_URL; oAuth.RequestTokenUrl = FLICKR_REQUEST_TOKEN_URL; oAuth.LoginTitle = "Flickr authorization"; oAuth.Token = config.FlickrToken; oAuth.TokenSecret = config.FlickrTokenSecret; if (string.IsNullOrEmpty(oAuth.Token)) { if (!oAuth.Authorize()) { return null; } if (!string.IsNullOrEmpty(oAuth.Token)) { config.FlickrToken = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { config.FlickrTokenSecret = oAuth.TokenSecret; } IniConfig.Save(); } try { IDictionary<string, object> signedParameters = new Dictionary<string, object>(); signedParameters.Add("content_type", "2"); // Screenshot signedParameters.Add("tags", "Greenshot"); signedParameters.Add("is_public", config.IsPublic ? "1" : "0"); signedParameters.Add("is_friend", config.IsFriend ? "1" : "0"); signedParameters.Add("is_family", config.IsFamily ? "1" : "0"); signedParameters.Add("safety_level", string.Format("{0}", (int)config.SafetyLevel)); signedParameters.Add("hidden", config.HiddenFromSearch ? "1" : "2"); IDictionary<string, object> otherParameters = new Dictionary<string, object>(); otherParameters.Add("photo", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); string response = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_UPLOAD_URL, signedParameters, otherParameters, null); string photoId = GetPhotoId(response); // Get Photo Info signedParameters = new Dictionary<string, object> { { "photo_id", photoId } }; string photoInfo = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_GET_INFO_URL, signedParameters, null, null); return GetUrl(photoInfo); } catch (Exception ex) { LOG.Error("Upload error: ", ex); throw; } finally { if (!string.IsNullOrEmpty(oAuth.Token)) { config.FlickrToken = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { config.FlickrTokenSecret = oAuth.TokenSecret; } } }
public QualityDialog(SurfaceOutputSettings outputSettings) { Settings = outputSettings; // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); checkBox_reduceColors.Checked = Settings.ReduceColors; trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); trackBarJpegQuality.Value = Settings.JPGQuality; textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); textBoxJpegQuality.Text = Settings.JPGQuality.ToString(); ToFront = true; }
public QualityDialog(SurfaceOutputSettings outputSettings) { Settings = outputSettings; // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); Icon = GreenshotResources.getGreenshotIcon(); checkBox_reduceColors.Checked = Settings.ReduceColors; trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); trackBarJpegQuality.Value = Settings.JPGQuality; textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); textBoxJpegQuality.Text = Settings.JPGQuality.ToString(); WindowDetails.ToForeground(Handle); }
public static string UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string filename) { OAuthSession oAuth = new OAuthSession(DropBoxCredentials.CONSUMER_KEY, DropBoxCredentials.CONSUMER_SECRET); oAuth.BrowserSize = new Size(1080, 650); oAuth.CheckVerifier = false; oAuth.AccessTokenUrl = "https://api.dropbox.com/1/oauth/access_token"; oAuth.AuthorizeUrl = "https://api.dropbox.com/1/oauth/authorize"; oAuth.RequestTokenUrl = "https://api.dropbox.com/1/oauth/request_token"; oAuth.LoginTitle = "Dropbox authorization"; oAuth.Token = config.DropboxToken; oAuth.TokenSecret = config.DropboxTokenSecret; try { SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename); string uploadResponse = oAuth.MakeOAuthRequest(HTTPMethod.POST, "https://api-content.dropbox.com/1/files_put/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, imageToUpload); LOG.DebugFormat("Upload response: {0}", uploadResponse); } catch (Exception ex) { LOG.Error("Upload error: ", ex); throw; } finally { if (!string.IsNullOrEmpty(oAuth.Token)) { config.DropboxToken = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { config.DropboxTokenSecret = oAuth.TokenSecret; } } // Try to get a URL to the uploaded image try { string responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, "https://api.dropbox.com/1/shares/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, null); if (responseString != null) { LOG.DebugFormat("Parsing output: {0}", responseString); IDictionary<string, object> returnValues = JSONHelper.JsonDecode(responseString); if (returnValues.ContainsKey("url")) { return returnValues["url"] as string; } } } catch (Exception ex) { LOG.Error("Can't parse response.", ex); } return null; }
/// <summary> /// Create an image from a surface with the settings from the output settings applied /// </summary> /// <param name="surface"></param> /// <param name="outputSettings"></param> /// <param name="imageToSave"></param> /// <returns>true if the image must be disposed</returns> public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) { bool disposeImage = false; if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) { // We save the image of the surface, this should not be disposed imageToSave = surface.Image; } else { // We create the export image of the surface to save imageToSave = surface.GetImageForExport(); disposeImage = true; } // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! if (outputSettings.Format == OutputFormat.greenshot) { return disposeImage; } Image tmpImage; if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) { // apply effects, if there are any using (Matrix matrix = new Matrix()) { tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix); } if (tmpImage != null) { if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; disposeImage = true; } } return disposeImage; }
/// <summary> /// Do the actual upload to Imgur /// For more details on the available parameters, see: http://api.imgur.com/resources_anon /// </summary> /// <param name="surfaceToUpload">ISurface to upload</param> /// <param name="outputSettings">OutputSettings for the image file format</param> /// <param name="title">Title</param> /// <param name="filename">Filename</param> /// <returns>ImgurInfo with details</returns> public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { IDictionary<string, object> uploadParameters = new Dictionary<string, object>(); IDictionary<string, object> otherParameters = new Dictionary<string, object>(); // add title if (title != null && config.AddTitle) { otherParameters.Add("title", title); } // add filename if (filename != null && config.AddFilename) { otherParameters.Add("name", filename); } string responseString = null; if (config.AnonymousAccess) { // add key, we only use the other parameters for the AnonymousAccess otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY); HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(config.ImgurApiUrl + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters)); webRequest.Method = "POST"; webRequest.ContentType = "image/" + outputSettings.Format.ToString(); webRequest.ServicePoint.Expect100Continue = false; try { using (var requestStream = webRequest.GetRequestStream()) { ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings); } using (WebResponse response = webRequest.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) { responseString = reader.ReadToEnd(); } LogCredits(response); } } catch (Exception ex) { LOG.Error("Upload to imgur gave an exeption: ", ex); throw; } } else { OAuthSession oAuth = new OAuthSession(ImgurCredentials.CONSUMER_KEY, ImgurCredentials.CONSUMER_SECRET); oAuth.BrowserSize = new Size(650, 500); oAuth.CallbackUrl = "http://getgreenshot.org"; oAuth.AccessTokenUrl = "http://api.imgur.com/oauth/access_token"; oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize"; oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token"; oAuth.LoginTitle = "Imgur authorization"; oAuth.Token = config.ImgurToken; oAuth.TokenSecret = config.ImgurTokenSecret; if (string.IsNullOrEmpty(oAuth.Token)) { if (!oAuth.Authorize()) { return null; } if (!string.IsNullOrEmpty(oAuth.Token)) { config.ImgurToken = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { config.ImgurTokenSecret = oAuth.TokenSecret; } IniConfig.Save(); } try { otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); responseString = oAuth.MakeOAuthRequest(HTTPMethod.POST, "http://api.imgur.com/2/account/images.xml", uploadParameters, otherParameters, null); } catch (Exception ex) { LOG.Error("Upload to imgur gave an exeption: ", ex); throw; } finally { if (oAuth.Token != null) { config.ImgurToken = oAuth.Token; } if (oAuth.TokenSecret != null) { config.ImgurTokenSecret = oAuth.TokenSecret; } IniConfig.Save(); } } return ImgurInfo.ParseResponse(responseString); }
public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) { _surface = surface; _outputSettings = outputSettings; _fileName = filename; }
public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) { _bitmap = bitmap; _outputSettings = outputSettings; _fileName = filename; }
/// <summary> /// Create an image from a surface with the settings from the output settings applied /// </summary> /// <param name="surface"></param> /// <param name="outputSettings"></param> /// <param name="imageToSave"></param> /// <returns>true if the image must be disposed</returns> public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) { bool disposeImage = false; ImageFormat imageFormat = null; switch (outputSettings.Format) { case OutputFormat.bmp: imageFormat = ImageFormat.Bmp; break; case OutputFormat.gif: imageFormat = ImageFormat.Gif; break; case OutputFormat.jpg: imageFormat = ImageFormat.Jpeg; break; case OutputFormat.tiff: imageFormat = ImageFormat.Tiff; break; case OutputFormat.greenshot: case OutputFormat.png: default: imageFormat = ImageFormat.Png; break; } if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) { // We save the image of the surface, this should not be disposed imageToSave = surface.Image; } else { // We create the export image of the surface to save imageToSave = surface.GetImageForExport(); disposeImage = true; } // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! if (outputSettings.Format != OutputFormat.greenshot) { Image tmpImage; if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) { // apply effects, if there are any Point ignoreOffset; tmpImage = ImageHelper.ApplyEffects((Bitmap)imageToSave, outputSettings.Effects, out ignoreOffset); if (tmpImage != null) { if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; disposeImage = true; } } // check for color reduction, forced or automatically, only when the DisableReduceColors is false if (!outputSettings.DisableReduceColors && (conf.OutputFileAutoReduceColors || outputSettings.ReduceColors)) { bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors)) { using (WuQuantizer quantizer = new WuQuantizer((Bitmap)imageToSave)) { int colorCount = quantizer.GetColorCount(); LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); if (outputSettings.ReduceColors || colorCount < 256) { try { LOG.Info("Reducing colors on bitmap to 256."); tmpImage = quantizer.GetQuantizedImage(256); if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; // Make sure the "new" image is disposed disposeImage = true; } catch (Exception e) { LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } } else if (isAlpha && !outputSettings.ReduceColors) { LOG.Info("Skipping 'optional' color reduction as the image has alpha"); } } } return disposeImage; }
/// <summary> /// Upload the capture to Facebook /// </summary> /// <param name="captureDetails"></param> /// <param name="surfaceToUpload">ISurface</param> /// <param name="uploadURL">out string for the url</param> /// <returns>true if the upload succeeded</returns> public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadURL) { SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png); try { string filename = Path.GetFileName(FilenameHelper.GetFilename(OutputFormat.png, captureDetails)); FacebookInfo FacebookInfo = null; // Run upload in the background new PleaseWaitForm().ShowAndWait("Facebook plug-in", Language.GetString("facebook", LangKey.communication_wait), delegate { FacebookInfo = FacebookUtils.UploadToFacebook(surfaceToUpload, outputSettings, config.IncludeTitle ? captureDetails.Title : null, filename); } ); // This causes an exeption if the upload failed :) LOG.DebugFormat("Uploaded to Facebook page: " + FacebookInfo.Page); uploadURL = null; try { uploadURL = FacebookInfo.Page; Clipboard.SetText(FacebookInfo.Page); } catch (Exception ex) { LOG.Error("Can't write to clipboard: ", ex); } return true; } catch (Exception e) { LOG.Error(e); MessageBox.Show(Language.GetString("facebook", LangKey.upload_failure) + " " + e.Message); } uploadURL = null; return false; }
private bool upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) { SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, config.UploadReduceColors); errorMessage = null; try { new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait), delegate() { ConfluencePlugin.ConfluenceConnector.addAttachment(page.id, "image/" + config.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename)); } ); LOG.Debug("Uploaded to Confluence."); if (config.CopyWikiMarkupForImageToClipboard) { int retryCount = 2; while (retryCount >= 0) { try { Clipboard.SetText("!" + filename + "!"); break; } catch (Exception ee) { if (retryCount == 0) { LOG.Error(ee); } else { Thread.Sleep(100); } } finally { --retryCount; } } } return true; } catch(Exception e) { errorMessage = e.Message; } return false; }
public static void SetClipboardData(ISurface surface) { DataObject dataObject = new DataObject(); // This will work for Office and most other applications //ido.SetData(DataFormats.Bitmap, true, image); MemoryStream dibStream = null; MemoryStream dibV5Stream = null; MemoryStream pngStream = null; Image imageToSave = null; bool disposeImage = false; try { 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 disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave); try { // Create PNG stream if (config.ClipboardFormats.Contains(ClipboardFormat.PNG)) { pngStream = new MemoryStream(); // PNG works for e.g. Powerpoint SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings); pngStream.Seek(0, SeekOrigin.Begin); // Set the PNG stream dataObject.SetData(FORMAT_PNG, false, pngStream); } } catch (Exception pngEX) { LOG.Error("Error creating PNG for the Clipboard.", pngEX); } try { if (config.ClipboardFormats.Contains(ClipboardFormat.DIB)) { using (MemoryStream tmpBmpStream = new MemoryStream()) { // Save image as BMP SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false); ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings); dibStream = new MemoryStream(); // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14 dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int)tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH); } // Set the DIB to the clipboard DataObject dataObject.SetData(DataFormats.Dib, true, dibStream); } } catch (Exception dibEx) { LOG.Error("Error creating DIB for the Clipboard.", dibEx); } // CF_DibV5 try { if (config.ClipboardFormats.Contains(ClipboardFormat.DIBV5)) { // Create the stream for the clipboard dibV5Stream = new MemoryStream(); // Create the BITMAPINFOHEADER BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32); // Make sure we have BI_BITFIELDS, this seems to be normal for Format17? header.biCompression = BI_COMPRESSION.BI_BITFIELDS; // Create a byte[] to write byte[] headerBytes = BinaryStructHelper.ToByteArray<BITMAPINFOHEADER>(header); // Write the BITMAPINFOHEADER to the stream dibV5Stream.Write(headerBytes, 0, headerBytes.Length); // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added BitfieldColorMask colorMask = new BitfieldColorMask(); // Make sure the values are set colorMask.InitValues(); // Create the byte[] from the struct byte[] colorMaskBytes = BinaryStructHelper.ToByteArray<BitfieldColorMask>(colorMask); Array.Reverse(colorMaskBytes); // Write to the stream dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length); // Create the raw bytes for the pixels only byte[] bitmapBytes = BitmapToByteArray((Bitmap)imageToSave); // Write to the stream dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length); // Set the DIBv5 to the clipboard DataObject dataObject.SetData(FORMAT_17, true, dibV5Stream); } } catch (Exception dibEx) { LOG.Error("Error creating DIB for the Clipboard.", dibEx); } // Set the HTML if (config.ClipboardFormats.Contains(ClipboardFormat.HTML)) { string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null); string html = getHTMLString(surface, tmpFile); dataObject.SetText(html, TextDataFormat.Html); } else if (config.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL)) { string html; using (MemoryStream tmpPNGStream = new MemoryStream()) { SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); // Do not allow to reduce the colors, some applications dislike 256 color images // reported with bug #3594681 pngOutputSettings.DisableReduceColors = true; // Check if we can use the previously used image if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed) { ImageOutput.SaveToStream(imageToSave, surface, tmpPNGStream, pngOutputSettings); } else { ImageOutput.SaveToStream(surface, tmpPNGStream, pngOutputSettings); } html = getHTMLDataURLString(surface, tmpPNGStream); } dataObject.SetText(html, TextDataFormat.Html); } } finally { // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone! // Check if Bitmap is wanted if (config.ClipboardFormats.Contains(ClipboardFormat.BITMAP)) { dataObject.SetImage(imageToSave); // Place the DataObject to the clipboard SetDataObject(dataObject, true); } else { // Place the DataObject to the clipboard SetDataObject(dataObject, true); } if (pngStream != null) { pngStream.Dispose(); pngStream = null; } if (dibStream != null) { dibStream.Dispose(); dibStream = null; } if (dibV5Stream != null) { dibV5Stream.Dispose(); dibV5Stream = null; } // cleanup if needed if (disposeImage && imageToSave != null) { imageToSave.Dispose(); } } }
private static FacebookInfo UploadToFacebook(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename, bool repeated) { FacebookCredentials oAuth = createSession(true); if (oAuth == null) { return null; } SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename); var client = new FacebookClient(config.Token); var img = new FacebookMediaObject {FileName = filename}; img.SetValue(container.ToByteArray()); img.ContentType = "multipart/form-data"; var param = new Dictionary<string, object> {{"attachment", img}}; if (!string.IsNullOrEmpty(title)) param.Add("message", title); // Not on timeline? if (config.NotOnTimeline) param.Add("no_story", "1"); JsonObject result; try { result = (JsonObject) client.Post("me/photos", param); } catch (FacebookOAuthException ex) { if (!repeated && ex.ErrorCode == 190) // App no long authorized, reauthorize if possible { config.Token = null; return UploadToFacebook(surfaceToUpload, outputSettings, title, filename, true); } throw; } catch (Exception ex) { LOG.Error("Error uploading to Facebook.", ex); throw; } FacebookInfo facebookInfo = FacebookInfo.FromUploadResponse(result); LOG.Debug("Upload to Facebook was finished"); return facebookInfo; }
/// <summary> /// Do the actual upload to Imgur /// For more details on the available parameters, see: http://api.imgur.com/resources_anon /// </summary> /// <param name="surfaceToUpload">ISurface to upload</param> /// <param name="outputSettings">OutputSettings for the image file format</param> /// <param name="title">Title</param> /// <param name="filename">Filename</param> /// <returns>ImgurInfo with details</returns> public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { IDictionary<string, object> otherParameters = new Dictionary<string, object>(); // add title if (title != null && Config.AddTitle) { otherParameters.Add("title", title); } // add filename if (filename != null && Config.AddFilename) { otherParameters.Add("name", filename); } string responseString; if (Config.AnonymousAccess) { // add key, we only use the other parameters for the AnonymousAccess //otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(Config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST); webRequest.ContentType = "image/" + outputSettings.Format; webRequest.ServicePoint.Expect100Continue = false; SetClientId(webRequest); try { using (var requestStream = webRequest.GetRequestStream()) { ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings); } using (WebResponse response = webRequest.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), true)) { responseString = reader.ReadToEnd(); } LogRateLimitInfo(response); } } catch (Exception ex) { LOG.Error("Upload to imgur gave an exeption: ", ex); throw; } } else { var oauth2Settings = new OAuth2Settings(); oauth2Settings.AuthUrlPattern = AuthUrlPattern; oauth2Settings.TokenUrl = TokenUrl; oauth2Settings.RedirectUrl = "https://imgur.com"; oauth2Settings.CloudServiceName = "Imgur"; oauth2Settings.ClientId = ImgurCredentials.CONSUMER_KEY; oauth2Settings.ClientSecret = ImgurCredentials.CONSUMER_SECRET; oauth2Settings.AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser; oauth2Settings.BrowserSize = new Size(680, 880); // Copy the settings from the config, which is kept in memory and on the disk oauth2Settings.RefreshToken = Config.RefreshToken; oauth2Settings.AccessToken = Config.AccessToken; oauth2Settings.AccessTokenExpires = Config.AccessTokenExpires; try { var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "/upload.xml", oauth2Settings); otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); NetworkHelper.WriteMultipartFormData(webRequest, otherParameters); responseString = NetworkHelper.GetResponseAsString(webRequest); } finally { // Copy the settings back to the config, so they are stored. Config.RefreshToken = oauth2Settings.RefreshToken; Config.AccessToken = oauth2Settings.AccessToken; Config.AccessTokenExpires = oauth2Settings.AccessTokenExpires; Config.IsDirty = true; IniConfig.Save(); } } return ImgurInfo.ParseResponse(responseString); }
/// <summary> /// This will be called when the menu item in the Editor is clicked /// </summary> public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { uploadUrl = null; SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, false); try { string dropboxUrl = null; new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("dropbox", LangKey.communication_wait), delegate() { string filename = Path.GetFileName(FilenameHelper.GetFilename(config.UploadFormat, captureDetails)); dropboxUrl = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, filename); } ); if (dropboxUrl == null) { return false; } uploadUrl = dropboxUrl; return true; } catch (Exception e) { LOG.Error(e); MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message); return false; } }
/// <summary> /// Do the actual upload to Facebook /// </summary> /// <returns>FacebookResponse</returns> public static FacebookInfo UploadToFacebook(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { return UploadToFacebook(surfaceToUpload, outputSettings, title, filename, false); }
/// <summary> /// Saves image to specific path with specified quality /// </summary> public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings 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 surface to {0}", fullPath); // Create the stream and call SaveToStream using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) { SaveToStream(surface, stream, outputSettings); } if (copyPathToClipboard) { ClipboardHelper.SetClipboardData(fullPath); } }
/// <summary> /// Upload the capture to Photobucket /// </summary> /// <param name="captureDetails"></param> /// <param name="surfaceToUpload">ISurface</param> /// <param name="uploadURL">out string for the url</param> /// <returns>true if the upload succeeded</returns> public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, string albumPath, out string uploadURL) { SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, config.UploadReduceColors); try { string filename = Path.GetFileName(FilenameHelper.GetFilename(config.UploadFormat, captureDetails)); PhotobucketInfo photobucketInfo = null; // Run upload in the background new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("photobucket", LangKey.communication_wait), delegate() { photobucketInfo = PhotobucketUtils.UploadToPhotobucket(surfaceToUpload, outputSettings, albumPath, captureDetails.Title, filename); } ); // This causes an exeption if the upload failed :) LOG.DebugFormat("Uploaded to Photobucket page: " + photobucketInfo.Page); uploadURL = null; try { if (config.UsePageLink) { uploadURL = photobucketInfo.Page; Clipboard.SetText(photobucketInfo.Page); } else { uploadURL = photobucketInfo.Original; Clipboard.SetText(photobucketInfo.Original); } } catch (Exception ex) { LOG.Error("Can't write to clipboard: ", ex); } return true; } catch (Exception e) { LOG.Error(e); MessageBox.Show(Language.GetString("photobucket", LangKey.upload_failure) + " " + e.Message); } uploadURL = null; return false; }
/// <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, SurfaceOutputSettings outputSettings) { string pattern = conf.OutputFileFilenamePattern; if (pattern == null || string.IsNullOrEmpty(pattern.Trim())) { pattern = "greenshot ${capturetime}"; } string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails); // Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML filename = Regex.Replace(filename, @"[^\d\w\.]", "_"); // Remove multiple "_" filename = Regex.Replace(filename, @"_+", "_"); string tmpFile = Path.Combine(Path.GetTempPath(), filename); LOG.Debug("Creating TMP File: " + tmpFile); // 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 { 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 = SaveWithDialog(surface, captureDetails); } return tmpFile; }
public bool Upload(ICaptureDetails captureDetails, ISurface surface, out String uploadUrl) { SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); uploadUrl = null; try { string flickrUrl = null; new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("flickr", LangKey.communication_wait), delegate { string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); flickrUrl = FlickrUtils.UploadToFlickr(surface, outputSettings, captureDetails.Title, filename); } ); if (flickrUrl == null) { return false; } uploadUrl = flickrUrl; if (_config.AfterUploadLinkToClipBoard) { ClipboardHelper.SetClipboardData(flickrUrl); } return true; } catch (Exception e) { LOG.Error("Error uploading.", e); MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message); } return false; }
/// <summary> /// Saves image to stream with specified quality /// To prevent problems with GDI version of before Windows 7: /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used. /// </summary> /// <param name="imageToSave">image to save</param> /// <param name="surface">surface for the elements, needed if the greenshot format is used</param> /// <param name="stream">Stream to save to</param> /// <param name="outputSettings">SurfaceOutputSettings</param> public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) { ImageFormat imageFormat = null; bool useMemoryStream = false; MemoryStream memoryStream = null; if (outputSettings.Format == OutputFormat.greenshot && surface == null) { throw new ArgumentException("Surface needs to be se when using OutputFormat.Greenshot"); } try { switch (outputSettings.Format) { case OutputFormat.bmp: imageFormat = ImageFormat.Bmp; break; case OutputFormat.gif: imageFormat = ImageFormat.Gif; break; case OutputFormat.jpg: imageFormat = ImageFormat.Jpeg; break; case OutputFormat.tiff: imageFormat = ImageFormat.Tiff; break; case OutputFormat.greenshot: case OutputFormat.png: default: // Problem with non-seekable streams most likely doesn't happen with Windows 7 (OS Version 6.1 and later) // http://stackoverflow.com/questions/8349260/generic-gdi-error-on-one-machine-but-not-the-other if (!stream.CanSeek) { int majorVersion = Environment.OSVersion.Version.Major; int minorVersion = Environment.OSVersion.Version.Minor; if (majorVersion < 6 || (majorVersion == 6 && minorVersion == 0)) { useMemoryStream = true; LOG.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); } } imageFormat = ImageFormat.Png; break; } 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 a issue which happens with Windows before "7". // The save is made to the targetStream, this is directed to either the MemoryStream or the original Stream targetStream = stream; if (useMemoryStream) { memoryStream = new MemoryStream(); targetStream = memoryStream; } if (imageFormat == ImageFormat.Jpeg) { bool foundEncoder = false; foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders()) { if (imageCodec.FormatID == imageFormat.Guid) { EncoderParameters parameters = new EncoderParameters(1); parameters.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(); nonAlphaImage = null; } 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 { // Removing transparency if it's not supported in the output if (imageFormat != ImageFormat.Png && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) { Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); AddTag(nonAlphaImage); nonAlphaImage.Save(targetStream, imageFormat); nonAlphaImage.Dispose(); nonAlphaImage = null; } else { AddTag(imageToSave); imageToSave.Save(targetStream, imageFormat); } } // If we used a memory stream, we need to stream the memory stream to the original stream. if (useMemoryStream) { memoryStream.WriteTo(stream); } // Output the surface elements, size and marker to the stream if (outputSettings.Format == OutputFormat.greenshot) { 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(String.Format("Greenshot{0:00}.{1:00}", v.Major, v.Minor)); writer.Write(marker); tmpStream.WriteTo(stream); } } } } finally { if (memoryStream != null) { memoryStream.Dispose(); } } }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surfaceToUpload, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description); string filename = Path.GetFileName(FilenameHelper.GetFilename(config.UploadFormat, captureDetails)); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, config.UploadReduceColors); if (jira != null) { try { // Run upload in the background new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), delegate() { jiraPlugin.JiraConnector.addAttachment(jira.Key, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename)); } ); LOG.Debug("Uploaded to Jira."); exportInformation.ExportMade = true; // TODO: This can't work: exportInformation.Uri = surfaceToUpload.UploadURL; } catch (Exception e) { MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); } } else { JiraForm jiraForm = new JiraForm(jiraPlugin.JiraConnector); if (jiraPlugin.JiraConnector.isLoggedIn) { jiraForm.setFilename(filename); DialogResult result = jiraForm.ShowDialog(); if (result == DialogResult.OK) { try { // Run upload in the background new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), delegate() { jiraForm.upload(new SurfaceContainer(surfaceToUpload, outputSettings, filename)); } ); LOG.Debug("Uploaded to Jira."); exportInformation.ExportMade = true; // TODO: This can't work: exportInformation.Uri = surfaceToUpload.UploadURL; } catch(Exception e) { MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); } } } } ProcessExport(exportInformation, surfaceToUpload); return exportInformation; }
/// <summary> /// Helper method to create a temp image file /// </summary> /// <param name="image"></param> /// <returns></returns> public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath) { string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format.ToString(); // Prevent problems with "other characters", which could cause problems tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", ""); if (destinationPath == null) { destinationPath = Path.GetTempPath(); } string tmpPath = Path.Combine(destinationPath, tmpFile); LOG.Debug("Creating TMP File : " + tmpPath); try { Save(surface, tmpPath, true, outputSettings, false); tmpFileCache.Add(tmpPath, tmpPath); } catch (Exception) { return null; } return tmpPath; }
/// <summary> /// Export the capture to the specified page /// </summary> /// <param name="oneNoteApplication">IOneNoteApplication</param> /// <param name="surfaceToUpload">ISurface</param> /// <param name="page">OneNotePage</param> /// <returns>bool true if everything worked</returns> private static bool ExportToPage(IOneNoteApplication oneNoteApplication, ISurface surfaceToUpload, OneNotePage page) { if(oneNoteApplication == null) { return false; } using (MemoryStream pngStream = new MemoryStream()) { SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings); string base64String = Convert.ToBase64String(pngStream.GetBuffer()); string imageXmlStr = string.Format(XML_IMAGE_CONTENT, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height); string pageChangesXml = string.Format(XML_OUTLINE, new object[] { imageXmlStr, page.ID, ONENOTE_NAMESPACE_2010, page.Name }); LOG.InfoFormat("Sending XML: {0}", pageChangesXml); oneNoteApplication.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false); try { oneNoteApplication.NavigateTo(page.ID, null, false); } catch(Exception ex) { LOG.Warn("Unable to navigate to the target page", ex); } return true; } }
/// <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; using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails)) { DialogResult dialogResult = saveImageFileDialog.ShowDialog(); if (dialogResult.Equals(DialogResult.OK)) { try { string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension; SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension)); if (conf.OutputFilePromptQuality) { QualityDialog qualityDialog = new QualityDialog(outputSettings); qualityDialog.ShowDialog(); } // TODO: For now we always overwrite, should be changed Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard); returnValue = fileNameWithExtension; IniConfig.Save(); } catch (ExternalException) { MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error")); } } } return returnValue; }