public static UIImage Filter(UIImage img, int puzzleSize) { int tileSize = 2; int paletteColorsNumber = BasePaletteColorsNumber + (8 * puzzleSize / 64); // 1/ Get the main colors // So we have a color palette Logger.I("Filter: getting palette..."); var colorPalette = getColorPalette(img, paletteColorsNumber); // 1/ Resize & Load image as readable UIImage resizedImg = UIImageEx.ResizeRatio(img, puzzleSize); Bitmap bitmap = new Bitmap(resizedImg); // 2/ Apply mosaic Logger.I("Filter: applying mosaic..."); var flippedImage = applyMosaic(tileSize, colorPalette, resizedImg, bitmap); // -- Flip because bitmap has inverted coordinates Logger.I("Filter: resizing..."); UIImage finalImg = new UIImage(flippedImage, 0f, UIImageOrientation.DownMirrored); // UIImage finalImg = new UIImage (flippedImage); // -- Resize the final // return ResizeRatio (finalImg, FinalSize); Logger.I("Filter: image ready!"); return(finalImg); }
private static List <Color> getColorPalette(UIImage img, int paletteColorsNumber) { // -- Make a thumbnail for better performace Logger.D("Palette -> resize"); UIImage thumb = UIImageEx.ResizeRatio(img, Math.Min(96, (int)Math.Max(img.Size.Width, img.Size.Height))); Bitmap thumbBitmap = new Bitmap(thumb); // -- Get each colors Logger.D("Palette -> get each color"); Dictionary <Color, int> rawColorList = new Dictionary <Color, int> (); for (int xq = 0; xq < thumb.Size.Width; xq++) { for (int yq = 0; yq < thumb.Size.Height; yq++) { Color c = thumbBitmap.GetPixel(xq, yq); if (rawColorList.ContainsKey(c)) { rawColorList [c] += 1; } else { rawColorList.Add(c, 1); } } // for y } // for x var orderedColorList = rawColorList .Where(c => c.Value > 1) // Take only colors that appear at least twice (huge optim) .OrderByDescending(c => c.Value) // Order by frequency .Select(c => c.Key) // Select only keys .ToList(); // -- Look if we have a similar color already in the palette Logger.D("Palette -> restrict to n"); List <Color> colorPalette = new List <Color> (paletteColorsNumber); while (colorPalette.Count < paletteColorsNumber) { if (orderedColorList.Any() == false) { Logger.W("Palette -> Not enough color!"); break; } Color c1 = orderedColorList.First(); List <Color> similarColors = new List <Color> (); similarColors.Add(c1); int avg_r = c1.R; int avg_b = c1.B; int avg_g = c1.G; // Look for similar colors foreach (Color c2 in orderedColorList) { if (c1 == c2) { continue; } double distance = Math.Abs(Math.Pow(c1.R - c2.R, 2) + Math.Pow(c1.G - c2.G, 2) + Math.Pow(c1.B - c2.B, 2)); if (distance < PaletteColorDifferenceThreshold) { // Too close, do the average avg_r += c2.R; avg_g += c2.G; avg_b += c2.B; similarColors.Add(c2); } } // Add the average colors Color newColor = Color.FromArgb( avg_r / similarColors.Count, avg_g / similarColors.Count, avg_b / similarColors.Count ); colorPalette.Add(newColor); // Remove checked colors foreach (var deletedColor in similarColors) { orderedColorList.Remove(deletedColor); } } // Free things thumbBitmap = null; return(colorPalette); }