Generate Image from XAML Grid + Image via c# - c#

I try to generate an image for a tile consisting of a grid with background color and a PNG with transparent background.
var TestTile = new Grid()
{
Background = colTemp,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Margin = new Thickness( 0, 12, 0, 0 ),
};
TestTile.Arrange(new Rect(0, 0, 366, 366));
var ico = new Image() {
Source = new BitmapImage(new Uri("Images/mCloudSunT.png", UriKind.Relative)),
};
TestTile.Children.Add(ico);
...
bitmap.Render(TestTile, new TranslateTransform());
...
I get the image with background color but without the PNG. I get no error and the URI is correct (tested).
new code:
var colTemp = new SolidColorBrush(Color.FromArgb(255, 174, 190, 206));
var TestTile = new Grid()
{
Background = colTemp,
Height = 336,
Width = 336,
};
var ico = new Image() {
Source = new BitmapImage(new Uri("Images/mCloudSunT.png", UriKind.Relative)),
};
Grid.SetColumn(ico, 0);
Grid.SetRow(ico, 0);
TestTile.Children.Add(ico);
TestTile.Measure(new Size(336, 336));
TestTile.Arrange(new Rect(0, 0, 366, 366));
TestTile.UpdateLayout();
Here is the code for generating the image:
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("shared/shellcontent"))
{
store.CreateDirectory("shared/shellcontent");
}
var bitmap = new WriteableBitmap(336, 336);
bitmap.Render(TestTile, new TranslateTransform());
var stream = store.CreateFile("/shared/shellcontent/test.jpg");
bitmap.Invalidate();
bitmap.SaveJpeg(stream, 366, 336, 0, 100);
stream.Close();
And here the code for the use as tile background:
ShellTile PinnedTile = ShellTile.ActiveTiles.First();
FlipTileData UpdatedTileData = new FlipTileData
{
BackgroundImage = new Uri("isostore:/shared/shellcontent/test.jpg", UriKind.RelativeOrAbsolute),
};
PinnedTile.Update(UpdatedTileData);

Call Measure and then Arrange after adding icon.
TestTile.Measure( new Size( 366,366 ) );
TestTile.Arrange( new Rect( 0, 0, 366, 366 ) );
TestTile.UpdateLayout();
...
WritableBitmap...

I see no reason for calling SetColumn, SetRow, Measure, Arrange, or UpdateLayout. Also, after calling Render(), call Invalidate(). Try this:
var colTemp = new SolidColorBrush(Color.FromArgb(255, 174, 190, 206));
var TestTile = new Grid()
{
Background = colTemp,
Height = 336,
Width = 336,
};
var ico = new Image() {
Source = new BitmapImage(new Uri("Images/mCloudSunT.png", UriKind.Relative)),
};
TestTile.Children.Add(ico);
....
bitmap.Render(TestTile, new TranslateTransform());
bitmap.Invalidate();

Related

C# Saving Live Chart to PNG in WinForms

I am having difficulties in exporting LiveCharts PieChart to a .png file.
So far what I have done is trying to draw the control to a bitmap (DrawToBitmap), but it is just outputting a black image. I have discarded other alternatives such as screenshots because the chart is not created to be deployed in a custom form for visualization. Its main purpose is just graphic statistic exporting.
This is my main code:
LiveCharts.WinForms.PieChart chart = initializePieChart2DFolder(true);
Bitmap bmp = new Bitmap(chart.Width, chart.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
chart.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height));
bmp.Save("graphFolder.png", System.Drawing.Imaging.ImageFormat.Png);
This is the method I use to create the Pie chart:
private LiveCharts.WinForms.PieChart initializePieChart2DFolder()
{
LiveCharts.WinForms.PieChart chart = new LiveCharts.WinForms.PieChart();
chart.Anchor = System.Windows.Forms.AnchorStyles.None;
chart.Location = new System.Drawing.Point(17, 56);
chart.Name = "pieChart2DFolder";
chart.Size = new System.Drawing.Size(364, 250);
chart.TabIndex = 0;
chart.BackColorTransparent = false;
chart.BackColor = Color.White;
chart.ForeColor = Color.Black;
SeriesCollection chartData = new SeriesCollection();
foreach(var annot in numAnnotsPerLabel)
{
System.Windows.Media.Color newColor = System.Windows.Media.Color.FromArgb(color[annot.Key].A, color[annot.Key].R, color[annot.Key].G, color[annot.Key].B);
chartData.Add( new PieSeries { Title = annot.Key,
Values = new ChartValues<int> { annot.Value },
DataLabels = true,
Stroke = System.Windows.Media.Brushes.DimGray,
Foreground = System.Windows.Media.Brushes.Black,
FontSize = 9,
Fill = new
System.Windows.Media.SolidColorBrush(newColor)});
}
chart.Series = chartData;
DefaultLegend customLegend = new DefaultLegend();
customLegend.BulletSize = 15;
customLegend.Foreground = System.Windows.Media.Brushes.Black;
customLegend.Orientation = System.Windows.Controls.Orientation.Vertical;
customLegend.FontSize = 10;
chart.DefaultLegend = customLegend;
chart.LegendLocation = LegendLocation.Right;
var tooltip = chart.DataTooltip as DefaultTooltip;
tooltip.SelectionMode = LiveCharts.TooltipSelectionMode.OnlySender;
return chart;
}
Thank you very much in advance!

