322 lines · 10.5 KB · Java
RawDownload
/* * Copyright (c) 2003, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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;import com.sun.imageio.plugins.common.ReaderUtil; /** 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 = ReaderUtil.readMultiByteInteger(iis);        metadata.width = width;         // Read image height        height = ReaderUtil.readMultiByteInteger(iis);        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;    }     /*     * 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;    }}