/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.code.appengine.imageio;
import java.util.Hashtable;
import org.apache.harmony.x.imageio.internal.nls.Messages;
import com.google.code.appengine.awt.Point;
import com.google.code.appengine.awt.Transparency;
import com.google.code.appengine.awt.color.ColorSpace;
import com.google.code.appengine.awt.image.BandedSampleModel;
import com.google.code.appengine.awt.image.BufferedImage;
import com.google.code.appengine.awt.image.ColorModel;
import com.google.code.appengine.awt.image.ComponentColorModel;
import com.google.code.appengine.awt.image.DataBuffer;
import com.google.code.appengine.awt.image.DirectColorModel;
import com.google.code.appengine.awt.image.IndexColorModel;
import com.google.code.appengine.awt.image.PixelInterleavedSampleModel;
import com.google.code.appengine.awt.image.Raster;
import com.google.code.appengine.awt.image.RenderedImage;
import com.google.code.appengine.awt.image.SampleModel;
import com.google.code.appengine.awt.image.WritableRaster;
import com.google.code.appengine.imageio.ImageTypeSpecifier;
public class ImageTypeSpecifier {
protected ColorModel colorModel;
protected SampleModel sampleModel;
public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel) {
if (colorModel == null) {
throw new IllegalArgumentException(Messages.getString("imageio.24"));
}
if (sampleModel == null) {
throw new IllegalArgumentException(Messages.getString("imageio.25"));
}
if (!colorModel.isCompatibleSampleModel(sampleModel)) {
throw new IllegalArgumentException(Messages.getString("imageio.26"));
}
this.colorModel = colorModel;
this.sampleModel = sampleModel;
}
public ImageTypeSpecifier(RenderedImage renderedImage) {
if (renderedImage == null) {
throw new IllegalArgumentException(Messages.getString("imageio.27"));
}
this.colorModel = renderedImage.getColorModel();
this.sampleModel = renderedImage.getSampleModel();
}
public static ImageTypeSpecifier createPacked(final ColorSpace colorSpace,
final int redMask, final int greenMask, final int blueMask,
final int alphaMask, final int transferType,
final boolean isAlphaPremultiplied) {
final ColorModel model = new DirectColorModel(colorSpace, 32, redMask,
greenMask, blueMask, alphaMask, isAlphaPremultiplied,
transferType);
return new ImageTypeSpecifier(model, model.createCompatibleSampleModel(
1, 1));
}
public static ImageTypeSpecifier createInterleaved(ColorSpace colorSpace,
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
if (colorSpace == null) {
throw new IllegalArgumentException();
}
if (bandOffsets == null) {
throw new IllegalArgumentException();
}
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_DOUBLE &&
dataType != DataBuffer.TYPE_FLOAT &&
dataType != DataBuffer.TYPE_INT &&
dataType != DataBuffer.TYPE_SHORT &&
dataType != DataBuffer.TYPE_USHORT) {
throw new IllegalArgumentException();
}
int numComponents = colorSpace.getNumComponents();
if (hasAlpha) {
numComponents++;
}
if (bandOffsets.length != numComponents) {
throw new IllegalArgumentException();
}
int transparency = hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
int[] bits = new int[numComponents];
for (int i = 0; i < numComponents; i++) {
bits[i] = DataBuffer.getDataTypeSize(dataType);
}
ColorModel colorModel = new ComponentColorModel(colorSpace,
bits,
hasAlpha,
isAlphaPremultiplied,
transparency,
dataType);
int minBandOffset = bandOffsets[0];
int maxBandOffset = bandOffsets[0];
for (int i = 0; i < bandOffsets.length; i++) {
if (minBandOffset > bandOffsets[i]) {
minBandOffset = bandOffsets[i];
}
if (maxBandOffset < bandOffsets[i]) {
maxBandOffset = bandOffsets[i];
}
}
int pixelStride = maxBandOffset - minBandOffset + 1;
SampleModel sampleModel = new PixelInterleavedSampleModel(dataType,
1,
1,
pixelStride,
pixelStride,
bandOffsets);
return new ImageTypeSpecifier(colorModel, sampleModel);
}
public static ImageTypeSpecifier createBanded(ColorSpace colorSpace,
int[] bankIndices,
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
if (colorSpace == null) {
throw new IllegalArgumentException();
}
if (bankIndices == null) {
throw new IllegalArgumentException();
}
if (bandOffsets == null) {
throw new IllegalArgumentException();
}
if (bankIndices.length != bandOffsets.length) {
throw new IllegalArgumentException();
}
int numComponents = colorSpace.getNumComponents();
if (hasAlpha) {
numComponents++;
}
if (bandOffsets.length != numComponents) {
throw new IllegalArgumentException();
}
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_DOUBLE &&
dataType != DataBuffer.TYPE_FLOAT &&
dataType != DataBuffer.TYPE_INT &&
dataType != DataBuffer.TYPE_SHORT &&
dataType != DataBuffer.TYPE_USHORT) {
throw new IllegalArgumentException();
}
int[] bits = new int[numComponents];
for (int i = 0; i < numComponents; i++) {
bits[i] = DataBuffer.getDataTypeSize(dataType);
}
int transparency = hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
ColorModel colorModel = new ComponentColorModel(colorSpace,
bits,
hasAlpha,
isAlphaPremultiplied,
transparency,
dataType);
SampleModel sampleModel = new BandedSampleModel(dataType,
1,
1,
1,
bankIndices,
bandOffsets);
return new ImageTypeSpecifier(colorModel, sampleModel);
}
public static ImageTypeSpecifier createGrayscale(int bits,
int dataType,
boolean isSigned) {
return createGrayscale(bits, dataType, isSigned, false, false);
}
public static ImageTypeSpecifier createGrayscale(int bits,
int dataType,
boolean isSigned,
boolean isAlphaPremultiplied) {
return createGrayscale(bits, dataType, isSigned, true, isAlphaPremultiplied);
}
private static ImageTypeSpecifier createGrayscale(int bits,
int dataType,
boolean isSigned,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
if ((bits != 1) && (bits != 2) && (bits != 4) && (bits != 8) && (bits != 16)) {
throw new IllegalArgumentException();
}
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int numComponent = hasAlpha ? 2 : 1;
int numBits[] = new int[numComponent];
numBits[0] = bits;
if (numComponent ==2) {
numBits[1] = bits;
}
int transparency = hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
ColorModel model = new ComponentColorModel(colorSpace, numBits, hasAlpha, isAlphaPremultiplied, transparency, dataType);
return new ImageTypeSpecifier(model, model.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createIndexed(byte[] redLUT,
byte[] greenLUT,
byte[] blueLUT,
byte[] alphaLUT,
int bits,
int dataType) {
if ((redLUT == null) || (greenLUT == null) || blueLUT == null) {
throw new IllegalArgumentException();
}
if ((bits != 1) && (bits != 2) && (bits != 4) && (bits != 8) && (bits != 16)) {
throw new IllegalArgumentException();
}
int length = 1 << bits;
if ((redLUT.length != length) || (greenLUT.length != length) || (blueLUT.length != length) ||
(alphaLUT != null && alphaLUT.length != length)) {
throw new IllegalArgumentException();
}
if ((dataType != DataBuffer.TYPE_BYTE) && (dataType != DataBuffer.TYPE_SHORT) &&
(dataType != DataBuffer.TYPE_USHORT) && (dataType != DataBuffer.TYPE_INT)) {
throw new IllegalArgumentException();
}
if ((bits > 8 && dataType == DataBuffer.TYPE_BYTE) ||
(bits > 16 && dataType == DataBuffer.TYPE_INT)) {
throw new IllegalArgumentException();
}
ColorModel model = null;
int size = redLUT.length;
if (alphaLUT == null) {
model = new IndexColorModel(bits, size, redLUT, greenLUT, blueLUT);
} else {
model = new IndexColorModel(bits, size, redLUT, greenLUT, blueLUT, alphaLUT);
}
return new ImageTypeSpecifier(model, model.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
switch (bufferedImageType) {
case BufferedImage.TYPE_INT_RGB :
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x00ff0000,
0x0000ff00,
0x000000ff,
0x0,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_INT_ARGB:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_INT_ARGB_PRE:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
true);
case BufferedImage.TYPE_INT_BGR:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x00ff0000,
0x0000ff00,
0x000000ff,
0x0,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_3BYTE_BGR:
return createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{2, 1, 0},
DataBuffer.TYPE_BYTE,
false,
false);
case BufferedImage.TYPE_4BYTE_ABGR:
return createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{3, 2, 1, 0},
DataBuffer.TYPE_BYTE,
true,
false);
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
return createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{3, 2, 1, 0},
DataBuffer.TYPE_BYTE,
true,
true);
case BufferedImage.TYPE_USHORT_565_RGB:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0xf800,
0x07e0,
0x001f,
0,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_USHORT_555_RGB:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x7c00,
0x03e0,
0x001f,
0,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_BYTE_GRAY:
return createGrayscale(8,
DataBuffer.TYPE_BYTE,
false);
case BufferedImage.TYPE_USHORT_GRAY:
return createGrayscale(16,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_BYTE_BINARY: {
byte[] redLUT = new byte[]{0, (byte)255};
byte[] greenLUT = new byte[]{0, (byte)255};
byte[] blueLUT = new byte[]{0, (byte)255};
return createIndexed(redLUT,
greenLUT,
blueLUT,
null,
1,
DataBuffer.TYPE_BYTE);
}
case BufferedImage.TYPE_BYTE_INDEXED: {
BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
IndexColorModel colorModel = (IndexColorModel) bufferedImage.getColorModel();
byte[] redLUT = new byte[256];
byte[] greenLUT = new byte[256];
byte[] blueLUT = new byte[256];
byte[] alphaLUT = new byte[256];
colorModel.getReds(redLUT);
colorModel.getGreens(greenLUT);
colorModel.getBlues(blueLUT);
colorModel.getAlphas(alphaLUT);
return createIndexed(redLUT,
greenLUT,
blueLUT,
alphaLUT,
8,
DataBuffer.TYPE_BYTE);
}
default:
throw new IllegalArgumentException();
}
}
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
if (null == image) {
throw new IllegalArgumentException(Messages.getString("imageio.27"));
}
return new ImageTypeSpecifier(image);
}
public int getBufferedImageType() {
BufferedImage bufferedImage = createBufferedImage(1, 1);
return bufferedImage.getType();
}
public int getNumComponents() {
return colorModel.getNumComponents();
}
public int getNumBands() {
return sampleModel.getNumBands();
}
public int getBitsPerBand(int band) {
if (band < 0 || band >= getNumBands()) {
throw new IllegalArgumentException();
}
return sampleModel.getSampleSize(band);
}
public SampleModel getSampleModel() {
return sampleModel;
}
public SampleModel getSampleModel(int width, int height) {
if ((long)width*height > Integer.MAX_VALUE) {
throw new IllegalArgumentException(Messages.getString("imageio.28")); //$NON-NLS-1$
}
return sampleModel.createCompatibleSampleModel(width, height);
}
public ColorModel getColorModel() {
return colorModel;
}
public BufferedImage createBufferedImage(int width, int height) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException();
}
if ((long)width*height > Integer.MAX_VALUE) {
throw new IllegalArgumentException();
}
SampleModel sm = sampleModel.createCompatibleSampleModel(width, height);
WritableRaster writableRaster = Raster.createWritableRaster(sm, new Point(0, 0));
return new BufferedImage(colorModel, writableRaster, colorModel.isAlphaPremultiplied(), new Hashtable());
}
@Override
public boolean equals(Object o) {
boolean rt = false;
if (o instanceof ImageTypeSpecifier) {
ImageTypeSpecifier ts = (ImageTypeSpecifier) o;
rt = colorModel.equals(ts.colorModel) && sampleModel.equals(ts.sampleModel);
}
return rt;
}
@Override
public int hashCode() {
return colorModel.hashCode() + sampleModel.hashCode();
}
}