1 /*
2  * $RCSfile: JPEGTileDecoder.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.1 $
9  * $Date: 2005/02/11 04:56:57 $
10  * $State: Exp $
11  */package com.lightcrafts.media.jai.tilecodec;
12 
13 import java.awt.Point;
14 import java.awt.RenderingHints;
15 import java.awt.image.Raster;
16 import java.awt.image.WritableRaster;
17 import java.awt.image.SampleModel;
18 import java.io.InputStream;
19 import java.io.ObjectInputStream;
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import com.lightcrafts.mediax.jai.ParameterListDescriptor;
23 import com.lightcrafts.mediax.jai.RasterFactory;
24 import com.lightcrafts.mediax.jai.tilecodec.TileCodecDescriptor;
25 import com.lightcrafts.mediax.jai.tilecodec.TileCodecParameterList;
26 import com.lightcrafts.mediax.jai.tilecodec.TileDecoderImpl;
27 import com.lightcrafts.mediax.jai.util.ImagingListener;
28 import com.sun.image.codec.jpeg.JPEGDecodeParam;
29 import com.sun.image.codec.jpeg.JPEGImageDecoder;
30 import com.sun.image.codec.jpeg.JPEGCodec;
31 import com.sun.image.codec.jpeg.JPEGQTable;
32 import com.lightcrafts.media.jai.util.ImageUtil;
33 /**
34  * A concrete implementation of the <code>TileDecoderImpl</code> class
35  * for the jpeg tile codec.
36  */
37 public class JPEGTileDecoder extends TileDecoderImpl {
38     /* The associated TileCodecDescriptor */
39     private TileCodecDescriptor tcd = null;
40 
41     /**
42      * Constructs a <code>JPEGTileDecoder</code>.
43      * <code>JPEGTileDecoder</code> may throw a
44      * <code>IllegalArgumentException</code> if <code>param</code>'s
45      * <code>getParameterListDescriptor()</code> method does not return
46      * the same descriptor as that from the associated
47      * <code>TileCodecDescriptor</code>'s
48      * <code>getParameterListDescriptor</code> method for the "tileDecoder"
49      * registry mode.
50      *
51      * <p> If param is null, then the default parameter list for decoding
52      * as defined by the associated <code>TileCodecDescriptor</code>'s
53      * <code>getDefaultParameters()</code> method will be used for decoding.
54      *
55      * @param input The <code>InputStream</code> to decode data from.
56      * @param param  The object containing the tile decoding parameters.
57      * @throws IllegalArgumentException if input is null.
58      * @throws IllegalArgumentException if param is not appropriate.
59      */
JPEGTileDecoder(InputStream input, TileCodecParameterList param)60     public JPEGTileDecoder(InputStream input, TileCodecParameterList param) {
61 	super("jpeg", input, param);
62         tcd = TileCodecUtils.getTileCodecDescriptor("tileDecoder", "jpeg");
63     }
64 
65     /**
66      * Returns a <code>Raster</code> that contains the decoded contents
67      * of the <code>InputStream</code> associated with this
68      * <code>TileDecoder</code>.
69      *
70      * <p>This method can perform the decoding correctly only when
71      * <code>includesLocationInfoInfo()</code> returns true.
72      *
73      * @throws IOException if an I/O error occurs while reading from the
74      * associated InputStream.
75      * @throws IllegalArgumentException if the associated
76      * TileCodecDescriptor's includesLocationInfoInfo() returns false.
77      */
decode()78     public Raster decode() throws IOException{
79 	if (!tcd.includesLocationInfo())
80 	    throw new IllegalArgumentException(
81 		JaiI18N.getString("JPEGTileDecoder0") );
82 	return decode(null);
83     }
84 
decode(Point location)85     public Raster decode(Point location) throws IOException{
86 	SampleModel sm = null;
87 	byte[] data = null;
88 
89         ObjectInputStream ois = new ObjectInputStream(inputStream);
90 
91         try {
92 	    // read the quality and qualitySet from the stream
93 	    paramList.setParameter("quality", ois.readFloat());
94 	    paramList.setParameter("qualitySet", ois.readBoolean());
95             sm = TileCodecUtils.deserializeSampleModel(ois.readObject());
96 	    location = (Point)ois.readObject();
97             data = (byte[]) ois.readObject();
98         }
99         catch (ClassNotFoundException e) {
100             ImagingListener listener =
101                 ImageUtil.getImagingListener((RenderingHints)null);
102             listener.errorOccurred(JaiI18N.getString("ClassNotFound"),
103                                    e, this, false);
104 //            e.printStackTrace();
105 	    return null;
106         }
107 	finally {
108             ois.close();
109 	}
110 
111 	ByteArrayInputStream bais = new ByteArrayInputStream(data);
112         JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(bais);
113 
114         Raster ras = decoder.decodeAsRaster()
115 			.createTranslatedChild(location.x, location.y);
116 	extractParameters(decoder.getJPEGDecodeParam(),
117 			  ras.getSampleModel().getNumBands());
118 
119 	// set the original sample model to the decoded raster
120 	if (sm != null) {
121 	    int minX = ras.getMinX();
122 	    int minY = ras.getMinY();
123 	    int h = ras.getHeight();
124 	    int w = ras.getWidth();
125 	    double[] buf = ras.getPixels(minX, minY, w, h, (double[])null);
126 	    ras = RasterFactory.createWritableRaster(sm,
127 						     new Point(minX, minY));
128 	    ((WritableRaster)ras).setPixels(minX, minY, w, h, buf);
129 	}
130 	return ras;
131     }
132 
extractParameters(JPEGDecodeParam jdp, int bandNum)133     private void extractParameters(JPEGDecodeParam jdp, int bandNum) {
134 
135 	// extract the horizontal subsampling rates
136 	int[] horizontalSubsampling = new int[bandNum];
137 	for (int i = 0; i < bandNum; i++)
138 	    horizontalSubsampling[i] = jdp.getHorizontalSubsampling(i);
139 	paramList.setParameter("horizontalSubsampling", horizontalSubsampling);
140 
141 	// extract the vertical subsampling rates
142 	int[] verticalSubsampling = new int[bandNum];
143 	for (int i = 0; i < bandNum; i++)
144 	    verticalSubsampling[i] = jdp.getVerticalSubsampling(i);
145 	paramList.setParameter("verticalSubsampling", verticalSubsampling);
146 
147 	// if the quality is not set, extract the quantization tables from
148 	// the stream; otherwise, define them with the default values.
149 	if (!paramList.getBooleanParameter("qualitySet"))
150 	    for (int i = 0; i < 4; i++) {
151 		JPEGQTable table = jdp.getQTable(i);
152 		paramList.setParameter("quantizationTable"+i,
153 		    (table == null) ? null : table.getTable());
154 	    }
155 	else {
156 	    ParameterListDescriptor pld
157 		= paramList.getParameterListDescriptor();
158 	    for (int i = 0; i < 4; i++) {
159 		paramList.setParameter("quantizationTable"+i,
160 		    pld.getParamDefaultValue("quantizationTable"+i));
161 	    }
162 	}
163 
164 	// extract the quantizationTableMapping
165 	int[] quanTableMapping = new int[bandNum];
166 	for (int i = 0; i < bandNum; i++)
167 	    quanTableMapping[i] = jdp.getQTableComponentMapping(i);
168 	paramList.setParameter("quantizationTableMapping", quanTableMapping);
169 
170 	// extract the writeTableInfo and writeImageInfo
171 	paramList.setParameter("writeTableInfo", jdp.isTableInfoValid());
172 	paramList.setParameter("writeImageInfo", jdp.isImageInfoValid());
173 
174 	// extract the restart interval
175 	paramList.setParameter("restartInterval", jdp.getRestartInterval());
176 
177 	// define writeJFIFHeader by examing the APP0_MARKER is set or not
178 	paramList.setParameter("writeJFIFHeader",
179 			       jdp.getMarker(JPEGDecodeParam.APP0_MARKER));
180     }
181 }
182 
183