// Calculating from fastBitmap depending if image is grayscale public Histogram(FastBitmap bmp, bool isGrayscale) { if (isGrayscale) { HistogramTable = new int[256]; for (int i = 0; i < bmp.Size.Width; ++i) { for (int j = 0; j < bmp.Size.Height; ++j) { HistogramTable[bmp[i, j].R]++; Total++; } } Max = HistogramTable.Max(); Average = HistogramTable.Average(); } else { // Calculating RGB histogram values HistogramTable = new int[256]; HistogramTableRed = new int[256]; HistogramTableGreen = new int[256]; HistogramTableBlue = new int[256]; for (int i = 0; i < bmp.Size.Width; ++i) { for (int j = 0; j < bmp.Size.Height; ++j) { HistogramTable[bmp[i, j].R]++; HistogramTableRed[bmp[i, j].R]++; HistogramTableGreen[bmp[i, j].G]++; HistogramTableBlue[bmp[i, j].B]++; Total++; } } Max = HistogramTable.Max(); Average = HistogramTable.Average(); } }
// Point operations public static FastBitmap Operation(FastBitmap bmp1, FastBitmap bmp2, Operations op) { // Combining two images FastBitmap bmp = new FastBitmap(Math.Max(bmp1.Width, bmp2.Width), Math.Max(bmp1.Height, bmp2.Height)); for (int i = 0; i < bmp.Size.Width; ++i) { for (int j = 0; j < bmp.Size.Height; ++j) { Color c1; Color c2; if (isPixelValid(i, j, bmp1.Width, bmp1.Height)) { c1 = bmp1[i, j]; } else { c1 = Color.Black; } if (isPixelValid(i, j, bmp2.Width, bmp2.Height)) { c2 = bmp2[i, j]; } else { c2 = Color.Black; } // Switching through operations and performing last one switch (op) { case Operations.Add: bmp[i, j] = Color.FromArgb(255, Math.Min(255, c1.R + c2.R), Math.Min(255, c1.G + c2.G), Math.Min(255, c1.B + c2.B)); break; case Operations.Subtract: bmp[i, j] = Color.FromArgb(255, Math.Max(0, c1.R - c2.R), Math.Max(0, c1.G - c2.G), Math.Max(0, c1.B - c2.B)); break; case Operations.Multiply: bmp[i, j] = Color.FromArgb(255, Math.Min(255, c1.R * c2.R), Math.Min(255, c1.G * c2.G), Math.Min(255, c1.B * c2.B)); break; case Operations.Divide: bmp[i, j] = Color.FromArgb(255, c1.R / Math.Max((byte)1, c2.R), c1.G / Math.Max((byte)1, c2.G), c1.B / Math.Max((byte)1, c2.B)); break; case Operations.Difference: bmp[i, j] = Color.FromArgb(255, Math.Abs(c1.R - c2.R), Math.Abs(c1.G - c2.G), Math.Abs(c1.B - c2.B)); break; case Operations.AND: bmp[i, j] = Color.FromArgb(255, Math.Max(0, Math.Min(255, c1.R & c2.R)), Math.Max(0, Math.Min(255, c1.G & c2.G)), Math.Max(0, Math.Min(255, c1.B & c2.B))); break; case Operations.OR: bmp[i, j] = Color.FromArgb(255, Math.Max(0, Math.Min(255, c1.R | c2.R)), Math.Max(0, Math.Min(255, c1.G | c2.G)), Math.Max(0, Math.Min(255, c1.B | c2.B))); break; case Operations.XOR: bmp[i, j] = Color.FromArgb(255, Math.Max(0, Math.Min(255, c1.R ^ c2.R)), Math.Max(0, Math.Min(255, c1.G ^ c2.G)), Math.Max(0, Math.Min(255, c1.B ^ c2.B))); break; } } } return(bmp); }
// Thinning (Skeletonization) method public static void Thinning(FastBitmap bmp) { // Init edge operators int[] dx = { 0, 1, 1, 1, 0, -1, -1, -1 }; int[] dy = { 1, 1, 0, -1, -1, -1, 0, 1 }; bool[,] img = new bool[bmp.Width, bmp.Height]; int W = bmp.Width; int H = bmp.Height; for (int i = 0; i < bmp.Width; ++i) { for (int j = 0; j < bmp.Height; ++j) { img[i, j] = bmp[i, j].B < 128; } } bool pass = false; LinkedList <Point> list; do { pass = !pass; list = new LinkedList <Point>(); for (int x = 1; x < W - 1; ++x) { for (int y = 1; y < H - 1; ++y) { if (img[x, y]) { int cnt = 0; int hm = 0; bool prev = img[x - 1, y + 1]; for (int i = 0; i < 8; ++i) { bool cur = img[x + dx[i], y + dy[i]]; hm += cur ? 1 : 0; if (prev && !cur) { ++cnt; } prev = cur; } if (hm > 1 && hm < 7 && cnt == 1) { if (pass && (!img[x + 1, y] || !img[x, y + 1] || !img[x, y - 1] && !img[x - 1, y])) { list.AddLast(new Point(x, y)); } if (!pass && (!img[x - 1, y] || !img[x, y - 1] || !img[x, y + 1] && !img[x + 1, y])) { list.AddLast(new Point(x, y)); } } } } } foreach (Point p in list) { img[p.X, p.Y] = false; } } while (list.Count != 0); for (int x = 0; x < W; ++x) { for (int y = 0; y < H; ++y) { bmp[x, y] = img[x, y] ? Color.Black : Color.White; } } }