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