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

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();
}
}
}

Related

C# Image to PathGeometry

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.

2D over 3D anti-aliasing artifacts

We have 3D models in WPF and use a cursor made from a Canvas and some internal parts. We turn the HW cursor off and move the Canvas through MouseEvent. The issue is that there are terrible artifacts on the screen as you move from left to right (not nearly as bad right to left). I have played with snaptodevicepixels, Edge mode and nvidea AA settings but the only thing that "fixes" is setting edge mode to aliased for the 3dviewport - and we don't want that. I have even made the cursor completely transparent and it still leaves artifacts.
I broke out some of the code for demonstration. You can especially see the artifacts moving upper-left to lower-right.
Anyone think they can help me out here? I'm head banging and not in a good way. It's looking more like a bug in the AA code.
Thanks
T
FYI: I used some Petzold code here for the beach ball.
Bad AA BeachBall
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
namespace Cursoraa2
{
class Program : Window
{
[STAThread]
public static void Main() => new Application().Run(new Program());
public Program()
{
Width = 500;
Height = 500;
var grid = new Grid();
var viewport = new Viewport3D();
grid.Children.Add(viewport);
Content = grid;
//RenderOptions.SetEdgeMode(viewport,EdgeMode.Aliased);
DynamicCurosr.Start(grid, grid, 40, Color.FromArgb(40, 0x33, 0x33, 0xff), Colors.Blue);
MouseMove += MainWindow_MouseMove;
MakeBeachBallSphere(viewport);
}
private void MainWindow_MouseMove(object sender, MouseEventArgs e) => DynamicCurosr.Move(e.GetPosition(this));
public void MakeBeachBallSphere(Viewport3D viewport)
{
// Get the MeshGeometry3D from the GenerateSphere method.
var mesh = GenerateSphere(new Point3D(0, 0, 0), 1, 36, 18);
mesh.Freeze();
// Define a brush for the sphere.
var brushes = new Brush[6] { Brushes.Red, Brushes.Blue,
Brushes.Yellow, Brushes.Orange,
Brushes.White, Brushes.Green };
var drawgrp = new DrawingGroup();
for (var i = 0; i < brushes.Length; i++)
{
var rectgeo = new RectangleGeometry(new Rect(10 * i, 0, 10, 60));
var geodraw = new GeometryDrawing(brushes[i], null, rectgeo);
drawgrp.Children.Add(geodraw);
}
var drawbrsh = new DrawingBrush(drawgrp);
drawbrsh.Freeze();
// Define the GeometryModel3D.
var geomod = new GeometryModel3D
{
Geometry = mesh,
Material = new DiffuseMaterial(drawbrsh)
};
// Create a ModelVisual3D for the GeometryModel3D.
var modvis = new ModelVisual3D { Content = geomod };
viewport.Children.Add(modvis);
// Create another ModelVisual3D for light.
var modgrp = new Model3DGroup();
modgrp.Children.Add(new AmbientLight(Color.FromRgb(128, 128, 128)));
modgrp.Children.Add(new DirectionalLight(Color.FromRgb(128, 128, 128), new Vector3D(2, -3, -1)));
modvis = new ModelVisual3D {Content = modgrp};
viewport.Children.Add(modvis);
// Create the camera.
var cam = new PerspectiveCamera(new Point3D(0, 0, 8), new Vector3D(0, 0, -1), new Vector3D(0, 1, 0), 45);
viewport.Camera = cam;
// Create a transform for the GeometryModel3D.
var axisangle = new AxisAngleRotation3D(new Vector3D(1, 1, 0), 180);
var rotate = new RotateTransform3D(axisangle);
geomod.Transform = rotate;
// Animate the RotateTransform3D.
//DoubleAnimation anima = new DoubleAnimation(360, new Duration(TimeSpan.FromSeconds(5)));
//anima.RepeatBehavior = RepeatBehavior.Forever;
//axisangle.BeginAnimation(AxisAngleRotation3D.AngleProperty, anima);
}
MeshGeometry3D GenerateSphere(Point3D center, double radius, int slices, int stacks)
{
// Create the MeshGeometry3D.
var mesh = new MeshGeometry3D();
// Fill the Position, Normals, and TextureCoordinates collections.
for (var stack = 0; stack <= stacks; stack++)
{
var phi = Math.PI / 2 - stack * Math.PI / stacks;
var y = radius * Math.Sin(phi);
var scale = -radius * Math.Cos(phi);
for (var slice = 0; slice <= slices; slice++)
{
var theta = slice * 2 * Math.PI / slices;
var x = scale * Math.Sin(theta);
var z = scale * Math.Cos(theta);
var normal = new Vector3D(x, y, z);
mesh.Normals.Add(normal);
mesh.Positions.Add(normal + center);
mesh.TextureCoordinates.Add(
new Point((double)slice / slices,
(double)stack / stacks));
}
}
// Fill the TriangleIndices collection.
for (var stack = 0; stack < stacks; stack++)
for (var slice = 0; slice < slices; slice++)
{
var n = slices + 1; // Keep the line length down.
if (stack != 0)
{
mesh.TriangleIndices.Add((stack + 0) * n + slice);
mesh.TriangleIndices.Add((stack + 1) * n + slice);
mesh.TriangleIndices.Add((stack + 0) * n + slice + 1);
}
if (stack != stacks - 1)
{
mesh.TriangleIndices.Add((stack + 0) * n + slice + 1);
mesh.TriangleIndices.Add((stack + 1) * n + slice);
mesh.TriangleIndices.Add((stack + 1) * n + slice + 1);
}
}
return mesh;
}
}
public static class DynamicCurosr
{
static public bool InSession { get; private set; }
private static Panel theCursor;
private static readonly ScaleTransform ScaleTransform = new ScaleTransform(1, 1);
private static readonly MatrixTransform MatrixTransform = new MatrixTransform(1, 0, 0, 1, 0, 0);
private static Color defaultFill = Color.FromArgb(20, 255, 255, 255);
private static Color fillFromUser;
private static double strokeFromUser = 0;
private static Color strokeColorFromUser = Colors.Black;
private static int centerDotSizeFromUser = 10; // need to get from user
private static double initialDiameter = double.NaN;
private static Panel cursorPanel;
private static Panel mousePanel;
public static bool Start(Panel cursorPanelIn, Panel mousePanelIn, double radius)
{
return Start(cursorPanelIn, mousePanelIn, radius, defaultFill);
}
public static bool Start(Panel cursorPanelIn, Panel mousePanelIn, double radius, Color fill, Color strokeColor = default(Color), double strokeSize = .16)
{
strokeColor = strokeColor == default(Color) ? Colors.Black : strokeColor;
strokeColorFromUser = strokeColor;
fillFromUser = fill;
strokeFromUser = strokeColor == default(Color) ? 0 : strokeSize;
initialDiameter = double.IsNaN(initialDiameter) ? radius * 2 : initialDiameter;
return Start(cursorPanelIn, mousePanelIn);
}
private static bool Start(Panel cursorPanelIn, Panel mousePanelIn)
{
if (InSession) return false;
cursorPanel = cursorPanelIn;
mousePanel = mousePanelIn;
var point = Mouse.GetPosition(cursorPanel);
theCursor = MakeACursor(theCursor, initialDiameter / 2);
InSession = true;
cursorPanel.Cursor = Cursors.None;
theCursor.Visibility = Visibility.Visible;
Move(point);
if (cursorPanel.Children.Contains(theCursor))
return false;
cursorPanel.Children.Add(theCursor);
Mouse.OverrideCursor = Cursors.None;
return true;
}
public static void Stop()
{
if (InSession)
{
Mouse.OverrideCursor = null;
theCursor.Visibility = Visibility.Collapsed;
cursorPanel.Children.Remove(theCursor);
InSession = false;
}
}
public static void Move(Point point)
{
if (InSession && theCursor.Visibility == Visibility.Visible)
{
var m = MatrixTransform.Matrix;
m.OffsetX = point.X - theCursor.Width / 2;
m.OffsetY = point.Y - theCursor.Height / 2;
MatrixTransform.Matrix = m;
theCursor.RenderTransform = MatrixTransform;
}
}
public static Panel MakeACursor(Panel theCursor, double radius, Color fillColorIn = default(Color), Color strokeColorIn = default(Color))
{
var strokeColor = new SolidColorBrush(strokeColorIn == default(Color) ? strokeColorFromUser : strokeColorIn);
if (theCursor == null)
{
theCursor = new Grid()
{
Width = radius * 2,
Height = radius * 2,
Background = null,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
RenderTransform = ScaleTransform,
RenderTransformOrigin = new Point(.5, .5),
};
var cursorElement = new Ellipse
{
Width = radius * 2,
Height = radius * 2,
Fill = new SolidColorBrush(fillColorIn == default(Color) ? fillFromUser : fillColorIn),
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
StrokeThickness = strokeFromUser,
Stroke = strokeColor,
RenderTransformOrigin = new Point(.5, .5)
};
theCursor.Children.Add(cursorElement);
}
MakeCursorOverlay(theCursor, radius, strokeColor);
return theCursor;
}
public static void MakeCursorOverlay(Panel theCursor, double radius, SolidColorBrush strokeColor)
{
var save = theCursor.Children[0];
theCursor.Children.Clear();
theCursor.Children.Add(save);
var circle = new Ellipse
{
Width = centerDotSizeFromUser,
Height = centerDotSizeFromUser,
Fill = null,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
StrokeThickness = strokeFromUser,
Stroke = strokeColor,
RenderTransformOrigin = new Point(.5, .5)
};
theCursor.Children.Add(circle);
}
}
}

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 draw a dynamic Grid with XNA

