Miscellaneous Code
Code Sample 1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Collections.Concurrent;
namespace Code_Sample1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Polygon Fill---------------------------------------------------------------------------------------
public struct Coord
{
public double x;
public double y;
}
public struct Box
{
public Coord Max;
public Coord Min;
}
public void PolyFill(ref Bitmap bmp, Coord[] Poly, Color FColor)
{
Coord P1;
Coord P2;
Box Bx;
double x1 = 0;
double x2 = 0;
double xi = 0;
double yi = 0;
double[] Table = null;
int tb = 0;
int nvert = Poly.Length - 1;
if (Poly[nvert].x != Poly[0].x || Poly[nvert].y != Poly[0].y)
{
MessageBox.Show("polygon opened , can't fill ");
return;
}
Bx.Max.x = double.MinValue;
Bx.Max.y = double.MinValue;
Bx.Min.x = double.MaxValue;
Bx.Min.y = double.MaxValue;
for (int i = 0; i <= nvert; i++)
{
Bx.Max.x = Math.Max(Bx.Max.x, Poly[i].x);
Bx.Max.y = Math.Max(Bx.Max.y, Poly[i].y);
Bx.Min.x = Math.Min(Bx.Min.x, Poly[i].x);
Bx.Min.y = Math.Min(Bx.Min.y, Poly[i].y);
}
// Generic Fill Algorithm
// x1,x2, Horizontal Scanline Area
x1 = Bx.Min.x;
x2 = Bx.Max.x;
// Scanline y
double tempVar = Bx.Max.y + 0.0001;
for (double y = Bx.Min.y + 0.0001; y <= tempVar; y++)
{
Table = new double[0];
tb = 0;
for (int i = 0; i < nvert; i++) { P1 = Poly[i]; P2 = Poly[i + 1]; if (SEGMENT_INTERSECT(P1.x, P1.y, P2.x, P2.y, x1, y, x2, y) == true) { if (LINE_INTERSECTION(P1.x, P1.y, P2.x, P2.y, x1, y, x2, y, ref xi, ref yi) == false) { tb = tb + 1; //Array.Resize(ref Table, tb + 1); //Table[tb] = xi; AddToLastInArray(ref Table, xi); } } } if (tb > 0) // There is at least an intersection
{
// Ordering the intersections from left to right using a generic QuickSort routine
DsortPoly(ref Table);
// Filling
for (int i = 0; i < tb - 1; i += 2)
{
Graphics g = Graphics.FromImage(bmp);
Pen pp = new Pen(FColor, 1);
g.DrawLine(pp, (int)Table[i], (int)y, (int)Table[i + 1], (int)y);
g.Dispose();
}
}
}
Table = null;
tb = 0;
}
private void DsortPoly(ref double[] objs)
{
int num1 = 0;
int num2 = 0;
int length = objs.Length - 1;
double temp;
for (num1 = 0; num1 <= length + 1; num1++)
{
for (num2 = (num1 + 1); num2 <= length; num2++)
{
if (objs[num1] < objs[num2])
{
temp = objs[num1];
objs[num1] = objs[num2];
objs[num2] = temp;
}
}
}
}
public Boolean SEGMENT_INTERSECT(double x1, double y1, double X2, double Y2, double x3, double y3, double x4, double y4)
{
// Returns True if the segment (x 1,y1)-(x 2,y2) intersects the
// segment (x3,y3)-(x4,y4)
Boolean i12 = false;
bool i21 = false;
// C he ck Inte rse ction be twe e n (x 3,x 4) - (x 1,x 2)
if (x1 == X2)
{
i12 = (((x3 <= x1) && (x4 >= x1)) || ((x3 >= x1) && (x4 <= x1)));
}
else if ((int)y1 == (int)Y2)
{
i12 = (((y3 <= y1) && (y4 >= y1)) || ((y3 >= y1) && (y4 <= y1))); } else { i12 = ((((x3 - x1) * (Y2 - y1) >= (y3 - y1) * (X2 - x1)) && ((x4 - x1) * (Y2 - y1) <= (y4 - y1) * (X2 - x1))) || (((x3 - x1) * (Y2 - y1) <= (y3 - y1) * (X2 - x1)) && ((x4 - x1) * (Y2 - y1) >= (y4 - y1) * (X2 - x1))));
}
// Check Intersection between (x1,x2)-(x3,x4)
if ((int)x3 == (int)x4)
{
i21 = ((x1 <= x3) && (X2 >= x3)) || ((x1 >= x3) && (X2 <= x3));
}
else if ((int)y3 == (int)y4)
{
i21 = ((y1 <= y3) && (Y2 >= y3)) || ((y1 >= y3) && (Y2 <= y3)); } else { i21 = ((((x1 - x3) * (y4 - y3) >= (y1 - y3) * (x4 - x3)) && ((X2 - x3) * (y4 - y3) <= (Y2 - y3) * (x4 - x3))) || (((x1 - x3) * (y4 - y3) <= (y1 - y3) * (x4 - x3)) && ((X2 - x3) * (y4 - y3) >= (Y2 - y3) * (x4 - x3))));
}
return i12 && i21;
}
public Boolean LINE_INTERSECTION(double x1, double y1, double X2, double Y2, double x3, double y3, double x4, double y4, ref double xi, ref double yi)
{
double M = 0;
double n = 0;
double P = 0;
double q = 0;
Boolean Parallelss = false;
if ((int)x1 == (int)X2)
{
if ((int)x3 == (int)x4)
{
Parallelss = true;
}
else
{
xi = x1;
yi = (y4 - y3) * (xi - x3) / (x4 - x3) + y3;
}
}
else if ((int)x3 == (int)x4)
{
xi = x3;
yi = (Y2 - y1) * (xi - x1) / (X2 - x1) + y1;
}
else
{
M = (Y2 - y1) / (X2 - x1);
P = y1 - x1 * M;
n = (y4 - y3) / (x4 - x3);
q = y3 - x3 * n;
if (M == n)
{
Parallelss = true;
}
else
{
xi = (q - P) / (M - n);
yi = xi * M + P;
}
}
return Parallelss;
}
private void AddToLastInArray(ref T[] myarray, T valuetoadd)
{
T[] tmp = new T[myarray.Length];
Array.Copy(myarray, tmp, myarray.Length);
myarray = new T[tmp.Length + 1];
Array.Copy(tmp, myarray, tmp.Length);
myarray[tmp.Length] = valuetoadd;
tmp = null;
}
private void AddToFirstInArray(ref T[] myarray, T valuetoadd)
{
T[] tmp = new T[myarray.Length];
Array.Copy(myarray, tmp, myarray.Length);
myarray = new T[tmp.Length + 1];
Array.Copy(tmp, 0, myarray, 1, tmp.Length);
myarray[0] = valuetoadd;
tmp = null;
}
//uses of polygon fill
private void button1_Click(object sender, EventArgs e)
{
Coord[] Poly = new Coord[5];
Poly[0].x = 10;
Poly[0].y = 10;
Poly[1].x = 100;
Poly[1].y = 10;
Poly[2].x = 10;
Poly[2].y = 200;
Poly[3].x = 100;
Poly[3].y = 200;
Poly[4].x = 10;
Poly[4].y = 10;
Bitmap bmp = new Bitmap(400, 400);
PolyFill(ref bmp, Poly, Color.Blue);
pictureBox1.Image = bmp;
}
//Quick draw line mathematically--------------------------------------------------------
private void button2_Click(object sender, EventArgs e)
{
int x1 = 10;
int y1 = 10;
int x2 = 200;
int y2 = 100;
Bitmap bmp = new Bitmap(400, 400);
int g = (int)Math.Pow(Math.Pow((double)(x2 - x1), 2) + Math.Pow((double)(y2 - y1), 2), 0.5);
if (g == 0) g = 1;
for (int r = 0; r <= g; r++) { int i = (int)((double)r * ((double)(x2 - x1) / (double)g) + (double)x1); int j = (int)((double)r * ((double)(y2 - y1) / (double)g) + (double)y1); if ((i >= 0) && (i < bmp.Width) && (j >= 0) && (j < bmp.Height)) bmp.SetPixel(i, j, Color.Red);
}
pictureBox1.Image = bmp;
}
//Erode, Dilate bitmap-----------------------------------------------------------------------------
//Erode darkcolors in bitmap with radius
private void Erode(ref Bitmap bmp, int radius)
{
BitmapData newData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] g_PixBytes = null;
byte[] g_OutBytes = null;
int g_RowSizeBytes = 0;
g_RowSizeBytes = newData.Stride;
int total_size = newData.Stride * newData.Height;
g_PixBytes = new byte[total_size + 1];
g_OutBytes = new byte[total_size + 1];
Marshal.Copy(newData.Scan0, g_PixBytes, 0, total_size);
Array.Copy(g_PixBytes, g_OutBytes, total_size);
int r = radius;
Point[] kernel1 = new Point[(r + 1) * 2 * (r + 1) * 2 + 1];
int kernelcount = 0;
for (double iy = -r; iy <= r; iy++)
{
for (double ix = -r; ix <= r; ix++) { kernel1[kernelcount].X = (int)ix; kernel1[kernelcount].Y = (int)iy; kernelcount = kernelcount + 1; } } int width = bmp.Width; int height = bmp.Height; Parallel.ForEach(Partitioner.Create((int)r, (int)(width - r)), (H) =>
{
for (int x = H.Item1; (x < H.Item2); x++)
{
for (int y = r; y < height - r; y++)
{
int pix = 0;
double rmax = double.MinValue;
double gmax = double.MinValue;
double bmax = double.MinValue;
double rmaxind = 0;
double gmaxind = 0;
double bmaxind = 0;
for (int a = 0; a < kernelcount; a++)
{
pix = (y + (int)kernel1[a].Y) * newData.Stride + 3 * (x + (int)kernel1[a].X);
if (rmax < g_PixBytes[pix + 2])
{
rmax = g_PixBytes[pix + 2];
rmaxind = rmax;
}
if (gmax < g_PixBytes[pix + 1])
{
gmax = g_PixBytes[pix + 1];
gmaxind = gmax;
}
if (bmax < g_PixBytes[pix + 0])
{
bmax = g_PixBytes[pix + 0];
bmaxind = bmax;
}
}
pix = y * newData.Stride + 3 * x;
g_OutBytes[pix + 2] = (byte)rmaxind;
g_OutBytes[pix + 1] = (byte)gmaxind;
g_OutBytes[pix + 0] = (byte)bmaxind;
}
}
});
Marshal.Copy(g_OutBytes, 0, newData.Scan0, total_size);
bmp.UnlockBits(newData);
kernel1 = null;
g_PixBytes = null;
g_OutBytes = null;
}
//Dilate darkcolors in bitmap with radius
private void Dilate(ref Bitmap bmp, int radius)
{
BitmapData newData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] g_PixBytes = null;
byte[] g_OutBytes = null;
int g_RowSizeBytes = 0;
g_RowSizeBytes = newData.Stride;
int total_size = newData.Stride * newData.Height;
g_PixBytes = new byte[total_size + 1];
g_OutBytes = new byte[total_size + 1];
Marshal.Copy(newData.Scan0, g_PixBytes, 0, total_size);
Array.Copy(g_PixBytes, g_OutBytes, total_size);
int r = radius;
Point[] kernel1 = new Point[(r + 1) * 2 * (r + 1) * 2 + 1];
int kernelcount = 0;
for (double iy = -r; iy <= r; iy++)
{
for (double ix = -r; ix <= r; ix++) { kernel1[kernelcount].X = (int)ix; kernel1[kernelcount].Y = (int)iy; kernelcount = kernelcount + 1; } } int width = bmp.Width; int height = bmp.Height; Parallel.ForEach(Partitioner.Create((int)r, (int)(width - r)), (H) =>
{
for (int x = H.Item1; (x < H.Item2); x++)
{
for (int y = r; y < height - r; y++)
{
int pix = 0;
double rmax = double.MaxValue;
double gmax = double.MaxValue;
double bmax = double.MaxValue;
double rmaxind = 0;
double gmaxind = 0;
double bmaxind = 0;
for (int a = 0; a < kernelcount; a++) { pix = (y + (int)kernel1[a].Y) * newData.Stride + 3 * (x + (int)kernel1[a].X); if (rmax > g_PixBytes[pix + 2])
{
rmax = g_PixBytes[pix + 2];
rmaxind = rmax;
}
if (gmax > g_PixBytes[pix + 1])
{
gmax = g_PixBytes[pix + 1];
gmaxind = gmax;
}
if (bmax > g_PixBytes[pix + 0])
{
bmax = g_PixBytes[pix + 0];
bmaxind = bmax;
}
}
pix = y * newData.Stride + 3 * x;
g_OutBytes[pix + 2] = (byte)rmaxind;
g_OutBytes[pix + 1] = (byte)gmaxind;
g_OutBytes[pix + 0] = (byte)bmaxind;
}
}
});
Marshal.Copy(g_OutBytes, 0, newData.Scan0, total_size);
bmp.UnlockBits(newData);
kernel1 = null;
g_PixBytes = null;
g_OutBytes = null;
}
//uses of erode bitmap
private void button3_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(@"C:\test.bmp");
//Erode(ref bmp, 1);
Dilate(ref bmp, 1);
pictureBox1.Image = bmp;
}
//denoise image with radius and sigma-----------------------------------------------------------------------------
private void button4_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(@"C:\test.bmp");
BitmapData newData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte[] g_PixBytes = null;
byte[] g_outBytes = null;
int total_size = newData.Stride * newData.Height;
g_PixBytes = new byte[total_size + 1];
g_outBytes = new byte[total_size + 1];
Marshal.Copy(newData.Scan0, g_PixBytes, 0, total_size);
Array.Copy(g_PixBytes, g_outBytes, g_PixBytes.Length);
int width = bmp.Width;
int height = bmp.Height;
int Nh = 6; //radius
int sigma = 20; //must be an integer 0<=sigma<=255
for (int x1 = Nh; x1 < width - Nh; x1++)
{
for (int y1 = Nh; y1 < height - Nh; y1++)
{
int xx, xxx, yy, yyy;
double r, g, b, sumR, sumG, sumB, countR, countG, countB;
double Rf, Gf, Bf;
sumR = sumG = sumB = countR = countG = countB = 0;
for (yy = -Nh; yy <= Nh; yy++)
{
yyy = y1 + yy;
for (xx = -Nh; xx <= Nh; xx++)
{
xxx = x1 + xx;
int pix1 = 0;
int pix2 = 0;
pix1 = yyy * newData.Stride + 3 * xxx;
r = g_PixBytes[pix1 + 2];
g = g_PixBytes[pix1 + 1];
b = g_PixBytes[pix1 + 0];
pix2 = y1 * newData.Stride + 3 * x1;
if (Math.Abs(g_PixBytes[pix2 + 2] - r) <= sigma)
{
sumR += r;
countR++;
}
if (Math.Abs(g_PixBytes[pix2 + 1] - g) <= sigma)
{
sumG += g;
countG++;
}
if (Math.Abs(g_PixBytes[pix2 + 0] - b) <= sigma)
{
sumB += b;
countB++;
}
}
}
Rf = sumR / countR;
Gf = sumG / countG;
Bf = sumB / countB;
int pix3 = 0;
pix3 = y1 * newData.Stride + 3 * x1;
g_outBytes[pix3 + 2] = (byte)Rf;
g_outBytes[pix3 + 1] = (byte)Gf;
g_outBytes[pix3 + 0] = (byte)Bf;
}
}
Marshal.Copy(g_outBytes, 0, newData.Scan0, total_size);
bmp.UnlockBits(newData);
g_PixBytes = null;
g_outBytes = null;
pictureBox1.Image = bmp;
}
//Convert color to prgb and back----------------------------------------------------------------------
private void button5_Click(object sender, EventArgs e)
{
byte color = 210;
byte alpha = 100;
byte ret = PremultiplyAlphaTonormal(PremultiplyAlpha_Component(color, alpha), alpha);
MessageBox.Show(ret.ToString());
}
private double PremultiplyAlpha_Component(double sourceColor, double alpha)
{
return ((sourceColor * alpha) / 255d);
}
private byte PremultiplyAlphaTonormal(double sourceColor, double alpha)
{
return (byte)(sourceColor / (alpha / 255d));
}
}
}
