public static void RemapPalette(FreeImageBitmap bitmap, Palette newPalette) { if (bitmap.ColorDepth > 8) { bitmap.Quantize(FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, 256, newPalette); } var sourcePal = bitmap.Palette.AsArray.Select(c => c.uintValue).ToArray(); var destPal = newPalette.AsArray.Select(c => c.uintValue).ToArray(); int[] srcToDest = new int[256]; for (int i = 0; i < 256; i++) { srcToDest[i] = -1; } //first map identical colors { Dictionary <int, int> rgbToPaletteIndex = new Dictionary <int, int>(); for (int i = 0; i < 256; i++) { int c = (int)(destPal[i] & 0xFFFFFF); if (!rgbToPaletteIndex.ContainsKey(c)) { rgbToPaletteIndex.Add(c, i); } } for (int i = 0; i < 256; i++) { int c = (int)(sourcePal[i] & 0xFFFFFF); if (rgbToPaletteIndex.ContainsKey(c)) { srcToDest[i] = rgbToPaletteIndex[c]; } } } //map remaining colors { for (int i = 0; i < 256; i++) { if (srcToDest[i] == -1) { int c = (int)(sourcePal[i] & 0xFFFFFF); int minDistance = int.MaxValue; int minIndex = -1; for (int j = 0; j < 256; j++) { int c2 = (int)(destPal[j] & 0xFFFFFF); int distance = GetDistance(c, c2); if (distance < minDistance) { minDistance = distance; minIndex = j; } } srcToDest[i] = minIndex; } } } byte[] sequence = new byte[256]; byte[] srcToDestByte = new byte[256]; { for (int i = 0; i < 256; i++) { sequence[i] = (byte)i; srcToDestByte[i] = (byte)srcToDest[i]; } } bitmap.ApplyPaletteIndexMapping(sequence, srcToDestByte, 256, false); bitmap.Palette.AsArray = newPalette.AsArray; }