I'm trying to draw grid using the XNA framework, this grid should have a fixed dimension, during the execution of XNA, but should be given to the user the opportunity to customize it before launch the game page (I'm building my app with the silverlight/xna template).
Does anyone has a suggestion on how achieve this goal?
Thank you
Set a tileSize, and then draw a texture over the size of grid you want.
Here is some reworked code. This is how I would start with generating a tilemap, by using a 2d array.
int tileSize = 32;
Vector2 position = Vector2.Zero;
Texture2D gridTexture;
int[,] map = new int[,]
{
{1, 1, 0,},
{0, 1, 1,},
{1, 1, 0,},
};
Then add something like this to your draw function:
for (int i = 0; i <= map.GetUpperBound(0); i++)
{
for (int j = 0; j <= map.GetUpperBound(1); j++)
{
int textureId = map[i, j];
if (textureId != 0)
{
Vector2 texturePosition = new Vector2(i * tileSize, j * tileSize) + position;
//Here you would typically index to a Texture based on the textureId.
spriteBatch.Draw(gridTexture, texturePosition, null, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0f);
}
}
}
ContentManager contentManager;
GameTimer timer;
SpriteBatch spriteBatch;
LifeGrid life;
int tileSize = 32;
Vector2 position = Vector2.Zero;
Texture2D gridTexture;
int[,] map;
public GamePage()
{
InitializeComponent();
// Get the content manager from the application
contentManager = (Application.Current as App).Content;
// Create a timer for this page
timer = new GameTimer();
//timer.UpdateInterval = TimeSpan.FromTicks(333333);
timer.UpdateInterval = TimeSpan.Zero;
timer.Update += OnUpdate;
timer.Draw += OnDraw;
List<Position> p = new List<Position>();
p.Add(new Position(1,1));
p.Add(new Position(1,4));
p.Add(new Position(1,5));
p.Add(new Position(1,6));
p.Add(new Position(1,7));
this.life = new LifeGrid(10, 10, p);
map = new int[,]{{1, 1, 0,},{0, 1, 1,},{1, 1, 0,},};
// LayoutUpdated += new EventHandler(GamePage_LayoutUpdated);
}
/// <summary>
/// Allows the page to draw itself.
/// </summary>
private void OnDraw(object sender, GameTimerEventArgs e)
{
// SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);
// SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.Black);
// Draw the sprite
spriteBatch.Begin();
for (int i = 0; i <= map.GetUpperBound(0); i++)
{
for (int j = 0; j <= map.GetUpperBound(1); j++)
{
int textureId = map[i, j];
if (textureId != 0)
{
Vector2 texturePosition = new Vector2(i * tileSize, j * tileSize) + position;
//Here you would typically index to a Texture based on the textureId.
spriteBatch.Draw(gridTexture, texturePosition, null, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0f);
}
}
}
spriteBatch.End();
}

