savepicture.java

来自「一个简单的visio程序。」· Java 代码 · 共 425 行

JAVA
425
字号
/**
 * @(#)SavePicture.java	98/06/18
 *
 * Copyright 1997-1998 by Halcyon Software Inc.,
 * All rights reserved.
 *
 * SavePicture is a class which takes a Picture and saves it to a stream
 * using the GIF file format.
 *
 * @version IB4J1.3
 */
 
package HPCore.stdstmt;

import java.io.*;
import java.awt.*;
import java.net.*;
import java.awt.image.*;

import HECore.stddata.*;
import HPCore.Exception.*;
import HAB.object.*;

public class SavePicture {
	private final int   RES_CODES = 2;
	private final short HASH_FREE = (short)0xFFFF;
	private final short NEXT_FIRST = (short)0xFFFF;
	private final int   MAXBITS = 12;
	private final int   MAXSTR = (1 << MAXBITS);
	private final short HASHSIZE = 9973;
	private final short HASHSTEP = 2039;

	private byte byte_;
	private byte separator_;
	private byte backgroundColorIndex_, pixelAspectRatio_;
	private short leftPosition_, topPosition_;

	byte[]  strChr_ = new byte[MAXSTR];
	short[] strNxt_ = new short[MAXSTR];
	short[] strHsh_ = new short[HASHSIZE];
	short numStrings_;

	short width_, height_;
	int numColors_;
	byte[] buffer_ = new byte[256];
	int index_ = 0, bitsLeft_ = 8;
	byte pixels_[], colors_[];

	public void SavePicture(Picture urlpicture, Variant filename) throws java.lang.Exception 
	{
		//String up_ = urlpicture.strValue();
		String fn_;
		int type = filename.getType();

		switch (type){
			case Variant.V_NULL:
				throw new HpException(94, "Invalid use of null");

			case Variant.V_DATE:    // Hope
				if(filename.strValue() == null)
					throw new HpException(75, "Path or File access error");
				else {
					if(filename.strValue().indexOf('/') == -1 ||
						filename.strValue().indexOf('\\')== -1)
						{fn_ = filename.strValue();        break;}
					else throw new HpException(76, "Path not found");
				}

			case Variant.V_BOL:
			case Variant.V_DBL:
			case Variant.V_LONG:
			case Variant.V_CURR:
			case Variant.V_SINGLE:
			case Variant.V_INT:
			case Variant.V_BYTE:
			// case Variant.V_ERR:  // Hope
			case Variant.V_STR:
			case Variant.V_FIX_STR:
				fn_ = filename.strValue();
			break;

			default: throw new HpException(53, "File not found");
		}

		if (fn_ == null)
			throw new HpException(53, "File not found");

		//Frame f = new Frame("TZGIF");
		//Image image = null;//((Picture)urlpicture.getObject().getobj()).image;
		Image image = urlpicture.image;
		//Image image = f.getToolkit().getImage(new URL(up_));

		if (image == null)
			throw new HpException(481, "Invalid picture");
		/*
		MediaTracker tracker = new MediaTracker(f);
		tracker.addImage(image, 0);
		try {
			tracker.waitForID(0);
		} catch (InterruptedException e) { ; }
		if (tracker.statusID(0, true) != MediaTracker.COMPLETE)
			throw new HpException(99, "Could not save," + 
				" Use statusID() to check for error is " +
					tracker.statusID(0, true));
		*/

		GIFEncoder(image);
		OutputStream output = new BufferedOutputStream(
			new FileOutputStream(fn_));
		SavePicture(output);

		//System.exit(0);
		return;
	}

