1167 lines · 48.3 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.common; import java.awt.Point;import java.awt.Rectangle;import java.awt.Transparency;import java.awt.color.ColorSpace;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.awt.image.ComponentColorModel;import java.awt.image.ComponentSampleModel;import java.awt.image.DataBuffer;import java.awt.image.DataBufferByte;import java.awt.image.DataBufferInt;import java.awt.image.DataBufferShort;import java.awt.image.DataBufferUShort;import java.awt.image.DirectColorModel;import java.awt.image.IndexColorModel;import java.awt.image.MultiPixelPackedSampleModel;import java.awt.image.Raster;import java.awt.image.RenderedImage;import java.awt.image.SampleModel;import java.awt.image.SinglePixelPackedSampleModel;import java.awt.image.WritableRaster;import java.util.Arrays; //import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException;import javax.imageio.IIOImage;import javax.imageio.ImageTypeSpecifier;import javax.imageio.ImageWriter;import javax.imageio.spi.ImageWriterSpi; public class ImageUtil {    /* XXX testing only    public static void main(String[] args) {        ImageTypeSpecifier bilevel =            ImageTypeSpecifier.createIndexed(new byte[] {(byte)0, (byte)255},                                             new byte[] {(byte)0, (byte)255},                                             new byte[] {(byte)0, (byte)255},                                             null, 1,                                             DataBuffer.TYPE_BYTE);        ImageTypeSpecifier gray =            ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false);        ImageTypeSpecifier grayAlpha =            ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false,                                               false);        ImageTypeSpecifier rgb =            ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),                                                 new int[] {0, 1, 2},                                                 DataBuffer.TYPE_BYTE,                                                 false,                                                 false);        ImageTypeSpecifier rgba =            ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),                                                 new int[] {0, 1, 2, 3},                                                 DataBuffer.TYPE_BYTE,                                                 true,                                                 false);        ImageTypeSpecifier packed =            ImageTypeSpecifier.createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),                                            0xff000000,                                            0x00ff0000,                                            0x0000ff00,                                            0x000000ff,                                            DataBuffer.TYPE_BYTE,                                            false);         SampleModel bandedSM =            new java.awt.image.BandedSampleModel(DataBuffer.TYPE_BYTE,                                                 1, 1, 15);         System.out.println(createColorModel(bilevel.getSampleModel()));        System.out.println(createColorModel(gray.getSampleModel()));        System.out.println(createColorModel(grayAlpha.getSampleModel()));        System.out.println(createColorModel(rgb.getSampleModel()));        System.out.println(createColorModel(rgba.getSampleModel()));        System.out.println(createColorModel(packed.getSampleModel()));        System.out.println(createColorModel(bandedSM));    }    */     /**     * Creates a <code>ColorModel</code> that may be used with the     * specified <code>SampleModel</code>.  If a suitable     * <code>ColorModel</code> cannot be found, this method returns     * <code>null</code>.     *     * <p> Suitable <code>ColorModel</code>s are guaranteed to exist     * for all instances of <code>ComponentSampleModel</code>.     * For 1- and 3- banded <code>SampleModel</code>s, the returned     * <code>ColorModel</code> will be opaque.  For 2- and 4-banded     * <code>SampleModel</code>s, the output will use alpha transparency     * which is not premultiplied.  1- and 2-banded data will use a     * grayscale <code>ColorSpace</code>, and 3- and 4-banded data a sRGB     * <code>ColorSpace</code>. Data with 5 or more bands will have a     * <code>BogusColorSpace</code>.</p>     *     * <p>An instance of <code>DirectColorModel</code> will be created for     * instances of <code>SinglePixelPackedSampleModel</code> with no more     * than 4 bands.</p>     *     * <p>An instance of <code>IndexColorModel</code> will be created for     * instances of <code>MultiPixelPackedSampleModel</code>. The colormap     * will be a grayscale ramp with <code>1&nbsp;<<&nbsp;numberOfBits</code>     * entries ranging from zero to at most 255.</p>     *     * @return An instance of <code>ColorModel</code> that is suitable for     *         the supplied <code>SampleModel</code>, or <code>null</code>.     *     * @throws IllegalArgumentException  If <code>sampleModel</code> is     *         <code>null</code>.     */    public static final ColorModel createColorModel(SampleModel sampleModel) {        // Check the parameter.        if(sampleModel == null) {            throw new IllegalArgumentException("sampleModel == null!");        }         // Get the data type.        int dataType = sampleModel.getDataType();         // Check the data type        switch(dataType) {        case DataBuffer.TYPE_BYTE:        case DataBuffer.TYPE_USHORT:        case DataBuffer.TYPE_SHORT:        case DataBuffer.TYPE_INT:        case DataBuffer.TYPE_FLOAT:        case DataBuffer.TYPE_DOUBLE:            break;        default:            // Return null for other types.            return null;        }         // The return variable.        ColorModel colorModel = null;         // Get the sample size.        int[] sampleSize = sampleModel.getSampleSize();         // Create a Component ColorModel.        if(sampleModel instanceof ComponentSampleModel) {            // Get the number of bands.            int numBands = sampleModel.getNumBands();             // Determine the color space.            ColorSpace colorSpace = null;            if(numBands <= 2) {                colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);            } else if(numBands <= 4) {                colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);            } else {                colorSpace = new BogusColorSpace(numBands);            }             boolean hasAlpha = (numBands == 2) || (numBands == 4);            boolean isAlphaPremultiplied = false;            int transparency = hasAlpha ?                Transparency.TRANSLUCENT : Transparency.OPAQUE;             colorModel = new ComponentColorModel(colorSpace,                                                 sampleSize,                                                 hasAlpha,                                                 isAlphaPremultiplied,                                                 transparency,                                                 dataType);        } else if (sampleModel.getNumBands() <= 4 &&                   sampleModel instanceof SinglePixelPackedSampleModel) {            SinglePixelPackedSampleModel sppsm =                (SinglePixelPackedSampleModel)sampleModel;             int[] bitMasks = sppsm.getBitMasks();            int rmask = 0;            int gmask = 0;            int bmask = 0;            int amask = 0;             int numBands = bitMasks.length;            if (numBands <= 2) {                rmask = gmask = bmask = bitMasks[0];                if (numBands == 2) {                    amask = bitMasks[1];                }            } else {                rmask = bitMasks[0];                gmask = bitMasks[1];                bmask = bitMasks[2];                if (numBands == 4) {                    amask = bitMasks[3];                }            }             int bits = 0;            for (int i = 0; i < sampleSize.length; i++) {                bits += sampleSize[i];            }             return new DirectColorModel(bits, rmask, gmask, bmask, amask);         } else if(sampleModel instanceof MultiPixelPackedSampleModel) {            // Load the colormap with a ramp.            int bitsPerSample = sampleSize[0];            int numEntries = 1 << bitsPerSample;            byte[] map = new byte[numEntries];            for (int i = 0; i < numEntries; i++) {                map[i] = (byte)(i*255/(numEntries - 1));            }             colorModel = new IndexColorModel(bitsPerSample, numEntries,                                             map, map, map);         }         return colorModel;    }     /**     * For the case of binary data (<code>isBinary()</code> returns     * <code>true</code>), return the binary data as a packed byte array.     * The data will be packed as eight bits per byte with no bit offset,     * i.e., the first bit in each image line will be the left-most of the     * first byte of the line.  The line stride in bytes will be     * <code>(int)((getWidth()+7)/8)</code>.  The length of the returned     * array will be the line stride multiplied by <code>getHeight()</code>     *     * @return the binary data as a packed array of bytes with zero offset     * of <code>null</code> if the data are not binary.     * @throws IllegalArgumentException if <code>isBinary()</code> returns     * <code>false</code> with the <code>SampleModel</code> of the     * supplied <code>Raster</code> as argument.     */    public static byte[] getPackedBinaryData(Raster raster,                                             Rectangle rect) {        SampleModel sm = raster.getSampleModel();        if(!isBinary(sm)) {            throw new IllegalArgumentException(I18N.getString("ImageUtil0"));        }         int rectX = rect.x;        int rectY = rect.y;        int rectWidth = rect.width;        int rectHeight = rect.height;         DataBuffer dataBuffer = raster.getDataBuffer();         int dx = rectX - raster.getSampleModelTranslateX();        int dy = rectY - raster.getSampleModelTranslateY();         MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm;        int lineStride = mpp.getScanlineStride();        int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);        int bitOffset = mpp.getBitOffset(dx);         int numBytesPerRow = (rectWidth + 7)/8;        if(dataBuffer instanceof DataBufferByte &&           eltOffset == 0 && bitOffset == 0 &&           numBytesPerRow == lineStride &&           ((DataBufferByte)dataBuffer).getData().length ==           numBytesPerRow*rectHeight) {            return ((DataBufferByte)dataBuffer).getData();        }         byte[] binaryDataArray = new byte[numBytesPerRow*rectHeight];         int b = 0;         if(bitOffset == 0) {            if(dataBuffer instanceof DataBufferByte) {                byte[] data = ((DataBufferByte)dataBuffer).getData();                int stride = numBytesPerRow;                int offset = 0;                for(int y = 0; y < rectHeight; y++) {                    System.arraycopy(data, eltOffset,                                     binaryDataArray, offset,                                     stride);                    offset += stride;                    eltOffset += lineStride;                }            } else if(dataBuffer instanceof DataBufferShort ||                      dataBuffer instanceof DataBufferUShort) {                short[] data = dataBuffer instanceof DataBufferShort ?                    ((DataBufferShort)dataBuffer).getData() :                    ((DataBufferUShort)dataBuffer).getData();                 for(int y = 0; y < rectHeight; y++) {                    int xRemaining = rectWidth;                    int i = eltOffset;                    while(xRemaining > 8) {                        short datum = data[i++];                        binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF);                        binaryDataArray[b++] = (byte)(datum & 0xFF);                        xRemaining -= 16;                    }                    if(xRemaining > 0) {                        binaryDataArray[b++] = (byte)((data[i] >>> 8) & 0XFF);                    }                    eltOffset += lineStride;                }            } else if(dataBuffer instanceof DataBufferInt) {                int[] data = ((DataBufferInt)dataBuffer).getData();                 for(int y = 0; y < rectHeight; y++) {                    int xRemaining = rectWidth;                    int i = eltOffset;                    while(xRemaining > 24) {                        int datum = data[i++];                        binaryDataArray[b++] = (byte)((datum >>> 24) & 0xFF);                        binaryDataArray[b++] = (byte)((datum >>> 16) & 0xFF);                        binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF);                        binaryDataArray[b++] = (byte)(datum & 0xFF);                        xRemaining -= 32;                    }                    int shift = 24;                    while(xRemaining > 0) {                        binaryDataArray[b++] =                            (byte)((data[i] >>> shift) & 0xFF);                        shift -= 8;                        xRemaining -= 8;                    }                    eltOffset += lineStride;                }            }        } else { // bitOffset != 0            if(dataBuffer instanceof DataBufferByte) {                byte[] data = ((DataBufferByte)dataBuffer).getData();                 if((bitOffset & 7) == 0) {                    int stride = numBytesPerRow;                    int offset = 0;                    for(int y = 0; y < rectHeight; y++) {                        System.arraycopy(data, eltOffset,                                         binaryDataArray, offset,                                         stride);                        offset += stride;                        eltOffset += lineStride;                    }                } else { // bitOffset % 8 != 0                    int leftShift = bitOffset & 7;                    int rightShift = 8 - leftShift;                    for(int y = 0; y < rectHeight; y++) {                        int i = eltOffset;                        int xRemaining = rectWidth;                        while(xRemaining > 0) {                            if(xRemaining > rightShift) {                                binaryDataArray[b++] =                                    (byte)(((data[i++]&0xFF) << leftShift) |                                           ((data[i]&0xFF) >>> rightShift));                            } else {                                binaryDataArray[b++] =                                    (byte)((data[i]&0xFF) << leftShift);                            }                            xRemaining -= 8;                        }                        eltOffset += lineStride;                    }                }            } else if(dataBuffer instanceof DataBufferShort ||                      dataBuffer instanceof DataBufferUShort) {                short[] data = dataBuffer instanceof DataBufferShort ?                    ((DataBufferShort)dataBuffer).getData() :                    ((DataBufferUShort)dataBuffer).getData();                 for(int y = 0; y < rectHeight; y++) {                    int bOffset = bitOffset;                    for(int x = 0; x < rectWidth; x += 8, bOffset += 8) {                        int i = eltOffset + bOffset/16;                        int mod = bOffset % 16;                        int left = data[i] & 0xFFFF;                        if(mod <= 8) {                            binaryDataArray[b++] = (byte)(left >>> (8 - mod));                        } else {                            int delta = mod - 8;                            int right = data[i+1] & 0xFFFF;                            binaryDataArray[b++] =                                (byte)((left << delta) |                                       (right >>> (16 - delta)));                        }                    }                    eltOffset += lineStride;                }            } else if(dataBuffer instanceof DataBufferInt) {                int[] data = ((DataBufferInt)dataBuffer).getData();                 for(int y = 0; y < rectHeight; y++) {                    int bOffset = bitOffset;                    for(int x = 0; x < rectWidth; x += 8, bOffset += 8) {                        int i = eltOffset + bOffset/32;                        int mod = bOffset % 32;                        int left = data[i];                        if(mod <= 24) {                            binaryDataArray[b++] =                                (byte)(left >>> (24 - mod));                        } else {                            int delta = mod - 24;                            int right = data[i+1];                            binaryDataArray[b++] =                                (byte)((left << delta) |                                       (right >>> (32 - delta)));                        }                    }                    eltOffset += lineStride;                }            }        }         return binaryDataArray;    }     /**     * Returns the binary data unpacked into an array of bytes.     * The line stride will be the width of the <code>Raster</code>.     *     * @throws IllegalArgumentException if <code>isBinary()</code> returns     * <code>false</code> with the <code>SampleModel</code> of the     * supplied <code>Raster</code> as argument.     */    public static byte[] getUnpackedBinaryData(Raster raster,                                               Rectangle rect) {        SampleModel sm = raster.getSampleModel();        if(!isBinary(sm)) {            throw new IllegalArgumentException(I18N.getString("ImageUtil0"));        }         int rectX = rect.x;        int rectY = rect.y;        int rectWidth = rect.width;        int rectHeight = rect.height;         DataBuffer dataBuffer = raster.getDataBuffer();         int dx = rectX - raster.getSampleModelTranslateX();        int dy = rectY - raster.getSampleModelTranslateY();         MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm;        int lineStride = mpp.getScanlineStride();        int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);        int bitOffset = mpp.getBitOffset(dx);         byte[] bdata = new byte[rectWidth*rectHeight];        int maxY = rectY + rectHeight;        int maxX = rectX + rectWidth;        int k = 0;         if(dataBuffer instanceof DataBufferByte) {            byte[] data = ((DataBufferByte)dataBuffer).getData();            for(int y = rectY; y < maxY; y++) {                int bOffset = eltOffset*8 + bitOffset;                for(int x = rectX; x < maxX; x++) {                    byte b = data[bOffset/8];                    bdata[k++] =                        (byte)((b >>> (7 - bOffset & 7)) & 0x0000001);                    bOffset++;                }                eltOffset += lineStride;            }        } else if(dataBuffer instanceof DataBufferShort ||                  dataBuffer instanceof DataBufferUShort) {            short[] data = dataBuffer instanceof DataBufferShort ?                ((DataBufferShort)dataBuffer).getData() :                ((DataBufferUShort)dataBuffer).getData();            for(int y = rectY; y < maxY; y++) {                int bOffset = eltOffset*16 + bitOffset;                for(int x = rectX; x < maxX; x++) {                    short s = data[bOffset/16];                    bdata[k++] =                        (byte)((s >>> (15 - bOffset % 16)) &                               0x0000001);                    bOffset++;                }                eltOffset += lineStride;            }        } else if(dataBuffer instanceof DataBufferInt) {            int[] data = ((DataBufferInt)dataBuffer).getData();

Lines 1–500 of 1167.