C# Image to PathGeometry - wpf

I am trying to Convert an Image to a PathGeometry. I upload a picture, and then I do canny edge detection and now I want to convert that in to a PathGeometry. My over all plan it to fill it with different colors.
So I tried this :`public Shape MakeSape(Brush customColor, double[,] image)
{
Path graphPath = new Path();
graphPath.Fill = customColor;
graphPath.Stroke = Brushes.Black;
PathFigure pf = new PathFigure();
pf.StartPoint = new Point(0, 0);
pf.IsClosed = true;
int row = image.GetLength(0);
int column = image.GetLength(1);
for (int y = 0; y < row; y++)
{
for (int x = 0; x < column; x++)
{
if (image[y, x] >= LowThreshold)
{
pf.Segments.Add(new LineSegment(new Point(x, y), true));
}
}
}
PathGeometry pg = new PathGeometry();
pg.Figures.Add(pf);
graphPath.Data = pg;
ImageAsShape = graphPath;
return graphPath;
}`
And that looked like it should work, but I am just getting all black.

Related

How can i capture screen region while not focusing wpf app?

I have a WPf application that monitors a certain region on screen keeping track of the count of pixels with certain colors.
What i want is the actual capturing of the region and reading of values to happen in another thread, but i cant seem to wrap my head around how to actuale grab the region while i focus another window.
Here is some code:
// Colors to keep track of
var fooColor = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#FF6ebfe2");
var barColor = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#FFe67e6e");
// previewWindow : Rectangle Control
var X = (int)previewWindow.PointToScreen(new System.Windows.Point(0, 0)).X;
var Y = (int)previewWindow.PointToScreen(new System.Windows.Point(0, 0)).Y;
Rectangle rect = new Rectangle(X, Y, (int)previewWindow.ActualWidth, (int)previewWindow.ActualHeight);
Bitmap bmp = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (var screenBmp = new Bitmap(
rect.Width,
rect.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb)
)
{
using (var bmpGraphics = Graphics.FromImage(screenBmp))
{
bmpGraphics.CopyFromScreen(X, Y, 0, 0, screenBmp.Size);
BitmapSource bmpSource = Imaging.CreateBitmapSourceFromHBitmap(
screenBmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
var red = 0;
var blue = 0;
for (int i = 0; i < rect.Width; i++)
{
for (int x = 0; x < rect.Height; x++)
{
System.Windows.Media.Color color = GetPixelColor(bmpSource, i, x);
if (color == fooColor)
{
blue++;
}
else if (color == barColor)
{
red++;
}
}
}
txtbar.Text = red.ToString();
txtfoo.Text = blue.ToString();
if (red < 150)
{
ProcessBar();
}
if (blue < 150)
{
ProcessFoo();
}
}
}

Save jpg data from database to a jpg file

I want to take the data in a field that contains a jpeg image and save it to an actual file that I can open with a paint editor. I know I could create an application to do this in c# but I'm wondering if there's a quick and easy way to just do it from a sql query?
It doesn't need to work on all records at once. I just need to be able to select a single record and save the image for that record to a file.
You can use MemoryStream object in C# as below
MemoryStream memstmSignature = new MemoryStream(InkToBytes(ds.Tables[1].Rows[0]["SIGNATURE"].ToString(), "image/gif", 0, 0));
Image imaSig = Image.FromStream(memstmSignature);
imaSig.RotateFlip(RotateFlipType.Rotate180FlipX);
imaSig.Save(Path.Combine(this.temporaryFilePath, this.signatureFileName));
memstmSignature.Close();
Helper functions below
private static byte[] InkToBytes(string inkStrokes, string encoderType, float x, float y)
{
ArrayList strokes = new ArrayList();
// max size for bit map
int maxX = 0;
int maxY = 0;
// intialize the strokes array with text string
int strokesCount;
if (inkStrokes.Length > 0)
{
if (inkStrokes.EndsWith(";"))
inkStrokes = inkStrokes.Remove((inkStrokes.Length - 1), 1);
char[] strokeSeperator = { ';' };
string[] strokeArray = inkStrokes.Split(strokeSeperator);
strokesCount = strokeArray.Length;
for (int i = 0; i < strokesCount; i++)
{
Stroke stroke = new Stroke(50);
stroke.Text = strokeArray[i];
strokes.Add(stroke);
Point[] points = stroke.ToPointArray();
int len = points.Length;
foreach (Point point in points)
{
maxX = (point.X > maxX ? point.X : maxX);
maxY = (point.Y > maxY ? point.Y : maxY);
}
}
}
// setup the gdi objects
Bitmap bitMap = new Bitmap(maxX + 20, maxY + 20); // leave some buffer room
Graphics graphics = Graphics.FromImage(bitMap);
Rectangle clientRect = new Rectangle(0, 0, bitMap.Width, bitMap.Height);
Pen pen = new Pen(Color.Black);
pen.Width = 2; // matches the client capture
// draw the bit map
if (x > 0 && y > 0)
graphics.DrawImage(bitMap, x, y);
else
graphics.DrawImage(bitMap, 0, 0);
graphics.FillRectangle(Brushes.White, clientRect);
graphics.DrawRectangle(pen, clientRect);
strokesCount = strokes.Count;
for (int j = 0; j < strokesCount; j++)
{
Stroke stroke = (Stroke)strokes[j];
if (stroke != null)
{
Point[] points = stroke.ToPointArray();
int len = points.Length;
if (len > 1)
{
Point prevPoint = points[0];
for (int i = 1; i < len; i++)
{
graphics.DrawLine(pen, prevPoint.X, prevPoint.Y, points[i].X, points[i].Y);
prevPoint = points[i];
}
}
}
}
// create the bytes from the bitmap to be returned
MemoryStream memStream = new MemoryStream(1000);
ImageCodecInfo imageCodedInfo = GetEncoderInfo(encoderType);
bitMap.Save(memStream, imageCodedInfo, null);
byte[] bytes = memStream.GetBuffer();
memStream.Close();
return bytes;
}
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
Hope this helps.
NOTE: I have not looked into to optimizing the above code

How to crop image and save into ImageSource in WPF?

I am new learner to WPF. here I got a question.
I have a image, width:360, height:360. Here I want to crop this image like below:
( 0,0 ) to (120,120) save to the first ImageSource object,
(120,0 ) to (240,120) save to the second ImageSource object,
(240,0 ) to (360,120) save to the third ImageSource object;,
……
pls see more details in below picture:
My code sample below:
private void CutImage(string img)
{
int iLeft = 0;
int iTop = 0;
int count = 0;
Image thisImg = new Image();
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(img, UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
thisImg.Source = src;
for (int i = 0; i < 3; i++)
{
iTop = i * 120;
for (int j = 0; j < 3; j++)
{
iLeft = j * 120;
Canvas canvas = new Canvas();
Rectangle destRect = new Rectangle();
destRect.SetValue(Canvas.LeftProperty, (double)0);
destRect.SetValue(Canvas.TopProperty,(double)0);
destRect.Width = destRect.Height = 120;
Rect srcRect = new Rect();
srcRect.X = iLeft;
srcRect.Y = iTop;
srcRect.Width = srcRect.Height = 120;
thisImg.Clip = new RectangleGeometry(srcRect);
thisImg.Clip.SetValue(Canvas.TopProperty, (double)iTop);
thisImg.Clip.SetValue(Canvas.LeftProperty, (double)iLeft);
thisImg.Clip.SetValue(Canvas.WidthProperty, (double)120);
thisImg.Clip.SetValue(Canvas.HeightProperty,(double)120);
objImg[count++] = (ImageSource)thisImg.GetValue(Image.SourceProperty);
}
}
}
but it doesn't work as I expected, seems that all the ImageSource objects store the same image, not the corping part. Any one can help me ? thx.
Use CroppedBitmap to do this:
private void CutImage(string img)
{
int count = 0;
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(img, UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
objImg[count++] = new CroppedBitmap(src, new Int32Rect(j * 120, i * 120, 120, 120));
}
Just do:
private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
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 Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
VisualBrush part1 = new VisualBrush(yourVISUAL);
part1.ViewBoxUnits = ..Absolute;
part1.ViewBox = new Rect(x, y, width, height);
BitmapSource bitmapSource = CaptureScreen(part1, 96, 96);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(fileStream);
}

Silverlight - Fill a rectangle with animation on mouseclick

I want to be able to fill a rectangle with an animation on leftmousebuttondown (this will later be changed to run on load).
My rectangles are drawn to a canvas in code behind based on the data that is passed (one rectangle per row of data)
At the moment they are filled with a static image but I want this Fill to be an animation, a spinner if I can.
I am very new to Silverlight and am not sure how to achieve this. Can someone point me in the right direction?
My code (part) so far.
XAML:
<Canvas x:Name="Grid" Background="LightGray"></Canvas>
CS:
public partial class ProductView : UserControl
{
Processing processingDialog = new Processing();
private int colsRequired = 0;
private int rowsRequired = 0;
private const int minSize = 5;
private int cellSize = 1;
public ProductView()
{
InitializeComponent();
}
public void UpdateGrid(ObservableCollection<Product> productList)
{
calculateRowsCols(productList);
drawGrid(productList);
}
public void calculateRowsCols(ObservableCollection<Product> productList)
{
int tileCount = productList.Count();
double tileHeight = Grid.ActualHeight;
double tileWidth = Grid.ActualWidth;
if (tileCount == 0)
return;
double maxSize = Math.Sqrt((tileHeight * tileWidth) / tileCount);
double noOfTilesHeight = Math.Floor(tileHeight / maxSize);
double noOfTilesWidth = Math.Floor(tileWidth / maxSize);
double total = noOfTilesHeight * noOfTilesWidth;
cellSize = (maxSize < minSize) ? minSize : Convert.ToInt32(maxSize);
while ((cellSize >= minSize) && (total < tileCount))
{
cellSize--;
noOfTilesHeight = Math.Floor(tileHeight / cellSize);
noOfTilesWidth = Math.Floor(tileWidth / cellSize);
total = noOfTilesHeight * noOfTilesWidth;
}
rowsRequired = Convert.ToInt32(Math.Floor(tileHeight / cellSize));
colsRequired = Convert.ToInt32(Math.Floor(tileWidth / cellSize));
}
private void drawCell(int row, int col, string label, Color fill)
{
Rectangle innertec = new Rectangle();
innertec.Height = cellSize * 0.7;
innertec.Width = cellSize * 0.9;
innertec.StrokeThickness = 1;
innertec.Stroke = new SolidColorBrush(Colors.Black);
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = new BitmapImage(new Uri("Assets/loading.png", UriKind.Relative));
innertec.Fill = imageBrush;
Grid.Children.Add(innertec);
Canvas.SetLeft(innertec, (col * cellSize) + ((cellSize - innertec.Width) / 2));
Canvas.SetTop(innertec, row * cellSize + 4);
Border productLabelBorder = new Border();
Grid.Children.Add(productLabelBorder);
Canvas.SetLeft(productLabelBorder, col * cellSize);
Canvas.SetTop(productLabelBorder, row * cellSize);
TextBlock productLabel = new TextBlock();
productLabel.Margin = new Thickness(0, innertec.Height + 5, 0, 5);
productLabel.TextAlignment = TextAlignment.Center;
productLabel.TextWrapping = TextWrapping.NoWrap;
productLabel.TextTrimming = TextTrimming.WordEllipsis;
productLabel.MaxWidth = cellSize;
productLabel.Height = cellSize * 0.3;
productLabel.Width = cellSize;
productLabel.Text = label;
productLabel.HorizontalAlignment = HorizontalAlignment.Center;
productLabel.VerticalAlignment = VerticalAlignment.Center;
productLabel.FontSize = cellSize * 0.13;
ToolTipService.SetToolTip(productLabel, label);
productLabelBorder.Child = productLabel;
}
public void drawGrid(ObservableCollection<Product> data)
{
int dataIndex = 0;
Grid.Children.Clear();
for (int i = 0; i < rowsRequired; i++)
{
for (int j = 0; j < colsRequired; j++)
{
Product product = (dataIndex < data.Count) ? data.ElementAt(dataIndex) : null;
if (product != null)
{
drawCell(i, j, product.productName, Colors.White);
}
dataIndex++;
}
}
}
}
Any help anyone can give, even a pointer in the right direction would be great.
Thanks in advance
Try creating custom control which will encapsulate everything you want from rectangle to do.
you can add new VisualState "MouseDownState" and do required animatin in xaml.
Please let me know if you need more details regarding the implementation.
late simply add new control instead of rectangle.

how to deform an ellipse in running time

i first sorry about my english,i´ll try to explain want i want to do
i need to draw an ellipse with wpf that represents an aura and it´s "deformations" representing problematic zones in it,in short an ellipse that can be deformed in running time in specific points
I'm trying to draw several bezier curves forming an ellipse but it´t very difficult (and i don´t know how) to make points that can be dragged forming convex or hollow zones in that ellipse.
¿i made myselft clear in my spanglish? ¿is there an easy way to do that?
Thanks in advance
I don't know what exactly you are trying to do but I recommend making a high resolution version of the ellipse and keeping track of the deformations yourself. Here is a sample program to get you started.
For this demo the XAML is simple:
<Canvas Name="canvas" Focusable="True" KeyDown="canvas_KeyDown" MouseDown="canvas_MouseDown" MouseMove="canvas_MouseMove" MouseUp="canvas_MouseUp"/>
and a the code-behind:
public partial class EllipseDemo : Window
{
const int resolution = 1000;
const double major = 150;
const double minor = 100;
const double xOrigin = 200;
const double yOrigin = 200;
const double radius = 10;
const double scale = 0.1;
const double spread = 10;
const double magnitude = 10;
Path path;
Ellipse controlPoint;
LineSegment[] segments;
double[] deformation;
double[] perturbation;
int controlPointIndex;
public EllipseDemo()
{
InitializeComponent();
segments = new LineSegment[resolution];
deformation = new double[resolution];
perturbation = new double[resolution];
for (int i = 0; i < resolution; i++)
{
var x = i >= resolution / 2 ? i - resolution : i;
perturbation[i] = magnitude * Math.Exp(-Math.Pow(scale * x, 2) / spread);
}
path = new Path();
path.Stroke = new SolidColorBrush(Colors.Black);
path.StrokeThickness = 5;
CalculateEllipse();
canvas.Children.Add(path);
controlPoint = new Ellipse();
controlPoint.Stroke = new SolidColorBrush(Colors.Red);
controlPoint.Fill = new SolidColorBrush(Colors.Transparent);
controlPoint.Width = 2 * radius;
controlPoint.Height = 2 * radius;
MoveControlPoint(0);
canvas.Children.Add(controlPoint);
canvas.Focus();
}
void CalculateEllipse()
{
for (int i = 0; i < resolution; i++)
{
double angle = 2 * Math.PI * i / resolution;
double x = xOrigin + Math.Cos(angle) * (major + deformation[i]);
double y = yOrigin + Math.Sin(angle) * (minor + deformation[i]);
segments[i] = new LineSegment(new Point(x, y), true);
}
var figure = new PathFigure(segments[0].Point, segments, true);
var figures = new PathFigureCollection();
figures.Add(figure);
var geometry = new PathGeometry();
geometry.Figures = figures;
path.Data = geometry;
}
void MoveControlPoint(int index)
{
controlPointIndex = index;
Canvas.SetLeft(controlPoint, segments[index].Point.X - radius);
Canvas.SetTop(controlPoint, segments[index].Point.Y - radius);
}
bool mouseDown;
void canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.DirectlyOver != controlPoint)
return;
mouseDown = true;
controlPoint.CaptureMouse();
}
void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (!mouseDown)
return;
int index = FindNearestIndex(e.GetPosition(canvas));
MoveControlPoint(index);
}
void canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
if (!mouseDown)
return;
controlPoint.ReleaseMouseCapture();
mouseDown = false;
}
private void canvas_KeyDown(object sender, KeyEventArgs e)
{
int delta = 0;
switch (e.Key)
{
case Key.Up:
delta = 1;
break;
case Key.Down:
delta = -1;
break;
}
if (delta == 0)
return;
int index = controlPointIndex;
for (int i = 0; i < resolution; i++)
deformation[(i + index) % resolution] += delta * perturbation[i];
CalculateEllipse();
MoveControlPoint(index);
}
int FindNearestIndex(Point point)
{
var min = double.PositiveInfinity;
var index = -1;
for (int i = 0; i < segments.Length; i++)
{
var vector = point - segments[i].Point;
var distance = vector.LengthSquared;
if (distance < min)
{
index = i;
min = distance;
}
}
return index;
}
}
This works mostly with a Path represented by line segments and an Ellipse as a control point. The mouse can move the control point around the ellipse and then the arrow keys add or remove a canned perturbation. Everything is hard coded but if you are OK with the math then it should help you get started.
Here's the program in action:

Resources