	void SavePicture(OutputStream output) throws IOException
	{
		WriteString(output, "GIF87a");  //GIF89a
		WriteWord(output, width_);
		WriteWord(output, height_);
		SetGlobalColorTableSize((byte)(BitsNeeded(numColors_) - 1));
		SetGlobalColorTableFlag((byte)1);
		SetSortFlag((byte)0);
		SetColorResolution((byte)7);
		backgroundColorIndex_ = 0;
		pixelAspectRatio_ = 0;
		output.write(byte_);
		output.write(backgroundColorIndex_);
		output.write(pixelAspectRatio_);

		output.write(colors_, 0, colors_.length);

		separator_ = (byte)',';
		leftPosition_ = 0;
		topPosition_ = 0;
		byte_ = 0;
		SetLocalColorTableSize((byte)0);
		SetReserved((byte)0);
		SetShortFlag((byte)0);
		SetInterlaceFlag((byte)0);
		SetLocalColorTableFlag((byte)0);
		output.write(separator_);
		WriteWord(output, leftPosition_);
		WriteWord(output, topPosition_);
		WriteWord(output, width_);
		WriteWord(output, height_);
		output.write(byte_);

		byte codesize = BitsNeeded(numColors_);
		if (codesize == 1)
			++codesize;
		output.write(codesize);    //size

		LZWCompress(output, codesize, pixels_); //load image
		output.write(0);         //no very vaild

		separator_ = (byte)';';
		output.write(separator_);
		WriteWord(output, leftPosition_);
		WriteWord(output, topPosition_);
		WriteWord(output, (byte)0);
		WriteWord(output, (byte)0);
		output.write(byte_);

		output.flush();         //flush
	}

	void GIFEncoder(Image image) throws HpException 
	{
		width_ = (short)image.getWidth(null);
		height_ = (short)image.getHeight(null);

		int values[] = new int[width_ * height_];
		PixelGrabber grabber = new PixelGrabber(
		image, 0, 0, width_, height_, values, 0, width_);

		try {
			if(grabber.grabPixels() != true)
				throw new HpException(111, "Grabber returned false: " +
			grabber.status());
		} catch (InterruptedException e) { ; }

		byte r[][] = new byte[width_][height_];
		byte g[][] = new byte[width_][height_];
		byte b[][] = new byte[width_][height_];
		int index = 0;
		for (int y = 0; y < height_; ++y)
			for (int x = 0; x < width_; ++x) {
				r[x][y] = (byte)((values[index] >> 16) & 0xFF);
				g[x][y] = (byte)((values[index] >> 8) & 0xFF);
				b[x][y] = (byte)((values[index]) & 0xFF);
				++index;
			}
		ToIndexedColor(r, g, b);
	}

	void ToIndexedColor(byte r[][], byte g[][], byte b[][]) throws HpException 
	{
		pixels_ = new byte[width_ * height_];
		colors_ = new byte[256 * 3];
		int colornum = 0;
		for (int x = 0; x < width_; ++x) {
			for (int y = 0; y < height_; ++y) {
				int search;
				for (search = 0; search < colornum; ++search)
					if (colors_[search * 3]     == r[x][y] &&
						colors_[search * 3 + 1] == g[x][y] &&
						colors_[search * 3 + 2] == b[x][y])
						break;

				if (search > 255)
					throw new HpException(103, "Too many colors.");

				pixels_[y * width_ + x] = (byte)search;

				if (search == colornum) {
					colors_[search * 3]     = r[x][y];
					colors_[search * 3 + 1] = g[x][y];
					colors_[search * 3 + 2] = b[x][y];
					++colornum;
				}
			}
		}
		numColors_ = 1 << BitsNeeded(colornum);
		byte copy[] = new byte[numColors_ * 3];
		System.arraycopy(colors_, 0, copy, 0, numColors_ * 3);
		colors_ = copy;
	}

	void LZWCompress(OutputStream output, int codesize,
						byte toCompress[]) throws IOException {
		byte c;
		short index;
		int clearcode, endofinfo, numbits, limit, errcode;
		short prefix = (short)0xFFFF;

		clearcode = 1 << codesize;
		endofinfo = clearcode + 1;

		numbits = codesize + 1;
		limit = (1 << numbits) - 1;

		ClearTable(codesize);
		WriteBits(output, clearcode, numbits);

		for (int loop = 0; loop < toCompress.length; ++loop) {
			c = toCompress[loop];
			if ((index = FindCharString(prefix, c)) != -1)
				prefix = index;
			else {
				WriteBits(output, prefix, numbits);
				if (AddCharString(prefix, c) > limit) {
					if (++numbits > 12) {
						WriteBits(output, clearcode, numbits - 1);
						ClearTable(codesize);
						numbits = codesize + 1;
					}
					limit = (1 << numbits) - 1;
				}

				prefix = (short)((short)c & 0xFF);
			}
		}

		if (prefix != -1)
			WriteBits(output, prefix, numbits);

		WriteBits(output, endofinfo, numbits);
		Flush(output);
	}

