summaryrefslogtreecommitdiffstats
path: root/awt/java/awt/image
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407 (patch)
treedf5a6539447324de36e95b057d6b9f0361b7a250 /awt/java/awt/image
downloadframeworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.zip
frameworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.tar.gz
frameworks_native-7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407.tar.bz2
Initial Contribution
Diffstat (limited to 'awt/java/awt/image')
-rw-r--r--awt/java/awt/image/AffineTransformOp.java617
-rw-r--r--awt/java/awt/image/AreaAveragingScaleFilter.java253
-rw-r--r--awt/java/awt/image/AwtImageBackdoorAccessorImpl.java153
-rw-r--r--awt/java/awt/image/BandCombineOp.java610
-rw-r--r--awt/java/awt/image/BandedSampleModel.java426
-rw-r--r--awt/java/awt/image/BufferStrategy.java72
-rw-r--r--awt/java/awt/image/BufferedImage.java931
-rw-r--r--awt/java/awt/image/BufferedImageFilter.java375
-rw-r--r--awt/java/awt/image/BufferedImageOp.java86
-rw-r--r--awt/java/awt/image/ByteLookupTable.java134
-rw-r--r--awt/java/awt/image/ColorConvertOp.java711
-rw-r--r--awt/java/awt/image/ColorModel.java911
-rw-r--r--awt/java/awt/image/ComponentColorModel.java1471
-rw-r--r--awt/java/awt/image/ComponentSampleModel.java690
-rw-r--r--awt/java/awt/image/ConvolveOp.java545
-rw-r--r--awt/java/awt/image/CropImageFilter.java193
-rw-r--r--awt/java/awt/image/DataBuffer.java442
-rw-r--r--awt/java/awt/image/DataBufferByte.java171
-rw-r--r--awt/java/awt/image/DataBufferDouble.java214
-rw-r--r--awt/java/awt/image/DataBufferFloat.java214
-rw-r--r--awt/java/awt/image/DataBufferInt.java170
-rw-r--r--awt/java/awt/image/DataBufferShort.java172
-rw-r--r--awt/java/awt/image/DataBufferUShort.java182
-rw-r--r--awt/java/awt/image/DirectColorModel.java862
-rw-r--r--awt/java/awt/image/FilteredImageSource.java88
-rw-r--r--awt/java/awt/image/ImageConsumer.java165
-rw-r--r--awt/java/awt/image/ImageFilter.java129
-rw-r--r--awt/java/awt/image/ImageObserver.java99
-rw-r--r--awt/java/awt/image/ImageProducer.java74
-rw-r--r--awt/java/awt/image/ImagingOpException.java44
-rw-r--r--awt/java/awt/image/IndexColorModel.java1020
-rw-r--r--awt/java/awt/image/Kernel.java138
-rw-r--r--awt/java/awt/image/LookupOp.java647
-rw-r--r--awt/java/awt/image/LookupTable.java93
-rw-r--r--awt/java/awt/image/MemoryImageSource.java512
-rw-r--r--awt/java/awt/image/MultiPixelPackedSampleModel.java454
-rw-r--r--awt/java/awt/image/PackedColorModel.java383
-rw-r--r--awt/java/awt/image/PixelGrabber.java408
-rw-r--r--awt/java/awt/image/PixelInterleavedSampleModel.java124
-rw-r--r--awt/java/awt/image/RGBImageFilter.java190
-rw-r--r--awt/java/awt/image/Raster.java1412
-rw-r--r--awt/java/awt/image/RasterFormatException.java45
-rw-r--r--awt/java/awt/image/RasterOp.java83
-rw-r--r--awt/java/awt/image/RenderedImage.java198
-rw-r--r--awt/java/awt/image/ReplicateScaleFilter.java213
-rw-r--r--awt/java/awt/image/RescaleOp.java659
-rw-r--r--awt/java/awt/image/SampleModel.java1053
-rw-r--r--awt/java/awt/image/ShortLookupTable.java132
-rw-r--r--awt/java/awt/image/SinglePixelPackedSampleModel.java508
-rw-r--r--awt/java/awt/image/TileObserver.java44
-rw-r--r--awt/java/awt/image/VolatileImage.java144
-rw-r--r--awt/java/awt/image/WritableRaster.java516
-rw-r--r--awt/java/awt/image/WritableRenderedImage.java101
-rw-r--r--awt/java/awt/image/renderable/ContextualRenderedImageFactory.java89
-rw-r--r--awt/java/awt/image/renderable/ParameterBlock.java548
-rw-r--r--awt/java/awt/image/renderable/RenderContext.java196
-rw-r--r--awt/java/awt/image/renderable/RenderableImage.java132
-rw-r--r--awt/java/awt/image/renderable/RenderableImageOp.java182
-rw-r--r--awt/java/awt/image/renderable/RenderableImageProducer.java141
-rw-r--r--awt/java/awt/image/renderable/RenderedImageFactory.java43
60 files changed, 21612 insertions, 0 deletions
diff --git a/awt/java/awt/image/AffineTransformOp.java b/awt/java/awt/image/AffineTransformOp.java
new file mode 100644
index 0000000..546837a
--- /dev/null
+++ b/awt/java/awt/image/AffineTransformOp.java
@@ -0,0 +1,617 @@
+/*
+ * 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 Oleg V. Khaschansky, Denis M. Kishenko
+ * @version $Revision$
+ */
+
+package java.awt.image;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.*;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The AffineTransform class translates coordinates from 2D coordinates
+ * in the source image or Raster to 2D coordinates in the destination
+ * image or Raster using Affine transformation. The number of bands in
+ * the source Raster should equal to the number of bands in the destination
+ * Raster.
+ */
+public class AffineTransformOp implements BufferedImageOp, RasterOp {
+
+ /**
+ * The Constant TYPE_NEAREST_NEIGHBOR indicates nearest-neighbor
+ * interpolation type.
+ */
+ public static final int TYPE_NEAREST_NEIGHBOR = 1;
+
+ /**
+ * The Constant TYPE_BILINEAR indicates bilinear interpolation type.
+ */
+ public static final int TYPE_BILINEAR = 2;
+
+ /** The Constant TYPE_BICUBIC indicates bicubic interpolation type. */
+ public static final int TYPE_BICUBIC = 3;
+
+ /** The i type. */
+ private int iType; // interpolation type
+
+ /** The at. */
+ private AffineTransform at;
+
+ /** The hints. */
+ private RenderingHints hints;
+
+ static {
+ // TODO - uncomment
+ //System.loadLibrary("imageops");
+ }
+
+ /**
+ * Instantiates a new AffineTransformOp with the specified
+ * AffineTransform and RenderingHints object which defines
+ * the interpolation type.
+ *
+ * @param xform the AffineTransform.
+ * @param hints the RenderingHints object which defines
+ * the interpolation type.
+ */
+ public AffineTransformOp(AffineTransform xform, RenderingHints hints) {
+ this(xform, TYPE_NEAREST_NEIGHBOR);
+ this.hints = hints;
+
+ if (hints != null) {
+ Object hint = hints.get(RenderingHints.KEY_INTERPOLATION);
+ if (hint != null) {
+ // Nearest neighbor is default
+ if (hint == RenderingHints.VALUE_INTERPOLATION_BILINEAR) {
+ this.iType = TYPE_BILINEAR;
+ } else if (hint == RenderingHints.VALUE_INTERPOLATION_BICUBIC) {
+ this.iType = TYPE_BICUBIC;
+ }
+ } else {
+ hint = hints.get(RenderingHints.KEY_RENDERING);
+ // Determine from rendering quality
+ if (hint == RenderingHints.VALUE_RENDER_QUALITY) {
+ this.iType = TYPE_BILINEAR;
+ // For speed use nearest neighbor
+ }
+ }
+ }
+ }
+
+ /**
+ * Instantiates a new AffineTransformOp with the specified
+ * AffineTransform and a specified interpolation type from the
+ * list of predefined interpolation types.
+ *
+ * @param xform the AffineTransform.
+ * @param interp the one of predefined interpolation types:
+ * TYPE_NEAREST_NEIGHBOR, TYPE_BILINEAR, or TYPE_BICUBIC.
+ */
+ public AffineTransformOp(AffineTransform xform, int interp) {
+ if (Math.abs(xform.getDeterminant()) <= Double.MIN_VALUE) {
+ // awt.24F=Unable to invert transform {0}
+ throw new ImagingOpException(Messages.getString("awt.24F", xform)); //$NON-NLS-1$
+ }
+
+ this.at = (AffineTransform) xform.clone();
+
+ if (interp != TYPE_NEAREST_NEIGHBOR && interp != TYPE_BILINEAR && interp != TYPE_BICUBIC) {
+ // awt.250=Unknown interpolation type: {0}
+ throw new IllegalArgumentException(Messages.getString("awt.250", interp)); //$NON-NLS-1$
+ }
+
+ this.iType = interp;
+ }
+
+ /**
+ * Gets the interpolation type.
+ *
+ * @return the interpolation type
+ */
+ public final int getInterpolationType() {
+ return iType;
+ }
+
+ public final RenderingHints getRenderingHints() {
+ if (hints == null) {
+ Object value = null;
+
+ switch (iType) {
+ case TYPE_NEAREST_NEIGHBOR:
+ value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+ break;
+ case TYPE_BILINEAR:
+ value = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
+ break;
+ case TYPE_BICUBIC:
+ value = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
+ break;
+ default:
+ value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+ }
+
+ hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, value);
+ }
+
+ return hints;
+ }
+
+ /**
+ * Gets the affine transform associated with this AffineTransformOp.
+ *
+ * @return the AffineTransform.
+ */
+ public final AffineTransform getTransform() {
+ return (AffineTransform) at.clone();
+ }
+
+ public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ return at.transform(srcPt, dstPt);
+ }
+
+ public final Rectangle2D getBounds2D(BufferedImage src) {
+ return getBounds2D(src.getRaster());
+ }
+
+ public final Rectangle2D getBounds2D(Raster src) {
+ // We position source raster to (0,0) even if it is translated child raster.
+ // This means that we need only width and height of the src
+ int width = src.getWidth();
+ int height = src.getHeight();
+
+ float[] corners = {
+ 0, 0,
+ width, 0,
+ width, height,
+ 0, height
+ };
+
+ at.transform(corners, 0, corners, 0, 4);
+
+ Rectangle2D.Float bounds = new Rectangle2D.Float(corners[0], corners[1], 0 , 0);
+ bounds.add(corners[2], corners[3]);
+ bounds.add(corners[4], corners[5]);
+ bounds.add(corners[6], corners[7]);
+
+ return bounds;
+ }
+
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
+ Rectangle2D newBounds = getBounds2D(src);
+
+ // Destination image should include (0,0) + positive part
+ // of the area bounded by newBounds (in source coordinate system).
+ double dstWidth = newBounds.getX() + newBounds.getWidth();
+ double dstHeight = newBounds.getY() + newBounds.getHeight();
+
+ if (dstWidth <= 0 || dstHeight <= 0) {
+ // awt.251=Transformed width ({0}) and height ({1}) should be greater than 0
+ throw new RasterFormatException(
+ Messages.getString("awt.251", dstWidth, dstHeight)); //$NON-NLS-1$
+ }
+
+ if (destCM != null) {
+ return new BufferedImage(destCM,
+ destCM.createCompatibleWritableRaster((int)dstWidth, (int)dstHeight),
+ destCM.isAlphaPremultiplied(),
+ null
+ );
+ }
+
+ ColorModel cm = src.getColorModel();
+
+ // Interpolation other than NN doesn't make any sense for index color
+ if (iType != TYPE_NEAREST_NEIGHBOR && cm instanceof IndexColorModel) {
+ return new BufferedImage((int)dstWidth, (int)dstHeight, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ // OK, we can get source color model
+ return new BufferedImage(cm,
+ src.getRaster().createCompatibleWritableRaster((int)dstWidth, (int)dstHeight),
+ cm.isAlphaPremultiplied(),
+ null
+ );
+ }
+
+ public WritableRaster createCompatibleDestRaster (Raster src) {
+ // Here approach is other then in createCompatibleDestImage -
+ // destination should include only
+ // transformed image, but not (0,0) in source coordinate system
+
+ Rectangle2D newBounds = getBounds2D(src);
+ return src.createCompatibleWritableRaster(
+ (int) newBounds.getX(), (int) newBounds.getY(),
+ (int) newBounds.getWidth(), (int)newBounds.getHeight()
+ );
+ }
+
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+ if (src == dst) {
+ // awt.252=Source can't be same as the destination
+ throw new IllegalArgumentException(Messages.getString("awt.252")); //$NON-NLS-1$
+ }
+
+ ColorModel srcCM = src.getColorModel();
+ BufferedImage finalDst = null;
+
+ if (
+ srcCM instanceof IndexColorModel &&
+ (iType != TYPE_NEAREST_NEIGHBOR || srcCM.getPixelSize() % 8 != 0)
+ ) {
+ src = ((IndexColorModel)srcCM).convertToIntDiscrete(src.getRaster(), true);
+ srcCM = src.getColorModel();
+ }
+
+ if (dst == null) {
+ dst = createCompatibleDestImage(src, srcCM);
+ } else {
+ if (!srcCM.equals(dst.getColorModel())) {
+ // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+ if (
+ !(
+ (src.getType() == BufferedImage.TYPE_INT_RGB ||
+ src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+ (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+ dst.getType() == BufferedImage.TYPE_INT_ARGB)
+ )
+ ) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, srcCM);
+ }
+ }
+ }
+
+ // Skip alpha channel for TYPE_INT_RGB images
+ if (slowFilter(src.getRaster(), dst.getRaster()) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ // TODO - uncomment
+ //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType()) != 0)
+ //throw new ImagingOpException ("Unable to transform source");
+ }
+
+ if (finalDst != null) {
+ Graphics2D g = finalDst.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.drawImage(dst, 0, 0, null);
+ } else {
+ finalDst = dst;
+ }
+
+ return finalDst;
+ }
+
+ public final WritableRaster filter(Raster src, WritableRaster dst) {
+ if (src == dst) {
+ // awt.252=Source can't be same as the destination
+ throw new IllegalArgumentException(Messages.getString("awt.252")); //$NON-NLS-1$
+ }
+
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else if (src.getNumBands() != dst.getNumBands()) {
+ // awt.253=Different number of bands in source and destination
+ throw new IllegalArgumentException(Messages.getString("awt.253")); //$NON-NLS-1$
+ }
+
+ if (slowFilter(src, dst) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException(Messages.getString("awt.21F")); //$NON-NLS-1$
+ // TODO - uncomment
+ //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM) != 0)
+ // throw new ImagingOpException("Unable to transform source");
+ }
+
+ return dst;
+ }
+
+ // TODO remove when method is used
+ /**
+ * Ipp filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param imageType the image type
+ *
+ * @return the int
+ */
+ @SuppressWarnings("unused")
+ private int ippFilter(Raster src, WritableRaster dst, int imageType) {
+ int srcStride, dstStride;
+ boolean skipChannel = false;
+ int channels;
+ int offsets[] = null;
+
+ switch (imageType) {
+ case BufferedImage.TYPE_INT_RGB:
+ case BufferedImage.TYPE_INT_BGR: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ skipChannel = true;
+ break;
+ }
+
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ break;
+ }
+
+ case BufferedImage.TYPE_BYTE_GRAY:
+ case BufferedImage.TYPE_BYTE_INDEXED: {
+ channels = 1;
+ srcStride = src.getWidth();
+ dstStride = dst.getWidth();
+ break;
+ }
+
+ case BufferedImage.TYPE_3BYTE_BGR: {
+ channels = 3;
+ srcStride = src.getWidth()*3;
+ dstStride = dst.getWidth()*3;
+ break;
+ }
+
+ case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in native code?
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ case BufferedImage.TYPE_BYTE_BINARY: {
+ return slowFilter(src, dst);
+ }
+
+ default: {
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+
+ if (
+ srcSM instanceof PixelInterleavedSampleModel &&
+ dstSM instanceof PixelInterleavedSampleModel
+ ) {
+ // Check PixelInterleavedSampleModel
+ if (
+ srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+ dstSM.getDataType() != DataBuffer.TYPE_BYTE
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+ if (channels != 1 && channels != 3 && channels != 4) {
+ return slowFilter(src, dst);
+ }
+
+ int dataTypeSize = DataBuffer.getDataTypeSize(srcSM.getDataType()) / 8;
+
+ srcStride = ((ComponentSampleModel) srcSM).getScanlineStride() * dataTypeSize;
+ dstStride = ((ComponentSampleModel) dstSM).getScanlineStride() * dataTypeSize;
+ } else if (
+ srcSM instanceof SinglePixelPackedSampleModel &&
+ dstSM instanceof SinglePixelPackedSampleModel
+ ) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+ SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+ // No IPP function for this type
+ if (sppsm1.getDataType() == DataBuffer.TYPE_USHORT) {
+ return slowFilter(src, dst);
+ }
+
+ channels = sppsm1.getNumBands();
+ // Have IPP functions for 1, 3 and 4 channels
+ if (channels != 1 && channels != 3 && channels != 4) {
+ return slowFilter(src, dst);
+ }
+
+ // Check compatibility of sample models
+ if (
+ sppsm1.getDataType() != sppsm2.getDataType() ||
+ !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+ !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ for (int i=0; i<channels; i++) {
+ if (sppsm1.getSampleSize(i) != 8) {
+ return slowFilter(src, dst);
+ }
+ }
+
+ if (channels == 3) {
+ channels = 4;
+ }
+
+ int dataTypeSize = DataBuffer.getDataTypeSize(sppsm1.getDataType()) / 8;
+
+ srcStride = sppsm1.getScanlineStride() * dataTypeSize;
+ dstStride = sppsm2.getScanlineStride() * dataTypeSize;
+ } else {
+ return slowFilter(src, dst);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (
+ src.getSampleModelTranslateX() != 0 ||
+ src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 ||
+ dst.getSampleModelTranslateY() != 0
+ ) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+ }
+ }
+
+ double m00 = at.getScaleX();
+ double m01 = at.getShearX();
+ double m02 = at.getTranslateX();
+ double m10 = at.getShearY();
+ double m11 = at.getScaleY();
+ double m12 = at.getTranslateY();
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ return ippAffineTransform(
+ m00, m01, m02, m10, m11, m12,
+ srcData, src.getWidth(), src.getHeight(), srcStride,
+ dstData, dst.getWidth(), dst.getHeight(), dstStride,
+ iType, channels, skipChannel, offsets);
+ }
+
+ /**
+ * Slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the int
+ */
+ private int slowFilter(Raster src, WritableRaster dst) {
+ // TODO: make correct interpolation
+ // TODO: what if there are different data types?
+
+ Rectangle srcBounds = src.getBounds();
+ Rectangle dstBounds = dst.getBounds();
+ Rectangle normDstBounds = new Rectangle(0, 0, dstBounds.width, dstBounds.height);
+ Rectangle bounds = getBounds2D(src).getBounds().intersection(normDstBounds);
+
+ AffineTransform inv = null;
+ try {
+ inv = at.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ return -1;
+ }
+
+ double[] m = new double[6];
+ inv.getMatrix(m);
+
+ int minSrcX = srcBounds.x;
+ int minSrcY = srcBounds.y;
+ int maxSrcX = srcBounds.x + srcBounds.width;
+ int maxSrcY = srcBounds.y + srcBounds.height;
+
+ int minX = bounds.x + dstBounds.x;
+ int minY = bounds.y + dstBounds.y;
+ int maxX = minX + bounds.width;
+ int maxY = minY + bounds.height;
+
+ int hx = (int)(m[0] * 256);
+ int hy = (int)(m[1] * 256);
+ int vx = (int)(m[2] * 256);
+ int vy = (int)(m[3] * 256);
+ int sx = (int)(m[4] * 256) + hx * bounds.x + vx * bounds.y + (srcBounds.x) * 256;
+ int sy = (int)(m[5] * 256) + hy * bounds.x + vy * bounds.y + (srcBounds.y) * 256;
+
+ vx -= hx * bounds.width;
+ vy -= hy * bounds.width;
+
+ if (src.getTransferType() == dst.getTransferType()) {
+ for (int y = minY; y < maxY; y++) {
+ for (int x = minX; x < maxX; x++) {
+ int px = sx >> 8;
+ int py = sy >> 8;
+ if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) {
+ Object val = src.getDataElements(px , py , null);
+ dst.setDataElements(x, y, val);
+ }
+ sx += hx;
+ sy += hy;
+ }
+ sx += vx;
+ sy += vy;
+ }
+ } else {
+ float pixel[] = null;
+ for (int y = minY; y < maxY; y++) {
+ for (int x = minX; x < maxX; x++) {
+ int px = sx >> 8;
+ int py = sy >> 8;
+ if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) {
+ pixel = src.getPixel(px, py, pixel);
+ dst.setPixel(x, y, pixel);
+ }
+ sx += hx;
+ sy += hy;
+ }
+ sx += vx;
+ sy += vy;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Ipp affine transform.
+ *
+ * @param m00 the m00
+ * @param m01 the m01
+ * @param m02 the m02
+ * @param m10 the m10
+ * @param m11 the m11
+ * @param m12 the m12
+ * @param src the src
+ * @param srcWidth the src width
+ * @param srcHeight the src height
+ * @param srcStride the src stride
+ * @param dst the dst
+ * @param dstWidth the dst width
+ * @param dstHeight the dst height
+ * @param dstStride the dst stride
+ * @param iType the i type
+ * @param channels the channels
+ * @param skipChannel the skip channel
+ * @param offsets the offsets
+ *
+ * @return the int
+ */
+ private native int ippAffineTransform(
+ double m00, double m01,
+ double m02, double m10,
+ double m11, double m12,
+ Object src, int srcWidth, int srcHeight, int srcStride,
+ Object dst, int dstWidth, int dstHeight, int dstStride,
+ int iType, int channels, boolean skipChannel,
+ int offsets[]);
+} \ No newline at end of file
diff --git a/awt/java/awt/image/AreaAveragingScaleFilter.java b/awt/java/awt/image/AreaAveragingScaleFilter.java
new file mode 100644
index 0000000..f4933db
--- /dev/null
+++ b/awt/java/awt/image/AreaAveragingScaleFilter.java
@@ -0,0 +1,253 @@
+/*
+ * 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.util.Arrays;
+
+
+/**
+ * The AreaAveragingScaleFilter class scales the source image using
+ * area averaging algorithm. This algorithm provides a source image
+ * with a new image containing the resampled image.
+ */
+public class AreaAveragingScaleFilter extends ReplicateScaleFilter {
+
+ /** The Constant rgbCM. */
+ private static final ColorModel rgbCM = ColorModel.getRGBdefault();
+
+ /** The Constant averagingFlags. */
+ private static final int averagingFlags = (ImageConsumer.TOPDOWNLEFTRIGHT |
+ ImageConsumer.COMPLETESCANLINES);
+
+ /** The reset. */
+ private boolean reset = true; // Flag for used superclass filter
+
+ /** The inited. */
+ private boolean inited = false; // All data inited
+
+ /** The sum_r. */
+ private int sum_r[]; // Array for average Red samples
+
+ /** The sum_g. */
+ private int sum_g[]; // Array for average Green samples
+
+ /** The sum_b. */
+ private int sum_b[]; // Array for average Blue samples
+
+ /** The sum_a. */
+ private int sum_a[]; // Array for average Alpha samples
+
+ /** The buff. */
+ private int buff[]; // Stride buffer
+
+ /** The avg factor. */
+ private int avgFactor; // Global averaging factor
+
+ /** The cached dy. */
+ private int cachedDY; // Cached number of the destination scanline
+
+ /** The cached dv rest. */
+ private int cachedDVRest; // Cached value of rest src scanlines for sum
+ // pixel samples
+ // Because data if transfering by whole scanlines
+ // we are caching only Y coordinate values
+
+ /**
+ * Instantiates a new AreaAveragingScaleFilter object which scales
+ * a source image with the specified width and height.
+ *
+ * @param width the scaled width of the image.
+ * @param height the scaled height of the image.
+ */
+ public AreaAveragingScaleFilter(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {
+ if(reset) {
+ super.setPixels(x, y, w, h, model, pixels, off, scansize);
+ } else {
+ setFilteredPixels(x, y, w, h, model, pixels, off, scansize);
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+ if(reset) {
+ super.setPixels(x, y, w, h, model, pixels, off, scansize);
+ } else {
+ setFilteredPixels(x, y, w, h, model, pixels, off, scansize);
+ }
+ }
+
+ @Override
+ public void setHints(int hints) {
+ super.setHints(hints);
+ reset = ((hints & averagingFlags) != averagingFlags);
+ }
+
+ /**
+ * This method implements the Area Averaging Scale filter.
+ * The description of algorithm is presented in Java API Specification.
+ *
+ * Arrays sum_r, sum_g, sum_b, sum_a have length equals width of destination
+ * image. In each array's element is accumulating pixel's component values,
+ * proportional to the area which source pixels will occupy in destination
+ * image. Then that values will divide by Global averaging
+ * factor (area of the destination image) for receiving
+ * average values of destination pixels.
+ *
+ * @param x - Src pixels X coordinate
+ * @param y - Src pixels Y coordinate
+ * @param w - width of the area of Src pixels
+ * @param h - height of the area of Src pixels
+ * @param model - Color Model of Src pixels
+ * @param pixels - array of Src pixels
+ * @param off - offset into the Src pixels array
+ * @param scansize - length of scanline in the pixels array
+ */
+ private void setFilteredPixels(int x, int y, int w, int h, ColorModel model, Object pixels, int off, int scansize){
+ if(!inited){
+ initialize();
+ }
+
+ int srcX, srcY, dx, dy;
+ int svRest, dvRest, shRest, dhRest, vDif, hDif;
+
+ if(y == 0){
+ dy = 0;
+ dvRest = srcHeight;
+ }else{
+ dy = cachedDY;
+ dvRest = cachedDVRest;
+ }
+
+ srcY = y;
+ svRest = destHeight;
+
+ int srcOff = off;
+ while (srcY < y + h) {
+ if (svRest < dvRest) {
+ vDif = svRest;
+ } else {
+ vDif = dvRest;
+ }
+
+ srcX = 0;
+ dx = 0;
+ shRest = destWidth;
+ dhRest = srcWidth;
+ while (srcX < w) {
+ if (shRest < dhRest) {
+ hDif = shRest;
+ } else {
+ hDif = dhRest;
+ }
+ int avg = hDif * vDif; // calculation of contribution factor
+
+ int rgb, pix;
+ if (pixels instanceof int[]) {
+ pix = ((int[]) pixels)[srcOff + srcX];
+ } else {
+ pix = ((byte[]) pixels)[srcOff + srcX] & 0xff;
+ }
+
+ rgb = model.getRGB(pix);
+ int a = rgb >>> 24;
+ int r = (rgb >> 16) & 0xff;
+ int g = (rgb >> 8) & 0xff;
+ int b = rgb & 0xff;
+
+ // accumulating pixel's component values
+ sum_a[dx] += a * avg;
+ sum_r[dx] += r * avg;
+ sum_g[dx] += g * avg;
+ sum_b[dx] += b * avg;
+
+ shRest -= hDif;
+ dhRest -= hDif;
+
+ if (shRest == 0) {
+ srcX++;
+ shRest = destWidth;
+ }
+
+ if (dhRest == 0) {
+ dx++;
+ dhRest = srcWidth;
+ }
+ }
+
+ svRest -= vDif;
+ dvRest -= vDif;
+
+ if (svRest == 0) {
+ svRest = destHeight;
+ srcY++;
+ srcOff += scansize;
+ }
+
+ if (dvRest == 0) {
+ // averaging destination pixel's values
+ for(int i = 0; i < destWidth; i++){
+ int a = (sum_a[i] / avgFactor) & 0xff;
+ int r = (sum_r[i] / avgFactor) & 0xff;
+ int g = (sum_g[i] / avgFactor) & 0xff;
+ int b = (sum_b[i] / avgFactor) & 0xff;
+ int frgb = (a << 24) | (r << 16) | (g << 8) | b;
+ buff[i] = frgb;
+ }
+ consumer.setPixels(0, dy, destWidth, 1, rgbCM, buff, 0,
+ destWidth);
+ dy++;
+ dvRest = srcHeight;
+ Arrays.fill(sum_a, 0);
+ Arrays.fill(sum_r, 0);
+ Arrays.fill(sum_g, 0);
+ Arrays.fill(sum_b, 0);
+ }
+
+ }
+
+ cachedDY = dy;
+ cachedDVRest = dvRest;
+
+ }
+
+ /**
+ * Initialization of the auxiliary data.
+ */
+ private void initialize(){
+
+ sum_a = new int[destWidth];
+ sum_r = new int[destWidth];
+ sum_g = new int[destWidth];
+ sum_b = new int[destWidth];
+
+ buff = new int[destWidth];
+ outpixbuf = buff;
+ avgFactor = srcWidth * srcHeight;
+
+ inited = true;
+ }
+}
+
diff --git a/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java b/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java
new file mode 100644
index 0000000..ce85ddd
--- /dev/null
+++ b/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java
@@ -0,0 +1,153 @@
+/*
+ * 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$
+ * Created on 23.11.2005
+ *
+ */
+package java.awt.image;
+
+import java.awt.Image;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferDouble;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.DataBufferUShort;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.gl.GLVolatileImage;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.image.DataBufferListener;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * This class not part of public API. It useful for receiving package private
+ * data from other packages.
+ */
+class AwtImageBackdoorAccessorImpl extends AwtImageBackdoorAccessor {
+
+ static void init(){
+ inst = new AwtImageBackdoorAccessorImpl();
+ }
+
+ @Override
+ public Surface getImageSurface(Image image) {
+ if (image instanceof BufferedImage){
+ return ((BufferedImage)image).getImageSurface();
+ } else if (image instanceof GLVolatileImage){
+ return ((GLVolatileImage)image).getImageSurface();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGrayPallete(IndexColorModel icm){
+ return icm.isGrayPallete();
+ }
+
+ @Override
+ public Object getData(DataBuffer db) {
+ if (db instanceof DataBufferByte){
+ return ((DataBufferByte)db).getData();
+ } else if (db instanceof DataBufferUShort){
+ return ((DataBufferUShort)db).getData();
+ } else if (db instanceof DataBufferShort){
+ return ((DataBufferShort)db).getData();
+ } else if (db instanceof DataBufferInt){
+ return ((DataBufferInt)db).getData();
+ } else if (db instanceof DataBufferFloat){
+ return ((DataBufferFloat)db).getData();
+ } else if (db instanceof DataBufferDouble){
+ return ((DataBufferDouble)db).getData();
+ } else {
+ // awt.235=Wrong Data Buffer type : {0}
+ throw new IllegalArgumentException(Messages.getString("awt.235", //$NON-NLS-1$
+ db.getClass()));
+ }
+ }
+
+ @Override
+ public int[] getDataInt(DataBuffer db) {
+ if (db instanceof DataBufferInt){
+ return ((DataBufferInt)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public byte[] getDataByte(DataBuffer db) {
+ if (db instanceof DataBufferByte){
+ return ((DataBufferByte)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public short[] getDataShort(DataBuffer db) {
+ if (db instanceof DataBufferShort){
+ return ((DataBufferShort)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public short[] getDataUShort(DataBuffer db) {
+ if (db instanceof DataBufferUShort){
+ return ((DataBufferUShort)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public double[] getDataDouble(DataBuffer db) {
+ if (db instanceof DataBufferDouble){
+ return ((DataBufferDouble)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public float[] getDataFloat(DataBuffer db) {
+ if (db instanceof DataBufferFloat){
+ return ((DataBufferFloat)db).getData();
+ }
+ return null;
+ }
+
+ @Override
+ public void addDataBufferListener(DataBuffer db, DataBufferListener listener) {
+ db.addDataBufferListener(listener);
+ }
+
+ @Override
+ public void removeDataBufferListener(DataBuffer db) {
+ db.removeDataBufferListener();
+ }
+
+ @Override
+ public void validate(DataBuffer db) {
+ db.validate();
+ }
+
+ @Override
+ public void releaseData(DataBuffer db) {
+ db.releaseData();
+ }
+}
diff --git a/awt/java/awt/image/BandCombineOp.java b/awt/java/awt/image/BandCombineOp.java
new file mode 100644
index 0000000..cd77a21
--- /dev/null
+++ b/awt/java/awt/image/BandCombineOp.java
@@ -0,0 +1,610 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 20, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BandCombineOp class translates coordinates from
+ * coordinates in the source Raster to coordinates in
+ * the destination Raster by an arbitrary linear combination
+ * of the bands in a source Raster, using a specified matrix.
+ * The number of bands in the matrix should equal to
+ * the number of bands in the source Raster plus 1.
+ */
+public class BandCombineOp implements RasterOp {
+
+ /** The Constant offsets3c. */
+ static final int offsets3c[] = {16, 8, 0};
+
+ /** The Constant offsets4ac. */
+ static final int offsets4ac[] = {16, 8, 0, 24};
+
+ /** The Constant masks3c. */
+ static final int masks3c[] = {0xFF0000, 0xFF00, 0xFF};
+
+ /** The Constant masks4ac. */
+ static final int masks4ac[] = {0xFF0000, 0xFF00, 0xFF, 0xFF000000};
+
+ /** The Constant piOffsets. */
+ private static final int piOffsets[] = {0, 1, 2};
+
+ /** The Constant piInvOffsets. */
+ private static final int piInvOffsets[] = {2, 1, 0};
+
+ /** The Constant TYPE_BYTE3C. */
+ private static final int TYPE_BYTE3C = 0;
+
+ /** The Constant TYPE_BYTE4AC. */
+ private static final int TYPE_BYTE4AC = 1;
+
+ /** The Constant TYPE_USHORT3C. */
+ private static final int TYPE_USHORT3C = 2;
+
+ /** The Constant TYPE_SHORT3C. */
+ private static final int TYPE_SHORT3C = 3;
+
+ /** The mx width. */
+ private int mxWidth;
+
+ /** The mx height. */
+ private int mxHeight;
+
+ /** The matrix. */
+ private float matrix[][];
+
+ /** The r hints. */
+ private RenderingHints rHints;
+
+ static {
+ // XXX - todo
+ //System.loadLibrary("imageops");
+ }
+
+ /**
+ * Instantiates a new BandCombineOp object with the specified
+ * matrix.
+ *
+ * @param matrix the specified matrix for band combining.
+ * @param hints the RenderingHints.
+ */
+ public BandCombineOp(float matrix[][], RenderingHints hints) {
+ this.mxHeight = matrix.length;
+ this.mxWidth = matrix[0].length;
+ this.matrix = new float[mxHeight][mxWidth];
+
+ for (int i=0; i<mxHeight; i++){
+ System.arraycopy(matrix[i], 0, this.matrix[i], 0, mxWidth);
+ }
+
+ this.rHints = hints;
+ }
+
+ public final RenderingHints getRenderingHints(){
+ return this.rHints;
+ }
+
+ /**
+ * Gets the matrix associated with this BandCombineOp object.
+ *
+ * @return the matrix associated with this BandCombineOp object.
+ */
+ public final float[][] getMatrix() {
+ float res[][] = new float[mxHeight][mxWidth];
+
+ for (int i=0; i<mxHeight; i++) {
+ System.arraycopy(matrix[i], 0, res[i], 0, mxWidth);
+ }
+
+ return res;
+ }
+
+ public final Point2D getPoint2D (Point2D srcPoint, Point2D dstPoint) {
+ if (dstPoint == null) {
+ dstPoint = new Point2D.Float();
+ }
+
+ dstPoint.setLocation(srcPoint);
+ return dstPoint;
+ }
+
+ public final Rectangle2D getBounds2D(Raster src){
+ return src.getBounds();
+ }
+
+ public WritableRaster createCompatibleDestRaster (Raster src) {
+ int numBands = src.getNumBands();
+ if (mxWidth != numBands && mxWidth != (numBands+1) || numBands != mxHeight) {
+ // awt.254=Number of bands in the source raster ({0}) is
+ // incompatible with the matrix [{1}x{2}]
+ throw new IllegalArgumentException(Messages.getString("awt.254", //$NON-NLS-1$
+ new Object[]{numBands, mxWidth, mxHeight}));
+ }
+
+ return src.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+ }
+
+ public WritableRaster filter(Raster src, WritableRaster dst) {
+ int numBands = src.getNumBands();
+
+ if (mxWidth != numBands && mxWidth != (numBands+1)) {
+ // awt.254=Number of bands in the source raster ({0}) is
+ // incompatible with the matrix [{1}x{2}]
+ throw new IllegalArgumentException(
+ Messages.getString("awt.254", //$NON-NLS-1$
+ new Object[]{numBands, mxWidth, mxHeight}));
+ }
+
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else if (dst.getNumBands() != mxHeight) {
+ // awt.255=Number of bands in the destination raster ({0}) is incompatible with the matrix [{1}x{2}]
+ throw new IllegalArgumentException(Messages.getString("awt.255", //$NON-NLS-1$
+ new Object[]{dst.getNumBands(), mxWidth, mxHeight}));
+ }
+
+ // XXX - todo
+ //if (ippFilter(src, dst) != 0)
+ if (verySlowFilter(src, dst) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ return dst;
+ }
+
+ /**
+ * The Class SampleModelInfo.
+ */
+ private static final class SampleModelInfo {
+
+ /** The channels. */
+ int channels;
+
+ /** The channels order. */
+ int channelsOrder[];
+
+ /** The stride. */
+ int stride;
+ }
+
+ /**
+ * Check sample model.
+ *
+ * @param sm the sm
+ *
+ * @return the sample model info
+ */
+ private final SampleModelInfo checkSampleModel(SampleModel sm) {
+ SampleModelInfo ret = new SampleModelInfo();
+
+ if (sm instanceof PixelInterleavedSampleModel) {
+ // Check PixelInterleavedSampleModel
+ if (sm.getDataType() != DataBuffer.TYPE_BYTE) {
+ return null;
+ }
+
+ ret.channels = sm.getNumBands();
+ ret.stride = ((ComponentSampleModel) sm).getScanlineStride();
+ ret.channelsOrder = ((ComponentSampleModel) sm).getBandOffsets();
+
+ } else if (sm instanceof SinglePixelPackedSampleModel) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) sm;
+
+ ret.channels = sppsm1.getNumBands();
+ if (sppsm1.getDataType() != DataBuffer.TYPE_INT) {
+ return null;
+ }
+
+ // Check sample models
+ for (int i=0; i<ret.channels; i++) {
+ if (sppsm1.getSampleSize(i) != 8) {
+ return null;
+ }
+ }
+
+ ret.channelsOrder = new int[ret.channels];
+ int bitOffsets[] = sppsm1.getBitOffsets();
+ for (int i=0; i<ret.channels; i++) {
+ if (bitOffsets[i] % 8 != 0) {
+ return null;
+ }
+
+ ret.channelsOrder[i] = bitOffsets[i] / 8;
+ }
+
+ ret.channels = 4;
+ ret.stride = sppsm1.getScanlineStride() * 4;
+ } else {
+ return null;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the int
+ */
+ private final int slowFilter(Raster src, WritableRaster dst) {
+ int res = 0;
+
+ SampleModelInfo srcInfo, dstInfo;
+ int offsets[] = null;
+
+ srcInfo = checkSampleModel(src.getSampleModel());
+ dstInfo = checkSampleModel(dst.getSampleModel());
+ if (srcInfo == null || dstInfo == null) {
+ return verySlowFilter(src, dst);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+
+ int rmxWidth = (srcInfo.channels+1); // width of the reordered matrix
+ float reorderedMatrix[] = new float[rmxWidth*dstInfo.channels];
+ for (int j=0; j<dstInfo.channels; j++) {
+ if (j >= dstInfo.channelsOrder.length) {
+ continue;
+ }
+
+ for (int i=0; i<srcInfo.channels; i++) {
+ if (i >= srcInfo.channelsOrder.length) {
+ break;
+ }
+
+ reorderedMatrix[dstInfo.channelsOrder[j]*rmxWidth + srcInfo.channelsOrder[i]] =
+ matrix[j][i];
+ }
+ if (mxWidth == rmxWidth) {
+ reorderedMatrix[(dstInfo.channelsOrder[j]+1)*rmxWidth - 1] = matrix[j][mxWidth-1];
+ }
+ }
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ simpleCombineBands(
+ srcData, src.getWidth(), src.getHeight(), srcInfo.stride, srcInfo.channels,
+ dstData, dstInfo.stride, dstInfo.channels,
+ reorderedMatrix, offsets
+ );
+
+ return res;
+ }
+
+ /**
+ * Very slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the int
+ */
+ private int verySlowFilter(Raster src, WritableRaster dst) {
+ int numBands = src.getNumBands();
+
+ int srcMinX = src.getMinX();
+ int srcY = src.getMinY();
+
+ int dstMinX = dst.getMinX();
+ int dstY = dst.getMinY();
+
+ int dX = src.getWidth();//< dst.getWidth() ? src.getWidth() : dst.getWidth();
+ int dY = src.getHeight();//< dst.getHeight() ? src.getHeight() : dst.getHeight();
+
+ float sample;
+ int srcPixels[] = new int[numBands*dX*dY];
+ int dstPixels[] = new int[mxHeight*dX*dY];
+
+ srcPixels = src.getPixels(srcMinX, srcY, dX, dY, srcPixels);
+
+ if (numBands == mxWidth) {
+ for (int i=0, j=0; i<srcPixels.length; i+=numBands) {
+ for (int dstB = 0; dstB < mxHeight; dstB++) {
+ sample = 0f;
+ for (int srcB = 0; srcB < numBands; srcB++) {
+ sample += matrix[dstB][srcB] * srcPixels[i+srcB];
+ }
+ dstPixels[j++] = (int) sample;
+ }
+ }
+ } else {
+ for (int i=0, j=0; i<srcPixels.length; i+=numBands) {
+ for (int dstB = 0; dstB < mxHeight; dstB++) {
+ sample = 0f;
+ for (int srcB = 0; srcB < numBands; srcB++) {
+ sample += matrix[dstB][srcB] * srcPixels[i+srcB];
+ }
+ dstPixels[j++] = (int) (sample + matrix[dstB][numBands]);
+ }
+ }
+ }
+
+ dst.setPixels(dstMinX, dstY, dX, dY, dstPixels);
+
+ return 0;
+ }
+
+ //TODO remove when method is used
+ /**
+ * Ipp filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the int
+ */
+ @SuppressWarnings("unused")
+ private int ippFilter(Raster src, WritableRaster dst) {
+ boolean invertChannels;
+ boolean inPlace = (src == dst);
+ int type;
+ int srcStride, dstStride;
+ int offsets[] = null;
+
+ int srcBands = src.getNumBands();
+ int dstBands = dst.getNumBands();
+
+ if (
+ dstBands != 3 ||
+ (srcBands != 3 &&
+ !(srcBands == 4 &&
+ matrix[0][3] == 0 &&
+ matrix[1][3] == 0 &&
+ matrix[2][3] == 0)
+ )
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+
+ if (
+ srcSM instanceof SinglePixelPackedSampleModel &&
+ dstSM instanceof SinglePixelPackedSampleModel
+ ) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+ SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+ if (
+ sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+ sppsm2.getDataType() != DataBuffer.TYPE_INT
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ // Check sample models
+ if (
+ !Arrays.equals(sppsm2.getBitOffsets(), offsets3c) ||
+ !Arrays.equals(sppsm2.getBitMasks(), masks3c)
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ if (srcBands == 3) {
+ if (
+ !Arrays.equals(sppsm1.getBitOffsets(), offsets3c) ||
+ !Arrays.equals(sppsm1.getBitMasks(), masks3c)
+ ) {
+ return slowFilter(src, dst);
+ }
+ } else if (srcBands == 4) {
+ if (
+ !Arrays.equals(sppsm1.getBitOffsets(), offsets4ac) ||
+ !Arrays.equals(sppsm1.getBitMasks(), masks4ac)
+ ) {
+ return slowFilter(src, dst);
+ }
+ }
+
+ type = TYPE_BYTE4AC;
+ invertChannels = true;
+
+ srcStride = sppsm1.getScanlineStride() * 4;
+ dstStride = sppsm2.getScanlineStride() * 4;
+ } else if (
+ srcSM instanceof PixelInterleavedSampleModel &&
+ dstSM instanceof PixelInterleavedSampleModel
+ ) {
+ if (srcBands != 3) {
+ return slowFilter(src, dst);
+ }
+
+ int srcDataType = srcSM.getDataType();
+
+ switch (srcDataType) {
+ case DataBuffer.TYPE_BYTE:
+ type = TYPE_BYTE3C;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ type = TYPE_USHORT3C;
+ break;
+ case DataBuffer.TYPE_SHORT:
+ type = TYPE_SHORT3C;
+ break;
+ default:
+ return slowFilter(src, dst);
+ }
+
+ // Check PixelInterleavedSampleModel
+ PixelInterleavedSampleModel pism1 = (PixelInterleavedSampleModel) srcSM;
+ PixelInterleavedSampleModel pism2 = (PixelInterleavedSampleModel) dstSM;
+
+ if (
+ srcDataType != pism2.getDataType() ||
+ pism1.getPixelStride() != 3 ||
+ pism2.getPixelStride() != 3 ||
+ !Arrays.equals(pism1.getBandOffsets(), pism2.getBandOffsets())
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ if (Arrays.equals(pism1.getBandOffsets(), piInvOffsets)) {
+ invertChannels = true;
+ } else if (Arrays.equals(pism1.getBandOffsets(), piOffsets)) {
+ invertChannels = false;
+ } else {
+ return slowFilter(src, dst);
+ }
+
+ int dataTypeSize = DataBuffer.getDataTypeSize(srcDataType) / 8;
+
+ srcStride = pism1.getScanlineStride() * dataTypeSize;
+ dstStride = pism2.getScanlineStride() * dataTypeSize;
+ } else { // XXX - todo - IPP allows support for planar data also
+ return slowFilter(src, dst);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ float ippMatrix[] = new float[12];
+
+ if (invertChannels) {
+ // IPP treats big endian integers like BGR, so we have to
+ // swap columns 1 and 3 and rows 1 and 3
+ for (int i = 0; i < mxHeight; i++) {
+ ippMatrix[i*4] = matrix[2-i][2];
+ ippMatrix[i*4+1] = matrix[2-i][1];
+ ippMatrix[i*4+2] = matrix[2-i][0];
+
+ if (mxWidth == 4) {
+ ippMatrix[i*4+3] = matrix[2-i][3];
+ } else if (mxWidth == 5) {
+ ippMatrix[i*4+3] = matrix[2-i][4];
+ }
+ }
+ } else {
+ for (int i = 0; i < mxHeight; i++) {
+ ippMatrix[i*4] = matrix[i][0];
+ ippMatrix[i*4+1] = matrix[i][1];
+ ippMatrix[i*4+2] = matrix[i][2];
+
+ if (mxWidth == 4) {
+ ippMatrix[i*4+3] = matrix[i][3];
+ } else if (mxWidth == 5) {
+ ippMatrix[i*4+3] = matrix[i][4];
+ }
+ }
+ }
+
+ return ippColorTwist(
+ srcData, src.getWidth(), src.getHeight(), srcStride,
+ dstData, dst.getWidth(), dst.getHeight(), dstStride,
+ ippMatrix, type, offsets, inPlace);
+ }
+
+ /**
+ * Ipp color twist.
+ *
+ * @param srcData the src data
+ * @param srcWidth the src width
+ * @param srcHeight the src height
+ * @param srcStride the src stride
+ * @param dstData the dst data
+ * @param dstWidth the dst width
+ * @param dstHeight the dst height
+ * @param dstStride the dst stride
+ * @param ippMatrix the ipp matrix
+ * @param type the type
+ * @param offsets the offsets
+ * @param inPlace the in place
+ *
+ * @return the int
+ */
+ private final native int ippColorTwist(
+ Object srcData, int srcWidth, int srcHeight, int srcStride,
+ Object dstData, int dstWidth, int dstHeight, int dstStride,
+ float ippMatrix[], int type, int offsets[], boolean inPlace
+ );
+
+ /**
+ * Simple combine bands.
+ *
+ * @param srcData the src data
+ * @param srcWidth the src width
+ * @param srcHeight the src height
+ * @param srcStride the src stride
+ * @param srcChannels the src channels
+ * @param dstData the dst data
+ * @param dstStride the dst stride
+ * @param dstChannels the dst channels
+ * @param m the m
+ * @param offsets the offsets
+ *
+ * @return the int
+ */
+ private final native int simpleCombineBands(
+ Object srcData, int srcWidth, int srcHeight, int srcStride, int srcChannels,
+ Object dstData, int dstStride, int dstChannels,
+ float m[], int offsets[]
+ );
+}
diff --git a/awt/java/awt/image/BandedSampleModel.java b/awt/java/awt/image/BandedSampleModel.java
new file mode 100644
index 0000000..392e44c
--- /dev/null
+++ b/awt/java/awt/image/BandedSampleModel.java
@@ -0,0 +1,426 @@
+/*
+ * 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 org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BandedSampleModel class provides samples of pixels in an image
+ * which is stored in a band interleaved method. Each pixel's sample
+ * takes one data element of the DataBuffer. The pixel stride for a
+ * BandedSampleModel is one.
+ */
+public final class BandedSampleModel extends ComponentSampleModel {
+
+ /**
+ * Creates the indices.
+ *
+ * @param numBands the num bands
+ *
+ * @return the int[]
+ */
+ private static int[] createIndices(int numBands) {
+ int indices[] = new int[numBands];
+ for (int i = 0; i < numBands; i++) {
+ indices[i] = i;
+ }
+ return indices;
+ }
+
+ /**
+ * Creates the offsets.
+ *
+ * @param numBands the num bands
+ *
+ * @return the int[]
+ */
+ private static int[] createOffsets(int numBands) {
+ int offsets[] = new int[numBands];
+ for (int i = 0; i < numBands; i++) {
+ offsets[i] = 0;
+ }
+ return offsets;
+ }
+
+ /**
+ * Instantiates a new BandedSampleModel object with the specified
+ * data type of samples, the width, height and bands number
+ * of image data.
+ *
+ * @param dataType the data type of samples.
+ * @param w the width of image data.
+ * @param h the height of image data.
+ * @param numBands the number of bands.
+ */
+ public BandedSampleModel(int dataType, int w, int h, int numBands) {
+ this(dataType, w, h, w, BandedSampleModel.createIndices(numBands),
+ BandedSampleModel.createOffsets(numBands));
+ }
+
+ /**
+ * Instantiates a new BandedSampleModel object with the specified
+ * data type of samples, the width, height and bands number
+ * of image data.
+ *
+ * @param dataType the data type of samples.
+ * @param w the width of image data.
+ * @param h the height of image data.
+ * @param scanlineStride the scanline stride of the of the image data.
+ * @param bankIndices the array of the bank indecies.
+ * @param bandOffsets the array of the band offsets.
+ */
+ public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
+ int bankIndices[], int bandOffsets[]) {
+ super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ return new BandedSampleModel(dataType, w, h, w, bankIndices,
+ bandOffsets);
+ }
+
+ @Override
+ public DataBuffer createDataBuffer() {
+ DataBuffer data = null;
+ int size = scanlineStride * height;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(size, numBanks);
+ break;
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(size, numBanks);
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ data = new DataBufferFloat(size, numBanks);
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ data = new DataBufferDouble(size, numBanks);
+ break;
+ }
+
+ return data;
+
+ }
+
+ @Override
+ public SampleModel createSubsetSampleModel(int[] bands) {
+ if (bands.length > numBands) {
+ // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+ throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+ }
+
+ int indices[] = new int[bands.length];
+ int offsets[] = new int[bands.length];
+
+ for (int i = 0; i < bands.length; i++) {
+ indices[i] = bankIndices[bands[i]];
+ offsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new BandedSampleModel(dataType, width, height, scanlineStride,
+ indices, offsets);
+ }
+
+ @Override
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE: {
+ byte bdata[];
+
+ if (obj == null) {
+ bdata = new byte[numBands];
+ } else {
+ bdata = (byte[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ bdata[i] = (byte) getSample(x, y, i, data);
+ }
+
+ obj = bdata;
+ break;
+ }
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT: {
+ short sdata[];
+
+ if (obj == null) {
+ sdata = new short[numBands];
+ } else {
+ sdata = (short[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ sdata[i] = (short) getSample(x, y, i, data);
+ }
+
+ obj = sdata;
+ break;
+ }
+ case DataBuffer.TYPE_INT: {
+ int idata[];
+
+ if (obj == null) {
+ idata = new int[numBands];
+ } else {
+ idata = (int[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ idata[i] = getSample(x, y, i, data);
+ }
+
+ obj = idata;
+ break;
+ }
+ case DataBuffer.TYPE_FLOAT: {
+ float fdata[];
+
+ if (obj == null) {
+ fdata = new float[numBands];
+ } else {
+ fdata = (float[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ fdata[i] = getSampleFloat(x, y, i, data);
+ }
+
+ obj = fdata;
+ break;
+ }
+ case DataBuffer.TYPE_DOUBLE: {
+ double ddata[];
+
+ if (obj == null) {
+ ddata = new double[numBands];
+ } else {
+ ddata = (double[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ ddata[i] = getSampleDouble(x, y, i, data);
+ }
+
+ obj = ddata;
+ break;
+ }
+ }
+
+ return obj;
+ }
+
+ @Override
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ int pixel[];
+ if (iArray == null) {
+ pixel = new int[numBands];
+ } else {
+ pixel = iArray;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ pixel[i] = getSample(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ @Override
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElem(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b]);
+ }
+
+ @Override
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElemDouble(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b]);
+ }
+
+ @Override
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElemFloat(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b]);
+ }
+
+ @Override
+ public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ int samples[];
+ int idx = 0;
+
+ if (iArray == null) {
+ samples = new int[w * h];
+ } else {
+ samples = iArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSample(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ int tmp = hash >>> 8;
+ hash <<= 8;
+ hash |= tmp;
+
+ return hash ^ 0x55;
+ }
+
+ @Override
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ byte bdata[] = (byte[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, bdata[i] & 0xff, data);
+ }
+ break;
+
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short sdata[] = (short[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, sdata[i] & 0xffff, data);
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int idata[] = (int[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, idata[i], data);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float fdata[] = (float[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, fdata[i], data);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double ddata[] = (double[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, ddata[i], data);
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, iArray[i], data);
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ int idx = 0;
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ setSample(j, i, n, iArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, double s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElemDouble(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b], s);
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, float s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElemFloat(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b], s);
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, int s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElem(bankIndices[b], y * scanlineStride + x +
+ bandOffsets[b], s);
+ }
+
+ @Override
+ public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ int idx = 0;
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(j, i, b, iArray[idx++], data);
+ }
+ }
+
+ }
+
+}
+
diff --git a/awt/java/awt/image/BufferStrategy.java b/awt/java/awt/image/BufferStrategy.java
new file mode 100644
index 0000000..e0508f0
--- /dev/null
+++ b/awt/java/awt/image/BufferStrategy.java
@@ -0,0 +1,72 @@
+/*
+ * 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.BufferCapabilities;
+import java.awt.Graphics;
+
+/**
+ * The BufferStrategy abstract class provides an opportunity
+ * to organize the buffers for a Canvas or Window. The BufferStrategy
+ * implementation depends on hardware and software limitations.
+ * These limitations are detectible through the capabilities
+ * object which can be obtained by the GraphicsConfiguration of the Canvas
+ * or Window.
+ */
+public abstract class BufferStrategy {
+
+ /**
+ * Returns true if the drawing buffer was lost since the last call
+ * of getDrawGraphics.
+ *
+ * @return true if the drawing buffer was lost since the last call
+ * of getDrawGraphics, false otherwise.
+ */
+ public abstract boolean contentsLost();
+
+ /**
+ * Returns true if the drawing buffer is restored from a lost state.
+ *
+ * @return true if the drawing buffer is restored from a lost state,
+ * false otherwise.
+ */
+ public abstract boolean contentsRestored();
+
+ /**
+ * Gets the BufferCapabilities of BufferStrategy.
+ *
+ * @return the BufferCapabilities of BufferStrategy.
+ */
+ public abstract BufferCapabilities getCapabilities();
+
+ /**
+ * Gets the Graphics object to use to draw to the buffer.
+ *
+ * @return the Graphics object to use to draw to the buffer.
+ */
+ public abstract Graphics getDrawGraphics();
+
+ /**
+ * Shows the next available buffer.
+ */
+ public abstract void show();
+
+}
diff --git a/awt/java/awt/image/BufferedImage.java b/awt/java/awt/image/BufferedImage.java
new file mode 100644
index 0000000..d305d66
--- /dev/null
+++ b/awt/java/awt/image/BufferedImage.java
@@ -0,0 +1,931 @@
+/*
+ * 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 com.android.internal.awt.AndroidGraphics2D;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.harmony.awt.gl.ImageSurface;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.image.BufferedImageSource;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+
+/**
+ * The BufferedImage class describes an Image which contains a buffer
+ * of image data and includes a ColorModel and a Raster for this data.
+ * This class provides methods for obtaining and setting the Raster
+ * and for manipulating the ColorModel parameters.
+ */
+public class BufferedImage extends
+Image implements WritableRenderedImage, Transparency{
+
+ /**
+ * The Constant TYPE_CUSTOM indicates that Image type
+ * is unknown.
+ */
+ public static final int TYPE_CUSTOM = 0;
+
+ /**
+ * The Constant TYPE_INT_RGB indicates an image with
+ * 8 bit RGB color components, it has a DirectColorModel
+ * without alpha.
+ */
+ public static final int TYPE_INT_RGB = 1;
+
+ /**
+ * The Constant TYPE_INT_ARGB indicates an image with
+ * 8 bit RGBA color components, it has a DirectColorModel
+ * with alpha.
+ */
+ public static final int TYPE_INT_ARGB = 2;
+
+ /**
+ * The Constant TYPE_INT_ARGB_PRE indicates an image with
+ * 8 bit RGBA color components, it has a DirectColorModel
+ * with alpha, and image data is premultiplied by alpha.
+ */
+ public static final int TYPE_INT_ARGB_PRE = 3;
+
+ /**
+ * The Constant TYPE_INT_BGR indicates an image with
+ * 8 bit RGB color components, BGR color model
+ * (with the colors Blue, Green, and Red). There is no
+ * alpha. The image has a DirectColorModel.
+ */
+ public static final int TYPE_INT_BGR = 4;
+
+ /**
+ * The Constant TYPE_3BYTE_BGR indicates an image with
+ * 8 bit RGB color components, BGR color model
+ * (with the colors Blue, Green, and Red stored in 3 bytes).
+ * There is no alpha. The image has a ComponentColorModel.
+ */
+ public static final int TYPE_3BYTE_BGR = 5;
+
+ /**
+ * The Constant TYPE_4BYTE_ABGR indicates an image with
+ * 8 bit RGBA color components stored in 3 bytes and 1 byte of alpha.
+ * It has a ComponentColorModel with alpha.
+ */
+ public static final int TYPE_4BYTE_ABGR = 6;
+
+ /**
+ * The Constant TYPE_4BYTE_ABGR_PRE indicates an image with
+ * 8 bit RGBA color components stored in 3 bytes and 1 byte
+ * for alpha. The image has a ComponentColorModel with alpha.
+ * The color data is premultiplied with alpha.
+ */
+ public static final int TYPE_4BYTE_ABGR_PRE = 7;
+
+ /**
+ * The Constant TYPE_USHORT_565_RGB indicates an image with
+ * 565 RGB color components (5-bits red, 6-bits green, 5-bits blue)
+ * with no alpha. This image has a DirectColorModel.
+ */
+ public static final int TYPE_USHORT_565_RGB = 8;
+
+ /**
+ * The Constant TYPE_USHORT_555_RGB indicates an image with
+ * 555 RGB color components (5-bits red, 5-bits green, 5-bits blue)
+ * with no alpha. This image has a DirectColorModel.
+ */
+ public static final int TYPE_USHORT_555_RGB = 9;
+
+ /**
+ * The Constant TYPE_BYTE_GRAY indicates a unsigned byte
+ * image. This image has a ComponentColorModel with
+ * a CS_GRAY ColorSpace.
+ */
+ public static final int TYPE_BYTE_GRAY = 10;
+
+ /**
+ * The Constant TYPE_USHORT_GRAY indicates an unsigned short
+ * image. This image has a ComponentColorModel with a CS_GRAY
+ * ColorSpace.
+ */
+ public static final int TYPE_USHORT_GRAY = 11;
+
+ /**
+ * The Constant TYPE_BYTE_BINARY indicates an opaque byte-packed
+ * 1, 2 or 4 bit image. The image has an IndexColorModel without
+ * alpha.
+ */
+ public static final int TYPE_BYTE_BINARY = 12;
+
+ /**
+ * The Constant TYPE_BYTE_INDEXED indicates an indexed byte image.
+ */
+ public static final int TYPE_BYTE_INDEXED = 13;
+
+ /** The Constant ALPHA_MASK. */
+ private static final int ALPHA_MASK = 0xff000000;
+
+ /** The Constant RED_MASK. */
+ private static final int RED_MASK = 0x00ff0000;
+
+ /** The Constant GREEN_MASK. */
+ private static final int GREEN_MASK = 0x0000ff00;
+
+ /** The Constant BLUE_MASK. */
+ private static final int BLUE_MASK = 0x000000ff;
+
+ /** The Constant RED_BGR_MASK. */
+ private static final int RED_BGR_MASK = 0x000000ff;
+
+ /** The Constant GREEN_BGR_MASK. */
+ private static final int GREEN_BGR_MASK = 0x0000ff00;
+
+ /** The Constant BLUE_BGR_MASK. */
+ private static final int BLUE_BGR_MASK = 0x00ff0000;
+
+ /** The Constant RED_565_MASK. */
+ private static final int RED_565_MASK = 0xf800;
+
+ /** The Constant GREEN_565_MASK. */
+ private static final int GREEN_565_MASK = 0x07e0;
+
+ /** The Constant BLUE_565_MASK. */
+ private static final int BLUE_565_MASK = 0x001f;
+
+ /** The Constant RED_555_MASK. */
+ private static final int RED_555_MASK = 0x7c00;
+
+ /** The Constant GREEN_555_MASK. */
+ private static final int GREEN_555_MASK = 0x03e0;
+
+ /** The Constant BLUE_555_MASK. */
+ private static final int BLUE_555_MASK = 0x001f;
+
+ /** The cm. */
+ private ColorModel cm;
+
+ /** The raster. */
+ private final WritableRaster raster;
+
+ /** The image type. */
+ private final int imageType;
+
+ /** The properties. */
+ private Hashtable<?, ?> properties;
+
+ // Surface of the Buffered Image - used for blitting one Buffered Image
+ // on the other one or on the Component
+ /** The image surf. */
+ private final ImageSurface imageSurf;
+
+ /**
+ * Instantiates a new BufferedImage with the specified ColorModel,
+ * and WritableRaster objects. The Raster data can be
+ * be divided or multiplied by alpha. It depends on the
+ * alphaPremultiplied state in the ColorModel.
+ *
+ * @param cm the ColorModel of the new image.
+ * @param raster the WritableRaster of the new image.
+ * @param isRasterPremultiplied if true the data of the specified
+ * Raster is premultiplied by alpha.
+ * @param properties the properties of new Image.
+ */
+ public BufferedImage(ColorModel cm, WritableRaster raster,
+ boolean isRasterPremultiplied, Hashtable<?, ?> properties) {
+ if (!cm.isCompatibleRaster(raster)) {
+ // awt.4D=The raster is incompatible with this ColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$
+ }
+
+ if (raster.getMinX() != 0 || raster.getMinY() != 0) {
+ // awt.228=minX or minY of this raster not equal to zero
+ throw new IllegalArgumentException(Messages.getString("awt.228")); //$NON-NLS-1$
+ }
+
+ this.cm = cm;
+ this.raster = raster;
+ this.properties = properties;
+
+ coerceData(isRasterPremultiplied);
+
+ imageType = Surface.getType(cm, raster);
+
+ imageSurf = createImageSurface(imageType);
+ }
+
+ /**
+ * Instantiates a new BufferedImage with the specified width, height
+ * predefined image type (TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED)
+ * and the specified IndexColorModel.
+ *
+ * @param width the width of new image.
+ * @param height the height of new image.
+ * @param imageType the predefined image type.
+ * @param cm the specified IndexColorModel.
+ */
+ public BufferedImage(int width, int height, int imageType,
+ IndexColorModel cm) {
+ switch (imageType) {
+ case TYPE_BYTE_BINARY:
+ if (cm.hasAlpha()) {
+ // awt.227=This image type can't have alpha
+ throw new IllegalArgumentException(Messages.getString("awt.227")); //$NON-NLS-1$
+ }
+ int pixel_bits = 0;
+ int mapSize = cm.getMapSize();
+ if (mapSize <= 2) {
+ pixel_bits = 1;
+ } else if (mapSize <= 4) {
+ pixel_bits = 2;
+ } else if (mapSize <= 16) {
+ pixel_bits = 4;
+ } else {
+ // awt.221=The imageType is TYPE_BYTE_BINARY and the color map has more than 16 entries
+ throw new IllegalArgumentException(Messages.getString("awt.221")); //$NON-NLS-1$
+ }
+
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width,
+ height, 1, pixel_bits, null);
+ break;
+
+ case TYPE_BYTE_INDEXED:
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ width, height, 1, null);
+ break;
+
+ default:
+ // awt.222=The imageType is not TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED
+ throw new IllegalArgumentException(Messages.getString("awt.222")); //$NON-NLS-1$
+
+ }
+
+ if (!cm.isCompatibleRaster(raster)) {
+ // awt.223=The imageType is not compatible with ColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.223")); //$NON-NLS-1$
+ }
+
+ this.cm = cm;
+ this.imageType = imageType;
+ imageSurf = createImageSurface(imageType);
+
+ }
+
+ /**
+ * Instantiates a new BufferedImage with the specified width, height
+ * and predefined image type.
+ *
+ * @param width the width of new image.
+ * @param height the height of new image.
+ * @param imageType the predefined image type.
+ */
+ public BufferedImage(int width, int height, int imageType) {
+
+ switch (imageType) {
+ case TYPE_INT_RGB:
+ cm = new DirectColorModel(24, RED_MASK, GREEN_MASK, BLUE_MASK);
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_INT_ARGB:
+ cm = ColorModel.getRGBdefault();
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_INT_ARGB_PRE:
+ cm = new DirectColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32,
+ RED_MASK,
+ GREEN_MASK,
+ BLUE_MASK,
+ ALPHA_MASK,
+ true,
+ DataBuffer.TYPE_INT);
+
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_INT_BGR:
+ cm = new DirectColorModel(24,
+ RED_BGR_MASK,
+ GREEN_BGR_MASK,
+ BLUE_BGR_MASK);
+
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_3BYTE_BGR: {
+ int bits[] = { 8, 8, 8 };
+ int bandOffsets[] = { 2, 1, 0 };
+ cm = new ComponentColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ bits,
+ false,
+ false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ width, height, width * 3, 3, bandOffsets, null);
+ }
+ break;
+
+ case TYPE_4BYTE_ABGR: {
+ int bits[] = { 8, 8, 8, 8 };
+ int bandOffsets[] = { 3, 2, 1, 0 };
+ cm = new ComponentColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ bits,
+ true,
+ false,
+ Transparency.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
+
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ width, height, width * 4, 4, bandOffsets, null);
+ }
+ break;
+
+ case TYPE_4BYTE_ABGR_PRE: {
+ int bits[] = { 8, 8, 8, 8 };
+ int bandOffsets[] = { 3, 2, 1, 0 };
+ cm = new ComponentColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ bits,
+ true,
+ true,
+ Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
+
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ width, height, width * 4, 4, bandOffsets, null);
+ }
+ break;
+
+ case TYPE_USHORT_565_RGB:
+ cm = new DirectColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 16,
+ RED_565_MASK,
+ GREEN_565_MASK,
+ BLUE_565_MASK,
+ 0,
+ false,
+ DataBuffer.TYPE_USHORT);
+
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_USHORT_555_RGB:
+ cm = new DirectColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 15,
+ RED_555_MASK,
+ GREEN_555_MASK,
+ BLUE_555_MASK,
+ 0,
+ false,
+ DataBuffer.TYPE_USHORT);
+
+ raster = cm.createCompatibleWritableRaster(width, height);
+ break;
+
+ case TYPE_BYTE_GRAY: {
+ int bits[] = { 8 };
+ cm = new ComponentColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_GRAY),
+ bits,
+ false,
+ false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+
+ raster = cm.createCompatibleWritableRaster(width, height);
+ }
+ break;
+
+ case TYPE_USHORT_GRAY: {
+ int bits[] = { 16 };
+ cm = new ComponentColorModel(
+ ColorSpace.getInstance(ColorSpace.CS_GRAY),
+ bits,
+ false,
+ false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_USHORT);
+ raster = cm.createCompatibleWritableRaster(width, height);
+ }
+ break;
+
+ case TYPE_BYTE_BINARY: {
+ int colorMap[] = { 0, 0xffffff };
+ cm = new IndexColorModel(1, 2, colorMap, 0, false, -1,
+ DataBuffer.TYPE_BYTE);
+
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width,
+ height, 1, 1, null);
+ }
+ break;
+
+ case TYPE_BYTE_INDEXED: {
+ int colorMap[] = new int[256];
+ int i = 0;
+ for (int r = 0; r < 256; r += 51) {
+ for (int g = 0; g < 256; g += 51) {
+ for (int b = 0; b < 256; b += 51) {
+ colorMap[i] = (r << 16) | (g << 8) | b;
+ i++;
+ }
+ }
+ }
+
+ int gray = 0x12;
+ for (; i < 256; i++, gray += 6) {
+ colorMap[i] = (gray << 16) | (gray << 8) | gray;
+ }
+ cm = new IndexColorModel(8, 256, colorMap, 0, false, -1,
+ DataBuffer.TYPE_BYTE);
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ width, height, 1, null);
+
+ }
+ break;
+ default:
+ // awt.224=Unknown image type
+ throw new IllegalArgumentException(Messages.getString("awt.224")); //$NON-NLS-1$
+ }
+ this.imageType = imageType;
+ imageSurf = createImageSurface(imageType);
+ }
+
+ @Override
+ public Object getProperty(String name, ImageObserver observer) {
+ return getProperty(name);
+ }
+
+ public Object getProperty(String name) {
+ if(name == null) {
+ // awt.225=Property name is null
+ throw new NullPointerException(Messages.getString("awt.225")); //$NON-NLS-1$
+ }
+ if (properties == null) {
+ return Image.UndefinedProperty;
+ }
+ Object property = properties.get(name);
+ if (property == null) {
+ property = Image.UndefinedProperty;
+ }
+ return property;
+ }
+
+ public WritableRaster copyData(WritableRaster outRaster) {
+ if (outRaster == null) {
+ outRaster = Raster.createWritableRaster(raster.getSampleModel(),
+ new Point(raster.getSampleModelTranslateX(),
+ raster.getSampleModelTranslateY()));
+ }
+
+ int w = outRaster.getWidth();
+ int h = outRaster.getHeight();
+ int minX = outRaster.getMinX();
+ int minY = outRaster.getMinY();
+
+ Object data = null;
+
+ data = raster.getDataElements(minX, minY, w, h, data);
+ outRaster.setDataElements(minX, minY, w, h, data);
+
+ return outRaster;
+ }
+
+ public Raster getData(Rectangle rect) {
+ int minX = rect.x;
+ int minY = rect.y;
+ int w = rect.width;
+ int h = rect.height;
+
+ SampleModel sm = raster.getSampleModel();
+ SampleModel nsm = sm.createCompatibleSampleModel(w, h);
+ WritableRaster outr = Raster.createWritableRaster(nsm,
+ rect.getLocation());
+ Object data = null;
+
+ data = raster.getDataElements(minX, minY, w, h, data);
+ outr.setDataElements(minX, minY, w, h, data);
+ return outr;
+ }
+
+ public Vector<RenderedImage> getSources() {
+ return null;
+ }
+
+ public String[] getPropertyNames() {
+ if (properties == null) {
+ return null;
+ }
+ Vector<String> v = new Vector<String>();
+ for (Enumeration<?> e = properties.keys(); e.hasMoreElements();) {
+ try {
+ v.add((String) e.nextElement());
+ } catch (ClassCastException ex) {
+ }
+ }
+ int size = v.size();
+ if (size > 0) {
+ String names[] = new String[size];
+ for (int i = 0; i < size; i++) {
+ names[i] = v.elementAt(i);
+ }
+ return names;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the string representation of this BufferedImage object.
+ *
+ * @return the string representation of this BufferedImage object.
+ */
+ @Override
+ public String toString() {
+ return "BufferedImage@" + Integer.toHexString(hashCode()) + //$NON-NLS-1$
+ ": type = " + imageType + " " + cm + " " + raster; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ public WritableRaster getWritableTile(int tileX, int tileY) {
+ return raster;
+ }
+
+ /**
+ * Gets the WritableRaster of this BufferedImage.
+ *
+ * @return the WritableRaster of this BufferedImage.
+ */
+ public WritableRaster getRaster() {
+ return raster;
+ }
+
+ /**
+ * Gets a WritableRaster object which contains the alpha channel of
+ * BufferedImage object with ColorModel objects that supports
+ * a separate alpha channel such as ComponentColorModel
+ * or DirectColorModel.
+ *
+ * @return the WritableRaster object which contains the alpha
+ * channel of this BufferedImage.
+ */
+ public WritableRaster getAlphaRaster() {
+ return cm.getAlphaRaster(raster);
+ }
+
+ public void removeTileObserver(TileObserver to) {
+ }
+
+ public void addTileObserver(TileObserver to) {
+ }
+
+ public SampleModel getSampleModel() {
+ return raster.getSampleModel();
+ }
+
+ public void setData(Raster r) {
+
+ Rectangle from = r.getBounds();
+ Rectangle to = raster.getBounds();
+ Rectangle intersection = to.intersection(from);
+
+ int minX = intersection.x;
+ int minY = intersection.y;
+ int w = intersection.width;
+ int h = intersection.height;
+
+ Object data = null;
+
+ data = r.getDataElements(minX, minY, w, h, data);
+ raster.setDataElements(minX, minY, w, h, data);
+ }
+
+ public Raster getTile(int tileX, int tileY) {
+ if (tileX == 0 && tileY == 0) {
+ return raster;
+ }
+ // awt.226=Both tileX and tileY are not equal to 0
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
+ }
+
+ public Raster getData() {
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+ int minX = raster.getMinX();
+ int minY = raster.getMinY();
+
+ WritableRaster outr = Raster.createWritableRaster(
+ raster.getSampleModel(),
+ new Point(raster.getSampleModelTranslateX(),
+ raster.getSampleModelTranslateY()));
+
+ Object data = null;
+
+ data = raster.getDataElements(minX, minY, w, h, data);
+ outr.setDataElements(minX, minY, w, h, data);
+
+ return outr;
+ }
+
+ @Override
+ public ImageProducer getSource() {
+ return new BufferedImageSource(this, properties);
+ }
+
+ @Override
+ public int getWidth(ImageObserver observer) {
+ return raster.getWidth();
+ }
+
+ @Override
+ public int getHeight(ImageObserver observer) {
+ return raster.getHeight();
+ }
+
+ public ColorModel getColorModel() {
+ return cm;
+ }
+
+ /**
+ * Gets the rectangular area of this BufferedImage as a subimage.
+ *
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ * @param w the width of the subimage.
+ * @param h the height of the subimage.
+ *
+ * @return the BufferedImage.
+ */
+ public BufferedImage getSubimage(int x, int y, int w, int h) {
+ WritableRaster wr = raster.createWritableChild(x, y, w, h, 0, 0, null);
+ return new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), properties);
+ }
+
+ public Point[] getWritableTileIndices() {
+ Point points[] = new Point[1];
+ points[0] = new Point(0, 0);
+ return points;
+ }
+
+ /**
+ * Creates the Graphics2D object which allows to draw into
+ * this BufferedImage.
+ *
+ * @return the graphics2D object.
+ */
+ public Graphics2D createGraphics() {
+ GraphicsEnvironment ge =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ //return ge.createGraphics(this);
+ //???AWT hack, FIXME
+ //return AndroidGraphics2D.getInstance();
+ //throw new RuntimeException("Not implemented!");
+ return null;
+ }
+
+ @Override
+ public Graphics getGraphics() {
+ return createGraphics();
+ }
+
+ /**
+ * Coerces the data to achieve the state which is specified by
+ * the isAlphaPremultiplied variable.
+ *
+ * @param isAlphaPremultiplied the is alpha premultiplied state.
+ */
+ public void coerceData(boolean isAlphaPremultiplied) {
+ if (cm.hasAlpha() &&
+ cm.isAlphaPremultiplied() != isAlphaPremultiplied) {
+ cm = cm.coerceData(raster, isAlphaPremultiplied);
+ }
+ }
+
+ /**
+ * Gets an array of colors in the TYPE_INT_ARGB color model and
+ * default sRGB colorspace of the specified area of this
+ * BufferedImage. The result array is composed by the following
+ * algirithm:
+ * <p>
+ * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]
+ *
+ * @param startX the start X area coordinate.
+ * @param startY the start Y area coordinate.
+ * @param w the width of the area.
+ * @param h the height of the area.
+ * @param rgbArray the result array will be stored to this array.
+ * @param offset the offset of the rgbArray array.
+ * @param scansize the scanline stride for the rgbArray.
+ *
+ * @return an array of colors for the specified area.
+ */
+ public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray,
+ int offset, int scansize) {
+ if (rgbArray == null) {
+ rgbArray = new int[offset + h * scansize];
+ }
+
+ int off = offset;
+ for (int y = startY; y < startY + h; y++, off += scansize) {
+ int i = off;
+ for (int x = startX; x < startX + w; x++, i++) {
+ rgbArray[i] = cm.getRGB(raster.getDataElements(x, y, null));
+ }
+ }
+ return rgbArray;
+ }
+
+ /**
+ * Sets RGB values from the specified array to the specified
+ * BufferedImage area. The pixels are in the default RGB color model
+ * (TYPE_INT_ARGB) and default sRGB color space.
+ *
+ * @param startX the start X coordinate.
+ * @param startY the start Y coordinate.
+ * @param w the width of the BufferedImage area.
+ * @param h the height of the BufferedImage area.
+ * @param rgbArray the array of RGB values.
+ * @param offset the offset of the rgbArray array.
+ * @param scansize the scanline stride for the rgbArray.
+ */
+ public void setRGB(int startX, int startY, int w, int h, int[] rgbArray,
+ int offset, int scansize) {
+ int off = offset;
+ for (int y = startY; y < startY + h; y++, off += scansize) {
+ int i = off;
+ for (int x = startX; x < startX + w; x++, i++) {
+ raster.setDataElements(x, y,
+ cm.getDataElements(rgbArray[i], null));
+ }
+ }
+ }
+
+ /**
+ * Sets a the specified RGB value to the specified pixel of
+ * this BufferedImage. The pixel should be in the default
+ * RGB color model (TYPE_INT_ARGB) and default sRGB color space.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param rgb the RGB value to be set.
+ */
+ public synchronized void setRGB(int x, int y, int rgb) {
+ raster.setDataElements(x, y, cm.getDataElements(rgb, null));
+ }
+
+ public boolean isTileWritable(int tileX, int tileY) {
+ if (tileX == 0 && tileY == 0) {
+ return true;
+ }
+ // awt.226=Both tileX and tileY are not equal to 0
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
+ }
+
+ public void releaseWritableTile(int tileX, int tileY) {
+ }
+
+ /**
+ * Gets a color in the TYPE_INT_ARGB color model and default
+ * sRGB colorspace of the specified pixel.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ *
+ * @return the color of the specified pixel in the TYPE_INT_ARGB
+ * color model and default sRGB colorspace.
+ */
+ public int getRGB(int x, int y) {
+ return cm.getRGB(raster.getDataElements(x, y, null));
+ }
+
+ /**
+ * Returnes true if alpha is premultiplied,
+ * false if alpha is not premultiplied or there is no alpha.
+ *
+ * @return true if alpha is premultiplied,
+ * false if alpha is not premultiplied or there is no alpha.
+ */
+ public boolean isAlphaPremultiplied() {
+ return cm.isAlphaPremultiplied();
+ }
+
+ public boolean hasTileWriters() {
+ return true;
+ }
+
+ @Override
+ public void flush() {
+ imageSurf.dispose();
+ }
+
+ public int getWidth() {
+ return raster.getWidth();
+ }
+
+ /**
+ * Gets the image type.
+ *
+ * @return the image type.
+ */
+ public int getType() {
+ return imageType;
+ }
+
+ public int getTileWidth() {
+ return raster.getWidth();
+ }
+
+ public int getTileHeight() {
+ return raster.getHeight();
+ }
+
+ public int getTileGridYOffset() {
+ return raster.getSampleModelTranslateY();
+ }
+
+ public int getTileGridXOffset() {
+ return raster.getSampleModelTranslateX();
+ }
+
+ public int getNumYTiles() {
+ return 1;
+ }
+
+ public int getNumXTiles() {
+ return 1;
+ }
+
+ public int getMinY() {
+ return raster.getMinY();
+ }
+
+ public int getMinX() {
+ return raster.getMinX();
+ }
+
+ public int getMinTileY() {
+ return 0;
+ }
+
+ public int getMinTileX() {
+ return 0;
+ }
+
+ public int getHeight() {
+ return raster.getHeight();
+ }
+
+ /**
+ * Creates the image surface.
+ *
+ * @param type the type
+ *
+ * @return the image surface
+ */
+ private ImageSurface createImageSurface(int type) {
+ return new ImageSurface(getColorModel(), getRaster(), type);
+ }
+
+ /**
+ * Gets the image surface.
+ *
+ * @return the image surface
+ */
+ ImageSurface getImageSurface() {
+ return imageSurf;
+ }
+
+ public int getTransparency() {
+ return cm.getTransparency();
+ }
+}
+
diff --git a/awt/java/awt/image/BufferedImageFilter.java b/awt/java/awt/image/BufferedImageFilter.java
new file mode 100644
index 0000000..44b3c2e
--- /dev/null
+++ b/awt/java/awt/image/BufferedImageFilter.java
@@ -0,0 +1,375 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BufferedImageFilter class provides filtering operations to
+ * the BufferedImage objects using operators which implement
+ * BufferedImageOp interface.
+ */
+public class BufferedImageFilter extends ImageFilter implements Cloneable {
+
+ /** The Constant accessor. */
+ private static final AwtImageBackdoorAccessor accessor = AwtImageBackdoorAccessor.getInstance();
+
+ /** The op. */
+ private BufferedImageOp op;
+
+ /** The raster. */
+ private WritableRaster raster;
+
+ /** The i data. */
+ private int iData[];
+
+ /** The b data. */
+ private byte bData[];
+
+ /** The width. */
+ private int width;
+
+ /** The height. */
+ private int height;
+
+ /** The cm. */
+ private ColorModel cm;
+
+ /** The forced rgb. */
+ private boolean forcedRGB = false;
+
+ /** The transfer type. */
+ private int transferType = DataBuffer.TYPE_UNDEFINED;
+
+ /**
+ * Instantiates a new BufferedImageFilter with the specified
+ * BufferedImageOp operator.
+ *
+ * @param op the specified BufferedImageOp operator.
+ *
+ * @throws NullPointerException if BufferedImageOp is null.
+ */
+ public BufferedImageFilter(BufferedImageOp op) {
+ if (op == null) {
+ throw new NullPointerException(Messages.getString("awt.05")); //$NON-NLS-1$
+ }
+ this.op = op;
+ }
+
+ /**
+ * Gets the BufferedImageOp operator associated with this
+ * BufferedImageFilter object.
+ *
+ * @return the BufferedImageOp associated with this
+ * BufferedImageFilter object.
+ */
+ public BufferedImageOp getBufferedImageOp() {
+ return op;
+ }
+
+ @Override
+ public void setDimensions(int width, int height) {
+ this.width = width;
+ this.height = height;
+ // Stop image consuming if no pixels expected.
+ if (width <= 0 || height <= 0) {
+ consumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ reset();
+ }
+ }
+
+ @Override
+ public void setColorModel(ColorModel model) {
+ if (this.cm != null && this.cm != model && raster != null) {
+ forceRGB();
+ } else {
+ this.cm = model;
+ }
+ }
+
+ @Override
+ public void setPixels(
+ int x, int y, int
+ w, int h,
+ ColorModel model, byte[] pixels,
+ int off, int scansize
+ ) {
+ setPixels(x, y, w, h, model, pixels, off, scansize, true);
+ }
+
+ @Override
+ public void setPixels(
+ int x, int y,
+ int w, int h,
+ ColorModel model, int[] pixels,
+ int off, int scansize
+ ) {
+ setPixels(x, y, w, h, model, pixels, off, scansize, false);
+ }
+
+ @Override
+ public void imageComplete(int status) {
+ if (status == STATICIMAGEDONE || status == SINGLEFRAMEDONE) {
+ BufferedImage bim = new BufferedImage(cm, raster, cm.isAlphaPremultiplied, null);
+ bim = op.filter(bim, null);
+ DataBuffer dstDb = bim.getRaster().getDataBuffer();
+ ColorModel dstCm = bim.getColorModel();
+ int dstW = bim.getWidth();
+ int dstH = bim.getHeight();
+
+ consumer.setDimensions(dstW, dstH);
+
+ if (dstDb.getDataType() == DataBuffer.TYPE_INT) {
+ consumer.setColorModel(dstCm);
+ consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor.getDataInt(dstDb), 0, dstW);
+ } else if (dstDb.getDataType() == DataBuffer.TYPE_BYTE) {
+ consumer.setColorModel(dstCm);
+ consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor.getDataByte(dstDb), 0, dstW);
+ } else {
+ int dstData[] = bim.getRGB(0, 0, dstW, dstH, null, 0, dstW);
+ dstCm = ColorModel.getRGBdefault();
+ consumer.setColorModel(dstCm);
+ consumer.setPixels(0, 0, dstW, dstH, dstCm, dstData, 0, dstW);
+ }
+ } else if (status == IMAGEERROR || status == IMAGEABORTED) {
+ reset();
+ }
+
+ consumer.imageComplete(status);
+ }
+
+ /**
+ * Sets the pixels.
+ *
+ * @param x the x
+ * @param y the y
+ * @param w the w
+ * @param h the h
+ * @param model the model
+ * @param pixels the pixels
+ * @param off the off
+ * @param scansize the scansize
+ * @param isByteData the is byte data
+ */
+ private void setPixels(
+ int x, int y,
+ int w, int h,
+ ColorModel model, Object pixels,
+ int off, int scansize, boolean isByteData
+ ) {
+ // Check bounds
+ // Need to copy only the pixels that will fit into the destination area
+ if (x < 0) {
+ w -= x;
+ off += x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h -= y;
+ off += y * scansize;
+ y = 0;
+ }
+
+ if (x + w > width) {
+ w = width - x;
+ }
+
+ if (y + h > height) {
+ h = height - y;
+ }
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ // Check model
+ if (this.cm == null) {
+ setColorModel(model);
+ } else if (model == null) {
+ model = this.cm;
+ } else if (!model.equals(this.cm)) {
+ forceRGB();
+ }
+
+ boolean canArraycopy;
+ // Process pixels
+ switch(transferType) {
+ case DataBuffer.TYPE_UNDEFINED: {
+ if (isByteData) {
+ transferType = DataBuffer.TYPE_BYTE;
+ createRaster(transferType);
+ //bData = new byte[width*height];
+ canArraycopy = !forcedRGB;
+ break;
+ }
+ transferType = DataBuffer.TYPE_INT;
+ createRaster(transferType);
+ //iData = new int[width*height];
+ canArraycopy = !forcedRGB || model.equals(ColorModel.getRGBdefault());
+ break;
+ } // And proceed to copy the pixels
+ case DataBuffer.TYPE_INT: {
+ if (isByteData) { // There are int data already but the new data are bytes
+ forceRGB();
+ canArraycopy = false;
+ break;
+ } else if (!forcedRGB || model.equals(ColorModel.getRGBdefault())) {
+ canArraycopy = true;
+ break;
+ } // Else fallback to the RGB conversion
+ }
+ case DataBuffer.TYPE_BYTE: {
+ if (isByteData && !forcedRGB) {
+ canArraycopy = true;
+ break;
+ }
+
+ // RGB conversion
+ canArraycopy = false;
+ break;
+ } default: {
+ throw new IllegalStateException(Messages.getString("awt.06")); //$NON-NLS-1$
+ }
+ }
+
+ off += x;
+ int maxOffset = off + h * scansize;
+ int dstOffset = x + y * width;
+
+ if (canArraycopy) {
+ Object dstArray = isByteData ? (Object) bData : (Object) iData;
+ for (; off < maxOffset; off += scansize, dstOffset += width) {
+ System.arraycopy(pixels, off, dstArray, dstOffset, w);
+ }
+ } else {
+ // RGB conversion
+ for (; off < maxOffset; off += scansize, dstOffset += width) {
+ int srcPos = off;
+ int dstPos = dstOffset;
+ int maxDstPos = dstOffset + w;
+ for (; dstPos < maxDstPos; dstPos++, srcPos++) {
+ iData[dstPos] = model.getRGB(
+ isByteData ?
+ ((byte[])pixels)[srcPos] :
+ ((int[])pixels)[srcPos]
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Force rgb.
+ */
+ private void forceRGB() {
+ if (!forcedRGB) {
+ forcedRGB = true;
+ int size = width*height;
+ int rgbData[] = new int[size];
+
+ if (bData != null) {
+ for (int i=0; i<size; i++) {
+ rgbData[i] = cm.getRGB(bData[i]);
+ }
+ } else if (iData != null) {
+ for (int i=0; i<size; i++) {
+ rgbData[i] = cm.getRGB(iData[i]);
+ }
+ }
+
+ cm = ColorModel.getRGBdefault();
+ DataBufferInt db = new DataBufferInt(rgbData, size);
+ int masks[] = new int[] {0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};
+ raster = Raster.createPackedRaster(db, width, height, width, masks, null);
+ iData = accessor.getDataInt(db);
+ bData = null;
+ transferType = DataBuffer.TYPE_INT;
+ }
+ }
+
+ /**
+ * Reset.
+ */
+ private void reset() {
+ width = 0;
+ height = 0;
+ forcedRGB = false;
+ cm = null;
+ iData = null;
+ bData = null;
+ transferType = DataBuffer.TYPE_UNDEFINED;
+ raster = null;
+ }
+
+ /**
+ * Creates the raster.
+ *
+ * @param dataType the data type
+ */
+ private void createRaster(int dataType) {
+ boolean createdValidBuffer = false;
+ try{
+ raster = cm.createCompatibleWritableRaster(width, height);
+ int rasterType = raster.getDataBuffer().getDataType();
+ if (rasterType == dataType) {
+ switch (rasterType) {
+ case DataBuffer.TYPE_INT: {
+ iData = accessor.getDataInt(raster.getDataBuffer());
+ if (iData != null) {
+ createdValidBuffer = true;
+ }
+ break;
+ }
+ case DataBuffer.TYPE_BYTE: {
+ bData = accessor.getDataByte(raster.getDataBuffer());
+ if (bData != null) {
+ createdValidBuffer = true;
+ }
+ break;
+ }
+ default:
+ createdValidBuffer = false;
+ }
+
+ if(cm == ColorModel.getRGBdefault()){
+ forcedRGB = true;
+ }
+ } else {
+ createdValidBuffer = false;
+ }
+ } catch(Exception e) {
+ createdValidBuffer = false;
+ }
+
+ if (createdValidBuffer == false) {
+ cm = ColorModel.getRGBdefault();
+ raster = cm.createCompatibleWritableRaster(width, height);
+ iData = accessor.getDataInt(raster.getDataBuffer());
+ bData = null;
+ forcedRGB = true;
+ }
+ }
+}
diff --git a/awt/java/awt/image/BufferedImageOp.java b/awt/java/awt/image/BufferedImageOp.java
new file mode 100644
index 0000000..85b9f4e
--- /dev/null
+++ b/awt/java/awt/image/BufferedImageOp.java
@@ -0,0 +1,86 @@
+/*
+ * 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 Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The BufferedImageOp interface provides methods for performing transformations
+ * from source data to destination data for BufferedImage objects. An object
+ * implementing this interface can be passed into a BufferedImageFilter
+ * to operate on a BufferedImage.
+ */
+public interface BufferedImageOp {
+
+ /**
+ * Creates a destination image with the specified BufferedImage and
+ * ColorModel; this destination image is empty and has the correct size
+ * and number of bands.
+ *
+ * @param src the source BufferedImage.
+ * @param destCM the destination ColorModel.
+ *
+ * @return the BufferedImage.
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM);
+
+ /**
+ * Performs a filter operation on the source BufferedImage and stores
+ * the resulting BufferedImage to the destination BufferedImage. If
+ * the destination BufferedImage is null, a BufferedImage with an
+ * appropriate ColorModel is created.
+ *
+ * @param src the source BufferedImage.
+ * @param dest the destination BufferedImage, where the result is stored.
+ *
+ * @return the filtered BufferedImage.
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dest);
+
+ /**
+ * Gets the bounds of filtered image.
+ *
+ * @param src the source BufferedImage to be filtered.
+ *
+ * @return the rectangle bounds of filtered image.
+ */
+ public Rectangle2D getBounds2D(BufferedImage src);
+
+ /**
+ * Gets the point of the destination image which corresponds
+ * to the specified point in the source image.
+ *
+ * @param srcPt the point of the source image.
+ * @param dstPt the point where the result will be stored.
+ *
+ * @return the destination point.
+ */
+ public Point2D getPoint2D(Point2D srcPt, Point2D dstPt);
+
+ /**
+ * Gets the RenderingHints of the BufferedImageOp.
+ *
+ * @return the RenderingHints of the BufferedImageOp.
+ */
+ public RenderingHints getRenderingHints();
+}
diff --git a/awt/java/awt/image/ByteLookupTable.java b/awt/java/awt/image/ByteLookupTable.java
new file mode 100644
index 0000000..043b533
--- /dev/null
+++ b/awt/java/awt/image/ByteLookupTable.java
@@ -0,0 +1,134 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+/**
+ * The ByteLookupTable class provides functionality for lookup operations,
+ * and is defined by an input byte array for bands or components of
+ * image and an offset value.
+ * The offset value will be subtracted from the input values before
+ * indexing the input arrays. The output of a lookup operation is
+ * represented as an array of unsigned bytes.
+ */
+public class ByteLookupTable extends LookupTable {
+
+ /** The data. */
+ private byte data[][];
+
+ /**
+ * Instantiates a new ByteLookupTable with the specified offset value
+ * and the specified byte array which represents the lookup table for
+ * all bands.
+ *
+ * @param offset the offset value.
+ * @param data the data array of bytes.
+ */
+ public ByteLookupTable(int offset, byte[] data) {
+ super(offset, 1);
+ if (data.length < 1)
+ throw new IllegalArgumentException("Length of data should not be less then one");
+ this.data = new byte[1][data.length];
+ // The data array stored as a reference
+ this.data[0] = data;
+ }
+
+ /**
+ * Instantiates a new ByteLookupTable with the specified offset value
+ * and the specified byte array of arrays which represents the lookup table
+ * for each band.
+ *
+ * @param offset the offset value.
+ * @param data the data array of bytes array for each band.
+ */
+ public ByteLookupTable(int offset, byte[][] data) {
+ super(offset, data.length);
+ this.data = new byte[data.length][data[0].length];
+ for (int i = 0; i < data.length; i++) {
+ // The data array for each band stored as a reference
+ this.data[i] = data[i];
+ }
+ }
+
+ /**
+ * Gets the lookup table of this ByteLookupTable object. If
+ * this ByteLookupTable object has one byte array for all bands,
+ * the returned array length is one.
+ *
+ * @return the lookup table of this ByteLookupTable object.
+ */
+ public final byte[][] getTable() {
+ // Returns data by reference
+ return data;
+ }
+
+ @Override
+ public int[] lookupPixel(int[] src, int[] dst) {
+ if (dst == null) {
+ dst = new int[src.length];
+ }
+
+ int offset = getOffset();
+ if (getNumComponents() == 1) {
+ for (int i = 0; i < src.length; i++) {
+ dst[i] = data[0][src[i]-offset];
+ }
+ } else {
+ for (int i = 0; i < getNumComponents(); i++) {
+ dst[i] = data[i][src[i]-offset];
+ }
+ }
+
+ return dst;
+ }
+
+ /**
+ * Returns a byte array which contains samples of the specified
+ * pixel which is translated with the lookup table of this
+ * ByteLookupTable object. The resulted array is stored to
+ * the dst array.
+ *
+ * @param src the source array.
+ * @param dst the destination array where the result can be stored.
+ *
+ * @return the byte array of translated samples of a pixel.
+ */
+ public byte[] lookupPixel(byte[] src, byte[] dst) {
+ if (dst == null) {
+ dst = new byte[src.length];
+ }
+
+ int offset = getOffset();
+ if (getNumComponents() == 1) {
+ for (int i = 0; i < src.length; i++) {
+ dst[i] = data[0][src[i]-offset];
+ }
+ } else {
+ for (int i = 0; i < getNumComponents(); i++) {
+ dst[i] = data[i][src[i]-offset];
+ }
+ }
+
+ return dst;
+ }
+}
diff --git a/awt/java/awt/image/ColorConvertOp.java b/awt/java/awt/image/ColorConvertOp.java
new file mode 100644
index 0000000..6d503d7
--- /dev/null
+++ b/awt/java/awt/image/ColorConvertOp.java
@@ -0,0 +1,711 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.image;
+
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+
+import org.apache.harmony.awt.gl.color.ColorConverter;
+import org.apache.harmony.awt.gl.color.ColorScaler;
+import org.apache.harmony.awt.gl.color.ICC_Transform;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ColorConvertOp class converts the pixels of the data in the
+ * source image with the specified ColorSpace objects or an array
+ * of ICC_Profile objects. The result pixels are scaled to the precision
+ * of the destination image.
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp {
+ // Unused but required by interfaces
+ /** The rendering hints. */
+ RenderingHints renderingHints;
+
+ // Sequence consisting of ColorSpace and ICC_Profile elements
+ /** The conversion sequence. */
+ Object conversionSequence[] = new ICC_Profile[0]; // To eliminate checks for null
+
+ // Not null if ColorConvertOp is constructed from the array of ICC profiles
+ /** The mid profiles. */
+ private ICC_Profile midProfiles[];
+
+ /** The cc. */
+ private final ColorConverter cc = new ColorConverter();
+
+ /** The t creator. */
+ private final ICC_TransfomCreator tCreator = new ICC_TransfomCreator();
+
+ /** The is icc. */
+ private boolean isICC = true;
+
+
+ // Cached ICC_Transform
+ /**
+ * The Class ICC_TransfomCreator.
+ */
+ private class ICC_TransfomCreator {
+
+ /** The transform. */
+ private ICC_Transform transform;
+
+ /** The max components. */
+ private int maxComponents;
+
+ /**
+ * For the full ICC case.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param convSeq the conv seq
+ *
+ * @return the transform
+ */
+ public ICC_Transform getTransform(ICC_Profile src, ICC_Profile dst, ICC_Profile convSeq[]) {
+ if (transform != null &&
+ src == transform.getSrc() &&
+ dst == transform.getDst()) {
+ return transform;
+ }
+
+ int length = convSeq.length;
+ int srcFlg = 0, dstFlg = 0;
+
+ if (length == 0 || src != convSeq[0]) {
+ if (src != null) {
+ srcFlg = 1; // need src profile
+ }
+ }
+ if (length == 0 || dst != convSeq[length-1]) {
+ if (dst != null) {
+ dstFlg = 1; // need dst profile
+ }
+ }
+
+ ICC_Profile profiles[];
+ int nProfiles = length + srcFlg + dstFlg;
+ if (nProfiles == length) {
+ profiles = convSeq;
+ } else {
+ profiles = new ICC_Profile[nProfiles];
+ int pos = 0;
+ if (srcFlg != 0) {
+ profiles[pos++] = src;
+ }
+ for (int i=0; i<length; i++) {
+ profiles[pos++] = convSeq[i];
+ }
+ if (dstFlg != 0) {
+ profiles[pos++] = dst;
+ }
+ }
+
+ return transform = new ICC_Transform(profiles);
+ }
+
+ /**
+ * Used only when there are non-ICC color spaces.
+ * Returns sequence of non-ICC color spaces and ICC transforms
+ * made from src, dst and conversionSequence.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the sequence
+ */
+ public Object[] getSequence(Object src, Object dst) {
+ ArrayList<Object> profiles = new ArrayList<Object>(10);
+ ArrayList<Object> sequence = new ArrayList<Object>(10);
+
+ // We need this profile anyway
+ ICC_Profile xyzProfile = ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ);
+
+ Object conversionFirst = null, conversionLast = null;
+ int conversionLength = conversionSequence.length;
+ if (conversionLength > 0) {
+ conversionFirst = conversionSequence[0];
+ conversionLast = conversionSequence[conversionLength-1];
+ }
+
+ boolean iccSequenceStarted = false;
+
+ if (src != conversionFirst && src != null) {
+ if (src instanceof ICC_Profile) {
+ profiles.add(src);
+ iccSequenceStarted = true;
+ } else {
+ profiles.add(xyzProfile);
+ sequence.add(src); // Add non-ICC color space to the sequence
+ }
+ } else {
+ profiles.add(xyzProfile);
+ }
+
+ for (int i=0; i<conversionLength; i++) {
+ if (conversionSequence[i] instanceof ICC_Profile) {
+ profiles.add(conversionSequence[i]);
+ iccSequenceStarted = true;
+ } else if (iccSequenceStarted) {
+ profiles.add(xyzProfile);
+
+ // Eliminate same profiles if there are any
+ // (e.g. xyzProfile may occur several times)
+ Object prev = profiles.get(0);
+ for (int k=1; k<profiles.size(); k++) {
+ if (prev == profiles.get(k)) {
+ k--;
+ profiles.remove(k);
+ }
+ prev = profiles.get(k);
+ }
+
+ // If only one profile left we skip the transform -
+ // it can be only CIEXYZ
+ if (profiles.size() > 1) {
+ sequence.add(new ICC_Transform(profiles.toArray(new ICC_Profile[0])));
+
+ // Add non-ICC color space to the sequence
+ sequence.add(conversionSequence[i]);
+ }
+
+ profiles.clear();
+ profiles.add(xyzProfile);
+ iccSequenceStarted = false; // Sequence of ICC profiles is processed
+ } else { // Add non-ICC color space to the sequence
+ sequence.add(conversionSequence[i]);
+ }
+ }
+
+ if (dst != conversionLast && dst != null) { // Add last profile if needed
+ if (dst instanceof ICC_Profile) {
+ profiles.add(dst);
+ iccSequenceStarted = true;
+ } else if (iccSequenceStarted) {
+ profiles.add(xyzProfile);
+ } else {
+ sequence.add(dst); // Add last non-ICC color space to the sequence
+ }
+ }
+
+ if (iccSequenceStarted) { // Make last transform if needed
+ sequence.add(new ICC_Transform(profiles.toArray(new ICC_Profile[0])));
+ if (dst != null && !(dst instanceof ICC_Profile)) {
+ sequence.add(dst); // Add last non-ICC color space to the
+ // sequence
+ }
+ }
+
+ // Calculate max number of components
+ // This number will be used for memory allocation
+ maxComponents = 0;
+ Object o;
+ for (int i=0, size = sequence.size(); i<size; i++) {
+ o = sequence.get(i);
+ if (o instanceof ICC_Transform) {
+ ICC_Transform t = (ICC_Transform) o;
+ maxComponents =
+ (maxComponents > t.getNumInputChannels() + 1) ?
+ maxComponents :
+ t.getNumInputChannels() + 1;
+ maxComponents =
+ (maxComponents > t.getNumOutputChannels() + 1) ?
+ maxComponents :
+ t.getNumOutputChannels() + 1;
+ } else {
+ ColorSpace cs = (ColorSpace) o;
+ maxComponents =
+ (maxComponents > cs.getNumComponents() + 1) ?
+ maxComponents :
+ cs.getNumComponents() + 1;
+ }
+ }
+
+ return sequence.toArray();
+ }
+ }
+
+ /**
+ * Instantiates a new ColorConvertOp object using two specified
+ * ColorSpace objects.
+ *
+ * @param srcCS the source ColorSpace.
+ * @param dstCS the destination ColorSpace.
+ * @param hints the RenderingHints object used for
+ * the color conversion, or null.
+ */
+ public ColorConvertOp(ColorSpace srcCS, ColorSpace dstCS, RenderingHints hints) {
+ if (srcCS == null || dstCS == null) {
+ throw new NullPointerException(Messages.getString("awt.25B")); //$NON-NLS-1$
+ }
+
+ renderingHints = hints;
+
+ boolean srcICC = srcCS instanceof ICC_ColorSpace;
+ boolean dstICC = dstCS instanceof ICC_ColorSpace;
+
+ if (srcICC && dstICC) {
+ conversionSequence = new ICC_Profile[2];
+ } else {
+ conversionSequence = new Object[2];
+ isICC = false;
+ }
+
+ if (srcICC) {
+ conversionSequence[0] = ((ICC_ColorSpace) srcCS).getProfile();
+ } else {
+ conversionSequence[0] = srcCS;
+ }
+
+ if (dstICC) {
+ conversionSequence[1] = ((ICC_ColorSpace) dstCS).getProfile();
+ } else {
+ conversionSequence[1] = dstCS;
+ }
+ }
+
+ /**
+ * Instantiates a new ColorConvertOp object from the specified
+ * ICC_Profile objects.
+ *
+ * @param profiles the array of ICC_Profile objects.
+ * @param hints the RenderingHints object used for
+ * the color conversion, or null.
+ */
+ public ColorConvertOp(ICC_Profile profiles[], RenderingHints hints) {
+ if (profiles == null) {
+ throw new NullPointerException(Messages.getString("awt.25C")); //$NON-NLS-1$
+ }
+
+ renderingHints = hints;
+
+ // This array is not used in the program logic, so don't need to copy it
+ // Store it only to return back
+ midProfiles = profiles;
+
+ conversionSequence = new ICC_Profile[midProfiles.length];
+
+ // Add profiles to the conversion sequence
+ for (int i=0, length=midProfiles.length; i<length; i++) {
+ conversionSequence[i] = midProfiles[i];
+ }
+ }
+
+ /**
+ * Instantiates a new ColorConvertOp object using the specified
+ * ColorSpace object.
+ *
+ * @param cs the destination ColorSpace or an intermediate ColorSpace.
+ * @param hints the RenderingHints object used for
+ * the color conversion, or null.
+ */
+ public ColorConvertOp(ColorSpace cs, RenderingHints hints) {
+ if (cs == null) {
+ throw new NullPointerException(Messages.getString("awt.25B")); //$NON-NLS-1$
+ }
+
+ renderingHints = hints;
+
+ if (cs instanceof ICC_ColorSpace) {
+ conversionSequence = new ICC_Profile[1];
+ conversionSequence[0] = ((ICC_ColorSpace) cs).getProfile();
+ } else {
+ conversionSequence = new Object[1];
+ conversionSequence[0] = cs;
+ isICC = false;
+ }
+ }
+
+ /**
+ * Instantiates a new ColorConvertOp object which converts from
+ * a source color space to a destination color space.
+ *
+ * @param hints the RenderingHints object used for
+ * the color conversion, or null.
+ */
+ public ColorConvertOp(RenderingHints hints) {
+ renderingHints = hints;
+ }
+
+ public final WritableRaster filter(Raster src, WritableRaster dst) {
+ if (conversionSequence.length < 2) {
+ throw new IllegalArgumentException(Messages.getString("awt.25D")); //$NON-NLS-1$
+ }
+
+ ICC_Profile srcPf = null, dstPf = null; // unused if isICC is false
+ int nSrcColorComps, nDstColorComps;
+ Object first = conversionSequence[0];
+ Object last = conversionSequence[conversionSequence.length - 1];
+
+ // Get the number of input/output color components
+ if (isICC) {
+ srcPf = (ICC_Profile) first;
+ dstPf = (ICC_Profile) last;
+ nSrcColorComps = srcPf.getNumComponents();
+ nDstColorComps = dstPf.getNumComponents();
+ } else {
+ if (first instanceof ICC_Profile) {
+ srcPf = (ICC_Profile) first;
+ nSrcColorComps = srcPf.getNumComponents();
+ } else {
+ nSrcColorComps = ((ColorSpace) first).getNumComponents();
+ }
+
+ if (last instanceof ICC_Profile) {
+ dstPf = (ICC_Profile) last;
+ nDstColorComps = dstPf.getNumComponents();
+ } else {
+ nDstColorComps = ((ColorSpace) last).getNumComponents();
+ }
+ }
+
+ // Check that source and destination rasters are compatible with
+ // transforms and with each other
+ if (src.getNumBands() != nSrcColorComps) {
+ // awt.25E=Incorrect number of source raster bands. Should be equal
+ // to the number of color components of source colorspace.
+ throw new IllegalArgumentException(Messages.getString("awt.25E")); //$NON-NLS-1$
+ }
+
+ if (dst != null) { // Check destination raster
+ if (dst.getNumBands() !=
+ nDstColorComps) {
+ // awt.25F=Incorrect number of destination raster bands. Should
+ // be equal to the number of color components of destination
+ // colorspace.
+ throw new IllegalArgumentException(Messages.getString("awt.25F")); //$NON-NLS-1$
+ }
+
+ if (src.getWidth() != dst.getWidth() ||
+ src.getHeight() != dst.getHeight()) {
+ throw new IllegalArgumentException(Messages.getString("awt.260")); //$NON-NLS-1$
+ }
+
+ } else {
+ dst = createCompatibleDestRaster(src);
+ }
+
+ if (isICC) {
+ // Create transform
+ ICC_Transform t = tCreator.getTransform(srcPf, dstPf,
+ (ICC_Profile[])conversionSequence);
+ cc.translateColor(t, src, dst);
+ } else {
+ Object[] sequence = tCreator.getSequence(null, null);
+
+ // Get data from the source raster
+ ColorScaler scaler = new ColorScaler();
+ scaler.loadScalingData(src, null);
+ float tmpData[][] = scaler.scaleNormalize(src);
+
+ // Get source and destination color spaces
+ ColorSpace srcCS = (srcPf == null) ?
+ (ColorSpace) first:
+ new ICC_ColorSpace(srcPf);
+ ColorSpace dstCS = (dstPf == null) ?
+ (ColorSpace) last:
+ new ICC_ColorSpace(dstPf);
+
+ applySequence(sequence, tmpData, srcCS, dstCS);
+
+ scaler.loadScalingData(dst, null);
+ scaler.unscaleNormalized(dst, tmpData);
+ }
+
+ return dst;
+ }
+
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
+ // If destination color model is passed only one line needed
+ if (destCM != null) {
+ return new BufferedImage(destCM,
+ destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()),
+ destCM.isAlphaPremultiplied(),
+ null);
+ }
+
+ int nSpaces = conversionSequence.length;
+
+ if (nSpaces < 1) {
+ throw new IllegalArgumentException(Messages.getString("awt.261")); //$NON-NLS-1$
+ }
+
+ // Get destination color space
+ Object destination = conversionSequence[nSpaces-1];
+ ColorSpace dstCS =
+ (destination instanceof ColorSpace) ?
+ (ColorSpace) destination :
+ new ICC_ColorSpace((ICC_Profile) destination);
+
+ ColorModel srcCM = src.getColorModel();
+ ColorModel dstCM = new ComponentColorModel(dstCS,
+ srcCM.hasAlpha(),
+ srcCM.isAlphaPremultiplied(),
+ srcCM.getTransparency(),
+ srcCM.getTransferType());
+
+ return new BufferedImage(dstCM,
+ destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()),
+ destCM.isAlphaPremultiplied(),
+ null);
+ }
+
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+ if (dst == null && conversionSequence.length < 1) {
+ throw new IllegalArgumentException(Messages.getString("awt.262")); //$NON-NLS-1$
+ }
+
+ ColorModel srcCM = src.getColorModel();
+ // First handle index color model
+ if (srcCM instanceof IndexColorModel) {
+ src = ((IndexColorModel) srcCM).convertToIntDiscrete(src.getRaster(), false);
+ }
+ ColorSpace srcCS = srcCM.getColorSpace();
+
+ BufferedImage res;
+ boolean isDstIndex = false;
+ if (dst != null) {
+
+ if (src.getWidth() != dst.getWidth() ||
+ src.getHeight() != dst.getHeight()) {
+ throw new IllegalArgumentException(Messages.getString("awt.263")); //$NON-NLS-1$
+ }
+
+ if (dst.getColorModel() instanceof IndexColorModel) {
+ isDstIndex = true;
+ res = createCompatibleDestImage(src, null);
+ } else {
+ res = dst;
+ }
+ } else {
+ res = createCompatibleDestImage(src, null);
+ }
+ ColorModel dstCM = res.getColorModel();
+ ColorSpace dstCS = dstCM.getColorSpace();
+
+ ICC_Profile srcPf = null, dstPf = null;
+ if (srcCS instanceof ICC_ColorSpace) {
+ srcPf = ((ICC_ColorSpace)srcCS).getProfile();
+ }
+ if (dstCS instanceof ICC_ColorSpace) {
+ dstPf = ((ICC_ColorSpace)dstCS).getProfile();
+ }
+
+ boolean isFullICC = isICC && srcPf != null && dstPf != null;
+
+ if (isFullICC) {
+ ICC_Transform t =
+ tCreator.getTransform(srcPf, dstPf, (ICC_Profile[]) conversionSequence);
+ cc.translateColor(t, src, res);
+ } else { // Perform non-ICC transform
+ Object sequence[] = tCreator.getSequence(
+ srcPf == null ? (Object) srcCS : srcPf,
+ dstPf == null ? (Object) dstCS : dstPf);
+
+ int srcW = src.getWidth();
+ int srcH = src.getHeight();
+ int numPixels = srcW*srcH;
+
+ // Load all pixel data into array tmpData
+ float tmpData[][] =
+ new float[numPixels][tCreator.maxComponents];
+ for (int row=0, dataPos=0; row<srcW; row++) {
+ for (int col=0; col<srcH; col++) {
+ tmpData[dataPos] =
+ srcCM.getNormalizedComponents(
+ src.getRaster().getDataElements(row, col, null),
+ tmpData[dataPos], 0);
+ dataPos++;
+ }
+ }
+
+ // Copy alpha channel if needed
+ float alpha[] = null;
+ int alphaIdx = srcCM.numComponents - 1;
+ if (srcCM.hasAlpha() && dstCM.hasAlpha()) {
+ alpha = new float[numPixels];
+ for (int i=0; i<numPixels; i++) {
+ alpha[i] = tmpData[i][alphaIdx];
+ }
+ }
+
+ // Translate colors
+ applySequence(sequence, tmpData, srcCS, dstCS);
+
+ // Copy alpha if needed
+ if (dstCM.hasAlpha()) {
+ alphaIdx = dstCM.numComponents - 1;
+ if (alpha != null) {
+ for (int i=0; i<numPixels; i++) {
+ tmpData[i][alphaIdx] = alpha[i];
+ }
+ } else {
+ for (int i=0; i<numPixels; i++) {
+ tmpData[i][alphaIdx] = 1f;
+ }
+ }
+ }
+
+ // Store data back to the image
+ for (int row=0, dataPos=0; row<srcW; row++) {
+ for (int col=0; col<srcH; col++) {
+ res.getRaster().setDataElements(row, col,
+ dstCM.getDataElements(tmpData[dataPos++], 0 , null));
+ }
+ }
+ }
+
+ if (isDstIndex) { // Convert image into indexed color
+ Graphics2D g2d = dst.createGraphics();
+ g2d.drawImage(res, 0, 0, null);
+ g2d.dispose();
+ return dst;
+ }
+
+ return res;
+ }
+
+ /**
+ * Apply sequence.
+ *
+ * @param sequence the sequence
+ * @param tmpData the tmp data
+ * @param srcCS the src cs
+ * @param dstCS the dst cs
+ */
+ private void applySequence(
+ Object sequence[],
+ float tmpData[][],
+ ColorSpace srcCS,
+ ColorSpace dstCS
+ ) {
+ ColorSpace xyzCS = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
+
+ int numPixels = tmpData.length;
+
+ // First transform...
+ if (sequence[0] instanceof ICC_Transform) { // ICC
+ ICC_Transform t = (ICC_Transform)sequence[0];
+ cc.translateColor(t, tmpData, srcCS, xyzCS, numPixels);
+ } else { // non ICC
+ for (int k=0; k<numPixels; k++) {
+ tmpData[k] = srcCS.toCIEXYZ(tmpData[k]);
+ }
+ cc.loadScalingData(xyzCS); // prepare for scaling XYZ
+ }
+
+ for (Object element : sequence) {
+ if (element instanceof ICC_Transform) {
+ ICC_Transform t = (ICC_Transform)element;
+ cc.translateColor(t, tmpData, null, null, numPixels);
+ } else {
+ ColorSpace cs = (ColorSpace) element;
+ for (int k=0; k<numPixels; k++) {
+ tmpData[k] = cs.fromCIEXYZ(tmpData[k]);
+ tmpData[k] = cs.toCIEXYZ(tmpData[k]);
+ }
+ }
+ }
+
+ // Last transform...
+ if (sequence[sequence.length-1] instanceof ICC_Transform) { // ICC
+ ICC_Transform t = (ICC_Transform)sequence[sequence.length-1];
+ cc.translateColor(t, tmpData, xyzCS, dstCS, numPixels);
+ } else { // non ICC
+ for (int k=0; k<numPixels; k++) {
+ tmpData[k] = dstCS.fromCIEXYZ(tmpData[k]);
+ }
+ }
+ }
+
+ public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ if (dstPt != null) {
+ dstPt.setLocation(srcPt);
+ return dstPt;
+ }
+ return new Point2D.Float((float) srcPt.getX(), (float) srcPt.getY());
+ }
+
+ public WritableRaster createCompatibleDestRaster(Raster src) {
+ int nComps = 0;
+ int nSpaces = conversionSequence.length;
+
+ if (nSpaces < 2) {
+ throw new IllegalArgumentException(Messages.getString("awt.261")); //$NON-NLS-1$
+ }
+
+ Object lastCS = conversionSequence[nSpaces-1];
+ if (lastCS instanceof ColorSpace) {
+ nComps = ((ColorSpace) lastCS).getNumComponents();
+ } else {
+ nComps = ((ICC_Profile) lastCS).getNumComponents();
+ }
+
+ // Calculate correct data type
+ int dstDataType = src.getDataBuffer().getDataType();
+ if (dstDataType != DataBuffer.TYPE_BYTE &&
+ dstDataType != DataBuffer.TYPE_SHORT) {
+ dstDataType = DataBuffer.TYPE_SHORT;
+ }
+
+ return Raster.createInterleavedRaster(
+ dstDataType,
+ src.getWidth(),
+ src.getHeight(),
+ nComps,
+ new Point(src.getMinX(), src.getMinY())
+ );
+ }
+
+ public final Rectangle2D getBounds2D(Raster src) {
+ return src.getBounds();
+ }
+
+ public final Rectangle2D getBounds2D(BufferedImage src) {
+ return src.getRaster().getBounds();
+ }
+
+ /**
+ * Gets an array of ICC_Profiles objects which constructs
+ * this ColorConvertOp object or returns null if this ColorConvertOp
+ * is not constructed from array of ICC_Profiles.
+ *
+ * @return an array of ICC_Profiles objects which constructs
+ * this ColorConvertOp object or returns null if this ColorConvertOp
+ * is not constructed from array of ICC_Profiles.
+ */
+ public final ICC_Profile[] getICC_Profiles() {
+ if (midProfiles != null) {
+ return midProfiles;
+ }
+ return null;
+ }
+
+ public final RenderingHints getRenderingHints() {
+ return renderingHints;
+ }
+}
diff --git a/awt/java/awt/image/ColorModel.java b/awt/java/awt/image/ColorModel.java
new file mode 100644
index 0000000..945c087
--- /dev/null
+++ b/awt/java/awt/image/ColorModel.java
@@ -0,0 +1,911 @@
+/*
+ * 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.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class ColorModel.
+ */
+public abstract class ColorModel implements Transparency {
+
+ /** The pixel_bits. */
+ protected int pixel_bits; // Pixel length in bits
+
+ /** The transfer type. */
+ protected int transferType;
+
+ /** The cs. */
+ ColorSpace cs;
+
+ /** The has alpha. */
+ boolean hasAlpha;
+
+ /** The is alpha premultiplied. */
+ boolean isAlphaPremultiplied;
+
+ /** The transparency. */
+ int transparency;
+
+ /** The num color components. */
+ int numColorComponents;
+
+ /** The num components. */
+ int numComponents;
+
+ /** The bits. */
+ int[] bits; // Array of components masks
+
+ /** The max values. */
+ int[] maxValues = null; // Max values that may be represent by color
+ // components
+
+ /** The max bit length. */
+ int maxBitLength; // Max length color components in bits
+
+ /** The RG bdefault. */
+ private static ColorModel RGBdefault;
+
+ /**
+ * Instantiates a new color model with the specified values.
+ *
+ * @param pixel_bits the pixel length in bits
+ * @param bits the array of component masks
+ * @param cspace the colorspace
+ * @param hasAlpha whether the color model has alpha
+ * @param isAlphaPremultiplied whether the alpha is premultiplied
+ * @param transparency the transparency strategy, @see java.awt.Transparency
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ */
+ protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
+ boolean hasAlpha, boolean isAlphaPremultiplied, int transparency,
+ int transferType) {
+
+ if (pixel_bits < 1) {
+ // awt.26B=The number of bits in the pixel values is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.26B")); //$NON-NLS-1$
+ }
+
+ if (bits == null) {
+ // awt.26C=bits is null
+ throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
+ }
+
+ int sum = 0;
+ for (int element : bits) {
+ if (element < 0) {
+ // awt.26D=The elements in bits is less than 0
+ throw new IllegalArgumentException(Messages.getString("awt.26D")); //$NON-NLS-1$
+ }
+ sum += element;
+ }
+
+ if (sum < 1) {
+ // awt.26E=The sum of the number of bits in bits is less than 1
+ throw new NullPointerException(Messages.getString("awt.26E")); //$NON-NLS-1$
+ }
+
+ if (cspace == null) {
+ // awt.26F=The cspace is null
+ throw new IllegalArgumentException(Messages.getString("awt.26F")); //$NON-NLS-1$
+ }
+
+ if (transparency < Transparency.OPAQUE ||
+ transparency > Transparency.TRANSLUCENT) {
+ // awt.270=The transparency is not a valid value
+ throw new IllegalArgumentException(Messages.getString("awt.270")); //$NON-NLS-1$
+ }
+
+ this.pixel_bits = pixel_bits;
+ this.bits = bits.clone();
+
+ maxValues = new int[bits.length];
+ maxBitLength = 0;
+ for (int i = 0; i < maxValues.length; i++) {
+ maxValues[i] = (1 << bits[i]) - 1;
+ if (bits[i] > maxBitLength) {
+ maxBitLength = bits[i];
+ }
+ }
+
+ cs = cspace;
+ this.hasAlpha = hasAlpha;
+ this.isAlphaPremultiplied = isAlphaPremultiplied;
+ numColorComponents = cs.getNumComponents();
+
+ if (hasAlpha) {
+ numComponents = numColorComponents + 1;
+ } else {
+ numComponents = numColorComponents;
+ }
+
+ this.transparency = transparency;
+ this.transferType = transferType;
+
+ }
+
+ /**
+ * Instantiates a new color model with the specified pixel bit depth.
+ * The transferType is chosen based on the pixel bits, and the other
+ * data fields are given default values.
+ *
+ * @param bits the array of component masks
+ */
+ public ColorModel(int bits) {
+
+ if (bits < 1) {
+ // awt.271=The number of bits in bits is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.271")); //$NON-NLS-1$
+ }
+
+ pixel_bits = bits;
+ transferType = getTransferType(bits);
+ cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ hasAlpha = true;
+ isAlphaPremultiplied = false;
+ transparency = Transparency.TRANSLUCENT;
+
+ numColorComponents = 3;
+ numComponents = 4;
+
+ this.bits = null;
+ }
+
+ /**
+ * Gets the data elements from the specified component array, transforming
+ * them according to rules of the color model.
+ *
+ * @param components the components
+ * @param offset the offset in the normComponents array
+ * @param obj the array that the result is written to: an array of values
+ * whose length must be the number of components used by the color model and
+ * whose type depends on the transfer type (based on the pixel bit depth),
+ * or null to have the appropriate array created
+ *
+ * @return the array of data elements
+ */
+ public Object getDataElements(int[] components, int offset, Object obj) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the data elements from the specified array of normalized components.
+ *
+ * @param normComponents the array normalized components
+ * @param normOffset the offset in the normComponents array
+ * @param obj the array that the result is written to: an array of values
+ * whose length must be the number of components used by the color model and
+ * whose type depends on the transfer type (based on the pixel bit depth),
+ * or null to have the appropriate array created
+ *
+ * @return the array of data elements
+ */
+ public Object getDataElements(float[] normComponents, int normOffset,
+ Object obj) {
+ int unnormComponents[] = getUnnormalizedComponents(normComponents,
+ normOffset, null, 0);
+ return getDataElements(unnormComponents, 0, obj);
+ }
+
+ /**
+ * Gets the data elements corresponding to the pixel determined by the
+ * RGB data.
+ *
+ * @param rgb the rgb int that defines the pixel
+ * @param pixel the array that the result is written to: an array of values
+ * whose length must be the number of components used by the color model and
+ * whose type depends on the transfer type (based on the pixel bit depth),
+ * or null to have the appropriate array created
+ *
+ * @return the array of data elements
+ */
+ public Object getDataElements(int rgb, Object pixel) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the child raster corresponding to the alpha channel of the
+ * specified writable raster, or null if alpha is not supported.
+ *
+ * @param raster the raster
+ *
+ * @return the alpha raster
+ */
+ public WritableRaster getAlphaRaster(WritableRaster raster) {
+ return null;
+ }
+
+ /**
+ * Creates a new color model by coercing the data in the writable raster
+ * in accordance with the alpha strategy of this color model.
+ *
+ * @param raster the raster
+ * @param isAlphaPremultiplied whether the alpha is premultiplied in this
+ * color model
+ *
+ * @return the new color model
+ */
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ @Override
+ public String toString() {
+ // The output format based on 1.5 release behaviour.
+ // It could be reveled such way:
+ // ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB,
+ // false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+ // System.out.println(cm.toString());
+ return "ColorModel: Color Space = " + cs.toString() + "; has alpha = " //$NON-NLS-1$ //$NON-NLS-2$
+ + hasAlpha + "; is alpha premultipied = " //$NON-NLS-1$
+ + isAlphaPremultiplied + "; transparency = " + transparency //$NON-NLS-1$
+ + "; number color components = " + numColorComponents //$NON-NLS-1$
+ + "; pixel bits = " + pixel_bits + "; transfer type = " //$NON-NLS-1$ //$NON-NLS-2$
+ + transferType;
+ }
+
+ /**
+ * Gets the components of the pixel determined by the data array.
+ *
+ * @param pixel the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ * @param components the the array where the resulting components
+ * are written (or null to prompt the method to create the return array)
+ * @param offset the offset that tells where the results should be written
+ * in the return array
+ *
+ * @return the array of components
+ */
+ public int[] getComponents(Object pixel, int[] components, int offset) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the normalized components of the pixel determined by the data array.
+ *
+ * @param pixel the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ * @param normComponents the array where the resulting normalised components
+ * are written (or null to prompt the method to create the return array)
+ * @param normOffset the offset that tells where the results should be written
+ * in the return array
+ *
+ * @return the array of normalized components
+ */
+ public float[] getNormalizedComponents(Object pixel,
+ float[] normComponents, int normOffset) {
+
+ if (pixel == null) {
+ // awt.294=pixel is null
+ throw new NullPointerException(Messages.getString("awt.294")); //$NON-NLS-1$
+ }
+
+ int unnormComponents[] = getComponents(pixel, null, 0);
+ return getNormalizedComponents(unnormComponents, 0, normComponents,
+ normOffset);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ColorModel)) {
+ return false;
+ }
+ ColorModel cm = (ColorModel) 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()));
+ }
+
+ /**
+ * Gets the red component of the pixel determined by the data array.
+ *
+ * @param inData the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ *
+ * @return the red
+ */
+ public int getRed(Object inData) {
+ return getRed(constructPixel(inData));
+ }
+
+ /**
+ * Gets the RGB int corresponding to the pixel defined by the data array.
+ *
+ * @param inData the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ *
+ * @return the int that gives the pixel's colors in RGB format
+ */
+ public int getRGB(Object inData) {
+ return (getAlpha(inData) << 24 | getRed(inData) << 16 |
+ getGreen(inData) << 8 | getBlue(inData));
+ }
+
+ /**
+ * Gets the green component of the pixel defined by the data array.
+ *
+ * @param inData the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ *
+ * @return the green
+ */
+ public int getGreen(Object inData) {
+ return getGreen(constructPixel(inData));
+ }
+
+ /**
+ * Gets the blue component of the pixel defined by the data array.
+ *
+ * @param inData the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ *
+ * @return the blue
+ */
+ public int getBlue(Object inData) {
+ return getBlue(constructPixel(inData));
+ }
+
+ /**
+ * Gets the alpha component of the pixel defined by the data array.
+ *
+ * @param inData the data array that defines the pixel (whose
+ * primitive type corresponds to the pixel length in bits,
+ * @see ColorModel#getTransferType()
+ *
+ * @return the alpha
+ */
+ public int getAlpha(Object inData) {
+ return getAlpha(constructPixel(inData));
+ }
+
+ /**
+ * Creates a compatible writable raster.
+ *
+ * @param w the width of the desired writable raster
+ * @param h the height of the desired writable raster
+ *
+ * @return the writable raster
+ */
+ public WritableRaster createCompatibleWritableRaster(int w, int h) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Checks if the sample model is compatible with this color model.
+ *
+ * @param sm the sample model
+ *
+ * @return true, if the sample model is compatible with this color model
+ */
+ public boolean isCompatibleSampleModel(SampleModel sm) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates the compatible sample model.
+ *
+ * @param w the width of the desired sample model
+ * @param h the height of the desired sample model
+ *
+ * @return the sample model
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Checks if the specified raster is compatible with this color model.
+ *
+ * @param raster the raster to inspect
+ *
+ * @return true, if the raster is compatible with this color model
+ */
+ public boolean isCompatibleRaster(Raster raster) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the color space of this color model.
+ *
+ * @return the color space
+ */
+ public final ColorSpace getColorSpace() {
+ return cs;
+ }
+
+ /**
+ * Gets the normalized components corresponding to the specified
+ * unnormalized components.
+ *
+ * @param components the array of unnormalized components
+ * @param offset the offset where the components should be read
+ * from the array of unnormalized components
+ * @param normComponents the array where the resulting normalised components
+ * are written (or null to prompt the method to create the return array)
+ * @param normOffset the offset that tells where the results should be written
+ * in the return array
+ *
+ * @return the normalized components
+ */
+ public float[] getNormalizedComponents(int[] components, int offset,
+ float normComponents[], int normOffset) {
+ if (bits == null) {
+ // awt.26C=bits is null
+ throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
+ }
+
+ if (normComponents == null) {
+ normComponents = new float[numComponents + normOffset];
+ }
+
+ if (hasAlpha && isAlphaPremultiplied) {
+ float normAlpha =
+ (float) components[offset + numColorComponents] /
+ maxValues[numColorComponents];
+ if (normAlpha != 0.0f) {
+ for (int i = 0; i < numColorComponents; i++) {
+ normComponents[normOffset + i] =
+ components[offset + i] /
+ (normAlpha * maxValues[i]);
+ }
+ normComponents[normOffset + numColorComponents] = normAlpha;
+ } else {
+ for (int i = 0; i < numComponents; i++) {
+ normComponents[normOffset + i] = 0.0f;
+ }
+ }
+ } else {
+ for (int i = 0; i < numComponents; i++) {
+ normComponents[normOffset + i] =
+ (float) components[offset + i] /
+ maxValues[i];
+ }
+ }
+
+ return normComponents;
+ }
+
+ /**
+ * Gets the data element corresponding to the unnormalized components.
+ *
+ * @param components the components
+ * @param offset the offset to start reading the components from the
+ * array of components
+ *
+ * @return the data element
+ */
+ public int getDataElement(int[] components, int offset) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the unnormalized components corresponding to the specified
+ * normalized components.
+ *
+ * @param normComponents the array of normalized components
+ * @param normOffset the offset where the components should be read
+ * from the array of normalized components
+ * @param components the array where the resulting unnormalised components
+ * are written (or null to prompt the method to create the return array)
+ * @param offset the offset that tells where the results should be written
+ * in the return array
+ *
+ * @return the unnormalized components
+ */
+ public int[] getUnnormalizedComponents(float normComponents[],
+ int normOffset, int components[], int offset) {
+
+ if (bits == null) {
+ // awt.26C=bits is null
+ throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
+ }
+
+ if (normComponents.length - normOffset < numComponents) {
+ // awt.273=The length of normComponents minus normOffset is less than numComponents
+ throw new IllegalArgumentException(Messages.getString("awt.273")); //$NON-NLS-1$
+ }
+
+ if (components == null) {
+ components = new int[numComponents + offset];
+ } else {
+ if (components.length - offset < numComponents) {
+ // awt.272=The length of components minus offset is less than numComponents
+ throw new IllegalArgumentException(Messages.getString("awt.272")); //$NON-NLS-1$
+ }
+ }
+
+ if (hasAlpha && isAlphaPremultiplied) {
+ float alpha = normComponents[normOffset + numColorComponents];
+ for (int i = 0; i < numColorComponents; i++) {
+ components[offset + i] = (int) (normComponents[normOffset + i]
+ * maxValues[i] * alpha + 0.5f);
+ }
+ components[offset + numColorComponents] =
+ (int) (normComponents[normOffset + numColorComponents] *
+ maxValues[numColorComponents] + 0.5f);
+ } else {
+ for (int i = 0; i < numComponents; i++) {
+ components[offset + i] =
+ (int) (normComponents[normOffset + i] *
+ maxValues[i] + 0.5f);
+ }
+ }
+
+ return components;
+ }
+
+ /**
+ * Gets the data element corresponding to the normalized components.
+ *
+ * @param normComponents the normalized components
+ * @param normOffset the offset where the normalized components should
+ * be read from the normalized component array
+ *
+ * @return the data element
+ */
+ public int getDataElement(float normComponents[], int normOffset) {
+ int unnormComponents[] = getUnnormalizedComponents(normComponents,
+ normOffset, null, 0);
+ return getDataElement(unnormComponents, 0);
+ }
+
+ /**
+ * Takes a pixel whose data is defined by an int, and writes the
+ * corresponding components into the components array, starting
+ * from the index offset.
+ *
+ * @param pixel the pixel data
+ * @param components the data array to write the components to (or
+ * null to have the method create the return array)
+ * @param offset the offset that determines where the results are
+ * written in the components array
+ *
+ * @return the array of components corresponding to the pixel
+ */
+ public int[] getComponents(int pixel, int components[], int offset) {
+ throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+ "supported by this ColorModel"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the red component of the pixel determined by the pixel data.
+ *
+ * @param pixel the pixel data
+ *
+ * @return the red component of the pixel
+ */
+ public abstract int getRed(int pixel);
+
+ /**
+ * Takes the pixel data and returns the int corresponding
+ * to the pixel's color in RGB format.
+ *
+ * @param pixel the pixel data
+ *
+ * @return the corresponding RGB int
+ */
+ public int getRGB(int pixel) {
+ return (getAlpha(pixel) << 24 | getRed(pixel) << 16
+ | getGreen(pixel) << 8 | getBlue(pixel));
+ }
+
+ /**
+ * Gets the green component of the pixel determined by the pixel data.
+ *
+ * @param pixel the pixel data
+ *
+ * @return the green component of the pixel
+ */
+ public abstract int getGreen(int pixel);
+
+ /**
+ * Gets the size of the desired component of this color model.
+ *
+ * @param componentIdx the index that determines which component size to get
+ *
+ * @return the component size corresponding to the index
+ *
+ * @throws NullPointerException if this color model doesn't support
+ * an array of separate components.
+ * @throws ArrayIndexOutOfBoundsException if the index is negative or
+ * greater than or equal to the number of components
+ */
+ public int getComponentSize(int componentIdx) {
+ if (bits == null) {
+ // awt.26C=bits is null
+ throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
+ }
+
+ if (componentIdx < 0 || componentIdx >= bits.length) {
+ // awt.274=componentIdx is greater than the number of components or less than zero
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.274")); //$NON-NLS-1$
+ }
+
+ return bits[componentIdx];
+ }
+
+ /**
+ * Gets the blue component of the pixel determined by the pixel data.
+ *
+ * @param pixel the pixel
+ *
+ * @return the blue component of the pixel
+ */
+ public abstract int getBlue(int pixel);
+
+ /**
+ * Gets the alpha component of the pixel determined by the pixel data.
+ *
+ * @param pixel the pixel
+ *
+ * @return the alpha component of the pixel
+ */
+ public abstract int getAlpha(int pixel);
+
+ /**
+ * Gets the array of sizes of the different components.
+ *
+ * @return the array of sizes of the different components
+ */
+ public int[] getComponentSize() {
+ if (bits != null) {
+ return bits.clone();
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the alpha component is premultiplied.
+ *
+ * @return true, if the alpha component is premultiplied
+ */
+ public final boolean isAlphaPremultiplied() {
+ return isAlphaPremultiplied;
+ }
+
+ /**
+ * Checks whether this color model supports alpha.
+ *
+ * @return true, if this color model has alpha
+ */
+ public final boolean hasAlpha() {
+ return hasAlpha;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ int tmp;
+
+ if (hasAlpha) {
+ hash ^= 1;
+ hash <<= 8;
+ }
+ if (isAlphaPremultiplied) {
+ hash ^= 1;
+ hash <<= 8;
+ }
+
+ tmp = hash >>> 24;
+ hash ^= numColorComponents;
+ hash <<= 8;
+ hash |= tmp;
+
+ tmp = hash >>> 24;
+ hash ^= transparency;
+ hash <<= 8;
+ hash |= tmp;
+
+ tmp = hash >>> 24;
+ hash ^= cs.getType();
+ hash <<= 8;
+ hash |= tmp;
+
+ tmp = hash >>> 24;
+ hash ^= pixel_bits;
+ hash <<= 8;
+ hash |= tmp;
+
+ tmp = hash >>> 24;
+ hash ^= transferType;
+ hash <<= 8;
+ hash |= tmp;
+
+ if (bits != null) {
+
+ for (int element : bits) {
+ tmp = hash >>> 24;
+ hash ^= element;
+ hash <<= 8;
+ hash |= tmp;
+ }
+
+ }
+
+ return hash;
+ }
+
+ public int getTransparency() {
+ return transparency;
+ }
+
+ /**
+ * Gets the transfer type, which is the type of Java primitive
+ * value that corresponds to the bit length per pixel: either
+ * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT},
+ * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
+ *
+ * @return the transfer type
+ */
+ public final int getTransferType() {
+ return transferType;
+ }
+
+ /**
+ * Gets the pixel size in bits.
+ *
+ * @return the pixel size
+ */
+ public int getPixelSize() {
+ return pixel_bits;
+ }
+
+ /**
+ * Gets the number of components of this color model.
+ *
+ * @return the number of components
+ */
+ public int getNumComponents() {
+ return numComponents;
+ }
+
+ /**
+ * Gets the number of color components of this color model.
+ *
+ * @return the number color components
+ */
+ public int getNumColorComponents() {
+ return numColorComponents;
+ }
+
+ /**
+ * Gets the default RGB color model.
+ *
+ * @return the default RGB color model
+ */
+ public static ColorModel getRGBdefault() {
+ if (RGBdefault == null) {
+ RGBdefault = new DirectColorModel(32, 0x00ff0000, 0x0000ff00,
+ 0x000000ff, 0xff000000);
+ }
+ return RGBdefault;
+ }
+
+ /*
+ * Construct INT pixel representation from Object
+ * @param obj
+ *
+ * @return
+ */
+ /**
+ * Construct pixel.
+ *
+ * @param obj the obj
+ *
+ * @return the int
+ */
+ private int constructPixel(Object obj) {
+ int pixel = 0;
+
+ switch (getTransferType()) {
+
+ case DataBuffer.TYPE_BYTE:
+ byte[] bPixel = (byte[]) obj;
+ if(bPixel.length > 1) {
+ // awt.275=This pixel representation is not suuported by tis Color Model
+ throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+ }
+ pixel = bPixel[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short[] sPixel = (short[]) obj;
+ if(sPixel.length > 1) {
+ // awt.275=This pixel representation is not suuported by tis Color Model
+ throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+ }
+ pixel = sPixel[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int[] iPixel = (int[]) obj;
+ if(iPixel.length > 1) {
+ // awt.275=This pixel representation is not suuported by tis Color Model
+ throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+ }
+ pixel = iPixel[0];
+ break;
+
+ default:
+ // awt.22D=This transferType ( {0} ) is not supported by this color model
+ throw new UnsupportedOperationException(Messages.getString("awt.22D", //$NON-NLS-1$
+ transferType));
+
+ }
+ return pixel;
+ }
+
+ /**
+ * Gets the transfer type, which is the type of Java primitive
+ * value that corresponds to the bit length per pixel: either
+ * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT},
+ * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
+ *
+ * @param bits the array of component masks
+ *
+ * @return the transfer type
+ */
+ static int getTransferType(int bits) {
+ if (bits <= 8) {
+ return DataBuffer.TYPE_BYTE;
+ } else if (bits <= 16) {
+ return DataBuffer.TYPE_USHORT;
+ } else if (bits <= 32) {
+ return DataBuffer.TYPE_INT;
+ } else {
+ return DataBuffer.TYPE_UNDEFINED;
+ }
+ }
+
+ @Override
+ public void finalize() {
+ // This method is added for the API compatibility
+ // Don't need to call super since Object's finalize is always empty
+ }
+}
diff --git a/awt/java/awt/image/ComponentColorModel.java b/awt/java/awt/image/ComponentColorModel.java
new file mode 100644
index 0000000..a152f55
--- /dev/null
+++ b/awt/java/awt/image/ComponentColorModel.java
@@ -0,0 +1,1471 @@
+/*
+ * 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.
+ */
+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 premultiplied
+ * @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 premultiplied
+ * @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 - int representation of pixel
+ *
+ * @return - 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 - pixel
+ * @param idx - index of component
+ *
+ * @return - 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 - pixel
+ * @param idx - index of component
+ *
+ * @return - 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$
+ }
+ }
+
+}
+
diff --git a/awt/java/awt/image/ComponentSampleModel.java b/awt/java/awt/image/ComponentSampleModel.java
new file mode 100644
index 0000000..2ff4f1a
--- /dev/null
+++ b/awt/java/awt/image/ComponentSampleModel.java
@@ -0,0 +1,690 @@
+/*
+ * 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.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ComponentSampleModel class represents a set of image data whose
+ * each element - the sample of a pixel - takes one data element of
+ * the DataBuffer.
+ * <p>
+ * The Bank indices denote the correspondence between the bank of data
+ * buffers and a band of image data. The Pixel stride is the number of data
+ * array elements between two samples for the same band on the same
+ * scanline. The pixel stride for a BandedSampleModel is one. The Scanline
+ * stride represents the number of data array elements between a
+ * specified sample and the corresponding sample in the same column in
+ * the next scanline. The array of band offsets gives the starting
+ * offsets within each data banks of the in the DataBuffer. The bank
+ * indices represents the indices within each bank of the DataBuffer
+ * corresponding to a band of image data.
+ */
+public class ComponentSampleModel extends SampleModel {
+
+ /** The band offsets array of this ComponentSampleModel. */
+ protected int bandOffsets[];
+
+ /** The bank indices array of this ComponentSampleModel. */
+ protected int bankIndices[];
+
+ /** The number of bands in this ComponentSampleModel. */
+ protected int numBands;
+
+ /** The number banks of this ComponentSampleModel. */
+ protected int numBanks;
+
+ /** The scanline stride of this ComponentSampleModel. */
+ protected int scanlineStride;
+
+ /** The pixel stride of this ComponentSampleModel. */
+ protected int pixelStride;
+
+ /**
+ * Instantiates a new ComponentSampleModel with the specified
+ * properties.
+ *
+ * @param dataType the data type of samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param pixelStride the pixel stride of the image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param bankIndices the array of the bank indices.
+ * @param bandOffsets the array of the band offsets.
+ */
+ public ComponentSampleModel(int dataType, int w, int h, int pixelStride,
+ int scanlineStride, int bankIndices[], int bandOffsets[]) {
+
+ super(dataType, w, h, bandOffsets.length);
+
+ if (pixelStride < 0) {
+ // awt.24B=Pixel stride must be >= 0
+ throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$
+ }
+
+ if (scanlineStride < 0) {
+ // awt.24C=Scanline stride must be >= 0
+ throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$
+ }
+
+ if (bankIndices.length != bandOffsets.length) {
+ // awt.24D=Bank Indices length must be equal Bank Offsets length
+ throw new IllegalArgumentException(Messages.getString("awt.24D")); //$NON-NLS-1$
+ }
+
+ this.pixelStride = pixelStride;
+ this.scanlineStride = scanlineStride;
+ this.bandOffsets = bandOffsets.clone();
+ this.bankIndices = bankIndices.clone();
+ this.numBands = bandOffsets.length;
+
+ int maxBank = 0;
+ for (int i = 0; i < bankIndices.length; i++) {
+ if (bankIndices[i] < 0) {
+ // awt.24E=Index of {0} bank must be >= 0
+ throw new IllegalArgumentException(Messages.getString("awt.24E", i)); //$NON-NLS-1$
+ }
+ if (bankIndices[i] > maxBank) {
+ maxBank = bankIndices[i];
+ }
+ }
+ this.numBanks = maxBank + 1;
+
+ }
+
+ /**
+ * Instantiates a new ComponentSampleModel with the specified
+ * properties.
+ *
+ * @param dataType the data type of the samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param pixelStride the pixel stride of the image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param bandOffsets the band offsets.
+ */
+ public ComponentSampleModel(int dataType, int w, int h, int pixelStride,
+ int scanlineStride, int bandOffsets[]) {
+
+ super(dataType, w, h, bandOffsets.length);
+ if (pixelStride < 0) {
+ // awt.24B=Pixel stride must be >= 0
+ throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$
+ }
+
+ if (scanlineStride < 0) {
+ // awt.24C=Scanline stride must be >= 0
+ throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$
+ }
+
+ this.pixelStride = pixelStride;
+ this.scanlineStride = scanlineStride;
+ this.bandOffsets = bandOffsets.clone();
+ this.numBands = bandOffsets.length;
+ this.numBanks = 1;
+
+ this.bankIndices = new int[numBands];
+ for (int i = 0; i < numBands; i++) {
+ bankIndices[i] = 0;
+ }
+ }
+
+ @Override
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ byte bdata[];
+ if (obj == null) {
+ bdata = new byte[numBands];
+ } else {
+ bdata = (byte[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ bdata[i] = (byte) getSample(x, y, i, data);
+ }
+
+ obj = bdata;
+ break;
+
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short sdata[];
+ if (obj == null) {
+ sdata = new short[numBands];
+ } else {
+ sdata = (short[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ sdata[i] = (short) getSample(x, y, i, data);
+ }
+
+ obj = sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int idata[];
+ if (obj == null) {
+ idata = new int[numBands];
+ } else {
+ idata = (int[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ idata[i] = getSample(x, y, i, data);
+ }
+
+ obj = idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float fdata[];
+ if (obj == null) {
+ fdata = new float[numBands];
+ } else {
+ fdata = (float[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ fdata[i] = getSampleFloat(x, y, i, data);
+ }
+
+ obj = fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double ddata[];
+ if (obj == null) {
+ ddata = new double[numBands];
+ } else {
+ ddata = (double[]) obj;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ ddata[i] = getSampleDouble(x, y, i, data);
+ }
+
+ obj = ddata;
+ break;
+ }
+
+ return obj;
+ }
+
+ @Override
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ byte barr[] = (byte[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, barr[i] & 0xff, data);
+ }
+ break;
+
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short sarr[] = (short[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, sarr[i] & 0xffff, data);
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int iarr[] = (int[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, iarr[i], data);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float farr[] = (float[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, farr[i], data);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double darr[] = (double[]) obj;
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, darr[i], data);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Compares this ComponentSampleModel with the specified Object.
+ *
+ * @param o the Object.
+ *
+ * @return true, if the object is a ComponentSampleModel with
+ * identical data values to this ComponentSampleModel, false otherwise.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof ComponentSampleModel)) {
+ return false;
+ }
+ ComponentSampleModel model = (ComponentSampleModel) o;
+ return this.width == model.width && this.height == model.height &&
+ this.numBands == model.numBands &&
+ this.dataType == model.dataType &&
+ Arrays.equals(this.bandOffsets, model.bandOffsets) &&
+ Arrays.equals(this.bankIndices, model.bankIndices) &&
+ this.numBands == model.numBands &&
+ this.numBanks == model.numBanks &&
+ this.scanlineStride == model.scanlineStride &&
+ this.pixelStride == model.pixelStride;
+ }
+
+ /**
+ * @see java.awt.image.SampleModel#createSubsetSampleModel(int[])
+ */
+ @Override
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands.length > this.numBands) {
+ // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+ throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+ }
+
+ int indices[] = new int[bands.length];
+ int offsets[] = new int[bands.length];
+
+ for (int i = 0; i < bands.length; i++) {
+ indices[i] = bankIndices[bands[i]];
+ offsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new ComponentSampleModel(dataType, width, height, pixelStride,
+ scanlineStride, indices, offsets);
+
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ return new ComponentSampleModel(dataType, w, h, pixelStride,
+ pixelStride * w, bankIndices, bandOffsets);
+ }
+
+ @Override
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ int pixel[];
+
+ if (iArray == null) {
+ pixel = new int[numBands];
+ } else {
+ pixel = iArray;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ pixel[i] = getSample(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ @Override
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, iArray[i], data);
+ }
+ }
+
+ @Override
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElem(bankIndices[b], y * scanlineStride +
+ x * pixelStride + bandOffsets[b]);
+ }
+
+ @Override
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElemFloat(bankIndices[b], y * scanlineStride +
+ x * pixelStride + bandOffsets[b]);
+ }
+
+ @Override
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ return data.getElemDouble(bankIndices[b], y * scanlineStride +
+ x * pixelStride + bandOffsets[b]);
+ }
+
+ @Override
+ public int[] getPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x > this.width || x + w > this.width
+ || y > this.height || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int pixels[] = null;
+ int idx = 0;
+
+ if (iArray == null) {
+ pixels = new int[w * h * numBands];
+ } else {
+ pixels = iArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ pixels[idx++] = getSample(j, i, n, data);
+ }
+ }
+ }
+
+ return pixels;
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ setSample(j, i, n, iArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, int s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElem(bankIndices[b], y * scanlineStride + x * pixelStride
+ + bandOffsets[b], s);
+ }
+
+ @Override
+ public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int samples[];
+ int idx = 0;
+
+ if (iArray == null) {
+ samples = new int[w * h];
+ } else {
+ samples = iArray;
+ }
+
+ if (data == null) {
+ // awt.295=data is null
+ throw new NullPointerException(Messages.getString("awt.295")); //$NON-NLS-1$
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSample(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ @Override
+ public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(j, i, b, iArray[idx++], data);
+ }
+ }
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, float s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElemFloat(bankIndices[b], y * scanlineStride +
+ x * pixelStride + bandOffsets[b], s);
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, double s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ data.setElemDouble(bankIndices[b], y * scanlineStride +
+ x * pixelStride + bandOffsets[b], s);
+ }
+
+ @Override
+ public DataBuffer createDataBuffer() {
+ DataBuffer data = null;
+
+ int maxOffset = bandOffsets[0];
+ for (int i = 1; i < bandOffsets.length; i++) {
+ if (bandOffsets[i] > maxOffset) {
+ maxOffset = bandOffsets[i];
+ }
+ }
+ int size = (height - 1) * scanlineStride +
+ (width - 1) * pixelStride + maxOffset + 1;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(size, numBanks);
+ break;
+ case DataBuffer.TYPE_SHORT:
+ data = new DataBufferShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(size, numBanks);
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ data = new DataBufferFloat(size, numBanks);
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ data = new DataBufferDouble(size, numBanks);
+ break;
+ }
+
+ return data;
+
+ }
+
+ /**
+ * Gets the offset of the specified band of the specified pixel.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the band.
+ *
+ * @return the offset of the specified band of the specified pixel.
+ */
+ public int getOffset(int x, int y, int b) {
+ return y * scanlineStride + x * pixelStride + bandOffsets[b];
+ }
+
+ /**
+ * Gets the offset of the first band of the specified pixel.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ *
+ * @return the offset of the first band of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ return y * scanlineStride + x * pixelStride + bandOffsets[0];
+ }
+
+ @Override
+ public final int getSampleSize(int band) {
+ return DataBuffer.getDataTypeSize(dataType);
+ }
+
+ @Override
+ public final int[] getSampleSize() {
+ int sampleSizes[] = new int[numBands];
+ int size = DataBuffer.getDataTypeSize(dataType);
+
+ for (int i = 0; i < numBands; i++) {
+ sampleSizes[i] = size;
+ }
+ return sampleSizes;
+ }
+
+ /**
+ * Gets an array of bank indices corresponding to this
+ * ComponentSampleModel.
+ *
+ * @return the array of bank indices.
+ */
+ public final int[] getBankIndices() {
+ return bankIndices.clone();
+ }
+
+ /**
+ * Gets an array of the band offsets corresponding to this
+ * ComponentSampleModel.
+ *
+ * @return the array of band offsets.
+ */
+ public final int[] getBandOffsets() {
+ return bandOffsets.clone();
+ }
+
+ /**
+ * Gets a hash code of this ComponentSampleModel object.
+ *
+ * @return a hash code of this ComponentSampleModel object.
+ */
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ int tmp = 0;
+
+ hash = width;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= height;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= numBands;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= dataType;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ for (int element : bandOffsets) {
+ hash ^= element;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ }
+ for (int element : bankIndices) {
+ hash ^= element;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ }
+ hash ^= pixelStride;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+
+ hash ^= scanlineStride;
+ return hash;
+ }
+
+ /**
+ * Gets the scanline stride of this ComponentSampleModel.
+ *
+ * @return the scanline stride of this ComponentSampleModel.
+ */
+ public final int getScanlineStride() {
+ return scanlineStride;
+ }
+
+ /**
+ * Gets the pixel stride.
+ *
+ * @return the pixel stride
+ */
+ public final int getPixelStride() {
+ return pixelStride;
+ }
+
+ @Override
+ public final int getNumDataElements() {
+ return numBands;
+ }
+
+}
+
+
+
diff --git a/awt/java/awt/image/ConvolveOp.java b/awt/java/awt/image/ConvolveOp.java
new file mode 100644
index 0000000..bb588bc
--- /dev/null
+++ b/awt/java/awt/image/ConvolveOp.java
@@ -0,0 +1,545 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 29, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ConvolveOp class convolves from the source data
+ * to the destination using a convolution kernel.
+ * Each output pixel is represented as the result of multiplying
+ * the kernel and the surround of the input pixel.
+ */
+public class ConvolveOp implements BufferedImageOp, RasterOp {
+
+ /**
+ * The Constant EDGE_ZERO_FILL indicates that pixels at the edge of
+ * the destination image are set to zero.
+ */
+ public static final int EDGE_ZERO_FILL = 0;
+
+ /**
+ * The Constant EDGE_NO_OP indicates that pixels at the edge of
+ * the source image are converted to the edge pixels in the
+ * destination without modification.
+ */
+ public static final int EDGE_NO_OP = 1;
+
+ /** The kernel. */
+ private Kernel kernel;
+
+ /** The edge cond. */
+ private int edgeCond;
+
+ /** The rhs. */
+ private RenderingHints rhs = null;
+
+ static {
+ // TODO
+ //System.loadLibrary("imageops");
+ }
+
+ /**
+ * Instantiates a new ConvolveOp object with the specified Kernel
+ * and specified edges condition.
+ *
+ * @param kernel the specified Kernel.
+ * @param edgeCondition the specified edge condition.
+ * @param hints the RenderingHints object, or null.
+ */
+ public ConvolveOp(Kernel kernel, int edgeCondition, RenderingHints hints) {
+ this.kernel = kernel;
+ this.edgeCond = edgeCondition;
+ this.rhs = hints;
+ }
+
+ /**
+ * Instantiates a new ConvolveOp object with the specified Kernel
+ * and EDGE_ZERO_FILL edge condition.
+ *
+ * @param kernel the specified Kernel.
+ */
+ public ConvolveOp(Kernel kernel) {
+ this.kernel = kernel;
+ this.edgeCond = EDGE_ZERO_FILL;
+ }
+
+ /**
+ * Gets the Kernel object of this ConvolveOp.
+ *
+ * @return the Kernel object of this ConvolveOp.
+ */
+ public final Kernel getKernel() {
+ return (Kernel) kernel.clone();
+ }
+
+ public final RenderingHints getRenderingHints() {
+ return rhs;
+ }
+
+ /**
+ * Gets the edge condition of this ConvolveOp.
+ *
+ * @return the edge condition: EDGE_NO_OP or EDGE_ZERO_FILL.
+ */
+ public int getEdgeCondition() {
+ return edgeCond;
+ }
+
+ public final Rectangle2D getBounds2D(Raster src) {
+ return src.getBounds();
+ }
+
+ public final Rectangle2D getBounds2D(BufferedImage src) {
+ return getBounds2D(src.getRaster());
+ }
+
+ public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ if (dstPt == null) {
+ dstPt = new Point2D.Float();
+ }
+
+ dstPt.setLocation(srcPt);
+ return dstPt;
+ }
+
+ public WritableRaster createCompatibleDestRaster(Raster src) {
+ return src.createCompatibleWritableRaster();
+ }
+
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+ if (dstCM == null) {
+ dstCM = src.getColorModel();
+ }
+
+ if (dstCM instanceof IndexColorModel) {
+ dstCM = ColorModel.getRGBdefault();
+ }
+
+ WritableRaster r =
+ dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+ src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+ dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+ return new BufferedImage(
+ dstCM,
+ r,
+ dstCM.isAlphaPremultiplied(),
+ null
+ );
+ }
+
+ public final WritableRaster filter(Raster src, WritableRaster dst) {
+ if (src == null) { // Should throw according to spec
+ // awt.256=Source raster is null
+ throw new NullPointerException(Messages.getString("awt.256")); //$NON-NLS-1$
+ }
+
+ if (src == dst){
+ // awt.257=Source raster is equal to destination
+ throw new IllegalArgumentException(Messages.getString("awt.257")); //$NON-NLS-1$
+ }
+
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else if (src.getNumBands() != dst.getNumBands()) {
+ // awt.258=Number of source bands ({0}) is not equal to number of destination bands ({1})
+ throw new IllegalArgumentException(
+ Messages.getString("awt.258", src.getNumBands(), dst.getNumBands())); //$NON-NLS-1$
+ }
+
+ // TODO
+ //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM) != 0)
+ if (slowFilter(src, dst) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ return dst;
+ }
+
+ /**
+ * Slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ *
+ * @return the int
+ */
+ private int slowFilter(Raster src, WritableRaster dst) {
+ try {
+ SampleModel sm = src.getSampleModel();
+
+ int numBands = src.getNumBands();
+ int srcHeight = src.getHeight();
+ int srcWidth = src.getWidth();
+
+ int xOrigin = kernel.getXOrigin();
+ int yOrigin = kernel.getYOrigin();
+ int kWidth = kernel.getWidth();
+ int kHeight = kernel.getHeight();
+ float[] data = kernel.getKernelData(null);
+
+ int srcMinX = src.getMinX();
+ int srcMinY = src.getMinY();
+ int dstMinX = dst.getMinX();
+ int dstMinY = dst.getMinY();
+
+ int srcConvMaxX = srcWidth - (kWidth - xOrigin - 1);
+ int srcConvMaxY = srcHeight - (kHeight - yOrigin - 1);
+
+ int[] maxValues = new int[numBands];
+ int[] masks = new int[numBands];
+ int[] sampleSizes = sm.getSampleSize();
+
+ for (int i=0; i < numBands; i++){
+ maxValues[i] = (1 << sampleSizes[i]) - 1;
+ masks[i] = ~(maxValues[i]);
+ }
+
+ // Processing bounds
+ float[] pixels = null;
+ pixels = src.getPixels(srcMinX, srcMinY, srcWidth, srcHeight, pixels);
+ float[] newPixels = new float[pixels.length];
+ int rowLength = srcWidth*numBands;
+ if (this.edgeCond == ConvolveOp.EDGE_NO_OP){
+ // top
+ int start = 0;
+ int length = yOrigin*rowLength;
+ System.arraycopy(pixels, start, newPixels, start, length);
+ // bottom
+ start = (srcHeight - (kHeight - yOrigin - 1))*rowLength;
+ length = (kHeight - yOrigin - 1)*rowLength;
+ System.arraycopy(pixels, start, newPixels, start, length);
+ // middle
+ length = xOrigin*numBands;
+ int length1 = (kWidth - xOrigin - 1)*numBands;
+ start = yOrigin*rowLength;
+ int start1 = (yOrigin+1)*rowLength - length1;
+ for (int i = yOrigin; i < (srcHeight - (kHeight - yOrigin - 1)); i ++) {
+ System.arraycopy(pixels, start, newPixels, start, length);
+ System.arraycopy(pixels, start1, newPixels, start1, length1);
+ start +=rowLength;
+ start1 +=rowLength;
+ }
+
+ }
+
+ // Cycle over pixels to be calculated
+ for (int i = yOrigin; i < srcConvMaxY; i++){
+ for (int j = xOrigin; j < srcConvMaxX; j++){
+
+ // Take kernel data in backward direction, convolution
+ int kernelIdx = data.length - 1;
+
+ int pixelIndex = i * rowLength + j * numBands;
+ for (int hIdx = 0, rasterHIdx = i - yOrigin;
+ hIdx < kHeight;
+ hIdx++, rasterHIdx++
+ ){
+ for (int wIdx = 0, rasterWIdx = j - xOrigin;
+ wIdx < kWidth;
+ wIdx++, rasterWIdx++
+ ){
+ int curIndex = rasterHIdx * rowLength + rasterWIdx * numBands;
+ for (int idx=0; idx < numBands; idx++){
+ newPixels[pixelIndex+idx] += data[kernelIdx] * pixels[curIndex+idx];
+ }
+ kernelIdx--;
+ }
+ }
+
+ // Check for overflow now
+ for (int idx=0; idx < numBands; idx++){
+ if (((int)newPixels[pixelIndex+idx] & masks[idx]) != 0) {
+ if (newPixels[pixelIndex+idx] < 0) {
+ newPixels[pixelIndex+idx] = 0;
+ } else {
+ newPixels[pixelIndex+idx] = maxValues[idx];
+ }
+ }
+ }
+ }
+ }
+
+ dst.setPixels(dstMinX, dstMinY, srcWidth, srcHeight, newPixels);
+ } catch (Exception e) { // Something goes wrong, signal error
+ return 1;
+ }
+ return 0;
+ }
+
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+ if (src == null) {
+ // awt.259=Source image is null
+ throw new NullPointerException(Messages.getString("awt.259")); //$NON-NLS-1$
+ }
+
+ if (src == dst){
+ // awt.25A=Source equals to destination
+ throw new IllegalArgumentException(Messages.getString("awt.25A")); //$NON-NLS-1$
+ }
+
+ ColorModel srcCM = src.getColorModel();
+ BufferedImage finalDst = null;
+
+ if (srcCM instanceof IndexColorModel) {
+ src = ((IndexColorModel)srcCM).convertToIntDiscrete(src.getRaster(), true);
+ srcCM = src.getColorModel();
+ }
+
+ if (dst == null) {
+ dst = createCompatibleDestImage(src, srcCM);
+ } else {
+ if (!srcCM.equals(dst.getColorModel())) {
+ // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+ if (
+ !((src.getType() == BufferedImage.TYPE_INT_RGB ||
+ src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+ (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+ dst.getType() == BufferedImage.TYPE_INT_ARGB))
+ ) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, srcCM);
+ }
+ }
+ }
+
+ // Skip alpha channel for TYPE_INT_RGB images
+ // TODO
+ //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType()) != 0)
+ if (slowFilter(src.getRaster(), dst.getRaster()) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ if (finalDst != null) {
+ Graphics2D g = finalDst.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.drawImage(dst, 0, 0, null);
+ } else {
+ finalDst = dst;
+ }
+
+ return finalDst;
+ }
+
+ // TODO remove when this method is used
+ /**
+ * Ipp filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param imageType the image type
+ *
+ * @return the int
+ */
+ @SuppressWarnings("unused")
+ private int ippFilter(Raster src, WritableRaster dst, int imageType) {
+ int srcStride, dstStride;
+ boolean skipChannel = false;
+ int channels;
+ int offsets[] = null;
+
+ switch (imageType) {
+ case BufferedImage.TYPE_INT_RGB:
+ case BufferedImage.TYPE_INT_BGR: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ skipChannel = true;
+ break;
+ }
+
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ break;
+ }
+
+ case BufferedImage.TYPE_BYTE_GRAY: {
+ channels = 1;
+ srcStride = src.getWidth();
+ dstStride = dst.getWidth();
+ break;
+ }
+
+ case BufferedImage.TYPE_3BYTE_BGR: {
+ channels = 3;
+ srcStride = src.getWidth()*3;
+ dstStride = dst.getWidth()*3;
+ break;
+ }
+
+ case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in native code?
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ case BufferedImage.TYPE_BYTE_BINARY: {
+ return slowFilter(src, dst);
+ }
+
+ default: {
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+
+ if (
+ srcSM instanceof PixelInterleavedSampleModel &&
+ dstSM instanceof PixelInterleavedSampleModel
+ ) {
+ // Check PixelInterleavedSampleModel
+ if (
+ srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+ dstSM.getDataType() != DataBuffer.TYPE_BYTE
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+ if (!(channels == 1 || channels == 3 || channels == 4)) {
+ return slowFilter(src, dst);
+ }
+
+ srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+ dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+ } else if (
+ srcSM instanceof SinglePixelPackedSampleModel &&
+ dstSM instanceof SinglePixelPackedSampleModel
+ ) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+ SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+ channels = sppsm1.getNumBands();
+
+ // TYPE_INT_RGB, TYPE_INT_ARGB...
+ if (
+ sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+ sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+ !(channels == 3 || channels == 4)
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ // Check compatibility of sample models
+ if (
+ !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+ !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+ ) {
+ return slowFilter(src, dst);
+ }
+
+ for (int i=0; i<channels; i++) {
+ if (sppsm1.getSampleSize(i) != 8) {
+ return slowFilter(src, dst);
+ }
+ }
+
+ if (channels == 3) { // Cannot skip channel, don't know which is alpha...
+ channels = 4;
+ }
+
+ srcStride = sppsm1.getScanlineStride() * 4;
+ dstStride = sppsm2.getScanlineStride() * 4;
+ } else {
+ return slowFilter(src, dst);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (
+ src.getSampleModelTranslateX() != 0 ||
+ src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 ||
+ dst.getSampleModelTranslateY() != 0
+ ) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+ }
+ }
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ return ippFilter32f(
+ kernel.data, kernel.getWidth(), kernel.getHeight(),
+ kernel.getXOrigin(), kernel.getYOrigin(), edgeCond,
+ srcData, src.getWidth(), src.getHeight(), srcStride,
+ dstData, dst.getWidth(), dst.getHeight(), dstStride,
+ channels, skipChannel, offsets
+ );
+ }
+
+ /**
+ * Ipp filter32f.
+ *
+ * @param kernel the kernel
+ * @param kWidth the k width
+ * @param kHeight the k height
+ * @param anchorX the anchor x
+ * @param anchorY the anchor y
+ * @param borderType the border type
+ * @param src the src
+ * @param srcWidth the src width
+ * @param srcHeight the src height
+ * @param srcStride the src stride
+ * @param dst the dst
+ * @param dstWidth the dst width
+ * @param dstHeight the dst height
+ * @param dstStride the dst stride
+ * @param channels the channels
+ * @param skipChannel the skip channel
+ * @param offsets the offsets
+ *
+ * @return the int
+ */
+ private native int ippFilter32f(
+ float kernel[], int kWidth, int kHeight,
+ int anchorX, int anchorY, int borderType,
+ Object src, int srcWidth, int srcHeight, int srcStride,
+ Object dst, int dstWidth, int dstHeight, int dstStride,
+ int channels, boolean skipChannel, int offsets[]
+ );
+}
+
diff --git a/awt/java/awt/image/CropImageFilter.java b/awt/java/awt/image/CropImageFilter.java
new file mode 100644
index 0000000..e90c44a
--- /dev/null
+++ b/awt/java/awt/image/CropImageFilter.java
@@ -0,0 +1,193 @@
+/*
+ * 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.util.Hashtable;
+
+/**
+ * The CropImageFilter class crops a rectangular region of an source
+ * Image and provides a source for a new image containing the extracted
+ * region.
+ */
+public class CropImageFilter extends ImageFilter {
+
+ /** The HEIGHT. */
+ private final int X, Y, WIDTH, HEIGHT;
+
+ /**
+ * Instantiates a new CropImageFilter object with the specified
+ * rectangular area.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ */
+ public CropImageFilter(int x, int y, int w, int h) {
+ X = x;
+ Y = y;
+ WIDTH = w;
+ HEIGHT = h;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void setProperties(Hashtable<?, ?> props) {
+ Hashtable<Object, Object> fprops;
+ if(props == null) {
+ fprops = new Hashtable<Object, Object>();
+ } else {
+ fprops = (Hashtable<Object, Object>) props.clone();
+ }
+ String propName = "Crop Filters"; //$NON-NLS-1$
+ String prop = "x=" + X + "; y=" + Y + "; width=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ WIDTH + "; height=" + HEIGHT; //$NON-NLS-1$
+ Object o = fprops.get(propName);
+ if(o != null){
+ if(o instanceof String){
+ prop = (String)o + "; " + prop; //$NON-NLS-1$
+ }else{
+ prop = o.toString() + "; " + prop; //$NON-NLS-1$
+ }
+ }
+ fprops.put(propName, prop);
+ consumer.setProperties(fprops);
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {
+
+ if(x + w < X || X + WIDTH < x ||
+ y + h < Y || Y + HEIGHT < y) {
+ return;
+ }
+
+ int destX, destY, destWidth, destHeight, endX, endY,
+ srcEndX, srcEndY;
+
+ int newOffset = off;
+
+ endX = X + WIDTH;
+ endY = Y + HEIGHT;
+
+ srcEndX = x + w;
+ srcEndY = y + h;
+
+ if(x <= X){
+ destX = 0;
+ newOffset += X;
+ if(endX >= srcEndX){
+ destWidth = srcEndX - X;
+ }else{
+ destWidth = WIDTH;
+ }
+ }else{
+ destX = x - X;
+ if(endX >= srcEndX){
+ destWidth = w;
+ }else{
+ destWidth = endX - x;
+ }
+ }
+
+
+ if(y <= Y){
+ newOffset += scansize * (Y - y);
+ destY = 0;
+ if(endY >= srcEndY){
+ destHeight = srcEndY - Y;
+ }else{
+ destHeight = HEIGHT;
+ }
+ }else{
+ destY = y - Y;
+ if(endY >= srcEndY){
+ destHeight = h;
+ }else{
+ destHeight = endY - y;
+ }
+ }
+ consumer.setPixels(destX, destY, destWidth, destHeight, model, pixels, newOffset, scansize);
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+
+ if(x + w < X || X + WIDTH < x ||
+ y + h < Y || Y + HEIGHT < y) {
+ return;
+ }
+
+ int destX, destY, destWidth, destHeight, endX, endY,
+ srcEndX, srcEndY;
+
+ int newOffset = off;
+
+ endX = X + WIDTH;
+ endY = Y + HEIGHT;
+
+ srcEndX = x + w;
+ srcEndY = y + h;
+
+ if(x <= X){
+ destX = 0;
+ newOffset += X;
+ if(endX >= srcEndX){
+ destWidth = srcEndX - X;
+ }else{
+ destWidth = WIDTH;
+ }
+ }else{
+ destX = x - X;
+ if(endX >= srcEndX){
+ destWidth = w;
+ }else{
+ destWidth = endX - x;
+ }
+ }
+
+
+ if(y <= Y){
+ newOffset += scansize * (Y - y);
+ destY = 0;
+ if(endY >= srcEndY){
+ destHeight = srcEndY - Y;
+ }else{
+ destHeight = HEIGHT;
+ }
+ }else{
+ destY = y - Y;
+ if(endY >= srcEndY){
+ destHeight = h;
+ }else{
+ destHeight = endY - y;
+ }
+ }
+ consumer.setPixels(destX, destY, destWidth, destHeight, model, pixels, newOffset, scansize);
+ }
+
+ @Override
+ public void setDimensions(int w, int h) {
+ consumer.setDimensions(WIDTH, HEIGHT);
+ }
+
+}
+
diff --git a/awt/java/awt/image/DataBuffer.java b/awt/java/awt/image/DataBuffer.java
new file mode 100644
index 0000000..6856aee
--- /dev/null
+++ b/awt/java/awt/image/DataBuffer.java
@@ -0,0 +1,442 @@
+/*
+ * 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 org.apache.harmony.awt.gl.image.DataBufferListener;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DataBuffer is a wrapper class for a data array
+ * to be used for the situation where a suite of functionality
+ * acts on a set of data in a consistent way even though the
+ * primitive type of the data may vary from one use to the next.
+ */
+public abstract class DataBuffer {
+
+ /** The Constant TYPE_BYTE. */
+ public static final int TYPE_BYTE = 0;
+
+ /** The Constant TYPE_USHORT. */
+ public static final int TYPE_USHORT = 1;
+
+ /** The Constant TYPE_SHORT. */
+ public static final int TYPE_SHORT = 2;
+
+ /** The Constant TYPE_INT. */
+ public static final int TYPE_INT = 3;
+
+ /** The Constant TYPE_FLOAT. */
+ public static final int TYPE_FLOAT = 4;
+
+ /** The Constant TYPE_DOUBLE. */
+ public static final int TYPE_DOUBLE = 5;
+
+ /** The Constant TYPE_UNDEFINED. */
+ public static final int TYPE_UNDEFINED = 32;
+
+ /** The data type indicates the primitive type of the
+ * data in this DataBuffer. */
+ protected int dataType;
+
+ /** The number of data arrays in this DataBuffer. */
+ protected int banks;
+
+ /** The starting index for reading the
+ * data from the first (or only) internal data array. */
+ protected int offset;
+
+ /** The length (number of elements) of the data arrays. */
+ protected int size;
+
+ /** The starting indices for reading the
+ * data from the internal data arrays. */
+ protected int offsets[];
+
+ /** The data changed. */
+ boolean dataChanged = true;
+
+ /** The data taken. */
+ boolean dataTaken = false;
+
+ /** The listener. */
+ DataBufferListener listener;
+
+ static {
+ AwtImageBackdoorAccessorImpl.init();
+ }
+
+ /**
+ * Instantiates a new data buffer.
+ *
+ * @param dataType the data type
+ * @param size the length (number of elements) of the data arrays
+ * @param numBanks the number of data arrays to create
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
+ this.dataType = dataType;
+ this.size = size;
+ this.banks = numBanks;
+ this.offsets = offsets.clone();
+ this.offset = offsets[0];
+ }
+
+ /**
+ * Instantiates a new data buffer with all of the
+ * data arrays starting at the same index.
+ *
+ * @param dataType the data type
+ * @param size the length (number of elements) of the data arrays
+ * @param numBanks the number of data arrays to create
+ * @param offset the offset to use for all of the data arrays
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int offset) {
+ this.dataType = dataType;
+ this.size = size;
+ this.banks = numBanks;
+ this.offset = offset;
+ this.offsets = new int[numBanks];
+ int i = 0;
+ while (i < numBanks) {
+ offsets[i++] = offset;
+ }
+ }
+
+ /**
+ * Instantiates a new data buffer with all of the
+ * data arrays read from the beginning (at offset zero).
+ *
+ * @param dataType the data type
+ * @param size the length (number of elements) of the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ protected DataBuffer(int dataType, int size, int numBanks) {
+ this.dataType = dataType;
+ this.size = size;
+ this.banks = numBanks;
+ this.offset = 0;
+ this.offsets = new int[numBanks];
+ }
+
+ /**
+ * Instantiates a new data buffer with one internal data array
+ * read from the beginning (at offset zero).
+ *
+ * @param dataType the data type
+ * @param size the length (number of elements) of the data arrays
+ */
+ protected DataBuffer(int dataType, int size) {
+ this.dataType = dataType;
+ this.size = size;
+ this.banks = 1;
+ this.offset = 0;
+ this.offsets = new int[1];
+ }
+
+ /**
+ * Sets the data value in the specified array at the
+ * specified index.
+ *
+ * @param bank the internal array to the data to
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public abstract void setElem(int bank, int i, int val);
+
+ /**
+ * Sets the float data value in the specified array at the
+ * specified index.
+ *
+ * @param bank the internal array to the data to
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public void setElemFloat(int bank, int i, float val) {
+ setElem(bank, i, (int) val);
+ }
+
+ /**
+ * Sets the double data value in the specified array at the
+ * specified index.
+ *
+ * @param bank the internal array to the data to
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public void setElemDouble(int bank, int i, double val) {
+ setElem(bank, i, (int) val);
+ }
+
+ /**
+ * Sets the data value in the first array at the
+ * specified index.
+ *
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public void setElem(int i, int val) {
+ setElem(0, i, val);
+ }
+
+ /**
+ * Gets the data value from the specified data array at the
+ * specified index.
+ *
+ * @param bank the data array to read from
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public abstract int getElem(int bank, int i);
+
+ /**
+ * Gets the float-type data value from the specified
+ * data array at the specified index.
+ *
+ * @param bank the data array to read from
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public float getElemFloat(int bank, int i) {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Gets the double-type data value from the specified
+ * data array at the specified index.
+ *
+ * @param bank the data array to read from
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public double getElemDouble(int bank, int i) {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Sets the float data value in the first array at the
+ * specified index.
+ *
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public void setElemFloat(int i, float val) {
+ setElemFloat(0, i, val);
+ }
+
+ /**
+ * Sets the double data value in the first array at the
+ * specified index.
+ *
+ * @param i the index within the array where the data
+ * should be written
+ * @param val the value to write into the array
+ */
+ public void setElemDouble(int i, double val) {
+ setElemDouble(0, i, val);
+ }
+
+ /**
+ * Gets the data value from the first
+ * data array at the specified index and returns it
+ * as an int.
+ *
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public int getElem(int i) {
+ return getElem(0, i);
+ }
+
+ /**
+ * Gets the data value from the first
+ * data array at the specified index and returns it
+ * as a float.
+ *
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public float getElemFloat(int i) {
+ return getElem(0, i);
+ }
+
+ /**
+ * Gets the data value from the first
+ * data array at the specified index and returns it
+ * as a double.
+ *
+ * @param i the index within the array where the data
+ * should be read
+ *
+ * @return the data element
+ */
+ public double getElemDouble(int i) {
+ return getElem(i);
+ }
+
+ /**
+ * Gets the array giving the offsets corresponding
+ * to the internal data arrays.
+ *
+ * @return the array of offsets
+ */
+ public int[] getOffsets() {
+ return offsets;
+ }
+
+ /**
+ * Gets the size in bits of the primitive data type.
+ *
+ * @return the size in bits of the primitive data type
+
+ */
+ public int getSize() {
+ return size;
+ }
+
+ /**
+ * Gets the offset corresponding to the first internal
+ * data array.
+ *
+ * @return the offset
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Gets the number of data arrays in this DataBuffer.
+ *
+ * @return the number of data arrays
+ */
+ public int getNumBanks() {
+ return banks;
+ }
+
+ /**
+ * Gets the primitive type of this buffer's data.
+ *
+ * @return the data type
+ */
+ public int getDataType() {
+ return this.dataType;
+ }
+
+ /**
+ * Gets the size in bits of the primitive data type.
+ *
+ * @param type the primitive type
+ *
+ * @return the size in bits of the primitive data type
+ */
+ public static int getDataTypeSize(int type) {
+ switch (type) {
+
+ case TYPE_BYTE:
+ return 8;
+
+ case TYPE_USHORT:
+ case TYPE_SHORT:
+ return 16;
+
+ case TYPE_INT:
+ case TYPE_FLOAT:
+ return 32;
+
+ case TYPE_DOUBLE:
+ return 64;
+
+ default:
+ // awt.22C=Unknown data type {0}
+ throw new IllegalArgumentException(Messages.getString("awt.22C", type)); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Notifies the listener that the data has changed.
+ */
+ void notifyChanged(){
+ if(listener != null && !dataChanged){
+ dataChanged = true;
+ listener.dataChanged();
+ }
+ }
+
+ /**
+ * Notifies the listener that the data has been released.
+ */
+ void notifyTaken(){
+ if(listener != null && !dataTaken){
+ dataTaken = true;
+ listener.dataTaken();
+ }
+ }
+
+ /**
+ * Release the data.
+ */
+ void releaseData(){
+ if(listener != null && dataTaken){
+ dataTaken = false;
+ listener.dataReleased();
+ }
+ }
+
+ /**
+ * Adds the data buffer listener.
+ *
+ * @param listener the listener
+ */
+ void addDataBufferListener(DataBufferListener listener){
+ this.listener = listener;
+ }
+
+ /**
+ * Removes the data buffer listener.
+ */
+ void removeDataBufferListener(){
+ listener = null;
+ }
+
+ /**
+ * Validate.
+ */
+ void validate(){
+ dataChanged = false;
+ }
+
+}
+
diff --git a/awt/java/awt/image/DataBufferByte.java b/awt/java/awt/image/DataBufferByte.java
new file mode 100644
index 0000000..4d29c9c
--- /dev/null
+++ b/awt/java/awt/image/DataBufferByte.java
@@ -0,0 +1,171 @@
+/*
+ * 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;
+
+/**
+ * The Class DataBufferByte is the subclass of DataBuffer
+ * for the case where the underlying data is of type byte.
+ */
+public final class DataBufferByte extends DataBuffer {
+
+ /** The data. */
+ byte data[][];
+
+ /**
+ * Instantiates a new data buffer of type unsigned short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferByte(byte dataArrays[][], int size, int offsets[]) {
+ super(TYPE_BYTE, size, dataArrays.length, offsets);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferByte(byte dataArrays[][], int size) {
+ super(TYPE_BYTE, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+ */
+ public DataBufferByte(byte dataArray[], int size, int offset) {
+ super(TYPE_BYTE, size, 1, offset);
+ data = new byte[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferByte(byte dataArray[], int size) {
+ super(TYPE_BYTE, size);
+ data = new byte[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type unsigned short
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferByte(int size, int numBanks) {
+ super(TYPE_BYTE, size, numBanks);
+ data = new byte[numBanks][];
+ int i = 0;
+ while (i < numBanks) {
+ data[i++] = new byte[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type unsigned short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferByte(int size) {
+ super(TYPE_BYTE, size);
+ data = new byte[1][];
+ data[0] = new byte[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = (byte) val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = (byte) val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (data[bank][offsets[bank] + i]) & 0xff;
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired data array
+ *
+ * @return the data
+ */
+ public byte[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return (data[0][offset + i]) & 0xff;
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public byte[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public byte[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+
+}
+
diff --git a/awt/java/awt/image/DataBufferDouble.java b/awt/java/awt/image/DataBufferDouble.java
new file mode 100644
index 0000000..fa3d324
--- /dev/null
+++ b/awt/java/awt/image/DataBufferDouble.java
@@ -0,0 +1,214 @@
+/*
+ * 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;
+
+/**
+ * The Class DataBufferDouble is the subclass of DataBuffer
+ * for the case where the underlying data is of type double.
+ */
+public final class DataBufferDouble extends DataBuffer {
+
+ /** The data. */
+ double data[][];
+
+ /**
+ * Instantiates a new data buffer of type double.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferDouble(double dataArrays[][], int size, int offsets[]) {
+ super(TYPE_DOUBLE, size, dataArrays.length, offsets);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type double.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferDouble(double dataArrays[][], int size) {
+ super(TYPE_DOUBLE, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type double
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+ */
+ public DataBufferDouble(double dataArray[], int size, int offset) {
+ super(TYPE_DOUBLE, size, 1, offset);
+ data = new double[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type double
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferDouble(double dataArray[], int size) {
+ super(TYPE_DOUBLE, size);
+ data = new double[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type double
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferDouble(int size, int numBanks) {
+ super(TYPE_DOUBLE, size, numBanks);
+ data = new double[numBanks][];
+ int i = 0;
+ while (i < numBanks) {
+ data[i++] = new double[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type double
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferDouble(int size) {
+ super(TYPE_DOUBLE, size);
+ data = new double[1][];
+ data[0] = new double[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemFloat(int bank, int i, float val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemDouble(int bank, int i, double val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (int) (data[bank][offsets[bank] + i]);
+ }
+
+ @Override
+ public float getElemFloat(int bank, int i) {
+ return (float) (data[bank][offsets[bank] + i]);
+ }
+
+ @Override
+ public double getElemDouble(int bank, int i) {
+ return data[bank][offsets[bank] + i];
+ }
+
+ @Override
+ public void setElemFloat(int i, float val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemDouble(int i, double val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired data array
+ *
+ * @return the data
+ */
+ public double[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return (int) (data[0][offset + i]);
+ }
+
+ @Override
+ public float getElemFloat(int i) {
+ return (float) (data[0][offset + i]);
+ }
+
+ @Override
+ public double getElemDouble(int i) {
+ return data[0][offset + i];
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public double[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public double[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+}
+
diff --git a/awt/java/awt/image/DataBufferFloat.java b/awt/java/awt/image/DataBufferFloat.java
new file mode 100644
index 0000000..e34245c
--- /dev/null
+++ b/awt/java/awt/image/DataBufferFloat.java
@@ -0,0 +1,214 @@
+/*
+ * 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;
+
+/**
+ * The Class DataBufferFloat is the subclass of DataBuffer
+ * for the case where the underlying data is float.
+ */
+public final class DataBufferFloat extends DataBuffer {
+
+ /** The data. */
+ float data[][];
+
+ /**
+ * Instantiates a new data buffer of type float.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferFloat(float dataArrays[][], int size, int offsets[]) {
+ super(TYPE_FLOAT, size, dataArrays.length, offsets);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type float.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferFloat(float dataArrays[][], int size) {
+ super(TYPE_FLOAT, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type float
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+ */
+ public DataBufferFloat(float dataArray[], int size, int offset) {
+ super(TYPE_FLOAT, size, 1, offset);
+ data = new float[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type float
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferFloat(float dataArray[], int size) {
+ super(TYPE_FLOAT, size);
+ data = new float[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type float
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferFloat(int size, int numBanks) {
+ super(TYPE_FLOAT, size, numBanks);
+ data = new float[numBanks][];
+ int i = 0;
+ while (i < numBanks) {
+ data[i++] = new float[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type float
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferFloat(int size) {
+ super(TYPE_FLOAT, size);
+ data = new float[1][];
+ data[0] = new float[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemFloat(int bank, int i, float val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemDouble(int bank, int i, double val) {
+ data[bank][offsets[bank] + i] = (float) val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (int) (data[bank][offsets[bank] + i]);
+ }
+
+ @Override
+ public float getElemFloat(int bank, int i) {
+ return data[bank][offsets[bank] + i];
+ }
+
+ @Override
+ public double getElemDouble(int bank, int i) {
+ return data[bank][offsets[bank] + i];
+ }
+
+ @Override
+ public void setElemFloat(int i, float val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElemDouble(int i, double val) {
+ data[0][offset + i] = (float) val;
+ notifyChanged();
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired array
+ *
+ * @return the data
+ */
+ public float[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return (int) (data[0][offset + i]);
+ }
+
+ @Override
+ public float getElemFloat(int i) {
+ return data[0][offset + i];
+ }
+
+ @Override
+ public double getElemDouble(int i) {
+ return data[0][offset + i];
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public float[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public float[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+}
+
diff --git a/awt/java/awt/image/DataBufferInt.java b/awt/java/awt/image/DataBufferInt.java
new file mode 100644
index 0000000..43dc188
--- /dev/null
+++ b/awt/java/awt/image/DataBufferInt.java
@@ -0,0 +1,170 @@
+/*
+ * 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;
+
+/**
+ * The Class DataBufferInt is the subclass of DataBuffer
+ * for the case where the underlying data is of type int.
+ */
+public final class DataBufferInt extends DataBuffer {
+
+ /** The data. */
+ int data[][];
+
+ /**
+ * Instantiates a new data buffer of type int.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferInt(int dataArrays[][], int size, int offsets[]) {
+ super(TYPE_INT, size, dataArrays.length, offsets);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type int.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferInt(int dataArrays[][], int size) {
+ super(TYPE_INT, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type int
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+ */
+ public DataBufferInt(int dataArray[], int size, int offset) {
+ super(TYPE_INT, size, 1, offset);
+ data = new int[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type int
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferInt(int dataArray[], int size) {
+ super(TYPE_INT, size);
+ data = new int[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type int
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferInt(int size, int numBanks) {
+ super(TYPE_INT, size, numBanks);
+ data = new int[numBanks][];
+ int i = 0;
+ while (i < numBanks) {
+ data[i++] = new int[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type int
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferInt(int size) {
+ super(TYPE_INT, size);
+ data = new int[1][];
+ data[0] = new int[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return data[bank][offsets[bank] + i];
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired data array
+ *
+ * @return the data
+ */
+ public int[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return data[0][offset + i];
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public int[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public int[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+}
+
diff --git a/awt/java/awt/image/DataBufferShort.java b/awt/java/awt/image/DataBufferShort.java
new file mode 100644
index 0000000..819ba4a
--- /dev/null
+++ b/awt/java/awt/image/DataBufferShort.java
@@ -0,0 +1,172 @@
+/*
+ * 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;
+
+/**
+ * The Class DataBufferShort is the subclass of DataBuffer
+ * for the case where the underlying data is short.
+ */
+public final class DataBufferShort extends DataBuffer {
+
+ /** The data. */
+ short data[][];
+
+ /**
+ * Instantiates a new data buffer of type short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferShort(short dataArrays[][], int size, int offsets[]) {
+ super(TYPE_SHORT, size, dataArrays.length, offsets);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferShort(short dataArrays[][], int size) {
+ super(TYPE_SHORT, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type short
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+
+ */
+ public DataBufferShort(short dataArray[], int size, int offset) {
+ super(TYPE_SHORT, size, 1, offset);
+ data = new short[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+
+ */
+ public DataBufferShort(short dataArray[], int size) {
+ super(TYPE_SHORT, size);
+ data = new short[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type short
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferShort(int size, int numBanks) {
+ super(TYPE_SHORT, size, numBanks);
+ data = new short[numBanks][];
+ int i = 0;
+ while (i < numBanks) {
+ data[i++] = new short[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferShort(int size) {
+ super(TYPE_SHORT, size);
+ data = new short[1][];
+ data[0] = new short[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = (short) val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = (short) val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (data[bank][offsets[bank] + i]);
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired data array
+ *
+ * @return the data
+ */
+ public short[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return (data[0][offset + i]);
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public short[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public short[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+}
+
diff --git a/awt/java/awt/image/DataBufferUShort.java b/awt/java/awt/image/DataBufferUShort.java
new file mode 100644
index 0000000..7982678
--- /dev/null
+++ b/awt/java/awt/image/DataBufferUShort.java
@@ -0,0 +1,182 @@
+/*
+ * 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 org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DataBufferUShort is the subclass of DataBuffer
+ * for the case where the underlying data is unsigned short.
+ */
+public final class DataBufferUShort extends DataBuffer {
+
+ /** The data. */
+ short data[][];
+
+ /**
+ * Instantiates a new data buffer of type unsigned short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param offsets the starting indices for reading the
+ * data from the internal data arrays
+ */
+ public DataBufferUShort(short dataArrays[][], int size, int offsets[]) {
+ super(TYPE_USHORT, size, dataArrays.length, offsets);
+ for(int i = 0; i < dataArrays.length; i++){
+ if(dataArrays[i].length < offsets[i] + size){
+ // awt.28d=Length of dataArray[{0}] is less than size + offset[{1}]
+ throw new IllegalArgumentException(Messages.getString("awt.28D", i, i)); //$NON-NLS-1$
+ }
+ }
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short.
+ *
+ * @param dataArrays the data arrays to copy the data from
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ */
+ public DataBufferUShort(short dataArrays[][], int size) {
+ super(TYPE_USHORT, size, dataArrays.length);
+ data = dataArrays.clone();
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short
+ * with a single underlying array of data.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ * @param offset the starting index to use when reading the data
+ */
+ public DataBufferUShort(short dataArray[], int size, int offset) {
+ super(TYPE_USHORT, size, 1, offset);
+ if(dataArray.length < size + offset){
+ // awt.28E=Length of dataArray is less than size + offset
+ throw new IllegalArgumentException(Messages.getString("awt.28E")); //$NON-NLS-1$
+ }
+ data = new short[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new data buffer of type unsigned short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param dataArray the data array to copy the data from
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferUShort(short dataArray[], int size) {
+ super(TYPE_USHORT, size);
+ data = new short[1][];
+ data[0] = dataArray;
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type unsigned short
+ * with offsets equal to zero.
+ *
+ * @param size the length (number of elements) to use
+ * from the data arrays
+ * @param numBanks the number of data arrays to create
+ */
+ public DataBufferUShort(int size, int numBanks) {
+ super(TYPE_USHORT, size, numBanks);
+ data = new short[numBanks][];
+ int i= 0;
+ while( i < numBanks) {
+ data[i++] = new short[size];
+ }
+ }
+
+ /**
+ * Instantiates a new empty data buffer of type unsigned short
+ * with a single underlying array of data starting at
+ * index 0.
+ *
+ * @param size the length (number of elements) to use
+ */
+ public DataBufferUShort(int size) {
+ super(TYPE_USHORT, size);
+ data = new short[1][];
+ data[0] = new short[size];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ data[bank][offsets[bank] + i] = (short)val;
+ notifyChanged();
+ }
+
+ @Override
+ public void setElem(int i, int val) {
+ data[0][offset + i] = (short)val;
+ notifyChanged();
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (data[bank][offsets[bank] + i]) & 0xffff;
+ }
+
+ /**
+ * Gets the data of the specified internal data array.
+ *
+ * @param bank the index of the desired data array
+ *
+ * @return the data
+ */
+ public short[] getData(int bank) {
+ notifyTaken();
+ return data[bank];
+ }
+
+ @Override
+ public int getElem(int i) {
+ return (data[0][offset + i]) & 0xffff;
+ }
+
+ /**
+ * Gets the bank data.
+ *
+ * @return the bank data
+ */
+ public short[][] getBankData() {
+ notifyTaken();
+ return data.clone();
+ }
+
+ /**
+ * Gets the data of the first data array.
+ *
+ * @return the data
+ */
+ public short[] getData() {
+ notifyTaken();
+ return data[0];
+ }
+}
+
diff --git a/awt/java/awt/image/DirectColorModel.java b/awt/java/awt/image/DirectColorModel.java
new file mode 100644
index 0000000..7a287c0
--- /dev/null
+++ b/awt/java/awt/image/DirectColorModel.java
@@ -0,0 +1,862 @@
+/*
+ * 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 java.awt.Transparency;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.color.LUTColorConverter;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DirectColorModel represents a standard (packed) RGB
+ * color model with additional support for converting between sRGB
+ * color space and 8 or 16 bit linear RGB color space using lookup tables.
+ */
+public class DirectColorModel extends PackedColorModel {
+
+ /** 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 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 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
+
+ /** The LINEA r_ rg b_ length. */
+ private int LINEAR_RGB_Length; // Linear RGB bit length
+
+ /** The factor. */
+ private float fFactor; // Scale factor
+
+ /**
+ * Instantiates a new direct color model.
+ *
+ * @param space the color space
+ * @param bits the array of component masks
+ * @param rmask the bitmask corresponding to the red band
+ * @param gmask the bitmask corresponding to the green band
+ * @param bmask the bitmask corresponding to the blue band
+ * @param amask the bitmask corresponding to the alpha band
+ * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ *
+ * @throws IllegalArgumentException if the number of bits in the combined
+ * bitmasks for the color bands is less than one or greater than 32
+ */
+ public DirectColorModel(ColorSpace space, int bits, int rmask, int gmask,
+ int bmask, int amask, boolean isAlphaPremultiplied,
+ int transferType) {
+
+ super(space, bits, rmask, gmask, bmask, amask, isAlphaPremultiplied,
+ (amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+ transferType);
+
+ initLUTs();
+ }
+
+ /**
+ * Instantiates a new direct color model, determining the transfer
+ * type from the bits array, the transparency from the alpha mask,
+ * and the default color space {@link ColorSpace#CS_sRGB}.
+ *
+ * @param bits the array of component masks
+ * @param rmask the bitmask corresponding to the red band
+ * @param gmask the bitmask corresponding to the green band
+ * @param bmask the bitmask corresponding to the blue band
+ * @param amask the bitmask corresponding to the alpha band
+ */
+ public DirectColorModel(int bits, int rmask, int gmask, int bmask,
+ int amask) {
+
+ super(ColorSpace.getInstance(ColorSpace.CS_sRGB), bits, rmask, gmask,
+ bmask, amask, false,
+ (amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+ ColorModel.getTransferType(bits));
+
+ initLUTs();
+ }
+
+ /**
+ * Instantiates a new direct color model with no alpha channel,
+ * determining the transfer type from the bits array,
+ * the default color space {@link ColorSpace#CS_sRGB},
+ * and with the transparency set to {@link Transparency#OPAQUE}.
+ *
+ * @param bits the array of component masks
+ * @param rmask the bitmask corresponding to the red band
+ * @param gmask the bitmask corresponding to the green band
+ * @param bmask the bitmask corresponding to the blue band
+ */
+ public DirectColorModel(int bits, int rmask, int gmask, int bmask) {
+ this(bits, rmask, gmask, bmask, 0);
+ }
+
+ @Override
+ public Object getDataElements(int components[], int offset, Object obj) {
+ int pixel = 0;
+ for (int i = 0; i < numComponents; i++) {
+ pixel |= (components[offset + i] << offsets[i]) & componentMasks[i];
+ }
+
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[];
+ if (obj == null) {
+ ba = new byte[1];
+ } else {
+ ba = (byte[]) obj;
+ }
+ ba[0] = (byte) pixel;
+ obj = ba;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[];
+ if (obj == null) {
+ sa = new short[1];
+ } else {
+ sa = (short[]) obj;
+ }
+ sa[0] = (short) pixel;
+ obj = sa;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[];
+ if (obj == null) {
+ ia = new int[1];
+ } else {
+ ia = (int[]) obj;
+ }
+ ia[0] = pixel;
+ obj = ia;
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+
+ return obj;
+ }
+
+ @Override
+ public Object getDataElements(int rgb, Object pixel) {
+ if (equals(ColorModel.getRGBdefault())) {
+ int ia[];
+ if (pixel == null) {
+ ia = new int[1];
+ } else {
+ ia = (int[]) pixel;
+ }
+ ia[0] = rgb;
+ return ia;
+ }
+
+ int alpha = (rgb >> 24) & 0xff;
+ int red = (rgb >> 16) & 0xff;
+ int green = (rgb >> 8) & 0xff;
+ int blue = rgb & 0xff;
+
+ float comp[] = new float[numColorComponents];
+ float normComp[] = null;
+
+ 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 rgbComp[] = cs.fromRGB(comp);
+ if (!hasAlpha) {
+ normComp = rgbComp;
+ } else {
+ float normAlpha = alpha / 255.0f;
+ normComp = new float[numComponents];
+ for (int i = 0; i < numColorComponents; i++) {
+ normComp[i] = rgbComp[i];
+ }
+ normComp[numColorComponents] = normAlpha;
+ }
+ }
+
+ int pxl = 0;
+ if (hasAlpha) {
+ float normAlpha = normComp[numColorComponents];
+ alpha = (int) (normAlpha * maxValues[numColorComponents] + 0.5f);
+ if (isAlphaPremultiplied) {
+ red = (int) (normComp[0] * normAlpha * maxValues[0] + 0.5f);
+ green = (int) (normComp[1] * normAlpha * maxValues[1] + 0.5f);
+ blue = (int) (normComp[2] * normAlpha * maxValues[2] + 0.5f);
+ } else {
+ red = (int) (normComp[0] * maxValues[0] + 0.5f);
+ green = (int) (normComp[1] * maxValues[1] + 0.5f);
+ blue = (int) (normComp[2] * maxValues[2] + 0.5f);
+ }
+ pxl = (alpha << offsets[3]) & componentMasks[3];
+ } else {
+ red = (int) (normComp[0] * maxValues[0] + 0.5f);
+ green = (int) (normComp[1] * maxValues[1] + 0.5f);
+ blue = (int) (normComp[2] * maxValues[2] + 0.5f);
+ }
+
+ pxl |= ((red << offsets[0]) & componentMasks[0]) |
+ ((green << offsets[1]) & componentMasks[1]) |
+ ((blue << offsets[2]) & componentMasks[2]);
+
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[];
+ if (pixel == null) {
+ ba = new byte[1];
+ } else {
+ ba = (byte[]) pixel;
+ }
+ ba[0] = (byte) pxl;
+ return ba;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[];
+ if (pixel == null) {
+ sa = new short[1];
+ } else {
+ sa = (short[]) pixel;
+ }
+ sa[0] = (short) pxl;
+ return sa;
+
+ case DataBuffer.TYPE_INT:
+ int ia[];
+ if (pixel == null) {
+ ia = new int[1];
+ } else {
+ ia = (int[]) pixel;
+ }
+ ia[0] = pxl;
+ return ia;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public final 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();
+
+ int components[] = null;
+ int transparentComponents[] = new int[numComponents];
+
+ float alphaFactor = maxValues[numColorComponents];
+
+ if (isAlphaPremultiplied) {
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ for (int i = 0; i < h; i++, minY++) {
+ for (int j = 0, x = minX; j < w; j++, x++) {
+ components = raster.getPixel(x, minY, components);
+ if (components[numColorComponents] == 0) {
+ raster.setPixel(x, minY, transparentComponents);
+ } else {
+ float alpha =
+ components[numColorComponents] /
+ alphaFactor;
+ for (int n = 0; n < numColorComponents; n++) {
+ components[n] =
+ (int) (alpha * components[n] + 0.5f);
+ }
+ raster.setPixel(x, minY, components);
+ }
+ }
+
+ }
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ } else {
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ for (int i = 0; i < h; i++, minY++) {
+ for (int j = 0, x = minX; j < w; j++, x++) {
+ components = raster.getPixel(x, minY, components);
+ if (components[numColorComponents] != 0) {
+ float alpha =
+ alphaFactor / components[numColorComponents];
+ for (int n = 0; n < numColorComponents; n++) {
+ components[n] =
+ (int) (alpha * components[n] + 0.5f);
+ }
+ raster.setPixel(x, minY, components);
+ }
+ }
+
+ }
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+
+ }
+
+ return new DirectColorModel(cs, pixel_bits, componentMasks[0],
+ componentMasks[1], componentMasks[2], componentMasks[3],
+ isAlphaPremultiplied, transferType);
+ }
+
+ @Override
+ public String toString() {
+ // The output format based on 1.5 release behaviour.
+ // It could be reveled such way:
+ // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ // ColorModel cm = bi.getColorModel();
+ // System.out.println(cm.toString());
+ String str = "DirectColorModel:" + " rmask = " + //$NON-NLS-1$ //$NON-NLS-2$
+ Integer.toHexString(componentMasks[0]) + " gmask = " + //$NON-NLS-1$
+ Integer.toHexString(componentMasks[1]) + " bmask = " + //$NON-NLS-1$
+ Integer.toHexString(componentMasks[2]) + " amask = " + //$NON-NLS-1$
+ (!hasAlpha ? "0" : Integer.toHexString(componentMasks[3])); //$NON-NLS-1$
+
+ return str;
+ }
+
+ @Override
+ public final int[] getComponents(Object pixel, int components[],
+ int offset) {
+
+ if (components == null) {
+ components = new int[numComponents + offset];
+ }
+
+ int intPixel = 0;
+
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) pixel;
+ intPixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) pixel;
+ intPixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) pixel;
+ intPixel = ia[0];
+ break;
+
+ default:
+ // awt.22D=This transferType ( {0} ) is not supported by this color model
+ throw new UnsupportedOperationException(Messages.getString("awt.22D", //$NON-NLS-1$
+ transferType));
+ }
+
+ return getComponents(intPixel, components, offset);
+ }
+
+ @Override
+ public int getRed(Object inData) {
+ int pixel = 0;
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) inData;
+ pixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) inData;
+ pixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) inData;
+ pixel = ia[0];
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ return getRed(pixel);
+ }
+
+ @Override
+ public int getRGB(Object inData) {
+ int pixel = 0;
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) inData;
+ pixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) inData;
+ pixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) inData;
+ pixel = ia[0];
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ return getRGB(pixel);
+ }
+
+ @Override
+ public int getGreen(Object inData) {
+ int pixel = 0;
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) inData;
+ pixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) inData;
+ pixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) inData;
+ pixel = ia[0];
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ return getGreen(pixel);
+ }
+
+ @Override
+ public int getBlue(Object inData) {
+ int pixel = 0;
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) inData;
+ pixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) inData;
+ pixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) inData;
+ pixel = ia[0];
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ return getBlue(pixel);
+ }
+
+ @Override
+ public int getAlpha(Object inData) {
+ int pixel = 0;
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) inData;
+ pixel = ba[0] & 0xff;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) inData;
+ pixel = sa[0] & 0xffff;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ia[] = (int[]) inData;
+ pixel = ia[0];
+ break;
+
+ default:
+ // awt.214=This Color Model doesn't support this transferType
+ throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+ }
+ return getAlpha(pixel);
+ }
+
+ @Override
+ public final WritableRaster createCompatibleWritableRaster(int w, int h) {
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new IllegalArgumentException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ int bandMasks[] = componentMasks.clone();
+
+ if (pixel_bits > 16) {
+ return Raster.createPackedRaster(DataBuffer.TYPE_INT, w, h,
+ bandMasks, null);
+ } else if (pixel_bits > 8) {
+ return Raster.createPackedRaster(DataBuffer.TYPE_USHORT, w, h,
+ bandMasks, null);
+ } else {
+ return Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h,
+ bandMasks, null);
+ }
+ }
+
+ @Override
+ public boolean isCompatibleRaster(Raster raster) {
+ SampleModel sm = raster.getSampleModel();
+ if (!(sm instanceof SinglePixelPackedSampleModel)) {
+ return false;
+ }
+
+ SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
+
+ if (sppsm.getNumBands() != numComponents) {
+ return false;
+ }
+ if (raster.getTransferType() != transferType) {
+ return false;
+ }
+
+ int maskBands[] = sppsm.getBitMasks();
+ return Arrays.equals(maskBands, componentMasks);
+ }
+
+ @Override
+ public int getDataElement(int components[], int offset) {
+ int pixel = 0;
+ for (int i = 0; i < numComponents; i++) {
+ pixel |= (components[offset + i] << offsets[i]) & componentMasks[i];
+ }
+ return pixel;
+ }
+
+ @Override
+ public final int[] getComponents(int pixel, int components[], int offset) {
+ if (components == null) {
+ components = new int[numComponents + offset];
+ }
+ for (int i = 0; i < numComponents; i++) {
+ components[offset + i] = (pixel & componentMasks[i]) >> offsets[i];
+ }
+ return components;
+ }
+
+ @Override
+ public final int getRed(int pixel) {
+ if (is_sRGB) {
+ return getComponentFrom_sRGB(pixel, 0);
+ }
+ if (is_LINEAR_RGB) {
+ return getComponentFrom_LINEAR_RGB(pixel, 0);
+ }
+ return getComponentFrom_RGB(pixel, 0);
+ }
+
+ @Override
+ public final int getRGB(int pixel) {
+ return (getAlpha(pixel) << 24) | (getRed(pixel) << 16) |
+ (getGreen(pixel) << 8) | getBlue(pixel);
+ }
+
+ @Override
+ public final int getGreen(int pixel) {
+ if (is_sRGB) {
+ return getComponentFrom_sRGB(pixel, 1);
+ }
+ if (is_LINEAR_RGB) {
+ return getComponentFrom_LINEAR_RGB(pixel, 1);
+ }
+ return getComponentFrom_RGB(pixel, 1);
+ }
+
+ @Override
+ public final int getBlue(int pixel) {
+ if (is_sRGB) {
+ return getComponentFrom_sRGB(pixel, 2);
+ }
+ if (is_LINEAR_RGB) {
+ return getComponentFrom_LINEAR_RGB(pixel, 2);
+ }
+ return getComponentFrom_RGB(pixel, 2);
+ }
+
+ @Override
+ public final int getAlpha(int pixel) {
+ if (!hasAlpha) {
+ return 255;
+ }
+ int a = (pixel & componentMasks[3]) >>> offsets[3];
+ if (bits[3] == 8) {
+ return a;
+ }
+ return alphaLUT[a] & 0xff;
+ }
+
+ /**
+ * Gets the red mask.
+ *
+ * @return the red mask
+ */
+ public final int getRedMask() {
+ return componentMasks[0];
+ }
+
+ /**
+ * Gets the green mask.
+ *
+ * @return the green mask
+ */
+ public final int getGreenMask() {
+ return componentMasks[1];
+ }
+
+ /**
+ * Gets the blue mask.
+ *
+ * @return the blue mask
+ */
+ public final int getBlueMask() {
+ return componentMasks[2];
+ }
+
+ /**
+ * Gets the alpha mask.
+ *
+ * @return the alpha mask
+ */
+ public final int getAlphaMask() {
+ if (hasAlpha) {
+ return componentMasks[3];
+ }
+ return 0;
+ }
+
+ /**
+ * Initialization of Lookup tables.
+ */
+ private void initLUTs() {
+ is_sRGB = cs.isCS_sRGB();
+ is_LINEAR_RGB = (cs == LUTColorConverter.LINEAR_RGB_CS);
+
+ 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 (hasAlpha && bits[3] != 8) {
+ alphaLUT = new byte[maxValues[3] + 1];
+ for (int i = 0; i <= maxValues[3]; i++) {
+ alphaLUT[i] = (byte) (scales[3] * i + 0.5f);
+ }
+
+ }
+
+ if (!isAlphaPremultiplied) {
+ 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[i]; j++) {
+ colorLUTs[i][j] = (byte) (scales[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) (scales[i] * j + 0.5f);
+ } else {
+ idx = (int) (scales[i] * j * 257.0f + 0.5f);
+ }
+ colorLUTs[i][j] = from_LINEAR_RGB_LUT[idx];
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ /**
+ * This method return RGB component value if Color Model has
+ * sRGB ColorSpace.
+ *
+ * @param pixel - INT representation of pixel
+ * @param idx - index of pixel component
+ *
+ * @return - value of the pixel component scaled fro 0 to 255
+ */
+ private int getComponentFrom_sRGB(int pixel, int idx) {
+ int comp = (pixel & componentMasks[idx]) >> offsets[idx];
+ if (isAlphaPremultiplied) {
+ int alpha = (pixel & componentMasks[3]) >>> offsets[3];
+ comp = alpha == 0 ? 0 : (int) (scales[idx] * comp * 255.0f /
+ (scales[3] * alpha) + 0.5f);
+ } else if (bits[idx] != 8) {
+ comp = colorLUTs[idx][comp] & 0xff;
+ }
+ return comp;
+ }
+
+ /**
+ * This method return RGB component value if Color Model has
+ * Linear RGB ColorSpace.
+ *
+ * @param pixel - INT representation of pixel
+ * @param idx - index of pixel component
+ *
+ * @return - value of the pixel component scaled fro 0 to 255
+ */
+ private int getComponentFrom_LINEAR_RGB(int pixel, int idx) {
+ int comp = (pixel & componentMasks[idx]) >> offsets[idx];
+ if (isAlphaPremultiplied) {
+ float factor = ((1 << LINEAR_RGB_Length) - 1);
+ int alpha = (pixel & componentMasks[3]) >> offsets[3];
+ comp = alpha == 0 ? 0 : (int) (scales[idx] * comp * factor /
+ (scales[3] * alpha) + 0.5f);
+ } else if (bits[idx] != LINEAR_RGB_Length) {
+ comp = colorLUTs[idx][comp] & 0xff;
+ } else {
+ comp = from_LINEAR_RGB_LUT[comp] & 0xff;
+ }
+ return comp;
+ }
+
+ /**
+ * This method return RGB component value if Color Model has
+ * arbitrary RGB ColorSapce.
+ *
+ * @param pixel - INT representation of pixel
+ * @param idx - index of pixel component
+ *
+ * @return - value of the pixel component scaled fro 0 to 255
+ */
+ private int getComponentFrom_RGB(int pixel, int idx) {
+ int components[] = getComponents(pixel, null, 0);
+ float[] normComponents = getNormalizedComponents(components, 0, null, 0);
+ float[] sRGBcomponents = cs.toRGB(normComponents);
+ return (int) (sRGBcomponents[idx] * 255.0f + 0.5f);
+ }
+
+}
+
diff --git a/awt/java/awt/image/FilteredImageSource.java b/awt/java/awt/image/FilteredImageSource.java
new file mode 100644
index 0000000..6a41fa7
--- /dev/null
+++ b/awt/java/awt/image/FilteredImageSource.java
@@ -0,0 +1,88 @@
+/*
+ * 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.util.Hashtable;
+
+
+/**
+ * The FilteredImageSource class is used for producing image data for a new
+ * filtered version of the original image using the specified filter object.
+ */
+public class FilteredImageSource implements ImageProducer {
+
+ /** The source. */
+ private final ImageProducer source;
+
+ /** The filter. */
+ private final ImageFilter filter;
+
+ /** The cons table. */
+ private final Hashtable<ImageConsumer, ImageConsumer> consTable = new Hashtable<ImageConsumer, ImageConsumer>();
+
+ /**
+ * Instantiates a new FilteredImageSource object with
+ * the specified ImageProducer and the ImageFilter objects.
+ *
+ * @param orig the specified ImageProducer.
+ * @param imgf the specified ImageFilter.
+ */
+ public FilteredImageSource(ImageProducer orig, ImageFilter imgf) {
+ source = orig;
+ filter = imgf;
+ }
+
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ if(ic != null) {
+ return consTable.containsKey(ic);
+ }
+ return false;
+ }
+
+ public void startProduction(ImageConsumer ic) {
+ addConsumer(ic);
+ ImageConsumer fic = consTable.get(ic);
+ source.startProduction(fic);
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {
+ if(ic != null && isConsumer(ic)){
+ ImageFilter fic = (ImageFilter) consTable.get(ic);
+ fic.resendTopDownLeftRight(source);
+ }
+ }
+
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ if(ic != null && isConsumer(ic)){
+ ImageConsumer fic = consTable.get(ic);
+ source.removeConsumer(fic);
+ consTable.remove(ic);
+ }
+ }
+
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if(ic != null && !isConsumer(ic)){
+ ImageConsumer fic = filter.getFilterInstance(ic);
+ source.addConsumer(fic);
+ consTable.put(ic, fic);
+ }
+ }
+}
diff --git a/awt/java/awt/image/ImageConsumer.java b/awt/java/awt/image/ImageConsumer.java
new file mode 100644
index 0000000..2eba290
--- /dev/null
+++ b/awt/java/awt/image/ImageConsumer.java
@@ -0,0 +1,165 @@
+/*
+ * 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.util.Hashtable;
+
+/**
+ * The ImageConsumer interface provides the data about the image
+ * and about how its data is delivered. A ImageProducer provides
+ * all of the information about the image using
+ * the methods defined in this interface.
+ */
+public interface ImageConsumer {
+
+ /**
+ * The Constant RANDOMPIXELORDER indicates that the pixels are
+ * delivered in a random order.
+ */
+ public static final int RANDOMPIXELORDER = 1;
+
+ /**
+ * The Constant TOPDOWNLEFTRIGHT indicates that the pixels are
+ * delivered in top-down, left-to-right order.
+ */
+ public static final int TOPDOWNLEFTRIGHT = 2;
+
+ /**
+ * The Constant COMPLETESCANLINES indicates that the pixels are
+ * delivered in complete scanline.
+ */
+ public static final int COMPLETESCANLINES = 4;
+
+ /**
+ * The Constant SINGLEPASS indicates that pixels are delivered
+ * in a single pass.
+ */
+ public static final int SINGLEPASS = 8;
+
+ /**
+ * The Constant SINGLEFRAME indicates that image consists of
+ * single frame.
+ */
+ public static final int SINGLEFRAME = 16;
+
+ /**
+ * The Constant IMAGEERROR indicates an image error during image producing.
+ */
+ public static final int IMAGEERROR = 1;
+
+ /**
+ * The Constant SINGLEFRAMEDONE indicates that only one of the
+ * image's frames is completed.
+ */
+ public static final int SINGLEFRAMEDONE = 2;
+
+ /**
+ * The Constant STATICIMAGEDONE indicates that the image is completed.
+ */
+ public static final int STATICIMAGEDONE = 3;
+
+ /**
+ * The Constant IMAGEABORTED indicates that the image producing
+ * process is aborted.
+ */
+ public static final int IMAGEABORTED = 4;
+
+ /**
+ * Sets the properties for the image associated with this ImageConsumer.
+ *
+ * @param props the properties for the image associated with
+ * this ImageConsumer.
+ */
+ public void setProperties(Hashtable<?, ?> props);
+
+ /**
+ * Sets the ColorModel object.
+ *
+ * @param model the new ColorModel.
+ */
+ public void setColorModel(ColorModel model);
+
+ /**
+ * Sets the pixels for the specified rectangular area of the image.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ * @param model the specified ColorModel to be used for pixels
+ * converting.
+ * @param pixels the array of pixels.
+ * @param off the offset of pixels array.
+ * @param scansize the distance from the one row of pixels
+ * to the next row in the specified array.
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize);
+
+ /**
+ * Sets the pixels for the specified rectangular area of the image.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ * @param model the specified ColorModel to be used for pixels
+ * converting.
+ * @param pixels the array of pixels.
+ * @param off the offset of pixels array.
+ * @param scansize the distance from the one row of pixels
+ * to the next row in the specified array.
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize);
+
+ /**
+ * Sets the dimensions of a source image.
+ *
+ * @param width the width of the image.
+ * @param height the height of the image.
+ */
+ public void setDimensions(int width, int height);
+
+ /**
+ * Sets the hint flags of pixels order, which is used by
+ * the ImageConsumer for obtaining pixels from the ImageProducer
+ * for which this ImageConsumer is added.
+ *
+ * @param hintflags the mask of hint flags.
+ */
+ public void setHints(int hintflags);
+
+ /**
+ * THis method is called in the one of the following cases:
+ * <ul>
+ * <li>The ImageProducer (for which this ImageConsumer is added)
+ * has been delivered all pixels of the source image. </li>
+ * <li>A one frame of an animation has been completed. </li>
+ * <li> An error while loading or producing of the image has occured.
+ * </ul>
+ *
+ * @param status the status of image producing.
+ */
+ public void imageComplete(int status);
+
+}
+
diff --git a/awt/java/awt/image/ImageFilter.java b/awt/java/awt/image/ImageFilter.java
new file mode 100644
index 0000000..e386d65
--- /dev/null
+++ b/awt/java/awt/image/ImageFilter.java
@@ -0,0 +1,129 @@
+/*
+ * 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.util.Hashtable;
+
+/**
+ * The ImageFilter class provides a filter for delivering image data
+ * from an ImageProducer to an ImageConsumer.
+ */
+public class ImageFilter implements ImageConsumer, Cloneable {
+
+ /** The consumer. */
+ protected ImageConsumer consumer;
+
+ /**
+ * Instantiates a new ImageFilter.
+ */
+ public ImageFilter() {
+ super();
+ }
+
+ /**
+ * Gets an instance of an ImageFilter object which performs
+ * the filtering for the specified ImageConsumer.
+ *
+ * @param ic the specified ImageConsumer.
+ *
+ * @return an ImageFilter used to perform the filtering for
+ * the specified ImageConsumer.
+ */
+ public ImageFilter getFilterInstance(ImageConsumer ic) {
+ ImageFilter filter = (ImageFilter) clone();
+ filter.consumer = ic;
+ return filter;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setProperties(Hashtable<?, ?> props) {
+ Hashtable<Object, Object> fprops;
+ if (props == null) {
+ fprops = new Hashtable<Object, Object>();
+ } else {
+ fprops = (Hashtable<Object, Object>) props.clone();
+ }
+ String propName = "Filters"; //$NON-NLS-1$
+ String prop = "Null filter"; //$NON-NLS-1$
+ Object o = fprops.get(propName);
+ if (o != null) {
+ if (o instanceof String) {
+ prop = (String) o + "; " + prop; //$NON-NLS-1$
+ } else {
+ prop = o.toString() + "; " + prop; //$NON-NLS-1$
+ }
+ }
+ fprops.put(propName, prop);
+ consumer.setProperties(fprops);
+ }
+
+ /**
+ * Returns a copy of this ImageFilter.
+ *
+ * @return a copy of this ImageFilter.
+ */
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Responds to a request for a Top-Down-Left-Right ordered
+ * resend of the pixel data from an ImageConsumer.
+ *
+ * @param ip the ImageProducer that provides this instance of
+ * the filter.
+ */
+ public void resendTopDownLeftRight(ImageProducer ip) {
+ ip.requestTopDownLeftRightResend(this);
+ }
+
+ public void setColorModel(ColorModel model) {
+ consumer.setColorModel(model);
+ }
+
+ public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off,
+ int scansize) {
+ consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
+ }
+
+ public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off,
+ int scansize) {
+ consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
+ }
+
+ public void setDimensions(int width, int height) {
+ consumer.setDimensions(width, height);
+ }
+
+ public void setHints(int hints) {
+ consumer.setHints(hints);
+ }
+
+ public void imageComplete(int status) {
+ consumer.imageComplete(status);
+ }
+
+}
diff --git a/awt/java/awt/image/ImageObserver.java b/awt/java/awt/image/ImageObserver.java
new file mode 100644
index 0000000..418bd07
--- /dev/null
+++ b/awt/java/awt/image/ImageObserver.java
@@ -0,0 +1,99 @@
+/*
+ * 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.Image;
+
+/**
+ * the ImageObserver interface is an asynchronous update interface
+ * for receiving notifications about Image construction status.
+ */
+public interface ImageObserver {
+
+ /**
+ * The Constant WIDTH indicates that the width of the image is
+ * available.
+ */
+ public static final int WIDTH = 1;
+
+ /**
+ * The Constant HEIGHT indicates that the width of the image is
+ * available.
+ */
+ public static final int HEIGHT = 2;
+
+ /**
+ * The Constant PROPERTIES indicates that the properties of the image
+ * are available.
+ */
+ public static final int PROPERTIES = 4;
+
+ /**
+ * The Constant SOMEBITS indicates that more bits needed for
+ * drawing a scaled variation of the image pixels are available.
+ */
+ public static final int SOMEBITS = 8;
+
+ /**
+ * The Constant FRAMEBITS indicates that complete frame of
+ * a image which was previously drawn is now available
+ * for drawing again.
+ */
+ public static final int FRAMEBITS = 16;
+
+ /**
+ * The Constant ALLBITS indicates that an image which
+ * was previously drawn is now complete and can be drawn again.
+ */
+ public static final int ALLBITS = 32;
+
+ /**
+ * The Constant ERROR indicates that error occured.
+ */
+ public static final int ERROR = 64;
+
+ /**
+ * The Constant ABORT indicates that the image producing is
+ * aborted.
+ */
+ public static final int ABORT = 128;
+
+ /**
+ * This method is called when information about an Image
+ * interface becomes available. This method returns true
+ * if further updates are needed, false if not.
+ *
+ * @param img the image to be observed.
+ * @param infoflags the bitwise OR combination of information flags:
+ * ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS,
+ * WIDTH.
+ * @param x the X coordinate.
+ * @param y the Y coordinate.
+ * @param width the width.
+ * @param height the height.
+ *
+ * @return true if further updates are needed, false if not.
+ */
+ public boolean imageUpdate(Image img, int infoflags, int x, int y,
+ int width, int height);
+
+}
+
diff --git a/awt/java/awt/image/ImageProducer.java b/awt/java/awt/image/ImageProducer.java
new file mode 100644
index 0000000..557ae08
--- /dev/null
+++ b/awt/java/awt/image/ImageProducer.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+
+/**
+ * The ImageProducer provides an interface for objects which produce
+ * the image data. ImageProducer is used for reconstructing the
+ * image. Each image contains an ImageProducer.
+ */
+public interface ImageProducer {
+
+ /**
+ * Checks if the specified ImageConsumer is registered with this
+ * ImageProvider or not.
+ *
+ * @param ic the ImageConsumer to be checked.
+ *
+ * @return true, if the specified ImageConsumer is registered with this
+ * ImageProvider, false otherwise.
+ */
+ public boolean isConsumer(ImageConsumer ic);
+
+ /**
+ * Starts a reconstruction of the image data which will
+ * be delivered to this consumer. This method addes the
+ * specified ImageConsumer before reconstructing the image.
+ *
+ * @param ic the specified ImageConsumer.
+ */
+ public void startProduction(ImageConsumer ic);
+
+ /**
+ * Requests the ImageProducer to resend the image data
+ * in ImageConsumer.TOPDOWNLEFTRIGHT order.
+ *
+ * @param ic the specified ImageConsumer.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic);
+
+ /**
+ * Deregisters the specified ImageConsumer.
+ *
+ * @param ic the specified ImageConsumer.
+ */
+ public void removeConsumer(ImageConsumer ic);
+
+ /**
+ * Adds the specified ImageConsumer object to this ImageProducer.
+ *
+ * @param ic the specified ImageConsumer.
+ */
+ public void addConsumer(ImageConsumer ic);
+
+}
+
diff --git a/awt/java/awt/image/ImagingOpException.java b/awt/java/awt/image/ImagingOpException.java
new file mode 100644
index 0000000..ebcaba4
--- /dev/null
+++ b/awt/java/awt/image/ImagingOpException.java
@@ -0,0 +1,44 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 5, 2005
+ */
+
+package java.awt.image;
+
+/**
+ * The ImagingOpException class provides error notification when
+ * the BufferedImageOp or RasterOp filter methods can not perform
+ * the desired filter operation.
+ */
+public class ImagingOpException extends RuntimeException {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 8026288481846276658L;
+
+ /**
+ * Instantiates a new ImagingOpException with a detail message.
+ *
+ * @param s the detail message.
+ */
+ public ImagingOpException(String s) {
+ super(s);
+ }
+}
diff --git a/awt/java/awt/image/IndexColorModel.java b/awt/java/awt/image/IndexColorModel.java
new file mode 100644
index 0000000..a7043f4
--- /dev/null
+++ b/awt/java/awt/image/IndexColorModel.java
@@ -0,0 +1,1020 @@
+/*
+ * 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.Transparency;
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class IndexColorModel represents a color model in which the
+ * color values of the pixels are read from a palette.
+ */
+public class IndexColorModel extends ColorModel {
+
+ /** The color map. */
+ private int colorMap[]; // Color Map
+
+ /** The map size. */
+ private int mapSize; // Color Map size
+
+ /** The transparent index. */
+ private int transparentIndex; // Index of fully transparent pixel
+
+ /** The gray palette. */
+ private boolean grayPalette; // Color Model has Color Map with Gray Pallete
+
+ /** The valid bits. */
+ private BigInteger validBits; // Specify valid Color Map values
+
+ /** The Constant CACHESIZE. */
+ private static final int CACHESIZE = 20; // Cache size. Cache used for
+ // improving performace of selection
+ // nearest color in Color Map
+
+ /** The cachetable. */
+ private final int cachetable[] = new int[CACHESIZE * 2]; // Cache table - used for
+ // storing RGB values and that appropriate indices
+ // in the Color Map
+
+
+ /** The next insert idx. */
+ private int nextInsertIdx = 0; // Next index for insertion into Cache table
+
+ /** The total inserted. */
+ private int totalInserted = 0; // Number of inserted values into Cache table
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param cmap the array that gives the color mapping
+ * @param start the start index of the color mapping data within the cmap array
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ * @param validBits a list of which bits represent valid colormap
+ * values, or null if all are valid
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ */
+ public IndexColorModel(int bits, int size, int cmap[], int start,
+ int transferType, BigInteger validBits) {
+
+ super(bits, IndexColorModel.createBits(true),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false,
+ Transparency.OPAQUE, validateTransferType(transferType));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ transparentIndex = -1;
+
+ if (validBits != null) {
+ for (int i = 0; i < mapSize; i++) {
+ if (!validBits.testBit(i)) {
+ this.validBits = validBits;
+ }
+ break;
+ }
+ }
+
+ transparency = Transparency.OPAQUE;
+ int alphaMask = 0xff000000;
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++, start++) {
+ colorMap[i] = cmap[start];
+ alpha = cmap[start] & alphaMask;
+
+ if (alpha == alphaMask) {
+ continue;
+ }
+ if (alpha == 0) {
+ if (transparentIndex < 0) {
+ transparentIndex = i;
+ }
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ } else if (alpha != alphaMask &&
+ transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param cmap the array that gives the color mapping
+ * @param start the start index of the color mapping data within the cmap array
+ * @param hasalpha whether this color model uses alpha
+ * @param trans the transparency supported, @see java.awt.Transparency
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ */
+ public IndexColorModel(int bits, int size, int cmap[], int start,
+ boolean hasalpha, int trans, int transferType) {
+
+ super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (hasalpha || (trans >= 0)), false, Transparency.OPAQUE,
+ validateTransferType(transferType));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ if (trans >= 0 && trans < mapSize) {
+ transparentIndex = trans;
+ transparency = Transparency.BITMASK;
+ } else {
+ transparentIndex = -1;
+ transparency = Transparency.OPAQUE;
+ }
+
+ int alphaMask = 0xff000000;
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++, start++) {
+ if (transparentIndex == i) {
+ colorMap[i] = cmap[start] & 0x00ffffff;
+ continue;
+ }
+ if (hasalpha) {
+ alpha = cmap[start] & alphaMask;
+ colorMap[i] = cmap[start];
+
+ if (alpha == alphaMask) {
+ continue;
+ }
+ if (alpha == 0) {
+ if (trans < 0) {
+ trans = i;
+ }
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ } else if (alpha != 0
+ && transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ } else {
+ colorMap[i] = alphaMask | cmap[start];
+ }
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map
+ * from arrays of red, green, blue, and alpha values.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param r the array giving the red components of the entries in the color map
+ * @param g the array giving the green components of the entries in the color map
+ * @param b the array giving the blue components of the entries in the color map
+ * @param a the array giving the alpha components of the entries in the color map
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ * @throws ArrayIndexOutOfBoundsException if the size of one of the
+ * component arrays is less than the size of the color map
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[],
+ byte a[]) {
+
+ super(bits, IndexColorModel.createBits(true),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false,
+ Transparency.OPAQUE,
+ validateTransferType(ColorModel.getTransferType(bits)));
+
+ createColorMap(size, r, g, b, a, -1);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map
+ * from arrays of red, green, and blue values.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param r the array giving the red components of the entries in the color map
+ * @param g the array giving the green components of the entries in the color map
+ * @param b the array giving the blue components of the entries in the color map
+ * @param trans the transparency supported, @see java.awt.Transparency
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ * @throws ArrayIndexOutOfBoundsException if the size of one of the
+ * component arrays is less than the size of the color map
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[],
+ int trans) {
+
+ super(bits, IndexColorModel.createBits((trans >= 0)),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), (trans >= 0), false,
+ Transparency.OPAQUE,
+ validateTransferType(ColorModel.getTransferType(bits)));
+
+ createColorMap(size, r, g, b, null, trans);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map
+ * from arrays of red, green, and blue values.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param r the array giving the red components of the entries in the color map
+ * @param g the array giving the green components of the entries in the color map
+ * @param b the array giving the blue components of the entries in the color map
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ * @throws ArrayIndexOutOfBoundsException if the size of one of the
+ * component arrays is less than the size of the color map
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[]) {
+ super(bits, IndexColorModel.createBits(false),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false,
+ Transparency.OPAQUE,
+ validateTransferType(ColorModel.getTransferType(bits)));
+
+ createColorMap(size, r, g, b, null, -1);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param cmap the array that gives the color mapping
+ * @param start the start index of the color mapping data within the cmap array
+ * @param hasalpha whether this color model uses alpha
+ * @param trans the transparency supported, @see java.awt.Transparency
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ */
+ public IndexColorModel(int bits, int size, byte cmap[], int start,
+ boolean hasalpha, int trans) {
+
+ super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (hasalpha || (trans >= 0)), false, Transparency.OPAQUE,
+ validateTransferType(ColorModel.getTransferType(bits)));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ transparentIndex = -1;
+
+ transparency = Transparency.OPAQUE;
+ int alpha = 0xff000000;
+
+ for (int i = 0; i < mapSize; i++) {
+ colorMap[i] = (cmap[start++] & 0xff) << 16 |
+ (cmap[start++] & 0xff) << 8 | (cmap[start++] & 0xff);
+ if (trans == i) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ if(hasalpha) {
+ start++;
+ }
+ continue;
+ }
+ if (hasalpha) {
+ alpha = cmap[start++] & 0xff;
+ if (alpha == 0) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ if (trans < 0) {
+ trans = i;
+ }
+ }
+ } else {
+ if (alpha != 0xff &&
+ transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ }
+ alpha <<= 24;
+ }
+ colorMap[i] |= alpha;
+ }
+
+ if (trans >= 0 && trans < mapSize) {
+ transparentIndex = trans;
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits the array of component masks
+ * @param size the size of the color map
+ * @param cmap the array that gives the color mapping
+ * @param start the start index of the color mapping data within the cmap array
+ * @param hasalpha whether this color model uses alpha
+ *
+ * @throws IllegalArgumentException if the size of the color map is
+ * less than one
+ */
+ public IndexColorModel(int bits, int size, byte cmap[], int start,
+ boolean hasalpha) {
+
+ this(bits, size, cmap, start, hasalpha, -1);
+ }
+
+ @Override
+ public Object getDataElements(int[] components, int offset, Object pixel) {
+ int rgb = (components[offset] << 16) | (components[offset + 1]) << 8 |
+ components[offset + 2];
+ if (hasAlpha) {
+ rgb |= components[offset + 3] << 24;
+ } else {
+ rgb |= 0xff000000;
+ }
+ return getDataElements(rgb, pixel);
+ }
+
+ @Override
+ public synchronized Object getDataElements(int rgb, Object pixel) {
+ int red = (rgb >> 16) & 0xff;
+ int green = (rgb >> 8) & 0xff;
+ int blue = rgb & 0xff;
+ int alpha = rgb >>> 24;
+ int pixIdx = 0;
+
+ for (int i = 0; i < totalInserted; i++) {
+ int idx = i * 2;
+ if (rgb == cachetable[idx]) {
+ return createDataObject(cachetable[idx + 1], pixel);
+ }
+ }
+
+ if (!hasAlpha && grayPalette) {
+ int grey = (red * 77 + green * 150 + blue * 29 + 128) >>> 8;
+ int minError = 255;
+ int error = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ error = Math.abs((colorMap[i] & 0xff) - grey);
+ if (error < minError) {
+ pixIdx = i;
+ if (error == 0) {
+ break;
+ }
+ minError = error;
+ }
+ }
+ } else if (alpha == 0 && transparentIndex > -1) {
+ pixIdx = transparentIndex;
+ } else {
+ int minAlphaError = 255;
+ int minError = 195075; // 255^2 + 255^2 + 255^2
+ int alphaError;
+ int error = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ int pix = colorMap[i];
+ if (rgb == pix) {
+ pixIdx = i;
+ break;
+ }
+ alphaError = Math.abs(alpha - (pix >>> 24));
+ if (alphaError <= minAlphaError) {
+ minAlphaError = alphaError;
+
+ int buf = ((pix >> 16) & 0xff) - red;
+ error = buf * buf;
+
+ if (error < minError) {
+ buf = ((pix >> 8) & 0xff) - green;
+ error += buf * buf;
+
+ if (error < minError) {
+ buf = (pix & 0xff) - blue;
+ error += buf * buf;
+
+ if (error < minError) {
+ pixIdx = i;
+ minError = error;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ cachetable[nextInsertIdx] = rgb;
+ cachetable[nextInsertIdx + 1] = pixIdx;
+
+ nextInsertIdx = (nextInsertIdx + 2) % (CACHESIZE * 2);
+ if (totalInserted < CACHESIZE) {
+ totalInserted++;
+ }
+
+ return createDataObject(pixIdx, pixel);
+ }
+
+ /**
+ * Converts an image from indexed to RGB format.
+ *
+ * @param raster the raster containing the source image
+ * @param forceARGB whether to use the default RGB color model
+ *
+ * @return the buffered image
+ *
+ * @throws IllegalArgumentException if the raster is not compatible with
+ * this color model
+ */
+ public BufferedImage convertToIntDiscrete(Raster raster,
+ boolean forceARGB) {
+
+ if (!isCompatibleRaster(raster)) {
+ // awt.265=The raster argument is not compatible with this IndexColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.265")); //$NON-NLS-1$
+ }
+
+ ColorModel model;
+ if (forceARGB || transparency == Transparency.TRANSLUCENT) {
+ model = ColorModel.getRGBdefault();
+ } else if (transparency == Transparency.BITMASK) {
+ model = new DirectColorModel(25, 0x00ff0000, 0x0000ff00,
+ 0x000000ff, 0x01000000);
+ } else {
+ model = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
+ }
+
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+
+ WritableRaster distRaster = model.createCompatibleWritableRaster(w, h);
+
+ int minX = raster.getMinX();
+ int minY = raster.getMinY();
+
+ Object obj = null;
+ int pixels[] = null;
+
+ for (int i = 0; i < h; i++, minY++) {
+ obj = raster.getDataElements(minX, minY, w, 1, obj);
+ if (obj instanceof byte[]) {
+ byte ba[] = (byte[]) obj;
+ if (pixels == null) {
+ pixels = new int[ba.length];
+ }
+ for (int j = 0; j < ba.length; j++) {
+ pixels[j] = colorMap[ba[j] & 0xff];
+ }
+ } else if (obj instanceof short[]) {
+ short sa[] = (short[]) obj;
+ if (pixels == null) {
+ pixels = new int[sa.length];
+ }
+ for (int j = 0; j < sa.length; j++) {
+ pixels[j] = colorMap[sa[j] & 0xffff];
+ }
+ }
+ if (obj instanceof int[]) {
+ int ia[] = (int[]) obj;
+ if (pixels == null) {
+ pixels = new int[ia.length];
+ }
+ for (int j = 0; j < ia.length; j++) {
+ pixels[j] = colorMap[ia[j]];
+ }
+ }
+
+ distRaster.setDataElements(0, i, w, 1, pixels);
+ }
+
+ return new BufferedImage(model, distRaster, false, null);
+ }
+
+ /**
+ * Gets the valid pixels.
+ *
+ * @return the valid pixels
+ */
+ public BigInteger getValidPixels() {
+ return validBits;
+ }
+
+ @Override
+ public String toString() {
+ // The output format based on 1.5 release behaviour.
+ // It could be reveled such way:
+ // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
+ // ColorModel cm = bi.getColorModel();
+ // System.out.println(cm.toString());
+ String str = "IndexColorModel: #pixel_bits = " + pixel_bits + //$NON-NLS-1$
+ " numComponents = " + numComponents + " color space = " + cs + //$NON-NLS-1$ //$NON-NLS-2$
+ " transparency = "; //$NON-NLS-1$
+
+ if (transparency == Transparency.OPAQUE) {
+ str = str + "Transparency.OPAQUE"; //$NON-NLS-1$
+ } else if (transparency == Transparency.BITMASK) {
+ str = str + "Transparency.BITMASK"; //$NON-NLS-1$
+ } else {
+ str = str + "Transparency.TRANSLUCENT"; //$NON-NLS-1$
+ }
+
+ str = str + " transIndex = " + transparentIndex + " has alpha = " + //$NON-NLS-1$ //$NON-NLS-2$
+ hasAlpha + " isAlphaPre = " + isAlphaPremultiplied; //$NON-NLS-1$
+
+ return str;
+ }
+
+ @Override
+ public int[] getComponents(Object pixel, int components[], int offset) {
+ int pixIdx = -1;
+ if (pixel instanceof byte[]) {
+ byte ba[] = (byte[]) pixel;
+ pixIdx = ba[0] & 0xff;
+ } else if (pixel instanceof short[]) {
+ short sa[] = (short[]) pixel;
+ pixIdx = sa[0] & 0xffff;
+ } else if (pixel instanceof int[]) {
+ int ia[] = (int[]) pixel;
+ pixIdx = ia[0];
+ } else {
+ // awt.219=This transferType is not supported by this color model
+ throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$
+ }
+
+ return getComponents(pixIdx, components, offset);
+ }
+
+ @Override
+ public WritableRaster createCompatibleWritableRaster(int w, int h) {
+ WritableRaster raster;
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h, 1,
+ pixel_bits, null);
+ } else if (pixel_bits <= 8) {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+ 1, null);
+ } else if (pixel_bits <= 16) {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, w,
+ h, 1, null);
+ } else {
+ // awt.266=The number of bits in a pixel is greater than 16
+ throw new UnsupportedOperationException(Messages.getString("awt.266")); //$NON-NLS-1$
+ }
+
+ return raster;
+ }
+
+ @Override
+ public boolean isCompatibleSampleModel(SampleModel sm) {
+ if (sm == null) {
+ return false;
+ }
+
+ if (!(sm instanceof MultiPixelPackedSampleModel)
+ && !(sm instanceof ComponentSampleModel)) {
+ return false;
+ }
+
+ if (sm.getTransferType() != transferType) {
+ return false;
+ }
+ if (sm.getNumBands() != 1) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+ return new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h,
+ pixel_bits);
+ }
+ int bandOffsets[] = new int[1];
+ bandOffsets[0] = 0;
+ return new ComponentSampleModel(transferType, w, h, 1, w,
+ bandOffsets);
+
+ }
+
+ @Override
+ public boolean isCompatibleRaster(Raster raster) {
+ int sampleSize = raster.getSampleModel().getSampleSize(0);
+ return (raster.getTransferType() == transferType &&
+ raster.getNumBands() == 1 && (1 << sampleSize) >= mapSize);
+ }
+
+ @Override
+ public int getDataElement(int components[], int offset) {
+ int rgb = (components[offset] << 16) | (components[offset + 1]) << 8
+ | components[offset + 2];
+
+ if (hasAlpha) {
+ rgb |= components[offset + 3] << 24;
+ } else {
+ rgb |= 0xff000000;
+ }
+
+ int pixel;
+
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[]) getDataElements(rgb, null);
+ pixel = ba[0] & 0xff;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[]) getDataElements(rgb, null);
+ pixel = sa[0] & 0xffff;
+ break;
+ default:
+ // awt.267=The transferType is invalid
+ throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+ }
+
+ return pixel;
+ }
+
+ /**
+ * Gets the color map.
+ *
+ * @param rgb the destination array where the color map is written
+ */
+ public final void getRGBs(int rgb[]) {
+ System.arraycopy(colorMap, 0, rgb, 0, mapSize);
+ }
+
+ /**
+ * Gets the red component of the color map.
+ *
+ * @param r the destination array
+ */
+ public final void getReds(byte r[]) {
+ for (int i = 0; i < mapSize; i++) {
+ r[i] = (byte) (colorMap[i] >> 16);
+ }
+ }
+
+ /**
+ * Gets the green component of the color map.
+ *
+ * @param g the destination array
+ */
+ public final void getGreens(byte g[]) {
+ for (int i = 0; i < mapSize; i++) {
+ g[i] = (byte) (colorMap[i] >> 8);
+ }
+ }
+
+ /**
+ * Gets the blue component of the color map.
+ *
+ * @param b the destination array
+ */
+ public final void getBlues(byte b[]) {
+ for (int i = 0; i < mapSize; i++) {
+ b[i] = (byte) colorMap[i];
+ }
+ }
+
+ /**
+ * Gets the alpha component of the color map.
+ *
+ * @param a the destination array
+ */
+ public final void getAlphas(byte a[]) {
+ for (int i = 0; i < mapSize; i++) {
+ a[i] = (byte) (colorMap[i] >> 24);
+ }
+ }
+
+ @Override
+ public int[] getComponents(int pixel, int components[], int offset) {
+ if (components == null) {
+ components = new int[offset + numComponents];
+ }
+
+ components[offset + 0] = getRed(pixel);
+ components[offset + 1] = getGreen(pixel);
+ components[offset + 2] = getBlue(pixel);
+ if (hasAlpha && (components.length - offset) > 3) {
+ components[offset + 3] = getAlpha(pixel);
+ }
+
+ return components;
+ }
+
+ /**
+ * Checks if the specified pixel is valid for this color model.
+ *
+ * @param pixel the pixel
+ *
+ * @return true, if the pixel is valid
+ */
+ public boolean isValid(int pixel) {
+ if (validBits == null) {
+ return (pixel >= 0 && pixel < mapSize);
+ }
+ return (pixel < mapSize && validBits.testBit(pixel));
+ }
+
+ @Override
+ public final int getRed(int pixel) {
+ return (colorMap[pixel] >> 16) & 0xff;
+ }
+
+ @Override
+ public final int getRGB(int pixel) {
+ return colorMap[pixel];
+ }
+
+ @Override
+ public final int getGreen(int pixel) {
+ return (colorMap[pixel] >> 8) & 0xff;
+ }
+
+ @Override
+ public final int getBlue(int pixel) {
+ return colorMap[pixel] & 0xff;
+ }
+
+ @Override
+ public final int getAlpha(int pixel) {
+ return (colorMap[pixel] >> 24) & 0xff;
+ }
+
+ @Override
+ public int[] getComponentSize() {
+ return bits.clone();
+ }
+
+ /**
+ * Checks if this color model validates pixels.
+ *
+ * @return true, if all pixels are valid, otherwise false
+ */
+ public boolean isValid() {
+ return (validBits == null);
+ }
+
+ @Override
+ public void finalize() {
+ // TODO: implement
+ return;
+ }
+
+ /**
+ * Gets the index that represents the transparent pixel.
+ *
+ * @return the index that represents the transparent pixel
+ */
+ public final int getTransparentPixel() {
+ return transparentIndex;
+ }
+
+ @Override
+ public int getTransparency() {
+ return transparency;
+ }
+
+ /**
+ * Gets the size of the color map.
+ *
+ * @return the map size
+ */
+ public final int getMapSize() {
+ return mapSize;
+ }
+
+ /**
+ * Creates the color map.
+ *
+ * @param size the size
+ * @param r the r
+ * @param g the g
+ * @param b the b
+ * @param a the a
+ * @param trans the trans
+ */
+ private void createColorMap(int size, byte r[], byte g[], byte b[],
+ byte a[], int trans) {
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ if (trans >= 0 && trans < mapSize) {
+ transparency = Transparency.BITMASK;
+ transparentIndex = trans;
+ } else {
+ transparency = Transparency.OPAQUE;
+ transparentIndex = -1;
+ }
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ colorMap[i] = ((r[i] & 0xff) << 16) | ((g[i] & 0xff) << 8) |
+ (b[i] & 0xff);
+
+ if (trans == i) {
+ continue;
+ }
+
+ if (a == null) {
+ colorMap[i] |= 0xff000000;
+ } else {
+ alpha = a[i] & 0xff;
+ if (alpha == 0xff) {
+ colorMap[i] |= 0xff000000;
+ } else if (alpha == 0) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ if (transparentIndex < 0) {
+ transparentIndex = i;
+ }
+ } else {
+ colorMap[i] |= (a[i] & 0xff) << 24;
+ if (transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * This method checking, if Color Map has Gray Palette.
+ */
+ private void checkPalette() {
+ grayPalette = false;
+ if (transparency > Transparency.OPAQUE) {
+ return;
+ }
+ int rgb = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ rgb = colorMap[i];
+ if (((rgb >> 16) & 0xff) != ((rgb >> 8) & 0xff) ||
+ ((rgb >> 8) & 0xff) != (rgb & 0xff)) {
+ return;
+ }
+ }
+ grayPalette = true;
+ }
+
+ /**
+ * Construction an array pixel representation.
+ *
+ * @param colorMapIdx - index into Color Map
+ * @param pixel - pixel
+ *
+ * @return - an array pixel representation
+ */
+ private Object createDataObject(int colorMapIdx, Object pixel) {
+ if (pixel == null) {
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte[] ba = new byte[1];
+ ba[0] = (byte) colorMapIdx;
+ pixel = ba;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short[] sa = new short[1];
+ sa[0] = (short) colorMapIdx;
+ pixel = sa;
+ break;
+ default:
+ // awt.267=The transferType is invalid
+ throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+ }
+ } else if (pixel instanceof byte[]
+ && transferType == DataBuffer.TYPE_BYTE) {
+ byte ba[] = (byte[]) pixel;
+ ba[0] = (byte) colorMapIdx;
+ pixel = ba;
+ } else if (pixel instanceof short[]&&
+ transferType == DataBuffer.TYPE_USHORT) {
+ short[] sa = (short[]) pixel;
+ sa[0] = (short) colorMapIdx;
+ pixel = sa;
+ } else if (pixel instanceof int[]) {
+ int ia[] = (int[]) pixel;
+ ia[0] = colorMapIdx;
+ pixel = ia;
+ } else {
+ // awt.268=The pixel is not a primitive array of type transferType
+ throw new ClassCastException(Messages.getString("awt.268")); //$NON-NLS-1$
+ }
+ return pixel;
+ }
+
+ /**
+ * Creates the bits.
+ *
+ * @param hasAlpha the has alpha
+ *
+ * @return the int[]
+ */
+ private static int[] createBits(boolean hasAlpha) {
+
+ int numChannels;
+ if (hasAlpha) {
+ numChannels = 4;
+ } else {
+ numChannels = 3;
+ }
+
+ int bits[] = new int[numChannels];
+ for (int i = 0; i < numChannels; i++) {
+ bits[i] = 8;
+ }
+
+ return bits;
+
+ }
+
+ /**
+ * Validate transfer type.
+ *
+ * @param transferType the transfer type
+ *
+ * @return the int
+ */
+ private static int validateTransferType(int transferType) {
+ if (transferType != DataBuffer.TYPE_BYTE &&
+ transferType != DataBuffer.TYPE_USHORT) {
+ // awt.269=The transferType is not one of DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
+ throw new IllegalArgumentException(Messages.getString("awt.269")); //$NON-NLS-1$
+ }
+ return transferType;
+ }
+
+ /**
+ * Checks if is gray pallete.
+ *
+ * @return true, if is gray pallete
+ */
+ boolean isGrayPallete(){
+ return grayPalette;
+ }
+
+}
+
+
diff --git a/awt/java/awt/image/Kernel.java b/awt/java/awt/image/Kernel.java
new file mode 100644
index 0000000..c6f00e2
--- /dev/null
+++ b/awt/java/awt/image/Kernel.java
@@ -0,0 +1,138 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 28, 2005
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Kernel class provides a matrix. This matrix is stored as a float array
+ * which describes how a specified pixel affects the value calculated for
+ * the pixel's position in the output image of a filtering operation.
+ * The X, Y origins indicate the kernel matrix element which corresponds to
+ * the pixel position for which an output value is being calculated.
+ */
+public class Kernel implements Cloneable {
+
+ /** The x origin. */
+ private final int xOrigin;
+
+ /** The y origin. */
+ private final int yOrigin;
+
+ /** The width. */
+ private int width;
+
+ /** The height. */
+ private int height;
+
+ /** The data. */
+ float data[];
+
+ /**
+ * Instantiates a new Kernel with the specified float array.
+ * The width*height elements of the data array are copied.
+ *
+ * @param width the width of the Kernel.
+ * @param height the height of the Kernel.
+ * @param data the data of Kernel.
+ */
+ public Kernel(int width, int height, float[] data) {
+ int dataLength = width*height;
+ if (data.length < dataLength) {
+ // awt.22B=Length of data should not be less than width*height
+ throw new IllegalArgumentException(Messages.getString("awt.22B")); //$NON-NLS-1$
+ }
+
+ this.width = width;
+ this.height = height;
+
+ this.data = new float[dataLength];
+ System.arraycopy(data, 0, this.data, 0, dataLength);
+
+ xOrigin = (width-1)/2;
+ yOrigin = (height-1)/2;
+ }
+
+ /**
+ * Gets the width of this Kernel.
+ *
+ * @return the width of this Kernel.
+ */
+ public final int getWidth() {
+ return width;
+ }
+
+ /**
+ * Gets the height of this Kernel.
+ *
+ * @return the height of this Kernel.
+ */
+ public final int getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the float data array of this Kernel.
+ *
+ * @param data the float array where the resulted data will be stored.
+ *
+ * @return the float data array of this Kernel.
+ */
+ public final float[] getKernelData(float[] data) {
+ if (data == null) {
+ data = new float[this.data.length];
+ }
+ System.arraycopy(this.data, 0, data, 0, this.data.length);
+
+ return data;
+ }
+
+ /**
+ * Gets the X origin of this Kernel.
+ *
+ * @return the X origin of this Kernel.
+ */
+ public final int getXOrigin() {
+ return xOrigin;
+ }
+
+ /**
+ * Gets the Y origin of this Kernel.
+ *
+ * @return the Y origin of this Kernel.
+ */
+ public final int getYOrigin() {
+ return yOrigin;
+ }
+
+ /**
+ * Returns a copy of this Kernel object.
+ *
+ * @return the copy of this Kernel object.
+ */
+ @Override
+ public Object clone() {
+ return new Kernel(width, height, data);
+ }
+}
diff --git a/awt/java/awt/image/LookupOp.java b/awt/java/awt/image/LookupOp.java
new file mode 100644
index 0000000..f9bd2c7
--- /dev/null
+++ b/awt/java/awt/image/LookupOp.java
@@ -0,0 +1,647 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The LookupOp class perfoms a lookup operation which transforms a
+ * source image by filtering each band using a table of data.
+ * The table may contain a single array or it may contain a
+ * different data array for each band of the image.
+ */
+public class LookupOp implements BufferedImageOp, RasterOp {
+
+ /** The lut. */
+ private final LookupTable lut;
+
+ /** The hints. */
+ private RenderingHints hints;
+
+ // TODO remove when this field is used
+ /** The can use ipp. */
+ @SuppressWarnings("unused")
+ private final boolean canUseIpp;
+
+ // We don't create levels/values when it is possible to reuse old
+ /** The cached levels. */
+ private int cachedLevels[];
+
+ /** The cached values. */
+ private int cachedValues[];
+ // Number of channels for which cache is valid.
+ // If negative number of channels is same as positive but skipAlpha was specified
+ /** The valid for channels. */
+ private int validForChannels;
+
+ /** The level initializer. */
+ static int levelInitializer[] = new int[0x10000];
+
+ static {
+ // TODO
+ // System.loadLibrary("imageops");
+
+ for (int i=1; i<=0x10000; i++) {
+ levelInitializer[i-1] = i;
+ }
+ }
+
+ /**
+ * Instantiates a new LookupOp object from the specified
+ * LookupTable object and a RenderingHints object.
+ *
+ * @param lookup the specified LookupTable object.
+ * @param hints the RenderingHints object or null.
+ */
+ public LookupOp(LookupTable lookup, RenderingHints hints) {
+ if (lookup == null){
+ throw new NullPointerException(Messages.getString("awt.01", "lookup")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ lut = lookup;
+ this.hints = hints;
+ canUseIpp = lut instanceof ByteLookupTable || lut instanceof ShortLookupTable;
+ }
+
+ /**
+ * Gets the LookupTable of the specified Object.
+ *
+ * @return the LookupTable of the specified Object.
+ */
+ public final LookupTable getTable() {
+ return lut;
+ }
+
+ public final RenderingHints getRenderingHints() {
+ return hints;
+ }
+
+ public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ if (dstPt == null) {
+ dstPt = new Point2D.Float();
+ }
+
+ dstPt.setLocation(srcPt);
+ return dstPt;
+ }
+
+ public final Rectangle2D getBounds2D(Raster src) {
+ return src.getBounds();
+ }
+
+ public final Rectangle2D getBounds2D(BufferedImage src) {
+ return getBounds2D(src.getRaster());
+ }
+
+ public WritableRaster createCompatibleDestRaster(Raster src) {
+ return src.createCompatibleWritableRaster();
+ }
+
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+ if (dstCM == null) {
+ dstCM = src.getColorModel();
+
+ // Sync transfer type with LUT for component color model
+ if (dstCM instanceof ComponentColorModel) {
+ int transferType = dstCM.getTransferType();
+ if (lut instanceof ByteLookupTable) {
+ transferType = DataBuffer.TYPE_BYTE;
+ } else if (lut instanceof ShortLookupTable) {
+ transferType = DataBuffer.TYPE_SHORT;
+ }
+
+ dstCM = new ComponentColorModel(
+ dstCM.cs,
+ dstCM.hasAlpha(),
+ dstCM.isAlphaPremultiplied,
+ dstCM.transparency,
+ transferType
+ );
+ }
+ }
+
+ WritableRaster r =
+ dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+ src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+ dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+ return new BufferedImage(
+ dstCM,
+ r,
+ dstCM.isAlphaPremultiplied(),
+ null
+ );
+ }
+
+ public final WritableRaster filter(Raster src, WritableRaster dst) {
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else {
+ if (src.getNumBands() != dst.getNumBands()) {
+ throw new IllegalArgumentException(Messages.getString("awt.237")); //$NON-NLS-1$ }
+ }
+ if (src.getWidth() != dst.getWidth()){
+ throw new IllegalArgumentException(Messages.getString("awt.28F")); //$NON-NLS-1$ }
+ }
+ if (src.getHeight() != dst.getHeight()){
+ throw new IllegalArgumentException(Messages.getString("awt.290")); //$NON-NLS-1$ }
+ }
+ }
+
+ if (lut.getNumComponents() != 1 && lut.getNumComponents() != src.getNumBands()) {
+ // awt.238=The number of arrays in the LookupTable does not meet the restrictions
+ throw new IllegalArgumentException(Messages.getString("awt.238")); //$NON-NLS-1$
+ }
+
+ // TODO
+ // if (!canUseIpp || ippFilter(src, dst, BufferedImage.TYPE_CUSTOM, false) != 0)
+ if (slowFilter(src, dst, false) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ return dst;
+ }
+
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+ ColorModel srcCM = src.getColorModel();
+
+ if (srcCM instanceof IndexColorModel) {
+ // awt.220=Source should not have IndexColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.220")); //$NON-NLS-1$
+ }
+
+ // Check if the number of scaling factors matches the number of bands
+ int nComponents = srcCM.getNumComponents();
+ int nLUTComponents = lut.getNumComponents();
+ boolean skipAlpha;
+ if (srcCM.hasAlpha()) {
+ if (nLUTComponents == 1 || nLUTComponents == nComponents-1) {
+ skipAlpha = true;
+ } else if (nLUTComponents == nComponents) {
+ skipAlpha = false;
+ } else {
+ // awt.229=Number of components in the LUT does not match the number of bands
+ throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
+ }
+ } else if (nLUTComponents == 1 || nLUTComponents == nComponents) {
+ skipAlpha = false;
+ } else {
+ // awt.229=Number of components in the LUT does not match the number of bands
+ throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
+ }
+
+ BufferedImage finalDst = null;
+ if (dst == null) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, null);
+ } else {
+ if (src.getWidth() != dst.getWidth()){
+ throw new IllegalArgumentException(Messages.getString("awt.291")); //$NON-NLS-1$
+ }
+
+ if (src.getHeight() != dst.getHeight()){
+ throw new IllegalArgumentException(Messages.getString("awt.292")); //$NON-NLS-1$
+ }
+
+ if (!srcCM.equals(dst.getColorModel())) {
+ // Treat BufferedImage.TYPE_INT_RGB and
+ // BufferedImage.TYPE_INT_ARGB as same
+ if (!((src.getType() == BufferedImage.TYPE_INT_RGB || src
+ .getType() == BufferedImage.TYPE_INT_ARGB) && (dst
+ .getType() == BufferedImage.TYPE_INT_RGB || dst
+ .getType() == BufferedImage.TYPE_INT_ARGB))) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, null);
+ }
+ }
+ }
+
+ // TODO
+ //if (!canUseIpp || ippFilter(src.getRaster(), dst.getRaster(), src.getType(), skipAlpha) != 0)
+ if (slowFilter(src.getRaster(), dst.getRaster(), skipAlpha) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ if (finalDst != null) {
+ Graphics2D g = finalDst.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.drawImage(dst, 0, 0, null);
+ } else {
+ finalDst = dst;
+ }
+
+ return dst;
+ }
+
+ /**
+ * Slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param skipAlpha the skip alpha
+ *
+ * @return the int
+ */
+ private final int slowFilter(Raster src, WritableRaster dst, boolean skipAlpha) {
+ int minSrcX = src.getMinX();
+ int minDstX = dst.getMinX();
+ int minSrcY = src.getMinY();
+ int minDstY = dst.getMinY();
+
+ int skippingChannels = skipAlpha ? 1 : 0;
+ int numBands2Process = src.getNumBands() - skippingChannels;
+
+ int numBands = src.getNumBands();
+ int srcHeight = src.getHeight();
+ int srcWidth = src.getWidth();
+
+ int[] pixels = null;
+ int offset = lut.getOffset();
+
+ if (lut instanceof ByteLookupTable){
+ byte[][] byteData = ((ByteLookupTable)lut).getTable();
+ pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);
+
+ if (lut.getNumComponents() != 1){
+ for (int i=0; i < pixels.length; i+= numBands){
+ for (int b = 0; b < numBands2Process; b++){
+ pixels[i+b] = byteData[b][pixels[i+b]-offset] & 0xFF;
+ }
+ }
+ } else {
+ for (int i=0; i < pixels.length; i+= numBands){
+ for (int b = 0; b < numBands2Process; b++){
+ pixels[i+b] = byteData[0][pixels[i+b]-offset] & 0xFF;
+ }
+ }
+ }
+
+ dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
+ } else if (lut instanceof ShortLookupTable){
+ short[][] shortData = ((ShortLookupTable)lut).getTable();
+ pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);
+
+ if (lut.getNumComponents() != 1){
+ for (int i=0; i < pixels.length; i+= numBands){
+ for (int b = 0; b < numBands2Process; b++){
+ pixels[i+b] = shortData[b][pixels[i+b]-offset] & 0xFFFF;
+ }
+ }
+ } else {
+ for (int i=0; i < pixels.length; i+= numBands){
+ for (int b = 0; b < numBands2Process; b++){
+ pixels[i+b] = shortData[0][pixels[i+b]-offset] & 0xFFFF;
+ }
+ }
+ }
+
+ dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
+ } else {
+ int pixel[] = new int[src.getNumBands()];
+ int maxY = minSrcY + srcHeight;
+ int maxX = minSrcX + srcWidth;
+ for (int srcY=minSrcY, dstY = minDstY; srcY < maxY; srcY++, dstY++){
+ for (int srcX=minSrcX, dstX = minDstX; srcX < maxX; srcX++, dstX++){
+ src.getPixel(srcX, srcY, pixel);
+ lut.lookupPixel(pixel, pixel);
+ dst.setPixel(dstX, dstY, pixel);
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Creates the byte levels.
+ *
+ * @param channels the channels
+ * @param skipAlpha the skip alpha
+ * @param levels the levels
+ * @param values the values
+ * @param channelsOrder the channels order
+ */
+ private final void createByteLevels(
+ int channels, boolean skipAlpha,
+ int levels[], int values[], int channelsOrder[]
+ ) {
+ byte data[][] = ((ByteLookupTable)lut).getTable();
+ int nLevels = data[0].length;
+ int offset = lut.getOffset();
+
+ // Use one data array for all channels or use several data arrays
+ int dataIncrement = data.length > 1 ? 1 : 0;
+
+ for (int ch = 0, dataIdx = 0; ch<channels; dataIdx+=dataIncrement, ch++) {
+ int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];
+ int channelBase = nLevels * channelOffset;
+
+ // Skip last channel if needed, zero values are OK -
+ // no changes to the channel information will be done in IPP
+ if ((channelOffset == channels-1 && skipAlpha) || (dataIdx >= data.length)) {
+ continue;
+ }
+
+ System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
+ for (int from=0, to=channelBase; from<nLevels; from++, to++) {
+ values[to] = data[dataIdx][from] & 0xFF;
+ }
+ }
+ }
+
+ /**
+ * Creates the short levels.
+ *
+ * @param channels the channels
+ * @param skipAlpha the skip alpha
+ * @param levels the levels
+ * @param values the values
+ * @param channelsOrder the channels order
+ */
+ private final void createShortLevels(
+ int channels, boolean skipAlpha,
+ int levels[], int values[], int channelsOrder[]
+ ) {
+ short data[][] = ((ShortLookupTable)lut).getTable();
+ int nLevels = data[0].length;
+ int offset = lut.getOffset();
+
+ // Use one data array for all channels or use several data arrays
+ int dataIncrement = data.length > 1 ? 1 : 0;
+
+ for (int ch = 0, dataIdx = 0; ch<channels; dataIdx+=dataIncrement, ch++) {
+ int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];
+
+ // Skip last channel if needed, zero values are OK -
+ // no changes to the channel information will be done in IPP
+ if ((channelOffset == channels-1 && skipAlpha) || (dataIdx >= data.length)) {
+ continue;
+ }
+
+ int channelBase = nLevels * channelOffset;
+ System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
+ for (int from=0, to=channelBase; from<nLevels; from++, to++) {
+ values[to] = data[dataIdx][from] & 0xFFFF;
+ }
+ }
+ }
+
+ // TODO remove when this method is used
+ /**
+ * Ipp filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param imageType the image type
+ * @param skipAlpha the skip alpha
+ *
+ * @return the int
+ */
+ @SuppressWarnings("unused")
+ private final int ippFilter(
+ Raster src, WritableRaster dst,
+ int imageType, boolean skipAlpha
+ ) {
+ int res;
+
+ int srcStride, dstStride;
+ int channels;
+ int offsets[] = null;
+ int channelsOrder[] = null;
+
+ switch (imageType) {
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ case BufferedImage.TYPE_INT_RGB: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ channelsOrder = new int[] {2, 1, 0, 3};
+ break;
+ }
+
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+ case BufferedImage.TYPE_INT_BGR: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ break;
+ }
+
+ case BufferedImage.TYPE_BYTE_GRAY: {
+ channels = 1;
+ srcStride = src.getWidth();
+ dstStride = dst.getWidth();
+ break;
+ }
+
+ case BufferedImage.TYPE_3BYTE_BGR: {
+ channels = 3;
+ srcStride = src.getWidth()*3;
+ dstStride = dst.getWidth()*3;
+ channelsOrder = new int[] {2, 1, 0};
+ break;
+ }
+
+ case BufferedImage.TYPE_USHORT_GRAY:
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ case BufferedImage.TYPE_BYTE_BINARY: {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ default: {
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+
+ if (
+ srcSM instanceof PixelInterleavedSampleModel &&
+ dstSM instanceof PixelInterleavedSampleModel
+ ) {
+ // Check PixelInterleavedSampleModel
+ if (
+ srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+ dstSM.getDataType() != DataBuffer.TYPE_BYTE
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ // Have IPP functions for 1, 3 and 4 channels
+ channels = srcSM.getNumBands();
+ if (!(channels == 1 || channels == 3 || channels == 4)) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+ dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+
+ channelsOrder = ((ComponentSampleModel) srcSM).getBandOffsets();
+ } else if (
+ srcSM instanceof SinglePixelPackedSampleModel &&
+ dstSM instanceof SinglePixelPackedSampleModel
+ ) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 =
+ (SinglePixelPackedSampleModel) srcSM;
+ SinglePixelPackedSampleModel sppsm2 =
+ (SinglePixelPackedSampleModel) dstSM;
+
+ channels = sppsm1.getNumBands();
+
+ // TYPE_INT_RGB, TYPE_INT_ARGB...
+ if (
+ sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+ sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+ !(channels == 3 || channels == 4)
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ // Check compatibility of sample models
+ if (
+ !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+ !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ for (int i=0; i<channels; i++) {
+ if (sppsm1.getSampleSize(i) != 8) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+ }
+
+ channelsOrder = new int[channels];
+ int bitOffsets[] = sppsm1.getBitOffsets();
+ for (int i=0; i<channels; i++) {
+ channelsOrder[i] = bitOffsets[i] / 8;
+ }
+
+ if (channels == 3) { // Don't skip channel now, could be optimized
+ channels = 4;
+ }
+
+ srcStride = sppsm1.getScanlineStride() * 4;
+ dstStride = sppsm2.getScanlineStride() * 4;
+ } else {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (
+ src.getSampleModelTranslateX() != 0 ||
+ src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 ||
+ dst.getSampleModelTranslateY() != 0
+ ) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+ }
+ }
+
+ int levels[] = null, values[] = null;
+ int channelMultiplier = skipAlpha ? -1 : 1;
+ if (channelMultiplier*channels == validForChannels) { // use existing levels/values
+ levels = cachedLevels;
+ values = cachedValues;
+ } else { // create new levels/values
+ if (lut instanceof ByteLookupTable) {
+ byte data[][] = ((ByteLookupTable)lut).getTable();
+ levels = new int[channels*data[0].length];
+ values = new int[channels*data[0].length];
+ createByteLevels(channels, skipAlpha, levels, values, channelsOrder);
+ } else if (lut instanceof ShortLookupTable) {
+ short data[][] = ((ShortLookupTable)lut).getTable();
+ levels = new int[channels*data[0].length];
+ values = new int[channels*data[0].length];
+ createShortLevels(channels, skipAlpha, levels, values, channelsOrder);
+ }
+
+ // cache levels/values
+ validForChannels = channelMultiplier*channels;
+ cachedLevels = levels;
+ cachedValues = values;
+ }
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ res = ippLUT(
+ srcData, src.getWidth(), src.getHeight(), srcStride,
+ dstData, dst.getWidth(), dst.getHeight(), dstStride,
+ levels, values,
+ channels, offsets,
+ false
+ );
+
+ return res;
+ }
+
+ /**
+ * Ipp lut.
+ *
+ * @param src the src
+ * @param srcWidth the src width
+ * @param srcHeight the src height
+ * @param srcStride the src stride
+ * @param dst the dst
+ * @param dstWidth the dst width
+ * @param dstHeight the dst height
+ * @param dstStride the dst stride
+ * @param levels the levels
+ * @param values the values
+ * @param channels the channels
+ * @param offsets the offsets
+ * @param linear the linear
+ *
+ * @return the int
+ */
+ final static native int ippLUT(
+ Object src, int srcWidth, int srcHeight, int srcStride,
+ Object dst, int dstWidth, int dstHeight, int dstStride,
+ int levels[], int values[],
+ int channels, int offsets[],
+ boolean linear
+ );
+}
diff --git a/awt/java/awt/image/LookupTable.java b/awt/java/awt/image/LookupTable.java
new file mode 100644
index 0000000..d15f23c
--- /dev/null
+++ b/awt/java/awt/image/LookupTable.java
@@ -0,0 +1,93 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * This abstract LookupTable class represents lookup table which
+ * is defined with the number of components and offset value.
+ * ByteLookupTable and ShortLookupTable classes are subclasses of
+ * LookupTable which contains byte and short data tables as
+ * an input arrays for bands or components of image.
+ */
+public abstract class LookupTable {
+
+ /** The offset. */
+ private int offset;
+
+ /** The num components. */
+ private int numComponents;
+
+ /**
+ * Instantiates a new LookupTable with the specified offset value
+ * and number of components.
+ *
+ * @param offset the offset value.
+ * @param numComponents the number of components.
+ */
+ protected LookupTable(int offset, int numComponents) {
+ if (offset < 0) {
+ // awt.232=Offset should be not less than zero
+ throw new IllegalArgumentException(Messages.getString("awt.232")); //$NON-NLS-1$
+ }
+ if (numComponents < 1) {
+ // awt.233=Number of components should be positive
+ throw new IllegalArgumentException(Messages.getString("awt.233")); //$NON-NLS-1$
+ }
+
+ this.offset = offset;
+ this.numComponents = numComponents;
+ }
+
+ /**
+ * Gets the offset value of this Lookup table.
+ *
+ * @return the offset value of this Lookup table.
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Gets the number of components of this Lookup table.
+ *
+ * @return the number components of this Lookup table.
+ */
+ public int getNumComponents() {
+ return numComponents;
+ }
+
+ /**
+ * Returns a int array which contains samples of the specified
+ * pixel which is translated with the lookup table of this
+ * LookupTable. The resulted array is stored to the dst array.
+ *
+ * @param src the source array.
+ * @param dst the destination array where the result can be stored.
+ *
+ * @return the int array of translated samples of a pixel.
+ */
+ public abstract int[] lookupPixel(int[] src, int[] dst);
+}
diff --git a/awt/java/awt/image/MemoryImageSource.java b/awt/java/awt/image/MemoryImageSource.java
new file mode 100644
index 0000000..983f19e
--- /dev/null
+++ b/awt/java/awt/image/MemoryImageSource.java
@@ -0,0 +1,512 @@
+/*
+ * 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.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The MemoryImageSource class is used to produces pixels of an image from
+ * an array. This class can manage a memory image which
+ * contains an animation or custom rendering.
+ */
+public class MemoryImageSource implements ImageProducer {
+
+ /** The width. */
+ int width;
+
+ /** The height. */
+ int height;
+
+ /** The cm. */
+ ColorModel cm;
+
+ /** The b data. */
+ byte bData[];
+
+ /** The i data. */
+ int iData[];
+
+ /** The offset. */
+ int offset;
+
+ /** The scanline. */
+ int scanline;
+
+ /** The properties. */
+ Hashtable<?, ?> properties;
+
+ /** The consumers. */
+ Vector<ImageConsumer> consumers;
+
+ /** The animated. */
+ boolean animated;
+
+ /** The fullbuffers. */
+ boolean fullbuffers;
+
+ /** The data type. */
+ int dataType;
+
+ /** The Constant DATA_TYPE_BYTE. */
+ static final int DATA_TYPE_BYTE = 0;
+
+ /** The Constant DATA_TYPE_INT. */
+ static final int DATA_TYPE_INT = 1;
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param cm the specified ColorModel.
+ * @param pix the pixel array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ * @param props the set of properties to be used for image
+ * processing.
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int pix[],
+ int off, int scan, Hashtable<?, ?> props) {
+ init(w, h, cm, pix, off, scan, props);
+ }
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param cm the specified ColorModel.
+ * @param pix the pixel array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ * @param props the set of properties to be used for image
+ * processing.
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte pix[],
+ int off, int scan, Hashtable<?, ?> props) {
+ init(w, h, cm, pix, off, scan, props);
+ }
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters and default RGB ColorModel.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param pix the pixel array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ * @param props the set of properties to be used for image
+ * processing.
+ */
+ public MemoryImageSource(int w, int h, int pix[], int off, int scan,
+ Hashtable<?, ?> props) {
+ init(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
+ }
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param cm the specified ColorModel.
+ * @param pix the pixel array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int pix[],
+ int off, int scan) {
+ init(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param cm the specified ColorModel.
+ * @param pix the pixel array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte pix[],
+ int off, int scan) {
+ init(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ * Instantiates a new MemoryImageSource with the specified
+ * parameters and default RGB ColorModel.
+ *
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param pix the pixels array.
+ * @param off the offset in the pixel array.
+ * @param scan the distance from one pixel's row to the next
+ * in the pixel array.
+ */
+ public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
+ init(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
+ }
+
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ return consumers.contains(ic);
+ }
+
+ public void startProduction(ImageConsumer ic) {
+ if(!isConsumer(ic) && ic != null) {
+ consumers.addElement(ic);
+ }
+ try{
+ setHeader(ic);
+ setPixels(ic, 0, 0, width, height);
+ if(animated){
+ ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+ }else{
+ ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ if(isConsumer(ic)) {
+ removeConsumer(ic);
+ }
+ }
+ }catch(Exception e){
+ if(isConsumer(ic)) {
+ ic.imageComplete(ImageConsumer.IMAGEERROR);
+ }
+ if(isConsumer(ic)) {
+ removeConsumer(ic);
+ }
+ }
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {
+ }
+
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ consumers.removeElement(ic);
+ }
+
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if(ic == null || consumers.contains(ic)) {
+ return;
+ }
+ consumers.addElement(ic);
+ }
+
+ /**
+ * Replaces the pixel data with a new pixel array for holding
+ * the pixels for this image. If an animation
+ * flag is set to true value by the setAnimated() method,
+ * the new pixels will be immediately delivered to the ImageConsumers.
+ *
+ * @param newpix the new pixel array.
+ * @param newmodel the new ColorModel.
+ * @param offset the offset in the array.
+ * @param scansize the distance from one row of pixels to the next row
+ * in the pixel array
+ */
+ public synchronized void newPixels(int newpix[], ColorModel newmodel,
+ int offset, int scansize) {
+ this.dataType = DATA_TYPE_INT;
+ this.iData = newpix;
+ this.cm = newmodel;
+ this.offset = offset;
+ this.scanline = scansize;
+ newPixels();
+ }
+
+ /**
+ * Replaces the pixel data with a new pixel array for holding
+ * the pixels for this image. If an animation
+ * flag is set to true value by the setAnimated() method,
+ * the new pixels will be immediately delivered to the ImageConsumers.
+ *
+ * @param newpix the new pixel array.
+ * @param newmodel the new ColorModel.
+ * @param offset the offset in the array.
+ * @param scansize the distance from one row of pixels to the next row
+ * in the pixel array
+ */
+ public synchronized void newPixels(byte newpix[], ColorModel newmodel,
+ int offset, int scansize) {
+ this.dataType = DATA_TYPE_BYTE;
+ this.bData = newpix;
+ this.cm = newmodel;
+ this.offset = offset;
+ this.scanline = scansize;
+ newPixels();
+ }
+
+ /**
+ * Sets the full buffer updates flag to true. If this is an
+ * animated image, the image consumers hints are updated
+ * accordingly.
+ *
+ * @param fullbuffers the true if the pixel buffer should be sent always.
+ */
+ public synchronized void setFullBufferUpdates(boolean fullbuffers) {
+ if(this.fullbuffers == fullbuffers) {
+ return;
+ }
+ this.fullbuffers = fullbuffers;
+ if(animated){
+ Object consAr[] = consumers.toArray();
+ for (Object element : consAr) {
+ ImageConsumer con = (ImageConsumer)element;
+ try{
+ if(fullbuffers){
+ con.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
+ ImageConsumer.COMPLETESCANLINES);
+ }else{
+ con.setHints(ImageConsumer.RANDOMPIXELORDER);
+ }
+ }catch(Exception e){
+ if(isConsumer(con)) {
+ con.imageComplete(ImageConsumer.IMAGEERROR);
+ }
+ if(isConsumer(con)) {
+ removeConsumer(con);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the flag that tells whether this memory image has more
+ * than one frame (for animation): true for multiple frames,
+ * false if this class represents a single frame image.
+ *
+ * @param animated whether this image represents an animation.
+ */
+ public synchronized void setAnimated(boolean animated) {
+ if(this.animated == animated) {
+ return;
+ }
+ Object consAr[] = consumers.toArray();
+ for (Object element : consAr) {
+ ImageConsumer con = (ImageConsumer)element;
+ try{
+ con.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }catch(Exception e){
+ if(isConsumer(con)) {
+ con.imageComplete(ImageConsumer.IMAGEERROR);
+ }
+ }
+ if(isConsumer(con)){
+ removeConsumer(con);
+ }
+ }
+ this.animated = animated;
+ }
+
+ /**
+ * Sends the specified rectangular area of the buffer to
+ * ImageConsumers and notifies them that an animation frame
+ * is completed only if framenotify parameter is true.
+ * That works only if the animated flag has been set to true
+ * by the setAnimated() method. If the full buffer update flag
+ * has been set to true by the setFullBufferUpdates() method,
+ * then the entire buffer will always be sent ignoring parameters.
+ *
+ * @param x the X coordinate of the rectangular area.
+ * @param y the Y coordinate of rthe ectangular area.
+ * @param w the width of the rectangular area.
+ * @param h the height of the rectangular area.
+ * @param framenotify true if a SINGLEFRAMEDONE notification
+ * should be sent to the registered consumers, false otherwise.
+ */
+ public synchronized void newPixels(int x, int y, int w, int h,
+ boolean framenotify) {
+ if(animated){
+ if(fullbuffers){
+ x = 0;
+ y = 0;
+ w = width;
+ h = height;
+ }else{
+ if(x < 0){
+ w += x;
+ x = 0;
+ }
+ if(w > width) {
+ w = width - x;
+ }
+ if(y < 0){
+ h += y;
+ y = 0;
+ }
+ }
+ if(h > height) {
+ h = height - y;
+ }
+ Object consAr[] = consumers.toArray();
+ for (Object element : consAr) {
+ ImageConsumer con = (ImageConsumer)element;
+ try{
+ if(w > 0 && h > 0) {
+ setPixels(con, x, y, w, h);
+ }
+ if(framenotify) {
+ con.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+ }
+ }catch(Exception ex){
+ if(isConsumer(con)) {
+ con.imageComplete(ImageConsumer.IMAGEERROR);
+ }
+ if(isConsumer(con)) {
+ removeConsumer(con);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends the specified rectangular area of the buffer to
+ * the ImageConsumers and notifies them that an animation frame
+ * is completed if the animated flag has been set to true
+ * by the setAnimated() method. If the full buffer update flag
+ * has been set to true by the setFullBufferUpdates() method,
+ * then the entire buffer will always be sent ignoring parameters.
+ *
+ * @param x the X coordinate of the rectangular area.
+ * @param y the Y coordinate of the rectangular area.
+ * @param w the width of the rectangular area.
+ * @param h the height of the rectangular area.
+ */
+ public synchronized void newPixels(int x, int y, int w, int h) {
+ newPixels(x, y, w, h, true);
+ }
+
+ /**
+ * Sends a new buffer of pixels to the ImageConsumers
+ * and notifies them that an animation frame is completed if
+ * the animated flag has been set to true by the setAnimated() method.
+ */
+ public void newPixels() {
+ newPixels(0, 0, width, height, true);
+ }
+
+ /**
+ * Inits the.
+ *
+ * @param width the width
+ * @param height the height
+ * @param model the model
+ * @param pixels the pixels
+ * @param off the off
+ * @param scan the scan
+ * @param prop the prop
+ */
+ private void init(int width, int height, ColorModel model, byte pixels[],
+ int off, int scan, Hashtable<?, ?> prop){
+
+ this.width = width;
+ this.height = height;
+ this.cm = model;
+ this.bData = pixels;
+ this.offset = off;
+ this.scanline = scan;
+ this.properties = prop;
+ this.dataType = DATA_TYPE_BYTE;
+ this.consumers = new Vector<ImageConsumer>();
+
+ }
+
+ /**
+ * Inits the.
+ *
+ * @param width the width
+ * @param height the height
+ * @param model the model
+ * @param pixels the pixels
+ * @param off the off
+ * @param scan the scan
+ * @param prop the prop
+ */
+ private void init(int width, int height, ColorModel model, int pixels[],
+ int off, int scan, Hashtable<?, ?> prop){
+
+ this.width = width;
+ this.height = height;
+ this.cm = model;
+ this.iData = pixels;
+ this.offset = off;
+ this.scanline = scan;
+ this.properties = prop;
+ this.dataType = DATA_TYPE_INT;
+ this.consumers = new Vector<ImageConsumer>();
+ }
+
+ /**
+ * Sets the pixels.
+ *
+ * @param con the con
+ * @param x the x
+ * @param y the y
+ * @param w the w
+ * @param h the h
+ */
+ private void setPixels(ImageConsumer con, int x, int y, int w, int h){
+ int pixelOff = scanline * y + offset + x;
+
+ switch(dataType){
+ case DATA_TYPE_BYTE:
+ con.setPixels(x, y, w, h, cm, bData, pixelOff, scanline);
+ break;
+ case DATA_TYPE_INT:
+ con.setPixels(x, y, w, h, cm, iData, pixelOff, scanline);
+ break;
+ default:
+ // awt.22A=Wrong type of pixels array
+ throw new IllegalArgumentException(Messages.getString("awt.22A")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the header.
+ *
+ * @param con the new header
+ */
+ private synchronized void setHeader(ImageConsumer con){
+ con.setDimensions(width, height);
+ con.setProperties(properties);
+ con.setColorModel(cm);
+ con.setHints(animated ? (fullbuffers ? (ImageConsumer.TOPDOWNLEFTRIGHT |
+ ImageConsumer.COMPLETESCANLINES) : ImageConsumer.RANDOMPIXELORDER) :
+ (ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
+ ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME));
+ }
+
+}
+
diff --git a/awt/java/awt/image/MultiPixelPackedSampleModel.java b/awt/java/awt/image/MultiPixelPackedSampleModel.java
new file mode 100644
index 0000000..dd44b49
--- /dev/null
+++ b/awt/java/awt/image/MultiPixelPackedSampleModel.java
@@ -0,0 +1,454 @@
+/*
+ * 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 org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The MultiPixelPackedSampleModel class represents image data with one
+ * band. This class packs multiple pixels with one sample in one data
+ * element and supports the following data types: DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT.
+ */
+public class MultiPixelPackedSampleModel extends SampleModel {
+
+ /** The pixel bit stride. */
+ private int pixelBitStride;
+
+ /** The scanline stride. */
+ private int scanlineStride;
+
+ /** The data bit offset. */
+ private int dataBitOffset;
+
+ /** The bit mask. */
+ private int bitMask;
+
+ /** The data element size. */
+ private int dataElementSize;
+
+ /** The pixels per data element. */
+ private int pixelsPerDataElement;
+
+ /**
+ * Instantiates a new MultiPixelPackedSampleModel with the specified
+ * parameters.
+ *
+ * @param dataType the data type of the samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param numberOfBits the number of bits per pixel.
+ * @param scanlineStride the scanline stride of the of the image data.
+ * @param dataBitOffset the array of the band offsets.
+ */
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits, int scanlineStride, int dataBitOffset) {
+
+ super(dataType, w, h, 1);
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ // awt.61=Unsupported data type: {0}
+ throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
+ dataType));
+ }
+
+ this.scanlineStride = scanlineStride;
+ if(numberOfBits == 0) {
+ // awt.20C=Number of Bits equals to zero
+ throw new RasterFormatException(Messages.getString("awt.20C")); //$NON-NLS-1$
+ }
+ this.pixelBitStride = numberOfBits;
+ this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
+ if(dataElementSize % pixelBitStride != 0) {
+ // awt.20D=The number of bits per pixel is not a power of 2 or pixels span data element boundaries
+ throw new RasterFormatException(Messages.getString("awt.20D")); //$NON-NLS-1$
+ }
+
+ if(dataBitOffset % numberOfBits != 0) {
+ // awt.20E=Data Bit offset is not a multiple of pixel bit stride
+ throw new RasterFormatException(Messages.getString("awt.20E")); //$NON-NLS-1$
+ }
+ this.dataBitOffset = dataBitOffset;
+
+ this.pixelsPerDataElement = dataElementSize / pixelBitStride;
+ this.bitMask = (1 << numberOfBits) - 1;
+ }
+
+ /**
+ * Instantiates a new MultiPixelPackedSampleModel with the specified
+ * parameters.
+ *
+ * @param dataType the data type of the samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param numberOfBits the number of bits per pixel.
+ */
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits) {
+
+ this(dataType, w, h, numberOfBits, (numberOfBits * w +
+ DataBuffer.getDataTypeSize(dataType) - 1) /
+ DataBuffer.getDataTypeSize(dataType), 0);
+ }
+
+ @Override
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ byte bdata[];
+ if (obj == null) {
+ bdata = new byte[1];
+ } else {
+ bdata = (byte[]) obj;
+ }
+ bdata[0] = (byte) getSample(x, y, 0, data);
+ obj = bdata;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short sdata[];
+ if (obj == null) {
+ sdata = new short[1];
+ } else {
+ sdata = (short[]) obj;
+ }
+ sdata[0] = (short) getSample(x, y, 0, data);
+ obj = sdata;
+ break;
+ case DataBuffer.TYPE_INT:
+ int idata[];
+ if (obj == null) {
+ idata = new int[1];
+ } else {
+ idata = (int[]) obj;
+ }
+ idata[0] = getSample(x, y, 0, data);
+ obj = idata;
+ break;
+ }
+
+ return obj;
+ }
+
+ @Override
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ setSample(x, y, obj, data, 1, 0);
+ }
+
+ /**
+ * Compares this MultiPixelPackedSampleModel object with
+ * the specified object.
+ *
+ * @param o the Object to be compared.
+ *
+ * @return true, if the object is a MultiPixelPackedSampleModel
+ * with the same data parameter values as this MultiPixelPackedSampleModel,
+ * false otherwise.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
+ return false;
+ }
+
+ MultiPixelPackedSampleModel model = (MultiPixelPackedSampleModel) o;
+ return this.width == model.width &&
+ this.height == model.height &&
+ this.numBands == model.numBands &&
+ this.dataType == model.dataType &&
+ this.pixelBitStride == model.pixelBitStride &&
+ this.bitMask == model.bitMask &&
+ this.pixelsPerDataElement == model.pixelsPerDataElement &&
+ this.dataElementSize == model.dataElementSize &&
+ this.dataBitOffset == model.dataBitOffset &&
+ this.scanlineStride == model.scanlineStride;
+ }
+
+ @Override
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands != null && bands.length != 1) {
+ // awt.20F=Number of bands must be only 1
+ throw new RasterFormatException(Messages.getString("awt.20F")); //$NON-NLS-1$
+ }
+ return createCompatibleSampleModel(width, height);
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ return new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
+ }
+
+ @Override
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int pixel[];
+ if (iArray == null) {
+ pixel = new int[numBands];
+ } else {
+ pixel = iArray;
+ }
+
+ pixel[0] = getSample(x, y, 0, data);
+ return pixel;
+ }
+
+ @Override
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ setSample(x, y, iArray, data, 2, 0);
+ }
+
+ @Override
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height || b != 0) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int bitnum = dataBitOffset + x * pixelBitStride;
+ int elem = data.getElem(y * scanlineStride + bitnum / dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize - 1)) -
+ pixelBitStride;
+
+ return (elem >> shift) & bitMask;
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, int s, DataBuffer data) {
+ if (b != 0) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ setSample(x, y, null, data, 3, s);
+ }
+
+ @Override
+ public DataBuffer createDataBuffer() {
+ DataBuffer dataBuffer = null;
+ int size = scanlineStride * height;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ dataBuffer = new DataBufferByte(size + (dataBitOffset + 7) / 8);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ dataBuffer = new DataBufferUShort(size + (dataBitOffset + 15) / 16);
+ break;
+ case DataBuffer.TYPE_INT:
+ dataBuffer = new DataBufferInt(size + (dataBitOffset + 31) / 32);
+ break;
+ }
+ return dataBuffer;
+ }
+
+ /**
+ * Gets the offset of the specified pixel in the data array.
+ *
+ * @param x the X coordinate of the specified pixel.
+ * @param y the Y coordinate of the specified pixel.
+ *
+ * @return the offset of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ return y * scanlineStride + (x * pixelBitStride + dataBitOffset) /
+ dataElementSize;
+ }
+
+ @Override
+ public int getSampleSize(int band) {
+ return pixelBitStride;
+ }
+
+ /**
+ * Gets the bit offset in the data element which
+ * is stored for the specified pixel of a scanline.
+ *
+ * @param x the pixel.
+ *
+ * @return the bit offset of the pixel in the data element.
+ */
+ public int getBitOffset(int x) {
+ return (x * pixelBitStride + dataBitOffset) % dataElementSize;
+ }
+
+ @Override
+ public int[] getSampleSize() {
+ int sampleSizes[] = { pixelBitStride };
+ return sampleSizes;
+ }
+
+ /**
+ * Returns a hash code of this MultiPixelPackedSampleModel class.
+ *
+ * @return the hash code of this MultiPixelPackedSampleModel class.
+ */
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ int tmp = 0;
+
+ hash = width;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= height;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= numBands;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= dataType;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= scanlineStride;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= pixelBitStride;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= dataBitOffset;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= bitMask;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= dataElementSize;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= pixelsPerDataElement;
+ return hash;
+ }
+
+ @Override
+ public int getTransferType() {
+ if (pixelBitStride > 16) {
+ return DataBuffer.TYPE_INT;
+ } else if (pixelBitStride > 8) {
+ return DataBuffer.TYPE_USHORT;
+ } else {
+ return DataBuffer.TYPE_BYTE;
+ }
+ }
+
+ /**
+ * Gets the scanline stride of this MultiPixelPackedSampleModel.
+ *
+ * @return the scanline stride of this MultiPixelPackedSampleModel.
+ */
+ public int getScanlineStride() {
+ return scanlineStride;
+ }
+
+ /**
+ * Gets the pixel bit stride of this MultiPixelPackedSampleModel.
+ *
+ * @return the pixel bit stride of this MultiPixelPackedSampleModel.
+ */
+ public int getPixelBitStride() {
+ return pixelBitStride;
+ }
+
+ @Override
+ public int getNumDataElements() {
+ return 1;
+ }
+
+ /**
+ * Gets the data bit offset.
+ *
+ * @return the data bit offset.
+ */
+ public int getDataBitOffset() {
+ return dataBitOffset;
+ }
+
+ /**
+ * This method is used by other methods of this class. The behaviour of
+ * this method depends on the method which has been invoke this one. The
+ * argument methodId is used to choose valid behaviour in a particular case.
+ * If methodId is equal to 1 it means that this method has been invoked by
+ * the setDataElements() method, 2 - means setPixel(), and setSample() in
+ * any other cases.
+ *
+ * @param x the x
+ * @param y the y
+ * @param obj the obj
+ * @param data the data
+ * @param methodId the method id
+ * @param s the s
+ */
+ private void setSample(final int x, final int y, final Object obj,
+ final DataBuffer data, final int methodId, int s) {
+ if ((x < 0) || (y < 0) || (x >= this.width) || (y >= this.height)) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages
+ .getString("awt.63")); //$NON-NLS-1$
+ }
+
+ final int bitnum = dataBitOffset + x * pixelBitStride;
+ final int idx = y * scanlineStride + bitnum / dataElementSize;
+ final int shift = dataElementSize - (bitnum & (dataElementSize - 1))
+ - pixelBitStride;
+ final int mask = ~(bitMask << shift);
+ int elem = data.getElem(idx);
+
+ switch (methodId) {
+ case 1: { // Invoked from setDataElements()
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ s = ((byte[]) obj)[0] & 0xff;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ s = ((short[]) obj)[0] & 0xffff;
+ break;
+ case DataBuffer.TYPE_INT:
+ s = ((int[]) obj)[0];
+ break;
+ }
+ break;
+ }
+ case 2: { // Invoked from setPixel()
+ s = ((int[]) obj)[0];
+ break;
+ }
+ }
+
+ elem &= mask;
+ elem |= (s & bitMask) << shift;
+ data.setElem(idx, elem);
+ }
+}
+
diff --git a/awt/java/awt/image/PackedColorModel.java b/awt/java/awt/image/PackedColorModel.java
new file mode 100644
index 0000000..7aaefbf
--- /dev/null
+++ b/awt/java/awt/image/PackedColorModel.java
@@ -0,0 +1,383 @@
+/*
+ * 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.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class PackedColorModel represents a color model where the
+ * components are just the red, green, and blue bands, plus an alpha
+ * band if alpha is supported.
+ */
+public abstract class PackedColorModel extends ColorModel {
+
+ /** The component masks. */
+ int componentMasks[];
+
+ /** The offsets. */
+ int offsets[];
+
+ /** The scales. */
+ float scales[];
+
+ /**
+ * Instantiates a new packed color model.
+ *
+ * @param space the color space
+ * @param bits the array of component masks
+ * @param colorMaskArray the array that gives the bitmask corresponding
+ * to each color band (red, green, and blue)
+ * @param alphaMask the bitmask corresponding to the alpha band
+ * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+ * @param trans the transparency strategy, @see java.awt.Transparency
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ *
+ * @throws IllegalArgumentException if the number of bits in the combined
+ * bitmasks for the color bands is less than one or greater than 32
+ */
+ 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();
+ }
+
+ /**
+ * Instantiates a new packed color model.
+ *
+ * @param space the color space
+ * @param bits the array of component masks
+ * @param rmask the bitmask corresponding to the red band
+ * @param gmask the bitmask corresponding to the green band
+ * @param bmask the bitmask corresponding to the blue band
+ * @param amask the bitmask corresponding to the alpha band
+ * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+ * @param trans the transparency strategy, @see java.awt.Transparency
+ * @param transferType the transfer type (primitive java type
+ * to use for the components)
+ *
+ * @throws IllegalArgumentException if the number of bits in the combined
+ * bitmasks for the color bands is less than one or greater than 32
+ */
+ 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);
+ }
+
+ /**
+ * Gets the bitmask corresponding to the specified color component.
+ *
+ * @param index the index of the desired color
+ *
+ * @return the mask
+ */
+ public final int getMask(int index) {
+ return componentMasks[index];
+ }
+
+ /**
+ * Gets the bitmasks of the components.
+ *
+ * @return the masks
+ */
+ public final int[] getMasks() {
+ return (componentMasks.clone());
+ }
+
+ /**
+ * Creates the bits.
+ *
+ * @param colorMaskArray the color mask array
+ * @param alphaMask the alpha mask
+ *
+ * @return the int[]
+ */
+ 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;
+ }
+
+ /**
+ * Creates the bits.
+ *
+ * @param rmask the rmask
+ * @param gmask the gmask
+ * @param bmask the bmask
+ * @param amask the amask
+ *
+ * @return the int[]
+ */
+ 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;
+ }
+
+ /**
+ * Count comp bits.
+ *
+ * @param compMask the comp mask
+ *
+ * @return the int
+ */
+ 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;
+ }
+
+ /**
+ * Validate transfer type.
+ *
+ * @param transferType the transfer type
+ *
+ * @return the int
+ */
+ 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;
+}
+
+ /**
+ * Parses the components.
+ */
+ 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];
+ }
+ }
+
+ }
+
+}
+
diff --git a/awt/java/awt/image/PixelGrabber.java b/awt/java/awt/image/PixelGrabber.java
new file mode 100644
index 0000000..cecd5c8
--- /dev/null
+++ b/awt/java/awt/image/PixelGrabber.java
@@ -0,0 +1,408 @@
+/*
+ * 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.Image;
+import java.util.Hashtable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class PixelGrabber implements ImageConsumer {
+
+ int width;
+ int height;
+ int X;
+ int Y;
+ int offset;
+ int scanline;
+ ImageProducer producer;
+
+ byte bData[];
+ int iData[];
+ ColorModel cm;
+
+ private int grabberStatus;
+ private int dataType;
+ private boolean isGrabbing;
+ private boolean isRGB;
+
+
+ private static final int DATA_TYPE_BYTE = 0;
+ private static final int DATA_TYPE_INT = 1;
+ private static final int DATA_TYPE_UNDEFINED = 2;
+
+ private static final int ALL_BITS = (ImageObserver.FRAMEBITS |
+ ImageObserver.ALLBITS);
+
+ private static final int GRABBING_STOP = ALL_BITS | ImageObserver.ERROR;
+
+
+
+ public PixelGrabber(ImageProducer ip, int x, int y, int w, int h, int[] pix,
+ int off, int scansize) {
+ initialize(ip, x, y, w, h, pix, off, scansize, true);
+ }
+
+ public PixelGrabber(Image img, int x, int y, int w, int h, int[] pix,
+ int off, int scansize) {
+ initialize(img.getSource(), x, y, w, h, pix, off, scansize, true);
+ }
+
+ public PixelGrabber(Image img, int x, int y, int w, int h, boolean forceRGB) {
+ initialize(img.getSource(), x, y, w, h, null, 0, 0, forceRGB);
+ }
+
+ public void setProperties(Hashtable<?, ?> props) {
+ return;
+ }
+
+ public synchronized Object getPixels() {
+ switch(dataType){
+ case DATA_TYPE_BYTE:
+ return bData;
+ case DATA_TYPE_INT:
+ return iData;
+ default:
+ return null;
+ }
+ }
+
+ public void setColorModel(ColorModel model) {
+ return;
+ }
+
+ public void setPixels(int srcX, int srcY, int srcW, int srcH,
+ ColorModel model, byte[] pixels, int srcOff, int srcScan) {
+ if(srcY < Y){
+ int delta = Y - srcY;
+ if(delta >= height) {
+ return;
+ }
+ srcY += delta;
+ srcH -= delta;
+ srcOff += srcScan * delta;
+ }
+
+ if(srcY + srcH > Y + height){
+ srcH = Y + height - srcY;
+ if(srcH <= 0) {
+ return;
+ }
+ }
+
+ if(srcX < X){
+ int delta = X - srcX;
+ if(delta >= width) {
+ return;
+ }
+ srcW -= delta;
+ srcX += delta;
+ srcOff += delta;
+ }
+
+ if(srcX + srcW > X + width){
+ srcW = X + width - srcX;
+ if(srcW <= 0) {
+ return;
+ }
+ }
+ if(scanline == 0) {
+ scanline = width;
+ }
+ int realOff = offset + (srcY - Y) * scanline + (srcX - X);
+ switch(dataType){
+ case DATA_TYPE_UNDEFINED:
+ cm = model;
+ if(model != ColorModel.getRGBdefault()){
+ bData = new byte[width * height];
+ isRGB = false;
+ dataType = DATA_TYPE_BYTE;
+ }else{
+ iData = new int[width * height];
+ isRGB = true;
+ dataType = DATA_TYPE_INT;
+ }
+ case DATA_TYPE_BYTE:
+ if(!isRGB && cm == model){
+ for(int y = 0; y < srcH; y++){
+ System.arraycopy(pixels, srcOff, bData, realOff, srcW);
+ srcOff += srcScan;
+ realOff += scanline;
+ }
+ break;
+ }
+ forceToRGB();
+ case DATA_TYPE_INT:
+ for(int y = 0; y < srcH; y++){
+ for(int x = 0; x < srcW; x++){
+ iData[realOff + x] = cm.getRGB(pixels[srcOff + x] & 0xff);
+ }
+ srcOff += srcScan;
+ realOff += scanline;
+ }
+ }
+
+ return;
+ }
+
+ public void setPixels(int srcX, int srcY, int srcW, int srcH,
+ ColorModel model, int[] pixels, int srcOff, int srcScan) {
+
+ if(srcY < Y){
+ int delta = Y - srcY;
+ if(delta >= height) {
+ return;
+ }
+ srcY += delta;
+ srcH -= delta;
+ srcOff += srcScan * delta;
+ }
+
+ if(srcY + srcH > Y + height){
+ srcH = Y + height - srcY;
+ if(srcH <= 0) {
+ return;
+ }
+ }
+
+ if(srcX < X){
+ int delta = X - srcX;
+ if(delta >= width) {
+ return;
+ }
+ srcW -= delta;
+ srcX += delta;
+ srcOff += delta;
+ }
+
+ if(srcX + srcW > X + width){
+ srcW = X + width - srcX;
+ if(srcW <= 0) {
+ return;
+ }
+ }
+ if(scanline == 0) {
+ scanline = width;
+ }
+ int realOff = offset + (srcY - Y) * scanline + (srcX - X);
+
+ int mask = 0xFF;
+
+ switch(dataType){
+ case DATA_TYPE_UNDEFINED:
+ cm = model;
+ iData = new int[width * height];
+ dataType = DATA_TYPE_INT;
+ isRGB = (cm == ColorModel.getRGBdefault());
+
+ case DATA_TYPE_INT:
+ if(cm == model){
+ for(int y = 0; y < srcH; y++){
+ System.arraycopy(pixels, srcOff, iData, realOff, srcW);
+ srcOff += srcScan;
+ realOff += scanline;
+ }
+ break;
+ }
+ mask = 0xFFFFFFFF;
+
+ case DATA_TYPE_BYTE:
+ forceToRGB();
+ for(int y = 0; y < srcH; y++){
+ for(int x = 0; x < srcW; x++){
+ iData[realOff+x] = cm.getRGB(pixels[srcOff+x] & mask);
+ }
+ srcOff += srcScan;
+ realOff += scanline;
+ }
+ }
+ }
+
+ public synchronized ColorModel getColorModel() {
+ return cm;
+ }
+
+ public synchronized boolean grabPixels(long ms)
+ throws InterruptedException {
+ if((grabberStatus & GRABBING_STOP) != 0){
+ return ((grabberStatus & ALL_BITS) != 0);
+ }
+
+ long start = System.currentTimeMillis();
+
+ if(!isGrabbing){
+ isGrabbing = true;
+ grabberStatus &= ~ImageObserver.ABORT;
+ producer.startProduction(this);
+ }
+ while((grabberStatus & GRABBING_STOP) == 0){
+ if(ms != 0){
+ ms = start + ms - System.currentTimeMillis();
+ if(ms <= 0) {
+ break;
+ }
+ }
+ wait(ms);
+ }
+
+ return ((grabberStatus & ALL_BITS) != 0);
+ }
+
+ public void setDimensions(int w, int h) {
+ if(width < 0) {
+ width = w - X;
+ }
+ if(height < 0) {
+ height = h - Y;
+ }
+
+ grabberStatus |= ImageObserver.WIDTH | ImageObserver.HEIGHT;
+
+ if(width <=0 || height <=0){
+ imageComplete(STATICIMAGEDONE);
+ return;
+ }
+
+ if(isRGB && dataType == DATA_TYPE_UNDEFINED){
+ iData = new int[width * height];
+ dataType = DATA_TYPE_INT;
+ scanline = width;
+ }
+ }
+
+ public void setHints(int hints) {
+ return;
+ }
+
+ public synchronized void imageComplete(int status) {
+ switch(status){
+ case IMAGEABORTED:
+ grabberStatus |= ImageObserver.ABORT;
+ break;
+ case IMAGEERROR:
+ grabberStatus |= ImageObserver.ERROR | ImageObserver.ABORT;
+ break;
+ case SINGLEFRAMEDONE:
+ grabberStatus |= ImageObserver.FRAMEBITS;
+ break;
+ case STATICIMAGEDONE:
+ grabberStatus |= ImageObserver.ALLBITS;
+ break;
+ default:
+ // awt.26A=Incorrect ImageConsumer completion status
+ throw new IllegalArgumentException(Messages.getString("awt.26A")); //$NON-NLS-1$
+ }
+ isGrabbing = false;
+ producer.removeConsumer(this);
+ notifyAll();
+ }
+
+ public boolean grabPixels() throws InterruptedException {
+ return grabPixels(0);
+ }
+
+ public synchronized void startGrabbing() {
+ if((grabberStatus & GRABBING_STOP) != 0){
+ return;
+ }
+ if(!isGrabbing){
+ isGrabbing = true;
+ grabberStatus &= ~ImageObserver.ABORT;
+ producer.startProduction(this);
+ }
+ }
+
+ public synchronized void abortGrabbing() {
+ imageComplete(IMAGEABORTED);
+ }
+
+ public synchronized int status() {
+ return grabberStatus;
+ }
+
+ public synchronized int getWidth() {
+ if(width < 0) {
+ return -1;
+ }
+ return width;
+ }
+
+ public synchronized int getStatus() {
+ return grabberStatus;
+ }
+
+ public synchronized int getHeight() {
+ if(height < 0) {
+ return -1;
+ }
+ return height;
+ }
+
+ private void initialize(ImageProducer ip, int x, int y, int w, int h,
+ int pixels[], int off, int scansize, boolean forceRGB){
+
+ producer = ip;
+ X = x;
+ Y = y;
+ width = w;
+ height = h;
+ iData = pixels;
+ dataType = (pixels == null) ? DATA_TYPE_UNDEFINED : DATA_TYPE_INT;
+ offset = off;
+ scanline = scansize;
+ if(forceRGB){
+ cm = ColorModel.getRGBdefault();
+ isRGB = true;
+ }
+ }
+
+ /**
+ * Force pixels to INT RGB mode
+ */
+ private void forceToRGB(){
+ if (isRGB)
+ return;
+
+ switch(dataType){
+ case DATA_TYPE_BYTE:
+ iData = new int[width * height];
+ for(int i = 0; i < iData.length; i++){
+ iData[i] = cm.getRGB(bData[i] & 0xff);
+ }
+ dataType = DATA_TYPE_INT;
+ bData = null;
+ break;
+
+ case DATA_TYPE_INT:
+ int buff[] = new int[width * height];
+ for(int i = 0; i < iData.length; i++){
+ buff[i] = cm.getRGB(iData[i]);
+ }
+ iData = buff;
+ break;
+ }
+ offset = 0;
+ scanline = width;
+ cm = ColorModel.getRGBdefault();
+ isRGB = true;
+ }
+
+}
diff --git a/awt/java/awt/image/PixelInterleavedSampleModel.java b/awt/java/awt/image/PixelInterleavedSampleModel.java
new file mode 100644
index 0000000..e41473e
--- /dev/null
+++ b/awt/java/awt/image/PixelInterleavedSampleModel.java
@@ -0,0 +1,124 @@
+/*
+ * 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 org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The PixelInterleavedSampleModel class represents image data
+ * as represented as interleaved pixels and for which each sample of
+ * a pixel takes one data element of the DataBuffer.
+ */
+public class PixelInterleavedSampleModel extends ComponentSampleModel {
+
+ /**
+ * Instantiates a new PixelInterleavedSampleModel with the
+ * specified parameters.
+ *
+ * @param dataType the data type of the samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param pixelStride the pixel stride of the image data.
+ * @param scanlineStride the scanline stride of the of the image data.
+ * @param bandOffsets the array of the band offsets.
+ */
+ public PixelInterleavedSampleModel(int dataType, int w, int h,
+ int pixelStride, int scanlineStride, int bandOffsets[]) {
+
+ super(dataType, w, h, pixelStride, scanlineStride, bandOffsets);
+
+ int maxOffset = bandOffsets[0];
+ int minOffset = bandOffsets[0];
+ for (int i = 1; i < bandOffsets.length; i++) {
+ if (bandOffsets[i] > maxOffset) {
+ maxOffset = bandOffsets[i];
+ }
+ if (bandOffsets[i] < minOffset) {
+ minOffset = bandOffsets[i];
+ }
+ }
+
+ maxOffset -= minOffset;
+
+ if (maxOffset > scanlineStride) {
+ // awt.241=Any offset between bands is greater than the Scanline stride
+ throw new IllegalArgumentException(Messages.getString("awt.241")); //$NON-NLS-1$
+ }
+
+ if (maxOffset > pixelStride) {
+ // awt.242=Pixel stride is less than any offset between bands
+ throw new IllegalArgumentException(Messages.getString("awt.242")); //$NON-NLS-1$
+ }
+
+ if (pixelStride * w > scanlineStride) {
+ // awt.243=Product of Pixel stride and w is greater than Scanline stride
+ throw new IllegalArgumentException(Messages.getString("awt.243")); //$NON-NLS-1$
+ }
+
+ }
+
+ @Override
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ int newOffsets[] = new int[bands.length];
+ for (int i = 0; i < bands.length; i++) {
+ newOffsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new PixelInterleavedSampleModel(dataType, width, height,
+ pixelStride, scanlineStride, newOffsets);
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ int newOffsets[];
+ int minOffset = bandOffsets[0];
+
+ for (int i = 1; i < numBands; i++) {
+ if (bandOffsets[i] < minOffset) {
+ minOffset = bandOffsets[i];
+ }
+ }
+
+ if (minOffset > 0) {
+ newOffsets = new int[numBands];
+ for (int i = 0; i < numBands; i++) {
+ newOffsets[i] = bandOffsets[i] - minOffset;
+ }
+ } else {
+ newOffsets = bandOffsets;
+ }
+
+ return new PixelInterleavedSampleModel(dataType, w, h, pixelStride,
+ pixelStride * w, newOffsets);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ int tmp = hash >>> 8;
+ hash <<= 8;
+ hash |= tmp;
+
+ return hash ^ 0x66;
+ }
+
+}
+
diff --git a/awt/java/awt/image/RGBImageFilter.java b/awt/java/awt/image/RGBImageFilter.java
new file mode 100644
index 0000000..9a76997
--- /dev/null
+++ b/awt/java/awt/image/RGBImageFilter.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+
+/**
+ * The RGBImageFilter class represents a filter which modifies
+ * pixels of an image in the default RGB ColorModel.
+ */
+public abstract class RGBImageFilter extends ImageFilter {
+
+ /**
+ * The origmodel is the ColorModel to be replaced by newmodel
+ * when substituteColorModel is called.
+ */
+ protected ColorModel origmodel;
+
+ /**
+ * The newmodel is the ColorModel with which to replace origmodel
+ * when substituteColorModel is called.
+ */
+ protected ColorModel newmodel;
+
+ /**
+ * The canFilterIndexColorModel indicates if it is
+ * acceptable to apply the color filtering of the filterRGB
+ * method to the color table entries of an IndexColorModel
+ * object.
+ * */
+ protected boolean canFilterIndexColorModel;
+
+ /**
+ * Instantiates a new RGBImageFilter.
+ */
+ public RGBImageFilter() {}
+
+ /**
+ * Filters an IndexColorModel object by calling filterRGB function for
+ * each entry of IndexColorModel.
+ *
+ * @param icm the IndexColorModel to be filtered.
+ *
+ * @return the IndexColorModel.
+ */
+ public IndexColorModel filterIndexColorModel(IndexColorModel icm) {
+ int transferType = icm.getTransferType();
+ int bits = icm.getPixelSize();
+ int mapSize = icm.getMapSize();
+ int colorMap[] = new int[mapSize];
+ int filteredColorMap[] = new int[mapSize];
+ icm.getRGBs(colorMap);
+ int trans = -1;
+ boolean hasAlpha = false;
+ for(int i = 0; i < mapSize; i++){
+ filteredColorMap[i] = filterRGB(-1, -1, colorMap[i]);
+ int alpha = filteredColorMap[i] >>> 24;
+ if(alpha != 0xff){
+ if(!hasAlpha) {
+ hasAlpha = true;
+ }
+ if(alpha == 0 && trans < 0) {
+ trans = i;
+ }
+ }
+ }
+
+ return new IndexColorModel(bits, mapSize, filteredColorMap, 0,
+ hasAlpha, trans, transferType);
+ }
+
+ /**
+ * Replaces the original color model and the new one.
+ *
+ * @param oldcm the old ColorModel.
+ * @param newcm the new ColorModel.
+ */
+ public void substituteColorModel(ColorModel oldcm, ColorModel newcm) {
+ origmodel = oldcm;
+ newmodel = newcm;
+ }
+
+ @Override
+ public void setColorModel(ColorModel model) {
+ if(model instanceof IndexColorModel &&
+ canFilterIndexColorModel){
+ IndexColorModel icm = (IndexColorModel) model;
+ ColorModel filteredModel = filterIndexColorModel(icm);
+ substituteColorModel(model, filteredModel);
+ consumer.setColorModel(filteredModel);
+ }else{
+ consumer.setColorModel(ColorModel.getRGBdefault());
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize) {
+
+ if(model == null || model == origmodel){
+ consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
+ }else{
+ int rgbPixels[] = new int[w];
+ for(int sy = y, pixelsOff = off; sy < y + h;
+ sy++, pixelsOff += scansize){
+
+ for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+ rgbPixels[idx] = model.getRGB(pixels[pixelsOff + idx]);
+ }
+ filterRGBPixels(x, sy, w, 1, rgbPixels, 0, w);
+ }
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize) {
+
+ if(model == null || model == origmodel){
+ consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
+ }else{
+ int rgbPixels[] = new int[w];
+ for(int sy = y, pixelsOff = off; sy < y + h;
+ sy++, pixelsOff += scansize){
+
+ for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+ rgbPixels[idx] =
+ model.getRGB(pixels[pixelsOff + idx] & 0xff);
+ }
+ filterRGBPixels(x, sy, w, 1, rgbPixels, 0, w);
+ }
+ }
+ }
+
+ /**
+ * Filters a region of pixels in the default RGB ColorModel
+ * by calling the filterRGB method for them.
+ *
+ * @param x the X coordinate of region.
+ * @param y the Y coordinate of region.
+ * @param w the width ofregion.
+ * @param h the height of region.
+ * @param pixels the pixels array.
+ * @param off the offset of array.
+ * @param scansize the distance between rows of pixels in the array.
+ */
+ public void filterRGBPixels(int x, int y, int w, int h,
+ int[] pixels, int off, int scansize) {
+
+ for(int sy = y, lineOff = off; sy < y + h; sy++, lineOff += scansize){
+ for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+ pixels[lineOff + idx] =
+ filterRGB(sx, sy, pixels[lineOff + idx]);
+ }
+ }
+ consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(),
+ pixels, off, scansize);
+ }
+
+ /**
+ * Coverts a single input pixel in the default RGB ColorModel
+ * to a single output pixel.
+ *
+ * @param x the X pixel's coordinate.
+ * @param y the Y pixel's coordinate.
+ * @param rgb a pixel in the default RGB color model.
+ *
+ * @return a filtered pixel in the default RGB color model.
+ */
+ public abstract int filterRGB(int x, int y, int rgb);
+
+}
+
diff --git a/awt/java/awt/image/Raster.java b/awt/java/awt/image/Raster.java
new file mode 100644
index 0000000..4b2426e
--- /dev/null
+++ b/awt/java/awt/image/Raster.java
@@ -0,0 +1,1412 @@
+/*
+ * 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.Point;
+import java.awt.Rectangle;
+
+import org.apache.harmony.awt.gl.image.OrdinaryWritableRaster;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Raster class represents a rectangular area of pixels.
+ * This class is defined by DataBuffer and SampleModel objects.
+ * The DataBuffer object stores sample values and DSampleModel defines
+ * the location of sample in this DataBuffer.
+ */
+public class Raster {
+
+ /** The DataBuffer of this Raster. */
+ protected DataBuffer dataBuffer;
+
+ /** The height of this Raster. */
+ protected int height;
+
+ /** The X coordinate of the upper left pixel in this Raster. */
+ protected int minX;
+
+ /** The Y coordinate of the upper left pixel in this Raster. */
+ protected int minY;
+
+ /** The number of bands in this Raster. */
+ protected int numBands;
+
+ /** The number of data elements. */
+ protected int numDataElements;
+
+ /** The parent of this Raster. */
+ protected Raster parent;
+
+ /** The SampleModel of this Raster. */
+ protected SampleModel sampleModel;
+
+ /**
+ * The X translation from the coordinate space of the
+ * SampleModel of this Raster.
+ */
+ protected int sampleModelTranslateX;
+
+ /**
+ * The Y translation from the coordinate space of the
+ * SampleModel of this Raster.
+ */
+ protected int sampleModelTranslateY;
+
+ /** The width of this Raster. */
+ protected int width;
+
+ /**
+ * Creates a Raster object with a BandedSampleModel and the specified
+ * DataBuffer. The number of bands is defined by the length of bandOffsets
+ * or bankIndices arrays.
+ *
+ * @param dataBuffer the specified DataBuffer.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bankIndices the bank indices of bands.
+ * @param bandOffsets the band offsets of bands.
+ * @param location the location which defines the upper left corner
+ * of Raster.
+ *
+ * @return the WritableRaster object.
+ */
+ public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int bankIndices[],
+ int bandOffsets[], Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bankIndices == null || bandOffsets == null) {
+ // awt.277=bankIndices or bandOffsets is null
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.277")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer == null) {
+ // awt.278=dataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+ }
+
+ int dataType = dataBuffer.getDataType();
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ BandedSampleModel sampleModel = new BandedSampleModel(dataType, w, h,
+ scanlineStride, bankIndices, bandOffsets);
+
+ return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+ }
+
+ /**
+ * Creates a Raster object with a BandedSampleModel and the specified
+ * data type. The Data type can be one of the following values:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ *
+ * @param dataType the data type of the samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param bankIndices the bank indices of bands.
+ * @param bandOffsets the band offsets of bands.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster object.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int scanlineStride, int bankIndices[], int bandOffsets[],
+ Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bankIndices == null || bandOffsets == null) {
+ // awt.277=bankIndices or bandOffsets is null
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.277")); //$NON-NLS-1$
+ }
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ int maxOffset = bandOffsets[0];
+ int maxBank = bankIndices[0];
+
+ for (int i = 0; i < bankIndices.length; i++) {
+ if (bandOffsets[i] > maxOffset) {
+ maxOffset = bandOffsets[i];
+ }
+ if (bankIndices[i] > maxBank) {
+ maxBank = bankIndices[i];
+ }
+ }
+
+ int numBanks = maxBank + 1;
+ int dataSize = scanlineStride * (h - 1) + w + maxOffset;
+
+ DataBuffer data = null;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(dataSize, numBanks);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(dataSize, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(dataSize, numBanks);
+ break;
+ }
+ return createBandedRaster(data, w, h, scanlineStride, bankIndices,
+ bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster object with a BandedSampleModel and the specified
+ * data type. The Data type can be one of the following values:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ *
+ * @param dataType the data type of the samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bands the number of bands.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster object.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int bands, Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bands < 1) {
+ // awt.279=bands is less than 1
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.279")); //$NON-NLS-1$
+ }
+
+ int bandOffsets[] = new int[bands];
+ int bankIndices[] = new int[bands];
+
+ for (int i = 0; i < bands; i++) {
+ bandOffsets[i] = 0;
+ bankIndices[i] = i;
+ }
+ return createBandedRaster(dataType, w, h, w, bankIndices, bandOffsets,
+ location);
+ }
+
+ /**
+ * Creates a Raster object with a PixelInterleavedSampleModel
+ * and the specified DataBuffer.
+ *
+ * @param dataBuffer the DataBuffer.
+ * @param w the width of image data.
+ * @param h the height of image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param pixelStride the pixel stride of image data.
+ * @param bandOffsets the band offsets of bands.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster object.
+ */
+ public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int pixelStride,
+ int bandOffsets[], Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer == null) {
+ // awt.278=dataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+ }
+
+ int dataType = dataBuffer.getDataType();
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer.getNumBanks() > 1) {
+ // awt.27A=dataBuffer has more than one bank
+ throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+ }
+
+ if (bandOffsets == null) {
+ // awt.27B=bandOffsets is null
+ throw new NullPointerException(Messages.getString("awt.27B")); //$NON-NLS-1$
+ }
+
+ PixelInterleavedSampleModel sampleModel =
+ new PixelInterleavedSampleModel(dataType, w, h,
+ pixelStride, scanlineStride, bandOffsets);
+
+ return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+
+ }
+
+ /**
+ * Creates a Raster object with a PixelInterleavedSampleModel
+ * and the specified data type. The Data type can be one of the
+ * following values:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ *
+ * @param dataType the data type of the samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of image data.
+ * @param h the height of image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param pixelStride the pixel stride of image data.
+ * @param bandOffsets the band offsets of bands.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster object.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType, int w,
+ int h, int scanlineStride, int pixelStride, int bandOffsets[],
+ Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ if (bandOffsets == null) {
+ // awt.27B=bandOffsets is null
+ throw new NullPointerException(Messages.getString("awt.27B")); //$NON-NLS-1$
+ }
+
+ int minOffset = bandOffsets[0];
+ for (int i = 1; i < bandOffsets.length; i++) {
+ if (bandOffsets[i] < minOffset) {
+ minOffset = bandOffsets[i];
+ }
+ }
+ int size = (h - 1) * scanlineStride + w * pixelStride + minOffset;
+ DataBuffer data = null;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(size);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(size);
+ break;
+ }
+
+ return createInterleavedRaster(data, w, h, scanlineStride, pixelStride,
+ bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster object with a PixelInterleavedSampleModel
+ * and the specified data type. The Data type can be one of the
+ * following values:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ *
+ * @param dataType the data type of samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of image data.
+ * @param h the height of image data.
+ * @param bands the number of bands.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType, int w,
+ int h, int bands, Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ int bandOffsets[] = new int[bands];
+ for (int i = 0; i < bands; i++) {
+ bandOffsets[i] = i;
+ }
+
+ return createInterleavedRaster(dataType, w, h, w * bands, bands,
+ bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster object with a SinglePixelPackedSampleModel
+ * and the specified DataBuffer.
+ *
+ * @param dataBuffer the DataBuffer.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param scanlineStride the scanline stride of the image data.
+ * @param bandMasks the band masks.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int bandMasks[], Point location) {
+ if (dataBuffer == null) {
+ // awt.278=dataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+ }
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bandMasks == null) {
+ // awt.27C=bandMasks is null
+ throw new RasterFormatException(Messages.getString("awt.27C")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer.getNumBanks() > 1) {
+ // awt.27A=dataBuffer has more than one bank
+ throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+ }
+
+ int dataType = dataBuffer.getDataType();
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ SinglePixelPackedSampleModel sampleModel =
+ new SinglePixelPackedSampleModel(dataType, w, h,
+ scanlineStride, bandMasks);
+
+ return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+ }
+
+ /**
+ * Creates a Raster object with a MultiPixelPackedSampleModel
+ * and the specified DataBuffer.
+ *
+ * @param dataBuffer the DataBuffer.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bitsPerPixel the number of bits per pixel.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int bitsPerPixel, Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer == null) {
+ // awt.278=dataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+ }
+
+ if (dataBuffer.getNumBanks() > 1) {
+ // awt.27A=dataBuffer has more than one bank
+ throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+ }
+
+ int dataType = dataBuffer.getDataType();
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ MultiPixelPackedSampleModel sampleModel =
+ new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel);
+
+ return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+
+ }
+
+ /**
+ * Creates a Raster object with a MultiPixelPackedSampleModel
+ * and the specified DataBuffer.
+ *
+ * @param dataType the data type of samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bands the number of bands.
+ * @param bitsPerBand the number of bits per band.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createPackedRaster(int dataType, int w, int h,
+ int bands, int bitsPerBand, Point location) {
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bands < 1 || bitsPerBand < 1) {
+ // awt.27D=bitsPerBand or bands is not greater than zero
+ throw new IllegalArgumentException(Messages.getString("awt.27D")); //$NON-NLS-1$
+ }
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ if (bitsPerBand * bands > DataBuffer.getDataTypeSize(dataType)) {
+ // awt.27E=The product of bitsPerBand and bands is greater than the number of bits held by dataType
+ throw new IllegalArgumentException(Messages.getString("awt.27E")); //$NON-NLS-1$
+ }
+
+ if (bands > 1) {
+
+ int bandMasks[] = new int[bands];
+ int mask = (1 << bitsPerBand) - 1;
+
+ for (int i = 0; i < bands; i++) {
+ bandMasks[i] = mask << (bitsPerBand * (bands - 1 - i));
+ }
+
+ return createPackedRaster(dataType, w, h, bandMasks, location);
+ }
+ DataBuffer data = null;
+ int size = ((bitsPerBand * w +
+ DataBuffer.getDataTypeSize(dataType) - 1) /
+ DataBuffer.getDataTypeSize(dataType)) * h;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(size);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(size);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(size);
+ break;
+ }
+ return createPackedRaster(data, w, h, bitsPerBand, location);
+ }
+
+ /**
+ * Creates a Raster object with a SinglePixelPackedSampleModel
+ * and the specified DataBuffer.
+ *
+ * @param dataType the data type of samples:
+ * TYPE_BYTE, TYPE_USHORT, or TYPE_INT.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bandMasks the band masks.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createPackedRaster(int dataType, int w, int h,
+ int bandMasks[], Point location) {
+
+ if (dataType != DataBuffer.TYPE_BYTE
+ && dataType != DataBuffer.TYPE_USHORT
+ && dataType != DataBuffer.TYPE_INT) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ if ((long) location.x + w > Integer.MAX_VALUE
+ || (long) location.y + h > Integer.MAX_VALUE) {
+ // awt.276=location.x + w or location.y + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+ }
+
+ if (bandMasks == null) {
+ // awt.27C=bandMasks is null
+ throw new NullPointerException(Messages.getString("awt.27C")); //$NON-NLS-1$
+ }
+
+ DataBuffer data = null;
+
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(w * h);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(w * h);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(w * h);
+ break;
+ }
+
+ return createPackedRaster(data, w, h, w, bandMasks, location);
+ }
+
+ /**
+ * Creates a Raster object with the specified DataBuffer and SampleModel.
+ *
+ * @param sm the specified SampleModel.
+ * @param db the specified DataBuffer.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the Raster.
+ */
+ public static Raster createRaster(SampleModel sm, DataBuffer db,
+ Point location) {
+
+ if (sm == null || db == null) {
+ // awt.27F=SampleModel or DataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.27F")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ return new Raster(sm, db, location);
+ }
+
+ /**
+ * Creates a WritableRaster with the specified SampleModel and DataBuffer.
+ *
+ * @param sm the specified SampleModel.
+ * @param db the specified DataBuffer.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ DataBuffer db, Point location) {
+
+ if (sm == null || db == null) {
+ // awt.27F=SampleModel or DataBuffer is null
+ throw new NullPointerException(Messages.getString("awt.27F")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ return new OrdinaryWritableRaster(sm, db, location);
+ }
+
+ /**
+ * Creates a WritableRaster with the specified SampleModel.
+ *
+ * @param sm the specified SampleModel.
+ * @param location the location which defines the upper left corner
+ * of the Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ Point location) {
+
+ if (sm == null) {
+ // awt.280=SampleModel is null
+ throw new NullPointerException(Messages.getString("awt.280")); //$NON-NLS-1$
+ }
+
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+
+ return createWritableRaster(sm, sm.createDataBuffer(), location);
+ }
+
+ /**
+ * Instantiates a new Raster object with the specified SampleModel and
+ * DataBuffer.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param dataBuffer the specified DataBuffer.
+ * @param origin the specified origin.
+ */
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin) {
+
+ this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
+ }
+
+ /**
+ * Instantiates a new Raster object with the specified SampleModel,
+ * DataBuffer, rectangular region and parent Raster.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param dataBuffer the specified DataBuffer.
+ * @param aRegion the a rectangular region which defines the new image bounds.
+ * @param sampleModelTranslate this point defines the translation point
+ * from the SampleModel coordinates to the new Raster coordinates.
+ * @param parent the parent of this Raster.
+ */
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Rectangle aRegion, Point sampleModelTranslate, Raster parent) {
+
+ if (sampleModel == null || dataBuffer == null || aRegion == null
+ || sampleModelTranslate == null) {
+ // awt.281=sampleModel, dataBuffer, aRegion or sampleModelTranslate is null
+ throw new NullPointerException(Messages.getString("awt.281")); //$NON-NLS-1$
+ }
+
+ if (aRegion.width <= 0 || aRegion.height <= 0) {
+ // awt.282=aRegion has width or height less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.282")); //$NON-NLS-1$
+ }
+
+ if ((long) aRegion.x + (long) aRegion.width > Integer.MAX_VALUE) {
+ // awt.283=Overflow X coordinate of Raster
+ throw new RasterFormatException(Messages.getString("awt.283")); //$NON-NLS-1$
+ }
+
+ if ((long) aRegion.y + (long) aRegion.height > Integer.MAX_VALUE) {
+ // awt.284=Overflow Y coordinate of Raster
+ throw new RasterFormatException(Messages.getString("awt.284")); //$NON-NLS-1$
+ }
+
+ if (sampleModel instanceof ComponentSampleModel) {
+ validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+ ((ComponentSampleModel) sampleModel).getScanlineStride());
+ } else if (sampleModel instanceof MultiPixelPackedSampleModel) {
+ validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+ ((MultiPixelPackedSampleModel) sampleModel)
+ .getScanlineStride());
+ } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
+ validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+ ((SinglePixelPackedSampleModel) sampleModel)
+ .getScanlineStride());
+ }
+
+ this.sampleModel = sampleModel;
+ this.dataBuffer = dataBuffer;
+ this.minX = aRegion.x;
+ this.minY = aRegion.y;
+ this.width = aRegion.width;
+ this.height = aRegion.height;
+ this.sampleModelTranslateX = sampleModelTranslate.x;
+ this.sampleModelTranslateY = sampleModelTranslate.y;
+ this.parent = parent;
+ this.numBands = sampleModel.getNumBands();
+ this.numDataElements = sampleModel.getNumDataElements();
+
+ }
+
+ /**
+ * Instantiates a new Raster with the specified SampleModel.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param origin the origin.
+ */
+ protected Raster(SampleModel sampleModel, Point origin) {
+ this(sampleModel, sampleModel.createDataBuffer(), new Rectangle(
+ origin.x, origin.y, sampleModel.getWidth(), sampleModel
+ .getHeight()), origin, null);
+ }
+
+ /**
+ * Creates the child of this Raster by sharing the specified rectangular
+ * area in this Raste. The parentX, parentY, width
+ * and height parameters specify the rectangular area to be shared.
+ *
+ * @param parentX the X coordinate of the upper left corner of this Raster.
+ * @param parentY the Y coordinate of the upper left corner of this Raster.
+ * @param width the width of the child area.
+ * @param height the height of the child area.
+ * @param childMinX the X coordinate of child area mapped to the parentX
+ * coordinate.
+ * @param childMinY the Y coordinate of child area mapped to the parentY
+ * coordinate.
+ * @param bandList the array of band indicies.
+ *
+ * @return the Raster.
+ */
+ public Raster createChild(int parentX, int parentY, int width, int height,
+ int childMinX, int childMinY, int bandList[]) {
+ if (width <= 0 || height <= 0) {
+ // awt.285=Width or Height of child Raster is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.285")); //$NON-NLS-1$
+ }
+
+ if (parentX < this.minX || parentX + width > this.minX + this.width) {
+ // awt.286=parentX disposes outside Raster
+ throw new RasterFormatException(Messages.getString("awt.286")); //$NON-NLS-1$
+ }
+
+ if (parentY < this.minY || parentY + height > this.minY + this.height) {
+ // awt.287=parentY disposes outside Raster
+ throw new RasterFormatException(Messages.getString("awt.287")); //$NON-NLS-1$
+ }
+
+ if ((long) parentX + width > Integer.MAX_VALUE) {
+ // awt.288=parentX + width results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.288")); //$NON-NLS-1$
+ }
+
+ if ((long) parentY + height > Integer.MAX_VALUE) {
+ // awt.289=parentY + height results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.289")); //$NON-NLS-1$
+ }
+
+ if ((long) childMinX + width > Integer.MAX_VALUE) {
+ // awt.28A=childMinX + width results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.28A")); //$NON-NLS-1$
+ }
+
+ if ((long) childMinY + height > Integer.MAX_VALUE) {
+ // awt.28B=childMinY + height results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.28B")); //$NON-NLS-1$
+ }
+
+ SampleModel childModel;
+
+ if (bandList == null) {
+ childModel = sampleModel;
+ } else {
+ childModel = sampleModel.createSubsetSampleModel(bandList);
+ }
+
+ int childTranslateX = childMinX - parentX;
+ int childTranslateY = childMinY - parentY;
+
+ return new Raster(childModel, dataBuffer, new Rectangle(childMinX,
+ childMinY, width, height), new Point(childTranslateX
+ + sampleModelTranslateX, childTranslateY
+ + sampleModelTranslateY), this);
+ }
+
+ /**
+ * Create a compatible WritableRaster with the same parameters
+ * as this Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createCompatibleWritableRaster() {
+ return new OrdinaryWritableRaster(sampleModel, new Point(0, 0));
+ }
+
+ /**
+ * Create a compatible WritableRaster with the same parameters
+ * as this Raster and the specified size.
+ *
+ * @param w the width of the new WritableRaster.
+ * @param h the height of the new WritableRaster.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createCompatibleWritableRaster(int w, int h) {
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
+
+ return new OrdinaryWritableRaster(sm, new Point(0, 0));
+ }
+
+ /**
+ * Create a compatible WritableRaster with the same parameters
+ * as this Raster and the specified size and location.
+ *
+ * @param x the X coordinate of the new WritableRaster.
+ * @param y the Y coordinate of the new WritableRaster.
+ * @param w the width of the new WritableRaster.
+ * @param h the height of the new WritableRaster.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createCompatibleWritableRaster(int x, int y, int w,
+ int h) {
+
+ WritableRaster raster = createCompatibleWritableRaster(w, h);
+
+ return raster.createWritableChild(0, 0, w, h, x, y, null);
+ }
+
+ /**
+ * Create a compatible WritableRaster with the same parameters
+ * as this Raster and the specified rectangle which determines
+ * new WritableRaster's location and size.
+ *
+ * @param rect the specified Rectangle.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createCompatibleWritableRaster(Rectangle rect) {
+ if (rect == null) {
+ // awt.28C=Rect is null
+ throw new NullPointerException(Messages.getString("awt.28C")); //$NON-NLS-1$
+ }
+
+ return createCompatibleWritableRaster(rect.x, rect.y, rect.width,
+ rect.height);
+ }
+
+ /**
+ * Creates the translated child of this Raster. The New Raster
+ * object is a reference to the this Raster with a
+ * different location.
+ *
+ * @param childMinX the X coordinate of the new Raster.
+ * @param childMinY the Y coordinate of the new Raster.
+ *
+ * @return the Raster.
+ */
+ public Raster createTranslatedChild(int childMinX, int childMinY) {
+ return createChild(minX, minY, width, height, childMinX, childMinY,
+ null);
+ }
+
+ /**
+ * Gets the bounds of this Raster as a rectangle.
+ *
+ * @return the bounds of this Raster.
+ */
+ public Rectangle getBounds() {
+ return new Rectangle(minX, minY, width, height);
+ }
+
+ /**
+ * Gets the DataBuffer associated with this Raster.
+ *
+ * @return the DataBuffer associated with this Raster.
+ */
+ public DataBuffer getDataBuffer() {
+ return dataBuffer;
+ }
+
+ /**
+ * Gets the data elements which represent the pixel data of the specified
+ * rectangle area as a primitive array. The following image data types
+ * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param outData the resulting array.
+ *
+ * @return the data elements of the specified area of this Raster.
+ */
+ public Object getDataElements(int x, int y, int w, int h, Object outData) {
+ return sampleModel.getDataElements(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, outData, dataBuffer);
+ }
+
+ /**
+ * Gets the data elements which represent the specified pixel of
+ * this Raster as a primitive array. The following image data types
+ * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param outData the resulting data.
+ *
+ * @return the data elements of the specified pixel of this Raster.
+ */
+ public Object getDataElements(int x, int y, Object outData) {
+ return sampleModel.getDataElements(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, outData, dataBuffer);
+ }
+
+ /**
+ * Gets the height of this Raster.
+ *
+ * @return the height of this Raster.
+ */
+ public final int getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the minimum X coordinate of this Raster.
+ *
+ * @return the minimum X coordinate of this Raster.
+ */
+ public final int getMinX() {
+ return minX;
+ }
+
+ /**
+ * Gets the minimum Y coordinate of this Raster.
+ *
+ * @return the minimum Y coordinate of this Raster.
+ */
+ public final int getMinY() {
+ return minY;
+ }
+
+ /**
+ * Gets the number of bands in this Raster.
+ *
+ * @return the number of bands in this Raster.
+ */
+ public final int getNumBands() {
+ return numBands;
+ }
+
+ /**
+ * Gets the number of data elements for one pixel.
+ *
+ * @return the number of data elements for one pixel.
+ */
+ public final int getNumDataElements() {
+ return numDataElements;
+ }
+
+ /**
+ * Gets the parent Raster for this Raster object.
+ *
+ * @return the parent Raster for this Raster object.
+ */
+ public Raster getParent() {
+ return parent;
+ }
+
+ /**
+ * Gets a double array of samples for the specified pixel in this Raster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param dArray the double array where result array will be stored.
+ *
+ * @return the double array of samples for the specified pixel in
+ * this Raster.
+ */
+ public double[] getPixel(int x, int y, double dArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, dArray, dataBuffer);
+ }
+
+ /**
+ * Gets a float array of samples for the specified pixel in this Raster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param fArray the float array where the result array will be stored.
+ *
+ * @return the float array of samples for the specified pixel in
+ * this Raster.
+ */
+ public float[] getPixel(int x, int y, float fArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, fArray, dataBuffer);
+ }
+
+ /**
+ * Gets an int array of samples for the specified pixel in this Raster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param iArray the int array where the result array will be stored.
+ *
+ * @return the int array of samples for the specified pixel in
+ * this Raster.
+ */
+ public int[] getPixel(int x, int y, int iArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, iArray, dataBuffer);
+ }
+
+ /**
+ * Gets an double array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param dArray the resulting array.
+ *
+ * @return the double array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ */
+ public double[] getPixels(int x, int y, int w, int h, double dArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, dArray, dataBuffer);
+ }
+
+ /**
+ * Gets an float array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param fArray the resulting array.
+ *
+ * @return the float array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ */
+ public float[] getPixels(int x, int y, int w, int h, float fArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, fArray, dataBuffer);
+ }
+
+ /**
+ * Gets an int array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of pixel's the area of pixels.
+ * @param h the height of pixel's the area of pixels.
+ * @param iArray the resulting array.
+ *
+ * @return the int array of samples for the specified rectangular
+ * area of pixels in this Raster.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int iArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, iArray, dataBuffer);
+ }
+
+ /**
+ * Gets the sample for the specified band of the specified
+ * pixel as an int.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the band.
+ *
+ * @return the sample for the specified band of the specified
+ * pixel as an int.
+ */
+ public int getSample(int x, int y, int b) {
+ return sampleModel.getSample(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Gets the sample for the specified band of the specified
+ * pixel as a double.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the band.
+ *
+ * @return the sample for the specified band of the specified
+ * pixel as a double.
+ */
+ public double getSampleDouble(int x, int y, int b) {
+ return sampleModel.getSampleDouble(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Gets the sample for the specified band of the specified
+ * pixel as a float.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the band.
+ *
+ * @return the sample for the specified band of the specified
+ * pixel as a float.
+ */
+ public float getSampleFloat(int x, int y, int b) {
+ return sampleModel.getSampleFloat(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Gets the SampleModel associated with this Raster.
+ *
+ * @return the SampleModel associated with this Raster.
+ */
+ public SampleModel getSampleModel() {
+ return sampleModel;
+ }
+
+ /**
+ * Gets the translation of the X coordinate from the SampleModel
+ * coordinate system to the Rasters's coordinate system.
+ *
+ * @return the value of the translation of the X coordinate from
+ * the SampleModel coordinate system to the Rasters's
+ * coordinate system.
+ */
+ public final int getSampleModelTranslateX() {
+ return sampleModelTranslateX;
+ }
+
+ /**
+ * Gets the translation of the Y coordinate from the SampleModel
+ * coordinate system to the Rasters's coordinate system.
+ *
+ * @return the value of the translation of the Y coordinate from
+ * the SampleModel coordinate system to the Rasters's
+ * coordinate system.
+
+ */
+ public final int getSampleModelTranslateY() {
+ return sampleModelTranslateY;
+ }
+
+ /**
+ * Gets the double array of samples for the specified band
+ * of the specified rectangular area of pixels in this Raster
+ * as a double array.
+ *
+ * @param x the X coordinate of the rectangular area of pixels.
+ * @param y the Y coordinate of the rectangular area of pixels.
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param b the band.
+ * @param dArray the resulting double array.
+ *
+ * @return the double array of samples for the specified band
+ * of the specified rectangular area of pixels.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double dArray[]) {
+
+ return sampleModel.getSamples(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
+ }
+
+ /**
+ * Gets the float array of samples for the specified band
+ * of the specified rectangular area of pixels in this Raster
+ * as a float array.
+ *
+ * @param x the X coordinate of the rectangular area of pixels.
+ * @param y the Y coordinate of the rectangular area of pixels.
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param b the band.
+ * @param fArray the resulting float array.
+ *
+ * @return the float array of samples for the specified band
+ * of the specified rectangular area of pixels.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b, float fArray[]) {
+
+ return sampleModel.getSamples(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
+ }
+
+ /**
+ * Gets the int array of samples for the specified band
+ * of the specified rectangular area of pixels in this Raster
+ * as a int array.
+ *
+ * @param x the X coordinate of the rectangular area of pixels.
+ * @param y the Y coordinate of the rectangular area of pixels.
+ * @param w the width of the rectangular area of pixels.
+ * @param h the height of the rectangular area of pixels.
+ * @param b the band.
+ * @param iArray the resulting int array.
+ *
+ * @return the int array of samples for the specified band
+ * of the specified rectangular area of pixels.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b, int iArray[]) {
+ return sampleModel.getSamples(x - sampleModelTranslateX, y
+ - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
+ }
+
+ /**
+ * Gets the transfer type for pixels of this Raster.
+ * @see SampleModel#getTransferType()
+ *
+ * @return the transfer type for pixels of this Raster.
+ */
+ public final int getTransferType() {
+ return sampleModel.getTransferType();
+ }
+
+ /**
+ * Gets the width of this Raster.
+ *
+ * @return the width of this Raster.
+ */
+ public final int getWidth() {
+ return width;
+ }
+
+ /**
+ * Validate data buffer.
+ *
+ * @param dataBuffer the data buffer
+ * @param w the w
+ * @param h the h
+ * @param scanlineStride the scanline stride
+ */
+ private static void validateDataBuffer(final DataBuffer dataBuffer, final int w,
+ final int h, final int scanlineStride) {
+ if (dataBuffer.getSize() < (scanlineStride * (h - 1) + w - 1)) {
+ // awt.298=dataBuffer is too small
+ throw new RasterFormatException(Messages.getString("awt.298")); //$NON-NLS-1$
+ }
+ }
+}
+
+
diff --git a/awt/java/awt/image/RasterFormatException.java b/awt/java/awt/image/RasterFormatException.java
new file mode 100644
index 0000000..8577dad
--- /dev/null
+++ b/awt/java/awt/image/RasterFormatException.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+
+/**
+ * The RasterFormatException class represents the exception
+ * that is thrown when there's an invalid layout
+ * in the Raster.
+ */
+public class RasterFormatException extends RuntimeException {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 96598996116164315L;
+
+ /**
+ * Instantiates a new RasterFormatException with the
+ * specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public RasterFormatException(String s) {
+ super(s);
+ }
+
+}
+
diff --git a/awt/java/awt/image/RasterOp.java b/awt/java/awt/image/RasterOp.java
new file mode 100644
index 0000000..e8933ee
--- /dev/null
+++ b/awt/java/awt/image/RasterOp.java
@@ -0,0 +1,83 @@
+/*
+ * 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 Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The RasterOp interface provides methods for performing transformations
+ * from source data to destination data for Raster objects. The source and
+ * destination objects should contain the appropriate number of bands for
+ * the particular classes which implement this interface.
+ */
+public interface RasterOp {
+
+ /**
+ * Creates a destination WritableRaster with the specified Raster;
+ * this destination image data is empty and has the correct size
+ * and number of bands.
+ *
+ * @param src the source Raster.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src);
+
+ /**
+ * Performs a filter operation on the source Raster and stores the resulting
+ * image data to the destination WritableRaster.
+ *
+ * @param src the source Raster.
+ * @param dst the destination WritableRaster, where the result is stored.
+ *
+ * @return the filtered WritableRaster.
+ */
+ public WritableRaster filter(Raster src, WritableRaster dst);
+
+ /**
+ * Gets the bounds of the filtered Raster.
+ *
+ * @param src the source Raster to be filtered.
+ *
+ * @return the rectangle bounds of the filtered Raster.
+ */
+ public Rectangle2D getBounds2D(Raster src);
+
+ /**
+ * Gets the point of the destination image which corresponds
+ * to the specified point in the source raster.
+ *
+ * @param srcPoint the point of the source raster.
+ * @param dstPoint the point where the result will be stored.
+ *
+ * @return the destination point.
+ */
+ public Point2D getPoint2D(Point2D srcPoint, Point2D dstPoint);
+
+ /**
+ * Gets the RenderingHints of the RasterOp.
+ *
+ * @return the RenderingHints of the RasterOp.
+ */
+ public RenderingHints getRenderingHints();
+}
diff --git a/awt/java/awt/image/RenderedImage.java b/awt/java/awt/image/RenderedImage.java
new file mode 100644
index 0000000..db3a4c8
--- /dev/null
+++ b/awt/java/awt/image/RenderedImage.java
@@ -0,0 +1,198 @@
+/*
+ * 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.Rectangle;
+import java.util.Vector;
+
+/**
+ * The RenderedImage interface should be implemented by all objects which
+ * contains image data. The image data is represented as a single tile or
+ * an array of tiles.
+ */
+public interface RenderedImage {
+
+ /**
+ * Gets the property with the specified name from the property set
+ * of this RenderedImage.
+ *
+ * @param name the property's name.
+ *
+ * @return the property value corresponded to this property's name.
+ */
+ public Object getProperty(String name);
+
+ /**
+ * Copies the region of this RenderedImage to the specified
+ * WritableRaster. The bounds of the region are the bounds of the
+ * WritableRaster.
+ *
+ * @param raster the WritableRaster.
+ *
+ * @return the created WritableRaster.
+ */
+ public WritableRaster copyData(WritableRaster raster);
+
+ /**
+ * Gets the image data of the image's region as one tile.
+ *
+ * @param rect the rectangular region of RenderedImage.
+ *
+ * @return the image data of the image's region as one tile.
+ */
+ public Raster getData(Rectangle rect);
+
+ /**
+ * Gets all RenderedImage objects which are the source of this
+ * RenderedImage object.
+ *
+ * @return a Vector of RenderedImage objects which are the source
+ * of this RenderedImage object or null, if there is no information
+ * about them.
+ */
+ public Vector<RenderedImage> getSources();
+
+ /**
+ * Gets the set of all property names for this RenderedImage.
+ *
+ * @return the array of all property names for this RenderedImage.
+ */
+ public String[] getPropertyNames();
+
+ /**
+ * Gets the SampleModel of this RenderedImage.
+ *
+ * @return the SampleModel of this RenderedImage.
+ */
+ public SampleModel getSampleModel();
+
+ /**
+ * Gets the tile corresponded to the specified indices in the tile
+ * array.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ *
+ * @return the tile corresponded to the specified indices in the tile
+ * array.
+ */
+ public Raster getTile(int tileX, int tileY);
+
+ /**
+ * Gets the image data of this image as one tile.
+ *
+ * @return the image data of this image as one tile.
+ */
+ public Raster getData();
+
+ /**
+ * Gets the ColorModel of this RenderedImage.
+ *
+ * @return the ColorModel of this RenderedImage.
+ */
+ public ColorModel getColorModel();
+
+ /**
+ * Gets the width of the RenderedImage.
+ *
+ * @return the width of the RenderedImage.
+ */
+ public int getWidth();
+
+ /**
+ * Gets the tile width.
+ *
+ * @return the tile width in pixels.
+ */
+ public int getTileWidth();
+
+ /**
+ * Gets the tile height.
+ *
+ * @return the tile height in pixels.
+ */
+ public int getTileHeight();
+
+ /**
+ * Gets the Y offset of the tile grid.
+ *
+ * @return the Y offset of the tile grid.
+ */
+ public int getTileGridYOffset();
+
+ /**
+ * Gets the X offset of the tile grid.
+ *
+ * @return the X offset of the tile grid.
+ */
+ public int getTileGridXOffset();
+
+ /**
+ * Gets the number of tiles along Y direction.
+ *
+ * @return the number of tiles along Y direction.
+ */
+ public int getNumYTiles();
+
+ /**
+ * Gets the number of tiles along X direction.
+ *
+ * @return the number of tiles along X direction.
+ */
+ public int getNumXTiles();
+
+ /**
+ * Gets the minimum Y coordinate of this RenderedImage.
+ *
+ * @return the minimum Y coordinate of this RenderedImage.
+ */
+ public int getMinY();
+
+ /**
+ * Gets the minimum X coordinate of this RenderedImage.
+ *
+ * @return the minimum X coordinate of this RenderedImage.
+ */
+ public int getMinX();
+
+ /**
+ * Gets the minimum tile's index along the Y direction.
+ *
+ * @return the minimum tile's index along the Y direction.
+ */
+ public int getMinTileY();
+
+ /**
+ * Gets the minimum tile's index along the X direction.
+ *
+ * @return the minimum tile's index along the X direction.
+ */
+ public int getMinTileX();
+
+ /**
+ * Gets the height of the RenderedImage.
+ *
+ * @return the height of the RenderedImage.
+ */
+ public int getHeight();
+
+}
+
diff --git a/awt/java/awt/image/ReplicateScaleFilter.java b/awt/java/awt/image/ReplicateScaleFilter.java
new file mode 100644
index 0000000..9298125
--- /dev/null
+++ b/awt/java/awt/image/ReplicateScaleFilter.java
@@ -0,0 +1,213 @@
+/*
+ * 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.util.Hashtable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+
+/**
+ * The ReplicateScaleFilter class scales an source image
+ * by replicating rows and columns of pixels to scale up or
+ * omitting rows and columns of pixels to scale down.
+ */
+public class ReplicateScaleFilter extends ImageFilter {
+
+ /** The width of a source image. */
+ protected int srcWidth;
+
+ /** The height of a source image. */
+ protected int srcHeight;
+
+ /** The width of a destination image. */
+ protected int destWidth;
+
+ /** The height of a destination image. */
+ protected int destHeight;
+
+ /** The int array of source rows. */
+ protected int[] srcrows;
+
+ /** The int array of source columns. */
+ protected int[] srccols;
+
+ /**
+ * An Object (byte array with a destination width) provides
+ * a row of pixel data to the ImageConsumer.
+ */
+ protected Object outpixbuf;
+
+ /**
+ * Instantiates a new ReplicateScaleFilter that filters
+ * the image with the specified width and height.
+ *
+ * @param width the width of scaled image.
+ * @param height the height of scaled image.
+ */
+ public ReplicateScaleFilter(int width, int height) {
+ if(width == 0 || height == 0) {
+ // awt.234=Width or Height equals zero
+ throw new IllegalArgumentException(Messages.getString("awt.234")); //$NON-NLS-1$
+ }
+
+ this.destWidth = width;
+ this.destHeight = height;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void setProperties(Hashtable<?, ?> props) {
+ Hashtable<Object, Object> fprops;
+ if(props == null) {
+ fprops = new Hashtable<Object, Object>();
+ } else {
+ fprops = (Hashtable<Object, Object>) props.clone();
+ }
+ String propName = "Rescale Filters"; //$NON-NLS-1$
+ String prop = "destWidth=" + destWidth + "; " + //$NON-NLS-1$ //$NON-NLS-2$
+ "destHeight=" + destHeight; //$NON-NLS-1$
+ Object o = fprops.get(propName);
+ if(o != null){
+ if(o instanceof String){
+ prop = (String)o + "; " + prop; //$NON-NLS-1$
+ }else{
+ prop = o.toString() + "; " + prop; //$NON-NLS-1$
+ }
+ }
+ fprops.put(propName, prop);
+ consumer.setProperties(fprops);
+ }
+
+ // setPixels methods produce pixels according to Java API Spacification
+
+ @Override
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int off, int scansize) {
+
+ if(srccols == null) {
+ initArrays();
+ }
+ int buff[];
+ if(outpixbuf == null || !(outpixbuf instanceof int[])){
+ buff = new int[destWidth];
+ outpixbuf = buff;
+ }else{
+ buff = (int[])outpixbuf;
+ }
+
+ int wa = (srcWidth - 1) >>> 1;
+ int ha = (srcHeight - 1) >>> 1;
+ int dstX = (x * destWidth + wa) / srcWidth;
+ int dstY = (y * destHeight + ha) / srcHeight;
+
+ int sx, sy, dx, dy;
+ dy = dstY;
+ while((dy < destHeight) && ((sy = srcrows[dy]) < y + h)){
+ dx = dstX;
+ int srcOff = off + (sy - y) * scansize;
+ while((dx < destWidth) && ((sx = srccols[dx]) < x + w)){
+ buff[dx] = pixels[srcOff + (sx - x)];
+ dx++;
+ }
+
+ consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff,
+ dstX, destWidth);
+ dy++;
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int off, int scansize) {
+
+ if(srccols == null) {
+ initArrays();
+ }
+ byte buff[];
+ if(outpixbuf == null || !(outpixbuf instanceof byte[])){
+ buff = new byte[destWidth];
+ outpixbuf = buff;
+ }else{
+ buff = (byte[])outpixbuf;
+ }
+
+ int wa = (srcWidth - 1) >>> 1;
+ int ha = (srcHeight - 1) >>> 1;
+ int dstX = (x * destWidth + wa) / srcWidth;
+ int dstY = (y * destHeight + ha) / srcHeight;
+
+ int sx, sy, dx, dy;
+ dy = dstY;
+ while((dy < destHeight) && ((sy = srcrows[dy]) < y + h)){
+ dx = dstX;
+ int srcOff = off + (sy - y) * scansize;
+ while((dx < destWidth) && ((sx = srccols[dx]) < x + w)){
+ buff[dx] = pixels[srcOff + (sx - x)];
+ dx++;
+ }
+
+ consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff,
+ dstX, destWidth);
+ dy++;
+ }
+ }
+
+ @Override
+ public void setDimensions(int w, int h) {
+ srcWidth = w;
+ srcHeight = h;
+
+ if(destWidth < 0 && destHeight < 0){
+ destWidth = srcWidth;
+ destHeight = srcHeight;
+ }else if(destWidth < 0){
+ destWidth = destHeight * srcWidth / srcHeight;
+ }else if(destHeight < 0){
+ destHeight = destWidth * srcHeight / srcWidth;
+ }
+ consumer.setDimensions(destWidth, destHeight);
+ }
+
+ /**
+ * Initialization of srccols and srcrows arrays.
+ */
+ private void initArrays(){
+ if ((destWidth < 0) || (destHeight < 0)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ srccols = new int[destWidth];
+ int ca = srcWidth >>> 1;
+ for(int i = 0; i < destWidth; i++){
+ srccols[i] = (i * srcWidth + ca) / destWidth;
+ }
+
+ srcrows = new int[destHeight];
+ int ra = srcHeight >>> 1;
+ for(int i = 0; i < destHeight; i++){
+ srcrows[i] = (i * srcHeight + ra) / destHeight;
+ }
+ }
+
+}
+
+
diff --git a/awt/java/awt/image/RescaleOp.java b/awt/java/awt/image/RescaleOp.java
new file mode 100644
index 0000000..0e96031
--- /dev/null
+++ b/awt/java/awt/image/RescaleOp.java
@@ -0,0 +1,659 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 6, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.*;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class RescaleOp performs rescaling of the source image data
+ * by multiplying the pixel values with a scale factor
+ * and then adding an offset.
+ */
+public class RescaleOp implements BufferedImageOp, RasterOp {
+
+ /** The scale factors. */
+ private float scaleFactors[];
+
+ /** The offsets. */
+ private float offsets[];
+
+ /** The hints. */
+ private RenderingHints hints;
+
+ static {
+ // TODO
+ //System.loadLibrary("imageops");
+ }
+
+ /**
+ * Instantiates a new RescaleOp object with the specified
+ * scale factors and offsets.
+ *
+ * @param scaleFactors the array of scale factor values.
+ * @param offsets the array of offset values.
+ * @param hints the RenderingHints or null.
+ */
+ public RescaleOp(float[] scaleFactors, float[] offsets, RenderingHints hints) {
+ int numFactors = Math.min(scaleFactors.length, offsets.length);
+
+ this.scaleFactors = new float[numFactors];
+ this.offsets = new float[numFactors];
+
+ System.arraycopy(scaleFactors, 0, this.scaleFactors, 0, numFactors);
+ System.arraycopy(offsets, 0, this.offsets, 0, numFactors);
+
+ this.hints = hints;
+ }
+
+ /**
+ * Instantiates a new RescaleOp object with the specified
+ * scale factor and offset.
+ *
+ * @param scaleFactor the scale factor.
+ * @param offset the offset.
+ * @param hints the RenderingHints or null.
+ */
+ public RescaleOp(float scaleFactor, float offset, RenderingHints hints) {
+ scaleFactors = new float[1];
+ offsets = new float[1];
+
+ scaleFactors[0] = scaleFactor;
+ offsets[0] = offset;
+
+ this.hints = hints;
+ }
+
+ /**
+ * Gets the number of scaling factors.
+ *
+ * @return the number of scaling factors.
+ */
+ public final int getNumFactors() {
+ return scaleFactors.length;
+ }
+
+ public final RenderingHints getRenderingHints() {
+ return hints;
+ }
+
+ /**
+ * Gets the scale factors of this RescaleOp.
+ *
+ * @param scaleFactors the desired scale factors array will be copied
+ * to this array.
+ *
+ * @return the scale factors array.
+ */
+ public final float[] getScaleFactors(float[] scaleFactors) {
+ if (scaleFactors == null) {
+ scaleFactors = new float[this.scaleFactors.length];
+ }
+
+ int minLength = Math.min(scaleFactors.length, this.scaleFactors.length);
+ System.arraycopy(this.scaleFactors, 0, scaleFactors, 0, minLength);
+ return scaleFactors;
+ }
+
+ /**
+ * Gets the offsets array of this RescaleOp.
+ *
+ * @param offsets the desired offsets array will be copied to this array.
+ *
+ * @return the offsets array of this RescaleOp.
+ */
+ public final float[] getOffsets(float[] offsets) {
+ if (offsets == null) {
+ offsets = new float[this.offsets.length];
+ }
+
+ int minLength = Math.min(offsets.length, this.offsets.length);
+ System.arraycopy(this.offsets, 0, offsets, 0, minLength);
+ return offsets;
+ }
+
+ public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ if (dstPt == null) {
+ dstPt = new Point2D.Float();
+ }
+
+ dstPt.setLocation(srcPt);
+ return dstPt;
+ }
+
+ public final Rectangle2D getBounds2D(Raster src) {
+ return src.getBounds();
+ }
+
+ public final Rectangle2D getBounds2D(BufferedImage src) {
+ return getBounds2D(src.getRaster());
+ }
+
+ public WritableRaster createCompatibleDestRaster(Raster src) {
+ return src.createCompatibleWritableRaster();
+ }
+
+ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+ if (dstCM == null) {
+ dstCM = src.getColorModel();
+ }
+
+ if (dstCM instanceof IndexColorModel) {
+ dstCM = ColorModel.getRGBdefault();
+ }
+
+ WritableRaster r =
+ dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+ src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+ dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+ return new BufferedImage(
+ dstCM,
+ r,
+ dstCM.isAlphaPremultiplied(),
+ null
+ );
+ }
+
+ public final WritableRaster filter(Raster src, WritableRaster dst) {
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else {
+ if (src.getNumBands() != dst.getNumBands()) {
+ // awt.21D=Number of src bands ({0}) does not match number of dst bands ({1})
+ throw new IllegalArgumentException(Messages.getString("awt.21D", //$NON-NLS-1$
+ src.getNumBands(), dst.getNumBands()));
+ }
+ }
+
+ if (
+ this.scaleFactors.length != 1 &&
+ this.scaleFactors.length != src.getNumBands()
+ ) {
+ // awt.21E=Number of scaling constants is not equal to the number of bands
+ throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+ }
+
+ // TODO
+ //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM, false) != 0)
+ if (slowFilter(src, dst, false) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ return dst;
+ }
+
+ /**
+ * Slow filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param skipAlpha the skip alpha
+ *
+ * @return the int
+ */
+ private final int slowFilter(Raster src, WritableRaster dst, boolean skipAlpha) {
+ SampleModel sm = src.getSampleModel();
+
+ int numBands = src.getNumBands();
+ int srcHeight = src.getHeight();
+ int srcWidth = src.getWidth();
+
+ int srcMinX = src.getMinX();
+ int srcMinY = src.getMinY();
+ int dstMinX = dst.getMinX();
+ int dstMinY = dst.getMinY();
+
+ int[] maxValues = new int[numBands];
+ int[] masks = new int[numBands];
+ int[] sampleSizes = sm.getSampleSize();
+
+ for (int i=0; i < numBands; i++){
+ maxValues[i] = (1 << sampleSizes[i]) - 1;
+ masks[i] = ~(maxValues[i]);
+ }
+
+ // Processing bounds
+ float[] pixels = null;
+ pixels = src.getPixels(srcMinX, srcMinY, srcWidth, srcHeight, pixels);
+
+ // Cycle over pixels to be calculated
+ if (skipAlpha) { // Always suppose that alpha channel is the last band
+ if (scaleFactors.length > 1) {
+ for (int i = 0; i < pixels.length; ){
+ for (int bandIdx = 0; bandIdx < numBands-1; bandIdx++, i++){
+ pixels[i] = pixels[i] * scaleFactors[bandIdx] + offsets[bandIdx];
+ // Check for overflow now
+ if (((int)pixels[i] & masks[bandIdx]) != 0) {
+ if (pixels[i] < 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = maxValues[bandIdx];
+ }
+ }
+ }
+
+ i++;
+ }
+ } else {
+ for (int i = 0; i < pixels.length; ){
+ for (int bandIdx = 0; bandIdx < numBands-1; bandIdx++, i++){
+ pixels[i] = pixels[i] * scaleFactors[0] + offsets[0];
+ // Check for overflow now
+ if (((int)pixels[i] & masks[bandIdx]) != 0) {
+ if (pixels[i] < 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = maxValues[bandIdx];
+ }
+ }
+ }
+
+ i++;
+ }
+ }
+ } else {
+ if (scaleFactors.length > 1) {
+ for (int i = 0; i < pixels.length; ){
+ for (int bandIdx = 0; bandIdx < numBands; bandIdx++, i++){
+ pixels[i] = pixels[i] * scaleFactors[bandIdx] + offsets[bandIdx];
+ // Check for overflow now
+ if (((int)pixels[i] & masks[bandIdx]) != 0) {
+ if (pixels[i] < 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = maxValues[bandIdx];
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < pixels.length; ){
+ for (int bandIdx = 0; bandIdx < numBands; bandIdx++, i++){
+ pixels[i] = pixels[i] * scaleFactors[0] + offsets[0];
+ // Check for overflow now
+ if (((int)pixels[i] & masks[bandIdx]) != 0) {
+ if (pixels[i] < 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = maxValues[bandIdx];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ dst.setPixels(dstMinX, dstMinY, srcWidth, srcHeight, pixels);
+
+ return 0;
+ }
+
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+ ColorModel srcCM = src.getColorModel();
+
+ if (srcCM instanceof IndexColorModel) {
+ // awt.220=Source should not have IndexColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.220")); //$NON-NLS-1$
+ }
+
+ // Check if the number of scaling factors matches the number of bands
+ int nComponents = srcCM.getNumComponents();
+ boolean skipAlpha;
+ if (srcCM.hasAlpha()) {
+ if (scaleFactors.length == 1 || scaleFactors.length == nComponents-1) {
+ skipAlpha = true;
+ } else if (scaleFactors.length == nComponents) {
+ skipAlpha = false;
+ } else {
+ // awt.21E=Number of scaling constants is not equal to the number of bands
+ throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+ }
+ } else if (scaleFactors.length == 1 || scaleFactors.length == nComponents) {
+ skipAlpha = false;
+ } else {
+ // awt.21E=Number of scaling constants is not equal to the number of bands
+ throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+ }
+
+ BufferedImage finalDst = null;
+ if (dst == null) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, srcCM);
+ } else if (!srcCM.equals(dst.getColorModel())) {
+ // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+ if (
+ !((src.getType() == BufferedImage.TYPE_INT_RGB ||
+ src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+ (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+ dst.getType() == BufferedImage.TYPE_INT_ARGB))
+ ) {
+ finalDst = dst;
+ dst = createCompatibleDestImage(src, srcCM);
+ }
+ }
+
+ // TODO
+ //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType(), skipAlpha) != 0)
+ if (slowFilter(src.getRaster(), dst.getRaster(), skipAlpha) != 0) {
+ // awt.21F=Unable to transform source
+ throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+ }
+
+ if (finalDst != null) {
+ Graphics2D g = finalDst.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.drawImage(dst, 0, 0, null);
+ } else {
+ finalDst = dst;
+ }
+
+ return finalDst;
+ }
+
+ // Don't forget to pass allocated arrays for levels and values, size should be numBands*4
+ /**
+ * Creates the levels.
+ *
+ * @param sm the sm
+ * @param numBands the num bands
+ * @param skipAlpha the skip alpha
+ * @param levels the levels
+ * @param values the values
+ * @param channelsOrder the channels order
+ */
+ private final void createLevels(
+ SampleModel sm, int numBands, boolean skipAlpha,
+ int levels[], int values[], int channelsOrder[]
+ ) {
+ // Suppose same sample size for all channels, otherwise use slow filter
+ int maxValue = (1 << sm.getSampleSize(0)) - 1;
+
+ // For simplicity introduce these arrays
+ float extScaleFactors[] = new float[numBands];
+ float extOffsets[] = new float[numBands];
+
+ if (scaleFactors.length != 1) {
+ System.arraycopy(scaleFactors, 0, extScaleFactors, 0, scaleFactors.length);
+ System.arraycopy(offsets, 0, extOffsets, 0, scaleFactors.length);
+ } else {
+ for (int i = 0; i < numBands; i++) {
+ extScaleFactors[i] = scaleFactors[0];
+ extOffsets[i] = offsets[0];
+ }
+ }
+
+ if (skipAlpha) {
+ extScaleFactors[numBands-1] = 1;
+ extOffsets[numBands-1] = 0;
+ }
+
+ // Create a levels
+ for (int i=0; i<numBands; i++) {
+ if (extScaleFactors[i] == 0) {
+ levels[i*4] = 0;
+ levels[i*4+1] = 0;
+ levels[i*4+2] = maxValue+1;
+ levels[i*4+3] = maxValue+1;
+ }
+
+ float minLevel = -extOffsets[i] / extScaleFactors[i];
+ float maxLevel = (maxValue - extOffsets[i]) / extScaleFactors[i];
+
+ if (minLevel < 0) {
+ minLevel = 0;
+ } else if (minLevel > maxValue){
+ minLevel = maxValue;
+ }
+
+ if (maxLevel < 0) {
+ maxLevel = 0;
+ } else if (maxLevel > maxValue){
+ maxLevel = maxValue;
+ }
+
+ levels[i*4] = 0;
+ if (minLevel > maxLevel) {
+ levels[i*4+1] = (int) maxLevel;
+ levels[i*4+2] = (int) minLevel;
+ } else {
+ levels[i*4+1] = (int) minLevel;
+ levels[i*4+2] = (int) maxLevel;
+ }
+ levels[i*4+3] = maxValue+1;
+
+ // Fill values
+ for (int k=0; k<4; k++) {
+ int idx = i*4+k;
+ values[idx] = (int) (extScaleFactors[i] * levels[idx] + extOffsets[i]);
+ if (values[idx] < 0) {
+ values[idx] = 0;
+ } else if (values[idx] > maxValue){
+ values[idx] = maxValue;
+ }
+ }
+ }
+
+ // Reorder data if channels are stored in different order
+ if (channelsOrder != null) {
+ int len = numBands*4;
+ int savedLevels[] = new int[len];
+ int savedValues[] = new int[len];
+ System.arraycopy(levels, 0, savedLevels, 0, len);
+ System.arraycopy(values, 0, savedValues, 0, len);
+ for (int i = 0; i < channelsOrder.length; i++) {
+ System.arraycopy(savedLevels, i*4, levels, channelsOrder[i]*4, 4);
+ System.arraycopy(savedValues, i*4, values, channelsOrder[i]*4, 4);
+ }
+ }
+ }
+
+ // TODO remove when this method is used
+ /**
+ * Ipp filter.
+ *
+ * @param src the src
+ * @param dst the dst
+ * @param imageType the image type
+ * @param skipAlpha the skip alpha
+ *
+ * @return the int
+ */
+ @SuppressWarnings("unused")
+ private final int ippFilter(
+ Raster src, WritableRaster dst,
+ int imageType, boolean skipAlpha
+ ) {
+ int res;
+
+ int srcStride, dstStride;
+ int channels;
+ int offsets[] = null;
+ int channelsOrder[] = null;
+
+ switch (imageType) {
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ case BufferedImage.TYPE_INT_RGB: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ channelsOrder = new int[] {2, 1, 0, 3};
+ break;
+ }
+
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+ case BufferedImage.TYPE_INT_BGR: {
+ channels = 4;
+ srcStride = src.getWidth()*4;
+ dstStride = dst.getWidth()*4;
+ break;
+ }
+
+ case BufferedImage.TYPE_BYTE_GRAY: {
+ channels = 1;
+ srcStride = src.getWidth();
+ dstStride = dst.getWidth();
+ break;
+ }
+
+ case BufferedImage.TYPE_3BYTE_BGR: {
+ channels = 3;
+ srcStride = src.getWidth()*3;
+ dstStride = dst.getWidth()*3;
+ channelsOrder = new int[] {2, 1, 0};
+ break;
+ }
+
+ case BufferedImage.TYPE_USHORT_GRAY:
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ case BufferedImage.TYPE_BYTE_BINARY: {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ default: {
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+
+ if (
+ srcSM instanceof PixelInterleavedSampleModel &&
+ dstSM instanceof PixelInterleavedSampleModel
+ ) {
+ // Check PixelInterleavedSampleModel
+ if (
+ srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+ dstSM.getDataType() != DataBuffer.TYPE_BYTE
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+ if (!(channels == 1 || channels == 3 || channels == 4)) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+ dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+
+ channelsOrder = ((ComponentSampleModel) srcSM).getBandOffsets();
+ } else if (
+ srcSM instanceof SinglePixelPackedSampleModel &&
+ dstSM instanceof SinglePixelPackedSampleModel
+ ) {
+ // Check SinglePixelPackedSampleModel
+ SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+ SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+ channels = sppsm1.getNumBands();
+
+ // TYPE_INT_RGB, TYPE_INT_ARGB...
+ if (
+ sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+ sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+ !(channels == 3 || channels == 4)
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ // Check compatibility of sample models
+ if (
+ !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+ !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+ ) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ for (int i=0; i<channels; i++) {
+ if (sppsm1.getSampleSize(i) != 8) {
+ return slowFilter(src, dst, skipAlpha);
+ }
+ }
+
+ channelsOrder = new int[channels];
+ int bitOffsets[] = sppsm1.getBitOffsets();
+ for (int i=0; i<channels; i++) {
+ channelsOrder[i] = bitOffsets[i] / 8;
+ }
+
+ if (channels == 3) { // Don't skip channel now, could be optimized
+ channels = 4;
+ }
+
+ srcStride = sppsm1.getScanlineStride() * 4;
+ dstStride = sppsm2.getScanlineStride() * 4;
+ } else {
+ return slowFilter(src, dst, skipAlpha);
+ }
+
+ // Fill offsets if there's a child raster
+ if (src.getParent() != null || dst.getParent() != null) {
+ if (
+ src.getSampleModelTranslateX() != 0 ||
+ src.getSampleModelTranslateY() != 0 ||
+ dst.getSampleModelTranslateX() != 0 ||
+ dst.getSampleModelTranslateY() != 0
+ ) {
+ offsets = new int[4];
+ offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+ offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+ offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+ offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+ }
+ }
+ }
+ }
+
+ int levels[] = new int[4*channels];
+ int values[] = new int[4*channels];
+
+ createLevels(src.getSampleModel(), channels, skipAlpha, levels, values, channelsOrder);
+
+ Object srcData, dstData;
+ AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+ try {
+ srcData = dbAccess.getData(src.getDataBuffer());
+ dstData = dbAccess.getData(dst.getDataBuffer());
+ } catch (IllegalArgumentException e) {
+ return -1; // Unknown data buffer type
+ }
+
+ res = LookupOp.ippLUT(
+ srcData, src.getWidth(), src.getHeight(), srcStride,
+ dstData, dst.getWidth(), dst.getHeight(), dstStride,
+ levels, values,
+ channels, offsets,
+ true
+ );
+
+ return res;
+ }
+}
diff --git a/awt/java/awt/image/SampleModel.java b/awt/java/awt/image/SampleModel.java
new file mode 100644
index 0000000..44059a0
--- /dev/null
+++ b/awt/java/awt/image/SampleModel.java
@@ -0,0 +1,1053 @@
+/*
+ * 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 org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The SampleModel class is abstract class for retrieving pixel's samples
+ * in the data of an image. Each pixel contains several samples. A
+ * sample is the set of values of the bands for single pixel.
+ * For example, each pixel in the RGB model contains three samples
+ * and there are three corresponding bands in the image
+ * data of such pixels representing red, green and blue components.
+ * <p>
+ * The image data is represented as a Raster with a DataBuffer
+ * and a SampleModel. The SampleModel allows access to the samples in the
+ * DataBuffer.
+ */
+public abstract class SampleModel {
+
+ /** The width of the image data which this SampleModel describes. */
+ protected int width;
+
+ /** The height of the image data which this SampleModel describes. */
+ protected int height;
+
+ /** The number of bands of image data which this SampleModel describes. */
+ protected int numBands;
+
+ /** The data type of the image data which this SampleModel describes. */
+ protected int dataType;
+
+ /**
+ * Instantiates a new SampleModel with the specified data type,
+ * width, height and number of bands.
+ *
+ * @param dataType the data type of the image data.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param numBands the number of bands of the image data.
+ */
+ public SampleModel(int dataType, int w, int h, int numBands) {
+ if (w <= 0 || h <= 0) {
+ // awt.22E=w or h is less than or equal to zero
+ throw new IllegalArgumentException(Messages.getString("awt.22E")); //$NON-NLS-1$
+ }
+
+ double squre = ((double) w) * ((double) h);
+ if (squre >= Integer.MAX_VALUE) {
+ // awt.22F=The product of w and h is greater than Integer.MAX_VALUE
+ throw new IllegalArgumentException(Messages.getString("awt.22F")); //$NON-NLS-1$
+ }
+
+ if (dataType < DataBuffer.TYPE_BYTE ||
+ dataType > DataBuffer.TYPE_DOUBLE &&
+ dataType != DataBuffer.TYPE_UNDEFINED) {
+ // awt.230=dataType is not one of the supported data types
+ throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+ }
+
+ if (numBands < 1) {
+ // awt.231=Number of bands must be more then 0
+ throw new IllegalArgumentException(Messages.getString("awt.231")); //$NON-NLS-1$
+ }
+
+ this.dataType = dataType;
+ this.width = w;
+ this.height = h;
+ this.numBands = numBands;
+
+ }
+
+ /**
+ * Gets the data array for the specified pixel of the specified
+ * DataBuffer with one of the following types:
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param obj the Object is a data where the result will be stored.
+ * @param data the image data.
+ *
+ * @return the data array for the specified pixel of the specified
+ * DataBuffer.
+ */
+ public abstract Object getDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+ /**
+ * Gets the array of pixel data for the specified rectangular
+ * area of pixels of the specified DataBuffer with one of
+ * the following types:
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+ *
+ *
+ * @param x the X coordinate of the rectangular pixel area.
+ * @param y the Y coordinate of the rectangular pixel area.
+ * @param w the width of the rectangular pixel area.
+ * @param h the height of the rectangular pixel area.
+ * @param obj the Object is an array with the primitive type,
+ * where the result array will be stored.
+ * @param data the image data.
+ *
+ * @return the array of pixel data for the specified rectangular
+ * area of pixels of the specified DataBuffer object.
+ */
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data) {
+ int numDataElements = getNumDataElements();
+ int idx = 0;
+
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ byte bdata[];
+ byte bbuf[] = null;
+
+ if (obj == null) {
+ bdata = new byte[numDataElements * w * h];
+ } else {
+ bdata = (byte[]) obj;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ bbuf = (byte[]) getDataElements(j, i, bbuf, data);
+ for (int n = 0; n < numDataElements; n++) {
+ bdata[idx++] = bbuf[n];
+ }
+ }
+ }
+ obj = bdata;
+ break;
+
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short sdata[];
+ short sbuf[] = null;
+
+ if (obj == null) {
+ sdata = new short[numDataElements * w * h];
+ } else {
+ sdata = (short[]) obj;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ sbuf = (short[]) getDataElements(j, i, sbuf, data);
+ for (int n = 0; n < numDataElements; n++) {
+ sdata[idx++] = sbuf[n];
+ }
+ }
+ }
+ obj = sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int idata[];
+ int ibuf[] = null;
+
+ if (obj == null) {
+ idata = new int[numDataElements * w * h];
+ } else {
+ idata = (int[]) obj;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ ibuf = (int[]) getDataElements(j, i, ibuf, data);
+ for (int n = 0; n < numDataElements; n++) {
+ idata[idx++] = ibuf[n];
+ }
+ }
+ }
+ obj = idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float fdata[];
+ float fbuf[] = null;
+
+ if (obj == null) {
+ fdata = new float[numDataElements * w * h];
+ } else {
+ fdata = (float[]) obj;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ fbuf = (float[]) getDataElements(j, i, fbuf, data);
+ for (int n = 0; n < numDataElements; n++) {
+ fdata[idx++] = fbuf[n];
+ }
+ }
+ }
+ obj = fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double ddata[];
+ double dbuf[] = null;
+
+ if (obj == null) {
+ ddata = new double[numDataElements * w * h];
+ } else {
+ ddata = (double[]) obj;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ dbuf = (double[]) getDataElements(j, i, dbuf, data);
+ for (int n = 0; n < numDataElements; n++) {
+ ddata[idx++] = dbuf[n];
+ }
+ }
+ }
+ obj = ddata;
+ break;
+
+ }
+
+ return obj;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified DataBuffer
+ * from a primitive array with one of the following types:
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param obj the Object - the array of primitive pixel data
+ * to be set.
+ * @param data the image data.
+ */
+ public abstract void setDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+ /**
+ * Sets the data elements for a rectangular area of pixels in
+ * the specified DataBuffer from a primitive array with one of
+ * the following types: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of the specified rectangular area.
+ * @param y the Y coordinate of the specified rectangular area.
+ * @param w the width of rectangle.
+ * @param h the height of rectangle.
+ * @param obj the Object - the array of primitive pixel data
+ * to be set.
+ * @param data the image data.
+ */
+ public void setDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data) {
+ int numDataElements = getNumDataElements();
+ int idx = 0;
+
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ byte bbuf[] = new byte[numDataElements];
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numDataElements; n++) {
+ bbuf[n] = ((byte[]) obj)[idx++];
+ }
+ setDataElements(j, i, bbuf, data);
+ }
+ }
+
+ break;
+
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short sbuf[] = new short[numDataElements];
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numDataElements; n++) {
+ sbuf[n] = ((short[]) obj)[idx++];
+ }
+ setDataElements(j, i, sbuf, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+ int ibuf[] = new int[numDataElements];
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numDataElements; n++) {
+ ibuf[n] = ((int[]) obj)[idx++];
+ }
+ setDataElements(j, i, ibuf, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float fbuf[] = new float[numDataElements];
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numDataElements; n++) {
+ fbuf[n] = ((float[]) obj)[idx++];
+ }
+ setDataElements(j, i, fbuf, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double dbuf[] = new double[numDataElements];
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numDataElements; n++) {
+ dbuf[n] = ((double[]) obj)[idx++];
+ }
+ setDataElements(j, i, dbuf, data);
+ }
+ }
+ break;
+
+ }
+ }
+
+ /**
+ * Creates a new SampleModel with the specified bands of
+ * this SampleModel.
+ *
+ * @param bands the array of bands from this SampleModel.
+ *
+ * @return the SampleModel with the specified bands of
+ * this SampleModel.
+ */
+ public abstract SampleModel createSubsetSampleModel(int bands[]);
+
+ /**
+ * Creates the SampleModel which has the same data as in
+ * this SampleModel with a different width and height.
+ *
+ * @param a0 the width of the image data.
+ * @param a1 the height of the image data.
+ *
+ * @return the SampleModel which has the same data as in
+ * this SampleModel with a different width and height.
+ */
+ public abstract SampleModel createCompatibleSampleModel(int a0, int a1);
+
+ /**
+ * Gets the samples of the specified pixel as a int array.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param iArray the int array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the int array with the samples of the specified pixel.
+
+ */
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int pixel[];
+
+ if (iArray == null) {
+ pixel = new int[numBands];
+ } else {
+ pixel = iArray;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ pixel[i] = getSample(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ /**
+ * Sets a pixel of the DataBuffer from a int array of samples.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param iArray the int array.
+ * @param data the image data.
+ */
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, iArray[i], data);
+ }
+ }
+
+ /**
+ * Gets the samples of the specified pixel as a float array.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param fArray the float array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the float array with the samples of the specified pixel.
+ */
+ public float[] getPixel(int x, int y, float fArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ float pixel[];
+
+ if (fArray == null) {
+ pixel = new float[numBands];
+ } else {
+ pixel = fArray;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ pixel[i] = getSampleFloat(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ /**
+ * Sets a pixel of the DataBuffer from a float array of samples.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param fArray the float array.
+ * @param data the image data.
+ */
+ public void setPixel(int x, int y, float fArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, fArray[i], data);
+ }
+ }
+
+ /**
+ * Gets the samples of the specified pixel as a double array.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param dArray the double array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the double array with the samples of the specified pixel.
+ */
+ public double[] getPixel(int x, int y, double dArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ double pixel[];
+
+ if (dArray == null) {
+ pixel = new double[numBands];
+ } else {
+ pixel = dArray;
+ }
+
+ for (int i = 0; i < numBands; i++) {
+ pixel[i] = getSampleDouble(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ /**
+ * Sets a pixel of the DataBuffer from a double array of samples.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param dArray the double array.
+ * @param data the image data.
+ */
+ public void setPixel(int x, int y, double dArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ for (int i = 0; i < numBands; i++) {
+ setSample(x, y, i, dArray[i], data);
+ }
+ }
+
+ /**
+ * Gets the sample of a specified band for the specified pixel
+ * as an int.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param b the specified band.
+ * @param data the image data.
+ *
+ * @return the sample of a specified band for the specified pixel.
+ */
+ public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+ /**
+ * Gets the sample of a specified band for the specified pixel
+ * as a float.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param b the specified band.
+ * @param data the image data.
+ *
+ * @return the sample of a specified band for the specified pixel.
+
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+ return getSample(x, y, b, data);
+ }
+
+ /**
+ * Gets the sample of a specified band for the specified pixel
+ * as a double.
+ *
+ * @param x the X coordinate of pixel.
+ * @param y the Y coordinate of pixel.
+ * @param b the specified band.
+ * @param data the image data.
+ *
+ * @return the sample of a specified band for the specified pixel.
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+ return getSample(x, y, b, data);
+ }
+
+ /**
+ * Gets the samples of the specified rectangular area of pixels
+ * as a int array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param iArray the int array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the int array with the samples of the specified
+ * rectangular area of pixels.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int pixels[];
+ int idx = 0;
+
+ if (iArray == null) {
+ pixels = new int[w * h * numBands];
+ } else {
+ pixels = iArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ pixels[idx++] = getSample(j, i, n, data);
+ }
+ }
+ }
+ return pixels;
+ }
+
+ /**
+ * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+ * from an int array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param iArray the int array.
+ * @param data the image data.
+ */
+ public void setPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ setSample(j, i, n, iArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the samples of the specified rectangular area of pixels
+ * as a float array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param fArray the float array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the float array with the samples of the specified
+ * rectangular area of pixels.
+ */
+ public float[] getPixels(int x, int y, int w, int h, float fArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ float pixels[];
+ int idx = 0;
+
+ if (fArray == null) {
+ pixels = new float[w * h * numBands];
+ } else {
+ pixels = fArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ pixels[idx++] = getSampleFloat(j, i, n, data);
+ }
+ }
+ }
+ return pixels;
+ }
+
+ /**
+ * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+ * from a float array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param fArray the float array.
+ * @param data the image data.
+ */
+ public void setPixels(int x, int y, int w, int h, float fArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ setSample(j, i, n, fArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the samples of the specified rectangular area of pixels
+ * as a double array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param dArray the double array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the double array with the samples of the specified
+ * rectangular area of pixels.
+ */
+ public double[] getPixels(int x, int y, int w, int h, double dArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ double pixels[];
+ int idx = 0;
+
+ if (dArray == null) {
+ pixels = new double[w * h * numBands];
+ } else {
+ pixels = dArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ pixels[idx++] = getSampleDouble(j, i, n, data);
+ }
+ }
+ }
+ return pixels;
+ }
+
+ /**
+ * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+ * from a double array.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param dArray the double array.
+ * @param data the image data.
+ */
+ public void setPixels(int x, int y, int w, int h, double dArray[],
+ DataBuffer data) {
+ if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < numBands; n++) {
+ setSample(j, i, n, dArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets a sample of the specified band for the specified pixel
+ * in the DataBuffer as int value.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample as an int value.
+ * @param data the image data.
+ */
+ public abstract void setSample(int x, int y, int b, int s, DataBuffer data);
+
+ /**
+ * Gets the samples of a specified band for a specified rectangular
+ * area of pixels as a int array.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param iArray the int array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the samples of a specified band for a specified rectangular
+ * area of pixels.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ int samples[];
+ int idx = 0;
+
+ if (iArray == null) {
+ samples = new int[w * h];
+ } else {
+ samples = iArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSample(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ /**
+ * Sets the samples from an int array in the specified band for
+ * the specified rectangle of pixels.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param iArray the int array.
+ * @param data the image data.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(j, i, b, iArray[idx++], data);
+ }
+ }
+ }
+
+ /**
+ * Gets the samples of a specified band for a specified rectangular
+ * area of pixels as a float array.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param fArray the float array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the samples of a specified band for a specified rectangular
+ * area of pixels.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float fArray[], DataBuffer data) {
+ float samples[];
+ int idx = 0;
+
+ if (fArray == null) {
+ samples = new float[w * h];
+ } else {
+ samples = fArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSampleFloat(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ /**
+ * Sets the samples from an float array in the specified band for
+ * the specified rectangle of pixels.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param fArray the float array
+ * @param data the image data.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, float fArray[],
+ DataBuffer data) {
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(j, i, b, fArray[idx++], data);
+ }
+ }
+ }
+
+ /**
+ * Gets the samples of a specified band for a specified rectangular
+ * area of pixels as a double array.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param dArray the double array where result will be stored.
+ * @param data the image data.
+ *
+ * @return the samples of a specified band for a specified rectangular
+ * area of pixels.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double dArray[], DataBuffer data) {
+ double samples[];
+ int idx = 0;
+
+ if (dArray == null) {
+ samples = new double[w * h];
+ } else {
+ samples = dArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSampleDouble(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ /**
+ * Sets the samples from an double array in the specified band for
+ * the specified rectangle of pixels.
+ *
+ * @param x the X coordinate of the rectangle.
+ * @param y the Y coordinate of the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param b the specified band.
+ * @param dArray the double array
+ * @param data the image data.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, double dArray[],
+ DataBuffer data) {
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(j, i, b, dArray[idx++], data);
+ }
+ }
+ }
+
+ /**
+ * Sets a sample of the specified band for the specified pixel
+ * in the DataBuffer as float value.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample as float value.
+ * @param data the image data.
+ */
+ public void setSample(int x, int y, int b, float s, DataBuffer data) {
+ setSample(x, y, b, (int) s, data);
+ }
+
+ /**
+ * Sets a sample of the specified band for the specified pixel
+ * in the DataBuffer as double value.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample as double value.
+ * @param data the image data.
+ */
+ public void setSample(int x, int y, int b, double s, DataBuffer data) {
+ setSample(x, y, b, (int) s, data);
+ }
+
+ /**
+ * Creates a DataBuffer object which corresponds to the SampleModel.
+ *
+ * @return the DataBuffer object which corresponds to
+ * the SampleModel.
+ */
+ public abstract DataBuffer createDataBuffer();
+
+ /**
+ * Gets the sample size in bits for the specified band.
+ *
+ * @param band the specified band.
+ *
+ * @return the sample size in bits for the specified band.
+ */
+ public abstract int getSampleSize(int band);
+
+ /**
+ * Gets an array of the sample size in bits for all bands.
+ *
+ * @return an array of the sample size in bits for all bands.
+ */
+ public abstract int[] getSampleSize();
+
+ /**
+ * Gets the width of the image data of this SampleModel object.
+ *
+ * @return the width of the image data of this SampleModel object.
+ */
+ public final int getWidth() {
+ return width;
+ }
+
+ /**
+ * Gets the transfer type used to transfer pixels via
+ * the getDataElements and setDataElements methods.
+ * Transfer type value can be one of the predefined type
+ * from DataBuffer class or not.
+ *
+ * @return the transfer type.
+ */
+ public int getTransferType() {
+ return dataType;
+ }
+
+ /**
+ * Returns the number of data elements for pixel transfering
+ * via the getDataElements and setDataElements methods.
+ *
+ * @return the number of data elements for pixel transfering
+ * via the getDataElements and setDataElements methods.
+ */
+ public abstract int getNumDataElements();
+
+ /**
+ * Gets the number of bands in the image data of this
+ * SampleModel object.
+ *
+ * @return the number of bands in the image data of this
+ * SampleModel object.
+ */
+ public final int getNumBands() {
+ return numBands;
+ }
+
+ /**
+ * Gets the height of the image data of this SampleModel object.
+ *
+ * @return the height of the image data of this SampleModel object.
+ */
+ public final int getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the data type of image data of this SampleModel object.
+ *
+ * @return the data type of image data of this SampleModel object.
+ */
+ public final int getDataType() {
+ return dataType;
+ }
+
+}
+
diff --git a/awt/java/awt/image/ShortLookupTable.java b/awt/java/awt/image/ShortLookupTable.java
new file mode 100644
index 0000000..77c9c45
--- /dev/null
+++ b/awt/java/awt/image/ShortLookupTable.java
@@ -0,0 +1,132 @@
+/*
+ * 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 Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+
+/**
+ * The ShortLookupTable class provides provides functionality for
+ * lookup operations, and is defined by an input short array for
+ * bands or components of image and an offset value.
+ * The offset value will be subtracted from the input values before
+ * indexing the input arrays. The output of a lookup operation is
+ * represented as an unsigned short array.
+ */
+public class ShortLookupTable extends LookupTable {
+
+ /** The data. */
+ private short data[][];
+
+ /**
+ * Instantiates a new ShortLookupTable with the specified offset value
+ * and the specified short array which represents lookup table for
+ * all bands.
+ *
+ * @param offset the offset value.
+ * @param data the data array.
+ */
+ public ShortLookupTable(int offset, short[] data) {
+ super(offset, 1);
+ this.data = new short[1][data.length];
+ // The data array stored as a reference
+ this.data[0] = data;
+ }
+
+ /**
+ * Instantiates a new ShortLookupTable with the specified offset value
+ * and the specified short array of arrays which represents lookup table
+ * for each band.
+ *
+ * @param offset the offset value.
+ * @param data the data array of arrays for each band.
+ */
+ public ShortLookupTable(int offset, short[][] data) {
+ super(offset, data.length);
+ this.data = new short[data.length][data[0].length];
+ for (int i = 0; i < data.length; i++) {
+ // The data array for each band stored as a reference
+ this.data[i] = data[i];
+ }
+ }
+
+ /**
+ * Gets the lookup table of this ShortLookupTable object. If
+ * this ShortLookupTable object has one short array for all bands,
+ * the returned array length is one.
+ *
+ * @return the lookup table of this ShortLookupTable object.
+ */
+ public final short[][] getTable() {
+ return data;
+ }
+
+ /**
+ * Returns a short array which contains samples of the specified
+ * pixel which is translated with the lookup table of this
+ * ShortLookupTable object. The resulted array is stored to
+ * the dst array.
+ *
+ * @param src the source array.
+ * @param dst the destination array where the result can be stored.
+ *
+ * @return the short array of translated samples of a pixel.
+ */
+ public short[] lookupPixel(short[] src, short[] dst) {
+ if (dst == null) {
+ dst = new short[src.length];
+ }
+
+ int offset = getOffset();
+ if (getNumComponents() == 1) {
+ for (int i = 0; i < src.length; i++) {
+ dst[i] = data[0][src[i]-offset];
+ }
+ } else {
+ for (int i = 0; i < getNumComponents(); i++) {
+ dst[i] = data[i][src[i]-offset];
+ }
+ }
+
+ return dst;
+ }
+
+ @Override
+ public int[] lookupPixel(int[] src, int[] dst) {
+ if (dst == null) {
+ dst = new int[src.length];
+ }
+
+ int offset = getOffset();
+ if (getNumComponents() == 1) {
+ for (int i = 0; i < src.length; i++) {
+ dst[i] = data[0][src[i]-offset];
+ }
+ } else {
+ for (int i = 0; i < getNumComponents(); i++) {
+ dst[i] = data[i][src[i]-offset];
+ }
+ }
+
+ return dst;
+ }
+}
diff --git a/awt/java/awt/image/SinglePixelPackedSampleModel.java b/awt/java/awt/image/SinglePixelPackedSampleModel.java
new file mode 100644
index 0000000..311395a
--- /dev/null
+++ b/awt/java/awt/image/SinglePixelPackedSampleModel.java
@@ -0,0 +1,508 @@
+/*
+ * 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.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The SinglePixelPackedSampleModel class represents pixel data
+ * where several samples combine to create a single pixel and
+ * are stored in a single data array element. This class
+ * supports TYPE_BYTE, TYPE_USHORT, TYPE_INT data types.
+ */
+public class SinglePixelPackedSampleModel extends SampleModel {
+
+ /** The bit masks. */
+ private int bitMasks[];
+
+ /** The bit offsets. */
+ private int bitOffsets[];
+
+ /** The bit sizes. */
+ private int bitSizes[];
+
+ /** The scanline stride. */
+ private int scanlineStride;
+
+ /** The max bit size. */
+ private int maxBitSize;
+
+ /**
+ * Instantiates a new SinglePixelPackedSampleModel with the specified
+ * parameters.
+ *
+ * @param dataType the data type of samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param bitMasks the bit masks for all the bands.
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int bitMasks[]) {
+ this(dataType, w, h, w, bitMasks);
+ }
+
+ /**
+ * Instantiates a new SinglePixelPackedSampleModel with the specified
+ * parameters.
+ *
+ * @param dataType the data type of the samples.
+ * @param w the width of the image data.
+ * @param h the height of the image data.
+ * @param scanlineStride The scanline stride of the image data.
+ * @param bitMasks the bit masks for all the bands.
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int scanlineStride, int bitMasks[]) {
+
+ super(dataType, w, h, bitMasks.length);
+
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ // awt.61=Unsupported data type: {0}
+ throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
+ dataType));
+ }
+
+ this.scanlineStride = scanlineStride;
+ this.bitMasks = bitMasks.clone();
+ this.bitOffsets = new int[this.numBands];
+ this.bitSizes = new int[this.numBands];
+
+ this.maxBitSize = 0;
+
+ for (int i = 0; i < this.numBands; i++) {
+ int offset = 0;
+ int size = 0;
+ int mask = bitMasks[i];
+
+ if (mask != 0) {
+ while ((mask & 1) == 0) {
+ mask >>>= 1;
+ offset++;
+ }
+
+ while ((mask & 1) == 1) {
+ mask >>>= 1;
+ size++;
+ }
+
+ if (mask != 0) {
+ // awt.62=Wrong mask : {0}
+ throw new IllegalArgumentException(Messages.getString(
+ "awt.62", bitMasks[i])); //$NON-NLS-1$
+ }
+ }
+
+ this.bitOffsets[i] = offset;
+ this.bitSizes[i] = size;
+
+ if (this.maxBitSize < size) {
+ this.maxBitSize = size;
+ }
+
+ }
+
+ }
+
+ @Override
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ byte bdata[];
+ if (obj == null) {
+ bdata = new byte[1];
+ } else {
+ bdata = (byte[]) obj;
+ }
+
+ bdata[0] = (byte) data.getElem(y * scanlineStride + x);
+ obj = bdata;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short sdata[];
+ if (obj == null) {
+ sdata = new short[1];
+ } else {
+ sdata = (short[]) obj;
+ }
+
+ sdata[0] = (short) data.getElem(y * scanlineStride + x);
+ obj = sdata;
+ break;
+ case DataBuffer.TYPE_INT:
+ int idata[];
+ if (obj == null) {
+ idata = new int[1];
+ } else {
+ idata = (int[]) obj;
+ }
+
+ idata[0] = data.getElem(y * scanlineStride + x);
+ obj = idata;
+ break;
+ }
+ return obj;
+ }
+
+ @Override
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ switch (getTransferType()) {
+ case DataBuffer.TYPE_BYTE:
+ data.setElem(y * scanlineStride + x, ((byte[]) obj)[0] & 0xff);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data.setElem(y * scanlineStride + x, ((short[]) obj)[0] & 0xffff);
+ break;
+ case DataBuffer.TYPE_INT:
+ data.setElem(y * scanlineStride + x, ((int[]) obj)[0]);
+ break;
+ }
+ }
+
+ /**
+ * Compares this SinglePixelPackedSampleModel object with
+ * the specified object.
+ *
+ * @param o the Object to be compared.
+ *
+ * @return true, if this SinglePixelPackedSampleModel object is
+ * equal to the specified object, false otherwise.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
+ return false;
+ }
+
+ SinglePixelPackedSampleModel model = (SinglePixelPackedSampleModel) o;
+ return this.width == model.width &&
+ this.height == model.height &&
+ this.numBands == model.numBands &&
+ this.dataType == model.dataType &&
+ Arrays.equals(this.bitMasks, model.bitMasks) &&
+ Arrays.equals(this.bitOffsets, model.bitOffsets) &&
+ Arrays.equals(this.bitSizes, model.bitSizes) &&
+ this.scanlineStride == model.scanlineStride;
+ }
+
+ @Override
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands.length > this.numBands) {
+ // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+ throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+ }
+
+ int masks[] = new int[bands.length];
+ for (int i = 0; i < bands.length; i++) {
+ masks[i] = this.bitMasks[bands[i]];
+ }
+ return new SinglePixelPackedSampleModel(this.dataType, this.width,
+ this.height, this.scanlineStride, masks);
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ return new SinglePixelPackedSampleModel(this.dataType, w, h,
+ this.bitMasks);
+ }
+
+ @Override
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int pixel[];
+ if (iArray == null) {
+ pixel = new int[this.numBands];
+ } else {
+ pixel = iArray;
+ }
+
+ for (int i = 0; i < this.numBands; i++) {
+ pixel[i] = getSample(x, y, i, data);
+ }
+
+ return pixel;
+ }
+
+ @Override
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ for (int i = 0; i < this.numBands; i++) {
+ setSample(x, y, i, iArray[i], data);
+ }
+ }
+
+ @Override
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int sample = data.getElem(y * scanlineStride + x);
+ return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
+ }
+
+ @Override
+ public int[] getPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+ || ((long) y + (long) h > this.height)) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int pixels[];
+
+ if (iArray == null) {
+ pixels = new int[w * h * this.numBands];
+ } else {
+ pixels = iArray;
+ }
+
+ int idx = 0;
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < this.numBands; n++) {
+ pixels[idx++] = getSample(j, i, n, data);
+ }
+ }
+ }
+ return pixels;
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, int iArray[],
+ DataBuffer data) {
+ if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+ || ((long) y + (long) h > this.height)) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages
+ .getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int idx = 0;
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ for (int n = 0; n < this.numBands; n++) {
+ setSample(j, i, n, iArray[idx++], data);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setSample(int x, int y, int b, int s, DataBuffer data) {
+ if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+ int tmp = data.getElem(y * scanlineStride + x);
+ tmp &= ~this.bitMasks[b];
+ tmp |= (s << this.bitOffsets[b]) & this.bitMasks[b];
+ data.setElem(y * scanlineStride + x, tmp);
+ }
+
+ @Override
+ public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+ || ((long) y + (long) h > this.height)) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages
+ .getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int samples[];
+ int idx = 0;
+
+ if (iArray == null) {
+ samples = new int[w * h];
+ } else {
+ samples = iArray;
+ }
+
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ samples[idx++] = getSample(j, i, b, data);
+ }
+ }
+
+ return samples;
+ }
+
+ @Override
+ public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+ DataBuffer data) {
+ if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+ || ((long) y + (long) h > this.height)) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int idx = 0;
+ for (int i = y; i < y + h; i++) {
+ for (int j = x; j < x + w; j++) {
+ setSample(x + j, y + i, b, iArray[idx++], data);
+ }
+ }
+ }
+
+ @Override
+ public DataBuffer createDataBuffer() {
+ DataBuffer data = null;
+ int size = (this.height - 1) * scanlineStride + width;
+
+ switch (this.dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new DataBufferByte(size);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new DataBufferUShort(size);
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new DataBufferInt(size);
+ break;
+ }
+ return data;
+ }
+
+ /**
+ * Gets the offset of the specified pixel in the data array.
+ *
+ * @param x the X coordinate of the specified pixel.
+ * @param y the Y coordinate of the specified pixel.
+ *
+ * @return the offset of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ return (y * scanlineStride + x);
+ }
+
+ @Override
+ public int getSampleSize(int band) {
+ return bitSizes[band];
+ }
+
+ @Override
+ public int[] getSampleSize() {
+ return bitSizes.clone();
+ }
+
+ /**
+ * Gets an array of the bit offsets of the data array elements.
+ *
+ * @return an array of the bit offsets.
+ */
+ public int[] getBitOffsets() {
+ return bitOffsets.clone();
+ }
+
+ /**
+ * Gets an array of the bit masks for all bands.
+ *
+ * @return an array of the bit masks for all bands.
+ */
+ public int[] getBitMasks() {
+ return bitMasks.clone();
+ }
+
+ /**
+ * Returns a hash code of this MultiPixelPackedSampleModel class.
+ *
+ * @return the hash code of this MultiPixelPackedSampleModel class.
+ */
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ int tmp = 0;
+
+ hash = width;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= height;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= numBands;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ hash ^= dataType;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ for (int element : bitMasks) {
+ hash ^= element;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ }
+ for (int element : bitOffsets) {
+ hash ^= element;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ }
+ for (int element : bitSizes) {
+ hash ^= element;
+ tmp = hash >>> 24;
+ hash <<= 8;
+ hash |= tmp;
+ }
+ hash ^= scanlineStride;
+ return hash;
+ }
+
+ /**
+ * Gets the scanline stride.
+ *
+ * @return the scanline stride
+ */
+ public int getScanlineStride() {
+ return this.scanlineStride;
+ }
+
+ @Override
+ public int getNumDataElements() {
+ return 1;
+ }
+
+}
+
diff --git a/awt/java/awt/image/TileObserver.java b/awt/java/awt/image/TileObserver.java
new file mode 100644
index 0000000..39ded02
--- /dev/null
+++ b/awt/java/awt/image/TileObserver.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+
+/**
+ * An asynchronous update interface for receiving notifications
+ * about tile information when tiles of a WritableRenderedImage
+ * become modifiable or unmodifiable.
+ */
+public interface TileObserver {
+
+ /**
+ * This method is called when information about a tile
+ * update is available.
+ *
+ * @param source the source image.
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ * @param willBeWritable parameter which indicates whether
+ * the tile will be grabbed for writing or be released.
+ */
+ public void tileUpdate(WritableRenderedImage source, int tileX, int tileY, boolean willBeWritable);
+
+}
+
diff --git a/awt/java/awt/image/VolatileImage.java b/awt/java/awt/image/VolatileImage.java
new file mode 100644
index 0000000..3b0cfb2
--- /dev/null
+++ b/awt/java/awt/image/VolatileImage.java
@@ -0,0 +1,144 @@
+/*
+ * 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 Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.ImageCapabilities;
+import java.awt.Transparency;
+
+/**
+ * The VolatileImage abstract class represents an image which can lose
+ * its contents at any point. VolatileImage objects are device specific.
+ * This class provies methods for checking if operation of this image
+ * are compatible for the GraphicsConfiguration.
+ */
+public abstract class VolatileImage extends Image
+ // Volatile image implements Transparency since 1.5
+ implements Transparency {
+
+ /**
+ * The Constant IMAGE_INCOMPATIBLE indicates that this VolatileImage
+ * is not applicable for the GraphicsConfiguration object.
+ */
+ public static final int IMAGE_INCOMPATIBLE = 2;
+
+ /**
+ * The Constant IMAGE_OK indicates that VolatileImage is ready
+ * for using.
+ */
+ public static final int IMAGE_OK = 0;
+
+ /**
+ * The Constant IMAGE_RESTORED indicates that VolatileImage
+ * will be ready to use after restoring.
+ */
+ public static final int IMAGE_RESTORED = 1;
+
+ /**
+ * The transparency value of this image.
+ */
+ protected int transparency = OPAQUE;
+
+ /**
+ * Instantiates a new VolatileImage object.
+ */
+ public VolatileImage() {
+ super();
+ }
+
+ /**
+ * Returns true if rendering data is lost during validating.
+ * This method should be called after rendering operation of image.
+ *
+ * @return true, if contents lost during validating, false otherwise.
+ */
+
+ public abstract boolean contentsLost();
+
+ /**
+ * Creates a Graphics2D used to draw in this VolatileImage.
+ *
+ * @return the Graphics2D object.
+ */
+ public abstract Graphics2D createGraphics();
+
+ /**
+ * Gets the ImageCapabilities of this VolatileImage.
+ *
+ * @return the ImageCapabilities of this VolatileImage.
+ */
+ public abstract ImageCapabilities getCapabilities();
+
+ /**
+ * Gets the height of this VolatileImage.
+ *
+ * @return the height of this VolatileImage.
+ */
+ public abstract int getHeight();
+
+ /**
+ * Gets a BufferedImage representation of current VolatileImage that
+ * won't be affected by any changes to this VolatileImage.
+ *
+ * @return a BufferedImage representation of current VolatileImage.
+ */
+ public abstract BufferedImage getSnapshot();
+
+ /**
+ * Gets the width of this VolatileImage.
+ *
+ * @return the width of this VolatileImage.
+ */
+ public abstract int getWidth();
+
+ /**
+ * Validates the drawing surface of the image if the surface had been
+ * lost and if the spacified GraphicsConfiguration object is
+ * applicable to this image.
+ *
+ * @param gc GraphicsConfiguration object.
+ *
+ * @return one of the image status constants: IMAGE_OK, IMAGE_RESTORED or
+ * IMAGE_INCOMPATIBLE.
+ */
+ public abstract int validate(GraphicsConfiguration gc);
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public Graphics getGraphics() {
+ return createGraphics();
+ }
+
+ @Override
+ public ImageProducer getSource() {
+ return getSnapshot().getSource();
+ }
+
+ public int getTransparency() {
+ return transparency;
+ }
+}
diff --git a/awt/java/awt/image/WritableRaster.java b/awt/java/awt/image/WritableRaster.java
new file mode 100644
index 0000000..0893915
--- /dev/null
+++ b/awt/java/awt/image/WritableRaster.java
@@ -0,0 +1,516 @@
+/*
+ * 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.Point;
+import java.awt.Rectangle;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The WritableRaster class provides functionality for
+ * writing samples and pixel capabilities to the Raster.
+ */
+public class WritableRaster extends Raster {
+
+ /**
+ * Instantiates a new WritableRaster object with the specified
+ * SampleModel, DataBuffer, rectangular region and parent
+ * WritableRaster.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param dataBuffer the specified DataBuffer.
+ * @param aRegion the rectangular region which defines the new image bounds.
+ * @param sampleModelTranslate this point defines the translation point
+ * from the SampleModel to the new WritableRaster coordinates.
+ * @param parent the parent of this WritableRaster.
+ */
+ protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Rectangle aRegion, Point sampleModelTranslate,
+ WritableRaster parent) {
+ super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
+ }
+
+ /**
+ * Instantiates a new WritableRaster object with the specified
+ * SampleModel which defines a layout of this WritableRaster and
+ * DataBuffer objects which defines the image data.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param dataBuffer the specified DataBuffer.
+ * @param origin the point of origin.
+ */
+ protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin) {
+ this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+ sampleModel.width, sampleModel.height), origin, null);
+ }
+
+ /**
+ * Instantiates a new WritableRaster with the specified SampleModel.
+ *
+ * @param sampleModel the specified SampleModel.
+ * @param origin the origin.
+ */
+ protected WritableRaster(SampleModel sampleModel, Point origin) {
+ this(sampleModel, sampleModel.createDataBuffer(), new Rectangle(
+ origin.x, origin.y, sampleModel.width, sampleModel.height),
+ origin, null);
+ }
+
+ /**
+ * Sets the data for a single pixel from an input Object which
+ * represents an array of primitive types: DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param inData the input data.
+ */
+ public void setDataElements(int x, int y, Object inData) {
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, inData, dataBuffer);
+ }
+
+ /**
+ * Sets the data elements which represent pixel data to the specified
+ * rectangle area as a primitive array. The following image data types
+ * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE.
+ *
+ * @param x the X coordinate of the rectangle of pixels.
+ * @param y the Y coordinate of the rectangle of pixels.
+ * @param w the width of the rectangle of pixels.
+ * @param h the height of the rectangle of pixels.
+ * @param inData the array of primitive type data to be set to the
+ * specified area.
+ */
+ public void setDataElements(int x, int y, int w, int h, Object inData) {
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, inData, dataBuffer);
+ }
+
+ /**
+ * Creates the child of this WritableRaster by sharing the specified
+ * rectangular area in this WritableRaster.
+ * The parentX, parentY, width and height parameters specify rectangular
+ * area to be shared.
+ *
+ * @param parentX the X coordinate of the upper left corner of
+ * the shared rectangle with respect to this WritableRaster' coordinates.
+ * @param parentY the Y coordinate of the upper left corner of
+ * the shared rectangle with respect to this WritableRaster' coordinates.
+ * @param w the width of the child area.
+ * @param h the height of the child area.
+ * @param childMinX the X coordinate of child area mapped to the parentX
+ * coordinate.
+ * @param childMinY the Y coordinate of child area mapped to the parentY
+ * coordinate.
+ * @param bandList the array of band indicies.
+ *
+ * @return the child WritableRaster.
+ */
+ public WritableRaster createWritableChild(int parentX, int parentY, int w,
+ int h, int childMinX, int childMinY, int bandList[]) {
+ if (w <= 0 || h <= 0) {
+ // awt.244=Width or Height of child Raster is less than or equal to zero
+ throw new RasterFormatException(Messages.getString("awt.244")); //$NON-NLS-1$
+ }
+
+ if (parentX < this.minX || parentX + w > this.minX + this.width) {
+ // awt.245=parentX disposes outside Raster
+ throw new RasterFormatException(Messages.getString("awt.245")); //$NON-NLS-1$
+ }
+
+ if (parentY < this.minY || parentY + h > this.minY + this.height) {
+ // awt.246=parentY disposes outside Raster
+ throw new RasterFormatException(Messages.getString("awt.246")); //$NON-NLS-1$
+ }
+
+ if ((long) parentX + w > Integer.MAX_VALUE) {
+ // awt.247=parentX + w results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.247")); //$NON-NLS-1$
+ }
+
+ if ((long) parentY + h > Integer.MAX_VALUE) {
+ // awt.248=parentY + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.248")); //$NON-NLS-1$
+ }
+
+ if ((long) childMinX + w > Integer.MAX_VALUE) {
+ // awt.249=childMinX + w results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.249")); //$NON-NLS-1$
+ }
+
+ if ((long) childMinY + h > Integer.MAX_VALUE) {
+ // awt.24A=childMinY + h results in integer overflow
+ throw new RasterFormatException(Messages.getString("awt.24A")); //$NON-NLS-1$
+ }
+
+ SampleModel childModel;
+
+ if (bandList == null) {
+ childModel = sampleModel;
+ } else {
+ childModel = sampleModel.createSubsetSampleModel(bandList);
+ }
+
+ int childTranslateX = childMinX - parentX;
+ int childTranslateY = childMinY - parentY;
+
+ return new WritableRaster(childModel, dataBuffer,
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(childTranslateX + sampleModelTranslateX,
+ childTranslateY + sampleModelTranslateY),
+ this);
+ }
+
+ /**
+ * Creates the translated child of this WritableRaster.
+ * New WritableRaster object is a reference to the this
+ * WritableRaster and with different location.
+ *
+ * @param childMinX the X coordinate of the new WritableRaster.
+ * @param childMinY the Y coordinate of the new WritableRaster.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster createWritableTranslatedChild(int childMinX,
+ int childMinY) {
+ return createWritableChild(minX, minY, width, height, childMinX,
+ childMinY, null);
+ }
+
+ /**
+ * Gets the parent WritableRaster for this WritableRaster object.
+ *
+ * @return the parent WritableRaster for this WritableRaster object.
+ */
+ public WritableRaster getWritableParent() {
+ return (WritableRaster) parent;
+ }
+
+ /**
+ * Sets pixels from the specified source Raster srcRaster to this
+ * WritableRaster.
+ *
+ * @param srcRaster the source Raster.
+ */
+ public void setRect(Raster srcRaster) {
+ setRect(0, 0, srcRaster);
+ }
+
+ /**
+ * Sets pixels from the specified source Raster srcRaster to this
+ * WritableRaster. Each pixel with (x, y) coordinates from the source
+ * Raster is copied to pixel with (x+dx, y+dy) coordinates in this
+ * WritableRaster. The pixels with (x+dx, y+dy) coordinates which
+ * are out the bounds of this raster are ignored.
+ *
+ * @param dx the distance the pixel's X coordinate in the source
+ * Raster is translated when writtien to this WritableRaster.
+ * @param dy the distance the pixel's Y coordinate in the source
+ * Raster is translated when writtien to this WritableRaster.
+ * @param srcRaster the source Raster.
+ */
+ public void setRect(int dx, int dy, Raster srcRaster) {
+ int w = srcRaster.getWidth();
+ int h = srcRaster.getHeight();
+
+ int srcX = srcRaster.getMinX();
+ int srcY = srcRaster.getMinY();
+
+ int dstX = srcX + dx;
+ int dstY = srcY + dy;
+
+ if (dstX < this.minX) {
+ int minOffX = this.minX - dstX;
+ w -= minOffX;
+ dstX = this.minX;
+ srcX += minOffX;
+ }
+
+ if (dstY < this.minY) {
+ int minOffY = this.minY - dstY;
+ h -= minOffY;
+ dstY = this.minY;
+ srcY += minOffY;
+ }
+
+ if (dstX + w > this.minX + this.width) {
+ int maxOffX = (dstX + w) - (this.minX + this.width);
+ w -= maxOffX;
+ }
+
+ if (dstY + h > this.minY + this.height) {
+ int maxOffY = (dstY + h) - (this.minY + this.height);
+ h -= maxOffY;
+ }
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ switch (sampleModel.getDataType()) {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ int iPixelsLine[] = null;
+ for (int i = 0; i < h; i++) {
+ iPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+ iPixelsLine);
+ setPixels(dstX, dstY + i, w, 1, iPixelsLine);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float fPixelsLine[] = null;
+ for (int i = 0; i < h; i++) {
+ fPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+ fPixelsLine);
+ setPixels(dstX, dstY + i, w, 1, fPixelsLine);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double dPixelsLine[] = null;
+ for (int i = 0; i < h; i++) {
+ dPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+ dPixelsLine);
+ setPixels(dstX, dstY + i, w, 1, dPixelsLine);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Sets the data for a rectangle of pixels from an input Raster to
+ * this WritableRaster.
+ *
+ * @param x the X coordinate of the point where the data of
+ * the input Raster is to be written.
+ * @param y the Y coordinate of the point where the data of
+ * the input Raster is to be written.
+ * @param inRaster the input Raster.
+ */
+ public void setDataElements(int x, int y, Raster inRaster) {
+ int dstX = x + inRaster.getMinX();
+ int dstY = y + inRaster.getMinY();
+
+ int w = inRaster.getWidth();
+ int h = inRaster.getHeight();
+
+ if (dstX < this.minX || dstX + w > this.minX + this.width ||
+ dstY < this.minY || dstY + h > this.minY + this.height) {
+ // awt.63=Coordinates are not in bounds
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+ }
+
+ int srcX = inRaster.getMinX();
+ int srcY = inRaster.getMinY();
+ Object line = null;
+
+ for (int i = 0; i < h; i++) {
+ line = inRaster.getDataElements(srcX, srcY + i, w, 1, line);
+ setDataElements(dstX, dstY + i, w, 1, line);
+ }
+ }
+
+ /**
+ * Sets a int array of samples for the specified pixel
+ * in this WritableRaster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param iArray the int array of samples.
+ */
+ public void setPixel(int x, int y, int iArray[]) {
+ sampleModel.setPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, iArray, dataBuffer);
+ }
+
+ /**
+ * Sets a float array of samples for the specified pixel
+ * in this WritableRaster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param fArray the float array of samples.
+ */
+ public void setPixel(int x, int y, float fArray[]) {
+ sampleModel.setPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, fArray, dataBuffer);
+ }
+
+ /**
+ * Sets a double array of samples for the specified pixel
+ * in this WritableRaster.
+ *
+ * @param x the pixel's X coordinate.
+ * @param y the pixel's Y coordinate.
+ * @param dArray the double array of samples.
+ */
+ public void setPixel(int x, int y, double dArray[]) {
+ sampleModel.setPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, dArray, dataBuffer);
+ }
+
+ /**
+ * Sets a int array of samples for the specified rectangular area
+ * of pixels in this WritableRaster.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ * @param iArray the int array of samples.
+ */
+ public void setPixels(int x, int y, int w, int h, int iArray[]) {
+ sampleModel.setPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, iArray, dataBuffer);
+ }
+
+ /**
+ * Sets a float array of samples for the specified rectangular area
+ * of pixels in this WritableRaster.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ * @param fArray the float array of samples.
+ */
+ public void setPixels(int x, int y, int w, int h, float fArray[]) {
+ sampleModel.setPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, fArray, dataBuffer);
+ }
+
+ /**
+ * Sets a double array of samples for the specified rectangular area
+ * of pixels in this WritableRaster.
+ *
+ * @param x the X coordinate of rectangular area.
+ * @param y the Y coordinate of rectangular area.
+ * @param w the width of rectangular area.
+ * @param h the height of rectangular area.
+ * @param dArray the double array of samples.
+ */
+ public void setPixels(int x, int y, int w, int h, double dArray[]) {
+ sampleModel.setPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, dArray, dataBuffer);
+ }
+
+ /**
+ * Sets the samples for the specified band and the specified
+ * rectangular area of pixels with an int array of samples.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param b the specified band.
+ * @param iArray the int array of samples.
+
+ */
+ public void setSamples(int x, int y, int w, int h, int b, int iArray[]) {
+ sampleModel.setSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
+ }
+
+ /**
+ * Sets the samples for the specified band and the specified
+ * rectangular area of pixels with a float array of samples.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param b the specified band.
+ * @param fArray the float array of samples.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, float fArray[]) {
+ sampleModel.setSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
+ }
+
+ /**
+ * Sets the samples for the specified band and the specified
+ * rectangular area of pixels with a double array of samples.
+ *
+ * @param x the X coordinate of the area of pixels.
+ * @param y the Y coordinate of the area of pixels.
+ * @param w the width of the area of pixels.
+ * @param h the height of the area of pixels.
+ * @param b the specified band.
+ * @param dArray the double array of samples.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, double dArray[]) {
+ sampleModel.setSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample for the specified band and the specified
+ * pixel with an int sample.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample to be set.
+ */
+ public void setSample(int x, int y, int b, int s) {
+ sampleModel.setSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, s, dataBuffer);
+ }
+
+ /**
+ * Sets the sample for the specified band and the specified
+ * pixel with a float sample.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample to be set.
+ */
+ public void setSample(int x, int y, int b, float s) {
+ sampleModel.setSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, s, dataBuffer);
+ }
+
+ /**
+ * Sets the sample for the specified band and the specified
+ * pixel with a int sample.
+ *
+ * @param x the X coordinate of the pixel.
+ * @param y the Y coordinate of the pixel.
+ * @param b the specified band.
+ * @param s the sample to be set.
+ */
+ public void setSample(int x, int y, int b, double s) {
+ sampleModel.setSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, s, dataBuffer);
+ }
+
+}
+
diff --git a/awt/java/awt/image/WritableRenderedImage.java b/awt/java/awt/image/WritableRenderedImage.java
new file mode 100644
index 0000000..ee1cb9e
--- /dev/null
+++ b/awt/java/awt/image/WritableRenderedImage.java
@@ -0,0 +1,101 @@
+/*
+ * 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.Point;
+
+/**
+ * The WriteableRenderedImage interface is interface for objects which
+ * contains Raster data of one or several tiles. This interface provides
+ * notification mehanism for obtaining tile's writing status.
+ */
+public interface WritableRenderedImage extends RenderedImage {
+
+ /**
+ * Gets and checks out the writable tile for writing.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ *
+ * @return the WritableRaster.
+ */
+ public WritableRaster getWritableTile(int tileX, int tileY);
+
+ /**
+ * Removes the registered TileObserver.
+ *
+ * @param to the TileObserver which is registered for this
+ * WritableRenderedImage.
+ */
+ public void removeTileObserver(TileObserver to);
+
+ /**
+ * Adds the specified TileObserver to this WritableRenderedImage.
+ *
+ * @param to the TileObserver object to be added.
+ */
+ public void addTileObserver(TileObserver to);
+
+ /**
+ * Sets this image to the contents of the specified Raster.
+ *
+ * @param r the specified Raster.
+ */
+ public void setData(Raster r);
+
+ /**
+ * Gets the array of points wich represent indices of tiles which
+ * are check out for writing.
+ *
+ * @return the array of Points.
+ */
+ public Point[] getWritableTileIndices();
+
+ /**
+ * Checks if the specified tile is writable or not.
+ *
+ * @param tileX the X index of tile.
+ * @param tileY the Y index of tile.
+ *
+ * @return true, if the specified tile is writable,
+ * false otherwise.
+ */
+ public boolean isTileWritable(int tileX, int tileY);
+
+ /**
+ * Release the specified writable tile. This method removes the writer
+ * from the tile.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ */
+ public void releaseWritableTile(int tileX, int tileY);
+
+ /**
+ * Checks if there is a tile which is checked out for writing.
+ *
+ * @return true, if any tile is checked out for writing, false if there
+ * is no such tile.
+ */
+ public boolean hasTileWriters();
+
+}
+
diff --git a/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java b/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java
new file mode 100644
index 0000000..3e96637
--- /dev/null
+++ b/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.renderable;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+
+/**
+ * A factory for creating ContextualRenderedImage objects with utilities
+ * for manipulating the properties in the parameter block.
+ */
+public interface ContextualRenderedImageFactory extends RenderedImageFactory {
+
+ /**
+ * Maps a render context to a parameter block and a renderable image.
+ *
+ * @param a0 the index
+ * @param a1 the RenderContext
+ * @param a2 the ParameterBlock
+ * @param a3 the RenderableImage
+ *
+ * @return the render context
+ */
+ public RenderContext mapRenderContext(int a0, RenderContext a1, ParameterBlock a2, RenderableImage a3);
+
+ /**
+ * Gets the value of the property from the parameter block.
+ *
+ * @param a0 the parameter block to examine to find the property
+ * @param a1 the name of the property
+ *
+ * @return the value of the property
+ */
+ public Object getProperty(ParameterBlock a0, String a1);
+
+ /**
+ * Creates the rendered image determined by the render context and
+ * parameter block.
+ *
+ * @param a0 the RenderContext
+ * @param a1 the ParameterBlock
+ *
+ * @return the rendered image
+ */
+ public RenderedImage create(RenderContext a0, ParameterBlock a1);
+
+ /**
+ * Gets the bounding rectangle from the parameter block.
+ *
+ * @param a0 the parameter block to read the bounds from
+ *
+ * @return the bounding rectangle
+ */
+ public Rectangle2D getBounds2D(ParameterBlock a0);
+
+ /**
+ * Gets the names of all of the supported properties.
+ *
+ * @return the property names
+ */
+ public String[] getPropertyNames();
+
+ /**
+ * Checks if this image factory is dynamic.
+ *
+ * @return true, if this image factory is dynamic
+ */
+ public boolean isDynamic();
+
+}
+
diff --git a/awt/java/awt/image/renderable/ParameterBlock.java b/awt/java/awt/image/renderable/ParameterBlock.java
new file mode 100644
index 0000000..1555f45
--- /dev/null
+++ b/awt/java/awt/image/renderable/ParameterBlock.java
@@ -0,0 +1,548 @@
+/*
+ * 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.renderable;
+
+import java.awt.image.RenderedImage;
+import java.io.Serializable;
+import java.util.Vector;
+
+/**
+ * The Class ParameterBlock groups an indexed set of parameter data
+ * with a set of renderable (source) images. The mapping between
+ * the indexed parameters and their property names is provided
+ * by a {@link ContextualRenderedImageFactory}
+ */
+public class ParameterBlock implements Cloneable, Serializable {
+
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = -7577115551785240750L;
+
+ /** The sources (renderable images). */
+ protected Vector<Object> sources = new Vector<Object>();
+
+ /** The parameters. */
+ protected Vector<Object> parameters = new Vector<Object>();
+
+ /**
+ * Instantiates a new parameter block.
+ *
+ * @param sources the vector of source images
+ * @param parameters the vector of parameters
+ */
+ public ParameterBlock(Vector<Object> sources, Vector<Object> parameters) {
+ setSources(sources);
+ setParameters(parameters);
+ }
+
+ /**
+ * Instantiates a new parameter block with no parameters.
+ *
+ * @param sources the vector of source images
+ */
+ public ParameterBlock(Vector<Object> sources) {
+ setSources(sources);
+ }
+
+ /**
+ * Instantiates a new parameter block with no image or parameter vectors.
+ */
+ public ParameterBlock() {}
+
+ /**
+ * Sets the source image at the specified index.
+ *
+ * @param source the source image
+ * @param index the index where the source will be placed
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock setSource(Object source, int index) {
+ if(sources.size() < index + 1){
+ sources.setSize(index + 1);
+ }
+ sources.setElementAt(source, index);
+ return this;
+ }
+
+ /**
+ * Sets the parameter value object at the specified index.
+ *
+ * @param obj the parameter value to place at the desired index
+ * @param index the index where the object is to be placed in the
+ * vector of parameters
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(Object obj, int index) {
+ if(parameters.size() < index + 1){
+ parameters.setSize(index + 1);
+ }
+ parameters.setElementAt(obj, index);
+ return this;
+ }
+
+ /**
+ * Adds a source to the vector of sources.
+ *
+ * @param source the source to add
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock addSource(Object source) {
+ sources.addElement(source);
+ return this;
+ }
+
+ /**
+ * Adds the object to the vector of parameter values
+ *
+ * @param obj the obj to add
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(Object obj) {
+ parameters.addElement(obj);
+ return this;
+ }
+
+ /**
+ * Sets the vector of sources, replacing the existing
+ * vector of sources, if any.
+ *
+ * @param sources the new sources
+ */
+ public void setSources(Vector<Object> sources) {
+ this.sources = sources;
+ }
+
+ /**
+ * Sets the vector of parameters, replacing the existing
+ * vector of parameters, if any.
+ *
+ * @param parameters the new parameters
+ */
+ public void setParameters(Vector<Object> parameters) {
+ this.parameters = parameters;
+ }
+
+ /**
+ * Gets the vector of sources.
+ *
+ * @return the sources
+ */
+ public Vector<Object> getSources() {
+ return sources;
+ }
+
+ /**
+ * Gets the vector of parameters.
+ *
+ * @return the parameters
+ */
+ public Vector<Object> getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Gets the source at the specified index.
+ *
+ * @param index the index
+ *
+ * @return the source object found at the specified index
+ */
+ public Object getSource(int index) {
+ return sources.elementAt(index);
+ }
+
+ /**
+ * Gets the object parameter found at the specified index.
+ *
+ * @param index the index
+ *
+ * @return the parameter object found at the specified index
+ */
+ public Object getObjectParameter(int index) {
+ return parameters.elementAt(index);
+ }
+
+ /**
+ * Shallow clone (clones using the superclass clone method).
+ *
+ * @return the clone of this object
+ */
+ public Object shallowClone() {
+ try{
+ return super.clone();
+ }catch(Exception e){
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object clone() {
+ ParameterBlock replica;
+ try{
+ replica = (ParameterBlock)super.clone();
+ }catch(Exception e){
+ return null;
+ }
+ if(sources != null){
+ replica.setSources((Vector<Object>)(sources.clone()));
+ }
+ if(parameters != null){
+ replica.setParameters((Vector<Object>)(parameters.clone()));
+ }
+ return replica;
+ }
+
+ /**
+ * Gets an array of classes corresponding to all of the parameter
+ * values found in the array of parameters, in order.
+ *
+ * @return the parameter classes
+ */
+ public Class[] getParamClasses() {
+ int count = parameters.size();
+ Class paramClasses[] = new Class[count];
+
+ for(int i = 0; i < count; i++){
+ paramClasses[i] = parameters.elementAt(i).getClass();
+ }
+ return paramClasses;
+ }
+
+ /**
+ * Gets the renderable source image found at the specified index
+ * in the source array.
+ *
+ * @param index the index
+ *
+ * @return the renderable source image
+ */
+ public RenderableImage getRenderableSource(int index) {
+ return (RenderableImage)sources.elementAt(index);
+ }
+
+ /**
+ * Wraps the short value in a Short and places it in the
+ * parameter block at the specified index.
+ *
+ * @param s the short value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(short s, int index) {
+ return set(new Short(s), index);
+ }
+
+ /**
+ * Wraps the short value in a Short and adds it to the
+ * parameter block.
+ *
+ * @param s the short value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(short s) {
+ return add(new Short(s));
+ }
+
+ /**
+ * Wraps the long value in a Long and places it in the
+ * parameter block at the specified index.
+ *
+ * @param l the long value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(long l, int index) {
+ return set(new Long(l), index);
+ }
+
+ /**
+ * Wraps the long value in a Long and adds it to the
+ * parameter block.
+ *
+ * @param l the long value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(long l) {
+ return add(new Long(l));
+ }
+
+ /**
+ * Wraps the int value in an Integer and places it in the
+ * parameter block at the specified index.
+ *
+ * @param i the int value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(int i, int index) {
+ return set(new Integer(i), index);
+ }
+
+ /**
+ * Wraps the int value in an Integer and adds it to the
+ * parameter block.
+ *
+ * @param i the int value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(int i) {
+ return add(new Integer(i));
+ }
+
+ /**
+ * Wraps the float value in a Float and places it in the
+ * parameter block at the specified index.
+ *
+ * @param f the float value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(float f, int index) {
+ return set(new Float(f), index);
+ }
+
+ /**
+ * Wraps the float value in a Float and adds it to the
+ * parameter block.
+ *
+ * @param f the float value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(float f) {
+ return add(new Float(f));
+ }
+
+ /**
+ * Wraps the double value in a Double and places it in the
+ * parameter block at the specified index.
+ *
+ * @param d the double value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(double d, int index) {
+ return set(new Double(d), index);
+ }
+
+ /**
+ * Wraps the double value in a Double and adds it to the
+ * parameter block.
+ *
+ * @param d the double value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(double d) {
+ return add(new Double(d));
+ }
+
+ /**
+ * Wraps the char value in a Character and places it in the
+ * parameter block at the specified index.
+ *
+ * @param c the char value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(char c, int index) {
+ return set(new Character(c), index);
+ }
+
+ /**
+ * Wraps the char value in a Character and adds it to the
+ * parameter block.
+ *
+ * @param c the char value of the parameter
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock add(char c) {
+ return add(new Character(c));
+ }
+
+ /**
+ * Wraps the byte value in a Byte and places it in the
+ * parameter block at the specified index.
+ *
+ * @param b the byte value of the parameter
+ * @param index the index
+ *
+ * @return this parameter block
+ */
+ public ParameterBlock set(byte b, int index) {
+ return set(new Byte(b), index);
+ }
+
+ /**
+ * Wraps the byte value in a Byte and adds it to the
+ * parameter block.
+ *
+ * @param b the byte value of the parameter
+ *
+ * @return the parameter block
+ */
+ public ParameterBlock add(byte b) {
+ return add(new Byte(b));
+ }
+
+ /**
+ * Gets the RenderedImage at the specified index from the
+ * vector of source images.
+ *
+ * @param index the index
+ *
+ * @return the rendered image
+ */
+ public RenderedImage getRenderedSource(int index) {
+ return (RenderedImage)sources.elementAt(index);
+ }
+
+ /**
+ * Gets the short-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the short parameter
+ */
+ public short getShortParameter(int index) {
+ return ((Short)parameters.elementAt(index)).shortValue();
+ }
+
+ /**
+ * Gets the long-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the long parameter
+ */
+ public long getLongParameter(int index) {
+ return ((Long)parameters.elementAt(index)).longValue();
+ }
+
+ /**
+ * Gets the int-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the int parameter
+ */
+ public int getIntParameter(int index) {
+ return ((Integer)parameters.elementAt(index)).intValue();
+ }
+
+ /**
+ * Gets the float-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the float parameter
+ */
+ public float getFloatParameter(int index) {
+ return ((Float)parameters.elementAt(index)).floatValue();
+ }
+
+ /**
+ * Gets the double-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the double parameter
+ */
+ public double getDoubleParameter(int index) {
+ return ((Double)parameters.elementAt(index)).doubleValue();
+ }
+
+ /**
+ * Gets the char-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the char parameter
+ */
+ public char getCharParameter(int index) {
+ return ((Character)parameters.elementAt(index)).charValue();
+ }
+
+ /**
+ * Gets the byte-valued parameter found at the desired index
+ * in the vector of parameter values.
+ *
+ * @param index the index
+ *
+ * @return the byte parameter
+ */
+ public byte getByteParameter(int index) {
+ return ((Byte)parameters.elementAt(index)).byteValue();
+ }
+
+ /**
+ * Clears the vector of sources.
+ */
+ public void removeSources() {
+ sources.removeAllElements();
+ }
+
+ /**
+ * Clears the vector of parameters.
+ */
+ public void removeParameters() {
+ parameters.removeAllElements();
+ }
+
+ /**
+ * Gets the number of elements in the vector of sources.
+ *
+ * @return the number of elements in the vector of sources
+ */
+ public int getNumSources() {
+ return sources.size();
+ }
+
+ /**
+ * Gets the number of elements in the vector of parameters.
+ *
+ * @return the number of elements in the vector of parameters
+ */
+ public int getNumParameters() {
+ return parameters.size();
+ }
+}
diff --git a/awt/java/awt/image/renderable/RenderContext.java b/awt/java/awt/image/renderable/RenderContext.java
new file mode 100644
index 0000000..3a3b93c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderContext.java
@@ -0,0 +1,196 @@
+/*
+ * 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.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+
+/**
+ * The Class RenderContext stores data on how an image is to be
+ * rendered: the affine transform, the area of interest, and
+ * the rendering hints.
+ */
+public class RenderContext implements Cloneable {
+
+ /** The affine transform. */
+ AffineTransform transform;
+
+ /** The area of interest. */
+ Shape aoi;
+
+ /** The rendering hints. */
+ RenderingHints hints;
+
+ /**
+ * Instantiates a new render context.
+ *
+ * @param usr2dev the affine transform
+ * @param aoi the area of interest
+ * @param hints the rendering hints
+ */
+ public RenderContext(AffineTransform usr2dev, Shape aoi, RenderingHints hints) {
+ this.transform = (AffineTransform)usr2dev.clone();
+ this.aoi = aoi;
+ this.hints = hints;
+ }
+
+ /**
+ * Instantiates a new render context with no specified hints.
+ *
+ * @param usr2dev the affine transform
+ * @param aoi the area of interest
+ */
+ public RenderContext(AffineTransform usr2dev, Shape aoi) {
+ this(usr2dev, aoi, null);
+ }
+
+ /**
+ * Instantiates a new render context with no specified area of interest.
+ *
+ * @param usr2dev the affine transform
+ * @param hints the rendering hints
+ */
+ public RenderContext(AffineTransform usr2dev, RenderingHints hints) {
+ this(usr2dev, null, hints);
+ }
+
+ /**
+ * Instantiates a new render context with no rendering hints or
+ * area of interest.
+ *
+ * @param usr2dev the affine transform
+ */
+ public RenderContext(AffineTransform usr2dev) {
+ this(usr2dev, null, null);
+ }
+
+ @Override
+ public Object clone() {
+ return new RenderContext(transform, aoi, hints);
+ }
+
+ /**
+ * Sets the affine transform for this render context.
+ *
+ * @param newTransform the new affine transform
+ */
+ public void setTransform(AffineTransform newTransform) {
+ transform = (AffineTransform)newTransform.clone();
+ }
+
+ /**
+ * Concatenates the current transform with the specified transform
+ * (so they are applied with the specified transform acting first)
+ * and sets the resulting transform as the affine transform of
+ * this rendering context.
+ *
+ * @param modTransform the new transform which modifies the
+ * current transform
+ *
+ * @deprecated use {@link RenderContext#preConcatenateTransform(AffineTransform)}
+ */
+ @Deprecated
+ public void preConcetenateTransform(AffineTransform modTransform) {
+ preConcatenateTransform(modTransform);
+ }
+
+ /**
+ * Concatenates the current transform with the specified transform
+ * (so they are applied with the specified transform acting first)
+ * and sets the resulting transform as the affine transform of
+ * this rendering context.
+ *
+ * @param modTransform the new transform which modifies the
+ * current transform
+ */
+ public void preConcatenateTransform(AffineTransform modTransform) {
+ transform.preConcatenate(modTransform);
+ }
+
+ /**
+ * Concatenate the specified transform with the current transform.
+ *
+ * @param modTransform the new transform which modifies the
+ * current transform
+ *
+ * @deprecated use {@link RenderContext#concatenateTransform(AffineTransform)}
+ */
+ @Deprecated
+ public void concetenateTransform(AffineTransform modTransform) {
+ concatenateTransform(modTransform);
+ }
+
+ /**
+ * Concatenate the specified transform with the current transform.
+ *
+ * @param modTransform the new transform which modifies the
+ * current transform
+ */
+ public void concatenateTransform(AffineTransform modTransform) {
+ transform.concatenate(modTransform);
+ }
+
+ /**
+ * Gets the transform.
+ *
+ * @return the transform
+ */
+ public AffineTransform getTransform() {
+ return (AffineTransform)transform.clone();
+ }
+
+ /**
+ * Sets the area of interest.
+ *
+ * @param newAoi the new area of interest
+ */
+ public void setAreaOfInterest(Shape newAoi) {
+ aoi = newAoi;
+ }
+
+ /**
+ * Gets the area of interest.
+ *
+ * @return the area of interest
+ */
+ public Shape getAreaOfInterest() {
+ return aoi;
+ }
+
+ /**
+ * Sets the rendering hints.
+ *
+ * @param hints the new rendering hints
+ */
+ public void setRenderingHints(RenderingHints hints) {
+ this.hints = hints;
+ }
+
+ /**
+ * Gets the rendering hints.
+ *
+ * @return the rendering hints
+ */
+ public RenderingHints getRenderingHints() {
+ return hints;
+ }
+}
diff --git a/awt/java/awt/image/renderable/RenderableImage.java b/awt/java/awt/image/renderable/RenderableImage.java
new file mode 100644
index 0000000..885dc06
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImage.java
@@ -0,0 +1,132 @@
+/*
+ * 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.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+/**
+ * The Interface RenderableImage is implemented by an object that
+ * collects all of the image-specific data that defines a single image
+ * that could be rendered to different rendering targets.
+ */
+public interface RenderableImage {
+
+ /** The Constant HINTS_OBSERVED indicates that the rendering
+ * hints are applied rather than ignored. */
+ public static final String HINTS_OBSERVED = "HINTS_OBSERVED"; //$NON-NLS-1$
+
+ /**
+ * Gets the property from the RenderableImage's parameter block.
+ *
+ * @param name the name of the property to get.
+ *
+ * @return the value of the property
+ */
+ public Object getProperty(String name);
+
+ /**
+ * Creates the rendered image based on the information contained
+ * in the parameters and the render context.
+ *
+ * @param renderContext the render context giving rendering specifications
+ * such as transformations
+ *
+ * @return the rendered image
+ */
+ public RenderedImage createRendering(RenderContext renderContext);
+
+ /**
+ * Creates the scaled rendered image based on the information contained
+ * in the parameters and the render context.
+ *
+ * @param w the desired width after scaling or zero if the scaling
+ * should be proportional, based on the height
+ * @param h the desired height after scaling or zero if the scaling
+ * should be proportional, based on the width
+ * @param hints the rendering hints to use
+ *
+ * @return the rendered image
+ *
+ * @throws IllegalArgumentException if both the height and width are zero
+ */
+ public RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
+
+ /**
+ * Gets the vector of sources from the parameter block.
+ *
+ * @return the sources
+ */
+ public Vector<RenderableImage> getSources();
+
+ /**
+ * Gets the names of all of the supported properties in the current context.
+ *
+ * @return the property names
+ */
+ public String[] getPropertyNames();
+
+ /**
+ * Creates the default rendering (using the identity transform
+ * and default render context).
+ *
+ * @return the rendered image
+ */
+ public RenderedImage createDefaultRendering();
+
+ /**
+ * Checks if this context supports dynamic rendering.
+ *
+ * @return true, if this context supports dynamic rendering
+ */
+ public boolean isDynamic();
+
+ /**
+ * Gets the width of the image.
+ *
+ * @return the width of the image
+ */
+ public float getWidth();
+
+ /**
+ * Gets the y coordinate of the upper left corner.
+ *
+ * @return the y coordinate of the upper left corner
+ */
+ public float getMinY();
+
+ /**
+ * Gets the x coordinate of the upper left corner.
+ *
+ * @return the x coordinate of the upper left corner
+ */
+ public float getMinX();
+
+ /**
+ * Gets the height of the image.
+ *
+ * @return the height of the image
+ */
+ public float getHeight();
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderableImageOp.java b/awt/java/awt/image/renderable/RenderableImageOp.java
new file mode 100644
index 0000000..993ba5f
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImageOp.java
@@ -0,0 +1,182 @@
+/*
+ * 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.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class RenderableImageOp is a basic implementation of RenderableImage,
+ * with methods to access the parameter data and perform rendering
+ * operations.
+ */
+public class RenderableImageOp implements RenderableImage {
+
+ /** The CRIF. */
+ ContextualRenderedImageFactory CRIF;
+
+ /** The param block. */
+ ParameterBlock paramBlock;
+
+ /** The height. */
+ float minX, minY, width, height;
+
+ /**
+ * Instantiates a new renderable image op.
+ *
+ * @param CRIF the cRIF
+ * @param paramBlock the param block
+ */
+ public RenderableImageOp(ContextualRenderedImageFactory CRIF, ParameterBlock paramBlock) {
+ this.CRIF = CRIF;
+ this.paramBlock = (ParameterBlock) paramBlock.clone();
+ Rectangle2D r = CRIF.getBounds2D(paramBlock);
+ minX = (float) r.getMinX();
+ minY = (float) r.getMinY();
+ width = (float) r.getWidth();
+ height = (float) r.getHeight();
+ }
+
+ public Object getProperty(String name) {
+ return CRIF.getProperty(paramBlock, name);
+ }
+
+ /**
+ * Sets the parameter block.
+ *
+ * @param paramBlock the param block
+ *
+ * @return the parameter block
+ */
+ public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
+ ParameterBlock oldParam = this.paramBlock;
+ this.paramBlock = (ParameterBlock) paramBlock.clone();
+ return oldParam;
+ }
+
+ public RenderedImage createRendering(RenderContext renderContext) {
+
+ Vector<RenderableImage> sources = getSources();
+ ParameterBlock rdParam = (ParameterBlock) paramBlock.clone();
+
+ if (sources != null) {
+ Vector<Object> rdSources = new Vector<Object>();
+ int i = 0;
+ while (i < sources.size()) {
+ RenderContext newContext = CRIF.mapRenderContext(i, renderContext, paramBlock,
+ this);
+ RenderedImage rdim = sources.elementAt(i).createRendering(newContext);
+
+ if (rdim != null) {
+ rdSources.addElement(rdim);
+ }
+ i++;
+ }
+ if (rdSources.size() > 0) {
+ rdParam.setSources(rdSources);
+ }
+ }
+ return CRIF.create(renderContext, rdParam);
+ }
+
+ public RenderedImage createScaledRendering(int w, int h, RenderingHints hints) {
+ if(w == 0 && h == 0) {
+ // awt.60=Width and Height mustn't be equal zero both
+ throw new IllegalArgumentException(Messages.getString("awt.60")); //$NON-NLS-1$
+ }
+ if(w == 0){
+ w = Math.round(h*(getWidth()/getHeight()));
+ }
+
+ if(h == 0){
+ h = Math.round(w*(getHeight()/getWidth()));
+ }
+
+ double sx = (double)w/getWidth();
+ double sy = (double)h/getHeight();
+
+ AffineTransform at = AffineTransform.getScaleInstance(sx, sy);
+ RenderContext context = new RenderContext(at, hints);
+ return createRendering(context);
+ }
+
+ public Vector<RenderableImage> getSources() {
+ if(paramBlock.getNumSources() == 0) {
+ return null;
+ }
+ Vector<RenderableImage> v = new Vector<RenderableImage>();
+ int i = 0;
+ while(i < paramBlock.getNumSources()){
+ Object o = paramBlock.getSource(i);
+ if(o instanceof RenderableImage){
+ v.addElement((RenderableImage) o);
+ }
+ i++;
+ }
+ return v;
+ }
+
+ public String[] getPropertyNames() {
+ return CRIF.getPropertyNames();
+ }
+
+ /**
+ * Gets the parameter block.
+ *
+ * @return the parameter block
+ */
+ public ParameterBlock getParameterBlock() {
+ return paramBlock;
+ }
+
+ public RenderedImage createDefaultRendering() {
+ AffineTransform at = new AffineTransform();
+ RenderContext context = new RenderContext(at);
+ return createRendering(context);
+ }
+
+ public boolean isDynamic() {
+ return CRIF.isDynamic();
+ }
+
+ public float getWidth() {
+ return width;
+ }
+
+ public float getMinY() {
+ return minY;
+ }
+
+ public float getMinX() {
+ return minX;
+ }
+
+ public float getHeight() {
+ return height;
+ }
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderableImageProducer.java b/awt/java/awt/image/renderable/RenderableImageProducer.java
new file mode 100644
index 0000000..7fda98c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImageProducer.java
@@ -0,0 +1,141 @@
+/*
+ * 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.renderable;
+
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+/**
+ * The Class RenderableImageProducer provides the implementation for
+ * the image rendering.
+ */
+public class RenderableImageProducer implements ImageProducer, Runnable {
+
+ /** The rbl. */
+ RenderableImage rbl;
+
+ /** The rc. */
+ RenderContext rc;
+
+ /** The consumers. */
+ Vector<ImageConsumer> consumers = new Vector<ImageConsumer>();
+
+ /**
+ * Instantiates a new renderable image producer.
+ *
+ * @param rdblImage the rdbl image
+ * @param rc the rc
+ */
+ public RenderableImageProducer(RenderableImage rdblImage, RenderContext rc) {
+ this.rbl = rdblImage;
+ this.rc = rc;
+ }
+
+ /**
+ * Sets the render context.
+ *
+ * @param rc the new render context
+ */
+ public synchronized void setRenderContext(RenderContext rc) {
+ this.rc = rc;
+ }
+
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ return consumers.contains(ic);
+ }
+
+ public synchronized void startProduction(ImageConsumer ic) {
+ addConsumer(ic);
+ Thread t = new Thread(this, "RenderableImageProducer thread"); //$NON-NLS-1$
+ t.start();
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {}
+
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ if(ic != null) {
+ consumers.removeElement(ic);
+ }
+ }
+
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if(ic != null && !consumers.contains(ic)){
+ consumers.addElement(ic);
+ }
+ }
+
+ /**
+ * Creates the rendered image in a new thread.
+ */
+ public void run() {
+ if(rbl == null) {
+ return;
+ }
+
+ RenderedImage rd;
+ if(rc != null) {
+ rd = rbl.createRendering(rc);
+ } else {
+ rd = rbl.createDefaultRendering();
+ }
+
+ ColorModel cm = rd.getColorModel();
+ if(cm == null) {
+ cm = ColorModel.getRGBdefault();
+ }
+
+ Raster r = rd.getData();
+ int w = r.getWidth();
+ int h = r.getHeight();
+
+ for (ImageConsumer c : consumers) {
+ c.setDimensions(w, h);
+ c.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
+ ImageConsumer.COMPLETESCANLINES |
+ ImageConsumer.SINGLEFRAME |
+ ImageConsumer.SINGLEPASS);
+ }
+
+ int scanLine[] = new int[w];
+ int pixel[] = null;
+
+ for(int y = 0; y < h; y++){
+ for(int x = 0; x < w; x++){
+ pixel = r.getPixel(x, y, pixel);
+ scanLine[x] = cm.getDataElement(pixel, 0);
+ }
+
+ for (ImageConsumer c : consumers) {
+ c.setPixels(0, y, w, 1, cm, scanLine, 0, w);
+ }
+ }
+
+ for (ImageConsumer c : consumers) {
+ c.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderedImageFactory.java b/awt/java/awt/image/renderable/RenderedImageFactory.java
new file mode 100644
index 0000000..345d82c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderedImageFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+
+/**
+ * A factory for creating RenderedImage objects based on parameters
+ * and rendering hints.
+ */
+public interface RenderedImageFactory {
+
+ /**
+ * Creates the rendered image.
+ *
+ * @param a0 the ParameterBlock
+ * @param a1 the RenderingHints
+ *
+ * @return the rendered image
+ */
+ public RenderedImage create(ParameterBlock a0, RenderingHints a1);
+
+}
+