/// <summary> /// Selects a guessed background of the input image /// </summary> /// <param name="input">The input image</param> /// <param name="token">The cancellation token</param> /// <remarks>Performs a BFS</remarks> /// <returns>Returns the list of pixels having the same color as the color of the guessed background, null when cancellation was requested</returns> private List <int> SelectBackground(PPImage input, CancellationToken token = default) { SKColor bgColor = SKColors.Transparent; Dictionary <SKColor, List <int> > components = new Dictionary <SKColor, List <int> >(); int[] cornerIndices = new int[] { 0, //top-left input.Bitmap.Width - 1, //top-right (input.Bitmap.Height - 1) * input.Bitmap.Width, //bottom-left input.Bitmap.Width *input.Bitmap.Height - 1 }; //bottom-right}; var pixels = input.Bitmap.Pixels; SKColor[] cornerColors = new SKColor[4] { pixels[cornerIndices[0]], pixels[cornerIndices[1]], pixels[cornerIndices[2]], pixels[cornerIndices[3]] }; bool[] visited = new bool[input.Bitmap.Width * input.Bitmap.Height]; Dictionary <SKColor, float> colorCounts = new Dictionary <SKColor, float>(); Queue <int> toVisit = new Queue <int>(); foreach (var corner in cornerIndices) { if (token.IsCancellationRequested) { return(null); } toVisit.Enqueue(corner); visited[corner] = true; } if (cornerColors.All(x => x == cornerColors[0])) { colorCounts.Add(cornerColors[0], 0.0f); components.Add(cornerColors[0], new List <int>()); int totalVisited = 0; while (toVisit.Count > 0) { if (token.IsCancellationRequested) { return(null); } var curr = toVisit.Dequeue(); totalVisited++; foreach (var neigh in GetNeighborhood(curr, input).Where(x => x != curr && x >= 0 && x < input.Bitmap.Width * input.Bitmap.Height)) { if (visited[neigh] || pixels[neigh] != cornerColors[0]) { continue; } toVisit.Enqueue(neigh); visited[neigh] = true; } if (pixels[curr] == cornerColors[0]) { components[cornerColors[0]].Add(curr); colorCounts[cornerColors[0]] += 1.0f; } } return(components[cornerColors[0]]); } else { var uniqueColors = cornerColors.Distinct(); foreach (var x in uniqueColors) { components.Add(x, new List <int>()); colorCounts.Add(x, 0.0f); } while (toVisit.Count > 0) { if (token.IsCancellationRequested) { return(null); } var curr = toVisit.Dequeue(); foreach (var neigh in GetNeighborhood(curr, input).Where(z => z != curr && z >= 0 && z < input.Bitmap.Width * input.Bitmap.Height)) { if (visited[neigh] || !cornerColors.Contains(pixels[neigh])) { continue; } toVisit.Enqueue(neigh); visited[neigh] = true; } //if (uniqueColors.Contains(input.Pixels[curr])) //{ components[pixels[curr]].Add(curr); float x = curr % input.Bitmap.Width; float y = curr / input.Bitmap.Width; float middleX = input.Bitmap.Width / 2.0f; float middleY = input.Bitmap.Height / 2.0f; colorCounts[pixels[curr]] += Max(Abs(middleX - x), Abs(middleY - y)); //colorCounts[input.Pixels[curr]] += 1.0f; //} visited[curr] = true; } bgColor = colorCounts.OrderByDescending(x => x.Value).First().Key; return(components[bgColor]); } //return bgColor; }