private IndexedImage CreateNewImageWithPalette(IndexedImage sourceImage, Palette palette, IndexedImage destImage) { if (destImage == null) { destImage = sourceImage.Clone(false); } destImage.Size = sourceImage.Size; destImage.Palette = palette.Clone(); var destPixels = destImage.Pixels; var searcher = new PaletteQuickColorSearcher(palette); Parallel.ForEach(sourceImage.Palette, sourceColor => { Color substColor = searcher.SearchSubstitute(sourceColor); Debug.Assert(substColor != null, "Substitute color was not found."); foreach (int occurrence in sourceColor.UsageOccurrences) { destPixels[occurrence] = substColor.Argb; } }); return(destImage); }
public void TestSearchSubstiture() { var palette = new Palette { new Color(0), new Color(250, 250, 250), new Color(100, 0, 0), new Color(0, 100, 0), new Color(0, 0, 100), new Color(0, 0, 101) }; var quickColorSearcher = new PaletteQuickColorSearcher(palette); using (ColorDistance.UseCoeffs(1, 1, 1)) { Assert.AreEqual(new Color(0), quickColorSearcher.SearchSubstitute(new Color(0))); Assert.AreEqual(new Color(250, 250, 250), quickColorSearcher.SearchSubstitute(new Color(254, 254, 254))); Assert.AreEqual(new Color(0, 0, 100), quickColorSearcher.SearchSubstitute(new Color(98, 98, 99))); Assert.AreEqual(new Color(0, 100, 0), quickColorSearcher.SearchSubstitute(new Color(98, 99, 98))); Assert.AreEqual(new Color(100, 0, 0), quickColorSearcher.SearchSubstitute(new Color(99, 98, 98))); Assert.AreEqual(new Color(0, 0, 100), quickColorSearcher.SearchSubstitute(new Color(0, 0, 99), true)); Assert.AreEqual(new Color(0, 0, 101), quickColorSearcher.SearchSubstitute(new Color(0, 0, 99), true)); } }
private void UpdateUsagesCounts(Palette palette, IndexedImage sourceImage) { foreach (Color color in palette) { color.ClearOccurrences(); } var searcher = new PaletteQuickColorSearcher(palette); foreach (Color sourceColor in sourceImage.Palette) { Color substColor = searcher.SearchSubstitute(sourceColor); Debug.Assert(substColor != null, "Substitute color was not found."); substColor.OccurrencesCount += sourceColor.OccurrencesCount; } }
public IndexedImage DitherNewImageWithPalette(IndexedImage sourceImage, Palette palette, int ditherLevel, IndexedImage destImage = null) { Debug.Assert((ditherLevel >= 1) && (ditherLevel <= MaxDitherLevel), "ditherLevel should is out of range"); if (destImage == null) { destImage = sourceImage.Clone(false); } destImage.Size = sourceImage.Size; destImage.Palette = palette.Clone(); var sourcePixels = sourceImage.Pixels; var destPixels = destImage.Pixels; const int ErrorCoeff = MaxDitherLevel * MaxDitherLevel * 16; var tempPixels = new int[sourcePixels.Length, 3]; for (var i = 0; i < sourcePixels.Length; i++) { var colorHash = sourcePixels[i]; tempPixels[i, ColorBytes.RedIdx] = colorHash.Red() * ErrorCoeff; tempPixels[i, ColorBytes.GreenIdx] = colorHash.Green() * ErrorCoeff; tempPixels[i, ColorBytes.BlueIdx] = colorHash.Blue() * ErrorCoeff; } var ditherLevel2 = ditherLevel * ditherLevel; var ditherCoeffRight = 7 * ditherLevel2; var ditherCoeffBottomLeft = 3 * ditherLevel2; var ditherCoeffBottomMiddle = 5 * ditherLevel2; var ditherCoeffBottomRight = 1 * ditherLevel2; var searcher = new PaletteQuickColorSearcher(palette); var sourceWidth = sourceImage.Size.Width; for (var i = 0; i < sourcePixels.Length; i++) { var r = tempPixels[i, ColorBytes.RedIdx] / ErrorCoeff; if (r < 0) { r = 0; } if (r > 255) { r = 255; } var g = tempPixels[i, ColorBytes.GreenIdx] / ErrorCoeff; if (g < 0) { g = 0; } if (g > 255) { g = 255; } var b = tempPixels[i, ColorBytes.BlueIdx] / ErrorCoeff; if (b < 0) { b = 0; } if (b > 255) { b = 255; } var colorSubs = searcher.SearchSubstitute((byte)r, (byte)g, (byte)b); Debug.Assert(colorSubs != null, "Substitute color was not found."); destPixels[i] = colorSubs.Argb; // Populate errors var colorHash = sourcePixels[i]; var dr = colorHash.Red() - colorSubs.R; var dg = colorHash.Green() - colorSubs.G; var db = colorHash.Blue() - colorSubs.B; var index = i + 1; // right if ((index < sourcePixels.Length) && ((index % sourceWidth) != 0)) { tempPixels[index, ColorBytes.RedIdx] += dr * ditherCoeffRight; tempPixels[index, ColorBytes.GreenIdx] += dg * ditherCoeffRight; tempPixels[index, ColorBytes.BlueIdx] += db * ditherCoeffRight; } index = i + sourceWidth - 1; // bottom left if ((index < sourcePixels.Length) && ((i % sourceWidth) != 0)) { tempPixels[index, ColorBytes.RedIdx] += dr * ditherCoeffBottomLeft; tempPixels[index, ColorBytes.GreenIdx] += dg * ditherCoeffBottomLeft; tempPixels[index, ColorBytes.BlueIdx] += db * ditherCoeffBottomLeft; } index++; // bottom middle if (index < sourcePixels.Length) { tempPixels[index, ColorBytes.RedIdx] += dr * ditherCoeffBottomMiddle; tempPixels[index, ColorBytes.GreenIdx] += dg * ditherCoeffBottomMiddle; tempPixels[index, ColorBytes.BlueIdx] += db * ditherCoeffBottomMiddle; } index++; // bottom right if ((index < sourcePixels.Length) && ((index % sourceWidth) != 0)) { tempPixels[index, ColorBytes.RedIdx] += dr * ditherCoeffBottomRight; tempPixels[index, ColorBytes.GreenIdx] += dg * ditherCoeffBottomRight; tempPixels[index, ColorBytes.BlueIdx] += db * ditherCoeffBottomRight; } } return(destImage); }