- /*
- * @(#)ImageUtil.java 1.2 03/12/19 16:54:01
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- 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 << 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 + bOffset16;
- 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 + bOffset32;
- 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[bOffset8];
- 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[bOffset16];
- bdata[k++] =
- (byte)((s >>> (15 - bOffset % 16)) &
- 0x0000001);
- bOffset++;
- }
- eltOffset += lineStride;
- }
- } else if(dataBuffer instanceof DataBufferInt) {
- int[] data = ((DataBufferInt)dataBuffer).getData();
- for(int y = rectY; y < maxY; y++) {
- int bOffset = eltOffset*32 + bitOffset;
- for(int x = rectX; x < maxX; x++) {
- int i = data[bOffset32];
- bdata[k++] =
- (byte)((i >>> (31 - bOffset % 32)) &
- 0x0000001);
- bOffset++;
- }
- eltOffset += lineStride;
- }
- }
-
- return bdata;
- }
-
- /**
- * Sets the supplied <code>Raster</code>'s data from an array
- * of packed binary data of the form returned by
- * <code>getPackedBinaryData()</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 void setPackedBinaryData(byte[] binaryDataArray,
- WritableRaster 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 b = 0;
-
- if(bitOffset == 0) {
- if(dataBuffer instanceof DataBufferByte) {
- byte[] data = ((DataBufferByte)dataBuffer).getData();
- if(data == binaryDataArray) {
- // Optimal case: simply return.
- return;
- }
- int stride = (rectWidth + 7)/8;
- int offset = 0;
- for(int y = 0; y < rectHeight; y++) {
- System.arraycopy(binaryDataArray, offset,
- data, eltOffset,
- 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) {
- data[i++] =
- (short)(((binaryDataArray[b++] & 0xFF) << 8) |
- (binaryDataArray[b++] & 0xFF));
- xRemaining -= 16;
- }
- if(xRemaining > 0) {
- data[i++] =
- (short)((binaryDataArray[b++] & 0xFF) << 8);
- }
- 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) {
- data[i++] =
- (int)(((binaryDataArray[b++] & 0xFF) << 24) |
- ((binaryDataArray[b++] & 0xFF) << 16) |
- ((binaryDataArray[b++] & 0xFF) << 8) |
- (binaryDataArray[b++] & 0xFF));
- xRemaining -= 32;
- }
- int shift = 24;
- while(xRemaining > 0) {
- data[i] |=
- (int)((binaryDataArray[b++] & 0xFF) << shift);
- shift -= 8;
- xRemaining -= 8;
- }
- eltOffset += lineStride;
- }
- }
- } else { // bitOffset != 0
- int stride = (rectWidth + 7)/8;
- int offset = 0;
- if(dataBuffer instanceof DataBufferByte) {
- byte[] data = ((DataBufferByte)dataBuffer).getData();
-
- if((bitOffset & 7) == 0) {
- for(int y = 0; y < rectHeight; y++) {
- System.arraycopy(binaryDataArray, offset,
- data, eltOffset,
- stride);
- offset += stride;
- eltOffset += lineStride;
- }
- } else { // bitOffset % 8 != 0
- int rightShift = bitOffset & 7;
- int leftShift = 8 - rightShift;
- int leftShift8 = 8 + leftShift;
- int mask = (byte)(255<<leftShift);
- int mask1 = (byte)~mask;
-
- for(int y = 0; y < rectHeight; y++) {
- int i = eltOffset;
- int xRemaining = rectWidth;
- while(xRemaining > 0) {
- byte datum = binaryDataArray[b++];
-
- if (xRemaining > leftShift8) {
- // when all the bits in this BYTE will be set
- // into the data buffer.
- data[i] = (byte)((data[i] & mask ) |
- ((datum&0xFF) >>> rightShift));
- data[++i] = (byte)((datum & 0xFF) << leftShift);
- } else if (xRemaining > leftShift) {
- // All the "leftShift" high bits will be set
- // into the data buffer. But not all the
- // "rightShift" low bits will be set.
- data[i] = (byte)((data[i] & mask ) |
- ((datum&0xFF) >>> rightShift));
- i++;
- data[i] =
- (byte)((data[i] & mask1) | ((datum & 0xFF) << leftShift));
- }
- else {
- // Less than "leftShift" high bits will be set.
- int remainMask = (1 << leftShift - xRemaining) - 1;
- data[i] =
- (byte)((data[i] & (mask | remainMask)) |
- (datum&0xFF) >>> rightShift & ~remainMask);
- }
- xRemaining -= 8;
- }
- eltOffset += lineStride;
- }
- }
- } else if(dataBuffer instanceof DataBufferShort ||
- dataBuffer instanceof DataBufferUShort) {
- short[] data = dataBuffer instanceof DataBufferShort ?
- ((DataBufferShort)dataBuffer).getData() :
- ((DataBufferUShort)dataBuffer).getData();
-
- int rightShift = bitOffset & 7;
- int leftShift = 8 - rightShift;
- int leftShift16 = 16 + leftShift;
- int mask = (short)(~(255 << leftShift));
- int mask1 = (short)(65535 << leftShift);
- int mask2 = (short)~mask1;
-
- for(int y = 0; y < rectHeight; y++) {
- int bOffset = bitOffset;
- int xRemaining = rectWidth;
- for(int x = 0; x < rectWidth;
- x += 8, bOffset += 8, xRemaining -= 8) {
- int i = eltOffset + (bOffset >> 4);
- int mod = bOffset & 15;
- int datum = binaryDataArray[b++] & 0xFF;
- if(mod <= 8) {
- // This BYTE is set into one SHORT
- if (xRemaining < 8) {
- // Mask the bits to be set.
- datum &= 255 << 8 - xRemaining;
- }
- data[i] = (short)((data[i] & mask) | (datum << leftShift));
- } else if (xRemaining > leftShift16) {
- // This BYTE will be set into two SHORTs
- data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF));
- data[++i] =
- (short)((datum << leftShift)&0xFFFF);
- } else if (xRemaining > leftShift) {
- // This BYTE will be set into two SHORTs;
- // But not all the low bits will be set into SHORT
- data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF));
- i++;
- data[i] =
- (short)((data[i] & mask2) | ((datum << leftShift)&0xFFFF));
- } else {
- // Only some of the high bits will be set into
- // SHORTs
- int remainMask = (1 << leftShift - xRemaining) - 1;
- data[i] = (short)((data[i] & (mask1 | remainMask)) |
- ((datum >>> rightShift)&0xFFFF & ~remainMask));
- }
- }
- eltOffset += lineStride;
- }
- } else if(dataBuffer instanceof DataBufferInt) {
- int[] data = ((DataBufferInt)dataBuffer).getData();
- int rightShift = bitOffset & 7;
- int leftShift = 8 - rightShift;
- int leftShift32 = 32 + leftShift;
- int mask = 0xFFFFFFFF << leftShift;
- int mask1 = ~mask;
-
- for(int y = 0; y < rectHeight; y++) {
- int bOffset = bitOffset;
- int xRemaining = rectWidth;
- for(int x = 0; x < rectWidth;
- x += 8, bOffset += 8, xRemaining -= 8) {
- int i = eltOffset + (bOffset >> 5);
- int mod = bOffset & 31;
- int datum = binaryDataArray[b++] & 0xFF;
- if(mod <= 24) {
- // This BYTE is set into one INT
- int shift = 24 - mod;
- if (xRemaining < 8) {
- // Mask the bits to be set.
- datum &= 255 << 8 - xRemaining;
- }
- data[i] = (data[i] & (~(255 << shift))) | (datum << shift);
- } else if (xRemaining > leftShift32) {
- // All the bits of this BYTE will be set into two INTs
- data[i] = (data[i] & mask) | (datum >>> rightShift);
- data[++i] = datum << leftShift;
- } else if (xRemaining > leftShift) {
- // This BYTE will be set into two INTs;
- // But not all the low bits will be set into INT
- data[i] = (data[i] & mask) | (datum >>> rightShift);
- i++;
- data[i] = (data[i] & mask1) | (datum << leftShift);
- } else {
- // Only some of the high bits will be set into INT
- int remainMask = (1 << leftShift - xRemaining) - 1;
- data[i] = (data[i] & (mask | remainMask)) |
- (datum >>> rightShift & ~remainMask);
- }
- }
- eltOffset += lineStride;
- }
- }
- }
- }
-
- /**
- * Copies data into the packed array of the <code>Raster</code>
- * from an array of unpacked data of the form returned by
- * <code>getUnpackedBinaryData()</code>.
- *
- * <p> If the data are binary, then the target bit will be set if
- * and only if the corresponding byte is non-zero.
- *
- * @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 void setUnpackedBinaryData(byte[] bdata,
- WritableRaster 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 k = 0;
-
- if(dataBuffer instanceof DataBufferByte) {
- byte[] data = ((DataBufferByte)dataBuffer).getData();
- for(int y = 0; y < rectHeight; y++) {
- int bOffset = eltOffset*8 + bitOffset;
- for(int x = 0; x < rectWidth; x++) {
- if(bdata[k++] != (byte)0) {
- data[bOffset8] |=
- (byte)(0x00000001 << (7 - bOffset & 7));
- }
- 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 = 0; y < rectHeight; y++) {
- int bOffset = eltOffset*16 + bitOffset;
- for(int x = 0; x < rectWidth; x++) {
- if(bdata[k++] != (byte)0) {
- data[bOffset16] |=
- (short)(0x00000001 <<
- (15 - bOffset % 16));
- }
- bOffset++;
- }
- eltOffset += lineStride;
- }
- } else if(dataBuffer instanceof DataBufferInt) {
- int[] data = ((DataBufferInt)dataBuffer).getData();
- for(int y = 0; y < rectHeight; y++) {
- int bOffset = eltOffset*32 + bitOffset;
- for(int x = 0; x < rectWidth; x++) {
- if(bdata[k++] != (byte)0) {
- data[bOffset32] |=
- (int)(0x00000001 <<
- (31 - bOffset % 32));
- }
- bOffset++;
- }
- eltOffset += lineStride;
- }
- }
- }
-
- public static boolean isBinary(SampleModel sm) {
- return sm instanceof MultiPixelPackedSampleModel &&
- ((MultiPixelPackedSampleModel)sm).getPixelBitStride() == 1 &&
- sm.getNumBands() == 1;
- }
-
- public static ColorModel createColorModel(ColorSpace colorSpace,
- SampleModel sampleModel) {
- ColorModel colorModel = null;
-
- if(sampleModel == null) {
- throw new IllegalArgumentException(I18N.getString("ImageUtil1"));
- }
-
- int numBands = sampleModel.getNumBands();
- if (numBands < 1 || numBands > 4) {
- return null;
- }
-
- int dataType = sampleModel.getDataType();
- if (sampleModel instanceof ComponentSampleModel) {
- if (dataType < DataBuffer.TYPE_BYTE ||
- //dataType == DataBuffer.TYPE_SHORT ||
- dataType > DataBuffer.TYPE_DOUBLE) {
- return null;
- }
-
- if (colorSpace == null)
- colorSpace =
- numBands <= 2 ?
- ColorSpace.getInstance(ColorSpace.CS_GRAY) :
- ColorSpace.getInstance(ColorSpace.CS_sRGB);
-
- boolean useAlpha = (numBands == 2) || (numBands == 4);
- int transparency = useAlpha ?
- Transparency.TRANSLUCENT : Transparency.OPAQUE;
-
- boolean premultiplied = false;
-
- int dataTypeSize = DataBuffer.getDataTypeSize(dataType);
- int[] bits = new int[numBands];
- for (int i = 0; i < numBands; i++) {
- bits[i] = dataTypeSize;
- }
-
- colorModel = new ComponentColorModel(colorSpace,
- bits,
- useAlpha,
- premultiplied,
- transparency,
- dataType);
- } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
- SinglePixelPackedSampleModel sppsm =
- (SinglePixelPackedSampleModel)sampleModel;
-
- int[] bitMasks = sppsm.getBitMasks();
- int rmask = 0;
- int gmask = 0;
- int bmask = 0;
- int amask = 0;
-
- 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[] sampleSize = sppsm.getSampleSize();
- int bits = 0;
- for (int i = 0; i < sampleSize.length; i++) {
- bits += sampleSize[i];
- }
-
- if (colorSpace == null)
- colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
-
- colorModel =
- new DirectColorModel(colorSpace,
- bits, rmask, gmask, bmask, amask,
- false,
- sampleModel.getDataType());
- } else if (sampleModel instanceof MultiPixelPackedSampleModel) {
- int bits =
- ((MultiPixelPackedSampleModel)sampleModel).getPixelBitStride();
- int size = 1 << bits;
- byte[] comp = new byte[size];
-
- for (int i = 0; i < size; i++)
- comp[i] = (byte)(255 * i / (size - 1));
-
- colorModel = new IndexColorModel(bits, size, comp, comp, comp);
- }
-
- return colorModel;
- }
-
- public static int getElementSize(SampleModel sm) {
- int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
-
- if (sm instanceof MultiPixelPackedSampleModel) {
- MultiPixelPackedSampleModel mppsm =
- (MultiPixelPackedSampleModel)sm;
- return mppsm.getSampleSize(0) * mppsm.getNumBands();
- } else if (sm instanceof ComponentSampleModel) {
- return sm.getNumBands() * elementSize;
- } else if (sm instanceof SinglePixelPackedSampleModel) {
- return elementSize;
- }
-
- return elementSize * sm.getNumBands();
-
- }
-
- public static long getTileSize(SampleModel sm) {
- int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
-
- if (sm instanceof MultiPixelPackedSampleModel) {
- MultiPixelPackedSampleModel mppsm =
- (MultiPixelPackedSampleModel)sm;
- return (mppsm.getScanlineStride() * mppsm.getHeight() +
- (mppsm.getDataBitOffset() + elementSize -1) / elementSize) *
- ((elementSize + 7) / 8);
- } else if (sm instanceof ComponentSampleModel) {
- ComponentSampleModel csm = (ComponentSampleModel)sm;
- int[] bandOffsets = csm.getBandOffsets();
- int maxBandOff = bandOffsets[0];
- for (int i=1; i<bandOffsets.length; i++)
- maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
-
- long size = 0;
- int pixelStride = csm.getPixelStride();
- int scanlineStride = csm.getScanlineStride();
- if (maxBandOff >= 0)
- size += maxBandOff + 1;
- if (pixelStride > 0)
- size += pixelStride * (sm.getWidth() - 1);
- if (scanlineStride > 0)
- size += scanlineStride * (sm.getHeight() - 1);
-
- int[] bankIndices = csm.getBankIndices();
- maxBandOff = bankIndices[0];
- for (int i=1; i<bankIndices.length; i++)
- maxBandOff = Math.max(maxBandOff, bankIndices[i]);
- return size * (maxBandOff + 1) * ((elementSize + 7) / 8);
- } else if (sm instanceof SinglePixelPackedSampleModel) {
- SinglePixelPackedSampleModel sppsm =
- (SinglePixelPackedSampleModel)sm;
- long size = sppsm.getScanlineStride() * (sppsm.getHeight() - 1) +
- sppsm.getWidth();
- return size * ((elementSize + 7) / 8);
- }
-
- return 0;
- }
-
- public static long getBandSize(SampleModel sm) {
- int elementSize = DataBuffer.getDataTypeSize(sm.getDataType());
-
- if (sm instanceof ComponentSampleModel) {
- ComponentSampleModel csm = (ComponentSampleModel)sm;
- int pixelStride = csm.getPixelStride();
- int scanlineStride = csm.getScanlineStride();
- long size = Math.min(pixelStride, scanlineStride);
-
- if (pixelStride > 0)
- size += pixelStride * (sm.getWidth() - 1);
- if (scanlineStride > 0)
- size += scanlineStride * (sm.getHeight() - 1);
- return size * ((elementSize + 7) / 8);
- } else
- return getTileSize(sm);
- }
- /**
- * Tests whether the color indices represent a gray-scale image.
- *
- * @param r The red channel color indices.
- * @param g The green channel color indices.
- * @param b The blue channel color indices.
- * @return If all the indices have 256 entries, and are identical mappings,
- * return <code>true</code> otherwise, return <code>false</code>.
- */
- public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) {
- if (r.length != g.length || r.length != b.length)
- return false;
-
- int size = r.length;
-
- if (size != 256)
- return false;
-
- for (int i = 0; i < size; i++) {
- byte temp = (byte) i;
-
- if (r[i] != temp || g[i] != temp || b[i] != temp)
- return false;
- }
-
- return true;
- }
-
- /** Converts the provided object to <code>String</code> */
- public static String convertObjectToString(Object obj) {
- if (obj == null)
- return "";
-
- String s = "";
- if (obj instanceof byte[]) {
- byte[] bArray = (byte[])obj;
- for (int i = 0; i < bArray.length; i++)
- s += bArray[i] + " ";
- return s;
- }
-
- if (obj instanceof int[]) {
- int[] iArray = (int[])obj;
- for (int i = 0; i < iArray.length; i++)
- s += iArray[i] + " " ;
- return s;
- }
-
- if (obj instanceof short[]) {
- short[] sArray = (short[])obj;
- for (int i = 0; i < sArray.length; i++)
- s += sArray[i] + " " ;
- return s;
- }
-
- return obj.toString();
-
- }
-
- /** Checks that the provided <code>ImageWriter</code> can encode
- * the provided <code>ImageTypeSpecifier</code> or not. If not, an
- * <code>IIOException</code> will be thrown.
- * @param writer The provided <code>ImageWriter</code>.
- * @param type The image to be tested.
- * @throws IIOException If the writer cannot encoded the provided image.
- */
- public static final void canEncodeImage(ImageWriter writer,
- ImageTypeSpecifier type)
- throws IIOException {
- ImageWriterSpi spi = writer.getOriginatingProvider();
-
- if(type != null && spi != null && !spi.canEncodeImage(type)) {
- throw new IIOException(I18N.getString("ImageUtil2")+" "+
- writer.getClass().getName());
- }
- }
-
- /** Checks that the provided <code>ImageWriter</code> can encode
- * the provided <code>ColorModel</code> and <code>SampleModel</code>.
- * If not, an <code>IIOException</code> will be thrown.
- * @param writer The provided <code>ImageWriter</code>.
- * @param colorModel The provided <code>ColorModel</code>.
- * @param sampleModel The provided <code>SampleModel</code>.
- * @throws IIOException If the writer cannot encoded the provided image.
- */
- public static final void canEncodeImage(ImageWriter writer,
- ColorModel colorModel,
- SampleModel sampleModel)
- throws IIOException {
- ImageTypeSpecifier type = null;
- if (colorModel != null && sampleModel != null)
- type = new ImageTypeSpecifier(colorModel, sampleModel);
- canEncodeImage(writer, type);
- }
-
- /**
- * Returns whether the image has contiguous data across rows.
- */
- public static final boolean imageIsContiguous(RenderedImage image) {
- SampleModel sm;
- if(image instanceof BufferedImage) {
- WritableRaster ras = ((BufferedImage)image).getRaster();
- sm = ras.getSampleModel();
- } else {
- sm = image.getSampleModel();
- }
-
- if (sm instanceof ComponentSampleModel) {
- // Ensure image rows samples are stored contiguously
- // in a single bank.
- ComponentSampleModel csm = (ComponentSampleModel)sm;
-
- if (csm.getPixelStride() != csm.getNumBands()) {
- return false;
- }
-
- int[] bandOffsets = csm.getBandOffsets();
- for (int i = 0; i < bandOffsets.length; i++) {
- if (bandOffsets[i] != i) {
- return false;
- }
- }
-
- int[] bankIndices = csm.getBankIndices();
- for (int i = 0; i < bandOffsets.length; i++) {
- if (bankIndices[i] != 0) {
- return false;
- }
- }
-
- return true;
- }
-
- // Otherwise true if and only if it's a bilevel image with
- // a MultiPixelPackedSampleModel, 1 bit per pixel, and 1 bit
- // pixel stride.
- return ImageUtil.isBinary(sm);
- }
- }
-
-
-
-