public void CalculatePalette(int colorCount = 256) { if (colorCount > 256) { colorCount = 256; // For some reason it fails with more... } var colorThief = new ColorThief(); var palette = new List <QuantizedColor>(); using (var image = ToBitmap()) palette = colorThief.GetPalette(image, colorCount, 10, false); // Sort colours by YIQ luma so they align nicely var sortedPalette = palette.OrderBy(entry => entry.CalculateYiqLuma(entry.Color)); Palette.Clear(); foreach (var color in sortedPalette) { if (color.Color.ToHsl().L > 0.009) // Filter out dark values { var newColor = new ColorC(color.Color.R, color.Color.G, color.Color.B); if (!Palette.Contains(newColor)) // Filter out duplicates { Palette.Add(newColor); } } } }
/// <summary> /// uint's are platform dependet representation of the color. /// They should stay private inside ImageC to prevent abuse. /// </summary> private static unsafe uint ColorToUint(ColorC color) { byte *byteArray = stackalloc byte[4]; byteArray[0] = color.B; byteArray[1] = color.G; byteArray[2] = color.R; byteArray[3] = color.A; return(*(uint *)byteArray); }
public void Fill(ColorC color) { for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { SetPixel(x, y, color); } } }
public void ApplyKernel(int xStart, int yStart, int width, int height, int weight, int[,] kernel) { ImageC oldImage = new ImageC(width, height, new byte[width * height * 4]); oldImage.CopyFrom(0, 0, this, xStart, yStart, width, height); int kernel_width = kernel.GetUpperBound(0) + 1; int kernel_height = kernel.GetUpperBound(1) + 1; for (int x = 0, xReal = xStart; x < width; x++, xReal++) { for (int y = 0, yReal = yStart; y < height; y++, yReal++) { int r = 0, g = 0, b = 0; for (int dx = 0; dx < kernel_width; dx++) { for (int dy = 0; dy < kernel_height; dy++) { int sourceX = MathC.Clamp(x + dx, 0, width - 1); int sourceY = MathC.Clamp(y + dy, 0, height - 1); ColorC clr = oldImage.GetPixel(sourceX, sourceY); r += (int)clr.R * kernel[dx, dy]; g += (int)clr.G * kernel[dx, dy]; b += (int)clr.B * kernel[dx, dy]; } } r = MathC.Clamp((int)(127 + r / weight), 0, 255); g = MathC.Clamp((int)(127 + g / weight), 0, 255); b = MathC.Clamp((int)(127 + b / weight), 0, 255); SetPixel(xReal, yReal, new ColorC((byte)r, (byte)g, (byte)b)); } } // Restore alpha for (int x = 0, xReal = xStart; x < width; x++, xReal++) { for (int y = 0, yReal = yStart; y < height; y++, yReal++) { var alpha = oldImage.GetPixel(xReal, yReal).A; var color = GetPixel(xReal, yReal); color.A = alpha; SetPixel(xReal, yReal, color); } } }
public unsafe void ReplaceColor(ColorC from, ColorC to) { uint fromUint = ColorToUint(from); uint toUint = ColorToUint(to); fixed(void *ptr = _data) { uint *ptrUint = (uint *)ptr; uint *ptrUintEnd = ptrUint + Width * Height; while (ptrUint < ptrUintEnd) { if (*ptrUint == fromUint) { *ptrUint = toUint; } ++ptrUint; } } }
public void SetPixel(int x, int y, ColorC color) { SetPixel(x, y, color.R, color.G, color.B, color.A); }
public void Set(int i, ColorC color) { Set(i, color.R, color.G, color.B, color.A); }