帆软使用的第三方框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
12 KiB

package com.fr.third.JAI;
/*
* Copyright (c) 2001 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:
*
* -Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduct 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 AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE 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 SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed,licensed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
/**
*/
public class PNMImageDecoder extends ImageDecoderImpl {
public PNMImageDecoder(SeekableStream input,
ImageDecodeParam param) {
super(input, param);
}
public RenderedImage decodeAsRenderedImage(int page) throws IOException {
if (page != 0) {
throw new IOException(JaiI18N.getString("PNMImageDecoder5"));
}
return new PNMImage(input);
}
}
class PNMImage extends SimpleRenderedImage {
private static final int PBM_ASCII = '1';
private static final int PGM_ASCII = '2';
private static final int PPM_ASCII = '3';
private static final int PBM_RAW = '4';
private static final int PGM_RAW = '5';
private static final int PPM_RAW = '6';
private static final int LINE_FEED = 0x0A;
private SeekableStream input;
private byte[] lineSeparator;
/** File variant: PBM/PGM/PPM, ASCII/RAW. */
private int variant;
/** Maximum pixel value. */
private int maxValue;
/** Raster that is the entire image. */
private Raster theTile;
private int numBands;
private int dataType;
/**
* Construct a PNMImage.
*
* @param input The SeekableStream for the PNM file.
*/
public PNMImage(SeekableStream input) {
theTile = null;
this.input = input;
String ls = (String)java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator"));
lineSeparator = ls.getBytes();
// Read file header.
try {
if (this.input.read() != 'P') { // magic number
throw new RuntimeException(JaiI18N.getString("PNMImageDecoder0"));
}
variant = this.input.read(); // file variant
if ((variant < PBM_ASCII) || (variant > PPM_RAW)) {
throw new RuntimeException(JaiI18N.getString("PNMImageDecoder1"));
}
width = readInteger(this.input); // width
height = readInteger(this.input); // height
if (variant == PBM_ASCII || variant == PBM_RAW) {
maxValue = 1;
} else {
maxValue = readInteger(this.input); // maximum value
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(JaiI18N.getString("PNMImageDecoder2"));
}
// The RAWBITS format can only support byte image data, which means
// maxValue should be less than 0x100. In case there's a conflict,
// base the maxValue on variant.
if (isRaw(variant) && maxValue >= 0x100) {
maxValue = 0xFF;
}
// Reset image layout so there's only one tile.
tileWidth = width;
tileHeight = height;
// Determine number of bands: pixmap (PPM) is 3 bands,
// bitmap (PBM) and greymap (PGM) are 1 band.
if (variant == PPM_ASCII || variant == PPM_RAW) {
this.numBands = 3;
} else {
this.numBands = 1;
}
// Determine data type based on maxValue.
if (maxValue < 0x100) {
this.dataType = DataBuffer.TYPE_BYTE;
} else if (maxValue < 0x10000) {
this.dataType = DataBuffer.TYPE_USHORT;
} else {
this.dataType = DataBuffer.TYPE_INT;
}
// Choose an appropriate SampleModel.
if ((variant == PBM_ASCII) || (variant == PBM_RAW)) {
// Each pixel takes 1 bit, pack 8 pixels into a byte.
sampleModel = new MultiPixelPackedSampleModel(
DataBuffer.TYPE_BYTE, width, height, 1);
colorModel =
ImageCodec.createGrayIndexColorModel(sampleModel, false);
} else {
int[] bandOffsets = numBands == 1 ?
new int[] {0} : new int[] {0, 1, 2};
sampleModel = RasterFactory.createPixelInterleavedSampleModel(
dataType, tileWidth, tileHeight,
numBands, tileWidth*numBands,
bandOffsets);
colorModel =
ImageCodec.createComponentColorModel(sampleModel);
}
}
/** Returns true if file variant is raw format, false if ASCII. */
private boolean isRaw(int v) {
return (v >= PBM_RAW);
}
/** Reads the next integer. */
private int readInteger(SeekableStream in) throws IOException {
int ret = 0;
boolean foundDigit = false;
int b;
while ((b = in.read()) != -1) {
char c = (char)b;
if (Character.isDigit(c)) {
ret = ret * 10 + Character.digit(c, 10);
foundDigit = true;
} else {
if (c == '#') { // skip to the end of comment line
int length = lineSeparator.length;
while ((b = in.read()) != -1) {
boolean eol = false;
for (int i = 0; i < length; i++) {
if (b == lineSeparator[i]) {
eol = true;
break;
}
}
if (eol) {
break;
}
}
if (b == -1) {
break;
}
}
if (foundDigit) {
break;
}
}
}
return ret;
}
private Raster computeTile(int tileX, int tileY) {
// Create a new tile.
Point org = new Point(tileXToX(tileX), tileYToY(tileY));
WritableRaster tile = Raster.createWritableRaster(sampleModel, org);
Rectangle tileRect = tile.getBounds();
// There should only be one tile.
try {
switch (variant) {
case PBM_ASCII:
case PBM_RAW:
// SampleModel for these cases should be MultiPixelPacked.
DataBuffer dataBuffer = tile.getDataBuffer();
if (isRaw(variant)) {
// Read the entire image.
byte[] buf = ((DataBufferByte)dataBuffer).getData();
input.readFully(buf, 0, buf.length);
} else {
// Read 8 rows at a time
byte[] pixels = new byte[8*width];
int offset = 0;
for (int row = 0; row < tileHeight; row += 8) {
int rows = Math.min(8, tileHeight - row);
int len = (rows*width + 7)/8;
for (int i = 0; i < rows*width; i++) {
pixels[i] = (byte)readInteger(input);
}
sampleModel.setDataElements(tileRect.x,
row,
tileRect.width,
rows,
pixels,
dataBuffer);
}
}
break;
case PGM_ASCII:
case PGM_RAW:
case PPM_ASCII:
case PPM_RAW:
// SampleModel for these cases should be PixelInterleaved.
int size = width*height*numBands;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
DataBufferByte bbuf =
(DataBufferByte)tile.getDataBuffer();
byte[] byteArray = bbuf.getData();
if (isRaw(variant)) {
input.readFully(byteArray);
} else {
for (int i = 0; i < size; i++) {
byteArray[i] = (byte)readInteger(input);
}
}
break;
case DataBuffer.TYPE_USHORT:
DataBufferUShort sbuf =
(DataBufferUShort)tile.getDataBuffer();
short[] shortArray = sbuf.getData();
for (int i = 0; i < size; i++) {
shortArray[i] = (short)readInteger(input);
}
break;
case DataBuffer.TYPE_INT:
DataBufferInt ibuf =
(DataBufferInt)tile.getDataBuffer();
int[] intArray = ibuf.getData();
for (int i = 0; i < size; i++) {
intArray[i] = readInteger(input);
}
break;
}
break;
}
// Close the PNM stream and release system resources.
input.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(JaiI18N.getString("PNMImageDecoder3"));
}
return tile;
}
public synchronized Raster getTile(int tileX, int tileY) {
if ((tileX != 0) || (tileY != 0)) {
throw new IllegalArgumentException(JaiI18N.getString("PNMImageDecoder4"));
}
if (theTile == null) {
theTile = computeTile(tileX, tileY);
}
return theTile;
}
}