001: /*
002: * $RCSfile: PNMCodec.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:55:38 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.codecimpl;
013:
014: import java.awt.image.DataBuffer;
015: import java.awt.image.RenderedImage;
016: import java.awt.image.SampleModel;
017: import java.io.BufferedInputStream;
018: import java.io.InputStream;
019: import java.io.IOException;
020: import java.io.OutputStream;
021: import com.sun.media.jai.codec.ForwardSeekableStream;
022: import com.sun.media.jai.codec.ImageCodec;
023: import com.sun.media.jai.codec.ImageDecoder;
024: import com.sun.media.jai.codec.ImageDecodeParam;
025: import com.sun.media.jai.codec.ImageEncoder;
026: import com.sun.media.jai.codec.ImageEncodeParam;
027: import com.sun.media.jai.codec.PNMEncodeParam;
028: import com.sun.media.jai.codec.SeekableStream;
029:
030: /**
031: * A subclass of <code>ImageCodec</code> that handles the
032: * PNM family of formats (PBM, PGM, PPM).
033: *
034: * <p> The PBM format encodes a single-banded, 1-bit image. The PGM
035: * format encodes a single-banded image of any bit depth between 1 and
036: * 32. The PPM format encodes three-banded images of any bit depth
037: * between 1 and 32. All formats have an ASCII and a raw
038: * representation.
039: *
040: * @since EA2
041: */
042: public final class PNMCodec extends ImageCodec {
043:
044: /** Constructs an instance of <code>PNMCodec</code>. */
045: public PNMCodec() {
046: }
047:
048: /** Returns the name of the format handled by this codec. */
049: public String getFormatName() {
050: return "pnm";
051: }
052:
053: public Class getEncodeParamClass() {
054: return com.sun.media.jai.codec.PNMEncodeParam.class;
055: }
056:
057: public Class getDecodeParamClass() {
058: return Object.class;
059: }
060:
061: public boolean canEncodeImage(RenderedImage im,
062: ImageEncodeParam param) {
063: SampleModel sampleModel = im.getSampleModel();
064:
065: int dataType = sampleModel.getTransferType();
066: if ((dataType == DataBuffer.TYPE_FLOAT)
067: || (dataType == DataBuffer.TYPE_DOUBLE)) {
068: return false;
069: }
070:
071: int numBands = sampleModel.getNumBands();
072: if (numBands != 1 && numBands != 3) {
073: return false;
074: }
075:
076: return true;
077: }
078:
079: /**
080: * Instantiates a <code>PNMImageEncoder</code> to write to the
081: * given <code>OutputStream</code>.
082: *
083: * @param dst the <code>OutputStream</code> to write to.
084: * @param param an instance of <code>PNMEncodeParam</code> used to
085: * control the encoding process, or <code>null</code>. A
086: * <code>ClassCastException</code> will be thrown if
087: * <code>param</code> is non-null but not an instance of
088: * <code>PNMEncodeParam</code>.
089: */
090: protected ImageEncoder createImageEncoder(OutputStream dst,
091: ImageEncodeParam param) {
092: PNMEncodeParam p = null;
093: if (param != null) {
094: p = (PNMEncodeParam) param; // May throw a ClassCast exception
095: }
096:
097: return new PNMImageEncoder(dst, p);
098: }
099:
100: /**
101: * Instantiates a <code>PNMImageDecoder</code> to read from the
102: * given <code>InputStream</code>.
103: *
104: * <p> By overriding this method, <code>PNMCodec</code> is able to
105: * ensure that a <code>ForwardSeekableStream</code> is used to
106: * wrap the source <code>InputStream</code> instead of the a
107: * general (and more expensive) subclass of
108: * <code>SeekableStream</code>. Since the PNM decoder does not
109: * require the ability to seek backwards in its input, this allows
110: * for greater efficiency.
111: *
112: * @param src the <code>InputStream</code> to read from.
113: * @param param an instance of <code>ImageDecodeParam</code> used to
114: * control the decoding process, or <code>null</code>.
115: * This parameter is ignored by this class.
116: */
117: protected ImageDecoder createImageDecoder(InputStream src,
118: ImageDecodeParam param) {
119: // Add buffering for efficiency
120: if (!(src instanceof BufferedInputStream)) {
121: src = new BufferedInputStream(src);
122: }
123: return new PNMImageDecoder(new ForwardSeekableStream(src), null);
124: }
125:
126: /**
127: * Instantiates a <code>PNMImageDecoder</code> to read from the
128: * given <code>SeekableStream</code>.
129: *
130: * @param src the <code>SeekableStream</code> to read from.
131: * @param param an instance of <code>ImageDecodeParam</code> used to
132: * control the decoding process, or <code>null</code>.
133: * This parameter is ignored by this class.
134: */
135: protected ImageDecoder createImageDecoder(SeekableStream src,
136: ImageDecodeParam param) {
137: return new PNMImageDecoder(src, null);
138: }
139:
140: /**
141: * Returns the number of bytes from the beginning of the data required
142: * to recognize it as being in PNM format.
143: */
144: public int getNumHeaderBytes() {
145: return 2;
146: }
147:
148: /**
149: * Returns <code>true</code> if the header bytes indicate PNM format.
150: *
151: * @param header an array of bytes containing the initial bytes of the
152: * input data. */
153: public boolean isFormatRecognized(byte[] header) {
154: return ((header[0] == 'P') && (header[1] >= '1') && (header[1] <= '6'));
155: }
156: }
|