C# Windows Phone - Creating a round mask

I need to mask dynamically created images, so that they will be shown as circles.
Pictures can be square, but are usually rectangles... so the circle that will be shown can be taken from the center of it...so the shown circle must be inscribed in the picture and centered in the center of it.
This is the code I'm using right now:
//Setting up the image
Image image = new Image();
image.Height = 70;
image.Width = 70;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource = new Uri("http://url-of-the-image", UriKind.Absolute);
image.CacheMode = new BitmapCache();
image.Source = bitmapImage;
image.Stretch = Stretch.UniformToFill;
image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
//Setting up the mask
RadialGradientBrush opacityMask = new RadialGradientBrush();
GradientStop gs1 = new GradientStop();
GradientStop gs2 = new GradientStop();
GradientStop gs3 = new GradientStop();
gs1.Color = Color.FromArgb(255, 0, 0, 0);
gs1.Offset = 0.0;
gs2.Color = Color.FromArgb(255, 0, 0, 0);
gs2.Offset = 0.999;
gs3.Color = Color.FromArgb(0, 0, 0, 0);
gs3.Offset = 1.0;
opacityMask.GradientStops.Add(gs1);
opacityMask.GradientStops.Add(gs2);
opacityMask.GradientStops.Add(gs3);
image.OpacityMask = opacityMask;
//Showing the image
panel.Children.Add(image);
This all works fine, but when the pictures are rectangular and not square, this creates an ellipse instead of a circle... any idea on how can I force it to create a circle?
I also tried to specify some more parameters, but doesn't seem to help:
opacityMask.Center = new Point(0.5, 0.5);
opacityMask.RadiusX = 0.5;
opacityMask.RadiusY = 0.5;
Okay, today i tried again to fix this, and i came out with a solution.
It's not the best, more clean solution ever...but works :)
I basically wrapped the picture (not masked) into a StackPanel and then applied the mask to the StackPanel instead ;)
This is how it looks like (the only lines that change from the original are the the last few ones):
//Setting up the image
Image image = new Image();
image.Height = 70;
image.Width = 70;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource = new Uri("http://url-of-the-image", UriKind.Absolute);
image.CacheMode = new BitmapCache();
image.Source = bitmapImage;
image.Stretch = Stretch.UniformToFill;
image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
//Setting up the mask
RadialGradientBrush opacityMask = new RadialGradientBrush();
GradientStop gs1 = new GradientStop();
GradientStop gs2 = new GradientStop();
GradientStop gs3 = new GradientStop();
gs1.Color = Color.FromArgb(255, 0, 0, 0);
gs1.Offset = 0.0;
gs2.Color = Color.FromArgb(255, 0, 0, 0);
gs2.Offset = 0.999;
gs3.Color = Color.FromArgb(0, 0, 0, 0);
gs3.Offset = 1.0;
opacityMask.GradientStops.Add(gs1);
opacityMask.GradientStops.Add(gs2);
opacityMask.GradientStops.Add(gs3);
//Setting up the StackPanel
StackPanel sp = new StackPanel();
sp.OpacityMask = opacityMask;
//Showing the image
sp.Children.Add(image);
panel.Children.Add(sp);

How can add shape to BitmapImage in wpf and c#

