|
|
|
@ -121,20 +121,78 @@ namespace ImageProcessor.Imaging |
|
|
|
/// </summary>
|
|
|
|
private class Octree |
|
|
|
{ |
|
|
|
#region Fields
|
|
|
|
/// <summary>
|
|
|
|
/// Mask used when getting the appropriate pixels for a given node
|
|
|
|
/// </summary>
|
|
|
|
private static int[] mask = new int[8] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The root of the octree
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode root; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Number of leaves in the tree
|
|
|
|
/// </summary>
|
|
|
|
private int leafCount; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Array of reducible nodes
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode[] reducibleNodes; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Maximum number of significant bits in the image
|
|
|
|
/// </summary>
|
|
|
|
private int maxColorBits; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Store the last node quantized
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode previousNode; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Cache the previous color quantized
|
|
|
|
/// </summary>
|
|
|
|
private int previousColor; |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="T:ImageProcessor.Imaging.OctreeQuantizer.Octree">Octree</see> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="maxColorBits">The maximum number of significant bits in the image</param>
|
|
|
|
public Octree(int maxColorBits) |
|
|
|
/// <param name="maxBits">The maximum number of significant bits in the image</param>
|
|
|
|
public Octree(int maxBits) |
|
|
|
{ |
|
|
|
this._maxColorBits = maxColorBits; |
|
|
|
this._leafCount = 0; |
|
|
|
this._reducibleNodes = new OctreeNode[9]; |
|
|
|
this._root = new OctreeNode(0, this._maxColorBits, this); |
|
|
|
this._previousColor = 0; |
|
|
|
this._previousNode = null; |
|
|
|
this.maxColorBits = maxBits; |
|
|
|
this.leafCount = 0; |
|
|
|
this.reducibleNodes = new OctreeNode[9]; |
|
|
|
this.root = new OctreeNode(0, this.maxColorBits, this); |
|
|
|
this.previousColor = 0; |
|
|
|
this.previousNode = null; |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the number of leaves in the tree
|
|
|
|
/// </summary>
|
|
|
|
public int Leaves |
|
|
|
{ |
|
|
|
get { return this.leafCount; } |
|
|
|
set { this.leafCount = value; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the array of reducible nodes
|
|
|
|
/// </summary>
|
|
|
|
protected OctreeNode[] ReducibleNodes |
|
|
|
{ |
|
|
|
get { return this.reducibleNodes; } |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Add a given colour value to the octree
|
|
|
|
/// </summary>
|
|
|
|
@ -144,25 +202,25 @@ namespace ImageProcessor.Imaging |
|
|
|
public void AddColor(Color32 pixel) |
|
|
|
{ |
|
|
|
// Check if this request is for the same colour as the last
|
|
|
|
if (this._previousColor == pixel.ARGB) |
|
|
|
if (this.previousColor == pixel.ARGB) |
|
|
|
{ |
|
|
|
// If so, check if I have a previous node setup. This will only occur if the first colour in the image
|
|
|
|
// happens to be black, with an alpha component of zero.
|
|
|
|
if (null == this._previousNode) |
|
|
|
if (null == this.previousNode) |
|
|
|
{ |
|
|
|
this._previousColor = pixel.ARGB; |
|
|
|
this._root.AddColor(pixel, this._maxColorBits, 0, this); |
|
|
|
this.previousColor = pixel.ARGB; |
|
|
|
this.root.AddColor(pixel, this.maxColorBits, 0, this); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Just update the previous node
|
|
|
|
this._previousNode.Increment(pixel); |
|
|
|
this.previousNode.Increment(pixel); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
this._previousColor = pixel.ARGB; |
|
|
|
this._root.AddColor(pixel, this._maxColorBits, 0, this); |
|
|
|
this.previousColor = pixel.ARGB; |
|
|
|
this.root.AddColor(pixel, this.maxColorBits, 0, this); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -172,48 +230,22 @@ namespace ImageProcessor.Imaging |
|
|
|
public void Reduce() |
|
|
|
{ |
|
|
|
// Find the deepest level containing at least one reducible node
|
|
|
|
int index = this._maxColorBits - 1; |
|
|
|
while ((index > 0) && (this._reducibleNodes[index] == null)) |
|
|
|
int index = this.maxColorBits - 1; |
|
|
|
while ((index > 0) && (this.reducibleNodes[index] == null)) |
|
|
|
{ |
|
|
|
index--; |
|
|
|
} |
|
|
|
|
|
|
|
// Reduce the node most recently added to the list at level 'index'
|
|
|
|
OctreeNode node = this._reducibleNodes[index]; |
|
|
|
this._reducibleNodes[index] = node.NextReducible; |
|
|
|
OctreeNode node = this.reducibleNodes[index]; |
|
|
|
this.reducibleNodes[index] = node.NextReducible; |
|
|
|
|
|
|
|
// Decrement the leaf count after reducing the node
|
|
|
|
this._leafCount -= node.Reduce(); |
|
|
|
this.leafCount -= node.Reduce(); |
|
|
|
|
|
|
|
// And just in case I've reduced the last color to be added, and the next color to
|
|
|
|
// be added is the same, invalidate the previousNode...
|
|
|
|
this._previousNode = null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get or sets the number of leaves in the tree
|
|
|
|
/// </summary>
|
|
|
|
public int Leaves |
|
|
|
{ |
|
|
|
get { return this._leafCount; } |
|
|
|
set { this._leafCount = value; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Return the array of reducible nodes
|
|
|
|
/// </summary>
|
|
|
|
protected OctreeNode[] ReducibleNodes |
|
|
|
{ |
|
|
|
get { return this._reducibleNodes; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Keep track of the previous node that was quantized
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="node">The node last quantized</param>
|
|
|
|
protected void TrackPrevious(OctreeNode node) |
|
|
|
{ |
|
|
|
this._previousNode = node; |
|
|
|
this.previousNode = null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -231,92 +263,132 @@ namespace ImageProcessor.Imaging |
|
|
|
// Now palletize the nodes
|
|
|
|
ArrayList palette = new ArrayList(this.Leaves); |
|
|
|
int paletteIndex = 0; |
|
|
|
this._root.ConstructPalette(palette, ref paletteIndex); |
|
|
|
this.root.ConstructPalette(palette, ref paletteIndex); |
|
|
|
|
|
|
|
// And return the palette
|
|
|
|
return palette; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get the palette index for the passed colour
|
|
|
|
/// Get the palette index for the passed colour.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="pixel"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <param name="pixel">
|
|
|
|
/// The color to return the palette index for.
|
|
|
|
/// </param>
|
|
|
|
/// <returns>
|
|
|
|
/// The palette index for the passed colour.
|
|
|
|
/// </returns>
|
|
|
|
public int GetPaletteIndex(Color32 pixel) |
|
|
|
{ |
|
|
|
return this._root.GetPaletteIndex(pixel, 0); |
|
|
|
return this.root.GetPaletteIndex(pixel, 0); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Mask used when getting the appropriate pixels for a given node
|
|
|
|
/// Keep track of the previous node that was quantized
|
|
|
|
/// </summary>
|
|
|
|
private static int[] mask = new int[8] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; |
|
|
|
/// <param name="node">The node last quantized</param>
|
|
|
|
protected void TrackPrevious(OctreeNode node) |
|
|
|
{ |
|
|
|
this.previousNode = node; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The root of the octree
|
|
|
|
/// Class which encapsulates each node in the tree
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode _root; |
|
|
|
protected class OctreeNode |
|
|
|
{ |
|
|
|
#region Fields
|
|
|
|
/// <summary>
|
|
|
|
/// Flag indicating that this is a leaf node
|
|
|
|
/// </summary>
|
|
|
|
private bool leaf; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Number of leaves in the tree
|
|
|
|
/// </summary>
|
|
|
|
private int _leafCount; |
|
|
|
/// <summary>
|
|
|
|
/// Number of pixels in this node
|
|
|
|
/// </summary>
|
|
|
|
private int pixelCount; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Array of reducible nodes
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode[] _reducibleNodes; |
|
|
|
/// <summary>
|
|
|
|
/// Red component
|
|
|
|
/// </summary>
|
|
|
|
private int red; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Maximum number of significant bits in the image
|
|
|
|
/// </summary>
|
|
|
|
private int _maxColorBits; |
|
|
|
/// <summary>
|
|
|
|
/// Green Component
|
|
|
|
/// </summary>
|
|
|
|
private int green; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Store the last node quantized
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode _previousNode; |
|
|
|
/// <summary>
|
|
|
|
/// Blue component
|
|
|
|
/// </summary>
|
|
|
|
private int blue; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Cache the previous color quantized
|
|
|
|
/// </summary>
|
|
|
|
private int _previousColor; |
|
|
|
/// <summary>
|
|
|
|
/// Pointers to any child nodes
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode[] children; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Class which encapsulates each node in the tree
|
|
|
|
/// </summary>
|
|
|
|
protected class OctreeNode |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Construct the node
|
|
|
|
/// The index of this node in the palette
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="level">The level in the tree = 0 - 7</param>
|
|
|
|
/// <param name="colorBits">The number of significant color bits in the image</param>
|
|
|
|
/// <param name="octree">The tree to which this node belongs</param>
|
|
|
|
private int paletteIndex; |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="OctreeNode"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="level">
|
|
|
|
/// The level in the tree = 0 - 7
|
|
|
|
/// </param>
|
|
|
|
/// <param name="colorBits">
|
|
|
|
/// The number of significant color bits in the image
|
|
|
|
/// </param>
|
|
|
|
/// <param name="octree">
|
|
|
|
/// The tree to which this node belongs
|
|
|
|
/// </param>
|
|
|
|
public OctreeNode(int level, int colorBits, Octree octree) |
|
|
|
{ |
|
|
|
// Construct the new node
|
|
|
|
this._leaf = (level == colorBits); |
|
|
|
this.leaf = level == colorBits; |
|
|
|
|
|
|
|
this._red = _green = _blue = 0; |
|
|
|
this._pixelCount = 0; |
|
|
|
this.red = this.green = this.blue = 0; |
|
|
|
this.pixelCount = 0; |
|
|
|
|
|
|
|
// If a leaf, increment the leaf count
|
|
|
|
if (this._leaf) |
|
|
|
if (this.leaf) |
|
|
|
{ |
|
|
|
octree.Leaves++; |
|
|
|
this._nextReducible = null; |
|
|
|
this._children = null; |
|
|
|
this.NextReducible = null; |
|
|
|
this.children = null; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Otherwise add this to the reducible nodes
|
|
|
|
this._nextReducible = octree.ReducibleNodes[level]; |
|
|
|
this.NextReducible = octree.ReducibleNodes[level]; |
|
|
|
octree.ReducibleNodes[level] = this; |
|
|
|
this._children = new OctreeNode[8]; |
|
|
|
this.children = new OctreeNode[8]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or the next reducible node
|
|
|
|
/// </summary>
|
|
|
|
public OctreeNode NextReducible { get; private set; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the child nodes
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode[] Children |
|
|
|
{ |
|
|
|
get { return this.children; } |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
|
|
/// Add a color into the tree
|
|
|
|
/// </summary>
|
|
|
|
@ -327,9 +399,10 @@ namespace ImageProcessor.Imaging |
|
|
|
public void AddColor(Color32 pixel, int colorBits, int level, Octree octree) |
|
|
|
{ |
|
|
|
// Update the color information if this is a leaf
|
|
|
|
if (this._leaf) |
|
|
|
if (this.leaf) |
|
|
|
{ |
|
|
|
Increment(pixel); |
|
|
|
this.Increment(pixel); |
|
|
|
|
|
|
|
// Setup the previous node
|
|
|
|
octree.TrackPrevious(this); |
|
|
|
} |
|
|
|
@ -339,38 +412,20 @@ namespace ImageProcessor.Imaging |
|
|
|
int shift = 7 - level; |
|
|
|
int index = ((pixel.Red & mask[level]) >> (shift - 2)) | |
|
|
|
((pixel.Green & mask[level]) >> (shift - 1)) | |
|
|
|
((pixel.Blue & mask[level]) >> (shift)); |
|
|
|
((pixel.Blue & mask[level]) >> shift); |
|
|
|
|
|
|
|
OctreeNode child = this._children[index]; |
|
|
|
OctreeNode child = this.Children[index]; |
|
|
|
|
|
|
|
if (null == child) |
|
|
|
{ |
|
|
|
// Create a new child node & store in the array
|
|
|
|
child = new OctreeNode(level + 1, colorBits, octree); |
|
|
|
this._children[index] = child; |
|
|
|
this.Children[index] = child; |
|
|
|
} |
|
|
|
|
|
|
|
// Add the color to the child node
|
|
|
|
child.AddColor(pixel, colorBits, level + 1, octree); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get or Sets the next reducible node
|
|
|
|
/// </summary>
|
|
|
|
public OctreeNode NextReducible |
|
|
|
{ |
|
|
|
get { return _nextReducible; } |
|
|
|
set { _nextReducible = value; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Return the child nodes
|
|
|
|
/// </summary>
|
|
|
|
public OctreeNode[] Children |
|
|
|
{ |
|
|
|
get { return _children; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -379,73 +434,84 @@ namespace ImageProcessor.Imaging |
|
|
|
/// <returns>The number of leaves removed</returns>
|
|
|
|
public int Reduce() |
|
|
|
{ |
|
|
|
this._red = this._green = this._blue = 0; |
|
|
|
int children = 0; |
|
|
|
this.red = this.green = this.blue = 0; |
|
|
|
int childPosition = 0; |
|
|
|
|
|
|
|
// Loop through all children and add their information to this node
|
|
|
|
for (int index = 0; index < 8; index++) |
|
|
|
{ |
|
|
|
if (null != this._children[index]) |
|
|
|
if (null != this.Children[index]) |
|
|
|
{ |
|
|
|
this._red += this._children[index]._red; |
|
|
|
this._green += this._children[index]._green; |
|
|
|
this._blue += this._children[index]._blue; |
|
|
|
this._pixelCount += this._children[index]._pixelCount; |
|
|
|
++children; |
|
|
|
this._children[index] = null; |
|
|
|
this.red += this.Children[index].red; |
|
|
|
this.green += this.Children[index].green; |
|
|
|
this.blue += this.Children[index].blue; |
|
|
|
this.pixelCount += this.Children[index].pixelCount; |
|
|
|
++childPosition; |
|
|
|
this.Children[index] = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Now change this to a leaf node
|
|
|
|
this._leaf = true; |
|
|
|
this.leaf = true; |
|
|
|
|
|
|
|
// Return the number of nodes to decrement the leaf count by
|
|
|
|
return children - 1; |
|
|
|
return childPosition - 1; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Traverse the tree, building up the color palette
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="palette">The palette</param>
|
|
|
|
/// <param name="paletteIndex">The current palette index</param>
|
|
|
|
public void ConstructPalette(ArrayList palette, ref int paletteIndex) |
|
|
|
/// <param name="currentPaletteIndex">The current palette index</param>
|
|
|
|
public void ConstructPalette(ArrayList palette, ref int currentPaletteIndex) |
|
|
|
{ |
|
|
|
if (_leaf) |
|
|
|
if (this.leaf) |
|
|
|
{ |
|
|
|
// Consume the next palette index
|
|
|
|
_paletteIndex = paletteIndex++; |
|
|
|
this.paletteIndex = currentPaletteIndex++; |
|
|
|
|
|
|
|
// And set the color of the palette entry
|
|
|
|
palette.Add(Color.FromArgb(_red / _pixelCount, _green / _pixelCount, _blue / _pixelCount)); |
|
|
|
palette.Add(Color.FromArgb(this.red / this.pixelCount, this.green / this.pixelCount, this.blue / this.pixelCount)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Loop through children looking for leaves
|
|
|
|
for (int index = 0; index < 8; index++) |
|
|
|
{ |
|
|
|
if (null != _children[index]) |
|
|
|
_children[index].ConstructPalette(palette, ref paletteIndex); |
|
|
|
if (null != this.children[index]) |
|
|
|
{ |
|
|
|
this.children[index].ConstructPalette(palette, ref currentPaletteIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Return the palette index for the passed color
|
|
|
|
/// Return the palette index for the passed color.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="pixel">
|
|
|
|
/// The pixel.
|
|
|
|
/// </param>
|
|
|
|
/// <param name="level">
|
|
|
|
/// The level.
|
|
|
|
/// </param>
|
|
|
|
/// <returns>
|
|
|
|
/// The palette index for the passed color.
|
|
|
|
/// </returns>
|
|
|
|
public int GetPaletteIndex(Color32 pixel, int level) |
|
|
|
{ |
|
|
|
int paletteIndex = _paletteIndex; |
|
|
|
int currentPaletteIndex = this.paletteIndex; |
|
|
|
|
|
|
|
if (!_leaf) |
|
|
|
if (!this.leaf) |
|
|
|
{ |
|
|
|
int shift = 7 - level; |
|
|
|
int index = ((pixel.Red & mask[level]) >> (shift - 2)) | |
|
|
|
((pixel.Green & mask[level]) >> (shift - 1)) | |
|
|
|
((pixel.Blue & mask[level]) >> (shift)); |
|
|
|
((pixel.Blue & mask[level]) >> shift); |
|
|
|
|
|
|
|
if (null != _children[index]) |
|
|
|
if (null != this.children[index]) |
|
|
|
{ |
|
|
|
paletteIndex = _children[index].GetPaletteIndex(pixel, level + 1); |
|
|
|
currentPaletteIndex = this.children[index].GetPaletteIndex(pixel, level + 1); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@ -453,59 +519,23 @@ namespace ImageProcessor.Imaging |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return paletteIndex; |
|
|
|
return currentPaletteIndex; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Increment the pixel count and add to the color information
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="pixel">
|
|
|
|
/// The pixel.
|
|
|
|
/// </param>
|
|
|
|
public void Increment(Color32 pixel) |
|
|
|
{ |
|
|
|
this._pixelCount++; |
|
|
|
this._red += pixel.Red; |
|
|
|
this._green += pixel.Green; |
|
|
|
this._blue += pixel.Blue; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Flag indicating that this is a leaf node
|
|
|
|
/// </summary>
|
|
|
|
private bool _leaf; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Number of pixels in this node
|
|
|
|
/// </summary>
|
|
|
|
private int _pixelCount; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Red component
|
|
|
|
/// </summary>
|
|
|
|
private int _red; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Green Component
|
|
|
|
/// </summary>
|
|
|
|
private int _green; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Blue component
|
|
|
|
/// </summary>
|
|
|
|
private int _blue; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Pointers to any child nodes
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode[] _children; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Pointer to next reducible node
|
|
|
|
/// </summary>
|
|
|
|
private OctreeNode _nextReducible; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The index of this node in the palette
|
|
|
|
/// </summary>
|
|
|
|
private int _paletteIndex; |
|
|
|
this.pixelCount++; |
|
|
|
this.red += pixel.Red; |
|
|
|
this.green += pixel.Green; |
|
|
|
this.blue += pixel.Blue; |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|