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

📄 gifencoder.java

📁 jrobin,使用纯java实现的RRD数据库,使用RRD数据库来统计数据.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* ============================================================
 * JRobin : Pure java implementation of RRDTool's functionality
 * ============================================================
 *
 * Project Info:  http://www.jrobin.org
 * Project Lead:  Sasa Markovic (saxon@jrobin.org)
 *
 * Developers:    Sasa Markovic (saxon@jrobin.org)
 *
 *
 * (C) Copyright 2003-2005, by Sasa Markovic.
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */

///////////////////////////////////////////////////////////////////
// GifEncoder from J.M.G. Elliott
// http://jmge.net/java/gifenc/
///////////////////////////////////////////////////////////////////

package org.jrobin.graph;

import java.awt.*;
import java.awt.image.PixelGrabber;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;

class GifEncoder {
	private Dimension dispDim = new Dimension(0, 0);
	private GifColorTable colorTable;
	private int bgIndex = 0;
	private int loopCount = 1;
	private String theComments;
	private Vector<Gif89Frame> vFrames = new Vector<Gif89Frame>();

	GifEncoder() {
		colorTable = new GifColorTable();
	}

	GifEncoder(Image static_image) throws IOException {
		this();
		addFrame(static_image);
	}

	GifEncoder(Color[] colors) {
		colorTable = new GifColorTable(colors);
	}

	GifEncoder(Color[] colors, int width, int height, byte ci_pixels[])
			throws IOException {
		this(colors);
		addFrame(width, height, ci_pixels);
	}

	int getFrameCount() {
		return vFrames.size();
	}

	Gif89Frame getFrameAt(int index) {
		return isOk(index) ? vFrames.elementAt(index) : null;
	}

	void addFrame(Gif89Frame gf) throws IOException {
		accommodateFrame(gf);
		vFrames.addElement(gf);
	}

	void addFrame(Image image) throws IOException {
		addFrame(new DirectGif89Frame(image));
	}

	void addFrame(int width, int height, byte ci_pixels[])
			throws IOException {
		addFrame(new IndexGif89Frame(width, height, ci_pixels));
	}

	void insertFrame(int index, Gif89Frame gf) throws IOException {
		accommodateFrame(gf);
		vFrames.insertElementAt(gf, index);
	}

	void setTransparentIndex(int index) {
		colorTable.setTransparent(index);
	}

	void setLogicalDisplay(Dimension dim, int background) {
		dispDim = new Dimension(dim);
		bgIndex = background;
	}

	void setLoopCount(int count) {
		loopCount = count;
	}

	void setComments(String comments) {
		theComments = comments;
	}

	void setUniformDelay(int interval) {
		for (int i = 0; i < vFrames.size(); ++i) {
			vFrames.elementAt(i).setDelay(interval);
		}
	}

	void encode(OutputStream out) throws IOException {
		int nframes = getFrameCount();
		boolean is_sequence = nframes > 1;
		colorTable.closePixelProcessing();
		Put.ascii("GIF89a", out);
		writeLogicalScreenDescriptor(out);
		colorTable.encode(out);
		if (is_sequence && loopCount != 1) {
			writeNetscapeExtension(out);
		}
		if (theComments != null && theComments.length() > 0) {
			writeCommentExtension(out);
		}
		for (int i = 0; i < nframes; ++i) {
			vFrames.elementAt(i).encode(
					out, is_sequence, colorTable.getDepth(), colorTable.getTransparent()
			);
		}
		out.write((int) ';');
		out.flush();
	}

	private void accommodateFrame(Gif89Frame gf) throws IOException {
		dispDim.width = Math.max(dispDim.width, gf.getWidth());
		dispDim.height = Math.max(dispDim.height, gf.getHeight());
		colorTable.processPixels(gf);
	}

	private void writeLogicalScreenDescriptor(OutputStream os) throws IOException {
		Put.leShort(dispDim.width, os);
		Put.leShort(dispDim.height, os);
		os.write(0xf0 | colorTable.getDepth() - 1);
		os.write(bgIndex);
		os.write(0);
	}


	private void writeNetscapeExtension(OutputStream os) throws IOException {
		os.write((int) '!');
		os.write(0xff);
		os.write(11);
		Put.ascii("NETSCAPE2.0", os);
		os.write(3);
		os.write(1);
		Put.leShort(loopCount > 1 ? loopCount - 1 : 0, os);
		os.write(0);
	}


	private void writeCommentExtension(OutputStream os) throws IOException {
		os.write((int) '!');
		os.write(0xfe);
		int remainder = theComments.length() % 255;
		int nsubblocks_full = theComments.length() / 255;
		int nsubblocks = nsubblocks_full + (remainder > 0 ? 1 : 0);
		int ibyte = 0;
		for (int isb = 0; isb < nsubblocks; ++isb) {
			int size = isb < nsubblocks_full ? 255 : remainder;
			os.write(size);
			Put.ascii(theComments.substring(ibyte, ibyte + size), os);
			ibyte += size;
		}
		os.write(0);
	}


	private boolean isOk(int frame_index) {
		return frame_index >= 0 && frame_index < vFrames.size();
	}
}

