1396 lines · 55.4 KB · Java
RawDownload
/* * Copyright (c) 1997, 2007, 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 sun.awt.image;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.awt.image.RasterFormatException;import java.awt.image.SampleModel;import java.awt.image.MultiPixelPackedSampleModel;import java.awt.image.DataBuffer;import java.awt.image.DataBufferByte;import java.awt.Rectangle;import java.awt.Point; /** * This class is useful for describing 1, 2, or 4 bit image data * elements.  This raster has one band whose pixels are packed * together into individual bytes in a single byte array.  This type * of raster can be used with an IndexColorModel. This raster uses a * MultiPixelPackedSampleModel. * */public class BytePackedRaster extends SunWritableRaster {     /** The data bit offset for each pixel. */    int           dataBitOffset;     /** Scanline stride of the image data contained in this Raster. */    int           scanlineStride;     /**     * The bit stride of a pixel, equal to the total number of bits     * required to store a pixel.     */    int           pixelBitStride;     /** The bit mask for extracting the pixel. */    int           bitMask;     /** The image data array. */    byte[]        data;     /** 8 minus the pixel bit stride. */    int shiftOffset;     int type;     /** A cached copy of minX + width for use in bounds checks. */    private int maxX;     /** A cached copy of minY + height for use in bounds checks. */    private int maxY;     static private native void initIDs();    static {        /* ensure that the necessary native libraries are loaded */        NativeLibLoader.loadLibraries();        initIDs();    }     /**     * Constructs a BytePackedRaster with the given SampleModel.     * The Raster's upper left corner is origin and it is the same     * size as the SampleModel.  A DataBuffer large enough to describe the     * Raster is automatically created.  SampleModel must be of type     * MultiPixelPackedSampleModel.     * @param sampleModel     The SampleModel that specifies the layout.     * @param origin          The Point that specified the origin.     */    public BytePackedRaster(SampleModel sampleModel,                            Point origin) {        this(sampleModel,             sampleModel.createDataBuffer(),             new Rectangle(origin.x,                           origin.y,                           sampleModel.getWidth(),                           sampleModel.getHeight()),             origin,             null);    }     /**     * Constructs a BytePackedRaster with the given SampleModel     * and DataBuffer.  The Raster's upper left corner is origin and     * it is the same size as the SampleModel.  The DataBuffer is not     * initialized and must be a DataBufferByte compatible with SampleModel.     * SampleModel must be of type MultiPixelPackedSampleModel.     * @param sampleModel     The SampleModel that specifies the layout.     * @param dataBuffer      The DataBufferShort that contains the image data.     * @param origin          The Point that specifies the origin.     */    public BytePackedRaster(SampleModel sampleModel,                            DataBuffer dataBuffer,                            Point origin) {        this(sampleModel,             dataBuffer,             new Rectangle(origin.x,                           origin.y,                           sampleModel.getWidth(),                           sampleModel.getHeight()),             origin,             null);    }     /**     * Constructs a BytePackedRaster with the given SampleModel,     * DataBuffer, and parent.  DataBuffer must be a DataBufferByte and     * SampleModel must be of type MultiPixelPackedSampleModel.     * When translated into the base Raster's     * coordinate system, aRegion must be contained by the base Raster.     * Origin is the coordinate in the new Raster's coordinate system of     * the origin of the base Raster.  (The base Raster is the Raster's     * ancestor which has no parent.)     *     * Note that this constructor should generally be called by other     * constructors or create methods, it should not be used directly.     * @param sampleModel     The SampleModel that specifies the layout.     * @param dataBuffer      The DataBufferShort that contains the image data.     * @param aRegion         The Rectangle that specifies the image area.     * @param origin          The Point that specifies the origin.     * @param parent          The parent (if any) of this raster.     *     * @exception RasterFormatException if the parameters do not conform     * to requirements of this Raster type.     */    public BytePackedRaster(SampleModel sampleModel,                            DataBuffer dataBuffer,                            Rectangle aRegion,                            Point origin,                            BytePackedRaster parent){        super(sampleModel,dataBuffer,aRegion,origin, parent);        this.maxX = minX + width;        this.maxY = minY + height;         if (!(dataBuffer instanceof DataBufferByte)) {           throw new RasterFormatException("BytePackedRasters must have" +                "byte DataBuffers");        }        DataBufferByte dbb = (DataBufferByte)dataBuffer;        this.data = stealData(dbb, 0);        if (dbb.getNumBanks() != 1) {            throw new                RasterFormatException("DataBuffer for BytePackedRasters"+                                      " must only have 1 bank.");        }        int dbOffset = dbb.getOffset();         if (sampleModel instanceof MultiPixelPackedSampleModel) {            MultiPixelPackedSampleModel mppsm =                (MultiPixelPackedSampleModel)sampleModel;            this.type = IntegerComponentRaster.TYPE_BYTE_BINARY_SAMPLES;            pixelBitStride = mppsm.getPixelBitStride();            if (pixelBitStride != 1 &&                pixelBitStride != 2 &&                pixelBitStride != 4) {                throw new RasterFormatException                  ("BytePackedRasters must have a bit depth of 1, 2, or 4");            }            scanlineStride = mppsm.getScanlineStride();            dataBitOffset = mppsm.getDataBitOffset() + dbOffset*8;            int xOffset = aRegion.x - origin.x;            int yOffset = aRegion.y - origin.y;            dataBitOffset += xOffset*pixelBitStride + yOffset*scanlineStride*8;            bitMask = (1 << pixelBitStride) -1;            shiftOffset = 8 - pixelBitStride;        } else {            throw new RasterFormatException("BytePackedRasters must have"+                "MultiPixelPackedSampleModel");        }        verify(false);    }     /**     * Returns the data bit offset for the Raster.  The data     * bit offset is the bit index into the data array element     * corresponding to the first sample of the first scanline.     */    public int getDataBitOffset() {        return dataBitOffset;    }     /**     * Returns the scanline stride -- the number of data array elements between     * a given sample and the sample in the same column     * of the next row.     */    public int getScanlineStride() {        return scanlineStride;    }     /**     * Returns pixel bit stride -- the number of bits between two     * samples on the same scanline.     */    public int getPixelBitStride() {        return pixelBitStride;    }     /**     * Returns a reference to the entire data array.     */    public byte[] getDataStorage() {        return data;    }     /**     * Returns the data element at the specified     * location.     * An ArrayIndexOutOfBounds exception will be thrown at runtime     * if the pixel coordinate is out of bounds.     * A ClassCastException will be thrown if the input object is non null     * and references anything other than an array of transferType.     * @param x        The X coordinate of the pixel location.     * @param y        The Y coordinate of the pixel location.     * @param outData  An object reference to an array of type defined by     *                 getTransferType() and length getNumDataElements().     *                 If null an array of appropriate type and size will be     *                 allocated.     * @return         An object reference to an array of type defined by     *                 getTransferType() with the request pixel data.     */    public Object getDataElements(int x, int y, Object obj) {        if ((x < this.minX) || (y < this.minY) ||            (x >= this.maxX) || (y >= this.maxY)) {            throw new ArrayIndexOutOfBoundsException                ("Coordinate out of bounds!");        }        byte outData[];        if (obj == null) {            outData = new byte[numDataElements];        } else {            outData = (byte[])obj;        }        int bitnum = dataBitOffset + (x-minX) * pixelBitStride;        // Fix 4184283        int element = data[(y-minY) * scanlineStride + (bitnum >> 3)] & 0xff;        int shift = shiftOffset - (bitnum & 7);        outData[0] = (byte)((element >> shift) & bitMask);        return outData;    }     /**     * Returns the pixel data for the specified rectangle of pixels in a     * primitive array of type TransferType.     * For image data supported by the Java 2D API, this     * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or     * DataBuffer.TYPE_INT.  Data may be returned in a packed format,     * thus increasing efficiency for data transfers.     *     * An ArrayIndexOutOfBoundsException may be thrown     * if the coordinates are not in bounds.     * A ClassCastException will be thrown if the input object is non null     * and references anything other than an array of TransferType.     * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, Object, DataBuffer)     * @param x        The X coordinate of the upper left pixel location.     * @param y        The Y coordinate of the upper left pixel location.     * @param w        Width of the pixel rectangle.     * @param h        Height of the pixel rectangle.     * @param outData  An object reference to an array of type defined by     *                 getTransferType() and length w*h*getNumDataElements().     *                 If null, an array of appropriate type and size will be     *                 allocated.     * @return         An object reference to an array of type defined by     *                 getTransferType() with the requested pixel data.     */    public Object getDataElements(int x, int y, int w, int h,                                  Object outData) {        return getByteData(x, y, w, h, (byte[])outData);    }     /**     * Returns an array  of data elements from the specified rectangular     * region.     *     * An ArrayIndexOutOfBounds exception will be thrown at runtime     * if the pixel coordinates are out of bounds.     * A ClassCastException will be thrown if the input object is non null     * and references anything other than an array of transferType.     * <pre>     *       byte[] bandData = (byte[])raster.getPixelData(x, y, w, h, null);     *       int pixel;     *       // To find a data element at location (x2, y2)     *       pixel = bandData[((y2-y)*w + (x2-x))];     * </pre>     * @param x        The X coordinate of the upper left pixel location.     * @param y        The Y coordinate of the upper left pixel location.     * @param width    Width of the pixel rectangle.     * @param height   Height of the pixel rectangle.     * @param outData  An object reference to an array of type defined by     *                 getTransferType() and length w*h*getNumDataElements().     *                 If null an array of appropriate type and size will be     *                 allocated.     * @return         An object reference to an array of type defined by     *                 getTransferType() with the request pixel data.     */    public Object getPixelData(int x, int y, int w, int h, Object obj) {        if ((x < this.minX) || (y < this.minY) ||            (x + w > this.maxX) || (y + h > this.maxY)) {            throw new ArrayIndexOutOfBoundsException                ("Coordinate out of bounds!");        }        byte outData[];        if (obj == null) {            outData = new byte[numDataElements*w*h];        } else {            outData = (byte[])obj;        }        int pixbits = pixelBitStride;        int scanbit = dataBitOffset + (x-minX) * pixbits;        int index = (y-minY) * scanlineStride;        int outindex = 0;        byte data[] = this.data;         for (int j = 0; j < h; j++) {            int bitnum = scanbit;            for (int i = 0; i < w; i++) {                int shift = shiftOffset - (bitnum & 7);                outData[outindex++] =                    (byte)(bitMask & (data[index + (bitnum >> 3)] >> shift));                bitnum += pixbits;            }            index += scanlineStride;        }        return outData;    }     /**     * Returns a byte array containing the specified data elements     * from the data array.  The band index will be ignored.     * An ArrayIndexOutOfBounds exception will be thrown at runtime     * if the pixel coordinates are out of bounds.     * <pre>     *       byte[] byteData = getByteData(x, y, band, w, h, null);     *       // To find a data element at location (x2, y2)     *       byte element = byteData[(y2-y)*w + (x2-x)];     * </pre>     * @param x        The X coordinate of the upper left pixel location.     * @param y        The Y coordinate of the upper left pixel location.     * @param width    Width of the pixel rectangle.     * @param height   Height of the pixel rectangle.     * @param band     The band to return, is ignored.     * @param outData  If non-null, data elements     *                 at the specified locations are returned in this array.     * @return         Byte array with data elements.     */    public byte[] getByteData(int x, int y, int w, int h,                              int band, byte[] outData) {        return getByteData(x, y, w, h, outData);    }     /**     * Returns a byte array containing the specified data elements     * from the data array.     * An ArrayIndexOutOfBounds exception will be thrown at runtime     * if the pixel coordinates are out of bounds.     * <pre>     *       byte[] byteData = raster.getByteData(x, y, w, h, null);     *       byte pixel;     *       // To find a data element at location (x2, y2)     *       pixel = byteData[((y2-y)*w + (x2-x))];     * </pre>     * @param x        The X coordinate of the upper left pixel location.     * @param y        The Y coordinate of the upper left pixel location.     * @param width    Width of the pixel rectangle.     * @param height   Height of the pixel rectangle.     * @param outData  If non-null, data elements     *                 at the specified locations are returned in this array.     * @return         Byte array with data elements.     */    public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {        if ((x < this.minX) || (y < this.minY) ||            (x + w > this.maxX) || (y + h > this.maxY)) {            throw new ArrayIndexOutOfBoundsException                ("Coordinate out of bounds!");        }        if (outData == null) {            outData = new byte[w * h];        }        int pixbits = pixelBitStride;        int scanbit = dataBitOffset + (x-minX) * pixbits;        int index = (y-minY) * scanlineStride;        int outindex = 0;        byte data[] = this.data;         for (int j = 0; j < h; j++) {            int bitnum = scanbit;            int element;             // Process initial portion of scanline            int i = 0;            while ((i < w) && ((bitnum & 7) != 0)) {                int shift = shiftOffset - (bitnum & 7);                outData[outindex++] =                    (byte)(bitMask & (data[index + (bitnum >> 3)] >> shift));                bitnum += pixbits;                i++;            }             // Process central portion of scanline 8 pixels at a time            int inIndex = index + (bitnum >> 3);            switch (pixbits) {            case 1:                for (; i < w - 7; i += 8) {                    element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 7) & 1);                    outData[outindex++] = (byte)((element >> 6) & 1);                    outData[outindex++] = (byte)((element >> 5) & 1);                    outData[outindex++] = (byte)((element >> 4) & 1);                    outData[outindex++] = (byte)((element >> 3) & 1);                    outData[outindex++] = (byte)((element >> 2) & 1);                    outData[outindex++] = (byte)((element >> 1) & 1);                    outData[outindex++] = (byte)(element & 1);                    bitnum += 8;                }                break;             case 2:                for (; i < w - 7; i += 8) {                    element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 6) & 3);                    outData[outindex++] = (byte)((element >> 4) & 3);                    outData[outindex++] = (byte)((element >> 2) & 3);                    outData[outindex++] = (byte)(element & 3);                     element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 6) & 3);                    outData[outindex++] = (byte)((element >> 4) & 3);                    outData[outindex++] = (byte)((element >> 2) & 3);                    outData[outindex++] = (byte)(element & 3);                     bitnum += 16;                }                break;             case 4:                for (; i < w - 7; i += 8) {                    element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 4) & 0xf);                    outData[outindex++] = (byte)(element & 0xf);                     element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 4) & 0xf);                    outData[outindex++] = (byte)(element & 0xf);                     element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 4) & 0xf);                    outData[outindex++] = (byte)(element & 0xf);                     element = data[inIndex++];                    outData[outindex++] = (byte)((element >> 4) & 0xf);                    outData[outindex++] = (byte)(element & 0xf);                     bitnum += 32;                }                break;            }             // Process final portion of scanline            for (; i < w; i++) {                int shift = shiftOffset - (bitnum & 7);                outData[outindex++] =                    (byte) (bitMask & (data[index + (bitnum >> 3)] >> shift));                bitnum += pixbits;            }             index += scanlineStride;        }         return outData;    }     /**     * Stores the data elements at the specified location.     * An ArrayIndexOutOfBounds exception will be thrown at runtime     * if the pixel coordinate is out of bounds.     * A ClassCastException will be thrown if the input object is non null     * and references anything other than an array of transferType.     * @param x        The X coordinate of the pixel location.

Lines 1–500 of 1396.