private static int FindNearestPal(RGBQUAD inputPal, List <RGBQUAD> palList, Dictionary <RGBQUAD, int> additionalPalMap) { if (additionalPalMap.TryGetValue(inputPal, out var addPal)) { return(addPal); } var ind = palList .IndexOf(palList .OrderBy(x => Math.Sqrt(Math.Pow(x.rgbBlue - inputPal.rgbBlue, 2) + Math.Pow(x.rgbGreen - inputPal.rgbGreen, 2) + Math.Pow(x.rgbRed - inputPal.rgbRed, 2))) .First()); additionalPalMap[inputPal] = ind; return(ind); }
private static void EncodeColorMapWithAlpha(byte[] decodedData, BITMAPINFOHEADER bmi, ProcessData processData, out byte[] encodedData, out byte[] alphaData, out RGBQUAD[] pal) { //must be padded to 4 bytes uint rgbStride = (uint)((bmi.biWidth * processData.Decoding.Bmi.biBitCount / 8 + 3) & ~3); alphaData = new byte[processData.Decoding.Bmi.biBitCount == 8 ? bmi.biHeight * bmi.biWidth : processData.Decoding.AlphaBuff.Length]; encodedData = new byte[processData.Decoding.Bmi.biBitCount == 8 ? bmi.biHeight * rgbStride : processData.Decoding.EncodedData.Length]; var palList = useExistingPal ? processData.Decoding?.PalArray.ToList() : new List <RGBQUAD>(); var additionalPalMap = new Dictionary <RGBQUAD, int>(); for (long y = 0; y < bmi.biHeight; y++) { uint alphaLineIndex = (uint)((bmi.biHeight - y - 1) * bmi.biWidth); uint rgbaLineIndex = (uint)(y * bmi.biWidth * 4); long rgbLineIndex = y * rgbStride; for (long x = 0; x < bmi.biWidth; x++) { long blueIndex = rgbaLineIndex + x * 4 + 0; if (processData.Decoding.Bmi.biBitCount == 8) { var newPal = new RGBQUAD { rgbBlue = decodedData[blueIndex], rgbGreen = decodedData[blueIndex + 1], rgbRed = decodedData[blueIndex + 2] }; var palIndex = palList.IndexOf(newPal); if (palIndex == -1) { palIndex = useExistingPal ? FindNearestPal(newPal, palList, additionalPalMap) : GetPal(newPal, palList, additionalPalMap); } encodedData[y * rgbStride + x] = (byte)palIndex; } else { encodedData[rgbLineIndex + x * 3] = decodedData[blueIndex]; encodedData[rgbLineIndex + x * 3 + 1] = decodedData[blueIndex + 1]; encodedData[rgbLineIndex + x * 3 + 2] = decodedData[blueIndex + 2]; } alphaData[alphaLineIndex + x] = decodedData[blueIndex + 3]; } } if (palList.Count < 256) { palList.AddRange(Enumerable.Repeat(new RGBQUAD(), 256 - palList.Count)); } pal = palList.ToArray(); }