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

📄 lzwcodec.java

📁 源码为Eclipse开源开发平台桌面开发工具SWT的源代码,
💻 JAVA
字号:
/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html *  * Contributors: *     IBM Corporation - initial API and implementation *******************************************************************************/package org.eclipse.swt.internal.image;import org.eclipse.swt.*;import org.eclipse.swt.graphics.*;final class LZWCodec {	int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft,		codeSize, clearCode, endCode, newCodes, topSlot, currentSlot,		imageWidth, imageHeight, imageX, imageY, pass, line, codeMask, buffer;	byte[] block, lineArray;	int[] stack, suffix, prefix;	LZWNode[] nodeStack;	LEDataInputStream inputStream;	LEDataOutputStream outputStream;	ImageData image;	ImageLoader loader;	boolean interlaced;	static final int[] MASK_TABLE = new int[] {		0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F,		0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF	};/** * Decode the input. */void decode() {	int code;	int oc = 0;	int fc = 0;	byte[] buf = new byte[imageWidth];	int stackIndex = 0;	int bufIndex = 0;	int c;	while ((c = nextCode()) != endCode) {		if (c == clearCode) {			codeSize = bitsPerPixel + 1;			codeMask = MASK_TABLE[bitsPerPixel];			currentSlot = newCodes;			topSlot = 1 << codeSize;			while ((c = nextCode()) == clearCode) {}			if (c != endCode) {				oc = fc = c;				buf[bufIndex] = (byte)c;				bufIndex++;				if (bufIndex == imageWidth) {					nextPutPixels(buf);					bufIndex = 0;				}			}		} else {			code = c;			if (code >= currentSlot) {				if (code > currentSlot)					SWT.error(SWT.ERROR_INVALID_IMAGE);				code = oc;				stack[stackIndex] = fc;				stackIndex++;			}			while (code >= newCodes) {				stack[stackIndex] = suffix[code];				stackIndex++;				code = prefix[code];			}			stack[stackIndex] = code;			stackIndex++;			if (currentSlot < topSlot) {				fc = code;				suffix[currentSlot] = fc;				prefix[currentSlot] = oc;				currentSlot++;				oc = c;			}			if (currentSlot >= topSlot) {				if (codeSize < 12) {					codeMask = MASK_TABLE[codeSize];					codeSize++;					topSlot = topSlot + topSlot;				}			}			while (stackIndex > 0) {				stackIndex--;				buf[bufIndex] = (byte)stack[stackIndex];				bufIndex++;				if (bufIndex == imageWidth) {					nextPutPixels(buf);					bufIndex = 0;				}			}		}	}	if (bufIndex != 0 && line < imageHeight) {		nextPutPixels(buf);	}}/** * Decode the LZW-encoded bytes in the given byte stream * into the given DeviceIndependentImage. */public void decode(LEDataInputStream inputStream, ImageLoader loader, ImageData image, boolean interlaced, int depth) {	this.inputStream = inputStream;	this.loader = loader;	this.image = image;	this.interlaced = interlaced;	this.bitsPerPixel = depth;	initializeForDecoding();	decode();}/** * Encode the image. */void encode() {	nextPutCode(clearCode);	int lastPrefix = encodeLoop();	nextPutCode(lastPrefix);	nextPutCode(endCode);	// Write out last partial block	if (bitsLeft == 8) {		block[0] = (byte)(blockIndex - 1); // Nothing in last byte	} else {		block[0] = (byte)(blockIndex); // Last byte has data	}	writeBlock();	// Write out empty block to indicate the end (if needed)	if (block[0] != 0) {		block[0] = 0;		writeBlock();	}}/** * Encode the bytes into the given byte stream * from the given DeviceIndependentImage. */public void encode(LEDataOutputStream byteStream, ImageData image) {	this.outputStream = byteStream;	this.image = image;	initializeForEncoding();	encode();}/** * Encoding loop broken out to allow early return. */int encodeLoop() {	int pixel = nextPixel();	boolean found;	LZWNode node;	while (true) {		int currentPrefix = pixel;		node = nodeStack[currentPrefix];		found = true;		pixel = nextPixel();		if (pixel < 0)			return currentPrefix;		while (found && (node.children != null)) {			node = node.children;			while (found && (node.suffix != pixel)) {				if (pixel < node.suffix) {					if (node.left == null) {						node.left = new LZWNode();						found = false;					}					node = node.left;				} else {					if (node.right == null) {						node.right = new LZWNode();						found = false;					}					node = node.right;				}			}			if (found) {				currentPrefix = node.code;				pixel = nextPixel();				if (pixel < 0)					return currentPrefix;			}		}		if (found) {			node.children = new LZWNode();			node = node.children;		}		node.children = null;		node.left = null;		node.right = null;		node.code = currentSlot;		node.prefix = currentPrefix;		node.suffix = pixel;		nextPutCode(currentPrefix);		currentSlot++;		// Off by one?		if (currentSlot < 4096) {			if (currentSlot > topSlot) {				codeSize++;				codeMask = MASK_TABLE[codeSize - 1];				topSlot *= 2;			}		} else {			nextPutCode(clearCode);			for (int i = 0; i < nodeStack.length; i++)				nodeStack[i].children = null;			codeSize = bitsPerPixel + 1;			codeMask = MASK_TABLE[codeSize - 1];			currentSlot = newCodes;			topSlot = 1 << codeSize;		}	}}/** * Initialize the receiver for decoding the given * byte array. */void initializeForDecoding() {	pass = 1;	line = 0;	codeSize = bitsPerPixel + 1;	topSlot = 1 << codeSize;	clearCode = 1 << bitsPerPixel;	endCode = clearCode + 1;	newCodes = currentSlot = endCode + 1;	currentByte = -1;	blockSize = bitsLeft = 0;	blockIndex = 0;	codeMask = MASK_TABLE[codeSize - 1];	stack = new int[4096];	suffix = new int[4096];	prefix = new int[4096];	block = new byte[256];	imageWidth = image.width;	imageHeight = image.height;}/** * Initialize the receiver for encoding the given * byte array. */void initializeForEncoding() {	interlaced = false;	bitsPerPixel = image.depth;	codeSize = bitsPerPixel + 1;	topSlot = 1 << codeSize;	clearCode = 1 << bitsPerPixel;	endCode = clearCode + 1;	newCodes = currentSlot = endCode + 1;	bitsLeft = 8;	currentByte = 0;	blockIndex = 1;	blockSize = 255;	block = new byte[blockSize];	block[0] = (byte)(blockSize - 1);	nodeStack = new LZWNode[1 << bitsPerPixel];	for (int i = 0; i < nodeStack.length; i++) {		LZWNode node = new LZWNode();		node.code = i + 1;		node.prefix = -1;		node.suffix = i + 1;		nodeStack[i] = node;	}	imageWidth = image.width;	imageHeight = image.height;	imageY = -1;	lineArray = new byte[imageWidth];	imageX = imageWidth + 1; // Force a read}/** * Answer the next code from the input byte array. */int nextCode() {	int code;	if (bitsLeft == 0) {		if (blockIndex >= blockSize) {			blockSize = readBlock();			blockIndex = 0;			if (blockSize == 0) return endCode;		}		blockIndex++;		currentByte = block[blockIndex] & 0xFF;		bitsLeft = 8;		code = currentByte;	} else {		int shift = bitsLeft - 8;		if (shift < 0)			code = currentByte >> (0 - shift);		else			code = currentByte << shift;	}	while (codeSize > bitsLeft) {		if (blockIndex >= blockSize) {			blockSize = readBlock();			blockIndex = 0;			if (blockSize == 0) return endCode;		}		blockIndex++;		currentByte = block[blockIndex] & 0xFF;		code += currentByte << bitsLeft;		bitsLeft += 8;	}	bitsLeft -= codeSize;	return code & codeMask;}/** * Answer the next pixel to encode in the image */int nextPixel() {	imageX++;	if (imageX > imageWidth) {		imageY++;		if (imageY >= imageHeight) {			return -1;		} else {			nextPixels(lineArray, imageWidth);		}		imageX = 1;	}	return this.lineArray[imageX - 1] & 0xFF;}/** * Copy a row of pixel values from the image. */void nextPixels(byte[] buf, int lineWidth) {	if (image.depth == 8) {		System.arraycopy(image.data, imageY * image.bytesPerLine, buf, 0, lineWidth);	} else {		image.getPixels(0, imageY, lineWidth, buf, 0);	}}/** * Output aCode to the output stream. */void nextPutCode(int aCode) {	int codeToDo = aCode;	int codeBitsToDo = codeSize;	// Fill in the remainder of the current byte with the	// *high-order* bits of the code.	int c = codeToDo & MASK_TABLE[bitsLeft - 1];	currentByte = currentByte | (c << (8 - bitsLeft));	block[blockIndex] = (byte)currentByte;	codeBitsToDo -= bitsLeft;	if (codeBitsToDo < 1) {		// The whole code fit in the first byte, so we are done.		bitsLeft -= codeSize;		if (bitsLeft == 0) {			// We used the whole last byte, so get ready			// for the next one.			bitsLeft = 8;			blockIndex++;			if (blockIndex >= blockSize) {				writeBlock();				blockIndex = 1;			}			currentByte = 0;		}		return;	}	codeToDo = codeToDo >> bitsLeft;	// Fill in any remaining whole bytes (i.e. not the last one!)	blockIndex++;	if (blockIndex >= blockSize) {		writeBlock();		blockIndex = 1;	}	while (codeBitsToDo >= 8) {		currentByte = codeToDo & 0xFF;		block[blockIndex] = (byte)currentByte;		codeToDo = codeToDo >> 8;		codeBitsToDo -= 8;		blockIndex++;		if (blockIndex >= blockSize) {			writeBlock();			blockIndex = 1;		}	}	// Fill the *low-order* bits of the last byte with the remainder	bitsLeft = 8 - codeBitsToDo;	currentByte = codeToDo;	block[blockIndex] = (byte)currentByte;}/** * Copy a row of pixel values to the image. */void nextPutPixels(byte[] buf) {	if (image.depth == 8) {		// Slight optimization for depth = 8.		int start = line * image.bytesPerLine;		for (int i = 0; i < imageWidth; i++)			image.data[start + i] = buf[i];	} else {		image.setPixels(0, line, imageWidth, buf, 0);	}	if (interlaced) {		if (pass == 1) {			copyRow(buf, 7);			line += 8;		} else if (pass == 2) {			copyRow(buf, 3);			line += 8;		} else if (pass == 3) {			copyRow(buf, 1);			line += 4;		} else if (pass == 4) {			line += 2;		} else if (pass == 5) {			line += 0;		}		if (line >= imageHeight) {			pass++;			if (pass == 2) line = 4;			else if (pass == 3) line = 2;			else if (pass == 4) line = 1;			else if (pass == 5) line = 0;			if (pass < 5) {				if (loader.hasListeners()) {					ImageData imageCopy = (ImageData) image.clone();					loader.notifyListeners(						new ImageLoaderEvent(loader, imageCopy, pass - 2, false));				}			}		}		if (line >= imageHeight) line = 0;	} else {		line++;	}}/** * Copy duplicate rows of pixel values to the image. * This is to fill in rows if the image is interlaced. */void copyRow(byte[] buf, int copies) {	for (int i = 1; i <= copies; i++) {		if (line + i < imageHeight) {			image.setPixels(0, line + i, imageWidth, buf, 0);		}	}}/** * Read a block from the byte stream. * Return the number of bytes read. * Throw an exception if the block could not be read. */int readBlock() {	int size = -1;	try {		size = inputStream.read();		if (size == -1) {			SWT.error(SWT.ERROR_INVALID_IMAGE);		}		block[0] = (byte)size;		size = inputStream.read(block, 1, size);		if (size == -1) {			SWT.error(SWT.ERROR_INVALID_IMAGE);		}	} catch (Exception e) {		SWT.error(SWT.ERROR_IO, e);	}	return size;}/** * Write a block to the byte stream. * Throw an exception if the block could not be written. */void writeBlock() {	try {		outputStream.write(block, 0, (block[0] & 0xFF) + 1);	} catch (Exception e) {		SWT.error(SWT.ERROR_IO, e);	}}}

⌨️ 快捷键说明

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