How can I return the image? - c#

It is created by a coordinate system with the two codesnippets listed below. Unfortunately, the second code snippet saves the image to the desktop. I would like to have the "image" returned. How can I return the image of the coordinate system? ( I have a method which has a return value as a picture )
At the end it should be preview = image;
So that from the coordinate system an "image" and not to the desktop is stored, but I can return it.
var stream = new MemoryStream();
var pngExporter = new PngExporter { Width = 600, Height = 400, Background = OxyColors.White };
pngExporter.Export(plotModel, stream);
preview = stream; //Does not work unfortunately
var pngExporter = new PngExporter { Width = 350, Height = 350, Background = OxyColors.White };
pngExporter.ExportToFile(plotModel, #"C:\Users\user\Desktop\test.png");
public bool createPreview(out string errorMessage, out System.Drawing.Image preview, int pWidth, int pHeight, int pMargin)
{
errorMessage = null;
preview = null;
bool folded = false;
try
{
PlotModel plotModel = new PlotModel { Title = "Vorschaukomponente" };
plotModel.Axes.Add(new OxyPlot.Axes.LinearAxis { Position = OxyPlot.Axes.AxisPosition.Bottom, MinimumPadding = 0.1, MaximumPadding = 0.1 });
plotModel.Axes.Add(new OxyPlot.Axes.LinearAxis { Position = OxyPlot.Axes.AxisPosition.Left, MinimumPadding = 0.1, MaximumPadding = 0.1 });
var series1 = new OxyPlot.Series.LineSeries
{
LineStyle = LineStyle.None,
MarkerType = MarkerType.Circle,
MarkerSize = 2,
MarkerFill = OxyColors.Transparent,
MarkerStroke = OxyColors.Black,
MarkerStrokeThickness = 1
};
if (pointX.Count == pointY.Count)
{
for (int i = 0; i < pointX.Count; i++)
{
for (int g = i; g < pointY.Count; g++)
{
series1.Points.Add(new DataPoint(pointX[i], pointY[g]));
Console.WriteLine(i+1 + " | "+ pointX[i].ToString() + "/" + pointY[g]);
break;
}
}
series1.Smooth = true;
plotModel.Series.Add(series1);
try
{
var stream = new MemoryStream();
var pngExporter = new PngExporter { Width = 600, Height = 400, Background = OxyColors.White };
pngExporter.Export(plotModel, stream);
preview = stream;
// var pngExporter = new PngExporter { Width = 350, Height = 350, Background = OxyColors.White };
// pngExporter.ExportToFile(plotModel, #"C:\Users\user\Desktop\test.png");
folded = true;
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine(exc.Message);
errorMessage = "Es konnt kein Bild erstellt werden.";
folded = false;
}
}
else
{
errorMessage = "Es ist nicht die gleiche Anzahl von xen und yen vorhanden.";
folded = false;
}
}
catch (Exception)
{
errorMessage= "Es trat ein unerwarteter Fehler auf";
folded = false;
}
return folded;
}

First of all, i suggest you to use System.Windows.Media.Imaging.BitmapImage rather than System.Drawing.Image since you are in the WPF-World.
After you changed that, you can easily write
preview.BeginInit();
preview.StreamSource = stream;
preview.EndInit();
after the PngExporter did its job.
Unfortunately i cannot test it since i dont have your pointX and pointY - Collections.
Let me know if that helps

Looks like you want Image.FromStream(stream)

Related

c# chart to image with LiveCharts

i have a little problem. I want to export to an image my charts. I known that is possible with the code given by beto-rodriguez (here).
But i have a problem, i can't have what i could have by displaying it in the screen. See the image above. On the bottom right, i have the image saved in png. And in the left of the image, i have the chart with all the parameters displayed where i want.
Do you known if it's possible to have the same chart (in the left) in the saved image ?
Actually, i use a thread to capture (copy/paste) the image automatically.
Do you known what are the parameters i must set on to have the correct image ?
Double chart
Thanks in advance.
Regards.
********************************* After edit
Sorry for my late repsonse. I try what you said but unfornately I can't made that i want.
I will explain what i do:
I have a class "MakeReport" who can call another class "GraphMaker" with:
MyGraph = new GraphMaker();
MyGraph = GiveAGraph(MyGraph);
And the class "MakeReport" will complete the chart with some values with the sub-program "GiveAGraph()":
GraphData.SeriesCollection.Add(new RowSeries
{
Title = Criteria,
Values = DataValues,
ScalesYAt = Index,
DataLabels = true
});
End of "GiveAGRaph()".
Now I have a chart ready to display, i want to use it to make an image and for test (and debug) i show it:
// Chart to Image
MyGraph.GiveMeAnImageFromChart(); <-- to make a picture with the chart
// Show the graph
MyGraph.Show(); <-- for debug and test, i display it.
With "MyGraph.GiveAnImageFromChart()", i don't have the same result than "MyGraph.Show()". The picture (save as png) is different to the displayed chart.
The sub-program "GiveAnImageFromChart" included in the "GraphMaker" class is :
public void GiveMeAnImageFromChart()
{
var viewbox = new Viewbox();
myChart.Background = Brushes.White;
myChart.DataContext = this;
// myChart il faut tout mettre en paramètres
viewbox.Child = myChart;
viewbox.Measure(myChart.RenderSize);
viewbox.Arrange(new Rect(new Point(0, 0), myChart.RenderSize));
myChart.Update(true, true); //force chart redraw
viewbox.UpdateLayout();
SaveToPng(myChart, "chart.png");
//png file was created at the root directory.
}
The "myChart" variable is public. The "SaveToPng" program used come from your example (here).
To save the picture, i try with the following method :
public System.Drawing.Bitmap ControlToImage(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
// render control content
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
Console.WriteLine("Bounds width = " + bounds.Width + " et bounds height = " + bounds.Height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), bounds.Size));
}
rtb.Render(dv);
//convert image format
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(stream);
return new System.Drawing.Bitmap(stream);
}
With :
Bitmap ImageChart = MyGraph.ControlToImage(MyGraph, MyGraph.Width, MyGraph.Height);
With this method, i have an error because the "bounds.Width" and "bounds.Height" are equal to -8. And finally, i don't have any chart to convert.
I think i give a wrong "visual Target" in the "ControlImage" and I miss something but i don't know what. If you need more information, ask me.
Thanks in advance for your help.
PS: sorry for my english. Don't hesitate to correct me.
thanks to bto-rdz, i made a solution. I found that i didn't use Livecharts correctly.
So i post my code if someone need it.
This is my GraphMaker.xaml file:
<UserControl x:Class="MyProject.GraphMaker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
d:DesignHeight="730" d:DesignWidth="1660">
<Grid>
</Grid>
</UserControl>
And my GraphMaker.xaml.cs file
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using LiveCharts;
using LiveCharts.Wpf;
using System.Collections.Generic;
using System.ComponentModel;
namespace MyProject
{
public partial class GraphMaker : UserControl
{
// PUBLIC
public CartesianChart MyTestChart;
public SeriesCollection MySeriesCollection { get; set; }
public string[] Labels { get; set; }
public string AxisTitle { get; set; }
public Func<double, string> YFormatter { get; set; }
public Axis Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, Axis8, Axis9, Axis10, AxisXChart;
public GraphMaker()
{
InitializeComponent();
MySeriesCollection = new SeriesCollection();
MyTestChart = new CartesianChart
{
DisableAnimations = true,
Width = 1600,
Height = 700,
Series = MySeriesCollection
};
MyTestChart.LegendLocation = LegendLocation.Right;
// *** Axis 1 ***
Axis1 = new Axis();
Axis1.Foreground = Brushes.DodgerBlue;
Axis1.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis1.LabelFormatter = YFormatter;
MyTestChart.AxisY.Add(Axis1);
// *** Axis 2 ***
Axis2 = new Axis();
Axis2.Foreground = Brushes.IndianRed;
Axis2.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis2.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis2);
// *** Axis 3 ***
Axis3 = new Axis();
Axis3.Foreground = Brushes.Gold;
Axis3.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis3.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis3);
// *** Axis 4 ***
Axis4 = new Axis();
Axis4.Foreground = Brushes.Gray;
Axis4.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis4.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis4);
// *** Axis 5 ***
Axis5 = new Axis();
Axis5.Foreground = Brushes.DeepSkyBlue;
Axis5.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis5.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis5);
// *** Axis 6 ***
Axis6 = new Axis();
Axis6.Foreground = Brushes.HotPink;
Axis6.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis6.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis6);
// *** Axis 7 ***
Axis7 = new Axis();
Axis7.Foreground = Brushes.Orange;
Axis7.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis7.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis7);
// *** Axis 8 ***
Axis8 = new Axis();
Axis8.Foreground = Brushes.RoyalBlue;
Axis8.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis8.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis8);
// *** Axis 9 ***
Axis9 = new Axis();
Axis9.Foreground = Brushes.Black;
Axis9.Position = AxisPosition.RightTop;
Axis9.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis9);
// *** Axis 10 ***
Axis10 = new Axis();
Axis10.Foreground = Brushes.DarkTurquoise;
Axis10.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis10.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis10);
AxisXChart = new Axis();
AxisXChart.Title = AxisTitle;
AxisXChart.Labels = Labels;
}
public void TakeTheChart()
{
var viewbox = new Viewbox();
viewbox.Child = MyTestChart;
viewbox.Measure(MyTestChart.RenderSize);
viewbox.Arrange(new Rect(new Point(0, 0), MyTestChart.RenderSize));
MyTestChart.Update(true, true); //force chart redraw
viewbox.UpdateLayout();
SaveToPng(MyTestChart, "Chart.png");
//png file was created at the root directory.
}
public void SaveToPng(FrameworkElement visual, string fileName)
{
var encoder = new PngBitmapEncoder();
EncodeVisual(visual, fileName, encoder);
}
private static void EncodeVisual(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
var bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
var frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName)) encoder.Save(stream);
}
}
}
Hope to help you.
Have a nice day. Bye.
The sample you pointed, is created a new chart instance in memory, that is why you are getting a different image, you could, reproduce the same properties in both charts, the one presented in the UI, and the one you are creating in memory, or you could just print the the current instance in the UI, as explained in this issue:
https://github.com/beto-rodriguez/Live-Charts/issues/243
Hope it helps
I have wrote extension method to save as image from cartesian chart for windows form. It can be edit your own way to get best one.
public static bool ChartToImage(this LiveCharts.WinForms.CartesianChart cartesianChart, LineSeries data, Axis AxisX, Axis AxisY,double Width, double Height, string fileName, string targetPath, out string locationOfImage, out Exception returnEx)
{
bool status = false;
returnEx = null;
locationPath = null;
try
{
var myChart = new LiveCharts.Wpf.CartesianChart
{
DisableAnimations = true,
Width = Width,
Height = Height,
Series = new SeriesCollection(cartesianChart.Series.Configuration)
{
new LineSeries
{
Title = data.Title,
LineSmoothness = data.LineSmoothness,
StrokeThickness = data.StrokeThickness,
PointGeometrySize = data.PointGeometrySize,
Stroke = data.Stroke,
Values=data.Values
}
}
};
myChart.AxisX.Add(new Axis { IsMerged = AxisX.IsMerged, FontSize = AxisX.FontSize, FontWeight = AxisX.FontWeight, Foreground = AxisX.Foreground, Separator = new LiveCharts.Wpf.Separator { Step = AxisX.Separator.Step, StrokeThickness = AxisX.Separator.StrokeThickness, StrokeDashArray = AxisX.Separator.StrokeDashArray, Stroke = AxisX.Separator.Stroke }, Title = AxisX.Title, MinValue = AxisX.MinValue, MaxValue = AxisX.MaxValue });
myChart.AxisY.Add(new Axis { IsMerged = AxisY.IsMerged, FontSize = AxisY.FontSize, FontWeight = AxisY.FontWeight, Foreground = AxisY.Foreground, Separator = new LiveCharts.Wpf.Separator { Step = AxisY.Separator.Step, StrokeThickness = AxisY.Separator.StrokeThickness, StrokeDashArray = AxisY.Separator.StrokeDashArray, Stroke = AxisX.Separator.Stroke }, Title = AxisY.Title, MinValue = AxisY.MinValue, MaxValue = AxisY.MaxValue });
var viewbox = new Viewbox();
viewbox.Child = myChart;
viewbox.Measure(myChart.RenderSize);
viewbox.Arrange(new Rect(new System.Windows.Point(0, 0), myChart.RenderSize));
myChart.Update(true, true); //force chart redraw
viewbox.UpdateLayout();
var encoder = new PngBitmapEncoder();
var bitmap = new RenderTargetBitmap((int)myChart.ActualWidth, (int)myChart.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(myChart);
var frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
string path = Path.Combine(targetPath, fileName);
using (var stream = File.Create(path))
{
encoder.Save(stream);
locationPath = path;
}
myChart = null;
viewbox = null;
encoder = null;
bitmap = null;
frame = null;
status = true;
}
catch (Exception ex)
{
returnEx = ex;
status = false;
}
return status;
}
On your main program :
if(cartesianChart1.ChartToImage(data,axisX,axisY,600,200,"test.png", locationImage, out string locationOfFile, out Exception returnEx))
{
System.Windows.Forms.MessageBox.Show(locationOfFile);
}

How can an animation be added properly to a CALayer when using AVAssetExportSession in Xamarin.ios?

I need your help regarding an animation I want to apply to an overlay image I add to a mp4 video. To add an overlay on a video, I followed Ray Wenderlich tutorials here: https://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos. At the end of that link, an animation is created on an overlay.
Ray Wenderlich is not coding with c# but I do since I use Xamarin to create my app.
Using the animation, the overlay is supposed to fade away during the very first seconds of the video. But nothing happens. I mean nothing animated happens except for the video: the overlay is well put on top of the video but it does not fade away.
Most of the posts I read about animations and CALayer create an animation within a UIView.
So I am asking myself: is the animation not working because I use c# or did I write something wrong?
Can somebody help me with this, please?
This is the function I wrote:
public static void addFadeOverlayAtTheBeginning (NSUrl source, String overlay, long secondsToFade, NSUrl destination)
{
AVUrlAsset videoAsset = new AVUrlAsset(source);
if (secondsToFade > videoAsset.Duration.Seconds)
secondsToFade = (long)videoAsset.Duration.Seconds;
CALayer overlayLayer = CALayer.Create();
UIImage image = new UIImage(overlay);
image.CreateResizableImage(new UIEdgeInsets(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height));
overlayLayer.Contents = image.CGImage;
overlayLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height);
overlayLayer.MasksToBounds = true;
CABasicAnimation animation = CABasicAnimation.FromKeyPath(#"opacity");
animation.BeginTime = 0; // GetSeconds(image.CGImage.StartTime);
animation.Duration = secondsToFade;
animation.SetFrom (NSNumber.FromFloat (1));
animation.SetTo (NSNumber.FromFloat(0));
overlayLayer.AddAnimation(animation, #"opacity");
AVMutableComposition videoComposition = AVMutableComposition.Create();
AVMutableCompositionTrack track = videoComposition.AddMutableTrack(AVMediaType.Video, 0);
AVAssetTrack sourceVideoTrack = videoAsset.TracksWithMediaType(AVMediaType.Video)[0];
CMTimeRange timeRangeInAsset = new CMTimeRange();
timeRangeInAsset.Start = CMTime.Zero;
timeRangeInAsset.Duration = videoAsset.Duration;
NSError videoInsertError = null;
track.InsertTimeRange(timeRangeInAsset, sourceVideoTrack, CMTime.Zero, out videoInsertError);
track.PreferredTransform = sourceVideoTrack.PreferredTransform;
CALayer parentLayer = CALayer.Create();
CALayer videoLayer = CALayer.Create();
parentLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height);
videoLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height);
parentLayer.AddSublayer(videoLayer);
parentLayer.AddSublayer(overlayLayer);
//parentLayer.AddAnimation(animation, "opacity");
AVMutableVideoComposition animationComposition = AVMutableVideoComposition.Create(); //videoComposition
animationComposition.AnimationTool = AVVideoCompositionCoreAnimationTool.FromLayer(videoLayer, parentLayer);
animationComposition.RenderSize = videoAsset.NaturalSize;
animationComposition.FrameDuration = new CMTime(1, 30);
AVMutableVideoCompositionInstruction instruction = AVMutableVideoCompositionInstruction.Create() as AVMutableVideoCompositionInstruction;
CMTimeRange timeRangeInstruction = new CMTimeRange();
timeRangeInstruction.Start = CMTime.Zero;
timeRangeInstruction.Duration = videoComposition.Duration;
instruction.TimeRange = timeRangeInstruction;
AVMutableVideoCompositionLayerInstruction layerInstruction = AVMutableVideoCompositionLayerInstruction.FromAssetTrack(track);
CMTimeRange timeRangeFading = new CMTimeRange();
timeRangeFading.Start = CMTime.Zero;
timeRangeFading.Duration = new CMTime(secondsToFade, 1);
//layerInstruction.SetOpacityRamp(1, 0, timeRangeFading);
instruction.LayerInstructions = new AVVideoCompositionLayerInstruction[] { layerInstruction };
List<AVVideoCompositionInstruction> instructions = new List<AVVideoCompositionInstruction>();
instructions.Add(instruction);
animationComposition.Instructions = instructions.ToArray();
if (File.Exists(destination.Path))
File.Delete(destination.Path);
AVAssetExportSession exporter = new AVAssetExportSession(videoComposition, AVAssetExportSession.PresetHighestQuality);
exporter.OutputUrl = destination;
exporter.VideoComposition = animationComposition;
exporter.OutputFileType = AVFileType.Mpeg4;
exporter.ExportAsynchronously(() => {
VideoManagement.state ++;
AVAssetExportSessionStatus status = exporter.Status;
Console.WriteLine("addFadeOverlayAtTheBeginning Done. Status: " + status.ToString());
switch (status)
{
case AVAssetExportSessionStatus.Completed:
Console.WriteLine("Sucessfully Completed");
if (File.Exists(destination.Path))
{
Console.WriteLine(String.Format("Saved to {0}", destination.Path));
}
else
Console.WriteLine("Failed");
break;
case AVAssetExportSessionStatus.Cancelled:
break;
case AVAssetExportSessionStatus.Exporting:
break;
case AVAssetExportSessionStatus.Failed:
Console.WriteLine("Task failed => {0}", exporter.Error);
Console.WriteLine(exporter.Error.Description);
break;
case AVAssetExportSessionStatus.Unknown:
break;
case AVAssetExportSessionStatus.Waiting:
break;
default:
break;
}
});
}
OK. Found it.
Apparently, animation.BeginTime = 0; is not supported. I changed it to 0.01 and everything works fine.
double Epsilon = 0.01;
if (secondsToFade > videoAsset.Duration.Seconds - Epsilon)
secondsToFade = videoAsset.Duration.Seconds - Epsilon;
CALayer overlayLayer = CALayer.Create();
UIImage image = new UIImage(overlay);
image.CreateResizableImage(new UIEdgeInsets(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height));
overlayLayer.Contents = image.CGImage;
overlayLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height);
overlayLayer.MasksToBounds = true;
//On crée l'animation pour le CAlayer
CABasicAnimation animation = CABasicAnimation.FromKeyPath(#"opacity");
animation.BeginTime = Epsilon;
animation.Duration = secondsToFade;
animation.SetFrom (NSNumber.FromFloat (1));
animation.SetTo (NSNumber.FromFloat(0));
animation.FillMode = CAFillMode.Forwards;
animation.RemovedOnCompletion = false;

How to save WebViewBrush as image? (UWP / Universal)

Summary: I have a collection FrameworkElements (basically web view brushes drawn on rectanlges), and I'd like to save each of these as a PNG file in my UWP app.
More details: I followed the example at https://stackoverflow.com/a/17222629/2884981 to split the content of a WebView into separate "pages".
I've put the main bits of code at the bottom.
At the bottom of GetWebPages() I have return pages;
At this point I have a list of all the "pages".
What I'd like to do, is then convert each of those pages into an image (so by the end of it I'd have a collection of PNG files, for instance).
Does anyone know how I can do this? Thanks in advance.
public async Task<WebViewBrush> GetWebViewBrush(WebView webView)
{
// resize width to content
double originalWidth = webView.Width;
var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthString, out contentWidth))
{
throw new Exception(string.Format("failure/width:{0}", widthString));
}
webView.Width = contentWidth;
// resize height to content
double originalHeight = webView.Height;
var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightString, out contentHeight))
{
throw new Exception(string.Format("failure/height:{0}", heightString));
}
webView.Height = contentHeight;
// create brush
var originalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
WebViewBrush brush = new WebViewBrush
{
SourceName = webView.Name,
Stretch = Stretch.Uniform
};
brush.Redraw();
// reset, return
webView.Width = originalWidth;
webView.Height = originalHeight;
webView.Visibility = originalVisibilty;
return brush;
}
And:
public async Task<IEnumerable<FrameworkElement>> GetWebPages(WebView webView, Windows.Foundation.Size page)
{
// ask the content its width
var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthString, out contentWidth))
{
throw new Exception(string.Format("failure/width:{0}", widthString));
}
webView.Width = contentWidth;
// ask the content its height
var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightString, out contentHeight))
{
throw new Exception(string.Format("failure/height:{0}", heightString));
}
webView.Height = contentHeight;
// how many pages will there be?
double scale = page.Width / contentWidth;
double scaledHeight = (contentHeight * scale);
double pageCount = (double) scaledHeight / page.Height;
pageCount = pageCount + ((pageCount > (int) pageCount) ? 1 : 0);
// create the pages
var pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)pageCount; i++)
{
var translateY = -page.Height * i;
var rectanglePage = new Windows.UI.Xaml.Shapes.Rectangle
{
Height = page.Height,
Width = page.Width,
Margin = new Thickness(5),
Tag = new TranslateTransform { Y = translateY },
};
rectanglePage.Loaded += (async (s, e) =>
{
var subRectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var subBrush = await GetWebViewBrush(webView);
subBrush.Stretch = Stretch.UniformToFill;
subBrush.AlignmentY = AlignmentY.Top;
subBrush.Transform = subRectangle.Tag as TranslateTransform;
subRectangle.Fill = subBrush;
});
pages.Add(rectanglePage);
}
return pages;
}
I'd like to save each of these as a PNG file in my UWP app.
You can get all the rectangles and show them in the ItemsControl in the NavigationCompleted event of WebView like this:
private async void webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
MyWebViewRectangle.Fill = await GetWebViewBrush(webView);
MyPrintPages.ItemsSource = await GetWebPages(webView, new Windows.Foundation.Size(842, 595));
}
Then in a button click event you can save all the items as .png images like this:
private async void Savetoimage_Clicked(object sender, RoutedEventArgs e)
{
var piclib = Windows.Storage.KnownFolders.PicturesLibrary;
foreach (var item in MyPrintPages.Items)
{
var rect = item as Rectangle;
RenderTargetBitmap renderbmp = new RenderTargetBitmap();
await renderbmp.RenderAsync(rect);
var pixels = await renderbmp.GetPixelsAsync();
var file = await piclib.CreateFileAsync("webview.png", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)rect.Width, (uint)rect.Height,
0, 0, bytes);
await encoder.FlushAsync();
}
}
}

