/// <summary> /// Checks whether all pixels within a row of a bitmap are the specified color. /// </summary> /// <param name="bitmap">The bitmap to check</param> /// <param name="y">The row of the bitmap to check</param> /// <param name="color">The color to check the row against</param> /// <param name="comparer">The comparer to use to compare the pixels against the specified color</param> /// <returns>Whether all the pixels within the row are the specified color</returns> public static bool IsHorizontalLineWithColor(Bitmap bitmap, int y, Color color, IColorComparer comparer) { using (var data = new LockedBitmapData(bitmap)) { return(IsHorizontalLineWithColor(data, y, color, comparer)); } }
private static bool IsHorizontalLineWithColor(LockedBitmapData data, int y, Color color, IColorComparer comparer) { for (int x = 0; x < data.Bitmap.Width; x++) { if (!comparer.Compare(data.GetPixel(x, y), color)) { return(false); } } return(true); }
/// <summary> /// Applies a transformation to each pixel of a bitmap. /// </summary> public static void TransformPixels(Bitmap bitmap, Func <Color, Color> transformFunc) { using (var data = new LockedBitmapData(bitmap, writeable: true)) { for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { data.SetPixel(x, y, transformFunc(data.GetPixel(x, y))); } } } }
/// <summary> /// Calculates the number of pixels that are different between a region of a test bitmap and a reference bitmap. /// </summary> /// <param name="bitmap">The test bitmap</param> /// <param name="offset">The offset from the top left of the test bitmap of the region to be compared /// against the reference bitmap</param> /// <param name="refBitmap">The reference bitmap</param> /// <param name="comparer">The comparer to use to compare pixels of the two bitmaps</param> /// <param name="maxDifference">The maximum number of different pixels before the comparision will stop early. /// If null, all pixels will be compared.</param> /// <returns>The number of different pixels</returns> public static int CalculateDifference(Bitmap bitmap, Point offset, Bitmap refBitmap, IColorComparer comparer, int?maxDifference = null) { if (!IsRectWithinRect(bitmap.Size, offset, refBitmap.Size)) { return(int.MaxValue); } using (var data1 = new LockedBitmapData(bitmap)) using (var data2 = new LockedBitmapData(refBitmap)) { return(CalculateBitmapRectDifference(data1, offset, data2, new Point(0, 0), refBitmap.Size, comparer, maxDifference)); } }
private static int GetVerticalLineLength(LockedBitmapData data, int x, int startY, Func <Color, bool> predicate) { int y; for (y = startY; y < data.Bitmap.Height; y++) { if (!predicate(data.GetPixel(x, y))) { break; } } return(y - startY); }
public static bool AreBitmapsIdentical(Bitmap bitmap1, Bitmap bitmap2) { if (bitmap1.Size != bitmap2.Size) { return(false); } using (var data1 = new LockedBitmapData(bitmap1)) using (var data2 = new LockedBitmapData(bitmap2)) { int len = data1.Data.Stride * data1.Data.Height; return(NativeMethods.memcmp(data1.Data.Scan0, data2.Data.Scan0, new UIntPtr((uint)len)) == 0); } }
/// <summary> /// Finds the first row within a bitmap for which all the pixels are the specified color. /// The search begins at the specified row and contains downwards until a match is found. /// </summary> /// <param name="bitmap">The bitmap to check</param> /// <param name="startY">The first row of the bitmap to check</param> /// <param name="color">The color to check rows against</param> /// <param name="comparer">The comparer to use to compare the pixels against the specified color</param> /// <returns>The Y coordinate of the first row which is the specified color, or null if none were found</returns> public static int?FindHorizontalLineWithColor(Bitmap bitmap, int startY, Color color, IColorComparer comparer) { using (var data = new LockedBitmapData(bitmap)) { for (int y = startY; y < bitmap.Height; y++) { if (IsHorizontalLineWithColor(data, y, color, comparer)) { return(y); } } } return(null); }
/// <summary> /// Same as FindFirstPoint but the search begins at the bottom right and proceeds backwards. /// </summary> public static Point?FindLastPoint(Bitmap bitmap, Rectangle searchRect, Func <Color, bool> predicate) { using (var data = new LockedBitmapData(bitmap)) { for (int y = searchRect.Bottom - 1; y >= searchRect.Top; y--) { for (int x = searchRect.Right - 1; x >= searchRect.Left; x--) { if (predicate(data.GetPixel(x, y))) { return(new Point(x, y)); } } } } return(null); }
/// <summary> /// Finds all vertical lines within a bitmap that match the specified conditions. /// </summary> /// <param name="bitmap">The bitmap to search</param> /// <param name="searchRect">The rectangle within the bitmap to search</param> /// <param name="minLength">The minimum length of lines to find</param> /// <param name="predicate">A function that returns true if a pixel is considered to be part of a line</param> /// <returns>A list of all vertical lines found</returns> public static IEnumerable <Rectangle> FindVerticalLines(Bitmap bitmap, Rectangle searchRect, int minLength, Func <Color, bool> predicate) { using (var data = new LockedBitmapData(bitmap)) { for (int x = searchRect.Left; x < searchRect.Right; x++) { for (int y = searchRect.Top; y < searchRect.Bottom; y++) { int length = GetVerticalLineLength(data, x, y, predicate); if (length >= minLength) { yield return(new Rectangle(x, y, 1, length)); // Jump past this line to avoid returning duplicates y += length; } } } } }
private static int CalculateBitmapRectDifference(LockedBitmapData data1, Point offset1, LockedBitmapData data2, Point offset2, Size size, IColorComparer comparer, int?maxDifference = null) { int diffs = 0; for (int y = 0; y < size.Height; y++) { for (int x = 0; x < size.Width; x++) { var col1 = data1.GetPixel(x + offset1.X, y + offset1.Y); var col2 = data2.GetPixel(x + offset2.X, y + offset2.Y); if (!comparer.Compare(col1, col2)) { diffs++; if (maxDifference.HasValue && diffs > maxDifference.Value) { return(diffs); } } } } return(diffs); }
/// <summary> /// Calculates how much of the bottom of bitmap1 is the same as the top of bitmap2. /// </summary> public static int CalculateVerticalOverlap(Bitmap bitmap1, Bitmap bitmap2, IColorComparer comparer, int maxDifference) { if (bitmap1.Width != bitmap2.Width) { return(0); } using (var data1 = new LockedBitmapData(bitmap1)) using (var data2 = new LockedBitmapData(bitmap2)) { // If bitmap2 is shorter than bitmap1, start further down, otherwise start at 0. int startY = Math.Max(0, bitmap1.Height - bitmap2.Height); for (int y1 = startY; y1 < bitmap1.Height; y1++) { if (CalculateBitmapRectDifference(data1, new Point(0, y1), data2, new Point(0, 0), new Size(bitmap1.Width, bitmap1.Height - y1), comparer, maxDifference) <= maxDifference) { return(bitmap1.Height - y1); } } return(0); } }