public static bool Solve(Bitmap puzzle, out int offsetX) { if (puzzle == null) { offsetX = 0; return(false); } using (Bitmap test = new GrayscaleBT709().Apply(puzzle)) { BitmapData data = test.LockBits(new Rectangle(0, 0, test.Width, test.Height), ImageLockMode.ReadWrite, test.PixelFormat); byte[] points = new byte[data.Stride * test.Height]; Marshal.Copy(data.Scan0, points, 0, points.Length); for (int y = 0; y < test.Height; y++) { for (int x = 0; x < data.Stride; x++) { int i = y * data.Stride + x; if (x > 50 && x < data.Stride - 10 && points[i] - points[i + 1] > 80) { points[i] = points[i + 1]; } else { points[i] = 255; } } } Marshal.Copy(points, 0, data.Scan0, points.Length); test.UnlockBits(data); new Invert().ApplyInPlace(test); new BlobsFiltering { MinHeight = 5, MaxWidth = 1 }.ApplyInPlace(test); BlobCounter counter = new BlobCounter(); counter.ObjectsOrder = ObjectsOrder.Size; counter.ProcessImage(test); Rectangle[] blobs = counter.GetObjectsRectangles(); offsetX = blobs.Length == 1 ? blobs[0].X - 5 : blobs.Length == 2 && blobs[0].X == blobs[1].X ? blobs[0].X - 5 : 0; return(offsetX > 0); } }