I've got two images, one of them I'll create using Graphics (a simple circle/ellipse).
Now I want to remove a part of the circle using another image. It should support removing alpha values too.
I hope the link works, if not please write it into comments & I'll fix it.
Thanks for any advice
EDIT:
Image 2 does not really have any border, it is just to show the frame size...
The following will do:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var image1 = new BitmapImage(new Uri("1.png", UriKind.Relative));
var image2 = new BitmapImage(new Uri("2.png", UriKind.Relative));
var bitmap1 = BitmapFactory.ConvertToPbgra32Format(image1);
var bitmap2 = BitmapFactory.ConvertToPbgra32Format(image2);
var width = 256;
var height = 256;
var bitmap3 = BitmapFactory.New(width, height);
var transparent = Color.FromArgb(0, 0, 0, 0);
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var color1 = bitmap1.GetPixel(x, y);
var color2 = bitmap2.GetPixel(x, y);
Color color3;
if (color1.Equals(transparent))
{
color3 = transparent;
}
else
{
if (color2.Equals(transparent))
{
color3 = color1;
}
else
{
color3 = transparent;
}
}
bitmap3.SetPixel(x, y, color3);
}
}
Image1.Source = bitmap3;
}
}
}
I've used https://www.nuget.org/packages/WriteableBitmapEx/ to make things simpler, be careful about having 32-bit PNG as well as what is a transparent color because in WPF it is a transparent white in fact.
You should be able to translate that to Forms easily if this is what you're using, with this https://msdn.microsoft.com/en-us/library/system.drawing.bitmap%28v=vs.110%29.aspx.
EDIT : you could have used an opacity mask but since pic.2 does not its outer dark, it wouldn't have worked.
Finally, I wrote the code by myself. This is it:
public static Bitmap RemovePart(Bitmap source, Bitmap toRemove)
{
Color c1, c2, c3;
c3 = Color.FromArgb(0, 0, 0, 0);
for (int x = 0; x < source.Width; x++)
{
for (int y = 0; y < source.Height; y++)
{
c1 = source.GetPixel(x, y);
c2 = toRemove.GetPixel(x, y);
if (c2 != c3)
{
source.SetPixel(x, y, Color.FromArgb(c2.A, c1));
}
}
}
}
Related
I would like to be able to create X x Y number of boxes / circles / buttons inside a picturebox. EXACTLY like Windows Defrag tool.
I tried to create a layout and keep adding buttons or pictureboxes to it, but its extremely slow and after 200 or so pictureboxes it crashes, runs out of window handles or memory.
What's the alternative? Can you show me a simple piece of code to add boxes just like Defrag tool where I can easily access them like
box[x,y].Color = Green as my app makes progress?
Currently I have this:
private void ResetTableStyles()
{
boardPanel.Controls.Clear();
boardPanel.RowStyles.Clear();
boardPanel.ColumnStyles.Clear();
boardPanel.RowCount = Rows;
boardPanel.ColumnCount = Columns;
for (int i = 0; i < Rows; i++)
{
boardPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100f));
}
for (int j = 0; j < Columns; j++)
{
boardPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
}
}
private void CreateButtons()
{
for (int i = 0; i < Rows; i++)
{
for (int j = 0; j < Columns; j++)
{
var button = new PictureBox
{
BackColor = Color.White,
Dock = DockStyle.Fill,
Margin = Padding.Empty,
Tag = new Point(i, j),
BackgroundImageLayout = ImageLayout.Stretch
};
//button.MouseDown += button_MouseDown;
boardPanel.Controls.Add(button, j, i);
}
}
}
which as I said doesn't work, after sometime it just crashes and it takes very long time.
Perhaps someone has a better answer, but you could use a Panel as the canvas and handle the Paint event to draw colored rectangles onto the Panel. You could then use the mouse events, such as MouseMove, to figure out which cell you're on.
Here is a super-simple proof of concept.
// Data.cs
namespace WindowsFormsApplication
{
public class Data
{
public int State { get; set; }
public string Tip { get; set; }
}
}
// Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var rng = new Random();
_data = new Data[30 * 30];
for (int i = 0; i < _data.Length; i++)
{
_data[i] = new Data
{
State = rng.Next(0, 3),
Tip = $"Data at index: {i}"
};
}
}
private Data[] _data;
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (var brush = new SolidBrush(Color.Gray))
using (var buffer = BufferedGraphicsManager.Current.Allocate(e.Graphics,
new Rectangle(0, 0, 450, 450)))
{
for (int x = 0; x < 30; x++)
{
for (int y = 0; y < 30; y++)
{
int dataIdx = (y * 30) + x;
Data data = _data[dataIdx];
if (data.State == 1)
{
brush.Color = Color.Blue;
}
else if (data.State == 2)
{
brush.Color = Color.Red;
}
else
{
brush.Color = Color.Gray;
}
buffer.Graphics.FillRectangle(brush, x * 15, y * 15, 15, 15);
buffer.Graphics.DrawLine(Pens.Black, 0, y * 15, 450, y * 15); //Gridline
}
buffer.Graphics.DrawLine(Pens.Black, x * 15, 0, x * 15, 450); //Gridline
}
buffer.Render(e.Graphics);
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
var point = e.Location;
int x = point.X / 15;
int y = point.Y / 15;
int dataIdx = (y * 30) + x;
System.Diagnostics.Debug.WriteLine(_data[dataIdx].Tip);
}
}
}
The Data class represents the model behind each segment on the panel and is pretty straight forward.
Form1 has a single control placed on it: a Panel named panel1 with a size of 450 x 450. Each cell on the panel will be 15 x 15, so we have 30 columns and 30 rows. In Form1's constructor, we initialize the Data that will be used to draw the panel.
Inside of Form1.panel1_Paint we iterate through the cells and look up the instance of Data for the given cell. Then, based on the State, set a color for the cell and draw a rectangle of that color. This is done on a buffer so the panel doesn't flicker when painting.
Inside of Form1.panel1_MouseMove we use the location of the mouse pointer relative to panel1 to figure out which cell the mouse is over, get the instance of Data for that cell, and display the Tip in the debug window.
You might be able to take this and build upon it, perhaps with a custom UserControl so you can easily access each individual cell with the column and row... your box[x, y].Color = Colors.Green example above.
I have a cropped version of an image that should appear on my screen.
Image 6Island = Image.FromFile("C:\\Users\\6Island.png");
Now the next goal is to Take an image of the screen.
Bitmap CaptureScreen()
{
var image = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
var gfx = Graphics.FromImage(image);
gfx.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
return image;
}
Image 6Island = Image.FromFile("C:\\Users\\6Island.png");
Image currentView = CaptureScreen();
I then want to see if I can I can find the image 6Island inside the new image. And the colors may vary a tiny bit. Is there anyway to do that?
This is just sample quick and dirty and very slow, but it works. This code make a "crop" of your big bitmap and compare it with your small bitmap. If equal then percentage must be 100, if unequal then percentage lower than that. I would say, if bigger than 98%, then you found it.
private static void CompareBigAndSmallBitmaps(string fileName1, string fileName2)
{
var bmpBig = (Bitmap) Image.FromFile(fileName1);
var bmpSmall = (Bitmap) Image.FromFile(fileName2);
for (var offX = 0; offX < bmpBig.Width - bmpSmall.Width; offX++)
{
for (var offY = 0; offY < bmpBig.Height - bmpSmall.Height; offY++)
{
var percentage = CompareSmallBitmaps(bmpBig, bmpSmall, offX, offY);
if (percentage > 98.0) // define percentage of equality
{
// Aha... found something here....and exit here if you want
}
}
}
}
private static double CompareSmallBitmaps(Bitmap bmpBig, Bitmap bmpSmall, int offX, int offY)
{
var equals = 0;
for (var x = 0; x < bmpSmall.Width; x++)
{
for (var y = 0; y < bmpSmall.Height; y++)
{
var color1 = bmpBig.GetPixel(x + offX, y + offY).ToArgb();
var color2 = bmpSmall.GetPixel(x, y).ToArgb();
if (color1 == color2)
{
equals++;
}
}
}
return (Convert.ToDouble(equals)/Convert.ToDouble(bmpSmall.Width*bmpSmall.Height))*100.0;
}
What would be the best way to draw 25 rectangles (5*5) in c#?
I later need to be able to reach a specific rectangle and change its color, for instance change the color to red if the user inputs the incorrect word.
Would it be more suitable to create an array of rectangles in this case?
This is what i have so far
Graphics g = pictureBox1.CreateGraphics();
int x =0;
int y= 0;
int width = 20;
int height = 20;
for (int i = 0; i < 25; i++)
{
if (i <= 4)
{
g.FillRectangle(Brushes.Blue, x, y, width, height);
x += 50;
}
else if (i > 4)
{
y = 50;
g.FillRectangle(Brushes.Blue, x, y, width, height);
x += 50;
}
}
This should get you started, not the complete code. You will need to add a PictureBox control and use the default name (picurebox1). EDIT: Need to add a button too :)
public partial class Form1 : Form
{
public List<Rectangle> listRec = new List<Rectangle>();
Graphics g;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Rectangle rect = new Rectangle();
rect.Size = new Size(100,20);
for (int x = 0; x < 5; x++)
{
rect.X = x * rect.Width;
for (int y = 0; y < 5; y++)
{
rect.Y = y * rect.Height;
listRec.Add(rect);
}
}
foreach (Rectangle rec in listRec)
{
g = pictureBox1.CreateGraphics();
Pen p = new Pen(Color.Blue);
g.DrawRectangle(p, rec);
}
}
public void ChangeColor(Rectangle target, Color targetColor)
{
Pen p = new Pen(targetColor);
g.DrawRectangle(p, target.X, target.Y, target.Width, target.Height);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.D0: ChangeColor(listRec[0], Color.Red);
break;
case Keys.D1: ChangeColor(listRec[1], Color.Red);
break;
//..more code to handle all keys..
}
}
}
If you're not concerned with performance or the looks, then the easiest approach would be to create a List of Lists of Panels in your Form_Load event as one of the comments mentions.
List<List<Panel>> panelGrid = new List<List<Panel>>();
for (var i = 0; i < 5; i++)
{
var panelRow = new List<Panel>();
for (var j = 0; j < 5; j++)
{
panelRow.Add(new Panel());
// add positioning logic here
}
panelGrid.Add(panelRow);
}
Then you will be able to reference each individual one at a later stage...
If you have to use Graphics class (which is the better approach), then you should setup something similar however replacing Panel with a class of your own. Then in Form_Paint event you would iterate through the list of objects and render them.
class MyPanel
{
public Size size;
public Color color;
}
...
foreach (var myPanelRow in myPanelGrid)
foreach (var myPanel in myPanelRow)
g.FillRectangle(myPanel.color, myPanel.size); // this obviously won't work as is, but you get the idea
Then when you need to change a color, you do something like:
myPanelsGrid[0][0].color = Color.Blue;
myForm.Invalidate();
The second line will result in Paint in event being called again.
I am developing a windows form application in C#. I have to add face recognition functionality. For that purpose I am using OpenNI Library. The hardware for video capture is Xtion PRO LIVE.
I have successfully installed it and I was able to run the sample code. This code continuously recording video and nothing else. I have modified it in such a way that after pressing Capture button, It saves the current picture to hard drive (Its fine!).
Now what I want to accomplish is to detect face by facial landmarks so that I can verify a person's image with saved images in database. How can I do this with OpenNI?
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenNI;
using System.Threading;
using System.Drawing.Imaging;
namespace CameraApp
{
public partial class MainWindow : Form
{
public MainWindow()
{
InitializeComponent();
this.context = Context.CreateFromXmlFile(SAMPLE_XML_FILE, out scriptNode);
this.depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
if (this.depth == null)
{
throw new Exception("Viewer must have a depth node!");
}
this.histogram = new int[this.depth.DeviceMaxDepth];
MapOutputMode mapMode = this.depth.MapOutputMode;
this.bitmap = new Bitmap((int)mapMode.XRes, (int)mapMode.YRes, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
this.shouldRun = true;
this.readerThread = new Thread(ReaderThread);
this.readerThread.Start();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
lock (this)
{
e.Graphics.DrawImage(this.bitmap,
this.panelView.Location.X,
this.panelView.Location.Y,
this.panelView.Size.Width,
this.panelView.Size.Height);
}
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//Don't allow the background to paint
}
protected override void OnClosing(CancelEventArgs e)
{
this.shouldRun = false;
this.readerThread.Join();
base.OnClosing(e);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == 27)
{
Close();
}
base.OnKeyPress(e);
}
private unsafe void CalcHist(DepthMetaData depthMD)
{
// reset
for (int i = 0; i < this.histogram.Length; ++i)
this.histogram[i] = 0;
ushort* pDepth = (ushort*)depthMD.DepthMapPtr.ToPointer();
int points = 0;
for (int y = 0; y < depthMD.YRes; ++y)
{
for (int x = 0; x < depthMD.XRes; ++x, ++pDepth)
{
ushort depthVal = *pDepth;
if (depthVal != 0)
{
this.histogram[depthVal]++;
points++;
}
}
}
for (int i = 1; i < this.histogram.Length; i++)
{
this.histogram[i] += this.histogram[i - 1];
}
if (points > 0)
{
for (int i = 1; i < this.histogram.Length; i++)
{
this.histogram[i] = (int)(256 * (1.0f - (this.histogram[i] / (float)points)));
}
}
}
private unsafe void ReaderThread()
{
DepthMetaData depthMD = new DepthMetaData();
while (this.shouldRun)
{
try
{
this.context.WaitOneUpdateAll(this.depth);
}
catch (Exception)
{
}
this.depth.GetMetaData(depthMD);
CalcHist(depthMD);
lock (this)
{
Rectangle rect = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height);
BitmapData data = this.bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer();
//// set pixels
//for (int y = 0; y < depthMD.YRes; ++y)
//{
// byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
// for (int x = 0; x < depthMD.XRes; ++x, ++pDepth, pDest += 3)
// {
// byte pixel = (byte)this.histogram[*pDepth];
// pDest[0] = 0;
// pDest[1] = pixel;
// pDest[2] = pixel;
// }
//}
// This will point to the depth image.
ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer();
// This will point to the RGB image.
RGB24Pixel* pRGB =
(RGB24Pixel*)this.depth.DepthMapPtr.ToPointer();
// Go over the depth and RGB image and set the bitmaps
// we're copying to based on our depth & RGB values.
for (int y = 0; y < depthMD.YRes; ++y)
{
// Assuming that the size of each data frame is
// 640x480.
// Scan line by line (480 lines), each line
// consists of 640 pointers.
byte* pDest_Depth =
(byte*)data.Scan0.ToPointer() + y *
data.Stride;
byte* pDest_Rgb = (byte*)data.Scan0.ToPointer()
+ y * data.Stride;
for (int x = 0; x < depthMD.XRes; ++x,
++pDepth, pDest_Depth += 3,
++pRGB, pDest_Rgb += 3)
{
// Change the color of the bitmap
// based on depth value.
byte pixel = (byte)this.histogram[*pDepth];
pDest_Depth[0] = 0;
pDest_Depth[1] = pixel;
pDest_Depth[2] = pixel;
// Get the RGB values to generate
// a whole RGB image.
byte red = pRGB->Red;
byte green = pRGB->Green;
byte blue = pRGB->Blue;
// Get depth information.
ushort depthVal = *pDepth;
}
}
this.bitmap.UnlockBits(data);
}
this.Invalidate();
}
}
private readonly string SAMPLE_XML_FILE = #"C:/Program Files/Microsoft Visual Studio 10.0/Microsoft Visual Studio 2010 Ultimate - ENU/OpenNI/Data/SamplesConfig.xml";
private Context context;
private ScriptNode scriptNode;
private DepthGenerator depth;
private Thread readerThread;
private bool shouldRun;
private Bitmap bitmap;
private int[] histogram;
private void button1_Click(object sender, EventArgs e)
{
this.readerThread.Abort();
this.bitmap.Save("D:\\Screenshot.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
this.readerThread = new Thread(ReaderThread);
this.readerThread.Start();
}
}
}
Any kind of help will be appreciated. Any tutorial/link anything!!!
I want to develop a noise reduction project, so
how to find pixel coordinates in an image .
you can try this
Bitmap bmp = new Bitmap("filename");
//to get the pixel color
Color c= bmp.GetPixel(50,50);
//to set the color of the pixel
bmp.SetPixel(50, 50, Color.Green);
The below code will give you all pixel coordinates in image
namespace WindowsFormsApplication4
{
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
private const string FILE_NAME = #"C:\Temp\Capture.png";
private const double BW_THRESHOLD = 0.5;
private readonly Color colorBlack =
Color.FromArgb(255, 0, 0, 0);
private readonly Color colorWhite =
Color.FromArgb(255, 255, 255, 255);
private readonly Bitmap originalImage;
private readonly Bitmap convertedImage;
private readonly List<Vertex> vertices = new List<Vertex>();
public Form1()
{
InitializeComponent();
pictureBox1.ImageLocation = FILE_NAME;
this.originalImage = new Bitmap(FILE_NAME);
this.convertedImage = this.Img2BW(this.originalImage, BW_THRESHOLD);
foreach (Vertex vert in this.vertices)
{
listBox1.Items.Add(vert.ToString());
}
}
private Bitmap Img2BW(Bitmap imgSrc, double threshold)
{
int width = imgSrc.Width;
int height = imgSrc.Height;
Color pixel;
Bitmap imgOut = new Bitmap(imgSrc);
for (int row = 0; row < height - 1; row++)
{
for (int col = 0; col < width - 1; col++)
{
pixel = imgSrc.GetPixel(col, row);
if (pixel.GetBrightness() < threshold)
{
this.vertices.Add(new Vertex(col, row));
imgOut.SetPixel(col, row, this.colorBlack);
}
else
{
imgOut.SetPixel(col, row, this.colorWhite);
}
}
}
return imgOut;
}
}
public class Vertex
{
public Vertex(int i, int j)
{
this.X = i;
this.Y = j;
}
public int X { get; set; }
public int Y { get; set; }
public string ToString()
{
return string.Format("({0}/{1})", this.X, this.Y);
}
}
}
A pixel is merely a colour located at a position in a cartesian coordinate system, to easily read and write these colours in an image, you can use the Bitmap class, using the GetPixel and SetPixel methods.