diff --git a/src/ImageProcessorCore/Formats/Quantizers/Octree/OctreeQuantizer.cs b/src/ImageProcessorCore/Formats/Quantizers/Octree/OctreeQuantizer.cs index f13f3aefed..b064fc7e66 100644 --- a/src/ImageProcessorCore/Formats/Quantizers/Octree/OctreeQuantizer.cs +++ b/src/ImageProcessorCore/Formats/Quantizers/Octree/OctreeQuantizer.cs @@ -12,7 +12,7 @@ namespace ImageProcessorCore.Formats /// Encapsulates methods to calculate the colour palette if an image using an Octree pattern. /// /// - public class OctreeQuantizer : Quantizer + public sealed class OctreeQuantizer : Quantizer { /// /// Stores the tree diff --git a/src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs b/src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs index b2a5ac8488..19b95bd006 100644 --- a/src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs +++ b/src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs @@ -45,17 +45,17 @@ namespace ImageProcessorCore.Formats /// /// The index count. /// - private const int IndexCount = (1 << WuQuantizer.IndexBits) + 1; + private const int IndexCount = (1 << IndexBits) + 1; /// /// The index alpha count. /// - private const int IndexAlphaCount = (1 << WuQuantizer.IndexAlphaBits) + 1; + private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1; /// /// The table length. /// - private const int TableLength = WuQuantizer.IndexCount * WuQuantizer.IndexCount * WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount; + private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount; /// /// Maximum allowed color depth @@ -114,25 +114,25 @@ namespace ImageProcessorCore.Formats Guard.MustBeBetweenOrEqualTo(maxColors, 1, 256, nameof(maxColors)); this.maxColors = maxColors; - this.vwt = new long[WuQuantizer.TableLength]; - this.vmr = new long[WuQuantizer.TableLength]; - this.vmg = new long[WuQuantizer.TableLength]; - this.vmb = new long[WuQuantizer.TableLength]; - this.vma = new long[WuQuantizer.TableLength]; - this.m2 = new double[WuQuantizer.TableLength]; - this.tag = new byte[WuQuantizer.TableLength]; + this.vwt = new long[TableLength]; + this.vmr = new long[TableLength]; + this.vmg = new long[TableLength]; + this.vmb = new long[TableLength]; + this.vma = new long[TableLength]; + this.m2 = new double[TableLength]; + this.tag = new byte[TableLength]; } /// public QuantizedImage Quantize(ImageBase image) { Guard.NotNull(image, nameof(image)); - + int colorCount = this.maxColors; this.Clear(); - this.Hist3d(image); + this.Build3DHistogram(image); this.M3d(); Box[] cube; @@ -151,13 +151,13 @@ namespace ImageProcessorCore.Formats /// The index. private static int Ind(int r, int g, int b, int a) { - return (r << ((WuQuantizer.IndexBits * 2) + WuQuantizer.IndexAlphaBits)) - + (r << (WuQuantizer.IndexBits + WuQuantizer.IndexAlphaBits + 1)) - + (g << (WuQuantizer.IndexBits + WuQuantizer.IndexAlphaBits)) - + (r << (WuQuantizer.IndexBits * 2)) - + (r << (WuQuantizer.IndexBits + 1)) - + (g << WuQuantizer.IndexBits) - + ((r + g + b) << WuQuantizer.IndexAlphaBits) + return (r << ((IndexBits * 2) + IndexAlphaBits)) + + (r << (IndexBits + IndexAlphaBits + 1)) + + (g << (IndexBits + IndexAlphaBits)) + + (r << (IndexBits * 2)) + + (r << (IndexBits + 1)) + + (g << IndexBits) + + ((r + g + b) << IndexAlphaBits) + r + g + b + a; } @@ -169,22 +169,22 @@ namespace ImageProcessorCore.Formats /// The result. private static double Volume(Box cube, long[] moment) { - return moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + return moment[Ind(cube.R1, cube.G1, cube.B1, cube.A1)] + - moment[Ind(cube.R1, cube.G1, cube.B1, cube.A0)] + - moment[Ind(cube.R1, cube.G1, cube.B0, cube.A1)] + + moment[Ind(cube.R1, cube.G1, cube.B0, cube.A0)] + - moment[Ind(cube.R1, cube.G0, cube.B1, cube.A1)] + + moment[Ind(cube.R1, cube.G0, cube.B1, cube.A0)] + + moment[Ind(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[Ind(cube.R1, cube.G0, cube.B0, cube.A0)] + - moment[Ind(cube.R0, cube.G1, cube.B1, cube.A1)] + + moment[Ind(cube.R0, cube.G1, cube.B1, cube.A0)] + + moment[Ind(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[Ind(cube.R0, cube.G1, cube.B0, cube.A0)] + + moment[Ind(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[Ind(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[Ind(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; } /// @@ -200,47 +200,47 @@ namespace ImageProcessorCore.Formats { // Red case 0: - return -moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[Ind(cube.R0, cube.G1, cube.B1, cube.A1)] + + moment[Ind(cube.R0, cube.G1, cube.B1, cube.A0)] + + moment[Ind(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[Ind(cube.R0, cube.G1, cube.B0, cube.A0)] + + moment[Ind(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[Ind(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[Ind(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; // Green case 1: - return -moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[Ind(cube.R1, cube.G0, cube.B1, cube.A1)] + + moment[Ind(cube.R1, cube.G0, cube.B1, cube.A0)] + + moment[Ind(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[Ind(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[Ind(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[Ind(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[Ind(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; // Blue case 2: - return -moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[Ind(cube.R1, cube.G1, cube.B0, cube.A1)] + + moment[Ind(cube.R1, cube.G1, cube.B0, cube.A0)] + + moment[Ind(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[Ind(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[Ind(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[Ind(cube.R0, cube.G1, cube.B0, cube.A0)] + - moment[Ind(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; // Alpha case 3: - return -moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[Ind(cube.R1, cube.G1, cube.B1, cube.A0)] + + moment[Ind(cube.R1, cube.G1, cube.B0, cube.A0)] + + moment[Ind(cube.R1, cube.G0, cube.B1, cube.A0)] + - moment[Ind(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[Ind(cube.R0, cube.G1, cube.B1, cube.A0)] + - moment[Ind(cube.R0, cube.G1, cube.B0, cube.A0)] + - moment[Ind(cube.R0, cube.G0, cube.B1, cube.A0)] + + moment[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; default: throw new ArgumentOutOfRangeException(nameof(direction)); @@ -261,50 +261,50 @@ namespace ImageProcessorCore.Formats { // Red case 0: - return moment[WuQuantizer.Ind(position, cube.G1, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(position, cube.G1, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(position, cube.G1, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(position, cube.G1, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(position, cube.G0, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(position, cube.G0, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(position, cube.G0, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(position, cube.G0, cube.B0, cube.A0)]; + return moment[Ind(position, cube.G1, cube.B1, cube.A1)] + - moment[Ind(position, cube.G1, cube.B1, cube.A0)] + - moment[Ind(position, cube.G1, cube.B0, cube.A1)] + + moment[Ind(position, cube.G1, cube.B0, cube.A0)] + - moment[Ind(position, cube.G0, cube.B1, cube.A1)] + + moment[Ind(position, cube.G0, cube.B1, cube.A0)] + + moment[Ind(position, cube.G0, cube.B0, cube.A1)] + - moment[Ind(position, cube.G0, cube.B0, cube.A0)]; // Green case 1: - return moment[WuQuantizer.Ind(cube.R1, position, cube.B1, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, position, cube.B1, cube.A0)] - - moment[WuQuantizer.Ind(cube.R1, position, cube.B0, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, position, cube.B0, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, position, cube.B1, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, position, cube.B1, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, position, cube.B0, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, position, cube.B0, cube.A0)]; + return moment[Ind(cube.R1, position, cube.B1, cube.A1)] + - moment[Ind(cube.R1, position, cube.B1, cube.A0)] + - moment[Ind(cube.R1, position, cube.B0, cube.A1)] + + moment[Ind(cube.R1, position, cube.B0, cube.A0)] + - moment[Ind(cube.R0, position, cube.B1, cube.A1)] + + moment[Ind(cube.R0, position, cube.B1, cube.A0)] + + moment[Ind(cube.R0, position, cube.B0, cube.A1)] + - moment[Ind(cube.R0, position, cube.B0, cube.A0)]; // Blue case 2: - return moment[WuQuantizer.Ind(cube.R1, cube.G1, position, cube.A1)] - - moment[WuQuantizer.Ind(cube.R1, cube.G1, position, cube.A0)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, position, cube.A1)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, position, cube.A0)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, position, cube.A1)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, position, cube.A0)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, position, cube.A1)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, position, cube.A0)]; + return moment[Ind(cube.R1, cube.G1, position, cube.A1)] + - moment[Ind(cube.R1, cube.G1, position, cube.A0)] + - moment[Ind(cube.R1, cube.G0, position, cube.A1)] + + moment[Ind(cube.R1, cube.G0, position, cube.A0)] + - moment[Ind(cube.R0, cube.G1, position, cube.A1)] + + moment[Ind(cube.R0, cube.G1, position, cube.A0)] + + moment[Ind(cube.R0, cube.G0, position, cube.A1)] + - moment[Ind(cube.R0, cube.G0, position, cube.A0)]; // Alpha case 3: - return moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, position)] - - moment[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, position)] - - moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, position)] - + moment[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, position)] - - moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, position)] - + moment[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, position)] - + moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, position)] - - moment[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, position)]; + return moment[Ind(cube.R1, cube.G1, cube.B1, position)] + - moment[Ind(cube.R1, cube.G1, cube.B0, position)] + - moment[Ind(cube.R1, cube.G0, cube.B1, position)] + + moment[Ind(cube.R1, cube.G0, cube.B0, position)] + - moment[Ind(cube.R0, cube.G1, cube.B1, position)] + + moment[Ind(cube.R0, cube.G1, cube.B0, position)] + + moment[Ind(cube.R0, cube.G0, cube.B1, position)] + - moment[Ind(cube.R0, cube.G0, cube.B0, position)]; default: - throw new ArgumentOutOfRangeException("direction"); + throw new ArgumentOutOfRangeException(nameof(direction)); } } @@ -313,22 +313,24 @@ namespace ImageProcessorCore.Formats /// private void Clear() { - Array.Clear(this.vwt, 0, WuQuantizer.TableLength); - Array.Clear(this.vmr, 0, WuQuantizer.TableLength); - Array.Clear(this.vmg, 0, WuQuantizer.TableLength); - Array.Clear(this.vmb, 0, WuQuantizer.TableLength); - Array.Clear(this.vma, 0, WuQuantizer.TableLength); - Array.Clear(this.m2, 0, WuQuantizer.TableLength); - - Array.Clear(this.tag, 0, WuQuantizer.TableLength); + Array.Clear(this.vwt, 0, TableLength); + Array.Clear(this.vmr, 0, TableLength); + Array.Clear(this.vmg, 0, TableLength); + Array.Clear(this.vmb, 0, TableLength); + Array.Clear(this.vma, 0, TableLength); + Array.Clear(this.m2, 0, TableLength); + + Array.Clear(this.tag, 0, TableLength); } /// /// Builds a 3-D color histogram of counts, r/g/b, c^2. /// /// The image. - private void Hist3d(ImageBase image) + private void Build3DHistogram(ImageBase image) { + + // TODO: Parallel for (int y = 0; y < image.Height; y++) { @@ -341,12 +343,12 @@ namespace ImageProcessorCore.Formats byte b = color.B; byte a = color.A; - int inr = r >> (8 - WuQuantizer.IndexBits); - int ing = g >> (8 - WuQuantizer.IndexBits); - int inb = b >> (8 - WuQuantizer.IndexBits); - int ina = a >> (8 - WuQuantizer.IndexAlphaBits); + int inr = r >> (8 - IndexBits); + int ing = g >> (8 - IndexBits); + int inb = b >> (8 - IndexBits); + int ina = a >> (8 - IndexAlphaBits); - int ind = WuQuantizer.Ind(inr + 1, ing + 1, inb + 1, ina + 1); + int ind = Ind(inr + 1, ing + 1, inb + 1, ina + 1); this.vwt[ind]++; this.vmr[ind] += r; @@ -364,39 +366,39 @@ namespace ImageProcessorCore.Formats /// private void M3d() { - long[] volume = new long[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - long[] volume_r = new long[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - long[] volume_g = new long[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - long[] volume_b = new long[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - long[] volume_a = new long[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - double[] volume2 = new double[WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount]; - - long[] area = new long[WuQuantizer.IndexAlphaCount]; - long[] area_r = new long[WuQuantizer.IndexAlphaCount]; - long[] area_g = new long[WuQuantizer.IndexAlphaCount]; - long[] area_b = new long[WuQuantizer.IndexAlphaCount]; - long[] area_a = new long[WuQuantizer.IndexAlphaCount]; - double[] area2 = new double[WuQuantizer.IndexAlphaCount]; - - for (int r = 1; r < WuQuantizer.IndexCount; r++) + long[] volume = new long[IndexCount * IndexAlphaCount]; + long[] volume_r = new long[IndexCount * IndexAlphaCount]; + long[] volume_g = new long[IndexCount * IndexAlphaCount]; + long[] volume_b = new long[IndexCount * IndexAlphaCount]; + long[] volume_a = new long[IndexCount * IndexAlphaCount]; + double[] volume2 = new double[IndexCount * IndexAlphaCount]; + + long[] area = new long[IndexAlphaCount]; + long[] area_r = new long[IndexAlphaCount]; + long[] area_g = new long[IndexAlphaCount]; + long[] area_b = new long[IndexAlphaCount]; + long[] area_a = new long[IndexAlphaCount]; + double[] area2 = new double[IndexAlphaCount]; + + for (int r = 1; r < IndexCount; r++) { - Array.Clear(volume, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - Array.Clear(volume_r, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - Array.Clear(volume_g, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - Array.Clear(volume_b, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - Array.Clear(volume_a, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - Array.Clear(volume2, 0, WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount); - - for (int g = 1; g < WuQuantizer.IndexCount; g++) + Array.Clear(volume, 0, IndexCount * IndexAlphaCount); + Array.Clear(volume_r, 0, IndexCount * IndexAlphaCount); + Array.Clear(volume_g, 0, IndexCount * IndexAlphaCount); + Array.Clear(volume_b, 0, IndexCount * IndexAlphaCount); + Array.Clear(volume_a, 0, IndexCount * IndexAlphaCount); + Array.Clear(volume2, 0, IndexCount * IndexAlphaCount); + + for (int g = 1; g < IndexCount; g++) { - Array.Clear(area, 0, WuQuantizer.IndexAlphaCount); - Array.Clear(area_r, 0, WuQuantizer.IndexAlphaCount); - Array.Clear(area_g, 0, WuQuantizer.IndexAlphaCount); - Array.Clear(area_b, 0, WuQuantizer.IndexAlphaCount); - Array.Clear(area_a, 0, WuQuantizer.IndexAlphaCount); - Array.Clear(area2, 0, WuQuantizer.IndexAlphaCount); - - for (int b = 1; b < WuQuantizer.IndexCount; b++) + Array.Clear(area, 0, IndexAlphaCount); + Array.Clear(area_r, 0, IndexAlphaCount); + Array.Clear(area_g, 0, IndexAlphaCount); + Array.Clear(area_b, 0, IndexAlphaCount); + Array.Clear(area_a, 0, IndexAlphaCount); + Array.Clear(area2, 0, IndexAlphaCount); + + for (int b = 1; b < IndexCount; b++) { long line = 0; long line_r = 0; @@ -405,9 +407,9 @@ namespace ImageProcessorCore.Formats long line_a = 0; double line2 = 0; - for (int a = 1; a < WuQuantizer.IndexAlphaCount; a++) + for (int a = 1; a < IndexAlphaCount; a++) { - int ind1 = WuQuantizer.Ind(r, g, b, a); + int ind1 = Ind(r, g, b, a); line += this.vwt[ind1]; line_r += this.vmr[ind1]; @@ -423,7 +425,7 @@ namespace ImageProcessorCore.Formats area_a[a] += line_a; area2[a] += line2; - int inv = (b * WuQuantizer.IndexAlphaCount) + a; + int inv = (b * IndexAlphaCount) + a; volume[inv] += area[a]; volume_r[inv] += area_r[a]; @@ -432,7 +434,7 @@ namespace ImageProcessorCore.Formats volume_a[inv] += area_a[a]; volume2[inv] += area2[a]; - int ind2 = ind1 - WuQuantizer.Ind(1, 0, 0, 0); + int ind2 = ind1 - Ind(1, 0, 0, 0); this.vwt[ind1] = this.vwt[ind2] + volume[inv]; this.vmr[ind1] = this.vmr[ind2] + volume_r[inv]; @@ -453,30 +455,30 @@ namespace ImageProcessorCore.Formats /// The result. private double Var(Box cube) { - double dr = WuQuantizer.Volume(cube, this.vmr); - double dg = WuQuantizer.Volume(cube, this.vmg); - double db = WuQuantizer.Volume(cube, this.vmb); - double da = WuQuantizer.Volume(cube, this.vma); + double dr = Volume(cube, this.vmr); + double dg = Volume(cube, this.vmg); + double db = Volume(cube, this.vmb); + double da = Volume(cube, this.vma); double xx = - this.m2[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, cube.A1)] - - this.m2[WuQuantizer.Ind(cube.R1, cube.G1, cube.B1, cube.A0)] - - this.m2[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A1)] - + this.m2[WuQuantizer.Ind(cube.R1, cube.G1, cube.B0, cube.A0)] - - this.m2[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A1)] - + this.m2[WuQuantizer.Ind(cube.R1, cube.G0, cube.B1, cube.A0)] - + this.m2[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A1)] - - this.m2[WuQuantizer.Ind(cube.R1, cube.G0, cube.B0, cube.A0)] - - this.m2[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A1)] - + this.m2[WuQuantizer.Ind(cube.R0, cube.G1, cube.B1, cube.A0)] - + this.m2[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A1)] - - this.m2[WuQuantizer.Ind(cube.R0, cube.G1, cube.B0, cube.A0)] - + this.m2[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A1)] - - this.m2[WuQuantizer.Ind(cube.R0, cube.G0, cube.B1, cube.A0)] - - this.m2[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A1)] - + this.m2[WuQuantizer.Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; - - return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / WuQuantizer.Volume(cube, this.vwt)); + this.m2[Ind(cube.R1, cube.G1, cube.B1, cube.A1)] + - this.m2[Ind(cube.R1, cube.G1, cube.B1, cube.A0)] + - this.m2[Ind(cube.R1, cube.G1, cube.B0, cube.A1)] + + this.m2[Ind(cube.R1, cube.G1, cube.B0, cube.A0)] + - this.m2[Ind(cube.R1, cube.G0, cube.B1, cube.A1)] + + this.m2[Ind(cube.R1, cube.G0, cube.B1, cube.A0)] + + this.m2[Ind(cube.R1, cube.G0, cube.B0, cube.A1)] + - this.m2[Ind(cube.R1, cube.G0, cube.B0, cube.A0)] + - this.m2[Ind(cube.R0, cube.G1, cube.B1, cube.A1)] + + this.m2[Ind(cube.R0, cube.G1, cube.B1, cube.A0)] + + this.m2[Ind(cube.R0, cube.G1, cube.B0, cube.A1)] + - this.m2[Ind(cube.R0, cube.G1, cube.B0, cube.A0)] + + this.m2[Ind(cube.R0, cube.G0, cube.B1, cube.A1)] + - this.m2[Ind(cube.R0, cube.G0, cube.B1, cube.A0)] + - this.m2[Ind(cube.R0, cube.G0, cube.B0, cube.A1)] + + this.m2[Ind(cube.R0, cube.G0, cube.B0, cube.A0)]; + + return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt)); } /// @@ -499,22 +501,22 @@ namespace ImageProcessorCore.Formats /// The result. private double Maximize(Box cube, int direction, int first, int last, out int cut, double whole_r, double whole_g, double whole_b, double whole_a, double whole_w) { - long base_r = WuQuantizer.Bottom(cube, direction, this.vmr); - long base_g = WuQuantizer.Bottom(cube, direction, this.vmg); - long base_b = WuQuantizer.Bottom(cube, direction, this.vmb); - long base_a = WuQuantizer.Bottom(cube, direction, this.vma); - long base_w = WuQuantizer.Bottom(cube, direction, this.vwt); + long base_r = Bottom(cube, direction, this.vmr); + long base_g = Bottom(cube, direction, this.vmg); + long base_b = Bottom(cube, direction, this.vmb); + long base_a = Bottom(cube, direction, this.vma); + long base_w = Bottom(cube, direction, this.vwt); double max = 0.0; cut = -1; for (int i = first; i < last; i++) { - double half_r = base_r + WuQuantizer.Top(cube, direction, i, this.vmr); - double half_g = base_g + WuQuantizer.Top(cube, direction, i, this.vmg); - double half_b = base_b + WuQuantizer.Top(cube, direction, i, this.vmb); - double half_a = base_a + WuQuantizer.Top(cube, direction, i, this.vma); - double half_w = base_w + WuQuantizer.Top(cube, direction, i, this.vwt); + double half_r = base_r + Top(cube, direction, i, this.vmr); + double half_g = base_g + Top(cube, direction, i, this.vmg); + double half_b = base_b + Top(cube, direction, i, this.vmb); + double half_a = base_a + Top(cube, direction, i, this.vma); + double half_w = base_w + Top(cube, direction, i, this.vwt); double temp; @@ -562,11 +564,11 @@ namespace ImageProcessorCore.Formats /// Returns a value indicating whether the box has been split. private bool Cut(Box set1, Box set2) { - double whole_r = WuQuantizer.Volume(set1, this.vmr); - double whole_g = WuQuantizer.Volume(set1, this.vmg); - double whole_b = WuQuantizer.Volume(set1, this.vmb); - double whole_a = WuQuantizer.Volume(set1, this.vma); - double whole_w = WuQuantizer.Volume(set1, this.vwt); + double whole_r = Volume(set1, this.vmr); + double whole_g = Volume(set1, this.vmg); + double whole_b = Volume(set1, this.vmb); + double whole_a = Volume(set1, this.vma); + double whole_w = Volume(set1, this.vwt); int cutr; int cutg; @@ -663,7 +665,7 @@ namespace ImageProcessorCore.Formats { for (int a = cube.A0 + 1; a <= cube.A1; a++) { - this.tag[WuQuantizer.Ind(r, g, b, a)] = label; + this.tag[Ind(r, g, b, a)] = label; } } } @@ -686,8 +688,8 @@ namespace ImageProcessorCore.Formats } cube[0].R0 = cube[0].G0 = cube[0].B0 = cube[0].A0 = 0; - cube[0].R1 = cube[0].G1 = cube[0].B1 = WuQuantizer.IndexCount - 1; - cube[0].A1 = WuQuantizer.IndexAlphaCount - 1; + cube[0].R1 = cube[0].G1 = cube[0].B1 = IndexCount - 1; + cube[0].A1 = IndexAlphaCount - 1; int next = 0; @@ -736,30 +738,28 @@ namespace ImageProcessorCore.Formats List pallette = new List(); byte[] pixels = new byte[image.Width * image.Height]; - Parallel.For( - 0, - colorCount, - k => - { - this.Mark(cube[k], (byte)k); + // Can't make this parallel. + for (int k = 0; k < colorCount; k++) + { + this.Mark(cube[k], (byte)k); - double weight = WuQuantizer.Volume(cube[k], this.vwt); + double weight = Volume(cube[k], this.vwt); - // TODO: Epsilon - if (Math.Abs(weight) > .0001) - { - byte r = (byte)(WuQuantizer.Volume(cube[k], this.vmr) / weight); - byte g = (byte)(WuQuantizer.Volume(cube[k], this.vmg) / weight); - byte b = (byte)(WuQuantizer.Volume(cube[k], this.vmb) / weight); - byte a = (byte)(WuQuantizer.Volume(cube[k], this.vma) / weight); + // TODO: Epsilon + if (Math.Abs(weight) > .0001) + { + byte r = (byte)(Volume(cube[k], this.vmr) / weight); + byte g = (byte)(Volume(cube[k], this.vmg) / weight); + byte b = (byte)(Volume(cube[k], this.vmb) / weight); + byte a = (byte)(Volume(cube[k], this.vma) / weight); - pallette.Add(new Bgra32(b, g, r, a)); - } - else - { - pallette.Add(new Bgra32(0, 0, 0)); - } - }); + pallette.Add(new Bgra32(b, g, r, a)); + } + else + { + pallette.Add(new Bgra32(0, 0, 0)); + } + } // TODO: Optimize here. int i = 0; @@ -768,12 +768,12 @@ namespace ImageProcessorCore.Formats for (int x = 0; x < image.Width; x++) { Bgra32 color = image[x, y]; - int a = color.A >> (8 - WuQuantizer.IndexAlphaBits); - int r = color.R >> (8 - WuQuantizer.IndexBits); - int g = color.G >> (8 - WuQuantizer.IndexBits); - int b = color.B >> (8 - WuQuantizer.IndexBits); + int a = color.A >> (8 - IndexAlphaBits); + int r = color.R >> (8 - IndexBits); + int g = color.G >> (8 - IndexBits); + int b = color.B >> (8 - IndexBits); - int ind = WuQuantizer.Ind(r + 1, g + 1, b + 1, a + 1); + int ind = Ind(r + 1, g + 1, b + 1, a + 1); pixels[i++] = this.tag[ind]; } }