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