Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
@@ -0,0 +1,375 @@
/* AffineTransformOp.java -- This class performs affine
transformation between two images or rasters in 2 dimensions.
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.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)
*/
public class AffineTransformOp implements BufferedImageOp, RasterOp
{
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 TYPE_BILINEAR, TYPE_BICUBIC or
* TYPE_NEAREST_NEIGHBOR.
*
* @param xform AffineTransform that will applied to the source image
* @param interpolationType type of interpolation used
*/
public AffineTransformOp (AffineTransform xform, int interpolationType)
{
this.transform = xform;
if (xform.getDeterminant() == 0)
throw new ImagingOpException(null);
switch (interpolationType)
{
case TYPE_BILINEAR:
hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
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);
}
}
/**
* Construct AffineTransformOp with the given xform and rendering hints.
*
* @param xform AffineTransform that will applied to the source image
* @param hints rendering hints that will be used during transformation
*/
public AffineTransformOp (AffineTransform xform, RenderingHints hints)
{
this.transform = xform;
this.hints = hints;
if (xform.getDeterminant() == 0)
throw new ImagingOpException(null);
}
/**
* Creates empty BufferedImage with the size equal to that of the
* transformed image and correct number of bands. The newly created
* image is created with the specified ColorModel.
* If the ColorModel is equal to null, then image is created
* with the ColorModel of the source image.
*
* @param src source image
* @param destCM color model for the destination image
* @return new compatible destination image
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM)
{
// if destCm is not specified, use color model of the source image
if (destCM == null)
destCM = src.getColorModel ();
return new BufferedImage (destCM,
createCompatibleDestRaster (src.getRaster ()),
src.isAlphaPremultiplied (),
null);
}
/**
* Creates empty WritableRaster with the size equal to the transformed
* source raster and correct number of bands
*
* @param src source raster
* @throws RasterFormatException if resulting width or height of raster is 0
* @return new compatible raster
*/
public WritableRaster createCompatibleDestRaster (Raster src)
{
Rectangle rect = (Rectangle) getBounds2D (src);
// throw RasterFormatException if resulting width or height of the
// transformed raster is 0
if (rect.getWidth () == 0 || rect.getHeight () == 0)
throw new RasterFormatException("width or height is 0");
return src.createCompatibleWritableRaster ((int) rect.getWidth (),
(int) rect.getHeight ());
}
/**
* Transforms source image using transform specified at the constructor.
* The resulting transformed image is stored in the destination image.
*
* @param src source image
* @param dst destination image
* @return transformed source image
*/
public final BufferedImage filter (BufferedImage src, BufferedImage dst)
{
if (dst == src)
throw new IllegalArgumentException ("src image cannot be the same as the dst image");
// If the destination image is null, then BufferedImage is
// created with ColorModel of the source image
if (dst == null)
dst = createCompatibleDestImage(src, src.getColorModel ());
// FIXME: Must check if color models of src and dst images are the same.
// If it is not, then source image should be converted to color model
// of the destination image
Graphics2D gr = (Graphics2D) dst.createGraphics ();
gr.setRenderingHints (hints);
gr.drawImage (src, transform, null);
return dst;
}
/**
* Transforms source raster using transform specified at the constructor.
* The resulting raster is stored in the destination raster.
*
* @param src source raster
* @param dst destination raster
* @return transformed raster
*/
public final WritableRaster filter (Raster src, WritableRaster dst)
{
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;
}
/**
* Transforms source image using transform specified at the constructor and
* returns bounds of the transformed image.
*
* @param src image to be transformed
* @return bounds of the transformed image.
*/
public final Rectangle2D getBounds2D (BufferedImage src)
{
return getBounds2D (src.getRaster());
}
/**
* Returns bounds of the transformed raster.
*
* @param src raster to be transformed
* @return bounds of the transformed raster.
*/
public final Rectangle2D getBounds2D (Raster src)
{
// determine new size for the transformed raster.
// Need to calculate transformed coordinates of the lower right
// corner of the raster. The upper left corner is always (0,0)
double x2 = (double) src.getWidth () + src.getMinX ();
double y2 = (double) src.getHeight () + src.getMinY ();
Point2D p2 = getPoint2D (new Point2D.Double (x2,y2), null);
Rectangle2D rect = new Rectangle (0, 0, (int) p2.getX (), (int) p2.getY ());
return rect.getBounds ();
}
/**
* Returns interpolation type used during transformations
*
* @return interpolation type
*/
public final int getInterpolationType ()
{
if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR))
return TYPE_BILINEAR;
else
return TYPE_NEAREST_NEIGHBOR;
}
/**
* Returns location of the transformed source point. The resulting point
* is stored in the dstPt if one is specified.
*
* @param srcPt point to be transformed
* @param dstPt destination point
* @return the location of the transformed source point.
*/
public Point2D getPoint2D (Point2D srcPt, Point2D dstPt)
{
return transform.transform (srcPt, dstPt);
}
/**
* Returns rendering hints that are used during transformation.
*
* @return rendering hints
*/
public final RenderingHints getRenderingHints ()
{
return hints;
}
/**
* Returns transform used in transformation between source and destination
* image.
*
* @return transform
*/
public final AffineTransform getTransform ()
{
return transform;
}
}
@@ -0,0 +1,127 @@
/* AreaAveragingScaleFilter.java -- Java class for filtering images
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* This filter should produce images which do not have image artifacts
* like broken lines which were originally unbroken. The cost is of
* course speed. Using bi-linear interpolation here against 4 pixel
* points should give the desired results although Sun does not
* specify what the exact algorithm should be.
* <br>
* Currently this filter does nothing and needs to be implemented.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public class AreaAveragingScaleFilter extends ReplicateScaleFilter
{
/**
* Construct an instance of <code>AreaAveragingScaleFilter</code> which
* should be used in conjunction with a <code>FilteredImageSource</code>
* object.
*
* @param width the width of the destination image
* @param height the height of the destination image
*/
public AreaAveragingScaleFilter(int width, int height) {
super(width, height);
}
/**
* The <code>ImageProducer</code> should call this method with a
* bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
* <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
* <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
* <code>ImageConsumer</code> interface.
* <br>
* FIXME - more than likely Sun's implementation desires
* <code>TOPDOWNLEFTRIGHT</code> order and this method is overloaded here
* in order to assure that mask is part of the hints added to
* the consumer.
*
* @param flags a bit mask of hints
* @see ImageConsumer
*/
public void setHints(int flags)
{
consumer.setHints(flags);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as a <code>byte</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize)
{
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as an <code>int</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize)
{
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
}
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
}
}
@@ -0,0 +1,548 @@
/* Copyright (C) 2004, 2005, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
private static int[] createBankArray(int size)
{
int[] result = new int[size];
for (int i = 0; i < size; i++)
result[i] = i;
return result;
}
public BandedSampleModel(int dataType, int w, int h, int numBands)
{
this(dataType, w, h, w, createBankArray(numBands), 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)
{
if (bands.length > bankIndices.length)
throw new
RasterFormatException("BandedSampleModel createSubsetSampleModel too"
+" many 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];
}
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, i, 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;
int maxX = x + w;
int maxY = y + h;
for (int yy = x; yy < maxY; yy++)
{
for (int xx = x; xx < maxX; xx++)
{
for (int b = 0; b < numBands; b++)
{
int offset = bandOffsets[b] + yy * scanlineStride + xx;
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;
int maxX = x + w;
int maxY = y + h;
for (int yy = y; yy < maxY; yy++)
{
for (int xx = x; xx < maxX; xx++)
{
int offset = bandOffsets[b] + yy * scanlineStride + xx;
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[i];
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[i];
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[i];
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[i];
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[i];
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[i];
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();
}
}
@@ -0,0 +1,124 @@
/* BufferStrategy.java -- describes image buffering resources
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.BufferCapabilities;
import java.awt.Graphics;
/**
* This class describes a strategy for managing image buffering
* resources on a Canvas or Window. A given buffer strategy may make
* use of hardware acceleration or take advantage of features of the
* native graphics system. Examples of buffering strategies are
* double or triple buffering using either flipping or blitting. For
* the details of these algorithms see BufferCapabilities.
*
* To use a buffer strategy, you retrieve it from either the current
* GraphicsConfiguration or from the Component on which you'd like to
* draw. Then you can query the strategy's capabilities to make sure
* they're suitable.
*
* If the strategy's capabilities are suitable, you can obtain a
* graphics object and use it to draw with this strategy. Drawing
* with a buffer strategy requires extra care, however. You'll need
* to manually cause the next buffer to be shown on the output device.
* And since buffer strategies are usually implemented with a
* VolatileImage, you must frequently check that the contents of the
* buffer are valid and that the buffer still exists.
*
* A buffer strategy is usually implemented using a VolatileImage.
*
* @see VolatileImage
* @since 1.4
*/
public abstract class BufferStrategy
{
/**
* Creates a new buffer strategy.
*/
public BufferStrategy()
{
}
/**
* Retrieves the capabilities of this buffer strategy.
*
* @return this buffer strategy's capabilities
*/
public abstract BufferCapabilities getCapabilities();
/**
* Retrieves a graphics object that can be used to draw using this
* buffer strategy. This method may not be synchronized so be
* careful when calling it from multiple threads. You also must
* manually dispose of this graphics object.
*
* @return a graphics object that can be used to draw using this
* buffer strategy
*/
public abstract Graphics getDrawGraphics();
/**
* Returns whether or not the buffer's resources have been reclaimed
* by the native graphics system. If the buffer resources have been
* lost then you'll need to obtain new resources before drawing
* again. For details, see the documentation for VolatileImage.
*
* @return true if the contents were lost, false otherwise
*/
public abstract boolean contentsLost();
/**
* Returns whether or not the buffer's resources were re-created and
* cleared to the default background color. If the buffer's
* resources have recently been re-created and initialized then the
* buffer's image may need to be re-rendered. For details, see the
* documentation for VolatileImage.
*
* @return true if the contents were restored, false otherwise
*/
public abstract boolean contentsRestored();
/**
* Applies this buffer strategy. In other words, this method brings
* the contents of the back or intermediate buffers to the front
* buffer.
*/
public abstract void show();
}
@@ -0,0 +1,693 @@
/* BufferedImage.java --
Copyright (C) 2000, 2002, 2003, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.ComponentDataBlitOp;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
/**
* A buffered image always starts at coordinates (0, 0).
*
* The buffered image is not subdivided into multiple tiles. Instead,
* the image consists of one large tile (0,0) with the width and
* height of the image. This tile is always considered to be checked
* out.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class BufferedImage extends Image
implements WritableRenderedImage
{
public static final int TYPE_CUSTOM = 0,
TYPE_INT_RGB = 1,
TYPE_INT_ARGB = 2,
TYPE_INT_ARGB_PRE = 3,
TYPE_INT_BGR = 4,
TYPE_3BYTE_BGR = 5,
TYPE_4BYTE_ABGR = 6,
TYPE_4BYTE_ABGR_PRE = 7,
TYPE_USHORT_565_RGB = 8,
TYPE_USHORT_555_RGB = 9,
TYPE_BYTE_GRAY = 10,
TYPE_USHORT_GRAY = 11,
TYPE_BYTE_BINARY = 12,
TYPE_BYTE_INDEXED = 13;
static final int[] bits3 = { 8, 8, 8 };
static final int[] bits4 = { 8, 8, 8 };
static final int[] bits1byte = { 8 };
static final int[] bits1ushort = { 16 };
static final int[] masks_int = { 0x00ff0000,
0x0000ff00,
0x000000ff,
DataBuffer.TYPE_INT };
static final int[] masks_565 = { 0xf800,
0x07e0,
0x001f,
DataBuffer.TYPE_USHORT};
static final int[] masks_555 = { 0x7c00,
0x03e0,
0x001f,
DataBuffer.TYPE_USHORT};
Vector observers;
public BufferedImage(int w, int h, int type)
{
ColorModel cm = null;
boolean alpha = false;
boolean premultiplied = false;
switch (type)
{
case TYPE_4BYTE_ABGR_PRE:
case TYPE_INT_ARGB_PRE:
premultiplied = true;
// fall through
case TYPE_INT_ARGB:
case TYPE_4BYTE_ABGR:
alpha = true;
}
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
switch (type)
{
case TYPE_INT_RGB:
case TYPE_INT_ARGB:
case TYPE_INT_ARGB_PRE:
case TYPE_USHORT_565_RGB:
case TYPE_USHORT_555_RGB:
int[] masks = null;
switch (type)
{
case TYPE_INT_RGB:
case TYPE_INT_ARGB:
case TYPE_INT_ARGB_PRE:
masks = masks_int;
break;
case TYPE_USHORT_565_RGB:
masks = masks_565;
break;
case TYPE_USHORT_555_RGB:
masks = masks_555;
break;
}
cm = new DirectColorModel(cs,
32, // 32 bits in an int
masks[0], // r
masks[1], // g
masks[2], // b
alpha ? 0xff000000 : 0,
premultiplied,
masks[3] // data type
);
break;
case TYPE_INT_BGR:
String msg =
"FIXME: Programmer is confused. Why (and how) does a " +
"TYPE_INT_BGR image use ComponentColorModel to store " +
"8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
"is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
throw new UnsupportedOperationException(msg);
case TYPE_3BYTE_BGR:
case TYPE_4BYTE_ABGR:
case TYPE_4BYTE_ABGR_PRE:
case TYPE_BYTE_GRAY:
case TYPE_USHORT_GRAY:
int[] bits = null;
int dataType = DataBuffer.TYPE_BYTE;
switch (type) {
case TYPE_3BYTE_BGR:
bits = bits3;
break;
case TYPE_4BYTE_ABGR:
case TYPE_4BYTE_ABGR_PRE:
bits = bits4;
break;
case TYPE_BYTE_GRAY:
bits = bits1byte;
break;
case TYPE_USHORT_GRAY:
bits = bits1ushort;
dataType = DataBuffer.TYPE_USHORT;
break;
}
cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
alpha ?
Transparency.TRANSLUCENT:
Transparency.OPAQUE,
dataType);
break;
case TYPE_BYTE_BINARY:
byte[] vals = { 0, (byte) 0xff };
cm = new IndexColorModel(8, 2, vals, vals, vals);
break;
case TYPE_BYTE_INDEXED:
String msg2 = "type not implemented yet";
throw new UnsupportedOperationException(msg2);
// FIXME: build color-cube and create color model
}
init(cm,
cm.createCompatibleWritableRaster(w, h),
premultiplied,
null, // no properties
type
);
}
public BufferedImage(int w, int h, int type,
IndexColorModel indexcolormodel)
{
if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
throw new IllegalArgumentException("type must be binary or indexed");
init(indexcolormodel,
indexcolormodel.createCompatibleWritableRaster(w, h),
false, // not premultiplied (guess)
null, // no properties
type);
}
public BufferedImage(ColorModel colormodel,
WritableRaster writableraster,
boolean premultiplied,
Hashtable properties)
{
init(colormodel, writableraster, premultiplied, properties,
TYPE_CUSTOM);
// TODO: perhaps try to identify type?
}
WritableRaster raster;
ColorModel colorModel;
Hashtable properties;
boolean isPremultiplied;
int type;
private void init(ColorModel cm,
WritableRaster writableraster,
boolean premultiplied,
Hashtable properties,
int type)
{
raster = writableraster;
colorModel = cm;
this.properties = properties;
isPremultiplied = premultiplied;
this.type = type;
}
//public void addTileObserver(TileObserver tileobserver) {}
public void coerceData(boolean premultiplied)
{
colorModel = colorModel.coerceData(raster, premultiplied);
}
public WritableRaster copyData(WritableRaster dest)
{
if (dest == null)
dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
getWidth(),getHeight());
int x = dest.getMinX();
int y = dest.getMinY();
int w = dest.getWidth();
int h = dest.getHeight();
// create a src child that has the right bounds...
WritableRaster src =
raster.createWritableChild(x, y, w, h, x, y,
null // same bands
);
if (src.getSampleModel () instanceof ComponentSampleModel
&& dest.getSampleModel () instanceof ComponentSampleModel)
// Refer to ComponentDataBlitOp for optimized data blitting:
ComponentDataBlitOp.INSTANCE.filter(src, dest);
else
{
// slower path
int samples[] = src.getPixels (x, y, w, h, (int [])null);
dest.setPixels (x, y, w, h, samples);
}
return dest;
}
public Graphics2D createGraphics()
{
GraphicsEnvironment env;
env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
return env.createGraphics (this);
}
public void flush() {
}
public WritableRaster getAlphaRaster()
{
return colorModel.getAlphaRaster(raster);
}
public ColorModel getColorModel()
{
return colorModel;
}
public Raster getData()
{
return copyData(null);
/* TODO: this might be optimized by returning the same
raster (not writable) as long as image data doesn't change. */
}
public Raster getData(Rectangle rectangle)
{
WritableRaster dest =
raster.createCompatibleWritableRaster(rectangle);
return copyData(dest);
}
public Graphics getGraphics()
{
return createGraphics();
}
public int getHeight()
{
return raster.getHeight();
}
public int getHeight(ImageObserver imageobserver)
{
return getHeight();
}
public int getMinTileX()
{
return 0;
}
public int getMinTileY()
{
return 0;
}
public int getMinX()
{
return 0;
}
public int getMinY()
{
return 0;
}
public int getNumXTiles()
{
return 1;
}
public int getNumYTiles()
{
return 1;
}
public Object getProperty(String string)
{
if (properties == null)
return null;
return properties.get(string);
}
public Object getProperty(String string, ImageObserver imageobserver)
{
return getProperty(string);
}
public String[] getPropertyNames()
{
// FIXME: implement
return null;
}
public int getRGB(int x, int y)
{
Object rgbElem = raster.getDataElements(x, y,
null // create as needed
);
return colorModel.getRGB(rgbElem);
}
public int[] getRGB(int startX, int startY, int w, int h,
int[] rgbArray,
int offset, int scanlineStride)
{
if (rgbArray == null)
{
/*
000000000000000000
00000[#######----- [ = start
-----########----- ] = end
-----#######]00000
000000000000000000 */
int size = (h-1)*scanlineStride + w;
rgbArray = new int[size];
}
int endX = startX + w;
int endY = startY + h;
/* *TODO*:
Opportunity for optimization by examining color models...
Perhaps wrap the rgbArray up in a WritableRaster with packed
sRGB color model and perform optimized rendering into the
array. */
Object rgbElem = null;
for (int y=startY; y<endY; y++)
{
int xoffset = offset;
for (int x=startX; x<endX; x++)
{
int rgb;
rgbElem = raster.getDataElements(x, y, rgbElem);
rgb = colorModel.getRGB(rgbElem);
rgbArray[xoffset++] = rgb;
}
offset += scanlineStride;
}
return rgbArray;
}
public WritableRaster getRaster()
{
return raster;
}
public SampleModel getSampleModel()
{
return raster.getSampleModel();
}
public ImageProducer getSource()
{
return new ImageProducer() {
Vector consumers = new Vector();
public void addConsumer(ImageConsumer ic)
{
if(!consumers.contains(ic))
consumers.add(ic);
}
public boolean isConsumer(ImageConsumer ic)
{
return consumers.contains(ic);
}
public void removeConsumer(ImageConsumer ic)
{
consumers.remove(ic);
}
public void startProduction(ImageConsumer ic)
{
int x = 0;
int y = 0;
int width = getWidth();
int height = getHeight();
int stride = width;
int offset = 0;
int[] pixels = getRGB(x, y,
width, height,
(int[])null, offset, stride);
ColorModel model = getColorModel();
consumers.add(ic);
for(int i=0;i<consumers.size();i++)
{
ImageConsumer c = (ImageConsumer) consumers.elementAt(i);
c.setHints(ImageConsumer.SINGLEPASS);
c.setDimensions(getWidth(), getHeight());
c.setPixels(x, y, width, height, model, pixels, offset, stride);
c.imageComplete(ImageConsumer.STATICIMAGEDONE);
}
}
public void requestTopDownLeftRightResend(ImageConsumer ic)
{
startProduction(ic);
}
};
}
public Vector getSources()
{
return null;
}
public BufferedImage getSubimage(int x, int y, int w, int h)
{
WritableRaster subRaster =
getRaster().createWritableChild(x, y, w, h, 0, 0, null);
return new BufferedImage(getColorModel(),
subRaster,
isPremultiplied,
properties);
}
public Raster getTile(int tileX, int tileY)
{
return getWritableTile(tileX, tileY);
}
public int getTileGridXOffset()
{
return 0; // according to javadocs
}
public int getTileGridYOffset()
{
return 0; // according to javadocs
}
public int getTileHeight()
{
return getHeight(); // image is one big tile
}
public int getTileWidth()
{
return getWidth(); // image is one big tile
}
public int getType()
{
return type;
}
public int getWidth()
{
return raster.getWidth();
}
public int getWidth(ImageObserver imageobserver)
{
return getWidth();
}
public WritableRaster getWritableTile(int tileX, int tileY)
{
isTileWritable(tileX, tileY); // for exception
return raster;
}
private static final Point[] tileIndices = { new Point() };
public Point[] getWritableTileIndices()
{
return tileIndices;
}
public boolean hasTileWriters()
{
return true;
}
public boolean isAlphaPremultiplied()
{
return isPremultiplied;
}
public boolean isTileWritable(int tileX, int tileY)
{
if ((tileX != 0) || (tileY != 0))
throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
return true;
}
public void releaseWritableTile(int tileX, int tileY)
{
isTileWritable(tileX, tileY); // for exception
}
//public void removeTileObserver(TileObserver tileobserver) {}
public void setData(Raster src)
{
int x = src.getMinX();
int y = src.getMinY();
int w = src.getWidth();
int h = src.getHeight();
// create a dest child that has the right bounds...
WritableRaster dest =
raster.createWritableChild(x, y, w, h, x, y,
null // same bands
);
if (src.getSampleModel () instanceof ComponentSampleModel
&& dest.getSampleModel () instanceof ComponentSampleModel)
// Refer to ComponentDataBlitOp for optimized data blitting:
ComponentDataBlitOp.INSTANCE.filter(src, dest);
else
{
// slower path
int samples[] = src.getPixels (x, y, w, h, (int [])null);
dest.setPixels (x, y, w, h, samples);
}
}
public void setRGB(int x, int y, int argb)
{
Object rgbElem = colorModel.getDataElements(argb, null);
raster.setDataElements(x, y, rgbElem);
}
public void setRGB(int startX, int startY, int w, int h,
int[] argbArray, int offset, int scanlineStride)
{
int endX = startX + w;
int endY = startY + h;
Object rgbElem = null;
for (int y=startY; y<endY; y++)
{
int xoffset = offset;
for (int x=startX; x<endX; x++)
{
int argb = argbArray[xoffset++];
rgbElem = colorModel.getDataElements(argb, rgbElem);
raster.setDataElements(x, y, rgbElem);
}
offset += scanlineStride;
}
}
public String toString()
{
StringBuffer buf;
buf = new StringBuffer(/* estimated length */ 120);
buf.append("BufferedImage@");
buf.append(Integer.toHexString(hashCode()));
buf.append(": type=");
buf.append(type);
buf.append(' ');
buf.append(colorModel);
buf.append(' ');
buf.append(raster);
return buf.toString();
}
/**
* Adds a tile observer. If the observer is already present, it receives
* multiple notifications.
*
* @param to The TileObserver to add.
*/
public void addTileObserver (TileObserver to)
{
if (observers == null)
observers = new Vector ();
observers.add (to);
}
/**
* Removes a tile observer. If the observer was not registered,
* nothing happens. If the observer was registered for multiple
* notifications, it is now registered for one fewer notification.
*
* @param to The TileObserver to remove.
*/
public void removeTileObserver (TileObserver to)
{
if (observers == null)
return;
observers.remove (to);
}
}
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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);
}
}
@@ -0,0 +1,55 @@
/* BufferedImageOp.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* NEEDS DOCUMENTATION
*/
public interface BufferedImageOp
{
BufferedImage filter(BufferedImage src, BufferedImage dst);
Rectangle2D getBounds2D(BufferedImage src);
BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM);
Point2D getPoint2D(Point2D src, Point2D dst);
RenderingHints getRenderingHints();
} // interface BufferedImageOp
@@ -0,0 +1,166 @@
/* ByteLookupTable.java -- Java class for a pixel translation table.
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* ByteLookupTable represents translation arrays for pixel values. It wraps
* one or more data arrays for each layer (or component) in an image, such as
* Alpha, R, G, and B. When doing translation, the offset is subtracted from
* the pixel values to allow a subset of an array to be used.
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @version 1.0
*/
public class ByteLookupTable extends LookupTable
{
// Array of translation tables.
private byte data[][];
/**
* Creates a new <code>ByteLookupTable</code> instance.
*
* Offset is subtracted from pixel values when looking up in the translation
* tables. If data.length is one, the same table is applied to all pixel
* components.
*
* @param offset Offset to be subtracted.
* @param data Array of lookup tables.
* @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
*/
public ByteLookupTable(int offset, byte[][] data)
throws IllegalArgumentException
{
super(offset, data.length);
this.data = data;
}
/**
* Creates a new <code>ByteLookupTable</code> instance.
*
* Offset is subtracted from pixel values when looking up in the translation
* table. The same table is applied to all pixel components.
*
* @param offset Offset to be subtracted.
* @param data Lookup table for all components.
* @exception IllegalArgumentException if offset &lt; 0.
*/
public ByteLookupTable(int offset, byte[] data)
throws IllegalArgumentException
{
super(offset, 1);
this.data = new byte[][] {data};
}
/**
* Return the lookup tables.
*
* @return the tables
*/
public final byte[][] getTable()
{
return data;
}
/**
* Return translated values for a pixel.
*
* For each value in the pixel src, use the value minus offset as an index
* in the component array and copy the value there to the output for the
* component. If dest is null, the output is a new array, otherwise the
* translated values are written to dest. Dest can be the same array as
* src.
*
* For example, if the pixel src is [2, 4, 3], and offset is 1, the output
* is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
* translation arrays.
*
* @param src Component values of a pixel.
* @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[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
dst[i] = data[0][src[i] - offset];
else
for (int i=0; i < src.length; i++)
dst[i] = data[i][src[i] - offset];
return dst;
}
/**
* Return translated values for a pixel.
*
* For each value in the pixel src, use the value minus offset as an index
* in the component array and copy the value there to the output for the
* component. If dest is null, the output is a new array, otherwise the
* translated values are written to dest. Dest can be the same array as
* src.
*
* For example, if the pixel src is [2, 4, 3], and offset is 1, the output
* is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
* translation arrays.
*
* @param src Component values of a pixel.
* @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[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
dst[i] = data[0][((int)src[i]) - offset];
else
for (int i=0; i < src.length; i++)
dst[i] = data[i][((int)src[i]) - offset];
return dst;
}
}
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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))));
}
}
}
@@ -0,0 +1,758 @@
/* ColorModel.java --
Copyright (C) 1999, 2000, 2002, 2003, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.lang.reflect.Constructor;
import java.util.Arrays;
/**
* A color model operates with colors in several formats:
*
* <ul>
* <li>normalized: component samples are in range [0.0, 1.0].</li>
*
* <li>color model pixel value: all the color component samples for a
* sigle pixel packed/encoded in a way natural for the color
* model.</li>
*
* <li>color model pixel int value: only makes sense if the natural
* encoding of a single pixel can fit in a single int value.</li>
*
* <li>array of transferType containing a single pixel: the pixel is
* encoded in the natural way of the color model, taking up as many
* array elements as needed.</li>
*
* <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
* default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
*
* <li>single [0, 255] scaled int samples from default sRGB color
* space. These are always assumed to be alpha non-premultiplied.</li>
*
* <li>arrays of unnormalized component samples of single pixel: these
* samples are scaled and multiplied according to the color model, but
* is otherwise not packed or encoded. Each element of the array is one
* separate component sample. The color model only operate on the
* components from one pixel at a time, but using offsets, allows
* manipulation of arrays that contain the components of more than one
* pixel.</li>
*
* </ul>
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author C. Brian Jones (cbj@gnu.org)
*/
public abstract class ColorModel implements Transparency
{
protected int pixel_bits;
protected int transferType;
int[] bits;
ColorSpace cspace;
int transparency;
boolean hasAlpha;
boolean isAlphaPremultiplied;
static int[] nArray(int value, int times)
{
int[] array = new int[times];
java.util.Arrays.fill(array, value);
return array;
}
static byte[] nArray(byte value, int times)
{
byte[] array = new byte[times];
java.util.Arrays.fill(array, value);
return array;
}
/**
* Constructs the default color model. The default color model
* can be obtained by calling <code>getRGBdefault</code> of this
* class.
* @param bits the number of bits wide used for bit size of pixel values
*/
public ColorModel(int bits)
{
this(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,
Buffers.smallestAppropriateTransferType(bits * 4));
}
/**
* Constructs a ColorModel that translates pixel values to
* color/alpha components.
*
* @exception IllegalArgumentException If the length of the bit array is less
* than the number of color or alpha components in this ColorModel, or if the
* transparency is not a valid value, or if the sum of the number of bits in
* bits is less than 1 or if any of the elements in bits is less than 0.
*/
protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
boolean hasAlpha, boolean isAlphaPremultiplied,
int transparency, int transferType)
{
int bits_sum = 0;
for (int i = 0; i < bits.length; i++)
{
if (bits [i] < 0)
throw new IllegalArgumentException ();
bits_sum |= bits [i];
}
if ((bits.length < cspace.getNumComponents())
|| (bits_sum < 1))
throw new IllegalArgumentException ();
this.pixel_bits = pixel_bits;
this.bits = bits;
this.cspace = cspace;
this.hasAlpha = hasAlpha;
this.isAlphaPremultiplied = isAlphaPremultiplied;
this.transparency = 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.
}
/**
* Returns the default color model which in Sun's case is an instance
* of <code>DirectColorModel</code>.
*/
public static ColorModel getRGBdefault()
{
return new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000);
}
public final boolean hasAlpha()
{
return hasAlpha;
}
public final boolean isAlphaPremultiplied()
{
return isAlphaPremultiplied;
}
/**
* Get get number of bits wide used for the bit size of pixel values
*/
public int getPixelSize()
{
return pixel_bits;
}
public int getComponentSize(int componentIdx)
{
return bits[componentIdx];
}
public int[] getComponentSize()
{
return bits;
}
public int getTransparency()
{
return transparency;
}
public int getNumComponents()
{
return getNumColorComponents() + (hasAlpha ? 1 : 0);
}
public int getNumColorComponents()
{
return cspace.getNumComponents();
}
/**
* Converts pixel value to sRGB and extract red int sample scaled
* to range [0, 255].
*
* @param pixel pixel value that will be interpreted according to
* the color model, (assumed alpha premultiplied if color model says
* so.)
*
* @return red sample scaled to range [0, 255], from default color
* space sRGB, alpha non-premultiplied.
*/
public abstract int getRed(int pixel);
/**
* Converts pixel value to sRGB and extract green int sample
* scaled to range [0, 255].
*
* @see #getRed(int)
*/
public abstract int getGreen(int pixel);
/**
* Converts pixel value to sRGB and extract blue int sample
* scaled to range [0, 255].
*
* @see #getRed(int)
*/
public abstract int getBlue(int pixel);
/**
* Extract alpha int sample from pixel value, scaled to [0, 255].
*
* @param pixel pixel value that will be interpreted according to
* the color model.
*
* @return alpha sample, scaled to range [0, 255].
*/
public abstract int getAlpha(int pixel);
/**
* Converts a pixel int value of the color space of the color
* model to a sRGB pixel int value.
*
* This method is typically overriden in subclasses to provide a
* more efficient implementation.
*
* @param pixel pixel value that will be interpreted according to
* the color model.
*
* @return a pixel in sRGB color space, encoded in default
* 0xAARRGGBB format. */
public int getRGB(int pixel)
{
return
((getAlpha(pixel) & 0xff) << 24) |
(( getRed(pixel) & 0xff) << 16) |
((getGreen(pixel) & 0xff) << 8) |
(( getBlue(pixel) & 0xff) << 0);
}
/**
* In this color model we know that the whole pixel value will
* always be contained within the first element of the pixel
* array.
*/
final int getPixelFromArray(Object inData) {
DataBuffer data =
Buffers.createBufferFromData(transferType, inData, 1);
Object da = Buffers.getData(data);
return data.getElem(0);
}
/**
* Converts pixel in the given array to sRGB and extract blue int
* sample scaled to range [0-255].
*
* This method is typically overriden in subclasses to provide a
* more efficient implementation.
*
* @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)
{
return getRed(getPixelFromArray(inData));
}
/**
* @see #getRed(Object)
*/
public int getGreen(Object inData)
{
return getGreen(getPixelFromArray(inData));
}
/**
* @see #getRed(Object)
*/
public int getBlue(Object inData) {
return getBlue(getPixelFromArray(inData));
}
/**
* @see #getRed(Object)
*/
public int getAlpha(Object inData) {
return getAlpha(getPixelFromArray(inData));
}
/**
* Converts a pixel in the given array of the color space of the
* color model to an sRGB pixel int value.
*
* <p>This method performs the inverse function of
* <code>getDataElements(int rgb, Object pixel)</code>.
* I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
* null)))</code>.
*
* @param inData array of transferType containing a single pixel. The
* pixel should be encoded in the natural way of the color model.
*
* @return a pixel in sRGB color space, encoded in default
* 0xAARRGGBB format.
*
* @see #getDataElements(int, Object)
*/
public int getRGB(Object inData)
{
return
((getAlpha(inData) & 0xff) << 24) |
(( getRed(inData) & 0xff) << 16) |
((getGreen(inData) & 0xff) << 8) |
(( getBlue(inData) & 0xff) << 0);
}
/**
* Converts an sRGB pixel int value to an array containing a
* single pixel of the color space of the color model.
*
* <p>This method performs the inverse function of
* <code>getRGB(Object inData)</code>.
*
* Outline of conversion process:
*
* <ol>
*
* <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
*
* <li>Convert to color space components using fromRGB in
* ColorSpace.</li>
*
* <li>If color model has alpha and should be premultiplied,
* multiply color space components with alpha value</li>
*
* <li>Scale the components to the correct number of bits.</li>
*
* <li>Arrange the components in the output array</li>
*
* </ol>
*
* @param rgb The color to be converted to dataElements. A pixel
* in sRGB color space, encoded in default 0xAARRGGBB format,
* assumed not alpha premultiplied.
*
* @param pixel to avoid needless creation of arrays, an array to
* use to return the pixel can be given. If null, a suitable array
* will be created.
*
* @return An array of transferType values representing the color,
* in the color model format. The color model defines whether the
*
* @see #getRGB(Object)
*/
public Object getDataElements(int rgb, Object pixel)
{
// subclasses has to implement this method.
throw new UnsupportedOperationException();
}
/**
* Fills an array with the unnormalized component samples from a
* pixel value. I.e. decompose the pixel, but not perform any
* color conversion.
*
* This method is typically overriden in subclasses to provide a
* more efficient implementation.
*
* @param pixel pixel value encoded according to the color model.
*
* @return 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.
*/
public int[] getComponents(int pixel, int[] components, int offset)
{
// subclasses has to implement this method.
throw new UnsupportedOperationException();
}
/**
* Fills an array with the unnormalized component samples from an
* array of transferType containing a single pixel. I.e. decompose
* the pixel, but not perform any color conversion.
*
* This method is typically overriden in subclasses to provide a
* more efficient implementation.
*
* @param array of transferType containing a single pixel. The
* pixel should be encoded in the natural way of the color model.
*
* @return 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.
*/
public int[] getComponents(Object pixel, int[] components, int offset)
{
// subclasses has to implement this method.
throw new UnsupportedOperationException();
}
/**
* Convert normalized components to unnormalized components.
*/
public int[] getUnnormalizedComponents(float[] normComponents,
int normOffset,
int[] components,
int offset)
{
int numComponents = getNumComponents();
if (components == null)
{
components = new int[offset + numComponents];
}
for (int i=0; i<numComponents; i++)
{
float in = normComponents[normOffset++];
int out = (int) (in * ((1<<getComponentSize(i)) - 1));
components[offset++] = out;
}
return components;
}
/**
* Convert unnormalized components to normalized components.
*/
public float[] getNormalizedComponents(int[] components,
int offset,
float[] normComponents,
int normOffset)
{
int numComponents = getNumComponents();
if (normComponents == null)
{
normComponents = new float[normOffset + numComponents];
}
for (int i=0; i<numComponents; i++)
{
float in = components[offset++];
float out = in / ((1<<getComponentSize(i)) - 1);
normComponents[normOffset++] = out;
}
return normComponents;
}
/**
* Convert unnormalized components to normalized components.
*
* @since 1.4
*/
public float[] getNormalizedComponents (Object pixel,
float[] normComponents,
int normOffset)
{
// subclasses has to implement this method.
throw new UnsupportedOperationException();
}
/**
* Converts the unnormalized 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 performs the inverse function of
* <code>getComponents(int pixel, int[] components,
* int offset)</code>. I.e.
*
* <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
* 0), 0))</code>.
*
* This method is overriden in subclasses since this abstract class throws
* UnsupportedOperationException().
*
* @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 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)
{
return
getDataElement(getUnnormalizedComponents(components, offset, null, 0),
0);
}
public Object getDataElements(int[] components, int offset, Object obj)
{
// subclasses have to implement this method.
throw new UnsupportedOperationException();
}
/**
* 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)
{
return
getDataElements(getUnnormalizedComponents(components, offset, null, 0),
0, obj);
}
public boolean equals(Object obj)
{
if (!(obj instanceof ColorModel)) return false;
ColorModel o = (ColorModel) obj;
return
(pixel_bits == o.pixel_bits) &&
(transferType == o.transferType) &&
(transparency == o.transparency) &&
(hasAlpha == o.hasAlpha) &&
(isAlphaPremultiplied == o.isAlphaPremultiplied) &&
Arrays.equals(bits, o.bits) &&
(cspace.equals(o.cspace));
}
public final ColorSpace getColorSpace()
{
return cspace;
}
// Typically overridden
public ColorModel coerceData(WritableRaster raster,
boolean isAlphaPremultiplied)
{
if (this.isAlphaPremultiplied == isAlphaPremultiplied)
return this;
int w = raster.getWidth();
int h = raster.getHeight();
int x = raster.getMinX();
int y = raster.getMinY();
int size = w*h;
int numColors = getNumColorComponents();
int numComponents = getNumComponents();
int alphaScale = (1<<getComponentSize(numColors)) - 1;
double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
for (int i=0; i<size; i++)
{
double alpha = pixels[i*numComponents+numColors]*alphaScale;
for (int c=0; c<numColors; c++)
{
int offset = i*numComponents+c;
if (isAlphaPremultiplied)
pixels[offset] = pixels[offset]/alpha;
else
pixels[offset] = pixels[offset]*alpha;
}
}
raster.setPixels(0, 0, w, h, pixels);
// FIXME: what can we return?
return null;
}
/**
* Checks if the given raster has a compatible data-layout (SampleModel).
* @param raster The Raster to test.
* @return true if raster is compatible.
*/
public boolean isCompatibleRaster(Raster raster)
{
SampleModel sampleModel = raster.getSampleModel();
return isCompatibleSampleModel(sampleModel);
}
// Typically overridden
public WritableRaster createCompatibleWritableRaster(int w, int h)
{
return new WritableRaster(createCompatibleSampleModel(w, h),
new Point(0, 0));
}
// Typically overridden
public SampleModel createCompatibleSampleModel(int w, int h)
{
throw new UnsupportedOperationException();
}
// Typically overridden
public boolean isCompatibleSampleModel(SampleModel sm)
{
return sm.getTransferType() == transferType;
}
public final int getTransferType ()
{
return transferType;
}
/**
* Subclasses must override this method if it is possible for the
* color model to have an alpha channel.
*
* @return null, as per JDK 1.3 doc. Subclasses will only return
* null if no alpha raster exists.
*/
public WritableRaster getAlphaRaster(WritableRaster raster)
{
return null;
/* It is a mystery to me why we couldn't use the following code...
if (!hasAlpha()) return null;
SampleModel sm = raster.getSampleModel();
int[] alphaBand = { sm.getNumBands() - 1 };
SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
DataBuffer buffer = raster.getDataBuffer();
Point origin = new Point(0, 0);
return Raster.createWritableRaster(alphaModel, buffer, origin);
...here, and avoided overriding the method in subclasses,
but the Sun docs state that this method always will return
null, and that overriding is required. Oh, well.
*/
}
String stringParam()
{
return "pixel_bits=" + pixel_bits +
", cspace=" + cspace +
", transferType=" + transferType +
", transparency=" + transparency +
", hasAlpha=" + hasAlpha +
", isAlphaPremultiplied=" + isAlphaPremultiplied;
}
public String toString()
{
return getClass().getName() + "[" + stringParam() + "]";
}
}
@@ -0,0 +1,391 @@
/* ComponentColorModel.java --
Copyright (C) 2000, 2002, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
import java.awt.Point;
import java.awt.color.ColorSpace;
public class ComponentColorModel extends ColorModel
{
private static int sum(int[] values)
{
int sum = 0;
for (int i=0; i<values.length; i++)
sum += values[i];
return sum;
}
public ComponentColorModel(ColorSpace colorSpace, int[] bits,
boolean hasAlpha,
boolean isAlphaPremultiplied,
int transparency, int transferType)
{
super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
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();
return (int) getRGBFloat(pixel)[0];
}
public int getGreen(int pixel)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
return (int) getRGBFloat(pixel)[0];
}
public int getBlue(int pixel)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
return (int) getRGBFloat(pixel)[0];
}
public int getAlpha(int pixel)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
int shift = 8 - getComponentSize(getNumColorComponents());
if (shift >= 0) return pixel << shift;
return pixel >> (-shift);
}
public int getRGB(int pixel)
{
float[] rgb = getRGBFloat(pixel);
int ret = getRGB(rgb);
if (hasAlpha()) ret |= getAlpha(pixel) << 24;
return ret;
}
/* Note, it's OK to pass a to large array to toRGB(). Extra
elements are ignored. */
private float[] getRGBFloat(int pixel)
{
float[] data = { pixel };
return cspace.toRGB(data);
}
private float[] getRGBFloat(Object inData)
{
DataBuffer buffer =
Buffers.createBufferFromData(transferType, inData,
getNumComponents());
int colors = getNumColorComponents();
float[] data = new float[colors];
// FIXME: unpremultiply data that is premultiplied
for (int i=0; i<colors; i++)
{
float maxValue = (1<<getComponentSize(i))-1;
data[i] = buffer.getElemFloat(i)/maxValue;
}
float[] rgb = cspace.toRGB(data);
return rgb;
}
public int getRed(Object inData)
{
return (int) getRGBFloat(inData)[0]*255;
}
public int getGreen(Object inData)
{
return (int) getRGBFloat(inData)[1]*255;
}
public int getBlue(Object inData)
{
return (int) getRGBFloat(inData)[2]*255;
}
public int getAlpha(Object inData)
{
DataBuffer buffer =
Buffers.createBufferFromData(transferType, inData,
getNumComponents());
int shift = 8 - getComponentSize(getNumColorComponents());
int alpha = buffer.getElem(getNumColorComponents());
if (shift >= 0) return alpha << shift;
return alpha >> (-shift);
}
private int getRGB(float[] rgb)
{
/* NOTE: We could cast to byte instead of int here. This would
avoid bits spilling over from one bit field to
another. But, if we assume that floats are in the [0.0,
1.0] range, this will never happen anyway. */
/* Remember to multiply BEFORE casting to int, otherwise, decimal
point data will be lost. */
int ret =
(((int) (rgb[0]*255F)) << 16) |
(((int) (rgb[1]*255F)) << 8) |
(((int) (rgb[2]*255F)) << 0);
return ret;
}
/**
* @param inData pixel data of transferType, as returned by the
* getDataElements method in SampleModel.
*/
public int getRGB(Object inData)
{
float[] rgb = getRGBFloat(inData);
int ret = getRGB(rgb);
if (hasAlpha()) ret |= getAlpha(inData) << 24;
return ret;
}
public Object getDataElements(int rgb, Object pixel)
{
// Convert rgb to [0.0, 1.0] sRGB values.
float[] rgbFloats = {
((rgb >> 16)&0xff)/255.0F,
((rgb >> 8)&0xff)/255.0F,
((rgb >> 0)&0xff)/255.0F
};
// Convert from rgb to color space components.
float[] data = cspace.fromRGB(rgbFloats);
DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
getNumComponents());
int numColors = getNumColorComponents();
if (hasAlpha())
{
float alpha = ((rgb >> 24)&0xff)/255.0F;
/* If color model has alpha and should be premultiplied, multiply
color space components with alpha value. */
if (isAlphaPremultiplied()) {
for (int i=0; i<numColors; i++)
data[i] *= alpha;
}
// Scale the alpha sample to the correct number of bits.
alpha *= (1<<(bits[numColors]-1));
// Arrange the alpha sample in the output array.
buffer.setElemFloat(numColors, alpha);
}
for (int i=0; i<numColors; i++)
{
// Scale the color samples to the correct number of bits.
float value = data[i]*(1<<(bits[i]-1));
// Arrange the color samples in the output array.
buffer.setElemFloat(i, value);
}
return Buffers.getData(buffer);
}
public int[] getComponents(int pixel, int[] components, int offset)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
if (components == null)
components = new int[getNumComponents() + offset];
components[offset] = pixel;
return components;
}
public int[] getComponents(Object pixel, int[] components, int offset)
{
DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
getNumComponents());
int numComponents = getNumComponents();
if (components == null)
components = new int[numComponents + offset];
for (int i=0; i<numComponents; i++)
components[offset++] = buffer.getElem(i);
return components;
}
public int getDataElement(int[] components, int offset)
{
if (getNumComponents()>1) throw new IllegalArgumentException();
return components[offset];
}
public Object getDataElements(int[] components, int offset, Object obj)
{
DataBuffer buffer = Buffers.createBuffer(transferType, obj,
getNumComponents());
int numComponents = getNumComponents();
for (int i=0; i<numComponents; i++)
buffer.setElem(i, components[offset++]);
return Buffers.getData(buffer);
}
public ColorModel coerceData(WritableRaster raster,
boolean isAlphaPremultiplied) {
if (this.isAlphaPremultiplied == isAlphaPremultiplied)
return this;
/* TODO: provide better implementation based on the
assumptions we can make due to the specific type of the
color model. */
super.coerceData(raster, isAlphaPremultiplied);
return new ComponentColorModel(cspace, bits, hasAlpha(),
isAlphaPremultiplied, // argument
transparency, transferType);
}
public boolean isCompatibleRaster(Raster raster)
{
return super.isCompatibleRaster(raster);
// FIXME: Should we test something more here? (Why override?)
}
public WritableRaster createCompatibleWritableRaster(int w, int h)
{
SampleModel sm = createCompatibleSampleModel(w, h);
Point origin = new Point(0, 0);
return Raster.createWritableRaster(sm, origin);
}
/**
* Creates a <code>SampleModel</code> whose arrangement of pixel
* data is compatible to this <code>ColorModel</code>.
*
* @param w the number of pixels in the horizontal direction.
* @param h the number of pixels in the vertical direction.
*/
public SampleModel createCompatibleSampleModel(int w, int h)
{
int pixelStride, scanlineStride;
int[] bandOffsets;
pixelStride = getNumComponents();
scanlineStride = pixelStride * w;
/* We might be able to re-use the same bandOffsets array among
* multiple calls to this method. However, this optimization does
* not seem worthwile because setting up descriptive data
* structures (such as SampleModels) is neglectible in comparision
* to shuffling around masses of pixel data.
*/
bandOffsets = new int[pixelStride];
for (int i = 0; i < pixelStride; i++)
bandOffsets[i] = i;
/* FIXME: Think about whether it would make sense to return the
* possibly more efficient PixelInterleavedSampleModel for other
* transferTypes as well. It seems unlikely that this would break
* any user applications, so the Mauve tests on this method
* might be too restrictive.
*/
switch (transferType)
{
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
return new PixelInterleavedSampleModel(transferType, w, h,
pixelStride,
scanlineStride,
bandOffsets);
default:
return new ComponentSampleModel(transferType, w, h,
pixelStride,
scanlineStride,
bandOffsets);
}
}
public boolean isCompatibleSampleModel(SampleModel sm)
{
return
(sm instanceof ComponentSampleModel) &&
super.isCompatibleSampleModel(sm);
}
public WritableRaster getAlphaRaster(WritableRaster raster)
{
if (!hasAlpha()) return null;
SampleModel sm = raster.getSampleModel();
int[] alphaBand = { sm.getNumBands() - 1 };
SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
DataBuffer buffer = raster.getDataBuffer();
Point origin = new Point(0, 0);
return Raster.createWritableRaster(alphaModel, buffer, origin);
}
public boolean equals(Object obj)
{
if (!(obj instanceof ComponentColorModel)) return false;
return super.equals(obj);
}
}
@@ -0,0 +1,544 @@
/* Copyright (C) 2000, 2002 Free Software Foundation
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* 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
{
protected int[] bandOffsets;
protected int[] bankIndices;
// FIXME: Should we really shadow the numBands in the superclass?
//protected int numBands;
/** Used when creating data buffers. */
protected int numBanks;
protected int scanlineStride;
protected int pixelStride;
private boolean tightPixelPacking = false;
public ComponentSampleModel(int dataType,
int w, int h,
int pixelStride,
int scanlineStride,
int[] bandOffsets)
{
this(dataType, w, h, pixelStride, scanlineStride,
new int[bandOffsets.length], bandOffsets);
}
public ComponentSampleModel(int dataType,
int w, int h,
int pixelStride,
int scanlineStride,
int[] bankIndices,
int[] bandOffsets)
{
super(dataType, w, h, bandOffsets.length);
if ((pixelStride<0) || (scanlineStride<0) ||
(bandOffsets.length<1) ||
(bandOffsets.length != bankIndices.length))
throw new IllegalArgumentException();
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);
this.scanlineStride = scanlineStride;
this.pixelStride = pixelStride;
// See if we can use some speedups
/* FIXME: May these checks should be reserved for the
PixelInterleavedSampleModel? */
if (pixelStride == numBands)
{
tightPixelPacking = true;
for (int b=0; b<numBands; b++) {
if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
{
tightPixelPacking = false;
break;
}
}
}
}
public SampleModel createCompatibleSampleModel(int w, int h)
{
return new ComponentSampleModel(dataType, w, h, pixelStride,
scanlineStride, bankIndices,
bandOffsets);
}
public SampleModel createSubsetSampleModel(int[] bands)
{
int numBands = bands.length;
int[] bankIndices = new int[numBands];
int[] bandOffsets = new int[numBands];
for (int b=0; b<numBands; b++)
{
bankIndices[b] = this.bankIndices[bands[b]];
bandOffsets[b] = this.bandOffsets[bands[b]];
}
return new ComponentSampleModel(dataType, width, height, pixelStride,
scanlineStride, bankIndices,
bandOffsets);
}
public DataBuffer createDataBuffer()
{
// Maybe this value should be precalculated in the constructor?
int highestOffset = 0;
for (int b=0; b<numBands; b++)
{
highestOffset = Math.max(highestOffset, bandOffsets[b]);
}
int size = pixelStride*(width-1) + scanlineStride*(height-1) +
highestOffset + 1;
return Buffers.createBuffer(getDataType(), size, numBanks);
}
public int getOffset(int x, int y)
{
return getOffset(x, y, 0);
}
public int getOffset(int x, int y, int b)
{
return bandOffsets[b] + pixelStride*x + scanlineStride*y;
}
public final int[] getSampleSize()
{
int size = DataBuffer.getDataTypeSize(getDataType());
int[] sizes = new int[numBands];
java.util.Arrays.fill(sizes, size);
return sizes;
}
public final int getSampleSize(int band)
{
return DataBuffer.getDataTypeSize(getDataType());
}
public final int[] getBankIndices()
{
return bankIndices;
}
public final int[] getBandOffsets()
{
return bandOffsets;
}
public final int getScanlineStride()
{
return scanlineStride;
}
public final int getPixelStride()
{
return pixelStride;
}
public final int getNumDataElements()
{
return numBands;
}
public Object getDataElements(int x, int y, Object obj, DataBuffer data)
{
int xyOffset = pixelStride*x + scanlineStride*y;
int[] totalBandDataOffsets = new int[numBands];
/* Notice that band and bank offsets are different. Band offsets
are managed by the sample model, and bank offsets are managed
by the data buffer. Both must be accounted for. */
/* FIXME: For single pixels, it is probably easier to simple
call getElem instead of calculating the bank offset ourself.
On the other hand, then we need to push the value through
the int type returned by the getElem method. */
int[] bankOffsets = data.getOffsets();
for (int b=0; b<numBands; b++)
{
totalBandDataOffsets[b] =
bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
}
try
{
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
DataBufferByte inByte = (DataBufferByte) data;
byte[] outByte = (byte[]) obj;
if (outByte == null) outByte = new byte[numBands];
for (int b=0; b<numBands; b++)
{
int dOffset = totalBandDataOffsets[b];
outByte[b] = inByte.getData(bankIndices[b])[dOffset];
}
return outByte;
case DataBuffer.TYPE_USHORT:
DataBufferUShort inUShort = (DataBufferUShort) data;
short[] outUShort = (short[]) obj;
if (outUShort == null) outUShort = new short[numBands];
for (int b=0; b<numBands; b++)
{
int dOffset = totalBandDataOffsets[b];
outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
}
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;
if (outInt == null) outInt = new int[numBands];
for (int b=0; b<numBands; b++)
{
int dOffset = totalBandDataOffsets[b];
outInt[b] = inInt.getData(bankIndices[b])[dOffset];
}
return outInt;
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());
}
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
String msg = "While reading data elements, " +
"x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
", data.getSize()=" + data.getSize() + ": " + aioobe;
throw new ArrayIndexOutOfBoundsException(msg);
}
}
public Object getDataElements(int x, int y, int w, int h, Object obj,
DataBuffer data)
{
if (!tightPixelPacking)
{
return super.getDataElements(x, y, w, h, obj, data);
}
// using get speedup
// We can copy whole rows
int rowSize = w*numBands;
int dataSize = rowSize*h;
DataBuffer transferBuffer =
Buffers.createBuffer(getTransferType(), obj, dataSize);
obj = Buffers.getData(transferBuffer);
int inOffset =
pixelStride*x +
scanlineStride*y +
data.getOffset(); // Assumes only one band is used
/* We don't add band offsets since we assume that bands have
offsets 0, 1, 2, ... */
// See if we can copy everything in one go
if (scanlineStride == rowSize)
{
// Collapse scan lines:
rowSize *= h;
// We ignore scanlineStride since it won't be of any use
h = 1;
}
int outOffset = 0;
Object inArray = Buffers.getData(data);
for (int yd = 0; yd<h; yd++)
{
System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
inOffset += scanlineStride;
outOffset += rowSize;
}
return obj;
}
public void setDataElements(int x, int y, int w, int h,
Object obj, DataBuffer data)
{
if (!tightPixelPacking)
{
super.setDataElements(x, y, w, h, obj, data);
return;
}
// using set speedup, we can copy whole rows
int rowSize = w*numBands;
int dataSize = rowSize*h;
DataBuffer transferBuffer =
Buffers.createBufferFromData(getTransferType(), obj, dataSize);
int[] bankOffsets = data.getOffsets();
int outOffset =
pixelStride*x +
scanlineStride*y +
bankOffsets[0]; // same assuptions as in get...
// See if we can copy everything in one go
if (scanlineStride == rowSize)
{
// Collapse scan lines:
rowSize *= h;
h = 1;
}
int inOffset = 0;
Object outArray = Buffers.getData(data);
for (int yd = 0; yd<h; yd++)
{
System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
outOffset += scanlineStride;
inOffset += rowSize;
}
}
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
int offset = pixelStride*x + scanlineStride*y;
if (iArray == null) iArray = new int[numBands];
for (int b=0; b<numBands; b++)
{
iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
}
return iArray;
}
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int offset = pixelStride*x + scanlineStride*y;
if (iArray == null) iArray = new int[numBands*w*h];
int outOffset = 0;
for (y=0; y<h; y++)
{
int lineOffset = offset;
for (x=0; x<w; x++)
{
for (int b=0; b<numBands; b++)
{
iArray[outOffset++] =
data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
}
lineOffset += pixelStride;
}
offset += scanlineStride;
}
return iArray;
}
public int getSample(int x, int y, int b, DataBuffer data)
{
return data.getElem(bankIndices[b], getOffset(x, y, b));
}
public void setDataElements(int x, int y, Object obj, DataBuffer data)
{
int offset = pixelStride*x + scanlineStride*y;
int[] totalBandDataOffsets = new int[numBands];
int[] bankOffsets = data.getOffsets();
for (int b=0; b<numBands; b++)
totalBandDataOffsets[b] =
bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
{
DataBufferByte out = (DataBufferByte) data;
byte[] in = (byte[]) obj;
for (int b=0; b<numBands; b++)
out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
return;
}
case DataBuffer.TYPE_USHORT:
{
DataBufferUShort out = (DataBufferUShort) data;
short[] in = (short[]) obj;
for (int b=0; b<numBands; b++)
out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
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;
int[] in = (int[]) obj;
for (int b=0; b<numBands; b++)
out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
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");
}
}
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
int offset = pixelStride*x + scanlineStride*y;
for (int b=0; b<numBands; b++)
data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
}
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
data.setElem(bankIndices[b], getOffset(x, y, b), s);
}
}
@@ -0,0 +1,337 @@
/* ConvolveOp.java --
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
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;
}
}
@@ -0,0 +1,180 @@
/* CropImageFilter.java -- Java class for cropping image filter
Copyright (C) 1999, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Rectangle;
import java.util.Hashtable;
/**
* Currently this filter does almost nothing and needs to be implemented.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public class CropImageFilter extends ImageFilter
{
int x;
int y;
int width;
int height;
/**
* Construct a new <code>CropImageFilter</code> instance.
*
* @param x the x-coordinate location of the top-left of the cropped rectangle
* @param y the y-coordinate location of the top-left of the cropped rectangle
* @param width the width of the cropped rectangle
* @param height the height of the cropped rectangle
*/
public CropImageFilter(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
/**
* An <code>ImageProducer</code> indicates the size of the image
* being produced using this method. This filter overrides this
* method in order to set the dimentions to the size of the
* cropped rectangle instead of the size of the image.
*
* @param width the width of the image
* @param height the height of the image
*/
public void setDimensions(int width, int height)
{
consumer.setDimensions(this.width, this.height);
}
/**
* An <code>ImageProducer</code> can set a list of properties
* associated with this image by using this method.
* <br>
* FIXME - What property is set for this class?
*
* @param props the list of properties associated with this image
*/
public void setProperties(Hashtable props)
{
props.put("filters", "CropImageFilter");
consumer.setProperties(props);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as a <code>byte</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize)
{
Rectangle filterBounds = new Rectangle(this.x, this.y,
this.width, this.height);
Rectangle pixelBounds = new Rectangle(x, y, w, h);
if (filterBounds.intersects(pixelBounds))
{
Rectangle bounds = filterBounds.intersection(pixelBounds);
byte[] cropped = new byte[bounds.width * bounds.height];
for (int i = 0; i < bounds.height; i++)
{
int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
for (int j = 0; j < bounds.width; j++)
cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
}
consumer.setPixels(bounds.x, bounds.y,
bounds.width, bounds.height,
model, cropped, 0, bounds.width);
}
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as an <code>int</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize)
{
Rectangle filterBounds = new Rectangle(this.x, this.y,
this.width, this.height);
Rectangle pixelBounds = new Rectangle(x, y, w, h);
if (filterBounds.intersects(pixelBounds))
{
Rectangle bounds = filterBounds.intersection(pixelBounds);
int[] cropped = new int[bounds.width * bounds.height];
for (int i = 0; i < bounds.height; i++)
{
int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
for (int j = 0; j < bounds.width; j++)
cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
}
consumer.setPixels(bounds.x, bounds.y,
bounds.width, bounds.height,
model, cropped, 0, bounds.width);
}
}
}
@@ -0,0 +1,436 @@
/* Copyright (C) 2000, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* Class that manages arrays of data elements. A data buffer consists
* of one or more banks. A bank is a continuous region of data
* elements.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public abstract class DataBuffer
{
/**
* A constant representing a data type that uses <code>byte</code> primitives
* as the storage unit.
*/
public static final int TYPE_BYTE = 0;
/**
* A constant representing a data type that uses <code>short</code>
* primitives as the storage unit.
*/
public static final int TYPE_USHORT = 1;
/**
* A constant representing a data type that uses <code>short</code>
* primitives as the storage unit.
*/
public static final int TYPE_SHORT = 2;
/**
* A constant representing a data type that uses <code>int</code>
* primitives as the storage unit.
*/
public static final int TYPE_INT = 3;
/**
* A constant representing a data type that uses <code>float</code>
* primitives as the storage unit.
*/
public static final int TYPE_FLOAT = 4;
/**
* A constant representing a data type that uses <code>double</code>
* primitives as the storage unit.
*/
public static final int TYPE_DOUBLE = 5;
/**
* A constant representing an undefined data type.
*/
public static final int TYPE_UNDEFINED = 32;
/** The type of the data elements stored in the data buffer. */
protected int dataType;
/** The number of banks in this buffer. */
protected int banks = 1;
/** Offset into the default (0'th) bank). */
protected int offset; // FIXME: Is offsets[0] always mirrored in offset?
/** The size of the banks. */
protected int size;
/** 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);
java.util.Arrays.fill(offsets, offset);
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)
throw new ArrayIndexOutOfBoundsException();
banks = numBanks;
this.offsets = offsets;
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)
{
case TYPE_BYTE:
return 8;
case TYPE_USHORT:
case TYPE_SHORT:
return 16;
case TYPE_INT:
case TYPE_FLOAT:
return 32;
case TYPE_DOUBLE:
return 64;
default:
throw new IllegalArgumentException();
}
}
/**
* 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)
{
// is this necessary?
offsets = new int[1];
offsets[0] = offset;
}
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);
}
}
@@ -0,0 +1,245 @@
/* Copyright (C) 2000, 2002 Free Software Foundation
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>byte</code> primitives
* to represent each of its banks.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
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, 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);
bankData = new byte[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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;
}
}
@@ -0,0 +1,288 @@
/* Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>double</code> primitives
* to represent each of its banks.
*
* @since 1.4
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
public final class DataBufferDouble
extends DataBuffer
{
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, 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);
bankData = new double[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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] = 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]] = val;
}
public float getElemFloat(int i)
{
return (float) data[i+offset];
}
public float getElemFloat(int bank, int i)
{
return (float) bankData[bank][i+offsets[bank]];
}
public void setElemFloat(int i, float val)
{
data[i+offset] = val;
}
public void setElemFloat(int bank, int i, float val)
{
bankData[bank][i+offsets[bank]] = val;
}
public double getElemDouble(int i)
{
return data[i + offset];
}
public double getElemDouble(int bank, int i)
{
return bankData[bank][i + offsets[bank]];
}
public void setElemDouble(int i, double val)
{
data[i + offset] = val;
}
public void setElemDouble(int bank, int i, double val)
{
bankData[bank][i + offsets[bank]] = val;
}
}
@@ -0,0 +1,286 @@
/* Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>float</code> primitives
* to represent each of its banks.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
public final class DataBufferFloat
extends DataBuffer
{
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, 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);
bankData = new float[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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] = 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]] = val;
}
public float getElemFloat(int i)
{
return data[i+offset];
}
public float getElemFloat(int bank, int i)
{
return bankData[bank][i+offsets[bank]];
}
public void setElemFloat(int i, float val)
{
data[i+offset] = val;
}
public void setElemFloat(int bank, int i, float val)
{
bankData[bank][i+offsets[bank]] = val;
}
public double getElemDouble(int i)
{
return getElemFloat(i);
}
public double getElemDouble(int bank, int i)
{
return getElemFloat(bank, i);
}
public void setElemDouble(int i, double val)
{
setElemFloat(i, (float) val);
}
public void setElemDouble(int bank, int i, double val)
{
setElemFloat(bank, i, (float) val);
}
}
@@ -0,0 +1,244 @@
/* Copyright (C) 2000, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>int</code> primitives
* to represent each of its banks.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
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, 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);
bankData = new int[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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] = 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]] = val;
}
}
@@ -0,0 +1,245 @@
/* DataBufferShort.java --
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>short</code> primitives
* to represent each of its banks.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
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, 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);
bankData = new short[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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;
}
}
@@ -0,0 +1,246 @@
/* DataBufferUShort.java --
Copyright (C) 2000, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/* This is one of several classes that are nearly identical. Maybe we
should have a central template and generate all these files. This
is one of the cases where templates or macros would have been
useful to have in Java.
This file has been created using search-replace. My only fear is
that these classes will grow out-of-sync as of a result of changes
that are not propagated to the other files. As always, mirroring
code is a maintenance nightmare. */
/**
* A {@link DataBuffer} that uses an array of <code>short</code> primitives
* to represent each of its banks.
*
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
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, 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);
bankData = new short[numBanks][size];
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, 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);
bankData = dataArray;
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);
bankData = dataArray;
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;
}
}
@@ -0,0 +1,420 @@
/* DirectColorModel.java --
Copyright (C) 1999, 2000, 2002, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author C. Brian Jones (cbj@gnu.org)
* @author Mark Benvenuto (mcb54@columbia.edu)
*/
public class DirectColorModel extends PackedColorModel
{
/**
* For the color model created with this constructor the pixels
* will have fully opaque alpha components with a value of 255.
* Each mask should describe a fully contiguous set of bits in the
* most likely order of alpha, red, green, blue from the most significant
* byte to the least significant byte.
*
* @param 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
*/
public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
{
this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
rmask, gmask, bmask, 0,
false, // not alpha premultiplied
Buffers.smallestAppropriateTransferType(pixelBits) // find type
);
}
/**
* For the color model created with this constructor the pixels
* will have fully opaque alpha components with a value of 255.
* Each mask should describe a fully contiguous set of bits in the
* most likely order of red, green, blue from the most significant
* byte to the least significant byte.
*
* @param 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
* @param amask the bits describing the alpha component of a pixel
*/
public DirectColorModel(int pixelBits,
int rmask, int gmask, int bmask, int amask)
{
this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
rmask, gmask, bmask, amask,
false, // not alpha premultiplied
Buffers.smallestAppropriateTransferType(pixelBits) // find type
);
}
public DirectColorModel(ColorSpace cspace, int pixelBits,
int rmask, int gmask, int bmask, int amask,
boolean isAlphaPremultiplied,
int transferType)
{
super(cspace, pixelBits,
rmask, gmask, bmask, amask, isAlphaPremultiplied,
((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
transferType);
}
public final int getRedMask()
{
return getMask(0);
}
public final int getGreenMask()
{
return getMask(1);
}
public final int getBlueMask()
{
return getMask(2);
}
public final int getAlphaMask()
{
return hasAlpha() ? getMask(3) : 0;
}
/**
* Get the red component of the given pixel.
* <br>
*/
public final int getRed(int pixel)
{
return extractAndNormalizeSample(pixel, 0);
}
/**
* Get the green component of the given pixel.
* <br>
*/
public final int getGreen(int pixel)
{
return extractAndNormalizeSample(pixel, 1);
}
/**
* Get the blue component of the given pixel.
* <br>
*/
public final int getBlue(int pixel)
{
return extractAndNormalizeSample(pixel, 2);
}
/**
* Get the alpha component of the given pixel.
* <br>
*/
public final int getAlpha(int pixel)
{
if (!hasAlpha())
return 255;
return extractAndScaleSample(pixel, 3);
}
private int extractAndNormalizeSample(int pixel, int component)
{
int value = extractAndScaleSample(pixel, component);
if (hasAlpha() && isAlphaPremultiplied())
value = value*255/getAlpha(pixel);
return value;
}
private int extractAndScaleSample(int pixel, int component)
{
int field = pixel & getMask(component);
int to8BitShift =
8 - shifts[component] - getComponentSize(component);
return (to8BitShift>0) ?
(field << to8BitShift) :
(field >>> (-to8BitShift));
}
/**
* Get the RGB color value of the given pixel using the default
* RGB color model.
* <br>
*
* @param pixel a pixel value
*/
public final int getRGB(int pixel)
{
/* FIXME: The Sun docs show that this method is overridden, but I
don't see any way to improve on the superclass
implementation. */
return super.getRGB(pixel);
}
public int getRed(Object inData)
{
return getRed(getPixelFromArray(inData));
}
public int getGreen(Object inData)
{
return getGreen(getPixelFromArray(inData));
}
public int getBlue(Object inData)
{
return getBlue(getPixelFromArray(inData));
}
public int getAlpha(Object inData)
{
return getAlpha(getPixelFromArray(inData));
}
public int getRGB(Object inData)
{
return getRGB(getPixelFromArray(inData));
}
/**
* Converts a normalized pixel int value in the sRGB color
* space to an array containing a single pixel of the color space
* of the color model.
*
* <p>This method performs the inverse function of
* <code>getRGB(Object inData)</code>.
*
* @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
*
* @param pixel to avoid needless creation of arrays, an array to
* use to return the pixel can be given. If null, a suitable array
* will be created.
*
* @return array of transferType containing a single pixel. The
* pixel should be encoded in the natural way of the color model.
*
* @see #getRGB(Object)
*/
public Object getDataElements(int rgb, Object pixel)
{
// FIXME: handle alpha multiply
int pixelValue = 0;
int a = 0;
if (hasAlpha()) {
a = (rgb >>> 24) & 0xff;
pixelValue = valueToField(a, 3, 8);
}
if (hasAlpha() && isAlphaPremultiplied())
{
int r, g, b;
/* if r=0xff and a=0xff, then resulting
value will be (r*a)>>>8 == 0xfe... This seems wrong.
We should divide by 255 rather than shifting >>>8 after
multiplying.
Too bad, shifting is probably less expensive.
r = ((rgb >>> 16) & 0xff)*a;
g = ((rgb >>> 8) & 0xff)*a;
b = ((rgb >>> 0) & 0xff)*a; */
/* The r, g, b values we calculate are 16 bit. This allows
us to avoid discarding the lower 8 bits obtained if
multiplying with the alpha band. */
// using 16 bit values
r = ((rgb >>> 8) & 0xff00)*a/255;
g = ((rgb >>> 0) & 0xff00)*a/255;
b = ((rgb << 8) & 0xff00)*a/255;
pixelValue |=
valueToField(r, 0, 16) | // Red
valueToField(g, 1, 16) | // Green
valueToField(b, 2, 16); // Blue
}
else
{
int r, g, b;
// using 8 bit values
r = (rgb >>> 16) & 0xff;
g = (rgb >>> 8) & 0xff;
b = (rgb >>> 0) & 0xff;
pixelValue |=
valueToField(r, 0, 8) | // Red
valueToField(g, 1, 8) | // Green
valueToField(b, 2, 8); // Blue
}
/* In this color model, the whole pixel fits in the first element
of the array. */
DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
buffer.setElem(0, pixelValue);
return Buffers.getData(buffer);
}
/**
* Converts a value to the correct field bits based on the
* information derived from the field masks.
*
* @param highBit the position of the most significant bit in the
* val parameter.
*/
private int valueToField(int val, int component, int highBit)
{
int toFieldShift =
getComponentSize(component) + shifts[component] - highBit;
int ret = (toFieldShift>0) ?
(val << toFieldShift) :
(val >>> (-toFieldShift));
return ret & getMask(component);
}
/**
* Converts a 16 bit value to the correct field bits based on the
* information derived from the field masks.
*/
private int value16ToField(int val, int component)
{
int toFieldShift = getComponentSize(component) + shifts[component] - 16;
return (toFieldShift>0) ?
(val << toFieldShift) :
(val >>> (-toFieldShift));
}
/**
* Fills an array with the unnormalized component samples from a
* pixel value. I.e. decompose the pixel, but not perform any
* color conversion.
*/
public final int[] getComponents(int pixel, int[] components, int offset)
{
int numComponents = getNumComponents();
if (components == null) components = new int[offset + numComponents];
for (int b=0; b<numComponents; b++)
components[offset++] = (pixel&getMask(b)) >>> shifts[b];
return components;
}
public final int[] getComponents(Object pixel, int[] components,
int offset)
{
return getComponents(getPixelFromArray(pixel), components, offset);
}
public final WritableRaster createCompatibleWritableRaster(int w, int h)
{
SampleModel sm = createCompatibleSampleModel(w, h);
Point origin = new Point(0, 0);
return Raster.createWritableRaster(sm, origin);
}
public int getDataElement(int[] components, int offset)
{
int numComponents = getNumComponents();
int pixelValue = 0;
for (int c=0; c<numComponents; c++)
pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
return pixelValue;
}
public Object getDataElements(int[] components, int offset, Object obj)
{
/* In this color model, the whole pixel fits in the first element
of the array. */
int pixelValue = getDataElement(components, offset);
DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
buffer.setElem(0, pixelValue);
return Buffers.getData(buffer);
}
public final ColorModel coerceData (WritableRaster raster,
boolean isAlphaPremultiplied)
{
if (this.isAlphaPremultiplied == isAlphaPremultiplied)
return this;
/* TODO: provide better implementation based on the
assumptions we can make due to the specific type of the
color model. */
super.coerceData(raster, isAlphaPremultiplied);
return new ComponentColorModel(cspace, bits, hasAlpha(),
isAlphaPremultiplied, // argument
transparency, transferType);
}
public boolean isCompatibleRaster(Raster raster)
{
/* FIXME: the Sun docs say this method is overridden here,
but I don't see any way to improve upon the implementation
in ColorModel. */
return super.isCompatibleRaster(raster);
}
String stringParam()
{
return super.stringParam() +
", redMask=" + Integer.toHexString(getRedMask()) +
", greenMask=" + Integer.toHexString(getGreenMask()) +
", blueMask=" + Integer.toHexString(getBlueMask()) +
", alphaMask=" + Integer.toHexString(getAlphaMask());
}
public String toString()
{
/* FIXME: Again, docs say override, but how do we improve upon the
superclass implementation? */
return super.toString();
}
}
@@ -0,0 +1,125 @@
/* FilteredImageSource.java -- Java class for providing image data
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.util.Hashtable;
/**
*
* @see ImageConsumer
* @author C. Brian Jones (cbj@gnu.org)
*/
public class FilteredImageSource implements ImageProducer
{
ImageProducer ip;
ImageFilter filter;
Hashtable consumers = new Hashtable();
/**
* The given filter is applied to the given image producer
* to create a new image producer.
*/
public FilteredImageSource(ImageProducer ip, ImageFilter filter) {
this.ip = ip;
this.filter = filter;
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code>.
*/
public synchronized void addConsumer(ImageConsumer ic) {
if (consumers.containsKey(ic))
return;
ImageFilter f = filter.getFilterInstance(ic);
consumers.put(ic, f);
ip.addConsumer(f);
}
/**
* Used to determine if the given <code>ImageConsumer</code> is
* already registered with this <code>ImageProducer</code>.
*/
public synchronized boolean isConsumer(ImageConsumer ic) {
ImageFilter f = (ImageFilter)consumers.get(ic);
if (f != null)
return ip.isConsumer(f);
return false;
}
/**
* Used to remove an <code>ImageConsumer</code> from the list of
* registered consumers for this <code>ImageProducer</code>.
*/
public synchronized void removeConsumer(ImageConsumer ic) {
ImageFilter f = (ImageFilter)consumers.remove(ic);
if (f != null)
ip.removeConsumer(f);
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then immediately start
* reconstruction of the image data to be delivered to all
* registered consumers.
*/
public void startProduction(ImageConsumer ic) {
ImageFilter f;
if (!(consumers.containsKey(ic))) {
f = filter.getFilterInstance(ic);
consumers.put(ic, f);
ip.addConsumer(f);
} else {
f = (ImageFilter)consumers.get( ic );
}
ip.startProduction(f);
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then request that this producer
* resend the image data in the order top-down, left-right.
*/
public void requestTopDownLeftRightResend(ImageConsumer ic) {
ImageFilter f = (ImageFilter)consumers.get(ic);
ip.requestTopDownLeftRightResend(f);
}
}
@@ -0,0 +1,216 @@
/* ImageConsumer.java -- Java interface for image consumption
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.util.Hashtable;
/**
* An object implementing the <code>ImageProducer</code> interface can
* use objects implementing this interface to deliver the image data.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public interface ImageConsumer
{
/**
* The pixel order may be random. This should be
* the default assumption of the <code>ImageConsumer</code>.
*
* @see #setHints
*/
int RANDOMPIXELORDER = 1;
/**
* The pixel order is top-down, left-right.
*
* @see #setHints
*/
int TOPDOWNLEFTRIGHT = 2;
/**
* The pixel order is in multiples of complete scanlines.
*
* @see #setHints
*/
int COMPLETESCANLINES = 4;
/**
* The pixels will be delivered in a single pass. There is at
* most one call to <code>setPixels</code> for any single pixel.
*
* @see #setHints
* @see #setPixels
*/
int SINGLEPASS = 8;
/**
* The pixels will be delivered with multiple calls to
* <code>setPixels</code>. The image contains a single frame
* which ends when <code>imageComplete</code> is called with the
* <code>STATICIMAGEDONE</code> flag. If the image is constantly
* changing such as with video then the end of each frame is
* marked by a similar call to <code>imageComplete</code> with the
* <code>SINGLEFRAMEDONE</code> flag.
*
* @see #setHints
* @see #imageComplete
*/
int SINGLEFRAME = 16;
/**
* Indicates an error occurred while producing an image.
*
* @see #imageComplete
*/
int IMAGEERROR = 1;
/**
* A single frame is complete but more will follow.
*
* @see #imageComplete
*/
int SINGLEFRAMEDONE = 2;
/**
* The image is complete and no more pixels or frames will follow.
*
* @see #imageComplete
*/
int STATICIMAGEDONE = 3;
/**
* Production of the image has been aborted.
*
* @see #imageComplete
*/
int IMAGEABORTED = 4;
/**
* An <code>ImageProducer</code> indicates the size of the image
* being produced using this method.
*
* @param width the width of the image
* @param height the height of the image
*/
void setDimensions(int width, int height);
/**
* An <code>ImageProducer</code> can set a list of properties
* associated with this image by using this method.
*
* @param props the list of properties associated with this image
*/
void setProperties(Hashtable props);
/**
* This <code>ColorModel</code> should indicate the model used by
* the majority of calls to <code>setPixels</code>. Each call to
* <code>setPixels</code> could however indicate a different
* <code>ColorModel</code>.
*
* @param model the color model to be used most often by setPixels
* @see ColorModel
*/
void setColorModel(ColorModel model);
/**
* The <code>ImageProducer</code> should call this method with a
* bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
* <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
* <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
*
* @param flags a bit mask of hints
*/
void setHints(int flags);
/**
* Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
*
* Each element of the pixels array represents one pixel. The
* pixel data is formatted according to the color model model.
* The x and y parameters are the coordinates of the block of
* pixels being delivered to this ImageConsumer. They are
* specified relative to the top left corner of the image being
* produced. Likewise, w and h are the pixel block's dimensions.
*
* @param x x coordinate of pixel block
* @param y y coordinate of pixel block
* @param w width of pixel block
* @param h height of pixel block
* @param model color model used to interpret pixel data
* @param pixels pixel block data
* @param offset offset into pixels array
* @param scansize width of one row in the pixel block
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize);
/**
* Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
*
* Each element of the pixels array represents one pixel. The
* pixel data is formatted according to the color model model.
* The x and y parameters are the coordinates of the rectangular
* region of pixels being delivered to this ImageConsumer,
* specified relative to the top left corner of the image being
* produced. Likewise, w and h are the pixel region's dimensions.
*
* @param x x coordinate of pixel block
* @param y y coordinate of pixel block
* @param w width of pixel block
* @param h height of pixel block
* @param model color model used to interpret pixel data
* @param pixels pixel block data
* @param offset offset into pixels array
* @param scansize width of one row in the pixel block
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize);
/**
* The <code>ImageProducer</code> calls this method to indicate a
* single frame or the entire image is complete. The method is
* also used to indicate an error in loading or producing the
* image.
*
* @param status the status of image production, represented by a
* bitwise OR of ImageConsumer flags
*/
void imageComplete(int status);
}
@@ -0,0 +1,221 @@
/* ImageFilter.java -- Java class for filtering images
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.util.Hashtable;
/**
* The <code>ImageFilter</code> class is a base class which can be
* extended to provide different types of filters for an image. By
* default this class does nothing to an image passing through it.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public class ImageFilter implements ImageConsumer, Cloneable
{
/**
* The consumer this filter is filtering an image data stream for.
* It is initialized in the method <code>getFilterInstance</code>.
*/
protected ImageConsumer consumer = null;
/**
* The <code>ImageConsumer</code> can use this method to request
* the pixels be delivered in top-down, left-right order.
* <br>
* The filter can respond in three different ways.
* <ul>
* <li>The default behavior is to forward the request to the
* <code>ImageProducer</code>
* using the method <code>requestTopDownLeftRightResend</code>
* and using the filter as the consumer.</li>
* <li>The filter has the pixels and can retransmit them in the
* top-down, left-right order.</li>
* <li>The filter can do nothing when this method is called.</li>
* </ul>
*/
public void resendTopDownLeftRight(ImageProducer ip)
{
ip.requestTopDownLeftRightResend(this);
}
/**
* By default, returns a shallow copy of the object created by
* <code>Object.clone()</code>
*
* @see java.lang.Object#clone ()
*/
public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
// This should never happen as this class implements the
// Cloneable interface.
throw new InternalError ();
}
}
/**
* This is the only method which can set the
* <code>ImageConsumer</code> for this filter. By default a clone
* of this filter with the appropriate consumer set is returned.
*
* @see #clone ()
*/
public ImageFilter getFilterInstance(ImageConsumer ic)
{
if ( ic == null )
throw new IllegalArgumentException("null argument for ImageFilter.getFilterInstance(ImageConsumer)");
consumer = ic;
ImageFilter f = (ImageFilter)clone();
consumer = null;
return f;
}
/**
* An <code>ImageProducer</code> indicates the size of the image
* being produced using this method. A filter can override this
* method to intercept these calls from the producer in order to
* change either the width or the height before in turn calling
* the consumer's <code>setDimensions</code> method.
*
* @param width the width of the image
* @param height the height of the image
*/
public void setDimensions(int width, int height)
{
consumer.setDimensions(width, height);
}
/**
* An <code>ImageProducer</code> can set a list of properties
* associated with this image by using this method.
*
* @param props the list of properties associated with this image
*/
public void setProperties(Hashtable props)
{
props.put("filters", "ImageFilter");
consumer.setProperties(props);
}
/**
* Override this method to process calls to this method from the
* <code>ImageProducer</code>. By default the <code>setColorModel</code>
* method of the consumer is called with the specified <code>model</code>.
*
* @param model the color model to be used most often by setPixels
* @see ColorModel */
public void setColorModel(ColorModel model)
{
consumer.setColorModel(model);
}
/**
* The <code>ImageProducer</code> should call this method with a
* bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
* <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
* <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
* <code>ImageConsumer</code> interface.
*
* @param flags a bit mask of hints
* @see ImageConsumer
*/
public void setHints(int flags)
{
consumer.setHints(flags);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as a <code>byte</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize)
{
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as an <code>int</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize)
{
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
/**
* The <code>ImageProducer</code> calls this method to indicate a
* single frame or the entire image is complete. The method is
* also used to indicate an error in loading or producing the
* image.
*/
public void imageComplete(int status)
{
consumer.imageComplete(status);
}
}
@@ -0,0 +1,129 @@
/* ImageObserver.java -- Java interface for asynchronous updates to an image
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Image;
/**
* An object implementing the <code>ImageObserver</code> interface can
* receive updates on image construction from an
* <code>ImageProducer</code> asynchronously.
*
* @see ImageProducer
* @author C. Brian Jones (cbj@gnu.org)
*/
public interface ImageObserver
{
/**
* The width of the image has been provided as the
* <code>width</code> argument to <code>imageUpdate</code>.
*
* @see #imageUpdate
*/
int WIDTH = 1;
/**
* The height of the image has been provided as the
* <code>height</code> argument to <code>imageUpdate</code>.
*
* @see #imageUpdate
*/
int HEIGHT = 2;
/**
* The properties of the image have been provided.
*
* @see #imageUpdate
* @see java.awt.Image#getProperty (java.lang.String, java.awt.image.ImageObserver)
*/
int PROPERTIES = 4;
/**
* More pixels are now available for drawing a scaled variation of
* the image.
*
* @see #imageUpdate
*/
int SOMEBITS = 8;
/**
* All the pixels needed to draw a complete frame of a multi-frame
* image are available.
*
* @see #imageUpdate
*/
int FRAMEBITS = 16;
/**
* An image with a single frame, a static image, is complete.
*
* @see #imageUpdate
*/
int ALLBITS = 32;
/**
* An error was encountered while producing the image.
*
* @see #imageUpdate
*/
int ERROR = 64;
/**
* Production of the image was aborted.
*
* @see #imageUpdate
*/
int ABORT = 128;
/**
* This is a callback method for an asynchronous image producer to
* provide updates on the production of the image as it happens.
*
* @param image the image the update refers to
* @param flags a bit mask indicating what is provided with this update
* @param x the x coordinate of the image
* @param y the y coordinate of the image
* @param width the width of the image
* @param height the height of the image
*
* @see java.awt.Image
*/
boolean imageUpdate(Image image, int flags, int x,
int y, int width, int height);
}
@@ -0,0 +1,85 @@
/* ImageProducer.java -- Java interface for image production
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* An object implementing the <code>ImageProducer</code> interface can
* produce data for images. Each image has a corresponding
* <code>ImageProducer</code> which is needed for things such as
* resizing the image.
*
* @see ImageConsumer
* @author C. Brian Jones (cbj@gnu.org)
*/
public interface ImageProducer
{
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code>.
*/
void addConsumer(ImageConsumer ic);
/**
* Used to determine if the given <code>ImageConsumer</code> is
* already registered with this <code>ImageProducer</code>.
*/
boolean isConsumer(ImageConsumer ic);
/**
* Used to remove an <code>ImageConsumer</code> from the list of
* registered consumers for this <code>ImageProducer</code>.
*/
void removeConsumer(ImageConsumer ic);
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then immediately start
* reconstruction of the image data to be delivered to all
* registered consumers.
*/
void startProduction(ImageConsumer ic);
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then request that this producer
* resend the image data in the order top-down, left-right.
*/
void requestTopDownLeftRightResend(ImageConsumer ic);
}
@@ -0,0 +1,66 @@
/* ImagingOpException.java -- indicates an imaging filter failure
Copyright (C) 2002, 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* This exception is thrown when <code>BufferedImageOp</code> or
* <code>RasterOp</code> filters cannot process an image.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see BufferedImageOp
* @see RasterOp
* @status updated to 1.4
*/
public class ImagingOpException extends RuntimeException
{
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 8026288481846276658L;
/**
* Create a new instance with a descriptive error message.
*
* @param message the descriptive error message
*/
public ImagingOpException(String message)
{
super(message);
}
} // class ImagingOpException
@@ -0,0 +1,697 @@
/* IndexColorModel.java -- Java class for interpreting Pixel objects
Copyright (C) 1999, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
import java.awt.color.ColorSpace;
import java.math.BigInteger;
/**
* Color model similar to pseudo visual in X11.
* <br><br>
* 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.
* <br><br>
* The <code>IndexColorModel</code> supports a map of valid pixels, allowing
* the representation of holes in the the color map. The valid map is
* represented as a {@link BigInteger} where each bit indicates the validity
* of the map entry with the same index.
* <br><br>
* 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.
* <br><br>
* <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index
* values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and
* {@link DataBuffer#TYPE_USHORT}.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public class IndexColorModel extends ColorModel
{
private int map_size;
private boolean opaque; // no alpha, but doesn't account for trans
private int trans = -1;
private int[] rgb;
private BigInteger validBits = BigInteger.ZERO;
/**
* Creates a new indexed color model for <code>size</code> color elements
* with no alpha component. Each array must contain at least
* <code>size</code> elements. For each array, the i-th color is described
* by reds[i], greens[i] and blues[i].
*
* @param bits the number of bits needed to represent <code>size</code>
* colors.
* @param size the number of colors in the color map.
* @param reds the red component of all colors.
* @param greens the green component of all colors.
* @param blues the blue component of all colors.
*
* @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
* <code>bits</code> &gt; 16.
* @throws NullPointerException if any of the arrays is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
* than the length of the component arrays.
*/
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
byte[] blues)
{
this(bits, size, reds, greens, blues, (byte[]) null);
}
/**
* Creates a new indexed color model for <code>size</code> color elements.
* Each array must contain at least <code>size</code> elements. For each
* array, the i-th color is described by reds[i], greens[i] and blues[i].
* 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 reds the red component of all colors
* @param greens the green component of all colors
* @param blues the blue component of all colors
* @param trans the index of the transparent color (use -1 for no
* transparent color).
*
* @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
* <code>bits</code> &gt; 16.
* @throws NullPointerException if any of the arrays is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
* than the length of the component arrays.
*/
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
byte[] blues, int trans)
{
super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
(0 <= trans && trans < size), // hasAlpha
false, OPAQUE,
Buffers.smallestAppropriateTransferType(bits));
if (bits < 1)
throw new IllegalArgumentException("bits < 1");
if (bits > 16)
throw new IllegalArgumentException("bits > 16");
if (size < 1)
throw new IllegalArgumentException("size < 1");
map_size = size;
if (0 <= trans && trans < size) {
this.trans = trans;
transparency = BITMASK;
}
rgb = new int[size];
for (int i = 0; i < size; i++)
{
rgb[i] = (0xff000000
| ((reds[i] & 0xff) << 16)
| ((greens[i] & 0xff) << 8)
| (blues[i] & 0xff));
}
// Generate a bigint with 1's for every pixel
validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
/**
* Creates a new indexed color model for <code>size</code> color elements
* including alpha. Each array must contain at least <code>size</code>
* elements. For each array, the i-th color is described
* by reds[i], greens[i], blues[i] and alphas[i].
*
* @param bits the number of bits needed to represent <code>size</code>
* colors.
* @param size the number of colors in the color map.
* @param reds the red component of all colors.
* @param greens the green component of all colors.
* @param blues the blue component of all colors.
* @param alphas the alpha component of all colors (<code>null</code>
* permitted).
*
* @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
* <code>bits</code> &gt; 16.
* @throws NullPointerException if <code>reds</code>, <code>greens</code> or
* <code>blues</code> is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
* than the length of the component arrays.
*/
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
byte[] blues, byte[] alphas)
{
super(bits, nArray(8, (alphas == null ? 3 : 4)),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
(alphas != null), false, TRANSLUCENT,
Buffers.smallestAppropriateTransferType(bits));
if (bits < 1)
throw new IllegalArgumentException("bits < 1");
if (bits > 16)
throw new IllegalArgumentException("bits > 16");
if (size < 1)
throw new IllegalArgumentException("size < 1");
map_size = size;
opaque = (alphas == null);
rgb = new int[size];
if (alphas == null)
{
for (int i = 0; i < size; i++)
{
rgb[i] = (0xff000000
| ((reds[i] & 0xff) << 16)
| ((greens[i] & 0xff) << 8)
| (blues[i] & 0xff));
}
transparency = OPAQUE;
}
else
{
byte alphaZero = (byte) 0x00;
byte alphaOne = (byte) 0xFF;
for (int i = 0; i < size; i++)
{
alphaZero = (byte) (alphaZero | alphas[i]);
alphaOne = (byte) (alphaOne & alphas[i]);
rgb[i] = ((alphas[i] & 0xff) << 24
| ((reds[i] & 0xff) << 16)
| ((greens[i] & 0xff) << 8)
| (blues[i] & 0xff));
}
if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF))
transparency = BITMASK;
else
transparency = TRANSLUCENT;
}
// Generate a bigint with 1's for every pixel
validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
/**
* Creates a new indexed color model using the color components in
* <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then
* <code>cmap</code> contains an alpha component after each of the red, green
* and blue components.
*
* @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
* @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
* &lt; 1.
* @throws NullPointerException if <code>cmap</code> is <code>null</code>.
*/
public IndexColorModel(int bits, int size, byte[] cmap, int start,
boolean hasAlpha)
{
this(bits, size, cmap, start, hasAlpha, -1);
}
/**
* 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 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 &lt; 1, bits &gt; 16, or size
* &lt; 1.
* @throws NullPointerException if <code>cmap</code> is <code>null</code>.
*/
public IndexColorModel(int bits, int size, byte[] cmap, int start,
boolean hasAlpha, int trans)
{
super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
hasAlpha || (0 <= trans && trans < size), false, OPAQUE,
Buffers.smallestAppropriateTransferType(bits));
if (bits < 1)
throw new IllegalArgumentException("bits < 1");
if (bits > 16)
throw new IllegalArgumentException("bits > 16");
if (size < 1)
throw new IllegalArgumentException("size < 1");
map_size = size;
opaque = !hasAlpha;
if (0 <= trans && trans < size)
this.trans = trans;
rgb = new int[size];
if (hasAlpha)
{
int alpha;
int alphaZero = 0x00; // use to detect all zeros
int alphaOne = 0xff; // use to detect all ones
for (int i = 0; i < size; i++) {
alpha = cmap[4 * i + 3 + start] & 0xff;
alphaZero = alphaZero | alpha;
alphaOne = alphaOne & alpha;
rgb[i] =
( alpha << 24
// red
| ((cmap[4 * i + start] & 0xff) << 16)
// green
| ((cmap[4 * i + 1 + start] & 0xff) << 8)
// blue
| (cmap[4 * i + 2 + start] & 0xff));
}
if (alphaZero == 0)
transparency = BITMASK;
else if (alphaOne == 255)
transparency = (trans != -1 ? BITMASK : OPAQUE);
else
transparency = TRANSLUCENT;
}
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));
if (trans != -1)
transparency = BITMASK;
}
// 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 {@link DataBuffer#TYPE_BYTE} or
{@link DataBuffer#TYPE_USHORT}.
* @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
* &lt; 1.
* @throws IllegalArgumentException if <code>transferType</code> is something
* other than {@link DataBuffer#TYPE_BYTE} or
* {@link DataBuffer#TYPE_USHORT}.
*/
public IndexColorModel(int bits, int size, int[] cmap, int start,
boolean hasAlpha, int trans, int transferType)
{
super(bits,
nArray(8, 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;
if (0 <= trans && trans < size)
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.
* <br><br>
* 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.
* <br><br>
* 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 {@link DataBuffer#TYPE_BYTE} or
* {@link DataBuffer#TYPE_USHORT}.
* @param validBits a map of the valid entries in <code>cmap</code>.
* @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
* &lt; 1.
* @throws IllegalArgumentException if transferType is something other than
* {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}.
*/
public IndexColorModel(int bits, int size, int[] cmap, int start,
int transferType, BigInteger validBits)
{
super(bits, // total bits, sRGB, four channels
nArray(8, 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);
}
/**
* Returns the size of the color lookup table.
*
* @return The size of the color lookup table.
*/
public final int getMapSize()
{
return map_size;
}
/**
* Get the index of the transparent color in this color model.
*
* @return The index of the color that is considered transparent, or -1 if
* there is no transparent color.
*/
public final int getTransparentPixel()
{
return trans;
}
/**
* Fills the supplied array with the red component of each color in the
* lookup table.
*
* @param r an array that is at least as large as {@link #getMapSize()}.
* @throws NullPointerException if <code>r</code> is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>r</code> has less
* than {@link #getMapSize()} elements.
*/
public final void getReds(byte[] r)
{
int i;
for (i = 0; i < map_size; i++)
r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16);
}
/**
* Fills the supplied array with the green component of each color in the
* lookup table.
*
* @param g an array that is at least as large as {@link #getMapSize()}.
* @throws NullPointerException if <code>g</code> is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>g</code> has less
* than {@link #getMapSize()} elements.
*/
public final void getGreens(byte[] g)
{
int i;
for (i = 0; i < map_size; i++)
g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8);
}
/**
* Fills the supplied array with the blue component of each color in the
* lookup table.
*
* @param b an array that is at least as large as {@link #getMapSize()}.
* @throws NullPointerException if <code>b</code> is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>b</code> has less
* than {@link #getMapSize()} elements.
*/
public final void getBlues(byte[] b)
{
int i;
for (i = 0; i < map_size; i++)
b[i] = (byte) (0x000000FF & rgb[i]);
}
/**
* Fills the supplied array with the alpha component of each color in the
* lookup table. If the model has a transparent pixel specified, the alpha
* for that pixel will be 0.
*
* @param a an array that is at least as large as {@link #getMapSize()}.
* @throws NullPointerException if <code>a</code> is <code>null</code>.
* @throws ArrayIndexOutOfBoundsException if <code>a</code> has less
* than {@link #getMapSize()} elements.
*/
public final void getAlphas(byte[] a)
{
int i;
for (i = 0; i < map_size; i++)
if (i == trans)
a[i] = (byte) 0;
else
a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24);
}
/**
* Returns the red component of the color in the lookup table for the
* given pixel value.
*
* @param pixel the pixel lookup value.
*
* @return The red component of the color in the lookup table.
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
*/
public final int getRed(int pixel)
{
if (pixel < map_size)
return (0x00FF0000 & rgb[pixel]) >> 16;
return 0;
}
/**
* Returns the green component of the color in the lookup table for the
* given pixel value.
*
* @param pixel the pixel lookup value.
*
* @return The green component of the color in the lookup table.
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
*/
public final int getGreen(int pixel)
{
if (pixel < map_size)
return (0x0000FF00 & rgb[pixel]) >> 8;
return 0;
}
/**
* Returns the blue component of the color in the lookup table for the
* given pixel value.
*
* @param pixel the pixel lookup value.
*
* @return The blue component of the color in the lookup table.
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
*/
public final int getBlue(int pixel)
{
if (pixel < map_size)
return 0x000000FF & rgb[pixel];
return 0;
}
/**
* Returns the alpha component of the color in the lookup table for the
* given pixel value. If no alpha channel was specified when the color model
* was created, then 255 is returned for all pixels except the transparent
* pixel (if one is defined - see {@link #getTransparentPixel()}) which
* returns an alpha of 0.
*
* @param pixel the pixel lookup value.
*
* @return The alpha component of the color in the lookup table (in the
* range 0 to 255).
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
*/
public final int getAlpha(int pixel)
{
if (opaque && pixel != trans)
return 255;
if ((pixel == trans && trans != -1) || pixel >= map_size)
return 0;
return (0xFF000000 & rgb[pixel]) >> 24;
}
/**
* Get the RGB color value of the given pixel using the default
* RGB color model.
*
* @param pixel the pixel lookup value.
* @return The RGB color value.
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
*/
public final int getRGB(int pixel)
{
if (pixel >= 0 && pixel < map_size)
return rgb[pixel];
return 0;
}
/**
* 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);
}
/**
* Return <code>true</code> if the lookup table contains valid data for
* <code>pixel</code>, and <code>false</code> otherwise.
*
* @param pixel the pixel value used to index the color lookup table.
* @return <code>true</code> if <code>pixel</code> is valid,
* <code>false</code> otherwise.
*/
public boolean isValid(int pixel)
{
if (pixel >= 0)
return validBits.testBit(pixel);
return false;
}
/**
* Return <code>true</code> if all pixels are valid, <code>false</code>
* otherwise.
*
* @return <code>true</code> if all pixels are valid, <code>false</code>
* otherwise.
*/
public boolean isValid()
{
// Generate a bigint with 1's for every pixel
BigInteger allbits = new BigInteger("0");
allbits = allbits.setBit(map_size);
allbits = allbits.subtract(new BigInteger("1"));
return allbits.equals(validBits);
}
/**
* Returns a binary value ({@link BigInteger}) where each bit represents an
* entry in the color lookup table. If the bit is on, the entry is valid.
*
* @return The binary value.
*/
public BigInteger getValidPixels()
{
return validBits;
}
/**
* Construct a {@link BufferedImage} with rgb pixel values from a
* {@link 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;
}
}
@@ -0,0 +1,143 @@
/* Kernel.java -- Java class for an image processing kernel
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* Kernel represents an image processing kernel. It gets used to hold
* convolution filters among other purposes. It stores an array of float
* values representing a 2-dimensional array in row-major order.
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @version 1.0
*/
public class Kernel implements Cloneable
{
private final int width;
private final int height;
private final float[] data;
/**
* Creates a new <code>Kernel</code> instance.
*
* @param width The 2D width of data.
* @param height The 2D height of data.
* @param data The source data array.
* @exception IllegalArgumentException if width * height < data.length.
*/
public Kernel(int width, int height, float[] data)
throws IllegalArgumentException
{
this.width = width;
this.height = height;
if (data.length < width * height || width < 0 || height < 0)
throw new IllegalArgumentException();
this.data = new float[width * height];
System.arraycopy(data, 0, this.data, 0, width * height);
}
/**
* Return the X origin: (width - 1) / 2
*/
public final int getXOrigin()
{
return (width - 1) / 2;
}
/**
* Return the Y origin: (height - 1) / 2
*/
public final int getYOrigin()
{
return (height - 1) / 2;
}
/**
* @return The kernel width.
*/
public final int getWidth()
{
return width;
}
/**
* @return The kernel height.
*/
public final int getHeight()
{
return height;
}
/**
* Return the kernel data.
*
* If data is null, allocates a new array and returns it. Otherwise, the
* kernel values are copied into data.
*
* @param data Array to copy values into, or null.
* @return The array with copied values.
* @exception IllegalArgumentException if data != null and too small.
*/
public final float[] getKernelData(float[] data)
throws IllegalArgumentException
{
if (data == null)
return (float[])this.data.clone();
if (data.length < this.data.length)
throw new IllegalArgumentException();
System.arraycopy(this.data, 0, data, 0, this.data.length);
return data;
}
/**
* @return a clone of this Kernel.
*/
public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
throw (Error) new InternalError().initCause(e); // Impossible
}
}
}
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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();
}
}
@@ -0,0 +1,109 @@
/* LookupTable.java -- Java class for a pixel translation table.
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* LookupTable represents translation arrays for pixel values. It wraps one
* or more data arrays for each layer (or component) in an image, such as
* Alpha, R, G, and B. When doing translation, the offset is subtracted from
* the pixel values to allow a subset of an array to be used.
*
* @see ByteLookupTable
* @see ShortLookupTable
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @version 1.0
*/
public abstract class LookupTable
{
// Not protected since that's part of the public API.
int offset;
int numComponents;
/**
* Creates a new <code>LookupTable</code> instance.
*
* If numComponents is 1, the same translation table is used for all pixel
* components.
*
* @param offset Offset to be subtracted.
* @param numComponents Number of image components.
* @exception IllegalArgumentException if offset < 0 or numComponents < 1.
*/
protected LookupTable(int offset, int numComponents)
throws IllegalArgumentException
{
if (offset < 0 || numComponents < 1)
throw new IllegalArgumentException();
this.offset = offset;
this.numComponents = numComponents;
}
/** Return the number of components. */
public int getNumComponents()
{
return numComponents;
}
/** Return the offset. */
public int getOffset()
{
return offset;
}
/**
* Return translated values for a pixel.
*
* For each value in the pixel src, use the value minus offset as an index
* in the component array and copy the value there to the output for the
* component. If dest is null, the output is a new array, otherwise the
* translated values are written to dest. Dest can be the same array as
* src.
*
* For example, if the pixel src is [2, 4, 3], and offset is 1, the output
* is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
* translation arrays.
*
* @param src Component values of a pixel.
* @param dest Destination array for values, or null.
* @return Translated values for the pixel.
*/
public abstract int[] lookupPixel(int[] src, int[] dest);
}
@@ -0,0 +1,373 @@
/* MemoryImageSource.java -- Java class for providing image data
Copyright (C) 1999, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.util.Hashtable;
import java.util.Vector;
public class MemoryImageSource implements ImageProducer
{
private boolean animated = false;
private boolean fullbuffers = false;
private int[] pixeli;
private int width;
private int height;
private int offset;
private int scansize;
private byte[] pixelb;
private ColorModel cm;
private Hashtable props = new Hashtable();
private Vector consumers = new Vector();
/**
* 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)
{
this(w, h, cm, pix, off, scan, null);
}
/**
* Constructs an ImageProducer from memory
*/
public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
int scan, Hashtable props)
{
width = w;
height = h;
this.cm = cm;
offset = off;
scansize = scan;
this.props = props;
int max = ((scansize > width) ? scansize : width);
pixelb = pix;
}
/**
* 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)
{
this(w, h, cm, pix, off, scan, null);
}
/**
Constructs an ImageProducer from memory
*/
public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
int scan, Hashtable props)
{
width = w;
height = h;
this.cm = cm;
offset = off;
scansize = scan;
this.props = props;
int max = ((scansize > width) ? scansize : width);
pixeli = pix;
}
/**
* Constructs an ImageProducer from memory using the default RGB ColorModel
*/
public MemoryImageSource(int w, int h, int[] pix, int off, int scan,
Hashtable props)
{
this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
}
/**
* Constructs an ImageProducer from memory using the default RGB ColorModel
*/
public MemoryImageSource(int w, int h, int[] pix, int off, int scan)
{
this(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code>.
*/
public synchronized void addConsumer(ImageConsumer ic)
{
if (consumers.contains(ic))
return;
consumers.addElement(ic);
}
/**
* Used to determine if the given <code>ImageConsumer</code> is
* already registered with this <code>ImageProducer</code>.
*/
public synchronized boolean isConsumer(ImageConsumer ic)
{
if (consumers.contains(ic))
return true;
return false;
}
/**
* Used to remove an <code>ImageConsumer</code> from the list of
* registered consumers for this <code>ImageProducer</code>.
*/
public synchronized void removeConsumer(ImageConsumer ic)
{
consumers.removeElement(ic);
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then immediately start
* reconstruction of the image data to be delivered to all
* registered consumers.
*/
public void startProduction(ImageConsumer ic)
{
if (! (consumers.contains(ic)))
consumers.addElement(ic);
Vector list = (Vector) consumers.clone();
for (int i = 0; i < list.size(); i++)
{
ic = (ImageConsumer) list.elementAt(i);
sendPicture(ic);
if (animated)
ic.imageComplete(ImageConsumer.SINGLEFRAME);
else
ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
}
}
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then request that this producer
* resend the image data in the order top-down, left-right.
*/
public void requestTopDownLeftRightResend(ImageConsumer ic)
{
startProduction(ic);
}
/**
* Changes a flag to indicate whether this MemoryImageSource supports
* animations.
*
* @param animated A flag indicating whether this class supports animations
*/
public synchronized void setAnimated(boolean animated)
{
this.animated = animated;
}
/**
* A flag to indicate whether or not to send full buffer updates when
* sending animation. If this flag is set then full buffers are sent
* in the newPixels methods instead of just regions.
*
* @param fullbuffers - a flag indicating whether to send the full buffers
*/
public synchronized void setFullBufferUpdates(boolean fullbuffers)
{
this.fullbuffers = fullbuffers;
}
/**
* Send an animation frame to the image consumers.
*/
public void newPixels()
{
if (animated == true)
{
ImageConsumer ic;
Vector list = (Vector) consumers.clone();
for (int i = 0; i < list.size(); i++)
{
ic = (ImageConsumer) list.elementAt(i);
sendPicture(ic);
ic.imageComplete(ImageConsumer.SINGLEFRAME);
}
}
}
private void sendPicture(ImageConsumer ic)
{
ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
if (props != null)
ic.setProperties(props);
ic.setDimensions(width, height);
ic.setColorModel(cm);
if (pixeli != null)
ic.setPixels(0, 0, width, height, cm, pixeli, offset, scansize);
else
ic.setPixels(0, 0, width, height, cm, pixelb, offset, scansize);
}
/**
* Send an animation frame to the image consumers containing the specified
* pixels unless setFullBufferUpdates is set.
*/
public synchronized void newPixels(int x, int y, int w, int h)
{
if (animated == true)
{
if (fullbuffers)
newPixels();
else
{
ImageConsumer ic;
Vector list = (Vector) consumers.clone();
for (int i = 0; i < list.size(); i++)
{
ic = (ImageConsumer) list.elementAt(i);
ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
if (props != null)
ic.setProperties(props);
if (pixeli != null)
{
int[] pixelbuf = new int[w * h];
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 < 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);
}
}
}
}
/**
* Send an animation frame to the image consumers containing the specified
* pixels unless setFullBufferUpdates is set.
*
* If framenotify is set then a notification is sent when the frame
* is sent otherwise no status is sent.
*/
public synchronized void newPixels(int x, int y, int w, int h,
boolean framenotify)
{
if (animated == true)
{
if (fullbuffers)
newPixels();
else
{
ImageConsumer ic;
Vector list = (Vector) consumers.clone();
for (int i = 0; i < list.size(); i++)
{
ic = (ImageConsumer) list.elementAt(i);
ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
if (props != null)
ic.setProperties(props);
if (pixeli != null)
{
int[] pixelbuf = new int[w * h];
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 < 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)
ic.imageComplete(ImageConsumer.SINGLEFRAME);
}
}
}
}
public synchronized void newPixels(byte[] newpix, ColorModel newmodel,
int offset, int scansize)
{
pixeli = null;
pixelb = newpix;
cm = newmodel;
this.offset = offset;
this.scansize = scansize;
if (animated == true)
newPixels();
}
public synchronized void newPixels(int[] newpix, ColorModel newmodel,
int offset, int scansize)
{
pixelb = null;
pixeli = newpix;
cm = newmodel;
this.offset = offset;
this.scansize = scansize;
if (animated == true)
newPixels();
}
}
@@ -0,0 +1,388 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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, numberOfBits, 0, 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);
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[numElems - i- 1] = numberOfBits * i;
bitMasks[numElems - i - 1] = ((1 << numberOfBits) - 1) <<
bitOffsets[numElems - i - 1];
}
}
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();
}
}
@@ -0,0 +1,192 @@
/* Copyright (C) 2000, 2002, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.BitMaskExtent;
import java.awt.Point;
import java.awt.color.ColorSpace;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public abstract class PackedColorModel extends ColorModel
{
private int masks[];
/* Package accessibility, the DirectColorModel needs this array */
int shifts[];
public PackedColorModel(ColorSpace cspace, int pixelBits,
int[] colorMaskArray, int alphaMask,
boolean isAlphaPremultiplied,
int transparency,
int transferType)
{
super(pixelBits, calcBitsPerComponent(colorMaskArray, alphaMask),
cspace, (alphaMask != 0), isAlphaPremultiplied, transparency,
transferType);
initMasks(colorMaskArray, alphaMask);
if ((pixelBits<1) || (pixelBits>32)) {
throw new IllegalArgumentException("pixels per bits must be " +
"in the range [1, 32]");
}
}
private static int[] calcBitsPerComponent(int[] colorMaskArray,
int alphaMask)
{
int numComponents = colorMaskArray.length;
if (alphaMask != 0) numComponents++;
int[] bitsPerComponent = new int[numComponents];
BitMaskExtent extent = new BitMaskExtent();
for (int b=0; b<colorMaskArray.length; b++)
{
extent.setMask(colorMaskArray[b]);
bitsPerComponent[b] = extent.bitWidth;
}
if (alphaMask != 0)
{
extent.setMask(alphaMask);
bitsPerComponent[numComponents-1] = extent.bitWidth;
}
return bitsPerComponent;
}
/** Initializes the masks.
*
* @return an array containing the number of bits per color
* component.
*/
private void initMasks(int[] colorMaskArray, int alphaMask)
{
int numComponents = colorMaskArray.length;
if (alphaMask == 0)
{
masks = colorMaskArray;
}
else
{
masks = new int[numComponents+1];
System.arraycopy(colorMaskArray, 0,
masks, 0,
numComponents);
masks[numComponents++] = alphaMask;
}
shifts = new int[numComponents];
// Bit field handling have been moved to a utility class
BitMaskExtent extent = new BitMaskExtent();
for (int b=0; b<numComponents; b++)
{
extent.setMask(masks[b]);
shifts[b] = extent.leastSignificantBit;
}
}
public PackedColorModel(ColorSpace cspace, int pixelBits,
int rmask, int gmask, int bmask,
int amask, boolean isAlphaPremultiplied,
int transparency,
int transferType)
{
this(cspace, pixelBits, makeColorMaskArray(rmask, gmask, bmask),
amask, isAlphaPremultiplied, transparency, transferType);
}
/* TODO: If there is a alpha mask, it is inefficient to create a
color mask array that will be discarded when the alpha mask is
appended. We should probably create a private constructor that
takes a complete array of masks (color+alpha) as an
argument. */
private static int[] makeColorMaskArray(int rmask, int gmask, int bmask)
{
int[] colorMaskArray = { rmask, gmask, bmask };
return colorMaskArray;
}
public final int getMask(int index)
{
return masks[index];
}
public final int[] getMasks()
{
return masks;
}
public SampleModel createCompatibleSampleModel(int w, int h)
{
return new SinglePixelPackedSampleModel(transferType, w, h, masks);
}
public boolean isCompatibleSampleModel(SampleModel sm)
{
if (!super.isCompatibleSampleModel(sm)) return false;
if (!(sm instanceof SinglePixelPackedSampleModel)) return false;
SinglePixelPackedSampleModel sppsm =
(SinglePixelPackedSampleModel) sm;
return java.util.Arrays.equals(sppsm.getBitMasks(), masks);
}
public WritableRaster getAlphaRaster(WritableRaster raster) {
if (!hasAlpha()) return null;
SampleModel sm = raster.getSampleModel();
int[] alphaBand = { sm.getNumBands() - 1 };
SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
DataBuffer buffer = raster.getDataBuffer();
Point origin = new Point(0, 0);
return Raster.createWritableRaster(alphaModel, buffer, origin);
}
public boolean equals(Object obj)
{
if (!super.equals(obj)) return false;
if (!(obj instanceof PackedColorModel)) return false;
PackedColorModel other = (PackedColorModel) obj;
return java.util.Arrays.equals(masks, other.masks);
}
}
@@ -0,0 +1,618 @@
/* PixelGrabber.java -- retrieve a subset of an image's data
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Image;
import java.util.Hashtable;
/**
* PixelGrabber is an ImageConsumer that extracts a rectangular region
* of pixels from an Image.
*/
public class PixelGrabber implements ImageConsumer
{
int x, y, offset;
int width = -1;
int height = -1;
int scansize = -1;
boolean forceRGB = true;
ColorModel model = ColorModel.getRGBdefault();
int hints;
Hashtable props;
int int_pixel_buffer[];
boolean ints_delivered = false;
byte byte_pixel_buffer[];
boolean bytes_delivered = false;
ImageProducer ip;
int observerStatus;
int consumerStatus;
private Thread grabberThread;
boolean grabbing = false;
/**
* Construct a PixelGrabber that will retrieve RGB data from a given
* Image.
*
* The RGB data will be retrieved from a rectangular region
* <code>(x, y, w, h)</code> within the image. The data will be
* stored in the provided <code>pix</code> array, which must have
* been initialized to a size of at least <code>w * h</code>. The
* data for a pixel (m, n) in the grab rectangle will be stored at
* <code>pix[(n - y) * scansize + (m - x) + off]</code>.
*
* @param img the Image from which to grab pixels
* @param x the x coordinate, relative to <code>img</code>'s
* top-left corner, of the grab rectangle's top-left pixel
* @param y the y coordinate, relative to <code>img</code>'s
* top-left corner, of the grab rectangle's top-left pixel
* @param w the width of the grab rectangle, in pixels
* @param h the height of the grab rectangle, in pixels
* @param pix the array in which to store grabbed RGB pixel data
* @param off the offset into the <code>pix</code> array at which to
* start storing RGB data
* @param scansize a set of <code>scansize</code> consecutive
* elements in the <code>pix</code> array represents one row of
* pixels in the grab rectangle
*/
public PixelGrabber(Image img, int x, int y, int w, int h,
int pix[], int off, int scansize)
{
this (img.getSource(), x, y, w, h, pix, off, scansize);
}
/**
* Construct a PixelGrabber that will retrieve RGB data from a given
* ImageProducer.
*
* The RGB data will be retrieved from a rectangular region
* <code>(x, y, w, h)</code> within the image produced by
* <code>ip</code>. The data will be stored in the provided
* <code>pix</code> array, which must have been initialized to a
* size of at least <code>w * h</code>. The data for a pixel (m, n)
* in the grab rectangle will be stored at
* <code>pix[(n - y) * scansize + (m - x) + off]</code>.
*
* @param ip the ImageProducer from which to grab pixels
* @param x the x coordinate of the grab rectangle's top-left pixel,
* specified relative to the top-left corner of the image produced
* by <code>ip</code>
* @param y the y coordinate of the grab rectangle's top-left pixel,
* specified relative to the top-left corner of the image produced
* by <code>ip</code>
* @param w the width of the grab rectangle, in pixels
* @param h the height of the grab rectangle, in pixels
* @param pix the array in which to store grabbed RGB pixel data
* @param off the offset into the <code>pix</code> array at which to
* start storing RGB data
* @param scansize a set of <code>scansize</code> consecutive
* elements in the <code>pix</code> array represents one row of
* pixels in the grab rectangle
*/
public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
int pix[], int off, int scansize)
{
this.ip = ip;
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.offset = off;
this.scansize = scansize;
int_pixel_buffer = pix;
// Initialize the byte array in case ip sends us byte-formatted
// pixel data.
byte_pixel_buffer = new byte[pix.length * 4];
}
/**
* Construct a PixelGrabber that will retrieve data from a given
* Image.
*
* The RGB data will be retrieved from a rectangular region
* <code>(x, y, w, h)</code> within the image. The data will be
* stored in an internal array which can be accessed by calling
* <code>getPixels</code>. The data for a pixel (m, n) in the grab
* rectangle will be stored in the returned array at index
* <code>(n - y) * scansize + (m - x) + off</code>.
* If forceRGB is false, then the returned data will be not be
* converted to RGB from its format in <code>img</code>.
*
* If <code>w</code> is negative, the width of the grab region will
* be from x to the right edge of the image. Likewise, if
* <code>h</code> is negative, the height of the grab region will be
* from y to the bottom edge of the image.
*
* @param img the Image from which to grab pixels
* @param x the x coordinate, relative to <code>img</code>'s
* top-left corner, of the grab rectangle's top-left pixel
* @param y the y coordinate, relative to <code>img</code>'s
* top-left corner, of the grab rectangle's top-left pixel
* @param w the width of the grab rectangle, in pixels
* @param h the height of the grab rectangle, in pixels
* @param forceRGB true to force conversion of the rectangular
* region's pixel data to RGB
*/
public PixelGrabber(Image img,
int x, int y,
int w, int h,
boolean forceRGB)
{
this.ip = img.getSource();
this.x = x;
this.y = y;
width = w;
height = h;
// If width or height is negative, postpone pixel buffer
// initialization until setDimensions is called back by ip.
if (width >= 0 && height >= 0)
{
int_pixel_buffer = new int[width * height];
byte_pixel_buffer = new byte[width * height];
}
this.forceRGB = forceRGB;
}
/**
* Start grabbing pixels.
*
* Spawns an image production thread that calls back to this
* PixelGrabber's ImageConsumer methods.
*/
public synchronized void startGrabbing()
{
// Make sure we're not already grabbing.
if (grabbing == false)
{
grabbing = true;
grabberThread = new Thread ()
{
public void run ()
{
ip.startProduction (PixelGrabber.this);
}
};
grabberThread.start ();
}
}
/**
* Abort pixel grabbing.
*/
public synchronized void abortGrabbing()
{
if (grabbing)
{
// Interrupt the grabbing thread.
Thread moribund = grabberThread;
grabberThread = null;
moribund.interrupt();
imageComplete (ImageConsumer.IMAGEABORTED);
}
}
/**
* Have our Image or ImageProducer start sending us pixels via our
* ImageConsumer methods and wait for all pixels in the grab
* rectangle to be delivered.
*
* @return true if successful, false on abort or error
*
* @throws InterruptedException if interrupted by another thread.
*/
public synchronized boolean grabPixels() throws InterruptedException
{
return grabPixels(0);
}
/**
* grabPixels's behavior depends on the value of <code>ms</code>.
*
* If ms < 0, return true if all pixels from the source image have
* been delivered, false otherwise. Do not wait.
*
* If ms >= 0 then we request that our Image or ImageProducer start
* delivering pixels to us via our ImageConsumer methods.
*
* If ms > 0, wait at most <code>ms</code> milliseconds for
* delivery of all pixels within the grab rectangle.
*
* If ms == 0, wait until all pixels have been delivered.
*
* @return true if all pixels from the source image have been
* delivered, false otherwise
*
* @throws InterruptedException if this thread is interrupted while
* we are waiting for pixels to be delivered
*/
public synchronized boolean grabPixels(long ms) throws InterruptedException
{
if (ms < 0)
return ((observerStatus & (ImageObserver.FRAMEBITS
| ImageObserver.ALLBITS)) != 0);
// Spawn a new ImageProducer thread to send us the image data via
// our ImageConsumer methods.
startGrabbing();
if (ms > 0)
{
long stop_time = System.currentTimeMillis() + ms;
long time_remaining;
while (grabbing)
{
time_remaining = stop_time - System.currentTimeMillis();
if (time_remaining <= 0)
break;
wait (time_remaining);
}
abortGrabbing ();
}
else
wait ();
// If consumerStatus is non-zero then the image is done loading or
// an error has occurred.
if (consumerStatus != 0)
return setObserverStatus ();
return ((observerStatus & (ImageObserver.FRAMEBITS
| ImageObserver.ALLBITS)) != 0);
}
// Set observer status flags based on the current consumer status
// flags. Return true if the consumer flags indicate that the
// image was loaded successfully, or false otherwise.
private synchronized boolean setObserverStatus ()
{
boolean retval = false;
if ((consumerStatus & IMAGEERROR) != 0)
observerStatus |= ImageObserver.ERROR;
if ((consumerStatus & IMAGEABORTED) != 0)
observerStatus |= ImageObserver.ABORT;
if ((consumerStatus & STATICIMAGEDONE) != 0)
{
observerStatus |= ImageObserver.ALLBITS;
retval = true;
}
if ((consumerStatus & SINGLEFRAMEDONE) != 0)
{
observerStatus |= ImageObserver.FRAMEBITS;
retval = true;
}
return retval;
}
/**
* @return the status of the pixel grabbing thread, represented by a
* bitwise OR of ImageObserver flags
*/
public synchronized int getStatus()
{
return observerStatus;
}
/**
* @return the width of the grab rectangle in pixels, or a negative
* number if the ImageProducer has not yet called our setDimensions
* method
*/
public synchronized int getWidth()
{
return width;
}
/**
* @return the height of the grab rectangle in pixels, or a negative
* number if the ImageProducer has not yet called our setDimensions
* method
*/
public synchronized int getHeight()
{
return height;
}
/**
* @return a byte array of pixel data if ImageProducer delivered
* pixel data using the byte[] variant of setPixels, or an int array
* otherwise
*/
public synchronized Object getPixels()
{
if (ints_delivered)
return int_pixel_buffer;
else if (bytes_delivered)
return byte_pixel_buffer;
else
return null;
}
/**
* @return the ColorModel currently being used for the majority of
* pixel data conversions
*/
public synchronized ColorModel getColorModel()
{
return model;
}
/**
* Our <code>ImageProducer</code> calls this method to indicate the
* size of the image being produced.
*
* setDimensions is an ImageConsumer method. None of PixelGrabber's
* ImageConsumer methods should be called by code that instantiates
* a PixelGrabber. They are only made public so they can be called
* by the PixelGrabber's ImageProducer.
*
* @param width the width of the image
* @param height the height of the image
*/
public synchronized void setDimensions(int width, int height)
{
// Our width wasn't set when we were constructed. Set our width
// so that the grab region includes all pixels from x to the right
// edge of the source image.
if (this.width < 0)
this.width = width - x;
// Our height wasn't set when we were constructed. Set our height
// so that the grab region includes all pixels from y to the
// bottom edge of the source image.
if (this.height < 0)
this.height = height - y;
if (scansize < 0)
scansize = this.width;
if (int_pixel_buffer == null)
int_pixel_buffer = new int[this.width * this.height];
if (byte_pixel_buffer == null)
byte_pixel_buffer = new byte[this.width * this.height];
}
/**
* Our <code>ImageProducer</code> may call this method to send us a
* list of its image's properties.
*
* setProperties is an ImageConsumer method. None of PixelGrabber's
* ImageConsumer methods should be called by code that instantiates
* a PixelGrabber. They are only made public so they can be called
* by the PixelGrabber's ImageProducer.
*
* @param props a list of properties associated with the image being
* produced
*/
public synchronized void setProperties(Hashtable props)
{
this.props = props;
}
/**
* Our ImageProducer will call <code>setColorModel</code> to
* indicate the model used by the majority of calls to
* <code>setPixels</code>. Each call to <code>setPixels</code>
* could however indicate a different <code>ColorModel</code>.
*
* setColorModel is an ImageConsumer method. None of PixelGrabber's
* ImageConsumer methods should be called by code that instantiates
* a PixelGrabber. They are only made public so they can be called
* by the PixelGrabber's ImageProducer.
*
* @param model the color model to be used most often by setPixels
*
* @see ColorModel
*/
public synchronized void setColorModel(ColorModel model)
{
this.model = model;
}
/**
* Our <code>ImageProducer</code> may call this method with a
* bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
* <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
* <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
*
* setHints is an ImageConsumer method. None of PixelGrabber's
* ImageConsumer methods should be called by code that instantiates
* a PixelGrabber. They are only made public so they can be called
* by the PixelGrabber's ImageProducer.
*
* @param flags a bit mask of hints
*/
public synchronized void setHints(int flags)
{
hints = flags;
}
/**
* Our ImageProducer calls setPixels to deliver a subset of its
* pixels.
*
* Each element of the pixels array represents one pixel. The
* pixel data is formatted according to the color model model.
* The x and y parameters are the coordinates of the rectangular
* region of pixels being delivered to this ImageConsumer,
* specified relative to the top left corner of the image being
* produced. Likewise, w and h are the pixel region's dimensions.
*
* @param x x coordinate of pixel block
* @param y y coordinate of pixel block
* @param w width of pixel block
* @param h height of pixel block
* @param model color model used to interpret pixel data
* @param pixels pixel block data
* @param offset offset into pixels array
* @param scansize width of one row in the pixel block
*/
public synchronized void setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels,
int offset, int scansize)
{
ColorModel currentModel;
if (model != null)
currentModel = model;
else
currentModel = this.model;
for(int yp = y; yp < (y + h); yp++)
{
for(int xp = x; xp < (x + w); xp++)
{
// Check if the coordinates (xp, yp) are within the
// pixel block that we are grabbing.
if(xp >= this.x
&& yp >= this.y
&& xp < (this.x + this.width)
&& yp < (this.y + this.height))
{
int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
int p = (yp - y) * scansize + (xp - x) + offset;
if (forceRGB)
{
ints_delivered = true;
int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF);
}
else
{
bytes_delivered = true;
byte_pixel_buffer[i] = pixels[p];
}
}
}
}
}
/**
* Our ImageProducer calls setPixels to deliver a subset of its
* pixels.
*
* Each element of the pixels array represents one pixel. The
* pixel data is formatted according to the color model model.
* The x and y parameters are the coordinates of the rectangular
* region of pixels being delivered to this ImageConsumer,
* specified relative to the top left corner of the image being
* produced. Likewise, w and h are the pixel region's dimensions.
*
* @param x x coordinate of pixel block
* @param y y coordinate of pixel block
* @param w width of pixel block
* @param h height of pixel block
* @param model color model used to interpret pixel data
* @param pixels pixel block data
* @param offset offset into pixels array
* @param scansize width of one row in the pixel block
*/
public synchronized void setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels,
int offset, int scansize)
{
ColorModel currentModel;
if (model != null)
currentModel = model;
else
currentModel = this.model;
ints_delivered = true;
for(int yp = y; yp < (y + h); yp++)
{
for(int xp = x; xp < (x + w); xp++)
{
// Check if the coordinates (xp, yp) are within the
// pixel block that we are grabbing.
if(xp >= this.x
&& yp >= this.y
&& xp < (this.x + this.width)
&& yp < (this.y + this.height))
{
int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
int p = (yp - y) * scansize + (xp - x) + offset;
if (forceRGB)
int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
else
int_pixel_buffer[i] = pixels[p];
}
}
}
}
/**
* Our <code>ImageProducer</code> calls this method to inform us
* that a single frame or the entire image is complete. The method
* is also used to inform us of an error in loading or producing the
* image.
*
* @param status the status of image production, represented by a
* bitwise OR of ImageConsumer flags
*/
public synchronized void imageComplete(int status)
{
consumerStatus = status;
setObserverStatus ();
grabbing = false;
ip.removeConsumer (this);
notifyAll ();
}
/**
* @return the return value of getStatus
*
* @specnote The newer getStatus should be used in place of status.
*/
public synchronized int status()
{
return getStatus();
}
}
@@ -0,0 +1,98 @@
/* PixelInterleavedSampleModel.java
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* A <code>SampleModel</code> that uses exactly one element of the
* raster&#x2019;s {@link DataBuffer} per pixel, holds all bands in a
* single bank, and stores band data in pixel-interleaved manner.
*
* @since 1.2
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
public class PixelInterleavedSampleModel
extends ComponentSampleModel
{
public PixelInterleavedSampleModel(int dataType, int width, int height,
int pixelStride, int scanlineStride,
int[] bandOffsets)
{
super(dataType, width, height, pixelStride, scanlineStride,
bandOffsets);
}
/**
* Creates a new <code>SampleModel</code> that is like this one, but
* uses the specified width and height.
*
* @param width the number of pixels in the horizontal direction.
*
* @param height the number of pixels in the vertical direction.
*/
public SampleModel createCompatibleSampleModel(int width, int height)
{
return new PixelInterleavedSampleModel(dataType, width, height,
pixelStride, scanlineStride,
bandOffsets);
}
/**
* Creates a new <code>SampleModel</code> that is like this one, but
* uses only a subset of its bands.
*
* @param bands an array whose elements indicate which bands shall
* be part of the subset. For example, <code>[0, 2, 3]</code> would
* create a SampleModel containing bands #0, #2 and #3.
*/
public SampleModel createSubsetSampleModel(int[] bands)
{
int[] subOffsets;
subOffsets = new int[bands.length];
for (int i = 0; i < bands.length; i++)
subOffsets[i] = bandOffsets[bands[i]];
return new PixelInterleavedSampleModel(dataType, width, height,
pixelStride, scanlineStride,
subOffsets);
}
}
@@ -0,0 +1,267 @@
/* RGBImageFilter.java -- Java class for filtering Pixels by RGB values
Copyright (C) 1999, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* A filter designed to filter images in the default RGBColorModel regardless of
* the ImageProducer's ColorModel.
*
* @author Mark Benvenuto (mcb54@columbia.edu)
*/
public abstract class RGBImageFilter extends ImageFilter
{
protected ColorModel origmodel;
protected ColorModel newmodel;
/**
Specifies whether to apply the filter to the index entries of the
IndexColorModel. Subclasses should set this to true if the filter
does not depend on the pixel's coordinate.
*/
protected boolean canFilterIndexColorModel = false;
/**
Construct new RGBImageFilter.
*/
public RGBImageFilter()
{
}
/**
* Sets the ColorModel used to filter with. If the specified ColorModel is IndexColorModel
* and canFilterIndexColorModel is true, we subsitute the ColorModel for a filtered one
* here and in setPixels whenever the original one appears. Otherwise overrides the default
* ColorModel of ImageProducer and specifies the default RGBColorModel
*
* @param model the color model to be used most often by setPixels
* @see ColorModel */
public void setColorModel(ColorModel model)
{
origmodel = model;
newmodel = model;
if( ( model instanceof IndexColorModel) && canFilterIndexColorModel ) {
newmodel = filterIndexColorModel( (IndexColorModel) model );
consumer.setColorModel(newmodel);
}
else {
consumer.setColorModel(ColorModel.getRGBdefault());
}
}
/**
Registers a new ColorModel to subsitute for the old ColorModel when
setPixels encounters the a pixel with the old ColorModel. The pixel
remains unchanged except for a new ColorModel.
@param oldcm the old ColorModel
@param newcm the new ColorModel
*/
public void substituteColorModel(ColorModel oldcm,
ColorModel newcm)
{
origmodel = oldcm;
newmodel = newcm;
}
/**
Filters an IndexColorModel through the filterRGB function. Uses
coordinates of -1 to indicate its filtering an index and not a pixel.
@param icm an IndexColorModel to filter
*/
public IndexColorModel filterIndexColorModel(IndexColorModel icm)
{
int len = icm.getMapSize(), rgb;
byte reds[] = new byte[len], greens[] = new byte[len], blues[] = new byte[len], alphas[] = new byte[len];
icm.getAlphas( alphas );
icm.getReds( reds );
icm.getGreens( greens );
icm.getBlues( blues );
for( int i = 0; i < len; i++ )
{
rgb = filterRGB( -1, -1, makeColor ( alphas[i], reds[i], greens[i], blues[i] ) );
alphas[i] = (byte)(( 0xff000000 & rgb ) >> 24);
reds[i] = (byte)(( 0xff0000 & rgb ) >> 16);
greens[i] = (byte)(( 0xff00 & rgb ) >> 8);
blues[i] = (byte)(0xff & rgb);
}
return new IndexColorModel( icm.getPixelSize(), len, reds, greens, blues, alphas );
}
private int makeColor( byte a, byte r, byte g, byte b )
{
return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
}
/**
This functions filters a set of RGB pixels through filterRGB.
@param x the x coordinate of the rectangle
@param y the y coordinate of the rectangle
@param w the width of the rectangle
@param h the height of the rectangle
@param 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 offset, int scansize)
{
for (int yp = 0; yp < h; yp++)
{
for (int xp = 0; xp < w; xp++)
{
pixels[offset + xp] = filterRGB(xp + x, yp + y, pixels[offset + xp]);
}
offset += scansize;
}
}
/**
* If the ColorModel is the same ColorModel which as already converted
* then it converts it the converted ColorModel. Otherwise it passes the
* array of pixels through filterRGBpixels.
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels,
int offset, int scansize)
{
if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
{
consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
}
else
{
int intPixels[] =
convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
filterRGBPixels( x, y, w, h, intPixels, offset, scansize );
consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), intPixels, offset, scansize);
}
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as an <code>int</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels,
int offset, int scansize)
{
if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
{
consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
}
else
{
//FIXME: Store the filtered pixels in a separate temporary buffer?
convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
filterRGBPixels( x, y, w, h, pixels, offset, scansize );
consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset, scansize);
}
}
private int[] convertColorModelToDefault(int x, int y, int w, int h,
ColorModel model, byte pixels[],
int offset, int scansize)
{
int intPixels[] = new int[pixels.length];
for (int i = 0; i < pixels.length; i++)
intPixels[i] = makeColorbyDefaultCM(model, pixels[i]);
return intPixels;
}
private void convertColorModelToDefault(int x, int y, int w, int h,
ColorModel model, int pixels[],
int offset, int scansize)
{
for (int i = 0; i < pixels.length; i++)
pixels[i] = makeColorbyDefaultCM(model, pixels[i]);
}
private int makeColorbyDefaultCM(ColorModel model, byte rgb)
{
return makeColor( model.getAlpha( rgb ) * 4, model.getRed( rgb ) * 4, model.getGreen( rgb ) * 4, model.getBlue( rgb ) * 4 );
}
private int makeColorbyDefaultCM(ColorModel model, int rgb)
{
return makeColor( model.getAlpha( rgb ), model.getRed( rgb ), model.getGreen( rgb ), model.getBlue( rgb ) );
}
private int makeColor( int a, int r, int g, int b )
{
return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
}
/**
Filters a single pixel from the default ColorModel.
@param x x-coordinate
@param y y-coordinate
@param rgb color
*/
public abstract int filterRGB(int x,
int y,
int rgb);
}
@@ -0,0 +1,546 @@
/* Copyright (C) 2000, 2002, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Rectangle;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class Raster
{
protected SampleModel sampleModel;
protected DataBuffer dataBuffer;
protected int minX;
protected int minY;
protected int width;
protected int height;
protected int sampleModelTranslateX;
protected int sampleModelTranslateY;
protected int numBands;
protected int numDataElements;
protected Raster parent;
protected Raster(SampleModel sampleModel, Point origin)
{
this(sampleModel, sampleModel.createDataBuffer(), origin);
}
protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
Point origin)
{
this(sampleModel, dataBuffer,
new Rectangle(origin.x, origin.y,
sampleModel.getWidth(), sampleModel.getHeight()),
origin, null);
}
protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
Rectangle aRegion,
Point sampleModelTranslate, Raster parent)
{
this.sampleModel = sampleModel;
this.dataBuffer = dataBuffer;
this.minX = aRegion.x;
this.minY = aRegion.y;
this.width = aRegion.width;
this.height = aRegion.height;
// If sampleModelTranslate is null, use (0,0). Methods such as
// Raster.createRaster are specified to allow for a null argument.
if (sampleModelTranslate != null)
{
this.sampleModelTranslateX = sampleModelTranslate.x;
this.sampleModelTranslateY = sampleModelTranslate.y;
}
this.numBands = sampleModel.getNumBands();
this.numDataElements = sampleModel.getNumDataElements();
this.parent = parent;
}
public static WritableRaster createInterleavedRaster(int dataType,
int w, int h,
int bands,
Point location)
{
int[] bandOffsets = new int[bands];
// TODO: Maybe not generate this every time.
for (int b=0; b<bands; b++) bandOffsets[b] = b;
int scanlineStride = bands*w;
return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
bandOffsets, location);
}
public static WritableRaster createInterleavedRaster(int dataType,
int w, int h,
int scanlineStride,
int pixelStride,
int[] bandOffsets,
Point location)
{
SampleModel sm = new ComponentSampleModel(dataType,
w, h,
pixelStride,
scanlineStride,
bandOffsets);
return createWritableRaster(sm, location);
}
public static WritableRaster createBandedRaster(int dataType,
int w, int h, int bands,
Point location)
{
SampleModel sm = new BandedSampleModel(dataType, w, h, bands);
return createWritableRaster(sm, location);
}
public static WritableRaster createBandedRaster(int dataType,
int w, int h,
int scanlineStride,
int[] bankIndices,
int[] bandOffsets,
Point location)
{
SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
bankIndices, bandOffsets);
return createWritableRaster(sm, location);
}
public static WritableRaster createPackedRaster(int dataType,
int w, int h,
int[] bandMasks,
Point location)
{
SampleModel sm = new SinglePixelPackedSampleModel(dataType,
w, h,
bandMasks);
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,
int[] bandOffsets, Point location)
{
SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(),
w, h,
scanlineStride,
pixelStride,
bandOffsets);
return createWritableRaster(sm, dataBuffer, location);
}
public static
WritableRaster createBandedRaster(DataBuffer dataBuffer,
int w, int h,
int scanlineStride,
int[] bankIndices,
int[] bandOffsets,
Point location)
{
SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(),
w, h, scanlineStride,
bankIndices, bandOffsets);
return createWritableRaster(sm, dataBuffer, location);
}
public static WritableRaster
createPackedRaster(DataBuffer dataBuffer,
int w, int h,
int scanlineStride,
int[] bandMasks,
Point location)
{
SampleModel sm =
new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
w, h,
scanlineStride,
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)
{
return new Raster(sm, db, location);
}
public static WritableRaster createWritableRaster(SampleModel sm,
Point location)
{
return new WritableRaster(sm, location);
}
public static WritableRaster createWritableRaster(SampleModel sm,
DataBuffer db,
Point location)
{
return new WritableRaster(sm, db, location);
}
public Raster getParent()
{
return parent;
}
public final int getSampleModelTranslateX()
{
return sampleModelTranslateX;
}
public final int getSampleModelTranslateY()
{
return sampleModelTranslateY;
}
public WritableRaster createCompatibleWritableRaster()
{
return new WritableRaster(getSampleModel(), new Point(minX, minY));
}
public WritableRaster createCompatibleWritableRaster(int w, int h)
{
return createCompatibleWritableRaster(minX, minY, w, h);
}
public WritableRaster createCompatibleWritableRaster(Rectangle rect)
{
return createCompatibleWritableRaster(rect.x, rect.y,
rect.width, rect.height);
}
public WritableRaster createCompatibleWritableRaster(int x, int y,
int w, int h)
{
SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
return new WritableRaster(sm, sm.createDataBuffer(),
new Point(x, y));
}
public Raster createTranslatedChild(int childMinX, int childMinY) {
int tcx = sampleModelTranslateX - minX + childMinX;
int tcy = sampleModelTranslateY - minY + childMinY;
return new Raster(sampleModel, dataBuffer,
new Rectangle(childMinX, childMinY,
width, height),
new Point(tcx, tcy),
this);
}
public Raster createChild(int parentX, int parentY, int width,
int height, int childMinX, int childMinY,
int[] bandList)
{
/* FIXME: Throw RasterFormatException if child bounds extends
beyond the bounds of this raster. */
SampleModel sm = (bandList == null) ?
sampleModel :
sampleModel.createSubsetSampleModel(bandList);
/*
data origin
/
+-------------------------
|\. __ parent trans
| \`.
| \ `. parent origin
| \ `. /
| /\ +-------- - -
|trans\ /<\-- deltaTrans
|child +-+-\---- - -
| /|`| \__ parent [x, y]
|child | |`. \
|origin| : `.\
| | / `\
| : / +
| child [x, y]
parent_xy - parent_trans = child_xy - child_trans
child_trans = parent_trans + child_xy - parent_xy
*/
return new Raster(sm, dataBuffer,
new Rectangle(childMinX, childMinY,
width, height),
new Point(sampleModelTranslateX+childMinX-parentX,
sampleModelTranslateY+childMinY-parentY),
this);
}
public Rectangle getBounds()
{
return new Rectangle(minX, minY, width, height);
}
public final int getMinX()
{
return minX;
}
public final int getMinY()
{
return minY;
}
public final int getWidth()
{
return width;
}
public final int getHeight()
{
return height;
}
public final int getNumBands()
{
return numBands;
}
public final int getNumDataElements()
{
return numDataElements;
}
public final int getTransferType()
{
return sampleModel.getTransferType();
}
public DataBuffer getDataBuffer()
{
return dataBuffer;
}
public SampleModel getSampleModel()
{
return sampleModel;
}
public Object getDataElements(int x, int y, Object outData)
{
return sampleModel.getDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
outData, dataBuffer);
}
public Object getDataElements(int x, int y, int w, int h,
Object outData)
{
return sampleModel.getDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, outData, dataBuffer);
}
public int[] getPixel(int x, int y, int[] iArray)
{
return sampleModel.getPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
iArray, dataBuffer);
}
public float[] getPixel(int x, int y, float[] fArray)
{
return sampleModel.getPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
fArray, dataBuffer);
}
public double[] getPixel(int x, int y, double[] dArray)
{
return sampleModel.getPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
dArray, dataBuffer);
}
public int[] getPixels(int x, int y, int w, int h, int[] iArray)
{
return sampleModel.getPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, iArray, dataBuffer);
}
public float[] getPixels(int x, int y, int w, int h,
float[] fArray)
{
return sampleModel.getPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, fArray, dataBuffer);
}
public double[] getPixels(int x, int y, int w, int h,
double[] dArray)
{
return sampleModel.getPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, dArray, dataBuffer);
}
public int getSample(int x, int y, int b)
{
return sampleModel.getSample(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, dataBuffer);
}
public float getSampleFloat(int x, int y, int b)
{
return sampleModel.getSampleFloat(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, dataBuffer);
}
public double getSampleDouble(int x, int y, int b)
{
return sampleModel.getSampleDouble(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, dataBuffer);
}
public int[] getSamples(int x, int y, int w, int h, int b,
int[] iArray)
{
return sampleModel.getSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, iArray, dataBuffer);
}
public float[] getSamples(int x, int y, int w, int h, int b,
float[] fArray)
{
return sampleModel.getSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, fArray, dataBuffer);
}
public double[] getSamples(int x, int y, int w, int h, int b,
double[] dArray)
{
return sampleModel.getSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, dArray, dataBuffer);
}
/**
* Create a String representing the stat of this Raster.
* @return A String representing the stat of this Raster.
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuffer result = new StringBuffer();
result.append(getClass().getName());
result.append("[(");
result.append(minX).append(",").append(minY).append("), ");
result.append(width).append(" x ").append(height).append(",");
result.append(sampleModel).append(",");
result.append(dataBuffer);
result.append("]");
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;
}
}
}
@@ -0,0 +1,65 @@
/* RasterFormatException.java -- indicates invalid layout in Raster
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* This exception is thrown when there is invalid layout information in
* <code>Raster</code>
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see Raster
* @status updated to 1.4
*/
public class RasterFormatException extends RuntimeException
{
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 96598996116164315L;
/**
* Create a new instance with a descriptive error message.
*
* @param message the descriptive error message
*/
public RasterFormatException(String message)
{
super(message);
}
} // class RasterFormatException
@@ -0,0 +1,57 @@
/* RasterOp.java --
Copyright (C) 2000, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
public interface RasterOp
{
WritableRaster filter(Raster src, WritableRaster dest);
Rectangle2D getBounds2D(Raster src);
WritableRaster createCompatibleDestRaster(Raster src);
Point2D getPoint2D(Point2D srcPoint, Point2D destPoint);
RenderingHints getRenderingHints();
}
@@ -0,0 +1,70 @@
/* RenderedImage.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Rectangle;
import java.util.Vector;
/**
* NEEDS DOCUMENTATION
*/
public interface RenderedImage
{
Vector getSources();
Object getProperty(String name);
String[] getPropertyNames();
ColorModel getColorModel();
SampleModel getSampleModel();
int getWidth();
int getHeight();
int getMinX();
int getMinY();
int getNumXTiles();
int getNumYTiles();
int getMinTileX();
int getMinTileY();
int getTileWidth();
int getTileHeight();
int getTileGridXOffset();
int getTileGridYOffset();
Raster getTile(int x, int y);
Raster getData();
Raster getData(Rectangle r);
WritableRaster copyData(WritableRaster raster);
} // interface RenderedImage
@@ -0,0 +1,244 @@
/* ReplicateScaleFilter.java -- Java class for filtering images
Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.util.Hashtable;
/**
* This filter should be used for fast scaling of images where the result
* does not need to ensure straight lines are still straight, etc. The
* exact method is not defined by Sun but some sort of fast Box filter should
* probably be correct.
* <br>
* Currently this filter does nothing and needs to be implemented.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
public class ReplicateScaleFilter extends ImageFilter
{
public ReplicateScaleFilter(int width, int height) {
destHeight = height;
destWidth = width;
}
/**
* The height of the destination image.
*/
protected int destHeight;
/**
* The width of the destination image.
*/
protected int destWidth;
/**
* The height of the source image.
*/
protected int srcHeight;
/**
* The width of the source image.
*/
protected int srcWidth;
/**
*
*/
protected int srcrows[];
/**
*
*/
protected int srccols[];
/**
*
*/
protected Object outpixbuf;
/**
* An <code>ImageProducer</code> indicates the size of the image
* being produced using this method. A filter can override this
* method to intercept these calls from the producer in order to
* change either the width or the height before in turn calling
* the consumer's <code>setDimensions</code> method.
*
* @param width the width of the image
* @param height the height of the image
*/
public void setDimensions(int width, int height)
{
srcWidth = width;
srcHeight = height;
/* If either destHeight or destWidth is < 0, the image should
maintain its original aspect ratio. When both are < 0,
just maintain the original width and height. */
if (destWidth < 0 && destHeight < 0)
{
destWidth = width;
destHeight = height;
}
else if (destWidth < 0)
{
destWidth = (int) (width * ((double) destHeight / srcHeight));
}
else if (destHeight < 0)
{
destHeight = (int) (height * ((double) destWidth / srcWidth));
}
consumer.setDimensions(destWidth, destHeight);
}
/**
* An <code>ImageProducer</code> can set a list of properties
* associated with this image by using this method.
*
* @param props the list of properties associated with this image
*/
public void setProperties(Hashtable props)
{
props.put("filters", "ReplicateScaleFilter");
consumer.setProperties(props);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as a <code>byte</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize)
{
double rx = ((double) srcWidth) / destWidth;
double ry = ((double) srcHeight) / destHeight;
int destScansize = (int) Math.round(scansize / rx);
byte[] destPixels = replicatePixels(x, y, w, h,
model, pixels, offset, scansize,
rx, ry, destScansize);
consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
(int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
model, destPixels, 0, destScansize);
}
/**
* This function delivers a rectangle of pixels where any
* pixel(m,n) is stored in the array as an <code>int</code> at
* index (n * scansize + m + offset).
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
* @param 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 setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize)
{
double rx = ((double) srcWidth) / destWidth;
double ry = ((double) srcHeight) / destHeight;
int destScansize = (int) Math.round(scansize / rx);
int[] destPixels = replicatePixels(x, y, w, h,
model, pixels, offset, scansize,
rx, ry, destScansize);
consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
(int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
model, destPixels, 0, destScansize);
}
private byte[] replicatePixels(int srcx, int srcy, int srcw, int srch,
ColorModel model, byte[] srcPixels,
int srcOffset, int srcScansize,
double rx, double ry, int destScansize)
{
byte[] destPixels =
new byte[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
int a, b;
for (int i = 0; i < destPixels.length; i++)
{
a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
b = (int) ((i % destScansize) * rx);
if ((a + b + srcOffset) < srcPixels.length)
destPixels[i] = srcPixels[a + b + srcOffset];
}
return destPixels;
}
private int[] replicatePixels(int srcx, int srcy, int srcw, int srch,
ColorModel model, int[] srcPixels,
int srcOffset, int srcScansize,
double rx, double ry, int destScansize)
{
int[] destPixels =
new int[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
int a, b;
for (int i = 0; i < destPixels.length; i++)
{
a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
b = (int) ((i % destScansize) * rx);
if ((a + b + srcOffset) < srcPixels.length)
destPixels[i] = srcPixels[a + b + srcOffset];
}
return destPixels;
}
}
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
}
}
@@ -0,0 +1,477 @@
/* Copyright (C) 2000, 2001, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public abstract class SampleModel
{
/** Width of image described. */
protected int width;
/** Height of image described. */
protected int height;
/** Number of bands in the image described. */
protected int numBands;
/**
* The DataBuffer type that is used to store the data of the image
* described.
*/
protected int dataType;
public SampleModel(int dataType, int w, int h, int numBands)
{
if ((w <= 0) || (h <= 0))
throw new IllegalArgumentException((w <= 0 ? " width<=0" : " width is ok")
+(h <= 0 ? " height<=0" : " height is ok"));
// FIXME: How can an int be greater than Integer.MAX_VALUE?
// FIXME: How do we identify an unsupported data type?
this.dataType = dataType;
this.width = w;
this.height = h;
this.numBands = numBands;
}
public final int getWidth()
{
return width;
}
public final int getHeight()
{
return height;
}
public final int getNumBands()
{
return numBands;
}
public abstract int getNumDataElements();
public final int getDataType()
{
return dataType;
}
public int getTransferType()
{
// FIXME: Is this a reasonable default implementation?
return dataType;
}
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
if (iArray == null) iArray = new int[numBands];
for (int b=0; b<numBands; b++) iArray[b] = getSample(x, y, b, data);
return iArray;
}
/**
*
* This method is provided as a faster alternative to getPixel(),
* that can be used when there is no need to decode the pixel into
* separate sample values.
*
* @param obj An array to return the pixel data in. If null, an
* array of the right type and size will be created.
*
* @return A single pixel as an array object of a primitive type,
* based on the transfer type. Eg. if transfer type is
* DataBuffer.TYPE_USHORT, then a short[] object is returned.
*/
public abstract Object getDataElements(int x, int y, Object obj,
DataBuffer data);
public Object getDataElements(int x, int y, int w, int h, Object obj,
DataBuffer data)
{
int size = w*h;
int numDataElements = getNumDataElements();
int dataSize = numDataElements*size;
if (obj == null)
{
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
obj = new byte[dataSize];
break;
case DataBuffer.TYPE_USHORT:
obj = new short[dataSize];
break;
case DataBuffer.TYPE_INT:
obj = new int[dataSize];
break;
default:
// Seems like the only sensible thing to do.
throw new ClassCastException();
}
}
Object pixelData = null;
int outOffset = 0;
for (int yy = y; yy<(y+h); yy++)
{
for (int xx = x; xx<(x+w); xx++)
{
pixelData = getDataElements(xx, yy, pixelData, data);
System.arraycopy(pixelData, 0, obj, outOffset,
numDataElements);
outOffset += numDataElements;
}
}
return obj;
}
public abstract void setDataElements(int x, int y, Object obj,
DataBuffer data);
public void setDataElements(int x, int y, int w, int h,
Object obj, DataBuffer data)
{
int size = w*h;
int numDataElements = getNumDataElements();
int dataSize = numDataElements*size;
Object pixelData;
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
pixelData = new byte[numDataElements];
break;
case DataBuffer.TYPE_USHORT:
pixelData = new short[numDataElements];
break;
case DataBuffer.TYPE_INT:
pixelData = new int[numDataElements];
break;
default:
// Seems like the only sensible thing to do.
throw new ClassCastException();
}
int inOffset = 0;
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
System.arraycopy(obj, inOffset, pixelData, 0,
numDataElements);
setDataElements(xx, yy, pixelData, data);
inOffset += numDataElements;
}
}
}
public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
{
if (fArray == null) fArray = new float[numBands];
for (int b=0; b<numBands; b++)
{
fArray[b] = getSampleFloat(x, y, b, data);
}
return fArray;
}
public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
if (dArray == null) dArray = new double[numBands];
for (int b=0; b<numBands; b++)
{
dArray[b] = getSampleDouble(x, y, b, data);
}
return dArray;
}
/* FIXME: Should it return a banded or pixel interleaved array of
samples? (Assume interleaved.) */
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int size = w*h;
int outOffset = 0;
int[] pixel = null;
if (iArray == null) iArray = new int[w*h*numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
pixel = getPixel(xx, yy, pixel, data);
System.arraycopy(pixel, 0, iArray, outOffset, numBands);
outOffset += numBands;
}
}
return iArray;
}
/* FIXME: Should it return a banded or pixel interleaved array of
samples? (Assume interleaved.) */
public float[] getPixels(int x, int y, int w, int h, float[] fArray,
DataBuffer data)
{
int size = w*h;
int outOffset = 0;
float[] pixel = null;
if (fArray == null) fArray = new float[w*h*numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
pixel = getPixel(xx, yy, pixel, data);
System.arraycopy(pixel, 0, fArray, outOffset, numBands);
outOffset += numBands;
}
}
return fArray;
}
/* FIXME: Should it return a banded or pixel interleaved array of
samples? (Assume interleaved.) */
public double[] getPixels(int x, int y, int w, int h, double[] dArray,
DataBuffer data)
{
int size = w*h;
int outOffset = 0;
double[] pixel = null;
if (dArray == null) dArray = new double[w*h*numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
pixel = getPixel(xx, yy, pixel, data);
System.arraycopy(pixel, 0, dArray, outOffset, numBands);
outOffset += numBands;
}
}
return dArray;
}
public abstract int getSample(int x, int y, int b, DataBuffer data);
public float getSampleFloat(int x, int y, int b, DataBuffer data)
{
return getSample(x, y, b, data);
}
public double getSampleDouble(int x, int y, int b, DataBuffer data)
{
return getSampleFloat(x, y, b, data);
}
public int[] getSamples(int x, int y, int w, int h, int b,
int[] iArray, DataBuffer data)
{
int size = w*h;
int outOffset = 0;
if (iArray == null) iArray = new int[size];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
iArray[outOffset++] = getSample(xx, yy, b, data);
}
}
return iArray;
}
public float[] getSamples(int x, int y, int w, int h, int b,
float[] fArray, DataBuffer data)
{
int size = w*h;
int outOffset = 0;
if (fArray == null) fArray = new float[size];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
fArray[outOffset++] = getSampleFloat(xx, yy, b, data);
}
}
return fArray;
}
public double[] getSamples(int x, int y, int w, int h, int b,
double[] dArray, DataBuffer data)
{
int size = w*h;
int outOffset = 0;
if (dArray == null) dArray = new double[size];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
dArray[outOffset++] = getSampleDouble(xx, yy, b, data);
}
}
return dArray;
}
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
for (int b=0; b<numBands; b++) setSample(x, y, b, iArray[b], data);
}
public void setPixel(int x, int y, float[] fArray, DataBuffer data)
{
for (int b=0; b<numBands; b++) setSample(x, y, b, fArray[b], data);
}
public void setPixel(int x, int y, double[] dArray, DataBuffer data)
{
for (int b=0; b<numBands; b++) setSample(x, y, b, dArray[b], data);
}
public void setPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int inOffset = 0;
int[] pixel = new int[numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
System.arraycopy(iArray, inOffset, pixel, 0, numBands);
setPixel(xx, yy, pixel, data);
inOffset += numBands;
}
}
}
public void setPixels(int x, int y, int w, int h, float[] fArray,
DataBuffer data)
{
int inOffset = 0;
float[] pixel = new float[numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
System.arraycopy(fArray, inOffset, pixel, 0, numBands);
setPixel(xx, yy, pixel, data);
inOffset += numBands;
}
}
}
public void setPixels(int x, int y, int w, int h, double[] dArray,
DataBuffer data)
{
int inOffset = 0;
double[] pixel = new double[numBands];
for (int yy=y; yy<(y+h); yy++)
{
for (int xx=x; xx<(x+w); xx++)
{
System.arraycopy(dArray, inOffset, pixel, 0, numBands);
setPixel(xx, yy, pixel, data);
inOffset += numBands;
}
}
}
public abstract void setSample(int x, int y, int b, int s,
DataBuffer data);
public void setSample(int x, int y, int b, float s,
DataBuffer data)
{
setSample(x, y, b, (int) s, data);
}
public void setSample(int x, int y, int b, double s,
DataBuffer data)
{
setSample(x, y, b, (float) s, data);
}
public void setSamples(int x, int y, int w, int h, int b,
int[] iArray, DataBuffer data)
{
int size = w*h;
int inOffset = 0;
for (int yy=y; yy<(y+h); yy++)
for (int xx=x; xx<(x+w); xx++)
setSample(xx, yy, b, iArray[inOffset++], data);
}
public void setSamples(int x, int y, int w, int h, int b,
float[] fArray, DataBuffer data)
{
int size = w*h;
int inOffset = 0;
for (int yy=y; yy<(y+h); yy++)
for (int xx=x; xx<(x+w); xx++)
setSample(xx, yy, b, fArray[inOffset++], data);
}
public void setSamples(int x, int y, int w, int h, int b,
double[] dArray, DataBuffer data) {
int size = w*h;
int inOffset = 0;
for (int yy=y; yy<(y+h); yy++)
for (int xx=x; xx<(x+w); xx++)
setSample(xx, yy, b, dArray[inOffset++], data);
}
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();
public abstract int[] getSampleSize();
public abstract int getSampleSize(int band);
}
@@ -0,0 +1,162 @@
/* ShortLookupTable.java -- Java class for a pixel translation table.
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* ShortLookupTable represents translation arrays for pixel values. It wraps
* one or more data arrays for each layer (or component) in an image, such as
* Alpha, R, G, and B. When doing translation, the offset is subtracted from
* the pixel values to allow a subset of an array to be used.
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @version 1.0
*/
public class ShortLookupTable extends LookupTable
{
// Array of translation tables.
private short data[][];
/**
* Creates a new <code>ShortLookupTable</code> instance.
*
* Offset is subtracted from pixel values when looking up in the translation
* tables. If data.length is one, the same table is applied to all pixel
* components.
*
* @param offset Offset to be subtracted.
* @param data Array of lookup tables.
* @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
*/
public ShortLookupTable(int offset, short[][] data)
throws IllegalArgumentException
{
super(offset, data.length);
this.data = data;
}
/**
* Creates a new <code>ShortLookupTable</code> instance.
*
* Offset is subtracted from pixel values when looking up in the translation
* table. The same table is applied to all pixel components.
*
* @param offset Offset to be subtracted.
* @param data Lookup table for all components.
* @exception IllegalArgumentException if offset &lt; 0.
*/
public ShortLookupTable(int offset, short[] data)
throws IllegalArgumentException
{
super(offset, 1);
this.data = new short[][] {data};
}
/** Return the lookup tables. */
public final short[][] getTable()
{
return data;
}
/**
* Return translated values for a pixel.
*
* For each value in the pixel src, use the value minus offset as an index
* in the component array and copy the value there to the output for the
* component. If dest is null, the output is a new array, otherwise the
* translated values are written to dest. Dest can be the same array as
* src.
*
* For example, if the pixel src is [2, 4, 3], and offset is 1, the output
* is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
* translation arrays.
*
* @param src Component values of a pixel.
* @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[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
dst[i] = data[0][src[i] - offset];
else
for (int i=0; i < src.length; i++)
dst[i] = data[i][src[i] - offset];
return dst;
}
/**
* Return translated values for a pixel.
*
* For each value in the pixel src, use the value minus offset as an index
* in the component array and copy the value there to the output for the
* component. If dest is null, the output is a new array, otherwise the
* translated values are written to dest. Dest can be the same array as
* src.
*
* For example, if the pixel src is [2, 4, 3], and offset is 1, the output
* is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
* translation arrays.
*
* @param src Component values of a pixel.
* @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[src.length];
if (data.length == 1)
for (int i=0; i < src.length; i++)
dst[i] = data[0][((int)src[i]) - offset];
else
for (int i=0; i < src.length; i++)
dst[i] = data[i][((int)src[i]) - offset];
return dst;
}
}
@@ -0,0 +1,449 @@
/* Copyright (C) 2000, 2002, 2003, 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.BitMaskExtent;
import gnu.java.awt.Buffers;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class SinglePixelPackedSampleModel extends SampleModel
{
private int scanlineStride;
private int[] bitMasks;
private int[] bitOffsets;
private int[] sampleSize;
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int[] bitMasks)
{
this(dataType, w, h, w, bitMasks);
}
public SinglePixelPackedSampleModel(int dataType, int w, int h,
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;
bitOffsets = new int[numBands];
sampleSize = new int[numBands];
BitMaskExtent extent = new BitMaskExtent();
for (int b=0; b<numBands; b++)
{
extent.setMask(bitMasks[b]);
sampleSize[b] = extent.bitWidth;
bitOffsets[b] = extent.leastSignificantBit;
}
}
public int getNumDataElements()
{
return 1;
}
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 SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
}
/**
* 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;
// 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 - 1) + width;
return Buffers.createBuffer(getDataType(), size);
}
public int[] getSampleSize()
{
return sampleSize;
}
public int getSampleSize(int band)
{
return sampleSize[band];
}
public int getOffset(int x, int y)
{
return scanlineStride*y + x;
}
public int[] getBitOffsets()
{
return bitOffsets;
}
public int[] getBitMasks()
{
return bitMasks;
}
public int getScanlineStride()
{
return scanlineStride;
}
public SampleModel createSubsetSampleModel(int[] bands)
{
// FIXME: Is this the right way to interpret bands?
int numBands = bands.length;
int[] bitMasks = new int[numBands];
for (int b=0; b<numBands; b++)
bitMasks[b] = this.bitMasks[bands[b]];
return new SinglePixelPackedSampleModel(dataType, width, height,
scanlineStride, bitMasks);
}
public Object getDataElements(int x, int y, Object obj,
DataBuffer data)
{
int offset = scanlineStride*y + x + data.getOffset();
return Buffers.getData(data, offset, obj,
0, // destination offset,
1 // length
);
}
/**
* This is a more efficient implementation of the default implementation in the super
* class.
* @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 w The width of the pixel rectangle to store in <code>obj</code>.
* @param h The height 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, int, int, java.lang.Object, java.awt.image.DataBuffer)
*/
public Object getDataElements(int x, int y, int w, int h, Object obj,
DataBuffer data)
{
int size = w*h;
int dataSize = size;
Object pixelData = null;
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
pixelData = ((DataBufferByte) data).getData();
if (obj == null) obj = new byte[dataSize];
break;
case DataBuffer.TYPE_USHORT:
pixelData = ((DataBufferUShort) data).getData();
if (obj == null) obj = new short[dataSize];
break;
case DataBuffer.TYPE_INT:
pixelData = ((DataBufferInt) data).getData();
if (obj == null) obj = new int[dataSize];
break;
default:
// Seems like the only sensible thing to do.
throw new ClassCastException();
}
if(x==0 && scanlineStride == w)
{
// The full width need to be copied therefore we can copy in one shot.
System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj, 0, size);
}
else
{
// Since we do not need the full width we need to copy line by line.
int outOffset = 0;
int dataOffset = scanlineStride*y + x + data.getOffset();
for (int yy = y; yy<(y+h); yy++)
{
System.arraycopy(pixelData, dataOffset, obj, outOffset, w);
dataOffset += scanlineStride;
outOffset += w;
}
}
return obj;
}
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
int offset = scanlineStride*y + x;
if (iArray == null) iArray = new int[numBands];
int samples = data.getElem(offset);
for (int b=0; b<numBands; b++)
iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
return iArray;
}
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int offset = scanlineStride*y + x;
if (iArray == null) iArray = new int[numBands*w*h];
int outOffset = 0;
for (y=0; y<h; y++)
{
int lineOffset = offset;
for (x=0; x<w; x++)
{
int samples = data.getElem(lineOffset++);
for (int b=0; b<numBands; b++)
iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
}
offset += scanlineStride;
}
return iArray;
}
public int getSample(int x, int y, int b, DataBuffer data)
{
int offset = scanlineStride*y + x;
int samples = data.getElem(offset);
return (samples & bitMasks[b]) >>> bitOffsets[b];
}
/**
* This method implements a more efficient way to set data elements than the default
* implementation of the super class. It sets the data elements line by line instead
* of pixel by pixel.
* @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 w The width of the data elements in <code>obj</code>.
* @param h The height 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, int w, int h,
Object obj, DataBuffer data)
{
Object pixelData;
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
pixelData = ((DataBufferByte) data).getData();
break;
case DataBuffer.TYPE_USHORT:
pixelData = ((DataBufferUShort) data).getData();
break;
case DataBuffer.TYPE_INT:
pixelData = ((DataBufferInt) data).getData();
break;
default:
// Seems like the only sensible thing to do.
throw new ClassCastException();
}
int inOffset = 0;
int dataOffset = scanlineStride*y + x + data.getOffset();
for (int yy=y; yy<(y+h); yy++)
{
System.arraycopy(obj,inOffset,pixelData,dataOffset,w);
dataOffset += scanlineStride;
inOffset += w;
}
}
public void setDataElements(int x, int y, Object obj, DataBuffer data)
{
int offset = scanlineStride*y + x + data.getOffset();
int transferType = getTransferType();
if (getTransferType() != data.getDataType())
{
throw new IllegalArgumentException("transfer type ("+
getTransferType()+"), "+
"does not match data "+
"buffer type (" +
data.getDataType() +
").");
}
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;
}
// FIXME: Fill in the other possible types.
default:
throw new InternalError();
}
}
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)
{
int offset = scanlineStride*y + x;
int samples = 0;
for (int b=0; b<numBands; b++)
samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
data.setElem(offset, samples);
}
/**
* This method implements a more efficient way to set pixels than the default
* implementation of the super class. It copies the pixel components directly
* from the input array instead of creating a intermediate buffer.
* @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
* @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 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)
*/
public void setPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int inOffset = 0;
int[] pixel = new int[numBands];
for (int yy=y; yy<(y+h); yy++)
{
int offset = scanlineStride*yy + x;
for (int xx=x; xx<(x+w); xx++)
{
int samples = 0;
for (int b=0; b<numBands; b++)
samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
data.setElem(0, offset, samples);
inOffset += numBands;
offset += 1;
}
}
}
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
int offset = scanlineStride*y + x;
int samples = data.getElem(offset);
int bitMask = bitMasks[b];
samples &= ~bitMask;
samples |= (s << bitOffsets[b]) & bitMask;
data.setElem(offset, samples);
}
/**
* 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();
}
}
@@ -0,0 +1,47 @@
/* TileObserver.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* NEEDS DOCUMENTATION
*/
public interface TileObserver
{
void tileUpdate(WritableRenderedImage src, int x, int y, boolean writable);
} // interface TileObserver
@@ -0,0 +1,253 @@
/* VolatileImage.java -- a hardware-accelerated image buffer
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.ImageCapabilities;
/**
* VolatileImage represents a hardware-accelerated graphics buffer.
* The native graphics system may free or damage the resources
* occupied by a VolatileImage at any time. As such, one must
* frequently check the "validity" of the image buffer's resources.
*
* A volatile image's "validity" depends on multiple factors. Its
* resources may have become unavailble in which case you must
* reallocate them. If you move the image from one output device to
* another, you may need to recreate the image's resources if the new
* output device's capabilities don't match the old one's. Finally,
* if the contents of the image's buffer have been damaged you must
* re-render the image.
*
* VolatileImages should always be created using either
* Component.createVolatileImage or
* GraphicsConfiguration.createCompatibleVolatileImage.
*/
public abstract class VolatileImage extends Image
implements Transparency
{
/**
* One of validate's possible return values. Indicates that the
* image buffer matches its graphics configuration's capabilities
* and that its resources are initialized and ready to be drawn
* into. Also implies that any existing image rendered to the
* buffer is intact and need not be re-rendered.
*/
public static final int IMAGE_OK = 0;
/**
* One of validate's possible return values. Indicates that the
* image buffer has been restored, meaning that it is valid and
* ready-to-use but that its previous contents have been lost. This
* return value implies that the image needs to be re-rendered.
*/
public static final int IMAGE_RESTORED = 1;
/**
* One of validate's possible return values. Indicates that the
* image buffer type is unsupported by the current graphics
* configuration. The graphics configuration may have changed, for
* example if the image moved from one output device to another.
* This return value implies that the image buffer's resources
* should be re-acquired.
*/
public static final int IMAGE_INCOMPATIBLE = 2;
/**
* This image's transparency type. One of Transparency.BITMASK,
* Transparency.OPAQUE or Transparency.TRANSLUCENT.
*
* @since 1.5
*/
protected int transparency;
/**
* Default constructor. VolatileImages should not be created
* directly. Rather, you should use Component.createVolatileImage
* or GraphicsConfiguration.createCompatibleVolatileImage.
*/
public VolatileImage()
{
}
/**
* Returns an image representing the current state of the volatile
* image buffer. The returned image is static meaning that it is
* not updated after being created. It is a snapshot of the
* volatile image buffer at the time getSnapshot is called.
*
* This method, which reads pixels from the volatile image buffer,
* may be less-performant than methods that write pixels since
* VolatileImages are typically optimized for writing.
*
* @return a BufferedImage representing this VolatileImage
*/
public abstract BufferedImage getSnapshot();
/**
* Returns the width of this image buffer.
*
* @return the width of this VolatileImage
*/
public abstract int getWidth();
/**
* Returns the height of this image buffer.
*
* @return the height of this VolatileImage
*/
public abstract int getHeight();
/**
* Calling this method is equivalent to calling
* getSnapshot().getSource(). The ImageProducer produces pixels
* from the BufferedImage snapshot and not from the VolatileImage
* itself. Thus, changes to the VolatileImage that occur after this
* ImageProducer has been retrieved will not be reflected in the
* produced pixels.
*
* This method, which reads pixels from the volatile image buffer,
* may be less-performant than methods that write pixels since
* VolatileImages are typically optimized for writing.
*
* @return an ImageProducer for a static BufferedImage snapshot of
* this image buffer
*/
public ImageProducer getSource()
{
return getSnapshot().getSource();
}
/**
* Releases the system resources taken by this image.
*/
public void flush()
{
}
/**
* Returns a Graphics2D object that can be used to draw onto this
* image. This method is present for backwards-compatibility. It
* simply returns the result of createGraphics.
*
* @return a Graphics2D object that can be used to draw onto this
* image
*/
public Graphics getGraphics()
{
return createGraphics();
}
/**
* Returns a Graphics2D object that can be used to draw onto this
* image.
*
* @return a Graphics2D object that can be used to draw onto this
* image
*/
public abstract Graphics2D createGraphics();
/**
* Validates and restores this image. If the image buffer has
* become unavailable for further use since the last call to
* validate, validate will allocate a new image buffer. The image
* is also "validated" against the GraphicsConfiguration parameter.
*
* "Validating" the image means checking that the capabilities it
* requires of the output device are indeed supported by the given
* output device. If the image's characteristics, which can be
* highly output device-specific, are not supported by the graphics
* configuration, then IMAGE_INCOMPATIBLE will be returned. This
* can happen, for example, if this image was created on one output
* device, then validated against a different output device with
* different capabilities. Calling validate with a NULL gc argument
* causes validate to skip the validation test.
*
* @param gc graphics configuration against which to validate or
* NULL
*
* @return a code indicating the result of validation. One of:
* <ul>
* <li><code>IMAGE_OK</code> if the image did not need to be
* validated and didn't need to be restored</li>
* <li><code>IMAGE_RESTORED</code> if the image may need to be
* re-rendered.</li>
* <li><code>IMAGE_INCOMPATIBLE</code> if this image's
* requirements are not fulfilled by the graphics configuration
* parameter. This implies that you need to create a new
* VolatileImage for the different GraphicsConfiguration or
* Component. This return value implies nothing about whether the
* image is valid or needs to be re-rendered.</li>
* </ul>
*/
public abstract int validate(GraphicsConfiguration gc);
/**
* Returns true if the contents of the image buffer have been
* damaged or if the image buffer's resources have been reclaimed by
* the graphics system. You should call this method after a series
* of rendering operations to or from the image, to see if the image
* buffer needs to be revalidated or the image re-rendered.
*
* @return true if the validate should be called, false otherwise
*/
public abstract boolean contentsLost();
/**
* Returns the capabilities of this image buffer.
*
* @return the capabilities of this image buffer
*/
public abstract ImageCapabilities getCapabilities();
/**
* Returns the transparency type of this image.
*
* @return Transparency.OPAQUE, Transparency.BITMASK or
* Transparency.TRANSLUCENT
*/
public int getTransparency()
{
return transparency;
}
}
@@ -0,0 +1,265 @@
/* Copyright (C) 2000, 2002, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.Rectangle;
/**
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class WritableRaster extends Raster
{
protected WritableRaster(SampleModel sampleModel, Point origin)
{
this(sampleModel, sampleModel.createDataBuffer(), origin);
}
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer, Point origin)
{
this(sampleModel, dataBuffer,
new Rectangle(origin != null ? origin.x : 0,
origin != null ? origin.y : 0,
sampleModel.getWidth(), sampleModel.getHeight()),
origin,
null);
}
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer,
Rectangle aRegion,
Point sampleModelTranslate,
WritableRaster parent)
{
super(sampleModel, dataBuffer, aRegion, sampleModelTranslate,
parent);
}
public WritableRaster getWritableParent()
{
return (WritableRaster) getParent();
}
public WritableRaster createWritableTranslatedChild(int childMinX,
int childMinY)
{
// This mirrors the code from the super class
int tcx = sampleModelTranslateX - minX + childMinX;
int tcy = sampleModelTranslateY - minY + childMinY;
return new WritableRaster(sampleModel, dataBuffer,
new Rectangle(childMinX, childMinY,
width, height),
new Point(tcx, tcy),
this);
}
public WritableRaster createWritableChild(int parentX,
int parentY,
int w, int h,
int childMinX,
int childMinY,
int[] bandList)
{
// This mirrors the code from the super class
// FIXME: Throw RasterFormatException if child bounds extends
// beyond the bounds of this raster.
SampleModel sm = (bandList == null) ?
sampleModel :
sampleModel.createSubsetSampleModel(bandList);
return new
WritableRaster(sm, dataBuffer,
new Rectangle(childMinX, childMinY,
w, h),
new Point(sampleModelTranslateX+childMinX-parentX,
sampleModelTranslateY+childMinY-parentY),
this);
}
public void setDataElements(int x, int y, Object inData)
{
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
inData, dataBuffer);
}
public void setDataElements(int x, int y, Raster inRaster)
{
Object dataElements = getDataElements(0, 0,
inRaster.getWidth(),
inRaster.getHeight(),
null);
setDataElements(x, y, dataElements);
}
public void setDataElements(int x, int y, int w, int h,
Object inData)
{
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, inData, dataBuffer);
}
public void setRect(Raster srcRaster)
{
setRect(0, 0, srcRaster);
}
public void setRect(int dx, int dy, Raster srcRaster)
{
Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX()+dx,
srcRaster.getMinY()+dy,
srcRaster.getWidth(),
srcRaster.getHeight());
Rectangle target = getBounds().intersection(targetUnclipped);
if (target.isEmpty()) return;
int sx = target.x - dx;
int sy = target.y - dy;
// FIXME: Do tests on rasters and use get/set data instead.
/* The JDK documentation seems to imply this implementation.
(the trucation of higher bits), but an implementation using
get/setDataElements would be more efficient. None of the
implementations would do anything sensible when the sample
models don't match.
But this is probably not the place to consider such
optimizations.*/
int[] pixels = srcRaster.getPixels(sx, sy,
target.width, target.height,
(int[]) null);
setPixels(target.x, target.y, target.width, target.height, pixels);
}
public void setPixel(int x, int y, int[] iArray)
{
sampleModel.setPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
iArray, dataBuffer);
}
public void setPixel(int x, int y, float[] fArray)
{
sampleModel.setPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
fArray, dataBuffer);
}
public void setPixel(int x, int y, double[] dArray)
{
sampleModel.setPixel(x-sampleModelTranslateX,
y-sampleModelTranslateY,
dArray, dataBuffer);
}
public void setPixels(int x, int y, int w, int h, int[] iArray)
{
sampleModel.setPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, iArray, dataBuffer);
}
public void setPixels(int x, int y, int w, int h, float[] fArray)
{
sampleModel.setPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, fArray, dataBuffer);
}
public void setPixels(int x, int y, int w, int h, double[] dArray)
{
sampleModel.setPixels(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, dArray, dataBuffer);
}
public void setSample(int x, int y, int b, int s)
{
sampleModel.setSample(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, s, dataBuffer);
}
public void setSample(int x, int y, int b, float s)
{
sampleModel.setSample(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, s, dataBuffer);
}
public void setSample(int x, int y, int b, double s)
{
sampleModel.setSample(x-sampleModelTranslateX,
y-sampleModelTranslateY,
b, s, dataBuffer);
}
public void setSamples(int x, int y, int w, int h, int b,
int[] iArray)
{
sampleModel.setSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, iArray, dataBuffer);
}
public void setSamples(int x, int y, int w, int h, int b,
float[] fArray)
{
sampleModel.setSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, fArray, dataBuffer);
}
public void setSamples(int x, int y, int w, int h, int b,
double[] dArray)
{
sampleModel.setSamples(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w, h, b, dArray, dataBuffer);
}
}
@@ -0,0 +1,56 @@
/* WritableRenderedImage.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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;
/**
* NEEDS DOCUMENTATION
*/
public interface WritableRenderedImage extends RenderedImage
{
void addTileObserver(TileObserver to);
void removeTileObserver(TileObserver to);
WritableRaster getWritableTile(int x, int y);
void releaseWritableTile(int x, int y);
boolean isTileWritable(int x, int y);
Point[] getWritableTileIndices();
boolean hasTileWriters();
void setData(Raster r);
} // interface WritableRenderedImage
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in java.awt.image package.
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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. -->
<html>
<head><title>GNU Classpath - java.awt.image</title></head>
<body>
<p>Image consumers, producers and filters.</p>
</body>
</html>
@@ -0,0 +1,56 @@
/* ContextualRenderedImageFactory.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
/**
* STUBBED
*/
public interface ContextualRenderedImageFactory extends RenderedImageFactory
{
RenderContext mapRenderContext(int i, RenderContext context,
ParameterBlock block, RenderableImage image);
RenderedImage create(RenderContext context, ParameterBlock block);
Rectangle2D getBounds2D(ParameterBlock block);
Object getProperty(ParameterBlock block, String name);
String[] getPropertyNames();
boolean isDynamic();
} // interface ContextualRenderedImageFactory
@@ -0,0 +1,308 @@
/* ParameterBlock.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.image.RenderedImage;
import java.io.Serializable;
import java.util.Vector;
public class ParameterBlock implements Cloneable, Serializable
{
private static final long serialVersionUID = -7577115551785240750L;
protected Vector sources;
protected Vector parameters;
public ParameterBlock()
{
this(new Vector(), new Vector());
}
public ParameterBlock(Vector sources)
{
this(sources, new Vector());
}
public ParameterBlock(Vector sources, Vector parameters)
{
this.sources = sources;
this.parameters = parameters;
}
public Object shallowClone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
throw (Error) new InternalError().initCause(e); // impossible
}
}
public Object clone()
{
ParameterBlock pb = (ParameterBlock) shallowClone();
if (sources != null)
pb.sources = (Vector) sources.clone();
if (parameters != null)
pb.parameters = (Vector) parameters.clone();
return pb;
}
public ParameterBlock addSource(Object source)
{
sources.add(source);
return this;
}
public Object getSource(int index)
{
return sources.get(index);
}
public ParameterBlock setSource(Object source, int index)
{
sources.ensureCapacity(index);
sources.set(index, source);
return this;
}
public RenderedImage getRenderedSource(int index)
{
return (RenderedImage) sources.get(index);
}
public RenderableImage getRenderableSource(int index)
{
return (RenderableImage) sources.get(index);
}
public int getNumSources()
{
return sources.size();
}
public Vector getSources()
{
return sources;
}
public void setSources(Vector sources)
{
this.sources = sources;
}
public void removeSources()
{
if (sources != null)
sources.clear();
}
public int getNumParameters()
{
return parameters.size();
}
public Vector getParameters()
{
return parameters;
}
public void setParameters(Vector parameters)
{
this.parameters = parameters;
}
public void removeParameters()
{
if (parameters != null)
parameters.clear();
}
public ParameterBlock add(Object o)
{
parameters.add(o);
return this;
}
public ParameterBlock add(byte b)
{
return add(new Byte(b));
}
public ParameterBlock add(char c)
{
return add(new Character(c));
}
public ParameterBlock add(short s)
{
return add(new Short(s));
}
public ParameterBlock add(int i)
{
return add(new Integer(i));
}
public ParameterBlock add(long l)
{
return add(new Long(l));
}
public ParameterBlock add(float f)
{
return add(new Float(f));
}
public ParameterBlock add(double d)
{
return add(new Double(d));
}
public ParameterBlock set(Object o, int index)
{
parameters.ensureCapacity(index);
parameters.set(index, o);
return this;
}
public ParameterBlock set(byte b, int index)
{
return set(new Byte(b), index);
}
public ParameterBlock set(char c, int index)
{
return set(new Character(c), index);
}
public ParameterBlock set(short s, int index)
{
return set(new Short(s), index);
}
public ParameterBlock set(int i, int index)
{
return set(new Integer(i), index);
}
public ParameterBlock set(long l, int index)
{
return set(new Long(l), index);
}
public ParameterBlock set(float f, int index)
{
return set(new Float(f), index);
}
public ParameterBlock set(double d, int index)
{
return set(new Double(d), index);
}
public Object getObjectParameter(int index)
{
return parameters.get(index);
}
public byte getByteParameter(int index)
{
return ((Byte) parameters.get(index)).byteValue();
}
public char getCharParameter(int index)
{
return ((Character) parameters.get(index)).charValue();
}
public short getShortParameter(int index)
{
return ((Short) parameters.get(index)).shortValue();
}
public int getIntParameter(int index)
{
return ((Integer) parameters.get(index)).intValue();
}
public long getLongParameter(int index)
{
return ((Long) parameters.get(index)).longValue();
}
public float getFloatParameter(int index)
{
return ((Float) parameters.get(index)).floatValue();
}
public double getDoubleParameter(int index)
{
return ((Double) parameters.get(index)).doubleValue();
}
public Class[] getParamClasses()
{
int i = parameters.size();
Class[] result = new Class[i];
while (--i >= 0)
{
Class c = parameters.get(i).getClass();
if (c == Byte.class)
result[i] = byte.class;
else if (c == Character.class)
result[i] = char.class;
else if (c == Short.class)
result[i] = short.class;
else if (c == Integer.class)
result[i] = int.class;
else if (c == Long.class)
result[i] = long.class;
else if (c == Float.class)
result[i] = float.class;
else if (c == Double.class)
result[i] = double.class;
else
result[i] = c;
}
return result;
}
} // class ParameterBlock
@@ -0,0 +1,141 @@
/* RenderContext.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
public class RenderContext implements Cloneable
{
private AffineTransform xform;
private Shape aoi;
private RenderingHints hints;
public RenderContext(AffineTransform xform, Shape aoi, RenderingHints hints)
{
this.xform = xform;
this.aoi = aoi;
this.hints = hints;
}
public RenderContext(AffineTransform xform)
{
this(xform, null, null);
}
public RenderContext(AffineTransform xform, RenderingHints hints)
{
this(xform, null, hints);
}
public RenderContext(AffineTransform xform, Shape aoi)
{
this(xform, aoi, null);
}
public RenderingHints getRenderingHints()
{
return hints;
}
public void setRenderingHints(RenderingHints hints)
{
this.hints = hints;
}
public void setTransform(AffineTransform xform)
{
this.xform = xform;
}
public void preConcatenateTransform(AffineTransform pre)
{
preConcetenateTransform (pre);
}
/** @deprecated */
public void preConcetenateTransform(AffineTransform pre)
{
xform.preConcatenate (pre);
}
public void concatenateTransform(AffineTransform post)
{
concetenateTransform (post);
}
/** @deprecated */
public void concetenateTransform(AffineTransform post)
{
xform.concatenate (post);
}
public AffineTransform getTransform()
{
return xform;
}
public void setAreaOfInterest(Shape aoi)
{
this.aoi = aoi;
}
public Shape getAreaOfInterest()
{
return aoi;
}
public Object clone()
{
try
{
RenderContext copy = (RenderContext) super.clone();
if (xform != null)
copy.xform = (AffineTransform) xform.clone();
if (hints != null)
copy.hints = (RenderingHints) hints.clone();
return copy;
}
catch (CloneNotSupportedException e)
{
throw (Error) new InternalError().initCause(e); // impossible
}
}
} // class RenderContext
@@ -0,0 +1,62 @@
/* RenderableImage.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.util.Vector;
public interface RenderableImage
{
String HINTS_OBSERVED = "HINTS_OBSERVED";
Vector getSources();
Object getProperty(String name);
String[] getPropertyNames();
boolean isDynamic();
float getWidth();
float getHeight();
float getMinX();
float getMinY();
RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
RenderedImage createDefaultRendering();
RenderedImage createRendering(RenderContext context);
} // interface RenderableImage
@@ -0,0 +1,157 @@
/* RenderableImageOp.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import java.util.Vector;
public class RenderableImageOp implements RenderableImage
{
private final ContextualRenderedImageFactory crif;
private ParameterBlock block;
public RenderableImageOp(ContextualRenderedImageFactory crif,
ParameterBlock block)
{
this.crif = crif;
this.block = (ParameterBlock) block.clone();
}
public Vector getSources()
{
if (block.sources == null)
return null;
int size = block.sources.size();
Vector v = new Vector();
for (int i = 0; i < size; i++)
{
Object o = block.sources.get(i);
if (o instanceof RenderableImage)
v.add(o);
}
return v;
}
public Object getProperty(String name)
{
return crif.getProperty(block, name);
}
public String[] getPropertyNames()
{
return crif.getPropertyNames();
}
public boolean isDynamic()
{
return crif.isDynamic();
}
public float getWidth()
{
return (float) crif.getBounds2D(block).getWidth();
}
public float getHeight()
{
return (float) crif.getBounds2D(block).getHeight();
}
public float getMinX()
{
return (float) crif.getBounds2D(block).getX();
}
public float getMinY()
{
return (float) crif.getBounds2D(block).getY();
}
public ParameterBlock setParameterBlock(ParameterBlock block)
{
ParameterBlock result = this.block;
this.block = (ParameterBlock) block.clone();
return result;
}
public ParameterBlock getParameterBlock()
{
return block;
}
public RenderedImage createScaledRendering(int w, int h,
RenderingHints hints)
{
if (w == 0)
if (h == 0)
throw new IllegalArgumentException();
else
w = Math.round(h * getWidth() / getHeight());
if (h == 0)
h = Math.round(w * getHeight() / getWidth());
AffineTransform xform = AffineTransform.getScaleInstance(w * getWidth(),
h * getHeight());
return createRendering(new RenderContext(xform, hints));
}
public RenderedImage createDefaultRendering()
{
return createRendering(new RenderContext(new AffineTransform()));
}
public RenderedImage createRendering(RenderContext context)
{
ParameterBlock copy = (ParameterBlock) block.clone();
int i = block.sources.size();
while (--i >= 0)
{
Object o = block.sources.get(i);
if (o instanceof RenderableImage)
{
RenderableImage ri = (RenderableImage) o;
RenderContext rc = crif.mapRenderContext(i, context, block, ri);
copy.sources.set(i, ri.createRendering(rc));
}
}
// Now copy.sources should be only RenderedImages.
return crif.create(context, copy);
}
} // class RenderableImageOp
@@ -0,0 +1,79 @@
/* RenderableImageProducer.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
public class RenderableImageProducer implements ImageProducer, Runnable
{
public RenderableImageProducer(RenderableImage image, RenderContext context)
{
throw new Error("not implemented");
}
public void setRenderContext(RenderContext context)
{
}
public void addConsumer(ImageConsumer consumer)
{
}
public boolean isConsumer(ImageConsumer consumer)
{
return false;
}
public void removeConsumer(ImageConsumer consumer)
{
}
public void startProduction(ImageConsumer consumer)
{
}
public void requestTopDownLeftRightResend(ImageConsumer consumer)
{
}
public void run()
{
}
} // class RenderableImageProducer
@@ -0,0 +1,47 @@
/* RenderedImageFactory.java --
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.renderable;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
public interface RenderedImageFactory
{
RenderedImage create(ParameterBlock block, RenderingHints hints);
} // interface RenderedImageFactory
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in java.awt.image.renderable package.
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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. -->
<html>
<head><title>GNU Classpath - java.awt.image.renderable</title></head>
<body>
<p></p>
</body>
</html>