I want to add path to image because I want to make curves on image. I don't know how can add curves to images. I want to draw shape on image and don't want to use canvas. because I want to convert line to Raster image this is my code:
Ellipse circle = new Ellipse();
circle.BeginInit();
circle.Height = 100;
circle.Width = 100;
circle.Stroke = System.Windows.Media.Brushes.Black;
circle.StrokeThickness = 1.0;
circle.Margin = new Thickness(0, 0, 0, 0);
circle.EndInit();
circle.Measure(new Size(200, 200));
circle.Arrange(
new Rect(new Size(200, 200)));
circle.UpdateLayout();
Line line = new Line();
line.BeginInit();
line.X1 = 0;
line.Y1 = 0;
line.X2 = 300;
line.Y2 = 300;
line.Stroke = System.Windows.Media.Brushes.Magenta;
line.StrokeThickness = 1;
line.EndInit();
line.Measure(new Size(300, 300));
line.Arrange(new
Rect(new Size(300, 300)));
SolidColorBrush blueBrush = new SolidColorBrush();
blueBrush.Color = Colors.Blue;
SolidColorBrush blackBrush = new SolidColorBrush();
blackBrush.Color = Colors.Black;
// Create a Path with black brush and blue fill
Path bluePath = new Path();
bluePath.BeginInit();
bluePath.Stroke = blackBrush;
bluePath.StrokeThickness = 3;
bluePath.Fill = blueBrush;
// Create a line geometry
LineGeometry blackLineGeometry = new LineGeometry();
blackLineGeometry.StartPoint = new Point(20, 200);
blackLineGeometry.EndPoint = new Point(300, 200);
// Create an ellipse geometry
EllipseGeometry blackEllipseGeometry = new EllipseGeometry();
blackEllipseGeometry.Center = new Point(80, 150);
blackEllipseGeometry.RadiusX = 50;
blackEllipseGeometry.RadiusY = 50;
// Create a rectangle geometry
RectangleGeometry blackRectGeometry = new RectangleGeometry();
Rect rct = new Rect();
rct.X = 80;
rct.Y = 167;
rct.Width = 150;
rct.Height = 30;
blackRectGeometry.Rect = rct;
// Add all the geometries to a GeometryGroup.
GeometryGroup blueGeometryGroup = new GeometryGroup();
blueGeometryGroup.Children.Add(blackLineGeometry);
blueGeometryGroup.Children.Add(blackEllipseGeometry);
blueGeometryGroup.Children.Add(blackRectGeometry);
// Set Path.Data
bluePath.Data = blueGeometryGroup;
bluePath.EndInit();
bluePath.Measure(new Size(300, 300));
bluePath.Arrange(new Rect(new Size(300, 300)));
RenderTargetBitmap RTbmap = new
RenderTargetBitmap(200, 200, 96, 96,
PixelFormats.Default);
RTbmap.Render(bluePath);
var renderTargetBitmap = RTbmap;
var bitmapImage = new BitmapImage();
var bitmapEncoder = new BmpBitmapEncoder();
bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (var stream = new System.IO.MemoryStream())
{
bitmapEncoder.Save(stream);
stream.Seek(0, System.IO.SeekOrigin.Begin);
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.UriSource = new Uri("C:\\Users\\ErnaGroup.Com\\Pictures\\Pictures\\cartoon-ice-cream-3 - Copy.jpg"); // I want to add line to this image.
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
}
image1.Source = bitmapImage;
}
How can I do this?
Image is not a container control. You definitely need a container control like Canvas to hold your shapes.
Alternatively you can set your BitmapImage as Background of Canvas using ImageBrush and draw Path/Line/Ellipse on Canvas and later you can save your drawing on Canvas as a JPG image.
<Canvas>
<Canvas.Background>
<ImageBrush ImageSource="Your BitmapImage Path"></ImageBrush>
</Canvas.Background>
</Canvas>
Then you can save your modified data as a JPG image
public static void CreateBitmapFromVisual(Visual target, string filename)
{
// target will be your Canvas
// filename is the path where you want to save the image
if (target == null)
return;
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Default);
rtb.Render(target);
JpegBitmapEncoder jpg = new JpegBitmapEncoder();
jpg.Frames.Add(BitmapFrame.Create(rtb));
using (Stream stm = File.Create(filename))
{
jpg.Save(stm);
}
}

Can't get dynamically generated tile working (Windows Phone)

