/*
* 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
*/
package com.google.code.appengine.awt.image;
import java.util.Arrays;
import org.apache.harmony.awt.internal.nls.Messages;
import com.google.code.appengine.awt.Transparency;
import com.google.code.appengine.awt.color.ColorSpace;
import com.google.code.appengine.awt.image.ColorModel;
import com.google.code.appengine.awt.image.DataBuffer;
import com.google.code.appengine.awt.image.PackedColorModel;
import com.google.code.appengine.awt.image.SampleModel;
import com.google.code.appengine.awt.image.SinglePixelPackedSampleModel;
import com.google.code.appengine.awt.image.WritableRaster;
public abstract class PackedColorModel extends ColorModel {
int componentMasks[];
int offsets[];
float scales[];
public PackedColorModel(ColorSpace space, int bits, int colorMaskArray[],
int alphaMask, boolean isAlphaPremultiplied, int trans,
int transferType) {
super(bits, createBits(colorMaskArray, alphaMask), space,
(alphaMask == 0 ? false : true), isAlphaPremultiplied, trans,
validateTransferType(transferType));
if (pixel_bits < 1 || pixel_bits > 32) {
// awt.236=The bits is less than 1 or greater than 32
throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
}
componentMasks = new int[numComponents];
for (int i = 0; i < numColorComponents; i++) {
componentMasks[i] = colorMaskArray[i];
}
if (hasAlpha) {
componentMasks[numColorComponents] = alphaMask;
if (this.bits[numColorComponents] == 1) {
transparency = Transparency.BITMASK;
}
}
parseComponents();
}
public PackedColorModel(ColorSpace space, int bits, int rmask, int gmask,
int bmask, int amask, boolean isAlphaPremultiplied, int trans,
int transferType) {
super(bits, createBits(rmask, gmask, bmask, amask), space,
(amask == 0 ? false : true), isAlphaPremultiplied, trans,
validateTransferType(transferType));
if (pixel_bits < 1 || pixel_bits > 32) {
// awt.236=The bits is less than 1 or greater than 32
throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
}
if (cs.getType() != ColorSpace.TYPE_RGB) {
// awt.239=The space is not a TYPE_RGB space
throw new IllegalArgumentException(Messages.getString("awt.239")); //$NON-NLS-1$
}
for (int i = 0; i < numColorComponents; i++) {
if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) {
// awt.23A=The min/max normalized component values are not 0.0/1.0
throw new IllegalArgumentException(Messages.getString("awt.23A")); //$NON-NLS-1$
}
}
componentMasks = new int[numComponents];
componentMasks[0] = rmask;
componentMasks[1] = gmask;
componentMasks[2] = bmask;
if (hasAlpha) {
componentMasks[3] = amask;
if (this.bits[3] == 1) {
transparency = Transparency.BITMASK;
}
}
parseComponents();
}
@Override
public WritableRaster getAlphaRaster(WritableRaster raster) {
if(!hasAlpha) {
return null;
}
int x = raster.getMinX();
int y = raster.getMinY();
int w = raster.getWidth();
int h = raster.getHeight();
int band[] = new int[1];
band[0] = raster.getNumBands() - 1;
return raster.createWritableChild(x, y, w, h, x, y, band);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof PackedColorModel)) {
return false;
}
PackedColorModel cm = (PackedColorModel) obj;
return (pixel_bits == cm.getPixelSize() &&
transferType == cm.getTransferType() &&
cs.getType() == cm.getColorSpace().getType() &&
hasAlpha == cm.hasAlpha() &&
isAlphaPremultiplied == cm.isAlphaPremultiplied() &&
transparency == cm.getTransparency() &&
numColorComponents == cm.getNumColorComponents()&&
numComponents == cm.getNumComponents() &&
Arrays.equals(bits, cm.getComponentSize()) &&
Arrays.equals(componentMasks, cm.getMasks()));
}
@Override
public boolean isCompatibleSampleModel(SampleModel sm) {
if (sm == null) {
return false;
}
if (!(sm instanceof SinglePixelPackedSampleModel)) {
return false;
}
SinglePixelPackedSampleModel esm = (SinglePixelPackedSampleModel) sm;
return ((esm.getNumBands() == numComponents) &&
(esm.getTransferType() == transferType) &&
Arrays.equals(esm.getBitMasks(), componentMasks));
}
@Override
public SampleModel createCompatibleSampleModel(int w, int h) {
return new SinglePixelPackedSampleModel(transferType, w, h,
componentMasks);
}
public final int getMask(int index) {
return componentMasks[index];
}
public final int[] getMasks() {
return (componentMasks.clone());
}
private static int[] createBits(int colorMaskArray[], int alphaMask) {
int bits[];
int numComp;
if (alphaMask == 0) {
numComp = colorMaskArray.length;
} else {
numComp = colorMaskArray.length + 1;
}
bits = new int[numComp];
int i = 0;
for (; i < colorMaskArray.length; i++) {
bits[i] = countCompBits(colorMaskArray[i]);
if (bits[i] < 0) {
// awt.23B=The mask of the {0} component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23B", i)); //$NON-NLS-1$
}
}
if (i < numComp) {
bits[i] = countCompBits(alphaMask);
if (bits[i] < 0) {
// awt.23C=The mask of the alpha component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23C")); //$NON-NLS-1$
}
}
return bits;
}
private static int[] createBits(int rmask, int gmask, int bmask,
int amask) {
int numComp;
if (amask == 0) {
numComp = 3;
} else {
numComp = 4;
}
int bits[] = new int[numComp];
bits[0] = countCompBits(rmask);
if (bits[0] < 0) {
// awt.23D=The mask of the red component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23D")); //$NON-NLS-1$
}
bits[1] = countCompBits(gmask);
if (bits[1] < 0) {
// awt.23E=The mask of the green component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23E")); //$NON-NLS-1$
}
bits[2] = countCompBits(bmask);
if (bits[2] < 0) {
// awt.23F=The mask of the blue component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23F")); //$NON-NLS-1$
}
if (amask != 0) {
bits[3] = countCompBits(amask);
if (bits[3] < 0) {
// awt.23C=The mask of the alpha component is not contiguous
throw new IllegalArgumentException(Messages.getString("awt.23C")); //$NON-NLS-1$
}
}
return bits;
}
private static int countCompBits(int compMask) {
int bits = 0;
if (compMask != 0) {
// Deleting final zeros
while ((compMask & 1) == 0) {
compMask >>>= 1;
}
// Counting component bits
while ((compMask & 1) == 1) {
compMask >>>= 1;
bits++;
}
}
if (compMask != 0) {
return -1;
}
return bits;
}
private static int validateTransferType(int transferType) {
if (transferType != DataBuffer.TYPE_BYTE &&
transferType != DataBuffer.TYPE_USHORT &&
transferType != DataBuffer.TYPE_INT) {
// awt.240=The transferType not is one of DataBuffer.TYPE_BYTE,
// DataBuffer.TYPE_USHORT or DataBuffer.TYPE_INT
throw new IllegalArgumentException(Messages.getString("awt.240")); //$NON-NLS-1$
}
return transferType;
}
private void parseComponents() {
offsets = new int[numComponents];
scales = new float[numComponents];
for (int i = 0; i < numComponents; i++) {
int off = 0;
int mask = componentMasks[i];
while ((mask & 1) == 0) {
mask >>>= 1;
off++;
}
offsets[i] = off;
if (bits[i] == 0) {
scales[i] = 256.0f; // May be any value different from zero,
// because will dividing by zero
} else {
scales[i] = 255.0f / maxValues[i];
}
}
}
}