private static TextureByteIndexPalette ReduceColorPalette(string name, Bitmap bitmap, List <Color> allColors, ColorPaletteAlgorithm algorithm, int targetColors) { if (targetColors > 256) { throw new ArgumentOutOfRangeException(nameof(targetColors));// Indices over byte.MaxValue are not supported } byte[] indices = new byte[bitmap.Width * bitmap.Height]; switch (algorithm) { case ColorPaletteAlgorithm.MostUsedColorsRGB: { int[] colorUsage = new int[allColors.Count]; // Calculate usage for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { colorUsage[allColors.IndexOf(bitmap.GetPixel(x, y))]++; } } var byUsage = allColors.OrderByDescending((col) => { int index = allColors.IndexOf(col); return(colorUsage[index]); // How many times was the color used }).ToArray(); Array.Resize(ref byUsage, targetColors); // Get nearest pixel by RGB for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { indices[x + y * bitmap.Width] = (byte)NearestColorRGB(byUsage, bitmap.GetPixel(x, y)); } } return(new TextureByteIndexPalette(name, bitmap.Width, bitmap.Height, indices, byUsage)); } case ColorPaletteAlgorithm.MostUsedColorsHSB: { int[] colorUsage = new int[allColors.Count]; // Calculate usage for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { colorUsage[allColors.IndexOf(bitmap.GetPixel(x, y))]++; } } var byUsage = allColors.OrderByDescending((col) => { int index = allColors.IndexOf(col); return(colorUsage[index]); // How many times was the color used }).ToArray(); Array.Resize(ref byUsage, targetColors); // Get nearest pixel by HSB for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { indices[x + y * bitmap.Width] = (byte)NearestColorHSB(byUsage, bitmap.GetPixel(x, y)); } } return(new TextureByteIndexPalette(name, bitmap.Width, bitmap.Height, indices, byUsage)); } case ColorPaletteAlgorithm.BasicPaletteNearestRGB: { if (targetColors != 256) { throw new ArgumentOutOfRangeException(nameof(targetColors)); } var palette = BasicPalette; // Get nearest pixel by RGB for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { indices[x + y * bitmap.Width] = (byte)NearestColorRGB(palette, bitmap.GetPixel(x, y)); } } return(new TextureByteIndexPalette(name, bitmap.Width, bitmap.Height, indices, palette)); } case ColorPaletteAlgorithm.BasicPaletteNearestHSB: { if (targetColors != 256) { throw new ArgumentOutOfRangeException(nameof(targetColors)); } var palette = BasicPalette; // Get nearest pixel by HSB for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { indices[x + y * bitmap.Width] = (byte)NearestColorHSB(palette, bitmap.GetPixel(x, y)); } } return(new TextureByteIndexPalette(name, bitmap.Width, bitmap.Height, indices, palette)); } } throw new NotSupportedException(); }
public static TextureByteIndexPalette CreateFromBitmap(string name, Bitmap bitmap, ColorPaletteAlgorithm algorithm = ColorPaletteAlgorithm.BasicPaletteNearestHSB) { var indices = new byte[bitmap.Width * bitmap.Height]; var colors = new List <Color>(); // Add all colors into the palette (to count them) for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { var c = bitmap.GetPixel(x, y); if (!colors.Contains(c)) { colors.Add(c); } } } if (colors.Count <= 256) { for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { Color c = bitmap.GetPixel(x, y); int index = colors.IndexOf(c); indices[x + y * bitmap.Width] = (byte)index; } } return(new TextureByteIndexPalette(name, bitmap.Width, bitmap.Height, indices, colors.ToArray())); } else { return(ReduceColorPalette(name, bitmap, colors, algorithm, 256)); } }