How To Customize MVC Chart Legend?

I have drawn an MVC chart.
Just wanted to know how to achieve circular series name.
Please help. My code is below:
public ActionResult CreateBar()
{
// Create OnPremise and Azure Output Models
var objOnPremiseOutPut = new OnPremisesOutputModel();
var objAzureOutPut = new AzureCostOutputModel();
// Get the data from the TempData. Check :: What if the TemData is empty ??
objOnPremiseOutPut = (OnPremisesOutputModel)TempData["TotalOnPremiseCost"];
objAzureOutPut = (AzureCostOutputModel)TempData["TotalAzureCost"];
// Create a new chart Object
var chart = new Chart();
// Set Dimensions of chart
chart.Width = 500;
chart.Height = 350;
// Set Color and Background color properties
chart.BackColor = Color.WhiteSmoke;//Color.FromArgb(255, 255, 255);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackSecondaryColor = Color.White;
//chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 0;
chart.Palette = ChartColorPalette.BrightPastel;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.None;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
// Set the Title and Legends for chart
chart.Titles.Add(CreateTitle());
chart.Legends.Add(new Legend("Costs Distribution")
{
BackColor = Color.Transparent,
Font = new Font("Trebuchet MS", 8.25f, FontStyle.Bold,
GraphicsUnit.Point),
IsTextAutoFit = false
});
// Clear any existing series and add the new series
chart.Series.Clear();
chart.Series.Add(new Series());
chart.Series.Add(new Series());
chart.Series.Add(new Series());
chart.Series.Add(new Series());
foreach (Series s in chart.Series)
{
s.ChartType = SeriesChartType.StackedColumn;
}
//var totalStorage = objAzureOutPut.GeoReplicatedStorageAnnualExpense+objAzureOutPut.LocallyRedundantStorageAnnualExpense
//chart.Series["Default"].Points[0].AxisLabel = "On Premises";
//chart.Series["Default"].Points[1].AxisLabel = "Azure";
chart.Series[0].Points.Add(new DataPoint(0, objOnPremiseOutPut.TotalOnPremServerExpense));
chart.Series[1].Points.Add(new DataPoint(0, objOnPremiseOutPut.TotalOnPremStorageCapacity));
chart.Series[2].Points.Add(new DataPoint(0, objOnPremiseOutPut.TotalOnPremNetworkExpense));
chart.Series[3].Points.Add(new DataPoint(0, objOnPremiseOutPut.TotalOnPremITExpense));
//chart.Series[0].AxisLabel = "Azure";
chart.Series[0].Points.Add(new DataPoint(1, objAzureOutPut.DiscVMPricingAnnualExpense));
chart.Series[1].Points.Add(new DataPoint(1, objAzureOutPut.TotalStorageExpense));
chart.Series[2].Points.Add(new DataPoint(1, objAzureOutPut.Zone1EgressAnnualExpense));
chart.Series[3].Points.Add(new DataPoint(1, objAzureOutPut.AdminExpense));
// Name the series
chart.Series["Series1"].Name = "Server";
chart.Series["Series2"].Name = "Storage";
chart.Series["Series3"].Name = "Network";
chart.Series["Series4"].Name = "IT";
chart.Series["IT"].MarkerStyle = MarkerStyle.Circle;
chart.Series["IT"].MarkerSize = 5;
// Create Memorysteam to dump the image
MemoryStream ms = new MemoryStream();
CreateChartArea(chart).SaveImage(ms);
return File(ms.GetBuffer(), #"image/png");
}
public Title CreateTitle()
{
Title title = new Title();
title.Text = "Cost Comparison";
title.ShadowColor = Color.FromArgb(32, 0, 0, 0);
title.Font = new Font("Trebuchet MS", 14F, FontStyle.Bold);
title.ShadowOffset = 3;
title.ForeColor = Color.FromArgb(26, 59, 105);
return title;
}
public Chart CreateChartArea(Chart chart)
{
ChartArea chartArea = new ChartArea();
chartArea.Name = "Cost Comaparison";
chartArea.BackColor = Color.WhiteSmoke;
// X Axis interval
chartArea.AxisX.Interval = 1;
// Set the Custom Labebls
CustomLabel onPremXLabel = new CustomLabel(-0.5, 0.5, "On Premise", 0, LabelMarkStyle.None);
CustomLabel azureXLabel = new CustomLabel(0.75, 1.25, "Azure", 0, LabelMarkStyle.None);
chartArea.AxisX.CustomLabels.Add(onPremXLabel);
chartArea.AxisX.CustomLabels.Add(azureXLabel);
//chartArea.AxisY.Title = "Costs (in $)";
chartArea.AxisY.LabelStyle.Format = "C";
//chartArea.AxisY.TitleFont = new Font("Verdana,Arial,Helvetica,sans-serif",
// 12F, FontStyle.Bold);
//chartArea.AxisX.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chart.ChartAreas.Add(chartArea);
chart.ChartAreas["Cost Comaparison"].AxisY.MajorGrid.Enabled = false;
chart.ChartAreas["Cost Comaparison"].AxisX.MajorGrid.Enabled = false;
chartArea.AxisX.MinorTickMark.Enabled = false;
chartArea.AxisX.MajorTickMark.Enabled = false;
return chart;
}
Handle the CustomizeLegend event, as below:
private void Chart1_CustomizeLegend(object sender, CustomizeLegendEventArgs e)
{
foreach (LegendItem li in e.LegendItems)
{
li.ImageStyle = LegendImageStyle.Marker;
li.MarkerStyle = MarkerStyle.Circle;
li.MarkerSize = 72;
}
}
EDIT: In the Controller, after creating the chart, and before returning it to the View, register to handle the event, like this:
chart1.CustomizeLegend += Chart1_CustomizeLegend;

How resize HttpPostedFileWrapper?

I need resize this image proportionally heigth 411px.
how do this?
[HttpPost]
public WrappedJsonResult UploadImage(HttpPostedFileWrapper imageFile, int id)
{
if (imageFile == null || imageFile.ContentLength == 0)
{
return new WrappedJsonResult
{
Data = new
{
IsValid = false,
Message = "No file was uploaded.",
ImagePath = string.Empty
}
};
}
var fileName = String.Format("{0}_{1}.jpg", id, Guid.NewGuid().ToString());
var imagePath = Path.Combine(Server.MapPath(Url.Content("~/Content/UploadPhoto")), fileName);
imageFile.SaveAs(imagePath);
}
public ActionResult UploadImage(HttpPostedFileBase imageFile, int id)
{
if (imageFile == null || imageFile.ContentLength == 0)
{
return new WrappedJsonResult
{
Data = new
{
IsValid = false,
Message = "No file was uploaded.",
ImagePath = string.Empty
}
};
}
var fileName = String.Format("{0}_{1}.jpg", id, Guid.NewGuid().ToString());
var imagePath = Path.Combine(Server.MapPath(Url.Content("~/Content/UploadPhoto")), fileName);
using (var input = new Bitmap(imageFile.InputStream))
{
int width;
int height;
if (input.Width > input.Height)
{
width = 411;
height = 411 * input.Height / input.Width;
}
else
{
height = 411;
width = 411 * input.Width / input.Height;
}
using (var thumb = new Bitmap(width, height))
using (var graphic = Graphics.FromImage(thumb))
{
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.AntiAlias;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.DrawImage(input, 0, 0, width, height);
using (var output = System.IO.File.Create(imagePath))
{
thumb.Save(output, ImageFormat.Jpeg);
}
}
}
...
}
By the way you will notice that I have replaced HttpPostedFileWrapper with HttpPostedFileBase in the action signature as this is the correct type to use.

Categories