caching and rendering spritesheets doesn't work

I'd like to cache my spritesheet (tilesheet) into an array. I do this because every spritesheet shall be cached inside of an array so my objects can pull their tiles from them easily. But my cache doesn't seem to work because absolutely nothing gets rendered out of it. I can't see anything.
There is something inside my cache (likely bitmapData) and it is not null so currently I don't know where the problem might be.
Can someone help me out with this issue, please?
this function shall render each tile of an array to a background via copypixels
public function renderCachedTile(canvasBitmapData:BitmapData, tileArray:Array):void
{
tileCache = tileArray;
tileArray = [];
x = nextX;
y = nextY;
point.x = x;
point.y = y;
tileRect.x = tileWidth;
tileRect.y = tileHeight;
if (animationCount >= animationDelay)
{
animationCount = 0;
if(reverse)
{
currentTile--;
if (currentTile < 1)
{
currentTile = tilesLength - 1;
}
} else {
currentTile++;
if (currentTile >= tilesLength - 1)
{
currentTile = 0;
}
}
} else {
animationCount++;
}
canvasBitmapData.lock();
canvasBitmapData.copyPixels(tileCache[currentTile], tileRect, point);
canvasBitmapData.unlock();
}
this function 'separates' my spritesheet into tiles and throws them into an array
private function tileToCache():void {
var tileBitmapData:BitmapData = new BitmapData(tileWidth, tileHeight, true, 0x00000000);
var tilePt:Point = new Point(0, 0);
var tileRect:Rectangle = new Rectangle;
tileCache = [];
for (var tileCtr:int = 0; tileCtr < tilesLength; tileCtr++) {
tileBitmapData.lock();
tileRect.x = int((tileCtr % spritesPerRow)) * tileWidth;
tileRect.y = int((tileCtr / spritesPerRow)) * tileHeight;
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
tileBitmapData.unlock();
tileCache.push(tileBitmapData);
}
}
Unless there is code missing from your example, in your tileToCache you instantiate and use tileRect without defining a width and height:
private function tileToCache():void {
var tileRect:Rectangle = new Rectangle;
/* ... */
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
If your source was at 0, 0 I presume you would want:
var tileRect:Rectangle = new Rectangle(0, 0, tileWidth, tileHeight);

Resources