Browse Source

Further quantizer cleanup

Former-commit-id: 12814847839fad273c06fd6a12d04629fed37f59
Former-commit-id: 169e61fbe889a6de7c3a4a8e51eaa53af79839bd
af/merge-core
James South 11 years ago
parent
commit
b1f809dd38
  1. 3
      src/ImageProcessor.Playground/Program.cs
  2. 3
      src/ImageProcessor.Playground/images/input/rgba.png
  3. 1
      src/ImageProcessor/ImageProcessor.csproj
  4. 206
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs
  5. 49
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/Histogram.cs
  6. 23
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
  7. 2
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs
  8. 17
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs

3
src/ImageProcessor.Playground/Program.cs

@ -49,7 +49,8 @@ namespace ImageProcessor.PlayGround
di.Create();
}
// Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask2.png"));
// Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask2.png"));
//FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "rgba.png"));
IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".png");
//IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif");

3
src/ImageProcessor.Playground/images/input/rgba.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:91c2a86b4f41313c9db541649ae0a97661a45ade40bb70b1ec784ab60b065e55
size 171

1
src/ImageProcessor/ImageProcessor.csproj

@ -185,6 +185,7 @@
<Compile Include="Imaging\Quantizers\OctreeQuantizer.cs" />
<Compile Include="Imaging\Quantizers\Quantizer.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\Box.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\Histogram.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\ColorMoment.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\PaletteColorHistory.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\PaletteLookup.cs" />

206
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs

@ -1,86 +1,186 @@

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ColorMoment.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The color moment for holding pixel information.
// Adapted from <see href="https://github.com/drewnoakes" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
/// <summary>
/// The color moment for holding pixel information.
/// Adapted from <see href="https://github.com/drewnoakes" />
/// </summary>
internal struct ColorMoment
{
/// <summary>
/// The alpha.
/// </summary>
public long Alpha;
public long Red;
public long Green;
/// <summary>
/// The blue.
/// </summary>
public long Blue;
public int Weight;
/// <summary>
/// The green.
/// </summary>
public long Green;
/// <summary>
/// The moment.
/// </summary>
public float Moment;
public static ColorMoment operator +(ColorMoment c1, ColorMoment c2)
{
c1.Alpha += c2.Alpha;
c1.Red += c2.Red;
c1.Green += c2.Green;
c1.Blue += c2.Blue;
c1.Weight += c2.Weight;
c1.Moment += c2.Moment;
return c1;
}
/// <summary>
/// The red.
/// </summary>
public long Red;
public static ColorMoment operator -(ColorMoment c1, ColorMoment c2)
/// <summary>
/// The weight.
/// </summary>
public int Weight;
/// <summary>
/// Adds one <see cref="ColorMoment"/> to another.
/// </summary>
/// <param name="firstAddend">
/// The first <see cref="ColorMoment"/>.
/// </param>
/// <param name="secondAddend">
/// The second <see cref="ColorMoment"/>.
/// </param>
/// <returns>
/// The <see cref="ColorMoment"/> representing the sum of the addition.
/// </returns>
public static ColorMoment operator +(ColorMoment firstAddend, ColorMoment secondAddend)
{
c1.Alpha -= c2.Alpha;
c1.Red -= c2.Red;
c1.Green -= c2.Green;
c1.Blue -= c2.Blue;
c1.Weight -= c2.Weight;
c1.Moment -= c2.Moment;
return c1;
firstAddend.Alpha += secondAddend.Alpha;
firstAddend.Red += secondAddend.Red;
firstAddend.Green += secondAddend.Green;
firstAddend.Blue += secondAddend.Blue;
firstAddend.Weight += secondAddend.Weight;
firstAddend.Moment += secondAddend.Moment;
return firstAddend;
}
public static ColorMoment operator -(ColorMoment c1)
/// <summary>
/// Subtracts one <see cref="ColorMoment "/> from another.
/// </summary>
/// <param name="minuend">
/// The <see cref="ColorMoment"/> from which the other <see cref="ColorMoment"/> will be subtracted
/// </param>
/// <param name="subtrahend">
/// The <see cref="ColorMoment"/> that is to be subtracted.
/// </param>
/// <returns>
/// The <see cref="ColorMoment"/> representing the difference of the subtraction.
/// </returns>
public static ColorMoment operator -(ColorMoment minuend, ColorMoment subtrahend)
{
c1.Alpha = -c1.Alpha;
c1.Red = -c1.Red;
c1.Green = -c1.Green;
c1.Blue = -c1.Blue;
c1.Weight = -c1.Weight;
c1.Moment = -c1.Moment;
return c1;
minuend.Alpha -= subtrahend.Alpha;
minuend.Red -= subtrahend.Red;
minuend.Green -= subtrahend.Green;
minuend.Blue -= subtrahend.Blue;
minuend.Weight -= subtrahend.Weight;
minuend.Moment -= subtrahend.Moment;
return minuend;
}
public void Add(Pixel p)
/// <summary>
/// Negates the given <see cref="ColorMoment"/> .
/// </summary>
/// <param name="moment">
/// The <see cref="ColorMoment"/> to negate.
/// </param>
/// <returns>
/// The negated result
/// </returns>
public static ColorMoment operator -(ColorMoment moment)
{
byte pAlpha = p.Alpha;
byte pRed = p.Red;
byte pGreen = p.Green;
byte pBlue = p.Blue;
Alpha += pAlpha;
Red += pRed;
Green += pGreen;
Blue += pBlue;
Weight++;
Moment += pAlpha * pAlpha + pRed * pRed + pGreen * pGreen + pBlue * pBlue;
moment.Alpha = -moment.Alpha;
moment.Red = -moment.Red;
moment.Green = -moment.Green;
moment.Blue = -moment.Blue;
moment.Weight = -moment.Weight;
moment.Moment = -moment.Moment;
return moment;
}
public void AddFast(ref ColorMoment c2)
/// <summary>
/// Adds a pixel to the current instance.
/// </summary>
/// <param name="pixel">
/// The pixel to add.
/// </param>
public void Add(Pixel pixel)
{
Alpha += c2.Alpha;
Red += c2.Red;
Green += c2.Green;
Blue += c2.Blue;
Weight += c2.Weight;
Moment += c2.Moment;
byte alpha = pixel.Alpha;
byte red = pixel.Red;
byte green = pixel.Green;
byte blue = pixel.Blue;
this.Alpha += alpha;
this.Red += red;
this.Green += green;
this.Blue += blue;
this.Weight++;
this.Moment += (alpha * alpha) + (red * red) + (green * green) + (blue * blue);
}
public long Amplitude()
/// <summary>
/// Adds a color moment to the current instance more quickly.
/// </summary>
/// <param name="moment">
/// The <see cref="ColorMoment"/> to add.
/// </param>
public void AddFast(ref ColorMoment moment)
{
return Alpha * Alpha + Red * Red + Green * Green + Blue * Blue;
this.Alpha += moment.Alpha;
this.Red += moment.Red;
this.Green += moment.Green;
this.Blue += moment.Blue;
this.Weight += moment.Weight;
this.Moment += moment.Moment;
}
public long WeightedDistance()
/// <summary>
/// The amplitude.
/// </summary>
/// <returns>
/// The <see cref="long"/> representing the amplitude.
/// </returns>
public long Amplitude()
{
return this.Amplitude() / this.Weight;
return (this.Alpha * this.Alpha) + (this.Red * this.Red) + (this.Green * this.Green) + (this.Blue * this.Blue);
}
/// <summary>
/// The variance.
/// </summary>
/// <returns>
/// The <see cref="float"/> representing the variance.
/// </returns>
public float Variance()
{
float result = this.Moment - ((float)this.Amplitude() / this.Weight);
return float.IsNaN(result) ? 0.0f : result;
}
/// <summary>
/// The weighted distance.
/// </summary>
/// <returns>
/// The <see cref="long"/>.
/// </returns>
public long WeightedDistance()
{
return this.Amplitude() / this.Weight;
}
}
}
}

