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 TestClone() { IndexedImage image = new IndexedImage { Size = new Size(3, 2) }; image.Pixels[0] = 1; image.Pixels[1] = 2; image.Pixels[2] = 3; image.Pixels[3] = 1; image.Pixels[4] = 4; image.Pixels[5] = 2; image.CompletePalette(); IndexedImage clonedImage = image.Clone(true, true); Assert.AreEqual(image.Size, clonedImage.Size); Assert.AreEqual(image.Pixels.Length, clonedImage.Pixels.Length); Assert.AreNotSame(image.Pixels, clonedImage.Pixels); Assert.AreEqual(image.Pixels[0], clonedImage.Pixels[0]); Assert.AreEqual(image.Pixels[1], clonedImage.Pixels[1]); Assert.AreEqual(image.Pixels[2], clonedImage.Pixels[2]); Assert.AreEqual(image.Pixels[3], clonedImage.Pixels[3]); Assert.AreEqual(image.Pixels[4], clonedImage.Pixels[4]); Assert.AreEqual(image.Pixels[5], clonedImage.Pixels[5]); Assert.AreEqual(image.Palette.Count, clonedImage.Palette.Count); Assert.AreNotSame(image.Palette, clonedImage.Palette); Assert.AreEqual(image.Palette[1], clonedImage.Palette[1]); Assert.AreEqual(image.Palette[2], clonedImage.Palette[2]); Assert.AreEqual(image.Palette[3], clonedImage.Palette[3]); Assert.AreEqual(image.Palette[4], clonedImage.Palette[4]); clonedImage[0, 0] = new Color(100); Assert.AreEqual(100, clonedImage.Pixels[0]); Assert.AreEqual(1, image.Pixels[0], "Changes in cloned image should not change original"); Assert.AreEqual(5, clonedImage.Palette.Count); Assert.AreEqual(4, image.Palette.Count, "Changes in cloned image should not change original"); PaletteTest.AssertColorInPalette(clonedImage.Palette, 100, 100, 0); PaletteTest.AssertColorInPalette(clonedImage.Palette, 1, 1, 3); PaletteTest.AssertColorInPalette(image.Palette, 1, 1, 0, 3); }
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); }