Browse Source

Moving exception to to the rest

Former-commit-id: bdaf0e14099acbcf79e9dc1cfef8d051e70a174d
Former-commit-id: 19d21cfd3784d77b1902b73cc5081365f1784536
pull/17/head
James South 11 years ago
parent
commit
f9a6d87d52
  1. 42
      src/ImageProcessor/Common/Exceptions/QuantizationException.cs
  2. 2
      src/ImageProcessor/ImageProcessor.csproj
  3. 2
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
  4. 226
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
  5. 16
      src/ImageProcessor/Imaging/Quantizers/WuQuantizer/QuantizationException.cs

42
src/ImageProcessor/Common/Exceptions/QuantizationException.cs

@ -0,0 +1,42 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="QuantizationException.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The exception that is thrown when quantizing an image has failed.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Common.Exceptions
{
using System;
/// <summary>
/// The exception that is thrown when quantizing an image has failed.
/// </summary>
[Serializable]
public class QuantizationException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="QuantizationException"/> class.
/// </summary>
/// <param name="message">
/// The message.
/// </param>
public QuantizationException(string message)
: base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="QuantizationException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
public QuantizationException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

2
src/ImageProcessor/ImageProcessor.csproj

@ -195,7 +195,7 @@
<Compile Include="Imaging\Quantizers\WuQuantizer\Pixel.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Imaging\Quantizers\WuQuantizer\QuantizationException.cs" />
<Compile Include="Common\Exceptions\QuantizationException.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\WuQuantizer.cs" />
<Compile Include="Imaging\Quantizers\WuQuantizer\WuQuantizerBase.cs" />
<Compile Include="Imaging\ResizeLayer.cs" />

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

@ -18,6 +18,8 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using ImageProcessor.Common.Exceptions;
/// <summary>
/// The image buffer for storing pixel information.
/// Adapted from <see href="https://github.com/drewnoakes"/>

226
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs

@ -1,32 +1,78 @@
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PaletteLookup.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Stores the indexed color palette of an image for fast access.
// Adapted from <see href="https://github.com/drewnoakes" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System;
using System.Collections.Generic;
using System.Linq;
class PaletteLookup
/// <summary>
/// Stores the indexed color palette of an image for fast access.
/// Adapted from <see href="https://github.com/drewnoakes" />
/// </summary>
internal class PaletteLookup
{
private int mMask;
private Dictionary<int, LookupNode[]> mLookup;
private LookupNode[] Palette { get; set; }
/// <summary>
/// The dictionary for caching lookup nodes.
/// </summary>
private Dictionary<int, LookupNode[]> lookupNodes;
/// <summary>
/// The palette mask.
/// </summary>
private int paletteMask;
/// <summary>
/// Initializes a new instance of the <see cref="PaletteLookup"/> class.
/// </summary>
/// <param name="palette">
/// The palette.
/// </param>
public PaletteLookup(Pixel[] palette)
{
Palette = new LookupNode[palette.Length];
this.Palette = new LookupNode[palette.Length];
for (int paletteIndex = 0; paletteIndex < palette.Length; paletteIndex++)
{
Palette[paletteIndex] = new LookupNode { Pixel = palette[paletteIndex], PaletteIndex = (byte)paletteIndex };
this.Palette[paletteIndex] = new LookupNode
{
Pixel = palette[paletteIndex],
PaletteIndex = (byte)paletteIndex
};
}
BuildLookup(palette);
this.BuildLookup(palette);
}
/// <summary>
/// Gets or sets the palette.
/// </summary>
private LookupNode[] Palette { get; set; }
/// <summary>
/// Gets palette index for the given pixel.
/// </summary>
/// <param name="pixel">
/// The pixel to return the index for.
/// </param>
/// <returns>
/// The <see cref="byte"/> representing the index.
/// </returns>
public byte GetPaletteIndex(Pixel pixel)
{
int pixelKey = pixel.Argb & mMask;
int pixelKey = pixel.Argb & this.paletteMask;
LookupNode[] bucket;
if (!mLookup.TryGetValue(pixelKey, out bucket))
if (!this.lookupNodes.TryGetValue(pixelKey, out bucket))
{
bucket = Palette;
bucket = this.Palette;
}
if (bucket.Length == 1)
@ -53,121 +99,169 @@
distance += deltaBlue * deltaBlue;
if (distance >= bestDistance)
{
continue;
}
bestDistance = distance;
bestMatch = lookup.PaletteIndex;
}
if ((bucket == Palette) && (pixelKey != 0))
if ((bucket == this.Palette) && (pixelKey != 0))
{
mLookup[pixelKey] = new LookupNode[] { bucket[bestMatch] };
this.lookupNodes[pixelKey] = new[] { bucket[bestMatch] };
}
return bestMatch;
}
private void BuildLookup(Pixel[] palette)
/// <summary>
/// Computes the bit mask.
/// </summary>
/// <param name="max">
/// The maximum byte value.
/// </param>
/// <param name="bits">
/// The number of bits.
/// </param>
/// <returns>
/// The <see cref="byte"/>.
/// </returns>
private static byte ComputeBitMask(byte max, int bits)
{
int mask = GetMask(palette);
Dictionary<int, List<LookupNode>> tempLookup = new Dictionary<int, List<LookupNode>>();
foreach (LookupNode lookup in Palette)
byte mask = 0;
if (bits != 0)
{
int pixelKey = lookup.Pixel.Argb & mask;
byte highestSetBitIndex = HighestSetBitIndex(max);
List<LookupNode> bucket;
if (!tempLookup.TryGetValue(pixelKey, out bucket))
for (int i = 0; i < bits; i++)
{
bucket = new List<LookupNode>();
tempLookup[pixelKey] = bucket;
mask <<= 1;
mask++;
}
bucket.Add(lookup);
}
mLookup = new Dictionary<int, LookupNode[]>(tempLookup.Count);
foreach (var key in tempLookup.Keys)
{
mLookup[key] = tempLookup[key].ToArray();
for (int i = 0; i <= highestSetBitIndex - bits; i++)
{
mask <<= 1;
}
}
mMask = mask;
return mask;
}
/// <summary>
/// Gets the mask value from the palette.
/// </summary>
/// <param name="palette">
/// The palette.
/// </param>
/// <returns>
/// The <see cref="int"/> representing the component value of the mask.
/// </returns>
private static int GetMask(Pixel[] palette)
{
IEnumerable<byte> alphas = from pixel in palette
select pixel.Alpha;
IEnumerable<byte> alphas = palette.Select(p => p.Alpha).ToArray();
byte maxAlpha = alphas.Max();
int uniqueAlphas = alphas.Distinct().Count();
IEnumerable<byte> reds = from pixel in palette
select pixel.Red;
IEnumerable<byte> reds = palette.Select(p => p.Red).ToArray();
byte maxRed = reds.Max();
int uniqueReds = reds.Distinct().Count();
IEnumerable<byte> greens = from pixel in palette
select pixel.Green;
IEnumerable<byte> greens = palette.Select(p => p.Green).ToArray();
byte maxGreen = greens.Max();
int uniqueGreens = greens.Distinct().Count();
IEnumerable<byte> blues = from pixel in palette
select pixel.Blue;
IEnumerable<byte> blues = palette.Select(p => p.Green).ToArray();
byte maxBlue = blues.Max();
int uniqueBlues = blues.Distinct().Count();
double totalUniques = uniqueAlphas + uniqueReds + uniqueGreens + uniqueBlues;
double AvailableBits = 1.0 + Math.Log(uniqueAlphas * uniqueReds * uniqueGreens * uniqueBlues);
double availableBits = 1.0 + Math.Log(uniqueAlphas * uniqueReds * uniqueGreens * uniqueBlues);
byte alphaMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueAlphas / totalUniques * AvailableBits)));
byte redMask = ComputeBitMask(maxRed, Convert.ToInt32(Math.Round(uniqueReds / totalUniques * AvailableBits)));
byte greenMask = ComputeBitMask(maxGreen, Convert.ToInt32(Math.Round(uniqueGreens / totalUniques * AvailableBits)));
byte blueMask = ComputeBitMask(maxBlue, Convert.ToInt32(Math.Round(uniqueBlues / totalUniques * AvailableBits)));
byte alphaMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueAlphas / totalUniques * availableBits)));
byte redMask = ComputeBitMask(maxRed, Convert.ToInt32(Math.Round(uniqueReds / totalUniques * availableBits)));
byte greenMask = ComputeBitMask(maxGreen, Convert.ToInt32(Math.Round(uniqueGreens / totalUniques * availableBits)));
byte blueMask = ComputeBitMask(maxBlue, Convert.ToInt32(Math.Round(uniqueBlues / totalUniques * availableBits)));
Pixel maskedPixel = new Pixel(alphaMask, redMask, greenMask, blueMask);
return maskedPixel.Argb;
}
private static byte ComputeBitMask(byte max, int bits)
/// <summary>
/// Gets the highest set bit index.
/// </summary>
/// <param name="value">
/// The value.
/// </param>
/// <returns>
/// The <see cref="byte"/>.
/// </returns>
private static byte HighestSetBitIndex(byte value)
{
byte mask = 0;
if (bits != 0)
byte index = 0;
for (int i = 0; i < 8; i++)
{
byte highestSetBitIndex = HighestSetBitIndex(max);
for (int i = 0; i < bits; i++)
if (0 != (value & 1))
{
mask <<= 1;
mask++;
index = (byte)i;
}
for (int i = 0; i <= highestSetBitIndex - bits; i++)
{
mask <<= 1;
}
value >>= 1;
}
return mask;
return index;
}
private static byte HighestSetBitIndex(byte value)
/// <summary>
/// The build lookup.
/// </summary>
/// <param name="palette">
/// The palette.
/// </param>
private void BuildLookup(Pixel[] palette)
{
byte index = 0;
for (int i = 0; i < 8; i++)
int mask = GetMask(palette);
Dictionary<int, List<LookupNode>> tempLookup = new Dictionary<int, List<LookupNode>>();
foreach (LookupNode lookup in this.Palette)
{
if (0 != (value & 1))
int pixelKey = lookup.Pixel.Argb & mask;
List<LookupNode> bucket;
if (!tempLookup.TryGetValue(pixelKey, out bucket))
{
index = (byte)i;
bucket = new List<LookupNode>();
tempLookup[pixelKey] = bucket;
}
value >>= 1;
bucket.Add(lookup);
}
return index;
this.lookupNodes = new Dictionary<int, LookupNode[]>(tempLookup.Count);
foreach (var key in tempLookup.Keys)
{
this.lookupNodes[key] = tempLookup[key].ToArray();
}
this.paletteMask = mask;
}
/// <summary>
/// Represents a single node containing the index and pixel.
/// </summary>
private struct LookupNode
{
public Pixel Pixel;
/// <summary>
/// The palette index.
/// </summary>
public byte PaletteIndex;
/// <summary>
/// The pixel.
/// </summary>
public Pixel Pixel;
}
}
}
}

16
src/ImageProcessor/Imaging/Quantizers/WuQuantizer/QuantizationException.cs

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
[Serializable]
public class QuantizationException : ApplicationException
{
public QuantizationException(string message) : base(message)
{
}
}
}
Loading…
Cancel
Save