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

📄 pngfileformat.java

📁 源码为Eclipse开源开发平台桌面开发工具SWT的源代码,
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
void setImageDataValues(byte[] data, ImageData imageData) {	byte[] result = validateBitDepth(data);	setPixelData(result, imageData);}/** * Read the image data from the data stream. This must handle * decoding the data, filtering, and interlacing. */void readPixelData(PngIdatChunk chunk, PngChunkReader chunkReader) {	decodingStream = new PngDecodingDataStream(chunk, chunkReader);	int interlaceMethod = headerChunk.getInterlaceMethod();	if (interlaceMethod == PngIhdrChunk.INTERLACE_METHOD_NONE) {		readNonInterlacedImage();	} else {		readInterlacedImage();	}	decodingStream.assertImageDataAtEnd();	decodingStream.checkAdler();}/** * Answer the number of bytes in a word-aligned row of pixel data. */int getAlignedBytesPerRow() {	return ((getBytesPerRow(headerChunk.getWidth()) + 3) / 4) * 4;}/** * Answer the number of bytes in each row of the image * data. Each PNG row is byte-aligned, so images with bit * depths less than a byte may have unused bits at the * end of each row. The value of these bits is undefined. */int getBytesPerRow() {	return getBytesPerRow(headerChunk.getWidth());}/** * Answer the number of bytes needed to represent a pixel. * This value depends on the image's color type and bit * depth.  * Note that this method rounds up if an image's pixel size * isn't byte-aligned. */int getBytesPerPixel() {	int bitsPerPixel = headerChunk.getBitsPerPixel();	return (bitsPerPixel + 7) / 8;	}/** * Answer the number of bytes in a row of the given pixel * width. Each row is byte-aligned, so images with bit * depths less than a byte may have unused bits at the * end of each row. The value of these bits is undefined. */int getBytesPerRow(int rowWidthInPixels) {	int bitsPerPixel = headerChunk.getBitsPerPixel();	int bitsPerRow = bitsPerPixel * rowWidthInPixels;	int bitsPerByte = 8;	return (bitsPerRow + (bitsPerByte - 1)) / bitsPerByte;}/** * 1. Read one of the seven frames of interlaced data. * 2. Update the imageData. * 3. Notify the image loader's listeners of the frame load. */void readInterlaceFrame(	int rowInterval,	int columnInterval,	int startRow,	int startColumn,	int frameCount) {	int width = headerChunk.getWidth();	int alignedBytesPerRow = getAlignedBytesPerRow();	int height = headerChunk.getHeight();	if (startRow >= height || startColumn >= width) return;		int pixelsPerRow = (width - startColumn + columnInterval - 1) / columnInterval;	int bytesPerRow = getBytesPerRow(pixelsPerRow);	byte[] row1 = new byte[bytesPerRow];	byte[] row2 = new byte[bytesPerRow];	byte[] currentRow = row1;		byte[] lastRow = row2;		for (int row = startRow; row < height; row += rowInterval) {		byte filterType = decodingStream.getNextDecodedByte();		for (int col = 0; col < bytesPerRow; col++) {			currentRow[col] = decodingStream.getNextDecodedByte();		}		filterRow(currentRow, lastRow, filterType);		if (headerChunk.getBitDepth() >= 8) {			int bytesPerPixel = getBytesPerPixel();			int dataOffset = (row * alignedBytesPerRow) + (startColumn * bytesPerPixel);			for (int rowOffset = 0; rowOffset < currentRow.length; rowOffset += bytesPerPixel) {				for (int byteOffset = 0; byteOffset < bytesPerPixel; byteOffset++) {					data[dataOffset + byteOffset] = currentRow[rowOffset + byteOffset];				}				dataOffset += (columnInterval * bytesPerPixel);			}		} else {			int bitsPerPixel = headerChunk.getBitDepth();			int pixelsPerByte = 8 / bitsPerPixel;			int column = startColumn;			int rowBase = row * alignedBytesPerRow;			int valueMask = 0;			for (int i = 0; i < bitsPerPixel; i++) {				valueMask <<= 1;				valueMask |= 1;			}			int maxShift = 8 - bitsPerPixel;			for (int byteOffset = 0; byteOffset < currentRow.length; byteOffset++) {				for (int bitOffset = maxShift; bitOffset >= 0; bitOffset -= bitsPerPixel) {					if (column < width) {						int dataOffset = rowBase + (column * bitsPerPixel / 8);													int value = (currentRow[byteOffset] >> bitOffset) & valueMask;						int dataShift = maxShift - (bitsPerPixel * (column % pixelsPerByte));						data[dataOffset] |= value << dataShift;					}					column += columnInterval;				}			}		}		currentRow = (currentRow == row1) ? row2 : row1;		lastRow = (lastRow == row1) ? row2 : row1;	}	setImageDataValues(data, imageData);	fireInterlacedFrameEvent(frameCount);}/** * Read the pixel data for an interlaced image from the * data stream. */void readInterlacedImage() {	readInterlaceFrame(8, 8, 0, 0, 0);	readInterlaceFrame(8, 8, 0, 4, 1);		readInterlaceFrame(8, 4, 4, 0, 2);		readInterlaceFrame(4, 4, 0, 2, 3);	readInterlaceFrame(4, 2, 2, 0, 4);	readInterlaceFrame(2, 2, 0, 1, 5);		readInterlaceFrame(2, 1, 1, 0, 6);}/** * Fire an event to let listeners know that an interlaced * frame has been loaded. * finalFrame should be true if the image has finished * loading, false if there are more frames to come. */void fireInterlacedFrameEvent(int frameCount) {	if (loader.hasListeners()) {		ImageData image = (ImageData) imageData.clone();		boolean finalFrame = frameCount == 6;		loader.notifyListeners(new ImageLoaderEvent(loader, image, frameCount, finalFrame));	}}/** * Read the pixel data for a non-interlaced image from the * data stream. * Update the imageData to reflect the new data. */void readNonInterlacedImage() {	int dataOffset = 0;	int alignedBytesPerRow = getAlignedBytesPerRow();	int bytesPerRow = getBytesPerRow();	byte[] row1 = new byte[bytesPerRow];	byte[] row2 = new byte[bytesPerRow];	byte[] currentRow = row1;		byte[] lastRow = row2;	for (int row = 0; row < headerChunk.getHeight(); row++) {		byte filterType = decodingStream.getNextDecodedByte();		for (int col = 0; col < bytesPerRow; col++) {			currentRow[col] = decodingStream.getNextDecodedByte();		}		filterRow(currentRow, lastRow, filterType);		System.arraycopy(currentRow, 0, data, dataOffset, bytesPerRow);		dataOffset += alignedBytesPerRow;		currentRow = (currentRow == row1) ? row2 : row1;		lastRow = (lastRow == row1) ? row2 : row1;	}	setImageDataValues(data, imageData);}/** * SWT does not support 16-bit depth color formats. * Convert the 16-bit data to 8-bit data. * The correct way to do this is to multiply each * 16 bit value by the value: * (2^8 - 1) / (2^16 - 1). * The fast way to do this is just to drop the low * byte of the 16-bit value. */static void compress16BitDepthTo8BitDepth(	byte[] source,	int sourceOffset,	byte[] destination, 	int destinationOffset,	int numberOfValues) {	//double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);	for (int i = 0; i < numberOfValues; i++) {		int sourceIndex = sourceOffset + (2 * i);		int destinationIndex = destinationOffset + i;		//int value = (source[sourceIndex] << 8) | source[sourceIndex + 1];		//byte compressedValue = (byte)(value * multiplier);		byte compressedValue = source[sourceIndex];		destination[destinationIndex] = compressedValue;	}}/** * SWT does not support 16-bit depth color formats. * Convert the 16-bit data to 8-bit data. * The correct way to do this is to multiply each * 16 bit value by the value: * (2^8 - 1) / (2^16 - 1). * The fast way to do this is just to drop the low * byte of the 16-bit value. */static int compress16BitDepthTo8BitDepth(int value) {	//double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);	//byte compressedValue = (byte)(value * multiplier);	return value >> 8;}/** * PNG supports four filtering types. These types are applied * per row of image data. This method unfilters the given row * based on the filterType. */void filterRow(byte[] row, byte[] previousRow, int filterType) {	int byteOffset = headerChunk.getFilterByteOffset();	switch (filterType) {		case PngIhdrChunk.FILTER_NONE:			break;		case PngIhdrChunk.FILTER_SUB:			for (int i = byteOffset; i < row.length; i++) {				int current = row[i] & 0xFF;				int left = row[i - byteOffset] & 0xFF;				row[i] = (byte)((current + left) & 0xFF);			}			break;		case PngIhdrChunk.FILTER_UP:			for (int i = 0; i < row.length; i++) {				int current = row[i] & 0xFF;				int above = previousRow[i] & 0xFF;								row[i] = (byte)((current + above) & 0xFF);			}			break;		case PngIhdrChunk.FILTER_AVERAGE:			for (int i = 0; i < row.length; i++) {				int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;				int above = previousRow[i] & 0xFF;				int current = row[i] & 0xFF;				row[i] = (byte)((current + ((left + above) / 2)) & 0xFF);			}			break;		case PngIhdrChunk.FILTER_PAETH:			for (int i = 0; i < row.length; i++) {				int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;				int aboveLeft = (i < byteOffset) ? 0 : previousRow[i - byteOffset] & 0xFF;				int above = previousRow[i] & 0xFF;								int a = Math.abs(above - aboveLeft);				int b = Math.abs(left - aboveLeft);				int c = Math.abs(left - aboveLeft + above - aboveLeft);								int preductor = 0;				if (a <= b && a <= c) {					preductor = left;				} else if (b <= c) {					preductor = above;				} else {					preductor = aboveLeft;				}								int currentValue = row[i] & 0xFF;				row[i] = (byte) ((currentValue + preductor) & 0xFF);			}			break;	}}}

⌨️ 快捷键说明

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