/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class implements the octree quantization method
* as it is described in the "Graphics Gems"
* (ISBN 0-12-286166-3, Chapter 4, pages 297-293)
*/
public class PaletteBuilder {
/**
* maximum of tree depth
*/
protected int requiredSize;
protected int numNodes;
protected int maxNodes;
protected int currLevel;
protected int currSize;
protected int transparency;
/**
* Creates an image representing given image
* <code>src</code> using <code>IndexColorModel</code>.
*
* Lossless conversion is not always possible (e.g. if number
* of colors in the given image exceeds maximum palette size).
* Result image then is an approximation constructed by octree
* quantization method.
*
* @exception IllegalArgumentException if <code>src</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>src</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexColorModel
*
* @see canCreatePalette
*
*/
pb.buildPalette();
return pb.getIndexedImage();
}
/**
* Creates an palette representing colors from given image
* <code>img</code>. If number of colors in the given image exceeds
* maximum palette size closest colors would be merged.
*
* @exception IllegalArgumentException if <code>img</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>img</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexedImage
*
* @see canCreatePalette
*
*/
pb.buildPalette();
return pb.getIndexColorModel();
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given image type.
*
* @param type an instance of <code>ImageTypeSpecifier</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>type</code>
* is <code>null</code>.
*/
throw new IllegalArgumentException("type == null");
}
return true;
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given rendered image.
*
* @param image an instance of <code>RenderedImage</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>image</code>
* is <code>null</code>.
*/
throw new IllegalArgumentException("image == null");
}
return canCreatePalette(type);
}
}
}
return dst;
}
this(src, 256);
}
this.transparency =
this.requiredSize = size;
}
}
{
return 0; // default transparnt pixel
}
return aNode.paletteIndex;
} else {
}
}
protected void buildPalette() {
reduceList[i] = null;
}
numNodes = 0;
maxNodes = 0;
currSize = 0;
/*
from the book
*/
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
/*
* If transparency of given image is not opaque we assume all
* colors with alpha less than 1.0 as fully transparent.
*/
{
if (transColor == null) {
this.requiredSize --; // one slot for transparent color
transColor = new ColorNode();
transColor.isLeaf = true;
}
} else {
}
if (currSize > requiredSize) {
reduceTree();
}
}
}
}
numNodes++;
}
currSize++;
}
}
aNode.colorCount++;
aNode.childCount++;
}
}
}
return aNode;
}
if (transColor != null) {
size ++; // we need place for transparent color;
}
int index = 0;
if (transColor != null) {
index ++;
}
}
if (transColor != null) {
} else {
}
return icm;
}
{
index++;
} else {
for (int i = 0; i < 8; i++) {
}
}
}
return index;
}
throw new IllegalArgumentException("Invalid octree node depth: " +
aLevel);
}
return index;
}
protected void reduceTree() {
level--;
}
// nothing to reduce
return;
}
// look for element with lower color count
int cnt = 1;
}
cnt++;
}
// save pointer to first reducible node
// NB: current color count for node could be changed in future
} else {
}
return;
}
// reduce node
for (int i = 0; i < 8; i++) {
}
}
return null;
}
for (int i = 0; i < 8; i++) {
}
numNodes--;
return null;
}
/**
* The node of color tree.
*/
protected class ColorNode {
public boolean isLeaf;
public int childCount;
public int colorCount;
public long red;
public long blue;
public long green;
public int paletteIndex;
public int level;
public ColorNode() {
isLeaf = false;
level = 0;
childCount = 0;
for (int i = 0; i < 8; i++) {
}
colorCount = 0;
paletteIndex = 0;
}
public int getLeafChildCount() {
if (isLeaf) {
return 0;
}
int cnt = 0;
cnt ++;
} else {
}
}
}
return cnt;
}
public int getRGB() {
int r = (int)red/colorCount;
int g = (int)green/colorCount;
int b = (int)blue/colorCount;
int c = 0xff << 24 | (0xff&r) << 16 | (0xff&g) << 8 | (0xff&b);
return c;
}
}
}