/* * 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. */ /** * @author Igor V. Stolyarov * @version $Revision$ */ package java.awt.image; import java.awt.color.ColorSpace; import org.apache.harmony.awt.gl.color.LUTColorConverter; import org.apache.harmony.awt.internal.nls.Messages; /** * The Class ComponentColorModel represents a color model that is defined in * terms of its components. * * @since Android 1.0 */ public class ComponentColorModel extends ColorModel { /** * The signed. */ private boolean signed; // Pixel samples are signed. // Samples with TransferType DataBuffer.TYPE_BYTE, // DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT - // unsigned. Samples with others TransferType - // signed. /** * The integral. */ private boolean integral; // Pixel samples are integral. // Samples with TransferType DataBuffer.TYPE_BYTE, // DataBuffer.TYPE_USHORT, DataBuffer.Short and // DataBuffer.TYPE_INT - integral. /** * The scale factors. */ private float scaleFactors[]; // Array of factors for reduction components // values into the form scaled from 0 to 255 /** * The donot support unnormalized. */ private boolean donotSupportUnnormalized; // This Color Model don't support // unnormolized form /** * The need alpha divide. */ private boolean needAlphaDivide; // hasAlpha && isAlphaPremultiplied /** * The calc value. */ private boolean calcValue; // Value was culculated /** * The need scale. */ private boolean needScale; // Normalized value need to scale /** * The min vals. */ private float minVals[]; // Array of Min normalized values /** * The ranges. */ private float ranges[]; // Array of range normalized values /** * The alpha lut. */ private byte alphaLUT[]; // Lookup table for scale alpha value /** * The color lu ts. */ private byte colorLUTs[][]; // Lookup tables for scale color values /** * The from_ linea r_ rg b_ lut. */ private byte from_LINEAR_RGB_LUT[]; // Lookup table for conversion from // Linear RGB Color Space into sRGB /** * The to_ linea r_8 rg b_ lut. */ private byte to_LINEAR_8RGB_LUT[]; // Lookup table for conversion from // sRGB Color Space into Linear RGB // 8 bit /** * The to_ linea r_16 rg b_ lut. */ private short to_LINEAR_16RGB_LUT[]; // Lookup table for conversion from // sRGB Color Space into Linear RGB // 16 bit /** * The LINEA r_ rg b_ length. */ private int LINEAR_RGB_Length; // Linear RGB bit length /** * The factor. */ private float fFactor; // Scale factor /** * The is_s rgb. */ private boolean is_sRGB; // ColorModel has sRGB ColorSpace /** * The is_ linea r_ rgb. */ private boolean is_LINEAR_RGB; // Color Model has Linear RGB Color // Space /** * Instantiates a new component color model. * * @param colorSpace * the color space. * @param bits * the array of component masks. * @param hasAlpha * whether the color model has alpha. * @param isAlphaPremultiplied * whether the alpha is pre-multiplied. * @param transparency * the transparency strategy, @see java.awt.Transparency. * @param transferType * the transfer type (primitive java type to use for the * components). */ public ComponentColorModel(ColorSpace colorSpace, int bits[], boolean hasAlpha, boolean isAlphaPremultiplied, int transparency, int transferType) { super(createPixelBits(colorSpace, hasAlpha, transferType), validateBits(bits, colorSpace, hasAlpha, transferType), colorSpace, hasAlpha, isAlphaPremultiplied, transparency, transferType); needScale = false; switch (transferType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_INT: signed = false; integral = true; donotSupportUnnormalized = false; scaleFactors = new float[numComponents]; for (int i = 0; i < numColorComponents; i++) { scaleFactors[i] = 1.0f / maxValues[i]; if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) { donotSupportUnnormalized = true; } } if (hasAlpha) { maxValues[numColorComponents] = (1 << bits[numColorComponents]) - 1; scaleFactors[numColorComponents] = 1.0f / maxValues[numColorComponents]; } break; case DataBuffer.TYPE_SHORT: signed = true; integral = true; donotSupportUnnormalized = true; scaleFactors = new float[numComponents]; for (int i = 0; i < numComponents; i++) { maxValues[i] = Short.MAX_VALUE; scaleFactors[i] = 1.0f / maxValues[i]; if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) { needScale = true; } } if (needScale) { minVals = new float[numColorComponents]; ranges = new float[numColorComponents]; for (int i = 0; i < numColorComponents; i++) { minVals[i] = cs.getMinValue(i); ranges[i] = cs.getMaxValue(i) - minVals[i]; } } break; case DataBuffer.TYPE_FLOAT: case DataBuffer.TYPE_DOUBLE: signed = true; integral = false; donotSupportUnnormalized = true; break; default: // awt.215=transferType is not one of DataBuffer.TYPE_BYTE, // DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, // DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, or // DataBuffer.TYPE_DOUBLE throw new IllegalArgumentException(Messages.getString("awt.215")); //$NON-NLS-1$ } needAlphaDivide = hasAlpha && isAlphaPremultiplied; initLUTs(); } /** * Instantiates a new component color model. * * @param colorSpace * the color space. * @param hasAlpha * whether the color model has alpha. * @param isAlphaPremultiplied * whether the alpha is pre-multiplied. * @param transparency * the transparency strategy, @see java.awt.Transparency. * @param transferType * the transfer type (primitive java type to use for the * components). */ public ComponentColorModel(ColorSpace colorSpace, boolean hasAlpha, boolean isAlphaPremultiplied, int transparency, int transferType) { this(colorSpace, createPixelBitsArray(colorSpace, hasAlpha, transferType), hasAlpha, isAlphaPremultiplied, transparency, transferType); } /** * Validate bits. * * @param bits * the bits. * @param colorSpace * the color space. * @param hasAlpha * the has alpha. * @param transferType * the transfer type. * @return the int[]. */ private static int[] validateBits(int bits[], ColorSpace colorSpace, boolean hasAlpha, int transferType) { if (bits != null) { return bits; } int numComponents = colorSpace.getNumComponents(); if (hasAlpha) { numComponents++; } bits = new int[numComponents]; int componentLength = DataBuffer.getDataTypeSize(transferType); for (int i = 0; i < numComponents; i++) { bits[i] = componentLength; } return bits; } /** * Creates the pixel bits. * * @param colorSpace * the color space. * @param hasAlpha * the has alpha. * @param transferType * the transfer type. * @return the int. */ private static int createPixelBits(ColorSpace colorSpace, boolean hasAlpha, int transferType) { int numComponents = colorSpace.getNumComponents(); if (hasAlpha) { numComponents++; } int componentLength = DataBuffer.getDataTypeSize(transferType); return numComponents * componentLength; } /** * Creates the pixel bits array. * * @param colorSpace * the color space. * @param hasAlpha * the has alpha. * @param transferType * the transfer type. * @return the int[]. */ private static int[] createPixelBitsArray(ColorSpace colorSpace, boolean hasAlpha, int transferType) { int numComponents = colorSpace.getNumComponents(); if (hasAlpha) { numComponents++; } int bits[] = new int[numComponents]; for (int i = 0; i < numComponents; i++) { bits[i] = DataBuffer.getDataTypeSize(transferType); } return bits; } @Override public Object getDataElements(int components[], int offset, Object obj) { if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } if (offset + numComponents > components.length) { // awt.216=The components array is not large enough to hold all the // color and alpha components throw new IllegalArgumentException(Messages.getString("awt.216")); //$NON-NLS-1$ } switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[]; if (obj == null) { ba = new byte[numComponents]; } else { ba = (byte[])obj; } for (int i = 0, idx = offset; i < numComponents; i++, idx++) { ba[i] = (byte)components[idx]; } return ba; case DataBuffer.TYPE_USHORT: short sa[]; if (obj == null) { sa = new short[numComponents]; } else { sa = (short[])obj; } for (int i = 0, idx = offset; i < numComponents; i++, idx++) { sa[i] = (short)components[idx]; } return sa; case DataBuffer.TYPE_INT: int ia[]; if (obj == null) { ia = new int[numComponents]; } else { ia = (int[])obj; } for (int i = 0, idx = offset; i < numComponents; i++, idx++) { ia[i] = components[idx]; } return ia; default: // awt.217=The transfer type of this ComponentColorModel is not // one // of the following transfer types: DataBuffer.TYPE_BYTE, // DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT throw new UnsupportedOperationException(Messages.getString("awt.217")); //$NON-NLS-1$ } } @Override public Object getDataElements(float normComponents[], int normOffset, Object obj) { if (needScale) { for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { normComponents[idx] = (normComponents[idx] - minVals[i]) / ranges[i]; } } switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[]; if (obj == null) { ba = new byte[numComponents]; } else { ba = (byte[])obj; } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = normOffset; i < numColorComponents; i++, idx++) { ba[i] = (byte)(normComponents[idx] * alpha * maxValues[i] + 0.5f); } ba[numColorComponents] = (byte)(normComponents[normOffset + numColorComponents] * maxValues[numColorComponents] + 0.5f); } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { ba[idx] = (byte)(normComponents[idx] * maxValues[i] + 0.5f); } } return ba; case DataBuffer.TYPE_USHORT: short usa[]; if (obj == null) { usa = new short[numComponents]; } else { usa = (short[])obj; } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { usa[i] = (short)(normComponents[idx] * alpha * maxValues[i] + 0.5f); } usa[numColorComponents] = (short)(alpha * maxValues[numColorComponents] + 0.5f); } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { usa[i] = (short)(normComponents[idx] * maxValues[i] + 0.5f); } } return usa; case DataBuffer.TYPE_INT: int ia[]; if (obj == null) { ia = new int[numComponents]; } else { ia = (int[])obj; } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { ia[i] = (int)(normComponents[idx] * alpha * maxValues[i] + 0.5f); } ia[numColorComponents] = (int)(alpha * maxValues[numColorComponents] + 0.5f); } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { ia[i] = (int)(normComponents[idx] * maxValues[i] + 0.5f); } } return ia; case DataBuffer.TYPE_SHORT: short sa[]; if (obj == null) { sa = new short[numComponents]; } else { sa = (short[])obj; } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { sa[i] = (short)(normComponents[idx] * alpha * maxValues[i] + 0.5f); } sa[numColorComponents] = (short)(alpha * maxValues[numColorComponents] + 0.5f); } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { sa[i] = (short)(normComponents[idx] * maxValues[i] + 0.5f); } } return sa; case DataBuffer.TYPE_FLOAT: float fa[]; if (obj == null) { fa = new float[numComponents]; } else { fa = (float[])obj; } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { fa[i] = normComponents[idx] * alpha; } fa[numColorComponents] = alpha; } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { fa[i] = normComponents[idx]; } } return fa; case DataBuffer.TYPE_DOUBLE: double da[]; if (obj == null) { da = new double[numComponents]; } else { da = (double[])obj; } if (needAlphaDivide) { double alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) { da[i] = normComponents[idx] * alpha; } da[numColorComponents] = alpha; } else { for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { da[i] = normComponents[idx]; } } return da; default: // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } } @Override public Object getDataElements(int rgb, Object pixel) { float normComp[]; float comp[]; int red = (rgb >> 16) & 0xff; int green = (rgb >> 8) & 0xff; int blue = rgb & 0xff; int alpha = (rgb >> 24) & 0xff; comp = new float[3]; if (is_sRGB || is_LINEAR_RGB) { if (is_LINEAR_RGB) { if (LINEAR_RGB_Length == 8) { red = to_LINEAR_8RGB_LUT[red] & 0xff; green = to_LINEAR_8RGB_LUT[green] & 0xff; blue = to_LINEAR_8RGB_LUT[blue] & 0xff; } else { red = to_LINEAR_16RGB_LUT[red] & 0xffff; green = to_LINEAR_16RGB_LUT[green] & 0xffff; blue = to_LINEAR_16RGB_LUT[blue] & 0xffff; } } comp[0] = red / fFactor; comp[1] = green / fFactor; comp[2] = blue / fFactor; if (!hasAlpha) { normComp = comp; } else { float normAlpha = alpha / 255.0f; normComp = new float[numComponents]; for (int i = 0; i < numColorComponents; i++) { normComp[i] = comp[i]; } normComp[numColorComponents] = normAlpha; } } else { comp[0] = red / fFactor; comp[1] = green / fFactor; comp[2] = blue / fFactor; float[] defComp = cs.fromRGB(comp); if (!hasAlpha) { normComp = defComp; } else { float normAlpha = alpha / 255.0f; normComp = new float[numComponents]; for (int i = 0; i < numColorComponents; i++) { normComp[i] = defComp[i]; } normComp[numColorComponents] = normAlpha; } } if (hasAlpha && isAlphaPremultiplied) { normComp[0] *= normComp[numColorComponents]; normComp[1] *= normComp[numColorComponents]; normComp[2] *= normComp[numColorComponents]; } return getDataElements(normComp, 0, pixel); } @Override public WritableRaster getAlphaRaster(WritableRaster raster) { if (!hasAlpha) { return null; } int x = raster.getMinX(); int y = raster.getMinY(); int bandList[] = new int[1]; bandList[0] = raster.getNumBands() - 1; return raster.createWritableChild(x, y, raster.getWidth(), raster.getHeight(), x, y, bandList); } @Override public ColorModel coerceData(WritableRaster raster, boolean isAlphaPremultiplied) { if (!hasAlpha || this.isAlphaPremultiplied == isAlphaPremultiplied) { return this; } int minX = raster.getMinX(); int minY = raster.getMinY(); int w = raster.getWidth(); int h = raster.getHeight(); if (isAlphaPremultiplied) { switch (transferType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_INT: float alphaFactor = maxValues[numColorComponents]; int iComponents[] = null; int iTransparentComponents[] = new int[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { iComponents = raster.getPixel(x, minY, iComponents); if (iComponents[numColorComponents] == 0) { raster.setPixel(x, minY, iTransparentComponents); } else { float alpha = iComponents[numColorComponents] / alphaFactor; for (int n = 0; n < numColorComponents; n++) { iComponents[n] = (int)(alpha * iComponents[n] + 0.5f); } raster.setPixel(x, minY, iComponents); } } } break; case DataBuffer.TYPE_SHORT: float sAlphaFactor = maxValues[numColorComponents]; short sComponents[] = null; short sTransparentComponents[] = new short[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { sComponents = (short[])raster.getDataElements(x, minY, sComponents); if (sComponents[numColorComponents] == 0) { raster.setDataElements(x, minY, sTransparentComponents); } else { float alpha = sComponents[numColorComponents] / sAlphaFactor; for (int n = 0; n < numColorComponents; n++) { sComponents[n] = (byte)(alpha * sComponents[n] + 0.5f); } raster.setDataElements(x, minY, sComponents); } } } break; case DataBuffer.TYPE_FLOAT: float fComponents[] = null; float fTransparentComponents[] = new float[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { fComponents = raster.getPixel(x, minY, fComponents); if (fComponents[numColorComponents] == 0.0f) { raster.setDataElements(x, minY, fTransparentComponents); } else { float alpha = fComponents[numColorComponents]; for (int n = 0; n < numColorComponents; n++) { fComponents[n] = fComponents[n] * alpha; } raster.setPixel(x, minY, fComponents); } } } break; case DataBuffer.TYPE_DOUBLE: double dComponents[] = null; double dTransparentComponents[] = new double[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { dComponents = raster.getPixel(x, minY, dComponents); if (dComponents[numColorComponents] == 0.0) { raster.setPixel(x, minY, dTransparentComponents); } else { double alpha = dComponents[numColorComponents]; for (int n = 0; n < numColorComponents; n++) { dComponents[n] = dComponents[n] * alpha; } raster.setPixel(x, minY, dComponents); } } } break; default: // awt.219=This transferType is not supported by this color // model throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$ } } else { switch (transferType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_INT: float alphaFactor = maxValues[numColorComponents]; int iComponents[] = null; int iTransparentComponents[] = new int[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { iComponents = raster.getPixel(x, minY, iComponents); if (iComponents[numColorComponents] == 0) { raster.setPixel(x, minY, iTransparentComponents); } else { float alpha = iComponents[numColorComponents] / alphaFactor; for (int n = 0; n < numColorComponents; n++) { iComponents[n] = (int)(iComponents[n] / alpha + 0.5f); } raster.setPixel(x, minY, iComponents); } } } break; case DataBuffer.TYPE_SHORT: float sAlphaFactor = maxValues[numColorComponents]; short sComponents[] = null; short sTransparentComponents[] = new short[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { sComponents = (short[])raster.getDataElements(x, minY, sComponents); if (sComponents[numColorComponents] == 0) { raster.setDataElements(x, minY, sTransparentComponents); } else { float alpha = sComponents[numColorComponents] / sAlphaFactor; for (int n = 0; n < numColorComponents; n++) { sComponents[n] = (byte)(sComponents[n] / alpha + 0.5f); } raster.setDataElements(x, minY, sComponents); } } } break; case DataBuffer.TYPE_FLOAT: float fComponents[] = null; float fTransparentComponents[] = new float[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { fComponents = raster.getPixel(x, minY, fComponents); if (fComponents[numColorComponents] == 0.0f) { raster.setDataElements(x, minY, fTransparentComponents); } else { float alpha = fComponents[numColorComponents]; for (int n = 0; n < numColorComponents; n++) { fComponents[n] = fComponents[n] / alpha; } raster.setPixel(x, minY, fComponents); } } } break; case DataBuffer.TYPE_DOUBLE: double dComponents[] = null; double dTransparentComponents[] = new double[numComponents]; for (int i = 0; i < h; i++, minY++) { for (int j = 0, x = minX; j < w; j++, x++) { dComponents = raster.getPixel(x, minY, dComponents); if (dComponents[numColorComponents] == 0.0) { raster.setPixel(x, minY, dTransparentComponents); } else { double alpha = dComponents[numColorComponents]; for (int n = 0; n < numColorComponents; n++) { dComponents[n] = dComponents[n] / alpha; } raster.setPixel(x, minY, dComponents); } } } break; default: // awt.219=This transferType is not supported by this color // model throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$ } } if (!signed) { return new ComponentColorModel(cs, bits, hasAlpha, isAlphaPremultiplied, transparency, transferType); } return new ComponentColorModel(cs, null, hasAlpha, isAlphaPremultiplied, transparency, transferType); } @Override public int[] getComponents(Object pixel, int[] components, int offset) { if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } if (components == null) { components = new int[offset + numComponents]; } else if (offset + numComponents > components.length) { // awt.218=The components array is not large enough to hold all the // color and alpha components throw new IllegalArgumentException(Messages.getString("awt.218")); //$NON-NLS-1$ } switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[] = (byte[])pixel; for (int i = 0, idx = offset; i < numComponents; i++, idx++) { components[idx] = ba[i] & 0xff; } return components; case DataBuffer.TYPE_USHORT: short sa[] = (short[])pixel; for (int i = 0, idx = offset; i < numComponents; i++, idx++) { components[idx] = sa[i] & 0xffff; } return components; case DataBuffer.TYPE_INT: int ia[] = (int[])pixel; for (int i = 0, idx = offset; i < numComponents; i++, idx++) { components[idx] = ia[i]; } return components; default: // awt.217=The transfer type of this ComponentColorModel is not // one // of the following transfer types: DataBuffer.TYPE_BYTE, // DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT throw new UnsupportedOperationException(Messages.getString("awt.217")); //$NON-NLS-1$ } } @Override public float[] getNormalizedComponents(Object pixel, float normComponents[], int normOffset) { if (normComponents == null) { normComponents = new float[numComponents + normOffset]; } switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[] = (byte[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = (ba[i] & 0xff) * scaleFactors[i]; } break; case DataBuffer.TYPE_USHORT: short usa[] = (short[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = (usa[i] & 0xffff) * scaleFactors[i]; } break; case DataBuffer.TYPE_INT: int ia[] = (int[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = ia[i] * scaleFactors[i]; } break; case DataBuffer.TYPE_SHORT: short sa[] = (short[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = sa[i] * scaleFactors[i]; } break; case DataBuffer.TYPE_FLOAT: float fa[] = (float[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = fa[i]; } break; case DataBuffer.TYPE_DOUBLE: double da[] = (double[])pixel; for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) { normComponents[idx] = (float)da[i]; } break; default: // awt.21A=This ComponentColorModel does not support this // transferType throw new IllegalArgumentException(Messages.getString("awt.21A")); //$NON-NLS-1$ } if (needAlphaDivide) { float alpha = normComponents[normOffset + numColorComponents]; for (int i = 0, idx = normOffset; i < numColorComponents; i++, idx++) { normComponents[idx] /= alpha; } } if (needScale) { for (int i = 0, idx = normOffset; i < numColorComponents; i++, idx++) { normComponents[idx] = minVals[i] + ranges[i] * normComponents[idx]; } } return normComponents; } @Override public boolean equals(Object obj) { if (!(obj instanceof ComponentColorModel)) { return false; } return super.equals(obj); } @Override public int getRed(Object inData) { return getRGBComponent(inData, 0); } @Override public int getRGB(Object inData) { int alpha = getAlpha(inData); if (cs.getType() == ColorSpace.TYPE_GRAY) { int gray = getRed(inData); return (alpha << 24 | gray << 16 | gray << 8 | gray); } return (alpha << 24 | getRed(inData) << 16 | getGreen(inData) << 8 | getBlue(inData)); } @Override public int getGreen(Object inData) { return getRGBComponent(inData, 1); } @Override public int getBlue(Object inData) { return getRGBComponent(inData, 2); } @Override public int getAlpha(Object inData) { if (!hasAlpha) { return 255; } int alpha = 0; switch (transferType) { case DataBuffer.TYPE_BYTE: { byte ba[] = (byte[])inData; alpha = ba[numColorComponents] & 0xff; if (bits[numColorComponents] != 8) { return alphaLUT[alpha] & 0xff; } return alpha; } case DataBuffer.TYPE_USHORT: { short usa[] = (short[])inData; alpha = usa[numColorComponents] & 0xffff; if (bits[numColorComponents] != 8) { return alphaLUT[alpha] & 0xff; } return alpha; } case DataBuffer.TYPE_INT: { int ia[] = (int[])inData; alpha = ia[numColorComponents]; if (bits[numColorComponents] != 8) { return alphaLUT[alpha] & 0xff; } return alpha; } case DataBuffer.TYPE_SHORT: { short sa[] = (short[])inData; alpha = sa[numColorComponents]; if (bits[numColorComponents] != 8) { return alphaLUT[alpha] & 0xff; } return alpha; } case DataBuffer.TYPE_FLOAT: { float fa[] = (float[])inData; return (int)(fa[numColorComponents] * 255.0f + 0.5f); } case DataBuffer.TYPE_DOUBLE: { double da[] = (double[])inData; return (int)(da[numColorComponents] * 255.0 + 0.5); } default: { // awt.214=This Color Model doesn't support this transferType throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$ } } } @Override public WritableRaster createCompatibleWritableRaster(int w, int h) { SampleModel sm = createCompatibleSampleModel(w, h); DataBuffer db = sm.createDataBuffer(); return Raster.createWritableRaster(sm, db, null); } @Override public boolean isCompatibleSampleModel(SampleModel sm) { if (!(sm instanceof ComponentSampleModel)) { return false; } if (numComponents != sm.getNumBands()) { return false; } if (transferType != sm.getTransferType()) { return false; } return true; } @Override public SampleModel createCompatibleSampleModel(int w, int h) { int bandOffsets[] = new int[numComponents]; for (int i = 0; i < numComponents; i++) { bandOffsets[i] = i; } switch (transferType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: return new PixelInterleavedSampleModel(transferType, w, h, numComponents, w * numComponents, bandOffsets); default: return new ComponentSampleModel(transferType, w, h, numComponents, w * numComponents, bandOffsets); } } @Override public boolean isCompatibleRaster(Raster raster) { SampleModel sm = raster.getSampleModel(); if (!(sm instanceof ComponentSampleModel)) { return false; } if (sm.getNumBands() != numComponents) { return false; } if (raster.getTransferType() != transferType) { return false; } int sampleSizes[] = sm.getSampleSize(); for (int i = 0; i < numComponents; i++) { if (bits[i] != sampleSizes[i]) { return false; } } return true; } @Override public float[] getNormalizedComponents(int components[], int offset, float normComponents[], int normOffset) { if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } return super.getNormalizedComponents(components, offset, normComponents, normOffset); } @Override public int getDataElement(int[] components, int offset) { if (numComponents > 1) { // awt.212=There is more than one component in this ColorModel throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$ } if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } return components[offset]; } @Override public int[] getUnnormalizedComponents(float[] normComponents, int normOffset, int[] components, int offset) { if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } if (normComponents.length - normOffset < numComponents) { // awt.21B=The length of normComponents minus normOffset is less // than numComponents throw new IllegalArgumentException(Messages.getString("awt.21B")); //$NON-NLS-1$ } return super.getUnnormalizedComponents(normComponents, normOffset, components, offset); } @Override public int getDataElement(float normComponents[], int normOffset) { if (numComponents > 1) { // awt.212=There is more than one component in this ColorModel throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$ } if (signed) { // awt.210=The component value for this ColorModel is signed throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$ } Object pixel = getDataElements(normComponents, normOffset, null); switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[] = (byte[])pixel; return ba[0] & 0xff; case DataBuffer.TYPE_USHORT: short sa[] = (short[])pixel; return sa[0] & 0xffff; case DataBuffer.TYPE_INT: int ia[] = (int[])pixel; return ia[0]; default: // awt.211=Pixel values for this ColorModel are not conveniently // representable as a single int throw new IllegalArgumentException(Messages.getString("awt.211")); //$NON-NLS-1$ } } @Override public int[] getComponents(int pixel, int components[], int offset) { if (numComponents > 1) { // awt.212=There is more than one component in this ColorModel throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$ } if (donotSupportUnnormalized) { // awt.213=This ComponentColorModel does not support the // unnormalized form throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$ } if (components == null) { components = new int[offset + 1]; } components[offset] = pixel & maxValues[0]; return components; } @Override public int getRed(int pixel) { float rgb[] = toRGB(pixel); return (int)(rgb[0] * 255.0f + 0.5f); } @Override public int getRGB(int pixel) { return (getAlpha(pixel) << 24) | (getRed(pixel) << 16) | (getGreen(pixel) << 8) | getBlue(pixel); } @Override public int getGreen(int pixel) { float rgb[] = toRGB(pixel); return (int)(rgb[1] * 255.0f + 0.5f); } @Override public int getBlue(int pixel) { float rgb[] = toRGB(pixel); return (int)(rgb[2] * 255.0f + 0.5f); } @Override public int getAlpha(int pixel) { // This method throw IllegalArgumentException according to // Java API Spacification if (signed) { // awt.210=The component value for this ColorModel is signed throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$ } if (numComponents > 1) { // awt.212=There is more than one component in this ColorModel throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$ } return 255; } /** * Initialization of Lookup tables. */ private void initLUTs() { is_sRGB = cs.isCS_sRGB(); is_LINEAR_RGB = (cs == LUTColorConverter.LINEAR_RGB_CS); if (hasAlpha && bits[numColorComponents] != 8 && integral) { alphaLUT = new byte[maxValues[numColorComponents] + 1]; for (int i = 0; i <= maxValues[numColorComponents]; i++) { alphaLUT[i] = (byte)(scaleFactors[numColorComponents] * i + 0.5f); } } if (is_LINEAR_RGB) { if (maxBitLength > 8) { LINEAR_RGB_Length = 16; from_LINEAR_RGB_LUT = LUTColorConverter.getFrom16lRGBtosRGB_LUT(); to_LINEAR_16RGB_LUT = LUTColorConverter.getFromsRGBto16lRGB_LUT(); } else { LINEAR_RGB_Length = 8; from_LINEAR_RGB_LUT = LUTColorConverter.getFrom8lRGBtosRGB_LUT(); to_LINEAR_8RGB_LUT = LUTColorConverter.getFromsRGBto8lRGB_LUT(); } fFactor = ((1 << LINEAR_RGB_Length) - 1); } else { fFactor = 255.0f; } if (!isAlphaPremultiplied && integral) { colorLUTs = new byte[3][]; if (is_sRGB) { for (int i = 0; i < numColorComponents; i++) { if (bits[i] != 8) { for (int j = 0; j < i; j++) { if (bits[i] == bits[j]) { colorLUTs[i] = colorLUTs[j]; break; } } colorLUTs[i] = new byte[maxValues[i] + 1]; for (int j = 0; j <= maxValues[0]; j++) { colorLUTs[i][j] = (byte)(scaleFactors[i] * j + 0.5f); } } } } if (is_LINEAR_RGB) { for (int i = 0; i < numColorComponents; i++) { if (bits[i] != LINEAR_RGB_Length) { for (int j = 0; j < i; j++) { if (bits[i] == bits[j]) { colorLUTs[i] = colorLUTs[j]; break; } } colorLUTs[i] = new byte[maxValues[i] + 1]; for (int j = 0; j <= maxValues[0]; j++) { int idx; if (LINEAR_RGB_Length == 8) { idx = (int)(scaleFactors[i] * j + 0.5f); } else { idx = (int)(scaleFactors[i] * j * 257.0f + 0.5f); } colorLUTs[i][j] = from_LINEAR_RGB_LUT[idx]; } } } } } } /** * To rgb. * * @param pixel * the integer representation of the pixel. * @return the array of normalized sRGB components. */ private float[] toRGB(int pixel) { // This method throw IllegalArgumentException according to // Java API Spacification if (signed) { // awt.210=The component value for this ColorModel is signed throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$ } if (numComponents > 1) { // awt.212=There is more than one component in this ColorModel throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$ } Object obj = null; switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[] = new byte[1]; ba[0] = (byte)pixel; obj = ba; break; case DataBuffer.TYPE_USHORT: short sa[] = new short[1]; sa[0] = (short)pixel; obj = sa; break; case DataBuffer.TYPE_INT: int ia[] = new int[1]; ia[0] = pixel; obj = ia; break; } return cs.toRGB(getNormalizedComponents(obj, null, 0)); } /** * Gets the RGB component. * * @param pixel * the pixel. * @param idx * the index of component. * @return the RGB value from 0 to 255 pixel's component. */ private int getRGBComponent(Object pixel, int idx) { if (is_sRGB) { int comp = getDefComponent(pixel, idx); if (calcValue || bits[idx] == 8) { return comp; } return colorLUTs[idx][comp] & 0xff; } else if (is_LINEAR_RGB) { int comp = getDefComponent(pixel, idx); if (calcValue || bits[idx] == LINEAR_RGB_Length) { return from_LINEAR_RGB_LUT[comp] & 0xff; } return colorLUTs[idx][comp] & 0xff; } float normComp[] = getNormalizedComponents(pixel, null, 0); float rgbComp[] = cs.toRGB(normComp); return (int)(rgbComp[idx] * 255.0f + 0.5f); } /** * Gets the def component. * * @param pixel * the pixel. * @param idx * the index of component. * @return the tentative value of the pixel component. */ private int getDefComponent(Object pixel, int idx) { int comp = 0; calcValue = false; switch (transferType) { case DataBuffer.TYPE_BYTE: byte ba[] = (byte[])pixel; comp = ba[idx] & 0xff; if (needAlphaDivide) { int alpha = ba[numColorComponents] & 0xff; if (alpha == 0) { comp = 0; } else { float normAlpha = scaleFactors[numColorComponents] * alpha; comp = (int)(comp * fFactor / normAlpha + 0.5f); } calcValue = true; } return comp; case DataBuffer.TYPE_USHORT: short usa[] = (short[])pixel; comp = usa[idx] & 0xffff; if (needAlphaDivide) { int alpha = usa[numColorComponents] & 0xffff; if (alpha == 0) { comp = 0; } else { float normAlpha = scaleFactors[numColorComponents] * alpha; comp = (int)(comp * fFactor / normAlpha + 0.5f); } calcValue = true; } return comp; case DataBuffer.TYPE_INT: int ia[] = (int[])pixel; comp = ia[idx]; if (needAlphaDivide) { int alpha = ia[numColorComponents]; if (alpha == 0) { comp = 0; } else { float normAlpha = scaleFactors[numColorComponents] * alpha; comp = (int)(comp * fFactor / normAlpha + 0.5f); } calcValue = true; } return comp; case DataBuffer.TYPE_SHORT: short sa[] = (short[])pixel; comp = sa[idx]; if (needAlphaDivide) { int alpha = sa[numColorComponents]; if (alpha == 0) { comp = 0; } else { float normAlpha = scaleFactors[numColorComponents] * alpha; comp = (int)(comp * fFactor / normAlpha + 0.5f); } calcValue = true; } return comp; case DataBuffer.TYPE_FLOAT: float fa[] = (float[])pixel; if (needAlphaDivide) { float alpha = fa[numColorComponents]; if (fa[numColorComponents] == 0.0f) { comp = 0; } else { comp = (int)(fa[idx] * fFactor / alpha + 0.5f); } } else { comp = (int)(fa[idx] * fFactor + 0.5f); } calcValue = true; return comp; case DataBuffer.TYPE_DOUBLE: double da[] = (double[])pixel; if (needAlphaDivide) { if (da[numColorComponents] == 0.0) { comp = 0; } else { comp = (int)(da[idx] * fFactor / da[numColorComponents] + 0.5); } } else { comp = (int)(da[idx] * fFactor + 0.5); } calcValue = true; return comp; default: // awt.214=This Color Model doesn't support this transferType throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$ } } }