⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 custompalettebuilder.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * $RCSfile: PaletteBuilder.java,v $
 *
 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistribution of source code must retain the above copyright
 *   notice, this  list of conditions and the following disclaimer.
 *
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed or intended for
 * use in the design, construction, operation or maintenance of any
 * nuclear facility.
 *
 */
package org.vfny.geoserver.wms.responses.palette;

import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;

import javax.imageio.ImageTypeSpecifier;

/**
 * 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)
 * 
 * @author Simone Giannecchini - GeoSolutions
 */
public final class CustomPaletteBuilder {
	/**
	 * Default value for the threshold to decide whether a pixel is opaque (>=)
	 * or transparent (<). Default is 1 to try to preserve antialising
	 */
	public static final int DEFAULT_ALPHA_TH = 1;

	/**
	 * maximum of tree depth
	 */
	protected int maxLevel;

	protected RenderedImage src;

	protected ColorModel srcColorModel;

	protected int requiredSize;

	protected ColorNode root;

	protected int numNodes;

	protected int maxNodes;

	protected int currLevel;

	protected int currSize;

	protected ColorNode[] reduceList;

	protected ColorNode[] palette;

	protected int transparency;

	protected ColorNode transColor;

	protected int subsampleX;

	protected int subsampley;

	protected int numBands;

	protected int alphaThreshold;

	/**
	 * 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>.
	 */
	public static boolean canCreatePalette(ImageTypeSpecifier type) {
		if (type == null) {
			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>.
	 */
	public static boolean canCreatePalette(RenderedImage image) {
		if (image == null) {
			throw new IllegalArgumentException("image == null");
		}

		ImageTypeSpecifier type = new ImageTypeSpecifier(image);

		return canCreatePalette(type);
	}

	public RenderedImage getIndexedImage() {
		// //
		//
		// Create the destination image
		//
		// //
		final IndexColorModel icm = getIndexColorModel();
		final WritableRaster destWr = icm.createCompatibleWritableRaster(src
				.getWidth(), src.getHeight());
		final BufferedImage dst = new BufferedImage(icm, destWr, false, null);

		// //
		//
		// Filter the image out
		//
		// //

		// //
		//
		// Collecting info about the source image
		//
		// //
		final int numBands = src.getSampleModel().getNumBands();
		final int rgba[] = new int[numBands];
		final boolean sourceHasAlpha = (numBands % 2 == 0);
		final int alphaBand = sourceHasAlpha ? numBands - 1 : -1;
		final int minx_ = src.getMinX();
		final int miny_ = src.getMinY();
		final int srcW_ = src.getWidth();
		final int srcH_ = src.getHeight();
		final int maxx_ = minx_ + srcW_;
		final int maxy_ = miny_ + srcH_;
		final int minTileX = src.getMinTileX();
		final int minTileY = src.getMinTileY();
		final int tileW = src.getTileWidth();
		final int tileH = src.getTileHeight();
		final int maxTileX = minTileX + src.getNumXTiles();
		final int maxTileY = minTileY + src.getNumYTiles();
		int dstTempX = 0;
		int dstTempY = 0;
		for (int ty = minTileY; ty < maxTileY; ty++) {
			dstTempX = 0;
			int actualWidth = 0;
			int actualHeight = 0;
			for (int tx = minTileX; tx < maxTileX; tx++) {
				// get the source raster
				final Raster r = src.getTile(tx, ty);

				int minx = r.getMinX();
				int miny = r.getMinY();
				minx = minx < minx_ ? minx_ : minx;
				miny = miny < miny_ ? miny_ : miny;
				int maxx = minx + tileW;
				int maxy = miny + tileH;
				maxx = maxx > maxx_ ? maxx_ : maxx;
				maxy = maxy > maxy_ ? maxy_ : maxy;
				actualWidth = maxx - minx;
				actualHeight = maxy - miny;
				for (int j = miny, jj = dstTempY; j < maxy; j++, jj++) {
					for (int i = minx, ii = dstTempX; i < maxx; i++, ii++) {
						r.getPixel(i, j, rgba);

						destWr.setSample(ii, jj, 0, findColorIndex(root, rgba,
								alphaBand));

					}
				}
				dstTempX += actualWidth;

			}
			dstTempY += actualHeight;
		}
		return dst;
	}

	public CustomPaletteBuilder(RenderedImage src) {
		this(src, 256, 1, 1, DEFAULT_ALPHA_TH);
	}

	public CustomPaletteBuilder(RenderedImage src, int size, int subsx,
			int subsy, int alpha_th) {
		if ((subsx <= 0) || (subsx >= src.getWidth())) {
			throw new IllegalArgumentException("Invalid subsample x size");
		}

		if ((subsy <= 0) || (subsy >= src.getWidth())) {
			throw new IllegalArgumentException("Invalid subsample y size");
		}

		this.alphaThreshold = alpha_th;
		this.src = src;
		this.srcColorModel = src.getColorModel();
		this.numBands = srcColorModel.getNumComponents();
		this.subsampleX = subsx;
		this.subsampley = subsy;
		this.transparency = srcColorModel.getTransparency();
		if (transparency != Transparency.OPAQUE) {
			transparency = Transparency.BITMASK;
			// make room for the transparent color
			this.requiredSize = size - 1;
			transColor = new ColorNode();
			transColor.isLeaf = true;
		} else {
			this.requiredSize = size;
		}

		if (this.requiredSize > 256) {
			throw new IllegalArgumentException(
					"Unvalid number of colors require.");
		}

		this.maxLevel = (int) Math.ceil(Math.log(requiredSize) / Math.log(2));
	}

	protected int findColorIndex(ColorNode aNode, int[] rgba, int transpBand) {
		if ((transparency != Transparency.OPAQUE)
				&& (rgba[transpBand] < alphaThreshold)) {
			return 0; // default transparent pixel
		}

		try {
			if (aNode.isLeaf) {
				return aNode.paletteIndex;
			} else {
				int childIndex = getBranchIndex(rgba, aNode.level);

				if (aNode.children[childIndex] == null) {
					int i = 1;
					for (; i < 8; i++) {
						if (((childIndex + i) < 8)
								&& (aNode.children[childIndex + i] != null)) {
							childIndex += i;

							break;
						}

						if (((childIndex - i) >= 0)
								&& (aNode.children[childIndex - i] != null)) {
							childIndex -= i;

							break;
						}
					}
				}
				return findColorIndex(aNode.children[childIndex], rgba,
						transpBand);
			}
		} catch (Exception e) {
		}
		return 0;
	}

	public CustomPaletteBuilder buildPalette() {
		reduceList = new ColorNode[maxLevel + 1];

		for (int i = 0; i < reduceList.length; i++) {
			reduceList[i] = null;
		}

		numNodes = 0;
		maxNodes = 0;
		root = null;
		currSize = 0;
		currLevel = maxLevel;

		// //
		//
		// Collecting info about the source image
		//
		// //
		final int numBands = src.getSampleModel().getNumBands();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -