Initial Commit
This commit is contained in:
205
Common/Auxiliary/ScreenshotHelper.cs
Normal file
205
Common/Auxiliary/ScreenshotHelper.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Threading;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Common.Auxiliary
|
||||
{
|
||||
internal static class ScreenshotHelper
|
||||
{
|
||||
/// <summary>Gets the encoder by extension</summary>
|
||||
/// <param name="extension">The extension</param>
|
||||
/// <returns>BitmapEncoder object</returns>
|
||||
internal static BitmapEncoder GetEncoderByExtension(string extension)
|
||||
{
|
||||
switch (extension)
|
||||
{
|
||||
case "bmp":
|
||||
return new BmpBitmapEncoder();
|
||||
case "jpg":
|
||||
return new JpegBitmapEncoder();
|
||||
case "gif":
|
||||
return new GifBitmapEncoder();
|
||||
case "png":
|
||||
return new PngBitmapEncoder();
|
||||
case "tiff":
|
||||
return new TiffBitmapEncoder();
|
||||
case "wmp":
|
||||
return new WmpBitmapEncoder();
|
||||
default:
|
||||
throw new ArgumentException(Strings.Exceptions.CannotDetermineImageTypeByExtension, "extension");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates the screenshot of entire plotter element</summary>
|
||||
/// <returns></returns>
|
||||
internal static BitmapSource CreateScreenshot(UIElement uiElement, Int32Rect screenshotSource)
|
||||
{
|
||||
Window window = Window.GetWindow(uiElement);
|
||||
if (window == null)
|
||||
{
|
||||
return CreateElementScreenshot(uiElement);
|
||||
}
|
||||
Size size = window.RenderSize;
|
||||
|
||||
//double dpiCoeff = 32 / SystemParameters.CursorWidth;
|
||||
//int dpi = (int)(dpiCoeff * 96);
|
||||
double dpiCoeff = 1;
|
||||
int dpi = 96;
|
||||
|
||||
RenderTargetBitmap bmp = new RenderTargetBitmap(
|
||||
(int)(size.Width * dpiCoeff), (int)(size.Height * dpiCoeff),
|
||||
dpi, dpi, PixelFormats.Default);
|
||||
|
||||
// white background
|
||||
Rectangle whiteRect = new Rectangle { Width = size.Width, Height = size.Height, Fill = Brushes.White };
|
||||
whiteRect.Measure(size);
|
||||
whiteRect.Arrange(new Rect(size));
|
||||
bmp.Render(whiteRect);
|
||||
// the very element
|
||||
bmp.Render(uiElement);
|
||||
|
||||
CroppedBitmap croppedBmp = new CroppedBitmap(bmp, screenshotSource);
|
||||
return croppedBmp;
|
||||
}
|
||||
|
||||
private static BitmapSource CreateElementScreenshot(UIElement uiElement)
|
||||
{
|
||||
bool measureValid = uiElement.IsMeasureValid;
|
||||
|
||||
if (!measureValid)
|
||||
{
|
||||
double width = 300;
|
||||
double height = 300;
|
||||
|
||||
FrameworkElement frElement = uiElement as FrameworkElement;
|
||||
if (frElement != null)
|
||||
{
|
||||
if (!Double.IsNaN(frElement.Width))
|
||||
width = frElement.Width;
|
||||
if (!Double.IsNaN(frElement.Height))
|
||||
height = frElement.Height;
|
||||
}
|
||||
|
||||
Size size = new Size(width, height);
|
||||
uiElement.Measure(size);
|
||||
uiElement.Arrange(new Rect(size));
|
||||
}
|
||||
|
||||
RenderTargetBitmap bmp = new RenderTargetBitmap(
|
||||
(int)uiElement.RenderSize.Width, (int)uiElement.RenderSize.Height,
|
||||
96, 96, PixelFormats.Default);
|
||||
|
||||
// this is waiting for dispatcher to perform measure, arrange and render passes
|
||||
uiElement.Dispatcher.Invoke(((Action)(() => { })), DispatcherPriority.Background);
|
||||
|
||||
Size elementSize = uiElement.DesiredSize;
|
||||
// white background
|
||||
Rectangle whiteRect = new Rectangle { Width = elementSize.Width, Height = elementSize.Height, Fill = Brushes.White };
|
||||
whiteRect.Measure(elementSize);
|
||||
whiteRect.Arrange(new Rect(elementSize));
|
||||
bmp.Render(whiteRect);
|
||||
|
||||
bmp.Render(uiElement);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
private static Dictionary<BitmapSource, string> pendingBitmaps = new Dictionary<BitmapSource, string>();
|
||||
|
||||
internal static void SaveBitmapToStream(BitmapSource bitmap, Stream stream, string fileExtension)
|
||||
{
|
||||
if (bitmap == null)
|
||||
throw new ArgumentNullException("bitmap");
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException("stream");
|
||||
if (String.IsNullOrEmpty(fileExtension))
|
||||
throw new ArgumentException(Strings.Exceptions.ExtensionCannotBeNullOrEmpty, fileExtension);
|
||||
|
||||
BitmapEncoder encoder = ScreenshotHelper.GetEncoderByExtension(fileExtension);
|
||||
encoder.Frames.Add(BitmapFrame.Create(bitmap, null, new BitmapMetadata(fileExtension.Trim('.')), null));
|
||||
encoder.Save(stream);
|
||||
}
|
||||
|
||||
internal static void SaveBitmapToFile(BitmapSource bitmap, string filePath)
|
||||
{
|
||||
if (String.IsNullOrEmpty(filePath))
|
||||
throw new ArgumentException(Strings.Exceptions.FilePathCannotbeNullOrEmpty, "filePath");
|
||||
|
||||
if (bitmap.IsDownloading)
|
||||
{
|
||||
pendingBitmaps[bitmap] = filePath;
|
||||
bitmap.DownloadCompleted += OnBitmapDownloadCompleted;
|
||||
return;
|
||||
}
|
||||
|
||||
string dirPath = System.IO.Path.GetDirectoryName(filePath);
|
||||
if (!String.IsNullOrEmpty(dirPath) && !Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
bool fileExistedBefore = File.Exists(filePath);
|
||||
try
|
||||
{
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
string extension = System.IO.Path.GetExtension(filePath).TrimStart('.');
|
||||
SaveBitmapToStream(bitmap, fs, extension);
|
||||
}
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
if (!fileExistedBefore && File.Exists(filePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch (IOException exc)
|
||||
{
|
||||
Debug.WriteLine("Exception while saving bitmap to file: " + exc.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveStreamToFile(Stream stream, string filePath)
|
||||
{
|
||||
string dirPath = System.IO.Path.GetDirectoryName(filePath);
|
||||
if (!String.IsNullOrEmpty(dirPath) && !Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
string extension = System.IO.Path.GetExtension(filePath).TrimStart('.');
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
private static void OnBitmapDownloadCompleted(object sender, EventArgs e)
|
||||
{
|
||||
BitmapSource bmp = (BitmapSource)sender;
|
||||
bmp.DownloadCompleted -= OnBitmapDownloadCompleted;
|
||||
string filePath = pendingBitmaps[bmp];
|
||||
pendingBitmaps.Remove(bmp);
|
||||
|
||||
SaveBitmapToFile(bmp, filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user