I have the method, which is executed in Application_Deacitvated/Closing().
public bool createBackTile()
{
if(AlarmClock.IsExists())
{
ImageBrush background = new ImageBrush()
{
ImageSource = new BitmapImage(new Uri("/BackBackgroundTheme.png", UriKind.Relative)),
AlignmentX = AlignmentX.Center,
AlignmentY = AlignmentY.Center
};
// Preparing tile image.
TextBox tileImageData = new TextBox()
{
Text = AlarmClock.Read().ToShortTimeString(),
FontSize = 45,
FontWeight = FontWeights.Bold,
Foreground = new SolidColorBrush(Colors.White),
//Background = background,
Height = 173,
Width = 173,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
Padding = new Thickness(-12),
Margin = new Thickness(0),
Clip = new RectangleGeometry { Rect = new Rect(0, 0, 173, 173) }
};
Canvas canvas = new Canvas()
{
Width = 173,
Height = 173,
Background = background,
Margin = new Thickness(0)
};
canvas.Children.Add(tileImageData);
// Saving tile image.
WriteableBitmap tileImage = new WriteableBitmap(173, 173);
tileImage.Render(canvas, null);
tileImage.Render(tileImageData, null);
tileImage.Invalidate();
using(var stream = IsolatedStorageFile.GetUserStoreForApplication().CreateFile("/Shared/ShellContent/BackBackground.jpg"))
{
tileImage.SaveJpeg(stream, 173, 173, 0, 100);
}
// Sets data for tile.
StandardTileData tileData = new StandardTileData()
{
BackgroundImage = new Uri("BackgroundAlarmSet.png", UriKind.Relative),
BackBackgroundImage = new Uri(#"isostore:/Shared/ShellContent/BackBackground.jpg"),
BackContent = "",
BackTitle = "",
};
// Sets tile.
ShellTile.ActiveTiles.FirstOrDefault().Update(tileData);
return true;
}
return false;
}
So, as you can see, I want to generate tile with my text in the center of it with image background "BackBackgroundTheme.png". That tile I'm trying to save in IsolatedStorage and assign it to BackBackgroundImage.
But it doesn't work. The tile is flipping over but the BackBackground is completly black. I have loaded this manipulated background and it seems that's indeed just black box. So, how to get it working?
Try: BackgroundImage = new Uri(#"isostore:/Shared/ShellContent/BackBackground.jpg", UriKind.Absolute)
I have finally found out where the problem is.
It seems, that generation of tile image isn't done properly in Application_Closing/Deactivating(). So I moved image generation to somwhere else and now, when application is closing/deactivating, I just set previously generated image to a tile.
Try this:
canvas.Children.Add(tileImageData);
canvas.UpdateLayout();
// Saving tile image.
WriteableBitmap tileImage = new WriteableBitmap(173, 173);

WriteableBitmap.SaveJpeg renders a black image (WP7)

I'm trying to render some text and an image to a writeable bitmap to make 1 larger image, and this method has worked in other locations for creating or manipulating images, but for some reason, this instance is only creating a black image. If I just set the image source to the original WriteableBitmap, it shows just fine, but when I call SaveJpeg and then LoadJpeg, it shows as a black image (and yes, I need to call SaveJpeg since this is actually getting passed up to a server). The following is how I'm trying to render the elements:
NoteViewModel note = Instance.Note;
var grid = new Grid()
{
Height = 929,
Width = 929
};
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(679) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
var noteText = new TextBlock()
{
Text = note.Text,
FontFamily = note.FontFamily,
Foreground = note.FontColor,
TextWrapping = System.Windows.TextWrapping.Wrap,
Width = 929,
Height = 679
};
Grid.SetRow(noteText, 0);
grid.Children.Add(noteText);
WriteableBitmap sigImage = Instance.Signature.SignatureImage;
var sig = new Image()
{
Source = sigImage,
Height = 250,
Width = (sigImage.PixelWidth / sigImage.PixelHeight) * 250,
Margin = new Thickness(929 - ((sigImage.PixelWidth / sigImage.PixelHeight) * 250), 0, 0, 0)
};
Grid.SetRow(sig, 1);
grid.Children.Add(sig);
var messagePicture = new WriteableBitmap(grid, null);
var stream = new MemoryStream();
messagePicture.SaveJpeg(stream, messagePicture.PixelWidth, messagePicture.PixelHeight, 0, 100); //Save to a temp stream
stream.Position = 0;
var test = new WriteableBitmap(929,929); //Load the picture back up to see it
test.LoadJpeg(stream);
img.Source = test; //Show the image on screen (img is an Image element)
So apparently WriteableBitmap will render a transparent background as black when calling SaveJpeg, so I solved this by rendering a white canvas as well, like so:
var background = new Canvas()
{
Width = 929,
Height = 929,
Background = new SolidColorBrush(Colors.White)
};
messagePicture.Render(background, new TranslateTransform());

Categories

Resources