this.root.pruneLevel(); this.depth--; if ( child == null ) { child = new Node( this, id, level, node ); if ( level == levelThreshold ) { this.numColors++; this.root.pruneToCubeDepth();
BufferedImage assignImageColors( BufferedImage image, boolean dither, boolean alphaToBitmask ) { this.root.fillColorMap( this.colorMap, this.firstColor ); node.parent.findClosestColor( red, green, blue, alpha, closest ); col = (byte) closest.colorIndex;
void findClosestColor( int red, int green, int blue, int alpha, ClosestColor closest ) { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) this.children[id].findClosestColor( red, green, blue, alpha, closest ); if ( this.uniqueCount != 0 ) { // Determine if this color is "closest". int dr = ( this.cube.colorMap[0][this.colorIndex] & 0xff ) - red; int dg = ( this.cube.colorMap[1][this.colorIndex] & 0xff ) - green; int db = ( this.cube.colorMap[2][this.colorIndex] & 0xff ) - blue; int da = ( this.cube.colorMap[3][this.colorIndex] & 0xff ) - alpha; int distance = da * da + dr * dr + dg * dg + db * db; if ( distance < closest.distance ) { closest.distance = distance; closest.colorIndex = this.colorIndex; } } }
void prune() { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) this.children[id].prune(); // Merge color statistics into parent. this.parent.uniqueCount += this.uniqueCount; this.parent.totalRed += this.totalRed; this.parent.totalGreen += this.totalGreen; this.parent.totalBlue += this.totalBlue; this.parent.totalAlpha += this.totalAlpha; this.parent.children[this.id] = null; this.parent.numChildren--; this.cube.numNodes--; }
int fillColorMap( byte colorMap[][], int index ) { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) index = this.children[id].fillColorMap( colorMap, index ); if ( this.uniqueCount != 0 ) { // Colormap entry is defined by the mean color in this cube. colorMap[0][index] = (byte) ( this.totalRed / this.uniqueCount + 0.5 ); colorMap[1][index] = (byte) ( this.totalGreen / this.uniqueCount + 0.5 ); colorMap[2][index] = (byte) ( this.totalBlue / this.uniqueCount + 0.5 ); colorMap[3][index] = (byte) ( this.totalAlpha / this.uniqueCount + 0.5 ); this.colorIndex = index++; } return index; } }
void reduce( long pruningThreshold ) { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) this.children[id].reduce( pruningThreshold ); if ( this.quantizeError <= pruningThreshold ) prune(); else { // Find minimum pruning threshold. if ( this.uniqueCount > 0 ) this.cube.numColors++; if ( this.quantizeError < this.cube.nextThreshold ) this.cube.nextThreshold = this.quantizeError; } }
void reduceImageColors( int maxColors ) { this.nextThreshold = 0; while ( this.numColors > maxColors ) { long pruningThreshold = this.nextThreshold; this.nextThreshold = this.root.quantizeError - 1; this.numColors = this.firstColor; this.root.reduce( pruningThreshold ); } }
Cube( int maxColors ) { this.depth = getDepth( maxColors ); this.numColors = 0; this.root = new Node( this ); }
void pruneLevel() { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) this.children[id].pruneLevel(); if ( this.level == this.cube.depth ) prune(); }
void pruneToCubeDepth() { // Traverse any children. if ( this.numChildren > 0 ) for ( int id = 0; id < MAX_CHILDREN; id++ ) if ( this.children[id] != null ) this.children[id].pruneToCubeDepth(); if ( this.level > this.cube.depth ) prune(); }