001: /*
002: * $RCSfile: TIFFJPEGDecompressor.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.2 $
042: * $Date: 2006/04/11 22:10:36 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.tiff;
046:
047: import java.io.IOException;
048: import java.io.ByteArrayInputStream;
049: import java.util.Iterator;
050: import javax.imageio.ImageIO;
051: import javax.imageio.ImageReader;
052: import javax.imageio.ImageReadParam;
053: import javax.imageio.stream.MemoryCacheImageInputStream;
054: import javax.imageio.stream.ImageInputStream;
055: import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
056: import com.sun.media.imageio.plugins.tiff.TIFFDecompressor;
057: import com.sun.media.imageio.plugins.tiff.TIFFField;
058:
059: public class TIFFJPEGDecompressor extends TIFFDecompressor {
060: private static final boolean DEBUG = false; // XXX false for release.
061:
062: // Start of Image
063: protected static final int SOI = 0xD8;
064:
065: // End of Image
066: protected static final int EOI = 0xD9;
067:
068: //private static ImageReaderSpi jpegReaderSPI = null;//XXX
069:
070: protected ImageReader JPEGReader = null;
071: protected ImageReadParam JPEGParam;
072:
073: protected boolean hasJPEGTables = false;
074: protected byte[] tables = null;
075:
076: private byte[] data = new byte[0];
077:
078: /* XXX
079: static {
080: try {
081: IIORegistry registry = IIORegistry.getDefaultInstance();
082: Class imageReaderClass =
083: Class.forName("javax.imageio.spi.ImageReaderSpi");
084: Iterator readerSPIs =
085: registry.getServiceProviders(imageReaderClass,
086: new JPEGSPIFilter(),
087: true);
088: if(readerSPIs.hasNext()) {
089: jpegReaderSPI = (ImageReaderSpi)readerSPIs.next();
090: }
091: } catch(Exception e) {
092: // Ignore it ...
093: }
094: }
095: */
096:
097: public TIFFJPEGDecompressor() {
098: }
099:
100: /* XXX
101: private static class JPEGSPIFilter implements ServiceRegistry.Filter {
102: JPEGSPIFilter() {}
103:
104: public boolean filter(Object provider) {
105: ImageReaderSpi readerSPI = (ImageReaderSpi)provider;
106:
107: if(readerSPI.getPluginClassName().startsWith("com.sun.imageio")) {
108: String streamMetadataName =
109: readerSPI.getNativeStreamMetadataFormatName();
110: if(streamMetadataName != null) {
111: return streamMetadataName.indexOf("jpeg_stream") != -1;
112: } else {
113: return false;
114: }
115: }
116:
117: return false;
118: }
119: }
120: */
121:
122: public void beginDecoding() {
123: // Initialize the JPEG reader if needed.
124: if (this .JPEGReader == null) {
125: if (DEBUG)
126: System.out.println("Initializing JPEGReader");
127:
128: /* XXX
129: if(this.jpegReaderSPI != null) {
130: try {
131: this.JPEGReader = jpegReaderSPI.createReaderInstance();
132: } catch(Exception e) {
133: }
134: }
135:
136: if(this.JPEGReader == null) {
137: */
138:
139: // Get all JPEG readers.
140: Iterator iter = ImageIO.getImageReadersByFormatName("jpeg");
141:
142: if (!iter.hasNext()) {
143: // XXX The exception thrown should be an IIOException.
144: throw new IllegalStateException(
145: "No JPEG readers found!");
146: }
147:
148: // Initialize reader to the first one.
149: this .JPEGReader = (ImageReader) iter.next();
150:
151: if (DEBUG)
152: System.out.println("Using "
153: + JPEGReader.getClass().getName());
154:
155: this .JPEGParam = JPEGReader.getDefaultReadParam();
156: }
157:
158: // Get the JPEGTables field.
159: TIFFImageMetadata tmetadata = (TIFFImageMetadata) metadata;
160: TIFFField f = tmetadata
161: .getTIFFField(BaselineTIFFTagSet.TAG_JPEG_TABLES);
162:
163: if (f != null) {
164: this .hasJPEGTables = true;
165: this .tables = f.getAsBytes();
166: } else {
167: this .hasJPEGTables = false;
168: }
169: }
170:
171: public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel,
172: int scanlineStride) throws IOException {
173: // Seek to the data position for this segment.
174: stream.seek(offset);
175:
176: // Set the stream variable depending on presence of JPEGTables.
177: ImageInputStream is;
178: if (this .hasJPEGTables) {
179: if (DEBUG)
180: System.out.println("Reading abbreviated stream.");
181: // The current strip or tile is an abbreviated JPEG stream.
182:
183: // Reallocate memory if there is not enough already.
184: int dataLength = tables.length + byteCount;
185: if (data.length < dataLength) {
186: data = new byte[dataLength];
187: }
188:
189: // Copy the tables ignoring any EOI and subsequent bytes.
190: int dataOffset = tables.length;
191: for (int i = tables.length - 2; i > 0; i--) {
192: if ((tables[i] & 0xff) == 0xff
193: && (tables[i + 1] & 0xff) == EOI) {
194: dataOffset = i;
195: break;
196: }
197: }
198: System.arraycopy(tables, 0, data, 0, dataOffset);
199:
200: // Check for SOI and skip it if present.
201: byte byte1 = (byte) stream.read();
202: byte byte2 = (byte) stream.read();
203: if (!((byte1 & 0xff) == 0xff && (byte2 & 0xff) == SOI)) {
204: data[dataOffset++] = (byte) byte1;
205: data[dataOffset++] = (byte) byte2;
206: }
207:
208: // Read remaining data.
209: stream.readFully(data, dataOffset, byteCount - 2);
210:
211: // Create ImageInputStream.
212: ByteArrayInputStream bais = new ByteArrayInputStream(data);
213: is = new MemoryCacheImageInputStream(bais);
214: } else {
215: if (DEBUG)
216: System.out.println("Reading complete stream.");
217: // The current strip or tile is a complete JPEG stream.
218: is = stream;
219: }
220:
221: // Set the stream on the reader.
222: JPEGReader.setInput(is, false, true);
223:
224: // Set the destination to the raw image ignoring the parameters.
225: JPEGParam.setDestination(rawImage);
226:
227: // Read the strip or tile.
228: JPEGReader.read(0, JPEGParam);
229: }
230:
231: protected void finalize() throws Throwable {
232: super.finalize();
233: JPEGReader.dispose();
234: }
235: }
|