summaryrefslogtreecommitdiffstats
path: root/libjava/java/awt/image
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/awt/image')
-rw-r--r--libjava/java/awt/image/AffineTransformOp.java159
-rw-r--r--libjava/java/awt/image/BandCombineOp.java168
-rw-r--r--libjava/java/awt/image/BandedSampleModel.java537
-rw-r--r--libjava/java/awt/image/BufferedImage.java26
-rw-r--r--libjava/java/awt/image/BufferedImageFilter.java110
-rw-r--r--libjava/java/awt/image/ByteLookupTable.java18
-rw-r--r--libjava/java/awt/image/ColorConvertOp.java319
-rw-r--r--libjava/java/awt/image/ColorModel.java120
-rw-r--r--libjava/java/awt/image/ComponentColorModel.java38
-rw-r--r--libjava/java/awt/image/ComponentSampleModel.java85
-rw-r--r--libjava/java/awt/image/ConvolveOp.java341
-rw-r--r--libjava/java/awt/image/CropImageFilter.java5
-rw-r--r--libjava/java/awt/image/DataBuffer.java231
-rw-r--r--libjava/java/awt/image/DataBufferByte.java115
-rw-r--r--libjava/java/awt/image/DataBufferDouble.java115
-rw-r--r--libjava/java/awt/image/DataBufferFloat.java115
-rw-r--r--libjava/java/awt/image/DataBufferInt.java118
-rw-r--r--libjava/java/awt/image/DataBufferShort.java118
-rw-r--r--libjava/java/awt/image/DataBufferUShort.java118
-rw-r--r--libjava/java/awt/image/DirectColorModel.java20
-rw-r--r--libjava/java/awt/image/IndexColorModel.java239
-rw-r--r--libjava/java/awt/image/LookupOp.java252
-rw-r--r--libjava/java/awt/image/MemoryImageSource.java60
-rw-r--r--libjava/java/awt/image/MultiPixelPackedSampleModel.java387
-rw-r--r--libjava/java/awt/image/PackedColorModel.java6
-rw-r--r--libjava/java/awt/image/PixelGrabber.java70
-rw-r--r--libjava/java/awt/image/RGBImageFilter.java25
-rw-r--r--libjava/java/awt/image/Raster.java86
-rw-r--r--libjava/java/awt/image/RasterOp.java5
-rw-r--r--libjava/java/awt/image/RescaleOp.java218
-rw-r--r--libjava/java/awt/image/SampleModel.java11
-rw-r--r--libjava/java/awt/image/ShortLookupTable.java12
-rw-r--r--libjava/java/awt/image/SinglePixelPackedSampleModel.java12
33 files changed, 4057 insertions, 202 deletions
diff --git a/libjava/java/awt/image/AffineTransformOp.java b/libjava/java/awt/image/AffineTransformOp.java
index 6219635fa51..1326a61c043 100644
--- a/libjava/java/awt/image/AffineTransformOp.java
+++ b/libjava/java/awt/image/AffineTransformOp.java
@@ -1,6 +1,6 @@
/* AffineTransformOp.java -- This class performs affine
- * transformation between two images or rasters in 2
- * dimensions. Copyright (C) 2004 Free Software Foundation
+ transformation between two images or rasters in 2 dimensions.
+ Copyright (C) 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -38,30 +38,39 @@ exception statement from your version. */
package java.awt.image;
-import java.awt.*;
-import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.geom.*;
-
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
/**
* This class performs affine transformation between two images or
* rasters in 2 dimensions.
*
- * @author Olga Rodimina <rodimina@redhat.com>
+ * @author Olga Rodimina (rodimina@redhat.com)
*/
-
public class AffineTransformOp implements BufferedImageOp, RasterOp
{
- public static final int TYPE_BILINEAR = 0;
public static final int TYPE_NEAREST_NEIGHBOR = 1;
+
+ public static final int TYPE_BILINEAR = 2;
+
+ /**
+ * @since 1.5.0
+ */
+ public static final int TYPE_BICUBIC = 3;
private AffineTransform transform;
private RenderingHints hints;
/**
* Construct AffineTransformOp with the given xform and interpolationType.
- * Interpolation type can be either TYPE_BILINEAR or TYPE_NEAREST_NEIGHBOR.
+ * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or
+ * TYPE_NEAREST_NEIGHBOR.
*
* @param xform AffineTransform that will applied to the source image
* @param interpolationType type of interpolation used
@@ -69,15 +78,23 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
public AffineTransformOp (AffineTransform xform, int interpolationType)
{
this.transform = xform;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
- if (interpolationType == 0)
+ switch (interpolationType)
+ {
+ case TYPE_BILINEAR:
hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
-
- else
+ break;
+ case TYPE_BICUBIC:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ break;
+ default:
hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-
+ }
}
/**
@@ -90,6 +107,8 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
{
this.transform = xform;
this.hints = hints;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
}
/**
@@ -149,7 +168,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
* @param dst destination image
* @return transformed source image
*/
- public BufferedImage filter (BufferedImage src, BufferedImage dst)
+ public final BufferedImage filter (BufferedImage src, BufferedImage dst)
{
if (dst == src)
@@ -180,9 +199,99 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
* @param dst destination raster
* @return transformed raster
*/
- public WritableRaster filter (Raster src, WritableRaster dst)
+ public final WritableRaster filter (Raster src, WritableRaster dst)
{
- throw new UnsupportedOperationException ("not implemented yet");
+ if (dst == src)
+ throw new IllegalArgumentException("src image cannot be the same as"
+ + " the dst image");
+
+ if (dst == null)
+ dst = createCompatibleDestRaster(src);
+
+ if (src.getNumBands() != dst.getNumBands())
+ throw new IllegalArgumentException("src and dst must have same number"
+ + " of bands");
+
+ double[] dpts = new double[dst.getWidth() * 2];
+ double[] pts = new double[dst.getWidth() * 2];
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ dpts[2 * x] = x + dst.getMinX();
+ dpts[2 * x + 1] = x;
+ }
+ Rectangle srcbounds = src.getBounds();
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ {
+ for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
+ {
+ try {
+ transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
+ } catch (NoninvertibleTransformException e) {
+ // Can't happen since the constructor traps this
+ e.printStackTrace();
+ }
+
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
+ continue;
+ dst.setDataElements(x + dst.getMinX(), y,
+ src.getDataElements((int)pts[2 * x],
+ (int)pts[2 * x + 1],
+ null));
+ }
+ }
+ }
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ {
+ double[] tmp = new double[4 * src.getNumBands()];
+ for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
+ {
+ try {
+ transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
+ } catch (NoninvertibleTransformException e) {
+ // Can't happen since the constructor traps this
+ e.printStackTrace();
+ }
+
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
+ continue;
+ int xx = (int)pts[2 * x];
+ int yy = (int)pts[2 * x + 1];
+ double dx = (pts[2 * x] - xx);
+ double dy = (pts[2 * x + 1] - yy);
+
+ // TODO write this more intelligently
+ if (xx == src.getMinX() + src.getWidth() - 1 ||
+ yy == src.getMinY() + src.getHeight() - 1)
+ {
+ // bottom or right edge
+ Arrays.fill(tmp, 0);
+ src.getPixel(xx, yy, tmp);
+ }
+ else
+ {
+ // Normal case
+ src.getPixels(xx, yy, 2, 2, tmp);
+ for (int b = 0; b < src.getNumBands(); b++)
+ tmp[b] = dx * dy * tmp[b]
+ + (1 - dx) * dy * tmp[b + src.getNumBands()]
+ + dx * (1 - dy) * tmp[b + 2 * src.getNumBands()]
+ + (1 - dx) * (1 - dy) * tmp[b + 3 * src.getNumBands()];
+ }
+ dst.setPixel(x, y, tmp);
+ }
+ }
+ }
+ else
+ {
+ // Bicubic
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+ return dst;
}
/**
@@ -192,7 +301,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
* @param src image to be transformed
* @return bounds of the transformed image.
*/
- public Rectangle2D getBounds2D (BufferedImage src)
+ public final Rectangle2D getBounds2D (BufferedImage src)
{
return getBounds2D (src.getRaster());
}
@@ -203,7 +312,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
* @param src raster to be transformed
* @return bounds of the transformed raster.
*/
- public Rectangle2D getBounds2D (Raster src)
+ public final Rectangle2D getBounds2D (Raster src)
{
// determine new size for the transformed raster.
// Need to calculate transformed coordinates of the lower right
@@ -222,7 +331,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
*
* @return interpolation type
*/
- public int getInterpolationType ()
+ public final int getInterpolationType ()
{
if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR))
return TYPE_BILINEAR;
@@ -243,21 +352,23 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
return transform.transform (srcPt, dstPt);
}
- /** Returns rendering hints that are used during transformation.
+ /**
+ * Returns rendering hints that are used during transformation.
*
* @return rendering hints
*/
- public RenderingHints getRenderingHints ()
+ public final RenderingHints getRenderingHints ()
{
return hints;
}
- /** Returns transform used in transformation between source and destination
+ /**
+ * Returns transform used in transformation between source and destination
* image.
*
* @return transform
*/
- public AffineTransform getTransform ()
+ public final AffineTransform getTransform ()
{
return transform;
}
diff --git a/libjava/java/awt/image/BandCombineOp.java b/libjava/java/awt/image/BandCombineOp.java
new file mode 100644
index 00000000000..48c61c57026
--- /dev/null
+++ b/libjava/java/awt/image/BandCombineOp.java
@@ -0,0 +1,168 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Filter Raster pixels by applying a matrix.
+ *
+ * BandCombineOp applies a matrix to each pixel to produce new pixel values.
+ * The width of the matrix must be the same or one more than the number of
+ * bands in the source Raster. If one more, the pixels in the source are
+ * assumed to contain an implicit 1.0 at the end.
+ *
+ * The rows of the matrix are multiplied by the pixel to produce the values
+ * for the destination. Therefore the destination Raster must contain the
+ * same number of bands as the number of rows in the filter matrix.
+ *
+ * @author Jerry Quinn <jlquinn@optonline.net>
+ */
+public class BandCombineOp implements RasterOp
+{
+ private RenderingHints hints;
+ private float[][] matrix;
+
+ /**
+ * Construct a BandCombineOp.
+ *
+ * @param matrix The matrix to filter pixels with.
+ * @param hints Rendering hints to apply. Ignored.
+ */
+ public BandCombineOp(float[][] matrix, RenderingHints hints)
+ {
+ this.matrix = matrix;
+ this.hints = hints;
+ }
+
+ /**
+ * Filter Raster pixels through a matrix.
+ *
+ * Applies the Op matrix to source pixes to produce dest pixels. Each row
+ * of the matrix is multiplied by the src pixel components to produce the
+ * dest pixel. If matrix is one more than the number of bands in the src,
+ * the last element is implicitly multiplied by 1, i.e. added to the sum
+ * for that dest component.
+ *
+ * If dest is null, a suitable Raster is created. This implementation uses
+ * createCompatibleDestRaster.
+ *
+ * @param src The source Raster.
+ * @param dest The destination Raster, or null.
+ * @returns The destination Raster or an allocated Raster.
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
+ *java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest) {
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+
+ // Filter the pixels
+ float[] spix = new float[matrix[0].length];
+ float[] dpix = new float[matrix.length];
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // In case matrix rows have implicit translation
+ spix[spix.length - 1] = 1.0f;
+ src.getPixel(x, y, spix);
+ for (int i = 0; i < matrix.length; i++)
+ {
+ dpix[i] = 0;
+ for (int j = 0; j < matrix[0].length; j++)
+ dpix[i] += spix[j] * matrix[i][j];
+ }
+ dest.setPixel(x, y, dpix);
+ }
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /**
+ * Creates a new WritableRaster that can be used as the destination for this
+ * Op. This implementation creates a Banded Raster with data type FLOAT.
+ * @see
+ *java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return Raster.createBandedRaster(DataBuffer.TYPE_FLOAT, src.getWidth(),
+ src.getHeight(), matrix.length,
+ new Point(src.getMinX(), src.getMinY()));
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
+ *java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /** Return the matrix for this Op. */
+ public float[][] getMatrix()
+ {
+ return matrix;
+ }
+
+}
diff --git a/libjava/java/awt/image/BandedSampleModel.java b/libjava/java/awt/image/BandedSampleModel.java
new file mode 100644
index 00000000000..93252d9cce6
--- /dev/null
+++ b/libjava/java/awt/image/BandedSampleModel.java
@@ -0,0 +1,537 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * MultiPixelPackedSampleModel provides a single band model that supports
+ * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
+ * per data element.
+ *
+ * @author Jerry Quinn <jlquinn@optonline.net>
+ */
+public final class BandedSampleModel extends ComponentSampleModel
+{
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ public BandedSampleModel(int dataType, int w, int h, int numBands)
+ {
+ super(dataType, w, h, 1, w, new int[numBands]);
+ }
+
+ public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
+ int[] bankIndices, int[] bandOffsets)
+ {
+ super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ // NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs
+ // disagree.
+
+ // Compress offsets so minimum is 0, others w*scanlineStride
+ int[] newoffsets = new int[bandOffsets.length];
+ int[] order = new int[bandOffsets.length];
+ for (int i=0; i < bandOffsets.length; i++)
+ order[i] = i;
+ // FIXME: This is N^2, but not a big issue, unless there's a lot of
+ // bands...
+ for (int i=0; i < bandOffsets.length; i++)
+ for (int j=i+1; j < bandOffsets.length; i++)
+ if (bankIndices[order[i]] > bankIndices[order[j]]
+ || (bankIndices[order[i]] == bankIndices[order[j]]
+ && bandOffsets[order[i]] > bandOffsets[order[j]]))
+ {
+ int t = order[i]; order[i] = order[j]; order[j] = t;
+ }
+ int bank = 0;
+ int offset = 0;
+ for (int i=0; i < bandOffsets.length; i++)
+ {
+ if (bankIndices[order[i]] != bank)
+ {
+ bank = bankIndices[order[i]];
+ offset = 0;
+ }
+ newoffsets[order[i]] = offset;
+ offset += w * scanlineStride;
+ }
+
+ return new BandedSampleModel(dataType, w, h, scanlineStride, bankIndices, newoffsets);
+ }
+
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int[] newoff = new int[bands.length];
+ int[] newbanks = new int[bands.length];
+ for (int i=0; i < bands.length; i++)
+ {
+ int b = bands[i];
+ newoff[i] = bandOffsets[b];
+ newbanks[i] = bankIndices[b];
+ }
+
+ if (bands.length > bankIndices.length)
+ throw new
+ RasterFormatException("BandedSampleModel createSubsetSampleModel too"
+ +" many bands");
+
+ return new BandedSampleModel(dataType, width, height, scanlineStride,
+ newbanks, newoff);
+ }
+
+ /**
+ * Extract all samples of one pixel and return in an array of transfer type.
+ *
+ * Extracts the pixel at x, y from data and stores samples into the array
+ * obj. If obj is null, a new array of getTransferType() is created.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int pixel = getSample(x, y, 0, data);
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] b = (byte[])obj;
+ if (b == null) b = new byte[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = (byte)getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] b = (short[])obj;
+ if (b == null) b = new short[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = (short)getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ int[] b = (int[])obj;
+ if (b == null) b = new int[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ float[] b = (float[])obj;
+ if (b == null) b = new float[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = getSampleFloat(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ double[] b = (double[])obj;
+ if (b == null) b = new double[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[numBands];
+ for (int i=0; i < numBands; i++)
+ iArray[i] = getSample(x, y, 0, data);
+
+ return iArray;
+ }
+
+ /**
+ * Copy pixels from a region into an array.
+ *
+ * Copies the samples of the pixels in the rectangle starting at x, y that
+ * is w pixels wide and h scanlines high. When there is more than one band,
+ * the samples stored in order before the next pixel. This ordering isn't
+ * well specified in Sun's docs as of 1.4.2.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param iArray The int array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[w*h*numBands];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w;)
+ {
+ for (int b=0; b < numBands; b++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElem(bankIndices[b], offset);
+ }
+
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemFloat(bankIndices[b], offset);
+ }
+
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemDouble(bankIndices[b], offset);
+ }
+
+ /**
+ * Copy one band's samples from a region into an array.
+ *
+ * Copies from one band the samples of the pixels in the rectangle starting
+ * at x, y that is w pixels wide and h scanlines high.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param b The band to retrieve.
+ * @param iArray The int array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
+ DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[w*h];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w;)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ return iArray;
+ }
+
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @param x The x-coordinate of the data elements in <code>obj</code>.
+ * @param y The y-coordinate of the data elements in <code>obj</code>.
+ * @param obj The primitive array containing the data elements to set.
+ * @param data The DataBuffer to store the data elements into.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int transferType = getTransferType();
+ if (getTransferType() != data.getDataType())
+ {
+ throw new IllegalArgumentException("transfer type ("+
+ getTransferType()+"), "+
+ "does not match data "+
+ "buffer type (" +
+ data.getDataType() +
+ ").");
+ }
+
+ int offset = y * scanlineStride + x;
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] in = (short[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ DataBufferFloat out = (DataBufferFloat) data;
+ float[] in = (float[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ DataBufferDouble out = (DataBufferDouble) data;
+ double[] in = (double[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
+ return;
+ }
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements" +
+ ", x="+x+", y="+y+
+ ", width="+width+", height="+height+
+ ", scanlineStride="+scanlineStride+
+ ", offset="+offset+
+ ", data.getSize()="+data.getSize()+
+ ", data.getOffset()="+data.getOffset()+
+ ": " +
+ aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ for (int b=0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ iArray[b]);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = y * scanlineStride + (x + ww);
+ for (int b=0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + offset,
+ iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSample(int x, int y, int b, float s, DataBuffer data)
+ {
+ data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSample(int x, int y, int b, double s, DataBuffer data)
+ {
+ data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (byte)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ case DataBuffer.TYPE_DOUBLE:
+ break;
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+
+ // Default implementation probably slower for float and double
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ data.setElem(bankIndices[b], offset, iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/java/awt/image/BufferedImage.java b/libjava/java/awt/image/BufferedImage.java
index b18779af146..723eeeb77d8 100644
--- a/libjava/java/awt/image/BufferedImage.java
+++ b/libjava/java/awt/image/BufferedImage.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2002, 2003 Free Software Foundation
+/* BufferedImage.java --
+ Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,6 +38,8 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.ComponentDataBlitOp;
+
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
@@ -45,11 +48,10 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import java.util.Hashtable;
-import java.util.Vector;
import java.util.HashSet;
+import java.util.Hashtable;
import java.util.Iterator;
-import gnu.java.awt.ComponentDataBlitOp;
+import java.util.Vector;
/**
* A buffered image always starts at coordinates (0, 0).
@@ -59,7 +61,7 @@ import gnu.java.awt.ComponentDataBlitOp;
* height of the image. This tile is always considered to be checked
* out.
*
- * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class BufferedImage extends Image
implements WritableRenderedImage
@@ -79,20 +81,20 @@ public class BufferedImage extends Image
TYPE_BYTE_BINARY = 12,
TYPE_BYTE_INDEXED = 13;
- final static int[] bits3 = { 8, 8, 8 };
- final static int[] bits4 = { 8, 8, 8 };
- final static int[] bits1byte = { 8 };
- final static int[] bits1ushort = { 16 };
+ static final int[] bits3 = { 8, 8, 8 };
+ static final int[] bits4 = { 8, 8, 8 };
+ static final int[] bits1byte = { 8 };
+ static final int[] bits1ushort = { 16 };
- final static int[] masks_int = { 0x00ff0000,
+ static final int[] masks_int = { 0x00ff0000,
0x0000ff00,
0x000000ff,
DataBuffer.TYPE_INT };
- final static int[] masks_565 = { 0xf800,
+ static final int[] masks_565 = { 0xf800,
0x07e0,
0x001f,
DataBuffer.TYPE_USHORT};
- final static int[] masks_555 = { 0x7c00,
+ static final int[] masks_555 = { 0x7c00,
0x03e0,
0x001f,
DataBuffer.TYPE_USHORT};
diff --git a/libjava/java/awt/image/BufferedImageFilter.java b/libjava/java/awt/image/BufferedImageFilter.java
new file mode 100644
index 00000000000..8fa7d473f12
--- /dev/null
+++ b/libjava/java/awt/image/BufferedImageFilter.java
@@ -0,0 +1,110 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * The BufferedImageFilter class wraps BufferedImageOp objects in a Filter.
+ *
+ * When pixels are pushed through the filter, we create a BufferedImage,
+ * apply the BufferedImageOp, and pass the filtered pixels to the base class.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class BufferedImageFilter extends ImageFilter implements Cloneable
+{
+ private BufferedImageOp op;
+
+ /**
+ *
+ */
+ public BufferedImageFilter(BufferedImageOp op)
+ {
+ super();
+ if (op == null)
+ throw new NullPointerException("BufferedImageFilter null"
+ + " op in constructor");
+ this.op = op;
+ }
+
+ /**
+ * @return Returns the contained BufferedImageOp.
+ */
+ public BufferedImageOp getBufferedImageOp()
+ {
+ return op;
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how to
+ // create a compatible sample model that incorporates scansize != w. I
+ // asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferByte db = new DataBufferByte(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferByte)dbout).getData(), 0,
+ scansize);
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how
+ // to create a compatible sample model that incorporates
+ // scansize != w. I asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferInt db = new DataBufferInt(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferInt)dbout).getData(), 0,
+ scansize);
+ }
+}
diff --git a/libjava/java/awt/image/ByteLookupTable.java b/libjava/java/awt/image/ByteLookupTable.java
index 572f6e9212d..f0221915a71 100644
--- a/libjava/java/awt/image/ByteLookupTable.java
+++ b/libjava/java/awt/image/ByteLookupTable.java
@@ -61,7 +61,7 @@ public class ByteLookupTable extends LookupTable
*
* @param offset Offset to be subtracted.
* @param data Array of lookup tables.
- * @exception IllegalArgumentException if offset < 0 or data.length < 1.
+ * @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
*/
public ByteLookupTable(int offset, byte[][] data)
throws IllegalArgumentException
@@ -78,7 +78,7 @@ public class ByteLookupTable extends LookupTable
*
* @param offset Offset to be subtracted.
* @param data Lookup table for all components.
- * @exception IllegalArgumentException if offset < 0.
+ * @exception IllegalArgumentException if offset &lt; 0.
*/
public ByteLookupTable(int offset, byte[] data)
throws IllegalArgumentException
@@ -87,7 +87,11 @@ public class ByteLookupTable extends LookupTable
this.data = new byte[][] {data};
}
- /** Return the lookup tables. */
+ /**
+ * Return the lookup tables.
+ *
+ * @return the tables
+ */
public final byte[][] getTable()
{
return data;
@@ -107,14 +111,14 @@ public class ByteLookupTable extends LookupTable
* translation arrays.
*
* @param src Component values of a pixel.
- * @param dest Destination array for values, or null.
+ * @param dst Destination array for values, or null.
* @return Translated values for the pixel.
*/
public int[] lookupPixel(int[] src, int[] dst)
throws ArrayIndexOutOfBoundsException
{
if (dst == null)
- dst = new int[numComponents];
+ dst = new int[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
@@ -140,14 +144,14 @@ public class ByteLookupTable extends LookupTable
* translation arrays.
*
* @param src Component values of a pixel.
- * @param dest Destination array for values, or null.
+ * @param dst Destination array for values, or null.
* @return Translated values for the pixel.
*/
public byte[] lookupPixel(byte[] src, byte[] dst)
throws ArrayIndexOutOfBoundsException
{
if (dst == null)
- dst = new byte[numComponents];
+ dst = new byte[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
diff --git a/libjava/java/awt/image/ColorConvertOp.java b/libjava/java/awt/image/ColorConvertOp.java
new file mode 100644
index 00000000000..5fcb37cc7f0
--- /dev/null
+++ b/libjava/java/awt/image/ColorConvertOp.java
@@ -0,0 +1,319 @@
+/* ColorModel.java --
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+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;
+
+/**
+ * ColorConvertOp is a filter for converting an image from one colorspace to
+ * another colorspace. The filter can convert the image through a sequence
+ * of colorspaces or just from source to destination.
+ *
+ * Color conversion is done on the color components without alpha. Thus
+ * if a BufferedImage has alpha premultiplied, this is divided out before
+ * color conversion, and premultiplication applied if the destination
+ * requires it.
+ *
+ * Color rendering and dithering hints may be applied if specified. This is
+ * likely platform-dependent.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp
+{
+ private ColorSpace srccs;
+ private ColorSpace dstcs;
+ private RenderingHints hints;
+ private ICC_Profile[] profiles;
+ private ColorSpace[] spaces;
+ private boolean rasterValid;
+
+
+ /**
+ * Convert BufferedImage through a ColorSpace.
+ *
+ * This filter version is only valid for BufferedImages. The source image
+ * is converted to cspace. If the destination is not null, it is then
+ * converted to the destination colorspace. Normally this filter will only
+ * be used with a null destination.
+ *
+ * @param cspace The target color space.
+ * @param hints Rendering hints to use in conversion, or null.
+ */
+ public ColorConvertOp(ColorSpace cspace, RenderingHints hints)
+ {
+ if (cspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{cspace};
+ this.hints = hints;
+ rasterValid = false;
+ }
+
+ public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
+ RenderingHints hints)
+ {
+ if (srcCspace == null || dstCspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{srcCspace, dstCspace};
+ this.hints = hints;
+ }
+
+ /**
+ * Convert from a source image destination image color space.
+ *
+ * This constructor builds a ColorConvertOp from an array of ICC_Profiles.
+ * The source image will be converted through the sequence of color spaces
+ * defined by the profiles. If the sequence of profiles doesn't give a
+ * well-defined conversion, throws IllegalArgumentException.
+ *
+ * NOTE: Sun's docs don't clearly define what a well-defined conversion is
+ * - or perhaps someone smarter can come along and sort it out.
+ *
+ * For BufferedImages, when the first and last profiles match the
+ * requirements of the source and destination color space respectively, the
+ * corresponding conversion is unnecessary. TODO: code this up. I don't
+ * yet understand how you determine this.
+ *
+ * For Rasters, the first and last profiles must have the same number of
+ * bands as the source and destination Rasters, respectively. If this is
+ * not the case, or there fewer than 2 profiles, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @param profiles
+ * @param hints
+ */
+ public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints)
+ {
+ if (profiles == null)
+ throw new NullPointerException();
+ this.hints = hints;
+ this.profiles = profiles;
+ // TODO: Determine if this is well-defined.
+ // Create colorspace array with space for src and dest colorspace
+ spaces = new ColorSpace[profiles.length];
+ for (int i = 0; i < profiles.length; i++)
+ spaces[i] = new ICC_ColorSpace(profiles[i]);
+ }
+
+ /** Convert from source image color space to destination image color space.
+ *
+ * Only valid for BufferedImage objects, this Op converts from the source
+ * color space to the destination color space. The destination can't be
+ * null for this operation.
+ *
+ * @param hints Rendering hints to use during conversion, or null.
+ */
+ public ColorConvertOp(RenderingHints hints)
+ {
+ this.hints = hints;
+ srccs = null;
+ dstcs = null;
+ rasterValid = false;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
+ java.awt.image.BufferedImage)
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // TODO: The plan is to create a scanline buffer for intermediate buffers.
+ // For now we just suck it up and create intermediate buffers.
+
+ if (dst == null && spaces.length == 0)
+ throw new IllegalArgumentException();
+
+ // Make sure input isn't premultiplied by alpha
+ if (src.isAlphaPremultiplied())
+ {
+ BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel());
+ copyimage(src, tmp);
+ tmp.coerceData(false);
+ src = tmp;
+ }
+
+ ColorModel scm = src.getColorModel();
+ for (int i = 0; i < spaces.length; i++)
+ {
+ ColorModel cm = scm.cloneColorModel(spaces[i]);
+ BufferedImage tmp = createCompatibleDestImage(src, cm);
+ copyimage(src, tmp);
+ src = tmp;
+ }
+
+ // Intermediate conversions leave result in src
+ if (dst == null)
+ return src;
+
+ // Apply final conversion
+ copyimage(src, dst);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied,
+ null);
+ }
+
+ public final ICC_Profile[] getICC_Profiles()
+ {
+ return profiles;
+ }
+
+ /** Return the rendering hints for this op. */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (!rasterValid)
+ throw new IllegalArgumentException();
+
+ // Need to iterate through each color space - there must be at least 2
+ for (int i = 1; i < spaces.length - 1; i++)
+ {
+ // FIXME: this is wrong. tmp needs to have the same number of bands as
+ // spaces[i] has.
+ WritableRaster tmp = createCompatibleDestRaster(src);
+ copyraster(src, spaces[i - 1], tmp, spaces[i]);
+ src = tmp;
+ }
+
+ // FIXME: this is wrong. dst needs to have the same number of bands as
+ // spaces[i] has.
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+ copyraster(src, spaces[spaces.length - 2],
+ dest, spaces[spaces.length - 1]);
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ // According to Sven de Marothy, we need to copy the src into the dest
+ // using Graphics2D, in order to use the rendering hints.
+ private void copyimage(BufferedImage src, BufferedImage dst)
+ {
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(src, 0, 0, null);
+ gg.dispose();
+ }
+
+ private void copyraster(Raster src, ColorSpace scs, WritableRaster dst,
+ ColorSpace dcs)
+ {
+ float[] sbuf = new float[src.getNumBands()];
+
+ if (hints.get(RenderingHints.KEY_COLOR_RENDERING) ==
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY)
+ {
+ // use cie for accuracy
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromCIEXYZ(scs.toCIEXYZ(src.getPixel(x, y, sbuf))));
+ }
+ else
+ {
+ // use rgb - it's probably faster
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromRGB(scs.toRGB(src.getPixel(x, y, sbuf))));
+ }
+ }
+
+}
diff --git a/libjava/java/awt/image/ColorModel.java b/libjava/java/awt/image/ColorModel.java
index 87ab942917a..11615fdadfb 100644
--- a/libjava/java/awt/image/ColorModel.java
+++ b/libjava/java/awt/image/ColorModel.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation
+/* ColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,11 +38,13 @@ exception statement from your version. */
package java.awt.image;
-import java.util.Arrays;
+import gnu.java.awt.Buffers;
+
import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import gnu.java.awt.Buffers;
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
/**
* A color model operates with colors in several formats:
@@ -76,8 +79,8 @@ import gnu.java.awt.Buffers;
*
* </ul>
*
- * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
- * @author C. Brian Jones <cbj@gnu.org>
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author C. Brian Jones (cbj@gnu.org)
*/
public abstract class ColorModel implements Transparency
{
@@ -108,7 +111,7 @@ public abstract class ColorModel implements Transparency
* Constructs the default color model. The default color model
* can be obtained by calling <code>getRGBdefault</code> of this
* class.
- * @param b the number of bits wide used for bit size of pixel values
+ * @param bits the number of bits wide used for bit size of pixel values
*/
public ColorModel(int bits)
{
@@ -156,6 +159,32 @@ public abstract class ColorModel implements Transparency
this.transferType = transferType;
}
+ // This is a hook for ColorConvertOp to create a colormodel with
+ // a new colorspace
+ ColorModel cloneColorModel(ColorSpace cspace)
+ {
+ Class cls = this.getClass();
+ ColorModel cm;
+ try {
+ // This constructor will exist.
+ Constructor ctor =
+ cls.getConstructor(new Class[]{int.class, int[].class,
+ ColorSpace.class, boolean.class,
+ boolean.class, int.class, int.class});
+ cm = (ColorModel)ctor.
+ newInstance(new Object[]{new Integer(pixel_bits),
+ bits, cspace, Boolean.valueOf(hasAlpha),
+ Boolean.valueOf(isAlphaPremultiplied),
+ new Integer(transparency),
+ new Integer(transferType)});
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException();
+ }
+ return cm;
+ }
+
public void finalize()
{
// Do nothing here.
@@ -294,7 +323,7 @@ public abstract class ColorModel implements Transparency
* This method is typically overriden in subclasses to provide a
* more efficient implementation.
*
- * @param array of transferType containing a single pixel. The
+ * @param inData array of transferType containing a single pixel. The
* pixel should be encoded in the natural way of the color model.
*/
public int getRed(Object inData)
@@ -508,40 +537,89 @@ public abstract class ColorModel implements Transparency
* <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
* 0), 0))</code>.
*
- * This method is typically overriden in subclasses to provide a
- * more efficient implementation.
+ * This method is overriden in subclasses since this abstract class throws
+ * UnsupportedOperationException().
*
- * @param arrays of unnormalized component samples of single
- * pixel. The scale and multiplication state of the samples are
- * according to the color model. Each component sample is stored
- * as a separate element in the array.
+ * @param components Array of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are according
+ * to the color model. Each component sample is stored as a separate element
+ * in the array.
+ * @param offset Position of the first value of the pixel in components.
*
* @return pixel value encoded according to the color model.
*/
public int getDataElement(int[] components, int offset)
{
- // subclasses has to implement this method.
+ // subclasses have to implement this method.
throw new UnsupportedOperationException();
}
+ /**
+ * Converts the normalized component samples from an array to a pixel
+ * value. I.e. composes the pixel from component samples, but does not
+ * perform any color conversion or scaling of the samples.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ *
+ * @return pixel value encoded according to the color model.
+ * @since 1.4
+ */
public int getDataElement (float[] components, int offset)
{
- // subclasses has to implement this method.
- throw new UnsupportedOperationException();
+ return
+ getDataElement(getUnnormalizedComponents(components, offset, null, 0),
+ 0);
}
public Object getDataElements(int[] components, int offset, Object obj)
{
- // subclasses has to implement this method.
+ // subclasses have to implement this method.
throw new UnsupportedOperationException();
}
- public int getDataElements (float[] components, Object obj)
+ /**
+ * Converts the normalized component samples from an array to an array of
+ * TransferType values. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * If obj is null, a new array of TransferType is allocated and returned.
+ * Otherwise the results are stored in obj and obj is returned. If obj is
+ * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array
+ * of primitives, ClassCastException is thrown.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int, Object).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ * @param obj Array of TransferType or null.
+ *
+ * @return pixel value encoded according to the color model.
+ * @throws ArrayIndexOutOfBounds
+ * @throws ClassCastException
+ * @since 1.4
+ */
+ public Object getDataElements(float[] components, int offset, Object obj)
{
- // subclasses has to implement this method.
- throw new UnsupportedOperationException();
+ return
+ getDataElements(getUnnormalizedComponents(components, offset, null, 0),
+ 0, obj);
}
-
+
public boolean equals(Object obj)
{
if (!(obj instanceof ColorModel)) return false;
diff --git a/libjava/java/awt/image/ComponentColorModel.java b/libjava/java/awt/image/ComponentColorModel.java
index 24d8b8ea685..2b065328ee0 100644
--- a/libjava/java/awt/image/ComponentColorModel.java
+++ b/libjava/java/awt/image/ComponentColorModel.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
+/* ComponentColorModel.java --
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,9 +38,10 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.Buffers;
+
import java.awt.Point;
import java.awt.color.ColorSpace;
-import gnu.java.awt.Buffers;
public class ComponentColorModel extends ColorModel
{
@@ -60,6 +62,32 @@ public class ComponentColorModel extends ColorModel
transparency, transferType);
}
+ /**
+ * Construct a new ComponentColorModel.
+ *
+ * This constructor makes all bits of each sample significant, so for a
+ * transferType of DataBuffer.BYTE, the bits per sample is 8, etc. If
+ * both hasAlpha and isAlphaPremultiplied are true, color samples are
+ * assumed to be premultiplied by the alpha component. Transparency may be
+ * one of OPAQUE, BITMASK, or TRANSLUCENT.
+ *
+ * @param colorSpace The colorspace for this color model.
+ * @param hasAlpha True if there is an alpha component.
+ * @param isAlphaPremultiplied True if colors are already multiplied by
+ * alpha.
+ * @param transparency The type of alpha values.
+ * @param transferType Data type of pixel sample values.
+ * @since 1.4
+ */
+ public ComponentColorModel(ColorSpace colorSpace,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
public int getRed(int pixel)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
@@ -95,12 +123,6 @@ public class ComponentColorModel extends ColorModel
}
- /* FIXME: Is the values returned from toRGB() in the [0.0, 1.0] or the
- [0.0, 256) range?
-
- we assume it is in the [0.0, 1.0] range along with the
- other color spaces. */
-
/* Note, it's OK to pass a to large array to toRGB(). Extra
elements are ignored. */
diff --git a/libjava/java/awt/image/ComponentSampleModel.java b/libjava/java/awt/image/ComponentSampleModel.java
index c7b08b919e5..0665f406793 100644
--- a/libjava/java/awt/image/ComponentSampleModel.java
+++ b/libjava/java/awt/image/ComponentSampleModel.java
@@ -41,6 +41,21 @@ import gnu.java.awt.Buffers;
/* FIXME: This class does not yet support data type TYPE_SHORT */
/**
+ * ComponentSampleModel supports a flexible organization of pixel samples in
+ * memory, permitting pixel samples to be interleaved by band, by scanline,
+ * and by pixel.
+ *
+ * A DataBuffer for this sample model has K banks of data. Pixels have N
+ * samples, so there are N bands in the DataBuffer. Each band is completely
+ * contained in one bank of data, but a bank may contain more than one band.
+ * Each pixel sample is stored in a single data element.
+ *
+ * Within a bank, each band begins at an offset stored in bandOffsets. The
+ * banks containing the band is given by bankIndices. Within the bank, there
+ * are three dimensions - band, pixel, and scanline. The dimension ordering
+ * is controlled by bandOffset, pixelStride, and scanlineStride, which means
+ * that any combination of interleavings is supported.
+ *
* @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
*/
public class ComponentSampleModel extends SampleModel
@@ -86,6 +101,7 @@ public class ComponentSampleModel extends SampleModel
this.bandOffsets = bandOffsets;
this.bankIndices = bankIndices;
+ this.numBanks = 0;
for (int b=0; b<bankIndices.length; b++)
this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
@@ -249,6 +265,18 @@ public class ComponentSampleModel extends SampleModel
}
return outUShort;
+ case DataBuffer.TYPE_SHORT:
+ DataBufferShort inShort = (DataBufferShort) data;
+ short[] outShort = (short[]) obj;
+ if (outShort == null) outShort = new short[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outShort[b] = inShort.getData(bankIndices[b])[dOffset];
+ }
+ return outShort;
+
case DataBuffer.TYPE_INT:
DataBufferInt inInt = (DataBufferInt) data;
int[] outInt = (int[]) obj;
@@ -260,8 +288,31 @@ public class ComponentSampleModel extends SampleModel
outInt[b] = inInt.getData(bankIndices[b])[dOffset];
}
return outInt;
-
- // FIXME: Fill in the other possible types.
+
+ case DataBuffer.TYPE_FLOAT:
+ DataBufferFloat inFloat = (DataBufferFloat) data;
+ float[] outFloat = (float[]) obj;
+ if (outFloat == null) outFloat = new float[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outFloat[b] = inFloat.getData(bankIndices[b])[dOffset];
+ }
+ return outFloat;
+
+ case DataBuffer.TYPE_DOUBLE:
+ DataBufferDouble inDouble = (DataBufferDouble) data;
+ double[] outDouble = (double[]) obj;
+ if (outDouble == null) outDouble = new double[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outDouble[b] = inDouble.getData(bankIndices[b])[dOffset];
+ }
+ return outDouble;
+
default:
throw new IllegalStateException("unknown transfer type " +
getTransferType());
@@ -433,6 +484,16 @@ public class ComponentSampleModel extends SampleModel
return;
}
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] in = (short[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
case DataBuffer.TYPE_INT:
{
DataBufferInt out = (DataBufferInt) data;
@@ -443,6 +504,26 @@ public class ComponentSampleModel extends SampleModel
return;
}
+ case DataBuffer.TYPE_FLOAT:
+ {
+ DataBufferFloat out = (DataBufferFloat) data;
+ float[] in = (float[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ DataBufferDouble out = (DataBufferDouble) data;
+ double[] in = (double[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
default:
throw new UnsupportedOperationException("transfer type not " +
"implemented");
diff --git a/libjava/java/awt/image/ConvolveOp.java b/libjava/java/awt/image/ConvolveOp.java
new file mode 100644
index 00000000000..c793eee1434
--- /dev/null
+++ b/libjava/java/awt/image/ConvolveOp.java
@@ -0,0 +1,341 @@
+/* Copyright (C) 2004 Free Software Foundation -- ConvolveOp
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+/*
+ * Created on Nov 1, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * Convolution filter.
+ *
+ * ConvolveOp convolves the source image with a Kernel to generate a
+ * destination image. This involves multiplying each pixel and its neighbors
+ * with elements in the kernel to compute a new pixel.
+ *
+ * Each band in a Raster is convolved and copied to the destination Raster.
+ *
+ * For BufferedImages, convolution is applied to all components. If the
+ * source is not premultiplied, the data will be premultiplied before
+ * convolving. Premultiplication will be undone if the destination is not
+ * premultiplied. Color conversion will be applied if needed.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ConvolveOp implements BufferedImageOp, RasterOp
+{
+ /** Edge pixels are set to 0. */
+ public static final int EDGE_ZERO_FILL = 0;
+
+ /** Edge pixels are copied from the source. */
+ public static final int EDGE_NO_OP = 1;
+
+ private Kernel kernel;
+ private int edge;
+ private RenderingHints hints;
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition specifies that pixels outside the area that can be
+ * filtered are either set to 0 or copied from the source image.
+ *
+ * @param kernel The kernel to convolve with.
+ * @param edgeCondition Either EDGE_ZERO_FILL or EDGE_NO_OP.
+ * @param hints Rendering hints for color conversion, or null.
+ */
+ public ConvolveOp(Kernel kernel,
+ int edgeCondition,
+ RenderingHints hints)
+ {
+ this.kernel = kernel;
+ edge = edgeCondition;
+ this.hints = hints;
+ }
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition defaults to EDGE_ZERO_FILL.
+ *
+ * @param kernel The kernel to convolve with.
+ */
+ public ConvolveOp(Kernel kernel)
+ {
+ this.kernel = kernel;
+ edge = EDGE_ZERO_FILL;
+ hints = null;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
+ * java.awt.image.BufferedImage)
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src == dst)
+ throw new IllegalArgumentException();
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel());
+
+ // Make sure source image is premultiplied
+ BufferedImage src1 = src;
+ if (!src.isPremultiplied)
+ {
+ src1 = createCompatibleDestImage(src, src.getColorModel());
+ src.copyData(src1.getRaster());
+ src1.coerceData(true);
+ }
+
+ BufferedImage dst1 = dst;
+ if (!src.getColorModel().equals(dst.getColorModel()))
+ dst1 = createCompatibleDestImage(src, src.getColorModel());
+
+ filter(src1.getRaster(), dst1.getRaster());
+
+ if (dst1 != dst)
+ {
+ // Convert between color models.
+ // TODO Check that premultiplied alpha is handled correctly here.
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(dst1, 0, 0, null);
+ gg.dispose();
+ }
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see
+ * java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
+ * java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied, null);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * @return The edge condition.
+ */
+ public int getEdgeCondition()
+ {
+ return edge;
+ }
+
+ /**
+ * @return The convolution kernel.
+ */
+ public Kernel getKernel()
+ {
+ return kernel;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
+ * java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest) {
+ if (src.numBands != dest.numBands)
+ throw new ImagingOpException(null);
+ if (src == dest)
+ throw new IllegalArgumentException();
+ if (src.getWidth() < kernel.getWidth() ||
+ src.getHeight() < kernel.getHeight())
+ throw new ImagingOpException(null);
+
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+
+ // Deal with bottom edge
+ if (edge == EDGE_ZERO_FILL)
+ {
+ float[] zeros = new float[src.getNumBands() * src.getWidth()
+ * (kernel.getYOrigin() - 1)];
+ Arrays.fill(zeros, 0);
+ dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
+ kernel.getYOrigin() - 1, zeros);
+ }
+ else
+ {
+ float[] vals = new float[src.getNumBands() * src.getWidth()
+ * (kernel.getYOrigin() - 1)];
+ src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(),
+ kernel.getYOrigin() - 1, vals);
+ dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
+ kernel.getYOrigin() - 1, vals);
+ }
+
+ // Handle main section
+ float[] kvals = kernel.getKernelData(null);
+
+ float[] tmp = new float[kernel.getWidth() * kernel.getHeight()];
+ for (int y = src.getMinY() + kernel.getYOrigin();
+ y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++)
+ {
+ // Handle unfiltered edge pixels at start of line
+ float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()];
+ if (edge == EDGE_ZERO_FILL)
+ Arrays.fill(t1, 0);
+ else
+ src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
+ dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
+
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // FIXME: This needs a much more efficient implementation
+ for (int b = 0; b < src.getNumBands(); b++)
+ {
+ float v = 0;
+ src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp);
+ for (int i=0; i < tmp.length; i++)
+ v += tmp[i] * kvals[i];
+ dest.setSample(x, y, b, v);
+ }
+ }
+
+ // Handle unfiltered edge pixels at end of line
+ float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()];
+ if (edge == EDGE_ZERO_FILL)
+ Arrays.fill(t2, 0);
+ else
+ src.getPixels(src.getMinX() + src.getWidth()
+ - (kernel.getWidth() / 2),
+ y, kernel.getWidth() / 2, 1, t2);
+ dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2),
+ y, kernel.getWidth() / 2, 1, t2);
+ }
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
+ {
+
+ }
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
+ {
+
+ }
+
+ // Handle top edge
+ if (edge == EDGE_ZERO_FILL)
+ {
+ float[] zeros = new float[src.getNumBands() * src.getWidth() *
+ (kernel.getHeight() / 2)];
+ Arrays.fill(zeros, 0);
+ dest.setPixels(src.getMinX(),
+ src.getHeight() + src.getMinY() - (kernel.getHeight() / 2),
+ src.getWidth(), kernel.getHeight() / 2, zeros);
+ }
+ else
+ {
+ float[] vals = new float[src.getNumBands() * src.getWidth() *
+ (kernel.getHeight() / 2)];
+ src.getPixels(src.getMinX(),
+ src.getHeight() + src.getMinY()
+ - (kernel.getHeight() / 2),
+ src.getWidth(), kernel.getHeight() / 2, vals);
+ dest.setPixels(src.getMinX(),
+ src.getHeight() + src.getMinY()
+ - (kernel.getHeight() / 2),
+ src.getWidth(), kernel.getHeight() / 2, vals);
+ }
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * ConvolveOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
+ * java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+}
diff --git a/libjava/java/awt/image/CropImageFilter.java b/libjava/java/awt/image/CropImageFilter.java
index c9a170b9b3b..a006d26d814 100644
--- a/libjava/java/awt/image/CropImageFilter.java
+++ b/libjava/java/awt/image/CropImageFilter.java
@@ -1,5 +1,5 @@
/* CropImageFilter.java -- Java class for cropping image filter
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,11 +38,10 @@ exception statement from your version. */
package java.awt.image;
-import java.util.Hashtable;
import java.awt.Rectangle;
+import java.util.Hashtable;
/**
- * <br>
* Currently this filter does almost nothing and needs to be implemented.
*
* @author C. Brian Jones (cbj@gnu.org)
diff --git a/libjava/java/awt/image/DataBuffer.java b/libjava/java/awt/image/DataBuffer.java
index 967e1a26c9c..b921953ec28 100644
--- a/libjava/java/awt/image/DataBuffer.java
+++ b/libjava/java/awt/image/DataBuffer.java
@@ -45,12 +45,45 @@ package java.awt.image;
*/
public abstract class DataBuffer
{
+ /**
+ * A constant representng a data type that uses <code>byte</code> primitives
+ * as the storage unit.
+ */
public static final int TYPE_BYTE = 0;
+
+ /**
+ * A constant representng a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
public static final int TYPE_USHORT = 1;
+
+ /**
+ * A constant representng a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
public static final int TYPE_SHORT = 2;
+
+ /**
+ * A constant representng a data type that uses <code>int</code>
+ * primitives as the storage unit.
+ */
public static final int TYPE_INT = 3;
+
+ /**
+ * A constant representng a data type that uses <code>float</code>
+ * primitives as the storage unit.
+ */
public static final int TYPE_FLOAT = 4;
+
+ /**
+ * A constant representng a data type that uses <code>double</code>
+ * primitives as the storage unit.
+ */
public static final int TYPE_DOUBLE = 5;
+
+ /**
+ * A constant representng an undefined data type.
+ */
public static final int TYPE_UNDEFINED = 32;
/** The type of the data elements stored in the data buffer. */
@@ -68,18 +101,57 @@ public abstract class DataBuffer
/** Offset into each bank. */
protected int[] offsets;
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type and
+ * size. The <code>dataType</code> should be one of the constants
+ * {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, {@link #TYPE_USHORT},
+ * {@link #TYPE_INT}, {@link #TYPE_FLOAT} and {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ */
protected DataBuffer(int dataType, int size)
{
this.dataType = dataType;
this.size = size;
}
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ */
protected DataBuffer(int dataType, int size, int numBanks) {
this(dataType, size);
banks = numBanks;
offsets = new int[numBanks];
}
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @param offset the offset to the first element for all banks.
+ */
protected DataBuffer(int dataType, int size, int numBanks, int offset) {
this(dataType, size, numBanks);
@@ -88,6 +160,24 @@ public abstract class DataBuffer
this.offset = offset;
}
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @param offsets the offsets to the first element for all banks.
+ *
+ * @throws ArrayIndexOutOfBoundsException if
+ * <code>numBanks != offsets.length</code>.
+ */
protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
this(dataType, size);
if (numBanks != offsets.length)
@@ -99,6 +189,17 @@ public abstract class DataBuffer
offset = offsets[0];
}
+ /**
+ * Returns the size (number of bits) of the specified data type. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @param dataType the data type.
+ * @return The number of bits for the specified data type.
+ * @throws IllegalArgumentException if <code>dataType < 0</code> or
+ * <code>dataType > TYPE_DOUBLE</code>.
+ */
public static int getDataTypeSize(int dataType) {
// Maybe this should be a lookup table instead.
switch (dataType)
@@ -118,21 +219,45 @@ public abstract class DataBuffer
}
}
+ /**
+ * Returns the type of the data elements in the data buffer. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @return The type.
+ */
public int getDataType()
{
return dataType;
}
+ /**
+ * Returns the size of the data buffer.
+ *
+ * @return The size.
+ */
public int getSize()
{
return size;
}
+ /**
+ * Returns the element offset for the first data bank.
+ *
+ * @return The element offset.
+ */
public int getOffset()
{
return offset;
}
+ /**
+ * Returns the offsets for all the data banks used by this
+ * <code>DataBuffer</code>.
+ *
+ * @return The offsets.
+ */
public int[] getOffsets()
{
if (offsets == null)
@@ -144,60 +269,166 @@ public abstract class DataBuffer
return offsets;
}
+ /**
+ * Returns the number of data banks for this <code>DataBuffer</code>.
+ * @return The number of data banks.
+ */
public int getNumBanks()
{
return banks;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return getElem(0, i);
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public abstract int getElem(int bank, int i);
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
setElem(0, i, val);
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public abstract void setElem(int bank, int i, int val);
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public float getElemFloat(int i)
{
return getElem(i);
}
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public float getElemFloat(int bank, int i)
{
return getElem(bank, i);
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElemFloat(int i, float val)
{
setElem(i, (int) val);
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElemFloat(int bank, int i, float val)
{
setElem(bank, i, (int) val);
}
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public double getElemDouble(int i)
{
return getElem(i);
}
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public double getElemDouble(int bank, int i)
{
return getElem(bank, i);
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElemDouble(int i, double val)
{
setElem(i, (int) val);
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElemDouble(int bank, int i, double val)
{
setElem(bank, i, (int) val);
diff --git a/libjava/java/awt/image/DataBufferByte.java b/libjava/java/awt/image/DataBufferByte.java
index 84df5510607..c56be6b31dd 100644
--- a/libjava/java/awt/image/DataBufferByte.java
+++ b/libjava/java/awt/image/DataBufferByte.java
@@ -54,12 +54,27 @@ public final class DataBufferByte extends DataBuffer
private byte[] data;
private byte[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferByte(int size)
{
- super(TYPE_BYTE, size);
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
data = new byte[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferByte(int size, int numBanks)
{
super(TYPE_BYTE, size, numBanks);
@@ -67,18 +82,53 @@ public final class DataBufferByte extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
public DataBufferByte(byte[] dataArray, int size)
{
- super(TYPE_BYTE, size);
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
public DataBufferByte(byte[] dataArray, int size, int offset)
{
super(TYPE_BYTE, size, 1, offset);
+ bankData = new byte[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferByte(byte[][] dataArray, int size)
{
super(TYPE_BYTE, size, dataArray.length);
@@ -86,6 +136,17 @@ public final class DataBufferByte extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferByte(byte[][] dataArray, int size, int[] offsets)
{
super(TYPE_BYTE, size, dataArray.length, offsets);
@@ -93,37 +154,87 @@ public final class DataBufferByte extends DataBuffer
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public byte[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public byte[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public byte[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return data[i+offset] & 0xff; // get unsigned byte as int
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
// get unsigned byte as int
return bankData[bank][i+offsets[bank]] & 0xff;
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
data[i+offset] = (byte) val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
bankData[bank][i+offsets[bank]] = (byte) val;
diff --git a/libjava/java/awt/image/DataBufferDouble.java b/libjava/java/awt/image/DataBufferDouble.java
index b1291f4165b..305cb00b2ff 100644
--- a/libjava/java/awt/image/DataBufferDouble.java
+++ b/libjava/java/awt/image/DataBufferDouble.java
@@ -58,12 +58,27 @@ public final class DataBufferDouble
private double[] data;
private double[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferDouble(int size)
{
- super(TYPE_DOUBLE, size);
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
data = new double[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferDouble(int size, int numBanks)
{
super(TYPE_DOUBLE, size, numBanks);
@@ -71,18 +86,53 @@ public final class DataBufferDouble
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
public DataBufferDouble(double[] dataArray, int size)
{
- super(TYPE_DOUBLE, size);
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
public DataBufferDouble(double[] dataArray, int size, int offset)
{
super(TYPE_DOUBLE, size, 1, offset);
+ bankData = new double[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferDouble(double[][] dataArray, int size)
{
super(TYPE_DOUBLE, size, dataArray.length);
@@ -90,6 +140,17 @@ public final class DataBufferDouble
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferDouble(double[][] dataArray, int size, int[] offsets)
{
super(TYPE_DOUBLE, size, dataArray.length, offsets);
@@ -97,36 +158,86 @@ public final class DataBufferDouble
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public double[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public double[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public double[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return (int) data[i+offset];
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
return (int) bankData[bank][i+offsets[bank]];
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
data[i+offset] = (double) val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
bankData[bank][i+offsets[bank]] = (double) val;
diff --git a/libjava/java/awt/image/DataBufferFloat.java b/libjava/java/awt/image/DataBufferFloat.java
index b2d88c16b8b..9673eddb458 100644
--- a/libjava/java/awt/image/DataBufferFloat.java
+++ b/libjava/java/awt/image/DataBufferFloat.java
@@ -56,12 +56,27 @@ public final class DataBufferFloat
private float[] data;
private float[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferFloat(int size)
{
- super(TYPE_FLOAT, size);
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
data = new float[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferFloat(int size, int numBanks)
{
super(TYPE_FLOAT, size, numBanks);
@@ -69,18 +84,53 @@ public final class DataBufferFloat
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
public DataBufferFloat(float[] dataArray, int size)
{
- super(TYPE_FLOAT, size);
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
public DataBufferFloat(float[] dataArray, int size, int offset)
{
super(TYPE_FLOAT, size, 1, offset);
+ bankData = new float[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferFloat(float[][] dataArray, int size)
{
super(TYPE_FLOAT, size, dataArray.length);
@@ -88,6 +138,17 @@ public final class DataBufferFloat
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferFloat(float[][] dataArray, int size, int[] offsets)
{
super(TYPE_FLOAT, size, dataArray.length, offsets);
@@ -95,36 +156,86 @@ public final class DataBufferFloat
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public float[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public float[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public float[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return (int) data[i+offset];
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
return (int) bankData[bank][i+offsets[bank]];
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
data[i+offset] = (float) val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
bankData[bank][i+offsets[bank]] = (float) val;
diff --git a/libjava/java/awt/image/DataBufferInt.java b/libjava/java/awt/image/DataBufferInt.java
index 54308fefd02..c5f08530d2b 100644
--- a/libjava/java/awt/image/DataBufferInt.java
+++ b/libjava/java/awt/image/DataBufferInt.java
@@ -54,12 +54,27 @@ public final class DataBufferInt extends DataBuffer
private int[] data;
private int[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferInt(int size)
{
- super(TYPE_INT, size);
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
data = new int[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferInt(int size, int numBanks)
{
super(TYPE_INT, size, numBanks);
@@ -67,18 +82,53 @@ public final class DataBufferInt extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
public DataBufferInt(int[] dataArray, int size)
{
- super(TYPE_INT, size);
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
public DataBufferInt(int[] dataArray, int size, int offset)
{
super(TYPE_INT, size, 1, offset);
+ bankData = new int[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferInt(int[][] dataArray, int size)
{
super(TYPE_INT, size, dataArray.length);
@@ -86,6 +136,17 @@ public final class DataBufferInt extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferInt(int[][] dataArray, int size, int[] offsets)
{
super(TYPE_INT, size, dataArray.length, offsets);
@@ -93,39 +154,88 @@ public final class DataBufferInt extends DataBuffer
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public int[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public int[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public int[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The <code>offset</code> is
+ * added to the specified index before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return data[i+offset];
}
+ /**
+ * Returns an element from a particular data bank. The <code>offset</code>
+ * is added to the specified index before accessing the underlying data
+ * array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
// get unsigned int as int
return bankData[bank][i+offsets[bank]];
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
- data[i+offset] = (int) val;
+ data[i+offset] = val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
- bankData[bank][i+offsets[bank]] = (int) val;
+ bankData[bank][i+offsets[bank]] = val;
}
}
diff --git a/libjava/java/awt/image/DataBufferShort.java b/libjava/java/awt/image/DataBufferShort.java
index 7a5c3942423..7a095c4e38e 100644
--- a/libjava/java/awt/image/DataBufferShort.java
+++ b/libjava/java/awt/image/DataBufferShort.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2004 Free Software Foundation
+/* DataBufferShort.java --
+ Copyright (C) 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -54,12 +55,27 @@ public final class DataBufferShort extends DataBuffer
private short[] data;
private short[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferShort(int size)
{
- super(TYPE_SHORT, size);
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
data = new short[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferShort(int size, int numBanks)
{
super(TYPE_SHORT, size, numBanks);
@@ -67,18 +83,53 @@ public final class DataBufferShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
public DataBufferShort(short[] dataArray, int size)
{
- super(TYPE_SHORT, size);
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
public DataBufferShort(short[] dataArray, int size, int offset)
{
super(TYPE_SHORT, size, 1, offset);
+ bankData = new short[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferShort(short[][] dataArray, int size)
{
super(TYPE_SHORT, size, dataArray.length);
@@ -86,6 +137,17 @@ public final class DataBufferShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferShort(short[][] dataArray, int size, int[] offsets)
{
super(TYPE_SHORT, size, dataArray.length, offsets);
@@ -93,36 +155,86 @@ public final class DataBufferShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public short[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public short[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public short[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return data[i+offset];
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
return bankData[bank][i+offsets[bank]];
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
data[i+offset] = (short) val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
bankData[bank][i+offsets[bank]] = (short) val;
diff --git a/libjava/java/awt/image/DataBufferUShort.java b/libjava/java/awt/image/DataBufferUShort.java
index e11b4ab10b2..6efe73d83ab 100644
--- a/libjava/java/awt/image/DataBufferUShort.java
+++ b/libjava/java/awt/image/DataBufferUShort.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2002 Free Software Foundation
+/* DataBufferUShort.java --
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -54,12 +55,27 @@ public final class DataBufferUShort extends DataBuffer
private short[] data;
private short[][] bankData;
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
public DataBufferUShort(int size)
{
- super(TYPE_USHORT, size);
+ super(TYPE_USHORT, size, 1, 0);
+ bankData = new short[1][];
data = new short[size];
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
public DataBufferUShort(int size, int numBanks)
{
super(TYPE_USHORT, size, numBanks);
@@ -67,18 +83,53 @@ public final class DataBufferUShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
public DataBufferUShort(short[] dataArray, int size)
{
- super(TYPE_USHORT, size);
+ super(TYPE_USHORT, size, 1, 0);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
public DataBufferUShort(short[] dataArray, int size, int offset)
{
super(TYPE_USHORT, size, 1, offset);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
data = dataArray;
+ bankData[0] = data;
}
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferUShort(short[][] dataArray, int size)
{
super(TYPE_USHORT, size, dataArray.length);
@@ -86,6 +137,17 @@ public final class DataBufferUShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
public DataBufferUShort(short[][] dataArray, int size, int[] offsets)
{
super(TYPE_USHORT, size, dataArray.length, offsets);
@@ -93,37 +155,87 @@ public final class DataBufferUShort extends DataBuffer
data = bankData[0];
}
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
public short[] getData()
{
return data;
}
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
public short[] getData(int bank)
{
return bankData[bank];
}
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
public short[][] getBankData()
{
return bankData;
}
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int i)
{
return data[i+offset] & 0xffff; // get unsigned short as int
}
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
public int getElem(int bank, int i)
{
// get unsigned short as int
return bankData[bank][i+offsets[bank]] & 0xffff;
}
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int i, int val)
{
data[i+offset] = (short) val;
}
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
public void setElem(int bank, int i, int val)
{
bankData[bank][i+offsets[bank]] = (short) val;
diff --git a/libjava/java/awt/image/DirectColorModel.java b/libjava/java/awt/image/DirectColorModel.java
index 3ac43cf25b6..b1aa6c0d335 100644
--- a/libjava/java/awt/image/DirectColorModel.java
+++ b/libjava/java/awt/image/DirectColorModel.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
+/* DirectColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,13 +38,14 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.Buffers;
+
import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import gnu.java.awt.Buffers;
/**
- * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author C. Brian Jones (cbj@gnu.org)
* @author Mark Benvenuto (mcb54@columbia.edu)
*/
@@ -56,7 +58,7 @@ public class DirectColorModel extends PackedColorModel
* most likely order of alpha, red, green, blue from the most significant
* byte to the least significant byte.
*
- * @param bits the number of bits wide used for bit size of pixel values
+ * @param pixelBits the number of bits wide used for bit size of pixel values
* @param rmask the bits describing the red component of a pixel
* @param gmask the bits describing the green component of a pixel
* @param bmask the bits describing the blue component of a pixel
@@ -77,7 +79,7 @@ public class DirectColorModel extends PackedColorModel
* most likely order of red, green, blue from the most significant
* byte to the least significant byte.
*
- * @param bits the number of bits wide used for bit size of pixel values
+ * @param pixelBits the number of bits wide used for bit size of pixel values
* @param rmask the bits describing the red component of a pixel
* @param gmask the bits describing the green component of a pixel
* @param bmask the bits describing the blue component of a pixel
@@ -162,7 +164,7 @@ public class DirectColorModel extends PackedColorModel
return extractAndScaleSample(pixel, 3);
}
- private final int extractAndNormalizeSample(int pixel, int component)
+ private int extractAndNormalizeSample(int pixel, int component)
{
int value = extractAndScaleSample(pixel, component);
if (hasAlpha() && isAlphaPremultiplied())
@@ -170,7 +172,7 @@ public class DirectColorModel extends PackedColorModel
return value;
}
- private final int extractAndScaleSample(int pixel, int component)
+ private int extractAndScaleSample(int pixel, int component)
{
int field = pixel & getMask(component);
int to8BitShift =
@@ -303,7 +305,7 @@ public class DirectColorModel extends PackedColorModel
* @param highBit the position of the most significant bit in the
* val parameter.
*/
- private final int valueToField(int val, int component, int highBit)
+ private int valueToField(int val, int component, int highBit)
{
int toFieldShift =
getComponentSize(component) + shifts[component] - highBit;
@@ -317,7 +319,7 @@ public class DirectColorModel extends PackedColorModel
* Converts a 16 bit value to the correct field bits based on the
* information derived from the field masks.
*/
- private final int value16ToField(int val, int component)
+ private int value16ToField(int val, int component)
{
int toFieldShift = getComponentSize(component) + shifts[component] - 16;
return (toFieldShift>0) ?
diff --git a/libjava/java/awt/image/IndexColorModel.java b/libjava/java/awt/image/IndexColorModel.java
index 9ceb0bf0944..6791589032e 100644
--- a/libjava/java/awt/image/IndexColorModel.java
+++ b/libjava/java/awt/image/IndexColorModel.java
@@ -38,7 +38,29 @@ exception statement from your version. */
package java.awt.image;
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
/**
+ * Color model similar to pseudo visual in X11.
+ *
+ * This color model maps linear pixel values to actual RGB and alpha colors.
+ * Thus, pixel values are indexes into the color map. Each color component is
+ * an 8-bit unsigned value.
+ *
+ * The IndexColorModel supports a map of valid pixels, allowing the
+ * representation of holes in the the color map. The valid map is represented
+ * as a BigInteger where each bit indicates the validity of the map entry with
+ * the same index.
+ *
+ * Colors can have alpha components for transparency support. If alpha
+ * component values aren't given, color values are opaque. The model also
+ * supports a reserved pixel value to represent completely transparent colors,
+ * no matter what the actual color component values are.
+ *
+ * IndexColorModel supports anywhere from 1 to 16 bit index values. The
+ * allowed transfer types are DataBuffer.TYPE_BYTE and DataBuffer.TYPE_USHORT.
+ *
* @author C. Brian Jones (cbj@gnu.org)
*/
public class IndexColorModel extends ColorModel
@@ -47,6 +69,7 @@ public class IndexColorModel extends ColorModel
private boolean opaque;
private int trans = -1;
private int[] rgb;
+ private BigInteger validBits = BigInteger.ZERO;
/**
* Each array much contain <code>size</code> elements. For each
@@ -127,6 +150,9 @@ public class IndexColorModel extends ColorModel
| (blues[i] & 0xff));
}
}
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
/**
@@ -140,6 +166,7 @@ public class IndexColorModel extends ColorModel
* @param cmap packed color components
* @param start the offset of the first color component in <code>cmap</code>
* @param hasAlpha <code>cmap</code> has alpha values
+ * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1.
*/
public IndexColorModel (int bits, int size, byte[] cmap, int start,
boolean hasAlpha)
@@ -148,25 +175,155 @@ public class IndexColorModel extends ColorModel
}
/**
- * Each array much contain <code>size</code> elements. For each
- * array, the i-th color is described by reds[i], greens[i],
- * blues[i], alphas[i], unless alphas is not specified, then all the
- * colors are opaque except for the transparent color.
- *
+ * Construct an IndexColorModel from an array of red, green, blue, and
+ * optional alpha components. The component values are interleaved as RGB(A).
+ *
* @param bits the number of bits needed to represent <code>size</code> colors
* @param size the number of colors in the color map
- * @param cmap packed color components
+ * @param cmap interleaved color components
* @param start the offset of the first color component in <code>cmap</code>
* @param hasAlpha <code>cmap</code> has alpha values
* @param trans the index of the transparent color
+ * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1.
*/
public IndexColorModel (int bits, int size, byte[] cmap, int start,
boolean hasAlpha, int trans)
{
super (bits);
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = !hasAlpha;
+ this.trans = trans;
+
+ rgb = new int[size];
+ if (hasAlpha)
+ {
+ for (int i = 0; i < size; i++)
+ rgb[i] =
+ // alpha
+ ((cmap[4 * i + 3 + start] & 0xff) << 24
+ // red
+ | ((cmap[4 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[4 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[4 * i + 2 + start] & 0xff));
+ }
+ else
+ {
+ for (int i = 0; i < size; i++)
+ rgb[i] = (0xff000000
+ // red
+ | ((cmap[3 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[3 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[3 * i + 2 + start] & 0xff));
+ }
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel from an array of <code>size</code> packed
+ * colors. Each int element contains 8-bit red, green, blue, and optional
+ * alpha values packed in order. If hasAlpha is false, then all the colors
+ * are opaque except for the transparent color.
+ *
+ * @param bits the number of bits needed to represent <code>size</code> colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @param trans the index of the transparent color
+ * @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
+ * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1.
+ * @throws IllegalArgumentException if transferType is something other than
+ * TYPE_BYTE or TYPE_USHORT.
+ */
+ public IndexColorModel (int bits, int size, int[] cmap, int start,
+ boolean hasAlpha, int trans, int transferType)
+ {
+ super(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
map_size = size;
opaque = !hasAlpha;
this.trans = trans;
+
+ rgb = new int[size];
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel using a colormap with holes.
+ *
+ * The IndexColorModel is built from the array of ints defining the
+ * colormap. Each element contains red, green, blue, and alpha
+ * components. The ColorSpace is sRGB. The transparency value is
+ * automatically determined.
+ *
+ * This constructor permits indicating which colormap entries are valid,
+ * using the validBits argument. Each entry in cmap is valid if the
+ * corresponding bit in validBits is set.
+ *
+ * @param bits the number of bits needed to represent <code>size</code> colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
+ * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1.
+ * @throws IllegalArgumentException if transferType is something other than
+ * TYPE_BYTE or TYPE_USHORT.
+ */
+ public IndexColorModel (int bits, int size, int[] cmap, int start,
+ int transferType, BigInteger validBits)
+ {
+ super(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = false;
+ this.trans = -1;
+ this.validBits = validBits;
+
+ rgb = new int[size];
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
}
public final int getMapSize ()
@@ -279,11 +436,79 @@ public class IndexColorModel extends ColorModel
return 0;
}
- //pixel_bits is number of bits to be in generated mask
+ /**
+ * Get the RGB color values of all pixels in the map using the default
+ * RGB color model.
+ *
+ * @param rgb The destination array.
+ */
+ public final void getRGBs (int[] rgb)
+ {
+ System.arraycopy(this.rgb, 0, rgb, 0, map_size);
+ }
+
+ //pixel_bits is number of bits to be in generated mask
private int generateMask (int offset)
{
return (((2 << pixel_bits ) - 1) << (pixel_bits * offset));
}
+ /** Return true if pixel is valid, false otherwise. */
+ public boolean isValid(int pixel)
+ {
+ return validBits.testBit(pixel);
+ }
+
+ /** Return true if all pixels are valid, false otherwise. */
+ public boolean isValid()
+ {
+ // Generate a bigint with 1's for every pixel
+ BigInteger allbits = new BigInteger("0");
+ allbits.setBit(map_size);
+ allbits.subtract(new BigInteger("1"));
+ return allbits.equals(validBits);
+ }
+
+ /**
+ * Returns a BigInteger where each bit represents an entry in the color
+ * model. If the bit is on, the entry is valid.
+ */
+ public BigInteger getValidPixels()
+ {
+ return validBits;
+ }
+
+ /**
+ * Construct a BufferedImage with rgb pixel values from a Raster.
+ *
+ * Constructs a new BufferedImage in which each pixel is an RGBA int from
+ * a Raster with index-valued pixels. If this model has no alpha component
+ * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB.
+ * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is
+ * forced to be TYPE_INT_ARGB no matter what.
+ *
+ * @param raster The source of pixel values.
+ * @param forceARGB True if type must be TYPE_INT_ARGB.
+ * @return New BufferedImage with RBGA int pixel values.
+ */
+ public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB)
+ {
+ int type = forceARGB ? BufferedImage.TYPE_INT_ARGB
+ : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB :
+ BufferedImage.TYPE_INT_ARGB);
+
+ // FIXME: assuming that raster has only 1 band since pixels are supposed
+ // to be int indexes.
+ // FIXME: it would likely be more efficient to fetch a complete array,
+ // but it would take much more memory.
+ // FIXME: I'm not sure if transparent pixels or alpha values need special
+ // handling here.
+ BufferedImage im = new BufferedImage(raster.width, raster.height, type);
+ for (int x = raster.minX; x < raster.width + raster.minX; x++)
+ for (int y = raster.minY; y < raster.height + raster.minY; y++)
+ im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]);
+
+ return im;
+ }
}
diff --git a/libjava/java/awt/image/LookupOp.java b/libjava/java/awt/image/LookupOp.java
new file mode 100644
index 00000000000..523aba45144
--- /dev/null
+++ b/libjava/java/awt/image/LookupOp.java
@@ -0,0 +1,252 @@
+/* LookupOp.java -- Filter that converts each pixel using a lookup table.
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * LookupOp is a filter that converts each pixel using a lookup table.
+ *
+ * For filtering Rasters, the lookup table must have either one component
+ * that is applied to all bands, or one component for every band in the
+ * Rasters.
+ *
+ * For BufferedImages, the lookup table may apply to both color and alpha
+ * components. If the lookup table contains one component, or if there are
+ * the same number of components as color components in the source, the table
+ * applies to all color components. Otherwise the table applies to all
+ * components including alpha. Alpha premultiplication is ignored during the
+ * lookup filtering.
+ *
+ * After filtering, if color conversion is necessary, the conversion happens,
+ * taking alpha premultiplication into account.
+ *
+ * @author jlquinn
+ */
+public class LookupOp implements BufferedImageOp, RasterOp
+{
+ private LookupTable lut;
+ private RenderingHints hints;
+
+ /** Construct a new LookupOp.
+ *
+ * @param lookup LookupTable to use.
+ * @param hints Rendering hints (can be null).
+ */
+ public LookupOp(LookupTable lookup, RenderingHints hints)
+ {
+ lut = lookup;
+ this.hints = hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src.getColorModel() instanceof IndexColorModel)
+ throw new IllegalArgumentException("LookupOp.filter: IndexColorModel "
+ + "not allowed");
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel());
+
+ // Set up for potential colormodel mismatch
+ BufferedImage tgt;
+ if (dst.getColorModel().equals(src.getColorModel()))
+ tgt = dst;
+ else
+ tgt = createCompatibleDestImage(src, src.getColorModel());
+
+ Raster sr = src.getRaster();
+ WritableRaster dr = tgt.getRaster();
+
+ if (src.getColorModel().hasAlpha() &&
+ (lut.getNumComponents() == 1 ||
+ lut.getNumComponents() == src.getColorModel().getNumColorComponents()))
+ {
+ // Need to ignore alpha for lookup
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+ int tmpBands = src.getColorModel().getNumColorComponents();
+ int[] tmp = new int[tmpBands];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // Filter only color components, but also copy alpha
+ sr.getPixel(x, y, dbuf);
+ System.arraycopy(dbuf, 0, tmp, 0, tmpBands);
+ dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf));
+ }
+ }
+ else if (lut.getNumComponents() != 1
+ &&
+ lut.getNumComponents() != src.getColorModel().getNumComponents())
+ throw new IllegalArgumentException("LookupOp.filter: "
+ + "Incompatible lookup "
+ + "table and source image");
+
+ // No alpha to ignore
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
+
+ if (tgt != dst)
+ {
+ // Convert between color models.
+ // TODO Check that premultiplied alpha is handled correctly here.
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(tgt, 0, 0, null);
+ gg.dispose();
+ }
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied, null);
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ return (Point2D) src.clone();
+
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /** Return the LookupTable for this op. */
+ public LookupTable getTable()
+ {
+ return lut;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /** Filter a raster through a lookup table.
+ *
+ * Applies the lookup table for this Rasterop to each pixel of src and
+ * puts the results in dest. If dest is null, a new Raster is created and
+ * returned.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @return The WritableRaster with the filtered pixels.
+ * @throws IllegalArgumentException if lookup table has more than one
+ * component but not the same as src and dest.
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (dest == null)
+ // Allocate a raster if needed
+ dest = createCompatibleDestRaster(src);
+ else
+ if (src.getNumBands() != dest.getNumBands())
+ throw new IllegalArgumentException();
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getNumBands())
+ throw new IllegalArgumentException();
+
+
+ // Allocate pixel storage.
+ int[] tmp = new int[src.getNumBands()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp));
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+}
diff --git a/libjava/java/awt/image/MemoryImageSource.java b/libjava/java/awt/image/MemoryImageSource.java
index ddd5800f14f..07e42cf077d 100644
--- a/libjava/java/awt/image/MemoryImageSource.java
+++ b/libjava/java/awt/image/MemoryImageSource.java
@@ -1,5 +1,5 @@
/* MemoryImageSource.java -- Java class for providing image data
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,8 +38,6 @@ exception statement from your version. */
package java.awt.image;
-import java.awt.Image;
-import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
@@ -54,8 +52,16 @@ public class MemoryImageSource implements ImageProducer
private Vector consumers = new Vector();
/**
- Constructs an ImageProducer from memory
- */
+ * Construct an image producer that reads image data from a byte
+ * array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix a byte array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
public MemoryImageSource(int w, int h, ColorModel cm,
byte pix[], int off, int scan)
{
@@ -75,12 +81,19 @@ public class MemoryImageSource implements ImageProducer
scansize = scan;
this.props = props;
int max = (( scansize > width ) ? scansize : width );
- pixelb = new byte[ max * height ];
- System.arraycopy( pix, 0, pixelb, 0, max * height );
+ pixelb = pix;
}
/**
- Constructs an ImageProducer from memory
- */
+ * Construct an image producer that reads image data from an
+ * integer array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix an integer array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
public MemoryImageSource(int w, int h, ColorModel cm,
int pix[], int off, int scan)
{
@@ -101,8 +114,7 @@ public class MemoryImageSource implements ImageProducer
scansize = scan;
this.props = props;
int max = (( scansize > width ) ? scansize : width );
- pixeli = new int[ max * height ];
- System.arraycopy( pix, 0, pixeli, 0, max * height );
+ pixeli = pix;
}
/**
Constructs an ImageProducer from memory using the default RGB ColorModel
@@ -166,9 +178,12 @@ public class MemoryImageSource implements ImageProducer
Vector list = (Vector) consumers.clone();
for(int i = 0; i < list.size(); i++) {
ic = (ImageConsumer) list.elementAt(i);
- sendPicture( ic );
- ic.imageComplete( ImageConsumer.STATICIMAGEDONE );
- }
+ sendPicture( ic );
+ if (animated)
+ ic.imageComplete( ImageConsumer.SINGLEFRAME );
+ else
+ ic.imageComplete( ImageConsumer.STATICIMAGEDONE );
+ }
}
/**
@@ -261,13 +276,14 @@ public class MemoryImageSource implements ImageProducer
}
if( pixeli != null ) {
int[] pixelbuf = new int[w * h];
- for (int row = y; row < h; row++)
- System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, row * w, w);
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, 0, w * h);
ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
} else {
byte[] pixelbuf = new byte[w * h];
- for (int row = y; row < h; row++)
- System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, row * w, w);
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, 0, w * h);
+
ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
}
ic.imageComplete( ImageConsumer.SINGLEFRAME );
@@ -306,13 +322,13 @@ public class MemoryImageSource implements ImageProducer
}
if( pixeli != null ) {
int[] pixelbuf = new int[w * h];
- for (int row = y; row < h; row++)
- System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, row * w, w);
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, 0, w * h);
ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
} else {
byte[] pixelbuf = new byte[w * h];
- for (int row = y; row < h; row++)
- System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, row * w, w);
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, 0, w * h);
ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
}
if( framenotify == true )
diff --git a/libjava/java/awt/image/MultiPixelPackedSampleModel.java b/libjava/java/awt/image/MultiPixelPackedSampleModel.java
new file mode 100644
index 00000000000..0525d37bd42
--- /dev/null
+++ b/libjava/java/awt/image/MultiPixelPackedSampleModel.java
@@ -0,0 +1,387 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+/**
+ * MultiPixelPackedSampleModel provides a single band model that supports
+ * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
+ * per data element.
+ *
+ * @author Jerry Quinn <jlquinn@optonline.net>
+ */
+public class MultiPixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits)
+ {
+ this(dataType, w, h, 0, numberOfBits, 0);
+ }
+
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits, int scanlineStride,
+ int dataBitOffset)
+ {
+ super(dataType, w, h, 1);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ elemBits = 8;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ elemBits = 16;
+ break;
+ case DataBuffer.TYPE_INT:
+ elemBits = 32;
+ break;
+ default:
+ throw new IllegalArgumentException("MultiPixelPackedSampleModel"
+ + " unsupported dataType");
+ }
+
+ this.dataBitOffset = dataBitOffset;
+
+ this.numberOfBits = numberOfBits;
+ if (numberOfBits > elemBits)
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel size"
+ + " larger than dataType");
+ switch (numberOfBits)
+ {
+ case 1: case 2: case 4: case 8: case 16: case 32: break;
+ default:
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel"
+ + " size not 2^n bits");
+ }
+ numElems = elemBits / numberOfBits;
+
+ // Compute scan line large enough for w pixels.
+ if (scanlineStride == 0)
+ scanlineStride = ((dataBitOffset + w * numberOfBits) / elemBits) + 1;
+ this.scanlineStride = scanlineStride;
+
+
+ sampleSize = new int[1];
+ sampleSize[0] = numberOfBits;
+
+ bitMasks = new int[numElems];
+ bitOffsets = new int[numElems];
+ for (int i=0; i < numElems; i++)
+ {
+ bitOffsets[i] = numberOfBits * i;
+ bitMasks[i] = ((1 << numberOfBits) - 1) << bitOffsets[i];
+ }
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ return new MultiPixelPackedSampleModel(dataType, w, h, numberOfBits);
+ }
+
+
+ /**
+ * Creates a DataBuffer for holding pixel data in the format and
+ * layout described by this SampleModel. The returned buffer will
+ * consist of one single bank.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ int size;
+
+ // FIXME: The comment refers to SinglePixelPackedSampleModel. See if the
+ // same can be done for MultiPixelPackedSampleModel.
+ // We can save (scanlineStride - width) pixels at the very end of
+ // the buffer. The Sun reference implementation (J2SE 1.3.1 and
+ // 1.4.1_01) seems to do this; tested with Mauve test code.
+ size = scanlineStride * height;
+
+ return Buffers.createBuffer(getDataType(), size);
+ }
+
+
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ public int[] getSampleSize()
+ {
+ return sampleSize;
+ }
+
+ public int getSampleSize(int band)
+ {
+ return sampleSize[0];
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits);
+ }
+
+ public int getBitOffset(int x)
+ {
+ return (dataBitOffset + x*numberOfBits) % elemBits;
+ }
+
+ public int getDataBitOffset()
+ {
+ return dataBitOffset;
+ }
+
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public int getPixelBitStride()
+ {
+ return numberOfBits;
+ }
+
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int numBands = bands.length;
+ if (numBands != 1)
+ throw new RasterFormatException("MultiPixelPackedSampleModel only"
+ + " supports one band");
+
+ return new MultiPixelPackedSampleModel(dataType, width, height,
+ numberOfBits, scanlineStride,
+ dataBitOffset);
+ }
+
+ /**
+ * Extract one pixel and return in an array of transfer type.
+ *
+ * Extracts the pixel at x, y from data and stores into the 0th index of the
+ * array obj, since there is only one band. If obj is null, a new array of
+ * getTransferType() is created.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int pixel = getSample(x, y, 0, data);
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ if (obj == null) obj = new byte[1];
+ ((byte[])obj)[0] = (byte)pixel;
+ return obj;
+ case DataBuffer.TYPE_USHORT:
+ if (obj == null) obj = new short[1];
+ ((short[])obj)[0] = (short)pixel;
+ return obj;
+ case DataBuffer.TYPE_INT:
+ if (obj == null) obj = new int[1];
+ ((int[])obj)[0] = pixel;
+ return obj;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[1];
+ iArray[0] = getSample(x, y, 0, data);
+
+ return iArray;
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = getOffset(x, y);
+ if (iArray == null) iArray = new int[w*h];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ int lineOffset = offset;
+ for (x=0; x<w;)
+ {
+ int samples = data.getElem(lineOffset++);
+ for (int b=0; b<numElems && x<w; b++)
+ {
+ iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
+ x++;
+ }
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int pos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[pos]) >>> bitOffsets[pos];
+ }
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @param x The x-coordinate of the data elements in <code>obj</code>.
+ * @param y The y-coordinate of the data elements in <code>obj</code>.
+ * @param obj The primitive array containing the data elements to set.
+ * @param data The DataBuffer to store the data elements into.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int transferType = getTransferType();
+ if (getTransferType() != data.getDataType())
+ {
+ throw new IllegalArgumentException("transfer type ("+
+ getTransferType()+"), "+
+ "does not match data "+
+ "buffer type (" +
+ data.getDataType() +
+ ").");
+ }
+
+ int offset = getOffset(x, y);
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements" +
+ ", x="+x+", y="+y+
+ ", width="+width+", height="+height+
+ ", scanlineStride="+scanlineStride+
+ ", offset="+offset+
+ ", data.getSize()="+data.getSize()+
+ ", data.getOffset()="+data.getOffset()+
+ ": " +
+ aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ setSample(x, y, 0, iArray[0], data);
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int bitpos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+
+ s = s << bitOffsets[bitpos];
+ s = s & bitMasks[bitpos];
+
+ int sample = data.getElem(offset);
+ sample |= s;
+ data.setElem(offset, sample);
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/java/awt/image/PackedColorModel.java b/libjava/java/awt/image/PackedColorModel.java
index 2d8b0e1ab3d..1f18cf68eb1 100644
--- a/libjava/java/awt/image/PackedColorModel.java
+++ b/libjava/java/awt/image/PackedColorModel.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2002 Free Software Foundation
+/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -34,11 +34,13 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+
package java.awt.image;
+import gnu.java.awt.BitMaskExtent;
+
import java.awt.Point;
import java.awt.color.ColorSpace;
-import gnu.java.awt.BitMaskExtent;
/**
* @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
diff --git a/libjava/java/awt/image/PixelGrabber.java b/libjava/java/awt/image/PixelGrabber.java
index d6d2403399e..bcfa050f3df 100644
--- a/libjava/java/awt/image/PixelGrabber.java
+++ b/libjava/java/awt/image/PixelGrabber.java
@@ -1,39 +1,39 @@
/* PixelGrabber.java -- retrieve a subset of an image's data
- Copyright (C) 1999, 2003 Free Software Foundation, Inc.
-
- This file is part of GNU Classpath.
-
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU Classpath is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA.
-
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
-
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
package java.awt.image;
diff --git a/libjava/java/awt/image/RGBImageFilter.java b/libjava/java/awt/image/RGBImageFilter.java
index 819580e0057..0fd977eab67 100644
--- a/libjava/java/awt/image/RGBImageFilter.java
+++ b/libjava/java/awt/image/RGBImageFilter.java
@@ -140,28 +140,19 @@ public abstract class RGBImageFilter extends ImageFilter
@param y the y coordinate of the rectangle
@param w the width of the rectangle
@param h the height of the rectangle
- @param model the <code>ColorModel</code> used to translate the pixels
@param pixels the array of pixel values
@param offset the index of the first pixels in the <code>pixels</code> array
@param scansize the width to use in extracting pixels from the <code>pixels</code> array
*/
- public void filterRGBPixels(int x,
- int y,
- int w,
- int h,
- int[] pixels,
- int off,
- int scansize)
+ public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
+ int offset, int scansize)
{
- int xp, yp, i;
-
- i = 0;
- for( xp = x; xp < ( x + w); xp++ )
- for( yp = y; yp < (y + h); yp++ )
- {
- pixels[i] = filterRGB( xp, yp, pixels[i] );
- i++;
- }
+ for (int xp = x; xp < (x + w); xp++)
+ for (int yp = y; yp < (y + h); yp++)
+ {
+ pixels[offset] = filterRGB(xp, yp, pixels[offset]);
+ offset++;
+ }
}
diff --git a/libjava/java/awt/image/Raster.java b/libjava/java/awt/image/Raster.java
index 4fd194e2a9e..0fad4ba0acb 100644
--- a/libjava/java/awt/image/Raster.java
+++ b/libjava/java/awt/image/Raster.java
@@ -128,8 +128,8 @@ public class Raster
int w, int h, int bands,
Point location)
{
- // FIXME: Implement;
- throw new UnsupportedOperationException("not implemented yet");
+ SampleModel sm = new BandedSampleModel(dataType, w, h, bands);
+ return createWritableRaster(sm, location);
}
public static WritableRaster createBandedRaster(int dataType,
@@ -139,8 +139,9 @@ public class Raster
int[] bandOffsets,
Point location)
{
- // FIXME: Implement;
- throw new UnsupportedOperationException("not implemented yet");
+ SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
+ bankIndices, bandOffsets);
+ return createWritableRaster(sm, location);
}
public static WritableRaster createPackedRaster(int dataType,
@@ -154,6 +155,35 @@ public class Raster
return createWritableRaster(sm, location);
}
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int bands, int bitsPerBand,
+ Point location)
+ {
+ if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType)))
+ throw new IllegalArgumentException();
+
+ SampleModel sm;
+
+ if (bands == 1)
+ sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand);
+ else
+ {
+ int[] bandMasks = new int[bands];
+ int mask = 0x1;
+ for (int bits = bitsPerBand; --bits != 0;)
+ mask = (mask << 1) | 0x1;
+ for (int i = 0; i < bands; i++)
+ {
+ bandMasks[i] = mask;
+ mask <<= bitsPerBand;
+ }
+
+ sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks);
+ }
+ return createWritableRaster(sm, location);
+ }
+
public static WritableRaster
createInterleavedRaster(DataBuffer dataBuffer, int w, int h,
int scanlineStride, int pixelStride,
@@ -175,8 +205,10 @@ public class Raster
int[] bandOffsets,
Point location)
{
- // FIXME: Implement;
- throw new UnsupportedOperationException("not implemented yet");
+ SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(),
+ w, h, scanlineStride,
+ bankIndices, bandOffsets);
+ return createWritableRaster(sm, dataBuffer, location);
}
public static WritableRaster
@@ -184,7 +216,8 @@ public class Raster
int w, int h,
int scanlineStride,
int[] bandMasks,
- Point location) {
+ Point location)
+ {
SampleModel sm =
new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
w, h,
@@ -192,6 +225,19 @@ public class Raster
bandMasks);
return createWritableRaster(sm, dataBuffer, location);
}
+
+ public static WritableRaster
+ createPackedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int bitsPerPixel,
+ Point location)
+ {
+ SampleModel sm =
+ new MultiPixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h,
+ bitsPerPixel);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
public static Raster createRaster(SampleModel sm, DataBuffer db,
Point location)
@@ -329,6 +375,11 @@ public class Raster
return height;
}
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
public final int getNumDataElements()
{
return numDataElements;
@@ -472,5 +523,24 @@ public class Raster
return result.toString();
}
-
+
+ // Map from datatype to bits
+ private static int getTypeBits(int dataType)
+ {
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ return 8;
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+ return 16;
+ case DataBuffer.TYPE_INT:
+ case DataBuffer.TYPE_FLOAT:
+ return 32;
+ case DataBuffer.TYPE_DOUBLE:
+ return 64;
+ default:
+ return 0;
+ }
+ }
}
diff --git a/libjava/java/awt/image/RasterOp.java b/libjava/java/awt/image/RasterOp.java
index 57961808e2e..84d47c11941 100644
--- a/libjava/java/awt/image/RasterOp.java
+++ b/libjava/java/awt/image/RasterOp.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2002 Free Software Foundation
+/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -34,11 +34,12 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+
package java.awt.image;
+import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-import java.awt.RenderingHints;
public interface RasterOp {
diff --git a/libjava/java/awt/image/RescaleOp.java b/libjava/java/awt/image/RescaleOp.java
new file mode 100644
index 00000000000..cc892b67707
--- /dev/null
+++ b/libjava/java/awt/image/RescaleOp.java
@@ -0,0 +1,218 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class RescaleOp implements BufferedImageOp, RasterOp
+{
+ private float[] scale;
+ private float[] offsets;
+ private RenderingHints hints = null;
+
+ public RescaleOp(float[] scaleFactors,
+ float[] offsets,
+ RenderingHints hints)
+ {
+ this.scale = scaleFactors;
+ this.offsets = offsets;
+ this.hints = hints;
+ }
+
+ public RescaleOp(float scaleFactor,
+ float offset,
+ RenderingHints hints)
+ {
+ scale = new float[]{ scaleFactor };
+ offsets = new float[]{offset};
+ this.hints = hints;
+ }
+
+ public final float[] getScaleFactors(float[] scaleFactors)
+ {
+ if (scaleFactors == null)
+ scaleFactors = new float[scale.length];
+ System.arraycopy(scale, 0, scaleFactors, 0, scale.length);
+ return scaleFactors;
+ }
+
+ public final float[] getOffsets(float[] offsets)
+ {
+ if (offsets == null)
+ offsets = new float[this.offsets.length];
+ System.arraycopy(this.offsets, 0, offsets, 0, this.offsets.length);
+ return offsets;
+ }
+
+ public final int getNumFactors()
+ {
+ return scale.length;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // TODO Make sure premultiplied alpha is handled correctly.
+ // TODO See that color conversion is handled.
+ // TODO figure out how to use rendering hints.
+ if (scale.length != offsets.length)
+ throw new IllegalArgumentException();
+
+ ColorModel scm = src.getColorModel();
+ if (dst == null) dst = createCompatibleDestImage(src, null);
+
+ WritableRaster wsrc = src.getRaster();
+ WritableRaster wdst = dst.getRaster();
+
+ // Share constant across colors except alpha
+ if (scale.length == 1 || scale.length == scm.getNumColorComponents())
+ {
+ // Construct a raster that doesn't include an alpha band.
+ int[] subbands = new int[scm.getNumColorComponents()];
+ for (int i=0; i < subbands.length; i++) subbands[i] = i;
+ wsrc =
+ wsrc.createWritableChild(wsrc.minX, wsrc.minY, wsrc.width, wsrc.height,
+ wsrc.minX, wsrc.minY, subbands);
+ }
+ // else all color bands
+
+ filter(wsrc, wdst);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (dest == null) dest = src.createCompatibleWritableRaster();
+
+ // Required sanity checks
+ if (src.numBands != dest.numBands || scale.length != offsets.length)
+ throw new IllegalArgumentException();
+ if (scale.length != 1 && scale.length != src.numBands)
+ throw new IllegalArgumentException();
+
+ // Create scaling arrays if needed
+ float[] lscale = scale;
+ float[] loff = offsets;
+ if (scale.length == 1)
+ {
+ lscale = new float[src.numBands];
+ Arrays.fill(lscale, scale[0]);
+ loff = new float[src.numBands];
+ Arrays.fill(loff, offsets[0]);
+ }
+
+ // TODO The efficiency here can be improved for various data storage
+ // patterns, aka SampleModels.
+ float[] pixel = new float[src.numBands];
+ for (int y = src.minY; y < src.height + src.minY; y++)
+ for (int x = src.minX; x < src.width + src.minX; x++)
+ {
+ src.getPixel(x, y, pixel);
+ for (int b = 0; b < src.numBands; b++)
+ pixel[b] = pixel[b] * lscale[b] + loff[b];
+ dest.setPixel(x, y, pixel);
+ }
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM == null) dstCM = src.getColorModel();
+ WritableRaster wr = src.getRaster().createCompatibleWritableRaster();
+ BufferedImage image
+ = new BufferedImage(dstCM, wr, src.isPremultiplied, null);
+ return image;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst) {
+ if (dst == null) dst = (Point2D) src.clone();
+ else dst.setLocation(src);
+ return dst;
+ }
+
+}
diff --git a/libjava/java/awt/image/SampleModel.java b/libjava/java/awt/image/SampleModel.java
index a5d65ff20fe..4e3b38b9922 100644
--- a/libjava/java/awt/image/SampleModel.java
+++ b/libjava/java/awt/image/SampleModel.java
@@ -456,6 +456,17 @@ public abstract class SampleModel
public abstract SampleModel createCompatibleSampleModel(int w, int h);
+ /**
+ * Return a SampleModel with a subset of the bands in this model.
+ *
+ * Selects bands.length bands from this sample model. The bands chosen
+ * are specified in the indices of bands[]. This also permits permuting
+ * the bands as well as taking a subset. Thus, giving an array with
+ * 1, 2, 3, ..., numbands, will give an identical sample model.
+ *
+ * @param bands Array with band indices to include.
+ * @return A new sample model
+ */
public abstract SampleModel createSubsetSampleModel(int[] bands);
public abstract DataBuffer createDataBuffer();
diff --git a/libjava/java/awt/image/ShortLookupTable.java b/libjava/java/awt/image/ShortLookupTable.java
index 223d03bf53b..36beb1df540 100644
--- a/libjava/java/awt/image/ShortLookupTable.java
+++ b/libjava/java/awt/image/ShortLookupTable.java
@@ -61,7 +61,7 @@ public class ShortLookupTable extends LookupTable
*
* @param offset Offset to be subtracted.
* @param data Array of lookup tables.
- * @exception IllegalArgumentException if offset < 0 or data.length < 1.
+ * @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
*/
public ShortLookupTable(int offset, short[][] data)
throws IllegalArgumentException
@@ -78,7 +78,7 @@ public class ShortLookupTable extends LookupTable
*
* @param offset Offset to be subtracted.
* @param data Lookup table for all components.
- * @exception IllegalArgumentException if offset < 0.
+ * @exception IllegalArgumentException if offset &lt; 0.
*/
public ShortLookupTable(int offset, short[] data)
throws IllegalArgumentException
@@ -107,14 +107,14 @@ public class ShortLookupTable extends LookupTable
* translation arrays.
*
* @param src Component values of a pixel.
- * @param dest Destination array for values, or null.
+ * @param dst Destination array for values, or null.
* @return Translated values for the pixel.
*/
public int[] lookupPixel(int[] src, int[] dst)
throws ArrayIndexOutOfBoundsException
{
if (dst == null)
- dst = new int[numComponents];
+ dst = new int[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
@@ -140,14 +140,14 @@ public class ShortLookupTable extends LookupTable
* translation arrays.
*
* @param src Component values of a pixel.
- * @param dest Destination array for values, or null.
+ * @param dst Destination array for values, or null.
* @return Translated values for the pixel.
*/
public short[] lookupPixel(short[] src, short[] dst)
throws ArrayIndexOutOfBoundsException
{
if (dst == null)
- dst = new short[numComponents];
+ dst = new short[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
diff --git a/libjava/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/java/awt/image/SinglePixelPackedSampleModel.java
index 578500dbd0a..94a9537318e 100644
--- a/libjava/java/awt/image/SinglePixelPackedSampleModel.java
+++ b/libjava/java/awt/image/SinglePixelPackedSampleModel.java
@@ -59,6 +59,16 @@ public class SinglePixelPackedSampleModel extends SampleModel
int scanlineStride, int[] bitMasks)
{
super(dataType, w, h, bitMasks.length);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ break;
+ default:
+ throw new IllegalArgumentException("SinglePixelPackedSampleModel unsupported dataType");
+ }
this.scanlineStride = scanlineStride;
this.bitMasks = bitMasks;
@@ -382,7 +392,7 @@ public class SinglePixelPackedSampleModel extends SampleModel
* @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
* @param w The width of the pixel rectangle in <code>obj</code>.
* @param h The height of the pixel rectangle in <code>obj</code>.
- * @param obj The primitive array containing the pixels to set.
+ * @param iArray The primitive array containing the pixels to set.
* @param data The DataBuffer to store the pixels into.
* @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], java.awt.image.DataBuffer)
*/
OpenPOWER on IntegriCloud