-/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath 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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.awt.image;
-
-import java.awt.Point;
-import java.awt.Transparency;
-import java.awt.color.ColorSpace;
-import gnu.java.awt.Buffers;
-
-/**
- * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
- * @author C. Brian Jones (cbj@gnu.org)
- * @author Mark Benvenuto (mcb54@columbia.edu)
- */
-public class DirectColorModel extends PackedColorModel
-{
- /**
- * For the color model created with this constructor the pixels
- * will have fully opaque alpha components with a value of 255.
- * Each mask should describe a fully contiguous set of bits in the
- * most likely order of alpha, red, green, blue from the most significant
- * byte to the least significant byte.
- *
- * @param bits the number of bits wide used for bit size of pixel values
- * @param rmask the bits describing the red component of a pixel
- * @param gmask the bits describing the green component of a pixel
- * @param bmask the bits describing the blue component of a pixel
- * @param amask the bits describing the alpha component of a pixel
- */
- public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
- {
- this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
- rmask, gmask, bmask, 0,
- false, // not alpha premultiplied
- Buffers.smallestAppropriateTransferType(pixelBits) // find type
- );
- }
-
- /**
- * For the color model created with this constructor the pixels
- * will have fully opaque alpha components with a value of 255.
- * Each mask should describe a fully contiguous set of bits in the
- * most likely order of red, green, blue from the most significant
- * byte to the least significant byte.
- *
- * @param bits the number of bits wide used for bit size of pixel values
- * @param rmask the bits describing the red component of a pixel
- * @param gmask the bits describing the green component of a pixel
- * @param bmask the bits describing the blue component of a pixel
- */
- public DirectColorModel(int pixelBits,
- int rmask, int gmask, int bmask, int amask)
- {
- this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
- rmask, gmask, bmask, amask,
- false, // not alpha premultiplied
- Buffers.smallestAppropriateTransferType(pixelBits) // find type
- );
- }
-
- public DirectColorModel(ColorSpace cspace, int pixelBits,
- int rmask, int gmask, int bmask, int amask,
- boolean isAlphaPremultiplied,
- int transferType)
- {
- super(cspace, pixelBits,
- rmask, gmask, bmask, amask, isAlphaPremultiplied,
- ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
- transferType);
- }
-
- public final int getRedMask()
- {
- return getMask(0);
- }
-
- public final int getGreenMask()
- {
- return getMask(1);
- }
-
- public final int getBlueMask()
- {
- return getMask(2);
- }
-
- public final int getAlphaMask()
- {
- return hasAlpha() ? getMask(3) : 0;
- }
-
- /**
- * Get the red component of the given pixel.
- * <br>
- */
- public final int getRed(int pixel)
- {
- return extractAndNormalizeSample(pixel, 0);
- }
-
- /**
- * Get the green component of the given pixel.
- * <br>
- */
- public final int getGreen(int pixel)
- {
- return extractAndNormalizeSample(pixel, 1);
- }
-
- /**
- * Get the blue component of the given pixel.
- * <br>
- */
- public final int getBlue(int pixel)
- {
- return extractAndNormalizeSample(pixel, 2);
- }
-
- /**
- * Get the alpha component of the given pixel.
- * <br>
- */
- public final int getAlpha(int pixel)
- {
- if (!hasAlpha())
- return 0;
- return extractAndScaleSample(pixel, 3);
- }
-
- private final int extractAndNormalizeSample(int pixel, int component)
- {
- int value = extractAndScaleSample(pixel, component);
- if (hasAlpha() && isAlphaPremultiplied())
- value = value*255/getAlpha(pixel);
- return value;
- }
-
- private final int extractAndScaleSample(int pixel, int component)
- {
- int field = pixel & getMask(component);
- int to8BitShift =
- 8 - shifts[component] - getComponentSize(component);
- return (to8BitShift>0) ?
- (field << to8BitShift) :
- (field >>> (-to8BitShift));
- }
-
- /**
- * Get the RGB color value of the given pixel using the default
- * RGB color model.
- * <br>
- *
- * @param pixel a pixel value
- */
- public final int getRGB(int pixel)
- {
- /* FIXME: The Sun docs show that this method is overridden, but I
- don't see any way to improve on the superclass
- implementation. */
- return super.getRGB(pixel);
- }
-
- public int getRed(Object inData)
- {
- return getRed(getPixelFromArray(inData));
- }
-
- public int getGreen(Object inData)
- {
- return getGreen(getPixelFromArray(inData));
- }
-
- public int getBlue(Object inData)
- {
- return getBlue(getPixelFromArray(inData));
- }
-
- public int getAlpha(Object inData)
- {
- return getAlpha(getPixelFromArray(inData));
- }
-
- public int getRGB(Object inData)
- {
- return getRGB(getPixelFromArray(inData));
- }
-
- /**
- * Converts a normalized pixel int value in the sRGB color
- * space to an array containing a single pixel of the color space
- * of the color model.
- *
- * <p>This method performs the inverse function of
- * <code>getRGB(Object inData)</code>.
- *
- * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
- *
- * @param pixel to avoid needless creation of arrays, an array to
- * use to return the pixel can be given. If null, a suitable array
- * will be created.
- *
- * @return array of transferType containing a single pixel. The
- * pixel should be encoded in the natural way of the color model.
- *
- * @see #getRGB(Object)
- */
- public Object getDataElements(int rgb, Object pixel)
- {
- // FIXME: handle alpha multiply
-
- int pixelValue = 0;
- int a = 0;
- if (hasAlpha()) {
- a = (rgb >>> 24) & 0xff;
- pixelValue = valueToField(a, 3, 8);
- }
-
- if (hasAlpha() && isAlphaPremultiplied())
- {
- int r, g, b;
- /* if r=0xff and a=0xff, then resulting
- value will be (r*a)>>>8 == 0xfe... This seems wrong.
- We should divide by 255 rather than shifting >>>8 after
- multiplying.
-
- Too bad, shifting is probably less expensive.
- r = ((rgb >>> 16) & 0xff)*a;
- g = ((rgb >>> 8) & 0xff)*a;
- b = ((rgb >>> 0) & 0xff)*a; */
- /* The r, g, b values we calculate are 16 bit. This allows
- us to avoid discarding the lower 8 bits obtained if
- multiplying with the alpha band. */
-
- // using 16 bit values
- r = ((rgb >>> 8) & 0xff00)*a/255;
- g = ((rgb >>> 0) & 0xff00)*a/255;
- b = ((rgb << 8) & 0xff00)*a/255;
- pixelValue |=
- valueToField(r, 0, 16) | // Red
- valueToField(g, 1, 16) | // Green
- valueToField(b, 2, 16); // Blue
- }
- else
- {
- int r, g, b;
- // using 8 bit values
- r = (rgb >>> 16) & 0xff;
- g = (rgb >>> 8) & 0xff;
- b = (rgb >>> 0) & 0xff;
-
- pixelValue |=
- valueToField(r, 0, 8) | // Red
- valueToField(g, 1, 8) | // Green
- valueToField(b, 2, 8); // Blue
- }
-
- /* In this color model, the whole pixel fits in the first element
- of the array. */
- DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
- buffer.setElem(0, pixelValue);
- return Buffers.getData(buffer);
- }
-
- /**
- * Converts a value to the correct field bits based on the
- * information derived from the field masks.
- *
- * @param highBit the position of the most significant bit in the
- * val parameter.
- */
- private final int valueToField(int val, int component, int highBit)
- {
- int toFieldShift =
- getComponentSize(component) + shifts[component] - highBit;
- int ret = (toFieldShift>0) ?
- (val << toFieldShift) :
- (val >>> (-toFieldShift));
- return ret & getMask(component);
- }
-
- /**
- * Converts a 16 bit value to the correct field bits based on the
- * information derived from the field masks.
- */
- private final int value16ToField(int val, int component)
- {
- int toFieldShift = getComponentSize(component) + shifts[component] - 16;
- return (toFieldShift>0) ?
- (val << toFieldShift) :
- (val >>> (-toFieldShift));
- }
-
- /**
- * Fills an array with the unnormalized component samples from a
- * pixel value. I.e. decompose the pixel, but not perform any
- * color conversion.
- */
- public final int[] getComponents(int pixel, int[] components, int offset)
- {
- int numComponents = getNumComponents();
- if (components == null) components = new int[offset + numComponents];
-
- for (int b=0; b<numComponents; b++)
- components[offset++] = (pixel&getMask(b)) >>> shifts[b];
-
- return components;
- }
-
- public final int[] getComponents(Object pixel, int[] components,
- int offset)
- {
- return getComponents(getPixelFromArray(pixel), components, offset);
- }
-
- public final WritableRaster createCompatibleWritableRaster(int w, int h)
- {
- SampleModel sm = createCompatibleSampleModel(w, h);
- Point origin = new Point(0, 0);
- return Raster.createWritableRaster(sm, origin);
- }
-
- public int getDataElement(int[] components, int offset)
- {
- int numComponents = getNumComponents();
- int pixelValue = 0;
-
- for (int c=0; c<numComponents; c++)
- pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
-
- return pixelValue;
- }
-
- public Object getDataElements(int[] components, int offset, Object obj)
- {
- /* In this color model, the whole pixel fits in the first element
- of the array. */
- int pixelValue = getDataElement(components, offset);
-
- DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
- buffer.setElem(0, pixelValue);
- return Buffers.getData(buffer);
- }
-
- public ColorModel coerceData(WritableRaster raster,
- boolean isAlphaPremultiplied)
- {
- if (this.isAlphaPremultiplied == isAlphaPremultiplied)
- return this;
-
- /* TODO: provide better implementation based on the
- assumptions we can make due to the specific type of the
- color model. */
- super.coerceData(raster, isAlphaPremultiplied);
-
- return new ComponentColorModel(cspace, bits, hasAlpha(),
- isAlphaPremultiplied, // argument
- transparency, transferType);
- }
-
- public boolean isCompatibleRaster(Raster raster)
- {
- /* FIXME: the Sun docs say this method is overridden here,
- but I don't see any way to improve upon the implementation
- in ColorModel. */
- return super.isCompatibleRaster(raster);
- }
-
- String stringParam()
- {
- return super.stringParam() +
- ", redMask=" + Integer.toHexString(getRedMask()) +
- ", greenMask=" + Integer.toHexString(getGreenMask()) +
- ", blueMask=" + Integer.toHexString(getBlueMask()) +
- ", alphaMask=" + Integer.toHexString(getAlphaMask());
- }
-
- public String toString()
- {
- /* FIXME: Again, docs say override, but how do we improve upon the
- superclass implementation? */
- return super.toString();
- }
-}