49
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/Histogram.cs

@ -0,0 +1,49 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Histogram.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The histogram representing the distribution of color data.
// Adapted from <see href="https://github.com/drewnoakes" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System;
/// <summary>
/// The histogram representing the distribution of color data.
/// Adapted from <see href="https://github.com/drewnoakes" />
/// </summary>
public class Histogram
{
/// <summary>
/// The moments.
/// </summary>
internal readonly ColorMoment[,,,] Moments;
/// <summary>
/// The side size.
/// </summary>
private const int SideSize = 33;
/// <summary>
/// Initializes a new instance of the <see cref="Histogram"/> class.
/// </summary>
public Histogram()
{
// 47,436,840 bytes
this.Moments = new ColorMoment[SideSize, SideSize, SideSize, SideSize];
}
/// <summary>
/// The clear.
/// </summary>
internal void Clear()
{
Array.Clear(this.Moments, 0, SideSize * SideSize * SideSize * SideSize);
}
}
}

23
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs

@ -11,8 +11,10 @@
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
@ -62,6 +64,20 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
int height = this.Image.Height;
int[] buffer = new int[width];
Pixel[] pixels = new Pixel[width];
//using (FastBitmap bitmap = new FastBitmap(this.Image))
//{
// for (int y = 0; y < height; y++)
// {
// for (int x = 0; x < width; x++)
// {
// Color color = bitmap.GetPixel(x, y);
// pixels[x] = new Pixel(color.A, color.R, color.G, color.B);
// }
// yield return pixels;
// }
//}
for (int rowIndex = 0; rowIndex < height; rowIndex++)
{
BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, rowIndex, width, rowIndex + 1), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
@ -93,11 +109,16 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
int width = this.Image.Width;
int height = this.Image.Height;
var indexesIterator = lineIndexes.GetEnumerator();
IEnumerator<byte[]> indexesIterator = lineIndexes.GetEnumerator();
for (int rowIndex = 0; rowIndex < height; rowIndex++)
{
indexesIterator.MoveNext();
BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, rowIndex, width, rowIndex + 1), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
try
{
Marshal.Copy(indexesIterator.Current, 0, data.Scan0, width);

2
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs

@ -59,7 +59,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
/// Adds a pixel to the color history.
/// </summary>
/// <param name="pixel">
/// The pixel.
/// The pixel to add.
/// </param>
public void AddPixel(Pixel pixel)
{

17
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs

@ -4,23 +4,6 @@ using System.Linq;
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
public class Histogram
{
private const int SideSize = 33;
internal readonly ColorMoment[, , ,] Moments;
public Histogram()
{
// 47,436,840 bytes
Moments = new ColorMoment[SideSize, SideSize, SideSize, SideSize];
}
internal void Clear()
{
Array.Clear(Moments, 0, SideSize * SideSize * SideSize * SideSize);
}
}
public abstract class WuQuantizerBase
{
protected const byte AlphaColor = 255;

Loading…
Cancel
Save