001/*
002 * $RCSfile: RawImageReader.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.1 $
042 * $Date: 2005/02/11 05:01:42 $
043 * $State: Exp $
044 */
045package com.github.jaiimageio.impl.plugins.raw;
046
047import java.awt.Point;
048import java.awt.Rectangle;
049import java.awt.Transparency;
050import java.awt.color.ColorSpace;
051import java.awt.image.BufferedImage;
052import java.awt.image.ColorModel;
053import java.awt.image.ComponentColorModel;
054import java.awt.image.ComponentSampleModel;
055import java.awt.image.DataBuffer;
056import java.awt.image.DataBufferByte;
057import java.awt.image.DataBufferInt;
058import java.awt.image.DataBufferUShort;
059import java.awt.image.IndexColorModel;
060import java.awt.image.MultiPixelPackedSampleModel;
061import java.awt.image.PixelInterleavedSampleModel;
062import java.awt.image.Raster;
063import java.awt.image.RenderedImage;
064import java.awt.image.SampleModel;
065import java.awt.image.WritableRaster;
066
067import javax.imageio.IIOException;
068import javax.imageio.ImageReader;
069import javax.imageio.ImageReadParam;
070import javax.imageio.ImageTypeSpecifier;
071import javax.imageio.metadata.IIOMetadata;
072import javax.imageio.spi.ImageReaderSpi;
073import javax.imageio.stream.ImageInputStream;
074
075import java.io.*;
076import java.util.ArrayList;
077import java.util.Hashtable;
078import java.util.Iterator;
079import java.util.StringTokenizer;
080
081import com.github.jaiimageio.stream.RawImageInputStream;
082
083/** This class is the Java Image IO plugin reader for Raw images.
084 *  It may subsample the image, clip the image, select sub-bands,
085 *  and shift the decoded image origin if the proper decoding parameter
086 *  are set in the provided <code>PNMImageReadParam</code>.
087 */
088public class RawImageReader extends ImageReader {
089    /** The input stream where reads from */
090    private RawImageInputStream iis = null;
091
092    /** Wrapper for the protected method <code>computeRegions</code>.  So it
093     *  can be access from the classes which are not in <code>ImageReader</code>
094     *  hierachy.
095     */
096    public static void computeRegionsWrapper(ImageReadParam param,
097                                      int srcWidth,
098                                      int srcHeight,
099                                      BufferedImage image,
100                                      Rectangle srcRegion,
101                                      Rectangle destRegion) {
102        computeRegions(param, srcWidth, srcHeight,
103                       image, srcRegion, destRegion) ;
104    }
105
106    /** Constructs <code>RawImageReader</code> from the provided
107     *  <code>ImageReaderSpi</code>.
108     */
109    public RawImageReader(ImageReaderSpi originator) {
110        super(originator);
111    }
112
113    /** Overrides the method defined in the superclass.
114     *  @throw ClassCastException If the provided <code>input</code> is not
115     *          an instance of <code>RawImageInputImage</code>
116     */
117    public void setInput(Object input,
118                         boolean seekForwardOnly,
119                         boolean ignoreMetadata) {
120        super.setInput(input, seekForwardOnly, ignoreMetadata);
121        iis = (RawImageInputStream) input; // Always works
122    }
123
124    /** Overrides the method defined in the superclass. */
125    public int getNumImages(boolean allowSearch) throws IOException {
126        return iis.getNumImages();
127    }
128
129    public int getWidth(int imageIndex) throws IOException {
130        checkIndex(imageIndex);
131        return iis.getImageDimension(imageIndex).width;
132    }
133
134    public int getHeight(int imageIndex) throws IOException {
135        checkIndex(imageIndex);
136
137        return iis.getImageDimension(imageIndex).height;
138    }
139
140    public int getTileWidth(int imageIndex) throws IOException {
141        checkIndex(imageIndex);
142        return iis.getImageType().getSampleModel().getWidth();
143    }
144
145    public int getTileHeight(int imageIndex) throws IOException {
146        checkIndex(imageIndex);
147        return iis.getImageType().getSampleModel().getHeight();
148    }
149
150    private void checkIndex(int imageIndex) throws IOException {
151        if (imageIndex <0 || imageIndex >= getNumImages(true)) {
152            throw new IndexOutOfBoundsException(I18N.getString("RawImageReader0"));
153        }
154    }
155
156    public Iterator getImageTypes(int imageIndex)
157        throws IOException {
158        checkIndex(imageIndex);
159        ArrayList list = new ArrayList(1);
160        list.add(iis.getImageType());
161        return list.iterator();
162    }
163
164    public ImageReadParam getDefaultReadParam() {
165        return new ImageReadParam();
166    }
167
168    public IIOMetadata getImageMetadata(int imageIndex)
169        throws IOException {
170        return null;
171    }
172
173    public IIOMetadata getStreamMetadata() throws IOException {
174        return null;
175    }
176
177    public boolean isRandomAccessEasy(int imageIndex) throws IOException {
178        checkIndex(imageIndex);
179        return true;
180    }
181
182    public BufferedImage read(int imageIndex, ImageReadParam param)
183        throws IOException {
184        if (param == null)
185            param = getDefaultReadParam();
186        checkIndex(imageIndex);
187        clearAbortRequest();
188        processImageStarted(imageIndex);
189
190        BufferedImage bi = param.getDestination();
191        RawRenderedImage image =
192            new RawRenderedImage(iis, this,  param, imageIndex);
193        Point offset = param.getDestinationOffset();
194        WritableRaster raster;
195
196        if (bi == null) {
197            ColorModel colorModel = image.getColorModel();
198            SampleModel sampleModel = image.getSampleModel();
199
200            // If the destination type is specified, use the color model of it.
201            ImageTypeSpecifier type = param.getDestinationType();
202            if (type != null)
203                colorModel = type.getColorModel();
204
205            raster = Raster.createWritableRaster(
206                sampleModel.createCompatibleSampleModel(image.getMinX()+
207                                                        image.getWidth(),
208                                                        image.getMinY() +
209                                                        image.getHeight()),
210                new Point(0, 0));
211
212            bi = new BufferedImage(colorModel,
213                                   raster,
214                                   colorModel != null ?
215                                   colorModel.isAlphaPremultiplied() : false,
216                                   new Hashtable());
217        } else {
218            raster = bi.getWritableTile(0, 0);
219        }
220
221        image.setDestImage(bi);
222
223        image.readAsRaster(raster);
224        image.clearDestImage();
225
226        if (abortRequested())
227            processReadAborted();
228        else
229            processImageComplete();
230        return bi;
231    }
232
233    public RenderedImage readAsRenderedImage(int imageIndex,
234                                            ImageReadParam param)
235                                            throws java.io.IOException {
236        if (param == null)
237            param = getDefaultReadParam();
238
239        checkIndex(imageIndex);
240        clearAbortRequest();
241        processImageStarted(0);
242
243        RenderedImage image =
244            new RawRenderedImage(iis, this, param, imageIndex);
245
246        if (abortRequested())
247            processReadAborted();
248        else
249            processImageComplete();
250        return image;
251    }
252
253    public Raster readRaster(int imageIndex,
254                             ImageReadParam param) throws IOException {
255        BufferedImage bi = read(imageIndex, param);
256        return bi.getData();
257    }
258
259    public boolean canReadRaster() {
260        return true;
261    }
262
263    public void reset() {
264        super.reset();
265        iis = null;
266    }
267
268    /** Wrapper for the protected method <code>processImageUpdate</code>
269     *  So it can be access from the classes which are not in
270     *  <code>ImageReader</code> hierachy.
271     */
272    public void processImageUpdateWrapper(BufferedImage theImage,
273                                      int minX, int minY,
274                                      int width, int height,
275                                      int periodX, int periodY,
276                                      int[] bands) {
277        processImageUpdate(theImage,
278                                  minX, minY,
279                                  width, height,
280                                  periodX, periodY,
281                                  bands);
282    }
283
284    /** Wrapper for the protected method <code>processImageProgress</code>
285     *  So it can be access from the classes which are not in
286     *  <code>ImageReader</code> hierachy.
287     */
288    public void processImageProgressWrapper(float percentageDone) {
289        processImageProgress(percentageDone);
290    }
291
292    /** This method wraps the protected method <code>abortRequested</code>
293     *  to allow the abortions be monitored by <code>J2KReadState</code>.
294     */
295    public boolean getAbortRequest() {
296        return abortRequested();
297    }
298}