private void GenerateBordersPaths(Bitmap bitmap) { Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); IntPtr ptr = bmpData.Scan0; int bytes = bmpData.Stride * bitmap.Height; byte[] rgbValues = new byte[bytes]; Marshal.Copy(ptr, rgbValues, 0, bytes); int height = bitmap.Height; int width = bitmap.Width; Color[,] pixelColors = new Color[bitmap.Height, bitmap.Width]; // Store pixel color in matrix Parallel.For(0, bytes / 3, (int i) => { i *= 3; int pRow = (i / 3) / width; int pCol = (i / 3) % width; pixelColors[pRow, pCol] = Color.FromArgb(rgbValues[i + 2], rgbValues[i + 1], rgbValues[i]); }); bitmap.UnlockBits(bmpData); // Stores vertical and horizontal border pixels of a province Dictionary <Color, HashSet <BorderPoint[]> > provincesPoints = new Dictionary <Color, HashSet <BorderPoint[]> >(this._mProvinceCount); object lockObj = new Object(); //Traverse lines Parallel.For(0, height, (int prow) => { for (int col = 0; col < width; col++) { Color color = pixelColors[prow, col]; lock (lockObj) { if (!provincesPoints.ContainsKey(color)) { provincesPoints.Add(color, new HashSet <BorderPoint[]>()); } } BorderPoint[] colorLine = new BorderPoint[3]; colorLine[0] = new BorderPoint(col, prow); do { if (col < width) { if (color == pixelColors[prow, col]) { col++; } else { break; } } else { break; } } while (true); col--; colorLine[1] = new BorderPoint(col, prow); colorLine[2] = new BorderPoint(-1, 0); // horizontal line lock (lockObj) { HashSet <BorderPoint[]> lines = provincesPoints[color]; lines.Add(colorLine); } } }); //Traverse columns Parallel.For(0, width, (int col) => { for (int row = 0; row < height; row++) { Color color = pixelColors[row, col]; BorderPoint[] colorLine = new BorderPoint[3]; colorLine[0] = new BorderPoint(col, row); do { if (row < height) { if (color == pixelColors[row, col]) { row++; } else { break; } } else { break; } } while (true); row--; colorLine[1] = new BorderPoint(col, row); colorLine[2] = new BorderPoint(-2, 0); // vertical line lock (lockObj) { HashSet <BorderPoint[]> lines = provincesPoints[color]; lines.Add(colorLine); } } }); this._mProvincesLines = new Dictionary <Color, HashSet <BorderLine> >(provincesPoints.Count); // Get border lines from border pixels object lockobj = new Object(); Parallel.ForEach(provincesPoints, (KeyValuePair <Color, HashSet <BorderPoint[]> > keyValue) => { lock (lockobj) { this._mProvincesLines.Add(keyValue.Key, new HashSet <BorderLine>(keyValue.Value.Count / 4)); } this.ProcessProvince(keyValue.Value, this._mProvincesLines[keyValue.Key]); }); }
/// <summary> /// Initialize a new instance of <see cref="BorderLine"/> that has the specified coordinates. /// </summary> /// <param name="start"> Start of the line.</param> /// <param name="end"> End of the line.</param> public BorderLine(BorderPoint start, BorderPoint end) { this._mStart = start; this._mEnd = end; }