class DirectGif89Frame extends Gif89Frame {
	private int[] argbPixels;

	DirectGif89Frame(Image img) throws IOException {
		PixelGrabber pg = new PixelGrabber(img, 0, 0, -1, -1, true);
		String errmsg = null;
		try {
			if (!pg.grabPixels()) {
				errmsg = "can't grab pixels from image";
			}
		}
		catch (InterruptedException e) {
			errmsg = "interrupted grabbing pixels from image";
		}
		if (errmsg != null) {
			throw new IOException(errmsg + " (" + getClass().getName() + ")");
		}
		theWidth = pg.getWidth();
		theHeight = pg.getHeight();
		argbPixels = (int[]) pg.getPixels();
		ciPixels = new byte[argbPixels.length];
	}

	DirectGif89Frame(int width, int height, int argb_pixels[]) {
		theWidth = width;
		theHeight = height;
		argbPixels = new int[theWidth * theHeight];
		System.arraycopy(argb_pixels, 0, argbPixels, 0, argbPixels.length);
		ciPixels = new byte[argbPixels.length];
	}

	Object getPixelSource() {
		return argbPixels;
	}
}


class GifColorTable {
	private int[] theColors = new int[256];
	private int colorDepth;
	private int transparentIndex = -1;
	private int ciCount = 0;
	private ReverseColorMap ciLookup;

	GifColorTable() {
		ciLookup = new ReverseColorMap();
	}

	GifColorTable(Color[] colors) {
		int n2copy = Math.min(theColors.length, colors.length);
		for (int i = 0; i < n2copy; ++i) {
			theColors[i] = colors[i].getRGB();
		}
	}

	int getDepth() {
		return colorDepth;
	}

	int getTransparent() {
		return transparentIndex;
	}

	void setTransparent(int color_index) {
		transparentIndex = color_index;
	}

	void processPixels(Gif89Frame gf) throws IOException {
		if (gf instanceof DirectGif89Frame) {
			filterPixels((DirectGif89Frame) gf);
		}
		else {
			trackPixelUsage((IndexGif89Frame) gf);
		}
	}

	void closePixelProcessing() {
		colorDepth = computeColorDepth(ciCount);
	}

	void encode(OutputStream os) throws IOException {
		int palette_size = 1 << colorDepth;
		for (int i = 0; i < palette_size; ++i) {
			os.write(theColors[i] >> 16 & 0xff);
			os.write(theColors[i] >> 8 & 0xff);
			os.write(theColors[i] & 0xff);
		}
	}

	private void filterPixels(DirectGif89Frame dgf) throws IOException {
		if (ciLookup == null) {
			throw new IOException("RGB frames require palette autodetection");
		}
		int[] argb_pixels = (int[]) dgf.getPixelSource();
		byte[] ci_pixels = dgf.getPixelSink();
		int npixels = argb_pixels.length;
		for (int i = 0; i < npixels; ++i) {
			int argb = argb_pixels[i];
			if ((argb >>> 24) < 0x80) {
				if (transparentIndex == -1) {
					transparentIndex = ciCount;
				}
				else if (argb != theColors[transparentIndex]) {
					ci_pixels[i] = (byte) transparentIndex;
					continue;
				}
			}
			int color_index = ciLookup.getPaletteIndex(argb & 0xffffff);
			if (color_index == -1) {
				if (ciCount == 256) {
					throw new IOException("can't encode as GIF (> 256 colors)");
				}
				theColors[ciCount] = argb;
				ciLookup.put(argb & 0xffffff, ciCount);
				ci_pixels[i] = (byte) ciCount;
				++ciCount;
			}
			else {
				ci_pixels[i] = (byte) color_index;
			}
		}
	}

	private void trackPixelUsage(IndexGif89Frame igf) {
		byte[] ci_pixels = (byte[]) igf.getPixelSource();
		int npixels = ci_pixels.length;
		for (int i = 0; i < npixels; ++i) {
			if (ci_pixels[i] >= ciCount) {
				ciCount = ci_pixels[i] + 1;
			}
		}
	}

	private int computeColorDepth(int colorcount) {
		if (colorcount <= 2) {
			return 1;
		}
		if (colorcount <= 4) {
			return 2;
		}
		if (colorcount <= 16) {
			return 4;
		}
		return 8;
	}
}

class ReverseColorMap {
	private static class ColorRecord {
		int rgb;
		int ipalette;

		ColorRecord(int rgb, int ipalette) {
			this.rgb = rgb;
			this.ipalette = ipalette;
		}
	}

	private static final int HCAPACITY = 2053;
	private ColorRecord[] hTable = new ColorRecord[HCAPACITY];

	int getPaletteIndex(int rgb) {
		ColorRecord rec;
		for (int itable = rgb % hTable.length;
			 (rec = hTable[itable]) != null && rec.rgb != rgb;
			 itable = ++itable % hTable.length
				) {
			;
		}
		if (rec != null) {
			return rec.ipalette;
		}
		return -1;
	}


	void put(int rgb, int ipalette) {
		int itable;
		for (itable = rgb % hTable.length;
			 hTable[itable] != null;
			 itable = ++itable % hTable.length

⌨️ 快捷键说明

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