	private void Flush(OutputStream output_) throws IOException {
		int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1);
		if (numBytes > 0) {
			output_.write(numBytes);
			output_.write(buffer_, 0, numBytes);
			buffer_[0] = 0;
			index_ = 0;
			bitsLeft_ = 8;
		}
	}

	private void WriteBits(OutputStream output_, int bits, int numbits) throws IOException {
		int bitsWritten = 0;
		int numBytes = 255;
		do {
			if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254) {
				output_.write(numBytes);
				output_.write(buffer_, 0, numBytes);

				buffer_[0] = 0;
				index_ = 0;
				bitsLeft_ = 8;
			}

			if (numbits <= bitsLeft_) {
				buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<
					(8 - bitsLeft_);
				bitsWritten += numbits;
				bitsLeft_ -= numbits;
				numbits = 0;
			}
			else {
				buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) <<
					(8 - bitsLeft_);
				bitsWritten += bitsLeft_;
				bits >>= bitsLeft_;
				numbits -= bitsLeft_;
				buffer_[++index_] = 0;
				bitsLeft_ = 8;
			}
		} while (numbits != 0);
	}

	private int AddCharString(short index, byte b) {
		int hshidx;

		if (numStrings_ >= MAXSTR)
			return 0xFFFF;

		hshidx = Hash(index, b);
		while (strHsh_[hshidx] != HASH_FREE)
			hshidx = (hshidx + HASHSTEP) % HASHSIZE;

		strHsh_[hshidx] = numStrings_;
		strChr_[numStrings_] = b;
		strNxt_[numStrings_] = (index != HASH_FREE) ? index : NEXT_FIRST;

		return numStrings_++;
	}

	private short FindCharString(short index, byte b) {
		int hshidx, nxtidx;

		if (index == HASH_FREE)
			return b;

		hshidx = Hash(index, b);
		while ((nxtidx = strHsh_[hshidx]) != HASH_FREE) {
			if (strNxt_[nxtidx] == index && strChr_[nxtidx] == b)
				return (short)nxtidx;
			hshidx = (hshidx + HASHSTEP) % HASHSIZE;
		}

		return (short)0xFFFF;
	}

	private void ClearTable(int codesize) {
		numStrings_ = 0;

		for (int q = 0; q < HASHSIZE; q++) {
			strHsh_[q] = HASH_FREE;
		}

		int w = (1 << codesize) + RES_CODES;
		for (int q = 0; q < w; q++)
			AddCharString((short)0xFFFF, (byte)q);
	}

	private int Hash(short index, byte lastbyte) {
		return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
	}

	private byte BitsNeeded(int n) {
		byte ret = 1;

		if (n-- == 0)
			return 0;

		while ((n >>= 1) != 0)
			++ret;

		return ret;
	}

	private void WriteWord(OutputStream output,
								short w) throws IOException {
		output.write(w & 0xFF);
		output.write((w >> 8) & 0xFF);
	}

	void WriteString(OutputStream output,
							String string) throws IOException {
		for (int loop = 0; loop < string.length(); ++loop)
			output.write((byte)(string.charAt(loop)));
	}

	private void SetGlobalColorTableSize(byte num) {
		byte_ |= (num & 7);
	}

	private void SetSortFlag(byte num) {
		byte_ |= (num & 1) << 3;
	}

	private void SetColorResolution(byte num) {
		byte_ |= (num & 7) << 4;
	}

	private void SetGlobalColorTableFlag(byte num) {
		byte_ |= (num & 1) << 7;
	}

	//ImageDescriptor
	private void SetLocalColorTableSize(byte num) {
		byte_ |= (num & 7);
	}

	private void SetReserved(byte num) {
		byte_ |= (num & 3) << 3;
	}

	private void SetShortFlag(byte num) {
		byte_ |= (num & 1) << 5;
	}

	private void SetInterlaceFlag(byte num) {
		byte_ |= (num & 1) << 6;
	}

	private void SetLocalColorTableFlag(byte num) {
		byte_ |= (num & 1) << 7;
	}
}

⌨️ 快捷键说明

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