private unsafe BorderAnalysis AnalyzeRgb(BitmapData bitmap, Rectangle rectangle, int colorThreshold, float bucketThreshold) { var h = bitmap.Height; var w = bitmap.Width; // Stride, scan width. var s = bitmap.Stride; // Scan0, pointer to first scan. var s0 = (byte *)bitmap.Scan0; // A list of counted colors found along the rectangle border var colors = new Dictionary <Color, int>(colorThreshold); // A list of counted color buckets var buckets = new Dictionary <int, int>(ColorExtensions.GetMaxColorBuckets()); // A loop of pixels along the left edge from top to bottom for (var y = 0; y < h; y++) { // Pointer to current scanline var row = s0 + y * s; // Pixels are stored in b,g,r-order // In this case one byte per color var p = rectangle.Left * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; // Create a color value var c = Color.FromArgb(r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } // A loop of pixels along the right edge from top to bottom for (var y = 0; y < h; y++) { var row = s0 + y * s; var p = (rectangle.Right - 1) * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var c = Color.FromArgb(r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } // A loop of pixels along the top edge from left to right for (var x = 0; x < w; x++) { var row = s0 + rectangle.Top * s; var p = x * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var c = Color.FromArgb(r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } // A loop of pixels along the bottom edge from left to right for (var x = 0; x < w; x++) { var row = s0 + (rectangle.Bottom - 1) * s; var p = x * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var c = Color.FromArgb(r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } return(new BorderAnalysis(colors, buckets, colorThreshold, bucketThreshold)); }
private unsafe BorderAnalysis AnalyzeArgb(BitmapData bitmap, Rectangle rectangle, int colorThreshold, float bucketThreshold) { var h = bitmap.Height; var w = bitmap.Width; var s = bitmap.Stride; var s0 = (byte *)bitmap.Scan0; var colors = new Dictionary <Color, int>(colorThreshold); var buckets = new Dictionary <int, int>(ColorExtensions.GetMaxColorBuckets()); unchecked { for (var y = 0; y < h; y++) { var row = s0 + y * s; var p = rectangle.Left * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var a = row[p + 3]; var c = a == 0 ? Color.Transparent : Color.FromArgb(a, r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } for (var y = 0; y < h; y++) { var row = s0 + y * s; var p = (rectangle.Right - 1) * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var a = row[p + 3]; var c = a == 0 ? Color.Transparent : Color.FromArgb(a, r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } for (var x = 0; x < w; x++) { var row = s0 + rectangle.Top * s; var p = x * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var a = row[p + 3]; var c = a == 0 ? Color.Transparent : Color.FromArgb(a, r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } for (var x = 0; x < w; x++) { var row = s0 + (rectangle.Bottom - 1) * s; var p = x * BytesPerPixel; var b = row[p]; var g = row[p + 1]; var r = row[p + 2]; var a = row[p + 3]; var c = a == 0 ? Color.Transparent : Color.FromArgb(a, r, g, b); var ce = colors.ContainsKey(c); if (ce) { colors[c]++; } else if (colors.Count < colorThreshold) { colors.Add(c, 1); } if (ce || colors.Count >= colorThreshold) { var cb = c.ToColorBucket(); if (buckets.ContainsKey(cb)) { buckets[cb]++; } else { buckets.Add(cb, 1); } } } } return(new BorderAnalysis(colors, buckets, colorThreshold, bucketThreshold)); }