Browse Source

OK actually now it works.

Former-commit-id: 6e7d3b8ca5887d468411011051e33ff0b375a676
Former-commit-id: 24528949db6743b12ad060fa19f5f6a889ba89d8
Former-commit-id: 5165f068be0bd610b313c692900c523d2f6ba8cb
af/merge-core
James Jackson-South 10 years ago
parent
commit
9f6ad2cf84
  1. 2
      src/ImageProcessorCore/Formats/Quantizers/Octree/OctreeQuantizer.cs
  2. 430
      src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs

2
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.
/// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/>
/// </summary>
public class OctreeQuantizer : Quantizer
public sealed class OctreeQuantizer : Quantizer
{
/// <summary>
/// Stores the tree

430
src/ImageProcessorCore/Formats/Quantizers/Wu/WuQuantizer.cs

@ -45,17 +45,17 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// The index count.
/// </summary>
private const int IndexCount = (1 << WuQuantizer.IndexBits) + 1;
private const int IndexCount = (1 << IndexBits) + 1;
/// <summary>
/// The index alpha count.
/// </summary>
private const int IndexAlphaCount = (1 << WuQuantizer.IndexAlphaBits) + 1;
private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1;
/// <summary>
/// The table length.
/// </summary>
private const int TableLength = WuQuantizer.IndexCount * WuQuantizer.IndexCount * WuQuantizer.IndexCount * WuQuantizer.IndexAlphaCount;
private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount;
/// <summary>
/// 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];
}
/// <inheritdoc/>
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
/// <returns>The index.</returns>
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
/// <returns>The result.</returns>
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)];
}
/// <summary>
@ -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
/// </summary>
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);
}
/// <summary>
/// Builds a 3-D color histogram of <c>counts, r/g/b, c^2</c>.
/// </summary>
/// <param name="image">The image.</param>
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
/// </summary>
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
/// <returns>The result.</returns>
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));
}
/// <summary>
@ -499,22 +501,22 @@ namespace ImageProcessorCore.Formats
/// <returns>The result.</returns>
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>Returns a value indicating whether the box has been split.</returns>
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<Bgra32> pallette = new List<Bgra32>();
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];
}
}

Loading…
Cancel
Save