jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java
changeset 2 90ce3da70b43
child 3012 1420628f14e4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.imageio.plugins.wbmp;
+
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+import javax.imageio.IIOException;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.sun.imageio.plugins.common.I18N;
+
+/** This class is the Java Image IO plugin reader for WBMP images.
+ *  It may subsample the image, clip the image,
+ *  and shift the decoded image origin if the proper decoding parameter
+ *  are set in the provided <code>WBMPImageReadParam</code>.
+ */
+public class WBMPImageReader extends ImageReader {
+    /** The input stream where reads from */
+    private ImageInputStream iis = null;
+
+    /** Indicates whether the header is read. */
+    private boolean gotHeader = false;
+
+    /** The original image width. */
+    private int width;
+
+    /** The original image height. */
+    private int height;
+
+    private int wbmpType;
+
+    private WBMPMetadata metadata;
+
+    /** Constructs <code>WBMPImageReader</code> from the provided
+     *  <code>ImageReaderSpi</code>.
+     */
+    public WBMPImageReader(ImageReaderSpi originator) {
+        super(originator);
+    }
+
+    /** Overrides the method defined in the superclass. */
+    public void setInput(Object input,
+                         boolean seekForwardOnly,
+                         boolean ignoreMetadata) {
+        super.setInput(input, seekForwardOnly, ignoreMetadata);
+        iis = (ImageInputStream) input; // Always works
+        gotHeader = false;
+    }
+
+    /** Overrides the method defined in the superclass. */
+    public int getNumImages(boolean allowSearch) throws IOException {
+        if (iis == null) {
+            throw new IllegalStateException(I18N.getString("GetNumImages0"));
+        }
+        if (seekForwardOnly && allowSearch) {
+            throw new IllegalStateException(I18N.getString("GetNumImages1"));
+        }
+        return 1;
+    }
+
+    public int getWidth(int imageIndex) throws IOException {
+        checkIndex(imageIndex);
+        readHeader();
+        return width;
+    }
+
+    public int getHeight(int imageIndex) throws IOException {
+        checkIndex(imageIndex);
+        readHeader();
+        return height;
+    }
+
+    public boolean isRandomAccessEasy(int imageIndex) throws IOException {
+        checkIndex(imageIndex);
+        return true;
+    }
+
+    private void checkIndex(int imageIndex) {
+        if (imageIndex != 0) {
+            throw new IndexOutOfBoundsException(I18N.getString("WBMPImageReader0"));
+        }
+    }
+
+    public void readHeader() throws IOException {
+        if (gotHeader)
+            return;
+
+        if (iis == null) {
+            throw new IllegalStateException("Input source not set!");
+        }
+
+        metadata = new WBMPMetadata();
+
+        wbmpType = iis.readByte();   // TypeField
+        byte fixHeaderField = iis.readByte();
+
+        // check for valid wbmp image
+        if (fixHeaderField != 0
+            || !isValidWbmpType(wbmpType))
+        {
+            throw new IIOException(I18N.getString("WBMPImageReader2"));
+        }
+
+        metadata.wbmpType = wbmpType;
+
+        // Read image width
+        width = readMultiByteInteger();
+        metadata.width = width;
+
+        // Read image height
+        height = readMultiByteInteger();
+        metadata.height = height;
+
+        gotHeader = true;
+    }
+
+    public Iterator getImageTypes(int imageIndex)
+        throws IOException {
+        checkIndex(imageIndex);
+        readHeader();
+
+        BufferedImage bi =
+            new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
+        ArrayList list = new ArrayList(1);
+        list.add(new ImageTypeSpecifier(bi));
+        return list.iterator();
+    }
+
+    public ImageReadParam getDefaultReadParam() {
+        return new ImageReadParam();
+    }
+
+    public IIOMetadata getImageMetadata(int imageIndex)
+        throws IOException {
+        checkIndex(imageIndex);
+        if (metadata == null) {
+            readHeader();
+        }
+        return metadata;
+    }
+
+    public IIOMetadata getStreamMetadata() throws IOException {
+        return null;
+    }
+
+    public BufferedImage read(int imageIndex, ImageReadParam param)
+        throws IOException {
+
+        if (iis == null) {
+            throw new IllegalStateException(I18N.getString("WBMPImageReader1"));
+        }
+
+        checkIndex(imageIndex);
+        clearAbortRequest();
+        processImageStarted(imageIndex);
+        if (param == null)
+            param = getDefaultReadParam();
+
+        //read header
+        readHeader();
+
+        Rectangle sourceRegion = new Rectangle(0, 0, 0, 0);
+        Rectangle destinationRegion = new Rectangle(0, 0, 0, 0);
+
+        computeRegions(param, this.width, this.height,
+                       param.getDestination(),
+                       sourceRegion,
+                       destinationRegion);
+
+        int scaleX = param.getSourceXSubsampling();
+        int scaleY = param.getSourceYSubsampling();
+        int xOffset = param.getSubsamplingXOffset();
+        int yOffset = param.getSubsamplingYOffset();
+
+        // If the destination is provided, then use it.  Otherwise, create new one
+        BufferedImage bi = param.getDestination();
+
+        if (bi == null)
+            bi = new BufferedImage(destinationRegion.x + destinationRegion.width,
+                              destinationRegion.y + destinationRegion.height,
+                              BufferedImage.TYPE_BYTE_BINARY);
+
+        boolean noTransform =
+            destinationRegion.equals(new Rectangle(0, 0, width, height)) &&
+            destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
+
+        // Get the image data.
+        WritableRaster tile = bi.getWritableTile(0, 0);
+
+        // Get the SampleModel.
+        MultiPixelPackedSampleModel sm =
+            (MultiPixelPackedSampleModel)bi.getSampleModel();
+
+        if (noTransform) {
+            if (abortRequested()) {
+                processReadAborted();
+                return bi;
+            }
+
+            // If noTransform is necessary, read the data.
+            iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
+                     0, height*sm.getScanlineStride());
+            processImageUpdate(bi,
+                               0, 0,
+                               width, height, 1, 1,
+                               new int[]{0});
+            processImageProgress(100.0F);
+        } else {
+            int len = (this.width + 7) / 8;
+            byte[] buf = new byte[len];
+            byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
+            int lineStride = sm.getScanlineStride();
+            iis.skipBytes(len * sourceRegion.y);
+            int skipLength = len * (scaleY - 1);
+
+            // cache the values to avoid duplicated computation
+            int[] srcOff = new int[destinationRegion.width];
+            int[] destOff = new int[destinationRegion.width];
+            int[] srcPos = new int[destinationRegion.width];
+            int[] destPos = new int[destinationRegion.width];
+
+            for (int i = destinationRegion.x, x = sourceRegion.x, j = 0;
+                i < destinationRegion.x + destinationRegion.width;
+                    i++, j++, x += scaleX) {
+                srcPos[j] = x >> 3;
+                srcOff[j] = 7 - (x & 7);
+                destPos[j] = i >> 3;
+                destOff[j] = 7 - (i & 7);
+            }
+
+            for (int j = 0, y = sourceRegion.y,
+                k = destinationRegion.y * lineStride;
+                j < destinationRegion.height; j++, y+=scaleY) {
+
+                if (abortRequested())
+                    break;
+                iis.read(buf, 0, len);
+                for (int i = 0; i < destinationRegion.width; i++) {
+                    //get the bit and assign to the data buffer of the raster
+                    int v = (buf[srcPos[i]] >> srcOff[i]) & 1;
+                    data[k + destPos[i]] |= v << destOff[i];
+                }
+
+                k += lineStride;
+                iis.skipBytes(skipLength);
+                        processImageUpdate(bi,
+                                           0, j,
+                                           destinationRegion.width, 1, 1, 1,
+                                           new int[]{0});
+                        processImageProgress(100.0F*j/destinationRegion.height);
+            }
+        }
+
+        if (abortRequested())
+            processReadAborted();
+        else
+            processImageComplete();
+        return bi;
+    }
+
+    public boolean canReadRaster() {
+        return true;
+    }
+
+    public Raster readRaster(int imageIndex,
+                             ImageReadParam param) throws IOException {
+        BufferedImage bi = read(imageIndex, param);
+        return bi.getData();
+    }
+
+    public void reset() {
+        super.reset();
+        iis = null;
+        gotHeader = false;
+    }
+
+    private int readMultiByteInteger() throws IOException {
+        int value = iis.readByte();
+        int result = value & 0x7f;
+        while((value & 0x80) == 0x80) {
+            result <<= 7;
+            value = iis.readByte();
+            result |= (value & 0x7f);
+        }
+        return result;
+    }
+
+    /*
+     * This method verifies that given byte is valid wbmp type marker.
+     * At the moment only 0x0 marker is described by wbmp spec.
+     */
+    boolean isValidWbmpType(int type) {
+        return type == 0;
+    }
+}